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