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