]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/terraform/terraform/graph_walk_context.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / graph_walk_context.go
index 89f376e54f81de066b43eadd1f31080113d59f27..03c192a86617b462695c994f278b81ff8780558a 100644 (file)
@@ -2,12 +2,19 @@ package terraform
 
 import (
        "context"
-       "fmt"
        "log"
        "sync"
 
-       "github.com/hashicorp/errwrap"
+       "github.com/zclconf/go-cty/cty"
+
+       "github.com/hashicorp/terraform/addrs"
+       "github.com/hashicorp/terraform/configs/configschema"
        "github.com/hashicorp/terraform/dag"
+       "github.com/hashicorp/terraform/plans"
+       "github.com/hashicorp/terraform/providers"
+       "github.com/hashicorp/terraform/provisioners"
+       "github.com/hashicorp/terraform/states"
+       "github.com/hashicorp/terraform/tfdiags"
 )
 
 // ContextGraphWalker is the GraphWalker implementation used with the
@@ -16,54 +23,56 @@ type ContextGraphWalker struct {
        NullGraphWalker
 
        // Configurable values
-       Context     *Context
-       Operation   walkOperation
-       StopContext context.Context
-
-       // Outputs, do not set these. Do not read these while the graph
-       // is being walked.
-       ValidationWarnings []string
-       ValidationErrors   []error
-
-       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
-       providerLock        sync.Mutex
-       provisionerCache    map[string]ResourceProvisioner
-       provisionerLock     sync.Mutex
+       Context            *Context
+       State              *states.SyncState  // Used for safe concurrent access to state
+       Changes            *plans.ChangesSync // Used for safe concurrent writes to changes
+       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
+       variableValues     map[string]map[string]cty.Value
+       variableValuesLock sync.Mutex
+       providerCache      map[string]providers.Interface
+       providerSchemas    map[string]*ProviderSchema
+       providerLock       sync.Mutex
+       provisionerCache   map[string]provisioners.Interface
+       provisionerSchemas map[string]*configschema.Block
+       provisionerLock    sync.Mutex
 }
 
-func (w *ContextGraphWalker) EnterPath(path []string) EvalContext {
+func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
        w.once.Do(w.init)
 
        w.contextLock.Lock()
        defer w.contextLock.Unlock()
 
        // If we already have a context for this path cached, use that
-       key := PathCacheKey(path)
+       key := path.String()
        if ctx, ok := w.contexts[key]; ok {
                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
-               }
+       // 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,
+               Operation:          w.Operation,
+               State:              w.State,
+               Changes:            w.Changes,
+               Schemas:            w.Context.schemas,
+               VariableValues:     w.variableValues,
+               VariableValuesLock: &w.variableValuesLock,
        }
-       w.interpolaterVars[key] = variables
-       w.interpolaterVarLock.Unlock()
 
        ctx := &BuiltinEvalContext{
                StopContext:         w.StopContext,
@@ -71,26 +80,17 @@ func (w *ContextGraphWalker) EnterPath(path []string) EvalContext {
                Hooks:               w.Context.hooks,
                InputValue:          w.Context.uiInput,
                Components:          w.Context.components,
+               Schemas:             w.Context.schemas,
                ProviderCache:       w.providerCache,
                ProviderInputConfig: w.Context.providerInputConfig,
                ProviderLock:        &w.providerLock,
                ProvisionerCache:    w.provisionerCache,
                ProvisionerLock:     &w.provisionerLock,
-               DiffValue:           w.Context.diff,
-               DiffLock:            &w.Context.diffLock,
-               StateValue:          w.Context.state,
-               StateLock:           &w.Context.stateLock,
-               Interpolater: &Interpolater{
-                       Operation:          w.Operation,
-                       Meta:               w.Context.meta,
-                       Module:             w.Context.module,
-                       State:              w.Context.state,
-                       StateLock:          &w.Context.stateLock,
-                       VariableValues:     variables,
-                       VariableValuesLock: &w.interpolaterVarLock,
-               },
-               InterpolaterVars:    w.interpolaterVars,
-               InterpolaterVarLock: &w.interpolaterVarLock,
+               ChangesValue:        w.Changes,
+               StateValue:          w.State,
+               Evaluator:           evaluator,
+               VariableValues:      w.variableValues,
+               VariableValuesLock:  &w.variableValuesLock,
        }
 
        w.contexts[key] = ctx
@@ -98,8 +98,7 @@ func (w *ContextGraphWalker) EnterPath(path []string) EvalContext {
 }
 
 func (w *ContextGraphWalker) EnterEvalTree(v dag.Vertex, n EvalNode) EvalNode {
-       log.Printf("[TRACE] [%s] Entering eval tree: %s",
-               w.Operation, dag.VertexName(v))
+       log.Printf("[TRACE] [%s] Entering eval tree: %s", w.Operation, dag.VertexName(v))
 
        // Acquire a lock on the semaphore
        w.Context.parallelSem.Acquire()
@@ -109,10 +108,8 @@ func (w *ContextGraphWalker) EnterEvalTree(v dag.Vertex, n EvalNode) EvalNode {
        return EvalFilter(n, EvalNodeFilterOp(w.Operation))
 }
 
-func (w *ContextGraphWalker) ExitEvalTree(
-       v dag.Vertex, output interface{}, err error) error {
-       log.Printf("[TRACE] [%s] Exiting eval tree: %s",
-               w.Operation, dag.VertexName(v))
+func (w *ContextGraphWalker) ExitEvalTree(v dag.Vertex, output interface{}, err error) tfdiags.Diagnostics {
+       log.Printf("[TRACE] [%s] Exiting eval tree: %s", w.Operation, dag.VertexName(v))
 
        // Release the semaphore
        w.Context.parallelSem.Release()
@@ -125,30 +122,36 @@ func (w *ContextGraphWalker) ExitEvalTree(
        w.errorLock.Lock()
        defer w.errorLock.Unlock()
 
-       // Try to get a validation error out of it. If its not a validation
-       // error, then just record the normal error.
-       verr, ok := err.(*EvalValidateError)
-       if !ok {
-               return err
-       }
-
-       for _, msg := range verr.Warnings {
-               w.ValidationWarnings = append(
-                       w.ValidationWarnings,
-                       fmt.Sprintf("%s: %s", dag.VertexName(v), msg))
-       }
-       for _, e := range verr.Errors {
-               w.ValidationErrors = append(
-                       w.ValidationErrors,
-                       errwrap.Wrapf(fmt.Sprintf("%s: {{err}}", dag.VertexName(v)), e))
+       // If the error is non-fatal then we'll accumulate its diagnostics in our
+       // non-fatal list, rather than returning it directly, so that the graph
+       // walk can continue.
+       if nferr, ok := err.(tfdiags.NonFatalError); ok {
+               log.Printf("[WARN] %s: %s", dag.VertexName(v), nferr)
+               w.NonFatalDiagnostics = w.NonFatalDiagnostics.Append(nferr.Diagnostics)
+               return nil
        }
 
-       return nil
+       // Otherwise, we'll let our usual diagnostics machinery figure out how to
+       // unpack this as one or more diagnostic messages and return that. If we
+       // get down here then the returned diagnostics will contain at least one
+       // error, causing the graph walk to halt.
+       var diags tfdiags.Diagnostics
+       diags = diags.Append(err)
+       return diags
 }
 
 func (w *ContextGraphWalker) init() {
-       w.contexts = make(map[string]*BuiltinEvalContext, 5)
-       w.providerCache = make(map[string]ResourceProvider, 5)
-       w.provisionerCache = make(map[string]ResourceProvisioner, 5)
-       w.interpolaterVars = make(map[string]map[string]interface{}, 5)
+       w.contexts = make(map[string]*BuiltinEvalContext)
+       w.providerCache = make(map[string]providers.Interface)
+       w.providerSchemas = make(map[string]*ProviderSchema)
+       w.provisionerCache = make(map[string]provisioners.Interface)
+       w.provisionerSchemas = make(map[string]*configschema.Block)
+       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
+       }
 }