github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/terraform_test.go (about)

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