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