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 }