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