github.com/tomaszheflik/terraform@v0.7.3-0.20160827060421-32f990b41594/terraform/terraform_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"log"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  	"sync"
    13  	"testing"
    14  
    15  	"github.com/hashicorp/go-getter"
    16  	"github.com/hashicorp/terraform/config"
    17  	"github.com/hashicorp/terraform/config/module"
    18  	"github.com/hashicorp/terraform/helper/logging"
    19  )
    20  
    21  // This is the directory where our test fixtures are.
    22  const fixtureDir = "./test-fixtures"
    23  
    24  func TestMain(m *testing.M) {
    25  	flag.Parse()
    26  	if testing.Verbose() {
    27  		// if we're verbose, use the logging requested by TF_LOG
    28  		logging.SetOutput()
    29  	} else {
    30  		// otherwise silence all logs
    31  		log.SetOutput(ioutil.Discard)
    32  	}
    33  
    34  	os.Exit(m.Run())
    35  }
    36  
    37  func tempDir(t *testing.T) string {
    38  	dir, err := ioutil.TempDir("", "tf")
    39  	if err != nil {
    40  		t.Fatalf("err: %s", err)
    41  	}
    42  	if err := os.RemoveAll(dir); err != nil {
    43  		t.Fatalf("err: %s", err)
    44  	}
    45  
    46  	return dir
    47  }
    48  
    49  // tempEnv lets you temporarily set an environment variable. It returns
    50  // a function to defer to reset the old value.
    51  // the old value that should be set via a defer.
    52  func tempEnv(t *testing.T, k string, v string) func() {
    53  	old := os.Getenv(k)
    54  	os.Setenv(k, v)
    55  	return func() { os.Setenv(k, old) }
    56  }
    57  
    58  func testConfig(t *testing.T, name string) *config.Config {
    59  	c, err := config.LoadFile(filepath.Join(fixtureDir, name, "main.tf"))
    60  	if err != nil {
    61  		t.Fatalf("err: %s", err)
    62  	}
    63  
    64  	return c
    65  }
    66  
    67  func testModule(t *testing.T, name string) *module.Tree {
    68  	mod, err := module.NewTreeModule("", filepath.Join(fixtureDir, name))
    69  	if err != nil {
    70  		t.Fatalf("err: %s", err)
    71  	}
    72  
    73  	s := &getter.FolderStorage{StorageDir: tempDir(t)}
    74  	if err := mod.Load(s, module.GetModeGet); err != nil {
    75  		t.Fatalf("err: %s", err)
    76  	}
    77  
    78  	return mod
    79  }
    80  
    81  // testModuleInline takes a map of path -> config strings and yields a config
    82  // structure with those files loaded from disk
    83  func testModuleInline(t *testing.T, config map[string]string) *module.Tree {
    84  	cfgPath, err := ioutil.TempDir("", "tf-test")
    85  	if err != nil {
    86  		t.Errorf("Error creating temporary directory for config: %s", err)
    87  	}
    88  	defer os.RemoveAll(cfgPath)
    89  
    90  	for path, configStr := range config {
    91  		dir := filepath.Dir(path)
    92  		if dir != "." {
    93  			err := os.MkdirAll(filepath.Join(cfgPath, dir), os.FileMode(0777))
    94  			if err != nil {
    95  				t.Fatalf("Error creating subdir: %s", err)
    96  			}
    97  		}
    98  		// Write the configuration
    99  		cfgF, err := os.Create(filepath.Join(cfgPath, path))
   100  		if err != nil {
   101  			t.Fatalf("Error creating temporary file for config: %s", err)
   102  		}
   103  
   104  		_, err = io.Copy(cfgF, strings.NewReader(configStr))
   105  		cfgF.Close()
   106  		if err != nil {
   107  			t.Fatalf("Error creating temporary file for config: %s", err)
   108  		}
   109  	}
   110  
   111  	// Parse the configuration
   112  	mod, err := module.NewTreeModule("", cfgPath)
   113  	if err != nil {
   114  		t.Fatalf("Error loading configuration: %s", err)
   115  	}
   116  
   117  	// Load the modules
   118  	modStorage := &getter.FolderStorage{
   119  		StorageDir: filepath.Join(cfgPath, ".tfmodules"),
   120  	}
   121  	err = mod.Load(modStorage, module.GetModeGet)
   122  	if err != nil {
   123  		t.Errorf("Error downloading modules: %s", err)
   124  	}
   125  
   126  	return mod
   127  }
   128  
   129  func testStringMatch(t *testing.T, s fmt.Stringer, expected string) {
   130  	actual := strings.TrimSpace(s.String())
   131  	expected = strings.TrimSpace(expected)
   132  	if actual != expected {
   133  		t.Fatalf("Actual\n\n%s\n\nExpected:\n\n%s", actual, expected)
   134  	}
   135  }
   136  
   137  func testProviderFuncFixed(rp ResourceProvider) ResourceProviderFactory {
   138  	return func() (ResourceProvider, error) {
   139  		return rp, nil
   140  	}
   141  }
   142  
   143  func testProvisionerFuncFixed(rp ResourceProvisioner) ResourceProvisionerFactory {
   144  	return func() (ResourceProvisioner, error) {
   145  		return rp, nil
   146  	}
   147  }
   148  
   149  // HookRecordApplyOrder is a test hook that records the order of applies
   150  // by recording the PreApply event.
   151  type HookRecordApplyOrder struct {
   152  	NilHook
   153  
   154  	Active bool
   155  
   156  	IDs    []string
   157  	States []*InstanceState
   158  	Diffs  []*InstanceDiff
   159  
   160  	l sync.Mutex
   161  }
   162  
   163  func (h *HookRecordApplyOrder) PreApply(
   164  	info *InstanceInfo,
   165  	s *InstanceState,
   166  	d *InstanceDiff) (HookAction, error) {
   167  	if h.Active {
   168  		h.l.Lock()
   169  		defer h.l.Unlock()
   170  
   171  		h.IDs = append(h.IDs, info.Id)
   172  		h.Diffs = append(h.Diffs, d)
   173  		h.States = append(h.States, s)
   174  	}
   175  
   176  	return HookActionContinue, nil
   177  }
   178  
   179  // Below are all the constant strings that are the expected output for
   180  // various tests.
   181  
   182  const testTerraformInputProviderStr = `
   183  aws_instance.bar:
   184    ID = foo
   185    bar = override
   186    foo = us-east-1
   187    type = aws_instance
   188  aws_instance.foo:
   189    ID = foo
   190    bar = baz
   191    num = 2
   192    type = aws_instance
   193  `
   194  
   195  const testTerraformInputProviderOnlyStr = `
   196  aws_instance.foo:
   197    ID = foo
   198    foo = us-west-2
   199    type = aws_instance
   200  `
   201  
   202  const testTerraformInputVarOnlyStr = `
   203  aws_instance.foo:
   204    ID = foo
   205    foo = us-east-1
   206    type = aws_instance
   207  `
   208  
   209  const testTerraformInputVarOnlyUnsetStr = `
   210  aws_instance.foo:
   211    ID = foo
   212    bar = baz
   213    foo = foovalue
   214    type = aws_instance
   215  `
   216  
   217  const testTerraformInputVarsStr = `
   218  aws_instance.bar:
   219    ID = foo
   220    bar = override
   221    foo = us-east-1
   222    type = aws_instance
   223  aws_instance.foo:
   224    ID = foo
   225    bar = baz
   226    num = 2
   227    type = aws_instance
   228  `
   229  
   230  const testTerraformApplyStr = `
   231  aws_instance.bar:
   232    ID = foo
   233    foo = bar
   234    type = aws_instance
   235  aws_instance.foo:
   236    ID = foo
   237    num = 2
   238    type = aws_instance
   239  `
   240  
   241  const testTerraformApplyProviderAliasStr = `
   242  aws_instance.bar:
   243    ID = foo
   244    provider = aws.bar
   245    foo = bar
   246    type = aws_instance
   247  aws_instance.foo:
   248    ID = foo
   249    num = 2
   250    type = aws_instance
   251  `
   252  
   253  const testTerraformApplyEmptyModuleStr = `
   254  <no state>
   255  Outputs:
   256  
   257  end = XXXX
   258  
   259  module.child:
   260  <no state>
   261  Outputs:
   262  
   263  aws_access_key = YYYYY
   264  aws_route53_zone_id = XXXX
   265  aws_secret_key = ZZZZ
   266  `
   267  
   268  const testTerraformApplyDependsCreateBeforeStr = `
   269  aws_instance.lb:
   270    ID = foo
   271    instance = foo
   272    type = aws_instance
   273  
   274    Dependencies:
   275      aws_instance.web
   276  aws_instance.web:
   277    ID = foo
   278    require_new = ami-new
   279    type = aws_instance
   280  `
   281  
   282  const testTerraformApplyCreateBeforeStr = `
   283  aws_instance.bar:
   284    ID = foo
   285    require_new = xyz
   286    type = aws_instance
   287  `
   288  
   289  const testTerraformApplyCreateBeforeUpdateStr = `
   290  aws_instance.bar:
   291    ID = foo
   292    foo = baz
   293    type = aws_instance
   294  `
   295  
   296  const testTerraformApplyCancelStr = `
   297  aws_instance.foo:
   298    ID = foo
   299    num = 2
   300  `
   301  
   302  const testTerraformApplyComputeStr = `
   303  aws_instance.bar:
   304    ID = foo
   305    foo = computed_dynamical
   306    type = aws_instance
   307  
   308    Dependencies:
   309      aws_instance.foo
   310  aws_instance.foo:
   311    ID = foo
   312    dynamical = computed_dynamical
   313    num = 2
   314    type = aws_instance
   315  `
   316  
   317  const testTerraformApplyCountDecStr = `
   318  aws_instance.foo.0:
   319    ID = bar
   320    foo = foo
   321    type = aws_instance
   322  aws_instance.foo.1:
   323    ID = bar
   324    foo = foo
   325    type = aws_instance
   326  `
   327  
   328  const testTerraformApplyCountDecToOneStr = `
   329  aws_instance.foo:
   330    ID = bar
   331    foo = foo
   332    type = aws_instance
   333  `
   334  
   335  const testTerraformApplyCountDecToOneCorruptedStr = `
   336  aws_instance.foo:
   337    ID = bar
   338    foo = foo
   339    type = aws_instance
   340  `
   341  
   342  const testTerraformApplyCountDecToOneCorruptedPlanStr = `
   343  DIFF:
   344  
   345  DESTROY: aws_instance.foo.0
   346  
   347  STATE:
   348  
   349  aws_instance.foo:
   350    ID = bar
   351    foo = foo
   352    type = aws_instance
   353  aws_instance.foo.0:
   354    ID = baz
   355    type = aws_instance
   356  `
   357  
   358  const testTerraformApplyCountTaintedStr = `
   359  <no state>
   360  `
   361  
   362  const testTerraformApplyCountVariableStr = `
   363  aws_instance.foo.0:
   364    ID = foo
   365    foo = foo
   366    type = aws_instance
   367  aws_instance.foo.1:
   368    ID = foo
   369    foo = foo
   370    type = aws_instance
   371  `
   372  
   373  const testTerraformApplyMinimalStr = `
   374  aws_instance.bar:
   375    ID = foo
   376  aws_instance.foo:
   377    ID = foo
   378  `
   379  
   380  const testTerraformApplyModuleStr = `
   381  aws_instance.bar:
   382    ID = foo
   383    foo = bar
   384    type = aws_instance
   385  aws_instance.foo:
   386    ID = foo
   387    num = 2
   388    type = aws_instance
   389  
   390  module.child:
   391    aws_instance.baz:
   392      ID = foo
   393      foo = bar
   394      type = aws_instance
   395  `
   396  
   397  const testTerraformApplyModuleBoolStr = `
   398  aws_instance.bar:
   399    ID = foo
   400    foo = 1
   401    type = aws_instance
   402  
   403    Dependencies:
   404      module.child
   405  
   406  module.child:
   407    <no state>
   408    Outputs:
   409  
   410    leader = 1
   411  `
   412  
   413  const testTerraformApplyModuleDestroyOrderStr = `
   414  <no state>
   415  module.child:
   416    <no state>
   417  `
   418  
   419  const testTerraformApplyMultiProviderStr = `
   420  aws_instance.bar:
   421    ID = foo
   422    foo = bar
   423    type = aws_instance
   424  do_instance.foo:
   425    ID = foo
   426    num = 2
   427    type = do_instance
   428  `
   429  
   430  const testTerraformApplyModuleOnlyProviderStr = `
   431  <no state>
   432  module.child:
   433    aws_instance.foo:
   434      ID = foo
   435    test_instance.foo:
   436      ID = foo
   437  `
   438  
   439  const testTerraformApplyModuleProviderAliasStr = `
   440  <no state>
   441  module.child:
   442    aws_instance.foo:
   443      ID = foo
   444      provider = aws.eu
   445  `
   446  
   447  const testTerraformApplyOutputOrphanStr = `
   448  <no state>
   449  Outputs:
   450  
   451  foo = bar
   452  `
   453  
   454  const testTerraformApplyProvisionerStr = `
   455  aws_instance.bar:
   456    ID = foo
   457  
   458    Dependencies:
   459      aws_instance.foo
   460  aws_instance.foo:
   461    ID = foo
   462    dynamical = computed_dynamical
   463    num = 2
   464    type = aws_instance
   465  `
   466  
   467  const testTerraformApplyProvisionerFailStr = `
   468  aws_instance.bar: (tainted)
   469    ID = foo
   470  aws_instance.foo:
   471    ID = foo
   472    num = 2
   473    type = aws_instance
   474  `
   475  
   476  const testTerraformApplyProvisionerFailCreateStr = `
   477  aws_instance.bar: (tainted)
   478    ID = foo
   479  `
   480  
   481  const testTerraformApplyProvisionerFailCreateNoIdStr = `
   482  <no state>
   483  `
   484  
   485  const testTerraformApplyProvisionerFailCreateBeforeDestroyStr = `
   486  aws_instance.bar: (1 deposed)
   487    ID = bar
   488    require_new = abc
   489    Deposed ID 1 = foo (tainted)
   490  `
   491  
   492  const testTerraformApplyProvisionerResourceRefStr = `
   493  aws_instance.bar:
   494    ID = foo
   495    num = 2
   496    type = aws_instance
   497  `
   498  
   499  const testTerraformApplyProvisionerSelfRefStr = `
   500  aws_instance.foo:
   501    ID = foo
   502    foo = bar
   503    type = aws_instance
   504  `
   505  
   506  const testTerraformApplyProvisionerMultiSelfRefStr = `
   507  aws_instance.foo.0:
   508    ID = foo
   509    foo = number 0
   510    type = aws_instance
   511  aws_instance.foo.1:
   512    ID = foo
   513    foo = number 1
   514    type = aws_instance
   515  aws_instance.foo.2:
   516    ID = foo
   517    foo = number 2
   518    type = aws_instance
   519  `
   520  
   521  const testTerraformApplyProvisionerDiffStr = `
   522  aws_instance.bar:
   523    ID = foo
   524    foo = bar
   525    type = aws_instance
   526  `
   527  
   528  const testTerraformApplyDestroyStr = `
   529  <no state>
   530  `
   531  
   532  const testTerraformApplyDestroyNestedModuleStr = `
   533  module.child.subchild:
   534    <no state>
   535  `
   536  
   537  const testTerraformApplyErrorStr = `
   538  aws_instance.bar:
   539    ID = bar
   540  
   541    Dependencies:
   542      aws_instance.foo
   543  aws_instance.foo:
   544    ID = foo
   545    num = 2
   546  `
   547  
   548  const testTerraformApplyErrorCreateBeforeDestroyStr = `
   549  aws_instance.bar:
   550    ID = bar
   551    require_new = abc
   552  `
   553  
   554  const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = `
   555  aws_instance.bar: (1 deposed)
   556    ID = foo
   557    Deposed ID 1 = bar
   558  `
   559  
   560  const testTerraformApplyErrorPartialStr = `
   561  aws_instance.bar:
   562    ID = bar
   563  
   564    Dependencies:
   565      aws_instance.foo
   566  aws_instance.foo:
   567    ID = foo
   568    num = 2
   569  `
   570  
   571  const testTerraformApplyTaintStr = `
   572  aws_instance.bar:
   573    ID = foo
   574    num = 2
   575    type = aws_instance
   576  `
   577  
   578  const testTerraformApplyTaintDepStr = `
   579  aws_instance.bar:
   580    ID = bar
   581    foo = foo
   582    num = 2
   583    type = aws_instance
   584  
   585    Dependencies:
   586      aws_instance.foo
   587  aws_instance.foo:
   588    ID = foo
   589    num = 2
   590    type = aws_instance
   591  `
   592  
   593  const testTerraformApplyTaintDepRequireNewStr = `
   594  aws_instance.bar:
   595    ID = foo
   596    foo = foo
   597    require_new = yes
   598    type = aws_instance
   599  
   600    Dependencies:
   601      aws_instance.foo
   602  aws_instance.foo:
   603    ID = foo
   604    num = 2
   605    type = aws_instance
   606  `
   607  
   608  const testTerraformApplyOutputStr = `
   609  aws_instance.bar:
   610    ID = foo
   611    foo = bar
   612    type = aws_instance
   613  aws_instance.foo:
   614    ID = foo
   615    num = 2
   616    type = aws_instance
   617  
   618  Outputs:
   619  
   620  foo_num = 2
   621  `
   622  
   623  const testTerraformApplyOutputAddStr = `
   624  aws_instance.test.0:
   625    ID = foo
   626    foo = foo0
   627    type = aws_instance
   628  aws_instance.test.1:
   629    ID = foo
   630    foo = foo1
   631    type = aws_instance
   632  
   633  Outputs:
   634  
   635  firstOutput = foo0
   636  secondOutput = foo1
   637  `
   638  
   639  const testTerraformApplyOutputListStr = `
   640  aws_instance.bar.0:
   641    ID = foo
   642    foo = bar
   643    type = aws_instance
   644  aws_instance.bar.1:
   645    ID = foo
   646    foo = bar
   647    type = aws_instance
   648  aws_instance.bar.2:
   649    ID = foo
   650    foo = bar
   651    type = aws_instance
   652  aws_instance.foo:
   653    ID = foo
   654    num = 2
   655    type = aws_instance
   656  
   657  Outputs:
   658  
   659  foo_num = [bar,bar,bar]
   660  `
   661  
   662  const testTerraformApplyOutputMultiStr = `
   663  aws_instance.bar.0:
   664    ID = foo
   665    foo = bar
   666    type = aws_instance
   667  aws_instance.bar.1:
   668    ID = foo
   669    foo = bar
   670    type = aws_instance
   671  aws_instance.bar.2:
   672    ID = foo
   673    foo = bar
   674    type = aws_instance
   675  aws_instance.foo:
   676    ID = foo
   677    num = 2
   678    type = aws_instance
   679  
   680  Outputs:
   681  
   682  foo_num = bar,bar,bar
   683  `
   684  
   685  const testTerraformApplyOutputMultiIndexStr = `
   686  aws_instance.bar.0:
   687    ID = foo
   688    foo = bar
   689    type = aws_instance
   690  aws_instance.bar.1:
   691    ID = foo
   692    foo = bar
   693    type = aws_instance
   694  aws_instance.bar.2:
   695    ID = foo
   696    foo = bar
   697    type = aws_instance
   698  aws_instance.foo:
   699    ID = foo
   700    num = 2
   701    type = aws_instance
   702  
   703  Outputs:
   704  
   705  foo_num = bar
   706  `
   707  
   708  const testTerraformApplyUnknownAttrStr = `
   709  aws_instance.foo:
   710    ID = foo
   711    num = 2
   712    type = aws_instance
   713  `
   714  
   715  const testTerraformApplyVarsStr = `
   716  aws_instance.bar:
   717    ID = foo
   718    bar = foo
   719    baz = override
   720    foo = us-west-2
   721    type = aws_instance
   722  aws_instance.foo:
   723    ID = foo
   724    bar = baz
   725    list = Hello,World
   726    map = Baz,Foo,Hello
   727    num = 2
   728    type = aws_instance
   729  `
   730  
   731  const testTerraformApplyVarsEnvStr = `
   732  aws_instance.bar:
   733    ID = foo
   734    bar = Hello,World
   735    baz = Baz,Foo,Hello
   736    foo = baz
   737    type = aws_instance
   738  `
   739  
   740  const testTerraformPlanStr = `
   741  DIFF:
   742  
   743  CREATE: aws_instance.bar
   744    foo:  "" => "2"
   745    type: "" => "aws_instance"
   746  CREATE: aws_instance.foo
   747    num:  "" => "2"
   748    type: "" => "aws_instance"
   749  
   750  STATE:
   751  
   752  <no state>
   753  `
   754  
   755  const testTerraformPlanComputedStr = `
   756  DIFF:
   757  
   758  CREATE: aws_instance.bar
   759    foo:  "" => "<computed>"
   760    type: "" => "aws_instance"
   761  CREATE: aws_instance.foo
   762    foo:  "" => "<computed>"
   763    num:  "" => "2"
   764    type: "" => "aws_instance"
   765  
   766  STATE:
   767  
   768  <no state>
   769  `
   770  
   771  const testTerraformPlanComputedIdStr = `
   772  DIFF:
   773  
   774  CREATE: aws_instance.bar
   775    foo:  "" => "<computed>"
   776    type: "" => "aws_instance"
   777  CREATE: aws_instance.foo
   778    foo:  "" => "<computed>"
   779    num:  "" => "2"
   780    type: "" => "aws_instance"
   781  
   782  STATE:
   783  
   784  <no state>
   785  `
   786  
   787  const testTerraformPlanComputedListStr = `
   788  DIFF:
   789  
   790  CREATE: aws_instance.bar
   791    foo:  "" => "<computed>"
   792    type: "" => "aws_instance"
   793  CREATE: aws_instance.foo
   794    list.#: "" => "<computed>"
   795    num:    "" => "2"
   796    type:   "" => "aws_instance"
   797  
   798  STATE:
   799  
   800  <no state>
   801  `
   802  
   803  const testTerraformPlanCountStr = `
   804  DIFF:
   805  
   806  CREATE: aws_instance.bar
   807    foo:  "" => "foo,foo,foo,foo,foo"
   808    type: "" => "aws_instance"
   809  CREATE: aws_instance.foo.0
   810    foo:  "" => "foo"
   811    type: "" => "aws_instance"
   812  CREATE: aws_instance.foo.1
   813    foo:  "" => "foo"
   814    type: "" => "aws_instance"
   815  CREATE: aws_instance.foo.2
   816    foo:  "" => "foo"
   817    type: "" => "aws_instance"
   818  CREATE: aws_instance.foo.3
   819    foo:  "" => "foo"
   820    type: "" => "aws_instance"
   821  CREATE: aws_instance.foo.4
   822    foo:  "" => "foo"
   823    type: "" => "aws_instance"
   824  
   825  STATE:
   826  
   827  <no state>
   828  `
   829  
   830  const testTerraformPlanCountIndexStr = `
   831  DIFF:
   832  
   833  CREATE: aws_instance.foo.0
   834    foo:  "" => "0"
   835    type: "" => "aws_instance"
   836  CREATE: aws_instance.foo.1
   837    foo:  "" => "1"
   838    type: "" => "aws_instance"
   839  
   840  STATE:
   841  
   842  <no state>
   843  `
   844  
   845  const testTerraformPlanCountIndexZeroStr = `
   846  DIFF:
   847  
   848  CREATE: aws_instance.foo
   849    foo:  "" => "0"
   850    type: "" => "aws_instance"
   851  
   852  STATE:
   853  
   854  <no state>
   855  `
   856  
   857  const testTerraformPlanCountOneIndexStr = `
   858  DIFF:
   859  
   860  CREATE: aws_instance.bar
   861    foo:  "" => "foo"
   862    type: "" => "aws_instance"
   863  CREATE: aws_instance.foo
   864    foo:  "" => "foo"
   865    type: "" => "aws_instance"
   866  
   867  STATE:
   868  
   869  <no state>
   870  `
   871  
   872  const testTerraformPlanCountZeroStr = `
   873  DIFF:
   874  
   875  CREATE: aws_instance.bar
   876    foo:  "" => ""
   877    type: "" => "aws_instance"
   878  
   879  STATE:
   880  
   881  <no state>
   882  `
   883  
   884  const testTerraformPlanCountVarStr = `
   885  DIFF:
   886  
   887  CREATE: aws_instance.bar
   888    foo:  "" => "foo,foo,foo"
   889    type: "" => "aws_instance"
   890  CREATE: aws_instance.foo.0
   891    foo:  "" => "foo"
   892    type: "" => "aws_instance"
   893  CREATE: aws_instance.foo.1
   894    foo:  "" => "foo"
   895    type: "" => "aws_instance"
   896  CREATE: aws_instance.foo.2
   897    foo:  "" => "foo"
   898    type: "" => "aws_instance"
   899  
   900  STATE:
   901  
   902  <no state>
   903  `
   904  
   905  const testTerraformPlanCountDecreaseStr = `
   906  DIFF:
   907  
   908  CREATE: aws_instance.bar
   909    foo:  "" => "bar"
   910    type: "" => "aws_instance"
   911  DESTROY: aws_instance.foo.1
   912  DESTROY: aws_instance.foo.2
   913  
   914  STATE:
   915  
   916  aws_instance.foo.0:
   917    ID = bar
   918    foo = foo
   919    type = aws_instance
   920  aws_instance.foo.1:
   921    ID = bar
   922  aws_instance.foo.2:
   923    ID = bar
   924  `
   925  
   926  const testTerraformPlanCountIncreaseStr = `
   927  DIFF:
   928  
   929  CREATE: aws_instance.bar
   930    foo:  "" => "bar"
   931    type: "" => "aws_instance"
   932  CREATE: aws_instance.foo.1
   933    foo:  "" => "foo"
   934    type: "" => "aws_instance"
   935  CREATE: aws_instance.foo.2
   936    foo:  "" => "foo"
   937    type: "" => "aws_instance"
   938  
   939  STATE:
   940  
   941  aws_instance.foo:
   942    ID = bar
   943    foo = foo
   944    type = aws_instance
   945  `
   946  
   947  const testTerraformPlanCountIncreaseFromOneStr = `
   948  DIFF:
   949  
   950  CREATE: aws_instance.bar
   951    foo:  "" => "bar"
   952    type: "" => "aws_instance"
   953  CREATE: aws_instance.foo.1
   954    foo:  "" => "foo"
   955    type: "" => "aws_instance"
   956  CREATE: aws_instance.foo.2
   957    foo:  "" => "foo"
   958    type: "" => "aws_instance"
   959  
   960  STATE:
   961  
   962  aws_instance.foo.0:
   963    ID = bar
   964    foo = foo
   965    type = aws_instance
   966  `
   967  
   968  const testTerraformPlanCountIncreaseFromOneCorruptedStr = `
   969  DIFF:
   970  
   971  CREATE: aws_instance.bar
   972    foo:  "" => "bar"
   973    type: "" => "aws_instance"
   974  DESTROY: aws_instance.foo
   975  CREATE: aws_instance.foo.1
   976    foo:  "" => "foo"
   977    type: "" => "aws_instance"
   978  CREATE: aws_instance.foo.2
   979    foo:  "" => "foo"
   980    type: "" => "aws_instance"
   981  
   982  STATE:
   983  
   984  aws_instance.foo:
   985    ID = bar
   986    foo = foo
   987    type = aws_instance
   988  aws_instance.foo.0:
   989    ID = bar
   990    foo = foo
   991    type = aws_instance
   992  `
   993  
   994  const testTerraformPlanDestroyStr = `
   995  DIFF:
   996  
   997  DESTROY: aws_instance.one
   998  DESTROY: aws_instance.two
   999  
  1000  STATE:
  1001  
  1002  aws_instance.one:
  1003    ID = bar
  1004  aws_instance.two:
  1005    ID = baz
  1006  `
  1007  
  1008  const testTerraformPlanDiffVarStr = `
  1009  DIFF:
  1010  
  1011  CREATE: aws_instance.bar
  1012    num:  "" => "3"
  1013    type: "" => "aws_instance"
  1014  UPDATE: aws_instance.foo
  1015    num: "2" => "3"
  1016  
  1017  STATE:
  1018  
  1019  aws_instance.foo:
  1020    ID = bar
  1021    num = 2
  1022  `
  1023  
  1024  const testTerraformPlanEmptyStr = `
  1025  DIFF:
  1026  
  1027  CREATE: aws_instance.bar
  1028  CREATE: aws_instance.foo
  1029  
  1030  STATE:
  1031  
  1032  <no state>
  1033  `
  1034  
  1035  const testTerraformPlanEscapedVarStr = `
  1036  DIFF:
  1037  
  1038  CREATE: aws_instance.foo
  1039    foo:  "" => "bar-${baz}"
  1040    type: "" => "aws_instance"
  1041  
  1042  STATE:
  1043  
  1044  <no state>
  1045  `
  1046  
  1047  const testTerraformPlanModulesStr = `
  1048  DIFF:
  1049  
  1050  CREATE: aws_instance.bar
  1051    foo:  "" => "2"
  1052    type: "" => "aws_instance"
  1053  CREATE: aws_instance.foo
  1054    num:  "" => "2"
  1055    type: "" => "aws_instance"
  1056  
  1057  module.child:
  1058    CREATE: aws_instance.foo
  1059      num:  "" => "2"
  1060      type: "" => "aws_instance"
  1061  
  1062  STATE:
  1063  
  1064  <no state>
  1065  `
  1066  
  1067  const testTerraformPlanModuleCycleStr = `
  1068  DIFF:
  1069  
  1070  CREATE: aws_instance.b
  1071  CREATE: aws_instance.c
  1072    some_input: "" => "<computed>"
  1073    type:       "" => "aws_instance"
  1074  
  1075  STATE:
  1076  
  1077  <no state>
  1078  `
  1079  
  1080  const testTerraformPlanModuleDestroyStr = `
  1081  DIFF:
  1082  
  1083  DESTROY: aws_instance.foo
  1084  
  1085  module.child:
  1086    DESTROY MODULE
  1087    DESTROY: aws_instance.foo
  1088  
  1089  STATE:
  1090  
  1091  aws_instance.foo:
  1092    ID = bar
  1093  
  1094  module.child:
  1095    aws_instance.foo:
  1096      ID = bar
  1097  `
  1098  
  1099  const testTerraformPlanModuleDestroyCycleStr = `
  1100  DIFF:
  1101  
  1102  module.a_module:
  1103    DESTROY MODULE
  1104    DESTROY: aws_instance.a
  1105  module.b_module:
  1106    DESTROY MODULE
  1107    DESTROY: aws_instance.b
  1108  
  1109  STATE:
  1110  
  1111  module.a_module:
  1112    aws_instance.a:
  1113      ID = a
  1114  module.b_module:
  1115    aws_instance.b:
  1116      ID = b
  1117  `
  1118  
  1119  const testTerraformPlanModuleDestroyMultivarStr = `
  1120  DIFF:
  1121  
  1122  module.child:
  1123    DESTROY MODULE
  1124    DESTROY: aws_instance.foo.0
  1125    DESTROY: aws_instance.foo.1
  1126  
  1127  STATE:
  1128  
  1129  <no state>
  1130  module.child:
  1131    aws_instance.foo.0:
  1132      ID = bar0
  1133    aws_instance.foo.1:
  1134      ID = bar1
  1135  `
  1136  
  1137  const testTerraformPlanModuleInputStr = `
  1138  DIFF:
  1139  
  1140  CREATE: aws_instance.bar
  1141    foo:  "" => "2"
  1142    type: "" => "aws_instance"
  1143  
  1144  module.child:
  1145    CREATE: aws_instance.foo
  1146      foo:  "" => "42"
  1147      type: "" => "aws_instance"
  1148  
  1149  STATE:
  1150  
  1151  <no state>
  1152  `
  1153  
  1154  const testTerraformPlanModuleInputComputedStr = `
  1155  DIFF:
  1156  
  1157  CREATE: aws_instance.bar
  1158    foo:  "" => "<computed>"
  1159    type: "" => "aws_instance"
  1160  
  1161  module.child:
  1162    CREATE: aws_instance.foo
  1163      foo:  "" => "<computed>"
  1164      type: "" => "aws_instance"
  1165  
  1166  STATE:
  1167  
  1168  <no state>
  1169  `
  1170  
  1171  const testTerraformPlanModuleInputVarStr = `
  1172  DIFF:
  1173  
  1174  CREATE: aws_instance.bar
  1175    foo:  "" => "2"
  1176    type: "" => "aws_instance"
  1177  
  1178  module.child:
  1179    CREATE: aws_instance.foo
  1180      foo:  "" => "52"
  1181      type: "" => "aws_instance"
  1182  
  1183  STATE:
  1184  
  1185  <no state>
  1186  `
  1187  
  1188  const testTerraformPlanModuleMultiVarStr = `
  1189  DIFF:
  1190  
  1191  CREATE: aws_instance.parent.0
  1192  CREATE: aws_instance.parent.1
  1193  
  1194  module.child:
  1195    CREATE: aws_instance.bar.0
  1196      baz:  "" => "baz"
  1197      type: "" => "aws_instance"
  1198    CREATE: aws_instance.bar.1
  1199      baz:  "" => "baz"
  1200      type: "" => "aws_instance"
  1201    CREATE: aws_instance.foo
  1202      foo:  "" => "baz,baz"
  1203      type: "" => "aws_instance"
  1204  
  1205  STATE:
  1206  
  1207  <no state>
  1208  `
  1209  
  1210  const testTerraformPlanModuleOrphansStr = `
  1211  DIFF:
  1212  
  1213  CREATE: aws_instance.foo
  1214    num:  "" => "2"
  1215    type: "" => "aws_instance"
  1216  
  1217  module.child:
  1218    DESTROY: aws_instance.foo
  1219  
  1220  STATE:
  1221  
  1222  module.child:
  1223    aws_instance.foo:
  1224      ID = baz
  1225  `
  1226  
  1227  const testTerraformPlanModuleVarStr = `
  1228  DIFF:
  1229  
  1230  CREATE: aws_instance.bar
  1231    foo:  "" => "2"
  1232    type: "" => "aws_instance"
  1233  
  1234  module.child:
  1235    CREATE: aws_instance.foo
  1236      num:  "" => "2"
  1237      type: "" => "aws_instance"
  1238  
  1239  STATE:
  1240  
  1241  <no state>
  1242  `
  1243  
  1244  const testTerraformPlanModuleVarComputedStr = `
  1245  DIFF:
  1246  
  1247  CREATE: aws_instance.bar
  1248    foo:  "" => "<computed>"
  1249    type: "" => "aws_instance"
  1250  
  1251  module.child:
  1252    CREATE: aws_instance.foo
  1253      foo:  "" => "<computed>"
  1254      type: "" => "aws_instance"
  1255  
  1256  STATE:
  1257  
  1258  <no state>
  1259  `
  1260  
  1261  const testTerraformPlanModuleVarIntStr = `
  1262  DIFF:
  1263  
  1264  module.child:
  1265    CREATE: aws_instance.foo
  1266      num:  "" => "2"
  1267      type: "" => "aws_instance"
  1268  
  1269  STATE:
  1270  
  1271  <no state>
  1272  `
  1273  
  1274  const testTerraformPlanOrphanStr = `
  1275  DIFF:
  1276  
  1277  DESTROY: aws_instance.baz
  1278  CREATE: aws_instance.foo
  1279    num:  "" => "2"
  1280    type: "" => "aws_instance"
  1281  
  1282  STATE:
  1283  
  1284  aws_instance.baz:
  1285    ID = bar
  1286  `
  1287  
  1288  const testTerraformPlanStateStr = `
  1289  DIFF:
  1290  
  1291  CREATE: aws_instance.bar
  1292    foo:  "" => "2"
  1293    type: "" => "aws_instance"
  1294  UPDATE: aws_instance.foo
  1295    num:  "" => "2"
  1296    type: "" => "aws_instance"
  1297  
  1298  STATE:
  1299  
  1300  aws_instance.foo:
  1301    ID = bar
  1302  `
  1303  
  1304  const testTerraformPlanTaintStr = `
  1305  DIFF:
  1306  
  1307  DESTROY/CREATE: aws_instance.bar
  1308    foo:  "" => "2"
  1309    type: "" => "aws_instance"
  1310  
  1311  STATE:
  1312  
  1313  aws_instance.bar: (tainted)
  1314    ID = baz
  1315  aws_instance.foo:
  1316    ID = bar
  1317    num = 2
  1318  `
  1319  
  1320  const testTerraformPlanMultipleTaintStr = `
  1321  DIFF:
  1322  
  1323  DESTROY/CREATE: aws_instance.bar
  1324    foo:  "" => "2"
  1325    type: "" => "aws_instance"
  1326  
  1327  STATE:
  1328  
  1329  aws_instance.bar: (2 tainted)
  1330    ID = <not created>
  1331    Tainted ID 1 = baz
  1332    Tainted ID 2 = zip
  1333  aws_instance.foo:
  1334    ID = bar
  1335    num = 2
  1336  `
  1337  
  1338  const testTerraformPlanVarMultiCountOneStr = `
  1339  DIFF:
  1340  
  1341  CREATE: aws_instance.bar
  1342    foo:  "" => "2"
  1343    type: "" => "aws_instance"
  1344  CREATE: aws_instance.foo
  1345    num:  "" => "2"
  1346    type: "" => "aws_instance"
  1347  
  1348  STATE:
  1349  
  1350  <no state>
  1351  `
  1352  
  1353  const testTerraformPlanPathVarStr = `
  1354  DIFF:
  1355  
  1356  CREATE: aws_instance.foo
  1357    cwd:    "" => "%s/barpath"
  1358    module: "" => "%s/foopath"
  1359    root:   "" => "%s/barpath"
  1360    type:   "" => "aws_instance"
  1361  
  1362  STATE:
  1363  
  1364  <no state>
  1365  `
  1366  
  1367  const testTerraformPlanIgnoreChangesStr = `
  1368  DIFF:
  1369  
  1370  UPDATE: aws_instance.foo
  1371    type: "" => "aws_instance"
  1372  
  1373  STATE:
  1374  
  1375  aws_instance.foo:
  1376    ID = bar
  1377    ami = ami-abcd1234
  1378  `
  1379  
  1380  const testTerraformPlanComputedValueInMap = `
  1381  DIFF:
  1382  
  1383  CREATE: aws_computed_source.intermediates
  1384    computed_read_only: "" => "<computed>"
  1385  
  1386  module.test_mod:
  1387    CREATE: aws_instance.inner2
  1388      looked_up: "" => "<computed>"
  1389      type:      "" => "aws_instance"
  1390  
  1391  STATE:
  1392  
  1393  <no state>
  1394  `
  1395  
  1396  const testTerraformPlanModuleVariableFromSplat = `
  1397  DIFF:
  1398  
  1399  module.mod1:
  1400    CREATE: aws_instance.test.0
  1401      thing: "" => "doesnt"
  1402      type:  "" => "aws_instance"
  1403    CREATE: aws_instance.test.1
  1404      thing: "" => "doesnt"
  1405      type:  "" => "aws_instance"
  1406  module.mod2:
  1407    CREATE: aws_instance.test.0
  1408      thing: "" => "doesnt"
  1409      type:  "" => "aws_instance"
  1410    CREATE: aws_instance.test.1
  1411      thing: "" => "doesnt"
  1412      type:  "" => "aws_instance"
  1413  
  1414  STATE:
  1415  
  1416  <no state>`
  1417  
  1418  const testTerraformInputHCL = `
  1419  hcl_instance.hcltest:
  1420    ID = foo
  1421    bar.w = z
  1422    bar.x = y
  1423    foo.# = 2
  1424    foo.0 = a
  1425    foo.1 = b
  1426    type = hcl_instance
  1427  `