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