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  }