Skip to content

Commit 1ff5764

Browse files
committed
fix(internal/provider): set all supported envbuilder options
1 parent 6cf3d93 commit 1ff5764

File tree

2 files changed

+133
-64
lines changed

2 files changed

+133
-64
lines changed

internal/provider/cached_image_resource.go

+123-59
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"github.com/hashicorp/terraform-plugin-framework/attr"
2727
"github.com/hashicorp/terraform-plugin-framework/diag"
28+
"github.com/hashicorp/terraform-plugin-framework/path"
2829
"github.com/hashicorp/terraform-plugin-framework/resource"
2930
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
3031
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
@@ -160,7 +161,6 @@ func (r *CachedImageResource) Schema(ctx context.Context, req resource.SchemaReq
160161
MarkdownDescription: "(Envbuilder option) Terminates upon a build failure. This is handy when preferring the FALLBACK_IMAGE in cases where no devcontainer.json or image is provided. However, it ensures that the container stops if the build process encounters an error.",
161162
Optional: true,
162163
},
163-
// TODO(mafredri): Map vs List? Support both?
164164
"extra_env": schema.MapAttribute{
165165
MarkdownDescription: "Extra environment variables to set for the container. This may include envbuilder options.",
166166
ElementType: types.StringType,
@@ -293,6 +293,124 @@ func (r *CachedImageResource) Configure(ctx context.Context, req resource.Config
293293
r.client = client
294294
}
295295

296+
// setComputedEnv sets data.Env and data.EnvMap based on the values of the
297+
// other fields in the model.
298+
func (data *CachedImageResourceModel) setComputedEnv(ctx context.Context) diag.Diagnostics {
299+
env := make(map[string]string)
300+
301+
env["ENVBUILDER_CACHE_REPO"] = tfValueToString(data.CacheRepo)
302+
env["ENVBUILDER_GIT_URL"] = tfValueToString(data.GitURL)
303+
304+
if !data.BaseImageCacheDir.IsNull() {
305+
env["ENVBUILDER_BASE_IMAGE_CACHE_DIR"] = tfValueToString(data.BaseImageCacheDir)
306+
}
307+
308+
if !data.BuildContextPath.IsNull() {
309+
env["ENVBUILDER_BUILD_CONTEXT_PATH"] = tfValueToString(data.BuildContextPath)
310+
}
311+
312+
if !data.CacheTTLDays.IsNull() {
313+
env["ENVBUILDER_CACHE_TTL_DAYS"] = tfValueToString(data.CacheTTLDays)
314+
}
315+
316+
if !data.DevcontainerDir.IsNull() {
317+
env["ENVBUILDER_DEVCONTAINER_DIR"] = tfValueToString(data.DevcontainerDir)
318+
}
319+
320+
if !data.DevcontainerJSONPath.IsNull() {
321+
env["ENVBUILDER_DEVCONTAINER_JSON_PATH"] = tfValueToString(data.DevcontainerJSONPath)
322+
}
323+
324+
if !data.DockerfilePath.IsNull() {
325+
env["ENVBUILDER_DOCKERFILE_PATH"] = tfValueToString(data.DockerfilePath)
326+
}
327+
328+
if !data.DockerConfigBase64.IsNull() {
329+
env["ENVBUILDER_DOCKER_CONFIG_BASE64"] = tfValueToString(data.DockerConfigBase64)
330+
}
331+
332+
if !data.ExitOnBuildFailure.IsNull() {
333+
env["ENVBUILDER_EXIT_ON_BUILD_FAILURE"] = tfValueToString(data.ExitOnBuildFailure)
334+
}
335+
336+
if !data.FallbackImage.IsNull() {
337+
env["ENVBUILDER_FALLBACK_IMAGE"] = tfValueToString(data.FallbackImage)
338+
}
339+
340+
if !data.GitCloneDepth.IsNull() {
341+
env["ENVBUILDER_GIT_CLONE_DEPTH"] = tfValueToString(data.GitCloneDepth)
342+
}
343+
344+
if !data.GitCloneSingleBranch.IsNull() {
345+
env["ENVBUILDER_GIT_CLONE_SINGLE_BRANCH"] = tfValueToString(data.GitCloneSingleBranch)
346+
}
347+
348+
if !data.GitHTTPProxyURL.IsNull() {
349+
env["ENVBUILDER_GIT_HTTP_PROXY_URL"] = tfValueToString(data.GitHTTPProxyURL)
350+
}
351+
352+
if !data.GitSSHPrivateKeyPath.IsNull() {
353+
env["ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH"] = tfValueToString(data.GitSSHPrivateKeyPath)
354+
}
355+
356+
if !data.GitUsername.IsNull() {
357+
env["ENVBUILDER_GIT_USERNAME"] = tfValueToString(data.GitUsername)
358+
}
359+
360+
if !data.GitPassword.IsNull() {
361+
env["ENVBUILDER_GIT_PASSWORD"] = tfValueToString(data.GitPassword)
362+
}
363+
364+
if !data.IgnorePaths.IsNull() {
365+
env["ENVBUILDER_IGNORE_PATHS"] = strings.Join(tfListToStringSlice(data.IgnorePaths), ",")
366+
}
367+
368+
if !data.Insecure.IsNull() {
369+
env["ENVBUILDER_INSECURE"] = tfValueToString(data.Insecure)
370+
}
371+
372+
// Default to remote build mode.
373+
if data.RemoteRepoBuildMode.IsNull() {
374+
env["ENVBUILDER_REMOTE_REPO_BUILD_MODE"] = "true"
375+
} else {
376+
env["ENVBUILDER_REMOTE_REPO_BUILD_MODE"] = tfValueToString(data.RemoteRepoBuildMode)
377+
}
378+
379+
if !data.SSLCertBase64.IsNull() {
380+
env["ENVBUILDER_SSL_CERT_BASE64"] = tfValueToString(data.SSLCertBase64)
381+
}
382+
383+
if !data.Verbose.IsNull() {
384+
env["ENVBUILDER_VERBOSE"] = tfValueToString(data.Verbose)
385+
}
386+
387+
if !data.WorkspaceFolder.IsNull() {
388+
env["ENVBUILDER_WORKSPACE_FOLDER"] = tfValueToString(data.WorkspaceFolder)
389+
}
390+
391+
// Do ExtraEnv last so that it can override any other values.
392+
var diag, ds diag.Diagnostics
393+
if !data.ExtraEnv.IsNull() {
394+
for key, elem := range data.ExtraEnv.Elements() {
395+
if _, ok := env[key]; ok {
396+
// This is a warning because it's possible that the user wants to override
397+
// a value set by the provider.
398+
diag.AddAttributeWarning(path.Root("extra_env"),
399+
"Overriding provider environment variable",
400+
fmt.Sprintf("The key %q in extra_env overrides an environment variable set by the provider.", key),
401+
)
402+
}
403+
env[key] = tfValueToString(elem)
404+
}
405+
}
406+
407+
data.EnvMap, ds = basetypes.NewMapValueFrom(ctx, types.StringType, env)
408+
diag = append(diag, ds...)
409+
data.Env, ds = basetypes.NewListValueFrom(ctx, types.StringType, sortedKeyValues(env))
410+
diag = append(diag, ds...)
411+
return diag
412+
}
413+
296414
func (r *CachedImageResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
297415
var data CachedImageResourceModel
298416

@@ -350,35 +468,7 @@ func (r *CachedImageResource) Read(ctx context.Context, req resource.ReadRequest
350468
data.Exists = types.BoolValue(true)
351469

352470
// Set the expected environment variables.
353-
env := make(map[string]string)
354-
for key, elem := range data.ExtraEnv.Elements() {
355-
env[key] = tfValueToString(elem)
356-
}
357-
358-
env["ENVBUILDER_CACHE_REPO"] = tfValueToString(data.CacheRepo)
359-
env["ENVBUILDER_GIT_URL"] = tfValueToString(data.GitURL)
360-
361-
if !data.CacheTTLDays.IsNull() {
362-
env["ENVBUILDER_CACHE_TTL_DAYS"] = tfValueToString(data.CacheTTLDays)
363-
}
364-
if !data.GitUsername.IsNull() {
365-
env["ENVBUILDER_GIT_USERNAME"] = tfValueToString(data.GitUsername)
366-
}
367-
if !data.GitPassword.IsNull() {
368-
env["ENVBUILDER_GIT_PASSWORD"] = tfValueToString(data.GitPassword)
369-
}
370-
// Default to remote build mode.
371-
if data.RemoteRepoBuildMode.IsNull() {
372-
env["ENVBUILDER_REMOTE_REPO_BUILD_MODE"] = "true"
373-
} else {
374-
env["ENVBUILDER_REMOTE_REPO_BUILD_MODE"] = tfValueToString(data.RemoteRepoBuildMode)
375-
}
376-
377-
var diag diag.Diagnostics
378-
data.EnvMap, diag = basetypes.NewMapValueFrom(ctx, types.StringType, env)
379-
resp.Diagnostics.Append(diag...)
380-
data.Env, diag = basetypes.NewListValueFrom(ctx, types.StringType, sortedKeyValues(env))
381-
resp.Diagnostics.Append(diag...)
471+
resp.Diagnostics.Append(data.setComputedEnv(ctx)...)
382472

383473
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
384474
}
@@ -415,36 +505,9 @@ func (r *CachedImageResource) Create(ctx context.Context, req resource.CreateReq
415505
data.Image = types.StringValue(fmt.Sprintf("%s@%s", data.CacheRepo.ValueString(), digest))
416506
data.ID = types.StringValue(digest.String())
417507
}
418-
// Compute the env attribute from the config map.
419-
env := make(map[string]string)
420-
for key, elem := range data.ExtraEnv.Elements() {
421-
env[key] = tfValueToString(elem)
422-
}
423508

424-
env["ENVBUILDER_CACHE_REPO"] = tfValueToString(data.CacheRepo)
425-
env["ENVBUILDER_GIT_URL"] = tfValueToString(data.GitURL)
426-
427-
if !data.CacheTTLDays.IsNull() {
428-
env["ENVBUILDER_CACHE_TTL_DAYS"] = tfValueToString(data.CacheTTLDays)
429-
}
430-
if !data.GitUsername.IsNull() {
431-
env["ENVBUILDER_GIT_USERNAME"] = tfValueToString(data.GitUsername)
432-
}
433-
if !data.GitPassword.IsNull() {
434-
env["ENVBUILDER_GIT_PASSWORD"] = tfValueToString(data.GitPassword)
435-
}
436-
// Default to remote build mode.
437-
if data.RemoteRepoBuildMode.IsNull() {
438-
env["ENVBUILDER_REMOTE_REPO_BUILD_MODE"] = "true"
439-
} else {
440-
env["ENVBUILDER_REMOTE_REPO_BUILD_MODE"] = tfValueToString(data.RemoteRepoBuildMode)
441-
}
442-
443-
var diag diag.Diagnostics
444-
data.EnvMap, diag = basetypes.NewMapValueFrom(ctx, types.StringType, env)
445-
resp.Diagnostics.Append(diag...)
446-
data.Env, diag = basetypes.NewListValueFrom(ctx, types.StringType, sortedKeyValues(env))
447-
resp.Diagnostics.Append(diag...)
509+
// Set the expected environment variables.
510+
resp.Diagnostics.Append(data.setComputedEnv(ctx)...)
448511

449512
// Save data into Terraform state
450513
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
@@ -556,6 +619,7 @@ func (r *CachedImageResource) runCacheProbe(ctx context.Context, data CachedImag
556619
Insecure: data.Insecure.ValueBool(), // might have internal CAs?
557620
IgnorePaths: tfListToStringSlice(data.IgnorePaths), // may need to be specified?
558621
// The below options are not relevant and are set to their zero value explicitly.
622+
// They must be set by extra_env.
559623
CoderAgentSubsystem: nil,
560624
CoderAgentToken: "",
561625
CoderAgentURL: "",

internal/provider/cached_image_resource_test.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,21 @@ func assertEnv(t *testing.T, deps testDependencies) resource.TestCheckFunc {
149149
return resource.ComposeAggregateTestCheckFunc(
150150
// Check that the environment variables are set correctly.
151151
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.0", fmt.Sprintf("ENVBUILDER_CACHE_REPO=%s", deps.CacheRepo)),
152-
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.1", fmt.Sprintf("ENVBUILDER_GIT_URL=%s", deps.Repo.URL)),
153-
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.2", "ENVBUILDER_REMOTE_REPO_BUILD_MODE=true"),
152+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.1", fmt.Sprintf("ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH=%s", deps.Repo.Key)),
153+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.2", fmt.Sprintf("ENVBUILDER_GIT_URL=%s", deps.Repo.URL)),
154+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.3", "ENVBUILDER_REMOTE_REPO_BUILD_MODE=true"),
155+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.4", "ENVBUILDER_VERBOSE=true"),
154156
// Check that the extra environment variables are set correctly.
155-
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.3", "FOO=bar\nbaz"),
157+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.5", "FOO=bar\nbaz"),
156158
// We should not have any other environment variables set.
157-
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "env.4"),
159+
resource.TestCheckNoResourceAttr("envbuilder_cached_image.test", "env.6"),
160+
158161
// Check that the same values are set in env_map.
159-
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.FOO", "bar\nbaz"),
160162
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.ENVBUILDER_CACHE_REPO", deps.CacheRepo),
163+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH", deps.Repo.Key),
161164
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.ENVBUILDER_GIT_URL", deps.Repo.URL),
162165
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.ENVBUILDER_REMOTE_REPO_BUILD_MODE", "true"),
166+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.ENVBUILDER_VERBOSE", "true"),
167+
resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env_map.FOO", "bar\nbaz"),
163168
)
164169
}

0 commit comments

Comments
 (0)