github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/state.go (about) 1 package terraform 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "log" 12 "os" 13 "reflect" 14 "sort" 15 "strconv" 16 "strings" 17 "sync" 18 19 "github.com/hashicorp/errwrap" 20 multierror "github.com/hashicorp/go-multierror" 21 uuid "github.com/hashicorp/go-uuid" 22 version "github.com/hashicorp/go-version" 23 "github.com/hashicorp/hcl/v2" 24 "github.com/hashicorp/hcl/v2/hclsyntax" 25 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 26 "github.com/hashicorp/terraform-plugin-sdk/internal/configs" 27 "github.com/hashicorp/terraform-plugin-sdk/internal/configs/configschema" 28 "github.com/hashicorp/terraform-plugin-sdk/internal/configs/hcl2shim" 29 "github.com/hashicorp/terraform-plugin-sdk/internal/plans" 30 "github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags" 31 tfversion "github.com/hashicorp/terraform-plugin-sdk/internal/version" 32 "github.com/mitchellh/copystructure" 33 "github.com/zclconf/go-cty/cty" 34 ctyjson "github.com/zclconf/go-cty/cty/json" 35 ) 36 37 const ( 38 // StateVersion is the current version for our state file 39 StateVersion = 3 40 ) 41 42 // rootModulePath is the path of the root module 43 var rootModulePath = []string{"root"} 44 45 // normalizeModulePath transforms a legacy module path (which may or may not 46 // have a redundant "root" label at the start of it) into an 47 // addrs.ModuleInstance representing the same module. 48 // 49 // For legacy reasons, different parts of Terraform disagree about whether the 50 // root module has the path []string{} or []string{"root"}, and so this 51 // function accepts both and trims off the "root". An implication of this is 52 // that it's not possible to actually have a module call in the root module 53 // that is itself named "root", since that would be ambiguous. 54 // 55 // normalizeModulePath takes a raw module path and returns a path that 56 // has the rootModulePath prepended to it. If I could go back in time I 57 // would've never had a rootModulePath (empty path would be root). We can 58 // still fix this but thats a big refactor that my branch doesn't make sense 59 // for. Instead, this function normalizes paths. 60 func normalizeModulePath(p []string) addrs.ModuleInstance { 61 // FIXME: Remove this once everyone is using addrs.ModuleInstance. 62 63 if len(p) > 0 && p[0] == "root" { 64 p = p[1:] 65 } 66 67 ret := make(addrs.ModuleInstance, len(p)) 68 for i, name := range p { 69 // For now we don't actually support modules with multiple instances 70 // identified by keys, so we just treat every path element as a 71 // step with no key. 72 ret[i] = addrs.ModuleInstanceStep{ 73 Name: name, 74 } 75 } 76 return ret 77 } 78 79 // State keeps track of a snapshot state-of-the-world that Terraform 80 // can use to keep track of what real world resources it is actually 81 // managing. 82 type State struct { 83 // Version is the state file protocol version. 84 Version int `json:"version"` 85 86 // TFVersion is the version of Terraform that wrote this state. 87 TFVersion string `json:"terraform_version,omitempty"` 88 89 // Serial is incremented on any operation that modifies 90 // the State file. It is used to detect potentially conflicting 91 // updates. 92 Serial int64 `json:"serial"` 93 94 // Lineage is set when a new, blank state is created and then 95 // never updated. This allows us to determine whether the serials 96 // of two states can be meaningfully compared. 97 // Apart from the guarantee that collisions between two lineages 98 // are very unlikely, this value is opaque and external callers 99 // should only compare lineage strings byte-for-byte for equality. 100 Lineage string `json:"lineage"` 101 102 // Remote is used to track the metadata required to 103 // pull and push state files from a remote storage endpoint. 104 Remote *RemoteState `json:"remote,omitempty"` 105 106 // Backend tracks the configuration for the backend in use with 107 // this state. This is used to track any changes in the backend 108 // configuration. 109 Backend *BackendState `json:"backend,omitempty"` 110 111 // Modules contains all the modules in a breadth-first order 112 Modules []*ModuleState `json:"modules"` 113 114 mu sync.Mutex 115 116 // IsBinaryDrivenTest is a special flag that assists with a binary driver 117 // heuristic, it should not be set externally 118 IsBinaryDrivenTest bool 119 } 120 121 func (s *State) Lock() { s.mu.Lock() } 122 func (s *State) Unlock() { s.mu.Unlock() } 123 124 // NewState is used to initialize a blank state 125 func NewState() *State { 126 s := &State{} 127 s.init() 128 return s 129 } 130 131 // Children returns the ModuleStates that are direct children of 132 // the given path. If the path is "root", for example, then children 133 // returned might be "root.child", but not "root.child.grandchild". 134 func (s *State) Children(path []string) []*ModuleState { 135 s.Lock() 136 defer s.Unlock() 137 // TODO: test 138 139 return s.children(path) 140 } 141 142 func (s *State) children(path []string) []*ModuleState { 143 result := make([]*ModuleState, 0) 144 for _, m := range s.Modules { 145 if m == nil { 146 continue 147 } 148 149 if len(m.Path) != len(path)+1 { 150 continue 151 } 152 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 153 continue 154 } 155 156 result = append(result, m) 157 } 158 159 return result 160 } 161 162 // AddModule adds the module with the given path to the state. 163 // 164 // This should be the preferred method to add module states since it 165 // allows us to optimize lookups later as well as control sorting. 166 func (s *State) AddModule(path addrs.ModuleInstance) *ModuleState { 167 s.Lock() 168 defer s.Unlock() 169 170 return s.addModule(path) 171 } 172 173 func (s *State) addModule(path addrs.ModuleInstance) *ModuleState { 174 // check if the module exists first 175 m := s.moduleByPath(path) 176 if m != nil { 177 return m 178 } 179 180 // Lower the new-style address into a legacy-style address. 181 // This requires that none of the steps have instance keys, which is 182 // true for all addresses at the time of implementing this because 183 // "count" and "for_each" are not yet implemented for modules. 184 // For the purposes of state, the legacy address format also includes 185 // a redundant extra prefix element "root". It is important to include 186 // this because the "prune" method will remove any module that has a 187 // path length less than one, and other parts of the state code will 188 // trim off the first element indiscriminately. 189 legacyPath := make([]string, len(path)+1) 190 legacyPath[0] = "root" 191 for i, step := range path { 192 if step.InstanceKey != addrs.NoKey { 193 // FIXME: Once the rest of Terraform is ready to use count and 194 // for_each, remove all of this and just write the addrs.ModuleInstance 195 // value itself into the ModuleState. 196 panic("state cannot represent modules with count or for_each keys") 197 } 198 199 legacyPath[i+1] = step.Name 200 } 201 202 m = &ModuleState{Path: legacyPath} 203 m.init() 204 s.Modules = append(s.Modules, m) 205 s.sort() 206 return m 207 } 208 209 // ModuleByPath is used to lookup the module state for the given path. 210 // This should be the preferred lookup mechanism as it allows for future 211 // lookup optimizations. 212 func (s *State) ModuleByPath(path addrs.ModuleInstance) *ModuleState { 213 if s == nil { 214 return nil 215 } 216 s.Lock() 217 defer s.Unlock() 218 219 return s.moduleByPath(path) 220 } 221 222 func (s *State) moduleByPath(path addrs.ModuleInstance) *ModuleState { 223 for _, mod := range s.Modules { 224 if mod == nil { 225 continue 226 } 227 if mod.Path == nil { 228 panic("missing module path") 229 } 230 modPath := normalizeModulePath(mod.Path) 231 if modPath.String() == path.String() { 232 return mod 233 } 234 } 235 return nil 236 } 237 238 // Empty returns true if the state is empty. 239 func (s *State) Empty() bool { 240 if s == nil { 241 return true 242 } 243 s.Lock() 244 defer s.Unlock() 245 246 return len(s.Modules) == 0 247 } 248 249 // HasResources returns true if the state contains any resources. 250 // 251 // This is similar to !s.Empty, but returns true also in the case where the 252 // state has modules but all of them are devoid of resources. 253 func (s *State) HasResources() bool { 254 if s.Empty() { 255 return false 256 } 257 258 for _, mod := range s.Modules { 259 if len(mod.Resources) > 0 { 260 return true 261 } 262 } 263 264 return false 265 } 266 267 // IsRemote returns true if State represents a state that exists and is 268 // remote. 269 func (s *State) IsRemote() bool { 270 if s == nil { 271 return false 272 } 273 s.Lock() 274 defer s.Unlock() 275 276 if s.Remote == nil { 277 return false 278 } 279 if s.Remote.Type == "" { 280 return false 281 } 282 283 return true 284 } 285 286 // Validate validates the integrity of this state file. 287 // 288 // Certain properties of the statefile are expected by Terraform in order 289 // to behave properly. The core of Terraform will assume that once it 290 // receives a State structure that it has been validated. This validation 291 // check should be called to ensure that. 292 // 293 // If this returns an error, then the user should be notified. The error 294 // response will include detailed information on the nature of the error. 295 func (s *State) Validate() error { 296 s.Lock() 297 defer s.Unlock() 298 299 var result error 300 301 // !!!! FOR DEVELOPERS !!!! 302 // 303 // Any errors returned from this Validate function will BLOCK TERRAFORM 304 // from loading a state file. Therefore, this should only contain checks 305 // that are only resolvable through manual intervention. 306 // 307 // !!!! FOR DEVELOPERS !!!! 308 309 // Make sure there are no duplicate module states. We open a new 310 // block here so we can use basic variable names and future validations 311 // can do the same. 312 { 313 found := make(map[string]struct{}) 314 for _, ms := range s.Modules { 315 if ms == nil { 316 continue 317 } 318 319 key := strings.Join(ms.Path, ".") 320 if _, ok := found[key]; ok { 321 result = multierror.Append(result, fmt.Errorf( 322 strings.TrimSpace(stateValidateErrMultiModule), key)) 323 continue 324 } 325 326 found[key] = struct{}{} 327 } 328 } 329 330 return result 331 } 332 333 // Remove removes the item in the state at the given address, returning 334 // any errors that may have occurred. 335 // 336 // If the address references a module state or resource, it will delete 337 // all children as well. To check what will be deleted, use a StateFilter 338 // first. 339 func (s *State) Remove(addr ...string) error { 340 s.Lock() 341 defer s.Unlock() 342 343 // Filter out what we need to delete 344 filter := &StateFilter{State: s} 345 results, err := filter.Filter(addr...) 346 if err != nil { 347 return err 348 } 349 350 // If we have no results, just exit early, we're not going to do anything. 351 // While what happens below is fairly fast, this is an important early 352 // exit since the prune below might modify the state more and we don't 353 // want to modify the state if we don't have to. 354 if len(results) == 0 { 355 return nil 356 } 357 358 // Go through each result and grab what we need 359 removed := make(map[interface{}]struct{}) 360 for _, r := range results { 361 // Convert the path to our own type 362 path := append([]string{"root"}, r.Path...) 363 364 // If we removed this already, then ignore 365 if _, ok := removed[r.Value]; ok { 366 continue 367 } 368 369 // If we removed the parent already, then ignore 370 if r.Parent != nil { 371 if _, ok := removed[r.Parent.Value]; ok { 372 continue 373 } 374 } 375 376 // Add this to the removed list 377 removed[r.Value] = struct{}{} 378 379 switch v := r.Value.(type) { 380 case *ModuleState: 381 s.removeModule(path, v) 382 case *ResourceState: 383 s.removeResource(path, v) 384 case *InstanceState: 385 s.removeInstance(path, r.Parent.Value.(*ResourceState), v) 386 default: 387 return fmt.Errorf("unknown type to delete: %T", r.Value) 388 } 389 } 390 391 // Prune since the removal functions often do the bare minimum to 392 // remove a thing and may leave around dangling empty modules, resources, 393 // etc. Prune will clean that all up. 394 s.prune() 395 396 return nil 397 } 398 399 func (s *State) removeModule(path []string, v *ModuleState) { 400 for i, m := range s.Modules { 401 if m == v { 402 s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil 403 return 404 } 405 } 406 } 407 408 func (s *State) removeResource(path []string, v *ResourceState) { 409 // Get the module this resource lives in. If it doesn't exist, we're done. 410 mod := s.moduleByPath(normalizeModulePath(path)) 411 if mod == nil { 412 return 413 } 414 415 // Find this resource. This is a O(N) lookup when if we had the key 416 // it could be O(1) but even with thousands of resources this shouldn't 417 // matter right now. We can easily up performance here when the time comes. 418 for k, r := range mod.Resources { 419 if r == v { 420 // Found it 421 delete(mod.Resources, k) 422 return 423 } 424 } 425 } 426 427 func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) { 428 // Go through the resource and find the instance that matches this 429 // (if any) and remove it. 430 431 // Check primary 432 if r.Primary == v { 433 r.Primary = nil 434 return 435 } 436 437 // Check lists 438 lists := [][]*InstanceState{r.Deposed} 439 for _, is := range lists { 440 for i, instance := range is { 441 if instance == v { 442 // Found it, remove it 443 is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil 444 445 // Done 446 return 447 } 448 } 449 } 450 } 451 452 // RootModule returns the ModuleState for the root module 453 func (s *State) RootModule() *ModuleState { 454 root := s.ModuleByPath(addrs.RootModuleInstance) 455 if root == nil { 456 panic("missing root module") 457 } 458 return root 459 } 460 461 // Equal tests if one state is equal to another. 462 func (s *State) Equal(other *State) bool { 463 // If one is nil, we do a direct check 464 if s == nil || other == nil { 465 return s == other 466 } 467 468 s.Lock() 469 defer s.Unlock() 470 return s.equal(other) 471 } 472 473 func (s *State) equal(other *State) bool { 474 if s == nil || other == nil { 475 return s == other 476 } 477 478 // If the versions are different, they're certainly not equal 479 if s.Version != other.Version { 480 return false 481 } 482 483 // If any of the modules are not equal, then this state isn't equal 484 if len(s.Modules) != len(other.Modules) { 485 return false 486 } 487 for _, m := range s.Modules { 488 // This isn't very optimal currently but works. 489 otherM := other.moduleByPath(normalizeModulePath(m.Path)) 490 if otherM == nil { 491 return false 492 } 493 494 // If they're not equal, then we're not equal! 495 if !m.Equal(otherM) { 496 return false 497 } 498 } 499 500 return true 501 } 502 503 // MarshalEqual is similar to Equal but provides a stronger definition of 504 // "equal", where two states are equal if and only if their serialized form 505 // is byte-for-byte identical. 506 // 507 // This is primarily useful for callers that are trying to save snapshots 508 // of state to persistent storage, allowing them to detect when a new 509 // snapshot must be taken. 510 // 511 // Note that the serial number and lineage are included in the serialized form, 512 // so it's the caller's responsibility to properly manage these attributes 513 // so that this method is only called on two states that have the same 514 // serial and lineage, unless detecting such differences is desired. 515 func (s *State) MarshalEqual(other *State) bool { 516 if s == nil && other == nil { 517 return true 518 } else if s == nil || other == nil { 519 return false 520 } 521 522 recvBuf := &bytes.Buffer{} 523 otherBuf := &bytes.Buffer{} 524 525 err := WriteState(s, recvBuf) 526 if err != nil { 527 // should never happen, since we're writing to a buffer 528 panic(err) 529 } 530 531 err = WriteState(other, otherBuf) 532 if err != nil { 533 // should never happen, since we're writing to a buffer 534 panic(err) 535 } 536 537 return bytes.Equal(recvBuf.Bytes(), otherBuf.Bytes()) 538 } 539 540 type StateAgeComparison int 541 542 const ( 543 StateAgeEqual StateAgeComparison = 0 544 StateAgeReceiverNewer StateAgeComparison = 1 545 StateAgeReceiverOlder StateAgeComparison = -1 546 ) 547 548 // CompareAges compares one state with another for which is "older". 549 // 550 // This is a simple check using the state's serial, and is thus only as 551 // reliable as the serial itself. In the normal case, only one state 552 // exists for a given combination of lineage/serial, but Terraform 553 // does not guarantee this and so the result of this method should be 554 // used with care. 555 // 556 // Returns an integer that is negative if the receiver is older than 557 // the argument, positive if the converse, and zero if they are equal. 558 // An error is returned if the two states are not of the same lineage, 559 // in which case the integer returned has no meaning. 560 func (s *State) CompareAges(other *State) (StateAgeComparison, error) { 561 // nil states are "older" than actual states 562 switch { 563 case s != nil && other == nil: 564 return StateAgeReceiverNewer, nil 565 case s == nil && other != nil: 566 return StateAgeReceiverOlder, nil 567 case s == nil && other == nil: 568 return StateAgeEqual, nil 569 } 570 571 if !s.SameLineage(other) { 572 return StateAgeEqual, fmt.Errorf( 573 "can't compare two states of differing lineage", 574 ) 575 } 576 577 s.Lock() 578 defer s.Unlock() 579 580 switch { 581 case s.Serial < other.Serial: 582 return StateAgeReceiverOlder, nil 583 case s.Serial > other.Serial: 584 return StateAgeReceiverNewer, nil 585 default: 586 return StateAgeEqual, nil 587 } 588 } 589 590 // SameLineage returns true only if the state given in argument belongs 591 // to the same "lineage" of states as the receiver. 592 func (s *State) SameLineage(other *State) bool { 593 s.Lock() 594 defer s.Unlock() 595 596 // If one of the states has no lineage then it is assumed to predate 597 // this concept, and so we'll accept it as belonging to any lineage 598 // so that a lineage string can be assigned to newer versions 599 // without breaking compatibility with older versions. 600 if s.Lineage == "" || other.Lineage == "" { 601 return true 602 } 603 604 return s.Lineage == other.Lineage 605 } 606 607 // DeepCopy performs a deep copy of the state structure and returns 608 // a new structure. 609 func (s *State) DeepCopy() *State { 610 if s == nil { 611 return nil 612 } 613 614 copy, err := copystructure.Config{Lock: true}.Copy(s) 615 if err != nil { 616 panic(err) 617 } 618 619 return copy.(*State) 620 } 621 622 // FromFutureTerraform checks if this state was written by a Terraform 623 // version from the future. 624 func (s *State) FromFutureTerraform() bool { 625 s.Lock() 626 defer s.Unlock() 627 628 // No TF version means it is certainly from the past 629 if s.TFVersion == "" { 630 return false 631 } 632 633 v := version.Must(version.NewVersion(s.TFVersion)) 634 return tfversion.SemVer.LessThan(v) 635 } 636 637 func (s *State) Init() { 638 s.Lock() 639 defer s.Unlock() 640 s.init() 641 } 642 643 func (s *State) init() { 644 if s.Version == 0 { 645 s.Version = StateVersion 646 } 647 648 if s.moduleByPath(addrs.RootModuleInstance) == nil { 649 s.addModule(addrs.RootModuleInstance) 650 } 651 s.ensureHasLineage() 652 653 for _, mod := range s.Modules { 654 if mod != nil { 655 mod.init() 656 } 657 } 658 659 if s.Remote != nil { 660 s.Remote.init() 661 } 662 663 } 664 665 func (s *State) EnsureHasLineage() { 666 s.Lock() 667 defer s.Unlock() 668 669 s.ensureHasLineage() 670 } 671 672 func (s *State) ensureHasLineage() { 673 if s.Lineage == "" { 674 lineage, err := uuid.GenerateUUID() 675 if err != nil { 676 panic(fmt.Errorf("Failed to generate lineage: %v", err)) 677 } 678 s.Lineage = lineage 679 log.Printf("[DEBUG] New state was assigned lineage %q\n", s.Lineage) 680 } else { 681 log.Printf("[TRACE] Preserving existing state lineage %q\n", s.Lineage) 682 } 683 } 684 685 // AddModuleState insert this module state and override any existing ModuleState 686 func (s *State) AddModuleState(mod *ModuleState) { 687 mod.init() 688 s.Lock() 689 defer s.Unlock() 690 691 s.addModuleState(mod) 692 } 693 694 func (s *State) addModuleState(mod *ModuleState) { 695 for i, m := range s.Modules { 696 if reflect.DeepEqual(m.Path, mod.Path) { 697 s.Modules[i] = mod 698 return 699 } 700 } 701 702 s.Modules = append(s.Modules, mod) 703 s.sort() 704 } 705 706 // prune is used to remove any resources that are no longer required 707 func (s *State) prune() { 708 if s == nil { 709 return 710 } 711 712 // Filter out empty modules. 713 // A module is always assumed to have a path, and it's length isn't always 714 // bounds checked later on. Modules may be "emptied" during destroy, but we 715 // never want to store those in the state. 716 for i := 0; i < len(s.Modules); i++ { 717 if s.Modules[i] == nil || len(s.Modules[i].Path) == 0 { 718 s.Modules = append(s.Modules[:i], s.Modules[i+1:]...) 719 i-- 720 } 721 } 722 723 for _, mod := range s.Modules { 724 mod.prune() 725 } 726 if s.Remote != nil && s.Remote.Empty() { 727 s.Remote = nil 728 } 729 } 730 731 // sort sorts the modules 732 func (s *State) sort() { 733 sort.Sort(moduleStateSort(s.Modules)) 734 735 // Allow modules to be sorted 736 for _, m := range s.Modules { 737 if m != nil { 738 m.sort() 739 } 740 } 741 } 742 743 func (s *State) String() string { 744 if s == nil { 745 return "<nil>" 746 } 747 s.Lock() 748 defer s.Unlock() 749 750 var buf bytes.Buffer 751 for _, m := range s.Modules { 752 mStr := m.String() 753 754 // If we're the root module, we just write the output directly. 755 if reflect.DeepEqual(m.Path, rootModulePath) { 756 buf.WriteString(mStr + "\n") 757 continue 758 } 759 760 buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], "."))) 761 762 s := bufio.NewScanner(strings.NewReader(mStr)) 763 for s.Scan() { 764 text := s.Text() 765 if text != "" { 766 text = " " + text 767 } 768 769 buf.WriteString(fmt.Sprintf("%s\n", text)) 770 } 771 } 772 773 return strings.TrimSpace(buf.String()) 774 } 775 776 // BackendState stores the configuration to connect to a remote backend. 777 type BackendState struct { 778 Type string `json:"type"` // Backend type 779 ConfigRaw json.RawMessage `json:"config"` // Backend raw config 780 Hash uint64 `json:"hash"` // Hash of portion of configuration from config files 781 } 782 783 // Empty returns true if BackendState has no state. 784 func (s *BackendState) Empty() bool { 785 return s == nil || s.Type == "" 786 } 787 788 // Config decodes the type-specific configuration object using the provided 789 // schema and returns the result as a cty.Value. 790 // 791 // An error is returned if the stored configuration does not conform to the 792 // given schema. 793 func (s *BackendState) Config(schema *configschema.Block) (cty.Value, error) { 794 ty := schema.ImpliedType() 795 if s == nil { 796 return cty.NullVal(ty), nil 797 } 798 return ctyjson.Unmarshal(s.ConfigRaw, ty) 799 } 800 801 // SetConfig replaces (in-place) the type-specific configuration object using 802 // the provided value and associated schema. 803 // 804 // An error is returned if the given value does not conform to the implied 805 // type of the schema. 806 func (s *BackendState) SetConfig(val cty.Value, schema *configschema.Block) error { 807 ty := schema.ImpliedType() 808 buf, err := ctyjson.Marshal(val, ty) 809 if err != nil { 810 return err 811 } 812 s.ConfigRaw = buf 813 return nil 814 } 815 816 // ForPlan produces an alternative representation of the reciever that is 817 // suitable for storing in a plan. The current workspace must additionally 818 // be provided, to be stored alongside the backend configuration. 819 // 820 // The backend configuration schema is required in order to properly 821 // encode the backend-specific configuration settings. 822 func (s *BackendState) ForPlan(schema *configschema.Block, workspaceName string) (*plans.Backend, error) { 823 if s == nil { 824 return nil, nil 825 } 826 827 configVal, err := s.Config(schema) 828 if err != nil { 829 return nil, errwrap.Wrapf("failed to decode backend config: {{err}}", err) 830 } 831 return plans.NewBackend(s.Type, configVal, schema, workspaceName) 832 } 833 834 // RemoteState is used to track the information about a remote 835 // state store that we push/pull state to. 836 type RemoteState struct { 837 // Type controls the client we use for the remote state 838 Type string `json:"type"` 839 840 // Config is used to store arbitrary configuration that 841 // is type specific 842 Config map[string]string `json:"config"` 843 844 mu sync.Mutex 845 } 846 847 func (s *RemoteState) Lock() { s.mu.Lock() } 848 func (s *RemoteState) Unlock() { s.mu.Unlock() } 849 850 func (r *RemoteState) init() { 851 r.Lock() 852 defer r.Unlock() 853 854 if r.Config == nil { 855 r.Config = make(map[string]string) 856 } 857 } 858 859 func (r *RemoteState) Empty() bool { 860 if r == nil { 861 return true 862 } 863 r.Lock() 864 defer r.Unlock() 865 866 return r.Type == "" 867 } 868 869 func (r *RemoteState) Equals(other *RemoteState) bool { 870 r.Lock() 871 defer r.Unlock() 872 873 if r.Type != other.Type { 874 return false 875 } 876 if len(r.Config) != len(other.Config) { 877 return false 878 } 879 for k, v := range r.Config { 880 if other.Config[k] != v { 881 return false 882 } 883 } 884 return true 885 } 886 887 // OutputState is used to track the state relevant to a single output. 888 type OutputState struct { 889 // Sensitive describes whether the output is considered sensitive, 890 // which may lead to masking the value on screen in some cases. 891 Sensitive bool `json:"sensitive"` 892 // Type describes the structure of Value. Valid values are "string", 893 // "map" and "list" 894 Type string `json:"type"` 895 // Value contains the value of the output, in the structure described 896 // by the Type field. 897 Value interface{} `json:"value"` 898 899 mu sync.Mutex 900 } 901 902 func (s *OutputState) Lock() { s.mu.Lock() } 903 func (s *OutputState) Unlock() { s.mu.Unlock() } 904 905 func (s *OutputState) String() string { 906 return fmt.Sprintf("%#v", s.Value) 907 } 908 909 // Equal compares two OutputState structures for equality. nil values are 910 // considered equal. 911 func (s *OutputState) Equal(other *OutputState) bool { 912 if s == nil && other == nil { 913 return true 914 } 915 916 if s == nil || other == nil { 917 return false 918 } 919 s.Lock() 920 defer s.Unlock() 921 922 if s.Type != other.Type { 923 return false 924 } 925 926 if s.Sensitive != other.Sensitive { 927 return false 928 } 929 930 if !reflect.DeepEqual(s.Value, other.Value) { 931 return false 932 } 933 934 return true 935 } 936 937 // ModuleState is used to track all the state relevant to a single 938 // module. Previous to Terraform 0.3, all state belonged to the "root" 939 // module. 940 type ModuleState struct { 941 // Path is the import path from the root module. Modules imports are 942 // always disjoint, so the path represents amodule tree 943 Path []string `json:"path"` 944 945 // Locals are kept only transiently in-memory, because we can always 946 // re-compute them. 947 Locals map[string]interface{} `json:"-"` 948 949 // Outputs declared by the module and maintained for each module 950 // even though only the root module technically needs to be kept. 951 // This allows operators to inspect values at the boundaries. 952 Outputs map[string]*OutputState `json:"outputs"` 953 954 // Resources is a mapping of the logically named resource to 955 // the state of the resource. Each resource may actually have 956 // N instances underneath, although a user only needs to think 957 // about the 1:1 case. 958 Resources map[string]*ResourceState `json:"resources"` 959 960 // Dependencies are a list of things that this module relies on 961 // existing to remain intact. For example: an module may depend 962 // on a VPC ID given by an aws_vpc resource. 963 // 964 // Terraform uses this information to build valid destruction 965 // orders and to warn the user if they're destroying a module that 966 // another resource depends on. 967 // 968 // Things can be put into this list that may not be managed by 969 // Terraform. If Terraform doesn't find a matching ID in the 970 // overall state, then it assumes it isn't managed and doesn't 971 // worry about it. 972 Dependencies []string `json:"depends_on"` 973 974 mu sync.Mutex 975 } 976 977 func (s *ModuleState) Lock() { s.mu.Lock() } 978 func (s *ModuleState) Unlock() { s.mu.Unlock() } 979 980 // Equal tests whether one module state is equal to another. 981 func (m *ModuleState) Equal(other *ModuleState) bool { 982 m.Lock() 983 defer m.Unlock() 984 985 // Paths must be equal 986 if !reflect.DeepEqual(m.Path, other.Path) { 987 return false 988 } 989 990 // Outputs must be equal 991 if len(m.Outputs) != len(other.Outputs) { 992 return false 993 } 994 for k, v := range m.Outputs { 995 if !other.Outputs[k].Equal(v) { 996 return false 997 } 998 } 999 1000 // Dependencies must be equal. This sorts these in place but 1001 // this shouldn't cause any problems. 1002 sort.Strings(m.Dependencies) 1003 sort.Strings(other.Dependencies) 1004 if len(m.Dependencies) != len(other.Dependencies) { 1005 return false 1006 } 1007 for i, d := range m.Dependencies { 1008 if other.Dependencies[i] != d { 1009 return false 1010 } 1011 } 1012 1013 // Resources must be equal 1014 if len(m.Resources) != len(other.Resources) { 1015 return false 1016 } 1017 for k, r := range m.Resources { 1018 otherR, ok := other.Resources[k] 1019 if !ok { 1020 return false 1021 } 1022 1023 if !r.Equal(otherR) { 1024 return false 1025 } 1026 } 1027 1028 return true 1029 } 1030 1031 // IsRoot says whether or not this module diff is for the root module. 1032 func (m *ModuleState) IsRoot() bool { 1033 m.Lock() 1034 defer m.Unlock() 1035 return reflect.DeepEqual(m.Path, rootModulePath) 1036 } 1037 1038 // IsDescendent returns true if other is a descendent of this module. 1039 func (m *ModuleState) IsDescendent(other *ModuleState) bool { 1040 m.Lock() 1041 defer m.Unlock() 1042 1043 i := len(m.Path) 1044 return len(other.Path) > i && reflect.DeepEqual(other.Path[:i], m.Path) 1045 } 1046 1047 // Orphans returns a list of keys of resources that are in the State 1048 // but aren't present in the configuration itself. Hence, these keys 1049 // represent the state of resources that are orphans. 1050 func (m *ModuleState) Orphans(c *configs.Module) []addrs.ResourceInstance { 1051 m.Lock() 1052 defer m.Unlock() 1053 1054 inConfig := make(map[string]struct{}) 1055 if c != nil { 1056 for _, r := range c.ManagedResources { 1057 inConfig[r.Addr().String()] = struct{}{} 1058 } 1059 for _, r := range c.DataResources { 1060 inConfig[r.Addr().String()] = struct{}{} 1061 } 1062 } 1063 1064 var result []addrs.ResourceInstance 1065 for k := range m.Resources { 1066 // Since we've not yet updated state to use our new address format, 1067 // we need to do some shimming here. 1068 legacyAddr, err := parseResourceAddressInternal(k) 1069 if err != nil { 1070 // Suggests that the user tampered with the state, since we always 1071 // generate valid internal addresses. 1072 log.Printf("ModuleState has invalid resource key %q. Ignoring.", k) 1073 continue 1074 } 1075 1076 addr := legacyAddr.AbsResourceInstanceAddr().Resource 1077 compareKey := addr.Resource.String() // compare by resource address, ignoring instance key 1078 if _, exists := inConfig[compareKey]; !exists { 1079 result = append(result, addr) 1080 } 1081 } 1082 return result 1083 } 1084 1085 // RemovedOutputs returns a list of outputs that are in the State but aren't 1086 // present in the configuration itself. 1087 func (s *ModuleState) RemovedOutputs(outputs map[string]*configs.Output) []addrs.OutputValue { 1088 if outputs == nil { 1089 // If we got no output map at all then we'll just treat our set of 1090 // configured outputs as empty, since that suggests that they've all 1091 // been removed by removing their containing module. 1092 outputs = make(map[string]*configs.Output) 1093 } 1094 1095 s.Lock() 1096 defer s.Unlock() 1097 1098 var ret []addrs.OutputValue 1099 for n := range s.Outputs { 1100 if _, declared := outputs[n]; !declared { 1101 ret = append(ret, addrs.OutputValue{ 1102 Name: n, 1103 }) 1104 } 1105 } 1106 1107 return ret 1108 } 1109 1110 // View returns a view with the given resource prefix. 1111 func (m *ModuleState) View(id string) *ModuleState { 1112 if m == nil { 1113 return m 1114 } 1115 1116 r := m.deepcopy() 1117 for k := range r.Resources { 1118 if id == k || strings.HasPrefix(k, id+".") { 1119 continue 1120 } 1121 1122 delete(r.Resources, k) 1123 } 1124 1125 return r 1126 } 1127 1128 func (m *ModuleState) init() { 1129 m.Lock() 1130 defer m.Unlock() 1131 1132 if m.Path == nil { 1133 m.Path = []string{} 1134 } 1135 if m.Outputs == nil { 1136 m.Outputs = make(map[string]*OutputState) 1137 } 1138 if m.Resources == nil { 1139 m.Resources = make(map[string]*ResourceState) 1140 } 1141 1142 if m.Dependencies == nil { 1143 m.Dependencies = make([]string, 0) 1144 } 1145 1146 for _, rs := range m.Resources { 1147 rs.init() 1148 } 1149 } 1150 1151 func (m *ModuleState) deepcopy() *ModuleState { 1152 if m == nil { 1153 return nil 1154 } 1155 1156 stateCopy, err := copystructure.Config{Lock: true}.Copy(m) 1157 if err != nil { 1158 panic(err) 1159 } 1160 1161 return stateCopy.(*ModuleState) 1162 } 1163 1164 // prune is used to remove any resources that are no longer required 1165 func (m *ModuleState) prune() { 1166 m.Lock() 1167 defer m.Unlock() 1168 1169 for k, v := range m.Resources { 1170 if v == nil || (v.Primary == nil || v.Primary.ID == "") && len(v.Deposed) == 0 { 1171 delete(m.Resources, k) 1172 continue 1173 } 1174 1175 v.prune() 1176 } 1177 1178 for k, v := range m.Outputs { 1179 if v.Value == hcl2shim.UnknownVariableValue { 1180 delete(m.Outputs, k) 1181 } 1182 } 1183 1184 m.Dependencies = uniqueStrings(m.Dependencies) 1185 } 1186 1187 func (m *ModuleState) sort() { 1188 for _, v := range m.Resources { 1189 v.sort() 1190 } 1191 } 1192 1193 func (m *ModuleState) String() string { 1194 m.Lock() 1195 defer m.Unlock() 1196 1197 var buf bytes.Buffer 1198 1199 if len(m.Resources) == 0 { 1200 buf.WriteString("<no state>") 1201 } 1202 1203 names := make([]string, 0, len(m.Resources)) 1204 for name := range m.Resources { 1205 names = append(names, name) 1206 } 1207 1208 sort.Sort(resourceNameSort(names)) 1209 1210 for _, k := range names { 1211 rs := m.Resources[k] 1212 var id string 1213 if rs.Primary != nil { 1214 id = rs.Primary.ID 1215 } 1216 if id == "" { 1217 id = "<not created>" 1218 } 1219 1220 taintStr := "" 1221 if rs.Primary.Tainted { 1222 taintStr = " (tainted)" 1223 } 1224 1225 deposedStr := "" 1226 if len(rs.Deposed) > 0 { 1227 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed)) 1228 } 1229 1230 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr)) 1231 buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) 1232 if rs.Provider != "" { 1233 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider)) 1234 } 1235 1236 var attributes map[string]string 1237 if rs.Primary != nil { 1238 attributes = rs.Primary.Attributes 1239 } 1240 attrKeys := make([]string, 0, len(attributes)) 1241 for ak := range attributes { 1242 if ak == "id" { 1243 continue 1244 } 1245 1246 attrKeys = append(attrKeys, ak) 1247 } 1248 1249 sort.Strings(attrKeys) 1250 1251 for _, ak := range attrKeys { 1252 av := attributes[ak] 1253 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) 1254 } 1255 1256 for idx, t := range rs.Deposed { 1257 taintStr := "" 1258 if t.Tainted { 1259 taintStr = " (tainted)" 1260 } 1261 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s%s\n", idx+1, t.ID, taintStr)) 1262 } 1263 1264 if len(rs.Dependencies) > 0 { 1265 buf.WriteString(fmt.Sprintf("\n Dependencies:\n")) 1266 for _, dep := range rs.Dependencies { 1267 buf.WriteString(fmt.Sprintf(" %s\n", dep)) 1268 } 1269 } 1270 } 1271 1272 if len(m.Outputs) > 0 { 1273 buf.WriteString("\nOutputs:\n\n") 1274 1275 ks := make([]string, 0, len(m.Outputs)) 1276 for k := range m.Outputs { 1277 ks = append(ks, k) 1278 } 1279 1280 sort.Strings(ks) 1281 1282 for _, k := range ks { 1283 v := m.Outputs[k] 1284 switch vTyped := v.Value.(type) { 1285 case string: 1286 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 1287 case []interface{}: 1288 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 1289 case map[string]interface{}: 1290 var mapKeys []string 1291 for key := range vTyped { 1292 mapKeys = append(mapKeys, key) 1293 } 1294 sort.Strings(mapKeys) 1295 1296 var mapBuf bytes.Buffer 1297 mapBuf.WriteString("{") 1298 for _, key := range mapKeys { 1299 mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key])) 1300 } 1301 mapBuf.WriteString("}") 1302 1303 buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String())) 1304 } 1305 } 1306 } 1307 1308 return buf.String() 1309 } 1310 1311 func (m *ModuleState) Empty() bool { 1312 return len(m.Locals) == 0 && len(m.Outputs) == 0 && len(m.Resources) == 0 1313 } 1314 1315 // ResourceStateKey is a structured representation of the key used for the 1316 // ModuleState.Resources mapping 1317 type ResourceStateKey struct { 1318 Name string 1319 Type string 1320 Mode ResourceMode 1321 Index int 1322 } 1323 1324 // Equal determines whether two ResourceStateKeys are the same 1325 func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool { 1326 if rsk == nil || other == nil { 1327 return false 1328 } 1329 if rsk.Mode != other.Mode { 1330 return false 1331 } 1332 if rsk.Type != other.Type { 1333 return false 1334 } 1335 if rsk.Name != other.Name { 1336 return false 1337 } 1338 if rsk.Index != other.Index { 1339 return false 1340 } 1341 return true 1342 } 1343 1344 func (rsk *ResourceStateKey) String() string { 1345 if rsk == nil { 1346 return "" 1347 } 1348 var prefix string 1349 switch rsk.Mode { 1350 case ManagedResourceMode: 1351 prefix = "" 1352 case DataResourceMode: 1353 prefix = "data." 1354 default: 1355 panic(fmt.Errorf("unknown resource mode %s", rsk.Mode)) 1356 } 1357 if rsk.Index == -1 { 1358 return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name) 1359 } 1360 return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index) 1361 } 1362 1363 // ParseResourceStateKey accepts a key in the format used by 1364 // ModuleState.Resources and returns a resource name and resource index. In the 1365 // state, a resource has the format "type.name.index" or "type.name". In the 1366 // latter case, the index is returned as -1. 1367 func ParseResourceStateKey(k string) (*ResourceStateKey, error) { 1368 parts := strings.Split(k, ".") 1369 mode := ManagedResourceMode 1370 if len(parts) > 0 && parts[0] == "data" { 1371 mode = DataResourceMode 1372 // Don't need the constant "data" prefix for parsing 1373 // now that we've figured out the mode. 1374 parts = parts[1:] 1375 } 1376 if len(parts) < 2 || len(parts) > 3 { 1377 return nil, fmt.Errorf("Malformed resource state key: %s", k) 1378 } 1379 rsk := &ResourceStateKey{ 1380 Mode: mode, 1381 Type: parts[0], 1382 Name: parts[1], 1383 Index: -1, 1384 } 1385 if len(parts) == 3 { 1386 index, err := strconv.Atoi(parts[2]) 1387 if err != nil { 1388 return nil, fmt.Errorf("Malformed resource state key index: %s", k) 1389 } 1390 rsk.Index = index 1391 } 1392 return rsk, nil 1393 } 1394 1395 // ResourceState holds the state of a resource that is used so that 1396 // a provider can find and manage an existing resource as well as for 1397 // storing attributes that are used to populate variables of child 1398 // resources. 1399 // 1400 // Attributes has attributes about the created resource that are 1401 // queryable in interpolation: "${type.id.attr}" 1402 // 1403 // Extra is just extra data that a provider can return that we store 1404 // for later, but is not exposed in any way to the user. 1405 // 1406 type ResourceState struct { 1407 // This is filled in and managed by Terraform, and is the resource 1408 // type itself such as "mycloud_instance". If a resource provider sets 1409 // this value, it won't be persisted. 1410 Type string `json:"type"` 1411 1412 // Dependencies are a list of things that this resource relies on 1413 // existing to remain intact. For example: an AWS instance might 1414 // depend on a subnet (which itself might depend on a VPC, and so 1415 // on). 1416 // 1417 // Terraform uses this information to build valid destruction 1418 // orders and to warn the user if they're destroying a resource that 1419 // another resource depends on. 1420 // 1421 // Things can be put into this list that may not be managed by 1422 // Terraform. If Terraform doesn't find a matching ID in the 1423 // overall state, then it assumes it isn't managed and doesn't 1424 // worry about it. 1425 Dependencies []string `json:"depends_on"` 1426 1427 // Primary is the current active instance for this resource. 1428 // It can be replaced but only after a successful creation. 1429 // This is the instances on which providers will act. 1430 Primary *InstanceState `json:"primary"` 1431 1432 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 1433 // Primary is Deposed to get it out of the way for the replacement Primary to 1434 // be created by Apply. If the replacement Primary creates successfully, the 1435 // Deposed instance is cleaned up. 1436 // 1437 // If there were problems creating the replacement Primary, the Deposed 1438 // instance and the (now tainted) replacement Primary will be swapped so the 1439 // tainted replacement will be cleaned up instead. 1440 // 1441 // An instance will remain in the Deposed list until it is successfully 1442 // destroyed and purged. 1443 Deposed []*InstanceState `json:"deposed"` 1444 1445 // Provider is used when a resource is connected to a provider with an alias. 1446 // If this string is empty, the resource is connected to the default provider, 1447 // e.g. "aws_instance" goes with the "aws" provider. 1448 // If the resource block contained a "provider" key, that value will be set here. 1449 Provider string `json:"provider"` 1450 1451 mu sync.Mutex 1452 } 1453 1454 func (s *ResourceState) Lock() { s.mu.Lock() } 1455 func (s *ResourceState) Unlock() { s.mu.Unlock() } 1456 1457 // Equal tests whether two ResourceStates are equal. 1458 func (s *ResourceState) Equal(other *ResourceState) bool { 1459 s.Lock() 1460 defer s.Unlock() 1461 1462 if s.Type != other.Type { 1463 return false 1464 } 1465 1466 if s.Provider != other.Provider { 1467 return false 1468 } 1469 1470 // Dependencies must be equal 1471 sort.Strings(s.Dependencies) 1472 sort.Strings(other.Dependencies) 1473 if len(s.Dependencies) != len(other.Dependencies) { 1474 return false 1475 } 1476 for i, d := range s.Dependencies { 1477 if other.Dependencies[i] != d { 1478 return false 1479 } 1480 } 1481 1482 // States must be equal 1483 if !s.Primary.Equal(other.Primary) { 1484 return false 1485 } 1486 1487 return true 1488 } 1489 1490 // Taint marks a resource as tainted. 1491 func (s *ResourceState) Taint() { 1492 s.Lock() 1493 defer s.Unlock() 1494 1495 if s.Primary != nil { 1496 s.Primary.Tainted = true 1497 } 1498 } 1499 1500 // Untaint unmarks a resource as tainted. 1501 func (s *ResourceState) Untaint() { 1502 s.Lock() 1503 defer s.Unlock() 1504 1505 if s.Primary != nil { 1506 s.Primary.Tainted = false 1507 } 1508 } 1509 1510 // ProviderAddr returns the provider address for the receiver, by parsing the 1511 // string representation saved in state. An error can be returned if the 1512 // value in state is corrupt. 1513 func (s *ResourceState) ProviderAddr() (addrs.AbsProviderConfig, error) { 1514 var diags tfdiags.Diagnostics 1515 1516 str := s.Provider 1517 traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1}) 1518 diags = diags.Append(travDiags) 1519 if travDiags.HasErrors() { 1520 return addrs.AbsProviderConfig{}, diags.Err() 1521 } 1522 1523 addr, addrDiags := addrs.ParseAbsProviderConfig(traversal) 1524 diags = diags.Append(addrDiags) 1525 return addr, diags.Err() 1526 } 1527 1528 func (s *ResourceState) init() { 1529 s.Lock() 1530 defer s.Unlock() 1531 1532 if s.Primary == nil { 1533 s.Primary = &InstanceState{} 1534 } 1535 s.Primary.init() 1536 1537 if s.Dependencies == nil { 1538 s.Dependencies = []string{} 1539 } 1540 1541 if s.Deposed == nil { 1542 s.Deposed = make([]*InstanceState, 0) 1543 } 1544 } 1545 1546 // prune is used to remove any instances that are no longer required 1547 func (s *ResourceState) prune() { 1548 s.Lock() 1549 defer s.Unlock() 1550 1551 n := len(s.Deposed) 1552 for i := 0; i < n; i++ { 1553 inst := s.Deposed[i] 1554 if inst == nil || inst.ID == "" { 1555 copy(s.Deposed[i:], s.Deposed[i+1:]) 1556 s.Deposed[n-1] = nil 1557 n-- 1558 i-- 1559 } 1560 } 1561 s.Deposed = s.Deposed[:n] 1562 1563 s.Dependencies = uniqueStrings(s.Dependencies) 1564 } 1565 1566 func (s *ResourceState) sort() { 1567 s.Lock() 1568 defer s.Unlock() 1569 1570 sort.Strings(s.Dependencies) 1571 } 1572 1573 func (s *ResourceState) String() string { 1574 s.Lock() 1575 defer s.Unlock() 1576 1577 var buf bytes.Buffer 1578 buf.WriteString(fmt.Sprintf("Type = %s", s.Type)) 1579 return buf.String() 1580 } 1581 1582 // InstanceState is used to track the unique state information belonging 1583 // to a given instance. 1584 type InstanceState struct { 1585 // A unique ID for this resource. This is opaque to Terraform 1586 // and is only meant as a lookup mechanism for the providers. 1587 ID string `json:"id"` 1588 1589 // Attributes are basic information about the resource. Any keys here 1590 // are accessible in variable format within Terraform configurations: 1591 // ${resourcetype.name.attribute}. 1592 Attributes map[string]string `json:"attributes"` 1593 1594 // Ephemeral is used to store any state associated with this instance 1595 // that is necessary for the Terraform run to complete, but is not 1596 // persisted to a state file. 1597 Ephemeral EphemeralState `json:"-"` 1598 1599 // Meta is a simple K/V map that is persisted to the State but otherwise 1600 // ignored by Terraform core. It's meant to be used for accounting by 1601 // external client code. The value here must only contain Go primitives 1602 // and collections. 1603 Meta map[string]interface{} `json:"meta"` 1604 1605 // Tainted is used to mark a resource for recreation. 1606 Tainted bool `json:"tainted"` 1607 1608 mu sync.Mutex 1609 } 1610 1611 func (s *InstanceState) Lock() { s.mu.Lock() } 1612 func (s *InstanceState) Unlock() { s.mu.Unlock() } 1613 1614 func (s *InstanceState) init() { 1615 s.Lock() 1616 defer s.Unlock() 1617 1618 if s.Attributes == nil { 1619 s.Attributes = make(map[string]string) 1620 } 1621 if s.Meta == nil { 1622 s.Meta = make(map[string]interface{}) 1623 } 1624 s.Ephemeral.init() 1625 } 1626 1627 // NewInstanceStateShimmedFromValue is a shim method to lower a new-style 1628 // object value representing the attributes of an instance object into the 1629 // legacy InstanceState representation. 1630 // 1631 // This is for shimming to old components only and should not be used in new code. 1632 func NewInstanceStateShimmedFromValue(state cty.Value, schemaVersion int) *InstanceState { 1633 attrs := hcl2shim.FlatmapValueFromHCL2(state) 1634 return &InstanceState{ 1635 ID: attrs["id"], 1636 Attributes: attrs, 1637 Meta: map[string]interface{}{ 1638 "schema_version": schemaVersion, 1639 }, 1640 } 1641 } 1642 1643 // AttrsAsObjectValue shims from the legacy InstanceState representation to 1644 // a new-style cty object value representation of the state attributes, using 1645 // the given type for guidance. 1646 // 1647 // The given type must be the implied type of the schema of the resource type 1648 // of the object whose state is being converted, or the result is undefined. 1649 // 1650 // This is for shimming from old components only and should not be used in 1651 // new code. 1652 func (s *InstanceState) AttrsAsObjectValue(ty cty.Type) (cty.Value, error) { 1653 if s == nil { 1654 // if the state is nil, we need to construct a complete cty.Value with 1655 // null attributes, rather than a single cty.NullVal(ty) 1656 s = &InstanceState{} 1657 } 1658 1659 if s.Attributes == nil { 1660 s.Attributes = map[string]string{} 1661 } 1662 1663 // make sure ID is included in the attributes. The InstanceState.ID value 1664 // takes precedence. 1665 if s.ID != "" { 1666 s.Attributes["id"] = s.ID 1667 } 1668 1669 return hcl2shim.HCL2ValueFromFlatmap(s.Attributes, ty) 1670 } 1671 1672 // Copy all the Fields from another InstanceState 1673 func (s *InstanceState) Set(from *InstanceState) { 1674 s.Lock() 1675 defer s.Unlock() 1676 1677 from.Lock() 1678 defer from.Unlock() 1679 1680 s.ID = from.ID 1681 s.Attributes = from.Attributes 1682 s.Ephemeral = from.Ephemeral 1683 s.Meta = from.Meta 1684 s.Tainted = from.Tainted 1685 } 1686 1687 func (s *InstanceState) DeepCopy() *InstanceState { 1688 copy, err := copystructure.Config{Lock: true}.Copy(s) 1689 if err != nil { 1690 panic(err) 1691 } 1692 1693 return copy.(*InstanceState) 1694 } 1695 1696 func (s *InstanceState) Empty() bool { 1697 if s == nil { 1698 return true 1699 } 1700 s.Lock() 1701 defer s.Unlock() 1702 1703 return s.ID == "" 1704 } 1705 1706 func (s *InstanceState) Equal(other *InstanceState) bool { 1707 // Short circuit some nil checks 1708 if s == nil || other == nil { 1709 return s == other 1710 } 1711 s.Lock() 1712 defer s.Unlock() 1713 1714 // IDs must be equal 1715 if s.ID != other.ID { 1716 return false 1717 } 1718 1719 // Attributes must be equal 1720 if len(s.Attributes) != len(other.Attributes) { 1721 return false 1722 } 1723 for k, v := range s.Attributes { 1724 otherV, ok := other.Attributes[k] 1725 if !ok { 1726 return false 1727 } 1728 1729 if v != otherV { 1730 return false 1731 } 1732 } 1733 1734 // Meta must be equal 1735 if len(s.Meta) != len(other.Meta) { 1736 return false 1737 } 1738 if s.Meta != nil && other.Meta != nil { 1739 // We only do the deep check if both are non-nil. If one is nil 1740 // we treat it as equal since their lengths are both zero (check 1741 // above). 1742 // 1743 // Since this can contain numeric values that may change types during 1744 // serialization, let's compare the serialized values. 1745 sMeta, err := json.Marshal(s.Meta) 1746 if err != nil { 1747 // marshaling primitives shouldn't ever error out 1748 panic(err) 1749 } 1750 otherMeta, err := json.Marshal(other.Meta) 1751 if err != nil { 1752 panic(err) 1753 } 1754 1755 if !bytes.Equal(sMeta, otherMeta) { 1756 return false 1757 } 1758 } 1759 1760 if s.Tainted != other.Tainted { 1761 return false 1762 } 1763 1764 return true 1765 } 1766 1767 // MergeDiff takes a ResourceDiff and merges the attributes into 1768 // this resource state in order to generate a new state. This new 1769 // state can be used to provide updated attribute lookups for 1770 // variable interpolation. 1771 // 1772 // If the diff attribute requires computing the value, and hence 1773 // won't be available until apply, the value is replaced with the 1774 // computeID. 1775 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 1776 result := s.DeepCopy() 1777 if result == nil { 1778 result = new(InstanceState) 1779 } 1780 result.init() 1781 1782 if s != nil { 1783 s.Lock() 1784 defer s.Unlock() 1785 for k, v := range s.Attributes { 1786 result.Attributes[k] = v 1787 } 1788 } 1789 if d != nil { 1790 for k, diff := range d.CopyAttributes() { 1791 if diff.NewRemoved { 1792 delete(result.Attributes, k) 1793 continue 1794 } 1795 if diff.NewComputed { 1796 result.Attributes[k] = hcl2shim.UnknownVariableValue 1797 continue 1798 } 1799 1800 result.Attributes[k] = diff.New 1801 } 1802 } 1803 1804 return result 1805 } 1806 1807 func (s *InstanceState) String() string { 1808 notCreated := "<not created>" 1809 1810 if s == nil { 1811 return notCreated 1812 } 1813 1814 s.Lock() 1815 defer s.Unlock() 1816 1817 var buf bytes.Buffer 1818 1819 if s.ID == "" { 1820 return notCreated 1821 } 1822 1823 buf.WriteString(fmt.Sprintf("ID = %s\n", s.ID)) 1824 1825 attributes := s.Attributes 1826 attrKeys := make([]string, 0, len(attributes)) 1827 for ak := range attributes { 1828 if ak == "id" { 1829 continue 1830 } 1831 1832 attrKeys = append(attrKeys, ak) 1833 } 1834 sort.Strings(attrKeys) 1835 1836 for _, ak := range attrKeys { 1837 av := attributes[ak] 1838 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1839 } 1840 1841 buf.WriteString(fmt.Sprintf("Tainted = %t\n", s.Tainted)) 1842 1843 return buf.String() 1844 } 1845 1846 // EphemeralState is used for transient state that is only kept in-memory 1847 type EphemeralState struct { 1848 // ConnInfo is used for the providers to export information which is 1849 // used to connect to the resource for provisioning. For example, 1850 // this could contain SSH or WinRM credentials. 1851 ConnInfo map[string]string `json:"-"` 1852 1853 // Type is used to specify the resource type for this instance. This is only 1854 // required for import operations (as documented). If the documentation 1855 // doesn't state that you need to set this, then don't worry about 1856 // setting it. 1857 Type string `json:"-"` 1858 } 1859 1860 func (e *EphemeralState) init() { 1861 if e.ConnInfo == nil { 1862 e.ConnInfo = make(map[string]string) 1863 } 1864 } 1865 1866 func (e *EphemeralState) DeepCopy() *EphemeralState { 1867 copy, err := copystructure.Config{Lock: true}.Copy(e) 1868 if err != nil { 1869 panic(err) 1870 } 1871 1872 return copy.(*EphemeralState) 1873 } 1874 1875 type jsonStateVersionIdentifier struct { 1876 Version int `json:"version"` 1877 } 1878 1879 // Check if this is a V0 format - the magic bytes at the start of the file 1880 // should be "tfstate" if so. We no longer support upgrading this type of 1881 // state but return an error message explaining to a user how they can 1882 // upgrade via the 0.6.x series. 1883 func testForV0State(buf *bufio.Reader) error { 1884 start, err := buf.Peek(len("tfstate")) 1885 if err != nil { 1886 return fmt.Errorf("Failed to check for magic bytes: %v", err) 1887 } 1888 if string(start) == "tfstate" { 1889 return fmt.Errorf("Terraform 0.7 no longer supports upgrading the binary state\n" + 1890 "format which was used prior to Terraform 0.3. Please upgrade\n" + 1891 "this state file using Terraform 0.6.16 prior to using it with\n" + 1892 "Terraform 0.7.") 1893 } 1894 1895 return nil 1896 } 1897 1898 // ErrNoState is returned by ReadState when the io.Reader contains no data 1899 var ErrNoState = errors.New("no state") 1900 1901 // ReadState reads a state structure out of a reader in the format that 1902 // was written by WriteState. 1903 func ReadState(src io.Reader) (*State, error) { 1904 // check for a nil file specifically, since that produces a platform 1905 // specific error if we try to use it in a bufio.Reader. 1906 if f, ok := src.(*os.File); ok && f == nil { 1907 return nil, ErrNoState 1908 } 1909 1910 buf := bufio.NewReader(src) 1911 1912 if _, err := buf.Peek(1); err != nil { 1913 if err == io.EOF { 1914 return nil, ErrNoState 1915 } 1916 return nil, err 1917 } 1918 1919 if err := testForV0State(buf); err != nil { 1920 return nil, err 1921 } 1922 1923 // If we are JSON we buffer the whole thing in memory so we can read it twice. 1924 // This is suboptimal, but will work for now. 1925 jsonBytes, err := ioutil.ReadAll(buf) 1926 if err != nil { 1927 return nil, fmt.Errorf("Reading state file failed: %v", err) 1928 } 1929 1930 versionIdentifier := &jsonStateVersionIdentifier{} 1931 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil { 1932 return nil, fmt.Errorf("Decoding state file version failed: %v", err) 1933 } 1934 1935 var result *State 1936 switch versionIdentifier.Version { 1937 case 0: 1938 return nil, fmt.Errorf("State version 0 is not supported as JSON.") 1939 case 1: 1940 v1State, err := ReadStateV1(jsonBytes) 1941 if err != nil { 1942 return nil, err 1943 } 1944 1945 v2State, err := upgradeStateV1ToV2(v1State) 1946 if err != nil { 1947 return nil, err 1948 } 1949 1950 v3State, err := upgradeStateV2ToV3(v2State) 1951 if err != nil { 1952 return nil, err 1953 } 1954 1955 // increment the Serial whenever we upgrade state 1956 v3State.Serial++ 1957 result = v3State 1958 case 2: 1959 v2State, err := ReadStateV2(jsonBytes) 1960 if err != nil { 1961 return nil, err 1962 } 1963 v3State, err := upgradeStateV2ToV3(v2State) 1964 if err != nil { 1965 return nil, err 1966 } 1967 1968 v3State.Serial++ 1969 result = v3State 1970 case 3: 1971 v3State, err := ReadStateV3(jsonBytes) 1972 if err != nil { 1973 return nil, err 1974 } 1975 1976 result = v3State 1977 default: 1978 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 1979 tfversion.SemVer.String(), versionIdentifier.Version) 1980 } 1981 1982 // If we reached this place we must have a result set 1983 if result == nil { 1984 panic("resulting state in load not set, assertion failed") 1985 } 1986 1987 // Prune the state when read it. Its possible to write unpruned states or 1988 // for a user to make a state unpruned (nil-ing a module state for example). 1989 result.prune() 1990 1991 // Validate the state file is valid 1992 if err := result.Validate(); err != nil { 1993 return nil, err 1994 } 1995 1996 return result, nil 1997 } 1998 1999 func ReadStateV1(jsonBytes []byte) (*stateV1, error) { 2000 v1State := &stateV1{} 2001 if err := json.Unmarshal(jsonBytes, v1State); err != nil { 2002 return nil, fmt.Errorf("Decoding state file failed: %v", err) 2003 } 2004 2005 if v1State.Version != 1 { 2006 return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+ 2007 "read %d, expected 1", v1State.Version) 2008 } 2009 2010 return v1State, nil 2011 } 2012 2013 func ReadStateV2(jsonBytes []byte) (*State, error) { 2014 state := &State{} 2015 if err := json.Unmarshal(jsonBytes, state); err != nil { 2016 return nil, fmt.Errorf("Decoding state file failed: %v", err) 2017 } 2018 2019 // Check the version, this to ensure we don't read a future 2020 // version that we don't understand 2021 if state.Version > StateVersion { 2022 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 2023 tfversion.SemVer.String(), state.Version) 2024 } 2025 2026 // Make sure the version is semantic 2027 if state.TFVersion != "" { 2028 if _, err := version.NewVersion(state.TFVersion); err != nil { 2029 return nil, fmt.Errorf( 2030 "State contains invalid version: %s\n\n"+ 2031 "Terraform validates the version format prior to writing it. This\n"+ 2032 "means that this is invalid of the state becoming corrupted through\n"+ 2033 "some external means. Please manually modify the Terraform version\n"+ 2034 "field to be a proper semantic version.", 2035 state.TFVersion) 2036 } 2037 } 2038 2039 // catch any unitialized fields in the state 2040 state.init() 2041 2042 // Sort it 2043 state.sort() 2044 2045 return state, nil 2046 } 2047 2048 func ReadStateV3(jsonBytes []byte) (*State, error) { 2049 state := &State{} 2050 if err := json.Unmarshal(jsonBytes, state); err != nil { 2051 return nil, fmt.Errorf("Decoding state file failed: %v", err) 2052 } 2053 2054 // Check the version, this to ensure we don't read a future 2055 // version that we don't understand 2056 if state.Version > StateVersion { 2057 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 2058 tfversion.SemVer.String(), state.Version) 2059 } 2060 2061 // Make sure the version is semantic 2062 if state.TFVersion != "" { 2063 if _, err := version.NewVersion(state.TFVersion); err != nil { 2064 return nil, fmt.Errorf( 2065 "State contains invalid version: %s\n\n"+ 2066 "Terraform validates the version format prior to writing it. This\n"+ 2067 "means that this is invalid of the state becoming corrupted through\n"+ 2068 "some external means. Please manually modify the Terraform version\n"+ 2069 "field to be a proper semantic version.", 2070 state.TFVersion) 2071 } 2072 } 2073 2074 // catch any unitialized fields in the state 2075 state.init() 2076 2077 // Sort it 2078 state.sort() 2079 2080 // Now we write the state back out to detect any changes in normaliztion. 2081 // If our state is now written out differently, bump the serial number to 2082 // prevent conflicts. 2083 var buf bytes.Buffer 2084 err := WriteState(state, &buf) 2085 if err != nil { 2086 return nil, err 2087 } 2088 2089 if !bytes.Equal(jsonBytes, buf.Bytes()) { 2090 log.Println("[INFO] state modified during read or write. incrementing serial number") 2091 state.Serial++ 2092 } 2093 2094 return state, nil 2095 } 2096 2097 // WriteState writes a state somewhere in a binary format. 2098 func WriteState(d *State, dst io.Writer) error { 2099 // writing a nil state is a noop. 2100 if d == nil { 2101 return nil 2102 } 2103 2104 // make sure we have no uninitialized fields 2105 d.init() 2106 2107 // Make sure it is sorted 2108 d.sort() 2109 2110 // Ensure the version is set 2111 d.Version = StateVersion 2112 2113 // If the TFVersion is set, verify it. We used to just set the version 2114 // here, but this isn't safe since it changes the MD5 sum on some remote 2115 // state storage backends such as Atlas. We now leave it be if needed. 2116 if d.TFVersion != "" { 2117 if _, err := version.NewVersion(d.TFVersion); err != nil { 2118 return fmt.Errorf( 2119 "Error writing state, invalid version: %s\n\n"+ 2120 "The Terraform version when writing the state must be a semantic\n"+ 2121 "version.", 2122 d.TFVersion) 2123 } 2124 } 2125 2126 // Encode the data in a human-friendly way 2127 data, err := json.MarshalIndent(d, "", " ") 2128 if err != nil { 2129 return fmt.Errorf("Failed to encode state: %s", err) 2130 } 2131 2132 // We append a newline to the data because MarshalIndent doesn't 2133 data = append(data, '\n') 2134 2135 // Write the data out to the dst 2136 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 2137 return fmt.Errorf("Failed to write state: %v", err) 2138 } 2139 2140 return nil 2141 } 2142 2143 // resourceNameSort implements the sort.Interface to sort name parts lexically for 2144 // strings and numerically for integer indexes. 2145 type resourceNameSort []string 2146 2147 func (r resourceNameSort) Len() int { return len(r) } 2148 func (r resourceNameSort) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 2149 2150 func (r resourceNameSort) Less(i, j int) bool { 2151 iParts := strings.Split(r[i], ".") 2152 jParts := strings.Split(r[j], ".") 2153 2154 end := len(iParts) 2155 if len(jParts) < end { 2156 end = len(jParts) 2157 } 2158 2159 for idx := 0; idx < end; idx++ { 2160 if iParts[idx] == jParts[idx] { 2161 continue 2162 } 2163 2164 // sort on the first non-matching part 2165 iInt, iIntErr := strconv.Atoi(iParts[idx]) 2166 jInt, jIntErr := strconv.Atoi(jParts[idx]) 2167 2168 switch { 2169 case iIntErr == nil && jIntErr == nil: 2170 // sort numerically if both parts are integers 2171 return iInt < jInt 2172 case iIntErr == nil: 2173 // numbers sort before strings 2174 return true 2175 case jIntErr == nil: 2176 return false 2177 default: 2178 return iParts[idx] < jParts[idx] 2179 } 2180 } 2181 2182 return r[i] < r[j] 2183 } 2184 2185 // moduleStateSort implements sort.Interface to sort module states 2186 type moduleStateSort []*ModuleState 2187 2188 func (s moduleStateSort) Len() int { 2189 return len(s) 2190 } 2191 2192 func (s moduleStateSort) Less(i, j int) bool { 2193 a := s[i] 2194 b := s[j] 2195 2196 // If either is nil, then the nil one is "less" than 2197 if a == nil || b == nil { 2198 return a == nil 2199 } 2200 2201 // If the lengths are different, then the shorter one always wins 2202 if len(a.Path) != len(b.Path) { 2203 return len(a.Path) < len(b.Path) 2204 } 2205 2206 // Otherwise, compare lexically 2207 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".") 2208 } 2209 2210 func (s moduleStateSort) Swap(i, j int) { 2211 s[i], s[j] = s[j], s[i] 2212 } 2213 2214 const stateValidateErrMultiModule = ` 2215 Multiple modules with the same path: %s 2216 2217 This means that there are multiple entries in the "modules" field 2218 in your state file that point to the same module. This will cause Terraform 2219 to behave in unexpected and error prone ways and is invalid. Please back up 2220 and modify your state file manually to resolve this. 2221 `