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