diff --git a/GNUmakefile b/GNUmakefile index 91fdce3..800fcb9 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -36,7 +36,7 @@ test-registry: test-registry-container test-images-pull test-images-push test-registry-container: .registry-cache if ! curl -fsSL http://localhost:5000/v2/_catalog > /dev/null 2>&1; then \ docker rm -f tfprov-envbuilder-registry && \ - docker run -d -p 5000:5000 --name envbuilder-registry --volume $(PWD)/.registry-cache:/var/lib/registry registry:2; \ + docker run -d -p 5000:5000 --name tfprov-envbuilder-registry --volume $(PWD)/.registry-cache:/var/lib/registry registry:2; \ fi # Pulls images referenced in integration tests and pushes them to the local cache. diff --git a/docs/resources/cached_image.md b/docs/resources/cached_image.md index 3efc2d8..8498720 100644 --- a/docs/resources/cached_image.md +++ b/docs/resources/cached_image.md @@ -41,6 +41,7 @@ The cached image resource can be used to retrieve a cached image produced by env - `git_username` (String) (Envbuilder option) The username to use for Git authentication. This is optional. - `ignore_paths` (List of String) (Envbuilder option) The comma separated list of paths to ignore when building the workspace. - `insecure` (Boolean) (Envbuilder option) Bypass TLS verification when cloning and pulling from container registries. +- `remote_repo_build_mode` (Boolean) (Envbuilder option) RemoteRepoBuildMode uses the remote repository as the source of truth when building the image. Enabling this option ignores user changes to local files and they will not be reflected in the image. This can be used to improve cache utilization when multiple users are working on the same repository. (NOTE: The Terraform provider will **always** use remote repo build mode for probing the cache repo.) - `ssl_cert_base64` (String) (Envbuilder option) The content of an SSL cert file. This is useful for self-signed certificates. - `verbose` (Boolean) (Envbuilder option) Enable verbose output. - `workspace_folder` (String) (Envbuilder option) path to the workspace folder that will be built. This is optional. diff --git a/internal/provider/cached_image_resource.go b/internal/provider/cached_image_resource.go index aedb8a1..4cbdfce 100644 --- a/internal/provider/cached_image_resource.go +++ b/internal/provider/cached_image_resource.go @@ -70,6 +70,7 @@ type CachedImageResourceModel struct { GitUsername types.String `tfsdk:"git_username"` IgnorePaths types.List `tfsdk:"ignore_paths"` Insecure types.Bool `tfsdk:"insecure"` + RemoteRepoBuildMode types.Bool `tfsdk:"remote_repo_build_mode"` SSLCertBase64 types.String `tfsdk:"ssl_cert_base64"` Verbose types.Bool `tfsdk:"verbose"` WorkspaceFolder types.String `tfsdk:"workspace_folder"` @@ -203,6 +204,13 @@ func (r *CachedImageResource) Schema(ctx context.Context, req resource.SchemaReq MarkdownDescription: "(Envbuilder option) Bypass TLS verification when cloning and pulling from container registries.", Optional: true, }, + "remote_repo_build_mode": schema.BoolAttribute{ + MarkdownDescription: "(Envbuilder option) RemoteRepoBuildMode uses the remote repository as the source of truth when building the image. Enabling this option ignores user changes to local files and they will not be reflected in the image. This can be used to improve cache utilization when multiple users are working on the same repository. (NOTE: The Terraform provider will **always** use remote repo build mode for probing the cache repo.)", + Optional: true, + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.RequiresReplace(), + }, + }, "ssl_cert_base64": schema.StringAttribute{ MarkdownDescription: "(Envbuilder option) The content of an SSL cert file. This is useful for self-signed certificates.", Optional: true, @@ -330,6 +338,12 @@ func (r *CachedImageResource) Read(ctx context.Context, req resource.ReadRequest if !data.GitPassword.IsNull() { data.Env = appendKnownEnvToList(data.Env, "ENVBUILDER_GIT_PASSWORD", data.GitPassword) } + // Default to remote build mode. + if data.RemoteRepoBuildMode.IsNull() { + data.Env = appendKnownEnvToList(data.Env, "ENVBUILDER_REMOTE_REPO_BUILD_MODE", types.BoolValue(true)) + } else { + data.Env = appendKnownEnvToList(data.Env, "ENVBUILDER_REMOTE_REPO_BUILD_MODE", data.RemoteRepoBuildMode) + } resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } @@ -379,6 +393,12 @@ func (r *CachedImageResource) Create(ctx context.Context, req resource.CreateReq if !data.GitPassword.IsNull() { data.Env = appendKnownEnvToList(data.Env, "ENVBUILDER_GIT_PASSWORD", data.GitPassword) } + // Default to remote build mode. + if data.RemoteRepoBuildMode.IsNull() { + data.Env = appendKnownEnvToList(data.Env, "ENVBUILDER_REMOTE_REPO_BUILD_MODE", types.BoolValue(true)) + } else { + data.Env = appendKnownEnvToList(data.Env, "ENVBUILDER_REMOTE_REPO_BUILD_MODE", data.RemoteRepoBuildMode) + } // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) @@ -479,6 +499,8 @@ func (r *CachedImageResource) runCacheProbe(ctx context.Context, data CachedImag GitPassword: data.GitPassword.ValueString(), GitSSHPrivateKeyPath: data.GitSSHPrivateKeyPath.ValueString(), GitHTTPProxyURL: data.GitHTTPProxyURL.ValueString(), + RemoteRepoBuildMode: data.RemoteRepoBuildMode.ValueBool(), + RemoteRepoDir: filepath.Join(tmpDir, "repo"), SSLCertBase64: data.SSLCertBase64.ValueString(), // Other options diff --git a/internal/provider/cached_image_resource_test.go b/internal/provider/cached_image_resource_test.go index 5d07371..e57ce8a 100644 --- a/internal/provider/cached_image_resource_test.go +++ b/internal/provider/cached_image_resource_test.go @@ -95,6 +95,8 @@ func TestAccCachedImageDataSource(t *testing.T) { resource.TestCheckResourceAttr("envbuilder_cached_image.test", "env.0", "FOO=bar"), 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 diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index f5ee889..59f21ed 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -57,7 +57,6 @@ resource "envbuilder_cached_image" "test" { git_url = {{ quote .Repo.URL }} git_ssh_private_key_path = {{ quote .Repo.Key }} verbose = true - workspace_folder = {{ quote .Repo.Dir }} }` fm := template.FuncMap{"quote": quote} @@ -131,10 +130,12 @@ func seedCache(ctx context.Context, t testing.TB, deps testDependencies) { require.NoError(t, err, "failed to run envbuilder to seed cache") t.Cleanup(func() { - _ = cli.ContainerRemove(ctx, ctr.ID, container.RemoveOptions{ + if err := cli.ContainerRemove(context.Background(), ctr.ID, container.RemoveOptions{ RemoveVolumes: true, Force: true, - }) + }); err != nil { + t.Errorf("removing container: %s", err.Error()) + } }) err = cli.ContainerStart(ctx, ctr.ID, container.StartOptions{}) require.NoError(t, err)