github.com/opentofu/opentofu@v1.7.1/internal/legacy/tofu/state.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package tofu 7 8 import ( 9 "bufio" 10 "bytes" 11 "encoding/json" 12 "errors" 13 "fmt" 14 "io" 15 "log" 16 "os" 17 "reflect" 18 "sort" 19 "strconv" 20 "strings" 21 "sync" 22 23 "github.com/hashicorp/errwrap" 24 multierror "github.com/hashicorp/go-multierror" 25 uuid "github.com/hashicorp/go-uuid" 26 version "github.com/hashicorp/go-version" 27 "github.com/hashicorp/hcl/v2" 28 "github.com/hashicorp/hcl/v2/hclsyntax" 29 "github.com/mitchellh/copystructure" 30 "github.com/opentofu/opentofu/internal/addrs" 31 "github.com/opentofu/opentofu/internal/configs" 32 "github.com/opentofu/opentofu/internal/configs/configschema" 33 "github.com/opentofu/opentofu/internal/configs/hcl2shim" 34 "github.com/opentofu/opentofu/internal/plans" 35 "github.com/opentofu/opentofu/internal/tfdiags" 36 tfversion "github.com/opentofu/opentofu/version" 37 "github.com/zclconf/go-cty/cty" 38 ctyjson "github.com/zclconf/go-cty/cty/json" 39 ) 40 41 const ( 42 // StateVersion is the current version for our state file 43 StateVersion = 3 44 ) 45 46 // rootModulePath is the path of the root module 47 var rootModulePath = []string{"root"} 48 49 // normalizeModulePath transforms a legacy module path (which may or may not 50 // have a redundant "root" label at the start of it) into an 51 // addrs.ModuleInstance representing the same module. 52 // 53 // For legacy reasons, different parts of OpenTofu disagree about whether the 54 // root module has the path []string{} or []string{"root"}, and so this 55 // function accepts both and trims off the "root". An implication of this is 56 // that it's not possible to actually have a module call in the root module 57 // that is itself named "root", since that would be ambiguous. 58 // 59 // normalizeModulePath takes a raw module path and returns a path that 60 // has the rootModulePath prepended to it. If I could go back in time I 61 // would've never had a rootModulePath (empty path would be root). We can 62 // still fix this but thats a big refactor that my branch doesn't make sense 63 // for. Instead, this function normalizes paths. 64 func normalizeModulePath(p []string) addrs.ModuleInstance { 65 // FIXME: Remove this once everyone is using addrs.ModuleInstance. 66 67 if len(p) > 0 && p[0] == "root" { 68 p = p[1:] 69 } 70 71 ret := make(addrs.ModuleInstance, len(p)) 72 for i, name := range p { 73 // For now we don't actually support modules with multiple instances 74 // identified by keys, so we just treat every path element as a 75 // step with no key. 76 ret[i] = addrs.ModuleInstanceStep{ 77 Name: name, 78 } 79 } 80 return ret 81 } 82 83 // State keeps track of a snapshot state-of-the-world that OpenTofu 84 // can use to keep track of what real world resources it is actually 85 // managing. 86 type State struct { 87 // Version is the state file protocol version. 88 Version int `json:"version"` 89 90 // TFVersion is the version of OpenTofu that wrote this state. 91 TFVersion string `json:"terraform_version,omitempty"` 92 93 // Serial is incremented on any operation that modifies 94 // the State file. It is used to detect potentially conflicting 95 // updates. 96 Serial int64 `json:"serial"` 97 98 // Lineage is set when a new, blank state is created and then 99 // never updated. This allows us to determine whether the serials 100 // of two states can be meaningfully compared. 101 // Apart from the guarantee that collisions between two lineages 102 // are very unlikely, this value is opaque and external callers 103 // should only compare lineage strings byte-for-byte for equality. 104 Lineage string `json:"lineage"` 105 106 // Remote is used to track the metadata required to 107 // pull and push state files from a remote storage endpoint. 108 Remote *RemoteState `json:"remote,omitempty"` 109 110 // Backend tracks the configuration for the backend in use with 111 // this state. This is used to track any changes in the backend 112 // configuration. 113 Backend *BackendState `json:"backend,omitempty"` 114 115 // Modules contains all the modules in a breadth-first order 116 Modules []*ModuleState `json:"modules"` 117 118 mu sync.Mutex 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 OpenTofu 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 OpenTofu in order 289 // to behave properly. The core of OpenTofu 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 OpenTofu 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 // FromFutureTofu checks if this state was written by a OpenTofu 623 // version from the future. 624 func (s *State) FromFutureTofu() 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: %w", 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) deepcopy() *RemoteState { 860 r.Lock() 861 defer r.Unlock() 862 863 confCopy := make(map[string]string, len(r.Config)) 864 for k, v := range r.Config { 865 confCopy[k] = v 866 } 867 return &RemoteState{ 868 Type: r.Type, 869 Config: confCopy, 870 } 871 } 872 873 func (r *RemoteState) Empty() bool { 874 if r == nil { 875 return true 876 } 877 r.Lock() 878 defer r.Unlock() 879 880 return r.Type == "" 881 } 882 883 func (r *RemoteState) Equals(other *RemoteState) bool { 884 r.Lock() 885 defer r.Unlock() 886 887 if r.Type != other.Type { 888 return false 889 } 890 if len(r.Config) != len(other.Config) { 891 return false 892 } 893 for k, v := range r.Config { 894 if other.Config[k] != v { 895 return false 896 } 897 } 898 return true 899 } 900 901 // OutputState is used to track the state relevant to a single output. 902 type OutputState struct { 903 // Sensitive describes whether the output is considered sensitive, 904 // which may lead to masking the value on screen in some cases. 905 Sensitive bool `json:"sensitive"` 906 // Type describes the structure of Value. Valid values are "string", 907 // "map" and "list" 908 Type string `json:"type"` 909 // Value contains the value of the output, in the structure described 910 // by the Type field. 911 Value interface{} `json:"value"` 912 913 mu sync.Mutex 914 } 915 916 func (s *OutputState) Lock() { s.mu.Lock() } 917 func (s *OutputState) Unlock() { s.mu.Unlock() } 918 919 func (s *OutputState) String() string { 920 return fmt.Sprintf("%#v", s.Value) 921 } 922 923 // Equal compares two OutputState structures for equality. nil values are 924 // considered equal. 925 func (s *OutputState) Equal(other *OutputState) bool { 926 if s == nil && other == nil { 927 return true 928 } 929 930 if s == nil || other == nil { 931 return false 932 } 933 s.Lock() 934 defer s.Unlock() 935 936 if s.Type != other.Type { 937 return false 938 } 939 940 if s.Sensitive != other.Sensitive { 941 return false 942 } 943 944 if !reflect.DeepEqual(s.Value, other.Value) { 945 return false 946 } 947 948 return true 949 } 950 951 func (s *OutputState) deepcopy() *OutputState { 952 if s == nil { 953 return nil 954 } 955 956 stateCopy, err := copystructure.Config{Lock: true}.Copy(s) 957 if err != nil { 958 panic(fmt.Errorf("Error copying output value: %w", err)) 959 } 960 961 return stateCopy.(*OutputState) 962 } 963 964 // ModuleState is used to track all the state relevant to a single 965 // module. Previous to Terraform 0.3, all state belonged to the "root" 966 // module. 967 type ModuleState struct { 968 // Path is the import path from the root module. Modules imports are 969 // always disjoint, so the path represents amodule tree 970 Path []string `json:"path"` 971 972 // Locals are kept only transiently in-memory, because we can always 973 // re-compute them. 974 Locals map[string]interface{} `json:"-"` 975 976 // Outputs declared by the module and maintained for each module 977 // even though only the root module technically needs to be kept. 978 // This allows operators to inspect values at the boundaries. 979 Outputs map[string]*OutputState `json:"outputs"` 980 981 // Resources is a mapping of the logically named resource to 982 // the state of the resource. Each resource may actually have 983 // N instances underneath, although a user only needs to think 984 // about the 1:1 case. 985 Resources map[string]*ResourceState `json:"resources"` 986 987 // Dependencies are a list of things that this module relies on 988 // existing to remain intact. For example: an module may depend 989 // on a VPC ID given by an aws_vpc resource. 990 // 991 // OpenTofu uses this information to build valid destruction 992 // orders and to warn the user if they're destroying a module that 993 // another resource depends on. 994 // 995 // Things can be put into this list that may not be managed by 996 // OpenTofu. If OpenTofu doesn't find a matching ID in the 997 // overall state, then it assumes it isn't managed and doesn't 998 // worry about it. 999 Dependencies []string `json:"depends_on"` 1000 1001 mu sync.Mutex 1002 } 1003 1004 func (s *ModuleState) Lock() { s.mu.Lock() } 1005 func (s *ModuleState) Unlock() { s.mu.Unlock() } 1006 1007 // Equal tests whether one module state is equal to another. 1008 func (m *ModuleState) Equal(other *ModuleState) bool { 1009 m.Lock() 1010 defer m.Unlock() 1011 1012 // Paths must be equal 1013 if !reflect.DeepEqual(m.Path, other.Path) { 1014 return false 1015 } 1016 1017 // Outputs must be equal 1018 if len(m.Outputs) != len(other.Outputs) { 1019 return false 1020 } 1021 for k, v := range m.Outputs { 1022 if !other.Outputs[k].Equal(v) { 1023 return false 1024 } 1025 } 1026 1027 // Dependencies must be equal. This sorts these in place but 1028 // this shouldn't cause any problems. 1029 sort.Strings(m.Dependencies) 1030 sort.Strings(other.Dependencies) 1031 if len(m.Dependencies) != len(other.Dependencies) { 1032 return false 1033 } 1034 for i, d := range m.Dependencies { 1035 if other.Dependencies[i] != d { 1036 return false 1037 } 1038 } 1039 1040 // Resources must be equal 1041 if len(m.Resources) != len(other.Resources) { 1042 return false 1043 } 1044 for k, r := range m.Resources { 1045 otherR, ok := other.Resources[k] 1046 if !ok { 1047 return false 1048 } 1049 1050 if !r.Equal(otherR) { 1051 return false 1052 } 1053 } 1054 1055 return true 1056 } 1057 1058 // IsRoot says whether or not this module diff is for the root module. 1059 func (m *ModuleState) IsRoot() bool { 1060 m.Lock() 1061 defer m.Unlock() 1062 return reflect.DeepEqual(m.Path, rootModulePath) 1063 } 1064 1065 // IsDescendent returns true if other is a descendent of this module. 1066 func (m *ModuleState) IsDescendent(other *ModuleState) bool { 1067 m.Lock() 1068 defer m.Unlock() 1069 1070 i := len(m.Path) 1071 return len(other.Path) > i && reflect.DeepEqual(other.Path[:i], m.Path) 1072 } 1073 1074 // Orphans returns a list of keys of resources that are in the State 1075 // but aren't present in the configuration itself. Hence, these keys 1076 // represent the state of resources that are orphans. 1077 func (m *ModuleState) Orphans(c *configs.Module) []addrs.ResourceInstance { 1078 m.Lock() 1079 defer m.Unlock() 1080 1081 inConfig := make(map[string]struct{}) 1082 if c != nil { 1083 for _, r := range c.ManagedResources { 1084 inConfig[r.Addr().String()] = struct{}{} 1085 } 1086 for _, r := range c.DataResources { 1087 inConfig[r.Addr().String()] = struct{}{} 1088 } 1089 } 1090 1091 var result []addrs.ResourceInstance 1092 for k := range m.Resources { 1093 // Since we've not yet updated state to use our new address format, 1094 // we need to do some shimming here. 1095 legacyAddr, err := parseResourceAddressInternal(k) 1096 if err != nil { 1097 // Suggests that the user tampered with the state, since we always 1098 // generate valid internal addresses. 1099 log.Printf("ModuleState has invalid resource key %q. Ignoring.", k) 1100 continue 1101 } 1102 1103 addr := legacyAddr.AbsResourceInstanceAddr().Resource 1104 compareKey := addr.Resource.String() // compare by resource address, ignoring instance key 1105 if _, exists := inConfig[compareKey]; !exists { 1106 result = append(result, addr) 1107 } 1108 } 1109 return result 1110 } 1111 1112 // RemovedOutputs returns a list of outputs that are in the State but aren't 1113 // present in the configuration itself. 1114 func (s *ModuleState) RemovedOutputs(outputs map[string]*configs.Output) []addrs.OutputValue { 1115 if outputs == nil { 1116 // If we got no output map at all then we'll just treat our set of 1117 // configured outputs as empty, since that suggests that they've all 1118 // been removed by removing their containing module. 1119 outputs = make(map[string]*configs.Output) 1120 } 1121 1122 s.Lock() 1123 defer s.Unlock() 1124 1125 var ret []addrs.OutputValue 1126 for n := range s.Outputs { 1127 if _, declared := outputs[n]; !declared { 1128 ret = append(ret, addrs.OutputValue{ 1129 Name: n, 1130 }) 1131 } 1132 } 1133 1134 return ret 1135 } 1136 1137 // View returns a view with the given resource prefix. 1138 func (m *ModuleState) View(id string) *ModuleState { 1139 if m == nil { 1140 return m 1141 } 1142 1143 r := m.deepcopy() 1144 for k, _ := range r.Resources { 1145 if id == k || strings.HasPrefix(k, id+".") { 1146 continue 1147 } 1148 1149 delete(r.Resources, k) 1150 } 1151 1152 return r 1153 } 1154 1155 func (m *ModuleState) init() { 1156 m.Lock() 1157 defer m.Unlock() 1158 1159 if m.Path == nil { 1160 m.Path = []string{} 1161 } 1162 if m.Outputs == nil { 1163 m.Outputs = make(map[string]*OutputState) 1164 } 1165 if m.Resources == nil { 1166 m.Resources = make(map[string]*ResourceState) 1167 } 1168 1169 if m.Dependencies == nil { 1170 m.Dependencies = make([]string, 0) 1171 } 1172 1173 for _, rs := range m.Resources { 1174 rs.init() 1175 } 1176 } 1177 1178 func (m *ModuleState) deepcopy() *ModuleState { 1179 if m == nil { 1180 return nil 1181 } 1182 1183 stateCopy, err := copystructure.Config{Lock: true}.Copy(m) 1184 if err != nil { 1185 panic(err) 1186 } 1187 1188 return stateCopy.(*ModuleState) 1189 } 1190 1191 // prune is used to remove any resources that are no longer required 1192 func (m *ModuleState) prune() { 1193 m.Lock() 1194 defer m.Unlock() 1195 1196 for k, v := range m.Resources { 1197 if v == nil || (v.Primary == nil || v.Primary.ID == "") && len(v.Deposed) == 0 { 1198 delete(m.Resources, k) 1199 continue 1200 } 1201 1202 v.prune() 1203 } 1204 1205 for k, v := range m.Outputs { 1206 if v.Value == hcl2shim.UnknownVariableValue { 1207 delete(m.Outputs, k) 1208 } 1209 } 1210 1211 m.Dependencies = uniqueStrings(m.Dependencies) 1212 } 1213 1214 func (m *ModuleState) sort() { 1215 for _, v := range m.Resources { 1216 v.sort() 1217 } 1218 } 1219 1220 func (m *ModuleState) String() string { 1221 m.Lock() 1222 defer m.Unlock() 1223 1224 var buf bytes.Buffer 1225 1226 if len(m.Resources) == 0 { 1227 buf.WriteString("<no state>") 1228 } 1229 1230 names := make([]string, 0, len(m.Resources)) 1231 for name, _ := range m.Resources { 1232 names = append(names, name) 1233 } 1234 1235 sort.Sort(resourceNameSort(names)) 1236 1237 for _, k := range names { 1238 rs := m.Resources[k] 1239 var id string 1240 if rs.Primary != nil { 1241 id = rs.Primary.ID 1242 } 1243 if id == "" { 1244 id = "<not created>" 1245 } 1246 1247 taintStr := "" 1248 if rs.Primary.Tainted { 1249 taintStr = " (tainted)" 1250 } 1251 1252 deposedStr := "" 1253 if len(rs.Deposed) > 0 { 1254 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed)) 1255 } 1256 1257 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr)) 1258 buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) 1259 if rs.Provider != "" { 1260 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider)) 1261 } 1262 1263 var attributes map[string]string 1264 if rs.Primary != nil { 1265 attributes = rs.Primary.Attributes 1266 } 1267 attrKeys := make([]string, 0, len(attributes)) 1268 for ak, _ := range attributes { 1269 if ak == "id" { 1270 continue 1271 } 1272 1273 attrKeys = append(attrKeys, ak) 1274 } 1275 1276 sort.Strings(attrKeys) 1277 1278 for _, ak := range attrKeys { 1279 av := attributes[ak] 1280 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) 1281 } 1282 1283 for idx, t := range rs.Deposed { 1284 taintStr := "" 1285 if t.Tainted { 1286 taintStr = " (tainted)" 1287 } 1288 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s%s\n", idx+1, t.ID, taintStr)) 1289 } 1290 1291 if len(rs.Dependencies) > 0 { 1292 buf.WriteString(fmt.Sprintf("\n Dependencies:\n")) 1293 for _, dep := range rs.Dependencies { 1294 buf.WriteString(fmt.Sprintf(" %s\n", dep)) 1295 } 1296 } 1297 } 1298 1299 if len(m.Outputs) > 0 { 1300 buf.WriteString("\nOutputs:\n\n") 1301 1302 ks := make([]string, 0, len(m.Outputs)) 1303 for k, _ := range m.Outputs { 1304 ks = append(ks, k) 1305 } 1306 1307 sort.Strings(ks) 1308 1309 for _, k := range ks { 1310 v := m.Outputs[k] 1311 switch vTyped := v.Value.(type) { 1312 case string: 1313 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 1314 case []interface{}: 1315 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 1316 case map[string]interface{}: 1317 var mapKeys []string 1318 for key, _ := range vTyped { 1319 mapKeys = append(mapKeys, key) 1320 } 1321 sort.Strings(mapKeys) 1322 1323 var mapBuf bytes.Buffer 1324 mapBuf.WriteString("{") 1325 for _, key := range mapKeys { 1326 mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key])) 1327 } 1328 mapBuf.WriteString("}") 1329 1330 buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String())) 1331 } 1332 } 1333 } 1334 1335 return buf.String() 1336 } 1337 1338 func (m *ModuleState) Empty() bool { 1339 return len(m.Locals) == 0 && len(m.Outputs) == 0 && len(m.Resources) == 0 1340 } 1341 1342 // ResourceStateKey is a structured representation of the key used for the 1343 // ModuleState.Resources mapping 1344 type ResourceStateKey struct { 1345 Name string 1346 Type string 1347 Mode ResourceMode 1348 Index int 1349 } 1350 1351 // Equal determines whether two ResourceStateKeys are the same 1352 func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool { 1353 if rsk == nil || other == nil { 1354 return false 1355 } 1356 if rsk.Mode != other.Mode { 1357 return false 1358 } 1359 if rsk.Type != other.Type { 1360 return false 1361 } 1362 if rsk.Name != other.Name { 1363 return false 1364 } 1365 if rsk.Index != other.Index { 1366 return false 1367 } 1368 return true 1369 } 1370 1371 func (rsk *ResourceStateKey) String() string { 1372 if rsk == nil { 1373 return "" 1374 } 1375 var prefix string 1376 switch rsk.Mode { 1377 case ManagedResourceMode: 1378 prefix = "" 1379 case DataResourceMode: 1380 prefix = "data." 1381 default: 1382 panic(fmt.Errorf("unknown resource mode %s", rsk.Mode)) 1383 } 1384 if rsk.Index == -1 { 1385 return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name) 1386 } 1387 return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index) 1388 } 1389 1390 // ParseResourceStateKey accepts a key in the format used by 1391 // ModuleState.Resources and returns a resource name and resource index. In the 1392 // state, a resource has the format "type.name.index" or "type.name". In the 1393 // latter case, the index is returned as -1. 1394 func ParseResourceStateKey(k string) (*ResourceStateKey, error) { 1395 parts := strings.Split(k, ".") 1396 mode := ManagedResourceMode 1397 if len(parts) > 0 && parts[0] == "data" { 1398 mode = DataResourceMode 1399 // Don't need the constant "data" prefix for parsing 1400 // now that we've figured out the mode. 1401 parts = parts[1:] 1402 } 1403 if len(parts) < 2 || len(parts) > 3 { 1404 return nil, fmt.Errorf("Malformed resource state key: %s", k) 1405 } 1406 rsk := &ResourceStateKey{ 1407 Mode: mode, 1408 Type: parts[0], 1409 Name: parts[1], 1410 Index: -1, 1411 } 1412 if len(parts) == 3 { 1413 index, err := strconv.Atoi(parts[2]) 1414 if err != nil { 1415 return nil, fmt.Errorf("Malformed resource state key index: %s", k) 1416 } 1417 rsk.Index = index 1418 } 1419 return rsk, nil 1420 } 1421 1422 // ResourceState holds the state of a resource that is used so that 1423 // a provider can find and manage an existing resource as well as for 1424 // storing attributes that are used to populate variables of child 1425 // resources. 1426 // 1427 // Attributes has attributes about the created resource that are 1428 // queryable in interpolation: "${type.id.attr}" 1429 // 1430 // Extra is just extra data that a provider can return that we store 1431 // for later, but is not exposed in any way to the user. 1432 type ResourceState struct { 1433 // This is filled in and managed by OpenTofu, and is the resource 1434 // type itself such as "mycloud_instance". If a resource provider sets 1435 // this value, it won't be persisted. 1436 Type string `json:"type"` 1437 1438 // Dependencies are a list of things that this resource relies on 1439 // existing to remain intact. For example: an AWS instance might 1440 // depend on a subnet (which itself might depend on a VPC, and so 1441 // on). 1442 // 1443 // OpenTofu uses this information to build valid destruction 1444 // orders and to warn the user if they're destroying a resource that 1445 // another resource depends on. 1446 // 1447 // Things can be put into this list that may not be managed by 1448 // OpenTofu. If OpenTofu doesn't find a matching ID in the 1449 // overall state, then it assumes it isn't managed and doesn't 1450 // worry about it. 1451 Dependencies []string `json:"depends_on"` 1452 1453 // Primary is the current active instance for this resource. 1454 // It can be replaced but only after a successful creation. 1455 // This is the instances on which providers will act. 1456 Primary *InstanceState `json:"primary"` 1457 1458 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 1459 // Primary is Deposed to get it out of the way for the replacement Primary to 1460 // be created by Apply. If the replacement Primary creates successfully, the 1461 // Deposed instance is cleaned up. 1462 // 1463 // If there were problems creating the replacement Primary, the Deposed 1464 // instance and the (now tainted) replacement Primary will be swapped so the 1465 // tainted replacement will be cleaned up instead. 1466 // 1467 // An instance will remain in the Deposed list until it is successfully 1468 // destroyed and purged. 1469 Deposed []*InstanceState `json:"deposed"` 1470 1471 // Provider is used when a resource is connected to a provider with an alias. 1472 // If this string is empty, the resource is connected to the default provider, 1473 // e.g. "aws_instance" goes with the "aws" provider. 1474 // If the resource block contained a "provider" key, that value will be set here. 1475 Provider string `json:"provider"` 1476 1477 mu sync.Mutex 1478 } 1479 1480 func (s *ResourceState) Lock() { s.mu.Lock() } 1481 func (s *ResourceState) Unlock() { s.mu.Unlock() } 1482 1483 // Equal tests whether two ResourceStates are equal. 1484 func (s *ResourceState) Equal(other *ResourceState) bool { 1485 s.Lock() 1486 defer s.Unlock() 1487 1488 if s.Type != other.Type { 1489 return false 1490 } 1491 1492 if s.Provider != other.Provider { 1493 return false 1494 } 1495 1496 // Dependencies must be equal 1497 sort.Strings(s.Dependencies) 1498 sort.Strings(other.Dependencies) 1499 if len(s.Dependencies) != len(other.Dependencies) { 1500 return false 1501 } 1502 for i, d := range s.Dependencies { 1503 if other.Dependencies[i] != d { 1504 return false 1505 } 1506 } 1507 1508 // States must be equal 1509 if !s.Primary.Equal(other.Primary) { 1510 return false 1511 } 1512 1513 return true 1514 } 1515 1516 // Taint marks a resource as tainted. 1517 func (s *ResourceState) Taint() { 1518 s.Lock() 1519 defer s.Unlock() 1520 1521 if s.Primary != nil { 1522 s.Primary.Tainted = true 1523 } 1524 } 1525 1526 // Untaint unmarks a resource as tainted. 1527 func (s *ResourceState) Untaint() { 1528 s.Lock() 1529 defer s.Unlock() 1530 1531 if s.Primary != nil { 1532 s.Primary.Tainted = false 1533 } 1534 } 1535 1536 // ProviderAddr returns the provider address for the receiver, by parsing the 1537 // string representation saved in state. An error can be returned if the 1538 // value in state is corrupt. 1539 func (s *ResourceState) ProviderAddr() (addrs.AbsProviderConfig, error) { 1540 var diags tfdiags.Diagnostics 1541 1542 str := s.Provider 1543 traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1}) 1544 diags = diags.Append(travDiags) 1545 if travDiags.HasErrors() { 1546 return addrs.AbsProviderConfig{}, diags.Err() 1547 } 1548 1549 addr, addrDiags := addrs.ParseAbsProviderConfig(traversal) 1550 diags = diags.Append(addrDiags) 1551 return addr, diags.Err() 1552 } 1553 1554 func (s *ResourceState) init() { 1555 s.Lock() 1556 defer s.Unlock() 1557 1558 if s.Primary == nil { 1559 s.Primary = &InstanceState{} 1560 } 1561 s.Primary.init() 1562 1563 if s.Dependencies == nil { 1564 s.Dependencies = []string{} 1565 } 1566 1567 if s.Deposed == nil { 1568 s.Deposed = make([]*InstanceState, 0) 1569 } 1570 } 1571 1572 func (s *ResourceState) deepcopy() *ResourceState { 1573 copy, err := copystructure.Config{Lock: true}.Copy(s) 1574 if err != nil { 1575 panic(err) 1576 } 1577 1578 return copy.(*ResourceState) 1579 } 1580 1581 // prune is used to remove any instances that are no longer required 1582 func (s *ResourceState) prune() { 1583 s.Lock() 1584 defer s.Unlock() 1585 1586 n := len(s.Deposed) 1587 for i := 0; i < n; i++ { 1588 inst := s.Deposed[i] 1589 if inst == nil || inst.ID == "" { 1590 copy(s.Deposed[i:], s.Deposed[i+1:]) 1591 s.Deposed[n-1] = nil 1592 n-- 1593 i-- 1594 } 1595 } 1596 s.Deposed = s.Deposed[:n] 1597 1598 s.Dependencies = uniqueStrings(s.Dependencies) 1599 } 1600 1601 func (s *ResourceState) sort() { 1602 s.Lock() 1603 defer s.Unlock() 1604 1605 sort.Strings(s.Dependencies) 1606 } 1607 1608 func (s *ResourceState) String() string { 1609 s.Lock() 1610 defer s.Unlock() 1611 1612 var buf bytes.Buffer 1613 buf.WriteString(fmt.Sprintf("Type = %s", s.Type)) 1614 return buf.String() 1615 } 1616 1617 // InstanceState is used to track the unique state information belonging 1618 // to a given instance. 1619 type InstanceState struct { 1620 // A unique ID for this resource. This is opaque to OpenTofu 1621 // and is only meant as a lookup mechanism for the providers. 1622 ID string `json:"id"` 1623 1624 // Attributes are basic information about the resource. Any keys here 1625 // are accessible in variable format within OpenTofu configurations: 1626 // ${resourcetype.name.attribute}. 1627 Attributes map[string]string `json:"attributes"` 1628 1629 // Ephemeral is used to store any state associated with this instance 1630 // that is necessary for the OpenTofu run to complete, but is not 1631 // persisted to a state file. 1632 Ephemeral EphemeralState `json:"-"` 1633 1634 // Meta is a simple K/V map that is persisted to the State but otherwise 1635 // ignored by OpenTofu core. It's meant to be used for accounting by 1636 // external client code. The value here must only contain Go primitives 1637 // and collections. 1638 Meta map[string]interface{} `json:"meta"` 1639 1640 ProviderMeta cty.Value 1641 1642 // Tainted is used to mark a resource for recreation. 1643 Tainted bool `json:"tainted"` 1644 1645 mu sync.Mutex 1646 } 1647 1648 func (s *InstanceState) Lock() { s.mu.Lock() } 1649 func (s *InstanceState) Unlock() { s.mu.Unlock() } 1650 1651 func (s *InstanceState) init() { 1652 s.Lock() 1653 defer s.Unlock() 1654 1655 if s.Attributes == nil { 1656 s.Attributes = make(map[string]string) 1657 } 1658 if s.Meta == nil { 1659 s.Meta = make(map[string]interface{}) 1660 } 1661 s.Ephemeral.init() 1662 } 1663 1664 // NewInstanceStateShimmedFromValue is a shim method to lower a new-style 1665 // object value representing the attributes of an instance object into the 1666 // legacy InstanceState representation. 1667 // 1668 // This is for shimming to old components only and should not be used in new code. 1669 func NewInstanceStateShimmedFromValue(state cty.Value, schemaVersion int) *InstanceState { 1670 attrs := hcl2shim.FlatmapValueFromHCL2(state) 1671 return &InstanceState{ 1672 ID: attrs["id"], 1673 Attributes: attrs, 1674 Meta: map[string]interface{}{ 1675 "schema_version": schemaVersion, 1676 }, 1677 } 1678 } 1679 1680 // AttrsAsObjectValue shims from the legacy InstanceState representation to 1681 // a new-style cty object value representation of the state attributes, using 1682 // the given type for guidance. 1683 // 1684 // The given type must be the implied type of the schema of the resource type 1685 // of the object whose state is being converted, or the result is undefined. 1686 // 1687 // This is for shimming from old components only and should not be used in 1688 // new code. 1689 func (s *InstanceState) AttrsAsObjectValue(ty cty.Type) (cty.Value, error) { 1690 if s == nil { 1691 // if the state is nil, we need to construct a complete cty.Value with 1692 // null attributes, rather than a single cty.NullVal(ty) 1693 s = &InstanceState{} 1694 } 1695 1696 if s.Attributes == nil { 1697 s.Attributes = map[string]string{} 1698 } 1699 1700 // make sure ID is included in the attributes. The InstanceState.ID value 1701 // takes precedence. 1702 if s.ID != "" { 1703 s.Attributes["id"] = s.ID 1704 } 1705 1706 return hcl2shim.HCL2ValueFromFlatmap(s.Attributes, ty) 1707 } 1708 1709 // Copy all the Fields from another InstanceState 1710 func (s *InstanceState) Set(from *InstanceState) { 1711 s.Lock() 1712 defer s.Unlock() 1713 1714 from.Lock() 1715 defer from.Unlock() 1716 1717 s.ID = from.ID 1718 s.Attributes = from.Attributes 1719 s.Ephemeral = from.Ephemeral 1720 s.Meta = from.Meta 1721 s.Tainted = from.Tainted 1722 } 1723 1724 func (s *InstanceState) DeepCopy() *InstanceState { 1725 copy, err := copystructure.Config{Lock: true}.Copy(s) 1726 if err != nil { 1727 panic(err) 1728 } 1729 1730 return copy.(*InstanceState) 1731 } 1732 1733 func (s *InstanceState) Empty() bool { 1734 if s == nil { 1735 return true 1736 } 1737 s.Lock() 1738 defer s.Unlock() 1739 1740 return s.ID == "" 1741 } 1742 1743 func (s *InstanceState) Equal(other *InstanceState) bool { 1744 // Short circuit some nil checks 1745 if s == nil || other == nil { 1746 return s == other 1747 } 1748 s.Lock() 1749 defer s.Unlock() 1750 1751 // IDs must be equal 1752 if s.ID != other.ID { 1753 return false 1754 } 1755 1756 // Attributes must be equal 1757 if len(s.Attributes) != len(other.Attributes) { 1758 return false 1759 } 1760 for k, v := range s.Attributes { 1761 otherV, ok := other.Attributes[k] 1762 if !ok { 1763 return false 1764 } 1765 1766 if v != otherV { 1767 return false 1768 } 1769 } 1770 1771 // Meta must be equal 1772 if len(s.Meta) != len(other.Meta) { 1773 return false 1774 } 1775 if s.Meta != nil && other.Meta != nil { 1776 // We only do the deep check if both are non-nil. If one is nil 1777 // we treat it as equal since their lengths are both zero (check 1778 // above). 1779 // 1780 // Since this can contain numeric values that may change types during 1781 // serialization, let's compare the serialized values. 1782 sMeta, err := json.Marshal(s.Meta) 1783 if err != nil { 1784 // marshaling primitives shouldn't ever error out 1785 panic(err) 1786 } 1787 otherMeta, err := json.Marshal(other.Meta) 1788 if err != nil { 1789 panic(err) 1790 } 1791 1792 if !bytes.Equal(sMeta, otherMeta) { 1793 return false 1794 } 1795 } 1796 1797 if s.Tainted != other.Tainted { 1798 return false 1799 } 1800 1801 return true 1802 } 1803 1804 // MergeDiff takes a ResourceDiff and merges the attributes into 1805 // this resource state in order to generate a new state. This new 1806 // state can be used to provide updated attribute lookups for 1807 // variable interpolation. 1808 // 1809 // If the diff attribute requires computing the value, and hence 1810 // won't be available until apply, the value is replaced with the 1811 // computeID. 1812 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 1813 result := s.DeepCopy() 1814 if result == nil { 1815 result = new(InstanceState) 1816 } 1817 result.init() 1818 1819 if s != nil { 1820 s.Lock() 1821 defer s.Unlock() 1822 for k, v := range s.Attributes { 1823 result.Attributes[k] = v 1824 } 1825 } 1826 if d != nil { 1827 for k, diff := range d.CopyAttributes() { 1828 if diff.NewRemoved { 1829 delete(result.Attributes, k) 1830 continue 1831 } 1832 if diff.NewComputed { 1833 result.Attributes[k] = hcl2shim.UnknownVariableValue 1834 continue 1835 } 1836 1837 result.Attributes[k] = diff.New 1838 } 1839 } 1840 1841 return result 1842 } 1843 1844 func (s *InstanceState) String() string { 1845 notCreated := "<not created>" 1846 1847 if s == nil { 1848 return notCreated 1849 } 1850 1851 s.Lock() 1852 defer s.Unlock() 1853 1854 var buf bytes.Buffer 1855 1856 if s.ID == "" { 1857 return notCreated 1858 } 1859 1860 buf.WriteString(fmt.Sprintf("ID = %s\n", s.ID)) 1861 1862 attributes := s.Attributes 1863 attrKeys := make([]string, 0, len(attributes)) 1864 for ak, _ := range attributes { 1865 if ak == "id" { 1866 continue 1867 } 1868 1869 attrKeys = append(attrKeys, ak) 1870 } 1871 sort.Strings(attrKeys) 1872 1873 for _, ak := range attrKeys { 1874 av := attributes[ak] 1875 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1876 } 1877 1878 buf.WriteString(fmt.Sprintf("Tainted = %t\n", s.Tainted)) 1879 1880 return buf.String() 1881 } 1882 1883 // EphemeralState is used for transient state that is only kept in-memory 1884 type EphemeralState struct { 1885 // ConnInfo is used for the providers to export information which is 1886 // used to connect to the resource for provisioning. For example, 1887 // this could contain SSH or WinRM credentials. 1888 ConnInfo map[string]string `json:"-"` 1889 1890 // Type is used to specify the resource type for this instance. This is only 1891 // required for import operations (as documented). If the documentation 1892 // doesn't state that you need to set this, then don't worry about 1893 // setting it. 1894 Type string `json:"-"` 1895 } 1896 1897 func (e *EphemeralState) init() { 1898 if e.ConnInfo == nil { 1899 e.ConnInfo = make(map[string]string) 1900 } 1901 } 1902 1903 func (e *EphemeralState) DeepCopy() *EphemeralState { 1904 copy, err := copystructure.Config{Lock: true}.Copy(e) 1905 if err != nil { 1906 panic(err) 1907 } 1908 1909 return copy.(*EphemeralState) 1910 } 1911 1912 type jsonStateVersionIdentifier struct { 1913 Version int `json:"version"` 1914 } 1915 1916 // Check if this is a V0 format - the magic bytes at the start of the file 1917 // should be "tfstate" if so. We no longer support upgrading this type of 1918 // state but return an error message explaining to a user how they can 1919 // upgrade via the 0.6.x series. 1920 func testForV0State(buf *bufio.Reader) error { 1921 start, err := buf.Peek(len("tfstate")) 1922 if err != nil { 1923 return fmt.Errorf("Failed to check for magic bytes: %w", err) 1924 } 1925 if string(start) == "tfstate" { 1926 return fmt.Errorf("OpenTofu 0.7 no longer supports upgrading the binary state\n" + 1927 "format which was used prior to OpenTofu 0.3. Please upgrade\n" + 1928 "this state file using OpenTofu 0.6.16 prior to using it with\n" + 1929 "OpenTofu 0.7.") 1930 } 1931 1932 return nil 1933 } 1934 1935 // ErrNoState is returned by ReadState when the io.Reader contains no data 1936 var ErrNoState = errors.New("no state") 1937 1938 // ReadState reads a state structure out of a reader in the format that 1939 // was written by WriteState. 1940 func ReadState(src io.Reader) (*State, error) { 1941 // check for a nil file specifically, since that produces a platform 1942 // specific error if we try to use it in a bufio.Reader. 1943 if f, ok := src.(*os.File); ok && f == nil { 1944 return nil, ErrNoState 1945 } 1946 1947 buf := bufio.NewReader(src) 1948 1949 if _, err := buf.Peek(1); err != nil { 1950 if err == io.EOF { 1951 return nil, ErrNoState 1952 } 1953 return nil, err 1954 } 1955 1956 if err := testForV0State(buf); err != nil { 1957 return nil, err 1958 } 1959 1960 // If we are JSON we buffer the whole thing in memory so we can read it twice. 1961 // This is suboptimal, but will work for now. 1962 jsonBytes, err := io.ReadAll(buf) 1963 if err != nil { 1964 return nil, fmt.Errorf("Reading state file failed: %w", err) 1965 } 1966 1967 versionIdentifier := &jsonStateVersionIdentifier{} 1968 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil { 1969 return nil, fmt.Errorf("Decoding state file version failed: %w", err) 1970 } 1971 1972 var result *State 1973 switch versionIdentifier.Version { 1974 case 0: 1975 return nil, fmt.Errorf("State version 0 is not supported as JSON.") 1976 case 1: 1977 v1State, err := ReadStateV1(jsonBytes) 1978 if err != nil { 1979 return nil, err 1980 } 1981 1982 v2State, err := upgradeStateV1ToV2(v1State) 1983 if err != nil { 1984 return nil, err 1985 } 1986 1987 v3State, err := upgradeStateV2ToV3(v2State) 1988 if err != nil { 1989 return nil, err 1990 } 1991 1992 // increment the Serial whenever we upgrade state 1993 v3State.Serial++ 1994 result = v3State 1995 case 2: 1996 v2State, err := ReadStateV2(jsonBytes) 1997 if err != nil { 1998 return nil, err 1999 } 2000 v3State, err := upgradeStateV2ToV3(v2State) 2001 if err != nil { 2002 return nil, err 2003 } 2004 2005 v3State.Serial++ 2006 result = v3State 2007 case 3: 2008 v3State, err := ReadStateV3(jsonBytes) 2009 if err != nil { 2010 return nil, err 2011 } 2012 2013 result = v3State 2014 default: 2015 return nil, fmt.Errorf("OpenTofu %s does not support state version %d, please update.", 2016 tfversion.SemVer.String(), versionIdentifier.Version) 2017 } 2018 2019 // If we reached this place we must have a result set 2020 if result == nil { 2021 panic("resulting state in load not set, assertion failed") 2022 } 2023 2024 // Prune the state when read it. Its possible to write unpruned states or 2025 // for a user to make a state unpruned (nil-ing a module state for example). 2026 result.prune() 2027 2028 // Validate the state file is valid 2029 if err := result.Validate(); err != nil { 2030 return nil, err 2031 } 2032 2033 return result, nil 2034 } 2035 2036 func ReadStateV1(jsonBytes []byte) (*stateV1, error) { 2037 v1State := &stateV1{} 2038 if err := json.Unmarshal(jsonBytes, v1State); err != nil { 2039 return nil, fmt.Errorf("Decoding state file failed: %w", err) 2040 } 2041 2042 if v1State.Version != 1 { 2043 return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+ 2044 "read %d, expected 1", v1State.Version) 2045 } 2046 2047 return v1State, nil 2048 } 2049 2050 func ReadStateV2(jsonBytes []byte) (*State, error) { 2051 state := &State{} 2052 if err := json.Unmarshal(jsonBytes, state); err != nil { 2053 return nil, fmt.Errorf("Decoding state file failed: %w", err) 2054 } 2055 2056 // Check the version, this to ensure we don't read a future 2057 // version that we don't understand 2058 if state.Version > StateVersion { 2059 return nil, fmt.Errorf("OpenTofu %s does not support state version %d, please update.", 2060 tfversion.SemVer.String(), state.Version) 2061 } 2062 2063 // Make sure the version is semantic 2064 if state.TFVersion != "" { 2065 if _, err := version.NewVersion(state.TFVersion); err != nil { 2066 return nil, fmt.Errorf( 2067 "State contains invalid version: %s\n\n"+ 2068 "OpenTofu validates the version format prior to writing it. This\n"+ 2069 "means that this is invalid of the state becoming corrupted through\n"+ 2070 "some external means. Please manually modify the OpenTofu version\n"+ 2071 "field to be a proper semantic version.", 2072 state.TFVersion) 2073 } 2074 } 2075 2076 // catch any unitialized fields in the state 2077 state.init() 2078 2079 // Sort it 2080 state.sort() 2081 2082 return state, nil 2083 } 2084 2085 func ReadStateV3(jsonBytes []byte) (*State, error) { 2086 state := &State{} 2087 if err := json.Unmarshal(jsonBytes, state); err != nil { 2088 return nil, fmt.Errorf("Decoding state file failed: %w", err) 2089 } 2090 2091 // Check the version, this to ensure we don't read a future 2092 // version that we don't understand 2093 if state.Version > StateVersion { 2094 return nil, fmt.Errorf("OpenTofu %s does not support state version %d, please update.", 2095 tfversion.SemVer.String(), state.Version) 2096 } 2097 2098 // Make sure the version is semantic 2099 if state.TFVersion != "" { 2100 if _, err := version.NewVersion(state.TFVersion); err != nil { 2101 return nil, fmt.Errorf( 2102 "State contains invalid version: %s\n\n"+ 2103 "OpenTofu validates the version format prior to writing it. This\n"+ 2104 "means that this is invalid of the state becoming corrupted through\n"+ 2105 "some external means. Please manually modify the OpenTofu version\n"+ 2106 "field to be a proper semantic version.", 2107 state.TFVersion) 2108 } 2109 } 2110 2111 // catch any unitialized fields in the state 2112 state.init() 2113 2114 // Sort it 2115 state.sort() 2116 2117 // Now we write the state back out to detect any changes in normaliztion. 2118 // If our state is now written out differently, bump the serial number to 2119 // prevent conflicts. 2120 var buf bytes.Buffer 2121 err := WriteState(state, &buf) 2122 if err != nil { 2123 return nil, err 2124 } 2125 2126 if !bytes.Equal(jsonBytes, buf.Bytes()) { 2127 log.Println("[INFO] state modified during read or write. incrementing serial number") 2128 state.Serial++ 2129 } 2130 2131 return state, nil 2132 } 2133 2134 // WriteState writes a state somewhere in a binary format. 2135 func WriteState(d *State, dst io.Writer) error { 2136 // writing a nil state is a noop. 2137 if d == nil { 2138 return nil 2139 } 2140 2141 // make sure we have no uninitialized fields 2142 d.init() 2143 2144 // Make sure it is sorted 2145 d.sort() 2146 2147 // Ensure the version is set 2148 d.Version = StateVersion 2149 2150 // If the TFVersion is set, verify it. We used to just set the version 2151 // here, but this isn't safe since it changes the MD5 sum on some remote 2152 // state storage backends such as Atlas. We now leave it be if needed. 2153 if d.TFVersion != "" { 2154 if _, err := version.NewVersion(d.TFVersion); err != nil { 2155 return fmt.Errorf( 2156 "Error writing state, invalid version: %s\n\n"+ 2157 "The OpenTofu version when writing the state must be a semantic\n"+ 2158 "version.", 2159 d.TFVersion) 2160 } 2161 } 2162 2163 // Encode the data in a human-friendly way 2164 data, err := json.MarshalIndent(d, "", " ") 2165 if err != nil { 2166 return fmt.Errorf("Failed to encode state: %w", err) 2167 } 2168 2169 // We append a newline to the data because MarshalIndent doesn't 2170 data = append(data, '\n') 2171 2172 // Write the data out to the dst 2173 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 2174 return fmt.Errorf("Failed to write state: %w", err) 2175 } 2176 2177 return nil 2178 } 2179 2180 // resourceNameSort implements the sort.Interface to sort name parts lexically for 2181 // strings and numerically for integer indexes. 2182 type resourceNameSort []string 2183 2184 func (r resourceNameSort) Len() int { return len(r) } 2185 func (r resourceNameSort) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 2186 2187 func (r resourceNameSort) Less(i, j int) bool { 2188 iParts := strings.Split(r[i], ".") 2189 jParts := strings.Split(r[j], ".") 2190 2191 end := len(iParts) 2192 if len(jParts) < end { 2193 end = len(jParts) 2194 } 2195 2196 for idx := 0; idx < end; idx++ { 2197 if iParts[idx] == jParts[idx] { 2198 continue 2199 } 2200 2201 // sort on the first non-matching part 2202 iInt, iIntErr := strconv.Atoi(iParts[idx]) 2203 jInt, jIntErr := strconv.Atoi(jParts[idx]) 2204 2205 switch { 2206 case iIntErr == nil && jIntErr == nil: 2207 // sort numerically if both parts are integers 2208 return iInt < jInt 2209 case iIntErr == nil: 2210 // numbers sort before strings 2211 return true 2212 case jIntErr == nil: 2213 return false 2214 default: 2215 return iParts[idx] < jParts[idx] 2216 } 2217 } 2218 2219 return r[i] < r[j] 2220 } 2221 2222 // moduleStateSort implements sort.Interface to sort module states 2223 type moduleStateSort []*ModuleState 2224 2225 func (s moduleStateSort) Len() int { 2226 return len(s) 2227 } 2228 2229 func (s moduleStateSort) Less(i, j int) bool { 2230 a := s[i] 2231 b := s[j] 2232 2233 // If either is nil, then the nil one is "less" than 2234 if a == nil || b == nil { 2235 return a == nil 2236 } 2237 2238 // If the lengths are different, then the shorter one always wins 2239 if len(a.Path) != len(b.Path) { 2240 return len(a.Path) < len(b.Path) 2241 } 2242 2243 // Otherwise, compare lexically 2244 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".") 2245 } 2246 2247 func (s moduleStateSort) Swap(i, j int) { 2248 s[i], s[j] = s[j], s[i] 2249 } 2250 2251 const stateValidateErrMultiModule = ` 2252 Multiple modules with the same path: %s 2253 2254 This means that there are multiple entries in the "modules" field 2255 in your state file that point to the same module. This will cause OpenTofu 2256 to behave in unexpected and error prone ways and is invalid. Please back up 2257 and modify your state file manually to resolve this. 2258 `