]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
vendor: github.com/hashicorp/terraform/...@v0.10.0
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / node_resource_refresh.go
index 3a44926cef76d51c8d32795403b2539996ffdd65..cd4fe9201ae4929a4863d028f1b9ef4035e8791b 100644 (file)
@@ -4,24 +4,98 @@ import (
        "fmt"
 
        "github.com/hashicorp/terraform/config"
+       "github.com/hashicorp/terraform/dag"
 )
 
-// NodeRefreshableResource represents a resource that is "applyable":
+// NodeRefreshableManagedResource represents a resource that is expanabled into
+// NodeRefreshableManagedResourceInstance. Resource count orphans are also added.
+type NodeRefreshableManagedResource struct {
+       *NodeAbstractCountResource
+}
+
+// GraphNodeDynamicExpandable
+func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
+       // Grab the state which we read
+       state, lock := ctx.State()
+       lock.RLock()
+       defer lock.RUnlock()
+
+       // Expand the resource count which must be available by now from EvalTree
+       count, err := n.Config.Count()
+       if err != nil {
+               return nil, err
+       }
+
+       // The concrete resource factory we'll use
+       concreteResource := func(a *NodeAbstractResource) dag.Vertex {
+               // Add the config and state since we don't do that via transforms
+               a.Config = n.Config
+
+               return &NodeRefreshableManagedResourceInstance{
+                       NodeAbstractResource: a,
+               }
+       }
+
+       // Start creating the steps
+       steps := []GraphTransformer{
+               // Expand the count.
+               &ResourceCountTransformer{
+                       Concrete: concreteResource,
+                       Count:    count,
+                       Addr:     n.ResourceAddr(),
+               },
+
+               // Add the count orphans to make sure these resources are accounted for
+               // during a scale in.
+               &OrphanResourceCountTransformer{
+                       Concrete: concreteResource,
+                       Count:    count,
+                       Addr:     n.ResourceAddr(),
+                       State:    state,
+               },
+
+               // Attach the state
+               &AttachStateTransformer{State: state},
+
+               // Targeting
+               &TargetsTransformer{ParsedTargets: n.Targets},
+
+               // Connect references so ordering is correct
+               &ReferenceTransformer{},
+
+               // Make sure there is a single root
+               &RootTransformer{},
+       }
+
+       // Build the graph
+       b := &BasicGraphBuilder{
+               Steps:    steps,
+               Validate: true,
+               Name:     "NodeRefreshableManagedResource",
+       }
+
+       return b.Build(ctx.Path())
+}
+
+// NodeRefreshableManagedResourceInstance represents a resource that is "applyable":
 // it is ready to be applied and is represented by a diff.
-type NodeRefreshableResource struct {
+type NodeRefreshableManagedResourceInstance struct {
        *NodeAbstractResource
 }
 
 // GraphNodeDestroyer
-func (n *NodeRefreshableResource) DestroyAddr() *ResourceAddress {
+func (n *NodeRefreshableManagedResourceInstance) DestroyAddr() *ResourceAddress {
        return n.Addr
 }
 
 // GraphNodeEvalable
-func (n *NodeRefreshableResource) EvalTree() EvalNode {
+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:
@@ -44,7 +118,7 @@ func (n *NodeRefreshableResource) EvalTree() EvalNode {
        }
 }
 
-func (n *NodeRefreshableResource) evalTreeManagedResource() EvalNode {
+func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalNode {
        addr := n.NodeAbstractResource.Addr
 
        // stateId is the ID to put into the state
@@ -98,3 +172,88 @@ func (n *NodeRefreshableResource) evalTreeManagedResource() EvalNode {
                },
        }
 }
+
+// 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()
+
+       return &EvalSequence{
+               Nodes: []EvalNode{
+                       &EvalInterpolate{
+                               Config:   n.Config.RawConfig.Copy(),
+                               Resource: resource,
+                               Output:   &resourceConfig,
+                       },
+                       &EvalGetProvider{
+                               Name:   n.ProvidedBy()[0],
+                               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.Config.Provider,
+                               Dependencies: stateDeps,
+                               State:        &state,
+                       },
+               },
+       }
+}