github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/graph_walk_context.go (about) 1 package terraform 2 3 import ( 4 "context" 5 "sync" 6 7 "github.com/zclconf/go-cty/cty" 8 9 "github.com/hashicorp/terraform/internal/addrs" 10 "github.com/hashicorp/terraform/internal/checks" 11 "github.com/hashicorp/terraform/internal/configs" 12 "github.com/hashicorp/terraform/internal/configs/configschema" 13 "github.com/hashicorp/terraform/internal/instances" 14 "github.com/hashicorp/terraform/internal/plans" 15 "github.com/hashicorp/terraform/internal/providers" 16 "github.com/hashicorp/terraform/internal/provisioners" 17 "github.com/hashicorp/terraform/internal/refactoring" 18 "github.com/hashicorp/terraform/internal/states" 19 "github.com/hashicorp/terraform/internal/tfdiags" 20 ) 21 22 // ContextGraphWalker is the GraphWalker implementation used with the 23 // Context struct to walk and evaluate the graph. 24 type ContextGraphWalker struct { 25 NullGraphWalker 26 27 // Configurable values 28 Context *Context 29 State *states.SyncState // Used for safe concurrent access to state 30 RefreshState *states.SyncState // Used for safe concurrent access to state 31 PrevRunState *states.SyncState // Used for safe concurrent access to state 32 Changes *plans.ChangesSync // Used for safe concurrent writes to changes 33 Checks *checks.State // Used for safe concurrent writes of checkable objects and their check results 34 InstanceExpander *instances.Expander // Tracks our gradual expansion of module and resource instances 35 MoveResults refactoring.MoveResults // Read-only record of earlier processing of move statements 36 Operation walkOperation 37 StopContext context.Context 38 RootVariableValues InputValues 39 Config *configs.Config 40 41 // This is an output. Do not set this, nor read it while a graph walk 42 // is in progress. 43 NonFatalDiagnostics tfdiags.Diagnostics 44 45 once sync.Once 46 contexts map[string]*BuiltinEvalContext 47 contextLock sync.Mutex 48 variableValues map[string]map[string]cty.Value 49 variableValuesLock sync.Mutex 50 providerCache map[string]providers.Interface 51 providerSchemas map[string]*ProviderSchema 52 providerLock sync.Mutex 53 provisionerCache map[string]provisioners.Interface 54 provisionerSchemas map[string]*configschema.Block 55 provisionerLock sync.Mutex 56 } 57 58 func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext { 59 w.contextLock.Lock() 60 defer w.contextLock.Unlock() 61 62 // If we already have a context for this path cached, use that 63 key := path.String() 64 if ctx, ok := w.contexts[key]; ok { 65 return ctx 66 } 67 68 ctx := w.EvalContext().WithPath(path) 69 w.contexts[key] = ctx.(*BuiltinEvalContext) 70 return ctx 71 } 72 73 func (w *ContextGraphWalker) EvalContext() EvalContext { 74 w.once.Do(w.init) 75 76 // Our evaluator shares some locks with the main context and the walker 77 // so that we can safely run multiple evaluations at once across 78 // different modules. 79 evaluator := &Evaluator{ 80 Meta: w.Context.meta, 81 Config: w.Config, 82 Operation: w.Operation, 83 State: w.State, 84 Changes: w.Changes, 85 Plugins: w.Context.plugins, 86 VariableValues: w.variableValues, 87 VariableValuesLock: &w.variableValuesLock, 88 } 89 90 ctx := &BuiltinEvalContext{ 91 StopContext: w.StopContext, 92 Hooks: w.Context.hooks, 93 InputValue: w.Context.uiInput, 94 InstanceExpanderValue: w.InstanceExpander, 95 Plugins: w.Context.plugins, 96 MoveResultsValue: w.MoveResults, 97 ProviderCache: w.providerCache, 98 ProviderInputConfig: w.Context.providerInputConfig, 99 ProviderLock: &w.providerLock, 100 ProvisionerCache: w.provisionerCache, 101 ProvisionerLock: &w.provisionerLock, 102 ChangesValue: w.Changes, 103 ChecksValue: w.Checks, 104 StateValue: w.State, 105 RefreshStateValue: w.RefreshState, 106 PrevRunStateValue: w.PrevRunState, 107 Evaluator: evaluator, 108 VariableValues: w.variableValues, 109 VariableValuesLock: &w.variableValuesLock, 110 } 111 112 return ctx 113 } 114 115 func (w *ContextGraphWalker) init() { 116 w.contexts = make(map[string]*BuiltinEvalContext) 117 w.providerCache = make(map[string]providers.Interface) 118 w.providerSchemas = make(map[string]*ProviderSchema) 119 w.provisionerCache = make(map[string]provisioners.Interface) 120 w.provisionerSchemas = make(map[string]*configschema.Block) 121 w.variableValues = make(map[string]map[string]cty.Value) 122 123 // Populate root module variable values. Other modules will be populated 124 // during the graph walk. 125 w.variableValues[""] = make(map[string]cty.Value) 126 for k, iv := range w.RootVariableValues { 127 w.variableValues[""][k] = iv.Value 128 } 129 } 130 131 func (w *ContextGraphWalker) Execute(ctx EvalContext, n GraphNodeExecutable) tfdiags.Diagnostics { 132 // Acquire a lock on the semaphore 133 w.Context.parallelSem.Acquire() 134 defer w.Context.parallelSem.Release() 135 136 return n.Execute(ctx, w.Operation) 137 }