github.com/jaredpalmer/terraform@v1.1.0-alpha20210908.0.20210911170307-88705c943a03/internal/terraform/context_walk.go (about) 1 package terraform 2 3 import ( 4 "log" 5 6 "github.com/hashicorp/terraform/internal/addrs" 7 "github.com/hashicorp/terraform/internal/configs" 8 "github.com/hashicorp/terraform/internal/instances" 9 "github.com/hashicorp/terraform/internal/plans" 10 "github.com/hashicorp/terraform/internal/refactoring" 11 "github.com/hashicorp/terraform/internal/states" 12 "github.com/hashicorp/terraform/internal/tfdiags" 13 ) 14 15 // graphWalkOpts captures some transient values we use (and possibly mutate) 16 // during a graph walk. 17 // 18 // The way these options get used unfortunately varies between the different 19 // walkOperation types. This is a historical design wart that dates back to 20 // us using the same graph structure for all operations; hopefully we'll 21 // make the necessary differences between the walk types more explicit someday. 22 type graphWalkOpts struct { 23 InputState *states.State 24 Changes *plans.Changes 25 Config *configs.Config 26 27 RootVariableValues InputValues 28 MoveResults map[addrs.UniqueKey]refactoring.MoveResult 29 } 30 31 func (c *Context) walk(graph *Graph, operation walkOperation, opts *graphWalkOpts) (*ContextGraphWalker, tfdiags.Diagnostics) { 32 log.Printf("[DEBUG] Starting graph walk: %s", operation.String()) 33 34 walker := c.graphWalker(operation, opts) 35 36 // Watch for a stop so we can call the provider Stop() API. 37 watchStop, watchWait := c.watchStop(walker) 38 39 // Walk the real graph, this will block until it completes 40 diags := graph.Walk(walker) 41 42 // Close the channel so the watcher stops, and wait for it to return. 43 close(watchStop) 44 <-watchWait 45 46 return walker, diags 47 } 48 49 func (c *Context) graphWalker(operation walkOperation, opts *graphWalkOpts) *ContextGraphWalker { 50 var state *states.SyncState 51 var refreshState *states.SyncState 52 var prevRunState *states.SyncState 53 54 // NOTE: None of the SyncState objects must directly wrap opts.InputState, 55 // because we use those to mutate the state object and opts.InputState 56 // belongs to our caller and thus we must treat it as immutable. 57 // 58 // To account for that, most of our SyncState values created below end up 59 // wrapping a _deep copy_ of opts.InputState instead. 60 inputState := opts.InputState 61 if inputState == nil { 62 // Lots of callers use nil to represent the "empty" case where we've 63 // not run Apply yet, so we tolerate that. 64 inputState = states.NewState() 65 } 66 67 switch operation { 68 case walkValidate: 69 // validate should not use any state 70 state = states.NewState().SyncWrapper() 71 72 // validate currently uses the plan graph, so we have to populate the 73 // refreshState and the prevRunState. 74 refreshState = states.NewState().SyncWrapper() 75 prevRunState = states.NewState().SyncWrapper() 76 77 case walkPlan, walkPlanDestroy: 78 state = inputState.DeepCopy().SyncWrapper() 79 refreshState = inputState.DeepCopy().SyncWrapper() 80 prevRunState = inputState.DeepCopy().SyncWrapper() 81 82 default: 83 state = inputState.DeepCopy().SyncWrapper() 84 // Only plan-like walks use refreshState and prevRunState 85 } 86 87 changes := opts.Changes 88 if changes == nil { 89 // Several of our non-plan walks end up sharing codepaths with the 90 // plan walk and thus expect to generate planned changes even though 91 // we don't care about them. To avoid those crashing, we'll just 92 // insert a placeholder changes object which'll get discarded 93 // afterwards. 94 changes = plans.NewChanges() 95 } 96 97 if opts.Config == nil { 98 panic("Context.graphWalker call without Config") 99 } 100 101 return &ContextGraphWalker{ 102 Context: c, 103 State: state, 104 Config: opts.Config, 105 RefreshState: refreshState, 106 PrevRunState: prevRunState, 107 Changes: changes.SyncWrapper(), 108 InstanceExpander: instances.NewExpander(), 109 MoveResults: opts.MoveResults, 110 Operation: operation, 111 StopContext: c.runContext, 112 RootVariableValues: opts.RootVariableValues, 113 } 114 }