github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/output_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package command
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/zclconf/go-cty/cty"
    13  
    14  	"github.com/terramate-io/tf/addrs"
    15  	"github.com/terramate-io/tf/states"
    16  )
    17  
    18  func TestOutput(t *testing.T) {
    19  	originalState := states.BuildState(func(s *states.SyncState) {
    20  		s.SetOutputValue(
    21  			addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
    22  			cty.StringVal("bar"),
    23  			false,
    24  		)
    25  	})
    26  
    27  	statePath := testStateFile(t, originalState)
    28  
    29  	view, done := testView(t)
    30  	c := &OutputCommand{
    31  		Meta: Meta{
    32  			testingOverrides: metaOverridesForProvider(testProvider()),
    33  			View:             view,
    34  		},
    35  	}
    36  
    37  	args := []string{
    38  		"-state", statePath,
    39  		"foo",
    40  	}
    41  	code := c.Run(args)
    42  	output := done(t)
    43  	if code != 0 {
    44  		t.Fatalf("bad: \n%s", output.Stderr())
    45  	}
    46  
    47  	actual := strings.TrimSpace(output.Stdout())
    48  	if actual != `"bar"` {
    49  		t.Fatalf("bad: %#v", actual)
    50  	}
    51  }
    52  
    53  func TestOutput_json(t *testing.T) {
    54  	originalState := states.BuildState(func(s *states.SyncState) {
    55  		s.SetOutputValue(
    56  			addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
    57  			cty.StringVal("bar"),
    58  			false,
    59  		)
    60  	})
    61  
    62  	statePath := testStateFile(t, originalState)
    63  
    64  	view, done := testView(t)
    65  	c := &OutputCommand{
    66  		Meta: Meta{
    67  			testingOverrides: metaOverridesForProvider(testProvider()),
    68  			View:             view,
    69  		},
    70  	}
    71  
    72  	args := []string{
    73  		"-state", statePath,
    74  		"-json",
    75  	}
    76  	code := c.Run(args)
    77  	output := done(t)
    78  	if code != 0 {
    79  		t.Fatalf("bad: \n%s", output.Stderr())
    80  	}
    81  
    82  	actual := strings.TrimSpace(output.Stdout())
    83  	expected := "{\n  \"foo\": {\n    \"sensitive\": false,\n    \"type\": \"string\",\n    \"value\": \"bar\"\n  }\n}"
    84  	if actual != expected {
    85  		t.Fatalf("wrong output\ngot:  %#v\nwant: %#v", actual, expected)
    86  	}
    87  }
    88  
    89  func TestOutput_emptyOutputs(t *testing.T) {
    90  	originalState := states.NewState()
    91  	statePath := testStateFile(t, originalState)
    92  
    93  	p := testProvider()
    94  	view, done := testView(t)
    95  	c := &OutputCommand{
    96  		Meta: Meta{
    97  			testingOverrides: metaOverridesForProvider(p),
    98  			View:             view,
    99  		},
   100  	}
   101  
   102  	args := []string{
   103  		"-no-color",
   104  		"-state", statePath,
   105  	}
   106  	code := c.Run(args)
   107  	output := done(t)
   108  	if code != 0 {
   109  		t.Fatalf("bad: \n%s", output.Stderr())
   110  	}
   111  	// Warning diagnostics should go to stdout
   112  	if got, want := output.Stdout(), "Warning: No outputs found"; !strings.Contains(got, want) {
   113  		t.Fatalf("bad output: expected to contain %q, got:\n%s", want, got)
   114  	}
   115  }
   116  
   117  func TestOutput_badVar(t *testing.T) {
   118  	originalState := states.BuildState(func(s *states.SyncState) {
   119  		s.SetOutputValue(
   120  			addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
   121  			cty.StringVal("bar"),
   122  			false,
   123  		)
   124  	})
   125  	statePath := testStateFile(t, originalState)
   126  
   127  	view, done := testView(t)
   128  	c := &OutputCommand{
   129  		Meta: Meta{
   130  			testingOverrides: metaOverridesForProvider(testProvider()),
   131  			View:             view,
   132  		},
   133  	}
   134  
   135  	args := []string{
   136  		"-state", statePath,
   137  		"bar",
   138  	}
   139  	code := c.Run(args)
   140  	output := done(t)
   141  	if code != 1 {
   142  		t.Fatalf("bad: \n%s", output.Stderr())
   143  	}
   144  }
   145  
   146  func TestOutput_blank(t *testing.T) {
   147  	originalState := states.BuildState(func(s *states.SyncState) {
   148  		s.SetOutputValue(
   149  			addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
   150  			cty.StringVal("bar"),
   151  			false,
   152  		)
   153  		s.SetOutputValue(
   154  			addrs.OutputValue{Name: "name"}.Absolute(addrs.RootModuleInstance),
   155  			cty.StringVal("john-doe"),
   156  			false,
   157  		)
   158  	})
   159  	statePath := testStateFile(t, originalState)
   160  
   161  	view, done := testView(t)
   162  	c := &OutputCommand{
   163  		Meta: Meta{
   164  			testingOverrides: metaOverridesForProvider(testProvider()),
   165  			View:             view,
   166  		},
   167  	}
   168  
   169  	args := []string{
   170  		"-state", statePath,
   171  		"",
   172  	}
   173  
   174  	code := c.Run(args)
   175  	output := done(t)
   176  	if code != 0 {
   177  		t.Fatalf("bad: \n%s", output.Stderr())
   178  	}
   179  
   180  	expectedOutput := "foo = \"bar\"\nname = \"john-doe\"\n"
   181  	if got := output.Stdout(); got != expectedOutput {
   182  		t.Fatalf("wrong output\ngot:  %#v\nwant: %#v", got, expectedOutput)
   183  	}
   184  }
   185  
   186  func TestOutput_manyArgs(t *testing.T) {
   187  	view, done := testView(t)
   188  	c := &OutputCommand{
   189  		Meta: Meta{
   190  			testingOverrides: metaOverridesForProvider(testProvider()),
   191  			View:             view,
   192  		},
   193  	}
   194  
   195  	args := []string{
   196  		"bad",
   197  		"bad",
   198  	}
   199  	code := c.Run(args)
   200  	output := done(t)
   201  	if code != 1 {
   202  		t.Fatalf("bad: \n%s", output.Stdout())
   203  	}
   204  }
   205  
   206  func TestOutput_noArgs(t *testing.T) {
   207  	view, done := testView(t)
   208  	c := &OutputCommand{
   209  		Meta: Meta{
   210  			testingOverrides: metaOverridesForProvider(testProvider()),
   211  			View:             view,
   212  		},
   213  	}
   214  
   215  	args := []string{}
   216  	code := c.Run(args)
   217  	output := done(t)
   218  	if code != 0 {
   219  		t.Fatalf("bad: \n%s", output.Stdout())
   220  	}
   221  }
   222  
   223  func TestOutput_noState(t *testing.T) {
   224  	originalState := states.NewState()
   225  	statePath := testStateFile(t, originalState)
   226  
   227  	view, done := testView(t)
   228  	c := &OutputCommand{
   229  		Meta: Meta{
   230  			testingOverrides: metaOverridesForProvider(testProvider()),
   231  			View:             view,
   232  		},
   233  	}
   234  
   235  	args := []string{
   236  		"-state", statePath,
   237  		"foo",
   238  	}
   239  	code := c.Run(args)
   240  	output := done(t)
   241  	if code != 0 {
   242  		t.Fatalf("bad: \n%s", output.Stderr())
   243  	}
   244  }
   245  
   246  func TestOutput_noVars(t *testing.T) {
   247  	originalState := states.NewState()
   248  
   249  	statePath := testStateFile(t, originalState)
   250  
   251  	view, done := testView(t)
   252  	c := &OutputCommand{
   253  		Meta: Meta{
   254  			testingOverrides: metaOverridesForProvider(testProvider()),
   255  			View:             view,
   256  		},
   257  	}
   258  
   259  	args := []string{
   260  		"-state", statePath,
   261  		"bar",
   262  	}
   263  	code := c.Run(args)
   264  	output := done(t)
   265  	if code != 0 {
   266  		t.Fatalf("bad: \n%s", output.Stderr())
   267  	}
   268  }
   269  
   270  func TestOutput_stateDefault(t *testing.T) {
   271  	originalState := states.BuildState(func(s *states.SyncState) {
   272  		s.SetOutputValue(
   273  			addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance),
   274  			cty.StringVal("bar"),
   275  			false,
   276  		)
   277  	})
   278  
   279  	// Write the state file in a temporary directory with the
   280  	// default filename.
   281  	td := testTempDir(t)
   282  	statePath := filepath.Join(td, DefaultStateFilename)
   283  
   284  	f, err := os.Create(statePath)
   285  	if err != nil {
   286  		t.Fatalf("err: %s", err)
   287  	}
   288  	err = writeStateForTesting(originalState, f)
   289  	f.Close()
   290  	if err != nil {
   291  		t.Fatalf("err: %s", err)
   292  	}
   293  
   294  	// Change to that directory
   295  	cwd, err := os.Getwd()
   296  	if err != nil {
   297  		t.Fatalf("err: %s", err)
   298  	}
   299  	if err := os.Chdir(filepath.Dir(statePath)); err != nil {
   300  		t.Fatalf("err: %s", err)
   301  	}
   302  	defer os.Chdir(cwd)
   303  
   304  	view, done := testView(t)
   305  	c := &OutputCommand{
   306  		Meta: Meta{
   307  			testingOverrides: metaOverridesForProvider(testProvider()),
   308  			View:             view,
   309  		},
   310  	}
   311  
   312  	args := []string{
   313  		"foo",
   314  	}
   315  	code := c.Run(args)
   316  	output := done(t)
   317  	if code != 0 {
   318  		t.Fatalf("bad: \n%s", output.Stderr())
   319  	}
   320  
   321  	actual := strings.TrimSpace(output.Stdout())
   322  	if actual != `"bar"` {
   323  		t.Fatalf("bad: %#v", actual)
   324  	}
   325  }