2015-02-04 17:44:23 -06:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
"bufio"
|
|
|
|
"bytes"
|
2015-02-04 19:02:18 -06:00
|
|
|
"fmt"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
"io/ioutil"
|
2019-02-11 19:05:24 -06:00
|
|
|
"log"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"sort"
|
2018-09-13 19:10:07 -05:00
|
|
|
"strconv"
|
2015-02-04 19:02:18 -06:00
|
|
|
"strings"
|
2015-02-04 17:44:23 -06:00
|
|
|
"testing"
|
2015-08-10 15:03:02 -05:00
|
|
|
"time"
|
2016-08-09 15:14:40 -05:00
|
|
|
|
2019-08-07 16:50:59 -05:00
|
|
|
"github.com/davecgh/go-spew/spew"
|
2018-09-06 18:36:35 -05:00
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
"github.com/hashicorp/go-version"
|
|
|
|
"github.com/hashicorp/terraform/configs"
|
|
|
|
"github.com/hashicorp/terraform/configs/configload"
|
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
2019-08-06 18:58:58 -05:00
|
|
|
"github.com/hashicorp/terraform/configs/hcl2shim"
|
2016-08-09 15:14:40 -05:00
|
|
|
"github.com/hashicorp/terraform/flatmap"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
"github.com/hashicorp/terraform/plans"
|
|
|
|
"github.com/hashicorp/terraform/plans/planfile"
|
2018-08-17 14:32:35 -05:00
|
|
|
"github.com/hashicorp/terraform/providers"
|
|
|
|
"github.com/hashicorp/terraform/provisioners"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
"github.com/hashicorp/terraform/states"
|
|
|
|
"github.com/hashicorp/terraform/states/statefile"
|
2018-09-10 15:37:35 -05:00
|
|
|
"github.com/hashicorp/terraform/tfdiags"
|
2017-10-19 20:48:08 -05:00
|
|
|
tfversion "github.com/hashicorp/terraform/version"
|
2019-08-07 16:50:59 -05:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
2015-02-04 17:44:23 -06:00
|
|
|
)
|
|
|
|
|
2018-09-06 18:36:35 -05:00
|
|
|
var (
|
|
|
|
equateEmpty = cmpopts.EquateEmpty()
|
|
|
|
typeComparer = cmp.Comparer(cty.Type.Equals)
|
|
|
|
valueComparer = cmp.Comparer(cty.Value.RawEquals)
|
2018-09-14 17:40:09 -05:00
|
|
|
valueTrans = cmp.Transformer("hcl2shim", hcl2shim.ConfigValueFromHCL2)
|
2018-09-06 18:36:35 -05:00
|
|
|
)
|
|
|
|
|
2016-11-12 18:50:26 -06:00
|
|
|
func TestNewContextRequiredVersion(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
Name string
|
|
|
|
Module string
|
|
|
|
Version string
|
|
|
|
Value string
|
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"no requirement",
|
|
|
|
"",
|
|
|
|
"0.1.0",
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
"doesn't match",
|
|
|
|
"",
|
|
|
|
"0.1.0",
|
|
|
|
"> 0.6.0",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
"matches",
|
|
|
|
"",
|
|
|
|
"0.7.0",
|
|
|
|
"> 0.6.0",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
"module matches",
|
|
|
|
"context-required-version-module",
|
|
|
|
"0.5.0",
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
"module doesn't match",
|
|
|
|
"context-required-version-module",
|
|
|
|
"0.4.0",
|
|
|
|
"",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range cases {
|
|
|
|
t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
|
|
|
|
// Reset the version for the tests
|
2017-10-19 20:48:08 -05:00
|
|
|
old := tfversion.SemVer
|
|
|
|
tfversion.SemVer = version.Must(version.NewVersion(tc.Version))
|
|
|
|
defer func() { tfversion.SemVer = old }()
|
2016-11-12 18:50:26 -06:00
|
|
|
|
|
|
|
name := "context-required-version"
|
|
|
|
if tc.Module != "" {
|
|
|
|
name = tc.Module
|
|
|
|
}
|
|
|
|
mod := testModule(t, name)
|
|
|
|
if tc.Value != "" {
|
2018-05-04 21:24:06 -05:00
|
|
|
constraint, err := version.NewConstraint(tc.Value)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("can't parse %q as version constraint", tc.Value)
|
|
|
|
}
|
|
|
|
mod.Module.CoreVersionConstraints = append(mod.Module.CoreVersionConstraints, configs.VersionConstraint{
|
|
|
|
Required: constraint,
|
|
|
|
})
|
2016-11-12 18:50:26 -06:00
|
|
|
}
|
2018-05-04 21:24:06 -05:00
|
|
|
_, diags := NewContext(&ContextOpts{
|
|
|
|
Config: mod,
|
2016-11-12 18:50:26 -06:00
|
|
|
})
|
2018-05-04 21:24:06 -05:00
|
|
|
if diags.HasErrors() != tc.Err {
|
|
|
|
t.Fatalf("err: %s", diags.Err())
|
2016-11-12 18:50:26 -06:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:15:36 -06:00
|
|
|
func testContext2(t *testing.T, opts *ContextOpts) *Context {
|
2017-11-07 12:09:36 -06:00
|
|
|
t.Helper()
|
2016-10-21 16:25:05 -05:00
|
|
|
|
2018-05-17 19:52:01 -05:00
|
|
|
ctx, diags := NewContext(opts)
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("failed to create test context\n\n%s\n", diags.Err())
|
2016-03-11 13:07:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return ctx
|
2015-02-04 17:44:23 -06:00
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
|
2016-10-23 20:53:00 -05:00
|
|
|
func testDataApplyFn(
|
|
|
|
info *InstanceInfo,
|
|
|
|
d *InstanceDiff) (*InstanceState, error) {
|
|
|
|
return testApplyFn(info, new(InstanceState), d)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testDataDiffFn(
|
|
|
|
info *InstanceInfo,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
return testDiffFn(info, new(InstanceState), c)
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
func testApplyFn(
|
|
|
|
info *InstanceInfo,
|
|
|
|
s *InstanceState,
|
|
|
|
d *InstanceDiff) (*InstanceState, error) {
|
|
|
|
if d.Destroy {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-05-30 10:25:28 -05:00
|
|
|
// find the OLD id, which is probably in the ID field for now, but eventually
|
|
|
|
// ID should only be in one place.
|
|
|
|
id := s.ID
|
|
|
|
if id == "" {
|
|
|
|
id = s.Attributes["id"]
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
if idAttr, ok := d.Attributes["id"]; ok && !idAttr.NewComputed {
|
|
|
|
id = idAttr.New
|
|
|
|
}
|
|
|
|
|
2019-07-17 21:41:24 -05:00
|
|
|
if id == "" || id == hcl2shim.UnknownVariableValue {
|
2018-05-30 10:25:28 -05:00
|
|
|
id = "foo"
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
result := &InstanceState{
|
2015-02-26 11:50:18 -06:00
|
|
|
ID: id,
|
|
|
|
Attributes: make(map[string]string),
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy all the prior attributes
|
|
|
|
for k, v := range s.Attributes {
|
|
|
|
result.Attributes[k] = v
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if d != nil {
|
|
|
|
result = result.MergeDiff(d)
|
|
|
|
}
|
2018-09-18 20:15:47 -05:00
|
|
|
|
|
|
|
// The id attribute always matches ID for the sake of this mock
|
|
|
|
// implementation, since it's following the pre-0.12 assumptions where
|
|
|
|
// these two were treated as synonyms.
|
|
|
|
result.Attributes["id"] = result.ID
|
2015-02-13 20:09:45 -06:00
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func testDiffFn(
|
|
|
|
info *InstanceInfo,
|
|
|
|
s *InstanceState,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
2016-04-21 14:59:10 -05:00
|
|
|
diff := new(InstanceDiff)
|
2015-02-13 20:09:45 -06:00
|
|
|
diff.Attributes = make(map[string]*ResourceAttrDiff)
|
|
|
|
|
2019-02-11 19:05:24 -06:00
|
|
|
defer func() {
|
|
|
|
log.Printf("[TRACE] testDiffFn: generated diff is:\n%s", spew.Sdump(diff))
|
|
|
|
}()
|
|
|
|
|
2016-04-21 14:59:10 -05:00
|
|
|
if s != nil {
|
|
|
|
diff.DestroyTainted = s.Tainted
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
for k, v := range c.Raw {
|
2016-02-24 09:55:55 -06:00
|
|
|
// Ignore __-prefixed keys since they're used for magic
|
|
|
|
if k[0] == '_' && k[1] == '_' {
|
2019-02-11 19:05:24 -06:00
|
|
|
// ...though we do still need to include them in the diff, to
|
|
|
|
// simulate normal provider behaviors.
|
|
|
|
old := s.Attributes[k]
|
|
|
|
var new string
|
|
|
|
switch tv := v.(type) {
|
|
|
|
case string:
|
|
|
|
new = tv
|
|
|
|
default:
|
|
|
|
new = fmt.Sprintf("%#v", v)
|
|
|
|
}
|
2019-08-07 16:50:59 -05:00
|
|
|
if new == hcl2shim.UnknownVariableValue {
|
2019-02-11 19:05:24 -06:00
|
|
|
diff.Attributes[k] = &ResourceAttrDiff{
|
|
|
|
Old: old,
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
diff.Attributes[k] = &ResourceAttrDiff{
|
|
|
|
Old: old,
|
|
|
|
New: new,
|
|
|
|
}
|
|
|
|
}
|
2016-02-24 09:55:55 -06:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
if k == "nil" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// This key is used for other purposes
|
|
|
|
if k == "compute_value" {
|
2019-02-11 19:05:24 -06:00
|
|
|
if old, ok := s.Attributes["compute_value"]; !ok || old != v.(string) {
|
|
|
|
diff.Attributes["compute_value"] = &ResourceAttrDiff{
|
|
|
|
Old: old,
|
|
|
|
New: v.(string),
|
|
|
|
}
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if k == "compute" {
|
2019-02-11 19:05:24 -06:00
|
|
|
// The "compute" value itself must be included in the diff if it
|
|
|
|
// has changed since prior.
|
|
|
|
if old, ok := s.Attributes["compute"]; !ok || old != v.(string) {
|
|
|
|
diff.Attributes["compute"] = &ResourceAttrDiff{
|
|
|
|
Old: old,
|
|
|
|
New: v.(string),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-07 16:50:59 -05:00
|
|
|
if v == hcl2shim.UnknownVariableValue || v == "unknown" {
|
2018-05-22 18:02:22 -05:00
|
|
|
// compute wasn't set in the config, so don't use these
|
|
|
|
// computed values from the schema.
|
|
|
|
delete(c.Raw, k)
|
|
|
|
delete(c.Raw, "compute_value")
|
|
|
|
|
|
|
|
// we need to remove this from the list of ComputedKeys too,
|
|
|
|
// since it would get re-added to the diff further down
|
|
|
|
newComputed := make([]string, 0, len(c.ComputedKeys))
|
|
|
|
for _, ck := range c.ComputedKeys {
|
|
|
|
if ck == "compute" || ck == "compute_value" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
newComputed = append(newComputed, ck)
|
|
|
|
}
|
|
|
|
c.ComputedKeys = newComputed
|
|
|
|
|
2018-05-24 15:11:03 -05:00
|
|
|
if v == "unknown" {
|
|
|
|
diff.Attributes["unknown"] = &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
c.ComputedKeys = append(c.ComputedKeys, "unknown")
|
|
|
|
}
|
|
|
|
|
2018-05-22 18:02:22 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
attrDiff := &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
if cv, ok := c.Config["compute_value"]; ok {
|
|
|
|
if cv.(string) == "1" {
|
|
|
|
attrDiff.NewComputed = false
|
|
|
|
attrDiff.New = fmt.Sprintf("computed_%s", v.(string))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
diff.Attributes[v.(string)] = attrDiff
|
2018-09-14 17:40:09 -05:00
|
|
|
continue
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// If this key is not computed, then look it up in the
|
|
|
|
// cleaned config.
|
|
|
|
found := false
|
|
|
|
for _, ck := range c.ComputedKeys {
|
|
|
|
if ck == k {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
v = c.Config[k]
|
|
|
|
}
|
|
|
|
|
2016-08-10 10:37:55 -05:00
|
|
|
for k, attrDiff := range testFlatAttrDiffs(k, v) {
|
2018-05-21 18:14:40 -05:00
|
|
|
// we need to ignore 'id' for now, since it's always inferred to be
|
|
|
|
// computed.
|
|
|
|
if k == "id" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2016-08-10 10:37:55 -05:00
|
|
|
if k == "require_new" {
|
|
|
|
attrDiff.RequiresNew = true
|
2016-08-09 15:14:40 -05:00
|
|
|
}
|
2016-08-10 10:37:55 -05:00
|
|
|
if _, ok := c.Raw["__"+k+"_requires_new"]; ok {
|
|
|
|
attrDiff.RequiresNew = true
|
|
|
|
}
|
2017-03-20 16:17:14 -05:00
|
|
|
|
|
|
|
if attr, ok := s.Attributes[k]; ok {
|
|
|
|
attrDiff.Old = attr
|
|
|
|
}
|
|
|
|
|
2016-08-10 10:37:55 -05:00
|
|
|
diff.Attributes[k] = attrDiff
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, k := range c.ComputedKeys {
|
2018-05-21 18:14:40 -05:00
|
|
|
if k == "id" {
|
|
|
|
continue
|
|
|
|
}
|
2018-09-18 15:53:25 -05:00
|
|
|
old := ""
|
|
|
|
if s != nil {
|
|
|
|
old = s.Attributes[k]
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
diff.Attributes[k] = &ResourceAttrDiff{
|
2018-09-18 15:53:25 -05:00
|
|
|
Old: old,
|
2015-02-13 20:09:45 -06:00
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-21 14:59:10 -05:00
|
|
|
// If we recreate this resource because it's tainted, we keep all attrs
|
|
|
|
if !diff.RequiresNew() {
|
|
|
|
for k, v := range diff.Attributes {
|
|
|
|
if v.NewComputed {
|
|
|
|
continue
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
|
2016-04-21 14:59:10 -05:00
|
|
|
old, ok := s.Attributes[k]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if old == v.New {
|
|
|
|
delete(diff.Attributes, k)
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !diff.Empty() {
|
|
|
|
diff.Attributes["type"] = &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: info.Type,
|
|
|
|
}
|
2018-09-17 19:17:42 -05:00
|
|
|
if s != nil && s.Attributes != nil {
|
|
|
|
diff.Attributes["type"].Old = s.Attributes["type"]
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
|
2016-04-21 14:59:10 -05:00
|
|
|
return diff, nil
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
|
2016-08-09 15:14:40 -05:00
|
|
|
// generate ResourceAttrDiffs for nested data structures in tests
|
|
|
|
func testFlatAttrDiffs(k string, i interface{}) map[string]*ResourceAttrDiff {
|
|
|
|
diffs := make(map[string]*ResourceAttrDiff)
|
2016-08-10 10:37:55 -05:00
|
|
|
// check for strings and empty containers first
|
|
|
|
switch t := i.(type) {
|
|
|
|
case string:
|
|
|
|
diffs[k] = &ResourceAttrDiff{New: t}
|
|
|
|
return diffs
|
|
|
|
case map[string]interface{}:
|
|
|
|
if len(t) == 0 {
|
|
|
|
diffs[k] = &ResourceAttrDiff{New: ""}
|
|
|
|
return diffs
|
|
|
|
}
|
|
|
|
case []interface{}:
|
|
|
|
if len(t) == 0 {
|
|
|
|
diffs[k] = &ResourceAttrDiff{New: ""}
|
|
|
|
return diffs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flat := flatmap.Flatten(map[string]interface{}{k: i})
|
2016-08-09 15:14:40 -05:00
|
|
|
|
|
|
|
for k, v := range flat {
|
|
|
|
attrDiff := &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: v,
|
|
|
|
}
|
|
|
|
diffs[k] = attrDiff
|
|
|
|
}
|
|
|
|
|
2018-09-13 19:10:07 -05:00
|
|
|
// The legacy flatmap-based diff producing done by helper/schema would
|
|
|
|
// additionally insert a k+".%" key here recording the length of the map,
|
|
|
|
// which is for some reason not also done by flatmap.Flatten. To make our
|
|
|
|
// mock shims helper/schema-compatible, we'll just fake that up here.
|
|
|
|
switch t := i.(type) {
|
|
|
|
case map[string]interface{}:
|
|
|
|
attrDiff := &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: strconv.Itoa(len(t)),
|
|
|
|
}
|
|
|
|
diffs[k+".%"] = attrDiff
|
|
|
|
}
|
|
|
|
|
2016-08-09 15:14:40 -05:00
|
|
|
return diffs
|
|
|
|
}
|
|
|
|
|
2018-08-17 14:32:35 -05:00
|
|
|
func testProvider(prefix string) *MockProvider {
|
|
|
|
p := new(MockProvider)
|
|
|
|
p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
|
|
|
|
return providers.ReadResourceResponse{NewState: req.PriorState}
|
2015-02-13 20:09:45 -06:00
|
|
|
}
|
|
|
|
|
2018-05-17 19:52:01 -05:00
|
|
|
p.GetSchemaReturn = testProviderSchema(prefix)
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2018-08-17 14:32:35 -05:00
|
|
|
func testProvisioner() *MockProvisioner {
|
|
|
|
p := new(MockProvisioner)
|
|
|
|
p.GetSchemaResponse = provisioners.GetSchemaResponse{
|
|
|
|
Provisioner: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"command": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"order": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"when": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-05-23 12:39:36 -05:00
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
}
|
2015-02-13 20:09:45 -06:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
func checkStateString(t *testing.T, state *states.State, expected string) {
|
2017-11-07 12:49:10 -06:00
|
|
|
t.Helper()
|
2015-03-04 12:15:53 -06:00
|
|
|
actual := strings.TrimSpace(state.String())
|
|
|
|
expected = strings.TrimSpace(expected)
|
|
|
|
|
|
|
|
if actual != expected {
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
t.Fatalf("incorrect state\ngot:\n%s\n\nwant:\n%s", actual, expected)
|
2015-03-04 12:15:53 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-30 15:17:28 -05:00
|
|
|
func resourceState(resourceType, resourceID string) *ResourceState {
|
2018-05-17 19:52:01 -05:00
|
|
|
providerResource := strings.Split(resourceType, "_")
|
2015-03-30 15:17:28 -05:00
|
|
|
return &ResourceState{
|
|
|
|
Type: resourceType,
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: resourceID,
|
2018-01-29 17:00:18 -06:00
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": resourceID,
|
|
|
|
},
|
2015-03-30 15:17:28 -05:00
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
Provider: "provider." + providerResource[0],
|
2015-03-30 15:17:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-10 15:03:02 -05:00
|
|
|
// Test helper that gives a function 3 seconds to finish, assumes deadlock and
|
|
|
|
// fails test if it does not.
|
|
|
|
func testCheckDeadlock(t *testing.T, f func()) {
|
2017-11-07 12:49:10 -06:00
|
|
|
t.Helper()
|
2015-08-10 15:03:02 -05:00
|
|
|
timeout := make(chan bool, 1)
|
|
|
|
done := make(chan bool, 1)
|
|
|
|
go func() {
|
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
timeout <- true
|
|
|
|
}()
|
|
|
|
go func(f func(), done chan bool) {
|
|
|
|
defer func() { done <- true }()
|
|
|
|
f()
|
|
|
|
}(f, done)
|
|
|
|
select {
|
|
|
|
case <-timeout:
|
|
|
|
t.Fatalf("timed out! probably deadlock")
|
|
|
|
case <-done:
|
|
|
|
// ok
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-17 19:52:01 -05:00
|
|
|
func testProviderSchema(name string) *ProviderSchema {
|
|
|
|
return &ProviderSchema{
|
|
|
|
Provider: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"region": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"foo": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-05-23 12:39:36 -05:00
|
|
|
"value": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"root": {
|
|
|
|
Type: cty.Number,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
name + "_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"ami": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"dep": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"num": {
|
|
|
|
Type: cty.Number,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"require_new": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"var": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"foo": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
2019-02-11 19:05:24 -06:00
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
"bar": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"compute": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
2018-09-14 17:40:09 -05:00
|
|
|
Computed: false,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
"compute_value": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"value": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
2019-02-11 19:05:24 -06:00
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
"output": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"write": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"instance": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"vpc_id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-09-07 19:25:58 -05:00
|
|
|
"type": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
2018-09-12 14:00:50 -05:00
|
|
|
|
|
|
|
// Generated by testDiffFn if compute = "unknown" is set in the test config
|
|
|
|
"unknown": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_eip": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"instance": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_resource": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"value": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"random": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_ami_list": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
2019-02-11 19:05:24 -06:00
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
"ids": {
|
|
|
|
Type: cty.List(cty.String),
|
|
|
|
Optional: true,
|
2019-02-11 19:05:24 -06:00
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_remote_state": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"foo": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"output": {
|
2018-05-23 12:39:36 -05:00
|
|
|
Type: cty.Map(cty.String),
|
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_file": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"template": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-06-01 13:06:25 -05:00
|
|
|
"rendered": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
2018-05-22 18:02:22 -05:00
|
|
|
"__template_requires_new": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
DataSources: map[string]*configschema.Block{
|
|
|
|
name + "_data_source": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
2020-05-08 17:46:32 -05:00
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
"foo": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
2020-05-08 17:46:32 -05:00
|
|
|
Computed: true,
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_remote_state": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"foo": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-05-23 12:39:36 -05:00
|
|
|
"output": {
|
|
|
|
Type: cty.Map(cty.String),
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
name + "_file": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"template": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
},
|
2018-06-01 13:06:25 -05:00
|
|
|
"rendered": {
|
|
|
|
Type: cty.String,
|
|
|
|
Computed: true,
|
|
|
|
},
|
2018-05-17 19:52:01 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
// contextForPlanViaFile is a helper that creates a temporary plan file, then
|
|
|
|
// reads it back in again and produces a ContextOpts object containing the
|
|
|
|
// planned changes, prior state and config from the plan file.
|
|
|
|
//
|
|
|
|
// This is intended for testing the separated plan/apply workflow in a more
|
|
|
|
// convenient way than spelling out all of these steps every time. Normally
|
|
|
|
// only the command and backend packages need to deal with such things, but
|
|
|
|
// our context tests try to exercise lots of stuff at once and so having them
|
|
|
|
// round-trip things through on-disk files is often an important part of
|
|
|
|
// fully representing an old bug in a regression test.
|
|
|
|
func contextOptsForPlanViaFile(configSnap *configload.Snapshot, state *states.State, plan *plans.Plan) (*ContextOpts, error) {
|
|
|
|
dir, err := ioutil.TempDir("", "terraform-contextForPlanViaFile")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
// We'll just create a dummy statefile.File here because we're not going
|
|
|
|
// to run through any of the codepaths that care about Lineage/Serial/etc
|
|
|
|
// here anyway.
|
|
|
|
stateFile := &statefile.File{
|
|
|
|
State: state,
|
|
|
|
}
|
|
|
|
|
2018-09-26 11:51:40 -05:00
|
|
|
// To make life a little easier for test authors, we'll populate a simple
|
|
|
|
// backend configuration if they didn't set one, since the backend is
|
|
|
|
// usually dealt with in a calling package and so tests in this package
|
|
|
|
// don't really care about it.
|
|
|
|
if plan.Backend.Config == nil {
|
|
|
|
cfg, err := plans.NewDynamicValue(cty.EmptyObjectVal, cty.EmptyObject)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("NewDynamicValue failed: %s", err)) // shouldn't happen because we control the inputs
|
|
|
|
}
|
|
|
|
plan.Backend.Type = "local"
|
|
|
|
plan.Backend.Config = cfg
|
|
|
|
plan.Backend.Workspace = "default"
|
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
filename := filepath.Join(dir, "tfplan")
|
|
|
|
err = planfile.Create(filename, configSnap, stateFile, plan)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
pr, err := planfile.Open(filename)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
config, diags := pr.ReadConfig()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
return nil, diags.Err()
|
|
|
|
}
|
|
|
|
|
|
|
|
stateFile, err = pr.ReadStateFile()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
plan, err = pr.ReadPlan()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
vars := make(InputValues)
|
|
|
|
for name, vv := range plan.VariableValues {
|
|
|
|
val, err := vv.Decode(cty.DynamicPseudoType)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("can't decode value for variable %q: %s", name, err)
|
|
|
|
}
|
|
|
|
vars[name] = &InputValue{
|
|
|
|
Value: val,
|
|
|
|
SourceType: ValueFromPlan,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &ContextOpts{
|
|
|
|
Config: config,
|
|
|
|
State: stateFile.State,
|
|
|
|
Changes: plan.Changes,
|
|
|
|
Variables: vars,
|
|
|
|
Targets: plan.TargetAddrs,
|
|
|
|
ProviderSHA256s: plan.ProviderSHA256s,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// legacyPlanComparisonString produces a string representation of the changes
|
|
|
|
// from a plan and a given state togther, as was formerly produced by the
|
|
|
|
// String method of terraform.Plan.
|
|
|
|
//
|
|
|
|
// This is here only for compatibility with existing tests that predate our
|
|
|
|
// new plan and state types, and should not be used in new tests. Instead, use
|
|
|
|
// a library like "cmp" to do a deep equality check and diff on the two
|
|
|
|
// data structures.
|
|
|
|
func legacyPlanComparisonString(state *states.State, changes *plans.Changes) string {
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"DIFF:\n\n%s\n\nSTATE:\n\n%s",
|
|
|
|
legacyDiffComparisonString(changes),
|
|
|
|
state.String(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// legacyDiffComparisonString produces a string representation of the changes
|
|
|
|
// from a planned changes object, as was formerly produced by the String method
|
|
|
|
// of terraform.Diff.
|
|
|
|
//
|
|
|
|
// This is here only for compatibility with existing tests that predate our
|
|
|
|
// new plan types, and should not be used in new tests. Instead, use a library
|
|
|
|
// like "cmp" to do a deep equality check and diff on the two data structures.
|
|
|
|
func legacyDiffComparisonString(changes *plans.Changes) string {
|
|
|
|
// The old string representation of a plan was grouped by module, but
|
|
|
|
// our new plan structure is not grouped in that way and so we'll need
|
|
|
|
// to preprocess it in order to produce that grouping.
|
|
|
|
type ResourceChanges struct {
|
|
|
|
Current *plans.ResourceInstanceChangeSrc
|
|
|
|
Deposed map[states.DeposedKey]*plans.ResourceInstanceChangeSrc
|
|
|
|
}
|
|
|
|
byModule := map[string]map[string]*ResourceChanges{}
|
|
|
|
resourceKeys := map[string][]string{}
|
|
|
|
var moduleKeys []string
|
|
|
|
for _, rc := range changes.Resources {
|
2018-09-18 17:37:04 -05:00
|
|
|
if rc.Action == plans.NoOp {
|
|
|
|
// We won't mention no-op changes here at all, since the old plan
|
|
|
|
// model we are emulating here didn't have such a concept.
|
|
|
|
continue
|
|
|
|
}
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
moduleKey := rc.Addr.Module.String()
|
|
|
|
if _, exists := byModule[moduleKey]; !exists {
|
|
|
|
moduleKeys = append(moduleKeys, moduleKey)
|
|
|
|
byModule[moduleKey] = make(map[string]*ResourceChanges)
|
|
|
|
}
|
|
|
|
resourceKey := rc.Addr.Resource.String()
|
|
|
|
if _, exists := byModule[moduleKey][resourceKey]; !exists {
|
|
|
|
resourceKeys[moduleKey] = append(resourceKeys[moduleKey], resourceKey)
|
|
|
|
byModule[moduleKey][resourceKey] = &ResourceChanges{
|
|
|
|
Deposed: make(map[states.DeposedKey]*plans.ResourceInstanceChangeSrc),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if rc.DeposedKey == states.NotDeposed {
|
|
|
|
byModule[moduleKey][resourceKey].Current = rc
|
|
|
|
} else {
|
|
|
|
byModule[moduleKey][resourceKey].Deposed[rc.DeposedKey] = rc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(moduleKeys)
|
|
|
|
for _, ks := range resourceKeys {
|
|
|
|
sort.Strings(ks)
|
|
|
|
}
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
|
|
|
for _, moduleKey := range moduleKeys {
|
|
|
|
rcs := byModule[moduleKey]
|
|
|
|
var mBuf bytes.Buffer
|
|
|
|
|
|
|
|
for _, resourceKey := range resourceKeys[moduleKey] {
|
|
|
|
rc := rcs[resourceKey]
|
|
|
|
|
|
|
|
crud := "UPDATE"
|
|
|
|
if rc.Current != nil {
|
|
|
|
switch rc.Current.Action {
|
2018-09-21 19:08:52 -05:00
|
|
|
case plans.DeleteThenCreate:
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
crud = "DESTROY/CREATE"
|
2018-09-21 19:08:52 -05:00
|
|
|
case plans.CreateThenDelete:
|
|
|
|
crud = "CREATE/DESTROY"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
case plans.Delete:
|
|
|
|
crud = "DESTROY"
|
|
|
|
case plans.Create:
|
|
|
|
crud = "CREATE"
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We must be working on a deposed object then, in which
|
|
|
|
// case destroying is the only possible action.
|
|
|
|
crud = "DESTROY"
|
|
|
|
}
|
|
|
|
|
|
|
|
extra := ""
|
|
|
|
if rc.Current == nil && len(rc.Deposed) > 0 {
|
|
|
|
extra = " (deposed only)"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(
|
|
|
|
&mBuf, "%s: %s%s\n",
|
|
|
|
crud, resourceKey, extra,
|
|
|
|
)
|
|
|
|
|
|
|
|
attrNames := map[string]bool{}
|
|
|
|
var oldAttrs map[string]string
|
|
|
|
var newAttrs map[string]string
|
2018-09-20 17:15:44 -05:00
|
|
|
if rc.Current != nil {
|
|
|
|
if before := rc.Current.Before; before != nil {
|
|
|
|
ty, err := before.ImpliedType()
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
if err == nil {
|
2018-09-20 17:15:44 -05:00
|
|
|
val, err := before.Decode(ty)
|
|
|
|
if err == nil {
|
|
|
|
oldAttrs = hcl2shim.FlatmapValueFromHCL2(val)
|
|
|
|
for k := range oldAttrs {
|
|
|
|
attrNames[k] = true
|
|
|
|
}
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-20 17:15:44 -05:00
|
|
|
if after := rc.Current.After; after != nil {
|
|
|
|
ty, err := after.ImpliedType()
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
if err == nil {
|
2018-09-20 17:15:44 -05:00
|
|
|
val, err := after.Decode(ty)
|
|
|
|
if err == nil {
|
|
|
|
newAttrs = hcl2shim.FlatmapValueFromHCL2(val)
|
|
|
|
for k := range newAttrs {
|
|
|
|
attrNames[k] = true
|
|
|
|
}
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if oldAttrs == nil {
|
|
|
|
oldAttrs = make(map[string]string)
|
|
|
|
}
|
|
|
|
if newAttrs == nil {
|
|
|
|
newAttrs = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
attrNamesOrder := make([]string, 0, len(attrNames))
|
|
|
|
keyLen := 0
|
|
|
|
for n := range attrNames {
|
|
|
|
attrNamesOrder = append(attrNamesOrder, n)
|
|
|
|
if len(n) > keyLen {
|
|
|
|
keyLen = len(n)
|
|
|
|
}
|
|
|
|
}
|
2018-09-25 18:15:49 -05:00
|
|
|
sort.Strings(attrNamesOrder)
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
|
|
|
|
for _, attrK := range attrNamesOrder {
|
|
|
|
v := newAttrs[attrK]
|
|
|
|
u := oldAttrs[attrK]
|
|
|
|
|
2019-07-17 21:41:24 -05:00
|
|
|
if v == hcl2shim.UnknownVariableValue {
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 16:24:45 -05:00
|
|
|
v = "<computed>"
|
|
|
|
}
|
|
|
|
// NOTE: we don't support <sensitive> here because we would
|
|
|
|
// need schema to do that. Excluding sensitive values
|
|
|
|
// is now done at the UI layer, and so should not be tested
|
|
|
|
// at the core layer.
|
|
|
|
|
|
|
|
updateMsg := ""
|
|
|
|
// TODO: Mark " (forces new resource)" in updateMsg when appropriate.
|
|
|
|
|
|
|
|
fmt.Fprintf(
|
|
|
|
&mBuf, " %s:%s %#v => %#v%s\n",
|
|
|
|
attrK,
|
|
|
|
strings.Repeat(" ", keyLen-len(attrK)),
|
|
|
|
u, v,
|
|
|
|
updateMsg,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if moduleKey == "" { // root module
|
|
|
|
buf.Write(mBuf.Bytes())
|
|
|
|
buf.WriteByte('\n')
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(&buf, "%s:\n", moduleKey)
|
|
|
|
s := bufio.NewScanner(&mBuf)
|
|
|
|
for s.Scan() {
|
|
|
|
buf.WriteString(fmt.Sprintf(" %s\n", s.Text()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.String()
|
|
|
|
}
|
|
|
|
|
2018-09-10 15:37:35 -05:00
|
|
|
// assertNoDiagnostics fails the test in progress (using t.Fatal) if the given
|
|
|
|
// diagnostics is non-empty.
|
|
|
|
func assertNoDiagnostics(t *testing.T, diags tfdiags.Diagnostics) {
|
|
|
|
t.Helper()
|
|
|
|
if len(diags) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logDiagnostics(t, diags)
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
// assertNoDiagnostics fails the test in progress (using t.Fatal) if the given
|
|
|
|
// diagnostics has any errors.
|
|
|
|
func assertNoErrors(t *testing.T, diags tfdiags.Diagnostics) {
|
|
|
|
t.Helper()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logDiagnostics(t, diags)
|
|
|
|
t.FailNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
// logDiagnostics is a test helper that logs the given diagnostics to to the
|
|
|
|
// given testing.T using t.Log, in a way that is hopefully useful in debugging
|
|
|
|
// a test. It does not generate any errors or fail the test. See
|
|
|
|
// assertNoDiagnostics and assertNoErrors for more specific helpers that can
|
|
|
|
// also fail the test.
|
|
|
|
func logDiagnostics(t *testing.T, diags tfdiags.Diagnostics) {
|
2018-09-11 18:27:13 -05:00
|
|
|
t.Helper()
|
2018-09-10 15:37:35 -05:00
|
|
|
for _, diag := range diags {
|
|
|
|
desc := diag.Description()
|
|
|
|
rng := diag.Source()
|
|
|
|
|
|
|
|
var severity string
|
|
|
|
switch diag.Severity() {
|
|
|
|
case tfdiags.Error:
|
|
|
|
severity = "ERROR"
|
|
|
|
case tfdiags.Warning:
|
|
|
|
severity = "WARN"
|
|
|
|
default:
|
|
|
|
severity = "???" // should never happen
|
|
|
|
}
|
|
|
|
|
|
|
|
if subj := rng.Subject; subj != nil {
|
|
|
|
if desc.Detail == "" {
|
|
|
|
t.Logf("[%s@%s] %s", severity, subj.StartString(), desc.Summary)
|
|
|
|
} else {
|
|
|
|
t.Logf("[%s@%s] %s: %s", severity, subj.StartString(), desc.Summary, desc.Detail)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if desc.Detail == "" {
|
|
|
|
t.Logf("[%s] %s", severity, desc.Summary)
|
|
|
|
} else {
|
|
|
|
t.Logf("[%s] %s: %s", severity, desc.Summary, desc.Detail)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
const testContextGraph = `
|
|
|
|
root: root
|
|
|
|
aws_instance.bar
|
|
|
|
aws_instance.bar -> provider.aws
|
|
|
|
aws_instance.foo
|
|
|
|
aws_instance.foo -> provider.aws
|
|
|
|
provider.aws
|
|
|
|
root
|
|
|
|
root -> aws_instance.bar
|
|
|
|
root -> aws_instance.foo
|
|
|
|
`
|
|
|
|
|
|
|
|
const testContextRefreshModuleStr = `
|
2016-04-21 14:59:10 -05:00
|
|
|
aws_instance.web: (tainted)
|
|
|
|
ID = bar
|
2020-04-01 12:13:40 -05:00
|
|
|
provider = provider["registry.terraform.io/hashicorp/aws"]
|
2015-02-13 20:09:45 -06:00
|
|
|
|
|
|
|
module.child:
|
|
|
|
aws_instance.web:
|
|
|
|
ID = new
|
2020-04-01 12:13:40 -05:00
|
|
|
provider = provider["registry.terraform.io/hashicorp/aws"]
|
2015-02-13 20:09:45 -06:00
|
|
|
`
|
|
|
|
|
2015-04-10 15:51:22 -05:00
|
|
|
const testContextRefreshOutputStr = `
|
|
|
|
aws_instance.web:
|
|
|
|
ID = foo
|
2020-04-01 12:13:40 -05:00
|
|
|
provider = provider["registry.terraform.io/hashicorp/aws"]
|
2015-04-10 15:51:22 -05:00
|
|
|
foo = bar
|
|
|
|
|
|
|
|
Outputs:
|
|
|
|
|
|
|
|
foo = bar
|
|
|
|
`
|
|
|
|
|
2015-02-13 20:09:45 -06:00
|
|
|
const testContextRefreshOutputPartialStr = `
|
|
|
|
<no state>
|
|
|
|
`
|
|
|
|
|
|
|
|
const testContextRefreshTaintedStr = `
|
2016-04-21 14:59:10 -05:00
|
|
|
aws_instance.web: (tainted)
|
|
|
|
ID = foo
|
2020-04-01 12:13:40 -05:00
|
|
|
provider = provider["registry.terraform.io/hashicorp/aws"]
|
2015-02-13 20:09:45 -06:00
|
|
|
`
|