save resolved providers for resources to state

Use the ResourceState.Provider field to store the full name of the
provider used during apply. This field is only used when a resource is
removed from the config, and will allow that resource to be removed by
the exact same provider with which it was created.

Modify the locations which might accept the alue of the
ResourceState.Provider field to detect that the name is resolved.
This commit is contained in:
James Bardin 2017-11-07 13:09:36 -05:00
parent 990acca758
commit b79adeae02
10 changed files with 31 additions and 13 deletions

View File

@ -261,7 +261,9 @@ func (r *Resource) ProviderFullName() string {
// the provider name is inferred from the resource type name.
func ResourceProviderFullName(resourceType, explicitProvider string) string {
if explicitProvider != "" {
return explicitProvider
// check for an explicit provider name, or return the original
parts := strings.SplitAfter(explicitProvider, "provider.")
return parts[len(parts)-1]
}
idx := strings.IndexRune(resourceType, '_')

View File

@ -147,6 +147,7 @@ func TestNewContextState(t *testing.T) {
}
func testContext2(t *testing.T, opts *ContextOpts) *Context {
t.Helper()
// Enable the shadow graph
opts.Shadow = true

View File

@ -108,7 +108,9 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
// Get the state if we have it, if not we build it
rs := n.ResourceState
if rs == nil {
rs = &ResourceState{}
rs = &ResourceState{
Provider: n.ResolvedProvider,
}
}
// If the config isn't empty we update the state

View File

@ -2,6 +2,7 @@ package terraform
import (
"fmt"
"strings"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/dag"
@ -25,6 +26,11 @@ type NodeAbstractProvider struct {
}
func ResolveProviderName(name string, path []string) string {
if strings.Contains(name, "provider.") {
// already resolved
return name
}
name = fmt.Sprintf("provider.%s", name)
if len(path) >= 1 {
name = fmt.Sprintf("%s.%s", modulePrefixStr(path), name)

View File

@ -158,7 +158,7 @@ func (n *NodeApplyableResource) evalTreeDataResource(
&EvalWriteState{
Name: stateId,
ResourceType: n.Config.Type,
Provider: n.Config.Provider,
Provider: n.ResolvedProvider,
Dependencies: stateDeps,
State: &state,
},
@ -308,7 +308,7 @@ func (n *NodeApplyableResource) evalTreeManagedResource(
&EvalWriteState{
Name: stateId,
ResourceType: n.Config.Type,
Provider: n.Config.Provider,
Provider: n.ResolvedProvider,
Dependencies: stateDeps,
State: &state,
},
@ -332,7 +332,7 @@ func (n *NodeApplyableResource) evalTreeManagedResource(
Else: &EvalWriteState{
Name: stateId,
ResourceType: n.Config.Type,
Provider: n.Config.Provider,
Provider: n.ResolvedProvider,
Dependencies: stateDeps,
State: &state,
},

View File

@ -149,7 +149,9 @@ func (n *NodeDestroyResource) EvalTree() EvalNode {
// Get our state
rs := n.ResourceState
if rs == nil {
rs = &ResourceState{}
rs = &ResourceState{
Provider: n.ResolvedProvider,
}
}
var diffApply *InstanceDiff

View File

@ -112,7 +112,7 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(
&EvalWriteState{
Name: stateId,
ResourceType: n.Config.Type,
Provider: n.Config.Provider,
Provider: n.ResolvedProvider,
Dependencies: stateDeps,
State: &state,
},
@ -177,7 +177,7 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(
&EvalWriteState{
Name: stateId,
ResourceType: n.Config.Type,
Provider: n.Config.Provider,
Provider: n.ResolvedProvider,
Dependencies: stateDeps,
State: &state,
},

View File

@ -251,7 +251,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState(
&EvalWriteState{
Name: stateID,
ResourceType: n.Config.Type,
Provider: n.Config.Provider,
Provider: n.ResolvedProvider,
Dependencies: stateDeps,
State: &state,
},

View File

@ -108,7 +108,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
&EvalWriteStateDeposed{
Name: n.ResourceName,
ResourceType: n.ResourceType,
Provider: n.ProviderName,
Provider: n.ResolvedProvider,
State: &state,
Index: n.Index,
},
@ -157,7 +157,7 @@ func (n *graphNodeDeposedResource) EvalTree() EvalNode {
&EvalWriteStateDeposed{
Name: n.ResourceName,
ResourceType: n.ResourceType,
Provider: n.ProviderName,
Provider: n.ResolvedProvider,
State: &state,
Index: n.Index,
},

View File

@ -52,7 +52,8 @@ type GraphNodeCloseProvider interface {
// GraphNodeProviderConsumer is an interface that nodes that require
// a provider must implement. ProvidedBy must return the name of the provider
// to use.
// to use. This may be a provider by type, type.alias or a fully resolved
// provider name
type GraphNodeProviderConsumer interface {
ProvidedBy() string
// Set the resolved provider address for this resource.
@ -127,7 +128,6 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
// in the graph are evaluated.
type CloseProviderTransformer struct{}
// FIXME: this doesn't close providers if the root provider is disabled
func (t *CloseProviderTransformer) Transform(g *Graph) error {
pm := providerVertexMap(g)
cpm := make(map[string]*graphNodeCloseProvider)
@ -286,6 +286,11 @@ 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 {
if strings.Contains(k, "provider.") {
// this is already resolved
return k
}
// we create a dummy provider to
var path []string
if sp, ok := v.(GraphNodeSubPath); ok {