]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/graph_walk_context.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / graph_walk_context.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "context"
bae9f6d2
JC
5 "log"
6 "sync"
7
107c1cdb
ND
8 "github.com/zclconf/go-cty/cty"
9
10 "github.com/hashicorp/terraform/addrs"
11 "github.com/hashicorp/terraform/configs/configschema"
bae9f6d2 12 "github.com/hashicorp/terraform/dag"
107c1cdb
ND
13 "github.com/hashicorp/terraform/plans"
14 "github.com/hashicorp/terraform/providers"
15 "github.com/hashicorp/terraform/provisioners"
16 "github.com/hashicorp/terraform/states"
17 "github.com/hashicorp/terraform/tfdiags"
bae9f6d2
JC
18)
19
20// ContextGraphWalker is the GraphWalker implementation used with the
21// Context struct to walk and evaluate the graph.
22type ContextGraphWalker struct {
23 NullGraphWalker
24
25 // Configurable values
107c1cdb
ND
26 Context *Context
27 State *states.SyncState // Used for safe concurrent access to state
28 Changes *plans.ChangesSync // Used for safe concurrent writes to changes
29 Operation walkOperation
30 StopContext context.Context
31 RootVariableValues InputValues
32
33 // This is an output. Do not set this, nor read it while a graph walk
34 // is in progress.
35 NonFatalDiagnostics tfdiags.Diagnostics
36
37 errorLock sync.Mutex
38 once sync.Once
39 contexts map[string]*BuiltinEvalContext
40 contextLock sync.Mutex
41 variableValues map[string]map[string]cty.Value
42 variableValuesLock sync.Mutex
43 providerCache map[string]providers.Interface
44 providerSchemas map[string]*ProviderSchema
45 providerLock sync.Mutex
46 provisionerCache map[string]provisioners.Interface
47 provisionerSchemas map[string]*configschema.Block
48 provisionerLock sync.Mutex
bae9f6d2
JC
49}
50
107c1cdb 51func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
bae9f6d2
JC
52 w.once.Do(w.init)
53
54 w.contextLock.Lock()
55 defer w.contextLock.Unlock()
56
57 // If we already have a context for this path cached, use that
107c1cdb 58 key := path.String()
bae9f6d2
JC
59 if ctx, ok := w.contexts[key]; ok {
60 return ctx
61 }
62
107c1cdb
ND
63 // Our evaluator shares some locks with the main context and the walker
64 // so that we can safely run multiple evaluations at once across
65 // different modules.
66 evaluator := &Evaluator{
67 Meta: w.Context.meta,
68 Config: w.Context.config,
69 Operation: w.Operation,
70 State: w.State,
71 Changes: w.Changes,
72 Schemas: w.Context.schemas,
73 VariableValues: w.variableValues,
74 VariableValuesLock: &w.variableValuesLock,
bae9f6d2 75 }
bae9f6d2
JC
76
77 ctx := &BuiltinEvalContext{
78 StopContext: w.StopContext,
79 PathValue: path,
80 Hooks: w.Context.hooks,
81 InputValue: w.Context.uiInput,
82 Components: w.Context.components,
107c1cdb 83 Schemas: w.Context.schemas,
bae9f6d2 84 ProviderCache: w.providerCache,
bae9f6d2
JC
85 ProviderInputConfig: w.Context.providerInputConfig,
86 ProviderLock: &w.providerLock,
87 ProvisionerCache: w.provisionerCache,
88 ProvisionerLock: &w.provisionerLock,
107c1cdb
ND
89 ChangesValue: w.Changes,
90 StateValue: w.State,
91 Evaluator: evaluator,
92 VariableValues: w.variableValues,
93 VariableValuesLock: &w.variableValuesLock,
bae9f6d2
JC
94 }
95
96 w.contexts[key] = ctx
97 return ctx
98}
99
100func (w *ContextGraphWalker) EnterEvalTree(v dag.Vertex, n EvalNode) EvalNode {
107c1cdb 101 log.Printf("[TRACE] [%s] Entering eval tree: %s", w.Operation, dag.VertexName(v))
bae9f6d2
JC
102
103 // Acquire a lock on the semaphore
104 w.Context.parallelSem.Acquire()
105
106 // We want to filter the evaluation tree to only include operations
107 // that belong in this operation.
108 return EvalFilter(n, EvalNodeFilterOp(w.Operation))
109}
110
107c1cdb
ND
111func (w *ContextGraphWalker) ExitEvalTree(v dag.Vertex, output interface{}, err error) tfdiags.Diagnostics {
112 log.Printf("[TRACE] [%s] Exiting eval tree: %s", w.Operation, dag.VertexName(v))
bae9f6d2
JC
113
114 // Release the semaphore
115 w.Context.parallelSem.Release()
116
117 if err == nil {
118 return nil
119 }
120
121 // Acquire the lock because anything is going to require a lock.
122 w.errorLock.Lock()
123 defer w.errorLock.Unlock()
124
107c1cdb
ND
125 // If the error is non-fatal then we'll accumulate its diagnostics in our
126 // non-fatal list, rather than returning it directly, so that the graph
127 // walk can continue.
128 if nferr, ok := err.(tfdiags.NonFatalError); ok {
129 log.Printf("[WARN] %s: %s", dag.VertexName(v), nferr)
130 w.NonFatalDiagnostics = w.NonFatalDiagnostics.Append(nferr.Diagnostics)
131 return nil
bae9f6d2
JC
132 }
133
107c1cdb
ND
134 // Otherwise, we'll let our usual diagnostics machinery figure out how to
135 // unpack this as one or more diagnostic messages and return that. If we
136 // get down here then the returned diagnostics will contain at least one
137 // error, causing the graph walk to halt.
138 var diags tfdiags.Diagnostics
139 diags = diags.Append(err)
140 return diags
bae9f6d2
JC
141}
142
143func (w *ContextGraphWalker) init() {
107c1cdb
ND
144 w.contexts = make(map[string]*BuiltinEvalContext)
145 w.providerCache = make(map[string]providers.Interface)
146 w.providerSchemas = make(map[string]*ProviderSchema)
147 w.provisionerCache = make(map[string]provisioners.Interface)
148 w.provisionerSchemas = make(map[string]*configschema.Block)
149 w.variableValues = make(map[string]map[string]cty.Value)
150
151 // Populate root module variable values. Other modules will be populated
152 // during the graph walk.
153 w.variableValues[""] = make(map[string]cty.Value)
154 for k, iv := range w.RootVariableValues {
155 w.variableValues[""][k] = iv.Value
156 }
bae9f6d2 157}