2015-07-10 22:08:49 +02:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"reflect"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"testing"
|
2018-05-05 04:24:06 +02:00
|
|
|
|
2018-05-23 02:53:56 +02:00
|
|
|
"github.com/davecgh/go-spew/spew"
|
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 23:24:45 +02:00
|
|
|
"github.com/google/go-cmp/cmp"
|
2018-05-05 04:24:06 +02:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
2018-05-23 02:53:56 +02:00
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
2018-09-28 02:57:08 +02:00
|
|
|
"github.com/hashicorp/terraform/config/hcl2shim"
|
2018-07-05 19:33:29 +02:00
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
2018-09-28 02:57:08 +02:00
|
|
|
"github.com/hashicorp/terraform/plans"
|
2018-08-17 21:32:35 +02:00
|
|
|
"github.com/hashicorp/terraform/providers"
|
2018-09-28 02:57:08 +02:00
|
|
|
"github.com/hashicorp/terraform/states"
|
2018-09-05 23:35:30 +02:00
|
|
|
"github.com/hashicorp/terraform/tfdiags"
|
2015-07-10 22:08:49 +02:00
|
|
|
)
|
|
|
|
|
2016-11-06 08:00:05 +01:00
|
|
|
func TestContext2Plan_basic(t *testing.T) {
|
2015-07-10 22:08:49 +02:00
|
|
|
m := testModule(t, "plan-good")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2017-06-06 02:08:02 +02:00
|
|
|
ProviderSHA256s: map[string][]byte{
|
|
|
|
"aws": []byte("placeholder"),
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02: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 23:24:45 +02:00
|
|
|
if l := len(plan.Changes.Resources); l < 2 {
|
|
|
|
t.Fatalf("wrong number of resources %d; want fewer than two\n%s", l, spew.Sdump(plan.Changes.Resources))
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2017-06-06 02:08:02 +02:00
|
|
|
if !reflect.DeepEqual(plan.ProviderSHA256s, ctx.providerSHA256s) {
|
|
|
|
t.Errorf("wrong ProviderSHA256s %#v; want %#v", plan.ProviderSHA256s, ctx.providerSHA256s)
|
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if !ctx.State().Empty() {
|
|
|
|
t.Fatalf("expected empty state, got %#v\n", ctx.State())
|
|
|
|
}
|
|
|
|
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
for _, r := range plan.Changes.Resources {
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := r.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
2018-09-19 00:44:51 +02:00
|
|
|
foo := ric.After.GetAttr("foo").AsString()
|
2018-09-15 00:40:09 +02:00
|
|
|
if foo != "2" {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatalf("incorrect plan for 'bar': %#v", ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
}
|
|
|
|
case "aws_instance.foo":
|
2018-09-19 00:44:51 +02:00
|
|
|
num, _ := ric.After.GetAttr("num").AsBigFloat().Int64()
|
2018-09-18 01:25:11 +02:00
|
|
|
if num != 2 {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatalf("incorrect plan for 'foo': %#v", ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-28 22:35:29 +01:00
|
|
|
func TestContext2Plan_createBefore_deposed(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-cbd")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2016-11-28 22:35:29 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz",
|
2018-09-15 00:40:09 +02:00
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "baz",
|
|
|
|
},
|
2016-11-28 22:35:29 +01:00
|
|
|
},
|
|
|
|
Deposed: []*InstanceState{
|
2018-09-15 00:40:09 +02:00
|
|
|
&InstanceState{
|
|
|
|
ID: "foo",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "foo",
|
|
|
|
},
|
|
|
|
},
|
2016-11-28 22:35:29 +01: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 23:24:45 +02:00
|
|
|
})
|
2016-11-28 22:35:29 +01:00
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-11-28 22:35:29 +01:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-11-28 22:35:29 +01:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
// the state should still show one deposed
|
|
|
|
expectedState := strings.TrimSpace(`
|
|
|
|
aws_instance.foo: (1 deposed)
|
|
|
|
ID = baz
|
|
|
|
provider = provider.aws
|
2018-09-18 01:25:11 +02:00
|
|
|
Deposed ID 1 = foo`)
|
2016-11-28 22:35:29 +01:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if ctx.State().String() != expectedState {
|
|
|
|
t.Fatalf("\nexpected: %q\ngot: %q\n", expectedState, ctx.State().String())
|
|
|
|
}
|
2016-11-28 22:35:29 +01:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-11-28 22:35:29 +01:00
|
|
|
|
2018-09-21 01:09:02 +02:00
|
|
|
type InstanceGen struct {
|
2018-09-24 21:14:32 +02:00
|
|
|
Addr string
|
2018-09-21 01:09:02 +02:00
|
|
|
DeposedKey states.DeposedKey
|
2018-09-15 00:40:09 +02:00
|
|
|
}
|
2018-09-21 01:09:02 +02:00
|
|
|
want := map[InstanceGen]bool{
|
|
|
|
{
|
|
|
|
Addr: "aws_instance.foo",
|
|
|
|
}: true,
|
|
|
|
{
|
2018-09-24 21:14:32 +02:00
|
|
|
Addr: "aws_instance.foo",
|
2018-09-21 01:09:02 +02:00
|
|
|
DeposedKey: states.DeposedKey("00000001"),
|
|
|
|
}: true,
|
|
|
|
}
|
|
|
|
got := make(map[InstanceGen]bool)
|
|
|
|
changes := make(map[InstanceGen]*plans.ResourceInstanceChangeSrc)
|
2018-09-15 00:40:09 +02:00
|
|
|
|
2018-09-21 01:09:02 +02:00
|
|
|
for _, change := range plan.Changes.Resources {
|
|
|
|
k := InstanceGen{
|
|
|
|
Addr: change.Addr.String(),
|
|
|
|
DeposedKey: change.DeposedKey,
|
|
|
|
}
|
|
|
|
got[k] = true
|
|
|
|
changes[k] = change
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Fatalf("wrong resource instance object changes in plan\ngot: %s\nwant: %s", spew.Sdump(got), spew.Sdump(want))
|
2018-09-15 00:40:09 +02:00
|
|
|
}
|
|
|
|
|
2018-09-21 01:09:02 +02:00
|
|
|
{
|
2018-09-24 21:14:32 +02:00
|
|
|
ric, err := changes[InstanceGen{Addr: "aws_instance.foo"}].Decode(ty)
|
2018-09-21 01:09:02 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got, want := ric.Action, plans.NoOp; got != want {
|
|
|
|
t.Errorf("current object change action is %s; want %s", got, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
// the existing instance should only have an unchanged id
|
|
|
|
expected, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{"id": cty.StringVal("baz")}))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
checkVals(t, expected, ric.After)
|
2016-11-28 22:35:29 +01:00
|
|
|
}
|
2018-09-15 00:40:09 +02:00
|
|
|
|
2018-09-21 01:09:02 +02:00
|
|
|
{
|
2018-09-24 21:14:32 +02:00
|
|
|
ric, err := changes[InstanceGen{Addr: "aws_instance.foo", DeposedKey: states.DeposedKey("00000001")}].Decode(ty)
|
2018-09-21 01:09:02 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got, want := ric.Action, plans.Delete; got != want {
|
|
|
|
t.Errorf("deposed object change action is %s; want %s", got, want)
|
|
|
|
}
|
|
|
|
}
|
2016-11-28 22:35:29 +01:00
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_createBefore_maintainRoot(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-cbd-maintain-root")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
|
|
|
"in": &InputValue{
|
|
|
|
Value: cty.StringVal("a,b,c"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if !ctx.State().Empty() {
|
|
|
|
t.Fatal("expected empty state, got:", ctx.State())
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if len(plan.Changes.Resources) != 4 {
|
|
|
|
t.Error("expected 4 resource in plan, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
// these should all be creates
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("unexpected action %s for %s", res.Action, res.Addr.String())
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_emptyDiff(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-empty")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = func(
|
|
|
|
info *InstanceInfo,
|
|
|
|
s *InstanceState,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if !ctx.State().Empty() {
|
|
|
|
t.Fatal("expected empty state, got:", ctx.State())
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Error("expected 2 resource in plan, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
actions := map[string]plans.Action{}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
actions[res.Addr.String()] = res.Action
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := map[string]plans.Action{
|
|
|
|
"aws_instance.foo": plans.Create,
|
|
|
|
"aws_instance.bar": plans.Create,
|
|
|
|
}
|
|
|
|
if !cmp.Equal(expected, actions) {
|
|
|
|
t.Fatal(cmp.Diff(expected, actions))
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-19 21:37:55 +01:00
|
|
|
func TestContext2Plan_escapedVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-escaped-var")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-01-19 21:37:55 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-01-19 21:37:55 +01:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Error("expected 1 resource in plan, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
res := plan.Changes.Resources[0]
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2016-01-19 21:37:55 +01:00
|
|
|
}
|
2018-09-15 00:40:09 +02:00
|
|
|
|
|
|
|
expected := objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("bar-${baz}"),
|
|
|
|
"type": cty.StringVal("aws_instance")},
|
|
|
|
)
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
checkVals(t, expected, ric.After)
|
2016-01-19 21:37:55 +01:00
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_minimal(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-empty")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if !ctx.State().Empty() {
|
|
|
|
t.Fatal("expected empty state, got:", ctx.State())
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Error("expected 2 resource in plan, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
actions := map[string]plans.Action{}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
actions[res.Addr.String()] = res.Action
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := map[string]plans.Action{
|
|
|
|
"aws_instance.foo": plans.Create,
|
|
|
|
"aws_instance.bar": plans.Create,
|
|
|
|
}
|
|
|
|
if !cmp.Equal(expected, actions) {
|
|
|
|
t.Fatal(cmp.Diff(expected, actions))
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_modules(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-modules")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if len(plan.Changes.Resources) != 3 {
|
|
|
|
t.Error("expected 3 resource in plan, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
expectFoo := objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("2"),
|
|
|
|
"type": cty.StringVal("aws_instance")},
|
|
|
|
)
|
|
|
|
|
|
|
|
expectNum := objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance")},
|
|
|
|
)
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var expected cty.Value
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
expected = expectFoo
|
|
|
|
case "aws_instance.foo":
|
|
|
|
expected = expectNum
|
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
expected = expectNum
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
checkVals(t, expected, ric.After)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GH-1475
|
|
|
|
func TestContext2Plan_moduleCycle(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-cycle")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
2018-05-23 18:59:03 +02:00
|
|
|
"id": {Type: cty.String, Computed: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
"some_input": {Type: cty.String, Optional: true},
|
2018-09-15 00:40:09 +02:00
|
|
|
"type": {Type: cty.String, Optional: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var expected cty.Value
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.b":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
})
|
|
|
|
case "aws_instance.c":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"some_input": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
checkVals(t, expected, ric.After)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleDeadlock(t *testing.T) {
|
2015-08-10 22:03:02 +02:00
|
|
|
testCheckDeadlock(t, func() {
|
|
|
|
m := testModule(t, "plan-module-deadlock")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
plan, err := ctx.Plan()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
expected := objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
})
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.foo[0]":
|
|
|
|
case "module.child.aws_instance.foo[1]":
|
|
|
|
case "module.child.aws_instance.foo[2]":
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
checkVals(t, expected, ric.After)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2015-08-10 22:03:02 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleInput(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-input")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var expected cty.Value
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("2"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
})
|
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("42"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
checkVals(t, expected, ric.After)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleInputComputed(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-input-computed")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleInputFromVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-input-var")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
|
|
|
"foo": &InputValue{
|
|
|
|
Value: cty.StringVal("52"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("2"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("52"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleMultiVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-multi-var")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {Type: cty.String, Computed: true},
|
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
"baz": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 5 {
|
|
|
|
t.Fatal("expected 5 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.parent[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.parent[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.bar[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"baz": cty.StringVal("baz"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.bar[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"baz": cty.StringVal("baz"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("baz,baz"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleOrphans(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-modules-remove")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "child"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz",
|
|
|
|
},
|
2018-09-15 00:40:09 +02:00
|
|
|
Provider: "provider.aws",
|
2015-07-10 22:08:49 +02: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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("expected resource delete, got %s", res.Action)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedState := `<no state>
|
|
|
|
module.child:
|
|
|
|
aws_instance.foo:
|
|
|
|
ID = baz
|
|
|
|
provider = provider.aws`
|
|
|
|
|
|
|
|
if ctx.State().String() != expectedState {
|
|
|
|
t.Fatalf("\nexpected state: %q\n\ngot: %q", expectedState, ctx.State().String())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
// https://github.com/hashicorp/terraform/issues/3114
|
|
|
|
func TestContext2Plan_moduleOrphansWithProvisioner(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-modules-remove-provisioners")
|
|
|
|
p := testProvider("aws")
|
|
|
|
pr := testProvisioner()
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.top": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "top",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "parent", "childone"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz",
|
|
|
|
},
|
2018-09-15 00:40:09 +02:00
|
|
|
Provider: "provider.aws",
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "parent", "childtwo"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz",
|
|
|
|
},
|
2018-09-15 00:40:09 +02:00
|
|
|
Provider: "provider.aws",
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01: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 23:24:45 +02:00
|
|
|
})
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-08-17 21:32:35 +02:00
|
|
|
Provisioners: map[string]ProvisionerFactory{
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
"shell": testProvisionerFuncFixed(pr),
|
|
|
|
},
|
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 3 {
|
|
|
|
t.Error("expected 3 planned resources, got", len(plan.Changes.Resources))
|
|
|
|
}
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.parent.module.childone.aws_instance.foo":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("expected resource Delete, got %s", res.Action)
|
|
|
|
}
|
|
|
|
case "module.parent.module.childtwo.aws_instance.foo":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("expected resource Delete, got %s", res.Action)
|
|
|
|
}
|
|
|
|
case "aws_instance.top":
|
|
|
|
if res.Action != plans.NoOp {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatal("expected no changes, got", res.Action)
|
2018-09-15 00:40:09 +02:00
|
|
|
}
|
|
|
|
default:
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatalf("unknown instance: %s\nafter: %#v", i, hcl2shim.ConfigValueFromHCL2(ric.After))
|
2018-09-15 00:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
expectedState := `aws_instance.top:
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
ID = top
|
2018-09-15 00:40:09 +02:00
|
|
|
provider = provider.aws
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
|
|
|
|
module.parent.childone:
|
|
|
|
aws_instance.foo:
|
|
|
|
ID = baz
|
2018-09-15 00:40:09 +02:00
|
|
|
provider = provider.aws
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
module.parent.childtwo:
|
|
|
|
aws_instance.foo:
|
|
|
|
ID = baz
|
2018-09-15 00:40:09 +02:00
|
|
|
provider = provider.aws`
|
|
|
|
|
|
|
|
if expectedState != ctx.State().String() {
|
|
|
|
t.Fatalf("\nexpect state: %q\ngot state: %q\n", expectedState, ctx.State().String())
|
core: fix bug detecting deeply nested module orphans
Context:
As part of building up a Plan, Terraform needs to detect "orphaned"
resources--resources which are present in the state but not in the
config. This happens when config for those resources is removed by the
user, making it Terraform's responsibility to destroy them.
Both state and config are organized by Module into a logical tree, so
the process of finding orphans involves checking for orphaned Resources
in the current module and for orphaned Modules, which themselves will
have all their Resources marked as orphans.
Bug:
In #3114 a problem was exposed where, given a module tree that looked
like this:
```
root
|
+-- parent (empty, except for sub-modules)
|
+-- child1 (1 resource)
|
+-- child2 (1 resource)
```
If `parent` was removed, a bunch of error messages would occur during
the plan. The root cause of this was duplicate orphans appearing for the
resources in child1 and child2.
Fix:
This turned out to be a bug in orphaned module detection. When looking
for deeply nested orphaned modules, root.parent was getting added twice
as an orphaned module to the graph.
Here, we add an additional check to prevent a double add, which
addresses this scenario properly.
Fixes #3114 (the Provisioner side of it was fixed in #4877)
2016-02-05 19:19:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_moduleProviderInherit(t *testing.T) {
|
|
|
|
var l sync.Mutex
|
|
|
|
var calls []string
|
|
|
|
|
|
|
|
m := testModule(t, "plan-module-provider-inherit")
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": func() (providers.Interface, error) {
|
2017-04-21 18:28:19 +02:00
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
2017-04-22 02:40:46 +02:00
|
|
|
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
Provider: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"from": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"from": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-04-22 02:40:46 +02:00
|
|
|
p.ConfigureFn = func(c *ResourceConfig) error {
|
|
|
|
if v, ok := c.Get("from"); !ok || v.(string) != "root" {
|
|
|
|
return fmt.Errorf("bad")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
p.DiffFn = func(
|
|
|
|
info *InstanceInfo,
|
|
|
|
state *InstanceState,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
v, _ := c.Get("from")
|
|
|
|
|
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
calls = append(calls, v.(string))
|
|
|
|
return testDiffFn(info, state, c)
|
|
|
|
}
|
|
|
|
return p, nil
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
2017-04-22 02:40:46 +02:00
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
actual := calls
|
|
|
|
sort.Strings(actual)
|
|
|
|
expected := []string{"child", "root"}
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
|
|
t.Fatalf("bad: %#v", actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-24 21:56:13 +01:00
|
|
|
// This tests (for GH-11282) that deeply nested modules properly inherit
|
|
|
|
// configuration.
|
|
|
|
func TestContext2Plan_moduleProviderInheritDeep(t *testing.T) {
|
|
|
|
var l sync.Mutex
|
|
|
|
|
|
|
|
m := testModule(t, "plan-module-provider-inherit-deep")
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": func() (providers.Interface, error) {
|
2017-04-22 02:40:46 +02:00
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
2017-01-24 21:56:13 +01:00
|
|
|
|
2017-04-22 02:40:46 +02:00
|
|
|
var from string
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
Provider: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"from": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2017-04-22 02:40:46 +02:00
|
|
|
p.ConfigureFn = func(c *ResourceConfig) error {
|
|
|
|
v, ok := c.Get("from")
|
|
|
|
if !ok || v.(string) != "root" {
|
|
|
|
return fmt.Errorf("bad")
|
|
|
|
}
|
|
|
|
|
|
|
|
from = v.(string)
|
|
|
|
return nil
|
2017-01-24 21:56:13 +01:00
|
|
|
}
|
|
|
|
|
2017-04-22 02:40:46 +02:00
|
|
|
p.DiffFn = func(
|
|
|
|
info *InstanceInfo,
|
|
|
|
state *InstanceState,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
if from != "root" {
|
|
|
|
return nil, fmt.Errorf("bad resource")
|
|
|
|
}
|
2017-01-24 21:56:13 +01:00
|
|
|
|
2017-04-22 02:40:46 +02:00
|
|
|
return testDiffFn(info, state, c)
|
2017-01-24 21:56:13 +01:00
|
|
|
}
|
2017-04-22 02:40:46 +02:00
|
|
|
return p, nil
|
|
|
|
},
|
2017-01-24 21:56:13 +01:00
|
|
|
},
|
2017-04-22 02:40:46 +02:00
|
|
|
),
|
2017-01-24 21:56:13 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) {
|
|
|
|
var l sync.Mutex
|
|
|
|
var calls []string
|
|
|
|
|
|
|
|
m := testModule(t, "plan-module-provider-defaults-var")
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": func() (providers.Interface, error) {
|
2017-04-21 18:28:19 +02:00
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
2017-04-22 02:40:46 +02:00
|
|
|
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
Provider: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"to": {Type: cty.String, Optional: true},
|
|
|
|
"from": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"from": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-04-22 02:40:46 +02:00
|
|
|
p.ConfigureFn = func(c *ResourceConfig) error {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
if v, ok := c.Get("from"); ok {
|
|
|
|
buf.WriteString(v.(string) + "\n")
|
|
|
|
}
|
|
|
|
if v, ok := c.Get("to"); ok {
|
|
|
|
buf.WriteString(v.(string) + "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
calls = append(calls, buf.String())
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
return p, nil
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
2017-04-22 02:40:46 +02:00
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
|
|
|
"foo": &InputValue{
|
|
|
|
Value: cty.StringVal("root"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := []string{
|
2017-10-13 16:11:10 +02:00
|
|
|
"child\nchild\n",
|
2017-11-01 23:34:18 +01:00
|
|
|
"root\n",
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2017-11-01 23:34:18 +01:00
|
|
|
sort.Strings(calls)
|
2015-07-10 22:08:49 +02:00
|
|
|
if !reflect.DeepEqual(calls, expected) {
|
2017-10-13 16:11:10 +02:00
|
|
|
t.Fatalf("expected:\n%#v\ngot:\n%#v\n", expected, calls)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-14 06:22:21 +01:00
|
|
|
func TestContext2Plan_moduleProviderVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-provider-var")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
Provider: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"value": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"value": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-12-14 06:22:21 +01:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-12-14 06:22:21 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-12-14 06:22:21 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-12-14 06:22:21 +01:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.test":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"value": cty.StringVal("hello"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-12-14 06:22:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_moduleVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-var")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var expected cty.Value
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("2"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
})
|
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
checkVals(t, expected, ric.After)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-07 22:55:35 +01:00
|
|
|
func TestContext2Plan_moduleVarWrongTypeBasic(t *testing.T) {
|
2016-04-15 21:07:54 +02:00
|
|
|
m := testModule(t, "plan-module-wrong-var-type")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-04-15 21:07:54 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("succeeded; want errors")
|
2016-04-15 21:07:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleVarWrongTypeNested(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-wrong-var-type-nested")
|
2017-04-22 02:40:46 +02:00
|
|
|
p := testProvider("null")
|
2016-04-15 21:07:54 +02:00
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"null": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-04-15 21:07:54 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("succeeded; want errors")
|
2016-04-15 21:07:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-22 06:30:34 +02:00
|
|
|
func TestContext2Plan_moduleVarWithDefaultValue(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-var-with-default-value")
|
|
|
|
p := testProvider("null")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"null": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-04-22 06:30:34 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-04-22 06:30:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_moduleVarComputed(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-var-computed")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-15 00:40:09 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-15 00:40:09 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-15 00:40:09 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
case "module.child.aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-15 00:40:09 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_preventDestroy_bad(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-prevent-destroy-bad")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
plan, err := ctx.Plan()
|
|
|
|
|
2018-05-22 20:45:07 +02:00
|
|
|
expectedErr := "aws_instance.foo has lifecycle.prevent_destroy"
|
2015-07-10 22:08:49 +02:00
|
|
|
if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
|
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 23:24:45 +02:00
|
|
|
if plan != nil {
|
|
|
|
t.Logf(legacyDiffComparisonString(plan.Changes))
|
|
|
|
}
|
|
|
|
t.Fatalf("expected err would contain %q\nerr: %s", expectedErr, err)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_preventDestroy_good(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-prevent-destroy-good")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-05-21 20:32:43 +02: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 23:24:45 +02:00
|
|
|
if !plan.Changes.Empty() {
|
2018-09-15 00:40:09 +02:00
|
|
|
t.Fatalf("expected no changes, got %#v\n", plan.Changes)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-29 03:31:47 +02:00
|
|
|
func TestContext2Plan_preventDestroy_countBad(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-prevent-destroy-count-bad")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2016-10-29 03:31:47 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc345",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2016-10-29 03:31:47 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
plan, err := ctx.Plan()
|
|
|
|
|
2018-05-22 20:45:07 +02:00
|
|
|
expectedErr := "aws_instance.foo[1] has lifecycle.prevent_destroy"
|
2016-10-29 03:31:47 +02:00
|
|
|
if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
|
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 23:24:45 +02:00
|
|
|
if plan != nil {
|
|
|
|
t.Logf(legacyDiffComparisonString(plan.Changes))
|
|
|
|
}
|
|
|
|
t.Fatalf("expected err would contain %q\nerr: %s", expectedErr, err)
|
2016-10-29 03:31:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_preventDestroy_countGood(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-prevent-destroy-count-good")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"current": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-10-29 03:31:47 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-10-29 03:31:47 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2016-10-29 03:31:47 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc345",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2016-10-29 03:31:47 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-10-29 03:31:47 +02:00
|
|
|
}
|
2018-05-21 20:32:43 +02: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 23:24:45 +02:00
|
|
|
if plan.Changes.Empty() {
|
|
|
|
t.Fatalf("Expected non-empty plan, got %s", legacyDiffComparisonString(plan.Changes))
|
2016-10-29 03:31:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_preventDestroy_countGoodNoChange(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-prevent-destroy-count-good")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"current": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-10-29 03:31:47 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-10-29 03:31:47 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2016-10-29 03:31:47 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"current": "0",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2016-10-29 03:31:47 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-10-29 03:31:47 +02:00
|
|
|
}
|
2018-05-21 20:32:43 +02: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 23:24:45 +02:00
|
|
|
if !plan.Changes.Empty() {
|
|
|
|
t.Fatalf("Expected empty plan, got %s", legacyDiffComparisonString(plan.Changes))
|
2016-10-29 03:31:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-prevent-destroy-good")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2015-07-10 22:08:49 +02:00
|
|
|
Destroy: 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 23:24:45 +02:00
|
|
|
plan, diags := ctx.Plan()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-05-22 20:45:07 +02:00
|
|
|
expectedErr := "aws_instance.foo has lifecycle.prevent_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 23:24:45 +02:00
|
|
|
if !strings.Contains(fmt.Sprintf("%s", diags.Err()), expectedErr) {
|
|
|
|
if plan != nil {
|
|
|
|
t.Logf(legacyDiffComparisonString(plan.Changes))
|
|
|
|
}
|
|
|
|
t.Fatalf("expected err would contain %q\nerr: %s", expectedErr, diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-30 22:27:08 +01:00
|
|
|
func TestContext2Plan_provisionerCycle(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-provisioner-cycle")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
pr := testProvisioner()
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-08-17 21:32:35 +02:00
|
|
|
Provisioners: map[string]ProvisionerFactory{
|
2016-10-30 22:27:08 +01:00
|
|
|
"local-exec": testProvisionerFuncFixed(pr),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("succeeded; want errors")
|
2016-10-30 22:27:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_computed(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 22:00:46 +02:00
|
|
|
func TestContext2Plan_computedDataResource(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-data-resource")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"num": {Type: cty.String, Optional: true},
|
|
|
|
"compute": {Type: cty.String, Optional: true},
|
|
|
|
"foo": {Type: cty.String, Computed: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
DataSources: map[string]*configschema.Block{
|
|
|
|
"aws_vpc": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-05-21 22:00:46 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-05-21 22:00:46 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-05-21 22:00:46 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-05-21 22:00:46 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.DataSources["aws_vpc"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-05-21 22:00:46 +02: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 23:24:45 +02:00
|
|
|
if rc := plan.Changes.ResourceInstance(addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "aws_instance", Name: "foo"}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)); rc == nil {
|
2016-05-21 22:00:46 +02:00
|
|
|
t.Fatalf("missing diff for aws_instance.foo")
|
|
|
|
}
|
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 23:24:45 +02:00
|
|
|
rcs := plan.Changes.ResourceInstance(addrs.Resource{
|
|
|
|
Mode: addrs.DataResourceMode,
|
|
|
|
Type: "aws_vpc",
|
|
|
|
Name: "bar",
|
|
|
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
|
|
|
|
if rcs == nil {
|
2016-05-21 22:00:46 +02:00
|
|
|
t.Fatalf("missing diff for data.aws_vpc.bar")
|
|
|
|
}
|
2016-05-21 22:23:28 +02:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
rc, err := rcs.Decode(ty)
|
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 23:24:45 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2016-05-21 22:23:28 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
|
|
|
|
checkVals(t,
|
|
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
}),
|
|
|
|
rc.After,
|
|
|
|
)
|
2016-05-21 22:00:46 +02:00
|
|
|
}
|
|
|
|
|
2018-10-02 10:45:17 +02:00
|
|
|
func TestContext2Plan_computedInFunction(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-in-function")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"attr": {Type: cty.Number, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
DataSources: map[string]*configschema.Block{
|
|
|
|
"aws_data_source": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"computed": {Type: cty.List(cty.String), Computed: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-02 19:58:49 +02:00
|
|
|
p.ReadDataSourceResponse = providers.ReadDataSourceResponse{
|
|
|
|
State: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
"computed": cty.ListVal([]cty.Value{
|
|
|
|
cty.StringVal("foo"),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
}
|
2018-10-02 10:45:17 +02:00
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
2018-10-02 19:58:49 +02:00
|
|
|
diags := ctx.Validate()
|
|
|
|
assertNoErrors(t, diags)
|
2018-10-02 10:45:17 +02:00
|
|
|
|
2018-10-02 19:58:49 +02:00
|
|
|
state, diags := ctx.Refresh() // data resource is read in this step
|
|
|
|
assertNoErrors(t, diags)
|
2018-10-02 10:45:17 +02:00
|
|
|
|
2018-10-02 19:58:49 +02:00
|
|
|
if !p.ReadDataSourceCalled {
|
|
|
|
t.Fatalf("ReadDataSource was not called on provider during refresh; should've been called")
|
2018-10-02 10:45:17 +02:00
|
|
|
}
|
2018-10-02 19:58:49 +02:00
|
|
|
p.ReadDataSourceCalled = false // reset for next call
|
2018-10-02 10:45:17 +02:00
|
|
|
|
2018-10-02 19:58:49 +02:00
|
|
|
t.Logf("state after refresh:\n%s", state)
|
|
|
|
|
|
|
|
_, diags = ctx.Plan() // should do nothing with data resource in this step, since it was already read
|
|
|
|
assertNoErrors(t, diags)
|
|
|
|
|
|
|
|
if p.ReadDataSourceCalled {
|
|
|
|
t.Fatalf("ReadDataSource was called on provider during plan; should not have been called")
|
2018-10-02 10:45:17 +02:00
|
|
|
}
|
2018-10-02 19:58:49 +02:00
|
|
|
|
2018-10-02 10:45:17 +02:00
|
|
|
}
|
|
|
|
|
2016-09-02 22:29:25 +02:00
|
|
|
func TestContext2Plan_computedDataCountResource(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-data-count")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"num": {Type: cty.String, Optional: true},
|
|
|
|
"compute": {Type: cty.String, Optional: true},
|
|
|
|
"foo": {Type: cty.String, Computed: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
DataSources: map[string]*configschema.Block{
|
|
|
|
"aws_vpc": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-09-02 22:29:25 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-09-02 22:29:25 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-09-02 22:29:25 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-09-02 22:29:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// make sure we created 3 "bar"s
|
|
|
|
for i := 0; i < 3; i++ {
|
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 23:24:45 +02:00
|
|
|
addr := addrs.Resource{
|
|
|
|
Mode: addrs.DataResourceMode,
|
|
|
|
Type: "aws_vpc",
|
|
|
|
Name: "bar",
|
|
|
|
}.Instance(addrs.IntKey(i)).Absolute(addrs.RootModuleInstance)
|
|
|
|
|
|
|
|
if rcs := plan.Changes.ResourceInstance(addr); rcs == nil {
|
|
|
|
t.Fatalf("missing changes for %s", addr)
|
2016-09-02 22:29:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-01 18:35:49 +02:00
|
|
|
func TestContext2Plan_localValueCount(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-local-value-count")
|
|
|
|
p := testProvider("test")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-09-01 18:35:49 +02:00
|
|
|
"test": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2017-09-01 18:35:49 +02: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 23:24:45 +02:00
|
|
|
// make sure we created 3 "foo"s
|
2017-09-01 18:35:49 +02:00
|
|
|
for i := 0; i < 3; i++ {
|
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 23:24:45 +02:00
|
|
|
addr := addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "test_resource",
|
|
|
|
Name: "foo",
|
|
|
|
}.Instance(addrs.IntKey(i)).Absolute(addrs.RootModuleInstance)
|
|
|
|
|
|
|
|
if rcs := plan.Changes.ResourceInstance(addr); rcs == nil {
|
|
|
|
t.Fatalf("missing changes for %s", addr)
|
2017-09-01 18:35:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
func TestContext2Plan_dataResourceBecomesComputed(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-data-resource-becomes-computed")
|
2016-07-01 01:22:20 +02:00
|
|
|
p := testProvider("aws")
|
2018-09-18 01:25:11 +02:00
|
|
|
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
2018-09-18 01:25:11 +02:00
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
"computed": {Type: cty.String, Computed: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
DataSources: map[string]*configschema.Block{
|
2018-09-18 01:25:11 +02:00
|
|
|
"aws_data_source": {
|
2018-05-23 02:53:56 +02:00
|
|
|
Attributes: map[string]*configschema.Attribute{
|
2018-09-18 01:25:11 +02:00
|
|
|
"foo": {Type: cty.String, Optional: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
|
|
|
|
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
2019-02-08 02:33:17 +01:00
|
|
|
fooVal := req.ProposedNewState.GetAttr("foo")
|
2018-09-18 01:25:11 +02:00
|
|
|
return providers.PlanResourceChangeResponse{
|
2019-02-08 02:33:17 +01:00
|
|
|
PlannedState: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
"foo": fooVal,
|
|
|
|
"computed": cty.UnknownVal(cty.String),
|
|
|
|
}),
|
2018-09-18 01:25:11 +02:00
|
|
|
PlannedPrivate: req.PriorPrivate,
|
2018-09-05 23:35:30 +02:00
|
|
|
}
|
2016-07-01 01:22:20 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
|
|
|
|
schema := p.GetSchemaReturn.DataSources["aws_data_source"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
p.ReadDataSourceResponse = providers.ReadDataSourceResponse{
|
2019-02-08 02:33:17 +01:00
|
|
|
// This should not be called, because the configuration for the
|
|
|
|
// data resource contains an unknown value for "foo".
|
|
|
|
Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("ReadDataSource called, but should not have been")),
|
2016-07-01 01:22:20 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
|
2016-07-01 01:22:20 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-09-18 01:25:11 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2016-07-01 01:22:20 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
2018-09-18 01:25:11 +02:00
|
|
|
"data.aws_data_source.foo": &ResourceState{
|
|
|
|
Type: "aws_data_source",
|
2016-07-01 01:22:20 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
Attributes: map[string]string{
|
2018-09-18 01:25:11 +02:00
|
|
|
"id": "i-abc123",
|
|
|
|
"foo": "baz",
|
2016-07-01 01:22:20 +02: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 23:24:45 +02:00
|
|
|
}),
|
2016-07-01 01:22:20 +02:00
|
|
|
})
|
|
|
|
|
2018-10-03 01:50:53 +02:00
|
|
|
_, diags := ctx.Refresh()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors during refresh: %s", diags.Err())
|
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
2018-10-03 01:50:53 +02:00
|
|
|
t.Fatalf("unexpected errors during plan: %s", diags.Err())
|
2016-07-01 01:22:20 +02:00
|
|
|
}
|
2016-05-28 21:39:36 +02:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
rcs := plan.Changes.ResourceInstance(addrs.Resource{
|
|
|
|
Mode: addrs.DataResourceMode,
|
|
|
|
Type: "aws_data_source",
|
|
|
|
Name: "foo",
|
|
|
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
|
|
|
|
if rcs == nil {
|
2018-10-03 01:50:53 +02:00
|
|
|
t.Logf("full changeset: %s", spew.Sdump(plan.Changes))
|
2018-09-18 01:25:11 +02:00
|
|
|
t.Fatalf("missing diff for data.aws_data_resource.foo")
|
|
|
|
}
|
2016-05-28 21:39:36 +02:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
rc, err := rcs.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-10-18 01:29:24 +02:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
// foo should now be unknown
|
|
|
|
foo := rc.After.GetAttr("foo")
|
|
|
|
if foo.IsKnown() {
|
|
|
|
t.Fatalf("foo should be unknown, got %#v", foo)
|
|
|
|
}
|
2016-05-28 21:39:36 +02:00
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_computedList(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-list")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"compute": {Type: cty.String, Optional: true},
|
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
"num": {Type: cty.String, Optional: true},
|
|
|
|
"list": {Type: cty.List(cty.String), Computed: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-11-19 22:59:27 +01:00
|
|
|
p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
diff := &InstanceDiff{
|
|
|
|
Attributes: map[string]*ResourceAttrDiff{},
|
|
|
|
}
|
|
|
|
|
|
|
|
computedKeys := map[string]bool{}
|
|
|
|
for _, k := range c.ComputedKeys {
|
|
|
|
computedKeys[k] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
compute, _ := c.Raw["compute"].(string)
|
|
|
|
if compute != "" {
|
|
|
|
diff.Attributes[compute] = &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fooOld := s.Attributes["foo"]
|
|
|
|
fooNew, _ := c.Raw["foo"].(string)
|
|
|
|
if fooOld != fooNew {
|
|
|
|
diff.Attributes["foo"] = &ResourceAttrDiff{
|
|
|
|
Old: fooOld,
|
|
|
|
New: fooNew,
|
|
|
|
NewComputed: computedKeys["foo"],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
numOld := s.Attributes["num"]
|
|
|
|
numNew, _ := c.Raw["num"].(string)
|
|
|
|
if numOld != numNew {
|
|
|
|
diff.Attributes["num"] = &ResourceAttrDiff{
|
|
|
|
Old: numOld,
|
|
|
|
New: numNew,
|
|
|
|
NewComputed: computedKeys["num"],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
listOld := s.Attributes["list.#"]
|
|
|
|
if listOld == "" {
|
|
|
|
diff.Attributes["list.#"] = &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return diff, nil
|
|
|
|
}
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
2018-11-19 23:59:38 +01:00
|
|
|
"list": cty.UnknownVal(cty.List(cty.String)),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"list": cty.UnknownVal(cty.List(cty.String)),
|
|
|
|
"num": cty.NumberIntVal(2),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-11 01:17:29 +01:00
|
|
|
// GH-8695. This tests that you can index into a computed list on a
|
|
|
|
// splatted resource.
|
|
|
|
func TestContext2Plan_computedMultiIndex(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-multi-index")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-11-19 22:59:27 +01:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"compute": {Type: cty.String, Optional: true},
|
|
|
|
"foo": {Type: cty.List(cty.String), Optional: true},
|
|
|
|
"ip": {Type: cty.List(cty.String), Computed: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2018-11-19 22:59:27 +01:00
|
|
|
p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
diff := &InstanceDiff{
|
|
|
|
Attributes: map[string]*ResourceAttrDiff{},
|
|
|
|
}
|
|
|
|
|
|
|
|
compute, _ := c.Raw["compute"].(string)
|
|
|
|
if compute != "" {
|
|
|
|
diff.Attributes[compute] = &ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fooOld := s.Attributes["foo"]
|
|
|
|
fooNew, _ := c.Raw["foo"].(string)
|
|
|
|
fooComputed := false
|
|
|
|
for _, k := range c.ComputedKeys {
|
|
|
|
if k == "foo" {
|
|
|
|
fooComputed = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if fooNew != "" {
|
|
|
|
diff.Attributes["foo"] = &ResourceAttrDiff{
|
|
|
|
Old: fooOld,
|
|
|
|
New: fooNew,
|
|
|
|
NewComputed: fooComputed,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ipOld := s.Attributes["ip"]
|
|
|
|
ipComputed := ipOld == ""
|
|
|
|
diff.Attributes["ip"] = &ResourceAttrDiff{
|
|
|
|
Old: ipOld,
|
|
|
|
New: "",
|
|
|
|
NewComputed: ipComputed,
|
|
|
|
}
|
|
|
|
|
|
|
|
return diff, nil
|
|
|
|
}
|
|
|
|
|
2016-12-11 01:17:29 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-12-11 01:17:29 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-12-11 01:17:29 +01:00
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 3 {
|
|
|
|
t.Fatal("expected 3 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
2018-11-19 22:59:27 +01:00
|
|
|
"ip": cty.UnknownVal(cty.List(cty.String)),
|
2019-01-23 00:38:17 +01:00
|
|
|
"foo": cty.NullVal(cty.List(cty.String)),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
2018-11-19 22:59:27 +01:00
|
|
|
"ip": cty.UnknownVal(cty.List(cty.String)),
|
2019-01-23 00:38:17 +01:00
|
|
|
"foo": cty.NullVal(cty.List(cty.String)),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.bar[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
2018-11-19 22:59:27 +01:00
|
|
|
"ip": cty.UnknownVal(cty.List(cty.String)),
|
2018-09-18 01:25:11 +02:00
|
|
|
"foo": cty.UnknownVal(cty.List(cty.String)),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-12-11 01:17:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_count(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 6 {
|
|
|
|
t.Fatal("expected 6 changes, got", len(plan.Changes.Resources))
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo,foo,foo,foo,foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[3]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[4]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countComputed(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-computed")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("should error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-11 20:02:49 +01:00
|
|
|
func TestContext2Plan_countComputedModule(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-computed-module")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-11-11 20:02:49 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
|
|
|
|
2018-05-24 00:03:01 +02:00
|
|
|
expectedErr := `The "count" value depends on resource attributes`
|
2016-11-11 20:02:49 +01:00
|
|
|
if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) {
|
|
|
|
t.Fatalf("expected err would contain %q\nerr: %s\n",
|
|
|
|
expectedErr, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-28 05:32:55 +01:00
|
|
|
func TestContext2Plan_countModuleStatic(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-module-static")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2017-01-28 05:32:55 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2017-01-28 05:32:55 +01:00
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2017-01-28 05:32:55 +01:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
if len(plan.Changes.Resources) != 3 {
|
|
|
|
t.Fatal("expected 3 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2017-01-28 05:32:55 +01:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-01-28 05:32:55 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "module.child.aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "module.child.aws_instance.foo[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "module.child.aws_instance.foo[2]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2017-01-28 05:32:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-28 05:38:07 +01:00
|
|
|
func TestContext2Plan_countModuleStaticGrandchild(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-module-static-grandchild")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2017-01-28 05:38:07 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2017-01-28 05:38:07 +01:00
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2017-01-28 05:38:07 +01:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
if len(plan.Changes.Resources) != 3 {
|
|
|
|
t.Fatal("expected 3 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2017-01-28 05:38:07 +01:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-01-28 05:38:07 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "module.child.module.child.aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "module.child.module.child.aws_instance.foo[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "module.child.module.child.aws_instance.foo[2]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2017-01-28 05:38:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_countIndex(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-index")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("0"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("1"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-var")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
2018-05-23 18:59:03 +02:00
|
|
|
"instance_count": &InputValue{
|
2018-05-05 04:24:06 +02:00
|
|
|
Value: cty.StringVal("3"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 4 {
|
|
|
|
t.Fatal("expected 4 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
2018-09-18 01:25:11 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo,foo,foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
2018-09-19 00:44:51 +02:00
|
|
|
}), ric.After)
|
2018-09-18 01:25:11 +02:00
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countZero(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-zero")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.DynamicPseudoType, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
|
|
|
|
// This schema contains a DynamicPseudoType, and therefore can't go through any shim functions
|
|
|
|
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
|
|
|
|
resp.PlannedState = req.ProposedNewState
|
|
|
|
resp.PlannedPrivate = req.PriorPrivate
|
|
|
|
return resp
|
|
|
|
}
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-18 01:25:11 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-18 01:25:11 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
res := plan.Changes.Resources[0]
|
2018-09-18 01:25:11 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2018-09-18 01:25:11 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
expected := cty.TupleVal(nil)
|
2018-09-18 01:25:11 +02:00
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
foo := ric.After.GetAttr("foo")
|
|
|
|
|
|
|
|
if !cmp.Equal(expected, foo, valueComparer) {
|
|
|
|
t.Fatal(cmp.Diff(expected, foo, valueComparer))
|
2018-09-19 00:44:51 +02:00
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countOneIndex(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-one-index")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countDecreaseToOne(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-dec")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "foo",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.2": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 4 {
|
|
|
|
t.Fatal("expected 4 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should be unchanged", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("expected resource delete, got %s", res.Action)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("expected resource delete, got %s", res.Action)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedState := `aws_instance.foo.0:
|
|
|
|
ID = bar
|
|
|
|
provider = provider.aws
|
|
|
|
foo = foo
|
|
|
|
type = aws_instance
|
|
|
|
aws_instance.foo.1:
|
|
|
|
ID = bar
|
|
|
|
provider = provider.aws
|
|
|
|
aws_instance.foo.2:
|
|
|
|
ID = bar
|
|
|
|
provider = provider.aws`
|
|
|
|
|
|
|
|
if ctx.State().String() != expectedState {
|
|
|
|
t.Fatalf("epected state:\n%q\n\ngot state:\n%q\n", expectedState, ctx.State().String())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-inc")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "foo",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 4 {
|
|
|
|
t.Fatal("expected 4 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should be unchanged", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_countIncreaseFromOne(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-inc")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "foo",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 4 {
|
|
|
|
t.Fatal("expected 4 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should be unchanged", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://github.com/PeoplePerHour/terraform/pull/11
|
|
|
|
//
|
|
|
|
// This tests a case where both a "resource" and "resource.0" are in
|
|
|
|
// the state file, which apparently is a reasonable backwards compatibility
|
|
|
|
// concern found in the above 3rd party repo.
|
|
|
|
func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-inc")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "foo",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "foo",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 5 {
|
|
|
|
t.Fatal("expected 5 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be removed", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should be unchanged", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-05 01:46:48 +02:00
|
|
|
// A common pattern in TF configs is to have a set of resources with the same
|
|
|
|
// count and to use count.index to create correspondences between them:
|
|
|
|
//
|
|
|
|
// foo_id = "${foo.bar.*.id[count.index]}"
|
|
|
|
//
|
|
|
|
// This test is for the situation where some instances already exist and the
|
|
|
|
// count is increased. In that case, we should see only the create diffs
|
|
|
|
// for the new instances and not any update diffs for the existing ones.
|
|
|
|
func TestContext2Plan_countIncreaseWithSplatReference(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-count-splat-reference")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"name": {Type: cty.String, Optional: true},
|
|
|
|
"foo_name": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-05-05 01:46:48 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2017-05-05 01:46:48 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"name": "foo 0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"name": "foo 1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.bar.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo_name": "foo 0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.bar.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo_name": "foo 1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2017-05-05 01:46:48 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2017-05-05 01:46:48 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2017-05-05 01:46:48 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2017-05-05 01:46:48 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 6 {
|
|
|
|
t.Fatal("expected 6 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2017-05-05 01:46:48 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-05-05 01:46:48 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar[0]", "aws_instance.bar[1]", "aws_instance.foo[0]", "aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should be unchanged", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.bar[2]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"foo_name": cty.StringVal("foo 2"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[2]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource create, got %s", res.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"name": cty.StringVal("foo 2"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2017-05-05 01:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_destroy(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-destroy")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.one": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.two": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
Destroy: true,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.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 23:24:45 +02:00
|
|
|
if len(plan.Changes.Resources) != 2 {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.one", "aws_instance.two":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be removed", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleDestroy(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-destroy")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "child"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
Destroy: true,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.foo", "module.child.aws_instance.foo":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be removed", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GH-1835
|
|
|
|
func TestContext2Plan_moduleDestroyCycle(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-destroy-gh-1835")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "a_module"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.a": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "a",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "b_module"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.b": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "b",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
Destroy: true,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "module.a_module.aws_instance.a", "module.b_module.aws_instance.b":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be removed", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_moduleDestroyMultivar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-destroy-multivar")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{},
|
|
|
|
},
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "child"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
Destroy: true,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "module.child.aws_instance.foo[0]", "module.child.aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be removed", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_pathVar(t *testing.T) {
|
|
|
|
cwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
m := testModule(t, "plan-path-var")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"cwd": {Type: cty.String, Optional: true},
|
|
|
|
"module": {Type: cty.String, Optional: true},
|
|
|
|
"root": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-05 04:24:06 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("err: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"cwd": cty.StringVal(cwd + "/barpath"),
|
|
|
|
"module": cty.StringVal(m.Module.SourceDir + "/foopath"),
|
|
|
|
"root": cty.StringVal(m.Module.SourceDir + "/barpath"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_diffVar(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-diffvar")
|
|
|
|
p := testProvider("aws")
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
2017-04-22 02:40:46 +02:00
|
|
|
Type: "aws_instance",
|
2015-07-10 22:08:49 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"num": "2",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
|
|
|
p.DiffFn = func(
|
|
|
|
info *InstanceInfo,
|
|
|
|
s *InstanceState,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
if s.ID != "bar" {
|
|
|
|
return testDiffFn(info, s, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &InstanceDiff{
|
|
|
|
Attributes: map[string]*ResourceAttrDiff{
|
|
|
|
"num": &ResourceAttrDiff{
|
|
|
|
Old: "2",
|
|
|
|
New: "3",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(3),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Update {
|
|
|
|
t.Fatalf("resource %s should be updated", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("bar"),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
}), ric.Before)
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("bar"),
|
|
|
|
"num": cty.NumberIntVal(3),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_hook(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-good")
|
|
|
|
h := new(MockHook)
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2015-07-10 22:08:49 +02:00
|
|
|
Hooks: []Hook{h},
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if !h.PreDiffCalled {
|
|
|
|
t.Fatal("should be called")
|
|
|
|
}
|
|
|
|
if !h.PostDiffCalled {
|
|
|
|
t.Fatal("should be called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 21:00:09 +01:00
|
|
|
func TestContext2Plan_closeProvider(t *testing.T) {
|
|
|
|
// this fixture only has an aliased provider located in the module, to make
|
|
|
|
// sure that the provier name contains a path more complex than
|
|
|
|
// "provider.aws".
|
|
|
|
m := testModule(t, "plan-close-module-provider")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2018-01-04 21:00:09 +01:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2018-01-04 21:00:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if !p.CloseCalled {
|
|
|
|
t.Fatal("provider not closed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_orphan(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-orphan")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.baz": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.baz":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be removed", i)
|
|
|
|
}
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-14 19:17:42 +01:00
|
|
|
// This tests that configurations with UUIDs don't produce errors.
|
|
|
|
// For shadows, this would produce errors since a UUID changes every time.
|
|
|
|
func TestContext2Plan_shadowUuid(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-shadow-uuid")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-11-14 19:17:42 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-11-14 19:17:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_state(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-good")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
2017-04-22 02:40:46 +02:00
|
|
|
Type: "aws_instance",
|
2015-07-10 22:08:49 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02: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 23:24:45 +02:00
|
|
|
if len(plan.Changes.Resources) < 2 {
|
|
|
|
t.Fatalf("bad: %#v", plan.Changes.Resources)
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("2"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Update {
|
|
|
|
t.Fatalf("resource %s should be updated", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("bar"),
|
|
|
|
"num": cty.NullVal(cty.Number),
|
|
|
|
"type": cty.NullVal(cty.String),
|
|
|
|
}), ric.Before)
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("bar"),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_taint(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-taint")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-07-10 22:08:49 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{"num": "2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.bar": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
2016-04-21 21:59:10 +02:00
|
|
|
ID: "baz",
|
|
|
|
Tainted: true,
|
2015-07-10 22:08:49 +02: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 23:24:45 +02:00
|
|
|
})
|
2015-07-10 22:08:49 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.bar":
|
2018-09-22 02:08:52 +02:00
|
|
|
if res.Action != plans.DeleteThenCreate {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatalf("resource %s should be replaced", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("2"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should not be changed", i)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-22 01:20:32 +02:00
|
|
|
func TestContext2Plan_taintIgnoreChanges(t *testing.T) {
|
2016-10-27 14:44:59 +02:00
|
|
|
m := testModule(t, "plan-taint-ignore-changes")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
2018-09-19 00:44:51 +02:00
|
|
|
"id": {Type: cty.String, Computed: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
"vars": {Type: cty.String, Optional: true},
|
2018-09-19 00:44:51 +02:00
|
|
|
"type": {Type: cty.String, Computed: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-10-27 14:44:59 +02:00
|
|
|
p.ApplyFn = testApplyFn
|
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2016-10-27 14:44:59 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "foo",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"vars": "foo",
|
|
|
|
"type": "aws_instance",
|
|
|
|
},
|
|
|
|
Tainted: 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 23:24:45 +02:00
|
|
|
})
|
2016-10-27 14:44:59 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-10-27 14:44:59 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-10-27 14:44:59 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.foo":
|
2018-09-22 02:08:52 +02:00
|
|
|
if res.Action != plans.DeleteThenCreate {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatalf("resource %s should be replaced", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("foo"),
|
|
|
|
"vars": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.Before)
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"vars": cty.StringVal("foo"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-10-27 14:44:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-06 00:40:35 +01:00
|
|
|
// Fails about 50% of the time before the fix for GH-4982, covers the fix.
|
|
|
|
func TestContext2Plan_taintDestroyInterpolatedCountRace(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-taint-interpolated-count")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2016-02-06 00:40:35 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
2016-04-21 21:59:10 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Tainted: true,
|
2016-02-06 00:40:35 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{ID: "bar"},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.2": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{ID: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2016-02-06 00:40:35 +01:00
|
|
|
|
|
|
|
for i := 0; i < 100; i++ {
|
2018-09-19 00:44:51 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-02-06 00:40:35 +01:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-02-06 00:40:35 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 3 {
|
|
|
|
t.Fatal("expected 3 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2016-02-06 00:40:35 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-02-06 00:40:35 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.foo[0]":
|
2018-09-22 02:08:52 +02:00
|
|
|
if res.Action != plans.DeleteThenCreate {
|
2018-09-19 00:44:51 +02:00
|
|
|
t.Fatalf("resource %s should be replaced", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("bar"),
|
|
|
|
}), ric.Before)
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[1]", "aws_instance.foo[2]":
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should not be changed", i)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-02-06 00:40:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
func TestContext2Plan_targeted(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Resource(
|
|
|
|
addrs.ManagedResourceMode, "aws_instance", "foo",
|
|
|
|
),
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.foo":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", i)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"num": cty.NumberIntVal(2),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2015-11-11 18:35:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-13 05:54:46 +01:00
|
|
|
// Test that targeting a module properly plans any inputs that depend
|
|
|
|
// on another module.
|
|
|
|
func TestContext2Plan_targetedCrossModule(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted-cross-module")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Child("B", addrs.NoKey),
|
|
|
|
},
|
2016-12-13 05:54:46 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-12-13 05:54:46 +01:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-12-13 05:54:46 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2016-12-13 05:54:46 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", ric.Addr)
|
|
|
|
}
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "module.A.aws_instance.foo":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
case "module.B.aws_instance.bar":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-12-13 05:54:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-17 18:21:29 +01:00
|
|
|
func TestContext2Plan_targetedModuleWithProvider(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted-module-with-provider")
|
|
|
|
p := testProvider("null")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
Provider: &configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"key": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"null_resource": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-02-17 18:21:29 +01:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2017-02-17 18:21:29 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"null": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Child("child2", addrs.NoKey),
|
|
|
|
},
|
2017-02-17 18:21:29 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2017-02-17 18:21:29 +01:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["null_resource"]
|
|
|
|
ty := schema.ImpliedType()
|
2017-02-17 18:21:29 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2017-02-17 18:21:29 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
res := plan.Changes.Resources[0]
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-02-17 18:21:29 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if ric.Addr.String() != "module.child2.null_resource.foo" {
|
|
|
|
t.Fatalf("unexpcetd resource: %s", ric.Addr)
|
2017-02-17 18:21:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-11 18:35:35 +01:00
|
|
|
func TestContext2Plan_targetedOrphan(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted-orphan")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2015-11-11 18:35:35 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.orphan": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-789xyz",
|
|
|
|
},
|
|
|
|
},
|
2016-01-07 21:43:43 +01:00
|
|
|
"aws_instance.nottargeted": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
|
|
|
},
|
2015-11-11 18:35:35 +01: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 23:24:45 +02:00
|
|
|
}),
|
2015-11-11 18:35:35 +01:00
|
|
|
Destroy: true,
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Resource(
|
|
|
|
addrs.ManagedResourceMode, "aws_instance", "orphan",
|
|
|
|
),
|
|
|
|
},
|
2015-11-11 18:35:35 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-11-11 18:35:35 +01:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2015-11-11 18:35:35 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2015-11-11 18:35:35 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-11-11 18:35:35 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.orphan":
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be destroyed", ric.Addr)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-01-07 21:43:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://github.com/hashicorp/terraform/issues/2538
|
|
|
|
func TestContext2Plan_targetedModuleOrphan(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted-module-orphan")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2016-01-07 21:43:43 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: []string{"root", "child"},
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.orphan": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-789xyz",
|
|
|
|
},
|
2018-09-19 00:44:51 +02:00
|
|
|
Provider: "provider.aws",
|
2016-01-07 21:43:43 +01:00
|
|
|
},
|
|
|
|
"aws_instance.nottargeted": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "i-abc123",
|
|
|
|
},
|
2018-09-19 00:44:51 +02:00
|
|
|
Provider: "provider.aws",
|
2016-01-07 21:43:43 +01: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 23:24:45 +02:00
|
|
|
}),
|
2016-01-07 21:43:43 +01:00
|
|
|
Destroy: true,
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Child("child", addrs.NoKey).Resource(
|
|
|
|
addrs.ManagedResourceMode, "aws_instance", "orphan",
|
|
|
|
),
|
|
|
|
},
|
2016-01-07 21:43:43 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-01-07 21:43:43 +01:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-01-07 21:43:43 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2016-01-07 21:43:43 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
res := plan.Changes.Resources[0]
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-01-07 21:43:43 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if ric.Addr.String() != "module.child.aws_instance.orphan" {
|
|
|
|
t.Fatalf("unexpected resource :%s", ric.Addr)
|
|
|
|
}
|
|
|
|
if res.Action != plans.Delete {
|
|
|
|
t.Fatalf("resource %s should be deleted", ric.Addr)
|
2016-01-07 21:43:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-29 17:53:13 +02:00
|
|
|
func TestContext2Plan_targetedModuleUntargetedVariable(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted-module-untargeted-variable")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Resource(
|
|
|
|
addrs.ManagedResourceMode, "aws_instance", "blue",
|
|
|
|
),
|
|
|
|
addrs.RootModuleInstance.Child("blue_mod", addrs.NoKey),
|
|
|
|
},
|
2016-07-29 17:53:13 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-07-29 17:53:13 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-07-29 17:53:13 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
2016-07-29 17:53:13 +02:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", ric.Addr)
|
|
|
|
}
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.blue":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
}), ric.After)
|
|
|
|
case "module.blue_mod.aws_instance.mod":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"value": cty.UnknownVal(cty.String),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-07-29 17:53:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-20 01:32:37 +01:00
|
|
|
// ensure that outputs missing references due to targetting are removed from
|
|
|
|
// the graph.
|
|
|
|
func TestContext2Plan_outputContainsTargetedResource(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-untargeted-resource-output")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2018-03-20 01:32:37 +01:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.Child("mod", addrs.NoKey).Resource(
|
|
|
|
addrs.ManagedResourceMode, "aws_instance", "a",
|
|
|
|
),
|
|
|
|
},
|
2018-03-20 01:32:37 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-07 21:43:43 +01:00
|
|
|
// https://github.com/hashicorp/terraform/issues/4515
|
|
|
|
func TestContext2Plan_targetedOverTen(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-targeted-over-ten")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
|
|
|
|
resources := make(map[string]*ResourceState)
|
|
|
|
var expectedState []string
|
|
|
|
for i := 0; i < 13; i++ {
|
|
|
|
key := fmt.Sprintf("aws_instance.foo.%d", i)
|
|
|
|
id := fmt.Sprintf("i-abc%d", i)
|
|
|
|
resources[key] = &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{ID: id},
|
|
|
|
}
|
|
|
|
expectedState = append(expectedState,
|
|
|
|
fmt.Sprintf("%s:\n ID = %s\n", key, id))
|
|
|
|
}
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-10-16 03:07:01 +02:00
|
|
|
State: MustShimLegacyState(&State{
|
2016-01-07 21:43:43 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: resources,
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
}),
|
2018-05-05 04:24:06 +02:00
|
|
|
Targets: []addrs.Targetable{
|
|
|
|
addrs.RootModuleInstance.ResourceInstance(
|
|
|
|
addrs.ManagedResourceMode, "aws_instance", "foo", addrs.IntKey(1),
|
|
|
|
),
|
|
|
|
},
|
2016-01-07 21:43:43 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-01-07 21:43:43 +01:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
2016-01-07 21:43:43 +01:00
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("unexpected action %s for %s", res.Action, ric.Addr)
|
|
|
|
}
|
2015-07-10 22:08:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_provider(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-provider")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
|
|
|
|
var value interface{}
|
|
|
|
p.ConfigureFn = func(c *ResourceConfig) error {
|
|
|
|
value, _ = c.Get("foo")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
|
|
|
"foo": &InputValue{
|
|
|
|
Value: cty.StringVal("bar"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2015-07-10 22:08:49 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
if _, err := ctx.Plan(); err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if value != "bar" {
|
|
|
|
t.Fatalf("bad: %#v", value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_varListErr(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-var-list-err")
|
|
|
|
p := testProvider("aws")
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2015-07-10 22:08:49 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
_, err := ctx.Plan()
|
2016-04-15 21:07:54 +02:00
|
|
|
|
2015-07-10 22:08:49 +02:00
|
|
|
if err == nil {
|
|
|
|
t.Fatal("should error")
|
|
|
|
}
|
|
|
|
}
|
2015-08-09 10:02:28 +02:00
|
|
|
|
|
|
|
func TestContext2Plan_ignoreChanges(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-ignore-changes")
|
|
|
|
p := testProvider("aws")
|
2018-09-19 00:44:51 +02:00
|
|
|
|
2015-08-09 10:02:28 +02:00
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2015-08-09 10:02:28 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
2017-04-22 00:42:23 +02:00
|
|
|
Type: "aws_instance",
|
2015-08-09 10:02:28 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{"ami": "ami-abcd1234"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2015-08-09 10:02:28 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
|
|
|
"foo": &InputValue{
|
|
|
|
Value: cty.StringVal("ami-1234abcd"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2015-08-09 10:02:28 +02:00
|
|
|
},
|
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2015-08-09 10:02:28 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
res := plan.Changes.Resources[0]
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if res.Action != plans.Update {
|
|
|
|
t.Fatalf("resource %s should be updated, got %s", ric.Addr, res.Action)
|
2015-08-09 10:02:28 +02:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:44:51 +02:00
|
|
|
if ric.Addr.String() != "aws_instance.foo" {
|
|
|
|
t.Fatalf("unexpected resource: %s", ric.Addr)
|
2015-08-09 10:02:28 +02:00
|
|
|
}
|
2018-09-19 00:44:51 +02:00
|
|
|
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.StringVal("bar"),
|
|
|
|
"ami": cty.StringVal("ami-abcd1234"),
|
|
|
|
"type": cty.StringVal("aws_instance"),
|
|
|
|
}), ric.After)
|
2015-08-09 10:02:28 +02:00
|
|
|
}
|
2016-07-06 16:11:46 +02:00
|
|
|
|
2016-09-02 15:44:35 +02:00
|
|
|
func TestContext2Plan_ignoreChangesWildcard(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-ignore-changes-wildcard")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2016-09-02 15:44:35 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
2017-04-22 02:40:46 +02:00
|
|
|
Type: "aws_instance",
|
2016-09-02 15:44:35 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
2018-09-20 03:31:59 +02:00
|
|
|
"ami": "ami-abcd1234",
|
|
|
|
"instance": "t2.micro",
|
2016-09-02 15:44:35 +02: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 23:24:45 +02:00
|
|
|
})
|
2016-09-02 15:44:35 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2018-05-05 04:24:06 +02:00
|
|
|
Variables: InputValues{
|
|
|
|
"foo": &InputValue{
|
|
|
|
Value: cty.StringVal("ami-1234abcd"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
|
|
|
"bar": &InputValue{
|
|
|
|
Value: cty.StringVal("t2.small"),
|
|
|
|
SourceType: ValueFromCaller,
|
|
|
|
},
|
2016-09-02 15:44:35 +02:00
|
|
|
},
|
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-09-02 15:44:35 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("unexpected resource diffs in root module: %s", spew.Sdump(plan.Changes.Resources))
|
|
|
|
}
|
2016-09-02 15:44:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-06 16:11:46 +02:00
|
|
|
func TestContext2Plan_moduleMapLiteral(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-map-literal")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"meta": {Type: cty.Map(cty.String), Optional: true},
|
|
|
|
"tags": {Type: cty.Map(cty.String), Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-07-06 16:11:46 +02:00
|
|
|
p.ApplyFn = testApplyFn
|
|
|
|
p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
// Here we verify that both the populated and empty map literals made it
|
|
|
|
// through to the resource attributes
|
|
|
|
val, _ := c.Get("tags")
|
|
|
|
m, ok := val.(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("Tags attr not map: %#v", val)
|
|
|
|
}
|
|
|
|
if m["foo"] != "bar" {
|
|
|
|
t.Fatalf("Bad value in tags attr: %#v", m)
|
|
|
|
}
|
|
|
|
{
|
|
|
|
val, _ := c.Get("meta")
|
|
|
|
m, ok := val.(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("Meta attr not map: %#v", val)
|
|
|
|
}
|
|
|
|
if len(m) != 0 {
|
|
|
|
t.Fatalf("Meta attr not empty: %#v", val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-07-06 16:11:46 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-07-06 16:11:46 +02:00
|
|
|
}
|
|
|
|
}
|
2016-07-07 20:14:33 +02:00
|
|
|
|
|
|
|
func TestContext2Plan_computedValueInMap(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-value-in-map")
|
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"looked_up": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_computed_source": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"computed_read_only": {Type: cty.String, Computed: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-07-07 20:14:33 +02:00
|
|
|
p.DiffFn = func(info *InstanceInfo, state *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
switch info.Type {
|
|
|
|
case "aws_computed_source":
|
|
|
|
return &InstanceDiff{
|
|
|
|
Attributes: map[string]*ResourceAttrDiff{
|
|
|
|
"computed_read_only": &ResourceAttrDiff{
|
|
|
|
NewComputed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return testDiffFn(info, state, c)
|
|
|
|
}
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-07-07 20:14:33 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-07-07 20:14:33 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-07-07 20:14:33 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
2016-07-07 20:14:33 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes[res.Addr.Resource.Resource.Type]
|
|
|
|
|
|
|
|
ric, err := res.Decode(schema.ImpliedType())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", ric.Addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_computed_source.intermediates":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"computed_read_only": cty.UnknownVal(cty.String),
|
|
|
|
}), ric.After)
|
|
|
|
case "module.test_mod.aws_instance.inner2":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"looked_up": cty.UnknownVal(cty.String),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-07-07 20:14:33 +02:00
|
|
|
}
|
|
|
|
}
|
2016-07-13 19:23:56 +02:00
|
|
|
|
|
|
|
func TestContext2Plan_moduleVariableFromSplat(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-module-variable-from-splat")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"thing": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-07-13 19:23:56 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-07-13 19:23:56 +02:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-07-13 19:23:56 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
if len(plan.Changes.Resources) != 4 {
|
|
|
|
t.Fatal("expected 4 changes, got", len(plan.Changes.Resources))
|
2016-07-13 19:23:56 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes[res.Addr.Resource.Resource.Type]
|
|
|
|
|
|
|
|
ric, err := res.Decode(schema.ImpliedType())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created", ric.Addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "module.mod1.aws_instance.test[0]",
|
|
|
|
"module.mod1.aws_instance.test[1]",
|
|
|
|
"module.mod2.aws_instance.test[0]",
|
|
|
|
"module.mod2.aws_instance.test[1]":
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"thing": cty.StringVal("doesnt"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2016-07-13 19:23:56 +02:00
|
|
|
}
|
|
|
|
}
|
2016-11-03 23:31:25 +01:00
|
|
|
|
|
|
|
func TestContext2Plan_createBeforeDestroy_depends_datasource(t *testing.T) {
|
2018-05-25 01:07:15 +02:00
|
|
|
m := testModule(t, "plan-cbd-depends-datasource")
|
2016-11-03 23:31:25 +01:00
|
|
|
p := testProvider("aws")
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
2018-09-20 03:31:59 +02:00
|
|
|
"num": {Type: cty.String, Optional: true},
|
|
|
|
"computed": {Type: cty.String, Optional: true, Computed: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
DataSources: map[string]*configschema.Block{
|
|
|
|
"aws_vpc": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
2018-05-25 01:23:33 +02:00
|
|
|
"id": {Type: cty.String, Computed: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
"foo": {Type: cty.Number, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-09-28 23:54:59 +02:00
|
|
|
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
2018-09-28 03:17:06 +02:00
|
|
|
return providers.PlanResourceChangeResponse{
|
|
|
|
PlannedState: req.ProposedNewState,
|
|
|
|
}
|
|
|
|
}
|
2018-05-23 02:53:56 +02:00
|
|
|
|
2016-11-03 23:31:25 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-11-03 23:31:25 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-11-03 23:31:25 +01:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
var schema *configschema.Block
|
|
|
|
switch res.Addr.Resource.Resource.Mode {
|
|
|
|
case addrs.DataResourceMode:
|
|
|
|
schema = p.GetSchemaReturn.DataSources[res.Addr.Resource.Resource.Type]
|
|
|
|
case addrs.ManagedResourceMode:
|
|
|
|
schema = p.GetSchemaReturn.ResourceTypes[res.Addr.Resource.Resource.Type]
|
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 23:24:45 +02:00
|
|
|
}
|
2018-09-20 03:31:59 +02:00
|
|
|
|
|
|
|
ric, err := res.Decode(schema.ImpliedType())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-28 23:54:59 +02:00
|
|
|
t.Run(ric.Addr.String(), func(t *testing.T) {
|
2018-09-28 03:17:06 +02:00
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "aws_instance.foo[0]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created, got %s", ric.Addr, ric.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"num": cty.StringVal("2"),
|
|
|
|
"computed": cty.UnknownVal(cty.String),
|
|
|
|
}), ric.After)
|
|
|
|
case "aws_instance.foo[1]":
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("resource %s should be created, got %s", ric.Addr, ric.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"num": cty.StringVal("2"),
|
|
|
|
"computed": cty.UnknownVal(cty.String),
|
|
|
|
}), ric.After)
|
|
|
|
case "data.aws_vpc.bar[0]":
|
|
|
|
if res.Action != plans.Read {
|
|
|
|
t.Fatalf("resource %s should be read, got %s", ric.Addr, ric.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("0"),
|
|
|
|
}), ric.After)
|
|
|
|
case "data.aws_vpc.bar[1]":
|
|
|
|
if res.Action != plans.Read {
|
|
|
|
t.Fatalf("resource %s should be read, got %s", ric.Addr, ric.Action)
|
|
|
|
}
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"foo": cty.StringVal("1"),
|
|
|
|
}), ric.After)
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
2018-09-20 03:31:59 +02:00
|
|
|
}
|
2018-09-28 03:17:06 +02:00
|
|
|
})
|
2016-11-03 23:31:25 +01:00
|
|
|
}
|
|
|
|
}
|
2016-12-15 19:22:53 +01:00
|
|
|
|
|
|
|
// interpolated lists need to be stored in the original order.
|
|
|
|
func TestContext2Plan_listOrder(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-list-order")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.ApplyFn = testApplyFn
|
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.List(cty.String), Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2016-12-15 19:22:53 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2016-12-15 19:22:53 +01:00
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2016-12-15 19:22:53 +01: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 23:24:45 +02:00
|
|
|
changes := plan.Changes
|
|
|
|
rDiffA := changes.ResourceInstance(addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "a",
|
|
|
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
|
|
|
|
rDiffB := changes.ResourceInstance(addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "b",
|
|
|
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
|
2016-12-15 19:22:53 +01:00
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
if !cmp.Equal(rDiffA.After, rDiffB.After, valueComparer) {
|
|
|
|
t.Fatal(cmp.Diff(rDiffA.After, rDiffB.After, valueComparer))
|
2016-12-15 19:22:53 +01:00
|
|
|
}
|
|
|
|
}
|
2017-03-20 22:17:14 +01:00
|
|
|
|
|
|
|
// Make sure ignore-changes doesn't interfere with set/list/map diffs.
|
|
|
|
// If a resource was being replaced by a RequiresNew attribute that gets
|
2017-03-20 16:23:31 +01:00
|
|
|
// ignored, we need to filter the diff properly to properly update rather than
|
|
|
|
// replace.
|
2017-03-20 22:17:14 +01:00
|
|
|
func TestContext2Plan_ignoreChangesWithFlatmaps(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-ignore-changes-with-flatmaps")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-05-23 02:53:56 +02:00
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"user_data": {Type: cty.String, Optional: true},
|
|
|
|
"require_new": {Type: cty.String, Optional: true},
|
2018-05-24 21:40:33 +02:00
|
|
|
|
|
|
|
// This test predates the 0.12 work to integrate cty and
|
|
|
|
// HCL, and so it was ported as-is where its expected
|
|
|
|
// test output was clearly expecting a list of maps here
|
|
|
|
// even though it is named "set".
|
|
|
|
"set": {Type: cty.List(cty.Map(cty.String)), Optional: true},
|
|
|
|
"lst": {Type: cty.List(cty.String), Optional: true},
|
2018-05-23 02:53:56 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2017-03-20 22:17:14 +01:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"user_data": "x",
|
|
|
|
"require_new": "",
|
|
|
|
"set.#": "1",
|
2018-09-20 03:31:59 +02:00
|
|
|
"set.0.%": "1",
|
2017-03-20 22:17:14 +01:00
|
|
|
"set.0.a": "1",
|
|
|
|
"lst.#": "1",
|
|
|
|
"lst.0": "j",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2018-09-20 03:31:59 +02:00
|
|
|
|
2017-03-20 22:17:14 +01:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2017-03-20 22:17:14 +01:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
2017-03-20 22:17:14 +01:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
if len(plan.Changes.Resources) != 1 {
|
|
|
|
t.Fatal("expected 1 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
res := plan.Changes.Resources[0]
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes[res.Addr.Resource.Resource.Type]
|
|
|
|
|
|
|
|
ric, err := res.Decode(schema.ImpliedType())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if res.Action != plans.Update {
|
|
|
|
t.Fatalf("resource %s should be updated, got %s", ric.Addr, ric.Action)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ric.Addr.String() != "aws_instance.foo" {
|
|
|
|
t.Fatalf("unknown resource: %s", ric.Addr)
|
2017-03-20 22:17:14 +01:00
|
|
|
}
|
2018-09-20 03:31:59 +02:00
|
|
|
|
|
|
|
checkVals(t, objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"lst": cty.ListVal([]cty.Value{
|
|
|
|
cty.StringVal("j"),
|
|
|
|
cty.StringVal("k"),
|
|
|
|
}),
|
|
|
|
"require_new": cty.StringVal(""),
|
|
|
|
"user_data": cty.StringVal("x"),
|
|
|
|
"set": cty.ListVal([]cty.Value{cty.MapVal(map[string]cty.Value{
|
|
|
|
"a": cty.StringVal("1"),
|
|
|
|
"b": cty.StringVal("2"),
|
|
|
|
})}),
|
|
|
|
}), ric.After)
|
2017-03-20 22:17:14 +01:00
|
|
|
}
|
2017-04-20 07:23:52 +02:00
|
|
|
|
|
|
|
// TestContext2Plan_resourceNestedCount ensures resource sets that depend on
|
|
|
|
// the count of another resource set (ie: count of a data source that depends
|
|
|
|
// on another data source's instance count - data.x.foo.*.id) get properly
|
|
|
|
// normalized to the indexes they should be. This case comes up when there is
|
|
|
|
// an existing state (after an initial apply).
|
|
|
|
func TestContext2Plan_resourceNestedCount(t *testing.T) {
|
|
|
|
m := testModule(t, "nested-resource-count-plan")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-09-05 23:35:30 +02:00
|
|
|
p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
|
|
|
|
return providers.ReadResourceResponse{
|
|
|
|
NewState: req.PriorState,
|
|
|
|
}
|
2017-04-20 07:23:52 +02:00
|
|
|
}
|
2018-10-16 03:07:01 +02:00
|
|
|
s := MustShimLegacyState(&State{
|
2017-04-20 07:23:52 +02:00
|
|
|
Modules: []*ModuleState{
|
|
|
|
&ModuleState{
|
|
|
|
Path: rootModulePath,
|
|
|
|
Resources: map[string]*ResourceState{
|
|
|
|
"aws_instance.foo.0": &ResourceState{
|
2018-05-21 20:32:43 +02:00
|
|
|
Type: "aws_instance",
|
|
|
|
Provider: "provider.aws",
|
2017-04-20 07:23:52 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "foo0",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "foo0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.foo.1": &ResourceState{
|
2018-05-21 20:32:43 +02:00
|
|
|
Type: "aws_instance",
|
|
|
|
Provider: "provider.aws",
|
2017-04-20 07:23:52 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "foo1",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "foo1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.bar.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
2018-05-21 20:32:43 +02:00
|
|
|
Provider: "provider.aws",
|
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 23:24:45 +02:00
|
|
|
Dependencies: []string{"aws_instance.foo"},
|
2017-04-20 07:23:52 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar0",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "bar0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.bar.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
2018-05-21 20:32:43 +02:00
|
|
|
Provider: "provider.aws",
|
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 23:24:45 +02:00
|
|
|
Dependencies: []string{"aws_instance.foo"},
|
2017-04-20 07:23:52 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "bar1",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "bar1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.baz.0": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
2018-05-21 20:32:43 +02:00
|
|
|
Provider: "provider.aws",
|
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 23:24:45 +02:00
|
|
|
Dependencies: []string{"aws_instance.bar"},
|
2017-04-20 07:23:52 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz0",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "baz0",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"aws_instance.baz.1": &ResourceState{
|
|
|
|
Type: "aws_instance",
|
2018-05-21 20:32:43 +02:00
|
|
|
Provider: "provider.aws",
|
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 23:24:45 +02:00
|
|
|
Dependencies: []string{"aws_instance.bar"},
|
2017-04-20 07:23:52 +02:00
|
|
|
Primary: &InstanceState{
|
|
|
|
ID: "baz1",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"id": "baz1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
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 23:24:45 +02:00
|
|
|
})
|
2017-04-20 07:23:52 +02:00
|
|
|
ctx := testContext2(t, &ContextOpts{
|
2018-05-05 04:24:06 +02:00
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2017-04-22 02:40:46 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
2017-04-20 07:23:52 +02:00
|
|
|
State: s,
|
|
|
|
})
|
|
|
|
|
2017-11-22 00:08:00 +01:00
|
|
|
diags := ctx.Validate()
|
2018-05-21 20:32:43 +02:00
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("validate errors: %s", diags.Err())
|
2017-04-20 07:23:52 +02:00
|
|
|
}
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
_, diags = ctx.Refresh()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("refresh errors: %s", diags.Err())
|
2017-04-20 07:23:52 +02:00
|
|
|
}
|
|
|
|
|
2018-05-21 20:32:43 +02:00
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("plan errors: %s", diags.Err())
|
2017-04-20 07:23:52 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 03:31:59 +02:00
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
if res.Action != plans.NoOp {
|
|
|
|
t.Fatalf("resource %s should now change, plan returned %s", res.Addr, res.Action)
|
|
|
|
}
|
2017-04-20 07:23:52 +02:00
|
|
|
}
|
|
|
|
}
|
2018-05-25 22:12:07 +02:00
|
|
|
|
|
|
|
// Higher level test at TestResource_dataSourceListApplyPanic
|
|
|
|
func TestContext2Plan_computedAttrRefTypeMismatch(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-computed-attr-ref-type-mismatch")
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.DiffFn = testDiffFn
|
2018-09-15 00:40:09 +02:00
|
|
|
p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
|
2018-09-05 23:35:30 +02:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
if req.TypeName == "aws_instance" {
|
|
|
|
amiVal := req.Config.GetAttr("ami")
|
|
|
|
if amiVal.Type() != cty.String {
|
|
|
|
diags = diags.Append(fmt.Errorf("Expected ami to be cty.String, got %#v", amiVal))
|
2018-05-25 22:12:07 +02:00
|
|
|
}
|
|
|
|
}
|
2018-09-05 23:35:30 +02:00
|
|
|
return providers.ValidateResourceTypeConfigResponse{
|
|
|
|
Diagnostics: diags,
|
|
|
|
}
|
2018-05-25 22:12:07 +02:00
|
|
|
}
|
|
|
|
p.DiffFn = func(
|
|
|
|
info *InstanceInfo,
|
|
|
|
state *InstanceState,
|
|
|
|
c *ResourceConfig) (*InstanceDiff, error) {
|
|
|
|
switch info.Type {
|
|
|
|
case "aws_ami_list":
|
|
|
|
// Emulate a diff that says "we'll create this list and ids will be populated"
|
|
|
|
return &InstanceDiff{
|
|
|
|
Attributes: map[string]*ResourceAttrDiff{
|
|
|
|
"ids.#": &ResourceAttrDiff{NewComputed: true},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
case "aws_instance":
|
|
|
|
// If we get to the diff for instance, we should be able to assume types
|
|
|
|
ami, _ := c.Get("ami")
|
|
|
|
_ = ami.(string)
|
|
|
|
}
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
|
|
|
|
if info.Type != "aws_ami_list" {
|
|
|
|
t.Fatalf("Reached apply for unexpected resource type! %s", info.Type)
|
|
|
|
}
|
|
|
|
// Pretend like we make a thing and the computed list "ids" is populated
|
|
|
|
return &InstanceState{
|
|
|
|
ID: "someid",
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"ids.#": "2",
|
|
|
|
"ids.0": "ami-abc123",
|
|
|
|
"ids.1": "ami-bcd345",
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2018-05-25 22:12:07 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("Succeeded; want type mismatch error for 'ami' argument")
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := `Inappropriate value for attribute "ami"`
|
|
|
|
if errStr := diags.Err().Error(); !strings.Contains(errStr, expected) {
|
|
|
|
t.Fatalf("expected:\n\n%s\n\nto contain:\n\n%s", errStr, expected)
|
|
|
|
}
|
|
|
|
}
|
2018-06-23 01:54:27 +02:00
|
|
|
|
|
|
|
func TestContext2Plan_selfRef(t *testing.T) {
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
m := testModule(t, "plan-self-ref")
|
|
|
|
c := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2018-06-23 01:54:27 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
diags := c.Validate()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected validation failure: %s", diags.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
_, diags = c.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("plan succeeded; want error")
|
|
|
|
}
|
|
|
|
|
|
|
|
gotErrStr := diags.Err().Error()
|
|
|
|
wantErrStr := "Self-referential block"
|
|
|
|
if !strings.Contains(gotErrStr, wantErrStr) {
|
|
|
|
t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_selfRefMulti(t *testing.T) {
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.String, Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
m := testModule(t, "plan-self-ref-multi")
|
|
|
|
c := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2018-06-23 01:54:27 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
diags := c.Validate()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected validation failure: %s", diags.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
_, diags = c.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("plan succeeded; want error")
|
|
|
|
}
|
|
|
|
|
|
|
|
gotErrStr := diags.Err().Error()
|
|
|
|
wantErrStr := "Self-referential block"
|
|
|
|
if !strings.Contains(gotErrStr, wantErrStr) {
|
|
|
|
t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_selfRefMultiAll(t *testing.T) {
|
|
|
|
p := testProvider("aws")
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"aws_instance": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"foo": {Type: cty.List(cty.String), Optional: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
m := testModule(t, "plan-self-ref-multi-all")
|
|
|
|
c := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
2018-08-17 21:32:35 +02:00
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
2018-06-23 01:54:27 +02:00
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
diags := c.Validate()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected validation failure: %s", diags.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
_, diags = c.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
t.Fatalf("plan succeeded; want error")
|
|
|
|
}
|
|
|
|
|
|
|
|
gotErrStr := diags.Err().Error()
|
2018-09-20 03:31:59 +02:00
|
|
|
|
|
|
|
// The graph is checked for cycles before we can walk it, so we don't
|
|
|
|
// encounter the self-reference check.
|
|
|
|
//wantErrStr := "Self-referential block"
|
|
|
|
wantErrStr := "Cycle"
|
2018-06-23 01:54:27 +02:00
|
|
|
if !strings.Contains(gotErrStr, wantErrStr) {
|
|
|
|
t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr)
|
|
|
|
}
|
|
|
|
}
|
2018-09-15 00:40:09 +02:00
|
|
|
|
2018-09-24 21:14:32 +02:00
|
|
|
func TestContext2Plan_invalidOutput(t *testing.T) {
|
|
|
|
m := testModuleInline(t, map[string]string{
|
|
|
|
"main.tf": `
|
|
|
|
data "aws_data_source" "name" {}
|
|
|
|
|
|
|
|
output "out" {
|
|
|
|
value = "${data.aws_data_source.name.missing}"
|
|
|
|
}`,
|
|
|
|
})
|
|
|
|
|
|
|
|
p := testProvider("aws")
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
// Should get this error:
|
|
|
|
// Unsupported attribute: This object does not have an attribute named "missing"
|
|
|
|
t.Fatal("succeeded; want errors")
|
|
|
|
}
|
|
|
|
|
|
|
|
gotErrStr := diags.Err().Error()
|
|
|
|
wantErrStr := "Unsupported attribute"
|
|
|
|
if !strings.Contains(gotErrStr, wantErrStr) {
|
|
|
|
t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_invalidModuleOutput(t *testing.T) {
|
|
|
|
m := testModuleInline(t, map[string]string{
|
|
|
|
"child/main.tf": `
|
|
|
|
data "aws_data_source" "name" {}
|
|
|
|
|
|
|
|
output "out" {
|
|
|
|
value = "${data.aws_data_source.name.missing}"
|
|
|
|
}`,
|
|
|
|
"main.tf": `
|
|
|
|
module "child" {
|
|
|
|
source = "./child"
|
|
|
|
}
|
|
|
|
|
|
|
|
resource "aws_instance" "foo" {
|
|
|
|
foo = "${module.child.out}"
|
|
|
|
}`,
|
|
|
|
})
|
|
|
|
|
|
|
|
p := testProvider("aws")
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"aws": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
_, diags := ctx.Plan()
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
// Should get this error:
|
|
|
|
// Unsupported attribute: This object does not have an attribute named "missing"
|
|
|
|
t.Fatal("succeeded; want errors")
|
|
|
|
}
|
|
|
|
|
|
|
|
gotErrStr := diags.Err().Error()
|
|
|
|
wantErrStr := "Unsupported attribute"
|
|
|
|
if !strings.Contains(gotErrStr, wantErrStr) {
|
|
|
|
t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-15 00:40:09 +02:00
|
|
|
func checkVals(t *testing.T, expected, got cty.Value) {
|
|
|
|
t.Helper()
|
|
|
|
if !cmp.Equal(expected, got, valueComparer, typeComparer, equateEmpty) {
|
|
|
|
t.Fatal(cmp.Diff(expected, got, valueTrans, equateEmpty))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func objectVal(t *testing.T, schema *configschema.Block, m map[string]cty.Value) cty.Value {
|
|
|
|
t.Helper()
|
|
|
|
v, err := schema.CoerceValue(
|
|
|
|
cty.ObjectVal(m),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
2018-10-31 21:41:36 +01:00
|
|
|
|
|
|
|
func TestContext2Plan_requiredModuleOutput(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-required-output")
|
|
|
|
p := testProvider("test")
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"test_resource": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {Type: cty.String, Computed: true},
|
|
|
|
"required": {Type: cty.String, Required: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"test": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["test_resource"]
|
2018-11-02 01:41:35 +01:00
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
|
|
|
t.Run(fmt.Sprintf("%s %s", res.Action, res.Addr), func(t *testing.T) {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var expected cty.Value
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "test_resource.root":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"required": cty.UnknownVal(cty.String),
|
|
|
|
})
|
|
|
|
case "module.mod.test_resource.for_output":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"required": cty.StringVal("val"),
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
checkVals(t, expected, ric.After)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestContext2Plan_requiredModuleObject(t *testing.T) {
|
|
|
|
m := testModule(t, "plan-required-whole-mod")
|
|
|
|
p := testProvider("test")
|
|
|
|
p.GetSchemaReturn = &ProviderSchema{
|
|
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
|
|
"test_resource": {
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"id": {Type: cty.String, Computed: true},
|
|
|
|
"required": {Type: cty.String, Required: true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
p.DiffFn = testDiffFn
|
|
|
|
|
|
|
|
ctx := testContext2(t, &ContextOpts{
|
|
|
|
Config: m,
|
|
|
|
ProviderResolver: providers.ResolverFixed(
|
|
|
|
map[string]providers.Factory{
|
|
|
|
"test": testProviderFuncFixed(p),
|
|
|
|
},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
|
|
|
|
plan, diags := ctx.Plan()
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
|
|
|
}
|
|
|
|
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes["test_resource"]
|
2018-10-31 21:41:36 +01:00
|
|
|
ty := schema.ImpliedType()
|
|
|
|
|
|
|
|
if len(plan.Changes.Resources) != 2 {
|
|
|
|
t.Fatal("expected 2 changes, got", len(plan.Changes.Resources))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, res := range plan.Changes.Resources {
|
2018-11-02 01:32:30 +01:00
|
|
|
t.Run(fmt.Sprintf("%s %s", res.Action, res.Addr), func(t *testing.T) {
|
|
|
|
if res.Action != plans.Create {
|
|
|
|
t.Fatalf("expected resource creation, got %s", res.Action)
|
|
|
|
}
|
|
|
|
ric, err := res.Decode(ty)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2018-10-31 21:41:36 +01:00
|
|
|
|
2018-11-02 01:32:30 +01:00
|
|
|
var expected cty.Value
|
|
|
|
switch i := ric.Addr.String(); i {
|
|
|
|
case "test_resource.root":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"required": cty.UnknownVal(cty.String),
|
|
|
|
})
|
|
|
|
case "module.mod.test_resource.for_output":
|
|
|
|
expected = objectVal(t, schema, map[string]cty.Value{
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
"required": cty.StringVal("val"),
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
t.Fatal("unknown instance:", i)
|
|
|
|
}
|
2018-10-31 21:41:36 +01:00
|
|
|
|
2018-11-02 01:32:30 +01:00
|
|
|
checkVals(t, expected, ric.After)
|
|
|
|
})
|
2018-10-31 21:41:36 +01:00
|
|
|
}
|
|
|
|
}
|