github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/terraform/context.go (about)

     1  package terraform
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"sort"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/hashicorp/go-multierror"
    12  	"github.com/hashicorp/hcl"
    13  	"github.com/hashicorp/terraform/config"
    14  	"github.com/hashicorp/terraform/config/module"
    15  	"github.com/hashicorp/terraform/helper/experiment"
    16  )
    17  
    18  // InputMode defines what sort of input will be asked for when Input
    19  // is called on Context.
    20  type InputMode byte
    21  
    22  const (
    23  	// InputModeVar asks for all variables
    24  	InputModeVar InputMode = 1 << iota
    25  
    26  	// InputModeVarUnset asks for variables which are not set yet.
    27  	// InputModeVar must be set for this to have an effect.
    28  	InputModeVarUnset
    29  
    30  	// InputModeProvider asks for provider variables
    31  	InputModeProvider
    32  
    33  	// InputModeStd is the standard operating mode and asks for both variables
    34  	// and providers.
    35  	InputModeStd = InputModeVar | InputModeProvider
    36  )
    37  
    38  var (
    39  	// contextFailOnShadowError will cause Context operations to return
    40  	// errors when shadow operations fail. This is only used for testing.
    41  	contextFailOnShadowError = false
    42  
    43  	// contextTestDeepCopyOnPlan will perform a Diff DeepCopy on every
    44  	// Plan operation, effectively testing the Diff DeepCopy whenever
    45  	// a Plan occurs. This is enabled for tests.
    46  	contextTestDeepCopyOnPlan = false
    47  )
    48  
    49  // ContextOpts are the user-configurable options to create a context with
    50  // NewContext.
    51  type ContextOpts struct {
    52  	Meta               *ContextMeta
    53  	Destroy            bool
    54  	Diff               *Diff
    55  	Hooks              []Hook
    56  	Module             *module.Tree
    57  	Parallelism        int
    58  	State              *State
    59  	StateFutureAllowed bool
    60  	ProviderResolver   ResourceProviderResolver
    61  	Provisioners       map[string]ResourceProvisionerFactory
    62  	Shadow             bool
    63  	Targets            []string
    64  	Variables          map[string]interface{}
    65  
    66  	// If non-nil, will apply as additional constraints on the provider
    67  	// plugins that will be requested from the provider resolver.
    68  	ProviderSHA256s map[string][]byte
    69  
    70  	UIInput UIInput
    71  }
    72  
    73  // ContextMeta is metadata about the running context. This is information
    74  // that this package or structure cannot determine on its own but exposes
    75  // into Terraform in various ways. This must be provided by the Context
    76  // initializer.
    77  type ContextMeta struct {
    78  	Env string // Env is the state environment
    79  }
    80  
    81  // Context represents all the context that Terraform needs in order to
    82  // perform operations on infrastructure. This structure is built using
    83  // NewContext. See the documentation for that.
    84  //
    85  // Extra functions on Context can be found in context_*.go files.
    86  type Context struct {
    87  	// Maintainer note: Anytime this struct is changed, please verify
    88  	// that newShadowContext still does the right thing. Tests should
    89  	// fail regardless but putting this note here as well.
    90  
    91  	components contextComponentFactory
    92  	destroy    bool
    93  	diff       *Diff
    94  	diffLock   sync.RWMutex
    95  	hooks      []Hook
    96  	meta       *ContextMeta
    97  	module     *module.Tree
    98  	sh         *stopHook
    99  	shadow     bool
   100  	state      *State
   101  	stateLock  sync.RWMutex
   102  	targets    []string
   103  	uiInput    UIInput
   104  	variables  map[string]interface{}
   105  
   106  	l                   sync.Mutex // Lock acquired during any task
   107  	parallelSem         Semaphore
   108  	providerInputConfig map[string]map[string]interface{}
   109  	providerSHA256s     map[string][]byte
   110  	runLock             sync.Mutex
   111  	runCond             *sync.Cond
   112  	runContext          context.Context
   113  	runContextCancel    context.CancelFunc
   114  	shadowErr           error
   115  }
   116  
   117  // NewContext creates a new Context structure.
   118  //
   119  // Once a Context is creator, the pointer values within ContextOpts
   120  // should not be mutated in any way, since the pointers are copied, not
   121  // the values themselves.
   122  func NewContext(opts *ContextOpts) (*Context, error) {
   123  	// Validate the version requirement if it is given
   124  	if opts.Module != nil {
   125  		if err := checkRequiredVersion(opts.Module); err != nil {
   126  			return nil, err
   127  		}
   128  	}
   129  
   130  	// Copy all the hooks and add our stop hook. We don't append directly
   131  	// to the Config so that we're not modifying that in-place.
   132  	sh := new(stopHook)
   133  	hooks := make([]Hook, len(opts.Hooks)+1)
   134  	copy(hooks, opts.Hooks)
   135  	hooks[len(opts.Hooks)] = sh
   136  
   137  	state := opts.State
   138  	if state == nil {
   139  		state = new(State)
   140  		state.init()
   141  	}
   142  
   143  	// If our state is from the future, then error. Callers can avoid
   144  	// this error by explicitly setting `StateFutureAllowed`.
   145  	if !opts.StateFutureAllowed && state.FromFutureTerraform() {
   146  		return nil, fmt.Errorf(
   147  			"Terraform doesn't allow running any operations against a state\n"+
   148  				"that was written by a future Terraform version. The state is\n"+
   149  				"reporting it is written by Terraform '%s'.\n\n"+
   150  				"Please run at least that version of Terraform to continue.",
   151  			state.TFVersion)
   152  	}
   153  
   154  	// Explicitly reset our state version to our current version so that
   155  	// any operations we do will write out that our latest version
   156  	// has run.
   157  	state.TFVersion = Version
   158  
   159  	// Determine parallelism, default to 10. We do this both to limit
   160  	// CPU pressure but also to have an extra guard against rate throttling
   161  	// from providers.
   162  	par := opts.Parallelism
   163  	if par == 0 {
   164  		par = 10
   165  	}
   166  
   167  	// Set up the variables in the following sequence:
   168  	//    0 - Take default values from the configuration
   169  	//    1 - Take values from TF_VAR_x environment variables
   170  	//    2 - Take values specified in -var flags, overriding values
   171  	//        set by environment variables if necessary. This includes
   172  	//        values taken from -var-file in addition.
   173  	variables := make(map[string]interface{})
   174  	if opts.Module != nil {
   175  		var err error
   176  		variables, err = Variables(opts.Module, opts.Variables)
   177  		if err != nil {
   178  			return nil, err
   179  		}
   180  	}
   181  
   182  	// Bind available provider plugins to the constraints in config
   183  	var providers map[string]ResourceProviderFactory
   184  	if opts.ProviderResolver != nil {
   185  		var err error
   186  		deps := ModuleTreeDependencies(opts.Module, state)
   187  		reqd := deps.AllPluginRequirements()
   188  		if opts.ProviderSHA256s != nil {
   189  			reqd.LockExecutables(opts.ProviderSHA256s)
   190  		}
   191  		providers, err = resourceProviderFactories(opts.ProviderResolver, reqd)
   192  		if err != nil {
   193  			return nil, err
   194  		}
   195  	} else {
   196  		providers = make(map[string]ResourceProviderFactory)
   197  	}
   198  
   199  	diff := opts.Diff
   200  	if diff == nil {
   201  		diff = &Diff{}
   202  	}
   203  
   204  	return &Context{
   205  		components: &basicComponentFactory{
   206  			providers:    providers,
   207  			provisioners: opts.Provisioners,
   208  		},
   209  		destroy:   opts.Destroy,
   210  		diff:      diff,
   211  		hooks:     hooks,
   212  		meta:      opts.Meta,
   213  		module:    opts.Module,
   214  		shadow:    opts.Shadow,
   215  		state:     state,
   216  		targets:   opts.Targets,
   217  		uiInput:   opts.UIInput,
   218  		variables: variables,
   219  
   220  		parallelSem:         NewSemaphore(par),
   221  		providerInputConfig: make(map[string]map[string]interface{}),
   222  		providerSHA256s:     opts.ProviderSHA256s,
   223  		sh:                  sh,
   224  	}, nil
   225  }
   226  
   227  type ContextGraphOpts struct {
   228  	// If true, validates the graph structure (checks for cycles).
   229  	Validate bool
   230  
   231  	// Legacy graphs only: won't prune the graph
   232  	Verbose bool
   233  }
   234  
   235  // Graph returns the graph used for the given operation type.
   236  //
   237  // The most extensive or complex graph type is GraphTypePlan.
   238  func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, error) {
   239  	if opts == nil {
   240  		opts = &ContextGraphOpts{Validate: true}
   241  	}
   242  
   243  	log.Printf("[INFO] terraform: building graph: %s", typ)
   244  	switch typ {
   245  	case GraphTypeApply:
   246  		return (&ApplyGraphBuilder{
   247  			Module:       c.module,
   248  			Diff:         c.diff,
   249  			State:        c.state,
   250  			Providers:    c.components.ResourceProviders(),
   251  			Provisioners: c.components.ResourceProvisioners(),
   252  			Targets:      c.targets,
   253  			Destroy:      c.destroy,
   254  			Validate:     opts.Validate,
   255  		}).Build(RootModulePath)
   256  
   257  	case GraphTypeInput:
   258  		// The input graph is just a slightly modified plan graph
   259  		fallthrough
   260  	case GraphTypeValidate:
   261  		// The validate graph is just a slightly modified plan graph
   262  		fallthrough
   263  	case GraphTypePlan:
   264  		// Create the plan graph builder
   265  		p := &PlanGraphBuilder{
   266  			Module:    c.module,
   267  			State:     c.state,
   268  			Providers: c.components.ResourceProviders(),
   269  			Targets:   c.targets,
   270  			Validate:  opts.Validate,
   271  		}
   272  
   273  		// Some special cases for other graph types shared with plan currently
   274  		var b GraphBuilder = p
   275  		switch typ {
   276  		case GraphTypeInput:
   277  			b = InputGraphBuilder(p)
   278  		case GraphTypeValidate:
   279  			// We need to set the provisioners so those can be validated
   280  			p.Provisioners = c.components.ResourceProvisioners()
   281  
   282  			b = ValidateGraphBuilder(p)
   283  		}
   284  
   285  		return b.Build(RootModulePath)
   286  
   287  	case GraphTypePlanDestroy:
   288  		return (&DestroyPlanGraphBuilder{
   289  			Module:   c.module,
   290  			State:    c.state,
   291  			Targets:  c.targets,
   292  			Validate: opts.Validate,
   293  		}).Build(RootModulePath)
   294  
   295  	case GraphTypeRefresh:
   296  		return (&RefreshGraphBuilder{
   297  			Module:    c.module,
   298  			State:     c.state,
   299  			Providers: c.components.ResourceProviders(),
   300  			Targets:   c.targets,
   301  			Validate:  opts.Validate,
   302  		}).Build(RootModulePath)
   303  	}
   304  
   305  	return nil, fmt.Errorf("unknown graph type: %s", typ)
   306  }
   307  
   308  // ShadowError returns any errors caught during a shadow operation.
   309  //
   310  // A shadow operation is an operation run in parallel to a real operation
   311  // that performs the same tasks using new logic on copied state. The results
   312  // are compared to ensure that the new logic works the same as the old logic.
   313  // The shadow never affects the real operation or return values.
   314  //
   315  // The result of the shadow operation are only available through this function
   316  // call after a real operation is complete.
   317  //
   318  // For API consumers of Context, you can safely ignore this function
   319  // completely if you have no interest in helping report experimental feature
   320  // errors to Terraform maintainers. Otherwise, please call this function
   321  // after every operation and report this to the user.
   322  //
   323  // IMPORTANT: Shadow errors are _never_ critical: they _never_ affect
   324  // the real state or result of a real operation. They are purely informational
   325  // to assist in future Terraform versions being more stable. Please message
   326  // this effectively to the end user.
   327  //
   328  // This must be called only when no other operation is running (refresh,
   329  // plan, etc.). The result can be used in parallel to any other operation
   330  // running.
   331  func (c *Context) ShadowError() error {
   332  	return c.shadowErr
   333  }
   334  
   335  // State returns a copy of the current state associated with this context.
   336  //
   337  // This cannot safely be called in parallel with any other Context function.
   338  func (c *Context) State() *State {
   339  	return c.state.DeepCopy()
   340  }
   341  
   342  // Interpolater returns an Interpolater built on a copy of the state
   343  // that can be used to test interpolation values.
   344  func (c *Context) Interpolater() *Interpolater {
   345  	var varLock sync.Mutex
   346  	var stateLock sync.RWMutex
   347  	return &Interpolater{
   348  		Operation:          walkApply,
   349  		Meta:               c.meta,
   350  		Module:             c.module,
   351  		State:              c.state.DeepCopy(),
   352  		StateLock:          &stateLock,
   353  		VariableValues:     c.variables,
   354  		VariableValuesLock: &varLock,
   355  	}
   356  }
   357  
   358  // Input asks for input to fill variables and provider configurations.
   359  // This modifies the configuration in-place, so asking for Input twice
   360  // may result in different UI output showing different current values.
   361  func (c *Context) Input(mode InputMode) error {
   362  	defer c.acquireRun("input")()
   363  
   364  	if mode&InputModeVar != 0 {
   365  		// Walk the variables first for the root module. We walk them in
   366  		// alphabetical order for UX reasons.
   367  		rootConf := c.module.Config()
   368  		names := make([]string, len(rootConf.Variables))
   369  		m := make(map[string]*config.Variable)
   370  		for i, v := range rootConf.Variables {
   371  			names[i] = v.Name
   372  			m[v.Name] = v
   373  		}
   374  		sort.Strings(names)
   375  		for _, n := range names {
   376  			// If we only care about unset variables, then if the variable
   377  			// is set, continue on.
   378  			if mode&InputModeVarUnset != 0 {
   379  				if _, ok := c.variables[n]; ok {
   380  					continue
   381  				}
   382  			}
   383  
   384  			var valueType config.VariableType
   385  
   386  			v := m[n]
   387  			switch valueType = v.Type(); valueType {
   388  			case config.VariableTypeUnknown:
   389  				continue
   390  			case config.VariableTypeMap:
   391  				// OK
   392  			case config.VariableTypeList:
   393  				// OK
   394  			case config.VariableTypeString:
   395  				// OK
   396  			default:
   397  				panic(fmt.Sprintf("Unknown variable type: %#v", v.Type()))
   398  			}
   399  
   400  			// If the variable is not already set, and the variable defines a
   401  			// default, use that for the value.
   402  			if _, ok := c.variables[n]; !ok {
   403  				if v.Default != nil {
   404  					c.variables[n] = v.Default.(string)
   405  					continue
   406  				}
   407  			}
   408  
   409  			// this should only happen during tests
   410  			if c.uiInput == nil {
   411  				log.Println("[WARN] Content.uiInput is nil")
   412  				continue
   413  			}
   414  
   415  			// Ask the user for a value for this variable
   416  			var value string
   417  			retry := 0
   418  			for {
   419  				var err error
   420  				value, err = c.uiInput.Input(&InputOpts{
   421  					Id:          fmt.Sprintf("var.%s", n),
   422  					Query:       fmt.Sprintf("var.%s", n),
   423  					Description: v.Description,
   424  				})
   425  				if err != nil {
   426  					return fmt.Errorf(
   427  						"Error asking for %s: %s", n, err)
   428  				}
   429  
   430  				if value == "" && v.Required() {
   431  					// Redo if it is required, but abort if we keep getting
   432  					// blank entries
   433  					if retry > 2 {
   434  						return fmt.Errorf("missing required value for %q", n)
   435  					}
   436  					retry++
   437  					continue
   438  				}
   439  
   440  				break
   441  			}
   442  
   443  			// no value provided, so don't set the variable at all
   444  			if value == "" {
   445  				continue
   446  			}
   447  
   448  			decoded, err := parseVariableAsHCL(n, value, valueType)
   449  			if err != nil {
   450  				return err
   451  			}
   452  
   453  			if decoded != nil {
   454  				c.variables[n] = decoded
   455  			}
   456  		}
   457  	}
   458  
   459  	if mode&InputModeProvider != 0 {
   460  		// Build the graph
   461  		graph, err := c.Graph(GraphTypeInput, nil)
   462  		if err != nil {
   463  			return err
   464  		}
   465  
   466  		// Do the walk
   467  		if _, err := c.walk(graph, nil, walkInput); err != nil {
   468  			return err
   469  		}
   470  	}
   471  
   472  	return nil
   473  }
   474  
   475  // Apply applies the changes represented by this context and returns
   476  // the resulting state.
   477  //
   478  // Even in the case an error is returned, the state may be returned and will
   479  // potentially be partially updated.  In addition to returning the resulting
   480  // state, this context is updated with the latest state.
   481  //
   482  // If the state is required after an error, the caller should call
   483  // Context.State, rather than rely on the return value.
   484  //
   485  // TODO: Apply and Refresh should either always return a state, or rely on the
   486  //       State() method. Currently the helper/resource testing framework relies
   487  //       on the absence of a returned state to determine if Destroy can be
   488  //       called, so that will need to be refactored before this can be changed.
   489  func (c *Context) Apply() (*State, error) {
   490  	defer c.acquireRun("apply")()
   491  
   492  	// Copy our own state
   493  	c.state = c.state.DeepCopy()
   494  
   495  	// Build the graph.
   496  	graph, err := c.Graph(GraphTypeApply, nil)
   497  	if err != nil {
   498  		return nil, err
   499  	}
   500  
   501  	// Determine the operation
   502  	operation := walkApply
   503  	if c.destroy {
   504  		operation = walkDestroy
   505  	}
   506  
   507  	// Walk the graph
   508  	walker, err := c.walk(graph, graph, operation)
   509  	if len(walker.ValidationErrors) > 0 {
   510  		err = multierror.Append(err, walker.ValidationErrors...)
   511  	}
   512  
   513  	// Clean out any unused things
   514  	c.state.prune()
   515  
   516  	return c.state, err
   517  }
   518  
   519  // Plan generates an execution plan for the given context.
   520  //
   521  // The execution plan encapsulates the context and can be stored
   522  // in order to reinstantiate a context later for Apply.
   523  //
   524  // Plan also updates the diff of this context to be the diff generated
   525  // by the plan, so Apply can be called after.
   526  func (c *Context) Plan() (*Plan, error) {
   527  	defer c.acquireRun("plan")()
   528  
   529  	p := &Plan{
   530  		Module:  c.module,
   531  		Vars:    c.variables,
   532  		State:   c.state,
   533  		Targets: c.targets,
   534  
   535  		TerraformVersion: VersionString(),
   536  		ProviderSHA256s:  c.providerSHA256s,
   537  	}
   538  
   539  	var operation walkOperation
   540  	if c.destroy {
   541  		operation = walkPlanDestroy
   542  	} else {
   543  		// Set our state to be something temporary. We do this so that
   544  		// the plan can update a fake state so that variables work, then
   545  		// we replace it back with our old state.
   546  		old := c.state
   547  		if old == nil {
   548  			c.state = &State{}
   549  			c.state.init()
   550  		} else {
   551  			c.state = old.DeepCopy()
   552  		}
   553  		defer func() {
   554  			c.state = old
   555  		}()
   556  
   557  		operation = walkPlan
   558  	}
   559  
   560  	// Setup our diff
   561  	c.diffLock.Lock()
   562  	c.diff = new(Diff)
   563  	c.diff.init()
   564  	c.diffLock.Unlock()
   565  
   566  	// Build the graph.
   567  	graphType := GraphTypePlan
   568  	if c.destroy {
   569  		graphType = GraphTypePlanDestroy
   570  	}
   571  	graph, err := c.Graph(graphType, nil)
   572  	if err != nil {
   573  		return nil, err
   574  	}
   575  
   576  	// Do the walk
   577  	walker, err := c.walk(graph, graph, operation)
   578  	if err != nil {
   579  		return nil, err
   580  	}
   581  	p.Diff = c.diff
   582  
   583  	// If this is true, it means we're running unit tests. In this case,
   584  	// we perform a deep copy just to ensure that all context tests also
   585  	// test that a diff is copy-able. This will panic if it fails. This
   586  	// is enabled during unit tests.
   587  	//
   588  	// This should never be true during production usage, but even if it is,
   589  	// it can't do any real harm.
   590  	if contextTestDeepCopyOnPlan {
   591  		p.Diff.DeepCopy()
   592  	}
   593  
   594  	/*
   595  		// We don't do the reverification during the new destroy plan because
   596  		// it will use a different apply process.
   597  		if X_legacyGraph {
   598  			// Now that we have a diff, we can build the exact graph that Apply will use
   599  			// and catch any possible cycles during the Plan phase.
   600  			if _, err := c.Graph(GraphTypeLegacy, nil); err != nil {
   601  				return nil, err
   602  			}
   603  		}
   604  	*/
   605  
   606  	var errs error
   607  	if len(walker.ValidationErrors) > 0 {
   608  		errs = multierror.Append(errs, walker.ValidationErrors...)
   609  	}
   610  	return p, errs
   611  }
   612  
   613  // Refresh goes through all the resources in the state and refreshes them
   614  // to their latest state. This will update the state that this context
   615  // works with, along with returning it.
   616  //
   617  // Even in the case an error is returned, the state may be returned and
   618  // will potentially be partially updated.
   619  func (c *Context) Refresh() (*State, error) {
   620  	defer c.acquireRun("refresh")()
   621  
   622  	// Copy our own state
   623  	c.state = c.state.DeepCopy()
   624  
   625  	// Build the graph.
   626  	graph, err := c.Graph(GraphTypeRefresh, nil)
   627  	if err != nil {
   628  		return nil, err
   629  	}
   630  
   631  	// Do the walk
   632  	if _, err := c.walk(graph, graph, walkRefresh); err != nil {
   633  		return nil, err
   634  	}
   635  
   636  	// Clean out any unused things
   637  	c.state.prune()
   638  
   639  	return c.state, nil
   640  }
   641  
   642  // Stop stops the running task.
   643  //
   644  // Stop will block until the task completes.
   645  func (c *Context) Stop() {
   646  	log.Printf("[WARN] terraform: Stop called, initiating interrupt sequence")
   647  
   648  	c.l.Lock()
   649  	defer c.l.Unlock()
   650  
   651  	// If we're running, then stop
   652  	if c.runContextCancel != nil {
   653  		log.Printf("[WARN] terraform: run context exists, stopping")
   654  
   655  		// Tell the hook we want to stop
   656  		c.sh.Stop()
   657  
   658  		// Stop the context
   659  		c.runContextCancel()
   660  		c.runContextCancel = nil
   661  	}
   662  
   663  	// Grab the condition var before we exit
   664  	if cond := c.runCond; cond != nil {
   665  		cond.Wait()
   666  	}
   667  
   668  	log.Printf("[WARN] terraform: stop complete")
   669  }
   670  
   671  // Validate validates the configuration and returns any warnings or errors.
   672  func (c *Context) Validate() ([]string, []error) {
   673  	defer c.acquireRun("validate")()
   674  
   675  	var errs error
   676  
   677  	// Validate the configuration itself
   678  	if err := c.module.Validate(); err != nil {
   679  		errs = multierror.Append(errs, err)
   680  	}
   681  
   682  	// This only needs to be done for the root module, since inter-module
   683  	// variables are validated in the module tree.
   684  	if config := c.module.Config(); config != nil {
   685  		// Validate the user variables
   686  		if err := smcUserVariables(config, c.variables); len(err) > 0 {
   687  			errs = multierror.Append(errs, err...)
   688  		}
   689  	}
   690  
   691  	// If we have errors at this point, the graphing has no chance,
   692  	// so just bail early.
   693  	if errs != nil {
   694  		return nil, []error{errs}
   695  	}
   696  
   697  	// Build the graph so we can walk it and run Validate on nodes.
   698  	// We also validate the graph generated here, but this graph doesn't
   699  	// necessarily match the graph that Plan will generate, so we'll validate the
   700  	// graph again later after Planning.
   701  	graph, err := c.Graph(GraphTypeValidate, nil)
   702  	if err != nil {
   703  		return nil, []error{err}
   704  	}
   705  
   706  	// Walk
   707  	walker, err := c.walk(graph, graph, walkValidate)
   708  	if err != nil {
   709  		return nil, multierror.Append(errs, err).Errors
   710  	}
   711  
   712  	// Return the result
   713  	rerrs := multierror.Append(errs, walker.ValidationErrors...)
   714  
   715  	sort.Strings(walker.ValidationWarnings)
   716  	sort.Slice(rerrs.Errors, func(i, j int) bool {
   717  		return rerrs.Errors[i].Error() < rerrs.Errors[j].Error()
   718  	})
   719  
   720  	return walker.ValidationWarnings, rerrs.Errors
   721  }
   722  
   723  // Module returns the module tree associated with this context.
   724  func (c *Context) Module() *module.Tree {
   725  	return c.module
   726  }
   727  
   728  // Variables will return the mapping of variables that were defined
   729  // for this Context. If Input was called, this mapping may be different
   730  // than what was given.
   731  func (c *Context) Variables() map[string]interface{} {
   732  	return c.variables
   733  }
   734  
   735  // SetVariable sets a variable after a context has already been built.
   736  func (c *Context) SetVariable(k string, v interface{}) {
   737  	c.variables[k] = v
   738  }
   739  
   740  func (c *Context) acquireRun(phase string) func() {
   741  	// With the run lock held, grab the context lock to make changes
   742  	// to the run context.
   743  	c.l.Lock()
   744  	defer c.l.Unlock()
   745  
   746  	// Wait until we're no longer running
   747  	for c.runCond != nil {
   748  		c.runCond.Wait()
   749  	}
   750  
   751  	// Build our lock
   752  	c.runCond = sync.NewCond(&c.l)
   753  
   754  	// Setup debugging
   755  	dbug.SetPhase(phase)
   756  
   757  	// Create a new run context
   758  	c.runContext, c.runContextCancel = context.WithCancel(context.Background())
   759  
   760  	// Reset the stop hook so we're not stopped
   761  	c.sh.Reset()
   762  
   763  	// Reset the shadow errors
   764  	c.shadowErr = nil
   765  
   766  	return c.releaseRun
   767  }
   768  
   769  func (c *Context) releaseRun() {
   770  	// Grab the context lock so that we can make modifications to fields
   771  	c.l.Lock()
   772  	defer c.l.Unlock()
   773  
   774  	// setting the phase to "INVALID" lets us easily detect if we have
   775  	// operations happening outside of a run, or we missed setting the proper
   776  	// phase
   777  	dbug.SetPhase("INVALID")
   778  
   779  	// End our run. We check if runContext is non-nil because it can be
   780  	// set to nil if it was cancelled via Stop()
   781  	if c.runContextCancel != nil {
   782  		c.runContextCancel()
   783  	}
   784  
   785  	// Unlock all waiting our condition
   786  	cond := c.runCond
   787  	c.runCond = nil
   788  	cond.Broadcast()
   789  
   790  	// Unset the context
   791  	c.runContext = nil
   792  }
   793  
   794  func (c *Context) walk(
   795  	graph, shadow *Graph, operation walkOperation) (*ContextGraphWalker, error) {
   796  	// Keep track of the "real" context which is the context that does
   797  	// the real work: talking to real providers, modifying real state, etc.
   798  	realCtx := c
   799  
   800  	// If we don't want shadowing, remove it
   801  	if !experiment.Enabled(experiment.X_shadow) {
   802  		shadow = nil
   803  	}
   804  
   805  	// Just log this so we can see it in a debug log
   806  	if !c.shadow {
   807  		log.Printf("[WARN] terraform: shadow graph disabled")
   808  		shadow = nil
   809  	}
   810  
   811  	// If we have a shadow graph, walk that as well
   812  	var shadowCtx *Context
   813  	var shadowCloser Shadow
   814  	if shadow != nil {
   815  		// Build the shadow context. In the process, override the real context
   816  		// with the one that is wrapped so that the shadow context can verify
   817  		// the results of the real.
   818  		realCtx, shadowCtx, shadowCloser = newShadowContext(c)
   819  	}
   820  
   821  	log.Printf("[DEBUG] Starting graph walk: %s", operation.String())
   822  
   823  	walker := &ContextGraphWalker{
   824  		Context:     realCtx,
   825  		Operation:   operation,
   826  		StopContext: c.runContext,
   827  	}
   828  
   829  	// Watch for a stop so we can call the provider Stop() API.
   830  	watchStop, watchWait := c.watchStop(walker)
   831  
   832  	// Walk the real graph, this will block until it completes
   833  	realErr := graph.Walk(walker)
   834  
   835  	// Close the channel so the watcher stops, and wait for it to return.
   836  	close(watchStop)
   837  	<-watchWait
   838  
   839  	// If we have a shadow graph and we interrupted the real graph, then
   840  	// we just close the shadow and never verify it. It is non-trivial to
   841  	// recreate the exact execution state up until an interruption so this
   842  	// isn't supported with shadows at the moment.
   843  	if shadowCloser != nil && c.sh.Stopped() {
   844  		// Ignore the error result, there is nothing we could care about
   845  		shadowCloser.CloseShadow()
   846  
   847  		// Set it to nil so we don't do anything
   848  		shadowCloser = nil
   849  	}
   850  
   851  	// If we have a shadow graph, wait for that to complete.
   852  	if shadowCloser != nil {
   853  		// Build the graph walker for the shadow. We also wrap this in
   854  		// a panicwrap so that panics are captured. For the shadow graph,
   855  		// we just want panics to be normal errors rather than to crash
   856  		// Terraform.
   857  		shadowWalker := GraphWalkerPanicwrap(&ContextGraphWalker{
   858  			Context:   shadowCtx,
   859  			Operation: operation,
   860  		})
   861  
   862  		// Kick off the shadow walk. This will block on any operations
   863  		// on the real walk so it is fine to start first.
   864  		log.Printf("[INFO] Starting shadow graph walk: %s", operation.String())
   865  		shadowCh := make(chan error)
   866  		go func() {
   867  			shadowCh <- shadow.Walk(shadowWalker)
   868  		}()
   869  
   870  		// Notify the shadow that we're done
   871  		if err := shadowCloser.CloseShadow(); err != nil {
   872  			c.shadowErr = multierror.Append(c.shadowErr, err)
   873  		}
   874  
   875  		// Wait for the walk to end
   876  		log.Printf("[DEBUG] Waiting for shadow graph to complete...")
   877  		shadowWalkErr := <-shadowCh
   878  
   879  		// Get any shadow errors
   880  		if err := shadowCloser.ShadowError(); err != nil {
   881  			c.shadowErr = multierror.Append(c.shadowErr, err)
   882  		}
   883  
   884  		// Verify the contexts (compare)
   885  		if err := shadowContextVerify(realCtx, shadowCtx); err != nil {
   886  			c.shadowErr = multierror.Append(c.shadowErr, err)
   887  		}
   888  
   889  		// At this point, if we're supposed to fail on error, then
   890  		// we PANIC. Some tests just verify that there is an error,
   891  		// so simply appending it to realErr and returning could hide
   892  		// shadow problems.
   893  		//
   894  		// This must be done BEFORE appending shadowWalkErr since the
   895  		// shadowWalkErr may include expected errors.
   896  		//
   897  		// We only do this if we don't have a real error. In the case of
   898  		// a real error, we can't guarantee what nodes were and weren't
   899  		// traversed in parallel scenarios so we can't guarantee no
   900  		// shadow errors.
   901  		if c.shadowErr != nil && contextFailOnShadowError && realErr == nil {
   902  			panic(multierror.Prefix(c.shadowErr, "shadow graph:"))
   903  		}
   904  
   905  		// Now, if we have a walk error, we append that through
   906  		if shadowWalkErr != nil {
   907  			c.shadowErr = multierror.Append(c.shadowErr, shadowWalkErr)
   908  		}
   909  
   910  		if c.shadowErr == nil {
   911  			log.Printf("[INFO] Shadow graph success!")
   912  		} else {
   913  			log.Printf("[ERROR] Shadow graph error: %s", c.shadowErr)
   914  
   915  			// If we're supposed to fail on shadow errors, then report it
   916  			if contextFailOnShadowError {
   917  				realErr = multierror.Append(realErr, multierror.Prefix(
   918  					c.shadowErr, "shadow graph:"))
   919  			}
   920  		}
   921  	}
   922  
   923  	return walker, realErr
   924  }
   925  
   926  // watchStop immediately returns a `stop` and a `wait` chan after dispatching
   927  // the watchStop goroutine. This will watch the runContext for cancellation and
   928  // stop the providers accordingly.  When the watch is no longer needed, the
   929  // `stop` chan should be closed before waiting on the `wait` chan.
   930  // The `wait` chan is important, because without synchronizing with the end of
   931  // the watchStop goroutine, the runContext may also be closed during the select
   932  // incorrectly causing providers to be stopped. Even if the graph walk is done
   933  // at that point, stopping a provider permanently cancels its StopContext which
   934  // can cause later actions to fail.
   935  func (c *Context) watchStop(walker *ContextGraphWalker) (chan struct{}, <-chan struct{}) {
   936  	stop := make(chan struct{})
   937  	wait := make(chan struct{})
   938  
   939  	// get the runContext cancellation channel now, because releaseRun will
   940  	// write to the runContext field.
   941  	done := c.runContext.Done()
   942  
   943  	go func() {
   944  		defer close(wait)
   945  		// Wait for a stop or completion
   946  		select {
   947  		case <-done:
   948  			// done means the context was canceled, so we need to try and stop
   949  			// providers.
   950  		case <-stop:
   951  			// our own stop channel was closed.
   952  			return
   953  		}
   954  
   955  		// If we're here, we're stopped, trigger the call.
   956  
   957  		{
   958  			// Copy the providers so that a misbehaved blocking Stop doesn't
   959  			// completely hang Terraform.
   960  			walker.providerLock.Lock()
   961  			ps := make([]ResourceProvider, 0, len(walker.providerCache))
   962  			for _, p := range walker.providerCache {
   963  				ps = append(ps, p)
   964  			}
   965  			defer walker.providerLock.Unlock()
   966  
   967  			for _, p := range ps {
   968  				// We ignore the error for now since there isn't any reasonable
   969  				// action to take if there is an error here, since the stop is still
   970  				// advisory: Terraform will exit once the graph node completes.
   971  				p.Stop()
   972  			}
   973  		}
   974  
   975  		{
   976  			// Call stop on all the provisioners
   977  			walker.provisionerLock.Lock()
   978  			ps := make([]ResourceProvisioner, 0, len(walker.provisionerCache))
   979  			for _, p := range walker.provisionerCache {
   980  				ps = append(ps, p)
   981  			}
   982  			defer walker.provisionerLock.Unlock()
   983  
   984  			for _, p := range ps {
   985  				// We ignore the error for now since there isn't any reasonable
   986  				// action to take if there is an error here, since the stop is still
   987  				// advisory: Terraform will exit once the graph node completes.
   988  				p.Stop()
   989  			}
   990  		}
   991  	}()
   992  
   993  	return stop, wait
   994  }
   995  
   996  // parseVariableAsHCL parses the value of a single variable as would have been specified
   997  // on the command line via -var or in an environment variable named TF_VAR_x, where x is
   998  // the name of the variable. In order to get around the restriction of HCL requiring a
   999  // top level object, we prepend a sentinel key, decode the user-specified value as its
  1000  // value and pull the value back out of the resulting map.
  1001  func parseVariableAsHCL(name string, input string, targetType config.VariableType) (interface{}, error) {
  1002  	// expecting a string so don't decode anything, just strip quotes
  1003  	if targetType == config.VariableTypeString {
  1004  		return strings.Trim(input, `"`), nil
  1005  	}
  1006  
  1007  	// return empty types
  1008  	if strings.TrimSpace(input) == "" {
  1009  		switch targetType {
  1010  		case config.VariableTypeList:
  1011  			return []interface{}{}, nil
  1012  		case config.VariableTypeMap:
  1013  			return make(map[string]interface{}), nil
  1014  		}
  1015  	}
  1016  
  1017  	const sentinelValue = "SENTINEL_TERRAFORM_VAR_OVERRIDE_KEY"
  1018  	inputWithSentinal := fmt.Sprintf("%s = %s", sentinelValue, input)
  1019  
  1020  	var decoded map[string]interface{}
  1021  	err := hcl.Decode(&decoded, inputWithSentinal)
  1022  	if err != nil {
  1023  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL: %s", name, input, err)
  1024  	}
  1025  
  1026  	if len(decoded) != 1 {
  1027  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. Only one value may be specified.", name, input)
  1028  	}
  1029  
  1030  	parsedValue, ok := decoded[sentinelValue]
  1031  	if !ok {
  1032  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
  1033  	}
  1034  
  1035  	switch targetType {
  1036  	case config.VariableTypeList:
  1037  		return parsedValue, nil
  1038  	case config.VariableTypeMap:
  1039  		if list, ok := parsedValue.([]map[string]interface{}); ok {
  1040  			return list[0], nil
  1041  		}
  1042  
  1043  		return nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. One value must be specified.", name, input)
  1044  	default:
  1045  		panic(fmt.Errorf("unknown type %s", targetType.Printable()))
  1046  	}
  1047  }