github.com/maheshbr/terraform@v0.3.1-0.20141020033300-deec7194a3ea/terraform/context.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"sort"
     8  	"strconv"
     9  	"strings"
    10  	"sync"
    11  	"sync/atomic"
    12  
    13  	"github.com/hashicorp/terraform/config"
    14  	"github.com/hashicorp/terraform/config/module"
    15  	"github.com/hashicorp/terraform/depgraph"
    16  	"github.com/hashicorp/terraform/helper/multierror"
    17  )
    18  
    19  // This is a function type used to implement a walker for the resource
    20  // tree internally on the Terraform structure.
    21  type genericWalkFunc func(*walkContext, *Resource) error
    22  
    23  // Context represents all the context that Terraform needs in order to
    24  // perform operations on infrastructure. This structure is built using
    25  // ContextOpts and NewContext. See the documentation for those.
    26  //
    27  // Additionally, a context can be created from a Plan using Plan.Context.
    28  type Context struct {
    29  	module         *module.Tree
    30  	diff           *Diff
    31  	hooks          []Hook
    32  	state          *State
    33  	providerConfig map[string]map[string]map[string]interface{}
    34  	providers      map[string]ResourceProviderFactory
    35  	provisioners   map[string]ResourceProvisionerFactory
    36  	variables      map[string]string
    37  	uiInput        UIInput
    38  
    39  	parallelSem Semaphore    // Semaphore used to limit parallelism
    40  	l           sync.Mutex   // Lock acquired during any task
    41  	sl          sync.RWMutex // Lock acquired to R/W internal data
    42  	runCh       <-chan struct{}
    43  	sh          *stopHook
    44  }
    45  
    46  // ContextOpts are the user-creatable configuration structure to create
    47  // a context with NewContext.
    48  type ContextOpts struct {
    49  	Diff         *Diff
    50  	Hooks        []Hook
    51  	Module       *module.Tree
    52  	Parallelism  int
    53  	State        *State
    54  	Providers    map[string]ResourceProviderFactory
    55  	Provisioners map[string]ResourceProvisionerFactory
    56  	Variables    map[string]string
    57  
    58  	UIInput UIInput
    59  }
    60  
    61  // InputMode defines what sort of input will be asked for when Input
    62  // is called on Context.
    63  type InputMode byte
    64  
    65  const (
    66  	// InputModeVar asks for variables
    67  	InputModeVar InputMode = 1 << iota
    68  
    69  	// InputModeProvider asks for provider variables
    70  	InputModeProvider
    71  
    72  	// InputModeStd is the standard operating mode and asks for both variables
    73  	// and providers.
    74  	InputModeStd = InputModeVar | InputModeProvider
    75  )
    76  
    77  // NewContext creates a new context.
    78  //
    79  // Once a context is created, the pointer values within ContextOpts should
    80  // not be mutated in any way, since the pointers are copied, not the values
    81  // themselves.
    82  func NewContext(opts *ContextOpts) *Context {
    83  	sh := new(stopHook)
    84  
    85  	// Copy all the hooks and add our stop hook. We don't append directly
    86  	// to the Config so that we're not modifying that in-place.
    87  	hooks := make([]Hook, len(opts.Hooks)+1)
    88  	copy(hooks, opts.Hooks)
    89  	hooks[len(opts.Hooks)] = sh
    90  
    91  	// Make the parallelism channel
    92  	par := opts.Parallelism
    93  	if par == 0 {
    94  		par = 10
    95  	}
    96  
    97  	return &Context{
    98  		diff:           opts.Diff,
    99  		hooks:          hooks,
   100  		module:         opts.Module,
   101  		state:          opts.State,
   102  		providerConfig: make(map[string]map[string]map[string]interface{}),
   103  		providers:      opts.Providers,
   104  		provisioners:   opts.Provisioners,
   105  		variables:      opts.Variables,
   106  		uiInput:        opts.UIInput,
   107  
   108  		parallelSem: NewSemaphore(par),
   109  		sh:          sh,
   110  	}
   111  }
   112  
   113  // Apply applies the changes represented by this context and returns
   114  // the resulting state.
   115  //
   116  // In addition to returning the resulting state, this context is updated
   117  // with the latest state.
   118  func (c *Context) Apply() (*State, error) {
   119  	v := c.acquireRun()
   120  	defer c.releaseRun(v)
   121  
   122  	// Set our state right away. No matter what, this IS our new state,
   123  	// even if there is an error below.
   124  	c.state = c.state.deepcopy()
   125  	if c.state == nil {
   126  		c.state = &State{}
   127  	}
   128  	c.state.init()
   129  
   130  	// Walk
   131  	log.Printf("[INFO] Apply walk starting")
   132  	err := c.walkContext(walkApply, rootModulePath).Walk()
   133  	log.Printf("[INFO] Apply walk complete")
   134  
   135  	// Prune the state so that we have as clean a state as possible
   136  	c.state.prune()
   137  
   138  	return c.state, err
   139  }
   140  
   141  // Graph returns the graph for this context.
   142  func (c *Context) Graph() (*depgraph.Graph, error) {
   143  	return Graph(&GraphOpts{
   144  		Diff:         c.diff,
   145  		Module:       c.module,
   146  		Providers:    c.providers,
   147  		Provisioners: c.provisioners,
   148  		State:        c.state,
   149  	})
   150  }
   151  
   152  // Input asks for input to fill variables and provider configurations.
   153  // This modifies the configuration in-place, so asking for Input twice
   154  // may result in different UI output showing different current values.
   155  func (c *Context) Input(mode InputMode) error {
   156  	v := c.acquireRun()
   157  	defer c.releaseRun(v)
   158  
   159  	if mode&InputModeVar != 0 {
   160  		// Walk the variables first for the root module. We walk them in
   161  		// alphabetical order for UX reasons.
   162  		rootConf := c.module.Config()
   163  		names := make([]string, len(rootConf.Variables))
   164  		m := make(map[string]*config.Variable)
   165  		for i, v := range rootConf.Variables {
   166  			names[i] = v.Name
   167  			m[v.Name] = v
   168  		}
   169  		sort.Strings(names)
   170  		for _, n := range names {
   171  			v := m[n]
   172  			switch v.Type() {
   173  			case config.VariableTypeMap:
   174  				continue
   175  			case config.VariableTypeString:
   176  				// Good!
   177  			default:
   178  				panic(fmt.Sprintf("Unknown variable type: %s", v.Type()))
   179  			}
   180  
   181  			var defaultString string
   182  			if v.Default != nil {
   183  				defaultString = v.Default.(string)
   184  			}
   185  
   186  			// Ask the user for a value for this variable
   187  			var value string
   188  			for {
   189  				var err error
   190  				value, err = c.uiInput.Input(&InputOpts{
   191  					Id:          fmt.Sprintf("var.%s", n),
   192  					Query:       fmt.Sprintf("var.%s", n),
   193  					Default:     defaultString,
   194  					Description: v.Description,
   195  				})
   196  				if err != nil {
   197  					return fmt.Errorf(
   198  						"Error asking for %s: %s", n, err)
   199  				}
   200  
   201  				if value == "" && v.Required() {
   202  					// Redo if it is required.
   203  					continue
   204  				}
   205  
   206  				if value == "" {
   207  					// No value, just exit the loop. With no value, we just
   208  					// use whatever is currently set in variables.
   209  					break
   210  				}
   211  
   212  				break
   213  			}
   214  
   215  			if value != "" {
   216  				c.variables[n] = value
   217  			}
   218  		}
   219  	}
   220  
   221  	if mode&InputModeProvider != 0 {
   222  		// Create the walk context and walk the inputs, which will gather the
   223  		// inputs for any resource providers.
   224  		wc := c.walkContext(walkInput, rootModulePath)
   225  		wc.Meta = new(walkInputMeta)
   226  		return wc.Walk()
   227  	}
   228  
   229  	return nil
   230  }
   231  
   232  // Plan generates an execution plan for the given context.
   233  //
   234  // The execution plan encapsulates the context and can be stored
   235  // in order to reinstantiate a context later for Apply.
   236  //
   237  // Plan also updates the diff of this context to be the diff generated
   238  // by the plan, so Apply can be called after.
   239  func (c *Context) Plan(opts *PlanOpts) (*Plan, error) {
   240  	v := c.acquireRun()
   241  	defer c.releaseRun(v)
   242  
   243  	p := &Plan{
   244  		Module: c.module,
   245  		Vars:   c.variables,
   246  		State:  c.state,
   247  	}
   248  
   249  	wc := c.walkContext(walkInvalid, rootModulePath)
   250  	wc.Meta = p
   251  
   252  	if opts != nil && opts.Destroy {
   253  		wc.Operation = walkPlanDestroy
   254  	} else {
   255  		// Set our state to be something temporary. We do this so that
   256  		// the plan can update a fake state so that variables work, then
   257  		// we replace it back with our old state.
   258  		old := c.state
   259  		if old == nil {
   260  			c.state = &State{}
   261  			c.state.init()
   262  		} else {
   263  			c.state = old.deepcopy()
   264  		}
   265  		defer func() {
   266  			c.state = old
   267  		}()
   268  
   269  		wc.Operation = walkPlan
   270  	}
   271  
   272  	// Walk and run the plan
   273  	err := wc.Walk()
   274  
   275  	// Update the diff so that our context is up-to-date
   276  	c.diff = p.Diff
   277  
   278  	return p, err
   279  }
   280  
   281  // Refresh goes through all the resources in the state and refreshes them
   282  // to their latest state. This will update the state that this context
   283  // works with, along with returning it.
   284  //
   285  // Even in the case an error is returned, the state will be returned and
   286  // will potentially be partially updated.
   287  func (c *Context) Refresh() (*State, error) {
   288  	v := c.acquireRun()
   289  	defer c.releaseRun(v)
   290  
   291  	// Update our state
   292  	c.state = c.state.deepcopy()
   293  
   294  	// Walk the graph
   295  	err := c.walkContext(walkRefresh, rootModulePath).Walk()
   296  
   297  	// Prune the state
   298  	c.state.prune()
   299  	return c.state, err
   300  }
   301  
   302  // Stop stops the running task.
   303  //
   304  // Stop will block until the task completes.
   305  func (c *Context) Stop() {
   306  	c.l.Lock()
   307  	ch := c.runCh
   308  
   309  	// If we aren't running, then just return
   310  	if ch == nil {
   311  		c.l.Unlock()
   312  		return
   313  	}
   314  
   315  	// Tell the hook we want to stop
   316  	c.sh.Stop()
   317  
   318  	// Wait for us to stop
   319  	c.l.Unlock()
   320  	<-ch
   321  }
   322  
   323  // Validate validates the configuration and returns any warnings or errors.
   324  func (c *Context) Validate() ([]string, []error) {
   325  	var rerr *multierror.Error
   326  
   327  	// Validate the configuration itself
   328  	if err := c.module.Validate(); err != nil {
   329  		rerr = multierror.ErrorAppend(rerr, err)
   330  	}
   331  
   332  	// This only needs to be done for the root module, since inter-module
   333  	// variables are validated in the module tree.
   334  	if config := c.module.Config(); config != nil {
   335  		// Validate the user variables
   336  		if errs := smcUserVariables(config, c.variables); len(errs) > 0 {
   337  			rerr = multierror.ErrorAppend(rerr, errs...)
   338  		}
   339  	}
   340  
   341  	// Validate the entire graph
   342  	walkMeta := new(walkValidateMeta)
   343  	wc := c.walkContext(walkValidate, rootModulePath)
   344  	wc.Meta = walkMeta
   345  	if err := wc.Walk(); err != nil {
   346  		rerr = multierror.ErrorAppend(rerr, err)
   347  	}
   348  
   349  	// Flatten the warns/errs so that we get all the module errors as well,
   350  	// then aggregate.
   351  	warns, errs := walkMeta.Flatten()
   352  	if len(errs) > 0 {
   353  		rerr = multierror.ErrorAppend(rerr, errs...)
   354  	}
   355  
   356  	errs = nil
   357  	if rerr != nil && len(rerr.Errors) > 0 {
   358  		errs = rerr.Errors
   359  	}
   360  
   361  	return warns, errs
   362  }
   363  
   364  func (c *Context) acquireRun() chan<- struct{} {
   365  	c.l.Lock()
   366  	defer c.l.Unlock()
   367  
   368  	// Wait for no channel to exist
   369  	for c.runCh != nil {
   370  		c.l.Unlock()
   371  		ch := c.runCh
   372  		<-ch
   373  		c.l.Lock()
   374  	}
   375  
   376  	ch := make(chan struct{})
   377  	c.runCh = ch
   378  	return ch
   379  }
   380  
   381  func (c *Context) releaseRun(ch chan<- struct{}) {
   382  	c.l.Lock()
   383  	defer c.l.Unlock()
   384  
   385  	close(ch)
   386  	c.runCh = nil
   387  	c.sh.Reset()
   388  }
   389  
   390  func (c *Context) walkContext(op walkOperation, path []string) *walkContext {
   391  	// Get the config structure
   392  	m := c.module
   393  	for _, n := range path[1:] {
   394  		cs := m.Children()
   395  		m = cs[n]
   396  	}
   397  	var conf *config.Config
   398  	if m != nil {
   399  		conf = m.Config()
   400  	}
   401  
   402  	// Calculate the default variable values
   403  	defaultVars := make(map[string]string)
   404  	if conf != nil {
   405  		for _, v := range conf.Variables {
   406  			for k, val := range v.DefaultsMap() {
   407  				defaultVars[k] = val
   408  			}
   409  		}
   410  	}
   411  
   412  	return &walkContext{
   413  		Context:   c,
   414  		Operation: op,
   415  		Path:      path,
   416  		Variables: c.variables,
   417  
   418  		defaultVariables: defaultVars,
   419  	}
   420  }
   421  
   422  // walkContext is the context in which a graph walk is done. It stores
   423  // much the same as a Context but works on a specific module.
   424  type walkContext struct {
   425  	Context   *Context
   426  	Meta      interface{}
   427  	Operation walkOperation
   428  	Path      []string
   429  	Variables map[string]string
   430  
   431  	defaultVariables map[string]string
   432  
   433  	// This is only set manually by subsequent context creations
   434  	// in genericWalkFunc.
   435  	graph *depgraph.Graph
   436  }
   437  
   438  // walkOperation is an enum which tells the walkContext what to do.
   439  type walkOperation byte
   440  
   441  const (
   442  	walkInvalid walkOperation = iota
   443  	walkInput
   444  	walkApply
   445  	walkPlan
   446  	walkPlanDestroy
   447  	walkRefresh
   448  	walkValidate
   449  )
   450  
   451  func (c *walkContext) Walk() error {
   452  	g := c.graph
   453  	if g == nil {
   454  		gopts := &GraphOpts{
   455  			Module:       c.Context.module,
   456  			Providers:    c.Context.providers,
   457  			Provisioners: c.Context.provisioners,
   458  			State:        c.Context.state,
   459  		}
   460  		if c.Operation == walkApply {
   461  			gopts.Diff = c.Context.diff
   462  		}
   463  
   464  		var err error
   465  		g, err = Graph(gopts)
   466  		if err != nil {
   467  			return err
   468  		}
   469  	}
   470  
   471  	var walkFn depgraph.WalkFunc
   472  	switch c.Operation {
   473  	case walkInput:
   474  		walkFn = c.inputWalkFn()
   475  	case walkApply:
   476  		walkFn = c.applyWalkFn()
   477  	case walkPlan:
   478  		walkFn = c.planWalkFn()
   479  	case walkPlanDestroy:
   480  		walkFn = c.planDestroyWalkFn()
   481  	case walkRefresh:
   482  		walkFn = c.refreshWalkFn()
   483  	case walkValidate:
   484  		walkFn = c.validateWalkFn()
   485  	default:
   486  		panic(fmt.Sprintf("unknown operation: %s", c.Operation))
   487  	}
   488  
   489  	if err := g.Walk(walkFn); err != nil {
   490  		return err
   491  	}
   492  
   493  	switch c.Operation {
   494  	case walkInput:
   495  		fallthrough
   496  	case walkValidate:
   497  		// Don't calculate outputs
   498  		return nil
   499  	}
   500  
   501  	// We did an apply, so we need to calculate the outputs. If we have no
   502  	// outputs, then we're done.
   503  	m := c.Context.module
   504  	for _, n := range c.Path[1:] {
   505  		cs := m.Children()
   506  		m = cs[n]
   507  	}
   508  	if m == nil {
   509  		return nil
   510  	}
   511  	conf := m.Config()
   512  	if len(conf.Outputs) == 0 {
   513  		return nil
   514  	}
   515  
   516  	// Likewise, if we have no resources in our state, we're done. This
   517  	// guards against the case that we destroyed.
   518  	mod := c.Context.state.ModuleByPath(c.Path)
   519  	if mod == nil {
   520  		return nil
   521  	}
   522  	if c.Operation == walkApply {
   523  		// On Apply, we prune so that we don't do outputs if we destroyed
   524  		mod.prune()
   525  	}
   526  	if len(mod.Resources) == 0 {
   527  		mod.Outputs = nil
   528  		return nil
   529  	}
   530  
   531  	outputs := make(map[string]string)
   532  	for _, o := range conf.Outputs {
   533  		if err := c.computeVars(o.RawConfig, nil); err != nil {
   534  			return err
   535  		}
   536  		vraw := o.RawConfig.Config()["value"]
   537  		if vraw == nil {
   538  			// This likely means that the result of the output is
   539  			// a computed variable.
   540  			if o.RawConfig.Raw["value"] != nil {
   541  				vraw = config.UnknownVariableValue
   542  			}
   543  		}
   544  		if vraw != nil {
   545  			outputs[o.Name] = vraw.(string)
   546  		}
   547  	}
   548  
   549  	// Assign the outputs to the root module
   550  	mod.Outputs = outputs
   551  
   552  	return nil
   553  }
   554  
   555  func (c *walkContext) inputWalkFn() depgraph.WalkFunc {
   556  	meta := c.Meta.(*walkInputMeta)
   557  	meta.Lock()
   558  	if meta.Done == nil {
   559  		meta.Done = make(map[string]struct{})
   560  	}
   561  	meta.Unlock()
   562  
   563  	return func(n *depgraph.Noun) error {
   564  		// If it is the root node, ignore
   565  		if n.Name == GraphRootNode {
   566  			return nil
   567  		}
   568  
   569  		switch rn := n.Meta.(type) {
   570  		case *GraphNodeModule:
   571  			// Build another walkContext for this module and walk it.
   572  			wc := c.Context.walkContext(c.Operation, rn.Path)
   573  
   574  			// Set the graph to specifically walk this subgraph
   575  			wc.graph = rn.Graph
   576  
   577  			// Preserve the meta
   578  			wc.Meta = c.Meta
   579  
   580  			return wc.Walk()
   581  		case *GraphNodeResource:
   582  			// Resources don't matter for input. Continue.
   583  			return nil
   584  		case *GraphNodeResourceProvider:
   585  			// Acquire the lock the whole time so we only ask for input
   586  			// one at a time.
   587  			meta.Lock()
   588  			defer meta.Unlock()
   589  
   590  			// If we already did this provider, then we're done.
   591  			if _, ok := meta.Done[rn.ID]; ok {
   592  				return nil
   593  			}
   594  
   595  			// Get the raw configuration because this is what we
   596  			// pass into the API.
   597  			var raw *config.RawConfig
   598  			sharedProvider := rn.Provider
   599  			if sharedProvider.Config != nil {
   600  				raw = sharedProvider.Config.RawConfig
   601  			}
   602  			rc := NewResourceConfig(raw)
   603  			rc.Config = make(map[string]interface{})
   604  
   605  			// Wrap the input into a namespace
   606  			input := &PrefixUIInput{
   607  				IdPrefix:    fmt.Sprintf("provider.%s", rn.ID),
   608  				QueryPrefix: fmt.Sprintf("provider.%s.", rn.ID),
   609  				UIInput:     c.Context.uiInput,
   610  			}
   611  
   612  			// Go through each provider and capture the input necessary
   613  			// to satisfy it.
   614  			configs := make(map[string]map[string]interface{})
   615  			for k, p := range sharedProvider.Providers {
   616  				newc, err := p.Input(input, rc)
   617  				if err != nil {
   618  					return fmt.Errorf(
   619  						"Error configuring %s: %s", k, err)
   620  				}
   621  				if newc != nil && len(newc.Config) > 0 {
   622  					configs[k] = newc.Config
   623  				}
   624  			}
   625  
   626  			// Mark this provider as done
   627  			meta.Done[rn.ID] = struct{}{}
   628  
   629  			// Set the configuration
   630  			c.Context.providerConfig[rn.ID] = configs
   631  		}
   632  
   633  		return nil
   634  	}
   635  }
   636  
   637  func (c *walkContext) applyWalkFn() depgraph.WalkFunc {
   638  	cb := func(c *walkContext, r *Resource) error {
   639  		var err error
   640  
   641  		diff := r.Diff
   642  		if diff.Empty() {
   643  			log.Printf("[DEBUG] %s: Diff is empty. Will not apply.", r.Id)
   644  			return nil
   645  		}
   646  
   647  		is := r.State
   648  		if is == nil {
   649  			is = new(InstanceState)
   650  		}
   651  		is.init()
   652  
   653  		if !diff.Destroy {
   654  			// Since we need the configuration, interpolate the variables
   655  			if err := r.Config.interpolate(c, r); err != nil {
   656  				return err
   657  			}
   658  
   659  			diff, err = r.Provider.Diff(r.Info, is, r.Config)
   660  			if err != nil {
   661  				return err
   662  			}
   663  
   664  			// This can happen if we aren't actually applying anything
   665  			// except an ID (the "null" provider). It is not really an issue
   666  			// since the Same check later down will catch any real problems.
   667  			if diff == nil {
   668  				diff = new(InstanceDiff)
   669  				diff.init()
   670  			}
   671  
   672  			// Delete id from the diff because it is dependent on
   673  			// our internal plan function.
   674  			delete(r.Diff.Attributes, "id")
   675  			delete(diff.Attributes, "id")
   676  
   677  			// Verify the diffs are the same
   678  			if !r.Diff.Same(diff) {
   679  				log.Printf(
   680  					"[ERROR] Diffs don't match.\n\nDiff 1: %#v"+
   681  						"\n\nDiff 2: %#v",
   682  					r.Diff, diff)
   683  				return fmt.Errorf(
   684  					"%s: diffs didn't match during apply. This is a "+
   685  						"bug with the resource provider, please report a bug.",
   686  					r.Id)
   687  			}
   688  		}
   689  
   690  		// Remove any output values from the diff
   691  		for k, ad := range diff.Attributes {
   692  			if ad.Type == DiffAttrOutput {
   693  				delete(diff.Attributes, k)
   694  			}
   695  		}
   696  
   697  		for _, h := range c.Context.hooks {
   698  			handleHook(h.PreApply(r.Info, is, diff))
   699  		}
   700  
   701  		// We create a new instance if there was no ID
   702  		// previously or the diff requires re-creating the
   703  		// underlying instance
   704  		createNew := (is.ID == "" && !diff.Destroy) || diff.RequiresNew()
   705  
   706  		// With the completed diff, apply!
   707  		log.Printf("[DEBUG] %s: Executing Apply", r.Id)
   708  		is, applyerr := r.Provider.Apply(r.Info, is, diff)
   709  
   710  		var errs []error
   711  		if applyerr != nil {
   712  			errs = append(errs, applyerr)
   713  		}
   714  
   715  		// Make sure the result is instantiated
   716  		if is == nil {
   717  			is = new(InstanceState)
   718  		}
   719  		is.init()
   720  
   721  		// Force the "id" attribute to be our ID
   722  		if is.ID != "" {
   723  			is.Attributes["id"] = is.ID
   724  		}
   725  
   726  		for ak, av := range is.Attributes {
   727  			// If the value is the unknown variable value, then it is an error.
   728  			// In this case we record the error and remove it from the state
   729  			if av == config.UnknownVariableValue {
   730  				errs = append(errs, fmt.Errorf(
   731  					"Attribute with unknown value: %s", ak))
   732  				delete(is.Attributes, ak)
   733  			}
   734  		}
   735  
   736  		// Set the result state
   737  		r.State = is
   738  		c.persistState(r)
   739  
   740  		// Invoke any provisioners we have defined. This is only done
   741  		// if the resource was created, as updates or deletes do not
   742  		// invoke provisioners.
   743  		//
   744  		// Additionally, we need to be careful to not run this if there
   745  		// was an error during the provider apply.
   746  		tainted := false
   747  		if createNew && len(r.Provisioners) > 0 {
   748  			if applyerr == nil {
   749  				// If the apply succeeded, we have to run the provisioners
   750  				for _, h := range c.Context.hooks {
   751  					handleHook(h.PreProvisionResource(r.Info, is))
   752  				}
   753  
   754  				if err := c.applyProvisioners(r, is); err != nil {
   755  					errs = append(errs, err)
   756  					tainted = true
   757  				}
   758  
   759  				for _, h := range c.Context.hooks {
   760  					handleHook(h.PostProvisionResource(r.Info, is))
   761  				}
   762  			} else {
   763  				// If we failed to create properly and we have provisioners,
   764  				// then we have to mark ourselves as tainted to try again.
   765  				tainted = true
   766  			}
   767  		}
   768  
   769  		// If we're tainted then we need to update some flags
   770  		if tainted && r.Flags&FlagTainted == 0 {
   771  			r.Flags &^= FlagPrimary
   772  			r.Flags &^= FlagHasTainted
   773  			r.Flags |= FlagTainted
   774  			r.TaintedIndex = -1
   775  			c.persistState(r)
   776  		}
   777  
   778  		for _, h := range c.Context.hooks {
   779  			handleHook(h.PostApply(r.Info, is, applyerr))
   780  		}
   781  
   782  		// Determine the new state and update variables
   783  		err = nil
   784  		if len(errs) > 0 {
   785  			err = &multierror.Error{Errors: errs}
   786  		}
   787  
   788  		return err
   789  	}
   790  
   791  	return c.genericWalkFn(cb)
   792  }
   793  
   794  func (c *walkContext) planWalkFn() depgraph.WalkFunc {
   795  	var l sync.Mutex
   796  
   797  	// Initialize the result
   798  	result := c.Meta.(*Plan)
   799  	result.init()
   800  
   801  	cb := func(c *walkContext, r *Resource) error {
   802  		if r.Flags&FlagTainted != 0 {
   803  			// We don't diff tainted resources.
   804  			return nil
   805  		}
   806  
   807  		var diff *InstanceDiff
   808  
   809  		is := r.State
   810  
   811  		for _, h := range c.Context.hooks {
   812  			handleHook(h.PreDiff(r.Info, is))
   813  		}
   814  
   815  		if r.Flags&FlagOrphan != 0 {
   816  			log.Printf("[DEBUG] %s: Orphan, marking for destroy", r.Id)
   817  
   818  			// This is an orphan (no config), so we mark it to be destroyed
   819  			diff = &InstanceDiff{Destroy: true}
   820  		} else {
   821  			// Make sure the configuration is interpolated
   822  			if err := r.Config.interpolate(c, r); err != nil {
   823  				return err
   824  			}
   825  
   826  			// Get a diff from the newest state
   827  			log.Printf("[DEBUG] %s: Executing diff", r.Id)
   828  			var err error
   829  
   830  			diffIs := is
   831  			if diffIs == nil || r.Flags&FlagHasTainted != 0 {
   832  				// If we're tainted, we pretend to create a new thing.
   833  				diffIs = new(InstanceState)
   834  			}
   835  			diffIs.init()
   836  
   837  			diff, err = r.Provider.Diff(r.Info, diffIs, r.Config)
   838  			if err != nil {
   839  				return err
   840  			}
   841  		}
   842  
   843  		if diff == nil {
   844  			diff = new(InstanceDiff)
   845  		}
   846  
   847  		if r.Flags&FlagHasTainted != 0 {
   848  			// This primary has a tainted resource, so just mark for
   849  			// destroy...
   850  			log.Printf("[DEBUG] %s: Tainted children, marking for destroy", r.Id)
   851  			diff.DestroyTainted = true
   852  		}
   853  
   854  		if diff.RequiresNew() && is != nil && is.ID != "" {
   855  			// This will also require a destroy
   856  			diff.Destroy = true
   857  		}
   858  
   859  		if diff.RequiresNew() || is == nil || is.ID == "" {
   860  			var oldID string
   861  			if is != nil {
   862  				oldID = is.Attributes["id"]
   863  			}
   864  
   865  			// Add diff to compute new ID
   866  			diff.init()
   867  			diff.Attributes["id"] = &ResourceAttrDiff{
   868  				Old:         oldID,
   869  				NewComputed: true,
   870  				RequiresNew: true,
   871  				Type:        DiffAttrOutput,
   872  			}
   873  		}
   874  
   875  		if !diff.Empty() {
   876  			log.Printf("[DEBUG] %s: Diff: %#v", r.Id, diff)
   877  
   878  			l.Lock()
   879  			md := result.Diff.ModuleByPath(c.Path)
   880  			if md == nil {
   881  				md = result.Diff.AddModule(c.Path)
   882  			}
   883  			md.Resources[r.Id] = diff
   884  			l.Unlock()
   885  		}
   886  
   887  		for _, h := range c.Context.hooks {
   888  			handleHook(h.PostDiff(r.Info, diff))
   889  		}
   890  
   891  		// Determine the new state and update variables
   892  		if !diff.Empty() {
   893  			is = is.MergeDiff(diff)
   894  		}
   895  
   896  		// Set it so that it can be updated
   897  		r.State = is
   898  		c.persistState(r)
   899  
   900  		return nil
   901  	}
   902  
   903  	return c.genericWalkFn(cb)
   904  }
   905  
   906  func (c *walkContext) planDestroyWalkFn() depgraph.WalkFunc {
   907  	var l sync.Mutex
   908  
   909  	// Initialize the result
   910  	result := c.Meta.(*Plan)
   911  	result.init()
   912  
   913  	var walkFn depgraph.WalkFunc
   914  	walkFn = func(n *depgraph.Noun) error {
   915  		switch m := n.Meta.(type) {
   916  		case *GraphNodeModule:
   917  			// Build another walkContext for this module and walk it.
   918  			wc := c.Context.walkContext(c.Operation, m.Path)
   919  
   920  			// Set the graph to specifically walk this subgraph
   921  			wc.graph = m.Graph
   922  
   923  			// Preserve the meta
   924  			wc.Meta = c.Meta
   925  
   926  			return wc.Walk()
   927  		case *GraphNodeResource:
   928  			// If we're expanding, then expand the nodes, and then rewalk the graph
   929  			if m.ExpandMode > ResourceExpandNone {
   930  				return c.genericWalkResource(m, walkFn)
   931  			}
   932  
   933  			r := m.Resource
   934  
   935  			if r.State != nil && r.State.ID != "" {
   936  				log.Printf("[DEBUG] %s: Making for destroy", r.Id)
   937  
   938  				l.Lock()
   939  				defer l.Unlock()
   940  				md := result.Diff.ModuleByPath(c.Path)
   941  				if md == nil {
   942  					md = result.Diff.AddModule(c.Path)
   943  				}
   944  				md.Resources[r.Id] = &InstanceDiff{Destroy: true}
   945  			} else {
   946  				log.Printf("[DEBUG] %s: Not marking for destroy, no ID", r.Id)
   947  			}
   948  		}
   949  
   950  		return nil
   951  	}
   952  
   953  	return walkFn
   954  }
   955  
   956  func (c *walkContext) refreshWalkFn() depgraph.WalkFunc {
   957  	cb := func(c *walkContext, r *Resource) error {
   958  		is := r.State
   959  
   960  		if is == nil || is.ID == "" {
   961  			log.Printf("[DEBUG] %s: Not refreshing, ID is empty", r.Id)
   962  			return nil
   963  		}
   964  
   965  		for _, h := range c.Context.hooks {
   966  			handleHook(h.PreRefresh(r.Info, is))
   967  		}
   968  
   969  		is, err := r.Provider.Refresh(r.Info, is)
   970  		if err != nil {
   971  			return err
   972  		}
   973  		if is == nil {
   974  			is = new(InstanceState)
   975  			is.init()
   976  		}
   977  
   978  		// Set the updated state
   979  		r.State = is
   980  		c.persistState(r)
   981  
   982  		for _, h := range c.Context.hooks {
   983  			handleHook(h.PostRefresh(r.Info, is))
   984  		}
   985  
   986  		return nil
   987  	}
   988  
   989  	return c.genericWalkFn(cb)
   990  }
   991  
   992  func (c *walkContext) validateWalkFn() depgraph.WalkFunc {
   993  	var l sync.Mutex
   994  
   995  	meta := c.Meta.(*walkValidateMeta)
   996  	if meta.Children == nil {
   997  		meta.Children = make(map[string]*walkValidateMeta)
   998  	}
   999  
  1000  	var walkFn depgraph.WalkFunc
  1001  	walkFn = func(n *depgraph.Noun) error {
  1002  		// If it is the root node, ignore
  1003  		if n.Name == GraphRootNode {
  1004  			return nil
  1005  		}
  1006  
  1007  		switch rn := n.Meta.(type) {
  1008  		case *GraphNodeModule:
  1009  			// Build another walkContext for this module and walk it.
  1010  			wc := c.Context.walkContext(walkValidate, rn.Path)
  1011  
  1012  			// Set the graph to specifically walk this subgraph
  1013  			wc.graph = rn.Graph
  1014  
  1015  			// Build the meta parameter. Do this by sharing the Children
  1016  			// reference but copying the rest into our own Children list.
  1017  			newMeta := new(walkValidateMeta)
  1018  			newMeta.Children = meta.Children
  1019  			wc.Meta = newMeta
  1020  
  1021  			if err := wc.Walk(); err != nil {
  1022  				return err
  1023  			}
  1024  
  1025  			newMeta.Children = nil
  1026  			meta.Children[strings.Join(rn.Path, ".")] = newMeta
  1027  			return nil
  1028  		case *GraphNodeResource:
  1029  			if rn.Resource == nil {
  1030  				panic("resource should never be nil")
  1031  			}
  1032  
  1033  			// If we're expanding, then expand the nodes, and then rewalk the graph
  1034  			if rn.ExpandMode > ResourceExpandNone {
  1035  				// Interpolate the count and verify it is non-negative
  1036  				rc := NewResourceConfig(rn.Config.RawCount)
  1037  				rc.interpolate(c, rn.Resource)
  1038  				if !rc.IsComputed(rn.Config.RawCount.Key) {
  1039  					count, err := rn.Config.Count()
  1040  					if err == nil {
  1041  						if count < 0 {
  1042  							err = fmt.Errorf(
  1043  								"%s error: count must be positive", rn.Resource.Id)
  1044  						}
  1045  					}
  1046  					if err != nil {
  1047  						l.Lock()
  1048  						defer l.Unlock()
  1049  						meta.Errs = append(meta.Errs, err)
  1050  						return nil
  1051  					}
  1052  				}
  1053  
  1054  				return c.genericWalkResource(rn, walkFn)
  1055  			}
  1056  
  1057  			// If it doesn't have a provider, that is a different problem
  1058  			if rn.Resource.Provider == nil {
  1059  				return nil
  1060  			}
  1061  
  1062  			// Don't validate orphans or tainted since they never have a config
  1063  			if rn.Resource.Flags&FlagOrphan != 0 {
  1064  				return nil
  1065  			}
  1066  			if rn.Resource.Flags&FlagTainted != 0 {
  1067  				return nil
  1068  			}
  1069  
  1070  			// If the resouce name doesn't match the name regular
  1071  			// expression, show a warning.
  1072  			if !config.NameRegexp.Match([]byte(rn.Config.Name)) {
  1073  				l.Lock()
  1074  				meta.Warns = append(meta.Warns, fmt.Sprintf(
  1075  					"%s: module name can only contain letters, numbers, "+
  1076  						"dashes, and underscores.\n"+
  1077  						"This will be an error in Terraform 0.4",
  1078  					rn.Resource.Id))
  1079  				l.Unlock()
  1080  			}
  1081  
  1082  			// Compute the variables in this resource
  1083  			rn.Resource.Config.interpolate(c, rn.Resource)
  1084  
  1085  			log.Printf("[INFO] Validating resource: %s", rn.Resource.Id)
  1086  			ws, es := rn.Resource.Provider.ValidateResource(
  1087  				rn.Resource.Info.Type, rn.Resource.Config)
  1088  			for i, w := range ws {
  1089  				ws[i] = fmt.Sprintf("'%s' warning: %s", rn.Resource.Id, w)
  1090  			}
  1091  			for i, e := range es {
  1092  				es[i] = fmt.Errorf("'%s' error: %s", rn.Resource.Id, e)
  1093  			}
  1094  
  1095  			l.Lock()
  1096  			meta.Warns = append(meta.Warns, ws...)
  1097  			meta.Errs = append(meta.Errs, es...)
  1098  			l.Unlock()
  1099  
  1100  			for idx, p := range rn.Resource.Provisioners {
  1101  				ws, es := p.Provisioner.Validate(p.Config)
  1102  				for i, w := range ws {
  1103  					ws[i] = fmt.Sprintf("'%s.provisioner.%d' warning: %s", rn.Resource.Id, idx, w)
  1104  				}
  1105  				for i, e := range es {
  1106  					es[i] = fmt.Errorf("'%s.provisioner.%d' error: %s", rn.Resource.Id, idx, e)
  1107  				}
  1108  
  1109  				l.Lock()
  1110  				meta.Warns = append(meta.Warns, ws...)
  1111  				meta.Errs = append(meta.Errs, es...)
  1112  				l.Unlock()
  1113  			}
  1114  
  1115  		case *GraphNodeResourceProvider:
  1116  			sharedProvider := rn.Provider
  1117  
  1118  			// Check if we have an override
  1119  			cs, ok := c.Context.providerConfig[rn.ID]
  1120  			if !ok {
  1121  				cs = make(map[string]map[string]interface{})
  1122  			}
  1123  
  1124  			for k, p := range sharedProvider.Providers {
  1125  				// Merge the configurations to get what we use to configure with
  1126  				rc := sharedProvider.MergeConfig(false, cs[k])
  1127  				rc.interpolate(c, nil)
  1128  
  1129  				log.Printf("[INFO] Validating provider: %s", k)
  1130  				ws, es := p.Validate(rc)
  1131  				for i, w := range ws {
  1132  					ws[i] = fmt.Sprintf("Provider '%s' warning: %s", k, w)
  1133  				}
  1134  				for i, e := range es {
  1135  					es[i] = fmt.Errorf("Provider '%s' error: %s", k, e)
  1136  				}
  1137  
  1138  				l.Lock()
  1139  				meta.Warns = append(meta.Warns, ws...)
  1140  				meta.Errs = append(meta.Errs, es...)
  1141  				l.Unlock()
  1142  			}
  1143  		}
  1144  
  1145  		return nil
  1146  	}
  1147  
  1148  	return walkFn
  1149  }
  1150  
  1151  func (c *walkContext) genericWalkFn(cb genericWalkFunc) depgraph.WalkFunc {
  1152  	// This will keep track of whether we're stopped or not
  1153  	var stop uint32 = 0
  1154  
  1155  	var walkFn depgraph.WalkFunc
  1156  	walkFn = func(n *depgraph.Noun) error {
  1157  		// If it is the root node, ignore
  1158  		if n.Name == GraphRootNode {
  1159  			return nil
  1160  		}
  1161  
  1162  		// If we're stopped, return right away
  1163  		if atomic.LoadUint32(&stop) != 0 {
  1164  			return nil
  1165  		}
  1166  
  1167  		switch m := n.Meta.(type) {
  1168  		case *GraphNodeModule:
  1169  			// Build another walkContext for this module and walk it.
  1170  			wc := c.Context.walkContext(c.Operation, m.Path)
  1171  
  1172  			// Set the graph to specifically walk this subgraph
  1173  			wc.graph = m.Graph
  1174  
  1175  			// Preserve the meta
  1176  			wc.Meta = c.Meta
  1177  
  1178  			// Set the variables
  1179  			if m.Config != nil {
  1180  				wc.Variables = make(map[string]string)
  1181  
  1182  				rc := NewResourceConfig(m.Config.RawConfig)
  1183  				rc.interpolate(c, nil)
  1184  				for k, v := range rc.Config {
  1185  					wc.Variables[k] = v.(string)
  1186  				}
  1187  				for k, _ := range rc.Raw {
  1188  					if _, ok := wc.Variables[k]; !ok {
  1189  						wc.Variables[k] = config.UnknownVariableValue
  1190  					}
  1191  				}
  1192  			}
  1193  
  1194  			return wc.Walk()
  1195  		case *GraphNodeResource:
  1196  			// Continue, we care about this the most
  1197  		case *GraphNodeResourceProvider:
  1198  			sharedProvider := m.Provider
  1199  
  1200  			// Check if we have an override
  1201  			cs, ok := c.Context.providerConfig[m.ID]
  1202  			if !ok {
  1203  				cs = make(map[string]map[string]interface{})
  1204  			}
  1205  
  1206  			for k, p := range sharedProvider.Providers {
  1207  				// Interpolate our own configuration before merging
  1208  				if sharedProvider.Config != nil {
  1209  					rc := NewResourceConfig(sharedProvider.Config.RawConfig)
  1210  					rc.interpolate(c, nil)
  1211  				}
  1212  
  1213  				// Merge the configurations to get what we use to configure
  1214  				// with. We don't need to interpolate this because the
  1215  				// lines above verify that all parents are interpolated
  1216  				// properly.
  1217  				rc := sharedProvider.MergeConfig(false, cs[k])
  1218  
  1219  				log.Printf("[INFO] Configuring provider: %s", k)
  1220  				err := p.Configure(rc)
  1221  				if err != nil {
  1222  					return err
  1223  				}
  1224  			}
  1225  
  1226  			return nil
  1227  		default:
  1228  			panic(fmt.Sprintf("unknown graph node: %#v", n.Meta))
  1229  		}
  1230  
  1231  		rn := n.Meta.(*GraphNodeResource)
  1232  
  1233  		// If we're expanding, then expand the nodes, and then rewalk the graph
  1234  		if rn.ExpandMode > ResourceExpandNone {
  1235  			return c.genericWalkResource(rn, walkFn)
  1236  		}
  1237  
  1238  		// Make sure that at least some resource configuration is set
  1239  		if rn.Config == nil {
  1240  			rn.Resource.Config = new(ResourceConfig)
  1241  		} else {
  1242  			rn.Resource.Config = NewResourceConfig(rn.Config.RawConfig)
  1243  		}
  1244  
  1245  		// Handle recovery of special panic scenarios
  1246  		defer func() {
  1247  			if v := recover(); v != nil {
  1248  				if v == HookActionHalt {
  1249  					atomic.StoreUint32(&stop, 1)
  1250  				} else {
  1251  					panic(v)
  1252  				}
  1253  			}
  1254  		}()
  1255  
  1256  		// Limit parallelism
  1257  		c.Context.parallelSem.Acquire()
  1258  		defer c.Context.parallelSem.Release()
  1259  
  1260  		// Call the callack
  1261  		log.Printf(
  1262  			"[INFO] Module %s walking: %s (Graph node: %s)",
  1263  			strings.Join(c.Path, "."),
  1264  			rn.Resource.Id,
  1265  			n.Name)
  1266  		if err := cb(c, rn.Resource); err != nil {
  1267  			log.Printf("[ERROR] Error walking '%s': %s", rn.Resource.Id, err)
  1268  			return err
  1269  		}
  1270  
  1271  		return nil
  1272  	}
  1273  
  1274  	return walkFn
  1275  }
  1276  
  1277  func (c *walkContext) genericWalkResource(
  1278  	rn *GraphNodeResource, fn depgraph.WalkFunc) error {
  1279  	// Interpolate the count
  1280  	rc := NewResourceConfig(rn.Config.RawCount)
  1281  	rc.interpolate(c, rn.Resource)
  1282  
  1283  	// If we're validating, then we set the count to 1 if it is computed
  1284  	if c.Operation == walkValidate {
  1285  		if key := rn.Config.RawCount.Key; rc.IsComputed(key) {
  1286  			// Preserve the old value so that we reset it properly
  1287  			old := rn.Config.RawCount.Raw[key]
  1288  			defer func() {
  1289  				rn.Config.RawCount.Raw[key] = old
  1290  			}()
  1291  
  1292  			// Set th count to 1 for validation purposes
  1293  			rn.Config.RawCount.Raw[key] = "1"
  1294  		}
  1295  	}
  1296  
  1297  	// Expand the node to the actual resources
  1298  	g, err := rn.Expand()
  1299  	if err != nil {
  1300  		return err
  1301  	}
  1302  
  1303  	// Walk the graph with our function
  1304  	if err := g.Walk(fn); err != nil {
  1305  		return err
  1306  	}
  1307  
  1308  	return nil
  1309  }
  1310  
  1311  // applyProvisioners is used to run any provisioners a resource has
  1312  // defined after the resource creation has already completed.
  1313  func (c *walkContext) applyProvisioners(r *Resource, is *InstanceState) error {
  1314  	// Store the original connection info, restore later
  1315  	origConnInfo := is.Ephemeral.ConnInfo
  1316  	defer func() {
  1317  		is.Ephemeral.ConnInfo = origConnInfo
  1318  	}()
  1319  
  1320  	for _, prov := range r.Provisioners {
  1321  		// Interpolate since we may have variables that depend on the
  1322  		// local resource.
  1323  		if err := prov.Config.interpolate(c, r); err != nil {
  1324  			return err
  1325  		}
  1326  
  1327  		// Interpolate the conn info, since it may contain variables
  1328  		connInfo := NewResourceConfig(prov.ConnInfo)
  1329  		if err := connInfo.interpolate(c, r); err != nil {
  1330  			return err
  1331  		}
  1332  
  1333  		// Merge the connection information
  1334  		overlay := make(map[string]string)
  1335  		if origConnInfo != nil {
  1336  			for k, v := range origConnInfo {
  1337  				overlay[k] = v
  1338  			}
  1339  		}
  1340  		for k, v := range connInfo.Config {
  1341  			switch vt := v.(type) {
  1342  			case string:
  1343  				overlay[k] = vt
  1344  			case int64:
  1345  				overlay[k] = strconv.FormatInt(vt, 10)
  1346  			case int32:
  1347  				overlay[k] = strconv.FormatInt(int64(vt), 10)
  1348  			case int:
  1349  				overlay[k] = strconv.FormatInt(int64(vt), 10)
  1350  			case float32:
  1351  				overlay[k] = strconv.FormatFloat(float64(vt), 'f', 3, 32)
  1352  			case float64:
  1353  				overlay[k] = strconv.FormatFloat(vt, 'f', 3, 64)
  1354  			case bool:
  1355  				overlay[k] = strconv.FormatBool(vt)
  1356  			default:
  1357  				overlay[k] = fmt.Sprintf("%v", vt)
  1358  			}
  1359  		}
  1360  		is.Ephemeral.ConnInfo = overlay
  1361  
  1362  		// Invoke the Provisioner
  1363  		for _, h := range c.Context.hooks {
  1364  			handleHook(h.PreProvision(r.Info, prov.Type))
  1365  		}
  1366  
  1367  		output := ProvisionerUIOutput{
  1368  			Info:  r.Info,
  1369  			Type:  prov.Type,
  1370  			Hooks: c.Context.hooks,
  1371  		}
  1372  		err := prov.Provisioner.Apply(&output, is, prov.Config)
  1373  		if err != nil {
  1374  			return err
  1375  		}
  1376  
  1377  		for _, h := range c.Context.hooks {
  1378  			handleHook(h.PostProvision(r.Info, prov.Type))
  1379  		}
  1380  	}
  1381  
  1382  	return nil
  1383  }
  1384  
  1385  // persistState persists the state in a Resource to the actual final
  1386  // state location.
  1387  func (c *walkContext) persistState(r *Resource) {
  1388  	// Acquire a state lock around this whole thing since we're updating that
  1389  	c.Context.sl.Lock()
  1390  	defer c.Context.sl.Unlock()
  1391  
  1392  	// If we have no state, then we don't persist.
  1393  	if c.Context.state == nil {
  1394  		return
  1395  	}
  1396  
  1397  	// Get the state for this resource. The resource state should always
  1398  	// exist because we call graphInitState before anything that could
  1399  	// potentially call this.
  1400  	module := c.Context.state.ModuleByPath(c.Path)
  1401  	if module == nil {
  1402  		module = c.Context.state.AddModule(c.Path)
  1403  	}
  1404  	rs := module.Resources[r.Id]
  1405  	if rs == nil {
  1406  		rs = &ResourceState{Type: r.Info.Type}
  1407  		rs.init()
  1408  		module.Resources[r.Id] = rs
  1409  	}
  1410  	rs.Dependencies = r.Dependencies
  1411  
  1412  	// Assign the instance state to the proper location
  1413  	if r.Flags&FlagDeposed != 0 {
  1414  		// We were previously the primary and have been deposed, so
  1415  		// now we are the final tainted resource
  1416  		r.TaintedIndex = len(rs.Tainted) - 1
  1417  		rs.Tainted[r.TaintedIndex] = r.State
  1418  
  1419  	} else if r.Flags&FlagTainted != 0 {
  1420  		if r.TaintedIndex >= 0 {
  1421  			// Tainted with a pre-existing index, just update that spot
  1422  			rs.Tainted[r.TaintedIndex] = r.State
  1423  
  1424  		} else if r.Flags&FlagReplacePrimary != 0 {
  1425  			// We just replaced the primary, so restore the primary
  1426  			rs.Primary = rs.Tainted[len(rs.Tainted)-1]
  1427  
  1428  			// Set ourselves as tainted
  1429  			rs.Tainted[len(rs.Tainted)-1] = r.State
  1430  
  1431  		} else {
  1432  			// Newly tainted, so append it to the list, update the
  1433  			// index, and remove the primary.
  1434  			rs.Tainted = append(rs.Tainted, r.State)
  1435  			r.TaintedIndex = len(rs.Tainted) - 1
  1436  			rs.Primary = nil
  1437  		}
  1438  
  1439  	} else if r.Flags&FlagReplacePrimary != 0 {
  1440  		// If the ID is blank (there was an error), then we leave
  1441  		// the primary that exists, and do not store this as a tainted
  1442  		// instance
  1443  		if r.State.ID == "" {
  1444  			return
  1445  		}
  1446  
  1447  		// Push the old primary into the tainted state
  1448  		rs.Tainted = append(rs.Tainted, rs.Primary)
  1449  
  1450  		// Set this as the new primary
  1451  		rs.Primary = r.State
  1452  
  1453  	} else {
  1454  		// The primary instance, so just set it directly
  1455  		rs.Primary = r.State
  1456  	}
  1457  
  1458  	// Do a pruning so that empty resources are not saved
  1459  	rs.prune()
  1460  }
  1461  
  1462  // computeVars takes the State and given RawConfig and processes all
  1463  // the variables. This dynamically discovers the attributes instead of
  1464  // using a static map[string]string that the genericWalkFn uses.
  1465  func (c *walkContext) computeVars(
  1466  	raw *config.RawConfig, r *Resource) error {
  1467  	// If there isn't a raw configuration, don't do anything
  1468  	if raw == nil {
  1469  		return nil
  1470  	}
  1471  
  1472  	// Copy the default variables
  1473  	vs := make(map[string]string)
  1474  	for k, v := range c.defaultVariables {
  1475  		vs[k] = v
  1476  	}
  1477  
  1478  	// Next, the actual computed variables
  1479  	for n, rawV := range raw.Variables {
  1480  		switch v := rawV.(type) {
  1481  		case *config.CountVariable:
  1482  			switch v.Type {
  1483  			case config.CountValueIndex:
  1484  				if r != nil {
  1485  					vs[n] = strconv.FormatInt(int64(r.CountIndex), 10)
  1486  				}
  1487  			}
  1488  		case *config.ModuleVariable:
  1489  			if c.Operation == walkValidate {
  1490  				vs[n] = config.UnknownVariableValue
  1491  				continue
  1492  			}
  1493  
  1494  			value, err := c.computeModuleVariable(v)
  1495  			if err != nil {
  1496  				return err
  1497  			}
  1498  
  1499  			vs[n] = value
  1500  		case *config.PathVariable:
  1501  			switch v.Type {
  1502  			case config.PathValueCwd:
  1503  				wd, err := os.Getwd()
  1504  				if err != nil {
  1505  					return fmt.Errorf(
  1506  						"Couldn't get cwd for var %s: %s",
  1507  						v.FullKey(), err)
  1508  				}
  1509  
  1510  				vs[n] = wd
  1511  			case config.PathValueModule:
  1512  				if t := c.Context.module.Child(c.Path[1:]); t != nil {
  1513  					vs[n] = t.Config().Dir
  1514  				}
  1515  			case config.PathValueRoot:
  1516  				vs[n] = c.Context.module.Config().Dir
  1517  			}
  1518  		case *config.ResourceVariable:
  1519  			if c.Operation == walkValidate {
  1520  				vs[n] = config.UnknownVariableValue
  1521  				continue
  1522  			}
  1523  
  1524  			var attr string
  1525  			var err error
  1526  			if v.Multi && v.Index == -1 {
  1527  				attr, err = c.computeResourceMultiVariable(v)
  1528  			} else {
  1529  				attr, err = c.computeResourceVariable(v)
  1530  			}
  1531  			if err != nil {
  1532  				return err
  1533  			}
  1534  
  1535  			vs[n] = attr
  1536  		case *config.UserVariable:
  1537  			val, ok := c.Variables[v.Name]
  1538  			if ok {
  1539  				vs[n] = val
  1540  				continue
  1541  			}
  1542  
  1543  			if _, ok := vs[n]; !ok && c.Operation == walkValidate {
  1544  				vs[n] = config.UnknownVariableValue
  1545  				continue
  1546  			}
  1547  
  1548  			// Look up if we have any variables with this prefix because
  1549  			// those are map overrides. Include those.
  1550  			for k, val := range c.Variables {
  1551  				if strings.HasPrefix(k, v.Name+".") {
  1552  					vs["var."+k] = val
  1553  				}
  1554  			}
  1555  		}
  1556  	}
  1557  
  1558  	// Interpolate the variables
  1559  	return raw.Interpolate(vs)
  1560  }
  1561  
  1562  func (c *walkContext) computeModuleVariable(
  1563  	v *config.ModuleVariable) (string, error) {
  1564  	// Build the path to our child
  1565  	path := make([]string, len(c.Path), len(c.Path)+1)
  1566  	copy(path, c.Path)
  1567  	path = append(path, v.Name)
  1568  
  1569  	// Grab some locks
  1570  	c.Context.sl.RLock()
  1571  	defer c.Context.sl.RUnlock()
  1572  
  1573  	// Get that module from our state
  1574  	mod := c.Context.state.ModuleByPath(path)
  1575  	if mod == nil {
  1576  		return "", fmt.Errorf(
  1577  			"Module '%s' not found for variable '%s'",
  1578  			strings.Join(path[1:], "."),
  1579  			v.FullKey())
  1580  	}
  1581  
  1582  	value, ok := mod.Outputs[v.Field]
  1583  	if !ok {
  1584  		return "", fmt.Errorf(
  1585  			"Output field '%s' not found for variable '%s'",
  1586  			v.Field,
  1587  			v.FullKey())
  1588  	}
  1589  
  1590  	return value, nil
  1591  }
  1592  
  1593  func (c *walkContext) computeResourceVariable(
  1594  	v *config.ResourceVariable) (string, error) {
  1595  	id := v.ResourceId()
  1596  	if v.Multi {
  1597  		id = fmt.Sprintf("%s.%d", id, v.Index)
  1598  	}
  1599  
  1600  	c.Context.sl.RLock()
  1601  	defer c.Context.sl.RUnlock()
  1602  
  1603  	// Get the relevant module
  1604  	module := c.Context.state.ModuleByPath(c.Path)
  1605  
  1606  	r, ok := module.Resources[id]
  1607  	if !ok {
  1608  		if v.Multi && v.Index == 0 {
  1609  			r, ok = module.Resources[v.ResourceId()]
  1610  		}
  1611  		if !ok {
  1612  			return "", fmt.Errorf(
  1613  				"Resource '%s' not found for variable '%s'",
  1614  				id,
  1615  				v.FullKey())
  1616  		}
  1617  	}
  1618  
  1619  	if r.Primary == nil {
  1620  		goto MISSING
  1621  	}
  1622  
  1623  	if attr, ok := r.Primary.Attributes[v.Field]; ok {
  1624  		return attr, nil
  1625  	}
  1626  
  1627  	// We didn't find the exact field, so lets separate the dots
  1628  	// and see if anything along the way is a computed set. i.e. if
  1629  	// we have "foo.0.bar" as the field, check to see if "foo" is
  1630  	// a computed list. If so, then the whole thing is computed.
  1631  	if parts := strings.Split(v.Field, "."); len(parts) > 1 {
  1632  		for i := 1; i < len(parts); i++ {
  1633  			key := fmt.Sprintf("%s.#", strings.Join(parts[:i], "."))
  1634  			if attr, ok := r.Primary.Attributes[key]; ok {
  1635  				return attr, nil
  1636  			}
  1637  		}
  1638  	}
  1639  
  1640  MISSING:
  1641  	return "", fmt.Errorf(
  1642  		"Resource '%s' does not have attribute '%s' "+
  1643  			"for variable '%s'",
  1644  		id,
  1645  		v.Field,
  1646  		v.FullKey())
  1647  }
  1648  
  1649  func (c *walkContext) computeResourceMultiVariable(
  1650  	v *config.ResourceVariable) (string, error) {
  1651  	c.Context.sl.RLock()
  1652  	defer c.Context.sl.RUnlock()
  1653  
  1654  	// Get the resource from the configuration so we can know how
  1655  	// many of the resource there is.
  1656  	var cr *config.Resource
  1657  	for _, r := range c.Context.module.Config().Resources {
  1658  		if r.Id() == v.ResourceId() {
  1659  			cr = r
  1660  			break
  1661  		}
  1662  	}
  1663  	if cr == nil {
  1664  		return "", fmt.Errorf(
  1665  			"Resource '%s' not found for variable '%s'",
  1666  			v.ResourceId(),
  1667  			v.FullKey())
  1668  	}
  1669  
  1670  	// Get the relevant module
  1671  	// TODO: Not use only root module
  1672  	module := c.Context.state.RootModule()
  1673  
  1674  	count, err := cr.Count()
  1675  	if err != nil {
  1676  		return "", fmt.Errorf(
  1677  			"Error reading %s count: %s",
  1678  			v.ResourceId(),
  1679  			err)
  1680  	}
  1681  
  1682  	// If we have no count, return empty
  1683  	if count == 0 {
  1684  		return "", nil
  1685  	}
  1686  
  1687  	var values []string
  1688  	for i := 0; i < count; i++ {
  1689  		id := fmt.Sprintf("%s.%d", v.ResourceId(), i)
  1690  
  1691  		// If we're dealing with only a single resource, then the
  1692  		// ID doesn't have a trailing index.
  1693  		if count == 1 {
  1694  			id = v.ResourceId()
  1695  		}
  1696  
  1697  		r, ok := module.Resources[id]
  1698  		if !ok {
  1699  			continue
  1700  		}
  1701  
  1702  		if r.Primary == nil {
  1703  			continue
  1704  		}
  1705  
  1706  		attr, ok := r.Primary.Attributes[v.Field]
  1707  		if !ok {
  1708  			continue
  1709  		}
  1710  
  1711  		values = append(values, attr)
  1712  	}
  1713  
  1714  	if len(values) == 0 {
  1715  		return "", fmt.Errorf(
  1716  			"Resource '%s' does not have attribute '%s' "+
  1717  				"for variable '%s'",
  1718  			v.ResourceId(),
  1719  			v.Field,
  1720  			v.FullKey())
  1721  	}
  1722  
  1723  	return strings.Join(values, config.InterpSplitDelim), nil
  1724  }
  1725  
  1726  type walkInputMeta struct {
  1727  	sync.Mutex
  1728  
  1729  	Done map[string]struct{}
  1730  }
  1731  
  1732  type walkValidateMeta struct {
  1733  	Errs     []error
  1734  	Warns    []string
  1735  	Children map[string]*walkValidateMeta
  1736  }
  1737  
  1738  func (m *walkValidateMeta) Flatten() ([]string, []error) {
  1739  	// Prune out the empty children
  1740  	for k, m2 := range m.Children {
  1741  		if len(m2.Errs) == 0 && len(m2.Warns) == 0 {
  1742  			delete(m.Children, k)
  1743  		}
  1744  	}
  1745  
  1746  	// If we have no children, then just return what we have
  1747  	if len(m.Children) == 0 {
  1748  		return m.Warns, m.Errs
  1749  	}
  1750  
  1751  	// Otherwise, copy the errors and warnings
  1752  	errs := make([]error, len(m.Errs))
  1753  	warns := make([]string, len(m.Warns))
  1754  	for i, err := range m.Errs {
  1755  		errs[i] = err
  1756  	}
  1757  	for i, warn := range m.Warns {
  1758  		warns[i] = warn
  1759  	}
  1760  
  1761  	// Now go through each child and copy it in...
  1762  	for k, c := range m.Children {
  1763  		for _, err := range c.Errs {
  1764  			errs = append(errs, fmt.Errorf(
  1765  				"Module %s: %s", k, err))
  1766  		}
  1767  		for _, warn := range c.Warns {
  1768  			warns = append(warns, fmt.Sprintf(
  1769  				"Module %s: %s", k, warn))
  1770  		}
  1771  	}
  1772  
  1773  	return warns, errs
  1774  }