github.com/atsaki/terraform@v0.4.3-0.20150919165407-25bba5967654/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 return true 969 } 970 971 // MergeDiff takes a ResourceDiff and merges the attributes into 972 // this resource state in order to generate a new state. This new 973 // state can be used to provide updated attribute lookups for 974 // variable interpolation. 975 // 976 // If the diff attribute requires computing the value, and hence 977 // won't be available until apply, the value is replaced with the 978 // computeID. 979 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 980 result := s.deepcopy() 981 if result == nil { 982 result = new(InstanceState) 983 } 984 result.init() 985 986 if s != nil { 987 for k, v := range s.Attributes { 988 result.Attributes[k] = v 989 } 990 } 991 if d != nil { 992 for k, diff := range d.Attributes { 993 if diff.NewRemoved { 994 delete(result.Attributes, k) 995 continue 996 } 997 if diff.NewComputed { 998 result.Attributes[k] = config.UnknownVariableValue 999 continue 1000 } 1001 1002 result.Attributes[k] = diff.New 1003 } 1004 } 1005 1006 return result 1007 } 1008 1009 func (i *InstanceState) GoString() string { 1010 return fmt.Sprintf("*%#v", *i) 1011 } 1012 1013 func (i *InstanceState) String() string { 1014 var buf bytes.Buffer 1015 1016 if i == nil || i.ID == "" { 1017 return "<not created>" 1018 } 1019 1020 buf.WriteString(fmt.Sprintf("ID = %s\n", i.ID)) 1021 1022 attributes := i.Attributes 1023 attrKeys := make([]string, 0, len(attributes)) 1024 for ak, _ := range attributes { 1025 if ak == "id" { 1026 continue 1027 } 1028 1029 attrKeys = append(attrKeys, ak) 1030 } 1031 sort.Strings(attrKeys) 1032 1033 for _, ak := range attrKeys { 1034 av := attributes[ak] 1035 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1036 } 1037 1038 return buf.String() 1039 } 1040 1041 // EphemeralState is used for transient state that is only kept in-memory 1042 type EphemeralState struct { 1043 // ConnInfo is used for the providers to export information which is 1044 // used to connect to the resource for provisioning. For example, 1045 // this could contain SSH or WinRM credentials. 1046 ConnInfo map[string]string `json:"-"` 1047 } 1048 1049 func (e *EphemeralState) init() { 1050 if e.ConnInfo == nil { 1051 e.ConnInfo = make(map[string]string) 1052 } 1053 } 1054 1055 func (e *EphemeralState) deepcopy() *EphemeralState { 1056 if e == nil { 1057 return nil 1058 } 1059 n := &EphemeralState{} 1060 if e.ConnInfo != nil { 1061 n.ConnInfo = make(map[string]string, len(e.ConnInfo)) 1062 for k, v := range e.ConnInfo { 1063 n.ConnInfo[k] = v 1064 } 1065 } 1066 return n 1067 } 1068 1069 // ReadState reads a state structure out of a reader in the format that 1070 // was written by WriteState. 1071 func ReadState(src io.Reader) (*State, error) { 1072 buf := bufio.NewReader(src) 1073 1074 // Check if this is a V1 format 1075 start, err := buf.Peek(len(stateFormatMagic)) 1076 if err != nil { 1077 return nil, fmt.Errorf("Failed to check for magic bytes: %v", err) 1078 } 1079 if string(start) == stateFormatMagic { 1080 // Read the old state 1081 old, err := ReadStateV1(buf) 1082 if err != nil { 1083 return nil, err 1084 } 1085 return upgradeV1State(old) 1086 } 1087 1088 // Otherwise, must be V2 1089 dec := json.NewDecoder(buf) 1090 state := &State{} 1091 if err := dec.Decode(state); err != nil { 1092 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1093 } 1094 1095 // Check the version, this to ensure we don't read a future 1096 // version that we don't understand 1097 if state.Version > StateVersion { 1098 return nil, fmt.Errorf("State version %d not supported, please update.", 1099 state.Version) 1100 } 1101 1102 // Sort it 1103 state.sort() 1104 1105 return state, nil 1106 } 1107 1108 // WriteState writes a state somewhere in a binary format. 1109 func WriteState(d *State, dst io.Writer) error { 1110 // Make sure it is sorted 1111 d.sort() 1112 1113 // Ensure the version is set 1114 d.Version = StateVersion 1115 1116 // Encode the data in a human-friendly way 1117 data, err := json.MarshalIndent(d, "", " ") 1118 if err != nil { 1119 return fmt.Errorf("Failed to encode state: %s", err) 1120 } 1121 1122 // We append a newline to the data because MarshalIndent doesn't 1123 data = append(data, '\n') 1124 1125 // Write the data out to the dst 1126 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 1127 return fmt.Errorf("Failed to write state: %v", err) 1128 } 1129 1130 return nil 1131 } 1132 1133 // upgradeV1State is used to upgrade a V1 state representation 1134 // into a proper State representation. 1135 func upgradeV1State(old *StateV1) (*State, error) { 1136 s := &State{} 1137 s.init() 1138 1139 // Old format had no modules, so we migrate everything 1140 // directly into the root module. 1141 root := s.RootModule() 1142 1143 // Copy the outputs 1144 root.Outputs = old.Outputs 1145 1146 // Upgrade the resources 1147 for id, rs := range old.Resources { 1148 newRs := &ResourceState{ 1149 Type: rs.Type, 1150 } 1151 root.Resources[id] = newRs 1152 1153 // Migrate to an instance state 1154 instance := &InstanceState{ 1155 ID: rs.ID, 1156 Attributes: rs.Attributes, 1157 } 1158 1159 // Check if this is the primary or tainted instance 1160 if _, ok := old.Tainted[id]; ok { 1161 newRs.Tainted = append(newRs.Tainted, instance) 1162 } else { 1163 newRs.Primary = instance 1164 } 1165 1166 // Warn if the resource uses Extra, as there is 1167 // no upgrade path for this! Now totally deprecated. 1168 if len(rs.Extra) > 0 { 1169 log.Printf( 1170 "[WARN] Resource %s uses deprecated attribute "+ 1171 "storage, state file upgrade may be incomplete.", 1172 rs.ID, 1173 ) 1174 } 1175 } 1176 return s, nil 1177 } 1178 1179 // moduleStateSort implements sort.Interface to sort module states 1180 type moduleStateSort []*ModuleState 1181 1182 func (s moduleStateSort) Len() int { 1183 return len(s) 1184 } 1185 1186 func (s moduleStateSort) Less(i, j int) bool { 1187 a := s[i] 1188 b := s[j] 1189 1190 // If the lengths are different, then the shorter one always wins 1191 if len(a.Path) != len(b.Path) { 1192 return len(a.Path) < len(b.Path) 1193 } 1194 1195 // Otherwise, compare by last path element 1196 idx := len(a.Path) - 1 1197 return a.Path[idx] < b.Path[idx] 1198 } 1199 1200 func (s moduleStateSort) Swap(i, j int) { 1201 s[i], s[j] = s[j], s[i] 1202 }