github.com/anfernee/terraform@v0.6.16-0.20160430000239-06e5085a92f2/terraform/state.go (about) 1 package terraform 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "io" 9 "log" 10 "reflect" 11 "sort" 12 "strconv" 13 "strings" 14 15 "github.com/hashicorp/terraform/config" 16 ) 17 18 const ( 19 // StateVersion is the current version for our state file 20 StateVersion = 1 21 ) 22 23 // rootModulePath is the path of the root module 24 var rootModulePath = []string{"root"} 25 26 // State keeps track of a snapshot state-of-the-world that Terraform 27 // can use to keep track of what real world resources it is actually 28 // managing. This is the latest format as of Terraform 0.3 29 type State struct { 30 // Version is the protocol version. Currently only "1". 31 Version int `json:"version"` 32 33 // Serial is incremented on any operation that modifies 34 // the State file. It is used to detect potentially conflicting 35 // updates. 36 Serial int64 `json:"serial"` 37 38 // Remote is used to track the metadata required to 39 // pull and push state files from a remote storage endpoint. 40 Remote *RemoteState `json:"remote,omitempty"` 41 42 // Modules contains all the modules in a breadth-first order 43 Modules []*ModuleState `json:"modules"` 44 } 45 46 // NewState is used to initialize a blank state 47 func NewState() *State { 48 s := &State{} 49 s.init() 50 return s 51 } 52 53 // Children returns the ModuleStates that are direct children of 54 // the given path. If the path is "root", for example, then children 55 // returned might be "root.child", but not "root.child.grandchild". 56 func (s *State) Children(path []string) []*ModuleState { 57 // TODO: test 58 59 result := make([]*ModuleState, 0) 60 for _, m := range s.Modules { 61 if len(m.Path) != len(path)+1 { 62 continue 63 } 64 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 65 continue 66 } 67 68 result = append(result, m) 69 } 70 71 return result 72 } 73 74 // AddModule adds the module with the given path to the state. 75 // 76 // This should be the preferred method to add module states since it 77 // allows us to optimize lookups later as well as control sorting. 78 func (s *State) AddModule(path []string) *ModuleState { 79 m := &ModuleState{Path: path} 80 m.init() 81 s.Modules = append(s.Modules, m) 82 s.sort() 83 return m 84 } 85 86 // ModuleByPath is used to lookup the module state for the given path. 87 // This should be the preferred lookup mechanism as it allows for future 88 // lookup optimizations. 89 func (s *State) ModuleByPath(path []string) *ModuleState { 90 if s == nil { 91 return nil 92 } 93 for _, mod := range s.Modules { 94 if mod.Path == nil { 95 panic("missing module path") 96 } 97 if reflect.DeepEqual(mod.Path, path) { 98 return mod 99 } 100 } 101 return nil 102 } 103 104 // ModuleOrphans returns all the module orphans in this state by 105 // returning their full paths. These paths can be used with ModuleByPath 106 // to return the actual state. 107 func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string { 108 // direct keeps track of what direct children we have both in our config 109 // and in our state. childrenKeys keeps track of what isn't an orphan. 110 direct := make(map[string]struct{}) 111 childrenKeys := make(map[string]struct{}) 112 if c != nil { 113 for _, m := range c.Modules { 114 childrenKeys[m.Name] = struct{}{} 115 direct[m.Name] = struct{}{} 116 } 117 } 118 119 // Go over the direct children and find any that aren't in our keys. 120 var orphans [][]string 121 for _, m := range s.Children(path) { 122 key := m.Path[len(m.Path)-1] 123 124 // Record that we found this key as a direct child. We use this 125 // later to find orphan nested modules. 126 direct[key] = struct{}{} 127 128 // If we have a direct child still in our config, it is not an orphan 129 if _, ok := childrenKeys[key]; ok { 130 continue 131 } 132 133 orphans = append(orphans, m.Path) 134 } 135 136 // Find the orphans that are nested... 137 for _, m := range s.Modules { 138 // We only want modules that are at least grandchildren 139 if len(m.Path) < len(path)+2 { 140 continue 141 } 142 143 // If it isn't part of our tree, continue 144 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 145 continue 146 } 147 148 // If we have the direct child, then just skip it. 149 key := m.Path[len(path)] 150 if _, ok := direct[key]; ok { 151 continue 152 } 153 154 orphanPath := m.Path[:len(path)+1] 155 156 // Don't double-add if we've already added this orphan (which can happen if 157 // there are multiple nested sub-modules that get orphaned together). 158 alreadyAdded := false 159 for _, o := range orphans { 160 if reflect.DeepEqual(o, orphanPath) { 161 alreadyAdded = true 162 break 163 } 164 } 165 if alreadyAdded { 166 continue 167 } 168 169 // Add this orphan 170 orphans = append(orphans, orphanPath) 171 } 172 173 return orphans 174 } 175 176 // Empty returns true if the state is empty. 177 func (s *State) Empty() bool { 178 if s == nil { 179 return true 180 } 181 182 return len(s.Modules) == 0 183 } 184 185 // IsRemote returns true if State represents a state that exists and is 186 // remote. 187 func (s *State) IsRemote() bool { 188 if s == nil { 189 return false 190 } 191 if s.Remote == nil { 192 return false 193 } 194 if s.Remote.Type == "" { 195 return false 196 } 197 198 return true 199 } 200 201 // RootModule returns the ModuleState for the root module 202 func (s *State) RootModule() *ModuleState { 203 root := s.ModuleByPath(rootModulePath) 204 if root == nil { 205 panic("missing root module") 206 } 207 return root 208 } 209 210 // Equal tests if one state is equal to another. 211 func (s *State) Equal(other *State) bool { 212 // If one is nil, we do a direct check 213 if s == nil || other == nil { 214 return s == other 215 } 216 217 // If the versions are different, they're certainly not equal 218 if s.Version != other.Version { 219 return false 220 } 221 222 // If any of the modules are not equal, then this state isn't equal 223 if len(s.Modules) != len(other.Modules) { 224 return false 225 } 226 for _, m := range s.Modules { 227 // This isn't very optimal currently but works. 228 otherM := other.ModuleByPath(m.Path) 229 if otherM == nil { 230 return false 231 } 232 233 // If they're not equal, then we're not equal! 234 if !m.Equal(otherM) { 235 return false 236 } 237 } 238 239 return true 240 } 241 242 // DeepCopy performs a deep copy of the state structure and returns 243 // a new structure. 244 func (s *State) DeepCopy() *State { 245 if s == nil { 246 return nil 247 } 248 n := &State{ 249 Version: s.Version, 250 Serial: s.Serial, 251 Modules: make([]*ModuleState, 0, len(s.Modules)), 252 } 253 for _, mod := range s.Modules { 254 n.Modules = append(n.Modules, mod.deepcopy()) 255 } 256 if s.Remote != nil { 257 n.Remote = s.Remote.deepcopy() 258 } 259 return n 260 } 261 262 // IncrementSerialMaybe increments the serial number of this state 263 // if it different from the other state. 264 func (s *State) IncrementSerialMaybe(other *State) { 265 if s == nil { 266 return 267 } 268 if other == nil { 269 return 270 } 271 if s.Serial > other.Serial { 272 return 273 } 274 if !s.Equal(other) { 275 if other.Serial > s.Serial { 276 s.Serial = other.Serial 277 } 278 279 s.Serial++ 280 } 281 } 282 283 func (s *State) init() { 284 if s.Version == 0 { 285 s.Version = StateVersion 286 } 287 if len(s.Modules) == 0 { 288 root := &ModuleState{ 289 Path: rootModulePath, 290 } 291 root.init() 292 s.Modules = []*ModuleState{root} 293 } 294 } 295 296 // prune is used to remove any resources that are no longer required 297 func (s *State) prune() { 298 if s == nil { 299 return 300 } 301 for _, mod := range s.Modules { 302 mod.prune() 303 } 304 if s.Remote != nil && s.Remote.Empty() { 305 s.Remote = nil 306 } 307 } 308 309 // sort sorts the modules 310 func (s *State) sort() { 311 sort.Sort(moduleStateSort(s.Modules)) 312 313 // Allow modules to be sorted 314 for _, m := range s.Modules { 315 m.sort() 316 } 317 } 318 319 func (s *State) GoString() string { 320 return fmt.Sprintf("*%#v", *s) 321 } 322 323 func (s *State) String() string { 324 if s == nil { 325 return "<nil>" 326 } 327 328 var buf bytes.Buffer 329 for _, m := range s.Modules { 330 mStr := m.String() 331 332 // If we're the root module, we just write the output directly. 333 if reflect.DeepEqual(m.Path, rootModulePath) { 334 buf.WriteString(mStr + "\n") 335 continue 336 } 337 338 buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], "."))) 339 340 s := bufio.NewScanner(strings.NewReader(mStr)) 341 for s.Scan() { 342 text := s.Text() 343 if text != "" { 344 text = " " + text 345 } 346 347 buf.WriteString(fmt.Sprintf("%s\n", text)) 348 } 349 } 350 351 return strings.TrimSpace(buf.String()) 352 } 353 354 // RemoteState is used to track the information about a remote 355 // state store that we push/pull state to. 356 type RemoteState struct { 357 // Type controls the client we use for the remote state 358 Type string `json:"type"` 359 360 // Config is used to store arbitrary configuration that 361 // is type specific 362 Config map[string]string `json:"config"` 363 } 364 365 func (r *RemoteState) deepcopy() *RemoteState { 366 confCopy := make(map[string]string, len(r.Config)) 367 for k, v := range r.Config { 368 confCopy[k] = v 369 } 370 return &RemoteState{ 371 Type: r.Type, 372 Config: confCopy, 373 } 374 } 375 376 func (r *RemoteState) Empty() bool { 377 return r == nil || r.Type == "" 378 } 379 380 func (r *RemoteState) Equals(other *RemoteState) bool { 381 if r.Type != other.Type { 382 return false 383 } 384 if len(r.Config) != len(other.Config) { 385 return false 386 } 387 for k, v := range r.Config { 388 if other.Config[k] != v { 389 return false 390 } 391 } 392 return true 393 } 394 395 func (r *RemoteState) GoString() string { 396 return fmt.Sprintf("*%#v", *r) 397 } 398 399 // ModuleState is used to track all the state relevant to a single 400 // module. Previous to Terraform 0.3, all state belonged to the "root" 401 // module. 402 type ModuleState struct { 403 // Path is the import path from the root module. Modules imports are 404 // always disjoint, so the path represents amodule tree 405 Path []string `json:"path"` 406 407 // Outputs declared by the module and maintained for each module 408 // even though only the root module technically needs to be kept. 409 // This allows operators to inspect values at the boundaries. 410 Outputs map[string]string `json:"outputs"` 411 412 // Resources is a mapping of the logically named resource to 413 // the state of the resource. Each resource may actually have 414 // N instances underneath, although a user only needs to think 415 // about the 1:1 case. 416 Resources map[string]*ResourceState `json:"resources"` 417 418 // Dependencies are a list of things that this module relies on 419 // existing to remain intact. For example: an module may depend 420 // on a VPC ID given by an aws_vpc resource. 421 // 422 // Terraform uses this information to build valid destruction 423 // orders and to warn the user if they're destroying a module that 424 // another resource depends on. 425 // 426 // Things can be put into this list that may not be managed by 427 // Terraform. If Terraform doesn't find a matching ID in the 428 // overall state, then it assumes it isn't managed and doesn't 429 // worry about it. 430 Dependencies []string `json:"depends_on,omitempty"` 431 } 432 433 // Equal tests whether one module state is equal to another. 434 func (m *ModuleState) Equal(other *ModuleState) bool { 435 // Paths must be equal 436 if !reflect.DeepEqual(m.Path, other.Path) { 437 return false 438 } 439 440 // Outputs must be equal 441 if len(m.Outputs) != len(other.Outputs) { 442 return false 443 } 444 for k, v := range m.Outputs { 445 if other.Outputs[k] != v { 446 return false 447 } 448 } 449 450 // Dependencies must be equal. This sorts these in place but 451 // this shouldn't cause any problems. 452 sort.Strings(m.Dependencies) 453 sort.Strings(other.Dependencies) 454 if len(m.Dependencies) != len(other.Dependencies) { 455 return false 456 } 457 for i, d := range m.Dependencies { 458 if other.Dependencies[i] != d { 459 return false 460 } 461 } 462 463 // Resources must be equal 464 if len(m.Resources) != len(other.Resources) { 465 return false 466 } 467 for k, r := range m.Resources { 468 otherR, ok := other.Resources[k] 469 if !ok { 470 return false 471 } 472 473 if !r.Equal(otherR) { 474 return false 475 } 476 } 477 478 return true 479 } 480 481 // IsRoot says whether or not this module diff is for the root module. 482 func (m *ModuleState) IsRoot() bool { 483 return reflect.DeepEqual(m.Path, rootModulePath) 484 } 485 486 // Orphans returns a list of keys of resources that are in the State 487 // but aren't present in the configuration itself. Hence, these keys 488 // represent the state of resources that are orphans. 489 func (m *ModuleState) Orphans(c *config.Config) []string { 490 keys := make(map[string]struct{}) 491 for k, _ := range m.Resources { 492 keys[k] = struct{}{} 493 } 494 495 if c != nil { 496 for _, r := range c.Resources { 497 delete(keys, r.Id()) 498 499 for k, _ := range keys { 500 if strings.HasPrefix(k, r.Id()+".") { 501 delete(keys, k) 502 } 503 } 504 } 505 } 506 507 result := make([]string, 0, len(keys)) 508 for k, _ := range keys { 509 result = append(result, k) 510 } 511 512 return result 513 } 514 515 // View returns a view with the given resource prefix. 516 func (m *ModuleState) View(id string) *ModuleState { 517 if m == nil { 518 return m 519 } 520 521 r := m.deepcopy() 522 for k, _ := range r.Resources { 523 if id == k || strings.HasPrefix(k, id+".") { 524 continue 525 } 526 527 delete(r.Resources, k) 528 } 529 530 return r 531 } 532 533 func (m *ModuleState) init() { 534 if m.Outputs == nil { 535 m.Outputs = make(map[string]string) 536 } 537 if m.Resources == nil { 538 m.Resources = make(map[string]*ResourceState) 539 } 540 } 541 542 func (m *ModuleState) deepcopy() *ModuleState { 543 if m == nil { 544 return nil 545 } 546 n := &ModuleState{ 547 Path: make([]string, len(m.Path)), 548 Outputs: make(map[string]string, len(m.Outputs)), 549 Resources: make(map[string]*ResourceState, len(m.Resources)), 550 } 551 copy(n.Path, m.Path) 552 for k, v := range m.Outputs { 553 n.Outputs[k] = v 554 } 555 for k, v := range m.Resources { 556 n.Resources[k] = v.deepcopy() 557 } 558 return n 559 } 560 561 // prune is used to remove any resources that are no longer required 562 func (m *ModuleState) prune() { 563 for k, v := range m.Resources { 564 v.prune() 565 566 if (v.Primary == nil || v.Primary.ID == "") && len(v.Tainted) == 0 && len(v.Deposed) == 0 { 567 delete(m.Resources, k) 568 } 569 } 570 571 for k, v := range m.Outputs { 572 if v == config.UnknownVariableValue { 573 delete(m.Outputs, k) 574 } 575 } 576 } 577 578 func (m *ModuleState) sort() { 579 for _, v := range m.Resources { 580 v.sort() 581 } 582 } 583 584 func (m *ModuleState) GoString() string { 585 return fmt.Sprintf("*%#v", *m) 586 } 587 588 func (m *ModuleState) String() string { 589 var buf bytes.Buffer 590 591 if len(m.Resources) == 0 { 592 buf.WriteString("<no state>") 593 } 594 595 names := make([]string, 0, len(m.Resources)) 596 for name, _ := range m.Resources { 597 names = append(names, name) 598 } 599 sort.Strings(names) 600 601 for _, k := range names { 602 rs := m.Resources[k] 603 var id string 604 if rs.Primary != nil { 605 id = rs.Primary.ID 606 } 607 if id == "" { 608 id = "<not created>" 609 } 610 611 taintStr := "" 612 if len(rs.Tainted) > 0 { 613 taintStr = fmt.Sprintf(" (%d tainted)", len(rs.Tainted)) 614 } 615 616 deposedStr := "" 617 if len(rs.Deposed) > 0 { 618 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed)) 619 } 620 621 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr)) 622 buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) 623 if rs.Provider != "" { 624 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider)) 625 } 626 627 var attributes map[string]string 628 if rs.Primary != nil { 629 attributes = rs.Primary.Attributes 630 } 631 attrKeys := make([]string, 0, len(attributes)) 632 for ak, _ := range attributes { 633 if ak == "id" { 634 continue 635 } 636 637 attrKeys = append(attrKeys, ak) 638 } 639 sort.Strings(attrKeys) 640 641 for _, ak := range attrKeys { 642 av := attributes[ak] 643 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) 644 } 645 646 for idx, t := range rs.Tainted { 647 buf.WriteString(fmt.Sprintf(" Tainted ID %d = %s\n", idx+1, t.ID)) 648 } 649 650 for idx, t := range rs.Deposed { 651 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s\n", idx+1, t.ID)) 652 } 653 654 if len(rs.Dependencies) > 0 { 655 buf.WriteString(fmt.Sprintf("\n Dependencies:\n")) 656 for _, dep := range rs.Dependencies { 657 buf.WriteString(fmt.Sprintf(" %s\n", dep)) 658 } 659 } 660 } 661 662 if len(m.Outputs) > 0 { 663 buf.WriteString("\nOutputs:\n\n") 664 665 ks := make([]string, 0, len(m.Outputs)) 666 for k, _ := range m.Outputs { 667 ks = append(ks, k) 668 } 669 sort.Strings(ks) 670 671 for _, k := range ks { 672 v := m.Outputs[k] 673 buf.WriteString(fmt.Sprintf("%s = %s\n", k, v)) 674 } 675 } 676 677 return buf.String() 678 } 679 680 // ResourceStateKey is a structured representation of the key used for the 681 // ModuleState.Resources mapping 682 type ResourceStateKey struct { 683 Name string 684 Type string 685 Index int 686 } 687 688 // Equal determines whether two ResourceStateKeys are the same 689 func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool { 690 if rsk == nil || other == nil { 691 return false 692 } 693 if rsk.Type != other.Type { 694 return false 695 } 696 if rsk.Name != other.Name { 697 return false 698 } 699 if rsk.Index != other.Index { 700 return false 701 } 702 return true 703 } 704 705 func (rsk *ResourceStateKey) String() string { 706 if rsk == nil { 707 return "" 708 } 709 if rsk.Index == -1 { 710 return fmt.Sprintf("%s.%s", rsk.Type, rsk.Name) 711 } 712 return fmt.Sprintf("%s.%s.%d", rsk.Type, rsk.Name, rsk.Index) 713 } 714 715 // ParseResourceStateKey accepts a key in the format used by 716 // ModuleState.Resources and returns a resource name and resource index. In the 717 // state, a resource has the format "type.name.index" or "type.name". In the 718 // latter case, the index is returned as -1. 719 func ParseResourceStateKey(k string) (*ResourceStateKey, error) { 720 parts := strings.Split(k, ".") 721 if len(parts) < 2 || len(parts) > 3 { 722 return nil, fmt.Errorf("Malformed resource state key: %s", k) 723 } 724 rsk := &ResourceStateKey{ 725 Type: parts[0], 726 Name: parts[1], 727 Index: -1, 728 } 729 if len(parts) == 3 { 730 index, err := strconv.Atoi(parts[2]) 731 if err != nil { 732 return nil, fmt.Errorf("Malformed resource state key index: %s", k) 733 } 734 rsk.Index = index 735 } 736 return rsk, nil 737 } 738 739 // ResourceState holds the state of a resource that is used so that 740 // a provider can find and manage an existing resource as well as for 741 // storing attributes that are used to populate variables of child 742 // resources. 743 // 744 // Attributes has attributes about the created resource that are 745 // queryable in interpolation: "${type.id.attr}" 746 // 747 // Extra is just extra data that a provider can return that we store 748 // for later, but is not exposed in any way to the user. 749 // 750 type ResourceState struct { 751 // This is filled in and managed by Terraform, and is the resource 752 // type itself such as "mycloud_instance". If a resource provider sets 753 // this value, it won't be persisted. 754 Type string `json:"type"` 755 756 // Dependencies are a list of things that this resource relies on 757 // existing to remain intact. For example: an AWS instance might 758 // depend on a subnet (which itself might depend on a VPC, and so 759 // on). 760 // 761 // Terraform uses this information to build valid destruction 762 // orders and to warn the user if they're destroying a resource that 763 // another resource depends on. 764 // 765 // Things can be put into this list that may not be managed by 766 // Terraform. If Terraform doesn't find a matching ID in the 767 // overall state, then it assumes it isn't managed and doesn't 768 // worry about it. 769 Dependencies []string `json:"depends_on,omitempty"` 770 771 // Primary is the current active instance for this resource. 772 // It can be replaced but only after a successful creation. 773 // This is the instances on which providers will act. 774 Primary *InstanceState `json:"primary"` 775 776 // Tainted is used to track any underlying instances that 777 // have been created but are in a bad or unknown state and 778 // need to be cleaned up subsequently. In the 779 // standard case, there is only at most a single instance. 780 // However, in pathological cases, it is possible for the number 781 // of instances to accumulate. 782 Tainted []*InstanceState `json:"tainted,omitempty"` 783 784 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 785 // Primary is Deposed to get it out of the way for the replacement Primary to 786 // be created by Apply. If the replacement Primary creates successfully, the 787 // Deposed instance is cleaned up. If there were problems creating the 788 // replacement, the instance remains in the Deposed list so it can be 789 // destroyed in a future run. Functionally, Deposed instances are very 790 // similar to Tainted instances in that Terraform is only tracking them in 791 // order to remember to destroy them. 792 Deposed []*InstanceState `json:"deposed,omitempty"` 793 794 // Provider is used when a resource is connected to a provider with an alias. 795 // If this string is empty, the resource is connected to the default provider, 796 // e.g. "aws_instance" goes with the "aws" provider. 797 // If the resource block contained a "provider" key, that value will be set here. 798 Provider string `json:"provider,omitempty"` 799 } 800 801 // Equal tests whether two ResourceStates are equal. 802 func (s *ResourceState) Equal(other *ResourceState) bool { 803 if s.Type != other.Type { 804 return false 805 } 806 807 if s.Provider != other.Provider { 808 return false 809 } 810 811 // Dependencies must be equal 812 sort.Strings(s.Dependencies) 813 sort.Strings(other.Dependencies) 814 if len(s.Dependencies) != len(other.Dependencies) { 815 return false 816 } 817 for i, d := range s.Dependencies { 818 if other.Dependencies[i] != d { 819 return false 820 } 821 } 822 823 // States must be equal 824 if !s.Primary.Equal(other.Primary) { 825 return false 826 } 827 828 // Tainted 829 taints := make(map[string]*InstanceState) 830 for _, t := range other.Tainted { 831 if t == nil { 832 continue 833 } 834 835 taints[t.ID] = t 836 } 837 for _, t := range s.Tainted { 838 if t == nil { 839 continue 840 } 841 842 otherT, ok := taints[t.ID] 843 if !ok { 844 return false 845 } 846 delete(taints, t.ID) 847 848 if !t.Equal(otherT) { 849 return false 850 } 851 } 852 853 // This means that we have stuff in other tainted that we don't 854 // have, so it is not equal. 855 if len(taints) > 0 { 856 return false 857 } 858 859 return true 860 } 861 862 // Taint takes the primary state and marks it as tainted. If there is no 863 // primary state, this does nothing. 864 func (r *ResourceState) Taint() { 865 // If there is no primary, nothing to do 866 if r.Primary == nil { 867 return 868 } 869 870 // Shuffle to the end of the taint list and set primary to nil 871 r.Tainted = append(r.Tainted, r.Primary) 872 r.Primary = nil 873 } 874 875 // Untaint takes a tainted InstanceState and marks it as primary. 876 // The index argument is used to select a single InstanceState from the 877 // array of Tainted when there are more than one. If index is -1, the 878 // first Tainted InstanceState will be untainted iff there is only one 879 // Tainted InstanceState. Index must be >= 0 to specify an InstanceState 880 // when Tainted has more than one member. 881 func (r *ResourceState) Untaint(index int) error { 882 if len(r.Tainted) == 0 { 883 return fmt.Errorf("Nothing to untaint.") 884 } 885 if r.Primary != nil { 886 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.") 887 } 888 if index == -1 && len(r.Tainted) > 1 { 889 return fmt.Errorf("There are %d tainted instances for this resource, please specify an index to select which one to untaint.", len(r.Tainted)) 890 } 891 if index == -1 { 892 index = 0 893 } 894 if index >= len(r.Tainted) { 895 return fmt.Errorf("There are %d tainted instances for this resource, the index specified (%d) is out of range.", len(r.Tainted), index) 896 } 897 898 // Perform the untaint 899 r.Primary = r.Tainted[index] 900 r.Tainted = append(r.Tainted[:index], r.Tainted[index+1:]...) 901 902 return nil 903 } 904 905 func (r *ResourceState) init() { 906 if r.Primary == nil { 907 r.Primary = &InstanceState{} 908 } 909 r.Primary.init() 910 } 911 912 func (r *ResourceState) deepcopy() *ResourceState { 913 if r == nil { 914 return nil 915 } 916 917 n := &ResourceState{ 918 Type: r.Type, 919 Dependencies: nil, 920 Primary: r.Primary.deepcopy(), 921 Tainted: nil, 922 Provider: r.Provider, 923 } 924 if r.Dependencies != nil { 925 n.Dependencies = make([]string, len(r.Dependencies)) 926 copy(n.Dependencies, r.Dependencies) 927 } 928 if r.Tainted != nil { 929 n.Tainted = make([]*InstanceState, 0, len(r.Tainted)) 930 for _, inst := range r.Tainted { 931 n.Tainted = append(n.Tainted, inst.deepcopy()) 932 } 933 } 934 if r.Deposed != nil { 935 n.Deposed = make([]*InstanceState, 0, len(r.Deposed)) 936 for _, inst := range r.Deposed { 937 n.Deposed = append(n.Deposed, inst.deepcopy()) 938 } 939 } 940 941 return n 942 } 943 944 // prune is used to remove any instances that are no longer required 945 func (r *ResourceState) prune() { 946 n := len(r.Tainted) 947 for i := 0; i < n; i++ { 948 inst := r.Tainted[i] 949 if inst == nil || inst.ID == "" { 950 copy(r.Tainted[i:], r.Tainted[i+1:]) 951 r.Tainted[n-1] = nil 952 n-- 953 i-- 954 } 955 } 956 957 r.Tainted = r.Tainted[:n] 958 959 n = len(r.Deposed) 960 for i := 0; i < n; i++ { 961 inst := r.Deposed[i] 962 if inst == nil || inst.ID == "" { 963 copy(r.Deposed[i:], r.Deposed[i+1:]) 964 r.Deposed[n-1] = nil 965 n-- 966 i-- 967 } 968 } 969 970 r.Deposed = r.Deposed[:n] 971 } 972 973 func (r *ResourceState) sort() { 974 sort.Strings(r.Dependencies) 975 } 976 977 func (s *ResourceState) GoString() string { 978 return fmt.Sprintf("*%#v", *s) 979 } 980 981 func (s *ResourceState) String() string { 982 var buf bytes.Buffer 983 buf.WriteString(fmt.Sprintf("Type = %s", s.Type)) 984 return buf.String() 985 } 986 987 // InstanceState is used to track the unique state information belonging 988 // to a given instance. 989 type InstanceState struct { 990 // A unique ID for this resource. This is opaque to Terraform 991 // and is only meant as a lookup mechanism for the providers. 992 ID string `json:"id"` 993 994 // Attributes are basic information about the resource. Any keys here 995 // are accessible in variable format within Terraform configurations: 996 // ${resourcetype.name.attribute}. 997 Attributes map[string]string `json:"attributes,omitempty"` 998 999 // Ephemeral is used to store any state associated with this instance 1000 // that is necessary for the Terraform run to complete, but is not 1001 // persisted to a state file. 1002 Ephemeral EphemeralState `json:"-"` 1003 1004 // Meta is a simple K/V map that is persisted to the State but otherwise 1005 // ignored by Terraform core. It's meant to be used for accounting by 1006 // external client code. 1007 Meta map[string]string `json:"meta,omitempty"` 1008 } 1009 1010 func (i *InstanceState) init() { 1011 if i.Attributes == nil { 1012 i.Attributes = make(map[string]string) 1013 } 1014 if i.Meta == nil { 1015 i.Meta = make(map[string]string) 1016 } 1017 i.Ephemeral.init() 1018 } 1019 1020 func (i *InstanceState) deepcopy() *InstanceState { 1021 if i == nil { 1022 return nil 1023 } 1024 n := &InstanceState{ 1025 ID: i.ID, 1026 Ephemeral: *i.Ephemeral.deepcopy(), 1027 } 1028 if i.Attributes != nil { 1029 n.Attributes = make(map[string]string, len(i.Attributes)) 1030 for k, v := range i.Attributes { 1031 n.Attributes[k] = v 1032 } 1033 } 1034 if i.Meta != nil { 1035 n.Meta = make(map[string]string, len(i.Meta)) 1036 for k, v := range i.Meta { 1037 n.Meta[k] = v 1038 } 1039 } 1040 return n 1041 } 1042 1043 func (s *InstanceState) Empty() bool { 1044 return s == nil || s.ID == "" 1045 } 1046 1047 func (s *InstanceState) Equal(other *InstanceState) bool { 1048 // Short circuit some nil checks 1049 if s == nil || other == nil { 1050 return s == other 1051 } 1052 1053 // IDs must be equal 1054 if s.ID != other.ID { 1055 return false 1056 } 1057 1058 // Attributes must be equal 1059 if len(s.Attributes) != len(other.Attributes) { 1060 return false 1061 } 1062 for k, v := range s.Attributes { 1063 otherV, ok := other.Attributes[k] 1064 if !ok { 1065 return false 1066 } 1067 1068 if v != otherV { 1069 return false 1070 } 1071 } 1072 1073 // Meta must be equal 1074 if len(s.Meta) != len(other.Meta) { 1075 return false 1076 } 1077 for k, v := range s.Meta { 1078 otherV, ok := other.Meta[k] 1079 if !ok { 1080 return false 1081 } 1082 1083 if v != otherV { 1084 return false 1085 } 1086 } 1087 1088 return true 1089 } 1090 1091 // MergeDiff takes a ResourceDiff and merges the attributes into 1092 // this resource state in order to generate a new state. This new 1093 // state can be used to provide updated attribute lookups for 1094 // variable interpolation. 1095 // 1096 // If the diff attribute requires computing the value, and hence 1097 // won't be available until apply, the value is replaced with the 1098 // computeID. 1099 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 1100 result := s.deepcopy() 1101 if result == nil { 1102 result = new(InstanceState) 1103 } 1104 result.init() 1105 1106 if s != nil { 1107 for k, v := range s.Attributes { 1108 result.Attributes[k] = v 1109 } 1110 } 1111 if d != nil { 1112 for k, diff := range d.Attributes { 1113 if diff.NewRemoved { 1114 delete(result.Attributes, k) 1115 continue 1116 } 1117 if diff.NewComputed { 1118 result.Attributes[k] = config.UnknownVariableValue 1119 continue 1120 } 1121 1122 result.Attributes[k] = diff.New 1123 } 1124 } 1125 1126 return result 1127 } 1128 1129 func (i *InstanceState) GoString() string { 1130 return fmt.Sprintf("*%#v", *i) 1131 } 1132 1133 func (i *InstanceState) String() string { 1134 var buf bytes.Buffer 1135 1136 if i == nil || i.ID == "" { 1137 return "<not created>" 1138 } 1139 1140 buf.WriteString(fmt.Sprintf("ID = %s\n", i.ID)) 1141 1142 attributes := i.Attributes 1143 attrKeys := make([]string, 0, len(attributes)) 1144 for ak, _ := range attributes { 1145 if ak == "id" { 1146 continue 1147 } 1148 1149 attrKeys = append(attrKeys, ak) 1150 } 1151 sort.Strings(attrKeys) 1152 1153 for _, ak := range attrKeys { 1154 av := attributes[ak] 1155 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1156 } 1157 1158 return buf.String() 1159 } 1160 1161 // EphemeralState is used for transient state that is only kept in-memory 1162 type EphemeralState struct { 1163 // ConnInfo is used for the providers to export information which is 1164 // used to connect to the resource for provisioning. For example, 1165 // this could contain SSH or WinRM credentials. 1166 ConnInfo map[string]string `json:"-"` 1167 } 1168 1169 func (e *EphemeralState) init() { 1170 if e.ConnInfo == nil { 1171 e.ConnInfo = make(map[string]string) 1172 } 1173 } 1174 1175 func (e *EphemeralState) deepcopy() *EphemeralState { 1176 if e == nil { 1177 return nil 1178 } 1179 n := &EphemeralState{} 1180 if e.ConnInfo != nil { 1181 n.ConnInfo = make(map[string]string, len(e.ConnInfo)) 1182 for k, v := range e.ConnInfo { 1183 n.ConnInfo[k] = v 1184 } 1185 } 1186 return n 1187 } 1188 1189 // ReadState reads a state structure out of a reader in the format that 1190 // was written by WriteState. 1191 func ReadState(src io.Reader) (*State, error) { 1192 buf := bufio.NewReader(src) 1193 1194 // Check if this is a V1 format 1195 start, err := buf.Peek(len(stateFormatMagic)) 1196 if err != nil { 1197 return nil, fmt.Errorf("Failed to check for magic bytes: %v", err) 1198 } 1199 if string(start) == stateFormatMagic { 1200 // Read the old state 1201 old, err := ReadStateV1(buf) 1202 if err != nil { 1203 return nil, err 1204 } 1205 return upgradeV1State(old) 1206 } 1207 1208 // Otherwise, must be V2 1209 dec := json.NewDecoder(buf) 1210 state := &State{} 1211 if err := dec.Decode(state); err != nil { 1212 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1213 } 1214 1215 // Check the version, this to ensure we don't read a future 1216 // version that we don't understand 1217 if state.Version > StateVersion { 1218 return nil, fmt.Errorf("State version %d not supported, please update.", 1219 state.Version) 1220 } 1221 1222 // Sort it 1223 state.sort() 1224 1225 return state, nil 1226 } 1227 1228 // WriteState writes a state somewhere in a binary format. 1229 func WriteState(d *State, dst io.Writer) error { 1230 // Make sure it is sorted 1231 d.sort() 1232 1233 // Ensure the version is set 1234 d.Version = StateVersion 1235 1236 // Encode the data in a human-friendly way 1237 data, err := json.MarshalIndent(d, "", " ") 1238 if err != nil { 1239 return fmt.Errorf("Failed to encode state: %s", err) 1240 } 1241 1242 // We append a newline to the data because MarshalIndent doesn't 1243 data = append(data, '\n') 1244 1245 // Write the data out to the dst 1246 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 1247 return fmt.Errorf("Failed to write state: %v", err) 1248 } 1249 1250 return nil 1251 } 1252 1253 // upgradeV1State is used to upgrade a V1 state representation 1254 // into a proper State representation. 1255 func upgradeV1State(old *StateV1) (*State, error) { 1256 s := &State{} 1257 s.init() 1258 1259 // Old format had no modules, so we migrate everything 1260 // directly into the root module. 1261 root := s.RootModule() 1262 1263 // Copy the outputs 1264 root.Outputs = old.Outputs 1265 1266 // Upgrade the resources 1267 for id, rs := range old.Resources { 1268 newRs := &ResourceState{ 1269 Type: rs.Type, 1270 } 1271 root.Resources[id] = newRs 1272 1273 // Migrate to an instance state 1274 instance := &InstanceState{ 1275 ID: rs.ID, 1276 Attributes: rs.Attributes, 1277 } 1278 1279 // Check if this is the primary or tainted instance 1280 if _, ok := old.Tainted[id]; ok { 1281 newRs.Tainted = append(newRs.Tainted, instance) 1282 } else { 1283 newRs.Primary = instance 1284 } 1285 1286 // Warn if the resource uses Extra, as there is 1287 // no upgrade path for this! Now totally deprecated. 1288 if len(rs.Extra) > 0 { 1289 log.Printf( 1290 "[WARN] Resource %s uses deprecated attribute "+ 1291 "storage, state file upgrade may be incomplete.", 1292 rs.ID, 1293 ) 1294 } 1295 } 1296 return s, nil 1297 } 1298 1299 // moduleStateSort implements sort.Interface to sort module states 1300 type moduleStateSort []*ModuleState 1301 1302 func (s moduleStateSort) Len() int { 1303 return len(s) 1304 } 1305 1306 func (s moduleStateSort) Less(i, j int) bool { 1307 a := s[i] 1308 b := s[j] 1309 1310 // If the lengths are different, then the shorter one always wins 1311 if len(a.Path) != len(b.Path) { 1312 return len(a.Path) < len(b.Path) 1313 } 1314 1315 // Otherwise, compare lexically 1316 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".") 1317 } 1318 1319 func (s moduleStateSort) Swap(i, j int) { 1320 s[i], s[j] = s[j], s[i] 1321 }