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"]`, `module.foo.module.bar.data.aws_instance.baz["hello"]`,
&Target{ &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 // ResourceMode defines which lifecycle applies to a given resource. Each
// resource lifecycle has a slightly different address format. // resource lifecycle has a slightly different address format.
type ResourceMode rune 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, Mode: addrs.ManagedResourceMode,
Type: "aws_instance", Type: "aws_instance",
Name: "bar", Name: "bar",
}.Instance(addrs.NoKey).Absolute(addrs.Module{"bar"}.UnkeyedInstanceShim()), }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("bar", addrs.NoKey)),
&states.ResourceInstanceObjectSrc{ &states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{ AttrsFlat: map[string]string{
"id": "bar", "id": "bar",
@ -658,7 +658,7 @@ func TestContextImport_moduleExisting(t *testing.T) {
Mode: addrs.ManagedResourceMode, Mode: addrs.ManagedResourceMode,
Type: "aws_instance", Type: "aws_instance",
Name: "bar", Name: "bar",
}.Instance(addrs.NoKey).Absolute(addrs.Module{"foo"}.UnkeyedInstanceShim()), }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("foo", addrs.NoKey)),
&states.ResourceInstanceObjectSrc{ &states.ResourceInstanceObjectSrc{
AttrsFlat: map[string]string{ AttrsFlat: map[string]string{
"id": "bar", "id": "bar",

View File

@ -65,8 +65,6 @@ type BuiltinEvalContext struct {
ChangesValue *plans.ChangesSync ChangesValue *plans.ChangesSync
StateValue *states.SyncState StateValue *states.SyncState
InstanceExpanderValue *instances.Expander InstanceExpanderValue *instances.Expander
once sync.Once
} }
// BuiltinEvalContext implements EvalContext // BuiltinEvalContext implements EvalContext
@ -106,16 +104,14 @@ 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) {
ctx.once.Do(ctx.init) if !addr.Module.Equal(ctx.Path().Module()) {
absAddr := addr
if !absAddr.Module.Equal(ctx.Path().Module()) {
// This indicates incorrect use of InitProvider: it should be used // This indicates incorrect use of InitProvider: it should be used
// only from the module that the provider configuration belongs to. // 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 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) return nil, fmt.Errorf("%s is already initialized", addr)
} }
@ -124,22 +120,20 @@ func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (provi
ctx.ProviderLock.Lock() ctx.ProviderLock.Lock()
defer ctx.ProviderLock.Unlock() defer ctx.ProviderLock.Unlock()
key := absAddr.String() key := addr.String()
p, err := ctx.Components.ResourceProvider(addr.Provider) p, err := ctx.Components.ResourceProvider(addr.Provider)
if err != nil { if err != nil {
return nil, err 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 ctx.ProviderCache[key] = p
return p, nil return p, nil
} }
func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface { func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface {
ctx.once.Do(ctx.init)
ctx.ProviderLock.Lock() ctx.ProviderLock.Lock()
defer ctx.ProviderLock.Unlock() defer ctx.ProviderLock.Unlock()
@ -147,12 +141,10 @@ func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.
} }
func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema { func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema {
ctx.once.Do(ctx.init)
return ctx.Schemas.ProviderSchema(addr.Provider) return ctx.Schemas.ProviderSchema(addr.Provider)
} }
func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error { func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error {
ctx.once.Do(ctx.init)
if !addr.Module.Equal(ctx.Path().Module()) { if !addr.Module.Equal(ctx.Path().Module()) {
// This indicates incorrect use of CloseProvider: it should be used // This indicates incorrect use of CloseProvider: it should be used
// only from the module that the provider configuration belongs to. // 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 { func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, cfg cty.Value) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics var diags tfdiags.Diagnostics
absAddr := addr if !addr.Module.Equal(ctx.Path().Module()) {
if !absAddr.Module.Equal(ctx.Path().Module()) {
// This indicates incorrect use of ConfigureProvider: it should be used // This indicates incorrect use of ConfigureProvider: it should be used
// only from the module that the provider configuration belongs to. // 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 { if p == nil {
diags = diags.Append(fmt.Errorf("%s not initialized", addr)) diags = diags.Append(fmt.Errorf("%s not initialized", addr))
return diags return diags
} }
providerSchema := ctx.ProviderSchema(absAddr) providerSchema := ctx.ProviderSchema(addr)
if providerSchema == nil { 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 return diags
} }
@ -241,8 +232,6 @@ func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.AbsProviderConfig, c ma
} }
func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) { func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) {
ctx.once.Do(ctx.init)
// If we already initialized, it is an error // If we already initialized, it is an error
if p := ctx.Provisioner(n); p != nil { if p := ctx.Provisioner(n); p != nil {
return nil, fmt.Errorf("Provisioner '%s' already initialized", n) 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 { func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface {
ctx.once.Do(ctx.init)
ctx.ProvisionerLock.Lock() ctx.ProvisionerLock.Lock()
defer ctx.ProvisionerLock.Unlock() defer ctx.ProvisionerLock.Unlock()
@ -273,14 +260,10 @@ func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface {
} }
func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block { func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block {
ctx.once.Do(ctx.init)
return ctx.Schemas.ProvisionerConfig(n) return ctx.Schemas.ProvisionerConfig(n)
} }
func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error {
ctx.once.Do(ctx.init)
ctx.ProvisionerLock.Lock() ctx.ProvisionerLock.Lock()
defer ctx.ProvisionerLock.Unlock() defer ctx.ProvisionerLock.Unlock()
@ -361,6 +344,3 @@ func (ctx *BuiltinEvalContext) State() *states.SyncState {
func (ctx *BuiltinEvalContext) InstanceExpander() *instances.Expander { func (ctx *BuiltinEvalContext) InstanceExpander() *instances.Expander {
return ctx.InstanceExpanderValue 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 // 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.Resource Addr addrs.ConfigResource
Module addrs.Module
Config *configs.Resource Config *configs.Resource
ProviderAddr addrs.AbsProviderConfig 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 // can refer to it. Since this node represents the abstract module, we need
// to expand the module here to create all resources. // to expand the module here to create all resources.
expander := ctx.InstanceExpander() 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 // 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.Absolute(module), eachMode, n.ProviderAddr)
switch eachMode { switch eachMode {
case states.EachList: case states.EachList:
expander.SetResourceCount(module, n.Addr, count) expander.SetResourceCount(module, n.Addr.Resource, count)
case states.EachMap: case states.EachMap:
expander.SetResourceForEach(module, n.Addr, forEach) expander.SetResourceForEach(module, n.Addr.Resource, forEach)
default: 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 continue
} }
switch tv.Addr.Name { switch tv.Addr.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":

View File

@ -59,7 +59,7 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
// 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.Module) { 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(path, n.ResourceAddr().Resource, count)

View File

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

View File

@ -110,8 +110,8 @@ func (n *evalPrepareModuleExpansion) Eval(ctx EvalContext) (interface{}, error)
eachMode = states.EachMap eachMode = states.EachMap
} }
// nodeExpandModule itself does not have visibility into how it's ancestors // nodeExpandModule itself does not have visibility into how its ancestors
// were expended, so we use the expander here to provide all possible paths // were expanded, so we use the expander here to provide all possible paths
// to our module, and register module instances with each of them. // to our module, and register module instances with each of them.
for _, path := range expander.ExpandModule(n.Addr.Parent()) { for _, path := range expander.ExpandModule(n.Addr.Parent()) {
switch eachMode { switch eachMode {

View File

@ -32,7 +32,7 @@ func (n *NodeModuleRemoved) Path() addrs.ModuleInstance {
// GraphNodeModulePath implementation // GraphNodeModulePath implementation
func (n *NodeModuleRemoved) ModulePath() addrs.Module { func (n *NodeModuleRemoved) ModulePath() addrs.Module {
// This node represents the module call within a 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 // call may expand into multiple child instances
return n.Addr.Module() return n.Addr.Module()
} }

View File

@ -41,6 +41,8 @@ func (n *NodeAbstractProvider) Name() string {
// GraphNodeModuleInstance // GraphNodeModuleInstance
func (n *NodeAbstractProvider) Path() addrs.ModuleInstance { 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() return n.Addr.Module.UnkeyedInstanceShim()
} }

View File

@ -14,7 +14,7 @@ type NodeDisabledProvider struct {
} }
var ( var (
_ GraphNodeModuleInstance = (*NodeDisabledProvider)(nil) _ GraphNodeModulePath = (*NodeDisabledProvider)(nil)
_ RemovableIfNotTargeted = (*NodeDisabledProvider)(nil) _ RemovableIfNotTargeted = (*NodeDisabledProvider)(nil)
_ GraphNodeReferencer = (*NodeDisabledProvider)(nil) _ GraphNodeReferencer = (*NodeDisabledProvider)(nil)
_ GraphNodeProvider = (*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 // operations. It registers all the interfaces for a resource that common
// across multiple operation types. // across multiple operation types.
type NodeAbstractResource struct { type NodeAbstractResource struct {
Addr addrs.Resource Addr addrs.ConfigResource
Module addrs.Module
// 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
@ -80,15 +79,18 @@ var (
) )
func (n *NodeAbstractResource) addr() addrs.AbsResource { 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 // 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.AbsResource) *NodeAbstractResource {
// FIXME: this should probably accept a ConfigResource
return &NodeAbstractResource{ return &NodeAbstractResource{
Addr: addr.Resource, Addr: addrs.ConfigResource{
Resource: addr.Resource,
Module: addr.Module.Module(), Module: addr.Module.Module(),
},
} }
} }
@ -136,9 +138,11 @@ func NewNodeAbstractResourceInstance(addr addrs.AbsResourceInstance) *NodeAbstra
// request. // request.
return &NodeAbstractResourceInstance{ return &NodeAbstractResourceInstance{
NodeAbstractResource: NodeAbstractResource{ NodeAbstractResource: NodeAbstractResource{
Addr: addr.Resource.Resource, Addr: addrs.ConfigResource{
Resource: addr.Resource.Resource,
Module: addr.Module.Module(), Module: addr.Module.Module(),
}, },
},
ModuleInstance: addr.Module, ModuleInstance: addr.Module,
InstanceKey: addr.Resource.Key, InstanceKey: addr.Resource.Key,
} }
@ -154,7 +158,7 @@ func (n *NodeAbstractResourceInstance) Name() string {
// GraphNodeModuleInstance // GraphNodeModuleInstance
func (n *NodeAbstractResource) Path() addrs.ModuleInstance { func (n *NodeAbstractResource) Path() addrs.ModuleInstance {
return n.Module.UnkeyedInstanceShim() return n.Addr.Module.UnkeyedInstanceShim()
} }
func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance { func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
@ -163,12 +167,12 @@ func (n *NodeAbstractResourceInstance) Path() addrs.ModuleInstance {
// GraphNodeModulePath // GraphNodeModulePath
func (n *NodeAbstractResource) ModulePath() addrs.Module { func (n *NodeAbstractResource) ModulePath() addrs.Module {
return n.Module return n.Addr.Module
} }
// GraphNodeReferenceable // GraphNodeReferenceable
func (n *NodeAbstractResource) ReferenceableAddrs() []addrs.Referenceable { func (n *NodeAbstractResource) ReferenceableAddrs() []addrs.Referenceable {
return []addrs.Referenceable{n.Addr} return []addrs.Referenceable{n.Addr.Resource}
} }
// GraphNodeReferenceable // GraphNodeReferenceable
@ -314,7 +318,7 @@ func (n *NodeAbstractResource) ProvidedBy() (addrs.ProviderConfig, bool) {
// GraphNodeProviderConsumer // GraphNodeProviderConsumer
func (n *NodeAbstractResource) ImpliedProvider() addrs.Provider { func (n *NodeAbstractResource) ImpliedProvider() addrs.Provider {
return n.Addr.DefaultProvider() return n.Addr.Resource.DefaultProvider()
} }
// GraphNodeProviderConsumer // GraphNodeProviderConsumer
@ -342,7 +346,7 @@ func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.ProviderConfig, bool)
// GraphNodeProviderConsumer // GraphNodeProviderConsumer
func (n *NodeAbstractResourceInstance) ImpliedProvider() addrs.Provider { func (n *NodeAbstractResourceInstance) ImpliedProvider() addrs.Provider {
return n.Addr.DefaultProvider() return n.Addr.Resource.DefaultProvider()
} }
// GraphNodeProvisionerConsumer // GraphNodeProvisionerConsumer

View File

@ -61,7 +61,6 @@ func (n *NodeApplyableResource) EvalTree() EvalNode {
return &EvalWriteResourceState{ return &EvalWriteResourceState{
Addr: n.Addr, Addr: n.Addr,
Module: n.Module,
Config: n.Config, Config: n.Config,
ProviderAddr: n.ResolvedProvider, 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 // this ensures we can reference the resource even if the count is 0
return &EvalWriteResourceState{ return &EvalWriteResourceState{
Addr: n.Addr, Addr: n.Addr,
Module: n.Module,
Config: n.Config, Config: n.Config,
ProviderAddr: n.ResolvedProvider, 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, // 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.Module) { 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(module, n.ResourceAddr().Resource, count)
@ -70,7 +70,7 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
expander.SetResourceSingle(module, n.ResourceAddr().Resource) 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 // 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.

View File

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

View File

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

View File

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