terraform-provider-envbuilder/internal/provider/provider_internal_test.go
Cian Johnston 4077a87dca
fix: set MagicDir to tempdir when performing cache probe ()
* fix: set MagicDir to tempdir when performing cache probe

* chore: update envbuilder to b7781d8

* imgutil: get default envbuilder binary path from envbuilder options
2024-09-10 09:47:39 +01:00

354 lines
13 KiB
Go

package provider
import (
"testing"
eboptions "github.com/coder/envbuilder/options"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/stretchr/testify/assert"
)
func Test_optionsFromDataModel(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
name string
data CachedImageResourceModel
expectOpts eboptions.Options
expectNumErrorDiags int
expectNumWarningDiags int
}{
{
name: "required only",
data: CachedImageResourceModel{
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
GitURL: basetypes.NewStringValue("git@git.local/devcontainer.git"),
},
expectOpts: eboptions.Options{
CacheRepo: "localhost:5000/cache",
GitURL: "git@git.local/devcontainer.git",
RemoteRepoBuildMode: true,
},
},
{
name: "all options without extra_env",
data: CachedImageResourceModel{
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
GitURL: basetypes.NewStringValue("git@git.local/devcontainer.git"),
BaseImageCacheDir: basetypes.NewStringValue("/tmp/cache"),
BuildContextPath: basetypes.NewStringValue("."),
CacheTTLDays: basetypes.NewInt64Value(7),
DevcontainerDir: basetypes.NewStringValue(".devcontainer"),
DevcontainerJSONPath: basetypes.NewStringValue(".devcontainer/devcontainer.json"),
DockerfilePath: basetypes.NewStringValue("Dockerfile"),
DockerConfigBase64: basetypes.NewStringValue("some base64"),
ExitOnBuildFailure: basetypes.NewBoolValue(true),
// ExtraEnv: map[string]basetypes.Value{},
FallbackImage: basetypes.NewStringValue("fallback"),
GitCloneDepth: basetypes.NewInt64Value(1),
GitCloneSingleBranch: basetypes.NewBoolValue(true),
GitHTTPProxyURL: basetypes.NewStringValue("http://proxy"),
GitPassword: basetypes.NewStringValue("password"),
GitSSHPrivateKeyPath: basetypes.NewStringValue("/tmp/id_rsa"),
GitUsername: basetypes.NewStringValue("user"),
IgnorePaths: listValue("ignore", "paths"),
Insecure: basetypes.NewBoolValue(true),
RemoteRepoBuildMode: basetypes.NewBoolValue(false),
SSLCertBase64: basetypes.NewStringValue("cert"),
Verbose: basetypes.NewBoolValue(true),
WorkspaceFolder: basetypes.NewStringValue("workspace"),
},
expectOpts: eboptions.Options{
CacheRepo: "localhost:5000/cache",
GitURL: "git@git.local/devcontainer.git",
BaseImageCacheDir: "/tmp/cache",
BuildContextPath: ".",
CacheTTLDays: 7,
DevcontainerDir: ".devcontainer",
DevcontainerJSONPath: ".devcontainer/devcontainer.json",
DockerfilePath: "Dockerfile",
DockerConfigBase64: "some base64",
ExitOnBuildFailure: true,
FallbackImage: "fallback",
GitCloneDepth: 1,
GitCloneSingleBranch: true,
GitHTTPProxyURL: "http://proxy",
GitPassword: "password",
GitSSHPrivateKeyPath: "/tmp/id_rsa",
GitUsername: "user",
IgnorePaths: []string{"ignore", "paths"},
Insecure: true,
RemoteRepoBuildMode: false,
SSLCertBase64: "cert",
Verbose: true,
WorkspaceFolder: "workspace",
},
},
{
name: "extra env override",
data: CachedImageResourceModel{
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
GitURL: basetypes.NewStringValue("git@git.local/devcontainer.git"),
ExtraEnv: extraEnvMap(t,
"CODER_AGENT_TOKEN", "token",
"CODER_AGENT_URL", "http://coder",
"FOO", "bar",
),
},
expectOpts: eboptions.Options{
CacheRepo: "localhost:5000/cache",
GitURL: "git@git.local/devcontainer.git",
RemoteRepoBuildMode: true,
CoderAgentToken: "token",
CoderAgentURL: "http://coder",
},
},
{
name: "extra_env override warnings",
data: CachedImageResourceModel{
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
GitURL: basetypes.NewStringValue("git@git.local/devcontainer.git"),
BaseImageCacheDir: basetypes.NewStringValue("/tmp/cache"),
BuildContextPath: basetypes.NewStringValue("."),
CacheTTLDays: basetypes.NewInt64Value(7),
DevcontainerDir: basetypes.NewStringValue(".devcontainer"),
DevcontainerJSONPath: basetypes.NewStringValue(".devcontainer/devcontainer.json"),
DockerfilePath: basetypes.NewStringValue("Dockerfile"),
DockerConfigBase64: basetypes.NewStringValue("some base64"),
ExitOnBuildFailure: basetypes.NewBoolValue(true),
// ExtraEnv: map[string]basetypes.Value{},
FallbackImage: basetypes.NewStringValue("fallback"),
GitCloneDepth: basetypes.NewInt64Value(1),
GitCloneSingleBranch: basetypes.NewBoolValue(true),
GitHTTPProxyURL: basetypes.NewStringValue("http://proxy"),
GitPassword: basetypes.NewStringValue("password"),
GitSSHPrivateKeyPath: basetypes.NewStringValue("/tmp/id_rsa"),
GitUsername: basetypes.NewStringValue("user"),
IgnorePaths: listValue("ignore", "paths"),
Insecure: basetypes.NewBoolValue(true),
RemoteRepoBuildMode: basetypes.NewBoolValue(false),
SSLCertBase64: basetypes.NewStringValue("cert"),
Verbose: basetypes.NewBoolValue(true),
WorkspaceFolder: basetypes.NewStringValue("workspace"),
ExtraEnv: extraEnvMap(t,
"ENVBUILDER_CACHE_REPO", "override",
"ENVBUILDER_GIT_URL", "override",
"ENVBUILDER_BASE_IMAGE_CACHE_DIR", "override",
"ENVBUILDER_BUILD_CONTEXT_PATH", "override",
"ENVBUILDER_CACHE_TTL_DAYS", "8",
"ENVBUILDER_DEVCONTAINER_DIR", "override",
"ENVBUILDER_DEVCONTAINER_JSON_PATH", "override",
"ENVBUILDER_DOCKERFILE_PATH", "override",
"ENVBUILDER_DOCKER_CONFIG_BASE64", "override",
"ENVBUILDER_EXIT_ON_BUILD_FAILURE", "false",
"ENVBUILDER_FALLBACK_IMAGE", "override",
"ENVBUILDER_GIT_CLONE_DEPTH", "2",
"ENVBUILDER_GIT_CLONE_SINGLE_BRANCH", "false",
"ENVBUILDER_GIT_HTTP_PROXY_URL", "override",
"ENVBUILDER_GIT_PASSWORD", "override",
"ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH", "override",
"ENVBUILDER_GIT_USERNAME", "override",
"ENVBUILDER_IGNORE_PATHS", "override",
"ENVBUILDER_INSECURE", "false",
"ENVBUILDER_REMOTE_REPO_BUILD_MODE", "true",
"ENVBUILDER_SSL_CERT_BASE64", "override",
"ENVBUILDER_VERBOSE", "false",
"ENVBUILDER_WORKSPACE_FOLDER", "override",
"FOO", "bar",
),
},
expectOpts: eboptions.Options{
// not overridden
CacheRepo: "localhost:5000/cache",
GitURL: "git@git.local/devcontainer.git",
// overridden
BaseImageCacheDir: "override",
BuildContextPath: "override",
CacheTTLDays: 8,
DevcontainerDir: "override",
DevcontainerJSONPath: "override",
DockerfilePath: "override",
DockerConfigBase64: "override",
ExitOnBuildFailure: false,
FallbackImage: "override",
GitCloneDepth: 2,
GitCloneSingleBranch: false,
GitHTTPProxyURL: "override",
GitPassword: "override",
GitSSHPrivateKeyPath: "override",
GitUsername: "override",
IgnorePaths: []string{"override"},
Insecure: false,
RemoteRepoBuildMode: true,
SSLCertBase64: "override",
Verbose: false,
WorkspaceFolder: "override",
},
expectNumWarningDiags: 23,
},
{
name: "extra_env override errors",
data: CachedImageResourceModel{
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
GitURL: basetypes.NewStringValue("git@git.local/devcontainer.git"),
ExtraEnv: extraEnvMap(t,
"ENVBUILDER_CACHE_TTL_DAYS", "not a number",
"ENVBUILDER_VERBOSE", "not a bool",
"FOO", "bar",
),
},
expectOpts: eboptions.Options{
// not overridden
CacheRepo: "localhost:5000/cache",
GitURL: "git@git.local/devcontainer.git",
RemoteRepoBuildMode: true,
},
expectNumErrorDiags: 2,
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
actual, diags := optionsFromDataModel(tc.data)
assert.Equal(t, tc.expectNumErrorDiags, diags.ErrorsCount())
assert.Equal(t, tc.expectNumWarningDiags, diags.WarningsCount())
assert.EqualValues(t, tc.expectOpts, actual)
})
}
}
func Test_computeEnvFromOptions(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
name string
opts eboptions.Options
extraEnv map[string]string
expectEnv map[string]string
}{
{
name: "empty",
opts: eboptions.Options{},
expectEnv: map[string]string{},
},
{
name: "all options",
opts: eboptions.Options{
BaseImageCacheDir: "string",
BinaryPath: "string",
BuildContextPath: "string",
CacheRepo: "string",
CacheTTLDays: 1,
CoderAgentSubsystem: []string{"one", "two"},
CoderAgentToken: "string",
CoderAgentURL: "string",
DevcontainerDir: "string",
DevcontainerJSONPath: "string",
DockerConfigBase64: "string",
DockerfilePath: "string",
ExitOnBuildFailure: true,
ExportEnvFile: "string",
FallbackImage: "string",
ForceSafe: true,
GetCachedImage: true,
GitCloneDepth: 1,
GitCloneSingleBranch: true,
GitHTTPProxyURL: "string",
GitPassword: "string",
GitSSHPrivateKeyPath: "string",
GitURL: "string",
GitUsername: "string",
IgnorePaths: []string{"one", "two"},
InitArgs: "string",
InitCommand: "string",
InitScript: "string",
Insecure: true,
LayerCacheDir: "string",
PostStartScriptPath: "string",
PushImage: true,
RemoteRepoBuildMode: true,
SetupScript: "string",
SkipRebuild: true,
SSLCertBase64: "string",
Verbose: true,
WorkspaceFolder: "string",
},
extraEnv: map[string]string{
"ENVBUILDER_SOMETHING": "string", // should be ignored
"FOO": "bar", // should be included
},
expectEnv: map[string]string{
"ENVBUILDER_BASE_IMAGE_CACHE_DIR": "string",
"ENVBUILDER_BINARY_PATH": "string",
"ENVBUILDER_BUILD_CONTEXT_PATH": "string",
"ENVBUILDER_CACHE_REPO": "string",
"ENVBUILDER_CACHE_TTL_DAYS": "1",
"ENVBUILDER_DEVCONTAINER_DIR": "string",
"ENVBUILDER_DEVCONTAINER_JSON_PATH": "string",
"ENVBUILDER_DOCKER_CONFIG_BASE64": "string",
"ENVBUILDER_DOCKERFILE_PATH": "string",
"ENVBUILDER_EXIT_ON_BUILD_FAILURE": "true",
"ENVBUILDER_EXPORT_ENV_FILE": "string",
"ENVBUILDER_FALLBACK_IMAGE": "string",
"ENVBUILDER_FORCE_SAFE": "true",
"ENVBUILDER_GET_CACHED_IMAGE": "true",
"ENVBUILDER_GIT_CLONE_DEPTH": "1",
"ENVBUILDER_GIT_CLONE_SINGLE_BRANCH": "true",
"ENVBUILDER_GIT_HTTP_PROXY_URL": "string",
"ENVBUILDER_GIT_PASSWORD": "string",
"ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH": "string",
"ENVBUILDER_GIT_URL": "string",
"ENVBUILDER_GIT_USERNAME": "string",
"ENVBUILDER_IGNORE_PATHS": "one,two",
"ENVBUILDER_INIT_ARGS": "string",
"ENVBUILDER_INIT_COMMAND": "string",
"ENVBUILDER_INIT_SCRIPT": "string",
"ENVBUILDER_INSECURE": "true",
"ENVBUILDER_LAYER_CACHE_DIR": "string",
"ENVBUILDER_POST_START_SCRIPT_PATH": "string",
"ENVBUILDER_PUSH_IMAGE": "true",
"ENVBUILDER_REMOTE_REPO_BUILD_MODE": "true",
"ENVBUILDER_SETUP_SCRIPT": "string",
"ENVBUILDER_SKIP_REBUILD": "true",
"ENVBUILDER_SSL_CERT_BASE64": "string",
"ENVBUILDER_VERBOSE": "true",
"ENVBUILDER_WORKSPACE_FOLDER": "string",
"FOO": "bar",
},
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if tc.extraEnv == nil {
tc.extraEnv = map[string]string{}
}
actual := computeEnvFromOptions(tc.opts, tc.extraEnv)
assert.EqualValues(t, tc.expectEnv, actual)
})
}
}
func listValue(vs ...string) basetypes.ListValue {
vals := make([]attr.Value, len(vs))
for i, s := range vs {
vals[i] = basetypes.NewStringValue(s)
}
return basetypes.NewListValueMust(basetypes.StringType{}, vals)
}
func extraEnvMap(t *testing.T, kvs ...string) basetypes.MapValue {
t.Helper()
if len(kvs)%2 != 0 {
t.Fatalf("extraEnvMap: expected even number of key-value pairs, got %d", len(kvs))
}
vals := make(map[string]attr.Value)
for i := 0; i < len(kvs); i += 2 {
vals[kvs[i]] = basetypes.NewStringValue(kvs[i+1])
}
return basetypes.NewMapValueMust(basetypes.StringType{}, vals)
}