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