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