From 024dcc9d324d2ebd86fc6371300514e6c2007bf5 Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Mon, 21 Mar 2016 18:17:18 -0500 Subject: [PATCH] terraform: share graph walker's variables lock w/ interpolater The ContextGraphWalker struct includes a lock that's passed down to BuiltinEvalContext and guards access to interpolation variables as they're written using SetVariables. The likely problem being expressed in #5733 is that the same map reference is also passed down to the Interpolater.Variables field, which is used for variable lookup. Here, we plumb the same lock we're using to guard access for writes down and acquire it before doing variable reads as well. It's not as fine grained as perhaps it could be, but all the context tests pass and I believe this should address #5733. --- terraform/graph_walk_context.go | 11 ++++++----- terraform/interpolate.go | 13 ++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/terraform/graph_walk_context.go b/terraform/graph_walk_context.go index 2994081ff..ac6310d08 100644 --- a/terraform/graph_walk_context.go +++ b/terraform/graph_walk_context.go @@ -81,11 +81,12 @@ func (w *ContextGraphWalker) EnterPath(path []string) EvalContext { StateValue: w.Context.state, StateLock: &w.Context.stateLock, Interpolater: &Interpolater{ - Operation: w.Operation, - Module: w.Context.module, - State: w.Context.state, - StateLock: &w.Context.stateLock, - Variables: variables, + Operation: w.Operation, + Module: w.Context.module, + State: w.Context.state, + StateLock: &w.Context.stateLock, + Variables: variables, + VariablesLock: &w.interpolaterVarLock, }, InterpolaterVars: w.interpolaterVars, InterpolaterVarLock: &w.interpolaterVarLock, diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 3db060b0b..7ec549c93 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -23,11 +23,12 @@ const ( // Interpolater is the structure responsible for determining the values // for interpolations such as `aws_instance.foo.bar`. type Interpolater struct { - Operation walkOperation - Module *module.Tree - State *State - StateLock *sync.RWMutex - Variables map[string]string + Operation walkOperation + Module *module.Tree + State *State + StateLock *sync.RWMutex + Variables map[string]string + VariablesLock *sync.Mutex } // InterpolationScope is the current scope of execution. This is required @@ -273,6 +274,8 @@ func (i *Interpolater) valueUserVar( n string, v *config.UserVariable, result map[string]ast.Variable) error { + i.VariablesLock.Lock() + defer i.VariablesLock.Unlock() val, ok := i.Variables[v.Name] if ok { result[n] = ast.Variable{