Merge pull request #24362 from hashicorp/jbardin/module-expansion-some-more

implement addrs.ConfigResource
This commit is contained in:
James Bardin 2020-03-13 09:08:26 -04:00 committed by GitHub
commit 50077eabe9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 316 additions and 95 deletions

View File

@ -249,6 +249,51 @@ func TestParseTarget(t *testing.T) {
},
``,
},
{
`module.foo.module.bar[0].data.aws_instance.baz`,
&Target{
Subject: AbsResource{
Resource: Resource{
Mode: DataResourceMode,
Type: "aws_instance",
Name: "baz",
},
Module: ModuleInstance{
{Name: "foo", InstanceKey: NoKey},
{Name: "bar", InstanceKey: IntKey(0)},
},
},
SourceRange: tfdiags.SourceRange{
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
End: tfdiags.SourcePos{Line: 1, Column: 47, Byte: 46},
},
},
``,
},
{
`module.foo.module.bar["a"].data.aws_instance.baz["hello"]`,
&Target{
Subject: AbsResourceInstance{
Resource: ResourceInstance{
Resource: Resource{
Mode: DataResourceMode,
Type: "aws_instance",
Name: "baz",
},
Key: StringKey("hello"),
},
Module: ModuleInstance{
{Name: "foo", InstanceKey: NoKey},
{Name: "bar", InstanceKey: StringKey("a")},
},
},
SourceRange: tfdiags.SourceRange{
Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
End: tfdiags.SourcePos{Line: 1, Column: 58, Byte: 57},
},
},
``,
},
{
`module.foo.module.bar.data.aws_instance.baz["hello"]`,
&Target{

View File

@ -253,6 +253,61 @@ func (r AbsResourceInstance) Less(o AbsResourceInstance) bool {
}
}
// ConfigResource is an address for a resource within a configuration.
type ConfigResource struct {
targetable
Module Module
Resource Resource
}
// Resource returns the address of a particular resource within the module.
func (m Module) Resource(mode ResourceMode, typeName string, name string) ConfigResource {
return ConfigResource{
Module: m,
Resource: Resource{
Mode: mode,
Type: typeName,
Name: name,
},
}
}
// Absolute produces the address for the receiver within a specific module instance.
func (r ConfigResource) Absolute(module ModuleInstance) AbsResource {
return AbsResource{
Module: module,
Resource: r.Resource,
}
}
// TargetContains implements Targetable by returning true if the given other
// address is either equal to the receiver or is an instance of the
// receiver.
func (r ConfigResource) TargetContains(other Targetable) bool {
switch to := other.(type) {
case ConfigResource:
// We'll use our stringification as a cheat-ish way to test for equality.
return to.String() == r.String()
case AbsResource:
return r.TargetContains(ConfigResource{Module: to.Module.Module(), Resource: to.Resource})
case AbsResourceInstance:
return r.TargetContains(to.ContainingResource())
default:
return false
}
}
func (r ConfigResource) String() string {
if len(r.Module) == 0 {
return r.Resource.String()
}
return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String())
}
func (r ConfigResource) Equal(o ConfigResource) bool {
return r.String() == o.String()
}
// ResourceMode defines which lifecycle applies to a given resource. Each
// resource lifecycle has a slightly different address format.
type ResourceMode rune

164
addrs/target_test.go Normal file
View File

@ -0,0 +1,164 @@
package addrs
import (
"fmt"
"testing"
)
func TestTargetContains(t *testing.T) {
for _, test := range []struct {
addr, other Targetable
expect bool
}{
{
mustParseTarget("module.foo"),
mustParseTarget("module.bar"),
false,
},
{
mustParseTarget("module.foo"),
mustParseTarget("module.foo"),
true,
},
{
// module.foo is an unkeyed module instance here, so it cannot
// contain another instance
mustParseTarget("module.foo"),
mustParseTarget("module.foo[0]"),
false,
},
{
RootModuleInstance,
mustParseTarget("module.foo"),
true,
},
{
mustParseTarget("module.foo"),
RootModuleInstance,
false,
},
{
mustParseTarget("module.foo"),
mustParseTarget("module.foo.module.bar[0]"),
true,
},
{
mustParseTarget("module.foo"),
mustParseTarget("module.foo.module.bar[0]"),
true,
},
{
mustParseTarget("module.foo[2]"),
mustParseTarget("module.foo[2].module.bar[0]"),
true,
},
{
mustParseTarget("module.foo"),
mustParseTarget("module.foo.test_resource.bar"),
true,
},
{
mustParseTarget("module.foo"),
mustParseTarget("module.foo.test_resource.bar[0]"),
true,
},
// Resources
{
mustParseTarget("test_resource.foo"),
mustParseTarget("test_resource.foo[\"bar\"]"),
true,
},
{
mustParseTarget(`test_resource.foo["bar"]`),
mustParseTarget(`test_resource.foo["bar"]`),
true,
},
{
mustParseTarget("test_resource.foo"),
mustParseTarget("test_resource.foo[2]"),
true,
},
{
mustParseTarget("test_resource.foo"),
mustParseTarget("module.bar.test_resource.foo[2]"),
false,
},
{
mustParseTarget("module.bar.test_resource.foo"),
mustParseTarget("module.bar.test_resource.foo[2]"),
true,
},
{
mustParseTarget("module.bar.test_resource.foo"),
mustParseTarget("module.bar[0].test_resource.foo[2]"),
false,
},
// Config paths, while never returned from parsing a target, must still be targetable
{
ConfigResource{
Module: []string{"bar"},
Resource: Resource{
Mode: ManagedResourceMode,
Type: "test_resource",
Name: "foo",
},
},
mustParseTarget("module.bar.test_resource.foo[2]"),
true,
},
{
ConfigResource{
Resource: Resource{
Mode: ManagedResourceMode,
Type: "test_resource",
Name: "foo",
},
},
mustParseTarget("module.bar.test_resource.foo[2]"),
false,
},
{
ConfigResource{
Module: []string{"bar"},
Resource: Resource{
Mode: ManagedResourceMode,
Type: "test_resource",
Name: "foo",
},
},
mustParseTarget("module.bar[0].test_resource.foo"),
true,
},
} {
t.Run(fmt.Sprintf("%s-in-%s", test.other, test.addr), func(t *testing.T) {
got := test.addr.TargetContains(test.other)
if got != test.expect {
t.Fatalf("expected %q.TargetContains(%q) == %t", test.addr, test.other, test.expect)
}
})
}
}
func TestResourceContains(t *testing.T) {
for _, test := range []struct {
in, other Targetable
expect bool
}{} {
t.Run(fmt.Sprintf("%s-in-%s", test.other, test.in), func(t *testing.T) {
got := test.in.TargetContains(test.other)
if got != test.expect {
t.Fatalf("expected %q.TargetContains(%q) == %t", test.in, test.other, test.expect)
}
})
}
}
func mustParseTarget(str string) Targetable {
t, diags := ParseTargetStr(str)
if diags != nil {
panic(fmt.Sprintf("%s: %s", str, diags.ErrWithWarnings()))
}
return t.Subject
}

View File

@ -597,7 +597,7 @@ func TestContextImport_moduleDiff(t *testing.T) {
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "bar",
}.Instance(addrs.NoKey).Absolute(addrs.Module{"bar"}.UnkeyedInstanceShim()),
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("bar", addrs.NoKey)),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "bar",
@ -658,7 +658,7 @@ func TestContextImport_moduleExisting(t *testing.T) {
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "bar",
}.Instance(addrs.NoKey).Absolute(addrs.Module{"foo"}.UnkeyedInstanceShim()),
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey)),
&states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{
"id": "bar",

View File

@ -65,8 +65,6 @@ type BuiltinEvalContext struct {
ChangesValue *plans.ChangesSync
StateValue *states.SyncState
InstanceExpanderValue *instances.Expander
once sync.Once
}
// BuiltinEvalContext implements EvalContext
@ -106,16 +104,14 @@ func (ctx *BuiltinEvalContext) Input() UIInput {
}
func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error) {
ctx.once.Do(ctx.init)
absAddr := addr
if !absAddr.Module.Equal(ctx.Path().Module()) {
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", absAddr, ctx.Path()))
panic(fmt.Sprintf("%s initialized by wrong module %s", addr, ctx.Path()))
}
// If we already initialized, it is an error
if p := ctx.Provider(absAddr); p != nil {
if p := ctx.Provider(addr); p != nil {
return nil, fmt.Errorf("%s is already initialized", addr)
}
@ -124,22 +120,20 @@ func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (provi
ctx.ProviderLock.Lock()
defer ctx.ProviderLock.Unlock()
key := absAddr.String()
key := addr.String()
p, err := ctx.Components.ResourceProvider(addr.Provider)
if err != nil {
return nil, err
}
log.Printf("[TRACE] BuiltinEvalContext: Initialized %q provider for %s", addr.LegacyString(), absAddr)
log.Printf("[TRACE] BuiltinEvalContext: Initialized %q provider for %s", addr.LegacyString(), addr)
ctx.ProviderCache[key] = p
return p, nil
}
func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface {
ctx.once.Do(ctx.init)
ctx.ProviderLock.Lock()
defer ctx.ProviderLock.Unlock()
@ -147,12 +141,10 @@ func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.
}
func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema {
ctx.once.Do(ctx.init)
return ctx.Schemas.ProviderSchema(addr.Provider)
}
func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error {
ctx.once.Do(ctx.init)
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.
@ -174,22 +166,21 @@ func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error
func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, cfg cty.Value) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
absAddr := addr
if !absAddr.Module.Equal(ctx.Path().Module()) {
if !addr.Module.Equal(ctx.Path().Module()) {
// This indicates incorrect use of ConfigureProvider: it should be used
// only from the module that the provider configuration belongs to.
panic(fmt.Sprintf("%s configured by wrong module %s", absAddr, ctx.Path()))
panic(fmt.Sprintf("%s configured by wrong module %s", addr, ctx.Path()))
}
p := ctx.Provider(absAddr)
p := ctx.Provider(addr)
if p == nil {
diags = diags.Append(fmt.Errorf("%s not initialized", addr))
return diags
}
providerSchema := ctx.ProviderSchema(absAddr)
providerSchema := ctx.ProviderSchema(addr)
if providerSchema == nil {
diags = diags.Append(fmt.Errorf("schema for %s is not available", absAddr))
diags = diags.Append(fmt.Errorf("schema for %s is not available", addr))
return diags
}
@ -241,8 +232,6 @@ func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.AbsProviderConfig, c ma
}
func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) {
ctx.once.Do(ctx.init)
// If we already initialized, it is an error
if p := ctx.Provisioner(n); p != nil {
return nil, fmt.Errorf("Provisioner '%s' already initialized", n)
@ -264,8 +253,6 @@ func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface
}
func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface {
ctx.once.Do(ctx.init)
ctx.ProvisionerLock.Lock()
defer ctx.ProvisionerLock.Unlock()
@ -273,14 +260,10 @@ func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface {
}
func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block {
ctx.once.Do(ctx.init)
return ctx.Schemas.ProvisionerConfig(n)
}
func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error {
ctx.once.Do(ctx.init)
ctx.ProvisionerLock.Lock()
defer ctx.ProvisionerLock.Unlock()
@ -361,6 +344,3 @@ func (ctx *BuiltinEvalContext) State() *states.SyncState {
func (ctx *BuiltinEvalContext) InstanceExpander() *instances.Expander {
return ctx.InstanceExpanderValue
}
func (ctx *BuiltinEvalContext) init() {
}

View File

@ -452,8 +452,7 @@ func (n *EvalMaybeRestoreDeposedObject) Eval(ctx EvalContext) (interface{}, erro
// in that case, allowing expression evaluation to see it as a zero-element
// list rather than as not set at all.
type EvalWriteResourceState struct {
Addr addrs.Resource
Module addrs.Module
Addr addrs.ConfigResource
Config *configs.Resource
ProviderAddr addrs.AbsProviderConfig
}
@ -489,18 +488,18 @@ func (n *EvalWriteResourceState) Eval(ctx EvalContext) (interface{}, error) {
// 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.Module) {
for _, module := range expander.ExpandModule(n.Addr.Module) {
// This method takes care of all of the business logic of updating this
// while ensuring that any existing instances are preserved, etc.
state.SetResourceMeta(n.Addr.Absolute(module), eachMode, n.ProviderAddr)
switch eachMode {
case states.EachList:
expander.SetResourceCount(module, n.Addr, count)
expander.SetResourceCount(module, n.Addr.Resource, count)
case states.EachMap:
expander.SetResourceForEach(module, n.Addr, forEach)
expander.SetResourceForEach(module, n.Addr.Resource, forEach)
default:
expander.SetResourceSingle(module, n.Addr)
expander.SetResourceSingle(module, n.Addr.Resource)
}
}

View File

@ -209,7 +209,7 @@ func TestApplyGraphBuilder_doubleCBD(t *testing.T) {
continue
}
switch tv.Addr.Name {
switch tv.Addr.Resource.Name {
case "A":
destroyA = fmt.Sprintf("test_object.A (destroy deposed %s)", tv.DeposedKey)
case "B":

View File

@ -59,7 +59,7 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
// Inform our instance expander about our expansion results above,
// and then use it to calculate the instance addresses we'll expand for.
expander := ctx.InstanceExpander()
for _, path := range expander.ExpandModule(n.Module) {
for _, path := range expander.ExpandModule(n.Addr.Module) {
switch {
case count >= 0:
expander.SetResourceCount(path, n.ResourceAddr().Resource, count)

View File

@ -40,12 +40,7 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleOut(t *testing.T) {
n := &NodeRefreshableDataResource{
NodeAbstractResource: &NodeAbstractResource{
Addr: addrs.Resource{
Mode: addrs.DataResourceMode,
Type: "aws_instance",
Name: "foo",
},
Module: addrs.RootModule,
Addr: addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo"),
Config: m.Module.DataResources["data.aws_instance.foo"],
},
}
@ -125,12 +120,7 @@ func TestNodeRefreshableDataResourceDynamicExpand_scaleIn(t *testing.T) {
n := &NodeRefreshableDataResource{
NodeAbstractResource: &NodeAbstractResource{
Addr: addrs.Resource{
Mode: addrs.DataResourceMode,
Type: "aws_instance",
Name: "foo",
},
Module: addrs.RootModule,
Addr: addrs.RootModule.Resource(addrs.DataResourceMode, "aws_instance", "foo"),
Config: m.Module.DataResources["data.aws_instance.foo"],
ResolvedProvider: addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("aws"),

View File

@ -110,8 +110,8 @@ func (n *evalPrepareModuleExpansion) Eval(ctx EvalContext) (interface{}, error)
eachMode = states.EachMap
}
// nodeExpandModule itself does not have visibility into how it's ancestors
// were expended, so we use the expander here to provide all possible paths
// 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 {

View File

@ -32,7 +32,7 @@ func (n *NodeModuleRemoved) Path() addrs.ModuleInstance {
// GraphNodeModulePath implementation
func (n *NodeModuleRemoved) ModulePath() addrs.Module {
// This node represents the module call within a module,
// so return the CallerAddr as the path as the module
// so return the CallerAddr as the path, as the module
// call may expand into multiple child instances
return n.Addr.Module()
}

View File

@ -41,6 +41,8 @@ func (n *NodeAbstractProvider) Name() string {
// GraphNodeModuleInstance
func (n *NodeAbstractProvider) Path() addrs.ModuleInstance {
// Providers cannot be contained inside an expanded module, so this shim
// converts our module path to the correct ModuleInstance.
return n.Addr.Module.UnkeyedInstanceShim()
}

View File

@ -14,7 +14,7 @@ type NodeDisabledProvider struct {
}
var (
_ GraphNodeModuleInstance = (*NodeDisabledProvider)(nil)
_ GraphNodeModulePath = (*NodeDisabledProvider)(nil)
_ RemovableIfNotTargeted = (*NodeDisabledProvider)(nil)
_ GraphNodeReferencer = (*NodeDisabledProvider)(nil)
_ GraphNodeProvider = (*NodeDisabledProvider)(nil)

View File

@ -43,8 +43,7 @@ type GraphNodeResourceInstance interface {
// operations. It registers all the interfaces for a resource that common
// across multiple operation types.
type NodeAbstractResource struct {
Addr addrs.Resource
Module addrs.Module
Addr addrs.ConfigResource
// The fields below will be automatically set using the Attach
// interfaces if you're running those transforms, but also be explicitly
@ -80,15 +79,18 @@ var (
)
func (n *NodeAbstractResource) addr() addrs.AbsResource {
return n.Addr.Absolute(n.Module.UnkeyedInstanceShim())
return n.Addr.Absolute(n.Addr.Module.UnkeyedInstanceShim())
}
// NewNodeAbstractResource creates an abstract resource graph node for
// the given absolute resource address.
func NewNodeAbstractResource(addr addrs.AbsResource) *NodeAbstractResource {
// FIXME: this should probably accept a ConfigResource
return &NodeAbstractResource{
Addr: addr.Resource,
Module: addr.Module.Module(),
Addr: addrs.ConfigResource{
Resource: addr.Resource,
Module: addr.Module.Module(),
},
}
}
@ -136,8 +138,10 @@ func NewNodeAbstractResourceInstance(addr addrs.AbsResourceInstance) *NodeAbstra
// request.
return &NodeAbstractResourceInstance{
NodeAbstractResource: NodeAbstractResource{
Addr: addr.Resource.Resource,
Module: addr.Module.Module(),
Addr: addrs.ConfigResource{
Resource: addr.Resource.Resource,
Module: addr.Module.Module(),
},
},
ModuleInstance: addr.Module,
InstanceKey: addr.Resource.Key,
@ -154,7 +158,7 @@ func (n *NodeAbstractResourceInstance) Name() string {
// GraphNodeModuleInstance
func (n *NodeAbstractResource) Path() addrs.ModuleInstance {
return n.Module.UnkeyedInstanceShim()
return n.Addr.Module.UnkeyedInstanceShim()
}
func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
@ -163,12 +167,12 @@ func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
// GraphNodeModulePath
func (n *NodeAbstractResource) ModulePath() addrs.Module {
return n.Module
return n.Addr.Module
}
// GraphNodeReferenceable
func (n *NodeAbstractResource) ReferenceableAddrs() []addrs.Referenceable {
return []addrs.Referenceable{n.Addr}
return []addrs.Referenceable{n.Addr.Resource}
}
// GraphNodeReferenceable
@ -314,7 +318,7 @@ func (n *NodeAbstractResource) ProvidedBy() (addrs.ProviderConfig, bool) {
// GraphNodeProviderConsumer
func (n *NodeAbstractResource) ImpliedProvider() addrs.Provider {
return n.Addr.DefaultProvider()
return n.Addr.Resource.DefaultProvider()
}
// GraphNodeProviderConsumer
@ -342,7 +346,7 @@ func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.ProviderConfig, bool)
// GraphNodeProviderConsumer
func (n *NodeAbstractResourceInstance) ImpliedProvider() addrs.Provider {
return n.Addr.DefaultProvider()
return n.Addr.Resource.DefaultProvider()
}
// GraphNodeProvisionerConsumer

View File

@ -61,7 +61,6 @@ func (n *NodeApplyableResource) EvalTree() EvalNode {
return &EvalWriteResourceState{
Addr: n.Addr,
Module: n.Module,
Config: n.Config,
ProviderAddr: n.ResolvedProvider,
}

View File

@ -38,7 +38,6 @@ func (n *NodePlannableResource) EvalTree() EvalNode {
// this ensures we can reference the resource even if the count is 0
return &EvalWriteResourceState{
Addr: n.Addr,
Module: n.Module,
Config: n.Config,
ProviderAddr: n.ResolvedProvider,
}

View File

@ -60,7 +60,7 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
// Inform our instance expander about our expansion results above,
// and then use it to calculate the instance addresses we'll expand for.
expander := ctx.InstanceExpander()
for _, module := range expander.ExpandModule(n.Module) {
for _, module := range expander.ExpandModule(n.Addr.Module) {
switch {
case count >= 0:
expander.SetResourceCount(module, n.ResourceAddr().Resource, count)
@ -70,7 +70,7 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
expander.SetResourceSingle(module, n.ResourceAddr().Resource)
}
}
instanceAddrs := expander.ExpandResource(n.Module, n.ResourceAddr().Resource)
instanceAddrs := expander.ExpandResource(n.Addr.Module, n.ResourceAddr().Resource)
// Our graph transformers require access to the full state, so we'll
// temporarily lock it while we work on this.

View File

@ -42,12 +42,7 @@ func TestNodeRefreshableManagedResourceDynamicExpand_scaleOut(t *testing.T) {
n := &NodeRefreshableManagedResource{
NodeAbstractResource: &NodeAbstractResource{
Addr: addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
},
Module: addrs.RootModule,
Addr: addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo"),
Config: m.Module.ManagedResources["aws_instance.foo"],
},
}
@ -127,12 +122,7 @@ func TestNodeRefreshableManagedResourceDynamicExpand_scaleIn(t *testing.T) {
n := &NodeRefreshableManagedResource{
NodeAbstractResource: &NodeAbstractResource{
Addr: addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
},
Module: addrs.RootModule,
Addr: addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo"),
Config: m.Module.ManagedResources["aws_instance.foo"],
},
}
@ -172,12 +162,7 @@ func TestNodeRefreshableManagedResourceEvalTree_scaleOut(t *testing.T) {
n := &NodeRefreshableManagedResourceInstance{
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
NodeAbstractResource: NodeAbstractResource{
Addr: addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "aws_instance",
Name: "foo",
},
Module: addrs.RootModule,
Addr: addrs.RootModule.Resource(addrs.ManagedResourceMode, "aws_instance", "foo"),
Config: m.Module.ManagedResources["aws_instance.foo"],
},
InstanceKey: addrs.IntKey(2),

View File

@ -8,9 +8,6 @@ import (
// GraphNodeAttachProvider is an interface that must be implemented by nodes
// that want provider configurations attached.
type GraphNodeAttachProvider interface {
// Must be implemented to determine the path for the configuration
GraphNodeModuleInstance
// ProviderName with no module prefix. Example: "aws".
ProviderAddr() addrs.AbsProviderConfig

View File

@ -111,8 +111,10 @@ func (t *ConfigTransformer) transformSingle(g *Graph, config *configs.Config) er
}
abstract := &NodeAbstractResource{
Addr: relAddr,
Module: path,
Addr: addrs.ConfigResource{
Resource: relAddr,
Module: path,
},
}
if _, ok := t.uniqueMap[abstract.Name()]; ok {