github.com/ezbercih/terraform@v0.1.1-0.20140729011846-3c33865e0839/terraform/graph.go (about)

     1  package terraform
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"sort"
     8  	"strings"
     9  
    10  	"github.com/hashicorp/terraform/config"
    11  	"github.com/hashicorp/terraform/depgraph"
    12  	"github.com/hashicorp/terraform/helper/multierror"
    13  )
    14  
    15  // GraphOpts are options used to create the resource graph that Terraform
    16  // walks to make changes to infrastructure.
    17  //
    18  // Depending on what options are set, the resulting graph will come in
    19  // varying degrees of completeness.
    20  type GraphOpts struct {
    21  	// Config is the configuration from which to build the basic graph.
    22  	// This is the only required item.
    23  	Config *config.Config
    24  
    25  	// Diff of changes that will be applied to the given state. This will
    26  	// associate a ResourceDiff with applicable resources. Additionally,
    27  	// new resource nodes representing resource destruction may be inserted
    28  	// into the graph.
    29  	Diff *Diff
    30  
    31  	// State, if present, will make the ResourceState available on each
    32  	// resource node. Additionally, any orphans will be added automatically
    33  	// to the graph.
    34  	State *State
    35  
    36  	// Providers is a mapping of prefixes to a resource provider. If given,
    37  	// resource providers will be found, initialized, and associated to the
    38  	// resources in the graph.
    39  	//
    40  	// This will also potentially insert new nodes into the graph for
    41  	// the configuration of resource providers.
    42  	Providers map[string]ResourceProviderFactory
    43  
    44  	// Provisioners is a mapping of names to a resource provisioner.
    45  	// These must be provided to support resource provisioners.
    46  	Provisioners map[string]ResourceProvisionerFactory
    47  }
    48  
    49  // GraphRootNode is the name of the root node in the Terraform resource
    50  // graph. This node is just a placemarker and has no associated functionality.
    51  const GraphRootNode = "root"
    52  
    53  // GraphNodeResource is a node type in the graph that represents a resource
    54  // that will be created or managed. Unlike the GraphNodeResourceMeta node,
    55  // this represents a _single_, _resource_ to be managed, not a set of resources
    56  // or a component of a resource.
    57  type GraphNodeResource struct {
    58  	Index              int
    59  	Type               string
    60  	Config             *config.Resource
    61  	Orphan             bool
    62  	Resource           *Resource
    63  	ResourceProviderID string
    64  }
    65  
    66  // GraphNodeResourceMeta is a node type in the graph that represents the
    67  // metadata for a resource. There will be one meta node for every resource
    68  // in the configuration.
    69  type GraphNodeResourceMeta struct {
    70  	ID    string
    71  	Name  string
    72  	Type  string
    73  	Count int
    74  }
    75  
    76  // GraphNodeResourceProvider is a node type in the graph that represents
    77  // the configuration for a resource provider.
    78  type GraphNodeResourceProvider struct {
    79  	ID           string
    80  	Providers    map[string]ResourceProvider
    81  	ProviderKeys []string
    82  	Config       *config.ProviderConfig
    83  }
    84  
    85  // Graph builds a dependency graph of all the resources for infrastructure
    86  // change.
    87  //
    88  // This dependency graph shows the correct order that any resources need
    89  // to be operated on.
    90  //
    91  // The Meta field of a graph Noun can contain one of the follow types. A
    92  // description is next to each type to explain what it is.
    93  //
    94  //   *GraphNodeResource - A resource. See the documentation of this
    95  //     struct for more details.
    96  //   *GraphNodeResourceProvider - A resource provider that needs to be
    97  //     configured at this point.
    98  //
    99  func Graph(opts *GraphOpts) (*depgraph.Graph, error) {
   100  	if opts.Config == nil {
   101  		return nil, errors.New("Config is required for Graph")
   102  	}
   103  
   104  	log.Printf("[DEBUG] Creating graph...")
   105  
   106  	g := new(depgraph.Graph)
   107  
   108  	// First, build the initial resource graph. This only has the resources
   109  	// and no dependencies.
   110  	graphAddConfigResources(g, opts.Config, opts.State)
   111  
   112  	// Add explicit dependsOn dependencies to the graph
   113  	graphAddExplicitDeps(g)
   114  
   115  	// Next, add the state orphans if we have any
   116  	if opts.State != nil {
   117  		graphAddOrphans(g, opts.Config, opts.State)
   118  	}
   119  
   120  	// Map the provider configurations to all of the resources
   121  	graphAddProviderConfigs(g, opts.Config)
   122  
   123  	// Setup the provisioners. These may have variable dependencies,
   124  	// and must be done before dependency setup
   125  	if err := graphMapResourceProvisioners(g, opts.Provisioners); err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	// Add all the variable dependencies
   130  	graphAddVariableDeps(g)
   131  
   132  	// Build the root so that we have a single valid root
   133  	graphAddRoot(g)
   134  
   135  	// If providers were given, lets associate the proper providers and
   136  	// instantiate them.
   137  	if len(opts.Providers) > 0 {
   138  		// Add missing providers from the mapping
   139  		if err := graphAddMissingResourceProviders(g, opts.Providers); err != nil {
   140  			return nil, err
   141  		}
   142  
   143  		// Initialize all the providers
   144  		if err := graphInitResourceProviders(g, opts.Providers); err != nil {
   145  			return nil, err
   146  		}
   147  
   148  		// Map the providers to resources
   149  		if err := graphMapResourceProviders(g); err != nil {
   150  			return nil, err
   151  		}
   152  	}
   153  
   154  	// If we have a diff, then make sure to add that in
   155  	if opts.Diff != nil {
   156  		if err := graphAddDiff(g, opts.Diff); err != nil {
   157  			return nil, err
   158  		}
   159  	}
   160  
   161  	// Validate
   162  	if err := g.Validate(); err != nil {
   163  		return nil, err
   164  	}
   165  
   166  	log.Printf(
   167  		"[DEBUG] Graph created and valid. %d nouns.",
   168  		len(g.Nouns))
   169  
   170  	return g, nil
   171  }
   172  
   173  // configGraph turns a configuration structure into a dependency graph.
   174  func graphAddConfigResources(
   175  	g *depgraph.Graph, c *config.Config, s *State) {
   176  	// This tracks all the resource nouns
   177  	nouns := make(map[string]*depgraph.Noun)
   178  	for _, r := range c.Resources {
   179  		resourceNouns := make([]*depgraph.Noun, r.Count)
   180  		for i := 0; i < r.Count; i++ {
   181  			name := r.Id()
   182  			index := -1
   183  
   184  			// If we have a count that is more than one, then make sure
   185  			// we suffix with the number of the resource that this is.
   186  			if r.Count > 1 {
   187  				name = fmt.Sprintf("%s.%d", name, i)
   188  				index = i
   189  			}
   190  
   191  			// Determine if this resource is tainted
   192  			tainted := false
   193  			if s != nil && s.Tainted != nil {
   194  				_, tainted = s.Tainted[r.Id()]
   195  			}
   196  
   197  			var state *ResourceState
   198  			if s != nil {
   199  				state = s.Resources[name]
   200  
   201  				if state == nil {
   202  					if r.Count == 1 {
   203  						// If the count is one, check the state for ".0"
   204  						// appended, which might exist if we go from
   205  						// count > 1 to count == 1.
   206  						state = s.Resources[r.Id()+".0"]
   207  					} else if i == 0 {
   208  						// If count is greater than one, check for state
   209  						// with just the ID, which might exist if we go
   210  						// from count == 1 to count > 1
   211  						state = s.Resources[r.Id()]
   212  					}
   213  				}
   214  			}
   215  			if state == nil {
   216  				state = &ResourceState{
   217  					Type: r.Type,
   218  				}
   219  			}
   220  
   221  			resourceNouns[i] = &depgraph.Noun{
   222  				Name: name,
   223  				Meta: &GraphNodeResource{
   224  					Index:  index,
   225  					Type:   r.Type,
   226  					Config: r,
   227  					Resource: &Resource{
   228  						Id:      name,
   229  						State:   state,
   230  						Config:  NewResourceConfig(r.RawConfig),
   231  						Tainted: tainted,
   232  					},
   233  				},
   234  			}
   235  		}
   236  
   237  		// If we have more than one, then create a meta node to track
   238  		// the resources.
   239  		if r.Count > 1 {
   240  			metaNoun := &depgraph.Noun{
   241  				Name: r.Id(),
   242  				Meta: &GraphNodeResourceMeta{
   243  					ID:    r.Id(),
   244  					Name:  r.Name,
   245  					Type:  r.Type,
   246  					Count: r.Count,
   247  				},
   248  			}
   249  
   250  			// Create the dependencies on this noun
   251  			for _, n := range resourceNouns {
   252  				metaNoun.Deps = append(metaNoun.Deps, &depgraph.Dependency{
   253  					Name:   n.Name,
   254  					Source: metaNoun,
   255  					Target: n,
   256  				})
   257  			}
   258  
   259  			// Assign it to the map so that we have it
   260  			nouns[metaNoun.Name] = metaNoun
   261  		}
   262  
   263  		for _, n := range resourceNouns {
   264  			nouns[n.Name] = n
   265  		}
   266  	}
   267  
   268  	// Build the list of nouns that we iterate over
   269  	nounsList := make([]*depgraph.Noun, 0, len(nouns))
   270  	for _, n := range nouns {
   271  		nounsList = append(nounsList, n)
   272  	}
   273  
   274  	g.Name = "terraform"
   275  	g.Nouns = append(g.Nouns, nounsList...)
   276  }
   277  
   278  // graphAddDiff takes an already-built graph of resources and adds the
   279  // diffs to the resource nodes themselves.
   280  //
   281  // This may also introduces new graph elements. If there are diffs that
   282  // require a destroy, new elements may be introduced since destroy order
   283  // is different than create order. For example, destroying a VPC requires
   284  // destroying the VPC's subnets first, whereas creating a VPC requires
   285  // doing it before the subnets are created. This function handles inserting
   286  // these nodes for you.
   287  func graphAddDiff(g *depgraph.Graph, d *Diff) error {
   288  	var nlist []*depgraph.Noun
   289  	for _, n := range g.Nouns {
   290  		rn, ok := n.Meta.(*GraphNodeResource)
   291  		if !ok {
   292  			continue
   293  		}
   294  
   295  		rd, ok := d.Resources[rn.Resource.Id]
   296  		if !ok {
   297  			continue
   298  		}
   299  		if rd.Empty() {
   300  			continue
   301  		}
   302  
   303  		if rd.Destroy {
   304  			// If we're destroying, we create a new destroy node with
   305  			// the proper dependencies. Perform a dirty copy operation.
   306  			newNode := new(GraphNodeResource)
   307  			*newNode = *rn
   308  			newNode.Resource = new(Resource)
   309  			*newNode.Resource = *rn.Resource
   310  
   311  			// Make the diff _just_ the destroy.
   312  			newNode.Resource.Diff = &ResourceDiff{Destroy: true}
   313  
   314  			// Create the new node
   315  			newN := &depgraph.Noun{
   316  				Name: fmt.Sprintf("%s (destroy)", newNode.Resource.Id),
   317  				Meta: newNode,
   318  			}
   319  			newN.Deps = make([]*depgraph.Dependency, 0, len(n.Deps))
   320  			for _, d := range n.Deps {
   321  				// We don't want to copy any resource dependencies
   322  				if _, ok := d.Target.Meta.(*GraphNodeResource); ok {
   323  					continue
   324  				}
   325  
   326  				newN.Deps = append(newN.Deps, &depgraph.Dependency{
   327  					Name:   d.Name,
   328  					Source: newN,
   329  					Target: d.Target,
   330  				})
   331  			}
   332  
   333  			// Append it to the list so we handle it later
   334  			nlist = append(nlist, newN)
   335  
   336  			// Mark the old diff to not destroy since we handle that in
   337  			// the dedicated node.
   338  			newDiff := new(ResourceDiff)
   339  			*newDiff = *rd
   340  			newDiff.Destroy = false
   341  			rd = newDiff
   342  
   343  			// Add to the new noun to our dependencies so that the destroy
   344  			// happens before the apply.
   345  			n.Deps = append(n.Deps, &depgraph.Dependency{
   346  				Name:   newN.Name,
   347  				Source: n,
   348  				Target: newN,
   349  			})
   350  
   351  			// If the resource is tainted, mark the state as nil so
   352  			// that a fresh create is done.
   353  			if rn.Resource.Tainted {
   354  				rn.Resource.State = &ResourceState{
   355  					Type: rn.Resource.State.Type,
   356  				}
   357  				rn.Resource.Tainted = false
   358  			}
   359  		}
   360  
   361  		rn.Resource.Diff = rd
   362  	}
   363  
   364  	// Go through each noun and make sure we calculate all the dependencies
   365  	// properly.
   366  	for _, n := range nlist {
   367  		rn := n.Meta.(*GraphNodeResource)
   368  
   369  		// If we have no dependencies, then just continue
   370  		deps := rn.Resource.State.Dependencies
   371  		if len(deps) == 0 {
   372  			continue
   373  		}
   374  
   375  		// We have dependencies. We must be destroyed BEFORE those
   376  		// dependencies. Look to see if they're managed.
   377  		for _, dep := range deps {
   378  			for _, n2 := range nlist {
   379  				rn2 := n2.Meta.(*GraphNodeResource)
   380  				if rn2.Resource.State.ID == dep.ID {
   381  					n2.Deps = append(n2.Deps, &depgraph.Dependency{
   382  						Name:   n.Name,
   383  						Source: n2,
   384  						Target: n,
   385  					})
   386  
   387  					break
   388  				}
   389  			}
   390  		}
   391  	}
   392  
   393  	// Add the nouns to the graph
   394  	g.Nouns = append(g.Nouns, nlist...)
   395  
   396  	return nil
   397  }
   398  
   399  // graphAddExplicitDeps adds the dependencies to the graph for the explicit
   400  // dependsOn configurations.
   401  func graphAddExplicitDeps(g *depgraph.Graph) {
   402  	depends := false
   403  
   404  	rs := make(map[string]*depgraph.Noun)
   405  	for _, n := range g.Nouns {
   406  		rn, ok := n.Meta.(*GraphNodeResource)
   407  		if !ok {
   408  			continue
   409  		}
   410  
   411  		rs[rn.Config.Id()] = n
   412  		if len(rn.Config.DependsOn) > 0 {
   413  			depends = true
   414  		}
   415  	}
   416  
   417  	// If we didn't have any dependsOn, just return
   418  	if !depends {
   419  		return
   420  	}
   421  
   422  	for _, n1 := range rs {
   423  		rn1 := n1.Meta.(*GraphNodeResource)
   424  		for _, d := range rn1.Config.DependsOn {
   425  			for _, n2 := range rs {
   426  				rn2 := n2.Meta.(*GraphNodeResource)
   427  				if rn2.Config.Id() != d {
   428  					continue
   429  				}
   430  
   431  				n1.Deps = append(n1.Deps, &depgraph.Dependency{
   432  					Name:   d,
   433  					Source: n1,
   434  					Target: n2,
   435  				})
   436  			}
   437  		}
   438  	}
   439  }
   440  
   441  // graphAddMissingResourceProviders adds GraphNodeResourceProvider nodes for
   442  // the resources that do not have an explicit resource provider specified
   443  // because no provider configuration was given.
   444  func graphAddMissingResourceProviders(
   445  	g *depgraph.Graph,
   446  	ps map[string]ResourceProviderFactory) error {
   447  	var errs []error
   448  
   449  	for _, n := range g.Nouns {
   450  		rn, ok := n.Meta.(*GraphNodeResource)
   451  		if !ok {
   452  			continue
   453  		}
   454  		if rn.ResourceProviderID != "" {
   455  			continue
   456  		}
   457  
   458  		prefixes := matchingPrefixes(rn.Type, ps)
   459  		if len(prefixes) == 0 {
   460  			errs = append(errs, fmt.Errorf(
   461  				"No matching provider for type: %s",
   462  				rn.Type))
   463  			continue
   464  		}
   465  
   466  		// The resource provider ID is simply the shortest matching
   467  		// prefix, since that'll give us the most resource providers
   468  		// to choose from.
   469  		rn.ResourceProviderID = prefixes[len(prefixes)-1]
   470  
   471  		// If we don't have a matching noun for this yet, insert it.
   472  		pn := g.Noun(fmt.Sprintf("provider.%s", rn.ResourceProviderID))
   473  		if pn == nil {
   474  			pn = &depgraph.Noun{
   475  				Name: fmt.Sprintf("provider.%s", rn.ResourceProviderID),
   476  				Meta: &GraphNodeResourceProvider{
   477  					ID:     rn.ResourceProviderID,
   478  					Config: nil,
   479  				},
   480  			}
   481  			g.Nouns = append(g.Nouns, pn)
   482  		}
   483  
   484  		// Add the provider configuration noun as a dependency
   485  		dep := &depgraph.Dependency{
   486  			Name:   pn.Name,
   487  			Source: n,
   488  			Target: pn,
   489  		}
   490  		n.Deps = append(n.Deps, dep)
   491  	}
   492  
   493  	if len(errs) > 0 {
   494  		return &multierror.Error{Errors: errs}
   495  	}
   496  
   497  	return nil
   498  }
   499  
   500  // graphAddOrphans adds the orphans to the graph.
   501  func graphAddOrphans(g *depgraph.Graph, c *config.Config, s *State) {
   502  	for _, k := range s.Orphans(c) {
   503  		rs := s.Resources[k]
   504  		noun := &depgraph.Noun{
   505  			Name: k,
   506  			Meta: &GraphNodeResource{
   507  				Index:  -1,
   508  				Type:   rs.Type,
   509  				Orphan: true,
   510  				Resource: &Resource{
   511  					Id:     k,
   512  					State:  rs,
   513  					Config: NewResourceConfig(nil),
   514  				},
   515  			},
   516  		}
   517  		g.Nouns = append(g.Nouns, noun)
   518  	}
   519  }
   520  
   521  // graphAddProviderConfigs cycles through all the resource-like nodes
   522  // and adds the provider configuration nouns into the tree.
   523  func graphAddProviderConfigs(g *depgraph.Graph, c *config.Config) {
   524  	nounsList := make([]*depgraph.Noun, 0, 2)
   525  	pcNouns := make(map[string]*depgraph.Noun)
   526  	for _, noun := range g.Nouns {
   527  		resourceNode, ok := noun.Meta.(*GraphNodeResource)
   528  		if !ok {
   529  			continue
   530  		}
   531  
   532  		// Look up the provider config for this resource
   533  		pcName := config.ProviderConfigName(
   534  			resourceNode.Type, c.ProviderConfigs)
   535  		if pcName == "" {
   536  			continue
   537  		}
   538  
   539  		// We have one, so build the noun if it hasn't already been made
   540  		pcNoun, ok := pcNouns[pcName]
   541  		if !ok {
   542  			var pc *config.ProviderConfig
   543  			for _, v := range c.ProviderConfigs {
   544  				if v.Name == pcName {
   545  					pc = v
   546  					break
   547  				}
   548  			}
   549  			if pc == nil {
   550  				panic("pc not found")
   551  			}
   552  
   553  			pcNoun = &depgraph.Noun{
   554  				Name: fmt.Sprintf("provider.%s", pcName),
   555  				Meta: &GraphNodeResourceProvider{
   556  					ID:     pcName,
   557  					Config: pc,
   558  				},
   559  			}
   560  			pcNouns[pcName] = pcNoun
   561  			nounsList = append(nounsList, pcNoun)
   562  		}
   563  
   564  		// Set the resource provider ID for this noun so we can look it
   565  		// up later easily.
   566  		resourceNode.ResourceProviderID = pcName
   567  
   568  		// Add the provider configuration noun as a dependency
   569  		dep := &depgraph.Dependency{
   570  			Name:   pcName,
   571  			Source: noun,
   572  			Target: pcNoun,
   573  		}
   574  		noun.Deps = append(noun.Deps, dep)
   575  	}
   576  
   577  	// Add all the provider config nouns to the graph
   578  	g.Nouns = append(g.Nouns, nounsList...)
   579  }
   580  
   581  // graphAddRoot adds a root element to the graph so that there is a single
   582  // root to point to all the dependencies.
   583  func graphAddRoot(g *depgraph.Graph) {
   584  	root := &depgraph.Noun{Name: GraphRootNode}
   585  	for _, n := range g.Nouns {
   586  		switch m := n.Meta.(type) {
   587  		case *GraphNodeResource:
   588  			// If the resource is part of a group, we don't need to make a dep
   589  			if m.Index != -1 {
   590  				continue
   591  			}
   592  		case *GraphNodeResourceMeta:
   593  			// Always in the graph
   594  		case *GraphNodeResourceProvider:
   595  			// ResourceProviders don't need to be in the root deps because
   596  			// they're always pointed to by some resource.
   597  			continue
   598  		}
   599  
   600  		root.Deps = append(root.Deps, &depgraph.Dependency{
   601  			Name:   n.Name,
   602  			Source: root,
   603  			Target: n,
   604  		})
   605  	}
   606  	g.Nouns = append(g.Nouns, root)
   607  }
   608  
   609  // graphAddVariableDeps inspects all the nouns and adds any dependencies
   610  // based on variable values.
   611  func graphAddVariableDeps(g *depgraph.Graph) {
   612  	for _, n := range g.Nouns {
   613  		var vars map[string]config.InterpolatedVariable
   614  		switch m := n.Meta.(type) {
   615  		case *GraphNodeResource:
   616  			// Ignore orphan nodes
   617  			if m.Orphan {
   618  				continue
   619  			}
   620  
   621  			// Handle the resource variables
   622  			vars = m.Config.RawConfig.Variables
   623  			nounAddVariableDeps(g, n, vars, false)
   624  
   625  			// Handle the variables of the resource provisioners
   626  			for _, p := range m.Resource.Provisioners {
   627  				vars = p.RawConfig.Variables
   628  				nounAddVariableDeps(g, n, vars, true)
   629  
   630  				vars = p.ConnInfo.Variables
   631  				nounAddVariableDeps(g, n, vars, true)
   632  			}
   633  
   634  		case *GraphNodeResourceProvider:
   635  			vars = m.Config.RawConfig.Variables
   636  			nounAddVariableDeps(g, n, vars, false)
   637  
   638  		default:
   639  			continue
   640  		}
   641  	}
   642  }
   643  
   644  // nounAddVariableDeps updates the dependencies of a noun given
   645  // a set of associated variable values
   646  func nounAddVariableDeps(
   647  	g *depgraph.Graph,
   648  	n *depgraph.Noun,
   649  	vars map[string]config.InterpolatedVariable,
   650  	removeSelf bool) {
   651  	for _, v := range vars {
   652  		// Only resource variables impose dependencies
   653  		rv, ok := v.(*config.ResourceVariable)
   654  		if !ok {
   655  			continue
   656  		}
   657  
   658  		// Find the target
   659  		target := g.Noun(rv.ResourceId())
   660  		if target == nil {
   661  			continue
   662  		}
   663  
   664  		// If we're ignoring self-references, then don't add that
   665  		// dependency.
   666  		if removeSelf && n == target {
   667  			continue
   668  		}
   669  
   670  		// Build the dependency
   671  		dep := &depgraph.Dependency{
   672  			Name:   rv.ResourceId(),
   673  			Source: n,
   674  			Target: target,
   675  		}
   676  
   677  		n.Deps = append(n.Deps, dep)
   678  	}
   679  }
   680  
   681  // graphInitResourceProviders maps the resource providers onto the graph
   682  // given a mapping of prefixes to resource providers.
   683  //
   684  // Unlike the graphAdd* functions, this one can return an error if resource
   685  // providers can't be found or can't be instantiated.
   686  func graphInitResourceProviders(
   687  	g *depgraph.Graph,
   688  	ps map[string]ResourceProviderFactory) error {
   689  	var errs []error
   690  
   691  	// Keep track of providers we know we couldn't instantiate so
   692  	// that we don't get a ton of errors about the same provider.
   693  	failures := make(map[string]struct{})
   694  
   695  	for _, n := range g.Nouns {
   696  		// We only care about the resource providers first. There is guaranteed
   697  		// to be only one node per tuple (providerId, providerConfig), which
   698  		// means we don't need to verify we have instantiated it before.
   699  		rn, ok := n.Meta.(*GraphNodeResourceProvider)
   700  		if !ok {
   701  			continue
   702  		}
   703  
   704  		prefixes := matchingPrefixes(rn.ID, ps)
   705  		if len(prefixes) > 0 {
   706  			if _, ok := failures[prefixes[0]]; ok {
   707  				// We already failed this provider, meaning this
   708  				// resource will never succeed, so just continue.
   709  				continue
   710  			}
   711  		}
   712  
   713  		// Go through each prefix and instantiate if necessary, then
   714  		// verify if this provider is of use to us or not.
   715  		rn.Providers = make(map[string]ResourceProvider)
   716  		rn.ProviderKeys = prefixes
   717  		for _, prefix := range prefixes {
   718  			p, err := ps[prefix]()
   719  			if err != nil {
   720  				errs = append(errs, fmt.Errorf(
   721  					"Error instantiating resource provider for "+
   722  						"prefix %s: %s", prefix, err))
   723  
   724  				// Record the error so that we don't check it again
   725  				failures[prefix] = struct{}{}
   726  
   727  				// Jump to the next prefix
   728  				continue
   729  			}
   730  
   731  			rn.Providers[prefix] = p
   732  		}
   733  
   734  		// If we never found a provider, then error and continue
   735  		if len(rn.Providers) == 0 {
   736  			errs = append(errs, fmt.Errorf(
   737  				"Provider for configuration '%s' not found.",
   738  				rn.ID))
   739  			continue
   740  		}
   741  	}
   742  
   743  	if len(errs) > 0 {
   744  		return &multierror.Error{Errors: errs}
   745  	}
   746  
   747  	return nil
   748  }
   749  
   750  // graphMapResourceProviders takes a graph that already has initialized
   751  // the resource providers (using graphInitResourceProviders) and maps the
   752  // resource providers to the resources themselves.
   753  func graphMapResourceProviders(g *depgraph.Graph) error {
   754  	var errs []error
   755  
   756  	// First build a mapping of resource provider ID to the node that
   757  	// contains those resources.
   758  	mapping := make(map[string]*GraphNodeResourceProvider)
   759  	for _, n := range g.Nouns {
   760  		rn, ok := n.Meta.(*GraphNodeResourceProvider)
   761  		if !ok {
   762  			continue
   763  		}
   764  		mapping[rn.ID] = rn
   765  	}
   766  
   767  	// Now go through each of the resources and find a matching provider.
   768  	for _, n := range g.Nouns {
   769  		rn, ok := n.Meta.(*GraphNodeResource)
   770  		if !ok {
   771  			continue
   772  		}
   773  
   774  		rpn, ok := mapping[rn.ResourceProviderID]
   775  		if !ok {
   776  			// This should never happen since when building the graph
   777  			// we ensure that everything matches up.
   778  			panic(fmt.Sprintf(
   779  				"Resource provider ID not found: %s (type: %s)",
   780  				rn.ResourceProviderID,
   781  				rn.Type))
   782  		}
   783  
   784  		var provider ResourceProvider
   785  		for _, k := range rpn.ProviderKeys {
   786  			// Only try this provider if it has the right prefix
   787  			if !strings.HasPrefix(rn.Type, k) {
   788  				continue
   789  			}
   790  
   791  			rp := rpn.Providers[k]
   792  			if ProviderSatisfies(rp, rn.Type) {
   793  				provider = rp
   794  				break
   795  			}
   796  		}
   797  
   798  		if provider == nil {
   799  			errs = append(errs, fmt.Errorf(
   800  				"Resource provider not found for resource type '%s'",
   801  				rn.Type))
   802  			continue
   803  		}
   804  
   805  		rn.Resource.Provider = provider
   806  	}
   807  
   808  	if len(errs) > 0 {
   809  		return &multierror.Error{Errors: errs}
   810  	}
   811  
   812  	return nil
   813  }
   814  
   815  // graphMapResourceProvisioners takes a graph that already has
   816  // the resources and maps the resource provisioners to the resources themselves.
   817  func graphMapResourceProvisioners(g *depgraph.Graph,
   818  	provisioners map[string]ResourceProvisionerFactory) error {
   819  	var errs []error
   820  
   821  	// Create a cache of resource provisioners, avoids duplicate
   822  	// initialization of the instances
   823  	cache := make(map[string]ResourceProvisioner)
   824  
   825  	// Go through each of the resources and find a matching provisioners
   826  	for _, n := range g.Nouns {
   827  		rn, ok := n.Meta.(*GraphNodeResource)
   828  		if !ok {
   829  			continue
   830  		}
   831  
   832  		// Ignore orphan nodes with no provisioners
   833  		if rn.Config == nil {
   834  			continue
   835  		}
   836  
   837  		// Check each provisioner
   838  		for _, p := range rn.Config.Provisioners {
   839  			// Check for a cached provisioner
   840  			provisioner, ok := cache[p.Type]
   841  			if !ok {
   842  				// Lookup the factory method
   843  				factory, ok := provisioners[p.Type]
   844  				if !ok {
   845  					errs = append(errs, fmt.Errorf(
   846  						"Resource provisioner not found for provisioner type '%s'",
   847  						p.Type))
   848  					continue
   849  				}
   850  
   851  				// Initialize the provisioner
   852  				prov, err := factory()
   853  				if err != nil {
   854  					errs = append(errs, fmt.Errorf(
   855  						"Failed to instantiate provisioner type '%s': %v",
   856  						p.Type, err))
   857  					continue
   858  				}
   859  				provisioner = prov
   860  
   861  				// Cache this type of provisioner
   862  				cache[p.Type] = prov
   863  			}
   864  
   865  			// Save the provisioner
   866  			rn.Resource.Provisioners = append(rn.Resource.Provisioners, &ResourceProvisionerConfig{
   867  				Type:        p.Type,
   868  				Provisioner: provisioner,
   869  				Config:      NewResourceConfig(p.RawConfig),
   870  				RawConfig:   p.RawConfig,
   871  				ConnInfo:    p.ConnInfo,
   872  			})
   873  		}
   874  	}
   875  
   876  	if len(errs) > 0 {
   877  		return &multierror.Error{Errors: errs}
   878  	}
   879  	return nil
   880  }
   881  
   882  // matchingPrefixes takes a resource type and a set of resource
   883  // providers we know about by prefix and returns a list of prefixes
   884  // that might be valid for that resource.
   885  //
   886  // The list returned is in the order that they should be attempted.
   887  func matchingPrefixes(
   888  	t string,
   889  	ps map[string]ResourceProviderFactory) []string {
   890  	result := make([]string, 0, 1)
   891  	for prefix, _ := range ps {
   892  		if strings.HasPrefix(t, prefix) {
   893  			result = append(result, prefix)
   894  		}
   895  	}
   896  
   897  	// Sort by longest first
   898  	sort.Sort(stringLenSort(result))
   899  
   900  	return result
   901  }
   902  
   903  // stringLenSort implements sort.Interface and sorts strings in increasing
   904  // length order. i.e. "a", "aa", "aaa"
   905  type stringLenSort []string
   906  
   907  func (s stringLenSort) Len() int {
   908  	return len(s)
   909  }
   910  
   911  func (s stringLenSort) Less(i, j int) bool {
   912  	return len(s[i]) < len(s[j])
   913  }
   914  
   915  func (s stringLenSort) Swap(i, j int) {
   916  	s[i], s[j] = s[j], s[i]
   917  }