Merge pull request #24461 from hashicorp/jbardin/eval-context-path
Module Expansion Activate!
This commit is contained in:
commit
34cab3bc99
|
@ -213,7 +213,7 @@ func TestApply_destroyTargeted(t *testing.T) {
|
||||||
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
|
|
|
@ -268,7 +268,7 @@ func testState() *states.State {
|
||||||
// of all of the containing wrapping objects and arrays.
|
// of all of the containing wrapping objects and arrays.
|
||||||
AttrsJSON: []byte("{\n \"id\": \"bar\"\n }"),
|
AttrsJSON: []byte("{\n \"id\": \"bar\"\n }"),
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
DependsOn: []addrs.Referenceable{},
|
DependsOn: []addrs.Referenceable{},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
|
@ -881,10 +881,10 @@ func normalizeJSON(t *testing.T, src []byte) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustResourceAddr(s string) addrs.AbsResource {
|
func mustResourceAddr(s string) addrs.ConfigResource {
|
||||||
addr, diags := addrs.ParseAbsResourceStr(s)
|
addr, diags := addrs.ParseAbsResourceStr(s)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
panic(diags.Err())
|
panic(diags.Err())
|
||||||
}
|
}
|
||||||
return addr
|
return addr.Config()
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,7 +277,7 @@ func TestRefresh_defaultState(t *testing.T) {
|
||||||
expected := &states.ResourceInstanceObjectSrc{
|
expected := &states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"yes\"\n }"),
|
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"yes\"\n }"),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
DependsOn: []addrs.Referenceable{},
|
DependsOn: []addrs.Referenceable{},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
@ -342,7 +342,7 @@ func TestRefresh_outPath(t *testing.T) {
|
||||||
expected := &states.ResourceInstanceObjectSrc{
|
expected := &states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"yes\"\n }"),
|
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"yes\"\n }"),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
DependsOn: []addrs.Referenceable{},
|
DependsOn: []addrs.Referenceable{},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
@ -572,7 +572,7 @@ func TestRefresh_backup(t *testing.T) {
|
||||||
expected := &states.ResourceInstanceObjectSrc{
|
expected := &states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"changed\"\n }"),
|
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"changed\"\n }"),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
DependsOn: []addrs.Referenceable{},
|
DependsOn: []addrs.Referenceable{},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
@ -639,7 +639,7 @@ func TestRefresh_disableBackup(t *testing.T) {
|
||||||
expected := &states.ResourceInstanceObjectSrc{
|
expected := &states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"yes\"\n }"),
|
AttrsJSON: []byte("{\n \"ami\": null,\n \"id\": \"yes\"\n }"),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
DependsOn: []addrs.Referenceable{},
|
DependsOn: []addrs.Referenceable{},
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actual, expected) {
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
|
|
@ -82,7 +82,7 @@ func TestShow_aliasedProvider(t *testing.T) {
|
||||||
// of all of the containing wrapping objects and arrays.
|
// of all of the containing wrapping objects and arrays.
|
||||||
AttrsJSON: []byte("{\n \"id\": \"bar\"\n }"),
|
AttrsJSON: []byte("{\n \"id\": \"bar\"\n }"),
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
DependsOn: []addrs.Referenceable{},
|
DependsOn: []addrs.Referenceable{},
|
||||||
},
|
},
|
||||||
addrs.RootModuleInstance.ProviderConfigAliased(addrs.NewLegacyProvider("test"), "alias"),
|
addrs.RootModuleInstance.ProviderConfigAliased(addrs.NewLegacyProvider("test"), "alias"),
|
||||||
|
|
|
@ -41,7 +41,7 @@ func TestStateMv(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("test"),
|
Provider: addrs.NewLegacyProvider("test"),
|
||||||
|
@ -172,7 +172,7 @@ func TestStateMv_resourceToInstance(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("test"),
|
Provider: addrs.NewLegacyProvider("test"),
|
||||||
|
@ -549,7 +549,7 @@ func TestStateMv_backupExplicit(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("test"),
|
Provider: addrs.NewLegacyProvider("test"),
|
||||||
|
@ -1068,7 +1068,7 @@ func TestStateMv_withinBackend(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_instance.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_instance.foo")},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("test"),
|
Provider: addrs.NewLegacyProvider("test"),
|
||||||
|
|
|
@ -68,26 +68,10 @@ func decodeModuleBlock(block *hcl.Block, override bool) (*ModuleCall, hcl.Diagno
|
||||||
|
|
||||||
if attr, exists := content.Attributes["count"]; exists {
|
if attr, exists := content.Attributes["count"]; exists {
|
||||||
mc.Count = attr.Expr
|
mc.Count = attr.Expr
|
||||||
|
|
||||||
// We currently parse this, but don't yet do anything with it.
|
|
||||||
diags = append(diags, &hcl.Diagnostic{
|
|
||||||
Severity: hcl.DiagError,
|
|
||||||
Summary: "Reserved argument name in module block",
|
|
||||||
Detail: fmt.Sprintf("The name %q is reserved for use in a future version of Terraform.", attr.Name),
|
|
||||||
Subject: &attr.NameRange,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if attr, exists := content.Attributes["for_each"]; exists {
|
if attr, exists := content.Attributes["for_each"]; exists {
|
||||||
mc.ForEach = attr.Expr
|
mc.ForEach = attr.Expr
|
||||||
|
|
||||||
// We currently parse this, but don't yet do anything with it.
|
|
||||||
diags = append(diags, &hcl.Diagnostic{
|
|
||||||
Severity: hcl.DiagError,
|
|
||||||
Summary: "Reserved argument name in module block",
|
|
||||||
Detail: fmt.Sprintf("The name %q is reserved for use in a future version of Terraform.", attr.Name),
|
|
||||||
Subject: &attr.NameRange,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if attr, exists := content.Attributes["depends_on"]; exists {
|
if attr, exists := content.Attributes["depends_on"]; exists {
|
||||||
|
|
|
@ -20,8 +20,6 @@ func TestLoadModuleCall(t *testing.T) {
|
||||||
|
|
||||||
file, diags := parser.LoadConfigFile("module-calls.tf")
|
file, diags := parser.LoadConfigFile("module-calls.tf")
|
||||||
assertExactDiagnostics(t, diags, []string{
|
assertExactDiagnostics(t, diags, []string{
|
||||||
`module-calls.tf:19,3-8: Reserved argument name in module block; The name "count" is reserved for use in a future version of Terraform.`,
|
|
||||||
`module-calls.tf:20,3-11: Reserved argument name in module block; The name "for_each" is reserved for use in a future version of Terraform.`,
|
|
||||||
`module-calls.tf:22,3-13: Reserved argument name in module block; The name "depends_on" is reserved for use in a future version of Terraform.`,
|
`module-calls.tf:22,3-13: Reserved argument name in module block; The name "depends_on" is reserved for use in a future version of Terraform.`,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ type ResourceInstanceObject struct {
|
||||||
// the dependency relationships for an object whose configuration is no
|
// the dependency relationships for an object whose configuration is no
|
||||||
// longer available, such as if it has been removed from configuration
|
// longer available, such as if it has been removed from configuration
|
||||||
// altogether, or is now deposed.
|
// altogether, or is now deposed.
|
||||||
Dependencies []addrs.AbsResource
|
Dependencies []addrs.ConfigResource
|
||||||
|
|
||||||
// CreateBeforeDestroy reflects the status of the lifecycle
|
// CreateBeforeDestroy reflects the status of the lifecycle
|
||||||
// create_before_destroy option when this instance was last updated.
|
// create_before_destroy option when this instance was last updated.
|
||||||
|
|
|
@ -53,7 +53,7 @@ type ResourceInstanceObjectSrc struct {
|
||||||
// ResourceInstanceObject.
|
// ResourceInstanceObject.
|
||||||
Private []byte
|
Private []byte
|
||||||
Status ObjectStatus
|
Status ObjectStatus
|
||||||
Dependencies []addrs.AbsResource
|
Dependencies []addrs.ConfigResource
|
||||||
CreateBeforeDestroy bool
|
CreateBeforeDestroy bool
|
||||||
// deprecated
|
// deprecated
|
||||||
DependsOn []addrs.Referenceable
|
DependsOn []addrs.Referenceable
|
||||||
|
|
|
@ -153,9 +153,9 @@ func (obj *ResourceInstanceObjectSrc) DeepCopy() *ResourceInstanceObjectSrc {
|
||||||
|
|
||||||
// Some addrs.Referencable implementations are technically mutable, but
|
// Some addrs.Referencable implementations are technically mutable, but
|
||||||
// we treat them as immutable by convention and so we don't deep-copy here.
|
// we treat them as immutable by convention and so we don't deep-copy here.
|
||||||
var dependencies []addrs.AbsResource
|
var dependencies []addrs.ConfigResource
|
||||||
if obj.Dependencies != nil {
|
if obj.Dependencies != nil {
|
||||||
dependencies = make([]addrs.AbsResource, len(obj.Dependencies))
|
dependencies = make([]addrs.ConfigResource, len(obj.Dependencies))
|
||||||
copy(dependencies, obj.Dependencies)
|
copy(dependencies, obj.Dependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,9 +198,9 @@ func (obj *ResourceInstanceObject) DeepCopy() *ResourceInstanceObject {
|
||||||
|
|
||||||
// Some addrs.Referenceable implementations are technically mutable, but
|
// Some addrs.Referenceable implementations are technically mutable, but
|
||||||
// we treat them as immutable by convention and so we don't deep-copy here.
|
// we treat them as immutable by convention and so we don't deep-copy here.
|
||||||
var dependencies []addrs.AbsResource
|
var dependencies []addrs.ConfigResource
|
||||||
if obj.Dependencies != nil {
|
if obj.Dependencies != nil {
|
||||||
dependencies = make([]addrs.AbsResource, len(obj.Dependencies))
|
dependencies = make([]addrs.ConfigResource, len(obj.Dependencies))
|
||||||
copy(dependencies, obj.Dependencies)
|
copy(dependencies, obj.Dependencies)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ func TestStateDeepCopy(t *testing.T) {
|
||||||
SchemaVersion: 1,
|
SchemaVersion: 1,
|
||||||
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
|
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
|
||||||
Private: []byte("private data"),
|
Private: []byte("private data"),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewDefaultProvider("test"),
|
Provider: addrs.NewDefaultProvider("test"),
|
||||||
|
@ -159,9 +159,9 @@ func TestStateDeepCopy(t *testing.T) {
|
||||||
SchemaVersion: 1,
|
SchemaVersion: 1,
|
||||||
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
|
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
|
||||||
Private: []byte("private data"),
|
Private: []byte("private data"),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
{
|
{
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_thing",
|
Type: "test_thing",
|
||||||
|
|
|
@ -218,14 +218,14 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||||
|
|
||||||
{
|
{
|
||||||
depsRaw := isV4.Dependencies
|
depsRaw := isV4.Dependencies
|
||||||
deps := make([]addrs.AbsResource, 0, len(depsRaw))
|
deps := make([]addrs.ConfigResource, 0, len(depsRaw))
|
||||||
for _, depRaw := range depsRaw {
|
for _, depRaw := range depsRaw {
|
||||||
addr, addrDiags := addrs.ParseAbsResourceStr(depRaw)
|
addr, addrDiags := addrs.ParseAbsResourceStr(depRaw)
|
||||||
diags = diags.Append(addrDiags)
|
diags = diags.Append(addrDiags)
|
||||||
if addrDiags.HasErrors() {
|
if addrDiags.HasErrors() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
deps = append(deps, addr)
|
deps = append(deps, addr.Config())
|
||||||
}
|
}
|
||||||
obj.Dependencies = deps
|
obj.Dependencies = deps
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,7 +298,7 @@ func TestContext2Apply_resourceDependsOnModuleStateOnly(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"parent"}`),
|
AttrsJSON: []byte(`{"id":"parent"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("module.child.aws_instance.child")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("module.child.aws_instance.child")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
||||||
)
|
)
|
||||||
|
@ -1273,7 +1273,7 @@ func testContext2Apply_destroyDependsOn(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("aws_instance.bar")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("aws_instance.bar")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
||||||
)
|
)
|
||||||
|
@ -1329,7 +1329,7 @@ func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("aws"),
|
Provider: addrs.NewLegacyProvider("aws"),
|
||||||
|
@ -1345,14 +1345,14 @@ func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "aws_instance",
|
Type: "aws_instance",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
},
|
},
|
||||||
Module: root.Addr,
|
Module: root.Addr.Module(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1427,7 +1427,7 @@ func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||||
Dependencies: []addrs.AbsResource{},
|
Dependencies: []addrs.ConfigResource{},
|
||||||
},
|
},
|
||||||
addrs.AbsProviderConfig{
|
addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("aws"),
|
Provider: addrs.NewLegacyProvider("aws"),
|
||||||
|
@ -1443,14 +1443,14 @@ func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "aws_instance",
|
Type: "aws_instance",
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
},
|
},
|
||||||
Module: child.Addr,
|
Module: child.Addr.Module(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2708,7 +2708,7 @@ func TestContext2Apply_moduleDestroyOrder(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"b"}`),
|
AttrsJSON: []byte(`{"id":"b"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("module.child.aws_instance.a")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("module.child.aws_instance.a")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
||||||
)
|
)
|
||||||
|
@ -3170,8 +3170,8 @@ func TestContext2Apply_moduleProviderAliasTargets(t *testing.T) {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Targets: []addrs.Targetable{
|
Targets: []addrs.Targetable{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "nonexistent",
|
Type: "nonexistent",
|
||||||
|
@ -8025,7 +8025,7 @@ func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
AttrsJSON: []byte(`{"id":"i-abc123"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("aws_instance.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("aws_instance.foo")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/aws"]`),
|
||||||
)
|
)
|
||||||
|
@ -8631,14 +8631,14 @@ func TestContext2Apply_createBefore_depends(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"baz","instance":"bar"}`),
|
AttrsJSON: []byte(`{"id":"baz","instance":"bar"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "aws_instance",
|
Type: "aws_instance",
|
||||||
Name: "web",
|
Name: "web",
|
||||||
},
|
},
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -8764,14 +8764,14 @@ func TestContext2Apply_singleDestroy(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"baz","instance":"bar"}`),
|
AttrsJSON: []byte(`{"id":"baz","instance":"bar"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "aws_instance",
|
Type: "aws_instance",
|
||||||
Name: "web",
|
Name: "web",
|
||||||
},
|
},
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -10639,22 +10639,22 @@ func TestContext2Apply_cbdCycle(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"a","require_new":"old","foo":"b"}`),
|
AttrsJSON: []byte(`{"id":"a","require_new":"old","foo":"b"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_instance",
|
Type: "test_instance",
|
||||||
Name: "b",
|
Name: "b",
|
||||||
},
|
},
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_instance",
|
Type: "test_instance",
|
||||||
Name: "c",
|
Name: "c",
|
||||||
},
|
},
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -10672,14 +10672,14 @@ func TestContext2Apply_cbdCycle(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"b","require_new":"old","foo":"c"}`),
|
AttrsJSON: []byte(`{"id":"b","require_new":"old","foo":"c"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_instance",
|
Type: "test_instance",
|
||||||
Name: "c",
|
Name: "c",
|
||||||
},
|
},
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -429,12 +429,9 @@ func TestContext2Plan_modules(t *testing.T) {
|
||||||
checkVals(t, expected, ric.After)
|
checkVals(t, expected, ric.After)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestContext2Plan_moduleCount(t *testing.T) {
|
func TestContext2Plan_moduleExpand(t *testing.T) {
|
||||||
// This test is skipped with count disabled.
|
// Test a smattering of plan expansion behavior
|
||||||
t.Skip()
|
m := testModule(t, "plan-modules-expand")
|
||||||
//FIXME: add for_each and single modules to this test
|
|
||||||
|
|
||||||
m := testModule(t, "plan-modules-count")
|
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
p.DiffFn = testDiffFn
|
p.DiffFn = testDiffFn
|
||||||
ctx := testContext2(t, &ContextOpts{
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
@ -451,31 +448,18 @@ func TestContext2Plan_moduleCount(t *testing.T) {
|
||||||
t.Fatalf("unexpected errors: %s", diags.Err())
|
t.Fatalf("unexpected errors: %s", diags.Err())
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(plan.Changes.Resources) != 6 {
|
|
||||||
t.Error("expected 6 resource in plan, got", len(plan.Changes.Resources))
|
|
||||||
}
|
|
||||||
|
|
||||||
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
|
||||||
ty := schema.ImpliedType()
|
ty := schema.ImpliedType()
|
||||||
|
|
||||||
expectFoo := objectVal(t, schema, map[string]cty.Value{
|
expected := map[string]struct{}{
|
||||||
"id": cty.UnknownVal(cty.String),
|
`aws_instance.foo["a"]`: struct{}{},
|
||||||
"foo": cty.StringVal("2"),
|
`module.count_child[1].aws_instance.foo[0]`: struct{}{},
|
||||||
"type": cty.StringVal("aws_instance")},
|
`module.count_child[1].aws_instance.foo[1]`: struct{}{},
|
||||||
)
|
`module.count_child[0].aws_instance.foo[0]`: struct{}{},
|
||||||
|
`module.count_child[0].aws_instance.foo[1]`: struct{}{},
|
||||||
expectNum := objectVal(t, schema, map[string]cty.Value{
|
`module.for_each_child["a"].aws_instance.foo[1]`: struct{}{},
|
||||||
"id": cty.UnknownVal(cty.String),
|
`module.for_each_child["a"].aws_instance.foo[0]`: struct{}{},
|
||||||
"num": cty.NumberIntVal(2),
|
}
|
||||||
"type": cty.StringVal("aws_instance"),
|
|
||||||
})
|
|
||||||
|
|
||||||
expectExpansion := objectVal(t, schema, map[string]cty.Value{
|
|
||||||
"bar": cty.StringVal("baz"),
|
|
||||||
"id": cty.UnknownVal(cty.String),
|
|
||||||
"num": cty.NumberIntVal(2),
|
|
||||||
"type": cty.StringVal("aws_instance"),
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, res := range plan.Changes.Resources {
|
for _, res := range plan.Changes.Resources {
|
||||||
if res.Action != plans.Create {
|
if res.Action != plans.Create {
|
||||||
|
@ -486,22 +470,14 @@ func TestContext2Plan_moduleCount(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var expected cty.Value
|
_, ok := expected[ric.Addr.String()]
|
||||||
switch i := ric.Addr.String(); i {
|
if !ok {
|
||||||
case "aws_instance.bar":
|
t.Fatal("unexpected resource:", ric.Addr.String())
|
||||||
expected = expectFoo
|
|
||||||
case "aws_instance.foo":
|
|
||||||
expected = expectNum
|
|
||||||
case "module.child[0].aws_instance.foo[0]",
|
|
||||||
"module.child[0].aws_instance.foo[1]",
|
|
||||||
"module.child[1].aws_instance.foo[0]",
|
|
||||||
"module.child[1].aws_instance.foo[1]":
|
|
||||||
expected = expectExpansion
|
|
||||||
default:
|
|
||||||
t.Fatal("unknown instance:", i)
|
|
||||||
}
|
}
|
||||||
|
delete(expected, ric.Addr.String())
|
||||||
checkVals(t, expected, ric.After)
|
}
|
||||||
|
for addr := range expected {
|
||||||
|
t.Error("missing resource", addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1985,10 +1985,10 @@ func TestRefresh_updateDependencies(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"foo"}`),
|
AttrsJSON: []byte(`{"id":"foo"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
// Existing dependencies should not be removed during refresh
|
// Existing dependencies should not be removed during refresh
|
||||||
{
|
{
|
||||||
Module: addrs.RootModuleInstance,
|
Module: addrs.RootModule,
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "aws_instance",
|
Type: "aws_instance",
|
||||||
|
|
|
@ -45,24 +45,16 @@ func Eval(n EvalNode, ctx EvalContext) (interface{}, error) {
|
||||||
// EvalRaw is like Eval except that it returns all errors, even if they
|
// EvalRaw is like Eval except that it returns all errors, even if they
|
||||||
// signal something normal such as EvalEarlyExitError.
|
// signal something normal such as EvalEarlyExitError.
|
||||||
func EvalRaw(n EvalNode, ctx EvalContext) (interface{}, error) {
|
func EvalRaw(n EvalNode, ctx EvalContext) (interface{}, error) {
|
||||||
path := "unknown"
|
log.Printf("[TRACE] eval: %T", n)
|
||||||
if ctx != nil {
|
|
||||||
path = ctx.Path().String()
|
|
||||||
}
|
|
||||||
if path == "" {
|
|
||||||
path = "<root>"
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("[TRACE] %s: eval: %T", path, n)
|
|
||||||
output, err := n.Eval(ctx)
|
output, err := n.Eval(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case EvalEarlyExitError:
|
case EvalEarlyExitError:
|
||||||
log.Printf("[TRACE] %s: eval: %T, early exit err: %s", path, n, err)
|
log.Printf("[TRACE] eval: %T, early exit err: %s", n, err)
|
||||||
case tfdiags.NonFatalError:
|
case tfdiags.NonFatalError:
|
||||||
log.Printf("[WARN] %s: eval: %T, non-fatal err: %s", path, n, err)
|
log.Printf("[WARN] eval: %T, non-fatal err: %s", n, err)
|
||||||
default:
|
default:
|
||||||
log.Printf("[ERROR] %s: eval: %T, err: %s", path, n, err)
|
log.Printf("[ERROR] eval: %T, err: %s", n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,4 +161,8 @@ type EvalContext interface {
|
||||||
// The InstanceExpander is a global object that is shared across all of the
|
// The InstanceExpander is a global object that is shared across all of the
|
||||||
// EvalContext objects for a given configuration.
|
// EvalContext objects for a given configuration.
|
||||||
InstanceExpander() *instances.Expander
|
InstanceExpander() *instances.Expander
|
||||||
|
|
||||||
|
// WithPath returns a copy of the context with the internal path set to the
|
||||||
|
// path argument.
|
||||||
|
WithPath(path addrs.ModuleInstance) EvalContext
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,13 @@ type BuiltinEvalContext struct {
|
||||||
// PathValue is the Path that this context is operating within.
|
// PathValue is the Path that this context is operating within.
|
||||||
PathValue addrs.ModuleInstance
|
PathValue addrs.ModuleInstance
|
||||||
|
|
||||||
|
// pathSet indicates that this context was explicitly created for a
|
||||||
|
// specific path, and can be safely used for evaluation. This lets us
|
||||||
|
// differentiate between Pathvalue being unset, and the zero value which is
|
||||||
|
// equivalent to RootModuleInstance. Path and Evaluation methods will
|
||||||
|
// panic if this is not set.
|
||||||
|
pathSet bool
|
||||||
|
|
||||||
// Evaluator is used for evaluating expressions within the scope of this
|
// Evaluator is used for evaluating expressions within the scope of this
|
||||||
// eval context.
|
// eval context.
|
||||||
Evaluator *Evaluator
|
Evaluator *Evaluator
|
||||||
|
@ -70,6 +77,13 @@ type BuiltinEvalContext struct {
|
||||||
// BuiltinEvalContext implements EvalContext
|
// BuiltinEvalContext implements EvalContext
|
||||||
var _ EvalContext = (*BuiltinEvalContext)(nil)
|
var _ EvalContext = (*BuiltinEvalContext)(nil)
|
||||||
|
|
||||||
|
func (ctx *BuiltinEvalContext) WithPath(path addrs.ModuleInstance) EvalContext {
|
||||||
|
ctx.pathSet = true
|
||||||
|
newCtx := *ctx
|
||||||
|
newCtx.PathValue = path
|
||||||
|
return &newCtx
|
||||||
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} {
|
func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} {
|
||||||
// This can happen during tests. During tests, we just block forever.
|
// This can happen during tests. During tests, we just block forever.
|
||||||
if ctx.StopContext == nil {
|
if ctx.StopContext == nil {
|
||||||
|
@ -104,12 +118,6 @@ func (ctx *BuiltinEvalContext) Input() UIInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error) {
|
func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error) {
|
||||||
if !addr.Module.Equal(ctx.Path().Module()) {
|
|
||||||
// This indicates incorrect use of InitProvider: it should be used
|
|
||||||
// only from the module that the provider configuration belongs to.
|
|
||||||
panic(fmt.Sprintf("%s initialized by wrong module %s", addr, ctx.Path()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we already initialized, it is an error
|
// If we already initialized, it is an error
|
||||||
if p := ctx.Provider(addr); p != nil {
|
if p := ctx.Provider(addr); p != nil {
|
||||||
return nil, fmt.Errorf("%s is already initialized", addr)
|
return nil, fmt.Errorf("%s is already initialized", addr)
|
||||||
|
@ -145,12 +153,6 @@ func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *Pro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error {
|
func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error {
|
||||||
if !addr.Module.Equal(ctx.Path().Module()) {
|
|
||||||
// This indicates incorrect use of CloseProvider: it should be used
|
|
||||||
// only from the module that the provider configuration belongs to.
|
|
||||||
panic(fmt.Sprintf("%s closed by wrong module %s", addr, ctx.Path()))
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.ProviderLock.Lock()
|
ctx.ProviderLock.Lock()
|
||||||
defer ctx.ProviderLock.Unlock()
|
defer ctx.ProviderLock.Unlock()
|
||||||
|
|
||||||
|
@ -213,13 +215,7 @@ func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.AbsProviderConfig) map[str
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.AbsProviderConfig, c map[string]cty.Value) {
|
func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.AbsProviderConfig, c map[string]cty.Value) {
|
||||||
absProvider := pc
|
absProvider := pc
|
||||||
if !absProvider.Module.Equal(ctx.Path().Module()) {
|
if !pc.Module.IsRoot() {
|
||||||
// This indicates incorrect use of InitProvider: it should be used
|
|
||||||
// only from the module that the provider configuration belongs to.
|
|
||||||
panic(fmt.Sprintf("%s initialized by wrong module %s", absProvider, ctx.Path()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ctx.Path().IsRoot() {
|
|
||||||
// Only root module provider configurations can have input.
|
// Only root module provider configurations can have input.
|
||||||
log.Printf("[WARN] BuiltinEvalContext: attempt to SetProviderInput for non-root module")
|
log.Printf("[WARN] BuiltinEvalContext: attempt to SetProviderInput for non-root module")
|
||||||
return
|
return
|
||||||
|
@ -291,6 +287,9 @@ func (ctx *BuiltinEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Ty
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope {
|
func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope {
|
||||||
|
if !ctx.pathSet {
|
||||||
|
panic("context path not set")
|
||||||
|
}
|
||||||
data := &evaluationStateData{
|
data := &evaluationStateData{
|
||||||
Evaluator: ctx.Evaluator,
|
Evaluator: ctx.Evaluator,
|
||||||
ModulePath: ctx.PathValue,
|
ModulePath: ctx.PathValue,
|
||||||
|
@ -301,6 +300,9 @@ func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance {
|
func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance {
|
||||||
|
if !ctx.pathSet {
|
||||||
|
panic("context path not set")
|
||||||
|
}
|
||||||
return ctx.PathValue
|
return ctx.PathValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +310,10 @@ func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance
|
||||||
ctx.VariableValuesLock.Lock()
|
ctx.VariableValuesLock.Lock()
|
||||||
defer ctx.VariableValuesLock.Unlock()
|
defer ctx.VariableValuesLock.Unlock()
|
||||||
|
|
||||||
|
if !ctx.pathSet {
|
||||||
|
panic("context path not set")
|
||||||
|
}
|
||||||
|
|
||||||
childPath := n.ModuleInstance(ctx.PathValue)
|
childPath := n.ModuleInstance(ctx.PathValue)
|
||||||
key := childPath.String()
|
key := childPath.String()
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ func TestBuiltinEvalContextProviderInput(t *testing.T) {
|
||||||
cache := make(map[string]map[string]cty.Value)
|
cache := make(map[string]map[string]cty.Value)
|
||||||
|
|
||||||
ctx1 := testBuiltinEvalContext(t)
|
ctx1 := testBuiltinEvalContext(t)
|
||||||
ctx1.PathValue = addrs.RootModuleInstance
|
ctx1 = ctx1.WithPath(addrs.RootModuleInstance).(*BuiltinEvalContext)
|
||||||
ctx1.ProviderInputConfig = cache
|
ctx1.ProviderInputConfig = cache
|
||||||
ctx1.ProviderLock = &lock
|
ctx1.ProviderLock = &lock
|
||||||
|
|
||||||
ctx2 := testBuiltinEvalContext(t)
|
ctx2 := testBuiltinEvalContext(t)
|
||||||
ctx2.PathValue = addrs.RootModuleInstance.Child("child", addrs.NoKey)
|
ctx2 = ctx2.WithPath(addrs.RootModuleInstance.Child("child", addrs.NoKey)).(*BuiltinEvalContext)
|
||||||
ctx2.ProviderInputConfig = cache
|
ctx2.ProviderInputConfig = cache
|
||||||
ctx2.ProviderLock = &lock
|
ctx2.ProviderLock = &lock
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ func TestBuildingEvalContextInitProvider(t *testing.T) {
|
||||||
testP := &MockProvider{}
|
testP := &MockProvider{}
|
||||||
|
|
||||||
ctx := testBuiltinEvalContext(t)
|
ctx := testBuiltinEvalContext(t)
|
||||||
|
ctx = ctx.WithPath(addrs.RootModuleInstance).(*BuiltinEvalContext)
|
||||||
ctx.ProviderLock = &lock
|
ctx.ProviderLock = &lock
|
||||||
ctx.ProviderCache = make(map[string]providers.Interface)
|
ctx.ProviderCache = make(map[string]providers.Interface)
|
||||||
ctx.Components = &basicComponentFactory{
|
ctx.Components = &basicComponentFactory{
|
||||||
|
|
|
@ -305,6 +305,12 @@ func (c *MockEvalContext) EvaluationScope(self addrs.Referenceable, keyData Inst
|
||||||
return c.EvaluationScopeScope
|
return c.EvaluationScopeScope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MockEvalContext) WithPath(path addrs.ModuleInstance) EvalContext {
|
||||||
|
newC := *c
|
||||||
|
newC.PathPath = path
|
||||||
|
return &newC
|
||||||
|
}
|
||||||
|
|
||||||
func (c *MockEvalContext) Path() addrs.ModuleInstance {
|
func (c *MockEvalContext) Path() addrs.ModuleInstance {
|
||||||
c.PathCalled = true
|
c.PathCalled = true
|
||||||
return c.PathPath
|
return c.PathPath
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
// EvalDeleteOutput is an EvalNode implementation that deletes an output
|
// EvalDeleteOutput is an EvalNode implementation that deletes an output
|
||||||
// from the state.
|
// from the state.
|
||||||
type EvalDeleteOutput struct {
|
type EvalDeleteOutput struct {
|
||||||
Addr addrs.OutputValue
|
Addr addrs.AbsOutputValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
|
@ -25,7 +25,7 @@ func (n *EvalDeleteOutput) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
state.RemoveOutputValue(n.Addr.Absolute(ctx.Path()))
|
state.RemoveOutputValue(n.Addr)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ type EvalWriteState struct {
|
||||||
|
|
||||||
// Dependencies are the inter-resource dependencies to be stored in the
|
// Dependencies are the inter-resource dependencies to be stored in the
|
||||||
// state.
|
// state.
|
||||||
Dependencies *[]addrs.AbsResource
|
Dependencies *[]addrs.ConfigResource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
|
@ -452,16 +452,20 @@ func (n *EvalMaybeRestoreDeposedObject) Eval(ctx EvalContext) (interface{}, erro
|
||||||
// in that case, allowing expression evaluation to see it as a zero-element
|
// in that case, allowing expression evaluation to see it as a zero-element
|
||||||
// list rather than as not set at all.
|
// list rather than as not set at all.
|
||||||
type EvalWriteResourceState struct {
|
type EvalWriteResourceState struct {
|
||||||
Addr addrs.ConfigResource
|
Addr addrs.AbsResource
|
||||||
Config *configs.Resource
|
Config *configs.Resource
|
||||||
ProviderAddr addrs.AbsProviderConfig
|
ProviderAddr addrs.AbsProviderConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
|
||||||
func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
|
func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
state := ctx.State()
|
state := ctx.State()
|
||||||
|
|
||||||
|
// We'll record our expansion decision in the shared "expander" object
|
||||||
|
// so that later operations (i.e. DynamicExpand and expression evaluation)
|
||||||
|
// can refer to it. Since this node represents the abstract module, we need
|
||||||
|
// to expand the module here to create all resources.
|
||||||
|
expander := ctx.InstanceExpander()
|
||||||
count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
|
count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
|
||||||
diags = diags.Append(countDiags)
|
diags = diags.Append(countDiags)
|
||||||
if countDiags.HasErrors() {
|
if countDiags.HasErrors() {
|
||||||
|
@ -482,25 +486,17 @@ func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
if forEach != nil {
|
if forEach != nil {
|
||||||
eachMode = states.EachMap
|
eachMode = states.EachMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll record our expansion decision in the shared "expander" object
|
|
||||||
// so that later operations (i.e. DynamicExpand and expression evaluation)
|
|
||||||
// can refer to it. Since this node represents the abstract module, we need
|
|
||||||
// to expand the module here to create all resources.
|
|
||||||
expander := ctx.InstanceExpander()
|
|
||||||
for _, module := range expander.ExpandModule(n.Addr.Module) {
|
|
||||||
// This method takes care of all of the business logic of updating this
|
// This method takes care of all of the business logic of updating this
|
||||||
// while ensuring that any existing instances are preserved, etc.
|
// while ensuring that any existing instances are preserved, etc.
|
||||||
state.SetResourceMeta(n.Addr.Absolute(module), eachMode, n.ProviderAddr)
|
state.SetResourceMeta(n.Addr, eachMode, n.ProviderAddr)
|
||||||
|
|
||||||
switch eachMode {
|
switch eachMode {
|
||||||
case states.EachList:
|
case states.EachList:
|
||||||
expander.SetResourceCount(module, n.Addr.Resource, count)
|
expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, count)
|
||||||
case states.EachMap:
|
case states.EachMap:
|
||||||
expander.SetResourceForEach(module, n.Addr.Resource, forEach)
|
expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEach)
|
||||||
default:
|
default:
|
||||||
expander.SetResourceSingle(module, n.Addr.Resource)
|
expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -542,7 +538,7 @@ type EvalRefreshDependencies struct {
|
||||||
// Prior State
|
// Prior State
|
||||||
State **states.ResourceInstanceObject
|
State **states.ResourceInstanceObject
|
||||||
// Dependencies to write to the new state
|
// Dependencies to write to the new state
|
||||||
Dependencies *[]addrs.AbsResource
|
Dependencies *[]addrs.ConfigResource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) {
|
func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
|
@ -552,7 +548,7 @@ func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
depMap := make(map[string]addrs.AbsResource)
|
depMap := make(map[string]addrs.ConfigResource)
|
||||||
for _, d := range *n.Dependencies {
|
for _, d := range *n.Dependencies {
|
||||||
depMap[d.String()] = d
|
depMap[d.String()] = d
|
||||||
}
|
}
|
||||||
|
@ -566,7 +562,7 @@ func (n *EvalRefreshDependencies) Eval(ctx EvalContext) (interface{}, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
deps := make([]addrs.AbsResource, 0, len(depMap))
|
deps := make([]addrs.ConfigResource, 0, len(depMap))
|
||||||
for _, d := range depMap {
|
for _, d := range depMap {
|
||||||
deps = append(deps, d)
|
deps = append(deps, d)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,7 @@ func (g *Graph) Walk(walker GraphWalker) tfdiags.Diagnostics {
|
||||||
|
|
||||||
func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
|
func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
|
||||||
// The callbacks for enter/exiting a graph
|
// The callbacks for enter/exiting a graph
|
||||||
ctx := walker.EnterPath(g.Path)
|
ctx := walker.EvalContext()
|
||||||
defer walker.ExitPath(g.Path)
|
|
||||||
|
|
||||||
// Walk the graph.
|
// Walk the graph.
|
||||||
var walkFn dag.WalkFunc
|
var walkFn dag.WalkFunc
|
||||||
|
@ -54,7 +53,7 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
|
||||||
// is normally the context of our graph but can be overridden
|
// is normally the context of our graph but can be overridden
|
||||||
// with a GraphNodeModuleInstance impl.
|
// with a GraphNodeModuleInstance impl.
|
||||||
vertexCtx := ctx
|
vertexCtx := ctx
|
||||||
if pn, ok := v.(GraphNodeModuleInstance); ok && len(pn.Path()) > 0 {
|
if pn, ok := v.(GraphNodeModuleInstance); ok {
|
||||||
vertexCtx = walker.EnterPath(pn.Path())
|
vertexCtx = walker.EnterPath(pn.Path())
|
||||||
defer walker.ExitPath(pn.Path())
|
defer walker.ExitPath(pn.Path())
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||||
return &NodeApplyableResource{
|
return &nodeExpandApplyableResource{
|
||||||
NodeAbstractResource: a,
|
NodeAbstractResource: a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ func TestApplyGraphBuilder_depCbd(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -209,7 +209,7 @@ func TestApplyGraphBuilder_doubleCBD(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch tv.Addr.Resource.Name {
|
switch tv.Addr.Resource.Resource.Name {
|
||||||
case "A":
|
case "A":
|
||||||
destroyA = fmt.Sprintf("test_object.A (destroy deposed %s)", tv.DeposedKey)
|
destroyA = fmt.Sprintf("test_object.A (destroy deposed %s)", tv.DeposedKey)
|
||||||
case "B":
|
case "B":
|
||||||
|
@ -273,7 +273,7 @@ func TestApplyGraphBuilder_destroyStateOnly(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"bar"}`),
|
AttrsJSON: []byte(`{"id":"bar"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("module.child.test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("module.child.test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -378,7 +378,7 @@ func TestApplyGraphBuilder_moduleDestroy(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"foo","value":"foo"}`),
|
AttrsJSON: []byte(`{"id":"foo","value":"foo"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("module.A.test_object.foo")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("module.A.test_object.foo")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -566,14 +566,14 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`),
|
AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_object",
|
Type: "test_object",
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
Module: root.Addr,
|
Module: root.Addr.Module(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -670,14 +670,14 @@ func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`),
|
AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
addrs.AbsResource{
|
addrs.ConfigResource{
|
||||||
Resource: addrs.Resource{
|
Resource: addrs.Resource{
|
||||||
Mode: addrs.ManagedResourceMode,
|
Mode: addrs.ManagedResourceMode,
|
||||||
Type: "test_object",
|
Type: "test_object",
|
||||||
Name: "a",
|
Name: "a",
|
||||||
},
|
},
|
||||||
Module: root.Addr,
|
Module: root.Addr.Module(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -196,7 +196,7 @@ func (b *PlanGraphBuilder) init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex {
|
b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex {
|
||||||
return &NodePlannableResource{
|
return &nodeExpandPlannableResource{
|
||||||
NodeAbstractResource: a,
|
NodeAbstractResource: a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex {
|
concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||||
return &NodeRefreshableManagedResource{
|
return &nodeExpandRefreshableManagedResource{
|
||||||
NodeAbstractResource: a,
|
NodeAbstractResource: a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
concreteDataResource := func(a *NodeAbstractResource) dag.Vertex {
|
concreteDataResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||||
return &NodeRefreshableDataResource{
|
return &nodeExpandRefreshableDataResource{
|
||||||
NodeAbstractResource: a,
|
NodeAbstractResource: a,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,11 +102,11 @@ provider["registry.terraform.io/-/test"] (close) - *terraform.graphNodeCloseProv
|
||||||
data.test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
data.test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
||||||
data.test_object.foo[2] - *terraform.NodeRefreshableManagedResourceInstance
|
data.test_object.foo[2] - *terraform.NodeRefreshableManagedResourceInstance
|
||||||
data.test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
data.test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
||||||
test_object.foo - *terraform.NodeRefreshableManagedResource
|
test_object.foo - *terraform.nodeExpandRefreshableManagedResource
|
||||||
test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
||||||
test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
test_object.foo[1] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
||||||
test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
test_object.foo[2] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
||||||
test_object.foo - *terraform.NodeRefreshableManagedResource
|
test_object.foo - *terraform.nodeExpandRefreshableManagedResource
|
||||||
provider["registry.terraform.io/-/test"] - *terraform.NodeApplyableProvider
|
provider["registry.terraform.io/-/test"] - *terraform.NodeApplyableProvider
|
||||||
test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
test_object.foo[0] (deposed 00000001) - *terraform.NodePlanDeposedResourceInstanceObject
|
||||||
provider["registry.terraform.io/-/test"] - *terraform.NodeApplyableProvider
|
provider["registry.terraform.io/-/test"] - *terraform.NodeApplyableProvider
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
// GraphWalker is an interface that can be implemented that when used
|
// GraphWalker is an interface that can be implemented that when used
|
||||||
// with Graph.Walk will invoke the given callbacks under certain events.
|
// with Graph.Walk will invoke the given callbacks under certain events.
|
||||||
type GraphWalker interface {
|
type GraphWalker interface {
|
||||||
|
EvalContext() EvalContext
|
||||||
EnterPath(addrs.ModuleInstance) EvalContext
|
EnterPath(addrs.ModuleInstance) EvalContext
|
||||||
ExitPath(addrs.ModuleInstance)
|
ExitPath(addrs.ModuleInstance)
|
||||||
EnterVertex(dag.Vertex)
|
EnterVertex(dag.Vertex)
|
||||||
|
@ -22,6 +23,7 @@ type GraphWalker interface {
|
||||||
// implementing all the required functions.
|
// implementing all the required functions.
|
||||||
type NullGraphWalker struct{}
|
type NullGraphWalker struct{}
|
||||||
|
|
||||||
|
func (NullGraphWalker) EvalContext() EvalContext { return new(MockEvalContext) }
|
||||||
func (NullGraphWalker) EnterPath(addrs.ModuleInstance) EvalContext { return new(MockEvalContext) }
|
func (NullGraphWalker) EnterPath(addrs.ModuleInstance) EvalContext { return new(MockEvalContext) }
|
||||||
func (NullGraphWalker) ExitPath(addrs.ModuleInstance) {}
|
func (NullGraphWalker) ExitPath(addrs.ModuleInstance) {}
|
||||||
func (NullGraphWalker) EnterVertex(dag.Vertex) {}
|
func (NullGraphWalker) EnterVertex(dag.Vertex) {}
|
||||||
|
|
|
@ -51,8 +51,6 @@ type ContextGraphWalker struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
|
func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
|
||||||
w.once.Do(w.init)
|
|
||||||
|
|
||||||
w.contextLock.Lock()
|
w.contextLock.Lock()
|
||||||
defer w.contextLock.Unlock()
|
defer w.contextLock.Unlock()
|
||||||
|
|
||||||
|
@ -62,6 +60,14 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := w.EvalContext().WithPath(path)
|
||||||
|
w.contexts[key] = ctx.(*BuiltinEvalContext)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ContextGraphWalker) EvalContext() EvalContext {
|
||||||
|
w.once.Do(w.init)
|
||||||
|
|
||||||
// Our evaluator shares some locks with the main context and the walker
|
// Our evaluator shares some locks with the main context and the walker
|
||||||
// so that we can safely run multiple evaluations at once across
|
// so that we can safely run multiple evaluations at once across
|
||||||
// different modules.
|
// different modules.
|
||||||
|
@ -78,7 +84,6 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
|
||||||
|
|
||||||
ctx := &BuiltinEvalContext{
|
ctx := &BuiltinEvalContext{
|
||||||
StopContext: w.StopContext,
|
StopContext: w.StopContext,
|
||||||
PathValue: path,
|
|
||||||
Hooks: w.Context.hooks,
|
Hooks: w.Context.hooks,
|
||||||
InputValue: w.Context.uiInput,
|
InputValue: w.Context.uiInput,
|
||||||
InstanceExpanderValue: w.InstanceExpander,
|
InstanceExpanderValue: w.InstanceExpander,
|
||||||
|
@ -96,7 +101,6 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
|
||||||
VariableValuesLock: &w.variableValuesLock,
|
VariableValuesLock: &w.variableValuesLock,
|
||||||
}
|
}
|
||||||
|
|
||||||
w.contexts[key] = ctx
|
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,45 @@ import (
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeRefreshableDataResource represents a resource that is "refreshable".
|
type nodeExpandRefreshableDataResource struct {
|
||||||
type NodeRefreshableDataResource struct {
|
|
||||||
*NodeAbstractResource
|
*NodeAbstractResource
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeDynamicExpandable = (*nodeExpandRefreshableDataResource)(nil)
|
||||||
|
_ GraphNodeReferenceable = (*nodeExpandRefreshableDataResource)(nil)
|
||||||
|
_ GraphNodeReferencer = (*nodeExpandRefreshableDataResource)(nil)
|
||||||
|
_ GraphNodeConfigResource = (*nodeExpandRefreshableDataResource)(nil)
|
||||||
|
_ GraphNodeAttachResourceConfig = (*nodeExpandRefreshableDataResource)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (n *nodeExpandRefreshableDataResource) References() []*addrs.Reference {
|
||||||
|
return (&NodeRefreshableManagedResource{NodeAbstractResource: n.NodeAbstractResource}).References()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nodeExpandRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
|
var g Graph
|
||||||
|
|
||||||
|
expander := ctx.InstanceExpander()
|
||||||
|
for _, module := range expander.ExpandModule(n.Addr.Module) {
|
||||||
|
g.Add(&NodeRefreshableDataResource{
|
||||||
|
NodeAbstractResource: n.NodeAbstractResource,
|
||||||
|
Addr: n.Addr.Resource.Absolute(module),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &g, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeRefreshableDataResource represents a resource that is "refreshable".
|
||||||
|
type NodeRefreshableDataResource struct {
|
||||||
|
*NodeAbstractResource
|
||||||
|
|
||||||
|
Addr addrs.AbsResource
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodeRefreshableDataResource)(nil)
|
||||||
_ GraphNodeDynamicExpandable = (*NodeRefreshableDataResource)(nil)
|
_ GraphNodeDynamicExpandable = (*NodeRefreshableDataResource)(nil)
|
||||||
_ GraphNodeReferenceable = (*NodeRefreshableDataResource)(nil)
|
_ GraphNodeReferenceable = (*NodeRefreshableDataResource)(nil)
|
||||||
_ GraphNodeReferencer = (*NodeRefreshableDataResource)(nil)
|
_ GraphNodeReferencer = (*NodeRefreshableDataResource)(nil)
|
||||||
|
@ -24,6 +57,10 @@ var (
|
||||||
_ GraphNodeAttachProviderMetaConfigs = (*NodeAbstractResource)(nil)
|
_ GraphNodeAttachProviderMetaConfigs = (*NodeAbstractResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodeRefreshableDataResource) Path() addrs.ModuleInstance {
|
||||||
|
return n.Addr.Module
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeDynamicExpandable
|
// GraphNodeDynamicExpandable
|
||||||
func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
@ -54,22 +91,18 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
|
||||||
// if we're transitioning whether "count" is set at all.
|
// if we're transitioning whether "count" is set at all.
|
||||||
fixResourceCountSetTransition(ctx, n.ResourceAddr(), count != -1)
|
fixResourceCountSetTransition(ctx, n.ResourceAddr(), count != -1)
|
||||||
|
|
||||||
var instanceAddrs []addrs.AbsResourceInstance
|
|
||||||
|
|
||||||
// Inform our instance expander about our expansion results above,
|
// Inform our instance expander about our expansion results above,
|
||||||
// and then use it to calculate the instance addresses we'll expand for.
|
// and then use it to calculate the instance addresses we'll expand for.
|
||||||
expander := ctx.InstanceExpander()
|
expander := ctx.InstanceExpander()
|
||||||
for _, path := range expander.ExpandModule(n.Addr.Module) {
|
|
||||||
switch {
|
switch {
|
||||||
case count >= 0:
|
case count >= 0:
|
||||||
expander.SetResourceCount(path, n.ResourceAddr().Resource, count)
|
expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, count)
|
||||||
case forEachMap != nil:
|
case forEachMap != nil:
|
||||||
expander.SetResourceForEach(path, n.ResourceAddr().Resource, forEachMap)
|
expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEachMap)
|
||||||
default:
|
default:
|
||||||
expander.SetResourceSingle(path, n.ResourceAddr().Resource)
|
expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource)
|
||||||
}
|
|
||||||
instanceAddrs = append(instanceAddrs, expander.ExpandResource(n.ResourceAddr().Absolute(path))...)
|
|
||||||
}
|
}
|
||||||
|
instanceAddrs := expander.ExpandResource(n.Addr)
|
||||||
|
|
||||||
// Our graph transformers require access to the full state, so we'll
|
// Our graph transformers require access to the full state, so we'll
|
||||||
// temporarily lock it while we work on this.
|
// temporarily lock it while we work on this.
|
||||||
|
@ -114,7 +147,7 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
|
||||||
// directly as NodeDestroyableDataResource.
|
// directly as NodeDestroyableDataResource.
|
||||||
&OrphanResourceCountTransformer{
|
&OrphanResourceCountTransformer{
|
||||||
Concrete: concreteResourceDestroyable,
|
Concrete: concreteResourceDestroyable,
|
||||||
Addr: n.ResourceAddr(),
|
Addr: n.Addr,
|
||||||
InstanceAddrs: instanceAddrs,
|
InstanceAddrs: instanceAddrs,
|
||||||
State: state,
|
State: state,
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,11 +38,13 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleOut(t *testing.T) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
addr := addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo")
|
||||||
n := &NodeRefreshableDataResource{
|
n := &NodeRefreshableDataResource{
|
||||||
NodeAbstractResource: &NodeAbstractResource{
|
NodeAbstractResource: &NodeAbstractResource{
|
||||||
Addr: addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo"),
|
Addr: addr,
|
||||||
Config: m.Module.DataResources["data.aws_instance.foo"],
|
Config: m.Module.DataResources["data.aws_instance.foo"],
|
||||||
},
|
},
|
||||||
|
Addr: addr.Absolute(addrs.RootModuleInstance),
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := n.DynamicExpand(&MockEvalContext{
|
g, err := n.DynamicExpand(&MockEvalContext{
|
||||||
|
@ -118,15 +120,17 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
addr := addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo")
|
||||||
n := &NodeRefreshableDataResource{
|
n := &NodeRefreshableDataResource{
|
||||||
NodeAbstractResource: &NodeAbstractResource{
|
NodeAbstractResource: &NodeAbstractResource{
|
||||||
Addr: addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo"),
|
Addr: addr,
|
||||||
Config: m.Module.DataResources["data.aws_instance.foo"],
|
Config: m.Module.DataResources["data.aws_instance.foo"],
|
||||||
ResolvedProvider: addrs.AbsProviderConfig{
|
ResolvedProvider: addrs.AbsProviderConfig{
|
||||||
Provider: addrs.NewLegacyProvider("aws"),
|
Provider: addrs.NewLegacyProvider("aws"),
|
||||||
Module: addrs.RootModule,
|
Module: addrs.RootModule,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Addr: addr.Absolute(addrs.RootModuleInstance),
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := n.DynamicExpand(&MockEvalContext{
|
g, err := n.DynamicExpand(&MockEvalContext{
|
||||||
|
|
|
@ -92,6 +92,11 @@ func (n *evalPrepareModuleExpansion) Eval(ctx EvalContext) (interface{}, error)
|
||||||
|
|
||||||
_, call := n.Addr.Call()
|
_, call := n.Addr.Call()
|
||||||
|
|
||||||
|
// nodeExpandModule itself does not have visibility into how its ancestors
|
||||||
|
// were expanded, so we use the expander here to provide all possible paths
|
||||||
|
// to our module, and register module instances with each of them.
|
||||||
|
for _, module := range expander.ExpandModule(n.Addr.Parent()) {
|
||||||
|
ctx = ctx.WithPath(module)
|
||||||
count, countDiags := evaluateResourceCountExpression(n.ModuleCall.Count, ctx)
|
count, countDiags := evaluateResourceCountExpression(n.ModuleCall.Count, ctx)
|
||||||
if countDiags.HasErrors() {
|
if countDiags.HasErrors() {
|
||||||
return nil, countDiags.Err()
|
return nil, countDiags.Err()
|
||||||
|
@ -110,17 +115,13 @@ func (n *evalPrepareModuleExpansion) Eval(ctx EvalContext) (interface{}, error)
|
||||||
eachMode = states.EachMap
|
eachMode = states.EachMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// nodeExpandModule itself does not have visibility into how its ancestors
|
|
||||||
// were expanded, so we use the expander here to provide all possible paths
|
|
||||||
// to our module, and register module instances with each of them.
|
|
||||||
for _, path := range expander.ExpandModule(n.Addr.Parent()) {
|
|
||||||
switch eachMode {
|
switch eachMode {
|
||||||
case states.EachList:
|
case states.EachList:
|
||||||
expander.SetModuleCount(path, call, count)
|
expander.SetModuleCount(module, call, count)
|
||||||
case states.EachMap:
|
case states.EachMap:
|
||||||
expander.SetModuleForEach(path, call, forEach)
|
expander.SetModuleForEach(module, call, forEach)
|
||||||
default:
|
default:
|
||||||
expander.SetModuleSingle(path, call)
|
expander.SetModuleSingle(module, call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,8 +235,7 @@ func (n *NodeApplyableOutput) DotNode(name string, opts *dag.DotOpts) *dag.DotNo
|
||||||
// NodeDestroyableOutput represents an output that is "destroybale":
|
// NodeDestroyableOutput represents an output that is "destroybale":
|
||||||
// its application will remove the output from the state.
|
// its application will remove the output from the state.
|
||||||
type NodeDestroyableOutput struct {
|
type NodeDestroyableOutput struct {
|
||||||
Addr addrs.OutputValue
|
Addr addrs.AbsOutputValue
|
||||||
Module addrs.Module
|
|
||||||
Config *configs.Output // Config is the output in the config
|
Config *configs.Output // Config is the output in the config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +253,7 @@ func (n *NodeDestroyableOutput) Name() string {
|
||||||
|
|
||||||
// GraphNodeModulePath
|
// GraphNodeModulePath
|
||||||
func (n *NodeDestroyableOutput) ModulePath() addrs.Module {
|
func (n *NodeDestroyableOutput) ModulePath() addrs.Module {
|
||||||
return n.Module
|
return n.Addr.Module.Module()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemovableIfNotTargeted
|
// RemovableIfNotTargeted
|
||||||
|
|
|
@ -47,7 +47,7 @@ func (n *NodeOutputOrphan) EvalTree() EvalNode {
|
||||||
return &EvalOpFilter{
|
return &EvalOpFilter{
|
||||||
Ops: []walkOperation{walkRefresh, walkApply, walkDestroy},
|
Ops: []walkOperation{walkRefresh, walkApply, walkDestroy},
|
||||||
Node: &EvalDeleteOutput{
|
Node: &EvalDeleteOutput{
|
||||||
Addr: n.Addr.OutputValue,
|
Addr: n.Addr,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ type GraphNodeResourceInstance interface {
|
||||||
|
|
||||||
// StateDependencies returns any inter-resource dependencies that are
|
// StateDependencies returns any inter-resource dependencies that are
|
||||||
// stored in the state.
|
// stored in the state.
|
||||||
StateDependencies() []addrs.AbsResource
|
StateDependencies() []addrs.ConfigResource
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAbstractResource represents a resource that has no associated
|
// NodeAbstractResource represents a resource that has no associated
|
||||||
|
@ -78,19 +78,11 @@ var (
|
||||||
_ dag.GraphNodeDotter = (*NodeAbstractResource)(nil)
|
_ dag.GraphNodeDotter = (*NodeAbstractResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (n *NodeAbstractResource) addr() addrs.AbsResource {
|
|
||||||
return n.Addr.Absolute(n.Addr.Module.UnkeyedInstanceShim())
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNodeAbstractResource creates an abstract resource graph node for
|
// NewNodeAbstractResource creates an abstract resource graph node for
|
||||||
// the given absolute resource address.
|
// the given absolute resource address.
|
||||||
func NewNodeAbstractResource(addr addrs.AbsResource) *NodeAbstractResource {
|
func NewNodeAbstractResource(addr addrs.ConfigResource) *NodeAbstractResource {
|
||||||
// FIXME: this should probably accept a ConfigResource
|
|
||||||
return &NodeAbstractResource{
|
return &NodeAbstractResource{
|
||||||
Addr: addrs.ConfigResource{
|
Addr: addr,
|
||||||
Resource: addr.Resource,
|
|
||||||
Module: addr.Module.Module(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,14 +93,13 @@ func NewNodeAbstractResource(addr addrs.AbsResource) *NodeAbstractResource {
|
||||||
// the "count" or "for_each" arguments.
|
// the "count" or "for_each" arguments.
|
||||||
type NodeAbstractResourceInstance struct {
|
type NodeAbstractResourceInstance struct {
|
||||||
NodeAbstractResource
|
NodeAbstractResource
|
||||||
ModuleInstance addrs.ModuleInstance
|
Addr addrs.AbsResourceInstance
|
||||||
InstanceKey addrs.InstanceKey
|
|
||||||
|
|
||||||
// The fields below will be automatically set using the Attach
|
// The fields below will be automatically set using the Attach
|
||||||
// interfaces if you're running those transforms, but also be explicitly
|
// interfaces if you're running those transforms, but also be explicitly
|
||||||
// set if you already have that information.
|
// set if you already have that information.
|
||||||
ResourceState *states.Resource
|
ResourceState *states.Resource
|
||||||
Dependencies []addrs.AbsResource
|
Dependencies []addrs.ConfigResource
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -136,15 +127,10 @@ func NewNodeAbstractResourceInstance(addr addrs.AbsResourceInstance) *NodeAbstra
|
||||||
// object and the InstanceKey field in our own struct. The
|
// object and the InstanceKey field in our own struct. The
|
||||||
// ResourceInstanceAddr method will stick these back together again on
|
// ResourceInstanceAddr method will stick these back together again on
|
||||||
// request.
|
// request.
|
||||||
|
r := NewNodeAbstractResource(addr.ContainingResource().Config())
|
||||||
return &NodeAbstractResourceInstance{
|
return &NodeAbstractResourceInstance{
|
||||||
NodeAbstractResource: NodeAbstractResource{
|
NodeAbstractResource: *r,
|
||||||
Addr: addrs.ConfigResource{
|
Addr: addr,
|
||||||
Resource: addr.Resource.Resource,
|
|
||||||
Module: addr.Module.Module(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ModuleInstance: addr.Module,
|
|
||||||
InstanceKey: addr.Resource.Key,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,13 +142,8 @@ func (n *NodeAbstractResourceInstance) Name() string {
|
||||||
return n.ResourceInstanceAddr().String()
|
return n.ResourceInstanceAddr().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeModuleInstance
|
|
||||||
func (n *NodeAbstractResource) Path() addrs.ModuleInstance {
|
|
||||||
return n.Addr.Module.UnkeyedInstanceShim()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
|
func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
|
||||||
return n.ModuleInstance
|
return n.Addr.Module
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeModulePath
|
// GraphNodeModulePath
|
||||||
|
@ -285,9 +266,9 @@ func dottedInstanceAddr(tr addrs.ResourceInstance) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateDependencies returns the dependencies saved in the state.
|
// StateDependencies returns the dependencies saved in the state.
|
||||||
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.AbsResource {
|
func (n *NodeAbstractResourceInstance) StateDependencies() []addrs.ConfigResource {
|
||||||
if rs := n.ResourceState; rs != nil {
|
if rs := n.ResourceState; rs != nil {
|
||||||
if s := rs.Instance(n.InstanceKey); s != nil {
|
if s := rs.Instance(n.Addr.Resource.Key); s != nil {
|
||||||
if s.Current != nil {
|
if s.Current != nil {
|
||||||
return s.Current.Dependencies
|
return s.Current.Dependencies
|
||||||
}
|
}
|
||||||
|
@ -360,7 +341,7 @@ func (n *NodeAbstractResourceInstance) Provider() addrs.Provider {
|
||||||
return n.Config.Provider
|
return n.Config.Provider
|
||||||
}
|
}
|
||||||
// FIXME: this will be a default provider
|
// FIXME: this will be a default provider
|
||||||
return addrs.NewLegacyProvider(n.Addr.Resource.ImpliedProvider())
|
return addrs.NewLegacyProvider(n.Addr.Resource.ContainingResource().ImpliedProvider())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeProvisionerConsumer
|
// GraphNodeProvisionerConsumer
|
||||||
|
@ -395,7 +376,7 @@ func (n *NodeAbstractResource) ResourceAddr() addrs.ConfigResource {
|
||||||
|
|
||||||
// GraphNodeResourceInstance
|
// GraphNodeResourceInstance
|
||||||
func (n *NodeAbstractResourceInstance) ResourceInstanceAddr() addrs.AbsResourceInstance {
|
func (n *NodeAbstractResourceInstance) ResourceInstanceAddr() addrs.AbsResourceInstance {
|
||||||
return n.NodeAbstractResource.addr().Instance(n.InstanceKey)
|
return n.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeTargetable
|
// GraphNodeTargetable
|
||||||
|
|
|
@ -8,6 +8,44 @@ import (
|
||||||
"github.com/hashicorp/terraform/lang"
|
"github.com/hashicorp/terraform/lang"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// nodeExpandApplyableResource handles the first layer of resource
|
||||||
|
// expansion during apply. Even though the resource instances themselves are
|
||||||
|
// already expanded from the plan, we still need to expand the
|
||||||
|
// NodeApplyableResource nodes into their respective modules.
|
||||||
|
type nodeExpandApplyableResource struct {
|
||||||
|
*NodeAbstractResource
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ GraphNodeDynamicExpandable = (*nodeExpandApplyableResource)(nil)
|
||||||
|
_ GraphNodeReferenceable = (*nodeExpandApplyableResource)(nil)
|
||||||
|
_ GraphNodeReferencer = (*nodeExpandApplyableResource)(nil)
|
||||||
|
_ GraphNodeConfigResource = (*nodeExpandApplyableResource)(nil)
|
||||||
|
_ GraphNodeAttachResourceConfig = (*nodeExpandApplyableResource)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (n *nodeExpandApplyableResource) References() []*addrs.Reference {
|
||||||
|
return (&NodeApplyableResource{NodeAbstractResource: n.NodeAbstractResource}).References()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nodeExpandApplyableResource) Name() string {
|
||||||
|
return n.NodeAbstractResource.Name() + " (prepare state)"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nodeExpandApplyableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
|
var g Graph
|
||||||
|
|
||||||
|
expander := ctx.InstanceExpander()
|
||||||
|
for _, module := range expander.ExpandModule(n.Addr.Module) {
|
||||||
|
g.Add(&NodeApplyableResource{
|
||||||
|
NodeAbstractResource: n.NodeAbstractResource,
|
||||||
|
Addr: n.Addr.Resource.Absolute(module),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &g, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NodeApplyableResource represents a resource that is "applyable":
|
// NodeApplyableResource represents a resource that is "applyable":
|
||||||
// it may need to have its record in the state adjusted to match configuration.
|
// it may need to have its record in the state adjusted to match configuration.
|
||||||
//
|
//
|
||||||
|
@ -18,9 +56,12 @@ import (
|
||||||
// in the state is suitably prepared to receive any updates to instances.
|
// in the state is suitably prepared to receive any updates to instances.
|
||||||
type NodeApplyableResource struct {
|
type NodeApplyableResource struct {
|
||||||
*NodeAbstractResource
|
*NodeAbstractResource
|
||||||
|
|
||||||
|
Addr addrs.AbsResource
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodeApplyableResource)(nil)
|
||||||
_ GraphNodeConfigResource = (*NodeApplyableResource)(nil)
|
_ GraphNodeConfigResource = (*NodeApplyableResource)(nil)
|
||||||
_ GraphNodeEvalable = (*NodeApplyableResource)(nil)
|
_ GraphNodeEvalable = (*NodeApplyableResource)(nil)
|
||||||
_ GraphNodeProviderConsumer = (*NodeApplyableResource)(nil)
|
_ GraphNodeProviderConsumer = (*NodeApplyableResource)(nil)
|
||||||
|
@ -28,8 +69,8 @@ var (
|
||||||
_ GraphNodeReferencer = (*NodeApplyableResource)(nil)
|
_ GraphNodeReferencer = (*NodeApplyableResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (n *NodeApplyableResource) Name() string {
|
func (n *NodeApplyableResource) Path() addrs.ModuleInstance {
|
||||||
return n.NodeAbstractResource.Name() + " (prepare state)"
|
return n.Addr.Module
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NodeApplyableResource) References() []*addrs.Reference {
|
func (n *NodeApplyableResource) References() []*addrs.Reference {
|
||||||
|
|
|
@ -24,7 +24,7 @@ type NodeApplyableResourceInstance struct {
|
||||||
*NodeAbstractResourceInstance
|
*NodeAbstractResourceInstance
|
||||||
|
|
||||||
destroyNode GraphNodeDestroyerCBD
|
destroyNode GraphNodeDestroyerCBD
|
||||||
graphNodeDeposer // implementation of GraphNodeDeposer
|
graphNodeDeposer // implementation of GraphNodeDeposerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -100,12 +100,7 @@ func (n *NodeApplyableResourceInstance) References() []*addrs.Reference {
|
||||||
|
|
||||||
// GraphNodeAttachDependencies
|
// GraphNodeAttachDependencies
|
||||||
func (n *NodeApplyableResourceInstance) AttachDependencies(deps []addrs.ConfigResource) {
|
func (n *NodeApplyableResourceInstance) AttachDependencies(deps []addrs.ConfigResource) {
|
||||||
var shimmed []addrs.AbsResource
|
n.Dependencies = deps
|
||||||
for _, r := range deps {
|
|
||||||
shimmed = append(shimmed, r.Absolute(r.Module.UnkeyedInstanceShim()))
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Dependencies = shimmed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeEvalable
|
// GraphNodeEvalable
|
||||||
|
|
|
@ -26,6 +26,7 @@ type NodeDestroyResourceInstance struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodeDestroyResourceInstance)(nil)
|
||||||
_ GraphNodeConfigResource = (*NodeDestroyResourceInstance)(nil)
|
_ GraphNodeConfigResource = (*NodeDestroyResourceInstance)(nil)
|
||||||
_ GraphNodeResourceInstance = (*NodeDestroyResourceInstance)(nil)
|
_ GraphNodeResourceInstance = (*NodeDestroyResourceInstance)(nil)
|
||||||
_ GraphNodeDestroyer = (*NodeDestroyResourceInstance)(nil)
|
_ GraphNodeDestroyer = (*NodeDestroyResourceInstance)(nil)
|
||||||
|
@ -63,7 +64,7 @@ func (n *NodeDestroyResourceInstance) CreateBeforeDestroy() bool {
|
||||||
|
|
||||||
// Otherwise check the state for a stored destroy order
|
// Otherwise check the state for a stored destroy order
|
||||||
if rs := n.ResourceState; rs != nil {
|
if rs := n.ResourceState; rs != nil {
|
||||||
if s := rs.Instance(n.InstanceKey); s != nil {
|
if s := rs.Instance(n.Addr.Resource.Key); s != nil {
|
||||||
if s.Current != nil {
|
if s.Current != nil {
|
||||||
return s.Current.CreateBeforeDestroy
|
return s.Current.CreateBeforeDestroy
|
||||||
}
|
}
|
||||||
|
@ -136,7 +137,7 @@ func (n *NodeDestroyResourceInstance) EvalTree() EvalNode {
|
||||||
rs := n.ResourceState
|
rs := n.ResourceState
|
||||||
var is *states.ResourceInstance
|
var is *states.ResourceInstance
|
||||||
if rs != nil {
|
if rs != nil {
|
||||||
is = rs.Instance(n.InstanceKey)
|
is = rs.Instance(n.Addr.Resource.Key)
|
||||||
}
|
}
|
||||||
if is == nil {
|
if is == nil {
|
||||||
log.Printf("[WARN] NodeDestroyResourceInstance for %s with no state", addr)
|
log.Printf("[WARN] NodeDestroyResourceInstance for %s with no state", addr)
|
||||||
|
@ -278,7 +279,7 @@ func (n *NodeDestroyResourceInstance) EvalTree() EvalNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeDestroyResourceInstance represents a resource that is to be destroyed.
|
// NodeDestroyResource represents a resource that is to be destroyed.
|
||||||
//
|
//
|
||||||
// Destroying a resource is a state-only operation: it is the individual
|
// Destroying a resource is a state-only operation: it is the individual
|
||||||
// instances being destroyed that affects remote objects. During graph
|
// instances being destroyed that affects remote objects. During graph
|
||||||
|
@ -292,6 +293,7 @@ type NodeDestroyResource struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodeDestroyResource)(nil)
|
||||||
_ GraphNodeConfigResource = (*NodeDestroyResource)(nil)
|
_ GraphNodeConfigResource = (*NodeDestroyResource)(nil)
|
||||||
_ GraphNodeReferenceable = (*NodeDestroyResource)(nil)
|
_ GraphNodeReferenceable = (*NodeDestroyResource)(nil)
|
||||||
_ GraphNodeReferencer = (*NodeDestroyResource)(nil)
|
_ GraphNodeReferencer = (*NodeDestroyResource)(nil)
|
||||||
|
@ -305,6 +307,10 @@ var (
|
||||||
_ GraphNodeNoProvider = (*NodeDestroyResource)(nil)
|
_ GraphNodeNoProvider = (*NodeDestroyResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodeDestroyResource) Path() addrs.ModuleInstance {
|
||||||
|
return n.Addr.Module
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NodeDestroyResource) Name() string {
|
func (n *NodeDestroyResource) Name() string {
|
||||||
return n.ResourceAddr().String() + " (clean up state)"
|
return n.ResourceAddr().String() + " (clean up state)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,16 @@ package terraform
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/dag"
|
"github.com/hashicorp/terraform/dag"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodePlannableResource represents a resource that is "plannable":
|
// nodeExpandPlannableResource handles the first layer of resource
|
||||||
// it is ready to be planned in order to create a diff.
|
// expansion. We need this extra layer so DynamicExpand is called twice for
|
||||||
type NodePlannableResource struct {
|
// the resource, the first to expand the Resource for each module instance, and
|
||||||
|
// the second to expand each ResourceInstance for the expanded Resources.
|
||||||
|
type nodeExpandPlannableResource struct {
|
||||||
*NodeAbstractResource
|
*NodeAbstractResource
|
||||||
|
|
||||||
// ForceCreateBeforeDestroy might be set via our GraphNodeDestroyerCBD
|
// ForceCreateBeforeDestroy might be set via our GraphNodeDestroyerCBD
|
||||||
|
@ -19,6 +22,64 @@ type NodePlannableResource struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeDestroyerCBD = (*nodeExpandPlannableResource)(nil)
|
||||||
|
_ GraphNodeDynamicExpandable = (*nodeExpandPlannableResource)(nil)
|
||||||
|
_ GraphNodeReferenceable = (*nodeExpandPlannableResource)(nil)
|
||||||
|
_ GraphNodeReferencer = (*nodeExpandPlannableResource)(nil)
|
||||||
|
_ GraphNodeConfigResource = (*nodeExpandPlannableResource)(nil)
|
||||||
|
_ GraphNodeAttachResourceConfig = (*nodeExpandPlannableResource)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// GraphNodeDestroyerCBD
|
||||||
|
func (n *nodeExpandPlannableResource) CreateBeforeDestroy() bool {
|
||||||
|
if n.ForceCreateBeforeDestroy != nil {
|
||||||
|
return *n.ForceCreateBeforeDestroy
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no config, we just assume no
|
||||||
|
if n.Config == nil || n.Config.Managed == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.Config.Managed.CreateBeforeDestroy
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeDestroyerCBD
|
||||||
|
func (n *nodeExpandPlannableResource) ModifyCreateBeforeDestroy(v bool) error {
|
||||||
|
n.ForceCreateBeforeDestroy = &v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nodeExpandPlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
|
var g Graph
|
||||||
|
|
||||||
|
expander := ctx.InstanceExpander()
|
||||||
|
for _, module := range expander.ExpandModule(n.Addr.Module) {
|
||||||
|
g.Add(&NodePlannableResource{
|
||||||
|
NodeAbstractResource: n.NodeAbstractResource,
|
||||||
|
Addr: n.Addr.Resource.Absolute(module),
|
||||||
|
ForceCreateBeforeDestroy: n.ForceCreateBeforeDestroy,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &g, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodePlannableResource represents a resource that is "plannable":
|
||||||
|
// it is ready to be planned in order to create a diff.
|
||||||
|
type NodePlannableResource struct {
|
||||||
|
*NodeAbstractResource
|
||||||
|
|
||||||
|
Addr addrs.AbsResource
|
||||||
|
|
||||||
|
// ForceCreateBeforeDestroy might be set via our GraphNodeDestroyerCBD
|
||||||
|
// during graph construction, if dependencies require us to force this
|
||||||
|
// on regardless of what the configuration says.
|
||||||
|
ForceCreateBeforeDestroy *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodePlannableResource)(nil)
|
||||||
_ GraphNodeDestroyerCBD = (*NodePlannableResource)(nil)
|
_ GraphNodeDestroyerCBD = (*NodePlannableResource)(nil)
|
||||||
_ GraphNodeDynamicExpandable = (*NodePlannableResource)(nil)
|
_ GraphNodeDynamicExpandable = (*NodePlannableResource)(nil)
|
||||||
_ GraphNodeReferenceable = (*NodePlannableResource)(nil)
|
_ GraphNodeReferenceable = (*NodePlannableResource)(nil)
|
||||||
|
@ -27,6 +88,19 @@ var (
|
||||||
_ GraphNodeAttachResourceConfig = (*NodePlannableResource)(nil)
|
_ GraphNodeAttachResourceConfig = (*NodePlannableResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodePlannableResource) Path() addrs.ModuleInstance {
|
||||||
|
return n.Addr.Module
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NodePlannableResource) Name() string {
|
||||||
|
return n.Addr.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GraphNodeModuleInstance
|
||||||
|
func (n *NodePlannableResource) ModuleInstance() addrs.ModuleInstance {
|
||||||
|
return n.Addr.Module
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeEvalable
|
// GraphNodeEvalable
|
||||||
func (n *NodePlannableResource) EvalTree() EvalNode {
|
func (n *NodePlannableResource) EvalTree() EvalNode {
|
||||||
if n.Config == nil {
|
if n.Config == nil {
|
||||||
|
@ -67,26 +141,16 @@ func (n *NodePlannableResource) ModifyCreateBeforeDestroy(v bool) error {
|
||||||
func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
|
// We need to potentially rename an instance address in the state
|
||||||
|
// if we're transitioning whether "count" is set at all.
|
||||||
|
fixResourceCountSetTransition(ctx, n.Addr.Config(), n.Config.Count != nil)
|
||||||
|
|
||||||
// Our instance expander should already have been informed about the
|
// Our instance expander should already have been informed about the
|
||||||
// expansion of this resource and of all of its containing modules, so
|
// expansion of this resource and of all of its containing modules, so
|
||||||
// it can tell us which instance addresses we need to process.
|
// it can tell us which instance addresses we need to process.
|
||||||
expander := ctx.InstanceExpander()
|
expander := ctx.InstanceExpander()
|
||||||
instanceAddrs := expander.ExpandResource(n.ResourceAddr().Absolute(ctx.Path()))
|
instanceAddrs := expander.ExpandResource(n.ResourceAddr().Absolute(ctx.Path()))
|
||||||
|
|
||||||
// We need to potentially rename an instance address in the state
|
|
||||||
// if we're transitioning whether "count" is set at all.
|
|
||||||
//
|
|
||||||
// FIXME: We're re-evaluating count here, even though the InstanceExpander
|
|
||||||
// has already dealt with our expansion above, because we need it to
|
|
||||||
// call fixResourceCountSetTransition; the expander API and that function
|
|
||||||
// are not compatible yet.
|
|
||||||
count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
|
|
||||||
diags = diags.Append(countDiags)
|
|
||||||
if countDiags.HasErrors() {
|
|
||||||
return nil, diags.Err()
|
|
||||||
}
|
|
||||||
fixResourceCountSetTransition(ctx, n.ResourceAddr(), count != -1)
|
|
||||||
|
|
||||||
// Our graph transformers require access to the full state, so we'll
|
// Our graph transformers require access to the full state, so we'll
|
||||||
// temporarily lock it while we work on this.
|
// temporarily lock it while we work on this.
|
||||||
state := ctx.State().Lock()
|
state := ctx.State().Lock()
|
||||||
|
@ -138,7 +202,7 @@ func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
// Add the count/for_each orphans
|
// Add the count/for_each orphans
|
||||||
&OrphanResourceCountTransformer{
|
&OrphanResourceCountTransformer{
|
||||||
Concrete: concreteResourceOrphan,
|
Concrete: concreteResourceOrphan,
|
||||||
Addr: n.ResourceAddr(),
|
Addr: n.Addr,
|
||||||
InstanceAddrs: instanceAddrs,
|
InstanceAddrs: instanceAddrs,
|
||||||
State: state,
|
State: state,
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,33 +14,75 @@ import (
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// nodeExpandRefreshableResource handles the first layer of resource
|
||||||
|
// expansion durin refresh. We need this extra layer so DynamicExpand is called
|
||||||
|
// twice for the resource, the first to expand the Resource for each module
|
||||||
|
// instance, and the second to expand each ResourceInstance for the expanded
|
||||||
|
// Resources.
|
||||||
|
type nodeExpandRefreshableManagedResource struct {
|
||||||
|
*NodeAbstractResource
|
||||||
|
|
||||||
|
// We attach dependencies to the Resource during refresh, since the
|
||||||
|
// instances are instantiated during DynamicExpand.
|
||||||
|
Dependencies []addrs.ConfigResource
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ GraphNodeDynamicExpandable = (*nodeExpandRefreshableManagedResource)(nil)
|
||||||
|
_ GraphNodeReferenceable = (*nodeExpandRefreshableManagedResource)(nil)
|
||||||
|
_ GraphNodeReferencer = (*nodeExpandRefreshableManagedResource)(nil)
|
||||||
|
_ GraphNodeConfigResource = (*nodeExpandRefreshableManagedResource)(nil)
|
||||||
|
_ GraphNodeAttachResourceConfig = (*nodeExpandRefreshableManagedResource)(nil)
|
||||||
|
_ GraphNodeAttachDependencies = (*nodeExpandRefreshableManagedResource)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// GraphNodeAttachDependencies
|
||||||
|
func (n *nodeExpandRefreshableManagedResource) AttachDependencies(deps []addrs.ConfigResource) {
|
||||||
|
n.Dependencies = deps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nodeExpandRefreshableManagedResource) References() []*addrs.Reference {
|
||||||
|
return (&NodeRefreshableManagedResource{NodeAbstractResource: n.NodeAbstractResource}).References()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *nodeExpandRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
||||||
|
var g Graph
|
||||||
|
|
||||||
|
expander := ctx.InstanceExpander()
|
||||||
|
for _, module := range expander.ExpandModule(n.Addr.Module) {
|
||||||
|
g.Add(&NodeRefreshableManagedResource{
|
||||||
|
NodeAbstractResource: n.NodeAbstractResource,
|
||||||
|
Addr: n.Addr.Resource.Absolute(module),
|
||||||
|
Dependencies: n.Dependencies,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &g, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NodeRefreshableManagedResource represents a resource that is expandable into
|
// NodeRefreshableManagedResource represents a resource that is expandable into
|
||||||
// NodeRefreshableManagedResourceInstance. Resource count orphans are also added.
|
// NodeRefreshableManagedResourceInstance. Resource count orphans are also added.
|
||||||
type NodeRefreshableManagedResource struct {
|
type NodeRefreshableManagedResource struct {
|
||||||
*NodeAbstractResource
|
*NodeAbstractResource
|
||||||
|
|
||||||
|
Addr addrs.AbsResource
|
||||||
|
|
||||||
// We attach dependencies to the Resource during refresh, since the
|
// We attach dependencies to the Resource during refresh, since the
|
||||||
// instances are instantiated during DynamicExpand.
|
// instances are instantiated during DynamicExpand.
|
||||||
Dependencies []addrs.AbsResource
|
Dependencies []addrs.ConfigResource
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodeRefreshableManagedResource)(nil)
|
||||||
_ GraphNodeDynamicExpandable = (*NodeRefreshableManagedResource)(nil)
|
_ GraphNodeDynamicExpandable = (*NodeRefreshableManagedResource)(nil)
|
||||||
_ GraphNodeReferenceable = (*NodeRefreshableManagedResource)(nil)
|
_ GraphNodeReferenceable = (*NodeRefreshableManagedResource)(nil)
|
||||||
_ GraphNodeReferencer = (*NodeRefreshableManagedResource)(nil)
|
_ GraphNodeReferencer = (*NodeRefreshableManagedResource)(nil)
|
||||||
_ GraphNodeConfigResource = (*NodeRefreshableManagedResource)(nil)
|
_ GraphNodeConfigResource = (*NodeRefreshableManagedResource)(nil)
|
||||||
_ GraphNodeAttachResourceConfig = (*NodeRefreshableManagedResource)(nil)
|
_ GraphNodeAttachResourceConfig = (*NodeRefreshableManagedResource)(nil)
|
||||||
_ GraphNodeAttachDependencies = (*NodeRefreshableManagedResource)(nil)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GraphNodeAttachDependencies
|
func (n *NodeRefreshableManagedResource) Path() addrs.ModuleInstance {
|
||||||
func (n *NodeRefreshableManagedResource) AttachDependencies(deps []addrs.ConfigResource) {
|
return n.Addr.Module
|
||||||
var shimmed []addrs.AbsResource
|
|
||||||
for _, r := range deps {
|
|
||||||
shimmed = append(shimmed, r.Absolute(r.Module.UnkeyedInstanceShim()))
|
|
||||||
}
|
|
||||||
|
|
||||||
n.Dependencies = shimmed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeDynamicExpandable
|
// GraphNodeDynamicExpandable
|
||||||
|
@ -60,22 +102,20 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
|
||||||
|
|
||||||
// Next we need to potentially rename an instance address in the state
|
// Next we need to potentially rename an instance address in the state
|
||||||
// if we're transitioning whether "count" is set at all.
|
// if we're transitioning whether "count" is set at all.
|
||||||
fixResourceCountSetTransition(ctx, n.ResourceAddr(), count != -1)
|
fixResourceCountSetTransition(ctx, n.Addr.Config(), count != -1)
|
||||||
|
|
||||||
// Inform our instance expander about our expansion results above,
|
// Inform our instance expander about our expansion results above,
|
||||||
// and then use it to calculate the instance addresses we'll expand for.
|
// and then use it to calculate the instance addresses we'll expand for.
|
||||||
expander := ctx.InstanceExpander()
|
expander := ctx.InstanceExpander()
|
||||||
for _, module := range expander.ExpandModule(n.Addr.Module) {
|
|
||||||
switch {
|
switch {
|
||||||
case count >= 0:
|
case count >= 0:
|
||||||
expander.SetResourceCount(module, n.ResourceAddr().Resource, count)
|
expander.SetResourceCount(n.Addr.Module, n.Addr.Resource, count)
|
||||||
case forEachMap != nil:
|
case forEachMap != nil:
|
||||||
expander.SetResourceForEach(module, n.ResourceAddr().Resource, forEachMap)
|
expander.SetResourceForEach(n.Addr.Module, n.Addr.Resource, forEachMap)
|
||||||
default:
|
default:
|
||||||
expander.SetResourceSingle(module, n.ResourceAddr().Resource)
|
expander.SetResourceSingle(n.Addr.Module, n.Addr.Resource)
|
||||||
}
|
}
|
||||||
}
|
instanceAddrs := expander.ExpandResource(n.Addr)
|
||||||
instanceAddrs := expander.ExpandModuleResource(n.Addr.Module, n.ResourceAddr().Resource)
|
|
||||||
|
|
||||||
// Our graph transformers require access to the full state, so we'll
|
// Our graph transformers require access to the full state, so we'll
|
||||||
// temporarily lock it while we work on this.
|
// temporarily lock it while we work on this.
|
||||||
|
@ -101,7 +141,7 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
|
||||||
&ResourceCountTransformer{
|
&ResourceCountTransformer{
|
||||||
Concrete: concreteResource,
|
Concrete: concreteResource,
|
||||||
Schema: n.Schema,
|
Schema: n.Schema,
|
||||||
Addr: n.ResourceAddr(),
|
Addr: n.Addr.Config(),
|
||||||
InstanceAddrs: instanceAddrs,
|
InstanceAddrs: instanceAddrs,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -109,7 +149,7 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
|
||||||
// during a scale in.
|
// during a scale in.
|
||||||
&OrphanResourceCountTransformer{
|
&OrphanResourceCountTransformer{
|
||||||
Concrete: concreteResource,
|
Concrete: concreteResource,
|
||||||
Addr: n.ResourceAddr(),
|
Addr: n.Addr,
|
||||||
InstanceAddrs: instanceAddrs,
|
InstanceAddrs: instanceAddrs,
|
||||||
State: state,
|
State: state,
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,11 +40,13 @@ func TestNodeRefreshableManagedResourceDynamicExpand_scaleOut(t *testing.T) {
|
||||||
},
|
},
|
||||||
}).SyncWrapper()
|
}).SyncWrapper()
|
||||||
|
|
||||||
|
cfgAddr := addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo")
|
||||||
n := &NodeRefreshableManagedResource{
|
n := &NodeRefreshableManagedResource{
|
||||||
NodeAbstractResource: &NodeAbstractResource{
|
NodeAbstractResource: &NodeAbstractResource{
|
||||||
Addr: addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo"),
|
Addr: cfgAddr,
|
||||||
Config: m.Module.ManagedResources["aws_instance.foo"],
|
Config: m.Module.ManagedResources["aws_instance.foo"],
|
||||||
},
|
},
|
||||||
|
Addr: cfgAddr.Absolute(addrs.RootModuleInstance),
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := n.DynamicExpand(&MockEvalContext{
|
g, err := n.DynamicExpand(&MockEvalContext{
|
||||||
|
@ -120,11 +122,13 @@ func TestNodeRefreshableManagedResourceDynamicExpand_scaleIn(t *testing.T) {
|
||||||
},
|
},
|
||||||
}).SyncWrapper()
|
}).SyncWrapper()
|
||||||
|
|
||||||
|
cfgAddr := addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo")
|
||||||
n := &NodeRefreshableManagedResource{
|
n := &NodeRefreshableManagedResource{
|
||||||
NodeAbstractResource: &NodeAbstractResource{
|
NodeAbstractResource: &NodeAbstractResource{
|
||||||
Addr: addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo"),
|
Addr: cfgAddr,
|
||||||
Config: m.Module.ManagedResources["aws_instance.foo"],
|
Config: m.Module.ManagedResources["aws_instance.foo"],
|
||||||
},
|
},
|
||||||
|
Addr: cfgAddr.Absolute(addrs.RootModuleInstance),
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := n.DynamicExpand(&MockEvalContext{
|
g, err := n.DynamicExpand(&MockEvalContext{
|
||||||
|
@ -160,15 +164,11 @@ func TestNodeRefreshableManagedResourceEvalTree_scaleOut(t *testing.T) {
|
||||||
m := testModule(t, "refresh-resource-scale-inout")
|
m := testModule(t, "refresh-resource-scale-inout")
|
||||||
|
|
||||||
n := &NodeRefreshableManagedResourceInstance{
|
n := &NodeRefreshableManagedResourceInstance{
|
||||||
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
|
NodeAbstractResourceInstance: NewNodeAbstractResourceInstance(addrs.RootModuleInstance.Resource(addrs.ManagedResourceMode, "aws_instance", "foo").Instance(addrs.IntKey(2))),
|
||||||
NodeAbstractResource: NodeAbstractResource{
|
|
||||||
Addr: addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo"),
|
|
||||||
Config: m.Module.ManagedResources["aws_instance.foo"],
|
|
||||||
},
|
|
||||||
InstanceKey: addrs.IntKey(2),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.AttachResourceConfig(m.Module.ManagedResources["aws_instance.foo"])
|
||||||
|
|
||||||
actual := n.EvalTree()
|
actual := n.EvalTree()
|
||||||
expected := n.evalTreeManagedResourceNoState()
|
expected := n.evalTreeManagedResourceNoState()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/configs/configschema"
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/providers"
|
"github.com/hashicorp/terraform/providers"
|
||||||
|
@ -15,6 +16,7 @@ type NodeValidatableResource struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
_ GraphNodeModuleInstance = (*NodeValidatableResource)(nil)
|
||||||
_ GraphNodeEvalable = (*NodeValidatableResource)(nil)
|
_ GraphNodeEvalable = (*NodeValidatableResource)(nil)
|
||||||
_ GraphNodeReferenceable = (*NodeValidatableResource)(nil)
|
_ GraphNodeReferenceable = (*NodeValidatableResource)(nil)
|
||||||
_ GraphNodeReferencer = (*NodeValidatableResource)(nil)
|
_ GraphNodeReferencer = (*NodeValidatableResource)(nil)
|
||||||
|
@ -23,6 +25,12 @@ var (
|
||||||
_ GraphNodeAttachProviderMetaConfigs = (*NodeValidatableResource)(nil)
|
_ GraphNodeAttachProviderMetaConfigs = (*NodeValidatableResource)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (n *NodeValidatableResource) Path() addrs.ModuleInstance {
|
||||||
|
// There is no expansion during validation, so we evaluate everything as
|
||||||
|
// single module instances.
|
||||||
|
return n.Addr.Module.UnkeyedInstanceShim()
|
||||||
|
}
|
||||||
|
|
||||||
// GraphNodeEvalable
|
// GraphNodeEvalable
|
||||||
func (n *NodeValidatableResource) EvalTree() EvalNode {
|
func (n *NodeValidatableResource) EvalTree() EvalNode {
|
||||||
addr := n.ResourceAddr()
|
addr := n.ResourceAddr()
|
||||||
|
|
|
@ -210,12 +210,12 @@ func mustResourceInstanceAddr(s string) addrs.AbsResourceInstance {
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustResourceAddr(s string) addrs.AbsResource {
|
func mustResourceAddr(s string) addrs.ConfigResource {
|
||||||
addr, diags := addrs.ParseAbsResourceStr(s)
|
addr, diags := addrs.ParseAbsResourceStr(s)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
panic(diags.Err())
|
panic(diags.Err())
|
||||||
}
|
}
|
||||||
return addr
|
return addr.Config()
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustProviderConfig(s string) addrs.AbsProviderConfig {
|
func mustProviderConfig(s string) addrs.AbsProviderConfig {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
locals {
|
locals {
|
||||||
val = 2
|
val = 2
|
||||||
bar = "baz"
|
bar = "baz"
|
||||||
|
m = {
|
||||||
|
"a" = "b"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "myvar" {
|
variable "myvar" {
|
||||||
|
@ -8,21 +11,20 @@ variable "myvar" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module "child" {
|
module "count_child" {
|
||||||
count = local.val
|
count = local.val
|
||||||
foo = 2
|
foo = 2
|
||||||
bar = var.myvar
|
bar = var.myvar
|
||||||
source = "./child"
|
source = "./child"
|
||||||
}
|
}
|
||||||
|
|
||||||
output "out" {
|
module "for_each_child" {
|
||||||
value = module.child[*].out
|
for_each = aws_instance.foo
|
||||||
|
foo = 2
|
||||||
|
bar = var.myvar
|
||||||
|
source = "./child"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "aws_instance" "foo" {
|
resource "aws_instance" "foo" {
|
||||||
num = 2
|
for_each = local.m
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_instance" "bar" {
|
|
||||||
foo = "${aws_instance.foo.num}"
|
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
|
@ -32,38 +31,14 @@ type ConfigTransformer struct {
|
||||||
// Mode will only add resources that match the given mode
|
// Mode will only add resources that match the given mode
|
||||||
ModeFilter bool
|
ModeFilter bool
|
||||||
Mode addrs.ResourceMode
|
Mode addrs.ResourceMode
|
||||||
|
|
||||||
l sync.Mutex
|
|
||||||
uniqueMap map[string]struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: should we have an addr.Module + addr.Resource type?
|
|
||||||
type configName interface {
|
|
||||||
Name() string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ConfigTransformer) Transform(g *Graph) error {
|
func (t *ConfigTransformer) Transform(g *Graph) error {
|
||||||
// Lock since we use some internal state
|
|
||||||
t.l.Lock()
|
|
||||||
defer t.l.Unlock()
|
|
||||||
|
|
||||||
// If no configuration is available, we don't do anything
|
// If no configuration is available, we don't do anything
|
||||||
if t.Config == nil {
|
if t.Config == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the uniqueness map. If we're tracking uniques, then populate
|
|
||||||
// it with addresses.
|
|
||||||
t.uniqueMap = make(map[string]struct{})
|
|
||||||
defer func() { t.uniqueMap = nil }()
|
|
||||||
if t.Unique {
|
|
||||||
for _, v := range g.Vertices() {
|
|
||||||
if rn, ok := v.(configName); ok {
|
|
||||||
t.uniqueMap[rn.Name()] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the transformation process
|
// Start the transformation process
|
||||||
return t.transform(g, t.Config)
|
return t.transform(g, t.Config)
|
||||||
}
|
}
|
||||||
|
@ -117,12 +92,6 @@ func (t *ConfigTransformer) transformSingle(g *Graph, config *configs.Config) er
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := t.uniqueMap[abstract.Name()]; ok {
|
|
||||||
// We've already seen a resource with this address. This should
|
|
||||||
// never happen, because we enforce uniqueness in the config loader.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var node dag.Vertex = abstract
|
var node dag.Vertex = abstract
|
||||||
if f := t.Concrete; f != nil {
|
if f := t.Concrete; f != nil {
|
||||||
node = f(abstract)
|
node = f(abstract)
|
||||||
|
|
|
@ -56,7 +56,7 @@ data.aws_ami.foo
|
||||||
func TestConfigTransformer_nonUnique(t *testing.T) {
|
func TestConfigTransformer_nonUnique(t *testing.T) {
|
||||||
g := Graph{Path: addrs.RootModuleInstance}
|
g := Graph{Path: addrs.RootModuleInstance}
|
||||||
g.Add(NewNodeAbstractResource(
|
g.Add(NewNodeAbstractResource(
|
||||||
addrs.RootModuleInstance.Resource(
|
addrs.RootModule.Resource(
|
||||||
addrs.ManagedResourceMode, "aws_instance", "web",
|
addrs.ManagedResourceMode, "aws_instance", "web",
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
@ -78,33 +78,6 @@ openstack_floating_ip.random
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigTransformer_unique(t *testing.T) {
|
|
||||||
g := Graph{Path: addrs.RootModuleInstance}
|
|
||||||
g.Add(NewNodeAbstractResource(
|
|
||||||
addrs.RootModuleInstance.Resource(
|
|
||||||
addrs.ManagedResourceMode, "aws_instance", "web",
|
|
||||||
),
|
|
||||||
))
|
|
||||||
tf := &ConfigTransformer{
|
|
||||||
Config: testModule(t, "graph-basic"),
|
|
||||||
Unique: true,
|
|
||||||
}
|
|
||||||
if err := tf.Transform(&g); err != nil {
|
|
||||||
t.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
actual := strings.TrimSpace(g.String())
|
|
||||||
expected := strings.TrimSpace(`
|
|
||||||
aws_instance.web
|
|
||||||
aws_load_balancer.weblb
|
|
||||||
aws_security_group.firewall
|
|
||||||
openstack_floating_ip.random
|
|
||||||
`)
|
|
||||||
if actual != expected {
|
|
||||||
t.Fatalf("bad:\n\n%s", actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const testConfigTransformerGraphBasicStr = `
|
const testConfigTransformerGraphBasicStr = `
|
||||||
aws_instance.web
|
aws_instance.web
|
||||||
aws_load_balancer.weblb
|
aws_load_balancer.weblb
|
||||||
|
|
|
@ -94,7 +94,7 @@ func TestCBDEdgeTransformer(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -164,7 +164,7 @@ func TestCBDEdgeTransformerMulti(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"C","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"C","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
mustResourceAddr("test_object.A"),
|
mustResourceAddr("test_object.A"),
|
||||||
mustResourceAddr("test_object.B"),
|
mustResourceAddr("test_object.B"),
|
||||||
},
|
},
|
||||||
|
@ -234,7 +234,7 @@ func TestCBDEdgeTransformer_depNonCBDCount(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -243,7 +243,7 @@ func TestCBDEdgeTransformer_depNonCBDCount(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -320,7 +320,7 @@ func TestCBDEdgeTransformer_depNonCBDCountBoth(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -329,7 +329,7 @@ func TestCBDEdgeTransformer_depNonCBDCountBoth(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
|
|
@ -172,7 +172,7 @@ func (t *DestroyEdgeTransformer) Transform(g *Graph) error {
|
||||||
// destroyed along with its dependencies.
|
// destroyed along with its dependencies.
|
||||||
func (t *DestroyEdgeTransformer) pruneResources(g *Graph) error {
|
func (t *DestroyEdgeTransformer) pruneResources(g *Graph) error {
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
n, ok := v.(*NodeApplyableResource)
|
n, ok := v.(*nodeExpandApplyableResource)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestDestroyEdgeTransformer_basic(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_string":"x"}`),
|
AttrsJSON: []byte(`{"id":"B","test_string":"x"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -72,7 +72,7 @@ func TestDestroyEdgeTransformer_multi(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"B","test_string":"x"}`),
|
AttrsJSON: []byte(`{"id":"B","test_string":"x"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("test_object.A")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("test_object.A")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -81,7 +81,7 @@ func TestDestroyEdgeTransformer_multi(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"C","test_string":"x"}`),
|
AttrsJSON: []byte(`{"id":"C","test_string":"x"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
mustResourceAddr("test_object.A"),
|
mustResourceAddr("test_object.A"),
|
||||||
mustResourceAddr("test_object.B"),
|
mustResourceAddr("test_object.B"),
|
||||||
},
|
},
|
||||||
|
@ -138,7 +138,7 @@ func TestDestroyEdgeTransformer_module(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"a"}`),
|
AttrsJSON: []byte(`{"id":"a"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("module.child.test_object.b")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("module.child.test_object.b")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -191,7 +191,7 @@ func TestDestroyEdgeTransformer_moduleOnly(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"b","test_string":"x"}`),
|
AttrsJSON: []byte(`{"id":"b","test_string":"x"}`),
|
||||||
Dependencies: []addrs.AbsResource{mustResourceAddr("module.child.test_object.a")},
|
Dependencies: []addrs.ConfigResource{mustResourceAddr("module.child.test_object.a")},
|
||||||
},
|
},
|
||||||
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
mustProviderConfig(`provider["registry.terraform.io/-/test"]`),
|
||||||
)
|
)
|
||||||
|
@ -200,7 +200,7 @@ func TestDestroyEdgeTransformer_moduleOnly(t *testing.T) {
|
||||||
&states.ResourceInstanceObjectSrc{
|
&states.ResourceInstanceObjectSrc{
|
||||||
Status: states.ObjectReady,
|
Status: states.ObjectReady,
|
||||||
AttrsJSON: []byte(`{"id":"c","test_string":"x"}`),
|
AttrsJSON: []byte(`{"id":"c","test_string":"x"}`),
|
||||||
Dependencies: []addrs.AbsResource{
|
Dependencies: []addrs.ConfigResource{
|
||||||
mustResourceAddr("module.child.test_object.a"),
|
mustResourceAddr("module.child.test_object.a"),
|
||||||
mustResourceAddr("module.child.test_object.b"),
|
mustResourceAddr("module.child.test_object.b"),
|
||||||
},
|
},
|
||||||
|
@ -237,12 +237,7 @@ module.child.test_object.c (destroy)
|
||||||
func testDestroyNode(addrString string) GraphNodeDestroyer {
|
func testDestroyNode(addrString string) GraphNodeDestroyer {
|
||||||
instAddr := mustResourceInstanceAddr(addrString)
|
instAddr := mustResourceInstanceAddr(addrString)
|
||||||
|
|
||||||
abs := NewNodeAbstractResource(instAddr.ContainingResource())
|
inst := NewNodeAbstractResourceInstance(instAddr)
|
||||||
|
|
||||||
inst := &NodeAbstractResourceInstance{
|
|
||||||
NodeAbstractResource: *abs,
|
|
||||||
InstanceKey: instAddr.Resource.Key,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &NodeDestroyResourceInstance{NodeAbstractResourceInstance: inst}
|
return &NodeDestroyResourceInstance{NodeAbstractResourceInstance: inst}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,17 @@ import (
|
||||||
type OrphanResourceCountTransformer struct {
|
type OrphanResourceCountTransformer struct {
|
||||||
Concrete ConcreteResourceInstanceNodeFunc
|
Concrete ConcreteResourceInstanceNodeFunc
|
||||||
|
|
||||||
Addr addrs.ConfigResource // Addr of the resource to look for orphans
|
Addr addrs.AbsResource // Addr of the resource to look for orphans
|
||||||
InstanceAddrs []addrs.AbsResourceInstance // Addresses that currently exist in config
|
InstanceAddrs []addrs.AbsResourceInstance // Addresses that currently exist in config
|
||||||
State *states.State // Full global state
|
State *states.State // Full global state
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *OrphanResourceCountTransformer) Transform(g *Graph) error {
|
func (t *OrphanResourceCountTransformer) Transform(g *Graph) error {
|
||||||
resources := t.State.Resources(t.Addr)
|
rs := t.State.Resource(t.Addr)
|
||||||
if len(resources) == 0 {
|
if rs == nil {
|
||||||
return nil // Resource doesn't exist in state, so nothing to do!
|
return nil // Resource doesn't exist in state, so nothing to do!
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rs := range resources {
|
|
||||||
// This is an O(n*m) analysis, which we accept for now because the
|
// This is an O(n*m) analysis, which we accept for now because the
|
||||||
// number of instances of a single resource ought to always be small in any
|
// number of instances of a single resource ought to always be small in any
|
||||||
// reasonable Terraform configuration.
|
// reasonable Terraform configuration.
|
||||||
|
@ -51,7 +50,6 @@ func (t *OrphanResourceCountTransformer) Transform(g *Graph) error {
|
||||||
log.Printf("[TRACE] OrphanResourceCountTransformer: adding %s as %T", thisAddr, node)
|
log.Printf("[TRACE] OrphanResourceCountTransformer: adding %s as %T", thisAddr, node)
|
||||||
g.Add(node)
|
g.Add(node)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ func (t *OrphanResourceTransformer) Transform(g *Graph) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := rs.Addr
|
addr := rs.Addr
|
||||||
abstract := NewNodeAbstractResource(addr)
|
abstract := NewNodeAbstractResource(addr.Config())
|
||||||
var node dag.Vertex = abstract
|
var node dag.Vertex = abstract
|
||||||
if f := t.Concrete; f != nil {
|
if f := t.Concrete; f != nil {
|
||||||
node = f(abstract)
|
node = f(abstract)
|
||||||
|
|
|
@ -79,8 +79,7 @@ func (t *DestroyOutputTransformer) Transform(g *Graph) error {
|
||||||
|
|
||||||
// create the destroy node for this output
|
// create the destroy node for this output
|
||||||
node := &NodeDestroyableOutput{
|
node := &NodeDestroyableOutput{
|
||||||
Addr: output.Addr,
|
Addr: output.Addr.Absolute(addrs.RootModuleInstance),
|
||||||
Module: output.Module,
|
|
||||||
Config: output.Config,
|
Config: output.Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
||||||
p := req.Addr
|
p := req.Addr
|
||||||
target := m[key]
|
target := m[key]
|
||||||
|
|
||||||
_, ok := v.(GraphNodeModuleInstance)
|
_, ok := v.(GraphNodeModulePath)
|
||||||
if !ok && target == nil {
|
if !ok && target == nil {
|
||||||
// No target and no path to traverse up from
|
// No target and no path to traverse up from
|
||||||
diags = diags.Append(fmt.Errorf("%s: provider %s couldn't be found", dag.VertexName(v), p))
|
diags = diags.Append(fmt.Errorf("%s: provider %s couldn't be found", dag.VertexName(v), p))
|
||||||
|
@ -470,11 +470,6 @@ func (n *graphNodeCloseProvider) Name() string {
|
||||||
return n.Addr.String() + " (close)"
|
return n.Addr.String() + " (close)"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphNodeModuleInstance impl.
|
|
||||||
func (n *graphNodeCloseProvider) Path() addrs.ModuleInstance {
|
|
||||||
return n.Addr.Module.UnkeyedInstanceShim()
|
|
||||||
}
|
|
||||||
|
|
||||||
// GraphNodeModulePath
|
// GraphNodeModulePath
|
||||||
func (n *graphNodeCloseProvider) ModulePath() addrs.Module {
|
func (n *graphNodeCloseProvider) ModulePath() addrs.Module {
|
||||||
return n.Addr.Module
|
return n.Addr.Module
|
||||||
|
@ -534,10 +529,6 @@ func (n *graphNodeProxyProvider) ProviderAddr() addrs.AbsProviderConfig {
|
||||||
return n.addr
|
return n.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *graphNodeProxyProvider) Path() addrs.ModuleInstance {
|
|
||||||
return n.addr.Module.UnkeyedInstanceShim()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *graphNodeProxyProvider) ModulePath() addrs.Module {
|
func (n *graphNodeProxyProvider) ModulePath() addrs.Module {
|
||||||
return n.addr.Module
|
return n.addr.Module
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue