github.com/nalum/terraform@v0.3.2-0.20141223102918-aa2c22ffeff6/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/config/module" 12 "github.com/hashicorp/terraform/depgraph" 13 "github.com/hashicorp/terraform/helper/multierror" 14 ) 15 16 // GraphOpts are options used to create the resource graph that Terraform 17 // walks to make changes to infrastructure. 18 // 19 // Depending on what options are set, the resulting graph will come in 20 // varying degrees of completeness. 21 type GraphOpts struct { 22 // Config is the configuration from which to build the basic graph. 23 // This is the only required item. 24 //Config *config.Config 25 26 // Module is the relative root of a module tree for this graph. This 27 // is the only required item. This should always be the absolute root 28 // of the tree. ModulePath below should be used to constrain the depth. 29 // 30 // ModulePath specifies the place in the tree where Module exists. 31 // This is used for State lookups. 32 Module *module.Tree 33 ModulePath []string 34 35 // Diff of changes that will be applied to the given state. This will 36 // associate a ResourceDiff with applicable resources. Additionally, 37 // new resource nodes representing resource destruction may be inserted 38 // into the graph. 39 Diff *Diff 40 41 // State, if present, will make the ResourceState available on each 42 // resource node. Additionally, any orphans will be added automatically 43 // to the graph. 44 // 45 // Note: the state will be modified so it is initialized with basic 46 // empty states for all modules/resources in this graph. If you call prune 47 // later, these will be removed, but the graph adds important metadata. 48 State *State 49 50 // Providers is a mapping of prefixes to a resource provider. If given, 51 // resource providers will be found, initialized, and associated to the 52 // resources in the graph. 53 // 54 // This will also potentially insert new nodes into the graph for 55 // the configuration of resource providers. 56 Providers map[string]ResourceProviderFactory 57 58 // Provisioners is a mapping of names to a resource provisioner. 59 // These must be provided to support resource provisioners. 60 Provisioners map[string]ResourceProvisionerFactory 61 62 // parent specifies the parent graph if there is one. This should not be 63 // set manually. 64 parent *depgraph.Graph 65 } 66 67 // GraphRootNode is the name of the root node in the Terraform resource 68 // graph. This node is just a placemarker and has no associated functionality. 69 const GraphRootNode = "root" 70 71 // GraphMeta is the metadata attached to the graph itself. 72 type GraphMeta struct { 73 // ModulePath is the path of the module that this graph represents. 74 ModulePath []string 75 } 76 77 // GraphNodeModule is a node type in the graph that represents a module 78 // that will be created/managed. 79 type GraphNodeModule struct { 80 Config *config.Module 81 Path []string 82 Graph *depgraph.Graph 83 State *ModuleState 84 Flags ResourceFlag 85 } 86 87 // GraphNodeResource is a node type in the graph that represents a resource 88 // that will be created or managed. Unlike the GraphNodeResourceMeta node, 89 // this represents a _single_, _resource_ to be managed, not a set of resources 90 // or a component of a resource. 91 type GraphNodeResource struct { 92 Index int 93 Config *config.Resource 94 Resource *Resource 95 ResourceProviderNode string 96 97 // All the fields below are related to expansion. These are set by 98 // the graph but aren't useful individually. 99 ExpandMode ResourceExpandMode 100 Diff *ModuleDiff 101 State *ModuleState 102 } 103 104 // GraphNodeResourceProvider is a node type in the graph that represents 105 // the configuration for a resource provider. 106 type GraphNodeResourceProvider struct { 107 ID string 108 Provider *graphSharedProvider 109 } 110 111 // graphSharedProvider is a structure that stores a configuration 112 // with initialized providers and might be shared across different 113 // graphs in order to have only one instance of a provider. 114 type graphSharedProvider struct { 115 Config *config.ProviderConfig 116 Providers map[string]ResourceProvider 117 ProviderKeys []string 118 Parent *graphSharedProvider 119 120 overrideConfig map[string]map[string]interface{} 121 parentNoun *depgraph.Noun 122 } 123 124 // ResourceExpandMode specifies the expand behavior of the GraphNodeResource 125 // node. 126 type ResourceExpandMode byte 127 128 const ( 129 ResourceExpandNone ResourceExpandMode = iota 130 ResourceExpandApply 131 ResourceExpandDestroy 132 ) 133 134 // Graph builds a dependency graph of all the resources for infrastructure 135 // change. 136 // 137 // This dependency graph shows the correct order that any resources need 138 // to be operated on. 139 // 140 // The Meta field of a graph Noun can contain one of the follow types. A 141 // description is next to each type to explain what it is. 142 // 143 // *GraphNodeResource - A resource. See the documentation of this 144 // struct for more details. 145 // *GraphNodeResourceProvider - A resource provider that needs to be 146 // configured at this point. 147 // 148 func Graph(opts *GraphOpts) (*depgraph.Graph, error) { 149 if opts.Module == nil { 150 return nil, errors.New("Module is required for Graph") 151 } 152 if opts.ModulePath == nil { 153 opts.ModulePath = rootModulePath 154 } 155 if !opts.Module.Loaded() { 156 return nil, errors.New("Module must be loaded") 157 } 158 159 // Get the correct module in the tree that we're looking for. 160 currentModule := opts.Module 161 for _, n := range opts.ModulePath[1:] { 162 children := currentModule.Children() 163 currentModule = children[n] 164 } 165 166 var conf *config.Config 167 if currentModule != nil { 168 conf = currentModule.Config() 169 } else { 170 conf = new(config.Config) 171 } 172 173 // Get the state and diff of the module that we're working with. 174 var modDiff *ModuleDiff 175 var modState *ModuleState 176 if opts.Diff != nil { 177 modDiff = opts.Diff.ModuleByPath(opts.ModulePath) 178 } 179 if opts.State != nil { 180 modState = opts.State.ModuleByPath(opts.ModulePath) 181 } 182 183 log.Printf("[DEBUG] Creating graph for path: %v", opts.ModulePath) 184 185 g := new(depgraph.Graph) 186 g.Meta = &GraphMeta{ 187 ModulePath: opts.ModulePath, 188 } 189 190 // First, build the initial resource graph. This only has the resources 191 // and no dependencies. This only adds resources that are in the config 192 // and not "orphans" (that are in the state, but not in the config). 193 graphAddConfigResources(g, conf, modState) 194 195 if modState != nil { 196 // Next, add the state orphans if we have any 197 graphAddOrphans(g, conf, modState) 198 199 // Add tainted resources if we have any. 200 graphAddTainted(g, modState) 201 } 202 203 // Create the resource provider nodes for explicitly configured 204 // providers within our graph. 205 graphAddConfigProviderConfigs(g, conf) 206 207 if opts.parent != nil { 208 // Add/merge the provider configurations from the parent so that 209 // we properly "inherit" providers. 210 graphAddParentProviderConfigs(g, opts.parent) 211 } 212 213 // First pass matching resources to providers. This will allow us to 214 // determine what providers are missing. 215 graphMapResourceProviderId(g) 216 217 if len(opts.Providers) > 0 { 218 // Add missing providers from the mapping. 219 if err := graphAddMissingResourceProviders(g, opts.Providers); err != nil { 220 return nil, err 221 } 222 223 // Initialize all the providers 224 if err := graphInitResourceProviders(g, opts.Providers); err != nil { 225 return nil, err 226 } 227 228 // Map the providers to resources 229 if err := graphMapResourceProviders(g); err != nil { 230 return nil, err 231 } 232 } 233 234 // Add the modules that are in the configuration. 235 if err := graphAddConfigModules(g, conf, opts); err != nil { 236 return nil, err 237 } 238 239 if opts.State != nil { 240 // Add module orphans if we have any of those 241 if ms := opts.State.Children(opts.ModulePath); len(ms) > 0 { 242 if err := graphAddModuleOrphans(g, conf, ms, opts); err != nil { 243 return nil, err 244 } 245 } 246 } 247 248 // Add the orphan dependencies 249 graphAddOrphanDeps(g, modState) 250 251 // Add the orphan module dependencies 252 graphAddOrphanModuleDeps(g, modState) 253 254 // Add the provider dependencies 255 graphAddResourceProviderDeps(g) 256 257 // Now, prune the providers that we aren't using. 258 graphPruneResourceProviders(g) 259 260 // Add explicit dependsOn dependencies to the graph 261 graphAddExplicitDeps(g) 262 263 // Setup the provisioners. These may have variable dependencies, 264 // and must be done before dependency setup 265 if err := graphMapResourceProvisioners(g, opts.Provisioners); err != nil { 266 return nil, err 267 } 268 269 // Add all the variable dependencies 270 graphAddVariableDeps(g) 271 272 // Build the root so that we have a single valid root 273 graphAddRoot(g) 274 275 // If we have a diff, then make sure to add that in 276 if modDiff != nil { 277 if err := graphAddDiff(g, opts.Diff, modDiff); err != nil { 278 return nil, err 279 } 280 } 281 282 // Encode the dependencies 283 graphEncodeDependencies(g) 284 285 // Validate 286 if err := g.Validate(); err != nil { 287 return nil, err 288 } 289 290 log.Printf( 291 "[DEBUG] Graph %v created and valid. %d nouns.", 292 opts.ModulePath, 293 len(g.Nouns)) 294 295 return g, nil 296 } 297 298 // graphEncodeDependencies is used to initialize a State with a ResourceState 299 // for every resource. 300 // 301 // This method is very important to call because it will properly setup 302 // the ResourceState dependency information with data from the graph. This 303 // allows orphaned resources to be destroyed in the proper order. 304 func graphEncodeDependencies(g *depgraph.Graph) { 305 for _, n := range g.Nouns { 306 switch rn := n.Meta.(type) { 307 case *GraphNodeResource: 308 // If we are using create-before-destroy, there 309 // are some special depedencies injected on the 310 // deposed node that would cause a circular depedency 311 // chain if persisted. We must only handle the new node, 312 // node the deposed node. 313 r := rn.Resource 314 if r.Flags&FlagDeposed != 0 { 315 continue 316 } 317 318 // Update the dependencies 319 var inject []string 320 for _, dep := range n.Deps { 321 switch target := dep.Target.Meta.(type) { 322 case *GraphNodeModule: 323 inject = append(inject, dep.Target.Name) 324 325 case *GraphNodeResource: 326 if target.Resource.Id == r.Id { 327 continue 328 } 329 inject = append(inject, target.Resource.Id) 330 331 case *GraphNodeResourceProvider: 332 // Do nothing 333 334 default: 335 panic(fmt.Sprintf("Unknown graph node: %#v", dep.Target)) 336 } 337 } 338 339 // Update the dependencies 340 r.Dependencies = inject 341 342 case *GraphNodeModule: 343 // Update the dependencies 344 var inject []string 345 for _, dep := range n.Deps { 346 switch target := dep.Target.Meta.(type) { 347 case *GraphNodeModule: 348 if dep.Target.Name == n.Name { 349 continue 350 } 351 inject = append(inject, dep.Target.Name) 352 353 case *GraphNodeResource: 354 inject = append(inject, target.Resource.Id) 355 356 case *GraphNodeResourceProvider: 357 // Do nothing 358 359 default: 360 panic(fmt.Sprintf("Unknown graph node: %#v", dep.Target)) 361 } 362 363 } 364 365 // Update the dependencies 366 if rn.State != nil { 367 rn.State.Dependencies = inject 368 } 369 } 370 } 371 } 372 373 // graphAddConfigModules adds the modules from a configuration structure 374 // into the graph, expanding each to their own sub-graph. 375 func graphAddConfigModules( 376 g *depgraph.Graph, 377 c *config.Config, 378 opts *GraphOpts) error { 379 // Just short-circuit the whole thing if we don't have modules 380 if len(c.Modules) == 0 { 381 return nil 382 } 383 384 // Build the list of nouns to add to the graph 385 nounsList := make([]*depgraph.Noun, 0, len(c.Modules)) 386 for _, m := range c.Modules { 387 if n, err := graphModuleNoun(m.Name, m, g, opts); err != nil { 388 return err 389 } else { 390 // Attach the module state if any 391 if opts.State != nil { 392 module := n.Meta.(*GraphNodeModule) 393 module.State = opts.State.ModuleByPath(module.Path) 394 if module.State == nil { 395 module.State = opts.State.AddModule(module.Path) 396 } 397 } 398 nounsList = append(nounsList, n) 399 } 400 } 401 402 g.Nouns = append(g.Nouns, nounsList...) 403 return nil 404 } 405 406 // configGraph turns a configuration structure into a dependency graph. 407 func graphAddConfigResources( 408 g *depgraph.Graph, c *config.Config, mod *ModuleState) { 409 meta := g.Meta.(*GraphMeta) 410 411 // This tracks all the resource nouns 412 nounsList := make([]*depgraph.Noun, len(c.Resources)) 413 for i, r := range c.Resources { 414 name := r.Id() 415 416 // Build the noun 417 nounsList[i] = &depgraph.Noun{ 418 Name: name, 419 Meta: &GraphNodeResource{ 420 Index: -1, 421 Config: r, 422 Resource: &Resource{ 423 Id: name, 424 Info: &InstanceInfo{ 425 Id: name, 426 ModulePath: meta.ModulePath, 427 Type: r.Type, 428 }, 429 }, 430 State: mod.View(name), 431 ExpandMode: ResourceExpandApply, 432 }, 433 } 434 435 /* 436 TODO: probably did something important, bring it back somehow 437 resourceNouns := make([]*depgraph.Noun, r.Count) 438 for i := 0; i < r.Count; i++ { 439 name := r.Id() 440 index := -1 441 442 // If we have a count that is more than one, then make sure 443 // we suffix with the number of the resource that this is. 444 if r.Count > 1 { 445 name = fmt.Sprintf("%s.%d", name, i) 446 index = i 447 } 448 449 var state *ResourceState 450 if mod != nil { 451 // Lookup the resource state 452 state = mod.Resources[name] 453 if state == nil { 454 if r.Count == 1 { 455 // If the count is one, check the state for ".0" 456 // appended, which might exist if we go from 457 // count > 1 to count == 1. 458 state = mod.Resources[r.Id()+".0"] 459 } else if i == 0 { 460 // If count is greater than one, check for state 461 // with just the ID, which might exist if we go 462 // from count == 1 to count > 1 463 state = mod.Resources[r.Id()] 464 } 465 466 // TODO(mitchellh): If one of the above works, delete 467 // the old style and just copy it to the new style. 468 } 469 } 470 471 if state == nil { 472 state = &ResourceState{ 473 Type: r.Type, 474 } 475 } 476 477 flags := FlagPrimary 478 if len(state.Tainted) > 0 { 479 flags |= FlagHasTainted 480 } 481 482 resourceNouns[i] = &depgraph.Noun{ 483 Name: name, 484 Meta: &GraphNodeResource{ 485 Index: index, 486 Config: r, 487 Resource: &Resource{ 488 Id: name, 489 Info: &InstanceInfo{ 490 Id: name, 491 ModulePath: meta.ModulePath, 492 Type: r.Type, 493 }, 494 State: state.Primary, 495 Config: NewResourceConfig(r.RawConfig), 496 Flags: flags, 497 }, 498 }, 499 } 500 } 501 502 // If we have more than one, then create a meta node to track 503 // the resources. 504 if r.Count > 1 { 505 metaNoun := &depgraph.Noun{ 506 Name: r.Id(), 507 Meta: &GraphNodeResourceMeta{ 508 ID: r.Id(), 509 Name: r.Name, 510 Type: r.Type, 511 Count: r.Count, 512 }, 513 } 514 515 // Create the dependencies on this noun 516 for _, n := range resourceNouns { 517 metaNoun.Deps = append(metaNoun.Deps, &depgraph.Dependency{ 518 Name: n.Name, 519 Source: metaNoun, 520 Target: n, 521 }) 522 } 523 524 // Assign it to the map so that we have it 525 nouns[metaNoun.Name] = metaNoun 526 } 527 528 for _, n := range resourceNouns { 529 nouns[n.Name] = n 530 } 531 */ 532 } 533 534 g.Name = "terraform" 535 g.Nouns = append(g.Nouns, nounsList...) 536 } 537 538 // graphAddDiff takes an already-built graph of resources and adds the 539 // diffs to the resource nodes themselves. 540 // 541 // This may also introduces new graph elements. If there are diffs that 542 // require a destroy, new elements may be introduced since destroy order 543 // is different than create order. For example, destroying a VPC requires 544 // destroying the VPC's subnets first, whereas creating a VPC requires 545 // doing it before the subnets are created. This function handles inserting 546 // these nodes for you. 547 func graphAddDiff(g *depgraph.Graph, gDiff *Diff, d *ModuleDiff) error { 548 var nlist []*depgraph.Noun 549 var modules []*depgraph.Noun 550 injected := make(map[*depgraph.Dependency]struct{}) 551 for _, n := range g.Nouns { 552 // A module is being destroyed if all it's resources are being 553 // destroyed (via a destroy plan) or if it is orphaned. Only in 554 // those cases do we need to handle depedency inversion. 555 if mod, ok := n.Meta.(*GraphNodeModule); ok { 556 md := gDiff.ModuleByPath(mod.Path) 557 if mod.Flags&FlagOrphan != 0 || (md != nil && md.Destroy) { 558 modules = append(modules, n) 559 } 560 continue 561 } 562 563 rn, ok := n.Meta.(*GraphNodeResource) 564 if !ok { 565 continue 566 } 567 if rn.Resource.Flags&FlagTainted != 0 { 568 continue 569 } 570 571 change := false 572 destroy := false 573 diffs := d.Instances(rn.Resource.Id) 574 if len(diffs) == 0 { 575 continue 576 } 577 for _, d := range diffs { 578 if d.Destroy { 579 destroy = true 580 } 581 582 if len(d.Attributes) > 0 { 583 change = true 584 } 585 } 586 587 // If we're expanding, save the diff so we can add it on later 588 if rn.ExpandMode > ResourceExpandNone { 589 rn.Diff = d 590 } 591 592 // If we are not expanding, then we assign the 593 // instance diff to the resource. 594 var rd *InstanceDiff 595 if rn.ExpandMode == ResourceExpandNone { 596 rd = diffs[0] 597 } 598 599 if destroy { 600 // If we're destroying, we create a new destroy node with 601 // the proper dependencies. Perform a dirty copy operation. 602 newNode := new(GraphNodeResource) 603 *newNode = *rn 604 newNode.Resource = new(Resource) 605 *newNode.Resource = *rn.Resource 606 607 // Make the diff _just_ the destroy. 608 newNode.Resource.Diff = &InstanceDiff{Destroy: true} 609 610 // Make sure ExpandDestroy is set if Expand 611 if newNode.ExpandMode == ResourceExpandApply { 612 newNode.ExpandMode = ResourceExpandDestroy 613 } 614 615 // Create the new node 616 newN := &depgraph.Noun{ 617 Name: fmt.Sprintf("%s (destroy)", newNode.Resource.Id), 618 Meta: newNode, 619 } 620 newN.Deps = make([]*depgraph.Dependency, len(n.Deps)) 621 622 // Copy all the dependencies and do a fixup later 623 copy(newN.Deps, n.Deps) 624 625 // Append it to the list so we handle it later 626 nlist = append(nlist, newN) 627 628 if rd != nil { 629 // Mark the old diff to not destroy since we handle that in 630 // the dedicated node. 631 newDiff := new(InstanceDiff) 632 *newDiff = *rd 633 newDiff.Destroy = false 634 rd = newDiff 635 } 636 637 // The dependency ordering depends on if the CreateBeforeDestroy 638 // flag is enabled. If so, we must create the replacement first, 639 // and then destroy the old instance. 640 if rn.Config != nil && rn.Config.Lifecycle.CreateBeforeDestroy && change { 641 dep := &depgraph.Dependency{ 642 Name: n.Name, 643 Source: newN, 644 Target: n, 645 } 646 647 // Add the old noun to the new noun dependencies so that 648 // the create happens before the destroy. 649 newN.Deps = append(newN.Deps, dep) 650 651 // Mark that this dependency has been injected so that 652 // we do not invert the direction below. 653 injected[dep] = struct{}{} 654 655 // Add a depedency from the root, since the create node 656 // does not depend on us 657 if g.Root != nil { 658 g.Root.Deps = append(g.Root.Deps, &depgraph.Dependency{ 659 Name: newN.Name, 660 Source: g.Root, 661 Target: newN, 662 }) 663 } 664 665 // Set the ReplacePrimary flag on the new instance so that 666 // it will become the new primary, and Diposed flag on the 667 // existing instance so that it will step down 668 rn.Resource.Flags |= FlagReplacePrimary 669 newNode.Resource.Flags |= FlagDeposed 670 671 // This logic is not intuitive, but we need to make the 672 // destroy depend upon any resources that depend on the 673 // create. The reason is suppose you have a LB depend on 674 // a web server. You need the order to be create, update LB, 675 // destroy. Without this, the update LB and destroy can 676 // be executed in an arbitrary order (likely in parallel). 677 incoming := g.DependsOn(n) 678 for _, inc := range incoming { 679 // Ignore the root... 680 if inc == g.Root { 681 continue 682 } 683 dep := &depgraph.Dependency{ 684 Name: inc.Name, 685 Source: newN, 686 Target: inc, 687 } 688 injected[dep] = struct{}{} 689 newN.Deps = append(newN.Deps, dep) 690 } 691 692 } else { 693 dep := &depgraph.Dependency{ 694 Name: newN.Name, 695 Source: n, 696 Target: newN, 697 } 698 699 // Add the new noun to our dependencies so that 700 // the destroy happens before the apply. 701 n.Deps = append(n.Deps, dep) 702 } 703 } 704 705 rn.Resource.Diff = rd 706 } 707 708 // Go through each resource and module and make sure we 709 // calculate all the dependencies properly. 710 invertDeps := [][]*depgraph.Noun{nlist, modules} 711 for _, list := range invertDeps { 712 for _, n := range list { 713 deps := n.Deps 714 num := len(deps) 715 for i := 0; i < num; i++ { 716 dep := deps[i] 717 718 // Check if this dependency was just injected, otherwise 719 // we will incorrectly flip the depedency twice. 720 if _, ok := injected[dep]; ok { 721 continue 722 } 723 724 switch target := dep.Target.Meta.(type) { 725 case *GraphNodeResource: 726 // If the other node is also being deleted, 727 // we must be deleted first. E.g. if A -> B, 728 // then when we create, B is created first then A. 729 // On teardown, A is destroyed first, then B. 730 // Thus we must flip our depedency and instead inject 731 // it on B. 732 for _, n2 := range nlist { 733 rn2 := n2.Meta.(*GraphNodeResource) 734 if target.Resource.Id == rn2.Resource.Id { 735 newDep := &depgraph.Dependency{ 736 Name: n.Name, 737 Source: n2, 738 Target: n, 739 } 740 injected[newDep] = struct{}{} 741 n2.Deps = append(n2.Deps, newDep) 742 break 743 } 744 } 745 746 // Drop the dependency. We may have created 747 // an inverse depedency if the dependent resource 748 // is also being deleted, but this dependence is 749 // no longer required. 750 deps[i], deps[num-1] = deps[num-1], nil 751 num-- 752 i-- 753 754 case *GraphNodeModule: 755 // We invert any module dependencies so we're destroyed 756 // first, before any modules are applied. 757 newDep := &depgraph.Dependency{ 758 Name: n.Name, 759 Source: dep.Target, 760 Target: n, 761 } 762 dep.Target.Deps = append(dep.Target.Deps, newDep) 763 764 // Drop the dependency. We may have created 765 // an inverse depedency if the dependent resource 766 // is also being deleted, but this dependence is 767 // no longer required. 768 deps[i], deps[num-1] = deps[num-1], nil 769 num-- 770 i-- 771 case *GraphNodeResourceProvider: 772 // Keep these around, but fix up the source to be ourselves 773 // rather than the old node. 774 newDep := *dep 775 newDep.Source = n 776 deps[i] = &newDep 777 default: 778 panic(fmt.Errorf("Unhandled depedency type: %#v", dep.Target.Meta)) 779 } 780 } 781 n.Deps = deps[:num] 782 } 783 } 784 785 // Add the nouns to the graph 786 g.Nouns = append(g.Nouns, nlist...) 787 788 return nil 789 } 790 791 // graphAddExplicitDeps adds the dependencies to the graph for the explicit 792 // dependsOn configurations. 793 func graphAddExplicitDeps(g *depgraph.Graph) { 794 depends := false 795 796 rs := make(map[string]*depgraph.Noun) 797 for _, n := range g.Nouns { 798 rn, ok := n.Meta.(*GraphNodeResource) 799 if !ok { 800 continue 801 } 802 if rn.Config == nil { 803 // Orphan. It can't be depended on or have depends (explicit) 804 // anyways. 805 continue 806 } 807 808 rs[rn.Resource.Id] = n 809 if rn.Config != nil && len(rn.Config.DependsOn) > 0 { 810 depends = true 811 } 812 } 813 814 // If we didn't have any dependsOn, just return 815 if !depends { 816 return 817 } 818 819 for _, n1 := range rs { 820 rn1 := n1.Meta.(*GraphNodeResource) 821 for _, d := range rn1.Config.DependsOn { 822 for _, n2 := range rs { 823 rn2 := n2.Meta.(*GraphNodeResource) 824 if rn2.Config.Id() != d { 825 continue 826 } 827 828 n1.Deps = append(n1.Deps, &depgraph.Dependency{ 829 Name: d, 830 Source: n1, 831 Target: n2, 832 }) 833 } 834 } 835 } 836 } 837 838 // graphAddMissingResourceProviders adds GraphNodeResourceProvider nodes for 839 // the resources that do not have an explicit resource provider specified 840 // because no provider configuration was given. 841 func graphAddMissingResourceProviders( 842 g *depgraph.Graph, 843 ps map[string]ResourceProviderFactory) error { 844 var errs []error 845 846 for _, n := range g.Nouns { 847 rn, ok := n.Meta.(*GraphNodeResource) 848 if !ok { 849 continue 850 } 851 if rn.ResourceProviderNode != "" { 852 continue 853 } 854 855 prefixes := matchingPrefixes(rn.Resource.Info.Type, ps) 856 if len(prefixes) == 0 { 857 errs = append(errs, fmt.Errorf( 858 "No matching provider for type: %s", 859 rn.Resource.Info.Type)) 860 continue 861 } 862 863 // The resource provider ID is simply the shortest matching 864 // prefix, since that'll give us the most resource providers 865 // to choose from. 866 id := prefixes[len(prefixes)-1] 867 rn.ResourceProviderNode = fmt.Sprintf("provider.%s", id) 868 869 // If we don't have a matching noun for this yet, insert it. 870 if g.Noun(rn.ResourceProviderNode) == nil { 871 pn := &depgraph.Noun{ 872 Name: rn.ResourceProviderNode, 873 Meta: &GraphNodeResourceProvider{ 874 ID: id, 875 Provider: new(graphSharedProvider), 876 }, 877 } 878 g.Nouns = append(g.Nouns, pn) 879 } 880 } 881 882 if len(errs) > 0 { 883 return &multierror.Error{Errors: errs} 884 } 885 886 return nil 887 } 888 889 func graphAddModuleOrphans( 890 g *depgraph.Graph, 891 config *config.Config, 892 ms []*ModuleState, 893 opts *GraphOpts) error { 894 // Build a lookup map for the modules we do have defined 895 childrenKeys := make(map[string]struct{}) 896 for _, m := range config.Modules { 897 childrenKeys[m.Name] = struct{}{} 898 } 899 900 // Go through each of the child modules. If we don't have it in our 901 // config, it is an orphan. 902 var nounsList []*depgraph.Noun 903 for _, m := range ms { 904 k := m.Path[len(m.Path)-1] 905 if _, ok := childrenKeys[k]; ok { 906 // We have this module configured 907 continue 908 } 909 910 if n, err := graphModuleNoun(k, nil, g, opts); err != nil { 911 return err 912 } else { 913 // Mark this module as being an orphan 914 module := n.Meta.(*GraphNodeModule) 915 module.Flags |= FlagOrphan 916 module.State = m 917 nounsList = append(nounsList, n) 918 } 919 } 920 921 g.Nouns = append(g.Nouns, nounsList...) 922 return nil 923 } 924 925 // graphAddOrphanDeps adds the dependencies to the orphans based on their 926 // explicit Dependencies state. 927 func graphAddOrphanDeps(g *depgraph.Graph, mod *ModuleState) { 928 for _, n := range g.Nouns { 929 rn, ok := n.Meta.(*GraphNodeResource) 930 if !ok { 931 continue 932 } 933 if rn.Resource.Flags&FlagOrphan == 0 { 934 continue 935 } 936 937 // If we have no dependencies, then just continue 938 rs := mod.Resources[n.Name] 939 if len(rs.Dependencies) == 0 { 940 continue 941 } 942 943 for _, n2 := range g.Nouns { 944 // Don't ever depend on ourselves 945 if n2.Meta == n.Meta { 946 continue 947 } 948 949 var compareName string 950 switch rn2 := n2.Meta.(type) { 951 case *GraphNodeModule: 952 compareName = n2.Name 953 case *GraphNodeResource: 954 compareName = rn2.Resource.Id 955 } 956 if compareName == "" { 957 continue 958 } 959 960 for _, depName := range rs.Dependencies { 961 if !strings.HasPrefix(depName, compareName) { 962 continue 963 } 964 dep := &depgraph.Dependency{ 965 Name: depName, 966 Source: n, 967 Target: n2, 968 } 969 n.Deps = append(n.Deps, dep) 970 break 971 } 972 } 973 } 974 } 975 976 // graphAddOrphanModuleDeps adds the dependencies to the orphan 977 // modules based on their explicit Dependencies state. 978 func graphAddOrphanModuleDeps(g *depgraph.Graph, mod *ModuleState) { 979 for _, n := range g.Nouns { 980 module, ok := n.Meta.(*GraphNodeModule) 981 if !ok { 982 continue 983 } 984 if module.Flags&FlagOrphan == 0 { 985 continue 986 } 987 988 // If we have no dependencies, then just continue 989 if len(module.State.Dependencies) == 0 { 990 continue 991 } 992 993 for _, n2 := range g.Nouns { 994 // Don't ever depend on ourselves 995 if n2.Meta == n.Meta { 996 continue 997 } 998 999 var compareName string 1000 switch rn2 := n2.Meta.(type) { 1001 case *GraphNodeModule: 1002 compareName = n2.Name 1003 case *GraphNodeResource: 1004 compareName = rn2.Resource.Id 1005 } 1006 if compareName == "" { 1007 continue 1008 } 1009 1010 for _, depName := range module.State.Dependencies { 1011 if !strings.HasPrefix(depName, compareName) { 1012 continue 1013 } 1014 dep := &depgraph.Dependency{ 1015 Name: depName, 1016 Source: n, 1017 Target: n2, 1018 } 1019 n.Deps = append(n.Deps, dep) 1020 break 1021 } 1022 } 1023 } 1024 } 1025 1026 // graphAddOrphans adds the orphans to the graph. 1027 func graphAddOrphans(g *depgraph.Graph, c *config.Config, mod *ModuleState) { 1028 meta := g.Meta.(*GraphMeta) 1029 1030 var nlist []*depgraph.Noun 1031 for _, k := range mod.Orphans(c) { 1032 rs := mod.Resources[k] 1033 noun := &depgraph.Noun{ 1034 Name: k, 1035 Meta: &GraphNodeResource{ 1036 Index: -1, 1037 Resource: &Resource{ 1038 Id: k, 1039 Info: &InstanceInfo{ 1040 Id: k, 1041 ModulePath: meta.ModulePath, 1042 Type: rs.Type, 1043 }, 1044 State: rs.Primary, 1045 Config: NewResourceConfig(nil), 1046 Flags: FlagOrphan, 1047 }, 1048 }, 1049 } 1050 1051 // Append it to the list so we handle it later 1052 nlist = append(nlist, noun) 1053 } 1054 1055 // Add the nouns to the graph 1056 g.Nouns = append(g.Nouns, nlist...) 1057 } 1058 1059 // graphAddParentProviderConfigs goes through and adds/merges provider 1060 // configurations from the parent. 1061 func graphAddParentProviderConfigs(g, parent *depgraph.Graph) { 1062 var nounsList []*depgraph.Noun 1063 for _, n := range parent.Nouns { 1064 pn, ok := n.Meta.(*GraphNodeResourceProvider) 1065 if !ok { 1066 continue 1067 } 1068 1069 // If we have a provider configuration with the exact same 1070 // name, then set specify the parent pointer to their shared 1071 // config. 1072 ourProviderRaw := g.Noun(n.Name) 1073 1074 // If we don't have a matching configuration, then create one. 1075 if ourProviderRaw == nil { 1076 noun := &depgraph.Noun{ 1077 Name: n.Name, 1078 Meta: &GraphNodeResourceProvider{ 1079 ID: pn.ID, 1080 Provider: &graphSharedProvider{ 1081 Parent: pn.Provider, 1082 parentNoun: n, 1083 }, 1084 }, 1085 } 1086 1087 nounsList = append(nounsList, noun) 1088 continue 1089 } 1090 1091 // If we have a matching configuration, then set the parent pointer 1092 ourProvider := ourProviderRaw.Meta.(*GraphNodeResourceProvider) 1093 ourProvider.Provider.Parent = pn.Provider 1094 ourProvider.Provider.parentNoun = n 1095 } 1096 1097 g.Nouns = append(g.Nouns, nounsList...) 1098 } 1099 1100 // graphAddConfigProviderConfigs adds a GraphNodeResourceProvider for every 1101 // `provider` configuration block. Note that a provider may exist that 1102 // isn't used for any resources. These will be pruned later. 1103 func graphAddConfigProviderConfigs(g *depgraph.Graph, c *config.Config) { 1104 nounsList := make([]*depgraph.Noun, 0, len(c.ProviderConfigs)) 1105 for _, pc := range c.ProviderConfigs { 1106 noun := &depgraph.Noun{ 1107 Name: fmt.Sprintf("provider.%s", pc.Name), 1108 Meta: &GraphNodeResourceProvider{ 1109 ID: pc.Name, 1110 Provider: &graphSharedProvider{ 1111 Config: pc, 1112 }, 1113 }, 1114 } 1115 1116 nounsList = append(nounsList, noun) 1117 } 1118 1119 // Add all the provider config nouns to the graph 1120 g.Nouns = append(g.Nouns, nounsList...) 1121 } 1122 1123 // graphAddRoot adds a root element to the graph so that there is a single 1124 // root to point to all the dependencies. 1125 func graphAddRoot(g *depgraph.Graph) { 1126 root := &depgraph.Noun{Name: GraphRootNode} 1127 for _, n := range g.Nouns { 1128 switch n.Meta.(type) { 1129 case *GraphNodeResourceProvider: 1130 // ResourceProviders don't need to be in the root deps because 1131 // they're always pointed to by some resource. 1132 continue 1133 } 1134 1135 root.Deps = append(root.Deps, &depgraph.Dependency{ 1136 Name: n.Name, 1137 Source: root, 1138 Target: n, 1139 }) 1140 } 1141 g.Nouns = append(g.Nouns, root) 1142 g.Root = root 1143 } 1144 1145 // graphAddVariableDeps inspects all the nouns and adds any dependencies 1146 // based on variable values. 1147 func graphAddVariableDeps(g *depgraph.Graph) { 1148 for _, n := range g.Nouns { 1149 switch m := n.Meta.(type) { 1150 case *GraphNodeModule: 1151 if m.Config != nil { 1152 vars := m.Config.RawConfig.Variables 1153 nounAddVariableDeps(g, n, vars, false) 1154 } 1155 1156 case *GraphNodeResource: 1157 if m.Config != nil { 1158 // Handle the count variables 1159 vars := m.Config.RawCount.Variables 1160 nounAddVariableDeps(g, n, vars, false) 1161 1162 // Handle the resource variables 1163 vars = m.Config.RawConfig.Variables 1164 nounAddVariableDeps(g, n, vars, false) 1165 } 1166 1167 // Handle the variables of the resource provisioners 1168 for _, p := range m.Resource.Provisioners { 1169 vars := p.RawConfig.Variables 1170 nounAddVariableDeps(g, n, vars, true) 1171 1172 vars = p.ConnInfo.Variables 1173 nounAddVariableDeps(g, n, vars, true) 1174 } 1175 1176 case *GraphNodeResourceProvider: 1177 if m.Provider != nil && m.Provider.Config != nil { 1178 vars := m.Provider.Config.RawConfig.Variables 1179 nounAddVariableDeps(g, n, vars, false) 1180 } 1181 1182 default: 1183 // Other node types don't have dependencies or we don't support it 1184 continue 1185 } 1186 } 1187 } 1188 1189 // graphAddTainted adds the tainted instances to the graph. 1190 func graphAddTainted(g *depgraph.Graph, mod *ModuleState) { 1191 meta := g.Meta.(*GraphMeta) 1192 1193 var nlist []*depgraph.Noun 1194 for k, rs := range mod.Resources { 1195 // If we have no tainted resources, continue on 1196 if len(rs.Tainted) == 0 { 1197 continue 1198 } 1199 1200 // Find the untainted resource of this in the noun list. If our 1201 // name is 3 parts, then we mus be a count instance, so our 1202 // untainted node is just the noun without the count. 1203 var untainted *depgraph.Noun 1204 untaintedK := k 1205 if ps := strings.Split(k, "."); len(ps) == 3 { 1206 untaintedK = strings.Join(ps[0:2], ".") 1207 } 1208 for _, n := range g.Nouns { 1209 if n.Name == untaintedK { 1210 untainted = n 1211 break 1212 } 1213 } 1214 1215 for i, is := range rs.Tainted { 1216 name := fmt.Sprintf("%s (tainted #%d)", k, i+1) 1217 1218 // Add each of the tainted resources to the graph, and encode 1219 // a dependency from the non-tainted resource to this so that 1220 // tainted resources are always destroyed first. 1221 noun := &depgraph.Noun{ 1222 Name: name, 1223 Meta: &GraphNodeResource{ 1224 Index: -1, 1225 Resource: &Resource{ 1226 Id: k, 1227 Info: &InstanceInfo{ 1228 Id: k, 1229 ModulePath: meta.ModulePath, 1230 Type: rs.Type, 1231 }, 1232 State: is, 1233 Config: NewResourceConfig(nil), 1234 Diff: &InstanceDiff{Destroy: true}, 1235 Flags: FlagTainted, 1236 TaintedIndex: i, 1237 }, 1238 }, 1239 } 1240 1241 // Append it to the list so we handle it later 1242 nlist = append(nlist, noun) 1243 1244 // If we have an untainted version, then make sure to add 1245 // the dependency. 1246 if untainted != nil { 1247 dep := &depgraph.Dependency{ 1248 Name: name, 1249 Source: untainted, 1250 Target: noun, 1251 } 1252 1253 untainted.Deps = append(untainted.Deps, dep) 1254 } 1255 } 1256 } 1257 1258 // Add the nouns to the graph 1259 g.Nouns = append(g.Nouns, nlist...) 1260 } 1261 1262 // graphModuleNoun creates a noun for a module. 1263 func graphModuleNoun( 1264 n string, m *config.Module, 1265 g *depgraph.Graph, opts *GraphOpts) (*depgraph.Noun, error) { 1266 name := fmt.Sprintf("module.%s", n) 1267 path := make([]string, len(opts.ModulePath)+1) 1268 copy(path, opts.ModulePath) 1269 path[len(opts.ModulePath)] = n 1270 1271 // Build the opts we'll use to make the next graph 1272 subOpts := *opts 1273 subOpts.ModulePath = path 1274 subOpts.parent = g 1275 subGraph, err := Graph(&subOpts) 1276 if err != nil { 1277 return nil, fmt.Errorf( 1278 "Error building module graph '%s': %s", 1279 n, err) 1280 } 1281 1282 return &depgraph.Noun{ 1283 Name: name, 1284 Meta: &GraphNodeModule{ 1285 Config: m, 1286 Path: path, 1287 Graph: subGraph, 1288 }, 1289 }, nil 1290 } 1291 1292 // nounAddVariableDeps updates the dependencies of a noun given 1293 // a set of associated variable values 1294 func nounAddVariableDeps( 1295 g *depgraph.Graph, 1296 n *depgraph.Noun, 1297 vars map[string]config.InterpolatedVariable, 1298 removeSelf bool) { 1299 for _, rawV := range vars { 1300 var name string 1301 var target *depgraph.Noun 1302 1303 switch v := rawV.(type) { 1304 case *config.ModuleVariable: 1305 name = fmt.Sprintf("module.%s", v.Name) 1306 target = g.Noun(name) 1307 case *config.ResourceVariable: 1308 // For resource variables, if we ourselves are a resource, then 1309 // we have to check whether to expand or not to create the proper 1310 // resource dependency. 1311 rn, ok := n.Meta.(*GraphNodeResource) 1312 if !ok || rn.ExpandMode > ResourceExpandNone { 1313 name = v.ResourceId() 1314 target = g.Noun(v.ResourceId()) 1315 break 1316 } 1317 1318 // We're an expanded resource, so add the specific index 1319 // as the dependency. 1320 name = fmt.Sprintf("%s.%d", v.ResourceId(), v.Index) 1321 target = g.Noun(name) 1322 default: 1323 } 1324 1325 if target == nil { 1326 continue 1327 } 1328 1329 // If we're ignoring self-references, then don't add that 1330 // dependency. 1331 if removeSelf && n == target { 1332 continue 1333 } 1334 1335 // Build the dependency 1336 dep := &depgraph.Dependency{ 1337 Name: name, 1338 Source: n, 1339 Target: target, 1340 } 1341 1342 n.Deps = append(n.Deps, dep) 1343 } 1344 } 1345 1346 // graphInitResourceProviders maps the resource providers onto the graph 1347 // given a mapping of prefixes to resource providers. 1348 // 1349 // Unlike the graphAdd* functions, this one can return an error if resource 1350 // providers can't be found or can't be instantiated. 1351 func graphInitResourceProviders( 1352 g *depgraph.Graph, 1353 ps map[string]ResourceProviderFactory) error { 1354 var errs []error 1355 1356 // Keep track of providers we know we couldn't instantiate so 1357 // that we don't get a ton of errors about the same provider. 1358 failures := make(map[string]struct{}) 1359 1360 for _, n := range g.Nouns { 1361 // We only care about the resource providers first. There is guaranteed 1362 // to be only one node per tuple (providerId, providerConfig), which 1363 // means we don't need to verify we have instantiated it before. 1364 rn, ok := n.Meta.(*GraphNodeResourceProvider) 1365 if !ok { 1366 continue 1367 } 1368 1369 prefixes := matchingPrefixes(rn.ID, ps) 1370 if len(prefixes) > 0 { 1371 if _, ok := failures[prefixes[0]]; ok { 1372 // We already failed this provider, meaning this 1373 // resource will never succeed, so just continue. 1374 continue 1375 } 1376 } 1377 1378 sharedProvider := rn.Provider 1379 1380 // Go through each prefix and instantiate if necessary, then 1381 // verify if this provider is of use to us or not. 1382 sharedProvider.Providers = make(map[string]ResourceProvider) 1383 sharedProvider.ProviderKeys = prefixes 1384 for _, prefix := range prefixes { 1385 p, err := ps[prefix]() 1386 if err != nil { 1387 errs = append(errs, fmt.Errorf( 1388 "Error instantiating resource provider for "+ 1389 "prefix %s: %s", prefix, err)) 1390 1391 // Record the error so that we don't check it again 1392 failures[prefix] = struct{}{} 1393 1394 // Jump to the next prefix 1395 continue 1396 } 1397 1398 sharedProvider.Providers[prefix] = p 1399 } 1400 1401 // If we never found a provider, then error and continue 1402 if len(sharedProvider.Providers) == 0 { 1403 errs = append(errs, fmt.Errorf( 1404 "Provider for configuration '%s' not found.", 1405 rn.ID)) 1406 continue 1407 } 1408 } 1409 1410 if len(errs) > 0 { 1411 return &multierror.Error{Errors: errs} 1412 } 1413 1414 return nil 1415 } 1416 1417 // graphAddResourceProviderDeps goes through all the nodes in the graph 1418 // and adds any dependencies to resource providers as needed. 1419 func graphAddResourceProviderDeps(g *depgraph.Graph) { 1420 for _, rawN := range g.Nouns { 1421 switch n := rawN.Meta.(type) { 1422 case *GraphNodeModule: 1423 // Check if the module depends on any of our providers 1424 // by seeing if there is a parent node back. 1425 for _, moduleRaw := range n.Graph.Nouns { 1426 pn, ok := moduleRaw.Meta.(*GraphNodeResourceProvider) 1427 if !ok { 1428 continue 1429 } 1430 if pn.Provider.parentNoun == nil { 1431 continue 1432 } 1433 1434 // Create the dependency to the provider 1435 dep := &depgraph.Dependency{ 1436 Name: pn.Provider.parentNoun.Name, 1437 Source: rawN, 1438 Target: pn.Provider.parentNoun, 1439 } 1440 rawN.Deps = append(rawN.Deps, dep) 1441 } 1442 case *GraphNodeResource: 1443 // Not sure how this would happen, but we might as well 1444 // check for it. 1445 if n.ResourceProviderNode == "" { 1446 continue 1447 } 1448 1449 // Get the noun this depends on. 1450 target := g.Noun(n.ResourceProviderNode) 1451 1452 // Create the dependency to the provider 1453 dep := &depgraph.Dependency{ 1454 Name: target.Name, 1455 Source: rawN, 1456 Target: target, 1457 } 1458 rawN.Deps = append(rawN.Deps, dep) 1459 } 1460 } 1461 } 1462 1463 // graphPruneResourceProviders will remove the GraphNodeResourceProvider 1464 // nodes that aren't used in any way. 1465 func graphPruneResourceProviders(g *depgraph.Graph) { 1466 // First, build a mapping of the providers we have. 1467 ps := make(map[string]struct{}) 1468 for _, n := range g.Nouns { 1469 _, ok := n.Meta.(*GraphNodeResourceProvider) 1470 if !ok { 1471 continue 1472 } 1473 1474 ps[n.Name] = struct{}{} 1475 } 1476 1477 // Now go through all the dependencies throughout and find 1478 // if any of these aren't reachable. 1479 for _, n := range g.Nouns { 1480 for _, dep := range n.Deps { 1481 delete(ps, dep.Target.Name) 1482 } 1483 } 1484 1485 if len(ps) == 0 { 1486 // We used all of them! 1487 return 1488 } 1489 1490 // Now go through and remove these nodes that aren't used 1491 for i := 0; i < len(g.Nouns); i++ { 1492 if _, ok := ps[g.Nouns[i].Name]; !ok { 1493 continue 1494 } 1495 1496 // Delete this node 1497 copy(g.Nouns[i:], g.Nouns[i+1:]) 1498 g.Nouns[len(g.Nouns)-1] = nil 1499 g.Nouns = g.Nouns[:len(g.Nouns)-1] 1500 i-- 1501 } 1502 } 1503 1504 // graphMapResourceProviderId goes through the graph and maps the 1505 // ID of a resource provider node to each resource. This lets us know which 1506 // configuration is for which resource. 1507 // 1508 // This is safe to call multiple times. 1509 func graphMapResourceProviderId(g *depgraph.Graph) { 1510 // Build the list of provider configs we have 1511 ps := make(map[string]string) 1512 for _, n := range g.Nouns { 1513 pn, ok := n.Meta.(*GraphNodeResourceProvider) 1514 if !ok { 1515 continue 1516 } 1517 1518 ps[n.Name] = pn.ID 1519 } 1520 1521 // Go through every resource and find the shortest matching provider 1522 for _, n := range g.Nouns { 1523 rn, ok := n.Meta.(*GraphNodeResource) 1524 if !ok { 1525 continue 1526 } 1527 1528 var match, matchNode string 1529 for n, p := range ps { 1530 if !strings.HasPrefix(rn.Resource.Info.Type, p) { 1531 continue 1532 } 1533 if len(p) > len(match) { 1534 match = p 1535 matchNode = n 1536 } 1537 } 1538 if matchNode == "" { 1539 continue 1540 } 1541 1542 rn.ResourceProviderNode = matchNode 1543 } 1544 } 1545 1546 // graphMapResourceProviders takes a graph that already has initialized 1547 // the resource providers (using graphInitResourceProviders) and maps the 1548 // resource providers to the resources themselves. 1549 func graphMapResourceProviders(g *depgraph.Graph) error { 1550 var errs []error 1551 1552 // First build a mapping of resource provider ID to the node that 1553 // contains those resources. 1554 mapping := make(map[string]*GraphNodeResourceProvider) 1555 for _, n := range g.Nouns { 1556 rn, ok := n.Meta.(*GraphNodeResourceProvider) 1557 if !ok { 1558 continue 1559 } 1560 mapping[rn.ID] = rn 1561 } 1562 1563 // Now go through each of the resources and find a matching provider. 1564 for _, n := range g.Nouns { 1565 rn, ok := n.Meta.(*GraphNodeResource) 1566 if !ok { 1567 continue 1568 } 1569 1570 rpnRaw := g.Noun(rn.ResourceProviderNode) 1571 if rpnRaw == nil { 1572 // This should never happen since when building the graph 1573 // we ensure that everything matches up. 1574 panic(fmt.Sprintf( 1575 "Resource provider not found: %s (type: %s)", 1576 rn.ResourceProviderNode, 1577 rn.Resource.Info.Type)) 1578 } 1579 rpn := rpnRaw.Meta.(*GraphNodeResourceProvider) 1580 1581 var provider ResourceProvider 1582 for _, k := range rpn.Provider.ProviderKeys { 1583 // Only try this provider if it has the right prefix 1584 if !strings.HasPrefix(rn.Resource.Info.Type, k) { 1585 continue 1586 } 1587 1588 rp := rpn.Provider.Providers[k] 1589 if ProviderSatisfies(rp, rn.Resource.Info.Type) { 1590 provider = rp 1591 break 1592 } 1593 } 1594 1595 if provider == nil { 1596 errs = append(errs, fmt.Errorf( 1597 "Resource provider not found for resource type '%s'", 1598 rn.Resource.Info.Type)) 1599 continue 1600 } 1601 1602 rn.Resource.Provider = provider 1603 } 1604 1605 if len(errs) > 0 { 1606 return &multierror.Error{Errors: errs} 1607 } 1608 1609 return nil 1610 } 1611 1612 // graphMapResourceProvisioners takes a graph that already has 1613 // the resources and maps the resource provisioners to the resources themselves. 1614 func graphMapResourceProvisioners(g *depgraph.Graph, 1615 provisioners map[string]ResourceProvisionerFactory) error { 1616 var errs []error 1617 1618 // Create a cache of resource provisioners, avoids duplicate 1619 // initialization of the instances 1620 cache := make(map[string]ResourceProvisioner) 1621 1622 // Go through each of the resources and find a matching provisioners 1623 for _, n := range g.Nouns { 1624 rn, ok := n.Meta.(*GraphNodeResource) 1625 if !ok { 1626 continue 1627 } 1628 1629 // Ignore orphan nodes with no provisioners 1630 if rn.Config == nil { 1631 continue 1632 } 1633 1634 // Check each provisioner 1635 for _, p := range rn.Config.Provisioners { 1636 // Check for a cached provisioner 1637 provisioner, ok := cache[p.Type] 1638 if !ok { 1639 // Lookup the factory method 1640 factory, ok := provisioners[p.Type] 1641 if !ok { 1642 errs = append(errs, fmt.Errorf( 1643 "Resource provisioner not found for provisioner type '%s'", 1644 p.Type)) 1645 continue 1646 } 1647 1648 // Initialize the provisioner 1649 prov, err := factory() 1650 if err != nil { 1651 errs = append(errs, fmt.Errorf( 1652 "Failed to instantiate provisioner type '%s': %v", 1653 p.Type, err)) 1654 continue 1655 } 1656 provisioner = prov 1657 1658 // Cache this type of provisioner 1659 cache[p.Type] = prov 1660 } 1661 1662 // Save the provisioner 1663 rn.Resource.Provisioners = append(rn.Resource.Provisioners, &ResourceProvisionerConfig{ 1664 Type: p.Type, 1665 Provisioner: provisioner, 1666 Config: NewResourceConfig(p.RawConfig), 1667 RawConfig: p.RawConfig, 1668 ConnInfo: p.ConnInfo, 1669 }) 1670 } 1671 } 1672 1673 if len(errs) > 0 { 1674 return &multierror.Error{Errors: errs} 1675 } 1676 return nil 1677 } 1678 1679 // grpahRemoveInvalidDeps goes through the graph and removes dependencies 1680 // that no longer exist. 1681 func graphRemoveInvalidDeps(g *depgraph.Graph) { 1682 check := make(map[*depgraph.Noun]struct{}) 1683 for _, n := range g.Nouns { 1684 check[n] = struct{}{} 1685 } 1686 for _, n := range g.Nouns { 1687 deps := n.Deps 1688 num := len(deps) 1689 for i := 0; i < num; i++ { 1690 if _, ok := check[deps[i].Target]; !ok { 1691 deps[i], deps[num-1] = deps[num-1], nil 1692 i-- 1693 num-- 1694 } 1695 } 1696 n.Deps = deps[:num] 1697 } 1698 } 1699 1700 // MergeConfig merges all the configurations in the proper order 1701 // to result in the final configuration to use to configure this 1702 // provider. 1703 func (p *graphSharedProvider) MergeConfig( 1704 raw bool, override map[string]interface{}) *ResourceConfig { 1705 var rawMap map[string]interface{} 1706 if p.Config != nil { 1707 rawMap = p.Config.RawConfig.Config() 1708 } 1709 if rawMap == nil { 1710 rawMap = make(map[string]interface{}) 1711 } 1712 for k, v := range override { 1713 rawMap[k] = v 1714 } 1715 1716 // Merge in all the parent configurations 1717 if p.Parent != nil { 1718 parent := p.Parent 1719 for parent != nil { 1720 if parent.Config != nil { 1721 var merge map[string]interface{} 1722 if raw { 1723 merge = parent.Config.RawConfig.Raw 1724 } else { 1725 merge = parent.Config.RawConfig.Config() 1726 } 1727 1728 for k, v := range merge { 1729 rawMap[k] = v 1730 } 1731 } 1732 1733 parent = parent.Parent 1734 } 1735 } 1736 1737 rc, err := config.NewRawConfig(rawMap) 1738 if err != nil { 1739 panic("error building config: " + err.Error()) 1740 } 1741 1742 return NewResourceConfig(rc) 1743 } 1744 1745 // Expand will expand this node into a subgraph if Expand is set. 1746 func (n *GraphNodeResource) Expand() (*depgraph.Graph, error) { 1747 // Expand the count out, which should be interpolated at this point. 1748 count, err := n.Config.Count() 1749 if err != nil { 1750 return nil, err 1751 } 1752 log.Printf("[DEBUG] %s: expanding to count = %d", n.Resource.Id, count) 1753 1754 // TODO: can we DRY this up? 1755 g := new(depgraph.Graph) 1756 g.Meta = &GraphMeta{ 1757 ModulePath: n.Resource.Info.ModulePath, 1758 } 1759 1760 // Do the initial expansion of the nodes, attaching diffs if 1761 // applicable 1762 n.expand(g, count, n.Diff) 1763 1764 // Add all the variable dependencies 1765 graphAddVariableDeps(g) 1766 1767 // Filter the nodes depending on the expansion type 1768 switch n.ExpandMode { 1769 case ResourceExpandApply: 1770 n.filterResources(g, false) 1771 case ResourceExpandDestroy: 1772 n.filterResources(g, true) 1773 default: 1774 panic(fmt.Sprintf("Unhandled expansion mode %d", n.ExpandMode)) 1775 } 1776 1777 // Return the finalized graph 1778 return g, n.finalizeGraph(g) 1779 } 1780 1781 // expand expands this resource and adds the resources to the graph. It 1782 // adds both create and destroy resources. 1783 func (n *GraphNodeResource) expand(g *depgraph.Graph, count int, diff *ModuleDiff) { 1784 // Create the list of nouns 1785 result := make([]*depgraph.Noun, 0, count) 1786 1787 // Build the key set so we know what is removed 1788 var keys map[string]struct{} 1789 if n.State != nil { 1790 keys = make(map[string]struct{}) 1791 for k, _ := range n.State.Resources { 1792 keys[k] = struct{}{} 1793 } 1794 } 1795 1796 // First thing, expand the counts that we have defined for our 1797 // current config into the full set of resources that are being 1798 // created. 1799 r := n.Config 1800 for i := 0; i < count; i++ { 1801 name := r.Id() 1802 index := -1 1803 1804 // If we have a count that is more than one, then make sure 1805 // we suffix with the number of the resource that this is. 1806 if count > 1 { 1807 name = fmt.Sprintf("%s.%d", name, i) 1808 index = i 1809 } 1810 1811 var state *ResourceState 1812 if n.State != nil { 1813 // Lookup the resource state 1814 if s, ok := n.State.Resources[name]; ok { 1815 state = s 1816 delete(keys, name) 1817 } 1818 1819 if count == 1 { 1820 // If the count is one, check the state for ".0" 1821 // appended, which might exist if we go from 1822 // count > 1 to count == 1. 1823 k := r.Id() + ".0" 1824 if state == nil { 1825 state = n.State.Resources[k] 1826 } 1827 delete(keys, k) 1828 } else if i == 0 { 1829 // If count is greater than one, check for state 1830 // with just the ID, which might exist if we go 1831 // from count == 1 to count > 1 1832 if state == nil { 1833 state = n.State.Resources[r.Id()] 1834 } 1835 delete(keys, r.Id()) 1836 } 1837 } 1838 1839 // Add in the diff if we have it 1840 var inDiff *InstanceDiff 1841 if diff != nil { 1842 // Looup the instance diff 1843 if d, ok := diff.Resources[name]; ok { 1844 inDiff = d 1845 } 1846 1847 if inDiff == nil { 1848 if count == 1 { 1849 // If the count is one, check the state for ".0" 1850 // appended, which might exist if we go from 1851 // count > 1 to count == 1. 1852 k := r.Id() + ".0" 1853 inDiff = diff.Resources[k] 1854 } else if i == 0 { 1855 // If count is greater than one, check for state 1856 // with just the ID, which might exist if we go 1857 // from count == 1 to count > 1 1858 inDiff = diff.Resources[r.Id()] 1859 } 1860 } 1861 } 1862 1863 // Initialize a default state if not available 1864 if state == nil { 1865 state = &ResourceState{ 1866 Type: r.Type, 1867 } 1868 } 1869 1870 // Prepare the diff if it exists 1871 if inDiff != nil { 1872 switch n.ExpandMode { 1873 case ResourceExpandApply: 1874 // Disable Destroy if we aren't doing a destroy expansion. 1875 // There is a seperate expansion for the destruction action. 1876 d := new(InstanceDiff) 1877 *d = *inDiff 1878 inDiff = d 1879 inDiff.Destroy = false 1880 1881 // If we require a new resource, there is a seperate delete 1882 // phase, so the create phase must not have access to the ID. 1883 if inDiff.RequiresNew() { 1884 s := new(ResourceState) 1885 *s = *state 1886 state = s 1887 state.Primary = nil 1888 } 1889 1890 case ResourceExpandDestroy: 1891 // If we are doing a destroy, make sure it is exclusively 1892 // a destroy, since there is a seperate expansion for the apply 1893 inDiff = new(InstanceDiff) 1894 inDiff.Destroy = true 1895 1896 default: 1897 panic(fmt.Sprintf("Unhandled expansion mode %d", n.ExpandMode)) 1898 } 1899 } 1900 1901 // Inherit the existing flags! 1902 flags := n.Resource.Flags 1903 if len(state.Tainted) > 0 { 1904 flags |= FlagHasTainted 1905 } 1906 1907 // Copy the base resource so we can fill it in 1908 resource := n.copyResource(name) 1909 resource.CountIndex = i 1910 resource.State = state.Primary 1911 resource.Flags = flags 1912 resource.Diff = inDiff 1913 1914 // Add the result 1915 result = append(result, &depgraph.Noun{ 1916 Name: name, 1917 Meta: &GraphNodeResource{ 1918 Index: index, 1919 Config: r, 1920 Resource: resource, 1921 }, 1922 }) 1923 } 1924 1925 // Go over the leftover keys which are orphans (decreasing counts) 1926 for k, _ := range keys { 1927 rs := n.State.Resources[k] 1928 1929 resource := n.copyResource(k) 1930 resource.Config = NewResourceConfig(nil) 1931 resource.State = rs.Primary 1932 resource.Flags = FlagOrphan 1933 resource.Diff = &InstanceDiff{Destroy: true} 1934 1935 noun := &depgraph.Noun{ 1936 Name: k, 1937 Meta: &GraphNodeResource{ 1938 Index: -1, 1939 Resource: resource, 1940 }, 1941 } 1942 1943 result = append(result, noun) 1944 } 1945 1946 g.Nouns = append(g.Nouns, result...) 1947 } 1948 1949 // copyResource copies the Resource structure to assign to a subgraph. 1950 func (n *GraphNodeResource) copyResource(id string) *Resource { 1951 info := *n.Resource.Info 1952 info.Id = id 1953 resource := *n.Resource 1954 resource.Id = id 1955 resource.Info = &info 1956 resource.Config = NewResourceConfig(n.Config.RawConfig) 1957 resource.Diff = nil 1958 return &resource 1959 } 1960 1961 // filterResources is used to remove resources from the sub-graph based 1962 // on the ExpandMode. This is because there is a Destroy sub-graph, and 1963 // Apply sub-graph, and we cannot includes the same instances in both 1964 // sub-graphs. 1965 func (n *GraphNodeResource) filterResources(g *depgraph.Graph, destroy bool) { 1966 result := make([]*depgraph.Noun, 0, len(g.Nouns)) 1967 for _, n := range g.Nouns { 1968 rn, ok := n.Meta.(*GraphNodeResource) 1969 if !ok { 1970 continue 1971 } 1972 1973 if destroy { 1974 if rn.Resource.Diff != nil && rn.Resource.Diff.Destroy { 1975 result = append(result, n) 1976 } 1977 continue 1978 } 1979 1980 if rn.Resource.Flags&FlagOrphan != 0 || 1981 rn.Resource.Diff == nil || !rn.Resource.Diff.Destroy { 1982 result = append(result, n) 1983 } 1984 } 1985 g.Nouns = result 1986 } 1987 1988 // finalizeGraph is used to ensure the generated graph is valid 1989 func (n *GraphNodeResource) finalizeGraph(g *depgraph.Graph) error { 1990 // Remove the dependencies that don't exist 1991 graphRemoveInvalidDeps(g) 1992 1993 // Build the root so that we have a single valid root 1994 graphAddRoot(g) 1995 1996 // Validate 1997 if err := g.Validate(); err != nil { 1998 return err 1999 } 2000 return nil 2001 } 2002 2003 // matchingPrefixes takes a resource type and a set of resource 2004 // providers we know about by prefix and returns a list of prefixes 2005 // that might be valid for that resource. 2006 // 2007 // The list returned is in the order that they should be attempted. 2008 func matchingPrefixes( 2009 t string, 2010 ps map[string]ResourceProviderFactory) []string { 2011 result := make([]string, 0, 1) 2012 for prefix, _ := range ps { 2013 if strings.HasPrefix(t, prefix) { 2014 result = append(result, prefix) 2015 } 2016 } 2017 2018 // Sort by longest first 2019 sort.Sort(stringLenSort(result)) 2020 2021 return result 2022 } 2023 2024 // stringLenSort implements sort.Interface and sorts strings in increasing 2025 // length order. i.e. "a", "aa", "aaa" 2026 type stringLenSort []string 2027 2028 func (s stringLenSort) Len() int { 2029 return len(s) 2030 } 2031 2032 func (s stringLenSort) Less(i, j int) bool { 2033 return len(s[i]) < len(s[j]) 2034 } 2035 2036 func (s stringLenSort) Swap(i, j int) { 2037 s[i], s[j] = s[j], s[i] 2038 }