opentofu/terraform/terraform_test.go

1819 lines
31 KiB
Go
Raw Normal View History

package terraform
import (
"flag"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"sync"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
"github.com/hashicorp/terraform/addrs"
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configload"
"github.com/hashicorp/terraform/helper/experiment"
"github.com/hashicorp/terraform/helper/logging"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/provisioners"
"github.com/hashicorp/terraform/states"
)
// This is the directory where our test fixtures are.
const fixtureDir = "./test-fixtures"
func TestMain(m *testing.M) {
// We want to shadow on tests just to make sure the shadow graph works
// in case we need it and to find any race issues.
experiment.SetEnabled(experiment.X_shadow, true)
experiment.Flag(flag.CommandLine)
flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
// Make sure shadow operations fail our real tests
contextFailOnShadowError = true
2016-10-01 23:30:09 -05:00
// Always DeepCopy the Diff on every Plan during a test
contextTestDeepCopyOnPlan = true
// We have fmt.Stringer implementations on lots of objects that hide
// details that we very often want to see in tests, so we just disable
// spew's use of String methods globally on the assumption that spew
// usage implies an intent to see the raw values and ignore any
// abstractions.
spew.Config.DisableMethods = true
os.Exit(m.Run())
}
func tempDir(t *testing.T) string {
t.Helper()
dir, err := ioutil.TempDir("", "tf")
if err != nil {
t.Fatalf("err: %s", err)
}
if err := os.RemoveAll(dir); err != nil {
t.Fatalf("err: %s", err)
}
return dir
}
// tempEnv lets you temporarily set an environment variable. It returns
2016-08-17 13:28:58 -05:00
// a function to defer to reset the old value.
// the old value that should be set via a defer.
2016-08-17 13:28:58 -05:00
func tempEnv(t *testing.T, k string, v string) func() {
t.Helper()
old, oldOk := os.LookupEnv(k)
os.Setenv(k, v)
return func() {
if !oldOk {
os.Unsetenv(k)
} else {
os.Setenv(k, old)
}
}
}
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
func testModule(t *testing.T, name string) *configs.Config {
t.Helper()
c, _ := testModuleWithSnapshot(t, name)
return c
}
func testModuleWithSnapshot(t *testing.T, name string) (*configs.Config, *configload.Snapshot) {
t.Helper()
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
dir := filepath.Join(fixtureDir, name)
2014-06-05 04:32:10 -05:00
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
// FIXME: We're not dealing with the cleanup function here because
// this testModule function is used all over and so we don't want to
// change its interface at this late stage.
loader, _ := configload.NewLoaderForTests(t)
2014-06-05 04:32:10 -05:00
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
// Test modules usually do not refer to remote sources, and for local
// sources only this ultimately just records all of the module paths
// in a JSON file so that we can load them below.
diags := loader.InstallModules(dir, true, configload.InstallHooksImpl{})
if diags.HasErrors() {
t.Fatal(diags.Error())
}
config, snap, diags := loader.LoadConfigWithSnapshot(dir)
terraform: ugly huge change to weave in new HCL2-oriented types Due to how deeply the configuration types go into Terraform Core, there isn't a great way to switch out to HCL2 gradually. As a consequence, this huge commit gets us from the old state to a _compilable_ new state, but does not yet attempt to fix any tests and has a number of known missing parts and bugs. We will continue to iterate on this in forthcoming commits, heading back towards passing tests and making Terraform fully-functional again. The three main goals here are: - Use the configuration models from the "configs" package instead of the older models in the "config" package, which is now deprecated and preserved only to help us write our migration tool. - Do expression inspection and evaluation using the functionality of the new "lang" package, instead of the Interpolator type and related functionality in the main "terraform" package. - Represent addresses of various objects using types in the addrs package, rather than hand-constructed strings. This is not critical to support the above, but was a big help during the implementation of these other points since it made it much more explicit what kind of address is expected in each context. Since our new packages are built to accommodate some future planned features that are not yet implemented (e.g. the "for_each" argument on resources, "count"/"for_each" on modules), and since there's still a fair amount of functionality still using old-style APIs, there is a moderate amount of shimming here to connect new assumptions with old, hopefully in a way that makes it easier to find and eliminate these shims later. I apologize in advance to the person who inevitably just found this huge commit while spelunking through the commit history.
2018-04-30 12:33:53 -05:00
if diags.HasErrors() {
t.Fatal(diags.Error())
}
return config, snap
}
// testModuleInline takes a map of path -> config strings and yields a config
// structure with those files loaded from disk
func testModuleInline(t *testing.T, sources map[string]string) *configs.Config {
t.Helper()
cfgPath, err := ioutil.TempDir("", "tf-test")
if err != nil {
t.Errorf("Error creating temporary directory for config: %s", err)
}
defer os.RemoveAll(cfgPath)
for path, configStr := range sources {
dir := filepath.Dir(path)
if dir != "." {
err := os.MkdirAll(filepath.Join(cfgPath, dir), os.FileMode(0777))
if err != nil {
t.Fatalf("Error creating subdir: %s", err)
}
}
// Write the configuration
cfgF, err := os.Create(filepath.Join(cfgPath, path))
if err != nil {
t.Fatalf("Error creating temporary file for config: %s", err)
}
_, err = io.Copy(cfgF, strings.NewReader(configStr))
cfgF.Close()
if err != nil {
t.Fatalf("Error creating temporary file for config: %s", err)
}
}
loader, cleanup := configload.NewLoaderForTests(t)
defer cleanup()
// Test modules usually do not refer to remote sources, and for local
// sources only this ultimately just records all of the module paths
// in a JSON file so that we can load them below.
diags := loader.InstallModules(cfgPath, true, configload.InstallHooksImpl{})
if diags.HasErrors() {
t.Fatal(diags.Error())
}
config, diags := loader.LoadConfig(cfgPath)
if diags.HasErrors() {
t.Fatal(diags.Error())
}
return config
}
func testProviderFuncFixed(rp providers.Interface) providers.Factory {
return func() (providers.Interface, error) {
return rp, nil
}
}
func testProvisionerFuncFixed(rp provisioners.Interface) ProvisionerFactory {
return func() (provisioners.Interface, error) {
return rp, nil
}
}
func mustResourceInstanceAddr(s string) addrs.AbsResourceInstance {
addr, diags := addrs.ParseAbsResourceInstanceStr(s)
if diags.HasErrors() {
panic(diags.Err())
}
return addr
}
func instanceObjectIdForTests(obj *states.ResourceInstanceObject) string {
v := obj.Value
if v.IsNull() || !v.IsKnown() {
return ""
}
idVal := v.GetAttr("id")
if idVal.IsNull() || !idVal.IsKnown() {
return ""
}
idVal, err := convert.Convert(idVal, cty.String)
if err != nil {
return "<invalid>" // placeholder value
}
return idVal.AsString()
}
// HookRecordApplyOrder is a test hook that records the order of applies
// by recording the PreApply event.
type HookRecordApplyOrder struct {
NilHook
Active bool
IDs []string
States []cty.Value
Diffs []*plans.Change
l sync.Mutex
}
func (h *HookRecordApplyOrder) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) {
if plannedNewState.RawEquals(priorState) {
return HookActionContinue, nil
}
if h.Active {
h.l.Lock()
defer h.l.Unlock()
h.IDs = append(h.IDs, addr.String())
h.Diffs = append(h.Diffs, &plans.Change{
Action: action,
Before: priorState,
After: plannedNewState,
})
h.States = append(h.States, priorState)
}
return HookActionContinue, nil
}
// Below are all the constant strings that are the expected output for
// various tests.
2014-09-29 11:13:15 -05:00
const testTerraformInputProviderStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
2014-09-29 11:13:15 -05:00
bar = override
foo = us-east-1
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
2014-09-29 11:13:15 -05:00
bar = baz
num = 2
type = aws_instance
`
const testTerraformInputProviderOnlyStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
foo = us-west-2
type = aws_instance
`
const testTerraformInputVarOnlyStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
foo = us-east-1
type = aws_instance
`
const testTerraformInputVarOnlyUnsetStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
bar = baz
foo = foovalue
type = aws_instance
`
const testTerraformInputVarsStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
bar = override
foo = us-east-1
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
bar = baz
num = 2
type = aws_instance
`
2014-06-18 18:38:08 -05:00
const testTerraformApplyStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
2014-06-18 18:38:08 -05:00
foo = bar
2014-07-01 12:28:42 -05:00
type = aws_instance
2014-06-18 18:38:08 -05:00
aws_instance.foo:
ID = foo
provider = provider.aws
2014-06-18 18:38:08 -05:00
num = 2
2014-07-01 12:28:42 -05:00
type = aws_instance
2014-06-18 18:38:08 -05:00
`
const testTerraformApplyDataBasicStr = `
data.null_data_source.testing:
ID = yo
provider = provider.null
`
const testTerraformApplyRefCountStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = 3
type = aws_instance
Dependencies:
aws_instance.foo
aws_instance.foo.0:
ID = foo
provider = provider.aws
aws_instance.foo.1:
ID = foo
provider = provider.aws
aws_instance.foo.2:
ID = foo
provider = provider.aws
`
const testTerraformApplyProviderAliasStr = `
aws_instance.bar:
ID = foo
provider = provider.aws.bar
foo = bar
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
`
const testTerraformApplyProviderAliasConfigStr = `
another_instance.bar:
ID = foo
provider = provider.another.two
another_instance.foo:
ID = foo
provider = provider.another
`
const testTerraformApplyEmptyModuleStr = `
<no state>
Outputs:
end = XXXX
module.child:
<no state>
Outputs:
aws_access_key = YYYYY
aws_route53_zone_id = XXXX
aws_secret_key = ZZZZ
`
const testTerraformApplyDependsCreateBeforeStr = `
aws_instance.lb:
ID = baz
provider = provider.aws
instance = foo
type = aws_instance
Dependencies:
aws_instance.web
aws_instance.web:
ID = foo
provider = provider.aws
require_new = ami-new
type = aws_instance
`
const testTerraformApplyCreateBeforeStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
require_new = xyz
type = aws_instance
`
const testTerraformApplyCreateBeforeUpdateStr = `
aws_instance.bar:
ID = bar
provider = provider.aws
foo = baz
type = aws_instance
`
2014-07-02 18:16:38 -05:00
const testTerraformApplyCancelStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
2018-05-25 11:13:22 -05:00
value = 2
2014-07-02 18:16:38 -05:00
`
2014-06-23 14:19:41 -05:00
const testTerraformApplyComputeStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
2018-05-30 12:03:05 -05:00
foo = computed_value
2014-07-01 12:28:42 -05:00
type = aws_instance
Dependencies:
aws_instance.foo
2014-06-23 14:19:41 -05:00
aws_instance.foo:
ID = foo
provider = provider.aws
2018-05-30 12:03:05 -05:00
compute = value
2014-07-01 12:28:42 -05:00
num = 2
type = aws_instance
2018-05-30 12:03:05 -05:00
value = computed_value
2014-06-23 14:19:41 -05:00
`
const testTerraformApplyCountDecStr = `
aws_instance.foo.0:
ID = bar
foo = foo
type = aws_instance
aws_instance.foo.1:
ID = bar
foo = foo
type = aws_instance
`
const testTerraformApplyCountDecToOneStr = `
2015-02-12 22:06:42 -06:00
aws_instance.foo:
ID = bar
foo = foo
type = aws_instance
`
const testTerraformApplyCountDecToOneCorruptedStr = `
aws_instance.foo:
ID = bar
foo = foo
type = aws_instance
`
const testTerraformApplyCountDecToOneCorruptedPlanStr = `
DIFF:
DESTROY: aws_instance.foo.0
STATE:
aws_instance.foo:
ID = bar
foo = foo
type = aws_instance
aws_instance.foo.0:
ID = baz
type = aws_instance
`
const testTerraformApplyCountTaintedStr = `
<no state>
`
const testTerraformApplyCountVariableStr = `
aws_instance.foo.0:
ID = foo
provider = provider.aws
foo = foo
type = aws_instance
aws_instance.foo.1:
ID = foo
provider = provider.aws
foo = foo
type = aws_instance
`
const testTerraformApplyCountVariableRefStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = 2
type = aws_instance
Dependencies:
aws_instance.foo
aws_instance.foo.0:
ID = foo
provider = provider.aws
aws_instance.foo.1:
ID = foo
provider = provider.aws
`
2014-07-08 18:12:14 -05:00
const testTerraformApplyMinimalStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
2014-07-08 18:12:14 -05:00
aws_instance.foo:
ID = foo
provider = provider.aws
2014-07-08 18:12:14 -05:00
`
2014-09-23 19:13:50 -05:00
const testTerraformApplyModuleStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
2014-09-23 19:13:50 -05:00
foo = bar
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
2014-09-23 19:13:50 -05:00
num = 2
type = aws_instance
module.child:
aws_instance.baz:
ID = foo
provider = provider.aws
2014-09-23 19:13:50 -05:00
foo = bar
type = aws_instance
`
const testTerraformApplyModuleBoolStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = true
type = aws_instance
Dependencies:
module.child
module.child:
<no state>
Outputs:
leader = true
`
const testTerraformApplyModuleDestroyOrderStr = `
<no state>
module.child:
<no state>
`
const testTerraformApplyMultiProviderStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
do_instance.foo:
ID = foo
provider = provider.do
num = 2
type = do_instance
`
const testTerraformApplyModuleOnlyProviderStr = `
<no state>
module.child:
aws_instance.foo:
ID = foo
provider = provider.aws
test_instance.foo:
ID = foo
provider = provider.test
`
const testTerraformApplyModuleProviderAliasStr = `
<no state>
module.child:
aws_instance.foo:
ID = foo
provider = module.child.provider.aws.eu
`
const testTerraformApplyModuleVarRefExistingStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
foo = bar
module.child:
aws_instance.foo:
ID = foo
provider = provider.aws
type = aws_instance
value = bar
`
const testTerraformApplyOutputOrphanStr = `
<no state>
Outputs:
foo = bar
`
const testTerraformApplyOutputOrphanModuleStr = `
module.child:
<no state>
Outputs:
foo = bar
`
2014-07-09 12:36:49 -05:00
const testTerraformApplyProvisionerStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
2014-09-17 19:42:43 -05:00
Dependencies:
aws_instance.foo
aws_instance.foo:
ID = foo
provider = provider.aws
compute = value
num = 2
type = aws_instance
value = computed_value
`
const testTerraformApplyProvisionerModuleStr = `
<no state>
module.child:
aws_instance.bar:
ID = foo
provider = provider.aws
`
const testTerraformApplyProvisionerFailStr = `
2016-04-21 14:59:10 -05:00
aws_instance.bar: (tainted)
ID = foo
provider = provider.aws
2014-07-09 12:36:49 -05:00
aws_instance.foo:
ID = foo
provider = provider.aws
2014-07-09 12:36:49 -05:00
num = 2
type = aws_instance
`
const testTerraformApplyProvisionerFailCreateStr = `
2016-04-21 14:59:10 -05:00
aws_instance.bar: (tainted)
ID = foo
provider = provider.aws
`
const testTerraformApplyProvisionerFailCreateNoIdStr = `
<no state>
`
const testTerraformApplyProvisionerFailCreateBeforeDestroyStr = `
aws_instance.bar: (tainted) (1 deposed)
ID = foo
provider = provider.aws
require_new = xyz
type = aws_instance
Deposed ID 1 = bar
`
const testTerraformApplyProvisionerResourceRefStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
`
2015-02-23 16:56:02 -06:00
const testTerraformApplyProvisionerSelfRefStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
2015-02-23 16:56:02 -06:00
foo = bar
type = aws_instance
`
2015-02-23 17:02:26 -06:00
const testTerraformApplyProvisionerMultiSelfRefStr = `
aws_instance.foo.0:
ID = foo
provider = provider.aws
2015-02-23 17:02:26 -06:00
foo = number 0
type = aws_instance
aws_instance.foo.1:
ID = foo
provider = provider.aws
2015-02-23 17:02:26 -06:00
foo = number 1
type = aws_instance
aws_instance.foo.2:
ID = foo
provider = provider.aws
2015-02-23 17:02:26 -06:00
foo = number 2
type = aws_instance
`
const testTerraformApplyProvisionerMultiSelfRefSingleStr = `
aws_instance.foo.0:
ID = foo
provider = provider.aws
foo = number 0
type = aws_instance
aws_instance.foo.1:
ID = foo
provider = provider.aws
foo = number 1
type = aws_instance
Dependencies:
aws_instance.foo.0
aws_instance.foo.2:
ID = foo
provider = provider.aws
foo = number 2
type = aws_instance
Dependencies:
aws_instance.foo.0
`
const testTerraformApplyProvisionerDiffStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
`
const testTerraformApplyDestroyStr = `
<no state>
`
const testTerraformApplyErrorStr = `
aws_instance.bar:
ID = bar
provider = provider.aws
2014-09-17 19:45:38 -05:00
Dependencies:
aws_instance.foo
aws_instance.foo:
ID = foo
provider = provider.aws
value = 2
`
const testTerraformApplyErrorCreateBeforeDestroyStr = `
aws_instance.bar:
ID = bar
provider = provider.aws
require_new = abc
`
const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = `
aws_instance.bar: (1 deposed)
ID = foo
provider = provider.aws
Deposed ID 1 = bar
`
const testTerraformApplyErrorPartialStr = `
aws_instance.bar:
ID = bar
provider = provider.aws
2014-09-17 19:45:38 -05:00
Dependencies:
aws_instance.foo
aws_instance.foo:
ID = foo
provider = provider.aws
value = 2
`
const testTerraformApplyResourceDependsOnModuleStr = `
aws_instance.a:
ID = foo
provider = provider.aws
Dependencies:
module.child
module.child:
aws_instance.child:
ID = foo
provider = provider.aws
`
const testTerraformApplyResourceDependsOnModuleDeepStr = `
aws_instance.a:
ID = foo
provider = provider.aws
Dependencies:
module.child
module.child.grandchild:
aws_instance.c:
ID = foo
provider = provider.aws
`
const testTerraformApplyResourceDependsOnModuleInModuleStr = `
<no state>
module.child:
aws_instance.b:
ID = foo
provider = provider.aws
Dependencies:
module.grandchild
module.child.grandchild:
aws_instance.c:
ID = foo
provider = provider.aws
`
const testTerraformApplyTaintStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
`
const testTerraformApplyTaintDepStr = `
aws_instance.bar:
ID = bar
provider = provider.aws
foo = foo
num = 2
type = aws_instance
Dependencies:
aws_instance.foo
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
`
const testTerraformApplyTaintDepRequireNewStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = foo
require_new = yes
type = aws_instance
Dependencies:
aws_instance.foo
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
`
const testTerraformApplyOutputStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
Outputs:
foo_num = 2
`
const testTerraformApplyOutputAddStr = `
aws_instance.test.0:
ID = foo
provider = provider.aws
foo = foo0
type = aws_instance
aws_instance.test.1:
ID = foo
provider = provider.aws
foo = foo1
type = aws_instance
Outputs:
firstOutput = foo0
secondOutput = foo1
`
const testTerraformApplyOutputListStr = `
aws_instance.bar.0:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.bar.1:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.bar.2:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
Outputs:
foo_num = [bar,bar,bar]
`
const testTerraformApplyOutputMultiStr = `
aws_instance.bar.0:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.bar.1:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.bar.2:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
Outputs:
foo_num = bar,bar,bar
`
const testTerraformApplyOutputMultiIndexStr = `
aws_instance.bar.0:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.bar.1:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.bar.2:
ID = foo
provider = provider.aws
foo = bar
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
Outputs:
foo_num = bar
`
const testTerraformApplyUnknownAttrStr = `
aws_instance.foo:
ID = foo
provider = provider.aws
num = 2
type = aws_instance
`
const testTerraformApplyVarsStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
bar = override
2014-07-22 10:18:53 -05:00
baz = override
foo = us-east-1
2014-07-01 12:28:42 -05:00
type = aws_instance
aws_instance.foo:
ID = foo
provider = provider.aws
bar = baz
list.# = 2
list.0 = Hello
list.1 = World
map.Baz = Foo
map.Foo = Bar
map.Hello = World
num = 2
2014-07-01 12:28:42 -05:00
type = aws_instance
`
const testTerraformApplyVarsEnvStr = `
aws_instance.bar:
ID = foo
provider = provider.aws
list.# = 2
list.0 = Hello
list.1 = World
map.Baz = Foo
map.Foo = Bar
map.Hello = World
string = baz
type = aws_instance
`
const testTerraformPlanStr = `
2014-06-25 20:22:42 -05:00
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
2014-06-18 11:30:59 -05:00
foo: "" => "2"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo
2014-06-18 11:30:59 -05:00
num: "" => "2"
type: "" => "aws_instance"
2014-06-25 20:22:42 -05:00
STATE:
<no state>
`
const testTerraformPlanComputedStr = `
2014-06-25 20:22:42 -05:00
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
2014-06-18 11:30:59 -05:00
foo: "" => "<computed>"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo
compute: "" => "foo"
compute_value: "" => "<computed>"
foo: "" => "<computed>"
num: "" => "2"
type: "" => "aws_instance"
2014-07-07 16:57:41 -05:00
STATE:
<no state>
`
const testTerraformPlanComputedIdStr = `
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
2014-07-07 16:57:41 -05:00
foo: "" => "<computed>"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo
2014-07-07 16:57:41 -05:00
foo: "" => "<computed>"
2014-06-18 11:30:59 -05:00
num: "" => "2"
type: "" => "aws_instance"
2014-06-25 20:22:42 -05:00
STATE:
<no state>
`
2014-08-30 19:25:34 -05:00
const testTerraformPlanComputedListStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "<computed>"
list: "" => "<computed>"
2014-08-30 19:25:34 -05:00
type: "" => "aws_instance"
CREATE: aws_instance.foo
compute: "" => "list.#"
list: "" => "<computed>"
list.#: "" => "<computed>"
num: "" => "2"
type: "" => "aws_instance"
2014-08-30 19:25:34 -05:00
STATE:
<no state>
`
const testTerraformPlanComputedMultiIndexStr = `
DIFF:
CREATE: aws_instance.bar.0
foo: "" => "<computed>"
type: "" => "aws_instance"
CREATE: aws_instance.foo.0
compute: "" => "ip.#"
compute_value: "" => "<computed>"
ip.#: "" => "<computed>"
type: "" => "aws_instance"
CREATE: aws_instance.foo.1
compute: "" => "ip.#"
compute_value: "" => "<computed>"
ip.#: "" => "<computed>"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanCountStr = `
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
foo: "" => "foo,foo,foo,foo,foo"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.0
foo: "" => "foo"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.1
foo: "" => "foo"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.2
foo: "" => "foo"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.3
foo: "" => "foo"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.4
foo: "" => "foo"
type: "" => "aws_instance"
STATE:
<no state>
`
2014-10-03 00:02:59 -05:00
const testTerraformPlanCountIndexStr = `
DIFF:
CREATE: aws_instance.foo.0
foo: "" => "0"
type: "" => "aws_instance"
CREATE: aws_instance.foo.1
foo: "" => "1"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanCountIndexZeroStr = `
DIFF:
CREATE: aws_instance.foo
foo: "" => "0"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanCountOneIndexStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "foo"
type: "" => "aws_instance"
CREATE: aws_instance.foo.0
foo: "" => "foo"
type: "" => "aws_instance"
STATE:
<no state>
`
2014-10-02 19:18:40 -05:00
const testTerraformPlanCountZeroStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => ""
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanCountVarStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "foo,foo,foo"
type: "" => "aws_instance"
CREATE: aws_instance.foo.0
foo: "" => "foo"
type: "" => "aws_instance"
CREATE: aws_instance.foo.1
foo: "" => "foo"
type: "" => "aws_instance"
CREATE: aws_instance.foo.2
foo: "" => "foo"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanCountDecreaseStr = `
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
foo: "" => "bar"
type: "" => "aws_instance"
DESTROY: aws_instance.foo.1
DESTROY: aws_instance.foo.2
STATE:
aws_instance.foo.0:
ID = bar
foo = foo
type = aws_instance
aws_instance.foo.1:
ID = bar
aws_instance.foo.2:
ID = bar
`
const testTerraformPlanCountIncreaseStr = `
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
foo: "" => "bar"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.1
foo: "" => "foo"
type: "" => "aws_instance"
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo.2
foo: "" => "foo"
type: "" => "aws_instance"
STATE:
aws_instance.foo:
ID = bar
foo = foo
type = aws_instance
`
const testTerraformPlanCountIncreaseFromOneStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "bar"
type: "" => "aws_instance"
CREATE: aws_instance.foo.1
foo: "" => "foo"
type: "" => "aws_instance"
CREATE: aws_instance.foo.2
foo: "" => "foo"
type: "" => "aws_instance"
STATE:
aws_instance.foo.0:
ID = bar
foo = foo
type = aws_instance
`
const testTerraformPlanCountIncreaseFromOneCorruptedStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "bar"
type: "" => "aws_instance"
DESTROY: aws_instance.foo
CREATE: aws_instance.foo.1
foo: "" => "foo"
type: "" => "aws_instance"
CREATE: aws_instance.foo.2
foo: "" => "foo"
type: "" => "aws_instance"
STATE:
aws_instance.foo:
ID = bar
foo = foo
type = aws_instance
aws_instance.foo.0:
ID = bar
foo = foo
type = aws_instance
`
const testTerraformPlanDestroyStr = `
DIFF:
DESTROY: aws_instance.one
DESTROY: aws_instance.two
STATE:
aws_instance.one:
ID = bar
aws_instance.two:
ID = baz
`
const testTerraformPlanDiffVarStr = `
DIFF:
CREATE: aws_instance.bar
num: "" => "3"
type: "" => "aws_instance"
UPDATE: aws_instance.foo
num: "2" => "3"
STATE:
aws_instance.foo:
ID = bar
num = 2
`
2014-07-08 18:58:31 -05:00
const testTerraformPlanEmptyStr = `
DIFF:
CREATE: aws_instance.bar
CREATE: aws_instance.foo
STATE:
<no state>
`
2016-01-19 14:37:55 -06:00
const testTerraformPlanEscapedVarStr = `
DIFF:
CREATE: aws_instance.foo
foo: "" => "bar-${baz}"
type: "" => "aws_instance"
STATE:
<no state>
`
2014-09-23 16:15:40 -05:00
const testTerraformPlanModulesStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
CREATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
module.child:
CREATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleCycleStr = `
DIFF:
CREATE: aws_instance.b
CREATE: aws_instance.c
some_input: "" => "<computed>"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleDestroyStr = `
DIFF:
DESTROY: aws_instance.foo
module.child:
DESTROY: aws_instance.foo
STATE:
aws_instance.foo:
ID = bar
module.child:
aws_instance.foo:
ID = bar
`
const testTerraformPlanModuleDestroyCycleStr = `
DIFF:
module.a_module:
DESTROY: aws_instance.a
module.b_module:
DESTROY: aws_instance.b
STATE:
module.a_module:
aws_instance.a:
ID = a
module.b_module:
aws_instance.b:
ID = b
`
const testTerraformPlanModuleDestroyMultivarStr = `
DIFF:
module.child:
DESTROY: aws_instance.foo.0
DESTROY: aws_instance.foo.1
STATE:
<no state>
module.child:
aws_instance.foo.0:
ID = bar0
aws_instance.foo.1:
ID = bar1
`
2014-09-23 18:44:21 -05:00
const testTerraformPlanModuleInputStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
module.child:
CREATE: aws_instance.foo
foo: "" => "42"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleInputComputedStr = `
DIFF:
CREATE: aws_instance.bar
compute: "" => "foo"
compute_value: "" => "<computed>"
foo: "" => "<computed>"
type: "" => "aws_instance"
module.child:
CREATE: aws_instance.foo
foo: "" => "<computed>"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleInputVarStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
module.child:
CREATE: aws_instance.foo
foo: "" => "52"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleMultiVarStr = `
DIFF:
CREATE: aws_instance.parent.0
CREATE: aws_instance.parent.1
module.child:
CREATE: aws_instance.bar.0
baz: "" => "baz"
type: "" => "aws_instance"
CREATE: aws_instance.bar.1
baz: "" => "baz"
type: "" => "aws_instance"
CREATE: aws_instance.foo
foo: "" => "baz,baz"
type: "" => "aws_instance"
STATE:
<no state>
`
2014-09-23 16:57:17 -05:00
const testTerraformPlanModuleOrphansStr = `
DIFF:
CREATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
module.child:
DESTROY: aws_instance.foo
STATE:
module.child:
aws_instance.foo:
ID = baz
`
const testTerraformPlanModuleProviderVarStr = `
DIFF:
module.child:
CREATE: aws_instance.test
type: "" => "aws_instance"
value: "" => "hello"
STATE:
<no state>
`
const testTerraformPlanModuleVarStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
module.child:
CREATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleVarComputedStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "<computed>"
type: "" => "aws_instance"
module.child:
CREATE: aws_instance.foo
compute: "" => "foo"
compute_value: "" => "<computed>"
foo: "" => "<computed>"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleVarIntStr = `
DIFF:
module.child:
CREATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
STATE:
<no state>
`
2014-06-25 23:58:33 -05:00
const testTerraformPlanOrphanStr = `
DIFF:
DESTROY: aws_instance.baz
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.foo
2014-06-25 23:58:33 -05:00
num: "" => "2"
type: "" => "aws_instance"
STATE:
aws_instance.baz:
ID = bar
`
2014-06-25 20:22:42 -05:00
const testTerraformPlanStateStr = `
DIFF:
2014-07-08 18:58:31 -05:00
CREATE: aws_instance.bar
2014-06-25 20:22:42 -05:00
foo: "" => "2"
type: "" => "aws_instance"
UPDATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
2014-06-25 20:22:42 -05:00
STATE:
aws_instance.foo:
ID = bar
`
const testTerraformPlanTaintStr = `
DIFF:
2014-09-17 20:03:19 -05:00
DESTROY/CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
STATE:
2016-04-21 14:59:10 -05:00
aws_instance.bar: (tainted)
ID = baz
2014-09-19 17:04:21 -05:00
aws_instance.foo:
ID = bar
num = 2
`
const testTerraformPlanTaintIgnoreChangesStr = `
DIFF:
DESTROY/CREATE: aws_instance.foo
type: "" => "aws_instance"
2017-03-20 16:27:30 -05:00
vars: "foo" => "foo"
STATE:
aws_instance.foo: (tainted)
ID = foo
type = aws_instance
vars = foo
`
2014-09-19 17:04:21 -05:00
const testTerraformPlanMultipleTaintStr = `
DIFF:
DESTROY/CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
STATE:
aws_instance.bar: (2 tainted)
ID = <not created>
Tainted ID 1 = baz
Tainted ID 2 = zip
aws_instance.foo:
ID = bar
num = 2
`
const testTerraformPlanVarMultiCountOneStr = `
DIFF:
CREATE: aws_instance.bar
foo: "" => "2"
type: "" => "aws_instance"
CREATE: aws_instance.foo
num: "" => "2"
type: "" => "aws_instance"
STATE:
<no state>
`
2014-10-07 22:09:30 -05:00
const testTerraformPlanPathVarStr = `
DIFF:
CREATE: aws_instance.foo
cwd: "" => "%s/barpath"
module: "" => "%s/foopath"
root: "" => "%s/barpath"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanIgnoreChangesStr = `
DIFF:
UPDATE: aws_instance.foo
type: "" => "aws_instance"
STATE:
aws_instance.foo:
ID = bar
ami = ami-abcd1234
`
const testTFPlanDiffIgnoreChangesWithFlatmaps = `
UPDATE: aws_instance.foo
lst.#: "1" => "2"
lst.0: "j" => "j"
lst.1: "" => "k"
set.#: "1" => "1"
set.0.a: "1" => "1"
set.0.b: "" => "2"
type: "" => "aws_instance"
`
const testTerraformPlanIgnoreChangesWildcardStr = `
DIFF:
STATE:
aws_instance.foo:
ID = bar
ami = ami-abcd1234
instance_type = t2.micro
`
const testTerraformPlanComputedValueInMap = `
DIFF:
CREATE: aws_computed_source.intermediates
computed_read_only: "" => "<computed>"
module.test_mod:
CREATE: aws_instance.inner2
looked_up: "" => "<computed>"
type: "" => "aws_instance"
STATE:
<no state>
`
const testTerraformPlanModuleVariableFromSplat = `
DIFF:
module.mod1:
CREATE: aws_instance.test.0
thing: "" => "doesnt"
type: "" => "aws_instance"
CREATE: aws_instance.test.1
thing: "" => "doesnt"
type: "" => "aws_instance"
module.mod2:
CREATE: aws_instance.test.0
thing: "" => "doesnt"
type: "" => "aws_instance"
CREATE: aws_instance.test.1
thing: "" => "doesnt"
type: "" => "aws_instance"
STATE:
<no state>`
const testTerraformInputHCL = `
hcl_instance.hcltest:
ID = foo
provider = provider.hcl
bar.w = z
bar.x = y
foo.# = 2
foo.0 = a
foo.1 = b
type = hcl_instance
`
const testTerraformRefreshDataRefDataStr = `
data.null_data_source.bar:
ID = foo
provider = provider.null
bar = yes
Dependencies:
data.null_data_source.foo
data.null_data_source.foo:
ID = foo
provider = provider.null
foo = yes
`