Skip to content

Commit

Permalink
add Show tests for uninitialised backends/modules
Browse files Browse the repository at this point in the history
  • Loading branch information
kmoe committed Jan 31, 2022
1 parent cd44940 commit f491a7c
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 11 deletions.
20 changes: 15 additions & 5 deletions tfexec/exit_errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,18 @@ var (

usageRegexp = regexp.MustCompile(`Too many command line arguments|^Usage: .*Options:.*|Error: Invalid -\d+ option`)

noInitErrRegexp = regexp.MustCompile(`Error: Could not satisfy plugin requirements|` +
`Error: Could not load plugin|` + // v0.13
`Please run \"terraform init\"|` + // v1.1.0 early alpha versions (ref 89b05050)
`run:\s+terraform init`) // v1.1.0 (ref df578afd)
noInitErrRegexp = regexp.MustCompile(
// UNINITIALISED PROVIDERS/MODULES
`Error: Could not satisfy plugin requirements|` +
`Error: Could not load plugin|` + // v0.13
`Please run \"terraform init\"|` + // v1.1.0 early alpha versions (ref 89b05050)
`run:\s+terraform init|` + // v1.1.0 (ref df578afd)
`Run\s+\"terraform init\"|` + // v1.2.0

// UNINITIALISED BACKENDS
`Error: Initialization required.|` + // v0.13
`Error: Backend initialization required, please run \"terraform init\"`, // v0.15
)

noConfigErrRegexp = regexp.MustCompile(`Error: No configuration files`)

Expand All @@ -35,7 +43,9 @@ var (

stateLockErrRegexp = regexp.MustCompile(`Error acquiring the state lock`)
stateLockInfoRegexp = regexp.MustCompile(`Lock Info:\n\s*ID:\s*([^\n]+)\n\s*Path:\s*([^\n]+)\n\s*Operation:\s*([^\n]+)\n\s*Who:\s*([^\n]+)\n\s*Version:\s*([^\n]+)\n\s*Created:\s*([^\n]+)\n`)
statePlanReadErrRegexp = regexp.MustCompile(`Terraform couldn't read the given file as a state or plan file.|Error: Failed to read the given file as a state or plan file`)
statePlanReadErrRegexp = regexp.MustCompile(
`Terraform couldn't read the given file as a state or plan file.|` +
`Error: Failed to read the given file as a state or plan file`)
)

func (tf *Terraform) wrapExitError(ctx context.Context, err error, stderr string) error {
Expand Down
108 changes: 102 additions & 6 deletions tfexec/internal/e2etest/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,24 +110,120 @@ func TestShow_emptyDir(t *testing.T) {
})
}

func TestShow_noInit(t *testing.T) {
// terraform show was added in 0.12
// before v1.2, running show without init first results in ErrNoInit
func TestShow_noInitBasic(t *testing.T) {
// Prior to v1.2.0, running show before init always results in ErrNoInit.
// In the basic case, in which the local backend is implicit and there are
// no providers to download, this is unintended behaviour, as
// init is not actually necessary. This is considered a known issue in
// pre-1.2.0 versions.
runTestVersions(t, []string{testutil.Latest012, testutil.Latest013, testutil.Latest014, testutil.Latest015, testutil.Latest_v1, testutil.Latest_v1_1}, "basic", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {

var noInit *tfexec.ErrNoInit
_, err := tf.Show(context.Background())
if !errors.As(err, &noInit) {
t.Fatalf("expected error ErrNoInit, got %T: %s", err, err)
}
})

// From v1.2.0 onwards, running show before init in the basic case returns
// an empty state with no error.
runTest(t, "basic", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
// KEM: Really I mean tfv.LessThan(version.Must(version.NewVersion("1.2.0")))
// HACK KEM: Really I mean tfv.LessThan(version.Must(version.NewVersion("1.2.0"))),
// but I want this test to run for refs/heads/main prior to the release of v1.2.0.
if tfv.LessThan(version.Must(version.NewVersion("1.2.0"))) {

t.Skip("test applies only to v1.2.0 and greater")
}
expected := &tfjson.State{
FormatVersion: "1.0",
}

actual, err := tf.Show(context.Background())
if err != nil {
t.Fatal(err)
}

if diff := diffState(expected, actual); diff != "" {
t.Fatalf("mismatch (-want +got):\n%s", diff)
}
})
}

func TestShow_noInitModule(t *testing.T) {
// Prior to v1.2.0, running show before init always results in ErrNoInit.
// In the basic case, in which the local backend is implicit and there are
// no providers to download, this is unintended behaviour, as
// init is not actually necessary. This is considered a known issue in
// pre-1.2.0 versions.
runTestVersions(t, []string{testutil.Latest012, testutil.Latest013, testutil.Latest014, testutil.Latest015, testutil.Latest_v1, testutil.Latest_v1_1}, "registry_module", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
var noInit *tfexec.ErrNoInit
_, err := tf.Show(context.Background())
if !errors.As(err, &noInit) {
t.Fatalf("expected error ErrNoInit, got %T: %s", err, err)
}
})

// From v1.2.0 onwards, running show before init in the basic case returns
// an empty state with no error.
runTest(t, "registry_module", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
// HACK KEM: Really I mean tfv.LessThan(version.Must(version.NewVersion("1.2.0"))),
// but I want this test to run for refs/heads/main prior to the release of v1.2.0.
if tfv.LessThanOrEqual(version.Must(version.NewVersion(testutil.Latest_v1_1))) {
t.Skip("test applies only to v1.2.0 and greater")
}
t.Fatalf("PLACEHOLDER: UNDEFINED BEHAVIOUR")
expected := &tfjson.State{
FormatVersion: "1.0",
}

actual, err := tf.Show(context.Background())
if err != nil {
t.Fatal(err)
}

if diff := diffState(expected, actual); diff != "" {
t.Fatalf("mismatch (-want +got):\n%s", diff)
}
})
}

func TestShow_noInitNonLocalBackend(t *testing.T) {
runTest(t, "inmem_backend", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
if tfv.LessThan(showMinVersion) {
t.Skip("terraform show was added in Terraform 0.12, so test is not valid")
}

var noInit *tfexec.ErrNoInit
_, err := tf.Show(context.Background())
if !errors.As(err, &noInit) {
t.Fatalf("expected error ErrNoInit, got %T: %s", err, err)
}
})
}

func TestShow_noInitLocalBackendNonDefaultState(t *testing.T) {
runTest(t, "local_backend_non_default_state", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
if tfv.LessThan(showMinVersion) {
t.Skip("terraform show was added in Terraform 0.12, so test is not valid")
}

var noInit *tfexec.ErrNoInit
_, err := tf.Show(context.Background())
if !errors.As(err, &noInit) {
t.Fatalf("expected error ErrNoInit, got %T: %s", err, err)
}
})
}

func TestShow_noInitEtcdBackend(t *testing.T) {
runTest(t, "etcd_backend", func(t *testing.T, tfv *version.Version, tf *tfexec.Terraform) {
if tfv.LessThan(showMinVersion) {
t.Skip("terraform show was added in Terraform 0.12, so test is not valid")
}

var noInit *tfexec.ErrNoInit
_, err := tf.Show(context.Background())
if !errors.As(err, &noInit) {
t.Fatalf("expected error ErrNoInit, got %T: %s", err, err)
}
})
}

Expand Down
Empty file.
4 changes: 4 additions & 0 deletions tfexec/internal/e2etest/testdata/etcd_backend/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
terraform {
backend "etcd" {
}
}
4 changes: 4 additions & 0 deletions tfexec/internal/e2etest/testdata/inmem_backend/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
terraform {
backend "inmem" {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
terraform {
backend "local" {
path = "foo.tfstate"
}
}

0 comments on commit f491a7c

Please sign in to comment.