]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / node_resource_refresh.go
index 6ab9df7a26f8a2b6f2edb91487858ea475a11ce7..697bd4942b9d51e1e3b9c0df2e6a1a421b2e31f3 100644 (file)
@@ -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,
@@ -45,13 +46,6 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
                        Addr:     n.ResourceAddr(),
                },
 
-               // Switch up any node missing state to a plannable resource. This helps
-               // catch cases where data sources depend on the counts from this resource
-               // during a scale out.
-               &ResourceRefreshPlannableTransformer{
-                       State: state,
-               },
-
                // Add the count orphans to make sure these resources are accounted for
                // during a scale in.
                &OrphanResourceCountTransformer{
@@ -100,6 +94,9 @@ func (n *NodeRefreshableManagedResourceInstance) EvalTree() EvalNode {
        // Eval info is different depending on what kind of resource this is
        switch mode := n.Addr.Mode; mode {
        case config.ManagedResourceMode:
+               if n.ResourceState == nil {
+                       return n.evalTreeManagedResourceNoState()
+               }
                return n.evalTreeManagedResource()
 
        case config.DataResourceMode:
@@ -153,7 +150,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
        return &EvalSequence{
                Nodes: []EvalNode{
                        &EvalGetProvider{
-                               Name:   n.ProvidedBy()[0],
+                               Name:   n.ResolvedProvider,
                                Output: &provider,
                        },
                        &EvalReadState{
@@ -169,10 +166,101 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
                        &EvalWriteState{
                                Name:         stateId,
                                ResourceType: n.ResourceState.Type,
-                               Provider:     n.ResourceState.Provider,
+                               Provider:     n.ResolvedProvider,
                                Dependencies: n.ResourceState.Dependencies,
                                State:        &state,
                        },
                },
        }
 }
+
+// evalTreeManagedResourceNoState produces an EvalSequence for refresh resource
+// nodes that don't have state attached. An example of where this functionality
+// is useful is when a resource that already exists in state is being scaled
+// out, ie: has its resource count increased. In this case, the scaled out node
+// needs to be available to other nodes (namely data sources) that may depend
+// on it for proper interpolation, or confusing "index out of range" errors can
+// occur.
+//
+// The steps in this sequence are very similar to the steps carried out in
+// plan, but nothing is done with the diff after it is created - it is dropped,
+// and its changes are not counted in the UI.
+func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState() EvalNode {
+       // Declare a bunch of variables that are used for state during
+       // evaluation. Most of this are written to by-address below.
+       var provider ResourceProvider
+       var state *InstanceState
+       var resourceConfig *ResourceConfig
+
+       addr := n.NodeAbstractResource.Addr
+       stateID := addr.stateId()
+       info := &InstanceInfo{
+               Id:         stateID,
+               Type:       addr.Type,
+               ModulePath: normalizeModulePath(addr.Path),
+       }
+
+       // Build the resource for eval
+       resource := &Resource{
+               Name:       addr.Name,
+               Type:       addr.Type,
+               CountIndex: addr.Index,
+       }
+       if resource.CountIndex < 0 {
+               resource.CountIndex = 0
+       }
+
+       // Determine the dependencies for the state.
+       stateDeps := n.StateReferences()
+
+       // n.Config can be nil if the config and state don't match
+       var raw *config.RawConfig
+       if n.Config != nil {
+               raw = n.Config.RawConfig.Copy()
+       }
+
+       return &EvalSequence{
+               Nodes: []EvalNode{
+                       &EvalInterpolate{
+                               Config:   raw,
+                               Resource: resource,
+                               Output:   &resourceConfig,
+                       },
+                       &EvalGetProvider{
+                               Name:   n.ResolvedProvider,
+                               Output: &provider,
+                       },
+                       // Re-run validation to catch any errors we missed, e.g. type
+                       // mismatches on computed values.
+                       &EvalValidateResource{
+                               Provider:       &provider,
+                               Config:         &resourceConfig,
+                               ResourceName:   n.Config.Name,
+                               ResourceType:   n.Config.Type,
+                               ResourceMode:   n.Config.Mode,
+                               IgnoreWarnings: true,
+                       },
+                       &EvalReadState{
+                               Name:   stateID,
+                               Output: &state,
+                       },
+                       &EvalDiff{
+                               Name:        stateID,
+                               Info:        info,
+                               Config:      &resourceConfig,
+                               Resource:    n.Config,
+                               Provider:    &provider,
+                               State:       &state,
+                               OutputState: &state,
+                               Stub:        true,
+                       },
+                       &EvalWriteState{
+                               Name:         stateID,
+                               ResourceType: n.Config.Type,
+                               Provider:     n.ResolvedProvider,
+                               Dependencies: stateDeps,
+                               State:        &state,
+                       },
+               },
+       }
+}