mirror of
https://github.com/coder/terraform-provider-envbuilder.git
synced 2025-10-08 16:30:18 +00:00
fix(provider): correctly handle devcontainer-only in cache probe mode (#33)
* chore(internal/provider): add test case for dockerfile-only operation * chore(deps): update envbuilder to include #315
This commit is contained in:
parent
68cc59d705
commit
9f455838b8
3 changed files with 128 additions and 105 deletions
internal/provider
|
@ -10,106 +10,129 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccCachedImageResource(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||
defer cancel()
|
||||
files := map[string]string{
|
||||
".devcontainer/devcontainer.json": `{"build": { "dockerfile": "Dockerfile" }}`,
|
||||
".devcontainer/Dockerfile": `FROM localhost:5000/test-ubuntu:latest
|
||||
RUN date > /date.txt`,
|
||||
}
|
||||
// testEnvValue is a multi-line environment variable value that we use in
|
||||
// tests to ensure that we can handle multi-line values correctly.
|
||||
var testEnvValue = `bar
|
||||
baz`
|
||||
|
||||
deps := setup(ctx, t, files)
|
||||
deps.ExtraEnv["FOO"] = `bar
|
||||
baz` // THIS IS A LOAD-BEARING NEWLINE. DO NOT REMOVE.
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
Steps: []resource.TestStep{
|
||||
// Initial state: cache has not been seeded.
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
PlanOnly: true,
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
// Should detect that no cached image is present and plan to create the resource.
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Computed values MUST be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "id", uuid.Nil.String()),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "exists", "false"),
|
||||
resource.TestCheckResourceAttrSet("envbuilder_cached_image.test", "env.0"),
|
||||
// Cached image should be set to the builder image.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "image", deps.BuilderImage),
|
||||
// Inputs should still be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "cache_repo", deps.CacheRepo),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "extra_env.FOO", "bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "git_url", deps.Repo.URL),
|
||||
// Should be empty
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_username"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_password"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "cache_ttl_days"),
|
||||
),
|
||||
ExpectNonEmptyPlan: true, // TODO: check the plan.
|
||||
},
|
||||
// Re-running plan should have the same effect.
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Computed values MUST be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "id", uuid.Nil.String()),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "exists", "false"),
|
||||
resource.TestCheckResourceAttrSet("envbuilder_cached_image.test", "env.0"),
|
||||
// Cached image should be set to the builder image.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "image", deps.BuilderImage),
|
||||
// Inputs should still be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "cache_repo", deps.CacheRepo),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "extra_env.FOO", "bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "git_url", deps.Repo.URL),
|
||||
// Should be empty
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_username"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_password"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "cache_ttl_days"),
|
||||
),
|
||||
ExpectNonEmptyPlan: true, // TODO: check the plan.
|
||||
},
|
||||
// Now, seed the cache and re-run. We should now successfully create the cached image resource.
|
||||
{
|
||||
PreConfig: func() {
|
||||
seedCache(ctx, t, deps)
|
||||
},
|
||||
Config: deps.Config(t),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Inputs should still be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "cache_repo", deps.CacheRepo),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "extra_env.FOO", "bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "git_url", deps.Repo.URL),
|
||||
// Should be empty
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_username"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_password"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "cache_ttl_days"),
|
||||
// Computed
|
||||
resource.TestCheckResourceAttrWith("envbuilder_cached_image.test", "id", quotedPrefix("sha256:")),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "exists", "true"),
|
||||
resource.TestCheckResourceAttrSet("envbuilder_cached_image.test", "image"),
|
||||
resource.TestCheckResourceAttrWith("envbuilder_cached_image.test", "image", quotedPrefix(deps.CacheRepo)),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.0", "FOO=bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.1", fmt.Sprintf("ENVBUILDER_CACHE_REPO=%s", deps.CacheRepo)),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.2", fmt.Sprintf("ENVBUILDER_GIT_URL=%s", deps.Repo.URL)),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.3", "ENVBUILDER_REMOTE_REPO_BUILD_MODE=true"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "env.4"),
|
||||
),
|
||||
},
|
||||
// Should produce an empty plan after apply
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
PlanOnly: true,
|
||||
},
|
||||
// Ensure idempotence in this state!
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
PlanOnly: true,
|
||||
func TestAccCachedImageResource(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
files map[string]string
|
||||
}{
|
||||
{
|
||||
name: "devcontainer only",
|
||||
files: map[string]string{
|
||||
".devcontainer/devcontainer.json": `{"image": "localhost:5000/test-ubuntu:latest"}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
{
|
||||
name: "devcontainer and Dockerfile",
|
||||
files: map[string]string{
|
||||
".devcontainer/devcontainer.json": `{"build": { "dockerfile": "Dockerfile" }}`,
|
||||
".devcontainer/Dockerfile": `FROM localhost:5000/test-ubuntu:latest
|
||||
RUN date > /date.txt`,
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
//nolint: paralleltest
|
||||
deps := setup(ctx, t, tc.files)
|
||||
deps.ExtraEnv["FOO"] = testEnvValue
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
Steps: []resource.TestStep{
|
||||
// Initial state: cache has not been seeded.
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
PlanOnly: true,
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
// Should detect that no cached image is present and plan to create the resource.
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Computed values MUST be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "id", uuid.Nil.String()),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "exists", "false"),
|
||||
resource.TestCheckResourceAttrSet("envbuilder_cached_image.test", "env.0"),
|
||||
// Cached image should be set to the builder image.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "image", deps.BuilderImage),
|
||||
// Inputs should still be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "cache_repo", deps.CacheRepo),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "extra_env.FOO", "bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "git_url", deps.Repo.URL),
|
||||
// Should be empty
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_username"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_password"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "cache_ttl_days"),
|
||||
),
|
||||
ExpectNonEmptyPlan: true, // TODO: check the plan.
|
||||
},
|
||||
// Re-running plan should have the same effect.
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Computed values MUST be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "id", uuid.Nil.String()),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "exists", "false"),
|
||||
resource.TestCheckResourceAttrSet("envbuilder_cached_image.test", "env.0"),
|
||||
// Cached image should be set to the builder image.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "image", deps.BuilderImage),
|
||||
// Inputs should still be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "cache_repo", deps.CacheRepo),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "extra_env.FOO", "bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "git_url", deps.Repo.URL),
|
||||
// Should be empty
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_username"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_password"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "cache_ttl_days"),
|
||||
),
|
||||
ExpectNonEmptyPlan: true, // TODO: check the plan.
|
||||
},
|
||||
// Now, seed the cache and re-run. We should now successfully create the cached image resource.
|
||||
{
|
||||
PreConfig: func() {
|
||||
seedCache(ctx, t, deps)
|
||||
},
|
||||
Config: deps.Config(t),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
// Inputs should still be present.
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "cache_repo", deps.CacheRepo),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "extra_env.FOO", "bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "git_url", deps.Repo.URL),
|
||||
// Should be empty
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_username"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "git_password"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "cache_ttl_days"),
|
||||
// Computed
|
||||
resource.TestCheckResourceAttrWith("envbuilder_cached_image.test", "id", quotedPrefix("sha256:")),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "exists", "true"),
|
||||
resource.TestCheckResourceAttrSet("envbuilder_cached_image.test", "image"),
|
||||
resource.TestCheckResourceAttrWith("envbuilder_cached_image.test", "image", quotedPrefix(deps.CacheRepo)),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.0", "FOO=bar\nbaz"),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.1", fmt.Sprintf("ENVBUILDER_CACHE_REPO=%s", deps.CacheRepo)),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.2", fmt.Sprintf("ENVBUILDER_GIT_URL=%s", deps.Repo.URL)),
|
||||
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.3", "ENVBUILDER_REMOTE_REPO_BUILD_MODE=true"),
|
||||
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "env.4"),
|
||||
),
|
||||
},
|
||||
// Should produce an empty plan after apply
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
PlanOnly: true,
|
||||
},
|
||||
// Ensure idempotence in this state!
|
||||
{
|
||||
Config: deps.Config(t),
|
||||
PlanOnly: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue