WIP reference providers by full name
This turned out to be a big messy commit, since the way providers are referenced is tightly coupled throughout the code. That starts to unify how providers are referenced, using the format output node Name method. Add a new field to the internal resource data types called ResolvedProvider. This is set by a new setter method SetProvider when a resource is connected to a provider during graph creation. This allows us to later lookup the provider instance a resource is connected to, without requiring it to have the same module path. The InitProvider context method now takes 2 arguments, one if the provider type and the second is the full name of the provider. While the provider type could still be parsed from the full name, this makes it more explicit and, and changes to the name format won't effect this code.
This commit is contained in:
parent
1d54d4b10d
commit
a14fd0344c
|
@ -861,7 +861,7 @@ func TestContext2Apply_createBeforeDestroy(t *testing.T) {
|
|||
actual := strings.TrimSpace(state.String())
|
||||
expected := strings.TrimSpace(testTerraformApplyCreateBeforeStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: \n%s", actual)
|
||||
t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -687,13 +687,10 @@ func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) {
|
|||
}
|
||||
|
||||
expected := []string{
|
||||
"root\n",
|
||||
// this test originally verified that a parent provider config can
|
||||
// partially override a child. That's no longer the case, so the child
|
||||
// config is used in its entirety here.
|
||||
//"root\nchild\n",
|
||||
"child\nchild\n",
|
||||
"root\n",
|
||||
}
|
||||
sort.Strings(calls)
|
||||
if !reflect.DeepEqual(calls, expected) {
|
||||
t.Fatalf("expected:\n%#v\ngot:\n%#v\n", expected, calls)
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ type EvalContext interface {
|
|||
// Input is the UIInput object for interacting with the UI.
|
||||
Input() UIInput
|
||||
|
||||
// InitProvider initializes the provider with the given name and
|
||||
// InitProvider initializes the provider with the given type and name, and
|
||||
// returns the implementation of the resource provider or an error.
|
||||
//
|
||||
// It is an error to initialize the same provider more than once.
|
||||
InitProvider(string) (ResourceProvider, error)
|
||||
InitProvider(typ string, name string) (ResourceProvider, error)
|
||||
|
||||
// Provider gets the provider instance with the given name (already
|
||||
// initialized) or returns nil if the provider isn't initialized.
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
|
@ -79,12 +78,12 @@ func (ctx *BuiltinEvalContext) Input() UIInput {
|
|||
return ctx.InputValue
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) InitProvider(n string) (ResourceProvider, error) {
|
||||
func (ctx *BuiltinEvalContext) InitProvider(typeName, name string) (ResourceProvider, error) {
|
||||
ctx.once.Do(ctx.init)
|
||||
|
||||
// If we already initialized, it is an error
|
||||
if p := ctx.Provider(n); p != nil {
|
||||
return nil, fmt.Errorf("Provider '%s' already initialized", n)
|
||||
if p := ctx.Provider(name); p != nil {
|
||||
return nil, fmt.Errorf("Provider '%s' already initialized", name)
|
||||
}
|
||||
|
||||
// Warning: make sure to acquire these locks AFTER the call to Provider
|
||||
|
@ -92,13 +91,12 @@ func (ctx *BuiltinEvalContext) InitProvider(n string) (ResourceProvider, error)
|
|||
ctx.ProviderLock.Lock()
|
||||
defer ctx.ProviderLock.Unlock()
|
||||
|
||||
typeName := strings.SplitN(n, ".", 2)[0]
|
||||
p, err := ctx.Components.ResourceProvider(typeName, n)
|
||||
p, err := ctx.Components.ResourceProvider(typeName, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.ProviderCache[n] = p
|
||||
ctx.ProviderCache[name] = p
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ func (c *MockEvalContext) Input() UIInput {
|
|||
return c.InputInput
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) InitProvider(n string) (ResourceProvider, error) {
|
||||
func (c *MockEvalContext) InitProvider(t, n string) (ResourceProvider, error) {
|
||||
c.InitProviderCalled = true
|
||||
c.InitProviderName = n
|
||||
return c.InitProviderProvider, c.InitProviderError
|
||||
|
|
|
@ -52,11 +52,12 @@ func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|||
// and returns nothing. The provider can be retrieved again with the
|
||||
// EvalGetProvider node.
|
||||
type EvalInitProvider struct {
|
||||
Name string
|
||||
TypeName string
|
||||
Name string
|
||||
}
|
||||
|
||||
func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) {
|
||||
return ctx.InitProvider(n.Name)
|
||||
return ctx.InitProvider(n.TypeName, n.Name)
|
||||
}
|
||||
|
||||
// EvalCloseProvider is an EvalNode implementation that closes provider
|
||||
|
@ -129,6 +130,7 @@ func (n *EvalInputProvider) Eval(ctx EvalContext) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.SetProviderInput(n.Name, confMap)
|
||||
|
||||
return nil, nil
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
)
|
||||
|
||||
// ProviderEvalTree returns the evaluation tree for initializing and
|
||||
// configuring providers.
|
||||
func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
||||
func ProviderEvalTree(n *NodeApplyableProvider, config *config.ProviderConfig) EvalNode {
|
||||
var provider ResourceProvider
|
||||
var resourceConfig *ResourceConfig
|
||||
|
||||
typeName := strings.SplitN(n.NameValue, ".", 2)[0]
|
||||
|
||||
seq := make([]EvalNode, 0, 5)
|
||||
seq = append(seq, &EvalInitProvider{Name: n})
|
||||
seq = append(seq, &EvalInitProvider{
|
||||
TypeName: typeName,
|
||||
Name: n.Name(),
|
||||
})
|
||||
|
||||
// Input stuff
|
||||
seq = append(seq, &EvalOpFilter{
|
||||
|
@ -19,7 +26,7 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n,
|
||||
Name: n.Name(),
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalInterpolateProvider{
|
||||
|
@ -27,12 +34,12 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalBuildProviderConfig{
|
||||
Provider: n,
|
||||
Provider: n.NameValue,
|
||||
Config: &resourceConfig,
|
||||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalInputProvider{
|
||||
Name: n,
|
||||
Name: n.NameValue,
|
||||
Provider: &provider,
|
||||
Config: &resourceConfig,
|
||||
},
|
||||
|
@ -45,7 +52,7 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n,
|
||||
Name: n.Name(),
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalInterpolateProvider{
|
||||
|
@ -53,7 +60,7 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalBuildProviderConfig{
|
||||
Provider: n,
|
||||
Provider: n.NameValue,
|
||||
Config: &resourceConfig,
|
||||
Output: &resourceConfig,
|
||||
},
|
||||
|
@ -71,7 +78,7 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n,
|
||||
Name: n.Name(),
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalInterpolateProvider{
|
||||
|
@ -79,7 +86,7 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalBuildProviderConfig{
|
||||
Provider: n,
|
||||
Provider: n.NameValue,
|
||||
Config: &resourceConfig,
|
||||
Output: &resourceConfig,
|
||||
},
|
||||
|
@ -94,7 +101,7 @@ func ProviderEvalTree(n string, config *config.ProviderConfig) EvalNode {
|
|||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalConfigProvider{
|
||||
Provider: n,
|
||||
Provider: n.Name(),
|
||||
Config: &resourceConfig,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -52,6 +52,13 @@ func (b *ImportGraphBuilder) Steps() []GraphTransformer {
|
|||
// Add the import steps
|
||||
&ImportStateTransformer{Targets: b.ImportTargets},
|
||||
|
||||
// add configured providers
|
||||
&ProviderConfigTransformer{
|
||||
Module: b.Module,
|
||||
Providers: b.Providers,
|
||||
Concrete: concreteProvider,
|
||||
},
|
||||
|
||||
// Provider-related transformations
|
||||
&MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider},
|
||||
&ProviderTransformer{},
|
||||
|
|
|
@ -126,6 +126,13 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
|
|||
// Add root variables
|
||||
&RootVariableTransformer{Module: b.Module},
|
||||
|
||||
// add configured providers
|
||||
&ProviderConfigTransformer{
|
||||
Module: b.Module,
|
||||
Providers: b.Providers,
|
||||
Concrete: concreteProvider,
|
||||
},
|
||||
|
||||
// Create all the providers
|
||||
&MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider},
|
||||
&ProviderTransformer{},
|
||||
|
|
|
@ -27,6 +27,7 @@ func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, er
|
|||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
|
||||
return &NodeRefreshableDataResourceInstance{
|
||||
NodeAbstractResource: a,
|
||||
|
@ -185,7 +186,7 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
|
|||
// provider configurations that need this data during
|
||||
// refresh/plan.
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
|
||||
|
|
|
@ -7,5 +7,5 @@ type NodeApplyableProvider struct {
|
|||
|
||||
// GraphNodeEvalable
|
||||
func (n *NodeApplyableProvider) EvalTree() EvalNode {
|
||||
return ProviderEvalTree(n.NameValue, n.ProviderConfig())
|
||||
return ProviderEvalTree(n, n.ProviderConfig())
|
||||
}
|
||||
|
|
|
@ -24,13 +24,17 @@ type NodeAbstractProvider struct {
|
|||
Config *config.ProviderConfig
|
||||
}
|
||||
|
||||
func (n *NodeAbstractProvider) Name() string {
|
||||
result := fmt.Sprintf("provider.%s", n.NameValue)
|
||||
if len(n.PathValue) > 1 {
|
||||
result = fmt.Sprintf("%s.%s", modulePrefixStr(n.PathValue), result)
|
||||
func ResolveProviderName(name string, path []string) string {
|
||||
name = fmt.Sprintf("provider.%s", name)
|
||||
if len(path) > 1 {
|
||||
name = fmt.Sprintf("%s.%s", modulePrefixStr(path), name)
|
||||
}
|
||||
|
||||
return result
|
||||
return name
|
||||
}
|
||||
|
||||
func (n *NodeAbstractProvider) Name() string {
|
||||
return ResolveProviderName(n.NameValue, n.PathValue)
|
||||
}
|
||||
|
||||
// GraphNodeSubPath
|
||||
|
|
|
@ -33,6 +33,9 @@ type NodeAbstractResource struct {
|
|||
ResourceState *ResourceState // ResourceState is the ResourceState for this
|
||||
|
||||
Targets []ResourceAddress // Set from GraphNodeTargetable
|
||||
|
||||
// The address of the provider this resource will use
|
||||
ResolvedProvider string
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResource) Name() string {
|
||||
|
@ -170,6 +173,10 @@ func (n *NodeAbstractResource) StateReferences() []string {
|
|||
return deps
|
||||
}
|
||||
|
||||
func (n *NodeAbstractResource) SetProvider(p string) {
|
||||
n.ResolvedProvider = p
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResource) ProvidedBy() []string {
|
||||
// If we have a config we prefer that above all else
|
||||
|
|
|
@ -135,7 +135,7 @@ func (n *NodeApplyableResource) evalTreeDataResource(
|
|||
},
|
||||
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
|
||||
|
@ -242,7 +242,7 @@ func (n *NodeApplyableResource) evalTreeManagedResource(
|
|||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadState{
|
||||
|
@ -283,7 +283,7 @@ func (n *NodeApplyableResource) evalTreeManagedResource(
|
|||
},
|
||||
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadState{
|
||||
|
|
|
@ -102,8 +102,9 @@ func (n *NodeDestroyResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
|||
|
||||
// We want deposed resources in the state to be destroyed
|
||||
steps = append(steps, &DeposedTransformer{
|
||||
State: state,
|
||||
View: n.Addr.stateId(),
|
||||
State: state,
|
||||
View: n.Addr.stateId(),
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
})
|
||||
|
||||
// Target
|
||||
|
@ -188,7 +189,7 @@ func (n *NodeDestroyResource) EvalTree() EvalNode {
|
|||
&EvalInstanceInfo{Info: info},
|
||||
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadState{
|
||||
|
|
|
@ -27,6 +27,7 @@ func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
|||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
|
||||
return &NodePlannableResourceInstance{
|
||||
NodeAbstractResource: a,
|
||||
|
@ -37,6 +38,7 @@ func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
|||
concreteResourceOrphan := func(a *NodeAbstractResource) dag.Vertex {
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
|
||||
return &NodePlannableResourceOrphan{
|
||||
NodeAbstractResource: a,
|
||||
|
|
|
@ -97,7 +97,7 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(
|
|||
},
|
||||
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
|
||||
|
@ -143,7 +143,7 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(
|
|||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
// Re-run validation to catch any errors we missed, e.g. type
|
||||
|
|
|
@ -30,6 +30,7 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
|
|||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
|
||||
return &NodeRefreshableManagedResourceInstance{
|
||||
NodeAbstractResource: a,
|
||||
|
@ -149,7 +150,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
|
|||
return &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadState{
|
||||
|
@ -220,7 +221,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState(
|
|||
Output: &resourceConfig,
|
||||
},
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
// Re-run validation to catch any errors we missed, e.g. type
|
||||
|
|
|
@ -39,6 +39,7 @@ func (n *NodeValidatableResource) DynamicExpand(ctx EvalContext) (*Graph, error)
|
|||
concreteResource := func(a *NodeAbstractResource) dag.Vertex {
|
||||
// Add the config and state since we don't do that via transforms
|
||||
a.Config = n.Config
|
||||
a.ResolvedProvider = n.ResolvedProvider
|
||||
|
||||
return &NodeValidatableResourceInstance{
|
||||
NodeAbstractResource: a,
|
||||
|
@ -108,7 +109,7 @@ func (n *NodeValidatableResourceInstance) EvalTree() EvalNode {
|
|||
Config: &n.Config.RawConfig,
|
||||
},
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalInterpolate{
|
||||
|
|
|
@ -12,6 +12,9 @@ type DeposedTransformer struct {
|
|||
// View, if non-empty, is the ModuleState.View used around the state
|
||||
// to find deposed resources.
|
||||
View string
|
||||
|
||||
// The provider used by the resourced which were deposed
|
||||
ResolvedProvider string
|
||||
}
|
||||
|
||||
func (t *DeposedTransformer) Transform(g *Graph) error {
|
||||
|
@ -33,14 +36,16 @@ func (t *DeposedTransformer) Transform(g *Graph) error {
|
|||
if len(rs.Deposed) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
deposed := rs.Deposed
|
||||
|
||||
for i, _ := range deposed {
|
||||
g.Add(&graphNodeDeposedResource{
|
||||
Index: i,
|
||||
ResourceName: k,
|
||||
ResourceType: rs.Type,
|
||||
Provider: rs.Provider,
|
||||
Index: i,
|
||||
ResourceName: k,
|
||||
ResourceType: rs.Type,
|
||||
ProviderName: rs.Provider,
|
||||
ResolvedProvider: t.ResolvedProvider,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -50,10 +55,11 @@ func (t *DeposedTransformer) Transform(g *Graph) error {
|
|||
|
||||
// graphNodeDeposedResource is the graph vertex representing a deposed resource.
|
||||
type graphNodeDeposedResource struct {
|
||||
Index int
|
||||
ResourceName string
|
||||
ResourceType string
|
||||
Provider string
|
||||
Index int
|
||||
ResourceName string
|
||||
ResourceType string
|
||||
ProviderName string
|
||||
ResolvedProvider string
|
||||
}
|
||||
|
||||
func (n *graphNodeDeposedResource) Name() string {
|
||||
|
@ -61,7 +67,11 @@ func (n *graphNodeDeposedResource) Name() string {
|
|||
}
|
||||
|
||||
func (n *graphNodeDeposedResource) ProvidedBy() []string {
|
||||
return []string{resourceProvider(n.ResourceName, n.Provider)}
|
||||
return []string{resourceProvider(n.ResourceName, n.ProviderName)}
|
||||
}
|
||||
|
||||
func (n *graphNodeDeposedResource) SetProvider(p string) {
|
||||
n.ResolvedProvider = p
|
||||
}
|
||||
|
||||
// GraphNodeEvalable impl.
|
||||
|
@ -81,7 +91,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
|
|||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadStateDeposed{
|
||||
|
@ -98,7 +108,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
|
|||
&EvalWriteStateDeposed{
|
||||
Name: n.ResourceName,
|
||||
ResourceType: n.ResourceType,
|
||||
Provider: n.Provider,
|
||||
Provider: n.ProviderName,
|
||||
State: &state,
|
||||
Index: n.Index,
|
||||
},
|
||||
|
@ -114,7 +124,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
|
|||
Node: &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalReadStateDeposed{
|
||||
|
@ -147,7 +157,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
|
|||
&EvalWriteStateDeposed{
|
||||
Name: n.ResourceName,
|
||||
ResourceType: n.ResourceType,
|
||||
Provider: n.Provider,
|
||||
Provider: n.ProviderName,
|
||||
State: &state,
|
||||
Index: n.Index,
|
||||
},
|
||||
|
|
|
@ -21,9 +21,9 @@ func (t *ImportStateTransformer) Transform(g *Graph) error {
|
|||
}
|
||||
|
||||
nodes = append(nodes, &graphNodeImportState{
|
||||
Addr: addr,
|
||||
ID: target.ID,
|
||||
Provider: target.Provider,
|
||||
Addr: addr,
|
||||
ID: target.ID,
|
||||
ProviderName: target.Provider,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,10 @@ func (t *ImportStateTransformer) Transform(g *Graph) error {
|
|||
}
|
||||
|
||||
type graphNodeImportState struct {
|
||||
Addr *ResourceAddress // Addr is the resource address to import to
|
||||
ID string // ID is the ID to import as
|
||||
Provider string // Provider string
|
||||
Addr *ResourceAddress // Addr is the resource address to import to
|
||||
ID string // ID is the ID to import as
|
||||
ProviderName string // Provider string
|
||||
ResolvedProvider string // provider node address
|
||||
|
||||
states []*InstanceState
|
||||
}
|
||||
|
@ -48,7 +49,11 @@ func (n *graphNodeImportState) Name() string {
|
|||
}
|
||||
|
||||
func (n *graphNodeImportState) ProvidedBy() []string {
|
||||
return []string{resourceProvider(n.Addr.Type, n.Provider)}
|
||||
return []string{resourceProvider(n.Addr.Type, n.ProviderName)}
|
||||
}
|
||||
|
||||
func (n *graphNodeImportState) SetProvider(p string) {
|
||||
n.ResolvedProvider = p
|
||||
}
|
||||
|
||||
// GraphNodeSubPath
|
||||
|
@ -72,7 +77,7 @@ func (n *graphNodeImportState) EvalTree() EvalNode {
|
|||
return &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: n.ProvidedBy()[0],
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalImportState{
|
||||
|
@ -149,10 +154,11 @@ func (n *graphNodeImportState) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
|||
// is safe.
|
||||
for i, state := range n.states {
|
||||
g.Add(&graphNodeImportStateSub{
|
||||
Target: addrs[i],
|
||||
Path_: n.Path(),
|
||||
State: state,
|
||||
Provider: n.Provider,
|
||||
Target: addrs[i],
|
||||
Path_: n.Path(),
|
||||
State: state,
|
||||
ProviderName: n.ProviderName,
|
||||
ResolvedProvider: n.ResolvedProvider,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -170,10 +176,11 @@ func (n *graphNodeImportState) DynamicExpand(ctx EvalContext) (*Graph, error) {
|
|||
// and is part of the subgraph. This node is responsible for refreshing
|
||||
// and adding a resource to the state once it is imported.
|
||||
type graphNodeImportStateSub struct {
|
||||
Target *ResourceAddress
|
||||
State *InstanceState
|
||||
Path_ []string
|
||||
Provider string
|
||||
Target *ResourceAddress
|
||||
State *InstanceState
|
||||
Path_ []string
|
||||
ProviderName string
|
||||
ResolvedProvider string
|
||||
}
|
||||
|
||||
func (n *graphNodeImportStateSub) Name() string {
|
||||
|
@ -216,7 +223,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode {
|
|||
return &EvalSequence{
|
||||
Nodes: []EvalNode{
|
||||
&EvalGetProvider{
|
||||
Name: resourceProvider(info.Type, n.Provider),
|
||||
Name: n.ResolvedProvider,
|
||||
Output: &provider,
|
||||
},
|
||||
&EvalRefresh{
|
||||
|
@ -233,7 +240,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode {
|
|||
&EvalWriteState{
|
||||
Name: key.String(),
|
||||
ResourceType: info.Type,
|
||||
Provider: resourceProvider(info.Type, n.Provider),
|
||||
Provider: resourceProvider(info.Type, n.ProviderName),
|
||||
State: &state,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -10,10 +10,12 @@ import (
|
|||
)
|
||||
|
||||
// GraphNodeProvider is an interface that nodes that can be a provider
|
||||
// must implement. The ProviderName returned is the name of the provider
|
||||
// they satisfy.
|
||||
// must implement.
|
||||
// ProviderName returns the name of the provider this satisfies.
|
||||
// Name returns the full name of the provider in the config.
|
||||
type GraphNodeProvider interface {
|
||||
ProviderName() string
|
||||
Name() string
|
||||
}
|
||||
|
||||
// GraphNodeCloseProvider is an interface that nodes that can be a close
|
||||
|
@ -29,6 +31,8 @@ type GraphNodeCloseProvider interface {
|
|||
type GraphNodeProviderConsumer interface {
|
||||
// TODO: make this return s string instead of a []string
|
||||
ProvidedBy() []string
|
||||
// Set the resolved provider address for this resource.
|
||||
SetProvider(string)
|
||||
}
|
||||
|
||||
// ProviderTransformer is a GraphTransformer that maps resources to
|
||||
|
@ -58,19 +62,16 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
|||
|
||||
// if we don't have a provider at this level, walk up the path looking for one
|
||||
for i := 1; target == nil; i++ {
|
||||
pathPrefix := ""
|
||||
raw := normalizeModulePath(sp.Path())
|
||||
if len(raw) < i {
|
||||
path := normalizeModulePath(sp.Path())
|
||||
if len(path) < i {
|
||||
break
|
||||
}
|
||||
|
||||
raw = raw[:len(raw)-i]
|
||||
|
||||
if len(raw) > len(rootModulePath) {
|
||||
pathPrefix = modulePrefixStr(raw) + "."
|
||||
}
|
||||
key = pathPrefix + p
|
||||
key = ResolveProviderName(p, path[:len(path)-i])
|
||||
target = m[key]
|
||||
if target != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if target == nil {
|
||||
|
@ -80,6 +81,7 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
|||
break
|
||||
}
|
||||
|
||||
pv.SetProvider(key)
|
||||
g.Connect(dag.BasicEdge(v, target))
|
||||
}
|
||||
}
|
||||
|
@ -95,36 +97,32 @@ type CloseProviderTransformer struct{}
|
|||
|
||||
func (t *CloseProviderTransformer) Transform(g *Graph) error {
|
||||
pm := providerVertexMap(g)
|
||||
cpm := closeProviderVertexMap(g)
|
||||
cpm := make(map[string]*graphNodeCloseProvider)
|
||||
var err error
|
||||
for _, v := range g.Vertices() {
|
||||
if pv, ok := v.(GraphNodeProviderConsumer); ok {
|
||||
for _, p := range pv.ProvidedBy() {
|
||||
key := p
|
||||
source := cpm[key]
|
||||
|
||||
if source == nil {
|
||||
// Create a new graphNodeCloseProvider and add it to the graph
|
||||
source = &graphNodeCloseProvider{ProviderNameValue: p}
|
||||
g.Add(source)
|
||||
for _, v := range pm {
|
||||
p := v.(GraphNodeProvider)
|
||||
|
||||
// Close node needs to depend on provider
|
||||
provider, ok := pm[key]
|
||||
if !ok {
|
||||
err = multierror.Append(err, fmt.Errorf(
|
||||
"%s: provider %s couldn't be found for closing",
|
||||
dag.VertexName(v), p))
|
||||
continue
|
||||
}
|
||||
g.Connect(dag.BasicEdge(source, provider))
|
||||
// get the close provider of this type if we alread created it
|
||||
closer := cpm[p.ProviderName()]
|
||||
|
||||
// Make sure we also add the new graphNodeCloseProvider to the map
|
||||
// so we don't create and add any duplicate graphNodeCloseProviders.
|
||||
cpm[key] = source
|
||||
}
|
||||
if closer == nil {
|
||||
// create a closer for this provider type
|
||||
closer = &graphNodeCloseProvider{ProviderNameValue: p.ProviderName()}
|
||||
g.Add(closer)
|
||||
cpm[p.ProviderName()] = closer
|
||||
}
|
||||
|
||||
// Close node depends on all nodes provided by the provider
|
||||
g.Connect(dag.BasicEdge(source, v))
|
||||
// Close node depends on the provider itself
|
||||
// this is added unconditionally, so it will connect to all instances
|
||||
// of the provider. Extra edges will be removed by transitive
|
||||
// reduction.
|
||||
g.Connect(dag.BasicEdge(closer, p))
|
||||
|
||||
// connect all the provider's resources to the close node
|
||||
for _, s := range g.UpEdges(p).List() {
|
||||
if _, ok := s.(GraphNodeResource); ok {
|
||||
g.Connect(dag.BasicEdge(closer, s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,54 +185,47 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
|||
}
|
||||
}
|
||||
|
||||
for _, p := range pv.ProvidedBy() {
|
||||
// always add the parent nodes to check, since configured providers
|
||||
// may have already been added for modules.
|
||||
if len(path) > 0 {
|
||||
// We'll need the parent provider as well, so let's
|
||||
// add a dummy node to check to make sure that we add
|
||||
// that parent provider.
|
||||
check = append(check, &graphNodeProviderConsumerDummy{
|
||||
ProviderValue: p,
|
||||
PathValue: path[:len(path)-1],
|
||||
})
|
||||
}
|
||||
p := pv.ProvidedBy()[0]
|
||||
// always add the parent nodes to check, since configured providers
|
||||
// may have already been added for modules.
|
||||
if len(path) > 0 {
|
||||
// We'll need the parent provider as well, so let's
|
||||
// add a dummy node to check to make sure that we add
|
||||
// that parent provider.
|
||||
check = append(check, &graphNodeProviderConsumerDummy{
|
||||
ProviderValue: p,
|
||||
PathValue: path[:len(path)-1],
|
||||
})
|
||||
}
|
||||
|
||||
key := providerMapKey(p, pv)
|
||||
key := providerMapKey(p, pv)
|
||||
if _, ok := m[key]; ok {
|
||||
// This provider already exists as a configure node
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: jbardin come back to this
|
||||
// only adding root level missing providers
|
||||
key = p
|
||||
if _, ok := m[key]; ok {
|
||||
// This provider already exists as a configure node
|
||||
// If the provider has an alias in it, we just want the type
|
||||
// TODO: jbardin -- stop adding aliased providers altogether
|
||||
ptype := p
|
||||
if idx := strings.IndexRune(p, '.'); idx != -1 {
|
||||
ptype = p[:idx]
|
||||
}
|
||||
|
||||
if !t.AllowAny {
|
||||
if _, ok := supported[ptype]; !ok {
|
||||
// If we don't support the provider type, skip it.
|
||||
// Validation later will catch this as an error.
|
||||
continue
|
||||
}
|
||||
|
||||
// If the provider has an alias in it, we just want the type
|
||||
// TODO: jbardin -- stop adding aliased providers altogether
|
||||
ptype := p
|
||||
if idx := strings.IndexRune(p, '.'); idx != -1 {
|
||||
ptype = p[:idx]
|
||||
}
|
||||
|
||||
if !t.AllowAny {
|
||||
if _, ok := supported[ptype]; !ok {
|
||||
// If we don't support the provider type, skip it.
|
||||
// Validation later will catch this as an error.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Add the missing provider node to the graph
|
||||
v := t.Concrete(&NodeAbstractProvider{
|
||||
NameValue: p,
|
||||
|
||||
// TODO: jbardin come back to this
|
||||
// only adding root level missing providers
|
||||
//PathValue: path,
|
||||
}).(dag.Vertex)
|
||||
m[key] = g.Add(v)
|
||||
}
|
||||
|
||||
// Add the missing provider node to the graph
|
||||
provider := t.Concrete(&NodeAbstractProvider{
|
||||
NameValue: p,
|
||||
PathValue: path,
|
||||
}).(dag.Vertex)
|
||||
|
||||
m[key] = g.Add(provider)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -274,15 +265,14 @@ func (t *ParentProviderTransformer) Transform(g *Graph) error {
|
|||
}
|
||||
path = normalizeModulePath(path)
|
||||
|
||||
// Build the key with path.name i.e. "child.subchild.aws"
|
||||
key := fmt.Sprintf("%s.%s", strings.Join(path, "."), pn.ProviderName())
|
||||
key := ResolveProviderName(pn.ProviderName(), path)
|
||||
m[key] = raw
|
||||
|
||||
// Determine the parent if we're non-root. This is length 1 since
|
||||
// the 0 index should be "root" since we normalize above.
|
||||
if len(path) > 1 {
|
||||
path = path[:len(path)-1]
|
||||
key := fmt.Sprintf("%s.%s", strings.Join(path, "."), pn.ProviderName())
|
||||
key := ResolveProviderName(pn.ProviderName(), path)
|
||||
parentMap[raw] = key
|
||||
}
|
||||
}
|
||||
|
@ -323,23 +313,19 @@ func (t *PruneProviderTransformer) Transform(g *Graph) error {
|
|||
// providerMapKey is a helper that gives us the key to use for the
|
||||
// maps returned by things such as providerVertexMap.
|
||||
func providerMapKey(k string, v dag.Vertex) string {
|
||||
pathPrefix := ""
|
||||
// we create a dummy provider to
|
||||
var path []string
|
||||
if sp, ok := v.(GraphNodeSubPath); ok {
|
||||
raw := normalizeModulePath(sp.Path())
|
||||
if len(raw) > len(rootModulePath) {
|
||||
pathPrefix = modulePrefixStr(raw) + "."
|
||||
}
|
||||
path = normalizeModulePath(sp.Path())
|
||||
}
|
||||
|
||||
return pathPrefix + k
|
||||
return ResolveProviderName(k, path)
|
||||
}
|
||||
|
||||
func providerVertexMap(g *Graph) map[string]dag.Vertex {
|
||||
m := make(map[string]dag.Vertex)
|
||||
for _, v := range g.Vertices() {
|
||||
if pv, ok := v.(GraphNodeProvider); ok {
|
||||
key := providerMapKey(pv.ProviderName(), v)
|
||||
m[key] = v
|
||||
m[pv.Name()] = v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,3 +402,5 @@ func (n *graphNodeProviderConsumerDummy) Path() []string {
|
|||
func (n *graphNodeProviderConsumerDummy) ProvidedBy() []string {
|
||||
return []string{n.ProviderValue}
|
||||
}
|
||||
|
||||
func (n *graphNodeProviderConsumerDummy) SetProvider(string) {}
|
||||
|
|
|
@ -256,7 +256,7 @@ func TestMissingProviderTransformer_moduleGrandchild(t *testing.T) {
|
|||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformMissingProviderModuleGrandchildStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad:\n\n%s", actual)
|
||||
t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -335,8 +335,13 @@ func ReferenceFromInterpolatedVar(v config.InterpolatedVariable) []string {
|
|||
}
|
||||
|
||||
func modulePrefixStr(p []string) string {
|
||||
// strip "root"
|
||||
if len(p) > 0 && p[0] == rootModulePath[0] {
|
||||
p = p[1:]
|
||||
}
|
||||
|
||||
parts := make([]string, 0, len(p)*2)
|
||||
for _, p := range p[1:] {
|
||||
for _, p := range p {
|
||||
parts = append(parts, "module", p)
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,9 @@ func (t *ResourceCountTransformer) Transform(g *Graph) error {
|
|||
addr.Index = index
|
||||
|
||||
// Build the abstract node and the concrete one
|
||||
abstract := &NodeAbstractResource{Addr: addr}
|
||||
abstract := &NodeAbstractResource{
|
||||
Addr: addr,
|
||||
}
|
||||
var node dag.Vertex = abstract
|
||||
if f := t.Concrete; f != nil {
|
||||
node = f(abstract)
|
||||
|
|
Loading…
Reference in New Issue