diff --git a/tfexec/internal/e2etest/show_test.go b/tfexec/internal/e2etest/show_test.go index 77b458ac..078b3ee4 100644 --- a/tfexec/internal/e2etest/show_test.go +++ b/tfexec/internal/e2etest/show_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "reflect" + "runtime" "testing" "github.com/davecgh/go-spew/spew" @@ -11,6 +12,7 @@ import ( tfjson "github.com/hashicorp/terraform-json" "github.com/hashicorp/terraform-exec/tfexec" + "github.com/hashicorp/terraform-exec/tfexec/internal/testutil" ) var ( @@ -104,3 +106,214 @@ func TestShow_versionMismatch(t *testing.T) { } }) } + +// Non-default state files cannot be migrated from 0.12 to 0.13, +// so we maintain one fixture per supported version. +// See github.com/hashicorp/terraform/25920 +func TestShowStateFile012(t *testing.T) { + runTestVersions(t, []string{testutil.Latest012}, "non_default_statefile_012", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) { + expected := tfjson.State{ + FormatVersion: "0.1", + TerraformVersion: "0.12.29", + Values: &tfjson.StateValues{ + RootModule: &tfjson.StateModule{ + Resources: []*tfjson.StateResource{{ + Address: "null_resource.foo", + AttributeValues: map[string]interface{}{ + "id": "3610244792381545397", + "triggers": nil, + }, + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderName: "null", + }}, + }, + }, + } + + err := tf.Init(context.Background()) + if err != nil { + t.Fatalf("error running Init in test directory: %s", err) + } + + actual, err := tf.ShowStateFile(context.Background(), "statefilefoo") + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(actual, &expected) { + t.Fatalf("actual: %s\nexpected: %s", spew.Sdump(actual), spew.Sdump(expected)) + } + }) +} + +func TestShowStateFile013(t *testing.T) { + runTestVersions(t, []string{testutil.Latest013}, "non_default_statefile_013", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) { + expected := tfjson.State{ + FormatVersion: "0.1", + TerraformVersion: "0.13.0", + Values: &tfjson.StateValues{ + RootModule: &tfjson.StateModule{ + Resources: []*tfjson.StateResource{{ + Address: "null_resource.foo", + AttributeValues: map[string]interface{}{ + "id": "3610244792381545397", + "triggers": nil, + }, + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderName: "registry.terraform.io/hashicorp/null", + }}, + }, + }, + } + + err := tf.Init(context.Background()) + if err != nil { + t.Fatalf("error running Init in test directory: %s", err) + } + + actual, err := tf.ShowStateFile(context.Background(), "statefilefoo") + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(actual, &expected) { + t.Fatalf("actual: %s\nexpected: %s", spew.Sdump(actual), spew.Sdump(expected)) + } + }) +} + +// Plan files cannot be transferred between different Terraform versions, +// so we maintain one fixture per supported version +func TestShowPlanFile012(t *testing.T) { + runTestVersions(t, []string{testutil.Latest012}, "non_default_planfile_012", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) { + // plan file fixture was created in Linux, and is + // not compatible with Windows + if runtime.GOOS == "windows" { + t.Skip("plan file created in 0.12 on Linux is not compatible with Windows") + } + + providerName := "null" + + expected := tfjson.Plan{ + FormatVersion: "0.1", + TerraformVersion: "0.12.29", + PlannedValues: &tfjson.StateValues{ + RootModule: &tfjson.StateModule{ + Resources: []*tfjson.StateResource{{ + Address: "null_resource.foo", + AttributeValues: map[string]interface{}{ + "triggers": nil, + }, + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderName: providerName, + }}, + }, + }, + ResourceChanges: []*tfjson.ResourceChange{{ + Address: "null_resource.foo", + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderName: providerName, + Change: &tfjson.Change{ + Actions: tfjson.Actions{tfjson.ActionCreate}, + After: map[string]interface{}{"triggers": nil}, + AfterUnknown: map[string]interface{}{"id": (true)}, + }, + }}, + Config: &tfjson.Config{ + RootModule: &tfjson.ConfigModule{ + Resources: []*tfjson.ConfigResource{{ + Address: "null_resource.foo", + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderConfigKey: "null", + }}, + }, + }, + } + + err := tf.Init(context.Background()) + if err != nil { + t.Fatalf("error running Init in test directory: %s", err) + } + + actual, err := tf.ShowPlanFile(context.Background(), "planfilefoo") + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(actual, &expected) { + t.Fatalf("actual: %s\nexpected: %s", spew.Sdump(actual), spew.Sdump(expected)) + } + }) +} + +func TestShowPlanFile013(t *testing.T) { + runTestVersions(t, []string{testutil.Latest013}, "non_default_planfile_013", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) { + providerName := "registry.terraform.io/hashicorp/null" + + expected := tfjson.Plan{ + FormatVersion: "0.1", + TerraformVersion: "0.13.0", + PlannedValues: &tfjson.StateValues{ + RootModule: &tfjson.StateModule{ + Resources: []*tfjson.StateResource{{ + Address: "null_resource.foo", + AttributeValues: map[string]interface{}{ + "triggers": nil, + }, + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderName: providerName, + }}, + }, + }, + ResourceChanges: []*tfjson.ResourceChange{{ + Address: "null_resource.foo", + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderName: providerName, + Change: &tfjson.Change{ + Actions: tfjson.Actions{tfjson.ActionCreate}, + After: map[string]interface{}{"triggers": nil}, + AfterUnknown: map[string]interface{}{"id": true}, + }, + }}, + Config: &tfjson.Config{ + RootModule: &tfjson.ConfigModule{ + Resources: []*tfjson.ConfigResource{{ + Address: "null_resource.foo", + Mode: tfjson.ManagedResourceMode, + Type: "null_resource", + Name: "foo", + ProviderConfigKey: "null", + }}, + }, + }, + } + + err := tf.Init(context.Background()) + if err != nil { + t.Fatalf("error running Init in test directory: %s", err) + } + + actual, err := tf.ShowPlanFile(context.Background(), "planfilefoo") + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(actual, &expected) { + t.Fatalf("actual: %s\nexpected: %s", spew.Sdump(actual), spew.Sdump(expected)) + } + }) +} diff --git a/tfexec/internal/e2etest/testdata/non_default_planfile_012/main.tf b/tfexec/internal/e2etest/testdata/non_default_planfile_012/main.tf new file mode 100644 index 00000000..fca4eb6d --- /dev/null +++ b/tfexec/internal/e2etest/testdata/non_default_planfile_012/main.tf @@ -0,0 +1,3 @@ +resource null_resource "foo" { +} + diff --git a/tfexec/internal/e2etest/testdata/non_default_planfile_012/planfilefoo b/tfexec/internal/e2etest/testdata/non_default_planfile_012/planfilefoo new file mode 100644 index 00000000..9da65dcf Binary files /dev/null and b/tfexec/internal/e2etest/testdata/non_default_planfile_012/planfilefoo differ diff --git a/tfexec/internal/e2etest/testdata/non_default_planfile_013/main.tf b/tfexec/internal/e2etest/testdata/non_default_planfile_013/main.tf new file mode 100644 index 00000000..fca4eb6d --- /dev/null +++ b/tfexec/internal/e2etest/testdata/non_default_planfile_013/main.tf @@ -0,0 +1,3 @@ +resource null_resource "foo" { +} + diff --git a/tfexec/internal/e2etest/testdata/non_default_planfile_013/planfilefoo b/tfexec/internal/e2etest/testdata/non_default_planfile_013/planfilefoo new file mode 100644 index 00000000..b8658a75 Binary files /dev/null and b/tfexec/internal/e2etest/testdata/non_default_planfile_013/planfilefoo differ diff --git a/tfexec/internal/e2etest/testdata/non_default_statefile_012/main.tf b/tfexec/internal/e2etest/testdata/non_default_statefile_012/main.tf new file mode 100644 index 00000000..fca4eb6d --- /dev/null +++ b/tfexec/internal/e2etest/testdata/non_default_statefile_012/main.tf @@ -0,0 +1,3 @@ +resource null_resource "foo" { +} + diff --git a/tfexec/internal/e2etest/testdata/non_default_statefile_012/statefilefoo b/tfexec/internal/e2etest/testdata/non_default_statefile_012/statefilefoo new file mode 100644 index 00000000..48785900 --- /dev/null +++ b/tfexec/internal/e2etest/testdata/non_default_statefile_012/statefilefoo @@ -0,0 +1,25 @@ +{ + "version": 4, + "terraform_version": "0.12.29", + "serial": 1, + "lineage": "b69e96b9-250f-2004-c603-1b11dc3459c1", + "outputs": {}, + "resources": [ + { + "mode": "managed", + "type": "null_resource", + "name": "foo", + "provider": "provider.null", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "3610244792381545397", + "triggers": null + }, + "private": "bnVsbA==" + } + ] + } + ] +} diff --git a/tfexec/internal/e2etest/testdata/non_default_statefile_013/main.tf b/tfexec/internal/e2etest/testdata/non_default_statefile_013/main.tf new file mode 100644 index 00000000..fca4eb6d --- /dev/null +++ b/tfexec/internal/e2etest/testdata/non_default_statefile_013/main.tf @@ -0,0 +1,3 @@ +resource null_resource "foo" { +} + diff --git a/tfexec/internal/e2etest/testdata/non_default_statefile_013/statefilefoo b/tfexec/internal/e2etest/testdata/non_default_statefile_013/statefilefoo new file mode 100644 index 00000000..2af868b8 --- /dev/null +++ b/tfexec/internal/e2etest/testdata/non_default_statefile_013/statefilefoo @@ -0,0 +1,25 @@ +{ + "version": 4, + "terraform_version": "0.13.0", + "serial": 1, + "lineage": "b69e96b9-250f-2004-c603-1b11dc3459c1", + "outputs": {}, + "resources": [ + { + "mode": "managed", + "type": "null_resource", + "name": "foo", + "provider": "provider[\"registry.terraform.io/hashicorp/null\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "3610244792381545397", + "triggers": null + }, + "private": "bnVsbA==" + } + ] + } + ] +} diff --git a/tfexec/internal/e2etest/util_test.go b/tfexec/internal/e2etest/util_test.go index faf50454..4dd87190 100644 --- a/tfexec/internal/e2etest/util_test.go +++ b/tfexec/internal/e2etest/util_test.go @@ -27,8 +27,6 @@ func runTest(t *testing.T, fixtureName string, cb func(t *testing.T, tfVersion * }, fixtureName, cb) } -// runTestVersions should probably not be used directly, better to use -// t.Skip in your test with a comment as to why you shouldn't test on a version func runTestVersions(t *testing.T, versions []string, fixtureName string, cb func(t *testing.T, tfVersion *version.Version, tf *tfexec.Terraform)) { t.Helper()