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

View File

@ -27,8 +27,14 @@ type BuiltinEvalContext struct {
// eval context.
Evaluator *Evaluator
ChildModuleCallArgs map[string]map[string]cty.Value
ChildModuleCallsLock *sync.Mutex
// VariableValues contains the variable values across all modules. This
// 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
Hooks []Hook
@ -322,16 +328,17 @@ func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance {
}
func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, vals map[string]cty.Value) {
ctx.ChildModuleCallsLock.Lock()
defer ctx.ChildModuleCallsLock.Unlock()
ctx.VariableValuesLock.Lock()
defer ctx.VariableValuesLock.Unlock()
childPath := ctx.Path().Child(n.Call.Name, n.Key)
childPath := n.ModuleInstance(ctx.PathValue)
key := childPath.String()
args := ctx.ChildModuleCallArgs[key]
args := ctx.VariableValues[key]
if args == nil {
args = make(map[string]cty.Value)
ctx.ChildModuleCallArgs[key] = args
ctx.VariableValues[key] = vals
return
}
for k, v := range vals {

View File

@ -24,10 +24,15 @@ type Evaluator struct {
// Config is the root node in the configuration tree.
Config *configs.Config
// RootVariableValues is a map of values for variables defined in the
// root module, passed in from external sources. This must not be
// modified during evaluation.
RootVariableValues map[string]*InputValue
// VariableValues is a map from variable names to their associated values,
// within the module indicated by ModulePath. VariableValues is modified
// concurrently, and so it must be accessed only while holding
// 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
// is mutated concurrently, and so it must be accessed only while holding

View File

@ -5,6 +5,8 @@ import (
"log"
"sync"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/config/configschema"
"github.com/hashicorp/terraform/tfdiags"
@ -19,26 +21,27 @@ type ContextGraphWalker struct {
NullGraphWalker
// Configurable values
Context *Context
Operation walkOperation
StopContext context.Context
Context *Context
Operation walkOperation
StopContext context.Context
RootVariableValues InputValues
// This is an output. Do not set this, nor read it while a graph walk
// is in progress.
NonFatalDiagnostics tfdiags.Diagnostics
errorLock sync.Mutex
once sync.Once
contexts map[string]*BuiltinEvalContext
contextLock sync.Mutex
interpolaterVars map[string]map[string]interface{}
interpolaterVarLock sync.Mutex
providerCache map[string]ResourceProvider
providerSchemas map[string]*ProviderSchema
providerLock sync.Mutex
provisionerCache map[string]ResourceProvisioner
provisionerSchemas map[string]*configschema.Block
provisionerLock sync.Mutex
errorLock sync.Mutex
once sync.Once
contexts map[string]*BuiltinEvalContext
contextLock sync.Mutex
variableValues map[string]map[string]cty.Value
variableValuesLock sync.Mutex
providerCache map[string]ResourceProvider
providerSchemas map[string]*ProviderSchema
providerLock sync.Mutex
provisionerCache map[string]ResourceProvisioner
provisionerSchemas map[string]*configschema.Block
provisionerLock sync.Mutex
}
func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
@ -53,38 +56,18 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
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
// so that we can safely run multiple evaluations at once across
// different modules.
evaluator := &Evaluator{
Meta: w.Context.meta,
Config: w.Context.config,
State: w.Context.state,
StateLock: &w.Context.stateLock,
ProviderSchemas: w.providerSchemas,
ProvidersLock: &w.providerLock,
// FIXME: This was a design mistake on the evaluator, which should
// 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{},
Meta: w.Context.meta,
Config: w.Context.config,
State: w.Context.state,
StateLock: &w.Context.stateLock,
ProviderSchemas: w.providerSchemas,
ProvidersLock: &w.providerLock,
VariableValues: w.variableValues,
VariableValuesLock: &w.variableValuesLock,
}
ctx := &BuiltinEvalContext{
@ -104,6 +87,8 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
StateValue: w.Context.state,
StateLock: &w.Context.stateLock,
Evaluator: evaluator,
VariableValues: w.variableValues,
VariableValuesLock: &w.variableValuesLock,
}
w.contexts[key] = ctx
@ -158,5 +143,12 @@ func (w *ContextGraphWalker) init() {
w.providerSchemas = make(map[string]*ProviderSchema)
w.provisionerCache = make(map[string]ResourceProvisioner)
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
}
}