1package terraform
2
3import (
4	"flag"
5	"io"
6	"io/ioutil"
7	"os"
8	"path/filepath"
9	"strings"
10	"sync"
11	"testing"
12
13	"github.com/davecgh/go-spew/spew"
14	"github.com/zclconf/go-cty/cty"
15
16	"github.com/hashicorp/terraform/internal/addrs"
17	"github.com/hashicorp/terraform/internal/configs"
18	"github.com/hashicorp/terraform/internal/configs/configload"
19	"github.com/hashicorp/terraform/internal/initwd"
20	"github.com/hashicorp/terraform/internal/plans"
21	"github.com/hashicorp/terraform/internal/providers"
22	"github.com/hashicorp/terraform/internal/provisioners"
23	"github.com/hashicorp/terraform/internal/registry"
24	"github.com/hashicorp/terraform/internal/states"
25
26	_ "github.com/hashicorp/terraform/internal/logging"
27)
28
29// This is the directory where our test fixtures are.
30const fixtureDir = "./testdata"
31
32func TestMain(m *testing.M) {
33	flag.Parse()
34
35	// We have fmt.Stringer implementations on lots of objects that hide
36	// details that we very often want to see in tests, so we just disable
37	// spew's use of String methods globally on the assumption that spew
38	// usage implies an intent to see the raw values and ignore any
39	// abstractions.
40	spew.Config.DisableMethods = true
41
42	os.Exit(m.Run())
43}
44
45func testModule(t *testing.T, name string) *configs.Config {
46	t.Helper()
47	c, _ := testModuleWithSnapshot(t, name)
48	return c
49}
50
51func testModuleWithSnapshot(t *testing.T, name string) (*configs.Config, *configload.Snapshot) {
52	t.Helper()
53
54	dir := filepath.Join(fixtureDir, name)
55	// FIXME: We're not dealing with the cleanup function here because
56	// this testModule function is used all over and so we don't want to
57	// change its interface at this late stage.
58	loader, _ := configload.NewLoaderForTests(t)
59
60	// Test modules usually do not refer to remote sources, and for local
61	// sources only this ultimately just records all of the module paths
62	// in a JSON file so that we can load them below.
63	inst := initwd.NewModuleInstaller(loader.ModulesDir(), registry.NewClient(nil, nil))
64	_, instDiags := inst.InstallModules(dir, true, initwd.ModuleInstallHooksImpl{})
65	if instDiags.HasErrors() {
66		t.Fatal(instDiags.Err())
67	}
68
69	// Since module installer has modified the module manifest on disk, we need
70	// to refresh the cache of it in the loader.
71	if err := loader.RefreshModules(); err != nil {
72		t.Fatalf("failed to refresh modules after installation: %s", err)
73	}
74
75	config, snap, diags := loader.LoadConfigWithSnapshot(dir)
76	if diags.HasErrors() {
77		t.Fatal(diags.Error())
78	}
79
80	return config, snap
81}
82
83// testModuleInline takes a map of path -> config strings and yields a config
84// structure with those files loaded from disk
85func testModuleInline(t *testing.T, sources map[string]string) *configs.Config {
86	t.Helper()
87
88	cfgPath, err := ioutil.TempDir("", "tf-test")
89	if err != nil {
90		t.Errorf("Error creating temporary directory for config: %s", err)
91	}
92	defer os.RemoveAll(cfgPath)
93
94	for path, configStr := range sources {
95		dir := filepath.Dir(path)
96		if dir != "." {
97			err := os.MkdirAll(filepath.Join(cfgPath, dir), os.FileMode(0777))
98			if err != nil {
99				t.Fatalf("Error creating subdir: %s", err)
100			}
101		}
102		// Write the configuration
103		cfgF, err := os.Create(filepath.Join(cfgPath, path))
104		if err != nil {
105			t.Fatalf("Error creating temporary file for config: %s", err)
106		}
107
108		_, err = io.Copy(cfgF, strings.NewReader(configStr))
109		cfgF.Close()
110		if err != nil {
111			t.Fatalf("Error creating temporary file for config: %s", err)
112		}
113	}
114
115	loader, cleanup := configload.NewLoaderForTests(t)
116	defer cleanup()
117
118	// Test modules usually do not refer to remote sources, and for local
119	// sources only this ultimately just records all of the module paths
120	// in a JSON file so that we can load them below.
121	inst := initwd.NewModuleInstaller(loader.ModulesDir(), registry.NewClient(nil, nil))
122	_, instDiags := inst.InstallModules(cfgPath, true, initwd.ModuleInstallHooksImpl{})
123	if instDiags.HasErrors() {
124		t.Fatal(instDiags.Err())
125	}
126
127	// Since module installer has modified the module manifest on disk, we need
128	// to refresh the cache of it in the loader.
129	if err := loader.RefreshModules(); err != nil {
130		t.Fatalf("failed to refresh modules after installation: %s", err)
131	}
132
133	config, diags := loader.LoadConfig(cfgPath)
134	if diags.HasErrors() {
135		t.Fatal(diags.Error())
136	}
137
138	return config
139}
140
141// testSetResourceInstanceCurrent is a helper function for tests that sets a Current,
142// Ready resource instance for the given module.
143func testSetResourceInstanceCurrent(module *states.Module, resource, attrsJson, provider string) {
144	module.SetResourceInstanceCurrent(
145		mustResourceInstanceAddr(resource).Resource,
146		&states.ResourceInstanceObjectSrc{
147			Status:    states.ObjectReady,
148			AttrsJSON: []byte(attrsJson),
149		},
150		mustProviderConfig(provider),
151	)
152}
153
154// testSetResourceInstanceTainted is a helper function for tests that sets a Current,
155// Tainted resource instance for the given module.
156func testSetResourceInstanceTainted(module *states.Module, resource, attrsJson, provider string) {
157	module.SetResourceInstanceCurrent(
158		mustResourceInstanceAddr(resource).Resource,
159		&states.ResourceInstanceObjectSrc{
160			Status:    states.ObjectTainted,
161			AttrsJSON: []byte(attrsJson),
162		},
163		mustProviderConfig(provider),
164	)
165}
166
167func testProviderFuncFixed(rp providers.Interface) providers.Factory {
168	return func() (providers.Interface, error) {
169		return rp, nil
170	}
171}
172
173func testProvisionerFuncFixed(rp *MockProvisioner) provisioners.Factory {
174	return func() (provisioners.Interface, error) {
175		// make sure this provisioner has has not been closed
176		rp.CloseCalled = false
177		return rp, nil
178	}
179}
180
181func mustResourceInstanceAddr(s string) addrs.AbsResourceInstance {
182	addr, diags := addrs.ParseAbsResourceInstanceStr(s)
183	if diags.HasErrors() {
184		panic(diags.Err())
185	}
186	return addr
187}
188
189func mustConfigResourceAddr(s string) addrs.ConfigResource {
190	addr, diags := addrs.ParseAbsResourceStr(s)
191	if diags.HasErrors() {
192		panic(diags.Err())
193	}
194	return addr.Config()
195}
196
197func mustAbsResourceAddr(s string) addrs.AbsResource {
198	addr, diags := addrs.ParseAbsResourceStr(s)
199	if diags.HasErrors() {
200		panic(diags.Err())
201	}
202	return addr
203}
204
205func mustProviderConfig(s string) addrs.AbsProviderConfig {
206	p, diags := addrs.ParseAbsProviderConfigStr(s)
207	if diags.HasErrors() {
208		panic(diags.Err())
209	}
210	return p
211}
212
213// HookRecordApplyOrder is a test hook that records the order of applies
214// by recording the PreApply event.
215type HookRecordApplyOrder struct {
216	NilHook
217
218	Active bool
219
220	IDs    []string
221	States []cty.Value
222	Diffs  []*plans.Change
223
224	l sync.Mutex
225}
226
227func (h *HookRecordApplyOrder) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
228	if plannedNewState.RawEquals(priorState) {
229		return HookActionContinue, nil
230	}
231
232	if h.Active {
233		h.l.Lock()
234		defer h.l.Unlock()
235
236		h.IDs = append(h.IDs, addr.String())
237		h.Diffs = append(h.Diffs, &plans.Change{
238			Action: action,
239			Before: priorState,
240			After:  plannedNewState,
241		})
242		h.States = append(h.States, priorState)
243	}
244
245	return HookActionContinue, nil
246}
247
248// Below are all the constant strings that are the expected output for
249// various tests.
250
251const testTerraformInputProviderOnlyStr = `
252aws_instance.foo:
253  ID =
254  provider = provider["registry.terraform.io/hashicorp/aws"]
255  foo = us-west-2
256  type =
257`
258
259const testTerraformApplyStr = `
260aws_instance.bar:
261  ID = foo
262  provider = provider["registry.terraform.io/hashicorp/aws"]
263  foo = bar
264  type = aws_instance
265aws_instance.foo:
266  ID = foo
267  provider = provider["registry.terraform.io/hashicorp/aws"]
268  num = 2
269  type = aws_instance
270`
271
272const testTerraformApplyDataBasicStr = `
273data.null_data_source.testing:
274  ID = yo
275  provider = provider["registry.terraform.io/hashicorp/null"]
276`
277
278const testTerraformApplyRefCountStr = `
279aws_instance.bar:
280  ID = foo
281  provider = provider["registry.terraform.io/hashicorp/aws"]
282  foo = 3
283  type = aws_instance
284
285  Dependencies:
286    aws_instance.foo
287aws_instance.foo.0:
288  ID = foo
289  provider = provider["registry.terraform.io/hashicorp/aws"]
290  type = aws_instance
291aws_instance.foo.1:
292  ID = foo
293  provider = provider["registry.terraform.io/hashicorp/aws"]
294  type = aws_instance
295aws_instance.foo.2:
296  ID = foo
297  provider = provider["registry.terraform.io/hashicorp/aws"]
298  type = aws_instance
299`
300
301const testTerraformApplyProviderAliasStr = `
302aws_instance.bar:
303  ID = foo
304  provider = provider["registry.terraform.io/hashicorp/aws"].bar
305  foo = bar
306  type = aws_instance
307aws_instance.foo:
308  ID = foo
309  provider = provider["registry.terraform.io/hashicorp/aws"]
310  num = 2
311  type = aws_instance
312`
313
314const testTerraformApplyProviderAliasConfigStr = `
315another_instance.bar:
316  ID = foo
317  provider = provider["registry.terraform.io/hashicorp/another"].two
318  type = another_instance
319another_instance.foo:
320  ID = foo
321  provider = provider["registry.terraform.io/hashicorp/another"]
322  type = another_instance
323`
324
325const testTerraformApplyEmptyModuleStr = `
326<no state>
327Outputs:
328
329end = XXXX
330`
331
332const testTerraformApplyDependsCreateBeforeStr = `
333aws_instance.lb:
334  ID = baz
335  provider = provider["registry.terraform.io/hashicorp/aws"]
336  instance = foo
337  type = aws_instance
338
339  Dependencies:
340    aws_instance.web
341aws_instance.web:
342  ID = foo
343  provider = provider["registry.terraform.io/hashicorp/aws"]
344  require_new = ami-new
345  type = aws_instance
346`
347
348const testTerraformApplyCreateBeforeStr = `
349aws_instance.bar:
350  ID = foo
351  provider = provider["registry.terraform.io/hashicorp/aws"]
352  require_new = xyz
353  type = aws_instance
354`
355
356const testTerraformApplyCreateBeforeUpdateStr = `
357aws_instance.bar:
358  ID = bar
359  provider = provider["registry.terraform.io/hashicorp/aws"]
360  foo = baz
361  type = aws_instance
362`
363
364const testTerraformApplyCancelStr = `
365aws_instance.foo:
366  ID = foo
367  provider = provider["registry.terraform.io/hashicorp/aws"]
368  type = aws_instance
369  value = 2
370`
371
372const testTerraformApplyComputeStr = `
373aws_instance.bar:
374  ID = foo
375  provider = provider["registry.terraform.io/hashicorp/aws"]
376  foo = computed_value
377  type = aws_instance
378
379  Dependencies:
380    aws_instance.foo
381aws_instance.foo:
382  ID = foo
383  provider = provider["registry.terraform.io/hashicorp/aws"]
384  compute = value
385  compute_value = 1
386  num = 2
387  type = aws_instance
388  value = computed_value
389`
390
391const testTerraformApplyCountDecStr = `
392aws_instance.bar:
393  ID = foo
394  provider = provider["registry.terraform.io/hashicorp/aws"]
395  foo = bar
396  type = aws_instance
397aws_instance.foo.0:
398  ID = bar
399  provider = provider["registry.terraform.io/hashicorp/aws"]
400  foo = foo
401  type = aws_instance
402aws_instance.foo.1:
403  ID = bar
404  provider = provider["registry.terraform.io/hashicorp/aws"]
405  foo = foo
406  type = aws_instance
407`
408
409const testTerraformApplyCountDecToOneStr = `
410aws_instance.foo:
411  ID = bar
412  provider = provider["registry.terraform.io/hashicorp/aws"]
413  foo = foo
414  type = aws_instance
415`
416
417const testTerraformApplyCountDecToOneCorruptedStr = `
418aws_instance.foo:
419  ID = bar
420  provider = provider["registry.terraform.io/hashicorp/aws"]
421  foo = foo
422  type = aws_instance
423`
424
425const testTerraformApplyCountDecToOneCorruptedPlanStr = `
426DIFF:
427
428DESTROY: aws_instance.foo[0]
429  id:   "baz" => ""
430  type: "aws_instance" => ""
431
432
433
434STATE:
435
436aws_instance.foo:
437  ID = bar
438  provider = provider["registry.terraform.io/hashicorp/aws"]
439  foo = foo
440  type = aws_instance
441aws_instance.foo.0:
442  ID = baz
443  provider = provider["registry.terraform.io/hashicorp/aws"]
444  type = aws_instance
445`
446
447const testTerraformApplyCountVariableStr = `
448aws_instance.foo.0:
449  ID = foo
450  provider = provider["registry.terraform.io/hashicorp/aws"]
451  foo = foo
452  type = aws_instance
453aws_instance.foo.1:
454  ID = foo
455  provider = provider["registry.terraform.io/hashicorp/aws"]
456  foo = foo
457  type = aws_instance
458`
459
460const testTerraformApplyCountVariableRefStr = `
461aws_instance.bar:
462  ID = foo
463  provider = provider["registry.terraform.io/hashicorp/aws"]
464  foo = 2
465  type = aws_instance
466
467  Dependencies:
468    aws_instance.foo
469aws_instance.foo.0:
470  ID = foo
471  provider = provider["registry.terraform.io/hashicorp/aws"]
472  type = aws_instance
473aws_instance.foo.1:
474  ID = foo
475  provider = provider["registry.terraform.io/hashicorp/aws"]
476  type = aws_instance
477`
478const testTerraformApplyForEachVariableStr = `
479aws_instance.foo["b15c6d616d6143248c575900dff57325eb1de498"]:
480  ID = foo
481  provider = provider["registry.terraform.io/hashicorp/aws"]
482  foo = foo
483  type = aws_instance
484aws_instance.foo["c3de47d34b0a9f13918dd705c141d579dd6555fd"]:
485  ID = foo
486  provider = provider["registry.terraform.io/hashicorp/aws"]
487  foo = foo
488  type = aws_instance
489aws_instance.foo["e30a7edcc42a846684f2a4eea5f3cd261d33c46d"]:
490  ID = foo
491  provider = provider["registry.terraform.io/hashicorp/aws"]
492  foo = foo
493  type = aws_instance
494aws_instance.one["a"]:
495  ID = foo
496  provider = provider["registry.terraform.io/hashicorp/aws"]
497  type = aws_instance
498aws_instance.one["b"]:
499  ID = foo
500  provider = provider["registry.terraform.io/hashicorp/aws"]
501  type = aws_instance
502aws_instance.two["a"]:
503  ID = foo
504  provider = provider["registry.terraform.io/hashicorp/aws"]
505  type = aws_instance
506
507  Dependencies:
508    aws_instance.one
509aws_instance.two["b"]:
510  ID = foo
511  provider = provider["registry.terraform.io/hashicorp/aws"]
512  type = aws_instance
513
514  Dependencies:
515    aws_instance.one`
516const testTerraformApplyMinimalStr = `
517aws_instance.bar:
518  ID = foo
519  provider = provider["registry.terraform.io/hashicorp/aws"]
520  type = aws_instance
521aws_instance.foo:
522  ID = foo
523  provider = provider["registry.terraform.io/hashicorp/aws"]
524  type = aws_instance
525`
526
527const testTerraformApplyModuleStr = `
528aws_instance.bar:
529  ID = foo
530  provider = provider["registry.terraform.io/hashicorp/aws"]
531  foo = bar
532  type = aws_instance
533aws_instance.foo:
534  ID = foo
535  provider = provider["registry.terraform.io/hashicorp/aws"]
536  num = 2
537  type = aws_instance
538
539module.child:
540  aws_instance.baz:
541    ID = foo
542    provider = provider["registry.terraform.io/hashicorp/aws"]
543    foo = bar
544    type = aws_instance
545`
546
547const testTerraformApplyModuleBoolStr = `
548aws_instance.bar:
549  ID = foo
550  provider = provider["registry.terraform.io/hashicorp/aws"]
551  foo = true
552  type = aws_instance
553`
554
555const testTerraformApplyModuleDestroyOrderStr = `
556<no state>
557`
558
559const testTerraformApplyMultiProviderStr = `
560aws_instance.bar:
561  ID = foo
562  provider = provider["registry.terraform.io/hashicorp/aws"]
563  foo = bar
564  type = aws_instance
565do_instance.foo:
566  ID = foo
567  provider = provider["registry.terraform.io/hashicorp/do"]
568  num = 2
569  type = do_instance
570`
571
572const testTerraformApplyModuleOnlyProviderStr = `
573<no state>
574module.child:
575  aws_instance.foo:
576    ID = foo
577    provider = provider["registry.terraform.io/hashicorp/aws"]
578    type = aws_instance
579  test_instance.foo:
580    ID = foo
581    provider = provider["registry.terraform.io/hashicorp/test"]
582    type = test_instance
583`
584
585const testTerraformApplyModuleProviderAliasStr = `
586<no state>
587module.child:
588  aws_instance.foo:
589    ID = foo
590    provider = module.child.provider["registry.terraform.io/hashicorp/aws"].eu
591    type = aws_instance
592`
593
594const testTerraformApplyModuleVarRefExistingStr = `
595aws_instance.foo:
596  ID = foo
597  provider = provider["registry.terraform.io/hashicorp/aws"]
598  foo = bar
599  type = aws_instance
600
601module.child:
602  aws_instance.foo:
603    ID = foo
604    provider = provider["registry.terraform.io/hashicorp/aws"]
605    type = aws_instance
606    value = bar
607
608    Dependencies:
609      aws_instance.foo
610`
611
612const testTerraformApplyOutputOrphanStr = `
613<no state>
614Outputs:
615
616foo = bar
617`
618
619const testTerraformApplyOutputOrphanModuleStr = `
620<no state>
621`
622
623const testTerraformApplyProvisionerStr = `
624aws_instance.bar:
625  ID = foo
626  provider = provider["registry.terraform.io/hashicorp/aws"]
627  type = aws_instance
628
629  Dependencies:
630    aws_instance.foo
631aws_instance.foo:
632  ID = foo
633  provider = provider["registry.terraform.io/hashicorp/aws"]
634  compute = value
635  compute_value = 1
636  num = 2
637  type = aws_instance
638  value = computed_value
639`
640
641const testTerraformApplyProvisionerModuleStr = `
642<no state>
643module.child:
644  aws_instance.bar:
645    ID = foo
646    provider = provider["registry.terraform.io/hashicorp/aws"]
647    type = aws_instance
648`
649
650const testTerraformApplyProvisionerFailStr = `
651aws_instance.bar: (tainted)
652  ID = foo
653  provider = provider["registry.terraform.io/hashicorp/aws"]
654  type = aws_instance
655aws_instance.foo:
656  ID = foo
657  provider = provider["registry.terraform.io/hashicorp/aws"]
658  num = 2
659  type = aws_instance
660`
661
662const testTerraformApplyProvisionerFailCreateStr = `
663aws_instance.bar: (tainted)
664  ID = foo
665  provider = provider["registry.terraform.io/hashicorp/aws"]
666  type = aws_instance
667`
668
669const testTerraformApplyProvisionerFailCreateNoIdStr = `
670<no state>
671`
672
673const testTerraformApplyProvisionerFailCreateBeforeDestroyStr = `
674aws_instance.bar: (tainted) (1 deposed)
675  ID = foo
676  provider = provider["registry.terraform.io/hashicorp/aws"]
677  require_new = xyz
678  type = aws_instance
679  Deposed ID 1 = bar
680`
681
682const testTerraformApplyProvisionerResourceRefStr = `
683aws_instance.bar:
684  ID = foo
685  provider = provider["registry.terraform.io/hashicorp/aws"]
686  num = 2
687  type = aws_instance
688`
689
690const testTerraformApplyProvisionerSelfRefStr = `
691aws_instance.foo:
692  ID = foo
693  provider = provider["registry.terraform.io/hashicorp/aws"]
694  foo = bar
695  type = aws_instance
696`
697
698const testTerraformApplyProvisionerMultiSelfRefStr = `
699aws_instance.foo.0:
700  ID = foo
701  provider = provider["registry.terraform.io/hashicorp/aws"]
702  foo = number 0
703  type = aws_instance
704aws_instance.foo.1:
705  ID = foo
706  provider = provider["registry.terraform.io/hashicorp/aws"]
707  foo = number 1
708  type = aws_instance
709aws_instance.foo.2:
710  ID = foo
711  provider = provider["registry.terraform.io/hashicorp/aws"]
712  foo = number 2
713  type = aws_instance
714`
715
716const testTerraformApplyProvisionerMultiSelfRefSingleStr = `
717aws_instance.foo.0:
718  ID = foo
719  provider = provider["registry.terraform.io/hashicorp/aws"]
720  foo = number 0
721  type = aws_instance
722aws_instance.foo.1:
723  ID = foo
724  provider = provider["registry.terraform.io/hashicorp/aws"]
725  foo = number 1
726  type = aws_instance
727aws_instance.foo.2:
728  ID = foo
729  provider = provider["registry.terraform.io/hashicorp/aws"]
730  foo = number 2
731  type = aws_instance
732`
733
734const testTerraformApplyProvisionerDiffStr = `
735aws_instance.bar:
736  ID = foo
737  provider = provider["registry.terraform.io/hashicorp/aws"]
738  foo = bar
739  type = aws_instance
740`
741
742const testTerraformApplyProvisionerSensitiveStr = `
743aws_instance.foo:
744  ID = foo
745  provider = provider["registry.terraform.io/hashicorp/aws"]
746  type = aws_instance
747`
748
749const testTerraformApplyDestroyStr = `
750<no state>
751`
752
753const testTerraformApplyErrorStr = `
754aws_instance.bar: (tainted)
755  ID =
756  provider = provider["registry.terraform.io/hashicorp/aws"]
757  foo = 2
758
759  Dependencies:
760    aws_instance.foo
761aws_instance.foo:
762  ID = foo
763  provider = provider["registry.terraform.io/hashicorp/aws"]
764  type = aws_instance
765  value = 2
766`
767
768const testTerraformApplyErrorCreateBeforeDestroyStr = `
769aws_instance.bar:
770  ID = bar
771  provider = provider["registry.terraform.io/hashicorp/aws"]
772  require_new = abc
773  type = aws_instance
774`
775
776const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = `
777aws_instance.bar: (1 deposed)
778  ID = foo
779  provider = provider["registry.terraform.io/hashicorp/aws"]
780  require_new = xyz
781  type = aws_instance
782  Deposed ID 1 = bar
783`
784
785const testTerraformApplyErrorPartialStr = `
786aws_instance.bar:
787  ID = bar
788  provider = provider["registry.terraform.io/hashicorp/aws"]
789  type = aws_instance
790
791  Dependencies:
792    aws_instance.foo
793aws_instance.foo:
794  ID = foo
795  provider = provider["registry.terraform.io/hashicorp/aws"]
796  type = aws_instance
797  value = 2
798`
799
800const testTerraformApplyResourceDependsOnModuleStr = `
801aws_instance.a:
802  ID = foo
803  provider = provider["registry.terraform.io/hashicorp/aws"]
804  ami = parent
805  type = aws_instance
806
807  Dependencies:
808    module.child.aws_instance.child
809
810module.child:
811  aws_instance.child:
812    ID = foo
813    provider = provider["registry.terraform.io/hashicorp/aws"]
814    ami = child
815    type = aws_instance
816`
817
818const testTerraformApplyResourceDependsOnModuleDeepStr = `
819aws_instance.a:
820  ID = foo
821  provider = provider["registry.terraform.io/hashicorp/aws"]
822  ami = parent
823  type = aws_instance
824
825  Dependencies:
826    module.child.module.grandchild.aws_instance.c
827
828module.child.grandchild:
829  aws_instance.c:
830    ID = foo
831    provider = provider["registry.terraform.io/hashicorp/aws"]
832    ami = grandchild
833    type = aws_instance
834`
835
836const testTerraformApplyResourceDependsOnModuleInModuleStr = `
837<no state>
838module.child:
839  aws_instance.b:
840    ID = foo
841    provider = provider["registry.terraform.io/hashicorp/aws"]
842    ami = child
843    type = aws_instance
844
845    Dependencies:
846      module.child.module.grandchild.aws_instance.c
847module.child.grandchild:
848  aws_instance.c:
849    ID = foo
850    provider = provider["registry.terraform.io/hashicorp/aws"]
851    ami = grandchild
852    type = aws_instance
853`
854
855const testTerraformApplyTaintStr = `
856aws_instance.bar:
857  ID = foo
858  provider = provider["registry.terraform.io/hashicorp/aws"]
859  num = 2
860  type = aws_instance
861`
862
863const testTerraformApplyTaintDepStr = `
864aws_instance.bar:
865  ID = bar
866  provider = provider["registry.terraform.io/hashicorp/aws"]
867  foo = foo
868  num = 2
869  type = aws_instance
870
871  Dependencies:
872    aws_instance.foo
873aws_instance.foo:
874  ID = foo
875  provider = provider["registry.terraform.io/hashicorp/aws"]
876  num = 2
877  type = aws_instance
878`
879
880const testTerraformApplyTaintDepRequireNewStr = `
881aws_instance.bar:
882  ID = foo
883  provider = provider["registry.terraform.io/hashicorp/aws"]
884  foo = foo
885  require_new = yes
886  type = aws_instance
887
888  Dependencies:
889    aws_instance.foo
890aws_instance.foo:
891  ID = foo
892  provider = provider["registry.terraform.io/hashicorp/aws"]
893  num = 2
894  type = aws_instance
895`
896
897const testTerraformApplyOutputStr = `
898aws_instance.bar:
899  ID = foo
900  provider = provider["registry.terraform.io/hashicorp/aws"]
901  foo = bar
902  type = aws_instance
903aws_instance.foo:
904  ID = foo
905  provider = provider["registry.terraform.io/hashicorp/aws"]
906  num = 2
907  type = aws_instance
908
909Outputs:
910
911foo_num = 2
912`
913
914const testTerraformApplyOutputAddStr = `
915aws_instance.test.0:
916  ID = foo
917  provider = provider["registry.terraform.io/hashicorp/aws"]
918  foo = foo0
919  type = aws_instance
920aws_instance.test.1:
921  ID = foo
922  provider = provider["registry.terraform.io/hashicorp/aws"]
923  foo = foo1
924  type = aws_instance
925
926Outputs:
927
928firstOutput = foo0
929secondOutput = foo1
930`
931
932const testTerraformApplyOutputListStr = `
933aws_instance.bar.0:
934  ID = foo
935  provider = provider["registry.terraform.io/hashicorp/aws"]
936  foo = bar
937  type = aws_instance
938aws_instance.bar.1:
939  ID = foo
940  provider = provider["registry.terraform.io/hashicorp/aws"]
941  foo = bar
942  type = aws_instance
943aws_instance.bar.2:
944  ID = foo
945  provider = provider["registry.terraform.io/hashicorp/aws"]
946  foo = bar
947  type = aws_instance
948aws_instance.foo:
949  ID = foo
950  provider = provider["registry.terraform.io/hashicorp/aws"]
951  num = 2
952  type = aws_instance
953
954Outputs:
955
956foo_num = [bar,bar,bar]
957`
958
959const testTerraformApplyOutputMultiStr = `
960aws_instance.bar.0:
961  ID = foo
962  provider = provider["registry.terraform.io/hashicorp/aws"]
963  foo = bar
964  type = aws_instance
965aws_instance.bar.1:
966  ID = foo
967  provider = provider["registry.terraform.io/hashicorp/aws"]
968  foo = bar
969  type = aws_instance
970aws_instance.bar.2:
971  ID = foo
972  provider = provider["registry.terraform.io/hashicorp/aws"]
973  foo = bar
974  type = aws_instance
975aws_instance.foo:
976  ID = foo
977  provider = provider["registry.terraform.io/hashicorp/aws"]
978  num = 2
979  type = aws_instance
980
981Outputs:
982
983foo_num = bar,bar,bar
984`
985
986const testTerraformApplyOutputMultiIndexStr = `
987aws_instance.bar.0:
988  ID = foo
989  provider = provider["registry.terraform.io/hashicorp/aws"]
990  foo = bar
991  type = aws_instance
992aws_instance.bar.1:
993  ID = foo
994  provider = provider["registry.terraform.io/hashicorp/aws"]
995  foo = bar
996  type = aws_instance
997aws_instance.bar.2:
998  ID = foo
999  provider = provider["registry.terraform.io/hashicorp/aws"]
1000  foo = bar
1001  type = aws_instance
1002aws_instance.foo:
1003  ID = foo
1004  provider = provider["registry.terraform.io/hashicorp/aws"]
1005  num = 2
1006  type = aws_instance
1007
1008Outputs:
1009
1010foo_num = bar
1011`
1012
1013const testTerraformApplyUnknownAttrStr = `
1014aws_instance.foo: (tainted)
1015  ID = foo
1016  provider = provider["registry.terraform.io/hashicorp/aws"]
1017  num = 2
1018  type = aws_instance
1019`
1020
1021const testTerraformApplyVarsStr = `
1022aws_instance.bar:
1023  ID = foo
1024  provider = provider["registry.terraform.io/hashicorp/aws"]
1025  bar = override
1026  baz = override
1027  foo = us-east-1
1028aws_instance.foo:
1029  ID = foo
1030  provider = provider["registry.terraform.io/hashicorp/aws"]
1031  bar = baz
1032  list.# = 2
1033  list.0 = Hello
1034  list.1 = World
1035  map.Baz = Foo
1036  map.Foo = Bar
1037  map.Hello = World
1038  num = 2
1039`
1040
1041const testTerraformApplyVarsEnvStr = `
1042aws_instance.bar:
1043  ID = foo
1044  provider = provider["registry.terraform.io/hashicorp/aws"]
1045  list.# = 2
1046  list.0 = Hello
1047  list.1 = World
1048  map.Baz = Foo
1049  map.Foo = Bar
1050  map.Hello = World
1051  string = baz
1052  type = aws_instance
1053`
1054
1055const testTerraformRefreshDataRefDataStr = `
1056data.null_data_source.bar:
1057  ID = foo
1058  provider = provider["registry.terraform.io/hashicorp/null"]
1059  bar = yes
1060data.null_data_source.foo:
1061  ID = foo
1062  provider = provider["registry.terraform.io/hashicorp/null"]
1063  foo = yes
1064`
1065