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