github.com/jrasell/terraform@v0.6.17-0.20160523115548-2652f5232949/terraform/state.go (about) 1 package terraform 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "reflect" 11 "sort" 12 "strconv" 13 "strings" 14 15 "github.com/hashicorp/go-version" 16 "github.com/hashicorp/terraform/config" 17 "github.com/mitchellh/copystructure" 18 ) 19 20 const ( 21 // StateVersion is the current version for our state file 22 StateVersion = 2 23 ) 24 25 // rootModulePath is the path of the root module 26 var rootModulePath = []string{"root"} 27 28 // normalizeModulePath takes a raw module path and returns a path that 29 // has the rootModulePath prepended to it. If I could go back in time I 30 // would've never had a rootModulePath (empty path would be root). We can 31 // still fix this but thats a big refactor that my branch doesn't make sense 32 // for. Instead, this function normalizes paths. 33 func normalizeModulePath(p []string) []string { 34 k := len(rootModulePath) 35 36 // If we already have a root module prefix, we're done 37 if len(p) >= len(rootModulePath) { 38 if reflect.DeepEqual(p[:k], rootModulePath) { 39 return p 40 } 41 } 42 43 // None? Prefix it 44 result := make([]string, len(rootModulePath)+len(p)) 45 copy(result, rootModulePath) 46 copy(result[k:], p) 47 return result 48 } 49 50 // State keeps track of a snapshot state-of-the-world that Terraform 51 // can use to keep track of what real world resources it is actually 52 // managing. This is the latest format as of Terraform 0.3 53 type State struct { 54 // Version is the protocol version. Currently only "1". 55 Version int `json:"version"` 56 57 // TFVersion is the version of Terraform that wrote this state. 58 TFVersion string `json:"terraform_version,omitempty"` 59 60 // Serial is incremented on any operation that modifies 61 // the State file. It is used to detect potentially conflicting 62 // updates. 63 Serial int64 `json:"serial"` 64 65 // Remote is used to track the metadata required to 66 // pull and push state files from a remote storage endpoint. 67 Remote *RemoteState `json:"remote,omitempty"` 68 69 // Modules contains all the modules in a breadth-first order 70 Modules []*ModuleState `json:"modules"` 71 } 72 73 // NewState is used to initialize a blank state 74 func NewState() *State { 75 s := &State{} 76 s.init() 77 return s 78 } 79 80 // Children returns the ModuleStates that are direct children of 81 // the given path. If the path is "root", for example, then children 82 // returned might be "root.child", but not "root.child.grandchild". 83 func (s *State) Children(path []string) []*ModuleState { 84 // TODO: test 85 86 result := make([]*ModuleState, 0) 87 for _, m := range s.Modules { 88 if len(m.Path) != len(path)+1 { 89 continue 90 } 91 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 92 continue 93 } 94 95 result = append(result, m) 96 } 97 98 return result 99 } 100 101 // AddModule adds the module with the given path to the state. 102 // 103 // This should be the preferred method to add module states since it 104 // allows us to optimize lookups later as well as control sorting. 105 func (s *State) AddModule(path []string) *ModuleState { 106 m := &ModuleState{Path: path} 107 m.init() 108 s.Modules = append(s.Modules, m) 109 s.sort() 110 return m 111 } 112 113 // ModuleByPath is used to lookup the module state for the given path. 114 // This should be the preferred lookup mechanism as it allows for future 115 // lookup optimizations. 116 func (s *State) ModuleByPath(path []string) *ModuleState { 117 if s == nil { 118 return nil 119 } 120 for _, mod := range s.Modules { 121 if mod.Path == nil { 122 panic("missing module path") 123 } 124 if reflect.DeepEqual(mod.Path, path) { 125 return mod 126 } 127 } 128 return nil 129 } 130 131 // ModuleOrphans returns all the module orphans in this state by 132 // returning their full paths. These paths can be used with ModuleByPath 133 // to return the actual state. 134 func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string { 135 // direct keeps track of what direct children we have both in our config 136 // and in our state. childrenKeys keeps track of what isn't an orphan. 137 direct := make(map[string]struct{}) 138 childrenKeys := make(map[string]struct{}) 139 if c != nil { 140 for _, m := range c.Modules { 141 childrenKeys[m.Name] = struct{}{} 142 direct[m.Name] = struct{}{} 143 } 144 } 145 146 // Go over the direct children and find any that aren't in our keys. 147 var orphans [][]string 148 for _, m := range s.Children(path) { 149 key := m.Path[len(m.Path)-1] 150 151 // Record that we found this key as a direct child. We use this 152 // later to find orphan nested modules. 153 direct[key] = struct{}{} 154 155 // If we have a direct child still in our config, it is not an orphan 156 if _, ok := childrenKeys[key]; ok { 157 continue 158 } 159 160 orphans = append(orphans, m.Path) 161 } 162 163 // Find the orphans that are nested... 164 for _, m := range s.Modules { 165 // We only want modules that are at least grandchildren 166 if len(m.Path) < len(path)+2 { 167 continue 168 } 169 170 // If it isn't part of our tree, continue 171 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 172 continue 173 } 174 175 // If we have the direct child, then just skip it. 176 key := m.Path[len(path)] 177 if _, ok := direct[key]; ok { 178 continue 179 } 180 181 orphanPath := m.Path[:len(path)+1] 182 183 // Don't double-add if we've already added this orphan (which can happen if 184 // there are multiple nested sub-modules that get orphaned together). 185 alreadyAdded := false 186 for _, o := range orphans { 187 if reflect.DeepEqual(o, orphanPath) { 188 alreadyAdded = true 189 break 190 } 191 } 192 if alreadyAdded { 193 continue 194 } 195 196 // Add this orphan 197 orphans = append(orphans, orphanPath) 198 } 199 200 return orphans 201 } 202 203 // Empty returns true if the state is empty. 204 func (s *State) Empty() bool { 205 if s == nil { 206 return true 207 } 208 209 return len(s.Modules) == 0 210 } 211 212 // IsRemote returns true if State represents a state that exists and is 213 // remote. 214 func (s *State) IsRemote() bool { 215 if s == nil { 216 return false 217 } 218 if s.Remote == nil { 219 return false 220 } 221 if s.Remote.Type == "" { 222 return false 223 } 224 225 return true 226 } 227 228 // Remove removes the item in the state at the given address, returning 229 // any errors that may have occurred. 230 // 231 // If the address references a module state or resource, it will delete 232 // all children as well. To check what will be deleted, use a StateFilter 233 // first. 234 func (s *State) Remove(addr ...string) error { 235 // Filter out what we need to delete 236 filter := &StateFilter{State: s} 237 results, err := filter.Filter(addr...) 238 if err != nil { 239 return err 240 } 241 242 // If we have no results, just exit early, we're not going to do anything. 243 // While what happens below is fairly fast, this is an important early 244 // exit since the prune below might modify the state more and we don't 245 // want to modify the state if we don't have to. 246 if len(results) == 0 { 247 return nil 248 } 249 250 // Go through each result and grab what we need 251 removed := make(map[interface{}]struct{}) 252 for _, r := range results { 253 // Convert the path to our own type 254 path := append([]string{"root"}, r.Path...) 255 256 // If we removed this already, then ignore 257 if _, ok := removed[r.Value]; ok { 258 continue 259 } 260 261 // If we removed the parent already, then ignore 262 if r.Parent != nil { 263 if _, ok := removed[r.Parent.Value]; ok { 264 continue 265 } 266 } 267 268 // Add this to the removed list 269 removed[r.Value] = struct{}{} 270 271 switch v := r.Value.(type) { 272 case *ModuleState: 273 s.removeModule(path, v) 274 case *ResourceState: 275 s.removeResource(path, v) 276 case *InstanceState: 277 s.removeInstance(path, r.Parent.Value.(*ResourceState), v) 278 default: 279 return fmt.Errorf("unknown type to delete: %T", r.Value) 280 } 281 } 282 283 // Prune since the removal functions often do the bare minimum to 284 // remove a thing and may leave around dangling empty modules, resources, 285 // etc. Prune will clean that all up. 286 s.prune() 287 288 return nil 289 } 290 291 func (s *State) removeModule(path []string, v *ModuleState) { 292 for i, m := range s.Modules { 293 if m == v { 294 s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil 295 return 296 } 297 } 298 } 299 300 func (s *State) removeResource(path []string, v *ResourceState) { 301 // Get the module this resource lives in. If it doesn't exist, we're done. 302 mod := s.ModuleByPath(path) 303 if mod == nil { 304 return 305 } 306 307 // Find this resource. This is a O(N) lookup when if we had the key 308 // it could be O(1) but even with thousands of resources this shouldn't 309 // matter right now. We can easily up performance here when the time comes. 310 for k, r := range mod.Resources { 311 if r == v { 312 // Found it 313 delete(mod.Resources, k) 314 return 315 } 316 } 317 } 318 319 func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) { 320 // Go through the resource and find the instance that matches this 321 // (if any) and remove it. 322 323 // Check primary 324 if r.Primary == v { 325 r.Primary = nil 326 return 327 } 328 329 // Check lists 330 lists := [][]*InstanceState{r.Tainted, r.Deposed} 331 for _, is := range lists { 332 for i, instance := range is { 333 if instance == v { 334 // Found it, remove it 335 is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil 336 337 // Done 338 return 339 } 340 } 341 } 342 } 343 344 // RootModule returns the ModuleState for the root module 345 func (s *State) RootModule() *ModuleState { 346 root := s.ModuleByPath(rootModulePath) 347 if root == nil { 348 panic("missing root module") 349 } 350 return root 351 } 352 353 // Equal tests if one state is equal to another. 354 func (s *State) Equal(other *State) bool { 355 // If one is nil, we do a direct check 356 if s == nil || other == nil { 357 return s == other 358 } 359 360 // If the versions are different, they're certainly not equal 361 if s.Version != other.Version { 362 return false 363 } 364 365 // If any of the modules are not equal, then this state isn't equal 366 if len(s.Modules) != len(other.Modules) { 367 return false 368 } 369 for _, m := range s.Modules { 370 // This isn't very optimal currently but works. 371 otherM := other.ModuleByPath(m.Path) 372 if otherM == nil { 373 return false 374 } 375 376 // If they're not equal, then we're not equal! 377 if !m.Equal(otherM) { 378 return false 379 } 380 } 381 382 return true 383 } 384 385 // DeepCopy performs a deep copy of the state structure and returns 386 // a new structure. 387 func (s *State) DeepCopy() *State { 388 if s == nil { 389 return nil 390 } 391 n := &State{ 392 Version: s.Version, 393 TFVersion: s.TFVersion, 394 Serial: s.Serial, 395 Modules: make([]*ModuleState, 0, len(s.Modules)), 396 } 397 for _, mod := range s.Modules { 398 n.Modules = append(n.Modules, mod.deepcopy()) 399 } 400 if s.Remote != nil { 401 n.Remote = s.Remote.deepcopy() 402 } 403 return n 404 } 405 406 // IncrementSerialMaybe increments the serial number of this state 407 // if it different from the other state. 408 func (s *State) IncrementSerialMaybe(other *State) { 409 if s == nil { 410 return 411 } 412 if other == nil { 413 return 414 } 415 if s.Serial > other.Serial { 416 return 417 } 418 if other.TFVersion != s.TFVersion || !s.Equal(other) { 419 if other.Serial > s.Serial { 420 s.Serial = other.Serial 421 } 422 423 s.Serial++ 424 } 425 } 426 427 // FromFutureTerraform checks if this state was written by a Terraform 428 // version from the future. 429 func (s *State) FromFutureTerraform() bool { 430 // No TF version means it is certainly from the past 431 if s.TFVersion == "" { 432 return false 433 } 434 435 v := version.Must(version.NewVersion(s.TFVersion)) 436 return SemVersion.LessThan(v) 437 } 438 439 func (s *State) init() { 440 if s.Version == 0 { 441 s.Version = StateVersion 442 } 443 if s.ModuleByPath(rootModulePath) == nil { 444 s.AddModule(rootModulePath) 445 } 446 } 447 448 // prune is used to remove any resources that are no longer required 449 func (s *State) prune() { 450 if s == nil { 451 return 452 } 453 for _, mod := range s.Modules { 454 mod.prune() 455 } 456 if s.Remote != nil && s.Remote.Empty() { 457 s.Remote = nil 458 } 459 } 460 461 // sort sorts the modules 462 func (s *State) sort() { 463 sort.Sort(moduleStateSort(s.Modules)) 464 465 // Allow modules to be sorted 466 for _, m := range s.Modules { 467 m.sort() 468 } 469 } 470 471 func (s *State) GoString() string { 472 return fmt.Sprintf("*%#v", *s) 473 } 474 475 func (s *State) String() string { 476 if s == nil { 477 return "<nil>" 478 } 479 480 var buf bytes.Buffer 481 for _, m := range s.Modules { 482 mStr := m.String() 483 484 // If we're the root module, we just write the output directly. 485 if reflect.DeepEqual(m.Path, rootModulePath) { 486 buf.WriteString(mStr + "\n") 487 continue 488 } 489 490 buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], "."))) 491 492 s := bufio.NewScanner(strings.NewReader(mStr)) 493 for s.Scan() { 494 text := s.Text() 495 if text != "" { 496 text = " " + text 497 } 498 499 buf.WriteString(fmt.Sprintf("%s\n", text)) 500 } 501 } 502 503 return strings.TrimSpace(buf.String()) 504 } 505 506 // RemoteState is used to track the information about a remote 507 // state store that we push/pull state to. 508 type RemoteState struct { 509 // Type controls the client we use for the remote state 510 Type string `json:"type"` 511 512 // Config is used to store arbitrary configuration that 513 // is type specific 514 Config map[string]string `json:"config"` 515 } 516 517 func (r *RemoteState) deepcopy() *RemoteState { 518 confCopy := make(map[string]string, len(r.Config)) 519 for k, v := range r.Config { 520 confCopy[k] = v 521 } 522 return &RemoteState{ 523 Type: r.Type, 524 Config: confCopy, 525 } 526 } 527 528 func (r *RemoteState) Empty() bool { 529 return r == nil || r.Type == "" 530 } 531 532 func (r *RemoteState) Equals(other *RemoteState) bool { 533 if r.Type != other.Type { 534 return false 535 } 536 if len(r.Config) != len(other.Config) { 537 return false 538 } 539 for k, v := range r.Config { 540 if other.Config[k] != v { 541 return false 542 } 543 } 544 return true 545 } 546 547 func (r *RemoteState) GoString() string { 548 return fmt.Sprintf("*%#v", *r) 549 } 550 551 // OutputState is used to track the state relevant to a single output. 552 type OutputState struct { 553 // Sensitive describes whether the output is considered sensitive, 554 // which may lead to masking the value on screen in some cases. 555 Sensitive bool `json:"sensitive"` 556 // Type describes the structure of Value. Valid values are "string", 557 // "map" and "list" 558 Type string `json:"type"` 559 // Value contains the value of the output, in the structure described 560 // by the Type field. 561 Value interface{} `json:"value"` 562 } 563 564 func (s *OutputState) String() string { 565 // This is a v0.6.x implementation only 566 return fmt.Sprintf("%s", s.Value.(string)) 567 } 568 569 // Equal compares two OutputState structures for equality. nil values are 570 // considered equal. 571 func (s *OutputState) Equal(other *OutputState) bool { 572 if s == nil && other == nil { 573 return true 574 } 575 576 if s == nil || other == nil { 577 return false 578 } 579 580 if s.Type != other.Type { 581 return false 582 } 583 584 if s.Sensitive != other.Sensitive { 585 return false 586 } 587 588 if !reflect.DeepEqual(s.Value, other.Value) { 589 return false 590 } 591 592 return true 593 } 594 595 func (s *OutputState) deepcopy() *OutputState { 596 if s == nil { 597 return nil 598 } 599 600 valueCopy, err := copystructure.Copy(s.Value) 601 if err != nil { 602 panic(fmt.Errorf("Error copying output value: %s", err)) 603 } 604 605 n := &OutputState{ 606 Type: s.Type, 607 Sensitive: s.Sensitive, 608 Value: valueCopy, 609 } 610 611 return n 612 } 613 614 // ModuleState is used to track all the state relevant to a single 615 // module. Previous to Terraform 0.3, all state belonged to the "root" 616 // module. 617 type ModuleState struct { 618 // Path is the import path from the root module. Modules imports are 619 // always disjoint, so the path represents amodule tree 620 Path []string `json:"path"` 621 622 // Outputs declared by the module and maintained for each module 623 // even though only the root module technically needs to be kept. 624 // This allows operators to inspect values at the boundaries. 625 Outputs map[string]*OutputState `json:"outputs"` 626 627 // Resources is a mapping of the logically named resource to 628 // the state of the resource. Each resource may actually have 629 // N instances underneath, although a user only needs to think 630 // about the 1:1 case. 631 Resources map[string]*ResourceState `json:"resources"` 632 633 // Dependencies are a list of things that this module relies on 634 // existing to remain intact. For example: an module may depend 635 // on a VPC ID given by an aws_vpc resource. 636 // 637 // Terraform uses this information to build valid destruction 638 // orders and to warn the user if they're destroying a module that 639 // another resource depends on. 640 // 641 // Things can be put into this list that may not be managed by 642 // Terraform. If Terraform doesn't find a matching ID in the 643 // overall state, then it assumes it isn't managed and doesn't 644 // worry about it. 645 Dependencies []string `json:"depends_on,omitempty"` 646 } 647 648 // Equal tests whether one module state is equal to another. 649 func (m *ModuleState) Equal(other *ModuleState) bool { 650 // Paths must be equal 651 if !reflect.DeepEqual(m.Path, other.Path) { 652 return false 653 } 654 655 // Outputs must be equal 656 if len(m.Outputs) != len(other.Outputs) { 657 return false 658 } 659 for k, v := range m.Outputs { 660 if !other.Outputs[k].Equal(v) { 661 return false 662 } 663 } 664 665 // Dependencies must be equal. This sorts these in place but 666 // this shouldn't cause any problems. 667 sort.Strings(m.Dependencies) 668 sort.Strings(other.Dependencies) 669 if len(m.Dependencies) != len(other.Dependencies) { 670 return false 671 } 672 for i, d := range m.Dependencies { 673 if other.Dependencies[i] != d { 674 return false 675 } 676 } 677 678 // Resources must be equal 679 if len(m.Resources) != len(other.Resources) { 680 return false 681 } 682 for k, r := range m.Resources { 683 otherR, ok := other.Resources[k] 684 if !ok { 685 return false 686 } 687 688 if !r.Equal(otherR) { 689 return false 690 } 691 } 692 693 return true 694 } 695 696 // IsRoot says whether or not this module diff is for the root module. 697 func (m *ModuleState) IsRoot() bool { 698 return reflect.DeepEqual(m.Path, rootModulePath) 699 } 700 701 // Orphans returns a list of keys of resources that are in the State 702 // but aren't present in the configuration itself. Hence, these keys 703 // represent the state of resources that are orphans. 704 func (m *ModuleState) Orphans(c *config.Config) []string { 705 keys := make(map[string]struct{}) 706 for k, _ := range m.Resources { 707 keys[k] = struct{}{} 708 } 709 710 if c != nil { 711 for _, r := range c.Resources { 712 delete(keys, r.Id()) 713 714 for k, _ := range keys { 715 if strings.HasPrefix(k, r.Id()+".") { 716 delete(keys, k) 717 } 718 } 719 } 720 } 721 722 result := make([]string, 0, len(keys)) 723 for k, _ := range keys { 724 result = append(result, k) 725 } 726 727 return result 728 } 729 730 // View returns a view with the given resource prefix. 731 func (m *ModuleState) View(id string) *ModuleState { 732 if m == nil { 733 return m 734 } 735 736 r := m.deepcopy() 737 for k, _ := range r.Resources { 738 if id == k || strings.HasPrefix(k, id+".") { 739 continue 740 } 741 742 delete(r.Resources, k) 743 } 744 745 return r 746 } 747 748 func (m *ModuleState) init() { 749 if m.Outputs == nil { 750 m.Outputs = make(map[string]*OutputState) 751 } 752 if m.Resources == nil { 753 m.Resources = make(map[string]*ResourceState) 754 } 755 } 756 757 func (m *ModuleState) deepcopy() *ModuleState { 758 if m == nil { 759 return nil 760 } 761 n := &ModuleState{ 762 Path: make([]string, len(m.Path)), 763 Outputs: make(map[string]*OutputState, len(m.Outputs)), 764 Resources: make(map[string]*ResourceState, len(m.Resources)), 765 Dependencies: make([]string, len(m.Dependencies)), 766 } 767 copy(n.Path, m.Path) 768 copy(n.Dependencies, m.Dependencies) 769 for k, v := range m.Outputs { 770 n.Outputs[k] = v.deepcopy() 771 } 772 for k, v := range m.Resources { 773 n.Resources[k] = v.deepcopy() 774 } 775 return n 776 } 777 778 // prune is used to remove any resources that are no longer required 779 func (m *ModuleState) prune() { 780 for k, v := range m.Resources { 781 v.prune() 782 783 if (v.Primary == nil || v.Primary.ID == "") && len(v.Tainted) == 0 && len(v.Deposed) == 0 { 784 delete(m.Resources, k) 785 } 786 } 787 788 for k, v := range m.Outputs { 789 if v.Value == config.UnknownVariableValue { 790 delete(m.Outputs, k) 791 } 792 } 793 } 794 795 func (m *ModuleState) sort() { 796 for _, v := range m.Resources { 797 v.sort() 798 } 799 } 800 801 func (m *ModuleState) GoString() string { 802 return fmt.Sprintf("*%#v", *m) 803 } 804 805 func (m *ModuleState) String() string { 806 var buf bytes.Buffer 807 808 if len(m.Resources) == 0 { 809 buf.WriteString("<no state>") 810 } 811 812 names := make([]string, 0, len(m.Resources)) 813 for name, _ := range m.Resources { 814 names = append(names, name) 815 } 816 sort.Strings(names) 817 818 for _, k := range names { 819 rs := m.Resources[k] 820 var id string 821 if rs.Primary != nil { 822 id = rs.Primary.ID 823 } 824 if id == "" { 825 id = "<not created>" 826 } 827 828 taintStr := "" 829 if len(rs.Tainted) > 0 { 830 taintStr = fmt.Sprintf(" (%d tainted)", len(rs.Tainted)) 831 } 832 833 deposedStr := "" 834 if len(rs.Deposed) > 0 { 835 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed)) 836 } 837 838 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr)) 839 buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) 840 if rs.Provider != "" { 841 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider)) 842 } 843 844 var attributes map[string]string 845 if rs.Primary != nil { 846 attributes = rs.Primary.Attributes 847 } 848 attrKeys := make([]string, 0, len(attributes)) 849 for ak, _ := range attributes { 850 if ak == "id" { 851 continue 852 } 853 854 attrKeys = append(attrKeys, ak) 855 } 856 sort.Strings(attrKeys) 857 858 for _, ak := range attrKeys { 859 av := attributes[ak] 860 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) 861 } 862 863 for idx, t := range rs.Tainted { 864 buf.WriteString(fmt.Sprintf(" Tainted ID %d = %s\n", idx+1, t.ID)) 865 } 866 867 for idx, t := range rs.Deposed { 868 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s\n", idx+1, t.ID)) 869 } 870 871 if len(rs.Dependencies) > 0 { 872 buf.WriteString(fmt.Sprintf("\n Dependencies:\n")) 873 for _, dep := range rs.Dependencies { 874 buf.WriteString(fmt.Sprintf(" %s\n", dep)) 875 } 876 } 877 } 878 879 if len(m.Outputs) > 0 { 880 buf.WriteString("\nOutputs:\n\n") 881 882 ks := make([]string, 0, len(m.Outputs)) 883 for k, _ := range m.Outputs { 884 ks = append(ks, k) 885 } 886 sort.Strings(ks) 887 888 for _, k := range ks { 889 v := m.Outputs[k] 890 switch vTyped := v.Value.(type) { 891 case string: 892 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 893 case []interface{}: 894 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 895 case map[string]interface{}: 896 var mapKeys []string 897 for key, _ := range vTyped { 898 mapKeys = append(mapKeys, key) 899 } 900 sort.Strings(mapKeys) 901 902 var mapBuf bytes.Buffer 903 mapBuf.WriteString("{") 904 for _, key := range mapKeys { 905 mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key])) 906 } 907 mapBuf.WriteString("}") 908 909 buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String())) 910 } 911 } 912 } 913 914 return buf.String() 915 } 916 917 // ResourceStateKey is a structured representation of the key used for the 918 // ModuleState.Resources mapping 919 type ResourceStateKey struct { 920 Name string 921 Type string 922 Mode config.ResourceMode 923 Index int 924 } 925 926 // Equal determines whether two ResourceStateKeys are the same 927 func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool { 928 if rsk == nil || other == nil { 929 return false 930 } 931 if rsk.Mode != other.Mode { 932 return false 933 } 934 if rsk.Type != other.Type { 935 return false 936 } 937 if rsk.Name != other.Name { 938 return false 939 } 940 if rsk.Index != other.Index { 941 return false 942 } 943 return true 944 } 945 946 func (rsk *ResourceStateKey) String() string { 947 if rsk == nil { 948 return "" 949 } 950 var prefix string 951 switch rsk.Mode { 952 case config.ManagedResourceMode: 953 prefix = "" 954 case config.DataResourceMode: 955 prefix = "data." 956 default: 957 panic(fmt.Errorf("unknown resource mode %s", rsk.Mode)) 958 } 959 if rsk.Index == -1 { 960 return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name) 961 } 962 return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index) 963 } 964 965 // ParseResourceStateKey accepts a key in the format used by 966 // ModuleState.Resources and returns a resource name and resource index. In the 967 // state, a resource has the format "type.name.index" or "type.name". In the 968 // latter case, the index is returned as -1. 969 func ParseResourceStateKey(k string) (*ResourceStateKey, error) { 970 parts := strings.Split(k, ".") 971 mode := config.ManagedResourceMode 972 if len(parts) > 0 && parts[0] == "data" { 973 mode = config.DataResourceMode 974 // Don't need the constant "data" prefix for parsing 975 // now that we've figured out the mode. 976 parts = parts[1:] 977 } 978 if len(parts) < 2 || len(parts) > 3 { 979 return nil, fmt.Errorf("Malformed resource state key: %s", k) 980 } 981 rsk := &ResourceStateKey{ 982 Mode: mode, 983 Type: parts[0], 984 Name: parts[1], 985 Index: -1, 986 } 987 if len(parts) == 3 { 988 index, err := strconv.Atoi(parts[2]) 989 if err != nil { 990 return nil, fmt.Errorf("Malformed resource state key index: %s", k) 991 } 992 rsk.Index = index 993 } 994 return rsk, nil 995 } 996 997 // ResourceState holds the state of a resource that is used so that 998 // a provider can find and manage an existing resource as well as for 999 // storing attributes that are used to populate variables of child 1000 // resources. 1001 // 1002 // Attributes has attributes about the created resource that are 1003 // queryable in interpolation: "${type.id.attr}" 1004 // 1005 // Extra is just extra data that a provider can return that we store 1006 // for later, but is not exposed in any way to the user. 1007 // 1008 type ResourceState struct { 1009 // This is filled in and managed by Terraform, and is the resource 1010 // type itself such as "mycloud_instance". If a resource provider sets 1011 // this value, it won't be persisted. 1012 Type string `json:"type"` 1013 1014 // Dependencies are a list of things that this resource relies on 1015 // existing to remain intact. For example: an AWS instance might 1016 // depend on a subnet (which itself might depend on a VPC, and so 1017 // on). 1018 // 1019 // Terraform uses this information to build valid destruction 1020 // orders and to warn the user if they're destroying a resource that 1021 // another resource depends on. 1022 // 1023 // Things can be put into this list that may not be managed by 1024 // Terraform. If Terraform doesn't find a matching ID in the 1025 // overall state, then it assumes it isn't managed and doesn't 1026 // worry about it. 1027 Dependencies []string `json:"depends_on,omitempty"` 1028 1029 // Primary is the current active instance for this resource. 1030 // It can be replaced but only after a successful creation. 1031 // This is the instances on which providers will act. 1032 Primary *InstanceState `json:"primary"` 1033 1034 // Tainted is used to track any underlying instances that 1035 // have been created but are in a bad or unknown state and 1036 // need to be cleaned up subsequently. In the 1037 // standard case, there is only at most a single instance. 1038 // However, in pathological cases, it is possible for the number 1039 // of instances to accumulate. 1040 Tainted []*InstanceState `json:"tainted,omitempty"` 1041 1042 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 1043 // Primary is Deposed to get it out of the way for the replacement Primary to 1044 // be created by Apply. If the replacement Primary creates successfully, the 1045 // Deposed instance is cleaned up. If there were problems creating the 1046 // replacement, the instance remains in the Deposed list so it can be 1047 // destroyed in a future run. Functionally, Deposed instances are very 1048 // similar to Tainted instances in that Terraform is only tracking them in 1049 // order to remember to destroy them. 1050 Deposed []*InstanceState `json:"deposed,omitempty"` 1051 1052 // Provider is used when a resource is connected to a provider with an alias. 1053 // If this string is empty, the resource is connected to the default provider, 1054 // e.g. "aws_instance" goes with the "aws" provider. 1055 // If the resource block contained a "provider" key, that value will be set here. 1056 Provider string `json:"provider,omitempty"` 1057 } 1058 1059 // Equal tests whether two ResourceStates are equal. 1060 func (s *ResourceState) Equal(other *ResourceState) bool { 1061 if s.Type != other.Type { 1062 return false 1063 } 1064 1065 if s.Provider != other.Provider { 1066 return false 1067 } 1068 1069 // Dependencies must be equal 1070 sort.Strings(s.Dependencies) 1071 sort.Strings(other.Dependencies) 1072 if len(s.Dependencies) != len(other.Dependencies) { 1073 return false 1074 } 1075 for i, d := range s.Dependencies { 1076 if other.Dependencies[i] != d { 1077 return false 1078 } 1079 } 1080 1081 // States must be equal 1082 if !s.Primary.Equal(other.Primary) { 1083 return false 1084 } 1085 1086 // Tainted 1087 taints := make(map[string]*InstanceState) 1088 for _, t := range other.Tainted { 1089 if t == nil { 1090 continue 1091 } 1092 1093 taints[t.ID] = t 1094 } 1095 for _, t := range s.Tainted { 1096 if t == nil { 1097 continue 1098 } 1099 1100 otherT, ok := taints[t.ID] 1101 if !ok { 1102 return false 1103 } 1104 delete(taints, t.ID) 1105 1106 if !t.Equal(otherT) { 1107 return false 1108 } 1109 } 1110 1111 // This means that we have stuff in other tainted that we don't 1112 // have, so it is not equal. 1113 if len(taints) > 0 { 1114 return false 1115 } 1116 1117 return true 1118 } 1119 1120 // Taint takes the primary state and marks it as tainted. If there is no 1121 // primary state, this does nothing. 1122 func (r *ResourceState) Taint() { 1123 // If there is no primary, nothing to do 1124 if r.Primary == nil { 1125 return 1126 } 1127 1128 // Shuffle to the end of the taint list and set primary to nil 1129 r.Tainted = append(r.Tainted, r.Primary) 1130 r.Primary = nil 1131 } 1132 1133 // Untaint takes a tainted InstanceState and marks it as primary. 1134 // The index argument is used to select a single InstanceState from the 1135 // array of Tainted when there are more than one. If index is -1, the 1136 // first Tainted InstanceState will be untainted iff there is only one 1137 // Tainted InstanceState. Index must be >= 0 to specify an InstanceState 1138 // when Tainted has more than one member. 1139 func (r *ResourceState) Untaint(index int) error { 1140 if len(r.Tainted) == 0 { 1141 return fmt.Errorf("Nothing to untaint.") 1142 } 1143 if r.Primary != nil { 1144 return fmt.Errorf("Resource has a primary instance in the state that would be overwritten by untainting. If you want to restore a tainted resource to primary, taint the existing primary instance first.") 1145 } 1146 if index == -1 && len(r.Tainted) > 1 { 1147 return fmt.Errorf("There are %d tainted instances for this resource, please specify an index to select which one to untaint.", len(r.Tainted)) 1148 } 1149 if index == -1 { 1150 index = 0 1151 } 1152 if index >= len(r.Tainted) { 1153 return fmt.Errorf("There are %d tainted instances for this resource, the index specified (%d) is out of range.", len(r.Tainted), index) 1154 } 1155 1156 // Perform the untaint 1157 r.Primary = r.Tainted[index] 1158 r.Tainted = append(r.Tainted[:index], r.Tainted[index+1:]...) 1159 1160 return nil 1161 } 1162 1163 func (r *ResourceState) init() { 1164 if r.Primary == nil { 1165 r.Primary = &InstanceState{} 1166 } 1167 r.Primary.init() 1168 } 1169 1170 func (r *ResourceState) deepcopy() *ResourceState { 1171 if r == nil { 1172 return nil 1173 } 1174 1175 n := &ResourceState{ 1176 Type: r.Type, 1177 Dependencies: nil, 1178 Primary: r.Primary.DeepCopy(), 1179 Tainted: nil, 1180 Provider: r.Provider, 1181 } 1182 if r.Dependencies != nil { 1183 n.Dependencies = make([]string, len(r.Dependencies)) 1184 copy(n.Dependencies, r.Dependencies) 1185 } 1186 if r.Tainted != nil { 1187 n.Tainted = make([]*InstanceState, 0, len(r.Tainted)) 1188 for _, inst := range r.Tainted { 1189 n.Tainted = append(n.Tainted, inst.DeepCopy()) 1190 } 1191 } 1192 if r.Deposed != nil { 1193 n.Deposed = make([]*InstanceState, 0, len(r.Deposed)) 1194 for _, inst := range r.Deposed { 1195 n.Deposed = append(n.Deposed, inst.DeepCopy()) 1196 } 1197 } 1198 1199 return n 1200 } 1201 1202 // prune is used to remove any instances that are no longer required 1203 func (r *ResourceState) prune() { 1204 n := len(r.Tainted) 1205 for i := 0; i < n; i++ { 1206 inst := r.Tainted[i] 1207 if inst == nil || inst.ID == "" { 1208 copy(r.Tainted[i:], r.Tainted[i+1:]) 1209 r.Tainted[n-1] = nil 1210 n-- 1211 i-- 1212 } 1213 } 1214 1215 r.Tainted = r.Tainted[:n] 1216 1217 n = len(r.Deposed) 1218 for i := 0; i < n; i++ { 1219 inst := r.Deposed[i] 1220 if inst == nil || inst.ID == "" { 1221 copy(r.Deposed[i:], r.Deposed[i+1:]) 1222 r.Deposed[n-1] = nil 1223 n-- 1224 i-- 1225 } 1226 } 1227 1228 r.Deposed = r.Deposed[:n] 1229 } 1230 1231 func (r *ResourceState) sort() { 1232 sort.Strings(r.Dependencies) 1233 } 1234 1235 func (s *ResourceState) GoString() string { 1236 return fmt.Sprintf("*%#v", *s) 1237 } 1238 1239 func (s *ResourceState) String() string { 1240 var buf bytes.Buffer 1241 buf.WriteString(fmt.Sprintf("Type = %s", s.Type)) 1242 return buf.String() 1243 } 1244 1245 // InstanceState is used to track the unique state information belonging 1246 // to a given instance. 1247 type InstanceState struct { 1248 // A unique ID for this resource. This is opaque to Terraform 1249 // and is only meant as a lookup mechanism for the providers. 1250 ID string `json:"id"` 1251 1252 // Attributes are basic information about the resource. Any keys here 1253 // are accessible in variable format within Terraform configurations: 1254 // ${resourcetype.name.attribute}. 1255 Attributes map[string]string `json:"attributes,omitempty"` 1256 1257 // Ephemeral is used to store any state associated with this instance 1258 // that is necessary for the Terraform run to complete, but is not 1259 // persisted to a state file. 1260 Ephemeral EphemeralState `json:"-"` 1261 1262 // Meta is a simple K/V map that is persisted to the State but otherwise 1263 // ignored by Terraform core. It's meant to be used for accounting by 1264 // external client code. 1265 Meta map[string]string `json:"meta,omitempty"` 1266 } 1267 1268 func (i *InstanceState) init() { 1269 if i.Attributes == nil { 1270 i.Attributes = make(map[string]string) 1271 } 1272 if i.Meta == nil { 1273 i.Meta = make(map[string]string) 1274 } 1275 i.Ephemeral.init() 1276 } 1277 1278 func (i *InstanceState) DeepCopy() *InstanceState { 1279 if i == nil { 1280 return nil 1281 } 1282 n := &InstanceState{ 1283 ID: i.ID, 1284 Ephemeral: *i.Ephemeral.DeepCopy(), 1285 } 1286 if i.Attributes != nil { 1287 n.Attributes = make(map[string]string, len(i.Attributes)) 1288 for k, v := range i.Attributes { 1289 n.Attributes[k] = v 1290 } 1291 } 1292 if i.Meta != nil { 1293 n.Meta = make(map[string]string, len(i.Meta)) 1294 for k, v := range i.Meta { 1295 n.Meta[k] = v 1296 } 1297 } 1298 return n 1299 } 1300 1301 func (s *InstanceState) Empty() bool { 1302 return s == nil || s.ID == "" 1303 } 1304 1305 func (s *InstanceState) Equal(other *InstanceState) bool { 1306 // Short circuit some nil checks 1307 if s == nil || other == nil { 1308 return s == other 1309 } 1310 1311 // IDs must be equal 1312 if s.ID != other.ID { 1313 return false 1314 } 1315 1316 // Attributes must be equal 1317 if len(s.Attributes) != len(other.Attributes) { 1318 return false 1319 } 1320 for k, v := range s.Attributes { 1321 otherV, ok := other.Attributes[k] 1322 if !ok { 1323 return false 1324 } 1325 1326 if v != otherV { 1327 return false 1328 } 1329 } 1330 1331 // Meta must be equal 1332 if len(s.Meta) != len(other.Meta) { 1333 return false 1334 } 1335 for k, v := range s.Meta { 1336 otherV, ok := other.Meta[k] 1337 if !ok { 1338 return false 1339 } 1340 1341 if v != otherV { 1342 return false 1343 } 1344 } 1345 1346 return true 1347 } 1348 1349 // MergeDiff takes a ResourceDiff and merges the attributes into 1350 // this resource state in order to generate a new state. This new 1351 // state can be used to provide updated attribute lookups for 1352 // variable interpolation. 1353 // 1354 // If the diff attribute requires computing the value, and hence 1355 // won't be available until apply, the value is replaced with the 1356 // computeID. 1357 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 1358 result := s.DeepCopy() 1359 if result == nil { 1360 result = new(InstanceState) 1361 } 1362 result.init() 1363 1364 if s != nil { 1365 for k, v := range s.Attributes { 1366 result.Attributes[k] = v 1367 } 1368 } 1369 if d != nil { 1370 for k, diff := range d.Attributes { 1371 if diff.NewRemoved { 1372 delete(result.Attributes, k) 1373 continue 1374 } 1375 if diff.NewComputed { 1376 result.Attributes[k] = config.UnknownVariableValue 1377 continue 1378 } 1379 1380 result.Attributes[k] = diff.New 1381 } 1382 } 1383 1384 return result 1385 } 1386 1387 func (i *InstanceState) GoString() string { 1388 return fmt.Sprintf("*%#v", *i) 1389 } 1390 1391 func (i *InstanceState) String() string { 1392 var buf bytes.Buffer 1393 1394 if i == nil || i.ID == "" { 1395 return "<not created>" 1396 } 1397 1398 buf.WriteString(fmt.Sprintf("ID = %s\n", i.ID)) 1399 1400 attributes := i.Attributes 1401 attrKeys := make([]string, 0, len(attributes)) 1402 for ak, _ := range attributes { 1403 if ak == "id" { 1404 continue 1405 } 1406 1407 attrKeys = append(attrKeys, ak) 1408 } 1409 sort.Strings(attrKeys) 1410 1411 for _, ak := range attrKeys { 1412 av := attributes[ak] 1413 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1414 } 1415 1416 return buf.String() 1417 } 1418 1419 // EphemeralState is used for transient state that is only kept in-memory 1420 type EphemeralState struct { 1421 // ConnInfo is used for the providers to export information which is 1422 // used to connect to the resource for provisioning. For example, 1423 // this could contain SSH or WinRM credentials. 1424 ConnInfo map[string]string `json:"-"` 1425 1426 // Type is used to specify the resource type for this instance. This is only 1427 // required for import operations (as documented). If the documentation 1428 // doesn't state that you need to set this, then don't worry about 1429 // setting it. 1430 Type string `json:"-"` 1431 } 1432 1433 func (e *EphemeralState) init() { 1434 if e.ConnInfo == nil { 1435 e.ConnInfo = make(map[string]string) 1436 } 1437 } 1438 1439 func (e *EphemeralState) DeepCopy() *EphemeralState { 1440 if e == nil { 1441 return nil 1442 } 1443 n := &EphemeralState{} 1444 if e.ConnInfo != nil { 1445 n.ConnInfo = make(map[string]string, len(e.ConnInfo)) 1446 for k, v := range e.ConnInfo { 1447 n.ConnInfo[k] = v 1448 } 1449 } 1450 return n 1451 } 1452 1453 type jsonStateVersionIdentifier struct { 1454 Version int `json:"version"` 1455 } 1456 1457 // ReadState reads a state structure out of a reader in the format that 1458 // was written by WriteState. 1459 func ReadState(src io.Reader) (*State, error) { 1460 buf := bufio.NewReader(src) 1461 1462 // Check if this is a V0 format 1463 start, err := buf.Peek(len(stateFormatMagic)) 1464 if err != nil { 1465 return nil, fmt.Errorf("Failed to check for magic bytes: %v", err) 1466 } 1467 if string(start) == stateFormatMagic { 1468 // Read the old state 1469 old, err := ReadStateV0(buf) 1470 if err != nil { 1471 return nil, err 1472 } 1473 return old.upgrade() 1474 } 1475 1476 // If we are JSON we buffer the whole thing in memory so we can read it twice. 1477 // This is suboptimal, but will work for now. 1478 jsonBytes, err := ioutil.ReadAll(buf) 1479 if err != nil { 1480 return nil, fmt.Errorf("Reading state file failed: %v", err) 1481 } 1482 1483 versionIdentifier := &jsonStateVersionIdentifier{} 1484 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil { 1485 return nil, fmt.Errorf("Decoding state file version failed: %v", err) 1486 } 1487 1488 switch versionIdentifier.Version { 1489 case 0: 1490 return nil, fmt.Errorf("State version 0 is not supported as JSON.") 1491 case 1: 1492 old, err := ReadStateV1(jsonBytes) 1493 if err != nil { 1494 return nil, err 1495 } 1496 return old.upgrade() 1497 case 2: 1498 state, err := ReadStateV2(jsonBytes) 1499 if err != nil { 1500 return nil, err 1501 } 1502 return state, nil 1503 default: 1504 return nil, fmt.Errorf("State version %d not supported, please update.", 1505 versionIdentifier.Version) 1506 } 1507 } 1508 1509 func ReadStateV1(jsonBytes []byte) (*stateV1, error) { 1510 state := &stateV1{} 1511 if err := json.Unmarshal(jsonBytes, state); err != nil { 1512 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1513 } 1514 1515 if state.Version != 1 { 1516 return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+ 1517 "read %d, expected 1", state.Version) 1518 } 1519 1520 return state, nil 1521 } 1522 1523 func ReadStateV2(jsonBytes []byte) (*State, error) { 1524 state := &State{} 1525 if err := json.Unmarshal(jsonBytes, state); err != nil { 1526 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1527 } 1528 1529 // Check the version, this to ensure we don't read a future 1530 // version that we don't understand 1531 if state.Version > StateVersion { 1532 return nil, fmt.Errorf("State version %d not supported, please update.", 1533 state.Version) 1534 } 1535 1536 // Make sure the version is semantic 1537 if state.TFVersion != "" { 1538 if _, err := version.NewVersion(state.TFVersion); err != nil { 1539 return nil, fmt.Errorf( 1540 "State contains invalid version: %s\n\n"+ 1541 "Terraform validates the version format prior to writing it. This\n"+ 1542 "means that this is invalid of the state becoming corrupted through\n"+ 1543 "some external means. Please manually modify the Terraform version\n"+ 1544 "field to be a proper semantic version.", 1545 state.TFVersion) 1546 } 1547 } 1548 1549 // Sort it 1550 state.sort() 1551 1552 return state, nil 1553 } 1554 1555 // WriteState writes a state somewhere in a binary format. 1556 func WriteState(d *State, dst io.Writer) error { 1557 // Make sure it is sorted 1558 d.sort() 1559 1560 // Ensure the version is set 1561 d.Version = StateVersion 1562 1563 // If the TFVersion is set, verify it. We used to just set the version 1564 // here, but this isn't safe since it changes the MD5 sum on some remote 1565 // state storage backends such as Atlas. We now leave it be if needed. 1566 if d.TFVersion != "" { 1567 if _, err := version.NewVersion(d.TFVersion); err != nil { 1568 return fmt.Errorf( 1569 "Error writing state, invalid version: %s\n\n"+ 1570 "The Terraform version when writing the state must be a semantic\n"+ 1571 "version.", 1572 d.TFVersion) 1573 } 1574 } 1575 1576 // Encode the data in a human-friendly way 1577 data, err := json.MarshalIndent(d, "", " ") 1578 if err != nil { 1579 return fmt.Errorf("Failed to encode state: %s", err) 1580 } 1581 1582 // We append a newline to the data because MarshalIndent doesn't 1583 data = append(data, '\n') 1584 1585 // Write the data out to the dst 1586 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 1587 return fmt.Errorf("Failed to write state: %v", err) 1588 } 1589 1590 return nil 1591 } 1592 1593 // moduleStateSort implements sort.Interface to sort module states 1594 type moduleStateSort []*ModuleState 1595 1596 func (s moduleStateSort) Len() int { 1597 return len(s) 1598 } 1599 1600 func (s moduleStateSort) Less(i, j int) bool { 1601 a := s[i] 1602 b := s[j] 1603 1604 // If the lengths are different, then the shorter one always wins 1605 if len(a.Path) != len(b.Path) { 1606 return len(a.Path) < len(b.Path) 1607 } 1608 1609 // Otherwise, compare lexically 1610 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".") 1611 } 1612 1613 func (s moduleStateSort) Swap(i, j int) { 1614 s[i], s[j] = s[j], s[i] 1615 }