]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/node_resource_plan.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / node_resource_plan.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
107c1cdb
ND
4 "log"
5
bae9f6d2 6 "github.com/hashicorp/terraform/dag"
107c1cdb 7 "github.com/hashicorp/terraform/tfdiags"
bae9f6d2
JC
8)
9
10// NodePlannableResource represents a resource that is "plannable":
11// it is ready to be planned in order to create a diff.
12type NodePlannableResource struct {
107c1cdb
ND
13 *NodeAbstractResource
14
15 // ForceCreateBeforeDestroy might be set via our GraphNodeDestroyerCBD
16 // during graph construction, if dependencies require us to force this
17 // on regardless of what the configuration says.
18 ForceCreateBeforeDestroy *bool
19}
20
21var (
22 _ GraphNodeSubPath = (*NodePlannableResource)(nil)
23 _ GraphNodeDestroyerCBD = (*NodePlannableResource)(nil)
24 _ GraphNodeDynamicExpandable = (*NodePlannableResource)(nil)
25 _ GraphNodeReferenceable = (*NodePlannableResource)(nil)
26 _ GraphNodeReferencer = (*NodePlannableResource)(nil)
27 _ GraphNodeResource = (*NodePlannableResource)(nil)
28 _ GraphNodeAttachResourceConfig = (*NodePlannableResource)(nil)
29)
30
31// GraphNodeEvalable
32func (n *NodePlannableResource) EvalTree() EvalNode {
33 addr := n.ResourceAddr()
34 config := n.Config
35
36 if config == nil {
37 // Nothing to do, then.
38 log.Printf("[TRACE] NodeApplyableResource: no configuration present for %s", addr)
39 return &EvalNoop{}
40 }
41
42 // this ensures we can reference the resource even if the count is 0
43 return &EvalWriteResourceState{
44 Addr: addr.Resource,
45 Config: config,
46 ProviderAddr: n.ResolvedProvider,
47 }
48}
49
50// GraphNodeDestroyerCBD
51func (n *NodePlannableResource) CreateBeforeDestroy() bool {
52 if n.ForceCreateBeforeDestroy != nil {
53 return *n.ForceCreateBeforeDestroy
54 }
55
56 // If we have no config, we just assume no
57 if n.Config == nil || n.Config.Managed == nil {
58 return false
59 }
60
61 return n.Config.Managed.CreateBeforeDestroy
62}
63
64// GraphNodeDestroyerCBD
65func (n *NodePlannableResource) ModifyCreateBeforeDestroy(v bool) error {
66 n.ForceCreateBeforeDestroy = &v
67 return nil
bae9f6d2
JC
68}
69
70// GraphNodeDynamicExpandable
71func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
107c1cdb
ND
72 var diags tfdiags.Diagnostics
73
74 count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
75 diags = diags.Append(countDiags)
76 if countDiags.HasErrors() {
77 return nil, diags.Err()
bae9f6d2
JC
78 }
79
107c1cdb
ND
80 // Next we need to potentially rename an instance address in the state
81 // if we're transitioning whether "count" is set at all.
82 fixResourceCountSetTransition(ctx, n.ResourceAddr(), count != -1)
83
84 // Our graph transformers require access to the full state, so we'll
85 // temporarily lock it while we work on this.
86 state := ctx.State().Lock()
87 defer ctx.State().Unlock()
88
bae9f6d2 89 // The concrete resource factory we'll use
107c1cdb 90 concreteResource := func(a *NodeAbstractResourceInstance) dag.Vertex {
bae9f6d2
JC
91 // Add the config and state since we don't do that via transforms
92 a.Config = n.Config
15c0b25d 93 a.ResolvedProvider = n.ResolvedProvider
107c1cdb
ND
94 a.Schema = n.Schema
95 a.ProvisionerSchemas = n.ProvisionerSchemas
bae9f6d2
JC
96
97 return &NodePlannableResourceInstance{
107c1cdb
ND
98 NodeAbstractResourceInstance: a,
99
100 // By the time we're walking, we've figured out whether we need
101 // to force on CreateBeforeDestroy due to dependencies on other
102 // nodes that have it.
103 ForceCreateBeforeDestroy: n.CreateBeforeDestroy(),
bae9f6d2
JC
104 }
105 }
106
107c1cdb
ND
107 // The concrete resource factory we'll use for orphans
108 concreteResourceOrphan := func(a *NodeAbstractResourceInstance) dag.Vertex {
bae9f6d2
JC
109 // Add the config and state since we don't do that via transforms
110 a.Config = n.Config
15c0b25d 111 a.ResolvedProvider = n.ResolvedProvider
107c1cdb
ND
112 a.Schema = n.Schema
113 a.ProvisionerSchemas = n.ProvisionerSchemas
bae9f6d2 114
107c1cdb
ND
115 return &NodePlannableResourceInstanceOrphan{
116 NodeAbstractResourceInstance: a,
bae9f6d2
JC
117 }
118 }
119
120 // Start creating the steps
121 steps := []GraphTransformer{
122 // Expand the count.
123 &ResourceCountTransformer{
124 Concrete: concreteResource,
107c1cdb 125 Schema: n.Schema,
bae9f6d2
JC
126 Count: count,
127 Addr: n.ResourceAddr(),
128 },
129
130 // Add the count orphans
131 &OrphanResourceCountTransformer{
132 Concrete: concreteResourceOrphan,
133 Count: count,
134 Addr: n.ResourceAddr(),
135 State: state,
136 },
137
138 // Attach the state
139 &AttachStateTransformer{State: state},
140
141 // Targeting
107c1cdb 142 &TargetsTransformer{Targets: n.Targets},
bae9f6d2
JC
143
144 // Connect references so ordering is correct
145 &ReferenceTransformer{},
146
147 // Make sure there is a single root
148 &RootTransformer{},
149 }
150
151 // Build the graph
152 b := &BasicGraphBuilder{
153 Steps: steps,
154 Validate: true,
155 Name: "NodePlannableResource",
156 }
107c1cdb
ND
157 graph, diags := b.Build(ctx.Path())
158 return graph, diags.ErrWithWarnings()
bae9f6d2 159}