github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/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/iaas-resource-provision/iaas-rpc/internal/addrs" 26 "github.com/iaas-resource-provision/iaas-rpc/internal/configs" 27 "github.com/iaas-resource-provision/iaas-rpc/internal/configs/configschema" 28 "github.com/iaas-resource-provision/iaas-rpc/internal/configs/hcl2shim" 29 "github.com/iaas-resource-provision/iaas-rpc/internal/plans" 30 "github.com/iaas-resource-provision/iaas-rpc/internal/tfdiags" 31 tfversion "github.com/iaas-resource-provision/iaas-rpc/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 // 1429 type ResourceState struct { 1430 // This is filled in and managed by Terraform, and is the resource 1431 // type itself such as "mycloud_instance". If a resource provider sets 1432 // this value, it won't be persisted. 1433 Type string `json:"type"` 1434 1435 // Dependencies are a list of things that this resource relies on 1436 // existing to remain intact. For example: an AWS instance might 1437 // depend on a subnet (which itself might depend on a VPC, and so 1438 // on). 1439 // 1440 // Terraform uses this information to build valid destruction 1441 // orders and to warn the user if they're destroying a resource that 1442 // another resource depends on. 1443 // 1444 // Things can be put into this list that may not be managed by 1445 // Terraform. If Terraform doesn't find a matching ID in the 1446 // overall state, then it assumes it isn't managed and doesn't 1447 // worry about it. 1448 Dependencies []string `json:"depends_on"` 1449 1450 // Primary is the current active instance for this resource. 1451 // It can be replaced but only after a successful creation. 1452 // This is the instances on which providers will act. 1453 Primary *InstanceState `json:"primary"` 1454 1455 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 1456 // Primary is Deposed to get it out of the way for the replacement Primary to 1457 // be created by Apply. If the replacement Primary creates successfully, the 1458 // Deposed instance is cleaned up. 1459 // 1460 // If there were problems creating the replacement Primary, the Deposed 1461 // instance and the (now tainted) replacement Primary will be swapped so the 1462 // tainted replacement will be cleaned up instead. 1463 // 1464 // An instance will remain in the Deposed list until it is successfully 1465 // destroyed and purged. 1466 Deposed []*InstanceState `json:"deposed"` 1467 1468 // Provider is used when a resource is connected to a provider with an alias. 1469 // If this string is empty, the resource is connected to the default provider, 1470 // e.g. "aws_instance" goes with the "aws" provider. 1471 // If the resource block contained a "provider" key, that value will be set here. 1472 Provider string `json:"provider"` 1473 1474 mu sync.Mutex 1475 } 1476 1477 func (s *ResourceState) Lock() { s.mu.Lock() } 1478 func (s *ResourceState) Unlock() { s.mu.Unlock() } 1479 1480 // Equal tests whether two ResourceStates are equal. 1481 func (s *ResourceState) Equal(other *ResourceState) bool { 1482 s.Lock() 1483 defer s.Unlock() 1484 1485 if s.Type != other.Type { 1486 return false 1487 } 1488 1489 if s.Provider != other.Provider { 1490 return false 1491 } 1492 1493 // Dependencies must be equal 1494 sort.Strings(s.Dependencies) 1495 sort.Strings(other.Dependencies) 1496 if len(s.Dependencies) != len(other.Dependencies) { 1497 return false 1498 } 1499 for i, d := range s.Dependencies { 1500 if other.Dependencies[i] != d { 1501 return false 1502 } 1503 } 1504 1505 // States must be equal 1506 if !s.Primary.Equal(other.Primary) { 1507 return false 1508 } 1509 1510 return true 1511 } 1512 1513 // Taint marks a resource as tainted. 1514 func (s *ResourceState) Taint() { 1515 s.Lock() 1516 defer s.Unlock() 1517 1518 if s.Primary != nil { 1519 s.Primary.Tainted = true 1520 } 1521 } 1522 1523 // Untaint unmarks a resource as tainted. 1524 func (s *ResourceState) Untaint() { 1525 s.Lock() 1526 defer s.Unlock() 1527 1528 if s.Primary != nil { 1529 s.Primary.Tainted = false 1530 } 1531 } 1532 1533 // ProviderAddr returns the provider address for the receiver, by parsing the 1534 // string representation saved in state. An error can be returned if the 1535 // value in state is corrupt. 1536 func (s *ResourceState) ProviderAddr() (addrs.AbsProviderConfig, error) { 1537 var diags tfdiags.Diagnostics 1538 1539 str := s.Provider 1540 traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1}) 1541 diags = diags.Append(travDiags) 1542 if travDiags.HasErrors() { 1543 return addrs.AbsProviderConfig{}, diags.Err() 1544 } 1545 1546 addr, addrDiags := addrs.ParseAbsProviderConfig(traversal) 1547 diags = diags.Append(addrDiags) 1548 return addr, diags.Err() 1549 } 1550 1551 func (s *ResourceState) init() { 1552 s.Lock() 1553 defer s.Unlock() 1554 1555 if s.Primary == nil { 1556 s.Primary = &InstanceState{} 1557 } 1558 s.Primary.init() 1559 1560 if s.Dependencies == nil { 1561 s.Dependencies = []string{} 1562 } 1563 1564 if s.Deposed == nil { 1565 s.Deposed = make([]*InstanceState, 0) 1566 } 1567 } 1568 1569 func (s *ResourceState) deepcopy() *ResourceState { 1570 copy, err := copystructure.Config{Lock: true}.Copy(s) 1571 if err != nil { 1572 panic(err) 1573 } 1574 1575 return copy.(*ResourceState) 1576 } 1577 1578 // prune is used to remove any instances that are no longer required 1579 func (s *ResourceState) prune() { 1580 s.Lock() 1581 defer s.Unlock() 1582 1583 n := len(s.Deposed) 1584 for i := 0; i < n; i++ { 1585 inst := s.Deposed[i] 1586 if inst == nil || inst.ID == "" { 1587 copy(s.Deposed[i:], s.Deposed[i+1:]) 1588 s.Deposed[n-1] = nil 1589 n-- 1590 i-- 1591 } 1592 } 1593 s.Deposed = s.Deposed[:n] 1594 1595 s.Dependencies = uniqueStrings(s.Dependencies) 1596 } 1597 1598 func (s *ResourceState) sort() { 1599 s.Lock() 1600 defer s.Unlock() 1601 1602 sort.Strings(s.Dependencies) 1603 } 1604 1605 func (s *ResourceState) String() string { 1606 s.Lock() 1607 defer s.Unlock() 1608 1609 var buf bytes.Buffer 1610 buf.WriteString(fmt.Sprintf("Type = %s", s.Type)) 1611 return buf.String() 1612 } 1613 1614 // InstanceState is used to track the unique state information belonging 1615 // to a given instance. 1616 type InstanceState struct { 1617 // A unique ID for this resource. This is opaque to Terraform 1618 // and is only meant as a lookup mechanism for the providers. 1619 ID string `json:"id"` 1620 1621 // Attributes are basic information about the resource. Any keys here 1622 // are accessible in variable format within Terraform configurations: 1623 // ${resourcetype.name.attribute}. 1624 Attributes map[string]string `json:"attributes"` 1625 1626 // Ephemeral is used to store any state associated with this instance 1627 // that is necessary for the Terraform run to complete, but is not 1628 // persisted to a state file. 1629 Ephemeral EphemeralState `json:"-"` 1630 1631 // Meta is a simple K/V map that is persisted to the State but otherwise 1632 // ignored by Terraform core. It's meant to be used for accounting by 1633 // external client code. The value here must only contain Go primitives 1634 // and collections. 1635 Meta map[string]interface{} `json:"meta"` 1636 1637 ProviderMeta cty.Value 1638 1639 // Tainted is used to mark a resource for recreation. 1640 Tainted bool `json:"tainted"` 1641 1642 mu sync.Mutex 1643 } 1644 1645 func (s *InstanceState) Lock() { s.mu.Lock() } 1646 func (s *InstanceState) Unlock() { s.mu.Unlock() } 1647 1648 func (s *InstanceState) init() { 1649 s.Lock() 1650 defer s.Unlock() 1651 1652 if s.Attributes == nil { 1653 s.Attributes = make(map[string]string) 1654 } 1655 if s.Meta == nil { 1656 s.Meta = make(map[string]interface{}) 1657 } 1658 s.Ephemeral.init() 1659 } 1660 1661 // NewInstanceStateShimmedFromValue is a shim method to lower a new-style 1662 // object value representing the attributes of an instance object into the 1663 // legacy InstanceState representation. 1664 // 1665 // This is for shimming to old components only and should not be used in new code. 1666 func NewInstanceStateShimmedFromValue(state cty.Value, schemaVersion int) *InstanceState { 1667 attrs := hcl2shim.FlatmapValueFromHCL2(state) 1668 return &InstanceState{ 1669 ID: attrs["id"], 1670 Attributes: attrs, 1671 Meta: map[string]interface{}{ 1672 "schema_version": schemaVersion, 1673 }, 1674 } 1675 } 1676 1677 // AttrsAsObjectValue shims from the legacy InstanceState representation to 1678 // a new-style cty object value representation of the state attributes, using 1679 // the given type for guidance. 1680 // 1681 // The given type must be the implied type of the schema of the resource type 1682 // of the object whose state is being converted, or the result is undefined. 1683 // 1684 // This is for shimming from old components only and should not be used in 1685 // new code. 1686 func (s *InstanceState) AttrsAsObjectValue(ty cty.Type) (cty.Value, error) { 1687 if s == nil { 1688 // if the state is nil, we need to construct a complete cty.Value with 1689 // null attributes, rather than a single cty.NullVal(ty) 1690 s = &InstanceState{} 1691 } 1692 1693 if s.Attributes == nil { 1694 s.Attributes = map[string]string{} 1695 } 1696 1697 // make sure ID is included in the attributes. The InstanceState.ID value 1698 // takes precedence. 1699 if s.ID != "" { 1700 s.Attributes["id"] = s.ID 1701 } 1702 1703 return hcl2shim.HCL2ValueFromFlatmap(s.Attributes, ty) 1704 } 1705 1706 // Copy all the Fields from another InstanceState 1707 func (s *InstanceState) Set(from *InstanceState) { 1708 s.Lock() 1709 defer s.Unlock() 1710 1711 from.Lock() 1712 defer from.Unlock() 1713 1714 s.ID = from.ID 1715 s.Attributes = from.Attributes 1716 s.Ephemeral = from.Ephemeral 1717 s.Meta = from.Meta 1718 s.Tainted = from.Tainted 1719 } 1720 1721 func (s *InstanceState) DeepCopy() *InstanceState { 1722 copy, err := copystructure.Config{Lock: true}.Copy(s) 1723 if err != nil { 1724 panic(err) 1725 } 1726 1727 return copy.(*InstanceState) 1728 } 1729 1730 func (s *InstanceState) Empty() bool { 1731 if s == nil { 1732 return true 1733 } 1734 s.Lock() 1735 defer s.Unlock() 1736 1737 return s.ID == "" 1738 } 1739 1740 func (s *InstanceState) Equal(other *InstanceState) bool { 1741 // Short circuit some nil checks 1742 if s == nil || other == nil { 1743 return s == other 1744 } 1745 s.Lock() 1746 defer s.Unlock() 1747 1748 // IDs must be equal 1749 if s.ID != other.ID { 1750 return false 1751 } 1752 1753 // Attributes must be equal 1754 if len(s.Attributes) != len(other.Attributes) { 1755 return false 1756 } 1757 for k, v := range s.Attributes { 1758 otherV, ok := other.Attributes[k] 1759 if !ok { 1760 return false 1761 } 1762 1763 if v != otherV { 1764 return false 1765 } 1766 } 1767 1768 // Meta must be equal 1769 if len(s.Meta) != len(other.Meta) { 1770 return false 1771 } 1772 if s.Meta != nil && other.Meta != nil { 1773 // We only do the deep check if both are non-nil. If one is nil 1774 // we treat it as equal since their lengths are both zero (check 1775 // above). 1776 // 1777 // Since this can contain numeric values that may change types during 1778 // serialization, let's compare the serialized values. 1779 sMeta, err := json.Marshal(s.Meta) 1780 if err != nil { 1781 // marshaling primitives shouldn't ever error out 1782 panic(err) 1783 } 1784 otherMeta, err := json.Marshal(other.Meta) 1785 if err != nil { 1786 panic(err) 1787 } 1788 1789 if !bytes.Equal(sMeta, otherMeta) { 1790 return false 1791 } 1792 } 1793 1794 if s.Tainted != other.Tainted { 1795 return false 1796 } 1797 1798 return true 1799 } 1800 1801 // MergeDiff takes a ResourceDiff and merges the attributes into 1802 // this resource state in order to generate a new state. This new 1803 // state can be used to provide updated attribute lookups for 1804 // variable interpolation. 1805 // 1806 // If the diff attribute requires computing the value, and hence 1807 // won't be available until apply, the value is replaced with the 1808 // computeID. 1809 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 1810 result := s.DeepCopy() 1811 if result == nil { 1812 result = new(InstanceState) 1813 } 1814 result.init() 1815 1816 if s != nil { 1817 s.Lock() 1818 defer s.Unlock() 1819 for k, v := range s.Attributes { 1820 result.Attributes[k] = v 1821 } 1822 } 1823 if d != nil { 1824 for k, diff := range d.CopyAttributes() { 1825 if diff.NewRemoved { 1826 delete(result.Attributes, k) 1827 continue 1828 } 1829 if diff.NewComputed { 1830 result.Attributes[k] = hcl2shim.UnknownVariableValue 1831 continue 1832 } 1833 1834 result.Attributes[k] = diff.New 1835 } 1836 } 1837 1838 return result 1839 } 1840 1841 func (s *InstanceState) String() string { 1842 notCreated := "<not created>" 1843 1844 if s == nil { 1845 return notCreated 1846 } 1847 1848 s.Lock() 1849 defer s.Unlock() 1850 1851 var buf bytes.Buffer 1852 1853 if s.ID == "" { 1854 return notCreated 1855 } 1856 1857 buf.WriteString(fmt.Sprintf("ID = %s\n", s.ID)) 1858 1859 attributes := s.Attributes 1860 attrKeys := make([]string, 0, len(attributes)) 1861 for ak, _ := range attributes { 1862 if ak == "id" { 1863 continue 1864 } 1865 1866 attrKeys = append(attrKeys, ak) 1867 } 1868 sort.Strings(attrKeys) 1869 1870 for _, ak := range attrKeys { 1871 av := attributes[ak] 1872 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1873 } 1874 1875 buf.WriteString(fmt.Sprintf("Tainted = %t\n", s.Tainted)) 1876 1877 return buf.String() 1878 } 1879 1880 // EphemeralState is used for transient state that is only kept in-memory 1881 type EphemeralState struct { 1882 // ConnInfo is used for the providers to export information which is 1883 // used to connect to the resource for provisioning. For example, 1884 // this could contain SSH or WinRM credentials. 1885 ConnInfo map[string]string `json:"-"` 1886 1887 // Type is used to specify the resource type for this instance. This is only 1888 // required for import operations (as documented). If the documentation 1889 // doesn't state that you need to set this, then don't worry about 1890 // setting it. 1891 Type string `json:"-"` 1892 } 1893 1894 func (e *EphemeralState) init() { 1895 if e.ConnInfo == nil { 1896 e.ConnInfo = make(map[string]string) 1897 } 1898 } 1899 1900 func (e *EphemeralState) DeepCopy() *EphemeralState { 1901 copy, err := copystructure.Config{Lock: true}.Copy(e) 1902 if err != nil { 1903 panic(err) 1904 } 1905 1906 return copy.(*EphemeralState) 1907 } 1908 1909 type jsonStateVersionIdentifier struct { 1910 Version int `json:"version"` 1911 } 1912 1913 // Check if this is a V0 format - the magic bytes at the start of the file 1914 // should be "tfstate" if so. We no longer support upgrading this type of 1915 // state but return an error message explaining to a user how they can 1916 // upgrade via the 0.6.x series. 1917 func testForV0State(buf *bufio.Reader) error { 1918 start, err := buf.Peek(len("tfstate")) 1919 if err != nil { 1920 return fmt.Errorf("Failed to check for magic bytes: %v", err) 1921 } 1922 if string(start) == "tfstate" { 1923 return fmt.Errorf("Terraform 0.7 no longer supports upgrading the binary state\n" + 1924 "format which was used prior to Terraform 0.3. Please upgrade\n" + 1925 "this state file using Terraform 0.6.16 prior to using it with\n" + 1926 "Terraform 0.7.") 1927 } 1928 1929 return nil 1930 } 1931 1932 // ErrNoState is returned by ReadState when the io.Reader contains no data 1933 var ErrNoState = errors.New("no state") 1934 1935 // ReadState reads a state structure out of a reader in the format that 1936 // was written by WriteState. 1937 func ReadState(src io.Reader) (*State, error) { 1938 // check for a nil file specifically, since that produces a platform 1939 // specific error if we try to use it in a bufio.Reader. 1940 if f, ok := src.(*os.File); ok && f == nil { 1941 return nil, ErrNoState 1942 } 1943 1944 buf := bufio.NewReader(src) 1945 1946 if _, err := buf.Peek(1); err != nil { 1947 if err == io.EOF { 1948 return nil, ErrNoState 1949 } 1950 return nil, err 1951 } 1952 1953 if err := testForV0State(buf); err != nil { 1954 return nil, err 1955 } 1956 1957 // If we are JSON we buffer the whole thing in memory so we can read it twice. 1958 // This is suboptimal, but will work for now. 1959 jsonBytes, err := ioutil.ReadAll(buf) 1960 if err != nil { 1961 return nil, fmt.Errorf("Reading state file failed: %v", err) 1962 } 1963 1964 versionIdentifier := &jsonStateVersionIdentifier{} 1965 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil { 1966 return nil, fmt.Errorf("Decoding state file version failed: %v", err) 1967 } 1968 1969 var result *State 1970 switch versionIdentifier.Version { 1971 case 0: 1972 return nil, fmt.Errorf("State version 0 is not supported as JSON.") 1973 case 1: 1974 v1State, err := ReadStateV1(jsonBytes) 1975 if err != nil { 1976 return nil, err 1977 } 1978 1979 v2State, err := upgradeStateV1ToV2(v1State) 1980 if err != nil { 1981 return nil, err 1982 } 1983 1984 v3State, err := upgradeStateV2ToV3(v2State) 1985 if err != nil { 1986 return nil, err 1987 } 1988 1989 // increment the Serial whenever we upgrade state 1990 v3State.Serial++ 1991 result = v3State 1992 case 2: 1993 v2State, err := ReadStateV2(jsonBytes) 1994 if err != nil { 1995 return nil, err 1996 } 1997 v3State, err := upgradeStateV2ToV3(v2State) 1998 if err != nil { 1999 return nil, err 2000 } 2001 2002 v3State.Serial++ 2003 result = v3State 2004 case 3: 2005 v3State, err := ReadStateV3(jsonBytes) 2006 if err != nil { 2007 return nil, err 2008 } 2009 2010 result = v3State 2011 default: 2012 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 2013 tfversion.SemVer.String(), versionIdentifier.Version) 2014 } 2015 2016 // If we reached this place we must have a result set 2017 if result == nil { 2018 panic("resulting state in load not set, assertion failed") 2019 } 2020 2021 // Prune the state when read it. Its possible to write unpruned states or 2022 // for a user to make a state unpruned (nil-ing a module state for example). 2023 result.prune() 2024 2025 // Validate the state file is valid 2026 if err := result.Validate(); err != nil { 2027 return nil, err 2028 } 2029 2030 return result, nil 2031 } 2032 2033 func ReadStateV1(jsonBytes []byte) (*stateV1, error) { 2034 v1State := &stateV1{} 2035 if err := json.Unmarshal(jsonBytes, v1State); err != nil { 2036 return nil, fmt.Errorf("Decoding state file failed: %v", err) 2037 } 2038 2039 if v1State.Version != 1 { 2040 return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+ 2041 "read %d, expected 1", v1State.Version) 2042 } 2043 2044 return v1State, nil 2045 } 2046 2047 func ReadStateV2(jsonBytes []byte) (*State, error) { 2048 state := &State{} 2049 if err := json.Unmarshal(jsonBytes, state); err != nil { 2050 return nil, fmt.Errorf("Decoding state file failed: %v", err) 2051 } 2052 2053 // Check the version, this to ensure we don't read a future 2054 // version that we don't understand 2055 if state.Version > StateVersion { 2056 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 2057 tfversion.SemVer.String(), state.Version) 2058 } 2059 2060 // Make sure the version is semantic 2061 if state.TFVersion != "" { 2062 if _, err := version.NewVersion(state.TFVersion); err != nil { 2063 return nil, fmt.Errorf( 2064 "State contains invalid version: %s\n\n"+ 2065 "Terraform validates the version format prior to writing it. This\n"+ 2066 "means that this is invalid of the state becoming corrupted through\n"+ 2067 "some external means. Please manually modify the Terraform version\n"+ 2068 "field to be a proper semantic version.", 2069 state.TFVersion) 2070 } 2071 } 2072 2073 // catch any unitialized fields in the state 2074 state.init() 2075 2076 // Sort it 2077 state.sort() 2078 2079 return state, nil 2080 } 2081 2082 func ReadStateV3(jsonBytes []byte) (*State, error) { 2083 state := &State{} 2084 if err := json.Unmarshal(jsonBytes, state); err != nil { 2085 return nil, fmt.Errorf("Decoding state file failed: %v", err) 2086 } 2087 2088 // Check the version, this to ensure we don't read a future 2089 // version that we don't understand 2090 if state.Version > StateVersion { 2091 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 2092 tfversion.SemVer.String(), state.Version) 2093 } 2094 2095 // Make sure the version is semantic 2096 if state.TFVersion != "" { 2097 if _, err := version.NewVersion(state.TFVersion); err != nil { 2098 return nil, fmt.Errorf( 2099 "State contains invalid version: %s\n\n"+ 2100 "Terraform validates the version format prior to writing it. This\n"+ 2101 "means that this is invalid of the state becoming corrupted through\n"+ 2102 "some external means. Please manually modify the Terraform version\n"+ 2103 "field to be a proper semantic version.", 2104 state.TFVersion) 2105 } 2106 } 2107 2108 // catch any unitialized fields in the state 2109 state.init() 2110 2111 // Sort it 2112 state.sort() 2113 2114 // Now we write the state back out to detect any changes in normaliztion. 2115 // If our state is now written out differently, bump the serial number to 2116 // prevent conflicts. 2117 var buf bytes.Buffer 2118 err := WriteState(state, &buf) 2119 if err != nil { 2120 return nil, err 2121 } 2122 2123 if !bytes.Equal(jsonBytes, buf.Bytes()) { 2124 log.Println("[INFO] state modified during read or write. incrementing serial number") 2125 state.Serial++ 2126 } 2127 2128 return state, nil 2129 } 2130 2131 // WriteState writes a state somewhere in a binary format. 2132 func WriteState(d *State, dst io.Writer) error { 2133 // writing a nil state is a noop. 2134 if d == nil { 2135 return nil 2136 } 2137 2138 // make sure we have no uninitialized fields 2139 d.init() 2140 2141 // Make sure it is sorted 2142 d.sort() 2143 2144 // Ensure the version is set 2145 d.Version = StateVersion 2146 2147 // If the TFVersion is set, verify it. We used to just set the version 2148 // here, but this isn't safe since it changes the MD5 sum on some remote 2149 // state storage backends such as Atlas. We now leave it be if needed. 2150 if d.TFVersion != "" { 2151 if _, err := version.NewVersion(d.TFVersion); err != nil { 2152 return fmt.Errorf( 2153 "Error writing state, invalid version: %s\n\n"+ 2154 "The Terraform version when writing the state must be a semantic\n"+ 2155 "version.", 2156 d.TFVersion) 2157 } 2158 } 2159 2160 // Encode the data in a human-friendly way 2161 data, err := json.MarshalIndent(d, "", " ") 2162 if err != nil { 2163 return fmt.Errorf("Failed to encode state: %s", err) 2164 } 2165 2166 // We append a newline to the data because MarshalIndent doesn't 2167 data = append(data, '\n') 2168 2169 // Write the data out to the dst 2170 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 2171 return fmt.Errorf("Failed to write state: %v", err) 2172 } 2173 2174 return nil 2175 } 2176 2177 // resourceNameSort implements the sort.Interface to sort name parts lexically for 2178 // strings and numerically for integer indexes. 2179 type resourceNameSort []string 2180 2181 func (r resourceNameSort) Len() int { return len(r) } 2182 func (r resourceNameSort) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 2183 2184 func (r resourceNameSort) Less(i, j int) bool { 2185 iParts := strings.Split(r[i], ".") 2186 jParts := strings.Split(r[j], ".") 2187 2188 end := len(iParts) 2189 if len(jParts) < end { 2190 end = len(jParts) 2191 } 2192 2193 for idx := 0; idx < end; idx++ { 2194 if iParts[idx] == jParts[idx] { 2195 continue 2196 } 2197 2198 // sort on the first non-matching part 2199 iInt, iIntErr := strconv.Atoi(iParts[idx]) 2200 jInt, jIntErr := strconv.Atoi(jParts[idx]) 2201 2202 switch { 2203 case iIntErr == nil && jIntErr == nil: 2204 // sort numerically if both parts are integers 2205 return iInt < jInt 2206 case iIntErr == nil: 2207 // numbers sort before strings 2208 return true 2209 case jIntErr == nil: 2210 return false 2211 default: 2212 return iParts[idx] < jParts[idx] 2213 } 2214 } 2215 2216 return r[i] < r[j] 2217 } 2218 2219 // moduleStateSort implements sort.Interface to sort module states 2220 type moduleStateSort []*ModuleState 2221 2222 func (s moduleStateSort) Len() int { 2223 return len(s) 2224 } 2225 2226 func (s moduleStateSort) Less(i, j int) bool { 2227 a := s[i] 2228 b := s[j] 2229 2230 // If either is nil, then the nil one is "less" than 2231 if a == nil || b == nil { 2232 return a == nil 2233 } 2234 2235 // If the lengths are different, then the shorter one always wins 2236 if len(a.Path) != len(b.Path) { 2237 return len(a.Path) < len(b.Path) 2238 } 2239 2240 // Otherwise, compare lexically 2241 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".") 2242 } 2243 2244 func (s moduleStateSort) Swap(i, j int) { 2245 s[i], s[j] = s[j], s[i] 2246 } 2247 2248 const stateValidateErrMultiModule = ` 2249 Multiple modules with the same path: %s 2250 2251 This means that there are multiple entries in the "modules" field 2252 in your state file that point to the same module. This will cause Terraform 2253 to behave in unexpected and error prone ways and is invalid. Please back up 2254 and modify your state file manually to resolve this. 2255 `