diff --git a/tfexec/terraform_test.go b/tfexec/terraform_test.go index d59aed9..d8145d7 100644 --- a/tfexec/terraform_test.go +++ b/tfexec/terraform_test.go @@ -93,13 +93,13 @@ func TestTerraformCLIRun(t *testing.T) { func TestAccTerraformCLIOverrideBackendToLocal(t *testing.T) { SkipUnlessAcceptanceTestEnabled(t) - backend := GetTestAccBackendS3Config(t.Name()) + backend := GetTestAccBackendS3Config(t.Name(), false) source := ` resource "aws_security_group" "foo" {} resource "aws_security_group" "bar" {} ` workspace := "work1" - terraformCLI := SetupTestAccWithApply(t, workspace, backend+source) + terraformCLI := SetupTestAccWithApply(t, workspace, backend+source, nil) updatedSource := ` resource "aws_security_group" "foo2" {} @@ -162,6 +162,79 @@ resource "aws_security_group" "bar" {} } } +func TestAccTerraformCLIOverrideBackendToLocalWithBackendConfig(t *testing.T) { + SkipUnlessAcceptanceTestEnabled(t) + + backend := GetTestAccBackendS3Config(t.Name(), true) + source := ` +resource "aws_security_group" "foo" {} +resource "aws_security_group" "bar" {} +` + workspace := "work1" + backendConfig := []string{"bucket=tfstate-test"} + terraformCLI := SetupTestAccWithApply(t, workspace, backend+source, backendConfig) + + updatedSource := ` +resource "aws_security_group" "foo2" {} +resource "aws_security_group" "bar" {} +` + UpdateTestAccSource(t, terraformCLI, backend+updatedSource) + + changed, err := terraformCLI.PlanHasChange(context.Background(), nil) + if err != nil { + t.Fatalf("failed to run PlanHasChange: %s", err) + } + if !changed { + t.Fatalf("expect to have changes") + } + + state, err := terraformCLI.StatePull(context.Background()) + if err != nil { + t.Fatalf("failed to run terraform state pull: %s", err) + } + + filename := "_tfexec_override.tf" + if _, err := os.Stat(filepath.Join(terraformCLI.Dir(), filename)); err == nil { + t.Fatalf("an override file already exists: %s", err) + } + + switchBackToRemotekFunc, err := terraformCLI.OverrideBackendToLocal(context.Background(), filename, workspace, false, backendConfig) + if err != nil { + t.Fatalf("failed to run OverrideBackendToLocal: %s", err) + } + + if _, err := os.Stat(filepath.Join(terraformCLI.Dir(), filename)); os.IsNotExist(err) { + t.Fatalf("the override file does not exist: %s", err) + } + + updatedState, _, err := terraformCLI.StateMv(context.Background(), state, nil, "aws_security_group.foo", "aws_security_group.foo2") + if err != nil { + t.Fatalf("failed to run terraform state mv: %s", err) + } + + changed, err = terraformCLI.PlanHasChange(context.Background(), updatedState) + if err != nil { + t.Fatalf("failed to run PlanHasChange: %s", err) + } + if changed { + t.Fatalf("expect not to have changes") + } + + switchBackToRemotekFunc() + + if _, err := os.Stat(filepath.Join(terraformCLI.Dir(), filename)); err == nil { + t.Fatalf("the override file wasn't removed: %s", err) + } + + changed, err = terraformCLI.PlanHasChange(context.Background(), nil) + if err != nil { + t.Fatalf("failed to run PlanHasChange: %s", err) + } + if !changed { + t.Fatalf("expect to have changes") + } +} + func TestAccTerraformCLIPlanHasChange(t *testing.T) { SkipUnlessAcceptanceTestEnabled(t) diff --git a/tfexec/test_helper.go b/tfexec/test_helper.go index 0a7568c..b6d4858 100644 --- a/tfexec/test_helper.go +++ b/tfexec/test_helper.go @@ -233,19 +233,20 @@ func setupTestPluginCacheDir(e Executor) error { // GetTestAccBackendS3Config returns mocked backend s3 config for testing. // Its endpoint can be set via LOCALSTACK_ENDPOINT environment variable. // default to "http://localhost:4566" -func GetTestAccBackendS3Config(dir string) string { +func GetTestAccBackendS3Config(dir string, skipS3Bucket bool) string { endpoint := "http://localhost:4566" localstackEndpoint := os.Getenv("LOCALSTACK_ENDPOINT") if len(localstackEndpoint) > 0 { endpoint = localstackEndpoint } - backendConfig := fmt.Sprintf(` + var backendConfig string + if skipS3Bucket { + backendConfig = fmt.Sprintf(` terraform { # https://www.terraform.io/docs/backends/types/s3.html backend "s3" { region = "ap-northeast-1" - bucket = "tfstate-test" key = "%s/terraform.tfstate" // mock s3 endpoint with localstack @@ -257,7 +258,28 @@ terraform { force_path_style = true } } +`, dir, endpoint) + } else { + backendConfig = fmt.Sprintf(` +terraform { + # https://www.terraform.io/docs/backends/types/s3.html + backend "s3" { + region = "ap-northeast-1" + bucket = "tfstate-test" + key = "%s/terraform.tfstate" + // mock s3 endpoint with localstack + endpoint = "%s" + access_key = "dummy" + secret_key = "dummy" + skip_credentials_validation = true + skip_metadata_api_check = true + force_path_style = true + } +} +`, dir, endpoint) + } + backendConfig += fmt.Sprintf(` # https://www.terraform.io/docs/providers/aws/index.html # https://www.terraform.io/docs/providers/aws/guides/custom-service-endpoints.html#localstack provider "aws" { @@ -278,20 +300,20 @@ provider "aws" { iam = "%s" } } -`, dir, endpoint, endpoint, endpoint, endpoint) +`, endpoint, endpoint, endpoint) return backendConfig } // SetupTestAccWithApply is an acceptance test helper for initializing a // temporary work directory and applying a given source. -func SetupTestAccWithApply(t *testing.T, workspace string, source string) TerraformCLI { +func SetupTestAccWithApply(t *testing.T, workspace string, source string, backendConfig []string) TerraformCLI { t.Helper() e := SetupTestAcc(t, source) tf := NewTerraformCLI(e) ctx := context.Background() - err := tf.Init(ctx, nil, "-input=false", "-no-color") + err := tf.Init(ctx, backendConfig, "-input=false", "-no-color") if err != nil { t.Fatalf("failed to run terraform init: %s", err) }