mirror of
https://github.com/hashicorp/terraform.git
synced 2026-03-21 18:10:30 -04:00
673 lines
19 KiB
Go
673 lines
19 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package command
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/cli"
|
|
)
|
|
|
|
func TestInit2_dynamicSourceErrors(t *testing.T) {
|
|
tests := map[string]struct {
|
|
fixture string
|
|
args []string
|
|
wantError string
|
|
}{
|
|
"version constraint added to previously unversioned module": {
|
|
fixture: "add-version-constraint",
|
|
args: []string{"-get=false"},
|
|
wantError: "Module version requirements have changed",
|
|
},
|
|
"invalid registry source with version argument": {
|
|
fixture: "invalid-registry-source-with-module",
|
|
wantError: "Invalid registry module source address",
|
|
},
|
|
"local source with version argument": {
|
|
fixture: "local-source-with-version",
|
|
wantError: "Invalid registry module source address",
|
|
},
|
|
"non-const variable in module source": {
|
|
fixture: "local-source-with-non-const-variable",
|
|
args: []string{"-var", "module_name=example"},
|
|
wantError: "Invalid module source",
|
|
},
|
|
"resource reference in module source": {
|
|
fixture: "source-with-resource-reference",
|
|
wantError: "Invalid module source",
|
|
},
|
|
"module output reference in module source": {
|
|
fixture: "source-with-module-output-reference",
|
|
wantError: "Invalid module source",
|
|
},
|
|
"each.key in module source": {
|
|
fixture: "each-in-module-source",
|
|
wantError: "Invalid module source",
|
|
},
|
|
"count.index in module source": {
|
|
fixture: "count-in-module-source",
|
|
wantError: "Invalid module source",
|
|
},
|
|
"terraform.workspace in module source": {
|
|
fixture: "terraform-attr-in-module-source",
|
|
wantError: "Invalid module source",
|
|
},
|
|
"required const variable not set": {
|
|
fixture: "local-source-with-variable",
|
|
wantError: "No value for required variable",
|
|
},
|
|
"override default with nonexistent module": {
|
|
fixture: "local-source-with-variable-default",
|
|
args: []string{"-var", "module_name=nonexistent"},
|
|
wantError: "", // any error; the module directory doesn't exist
|
|
},
|
|
"version mismatch with dynamic constraint": {
|
|
fixture: "plan-with-version-mismatch",
|
|
args: []string{"-get=false", "-var", "module_version=0.0.2"},
|
|
wantError: "Module version requirements have changed",
|
|
},
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", tc.fixture)), td)
|
|
t.Chdir(td)
|
|
|
|
ui := new(cli.MockUi)
|
|
view, done := testView(t)
|
|
c := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
View: view,
|
|
},
|
|
}
|
|
|
|
code := c.Run(tc.args)
|
|
testOutput := done(t)
|
|
if code != 1 {
|
|
t.Fatalf("got exit status %d; want 1\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout())
|
|
}
|
|
|
|
if tc.wantError != "" {
|
|
got := testOutput.All()
|
|
if !strings.Contains(got, tc.wantError) {
|
|
t.Fatalf("wrong error\ngot:\n%s\n\nwant: containing %q", got, tc.wantError)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInit2_dynamicSourceSuccess(t *testing.T) {
|
|
tests := map[string]struct {
|
|
fixture string
|
|
args []string
|
|
}{
|
|
"const variable via -var": {
|
|
fixture: "local-source-with-variable",
|
|
args: []string{"-var", "module_name=example"},
|
|
},
|
|
"const variable with default value": {
|
|
fixture: "local-source-with-variable-default",
|
|
},
|
|
"local value referencing const variable": {
|
|
fixture: "local-source-with-local-value",
|
|
args: []string{"-var", "module_name=example"},
|
|
},
|
|
"nested module with variable passed through parent": {
|
|
fixture: "nested-module-with-variable-source",
|
|
args: []string{"-var", "child_name=child"},
|
|
},
|
|
"const variable from tfvars file": {
|
|
fixture: "local-source-with-varsfile",
|
|
args: []string{"-var-file", "test.tfvars"},
|
|
},
|
|
"path.module in module source": {
|
|
fixture: "path-attr-in-module-source",
|
|
},
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", tc.fixture)), td)
|
|
t.Chdir(td)
|
|
|
|
ui := new(cli.MockUi)
|
|
view, done := testView(t)
|
|
c := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
View: view,
|
|
},
|
|
}
|
|
|
|
code := c.Run(tc.args)
|
|
testOutput := done(t)
|
|
if code != 0 {
|
|
t.Fatalf("got exit status %d; want 0\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInit2_getFalseWithDynamicSource(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "get-false-with-dynamic-source")), td)
|
|
t.Chdir(td)
|
|
|
|
// First, run init normally to install the module
|
|
ui := new(cli.MockUi)
|
|
view, done := testView(t)
|
|
c := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
View: view,
|
|
},
|
|
}
|
|
|
|
args := []string{"-var", "module_name=example"}
|
|
code := c.Run(args)
|
|
testOutput := done(t)
|
|
if code != 0 {
|
|
t.Fatalf("first init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout())
|
|
}
|
|
|
|
// Now run init with -get=false; should succeed since modules are already installed
|
|
ui2 := new(cli.MockUi)
|
|
view2, done2 := testView(t)
|
|
c2 := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui2,
|
|
View: view2,
|
|
},
|
|
}
|
|
|
|
args2 := []string{"-get=false", "-var", "module_name=example"}
|
|
code = c2.Run(args2)
|
|
testOutput2 := done2(t)
|
|
if code != 0 {
|
|
t.Fatalf("init -get=false failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, testOutput2.Stderr(), testOutput2.Stdout())
|
|
}
|
|
}
|
|
|
|
func TestInit2_getFalseWithDynamicSourceNotInstalled(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "get-false-with-dynamic-source")), td)
|
|
t.Chdir(td)
|
|
|
|
ui := new(cli.MockUi)
|
|
view, done := testView(t)
|
|
c := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
View: view,
|
|
},
|
|
}
|
|
|
|
// Run init with -get=false without having installed modules first
|
|
args := []string{"-get=false", "-var", "module_name=example"}
|
|
code := c.Run(args)
|
|
testOutput := done(t)
|
|
if code != 1 {
|
|
t.Fatalf("got exit status %d; want 1\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout())
|
|
}
|
|
}
|
|
|
|
func TestInit2_reinitWithDifferentVariable(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "local-source-with-variable-default")), td)
|
|
t.Chdir(td)
|
|
|
|
// First init with default variable (example)
|
|
ui := new(cli.MockUi)
|
|
view, done := testView(t)
|
|
c := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
View: view,
|
|
},
|
|
}
|
|
|
|
code := c.Run([]string{})
|
|
testOutput := done(t)
|
|
if code != 0 {
|
|
t.Fatalf("first init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout())
|
|
}
|
|
|
|
// Re-init with different variable
|
|
ui2 := new(cli.MockUi)
|
|
view2, done2 := testView(t)
|
|
c2 := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui2,
|
|
View: view2,
|
|
},
|
|
}
|
|
|
|
code = c2.Run([]string{"-var", "module_name=alternate"})
|
|
testOutput2 := done2(t)
|
|
if code != 0 {
|
|
t.Fatalf("second init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, testOutput2.Stderr(), testOutput2.Stdout())
|
|
}
|
|
}
|
|
|
|
func TestInit2_fromModuleWithDynamicSource(t *testing.T) {
|
|
// TODO: -from-module currently panics when the copied configuration
|
|
// contains a dynamic module source (e.g. "./modules/${var.module_name}").
|
|
t.Skip("skipping: -from-module panics on dynamic module sources (see TODO in from_module.go)")
|
|
|
|
// Create an empty target directory for -from-module to copy into
|
|
td := t.TempDir()
|
|
t.Chdir(td)
|
|
|
|
ui := new(cli.MockUi)
|
|
view, done := testView(t)
|
|
c := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
View: view,
|
|
},
|
|
}
|
|
|
|
// Use -from-module to copy the source module (which has a dynamic source)
|
|
// into the empty working directory. This should copy the files but the
|
|
// nested dynamic module won't be resolved by -from-module itself.
|
|
srcDir := testFixturePath(filepath.Join("dynamic-module-sources", "from-module-with-dynamic-source", "source-module"))
|
|
args := []string{"-from-module=" + srcDir}
|
|
code := c.Run(args)
|
|
testOutput := done(t)
|
|
|
|
// -from-module should succeed in copying. The dynamic module source
|
|
// within the copied configuration won't be resolved yet — that requires
|
|
// a separate init with the variable value.
|
|
if code != 0 {
|
|
t.Fatalf("init -from-module failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout())
|
|
}
|
|
|
|
// Verify the main.tf was copied
|
|
if _, err := os.Stat(filepath.Join(td, "main.tf")); os.IsNotExist(err) {
|
|
t.Fatal("main.tf was not copied from the source module")
|
|
}
|
|
}
|
|
|
|
func TestPlan_dynamicModuleSource(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "plan-with-dynamic-source")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
providerSource, close := newMockProviderSource(t, map[string][]string{
|
|
"hashicorp/test": {"1.0.0"},
|
|
})
|
|
defer close()
|
|
|
|
args := []string{"-var", "module_name=example"}
|
|
|
|
initUi := new(cli.MockUi)
|
|
initView, initDone := testView(t)
|
|
initCmd := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: initUi,
|
|
View: initView,
|
|
ProviderSource: providerSource,
|
|
},
|
|
}
|
|
|
|
initCode := initCmd.Run(args)
|
|
initOutput := initDone(t)
|
|
if initCode != 0 {
|
|
t.Fatalf("init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", initCode, initOutput.Stderr(), initOutput.Stdout())
|
|
}
|
|
|
|
// Now run plan
|
|
planUi := new(cli.MockUi)
|
|
planView, planDone := testView(t)
|
|
planCmd := &PlanCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: planUi,
|
|
View: planView,
|
|
},
|
|
}
|
|
|
|
planCode := planCmd.Run(args)
|
|
planOutput := planDone(t)
|
|
if planCode != 0 {
|
|
t.Fatalf("plan failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", planCode, planOutput.Stderr(), planOutput.Stdout())
|
|
}
|
|
|
|
output := planOutput.Stdout()
|
|
if !strings.Contains(output, "1 to add") {
|
|
t.Fatalf("expected plan to show 1 resource to add, got:\n%s", output)
|
|
}
|
|
}
|
|
|
|
func TestPlan_dynamicModuleSourceMismatch(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "plan-with-dynamic-source")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
providerSource, close := newMockProviderSource(t, map[string][]string{
|
|
"hashicorp/test": {"1.0.0"},
|
|
})
|
|
defer close()
|
|
args := []string{"-var", "module_name=example"}
|
|
|
|
initUi := new(cli.MockUi)
|
|
initView, initDone := testView(t)
|
|
initCmd := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: initUi,
|
|
View: initView,
|
|
ProviderSource: providerSource,
|
|
},
|
|
}
|
|
|
|
initCode := initCmd.Run(args)
|
|
initOutput := initDone(t)
|
|
if initCode != 0 {
|
|
t.Fatalf("init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", initCode, initOutput.Stderr(), initOutput.Stdout())
|
|
}
|
|
|
|
// Now run plan with a different variable value
|
|
planUi := new(cli.MockUi)
|
|
planView, planDone := testView(t)
|
|
planCmd := &PlanCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: planUi,
|
|
View: planView,
|
|
},
|
|
}
|
|
|
|
planArgs := []string{"-var", "module_name=nonexistent"}
|
|
code := planCmd.Run(planArgs)
|
|
planOutput := planDone(t)
|
|
if code == 0 {
|
|
t.Fatalf("expected plan to fail, but got exit status 0\nstdout:\n%s", planOutput.Stdout())
|
|
}
|
|
}
|
|
|
|
func TestApply_dynamicModuleSource(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "apply-with-dynamic-source")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
providerSource, close := newMockProviderSource(t, map[string][]string{
|
|
"hashicorp/test": {"1.0.0"},
|
|
})
|
|
defer close()
|
|
args := []string{"-var", "module_name=example"}
|
|
|
|
initUi := new(cli.MockUi)
|
|
initView, initDone := testView(t)
|
|
initCmd := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: initUi,
|
|
View: initView,
|
|
ProviderSource: providerSource,
|
|
},
|
|
}
|
|
|
|
initCode := initCmd.Run(args)
|
|
initOutput := initDone(t)
|
|
if initCode != 0 {
|
|
t.Fatalf("init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", initCode, initOutput.Stderr(), initOutput.Stdout())
|
|
}
|
|
|
|
applyUi := new(cli.MockUi)
|
|
applyView, applyDone := testView(t)
|
|
applyCmd := &ApplyCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: applyUi,
|
|
View: applyView,
|
|
},
|
|
}
|
|
|
|
applyArgs := []string{"-auto-approve", "-var", "module_name=example"}
|
|
code := applyCmd.Run(applyArgs)
|
|
applyOutput := applyDone(t)
|
|
if code != 0 {
|
|
t.Fatalf("apply failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, applyOutput.Stderr(), applyOutput.Stdout())
|
|
}
|
|
|
|
output := applyOutput.Stdout()
|
|
if !strings.Contains(output, "Apply complete!") {
|
|
t.Fatalf("expected apply to succeed, got:\n%s", output)
|
|
}
|
|
}
|
|
|
|
func TestApply_dynamicModuleSourceWithDefaultPlanFile(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "apply-plan-with-dynamic-source")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
providerSource, close := newMockProviderSource(t, map[string][]string{
|
|
"hashicorp/test": {"1.0.0"},
|
|
})
|
|
defer close()
|
|
|
|
initUi := new(cli.MockUi)
|
|
initView, initDone := testView(t)
|
|
initCmd := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: initUi,
|
|
View: initView,
|
|
ProviderSource: providerSource,
|
|
},
|
|
}
|
|
|
|
initCode := initCmd.Run([]string{})
|
|
initOutput := initDone(t)
|
|
if initCode != 0 {
|
|
t.Fatalf("init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", initCode, initOutput.Stderr(), initOutput.Stdout())
|
|
}
|
|
|
|
// Run plan with -out
|
|
planPath := filepath.Join(td, "saved.plan")
|
|
planUi := new(cli.MockUi)
|
|
planView, planDone := testView(t)
|
|
planCmd := &PlanCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: planUi,
|
|
View: planView,
|
|
},
|
|
}
|
|
|
|
planArgs := []string{"-out", planPath}
|
|
code := planCmd.Run(planArgs)
|
|
planOutput := planDone(t)
|
|
if code != 0 {
|
|
t.Fatalf("plan failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, planOutput.Stderr(), planOutput.Stdout())
|
|
}
|
|
|
|
// Verify the plan file was created
|
|
if _, err := os.Stat(planPath); os.IsNotExist(err) {
|
|
t.Fatalf("plan file was not created at %s", planPath)
|
|
}
|
|
|
|
// Apply the saved plan
|
|
applyUi := new(cli.MockUi)
|
|
applyView, applyDone := testView(t)
|
|
applyCmd := &ApplyCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: applyUi,
|
|
View: applyView,
|
|
},
|
|
}
|
|
|
|
applyArgs := []string{planPath}
|
|
code = applyCmd.Run(applyArgs)
|
|
applyOutput := applyDone(t)
|
|
if code != 0 {
|
|
t.Fatalf("apply failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", code, applyOutput.Stderr(), applyOutput.Stdout())
|
|
}
|
|
|
|
output := applyOutput.Stdout()
|
|
if !strings.Contains(output, "Apply complete!") {
|
|
t.Fatalf("expected apply to succeed, got:\n%s", output)
|
|
}
|
|
}
|
|
|
|
func TestPlan_dynamicModuleSourceWithCount(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "module-with-count")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
providerSource, close := newMockProviderSource(t, map[string][]string{
|
|
"hashicorp/test": {"1.0.0"},
|
|
})
|
|
defer close()
|
|
|
|
args := []string{"-var", "module_name=example"}
|
|
|
|
initUi := new(cli.MockUi)
|
|
initView, initDone := testView(t)
|
|
initCmd := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: initUi,
|
|
View: initView,
|
|
ProviderSource: providerSource,
|
|
},
|
|
}
|
|
|
|
initCode := initCmd.Run(args)
|
|
initOutput := initDone(t)
|
|
if initCode != 0 {
|
|
t.Fatalf("init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", initCode, initOutput.Stderr(), initOutput.Stdout())
|
|
}
|
|
|
|
// Now run plan
|
|
planUi := new(cli.MockUi)
|
|
planView, planDone := testView(t)
|
|
planCmd := &PlanCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: planUi,
|
|
View: planView,
|
|
},
|
|
}
|
|
|
|
planCode := planCmd.Run(args)
|
|
planOutput := planDone(t)
|
|
if planCode != 0 {
|
|
t.Fatalf("plan failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", planCode, planOutput.Stderr(), planOutput.Stdout())
|
|
}
|
|
|
|
output := planOutput.Stdout()
|
|
if !strings.Contains(output, "2 to add") {
|
|
t.Fatalf("expected plan to show 2 resources to add, got:\n%s", output)
|
|
}
|
|
}
|
|
|
|
func TestPlan_dynamicModuleSourceWithForEach(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "module-with-for-each")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
providerSource, close := newMockProviderSource(t, map[string][]string{
|
|
"hashicorp/test": {"1.0.0"},
|
|
})
|
|
defer close()
|
|
|
|
args := []string{"-var", "module_name=example"}
|
|
|
|
initUi := new(cli.MockUi)
|
|
initView, initDone := testView(t)
|
|
initCmd := &InitCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: initUi,
|
|
View: initView,
|
|
ProviderSource: providerSource,
|
|
},
|
|
}
|
|
|
|
initCode := initCmd.Run(args)
|
|
initOutput := initDone(t)
|
|
if initCode != 0 {
|
|
t.Fatalf("init failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", initCode, initOutput.Stderr(), initOutput.Stdout())
|
|
}
|
|
|
|
// Now run plan
|
|
planUi := new(cli.MockUi)
|
|
planView, planDone := testView(t)
|
|
planCmd := &PlanCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: planUi,
|
|
View: planView,
|
|
},
|
|
}
|
|
|
|
planCode := planCmd.Run(args)
|
|
planOutput := planDone(t)
|
|
if planCode != 0 {
|
|
t.Fatalf("plan failed with exit status %d\nstderr:\n%s\n\nstdout:\n%s", planCode, planOutput.Stderr(), planOutput.Stdout())
|
|
}
|
|
|
|
output := planOutput.Stdout()
|
|
if !strings.Contains(output, "2 to add") {
|
|
t.Fatalf("expected plan to show 2 resources to add, got:\n%s", output)
|
|
}
|
|
}
|
|
|
|
func TestPlan_dynamicModuleVersionMismatch(t *testing.T) {
|
|
td := t.TempDir()
|
|
testCopyDir(t, testFixturePath(filepath.Join("dynamic-module-sources", "plan-with-version-mismatch")), td)
|
|
t.Chdir(td)
|
|
|
|
p := planFixtureProvider()
|
|
|
|
// Plan should fail because the installed module version (0.0.1 in
|
|
// modules.json) doesn't satisfy the constraint we provide.
|
|
planUi := new(cli.MockUi)
|
|
planView, planDone := testView(t)
|
|
planCmd := &PlanCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: planUi,
|
|
View: planView,
|
|
},
|
|
}
|
|
|
|
planArgs := []string{"-var", "module_version=0.0.2"}
|
|
code := planCmd.Run(planArgs)
|
|
planOutput := planDone(t)
|
|
if code == 0 {
|
|
t.Fatalf("expected plan to fail, but got exit status 0\nstdout:\n%s", planOutput.Stdout())
|
|
}
|
|
got := planOutput.All()
|
|
|
|
want := "Module version requirements have changed"
|
|
if !strings.Contains(got, want) {
|
|
t.Fatalf("wrong error\ngot:\n%s\n\nwant: containing %q", got, want)
|
|
}
|
|
}
|