496 lines
11 KiB
Go
496 lines
11 KiB
Go
package command
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/mitchellh/cli"
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/states"
|
|
)
|
|
|
|
func TestOutput(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
})
|
|
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"foo",
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := strings.TrimSpace(ui.OutputWriter.String())
|
|
if actual != `"bar"` {
|
|
t.Fatalf("bad: %#v", actual)
|
|
}
|
|
}
|
|
|
|
func TestOutput_nestedListAndMap(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.ListVal([]cty.Value{
|
|
cty.MapVal(map[string]cty.Value{
|
|
"key": cty.StringVal("value"),
|
|
"key2": cty.StringVal("value2"),
|
|
}),
|
|
cty.MapVal(map[string]cty.Value{
|
|
"key": cty.StringVal("value"),
|
|
}),
|
|
}),
|
|
false,
|
|
)
|
|
})
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := strings.TrimSpace(ui.OutputWriter.String())
|
|
expected := strings.TrimSpace(`
|
|
foo = tolist([
|
|
tomap({
|
|
"key" = "value"
|
|
"key2" = "value2"
|
|
}),
|
|
tomap({
|
|
"key" = "value"
|
|
}),
|
|
])
|
|
`)
|
|
if actual != expected {
|
|
t.Fatalf("wrong output\ngot: %s\nwant: %s", actual, expected)
|
|
}
|
|
}
|
|
|
|
func TestOutput_json(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
})
|
|
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"-json",
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := strings.TrimSpace(ui.OutputWriter.String())
|
|
expected := "{\n \"foo\": {\n \"sensitive\": false,\n \"type\": \"string\",\n \"value\": \"bar\"\n }\n}"
|
|
if actual != expected {
|
|
t.Fatalf("wrong output\ngot: %#v\nwant: %#v", actual, expected)
|
|
}
|
|
}
|
|
|
|
func TestOutput_raw(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "str"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "multistr"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar\nbaz"),
|
|
false,
|
|
)
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "num"}.Absolute(addrs.RootModuleInstance),
|
|
cty.NumberIntVal(2),
|
|
false,
|
|
)
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "bool"}.Absolute(addrs.RootModuleInstance),
|
|
cty.True,
|
|
false,
|
|
)
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "obj"}.Absolute(addrs.RootModuleInstance),
|
|
cty.EmptyObjectVal,
|
|
false,
|
|
)
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "null"}.Absolute(addrs.RootModuleInstance),
|
|
cty.NullVal(cty.String),
|
|
false,
|
|
)
|
|
})
|
|
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
tests := map[string]struct {
|
|
WantOutput string
|
|
WantErr bool
|
|
}{
|
|
"str": {WantOutput: "bar"},
|
|
"multistr": {WantOutput: "bar\nbaz"},
|
|
"num": {WantOutput: "2"},
|
|
"bool": {WantOutput: "true"},
|
|
"obj": {WantErr: true},
|
|
"null": {WantErr: true},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
var printed string
|
|
ui := cli.NewMockUi()
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
rawPrint: func(s string) {
|
|
printed = s
|
|
},
|
|
}
|
|
args := []string{
|
|
"-state", statePath,
|
|
"-raw",
|
|
name,
|
|
}
|
|
code := c.Run(args)
|
|
|
|
if code != 0 {
|
|
if !test.WantErr {
|
|
t.Errorf("unexpected failure\n%s", ui.ErrorWriter.String())
|
|
}
|
|
return
|
|
}
|
|
|
|
if test.WantErr {
|
|
t.Fatalf("succeeded, but want error")
|
|
}
|
|
|
|
if got, want := printed, test.WantOutput; got != want {
|
|
t.Errorf("wrong result\ngot: %q\nwant: %q", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOutput_emptyOutputs(t *testing.T) {
|
|
originalState := states.NewState()
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
p := testProvider()
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
if got, want := ui.ErrorWriter.String(), "Warning: No outputs found"; !strings.Contains(got, want) {
|
|
t.Fatalf("bad output: expected to contain %q, got:\n%s", want, got)
|
|
}
|
|
}
|
|
|
|
func TestOutput_jsonEmptyOutputs(t *testing.T) {
|
|
originalState := states.NewState()
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
p := testProvider()
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"-json",
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := strings.TrimSpace(ui.OutputWriter.String())
|
|
expected := "{}"
|
|
if actual != expected {
|
|
t.Fatalf("bad:\n%#v\n%#v", expected, actual)
|
|
}
|
|
}
|
|
|
|
func TestMissingModuleOutput(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
})
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"-module", "not_existing_module",
|
|
"blah",
|
|
}
|
|
|
|
if code := c.Run(args); code != 1 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
}
|
|
|
|
func TestOutput_badVar(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
})
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"bar",
|
|
}
|
|
if code := c.Run(args); code != 1 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
}
|
|
|
|
func TestOutput_blank(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "name"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("john-doe"),
|
|
false,
|
|
)
|
|
})
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"",
|
|
}
|
|
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
|
|
expectedOutput := "foo = \"bar\"\nname = \"john-doe\"\n"
|
|
output := ui.OutputWriter.String()
|
|
if output != expectedOutput {
|
|
t.Fatalf("wrong output\ngot: %#v\nwant: %#v", output, expectedOutput)
|
|
}
|
|
}
|
|
|
|
func TestOutput_manyArgs(t *testing.T) {
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"bad",
|
|
"bad",
|
|
}
|
|
if code := c.Run(args); code != 1 {
|
|
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
|
|
}
|
|
}
|
|
|
|
func TestOutput_noArgs(t *testing.T) {
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.OutputWriter.String())
|
|
}
|
|
}
|
|
|
|
func TestOutput_noState(t *testing.T) {
|
|
originalState := states.NewState()
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"foo",
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
}
|
|
|
|
func TestOutput_noVars(t *testing.T) {
|
|
originalState := states.NewState()
|
|
|
|
statePath := testStateFile(t, originalState)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"-state", statePath,
|
|
"bar",
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
}
|
|
|
|
func TestOutput_stateDefault(t *testing.T) {
|
|
originalState := states.BuildState(func(s *states.SyncState) {
|
|
s.SetOutputValue(
|
|
addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
|
|
cty.StringVal("bar"),
|
|
false,
|
|
)
|
|
})
|
|
|
|
// Write the state file in a temporary directory with the
|
|
// default filename.
|
|
td := testTempDir(t)
|
|
statePath := filepath.Join(td, DefaultStateFilename)
|
|
|
|
f, err := os.Create(statePath)
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
err = writeStateForTesting(originalState, f)
|
|
f.Close()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
// Change to that directory
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
if err := os.Chdir(filepath.Dir(statePath)); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
defer os.Chdir(cwd)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &OutputCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
args := []string{
|
|
"foo",
|
|
}
|
|
if code := c.Run(args); code != 0 {
|
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := strings.TrimSpace(ui.OutputWriter.String())
|
|
if actual != `"bar"` {
|
|
t.Fatalf("bad: %#v", actual)
|
|
}
|
|
}
|