command: test `graph` with const variables

pull/38327/head
Daniel Banck 1 week ago committed by Daniel Banck
parent e81ffa2a02
commit 254ddfa276

@ -17,6 +17,7 @@ import (
"github.com/hashicorp/terraform/internal/backend/backendrun"
"github.com/hashicorp/terraform/internal/command/arguments"
"github.com/hashicorp/terraform/internal/configs"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/hashicorp/terraform/internal/tfdiags"
@ -143,6 +144,7 @@ func TestNewVariableBackend(result map[string]string) backend.Backend {
}
var _ backendrun.ConstVariableSupplier = (*TestVariableBackend)(nil)
var _ backendrun.Local = (*TestVariableBackend)(nil)
func (b *TestVariableBackend) FetchVariables(ctx context.Context, workspace string) (map[string]arguments.UnparsedVariableValue, tfdiags.Diagnostics) {
result := make(map[string]arguments.UnparsedVariableValue)
@ -157,6 +159,27 @@ func (b *TestVariableBackend) FetchVariables(ctx context.Context, workspace stri
return result, nil
}
func (b *TestVariableBackend) LocalRun(op *backendrun.Operation) (*backendrun.LocalRun, statemgr.Full, tfdiags.Diagnostics) {
// Sometimes a command (like graph) requires a local backend. The cloud
// backend implements LocalRun and will fetch variables from the backend.
// But our mock TestVariableBackend will fail in these tests, because it
// embends the backendrun.Local backend and never calls FetchVariables.
//
// We now set the variables manually here and defer to the regular backend
// run implementation, this helps us test the desired behavior.
if op.Variables == nil {
op.Variables = make(map[string]arguments.UnparsedVariableValue)
}
fetchedVars, _ := b.FetchVariables(context.Background(), op.Workspace)
for k, v := range fetchedVars {
if _, ok := op.Variables[k]; !ok {
op.Variables[k] = v
}
}
return b.Local.LocalRun(op)
}
type testUnparsedVariableValueString struct {
str string
name string

@ -14,6 +14,8 @@ import (
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/backend"
backendInit "github.com/hashicorp/terraform/internal/backend/init"
"github.com/hashicorp/terraform/internal/configs/configload"
"github.com/hashicorp/terraform/internal/configs/configschema"
"github.com/hashicorp/terraform/internal/initwd"
@ -359,3 +361,103 @@ func TestGraph_applyPhaseSavedPlan(t *testing.T) {
t.Fatalf("doesn't look like digraph:\n%s\n\nstderr:\n%s", output.Stdout(), output.Stderr())
}
}
func TestGraph_constVariable(t *testing.T) {
t.Run("missing value", func(t *testing.T) {
wd := tempWorkingDirFixture(t, "dynamic-module-sources/command-with-const-var")
t.Chdir(wd.RootModuleDir())
ui := cli.NewMockUi()
streams, closeStreams := terminal.StreamsForTesting(t)
c := &GraphCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
Streams: streams,
WorkingDir: wd,
},
}
args := []string{}
if code := c.Run(args); code != 1 {
output := closeStreams(t)
t.Fatalf("expected exit status 1\nstdout:\n%s\n\nstderr:\n%s", output.Stdout(), output.Stderr())
}
if !strings.Contains(ui.ErrorWriter.String(), "No value for required variable") {
t.Fatalf("expected missing variable error, got:\n%s", ui.ErrorWriter.String())
}
closeStreams(t)
})
t.Run("value via cli", func(t *testing.T) {
wd := tempWorkingDirFixture(t, "dynamic-module-sources/command-with-const-var")
t.Chdir(wd.RootModuleDir())
ui := cli.NewMockUi()
streams, closeStreams := terminal.StreamsForTesting(t)
c := &GraphCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
Streams: streams,
WorkingDir: wd,
},
}
args := []string{"-var", "module_name=child"}
if code := c.Run(args); code != 0 {
output := closeStreams(t)
t.Fatalf("bad:\nstdout:\n%s\n\nstderr:\n%s", output.Stdout(), output.Stderr())
}
output := closeStreams(t)
wantOutput := []string{
`"module.child.test_instance.test" [label="test_instance.test"]`,
}
for _, want := range wantOutput {
if !strings.Contains(output.Stdout(), want) {
t.Fatalf("output missing %s:\n%s", want, output.Stdout())
}
}
})
t.Run("value via backend", func(t *testing.T) {
mockBackend := TestNewVariableBackend(map[string]string{
"module_name": "child",
})
backendInit.Set("local-vars", func() backend.Backend { return mockBackend })
defer backendInit.Set("local-vars", nil)
wd := tempWorkingDirFixture(t, "dynamic-module-sources/command-with-const-var-backend")
t.Chdir(wd.RootModuleDir())
ui := cli.NewMockUi()
streams, closeStreams := terminal.StreamsForTesting(t)
c := &GraphCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
Streams: streams,
WorkingDir: wd,
},
}
args := []string{}
if code := c.Run(args); code != 0 {
output := closeStreams(t)
stderr := ui.ErrorWriter.String()
t.Fatalf("bad:\nstdout:\n%s\n\nstderr:\n%s", output.Stdout(), stderr)
}
output := closeStreams(t)
wantOutput := []string{
`"module.child.test_instance.test" [label="test_instance.test"]`,
}
for _, want := range wantOutput {
if !strings.Contains(output.Stdout(), want) {
t.Fatalf("output missing %s:\n%s", want, output.Stdout())
}
}
})
}

Loading…
Cancel
Save