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