core: Wire back in module input variables to the evaluator

I took some missteps here while doing the initial refactor for HCL2 types.
This restores the map of maps that retains all of the variable values, and
then makes it available to the evaluator.
This commit is contained in:
Martin Atkins 2018-05-03 18:25:16 -07:00
parent 4b5868f653
commit 25e3ac56d2
4 changed files with 68 additions and 64 deletions

View File

@ -347,12 +347,11 @@ func (c *Context) State() *State {
// receiving context. // receiving context.
func (c *Context) Evaluator() *Evaluator { func (c *Context) Evaluator() *Evaluator {
return &Evaluator{ return &Evaluator{
Operation: walkApply, Operation: walkApply,
Meta: c.meta, Meta: c.meta,
Config: c.config, Config: c.config,
State: c.state, State: c.state,
StateLock: &c.stateLock, StateLock: &c.stateLock,
RootVariableValues: c.variables,
} }
} }
@ -786,9 +785,10 @@ func (c *Context) walk(graph *Graph, operation walkOperation) (*ContextGraphWalk
log.Printf("[DEBUG] Starting graph walk: %s", operation.String()) log.Printf("[DEBUG] Starting graph walk: %s", operation.String())
walker := &ContextGraphWalker{ walker := &ContextGraphWalker{
Context: realCtx, Context: realCtx,
Operation: operation, Operation: operation,
StopContext: c.runContext, StopContext: c.runContext,
RootVariableValues: c.variables,
} }
// Watch for a stop so we can call the provider Stop() API. // Watch for a stop so we can call the provider Stop() API.

View File

@ -27,8 +27,14 @@ type BuiltinEvalContext struct {
// eval context. // eval context.
Evaluator *Evaluator Evaluator *Evaluator
ChildModuleCallArgs map[string]map[string]cty.Value // VariableValues contains the variable values across all modules. This
ChildModuleCallsLock *sync.Mutex // structure is shared across the entire containing context, and so it
// may be accessed only when holding VariableValuesLock.
// The keys of the first level of VariableValues are the string
// representations of addrs.ModuleInstance values. The second-level keys
// are variable names within each module instance.
VariableValues map[string]map[string]cty.Value
VariableValuesLock *sync.Mutex
Components contextComponentFactory Components contextComponentFactory
Hooks []Hook Hooks []Hook
@ -322,16 +328,17 @@ func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance {
} }
func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, vals map[string]cty.Value) { func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, vals map[string]cty.Value) {
ctx.ChildModuleCallsLock.Lock() ctx.VariableValuesLock.Lock()
defer ctx.ChildModuleCallsLock.Unlock() defer ctx.VariableValuesLock.Unlock()
childPath := ctx.Path().Child(n.Call.Name, n.Key) childPath := n.ModuleInstance(ctx.PathValue)
key := childPath.String() key := childPath.String()
args := ctx.ChildModuleCallArgs[key] args := ctx.VariableValues[key]
if args == nil { if args == nil {
args = make(map[string]cty.Value) args = make(map[string]cty.Value)
ctx.ChildModuleCallArgs[key] = args ctx.VariableValues[key] = vals
return
} }
for k, v := range vals { for k, v := range vals {

View File

@ -24,10 +24,15 @@ type Evaluator struct {
// Config is the root node in the configuration tree. // Config is the root node in the configuration tree.
Config *configs.Config Config *configs.Config
// RootVariableValues is a map of values for variables defined in the // VariableValues is a map from variable names to their associated values,
// root module, passed in from external sources. This must not be // within the module indicated by ModulePath. VariableValues is modified
// modified during evaluation. // concurrently, and so it must be accessed only while holding
RootVariableValues map[string]*InputValue // VariableValuesLock.
//
// The first map level is string representations of addr.ModuleInstance
// values, while the second level is variable names.
VariableValues map[string]map[string]cty.Value
VariableValuesLock *sync.Mutex
// State is the current state. During some operations this structure // State is the current state. During some operations this structure
// is mutated concurrently, and so it must be accessed only while holding // is mutated concurrently, and so it must be accessed only while holding

View File

@ -5,6 +5,8 @@ import (
"log" "log"
"sync" "sync"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/config/configschema" "github.com/hashicorp/terraform/config/configschema"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
@ -19,26 +21,27 @@ type ContextGraphWalker struct {
NullGraphWalker NullGraphWalker
// Configurable values // Configurable values
Context *Context Context *Context
Operation walkOperation Operation walkOperation
StopContext context.Context StopContext context.Context
RootVariableValues InputValues
// This is an output. Do not set this, nor read it while a graph walk // This is an output. Do not set this, nor read it while a graph walk
// is in progress. // is in progress.
NonFatalDiagnostics tfdiags.Diagnostics NonFatalDiagnostics tfdiags.Diagnostics
errorLock sync.Mutex errorLock sync.Mutex
once sync.Once once sync.Once
contexts map[string]*BuiltinEvalContext contexts map[string]*BuiltinEvalContext
contextLock sync.Mutex contextLock sync.Mutex
interpolaterVars map[string]map[string]interface{} variableValues map[string]map[string]cty.Value
interpolaterVarLock sync.Mutex variableValuesLock sync.Mutex
providerCache map[string]ResourceProvider providerCache map[string]ResourceProvider
providerSchemas map[string]*ProviderSchema providerSchemas map[string]*ProviderSchema
providerLock sync.Mutex providerLock sync.Mutex
provisionerCache map[string]ResourceProvisioner provisionerCache map[string]ResourceProvisioner
provisionerSchemas map[string]*configschema.Block provisionerSchemas map[string]*configschema.Block
provisionerLock sync.Mutex provisionerLock sync.Mutex
} }
func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext { func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
@ -53,38 +56,18 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
return ctx return ctx
} }
// Setup the variables for this interpolater
variables := make(map[string]interface{})
if len(path) <= 1 {
for k, v := range w.Context.variables {
variables[k] = v
}
}
w.interpolaterVarLock.Lock()
if m, ok := w.interpolaterVars[key]; ok {
for k, v := range m {
variables[k] = v
}
}
w.interpolaterVars[key] = variables
w.interpolaterVarLock.Unlock()
// Our evaluator shares some locks with the main context and the walker // Our evaluator shares some locks with the main context and the walker
// so that we can safely run multiple evaluations at once across // so that we can safely run multiple evaluations at once across
// different modules. // different modules.
evaluator := &Evaluator{ evaluator := &Evaluator{
Meta: w.Context.meta, Meta: w.Context.meta,
Config: w.Context.config, Config: w.Context.config,
State: w.Context.state, State: w.Context.state,
StateLock: &w.Context.stateLock, StateLock: &w.Context.stateLock,
ProviderSchemas: w.providerSchemas, ProviderSchemas: w.providerSchemas,
ProvidersLock: &w.providerLock, ProvidersLock: &w.providerLock,
VariableValues: w.variableValues,
// FIXME: This was a design mistake on the evaluator, which should VariableValuesLock: &w.variableValuesLock,
// get replaced with something like the interpolatorVars thing above
// once we verify exactly how that was used in the old Interpolator
// codepath.
RootVariableValues: map[string]*InputValue{},
} }
ctx := &BuiltinEvalContext{ ctx := &BuiltinEvalContext{
@ -104,6 +87,8 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
StateValue: w.Context.state, StateValue: w.Context.state,
StateLock: &w.Context.stateLock, StateLock: &w.Context.stateLock,
Evaluator: evaluator, Evaluator: evaluator,
VariableValues: w.variableValues,
VariableValuesLock: &w.variableValuesLock,
} }
w.contexts[key] = ctx w.contexts[key] = ctx
@ -158,5 +143,12 @@ func (w *ContextGraphWalker) init() {
w.providerSchemas = make(map[string]*ProviderSchema) w.providerSchemas = make(map[string]*ProviderSchema)
w.provisionerCache = make(map[string]ResourceProvisioner) w.provisionerCache = make(map[string]ResourceProvisioner)
w.provisionerSchemas = make(map[string]*configschema.Block) w.provisionerSchemas = make(map[string]*configschema.Block)
w.interpolaterVars = make(map[string]map[string]interface{}) w.variableValues = make(map[string]map[string]cty.Value)
// Populate root module variable values. Other modules will be populated
// during the graph walk.
w.variableValues[""] = make(map[string]cty.Value)
for k, iv := range w.RootVariableValues {
w.variableValues[""][k] = iv.Value
}
} }