github.com/kwoods/terraform@v0.6.11-0.20160809170336-13497db7138e/terraform/state.go (about) 1 package terraform 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "log" 11 "reflect" 12 "sort" 13 "strconv" 14 "strings" 15 16 "github.com/hashicorp/go-version" 17 "github.com/hashicorp/terraform/config" 18 "github.com/mitchellh/copystructure" 19 "github.com/satori/go.uuid" 20 ) 21 22 const ( 23 // StateVersion is the current version for our state file 24 StateVersion = 3 25 ) 26 27 // rootModulePath is the path of the root module 28 var rootModulePath = []string{"root"} 29 30 // normalizeModulePath takes a raw module path and returns a path that 31 // has the rootModulePath prepended to it. If I could go back in time I 32 // would've never had a rootModulePath (empty path would be root). We can 33 // still fix this but thats a big refactor that my branch doesn't make sense 34 // for. Instead, this function normalizes paths. 35 func normalizeModulePath(p []string) []string { 36 k := len(rootModulePath) 37 38 // If we already have a root module prefix, we're done 39 if len(p) >= len(rootModulePath) { 40 if reflect.DeepEqual(p[:k], rootModulePath) { 41 return p 42 } 43 } 44 45 // None? Prefix it 46 result := make([]string, len(rootModulePath)+len(p)) 47 copy(result, rootModulePath) 48 copy(result[k:], p) 49 return result 50 } 51 52 // State keeps track of a snapshot state-of-the-world that Terraform 53 // can use to keep track of what real world resources it is actually 54 // managing. This is the latest format as of Terraform 0.3 55 type State struct { 56 // Version is the protocol version. Currently only "1". 57 Version int `json:"version"` 58 59 // TFVersion is the version of Terraform that wrote this state. 60 TFVersion string `json:"terraform_version,omitempty"` 61 62 // Serial is incremented on any operation that modifies 63 // the State file. It is used to detect potentially conflicting 64 // updates. 65 Serial int64 `json:"serial"` 66 67 // Lineage is set when a new, blank state is created and then 68 // never updated. This allows us to determine whether the serials 69 // of two states can be meaningfully compared. 70 // Apart from the guarantee that collisions between two lineages 71 // are very unlikely, this value is opaque and external callers 72 // should only compare lineage strings byte-for-byte for equality. 73 Lineage string `json:"lineage,omitempty"` 74 75 // Remote is used to track the metadata required to 76 // pull and push state files from a remote storage endpoint. 77 Remote *RemoteState `json:"remote,omitempty"` 78 79 // Modules contains all the modules in a breadth-first order 80 Modules []*ModuleState `json:"modules"` 81 } 82 83 // NewState is used to initialize a blank state 84 func NewState() *State { 85 s := &State{} 86 s.init() 87 return s 88 } 89 90 // Children returns the ModuleStates that are direct children of 91 // the given path. If the path is "root", for example, then children 92 // returned might be "root.child", but not "root.child.grandchild". 93 func (s *State) Children(path []string) []*ModuleState { 94 // TODO: test 95 96 result := make([]*ModuleState, 0) 97 for _, m := range s.Modules { 98 if len(m.Path) != len(path)+1 { 99 continue 100 } 101 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 102 continue 103 } 104 105 result = append(result, m) 106 } 107 108 return result 109 } 110 111 // AddModule adds the module with the given path to the state. 112 // 113 // This should be the preferred method to add module states since it 114 // allows us to optimize lookups later as well as control sorting. 115 func (s *State) AddModule(path []string) *ModuleState { 116 m := &ModuleState{Path: path} 117 m.init() 118 s.Modules = append(s.Modules, m) 119 s.sort() 120 return m 121 } 122 123 // ModuleByPath is used to lookup the module state for the given path. 124 // This should be the preferred lookup mechanism as it allows for future 125 // lookup optimizations. 126 func (s *State) ModuleByPath(path []string) *ModuleState { 127 if s == nil { 128 return nil 129 } 130 for _, mod := range s.Modules { 131 if mod.Path == nil { 132 panic("missing module path") 133 } 134 if reflect.DeepEqual(mod.Path, path) { 135 return mod 136 } 137 } 138 return nil 139 } 140 141 // ModuleOrphans returns all the module orphans in this state by 142 // returning their full paths. These paths can be used with ModuleByPath 143 // to return the actual state. 144 func (s *State) ModuleOrphans(path []string, c *config.Config) [][]string { 145 // direct keeps track of what direct children we have both in our config 146 // and in our state. childrenKeys keeps track of what isn't an orphan. 147 direct := make(map[string]struct{}) 148 childrenKeys := make(map[string]struct{}) 149 if c != nil { 150 for _, m := range c.Modules { 151 childrenKeys[m.Name] = struct{}{} 152 direct[m.Name] = struct{}{} 153 } 154 } 155 156 // Go over the direct children and find any that aren't in our keys. 157 var orphans [][]string 158 for _, m := range s.Children(path) { 159 key := m.Path[len(m.Path)-1] 160 161 // Record that we found this key as a direct child. We use this 162 // later to find orphan nested modules. 163 direct[key] = struct{}{} 164 165 // If we have a direct child still in our config, it is not an orphan 166 if _, ok := childrenKeys[key]; ok { 167 continue 168 } 169 170 orphans = append(orphans, m.Path) 171 } 172 173 // Find the orphans that are nested... 174 for _, m := range s.Modules { 175 // We only want modules that are at least grandchildren 176 if len(m.Path) < len(path)+2 { 177 continue 178 } 179 180 // If it isn't part of our tree, continue 181 if !reflect.DeepEqual(path, m.Path[:len(path)]) { 182 continue 183 } 184 185 // If we have the direct child, then just skip it. 186 key := m.Path[len(path)] 187 if _, ok := direct[key]; ok { 188 continue 189 } 190 191 orphanPath := m.Path[:len(path)+1] 192 193 // Don't double-add if we've already added this orphan (which can happen if 194 // there are multiple nested sub-modules that get orphaned together). 195 alreadyAdded := false 196 for _, o := range orphans { 197 if reflect.DeepEqual(o, orphanPath) { 198 alreadyAdded = true 199 break 200 } 201 } 202 if alreadyAdded { 203 continue 204 } 205 206 // Add this orphan 207 orphans = append(orphans, orphanPath) 208 } 209 210 return orphans 211 } 212 213 // Empty returns true if the state is empty. 214 func (s *State) Empty() bool { 215 if s == nil { 216 return true 217 } 218 219 return len(s.Modules) == 0 220 } 221 222 // IsRemote returns true if State represents a state that exists and is 223 // remote. 224 func (s *State) IsRemote() bool { 225 if s == nil { 226 return false 227 } 228 if s.Remote == nil { 229 return false 230 } 231 if s.Remote.Type == "" { 232 return false 233 } 234 235 return true 236 } 237 238 // Remove removes the item in the state at the given address, returning 239 // any errors that may have occurred. 240 // 241 // If the address references a module state or resource, it will delete 242 // all children as well. To check what will be deleted, use a StateFilter 243 // first. 244 func (s *State) Remove(addr ...string) error { 245 // Filter out what we need to delete 246 filter := &StateFilter{State: s} 247 results, err := filter.Filter(addr...) 248 if err != nil { 249 return err 250 } 251 252 // If we have no results, just exit early, we're not going to do anything. 253 // While what happens below is fairly fast, this is an important early 254 // exit since the prune below might modify the state more and we don't 255 // want to modify the state if we don't have to. 256 if len(results) == 0 { 257 return nil 258 } 259 260 // Go through each result and grab what we need 261 removed := make(map[interface{}]struct{}) 262 for _, r := range results { 263 // Convert the path to our own type 264 path := append([]string{"root"}, r.Path...) 265 266 // If we removed this already, then ignore 267 if _, ok := removed[r.Value]; ok { 268 continue 269 } 270 271 // If we removed the parent already, then ignore 272 if r.Parent != nil { 273 if _, ok := removed[r.Parent.Value]; ok { 274 continue 275 } 276 } 277 278 // Add this to the removed list 279 removed[r.Value] = struct{}{} 280 281 switch v := r.Value.(type) { 282 case *ModuleState: 283 s.removeModule(path, v) 284 case *ResourceState: 285 s.removeResource(path, v) 286 case *InstanceState: 287 s.removeInstance(path, r.Parent.Value.(*ResourceState), v) 288 default: 289 return fmt.Errorf("unknown type to delete: %T", r.Value) 290 } 291 } 292 293 // Prune since the removal functions often do the bare minimum to 294 // remove a thing and may leave around dangling empty modules, resources, 295 // etc. Prune will clean that all up. 296 s.prune() 297 298 return nil 299 } 300 301 func (s *State) removeModule(path []string, v *ModuleState) { 302 for i, m := range s.Modules { 303 if m == v { 304 s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil 305 return 306 } 307 } 308 } 309 310 func (s *State) removeResource(path []string, v *ResourceState) { 311 // Get the module this resource lives in. If it doesn't exist, we're done. 312 mod := s.ModuleByPath(path) 313 if mod == nil { 314 return 315 } 316 317 // Find this resource. This is a O(N) lookup when if we had the key 318 // it could be O(1) but even with thousands of resources this shouldn't 319 // matter right now. We can easily up performance here when the time comes. 320 for k, r := range mod.Resources { 321 if r == v { 322 // Found it 323 delete(mod.Resources, k) 324 return 325 } 326 } 327 } 328 329 func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) { 330 // Go through the resource and find the instance that matches this 331 // (if any) and remove it. 332 333 // Check primary 334 if r.Primary == v { 335 r.Primary = nil 336 return 337 } 338 339 // Check lists 340 lists := [][]*InstanceState{r.Deposed} 341 for _, is := range lists { 342 for i, instance := range is { 343 if instance == v { 344 // Found it, remove it 345 is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil 346 347 // Done 348 return 349 } 350 } 351 } 352 } 353 354 // RootModule returns the ModuleState for the root module 355 func (s *State) RootModule() *ModuleState { 356 root := s.ModuleByPath(rootModulePath) 357 if root == nil { 358 panic("missing root module") 359 } 360 return root 361 } 362 363 // Equal tests if one state is equal to another. 364 func (s *State) Equal(other *State) bool { 365 // If one is nil, we do a direct check 366 if s == nil || other == nil { 367 return s == other 368 } 369 370 // If the versions are different, they're certainly not equal 371 if s.Version != other.Version { 372 return false 373 } 374 375 // If any of the modules are not equal, then this state isn't equal 376 if len(s.Modules) != len(other.Modules) { 377 return false 378 } 379 for _, m := range s.Modules { 380 // This isn't very optimal currently but works. 381 otherM := other.ModuleByPath(m.Path) 382 if otherM == nil { 383 return false 384 } 385 386 // If they're not equal, then we're not equal! 387 if !m.Equal(otherM) { 388 return false 389 } 390 } 391 392 return true 393 } 394 395 type StateAgeComparison int 396 397 const ( 398 StateAgeEqual StateAgeComparison = 0 399 StateAgeReceiverNewer StateAgeComparison = 1 400 StateAgeReceiverOlder StateAgeComparison = -1 401 ) 402 403 // CompareAges compares one state with another for which is "older". 404 // 405 // This is a simple check using the state's serial, and is thus only as 406 // reliable as the serial itself. In the normal case, only one state 407 // exists for a given combination of lineage/serial, but Terraform 408 // does not guarantee this and so the result of this method should be 409 // used with care. 410 // 411 // Returns an integer that is negative if the receiver is older than 412 // the argument, positive if the converse, and zero if they are equal. 413 // An error is returned if the two states are not of the same lineage, 414 // in which case the integer returned has no meaning. 415 func (s *State) CompareAges(other *State) (StateAgeComparison, error) { 416 417 // nil states are "older" than actual states 418 switch { 419 case s != nil && other == nil: 420 return StateAgeReceiverNewer, nil 421 case s == nil && other != nil: 422 return StateAgeReceiverOlder, nil 423 case s == nil && other == nil: 424 return StateAgeEqual, nil 425 } 426 427 if !s.SameLineage(other) { 428 return StateAgeEqual, fmt.Errorf( 429 "can't compare two states of differing lineage", 430 ) 431 } 432 433 switch { 434 case s.Serial < other.Serial: 435 return StateAgeReceiverOlder, nil 436 case s.Serial > other.Serial: 437 return StateAgeReceiverNewer, nil 438 default: 439 return StateAgeEqual, nil 440 } 441 } 442 443 // SameLineage returns true only if the state given in argument belongs 444 // to the same "lineage" of states as the reciever. 445 func (s *State) SameLineage(other *State) bool { 446 // If one of the states has no lineage then it is assumed to predate 447 // this concept, and so we'll accept it as belonging to any lineage 448 // so that a lineage string can be assigned to newer versions 449 // without breaking compatibility with older versions. 450 if s.Lineage == "" || other.Lineage == "" { 451 return true 452 } 453 454 return s.Lineage == other.Lineage 455 } 456 457 // DeepCopy performs a deep copy of the state structure and returns 458 // a new structure. 459 func (s *State) DeepCopy() *State { 460 copy, err := copystructure.Copy(s) 461 if err != nil { 462 panic(err) 463 } 464 465 return copy.(*State) 466 } 467 468 // IncrementSerialMaybe increments the serial number of this state 469 // if it different from the other state. 470 func (s *State) IncrementSerialMaybe(other *State) { 471 if s == nil { 472 return 473 } 474 if other == nil { 475 return 476 } 477 if s.Serial > other.Serial { 478 return 479 } 480 if other.TFVersion != s.TFVersion || !s.Equal(other) { 481 if other.Serial > s.Serial { 482 s.Serial = other.Serial 483 } 484 485 s.Serial++ 486 } 487 } 488 489 // FromFutureTerraform checks if this state was written by a Terraform 490 // version from the future. 491 func (s *State) FromFutureTerraform() bool { 492 // No TF version means it is certainly from the past 493 if s.TFVersion == "" { 494 return false 495 } 496 497 v := version.Must(version.NewVersion(s.TFVersion)) 498 return SemVersion.LessThan(v) 499 } 500 501 func (s *State) init() { 502 if s.Version == 0 { 503 s.Version = StateVersion 504 } 505 if s.ModuleByPath(rootModulePath) == nil { 506 s.AddModule(rootModulePath) 507 } 508 s.EnsureHasLineage() 509 } 510 511 func (s *State) EnsureHasLineage() { 512 if s.Lineage == "" { 513 s.Lineage = uuid.NewV4().String() 514 log.Printf("[DEBUG] New state was assigned lineage %q\n", s.Lineage) 515 } else { 516 log.Printf("[TRACE] Preserving existing state lineage %q\n", s.Lineage) 517 } 518 } 519 520 // prune is used to remove any resources that are no longer required 521 func (s *State) prune() { 522 if s == nil { 523 return 524 } 525 for _, mod := range s.Modules { 526 mod.prune() 527 } 528 if s.Remote != nil && s.Remote.Empty() { 529 s.Remote = nil 530 } 531 } 532 533 // sort sorts the modules 534 func (s *State) sort() { 535 sort.Sort(moduleStateSort(s.Modules)) 536 537 // Allow modules to be sorted 538 for _, m := range s.Modules { 539 m.sort() 540 } 541 } 542 543 func (s *State) GoString() string { 544 return fmt.Sprintf("*%#v", *s) 545 } 546 547 func (s *State) String() string { 548 if s == nil { 549 return "<nil>" 550 } 551 552 var buf bytes.Buffer 553 for _, m := range s.Modules { 554 mStr := m.String() 555 556 // If we're the root module, we just write the output directly. 557 if reflect.DeepEqual(m.Path, rootModulePath) { 558 buf.WriteString(mStr + "\n") 559 continue 560 } 561 562 buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], "."))) 563 564 s := bufio.NewScanner(strings.NewReader(mStr)) 565 for s.Scan() { 566 text := s.Text() 567 if text != "" { 568 text = " " + text 569 } 570 571 buf.WriteString(fmt.Sprintf("%s\n", text)) 572 } 573 } 574 575 return strings.TrimSpace(buf.String()) 576 } 577 578 // RemoteState is used to track the information about a remote 579 // state store that we push/pull state to. 580 type RemoteState struct { 581 // Type controls the client we use for the remote state 582 Type string `json:"type"` 583 584 // Config is used to store arbitrary configuration that 585 // is type specific 586 Config map[string]string `json:"config"` 587 } 588 589 func (r *RemoteState) deepcopy() *RemoteState { 590 confCopy := make(map[string]string, len(r.Config)) 591 for k, v := range r.Config { 592 confCopy[k] = v 593 } 594 return &RemoteState{ 595 Type: r.Type, 596 Config: confCopy, 597 } 598 } 599 600 func (r *RemoteState) Empty() bool { 601 return r == nil || r.Type == "" 602 } 603 604 func (r *RemoteState) Equals(other *RemoteState) bool { 605 if r.Type != other.Type { 606 return false 607 } 608 if len(r.Config) != len(other.Config) { 609 return false 610 } 611 for k, v := range r.Config { 612 if other.Config[k] != v { 613 return false 614 } 615 } 616 return true 617 } 618 619 func (r *RemoteState) GoString() string { 620 return fmt.Sprintf("*%#v", *r) 621 } 622 623 // OutputState is used to track the state relevant to a single output. 624 type OutputState struct { 625 // Sensitive describes whether the output is considered sensitive, 626 // which may lead to masking the value on screen in some cases. 627 Sensitive bool `json:"sensitive"` 628 // Type describes the structure of Value. Valid values are "string", 629 // "map" and "list" 630 Type string `json:"type"` 631 // Value contains the value of the output, in the structure described 632 // by the Type field. 633 Value interface{} `json:"value"` 634 } 635 636 func (s *OutputState) String() string { 637 return fmt.Sprintf("%#v", s.Value) 638 } 639 640 // Equal compares two OutputState structures for equality. nil values are 641 // considered equal. 642 func (s *OutputState) Equal(other *OutputState) bool { 643 if s == nil && other == nil { 644 return true 645 } 646 647 if s == nil || other == nil { 648 return false 649 } 650 651 if s.Type != other.Type { 652 return false 653 } 654 655 if s.Sensitive != other.Sensitive { 656 return false 657 } 658 659 if !reflect.DeepEqual(s.Value, other.Value) { 660 return false 661 } 662 663 return true 664 } 665 666 func (s *OutputState) deepcopy() *OutputState { 667 if s == nil { 668 return nil 669 } 670 671 valueCopy, err := copystructure.Copy(s.Value) 672 if err != nil { 673 panic(fmt.Errorf("Error copying output value: %s", err)) 674 } 675 676 n := &OutputState{ 677 Type: s.Type, 678 Sensitive: s.Sensitive, 679 Value: valueCopy, 680 } 681 682 return n 683 } 684 685 // ModuleState is used to track all the state relevant to a single 686 // module. Previous to Terraform 0.3, all state belonged to the "root" 687 // module. 688 type ModuleState struct { 689 // Path is the import path from the root module. Modules imports are 690 // always disjoint, so the path represents amodule tree 691 Path []string `json:"path"` 692 693 // Outputs declared by the module and maintained for each module 694 // even though only the root module technically needs to be kept. 695 // This allows operators to inspect values at the boundaries. 696 Outputs map[string]*OutputState `json:"outputs"` 697 698 // Resources is a mapping of the logically named resource to 699 // the state of the resource. Each resource may actually have 700 // N instances underneath, although a user only needs to think 701 // about the 1:1 case. 702 Resources map[string]*ResourceState `json:"resources"` 703 704 // Dependencies are a list of things that this module relies on 705 // existing to remain intact. For example: an module may depend 706 // on a VPC ID given by an aws_vpc resource. 707 // 708 // Terraform uses this information to build valid destruction 709 // orders and to warn the user if they're destroying a module that 710 // another resource depends on. 711 // 712 // Things can be put into this list that may not be managed by 713 // Terraform. If Terraform doesn't find a matching ID in the 714 // overall state, then it assumes it isn't managed and doesn't 715 // worry about it. 716 Dependencies []string `json:"depends_on,omitempty"` 717 } 718 719 // Equal tests whether one module state is equal to another. 720 func (m *ModuleState) Equal(other *ModuleState) bool { 721 // Paths must be equal 722 if !reflect.DeepEqual(m.Path, other.Path) { 723 return false 724 } 725 726 // Outputs must be equal 727 if len(m.Outputs) != len(other.Outputs) { 728 return false 729 } 730 for k, v := range m.Outputs { 731 if !other.Outputs[k].Equal(v) { 732 return false 733 } 734 } 735 736 // Dependencies must be equal. This sorts these in place but 737 // this shouldn't cause any problems. 738 sort.Strings(m.Dependencies) 739 sort.Strings(other.Dependencies) 740 if len(m.Dependencies) != len(other.Dependencies) { 741 return false 742 } 743 for i, d := range m.Dependencies { 744 if other.Dependencies[i] != d { 745 return false 746 } 747 } 748 749 // Resources must be equal 750 if len(m.Resources) != len(other.Resources) { 751 return false 752 } 753 for k, r := range m.Resources { 754 otherR, ok := other.Resources[k] 755 if !ok { 756 return false 757 } 758 759 if !r.Equal(otherR) { 760 return false 761 } 762 } 763 764 return true 765 } 766 767 // IsRoot says whether or not this module diff is for the root module. 768 func (m *ModuleState) IsRoot() bool { 769 return reflect.DeepEqual(m.Path, rootModulePath) 770 } 771 772 // Orphans returns a list of keys of resources that are in the State 773 // but aren't present in the configuration itself. Hence, these keys 774 // represent the state of resources that are orphans. 775 func (m *ModuleState) Orphans(c *config.Config) []string { 776 keys := make(map[string]struct{}) 777 for k, _ := range m.Resources { 778 keys[k] = struct{}{} 779 } 780 781 if c != nil { 782 for _, r := range c.Resources { 783 delete(keys, r.Id()) 784 785 for k, _ := range keys { 786 if strings.HasPrefix(k, r.Id()+".") { 787 delete(keys, k) 788 } 789 } 790 } 791 } 792 793 result := make([]string, 0, len(keys)) 794 for k, _ := range keys { 795 result = append(result, k) 796 } 797 798 return result 799 } 800 801 // View returns a view with the given resource prefix. 802 func (m *ModuleState) View(id string) *ModuleState { 803 if m == nil { 804 return m 805 } 806 807 r := m.deepcopy() 808 for k, _ := range r.Resources { 809 if id == k || strings.HasPrefix(k, id+".") { 810 continue 811 } 812 813 delete(r.Resources, k) 814 } 815 816 return r 817 } 818 819 func (m *ModuleState) init() { 820 if m.Outputs == nil { 821 m.Outputs = make(map[string]*OutputState) 822 } 823 if m.Resources == nil { 824 m.Resources = make(map[string]*ResourceState) 825 } 826 } 827 828 func (m *ModuleState) deepcopy() *ModuleState { 829 if m == nil { 830 return nil 831 } 832 n := &ModuleState{ 833 Path: make([]string, len(m.Path)), 834 Outputs: make(map[string]*OutputState, len(m.Outputs)), 835 Resources: make(map[string]*ResourceState, len(m.Resources)), 836 Dependencies: make([]string, len(m.Dependencies)), 837 } 838 copy(n.Path, m.Path) 839 copy(n.Dependencies, m.Dependencies) 840 for k, v := range m.Outputs { 841 n.Outputs[k] = v.deepcopy() 842 } 843 for k, v := range m.Resources { 844 n.Resources[k] = v.deepcopy() 845 } 846 return n 847 } 848 849 // prune is used to remove any resources that are no longer required 850 func (m *ModuleState) prune() { 851 for k, v := range m.Resources { 852 v.prune() 853 854 if (v.Primary == nil || v.Primary.ID == "") && len(v.Deposed) == 0 { 855 delete(m.Resources, k) 856 } 857 } 858 859 for k, v := range m.Outputs { 860 if v.Value == config.UnknownVariableValue { 861 delete(m.Outputs, k) 862 } 863 } 864 } 865 866 func (m *ModuleState) sort() { 867 for _, v := range m.Resources { 868 v.sort() 869 } 870 } 871 872 func (m *ModuleState) GoString() string { 873 return fmt.Sprintf("*%#v", *m) 874 } 875 876 func (m *ModuleState) String() string { 877 var buf bytes.Buffer 878 879 if len(m.Resources) == 0 { 880 buf.WriteString("<no state>") 881 } 882 883 names := make([]string, 0, len(m.Resources)) 884 for name, _ := range m.Resources { 885 names = append(names, name) 886 } 887 sort.Strings(names) 888 889 for _, k := range names { 890 rs := m.Resources[k] 891 var id string 892 if rs.Primary != nil { 893 id = rs.Primary.ID 894 } 895 if id == "" { 896 id = "<not created>" 897 } 898 899 taintStr := "" 900 if rs.Primary.Tainted { 901 taintStr = " (tainted)" 902 } 903 904 deposedStr := "" 905 if len(rs.Deposed) > 0 { 906 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed)) 907 } 908 909 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr)) 910 buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) 911 if rs.Provider != "" { 912 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider)) 913 } 914 915 var attributes map[string]string 916 if rs.Primary != nil { 917 attributes = rs.Primary.Attributes 918 } 919 attrKeys := make([]string, 0, len(attributes)) 920 for ak, _ := range attributes { 921 if ak == "id" { 922 continue 923 } 924 925 attrKeys = append(attrKeys, ak) 926 } 927 sort.Strings(attrKeys) 928 929 for _, ak := range attrKeys { 930 av := attributes[ak] 931 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) 932 } 933 934 for idx, t := range rs.Deposed { 935 taintStr := "" 936 if t.Tainted { 937 taintStr = " (tainted)" 938 } 939 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s%s\n", idx+1, t.ID, taintStr)) 940 } 941 942 if len(rs.Dependencies) > 0 { 943 buf.WriteString(fmt.Sprintf("\n Dependencies:\n")) 944 for _, dep := range rs.Dependencies { 945 buf.WriteString(fmt.Sprintf(" %s\n", dep)) 946 } 947 } 948 } 949 950 if len(m.Outputs) > 0 { 951 buf.WriteString("\nOutputs:\n\n") 952 953 ks := make([]string, 0, len(m.Outputs)) 954 for k, _ := range m.Outputs { 955 ks = append(ks, k) 956 } 957 sort.Strings(ks) 958 959 for _, k := range ks { 960 v := m.Outputs[k] 961 switch vTyped := v.Value.(type) { 962 case string: 963 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 964 case []interface{}: 965 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) 966 case map[string]interface{}: 967 var mapKeys []string 968 for key, _ := range vTyped { 969 mapKeys = append(mapKeys, key) 970 } 971 sort.Strings(mapKeys) 972 973 var mapBuf bytes.Buffer 974 mapBuf.WriteString("{") 975 for _, key := range mapKeys { 976 mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key])) 977 } 978 mapBuf.WriteString("}") 979 980 buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String())) 981 } 982 } 983 } 984 985 return buf.String() 986 } 987 988 // ResourceStateKey is a structured representation of the key used for the 989 // ModuleState.Resources mapping 990 type ResourceStateKey struct { 991 Name string 992 Type string 993 Mode config.ResourceMode 994 Index int 995 } 996 997 // Equal determines whether two ResourceStateKeys are the same 998 func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool { 999 if rsk == nil || other == nil { 1000 return false 1001 } 1002 if rsk.Mode != other.Mode { 1003 return false 1004 } 1005 if rsk.Type != other.Type { 1006 return false 1007 } 1008 if rsk.Name != other.Name { 1009 return false 1010 } 1011 if rsk.Index != other.Index { 1012 return false 1013 } 1014 return true 1015 } 1016 1017 func (rsk *ResourceStateKey) String() string { 1018 if rsk == nil { 1019 return "" 1020 } 1021 var prefix string 1022 switch rsk.Mode { 1023 case config.ManagedResourceMode: 1024 prefix = "" 1025 case config.DataResourceMode: 1026 prefix = "data." 1027 default: 1028 panic(fmt.Errorf("unknown resource mode %s", rsk.Mode)) 1029 } 1030 if rsk.Index == -1 { 1031 return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name) 1032 } 1033 return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index) 1034 } 1035 1036 // ParseResourceStateKey accepts a key in the format used by 1037 // ModuleState.Resources and returns a resource name and resource index. In the 1038 // state, a resource has the format "type.name.index" or "type.name". In the 1039 // latter case, the index is returned as -1. 1040 func ParseResourceStateKey(k string) (*ResourceStateKey, error) { 1041 parts := strings.Split(k, ".") 1042 mode := config.ManagedResourceMode 1043 if len(parts) > 0 && parts[0] == "data" { 1044 mode = config.DataResourceMode 1045 // Don't need the constant "data" prefix for parsing 1046 // now that we've figured out the mode. 1047 parts = parts[1:] 1048 } 1049 if len(parts) < 2 || len(parts) > 3 { 1050 return nil, fmt.Errorf("Malformed resource state key: %s", k) 1051 } 1052 rsk := &ResourceStateKey{ 1053 Mode: mode, 1054 Type: parts[0], 1055 Name: parts[1], 1056 Index: -1, 1057 } 1058 if len(parts) == 3 { 1059 index, err := strconv.Atoi(parts[2]) 1060 if err != nil { 1061 return nil, fmt.Errorf("Malformed resource state key index: %s", k) 1062 } 1063 rsk.Index = index 1064 } 1065 return rsk, nil 1066 } 1067 1068 // ResourceState holds the state of a resource that is used so that 1069 // a provider can find and manage an existing resource as well as for 1070 // storing attributes that are used to populate variables of child 1071 // resources. 1072 // 1073 // Attributes has attributes about the created resource that are 1074 // queryable in interpolation: "${type.id.attr}" 1075 // 1076 // Extra is just extra data that a provider can return that we store 1077 // for later, but is not exposed in any way to the user. 1078 // 1079 type ResourceState struct { 1080 // This is filled in and managed by Terraform, and is the resource 1081 // type itself such as "mycloud_instance". If a resource provider sets 1082 // this value, it won't be persisted. 1083 Type string `json:"type"` 1084 1085 // Dependencies are a list of things that this resource relies on 1086 // existing to remain intact. For example: an AWS instance might 1087 // depend on a subnet (which itself might depend on a VPC, and so 1088 // on). 1089 // 1090 // Terraform uses this information to build valid destruction 1091 // orders and to warn the user if they're destroying a resource that 1092 // another resource depends on. 1093 // 1094 // Things can be put into this list that may not be managed by 1095 // Terraform. If Terraform doesn't find a matching ID in the 1096 // overall state, then it assumes it isn't managed and doesn't 1097 // worry about it. 1098 Dependencies []string `json:"depends_on,omitempty"` 1099 1100 // Primary is the current active instance for this resource. 1101 // It can be replaced but only after a successful creation. 1102 // This is the instances on which providers will act. 1103 Primary *InstanceState `json:"primary"` 1104 1105 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing 1106 // Primary is Deposed to get it out of the way for the replacement Primary to 1107 // be created by Apply. If the replacement Primary creates successfully, the 1108 // Deposed instance is cleaned up. 1109 // 1110 // If there were problems creating the replacement Primary, the Deposed 1111 // instance and the (now tainted) replacement Primary will be swapped so the 1112 // tainted replacement will be cleaned up instead. 1113 // 1114 // An instance will remain in the Deposed list until it is successfully 1115 // destroyed and purged. 1116 Deposed []*InstanceState `json:"deposed,omitempty"` 1117 1118 // Provider is used when a resource is connected to a provider with an alias. 1119 // If this string is empty, the resource is connected to the default provider, 1120 // e.g. "aws_instance" goes with the "aws" provider. 1121 // If the resource block contained a "provider" key, that value will be set here. 1122 Provider string `json:"provider,omitempty"` 1123 } 1124 1125 // Equal tests whether two ResourceStates are equal. 1126 func (s *ResourceState) Equal(other *ResourceState) bool { 1127 if s.Type != other.Type { 1128 return false 1129 } 1130 1131 if s.Provider != other.Provider { 1132 return false 1133 } 1134 1135 // Dependencies must be equal 1136 sort.Strings(s.Dependencies) 1137 sort.Strings(other.Dependencies) 1138 if len(s.Dependencies) != len(other.Dependencies) { 1139 return false 1140 } 1141 for i, d := range s.Dependencies { 1142 if other.Dependencies[i] != d { 1143 return false 1144 } 1145 } 1146 1147 // States must be equal 1148 if !s.Primary.Equal(other.Primary) { 1149 return false 1150 } 1151 1152 return true 1153 } 1154 1155 // Taint marks a resource as tainted. 1156 func (r *ResourceState) Taint() { 1157 if r.Primary != nil { 1158 r.Primary.Tainted = true 1159 } 1160 } 1161 1162 // Untaint unmarks a resource as tainted. 1163 func (r *ResourceState) Untaint() { 1164 if r.Primary != nil { 1165 r.Primary.Tainted = false 1166 } 1167 } 1168 1169 func (r *ResourceState) init() { 1170 if r.Primary == nil { 1171 r.Primary = &InstanceState{} 1172 } 1173 r.Primary.init() 1174 } 1175 1176 func (r *ResourceState) deepcopy() *ResourceState { 1177 copy, err := copystructure.Copy(r) 1178 if err != nil { 1179 panic(err) 1180 } 1181 1182 return copy.(*ResourceState) 1183 } 1184 1185 // prune is used to remove any instances that are no longer required 1186 func (r *ResourceState) prune() { 1187 n := len(r.Deposed) 1188 for i := 0; i < n; i++ { 1189 inst := r.Deposed[i] 1190 if inst == nil || inst.ID == "" { 1191 copy(r.Deposed[i:], r.Deposed[i+1:]) 1192 r.Deposed[n-1] = nil 1193 n-- 1194 i-- 1195 } 1196 } 1197 1198 r.Deposed = r.Deposed[:n] 1199 } 1200 1201 func (r *ResourceState) sort() { 1202 sort.Strings(r.Dependencies) 1203 } 1204 1205 func (s *ResourceState) GoString() string { 1206 return fmt.Sprintf("*%#v", *s) 1207 } 1208 1209 func (s *ResourceState) String() string { 1210 var buf bytes.Buffer 1211 buf.WriteString(fmt.Sprintf("Type = %s", s.Type)) 1212 return buf.String() 1213 } 1214 1215 // InstanceState is used to track the unique state information belonging 1216 // to a given instance. 1217 type InstanceState struct { 1218 // A unique ID for this resource. This is opaque to Terraform 1219 // and is only meant as a lookup mechanism for the providers. 1220 ID string `json:"id"` 1221 1222 // Attributes are basic information about the resource. Any keys here 1223 // are accessible in variable format within Terraform configurations: 1224 // ${resourcetype.name.attribute}. 1225 Attributes map[string]string `json:"attributes,omitempty"` 1226 1227 // Ephemeral is used to store any state associated with this instance 1228 // that is necessary for the Terraform run to complete, but is not 1229 // persisted to a state file. 1230 Ephemeral EphemeralState `json:"-"` 1231 1232 // Meta is a simple K/V map that is persisted to the State but otherwise 1233 // ignored by Terraform core. It's meant to be used for accounting by 1234 // external client code. 1235 Meta map[string]string `json:"meta,omitempty"` 1236 1237 // Tainted is used to mark a resource for recreation. 1238 Tainted bool `json:"tainted,omitempty"` 1239 } 1240 1241 func (i *InstanceState) init() { 1242 if i.Attributes == nil { 1243 i.Attributes = make(map[string]string) 1244 } 1245 if i.Meta == nil { 1246 i.Meta = make(map[string]string) 1247 } 1248 i.Ephemeral.init() 1249 } 1250 1251 func (i *InstanceState) DeepCopy() *InstanceState { 1252 copy, err := copystructure.Copy(i) 1253 if err != nil { 1254 panic(err) 1255 } 1256 1257 return copy.(*InstanceState) 1258 } 1259 1260 func (s *InstanceState) Empty() bool { 1261 return s == nil || s.ID == "" 1262 } 1263 1264 func (s *InstanceState) Equal(other *InstanceState) bool { 1265 // Short circuit some nil checks 1266 if s == nil || other == nil { 1267 return s == other 1268 } 1269 1270 // IDs must be equal 1271 if s.ID != other.ID { 1272 return false 1273 } 1274 1275 // Attributes must be equal 1276 if len(s.Attributes) != len(other.Attributes) { 1277 return false 1278 } 1279 for k, v := range s.Attributes { 1280 otherV, ok := other.Attributes[k] 1281 if !ok { 1282 return false 1283 } 1284 1285 if v != otherV { 1286 return false 1287 } 1288 } 1289 1290 // Meta must be equal 1291 if len(s.Meta) != len(other.Meta) { 1292 return false 1293 } 1294 for k, v := range s.Meta { 1295 otherV, ok := other.Meta[k] 1296 if !ok { 1297 return false 1298 } 1299 1300 if v != otherV { 1301 return false 1302 } 1303 } 1304 1305 if s.Tainted != other.Tainted { 1306 return false 1307 } 1308 1309 return true 1310 } 1311 1312 // MergeDiff takes a ResourceDiff and merges the attributes into 1313 // this resource state in order to generate a new state. This new 1314 // state can be used to provide updated attribute lookups for 1315 // variable interpolation. 1316 // 1317 // If the diff attribute requires computing the value, and hence 1318 // won't be available until apply, the value is replaced with the 1319 // computeID. 1320 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { 1321 result := s.DeepCopy() 1322 if result == nil { 1323 result = new(InstanceState) 1324 } 1325 result.init() 1326 1327 if s != nil { 1328 for k, v := range s.Attributes { 1329 result.Attributes[k] = v 1330 } 1331 } 1332 if d != nil { 1333 for k, diff := range d.CopyAttributes() { 1334 if diff.NewRemoved { 1335 delete(result.Attributes, k) 1336 continue 1337 } 1338 if diff.NewComputed { 1339 result.Attributes[k] = config.UnknownVariableValue 1340 continue 1341 } 1342 1343 result.Attributes[k] = diff.New 1344 } 1345 } 1346 1347 return result 1348 } 1349 1350 func (i *InstanceState) GoString() string { 1351 return fmt.Sprintf("*%#v", *i) 1352 } 1353 1354 func (i *InstanceState) String() string { 1355 var buf bytes.Buffer 1356 1357 if i == nil || i.ID == "" { 1358 return "<not created>" 1359 } 1360 1361 buf.WriteString(fmt.Sprintf("ID = %s\n", i.ID)) 1362 1363 attributes := i.Attributes 1364 attrKeys := make([]string, 0, len(attributes)) 1365 for ak, _ := range attributes { 1366 if ak == "id" { 1367 continue 1368 } 1369 1370 attrKeys = append(attrKeys, ak) 1371 } 1372 sort.Strings(attrKeys) 1373 1374 for _, ak := range attrKeys { 1375 av := attributes[ak] 1376 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av)) 1377 } 1378 1379 buf.WriteString(fmt.Sprintf("Tainted = %t\n", i.Tainted)) 1380 1381 return buf.String() 1382 } 1383 1384 // EphemeralState is used for transient state that is only kept in-memory 1385 type EphemeralState struct { 1386 // ConnInfo is used for the providers to export information which is 1387 // used to connect to the resource for provisioning. For example, 1388 // this could contain SSH or WinRM credentials. 1389 ConnInfo map[string]string `json:"-"` 1390 1391 // Type is used to specify the resource type for this instance. This is only 1392 // required for import operations (as documented). If the documentation 1393 // doesn't state that you need to set this, then don't worry about 1394 // setting it. 1395 Type string `json:"-"` 1396 } 1397 1398 func (e *EphemeralState) init() { 1399 if e.ConnInfo == nil { 1400 e.ConnInfo = make(map[string]string) 1401 } 1402 } 1403 1404 func (e *EphemeralState) DeepCopy() *EphemeralState { 1405 copy, err := copystructure.Copy(e) 1406 if err != nil { 1407 panic(err) 1408 } 1409 1410 return copy.(*EphemeralState) 1411 } 1412 1413 type jsonStateVersionIdentifier struct { 1414 Version int `json:"version"` 1415 } 1416 1417 // Check if this is a V0 format - the magic bytes at the start of the file 1418 // should be "tfstate" if so. We no longer support upgrading this type of 1419 // state but return an error message explaining to a user how they can 1420 // upgrade via the 0.6.x series. 1421 func testForV0State(buf *bufio.Reader) error { 1422 start, err := buf.Peek(len("tfstate")) 1423 if err != nil { 1424 return fmt.Errorf("Failed to check for magic bytes: %v", err) 1425 } 1426 if string(start) == "tfstate" { 1427 return fmt.Errorf("Terraform 0.7 no longer supports upgrading the binary state\n" + 1428 "format which was used prior to Terraform 0.3. Please upgrade\n" + 1429 "this state file using Terraform 0.6.16 prior to using it with\n" + 1430 "Terraform 0.7.") 1431 } 1432 1433 return nil 1434 } 1435 1436 // ReadState reads a state structure out of a reader in the format that 1437 // was written by WriteState. 1438 func ReadState(src io.Reader) (*State, error) { 1439 buf := bufio.NewReader(src) 1440 1441 if err := testForV0State(buf); err != nil { 1442 return nil, err 1443 } 1444 1445 // If we are JSON we buffer the whole thing in memory so we can read it twice. 1446 // This is suboptimal, but will work for now. 1447 jsonBytes, err := ioutil.ReadAll(buf) 1448 if err != nil { 1449 return nil, fmt.Errorf("Reading state file failed: %v", err) 1450 } 1451 1452 versionIdentifier := &jsonStateVersionIdentifier{} 1453 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil { 1454 return nil, fmt.Errorf("Decoding state file version failed: %v", err) 1455 } 1456 1457 switch versionIdentifier.Version { 1458 case 0: 1459 return nil, fmt.Errorf("State version 0 is not supported as JSON.") 1460 case 1: 1461 v1State, err := ReadStateV1(jsonBytes) 1462 if err != nil { 1463 return nil, err 1464 } 1465 1466 v2State, err := upgradeStateV1ToV2(v1State) 1467 if err != nil { 1468 return nil, err 1469 } 1470 1471 v3State, err := upgradeStateV2ToV3(v2State) 1472 if err != nil { 1473 return nil, err 1474 } 1475 1476 // increment the Serial whenever we upgrade state 1477 v3State.Serial++ 1478 return v3State, nil 1479 case 2: 1480 v2State, err := ReadStateV2(jsonBytes) 1481 if err != nil { 1482 return nil, err 1483 } 1484 v3State, err := upgradeStateV2ToV3(v2State) 1485 if err != nil { 1486 return nil, err 1487 } 1488 1489 v3State.Serial++ 1490 return v3State, nil 1491 case 3: 1492 v3State, err := ReadStateV3(jsonBytes) 1493 if err != nil { 1494 return nil, err 1495 } 1496 return v3State, nil 1497 default: 1498 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 1499 SemVersion.String(), versionIdentifier.Version) 1500 } 1501 } 1502 1503 func ReadStateV1(jsonBytes []byte) (*stateV1, error) { 1504 v1State := &stateV1{} 1505 if err := json.Unmarshal(jsonBytes, v1State); err != nil { 1506 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1507 } 1508 1509 if v1State.Version != 1 { 1510 return nil, fmt.Errorf("Decoded state version did not match the decoder selection: "+ 1511 "read %d, expected 1", v1State.Version) 1512 } 1513 1514 return v1State, nil 1515 } 1516 1517 func ReadStateV2(jsonBytes []byte) (*State, error) { 1518 state := &State{} 1519 if err := json.Unmarshal(jsonBytes, state); err != nil { 1520 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1521 } 1522 1523 // Check the version, this to ensure we don't read a future 1524 // version that we don't understand 1525 if state.Version > StateVersion { 1526 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 1527 SemVersion.String(), state.Version) 1528 } 1529 1530 // Make sure the version is semantic 1531 if state.TFVersion != "" { 1532 if _, err := version.NewVersion(state.TFVersion); err != nil { 1533 return nil, fmt.Errorf( 1534 "State contains invalid version: %s\n\n"+ 1535 "Terraform validates the version format prior to writing it. This\n"+ 1536 "means that this is invalid of the state becoming corrupted through\n"+ 1537 "some external means. Please manually modify the Terraform version\n"+ 1538 "field to be a proper semantic version.", 1539 state.TFVersion) 1540 } 1541 } 1542 1543 // Sort it 1544 state.sort() 1545 1546 return state, nil 1547 } 1548 1549 func ReadStateV3(jsonBytes []byte) (*State, error) { 1550 state := &State{} 1551 if err := json.Unmarshal(jsonBytes, state); err != nil { 1552 return nil, fmt.Errorf("Decoding state file failed: %v", err) 1553 } 1554 1555 // Check the version, this to ensure we don't read a future 1556 // version that we don't understand 1557 if state.Version > StateVersion { 1558 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 1559 SemVersion.String(), state.Version) 1560 } 1561 1562 // Make sure the version is semantic 1563 if state.TFVersion != "" { 1564 if _, err := version.NewVersion(state.TFVersion); err != nil { 1565 return nil, fmt.Errorf( 1566 "State contains invalid version: %s\n\n"+ 1567 "Terraform validates the version format prior to writing it. This\n"+ 1568 "means that this is invalid of the state becoming corrupted through\n"+ 1569 "some external means. Please manually modify the Terraform version\n"+ 1570 "field to be a proper semantic version.", 1571 state.TFVersion) 1572 } 1573 } 1574 1575 // Sort it 1576 state.sort() 1577 1578 return state, nil 1579 } 1580 1581 // WriteState writes a state somewhere in a binary format. 1582 func WriteState(d *State, dst io.Writer) error { 1583 // Make sure it is sorted 1584 d.sort() 1585 1586 // Ensure the version is set 1587 d.Version = StateVersion 1588 1589 // If the TFVersion is set, verify it. We used to just set the version 1590 // here, but this isn't safe since it changes the MD5 sum on some remote 1591 // state storage backends such as Atlas. We now leave it be if needed. 1592 if d.TFVersion != "" { 1593 if _, err := version.NewVersion(d.TFVersion); err != nil { 1594 return fmt.Errorf( 1595 "Error writing state, invalid version: %s\n\n"+ 1596 "The Terraform version when writing the state must be a semantic\n"+ 1597 "version.", 1598 d.TFVersion) 1599 } 1600 } 1601 1602 // Encode the data in a human-friendly way 1603 data, err := json.MarshalIndent(d, "", " ") 1604 if err != nil { 1605 return fmt.Errorf("Failed to encode state: %s", err) 1606 } 1607 1608 // We append a newline to the data because MarshalIndent doesn't 1609 data = append(data, '\n') 1610 1611 // Write the data out to the dst 1612 if _, err := io.Copy(dst, bytes.NewReader(data)); err != nil { 1613 return fmt.Errorf("Failed to write state: %v", err) 1614 } 1615 1616 return nil 1617 } 1618 1619 // moduleStateSort implements sort.Interface to sort module states 1620 type moduleStateSort []*ModuleState 1621 1622 func (s moduleStateSort) Len() int { 1623 return len(s) 1624 } 1625 1626 func (s moduleStateSort) Less(i, j int) bool { 1627 a := s[i] 1628 b := s[j] 1629 1630 // If the lengths are different, then the shorter one always wins 1631 if len(a.Path) != len(b.Path) { 1632 return len(a.Path) < len(b.Path) 1633 } 1634 1635 // Otherwise, compare lexically 1636 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".") 1637 } 1638 1639 func (s moduleStateSort) Swap(i, j int) { 1640 s[i], s[j] = s[j], s[i] 1641 }