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/hcl2/hcl"
24 "github.com/hashicorp/hcl2/hcl/hclsyntax"
25 "github.com/mitchellh/copystructure"
26 "github.com/zclconf/go-cty/cty"
27 ctyjson "github.com/zclconf/go-cty/cty/json"
29 "github.com/hashicorp/terraform/addrs"
30 "github.com/hashicorp/terraform/config"
31 "github.com/hashicorp/terraform/config/hcl2shim"
32 "github.com/hashicorp/terraform/configs"
33 "github.com/hashicorp/terraform/configs/configschema"
34 "github.com/hashicorp/terraform/plans"
35 "github.com/hashicorp/terraform/tfdiags"
36 tfversion "github.com/hashicorp/terraform/version"
40 // StateVersion is the current version for our state file
44 // rootModulePath is the path of the root module
45 var rootModulePath = []string{"root"}
47 // normalizeModulePath transforms a legacy module path (which may or may not
48 // have a redundant "root" label at the start of it) into an
49 // addrs.ModuleInstance representing the same module.
51 // For legacy reasons, different parts of Terraform disagree about whether the
52 // root module has the path []string{} or []string{"root"}, and so this
53 // function accepts both and trims off the "root". An implication of this is
54 // that it's not possible to actually have a module call in the root module
55 // that is itself named "root", since that would be ambiguous.
57 // normalizeModulePath takes a raw module path and returns a path that
58 // has the rootModulePath prepended to it. If I could go back in time I
59 // would've never had a rootModulePath (empty path would be root). We can
60 // still fix this but thats a big refactor that my branch doesn't make sense
61 // for. Instead, this function normalizes paths.
62 func normalizeModulePath(p []string) addrs.ModuleInstance {
63 // FIXME: Remove this once everyone is using addrs.ModuleInstance.
65 if len(p) > 0 && p[0] == "root" {
69 ret := make(addrs.ModuleInstance, len(p))
70 for i, name := range p {
71 // For now we don't actually support modules with multiple instances
72 // identified by keys, so we just treat every path element as a
74 ret[i] = addrs.ModuleInstanceStep{
81 // State keeps track of a snapshot state-of-the-world that Terraform
82 // can use to keep track of what real world resources it is actually
85 // Version is the state file protocol version.
86 Version int `json:"version"`
88 // TFVersion is the version of Terraform that wrote this state.
89 TFVersion string `json:"terraform_version,omitempty"`
91 // Serial is incremented on any operation that modifies
92 // the State file. It is used to detect potentially conflicting
94 Serial int64 `json:"serial"`
96 // Lineage is set when a new, blank state is created and then
97 // never updated. This allows us to determine whether the serials
98 // of two states can be meaningfully compared.
99 // Apart from the guarantee that collisions between two lineages
100 // are very unlikely, this value is opaque and external callers
101 // should only compare lineage strings byte-for-byte for equality.
102 Lineage string `json:"lineage"`
104 // Remote is used to track the metadata required to
105 // pull and push state files from a remote storage endpoint.
106 Remote *RemoteState `json:"remote,omitempty"`
108 // Backend tracks the configuration for the backend in use with
109 // this state. This is used to track any changes in the backend
111 Backend *BackendState `json:"backend,omitempty"`
113 // Modules contains all the modules in a breadth-first order
114 Modules []*ModuleState `json:"modules"`
119 func (s *State) Lock() { s.mu.Lock() }
120 func (s *State) Unlock() { s.mu.Unlock() }
122 // NewState is used to initialize a blank state
123 func NewState() *State {
129 // Children returns the ModuleStates that are direct children of
130 // the given path. If the path is "root", for example, then children
131 // returned might be "root.child", but not "root.child.grandchild".
132 func (s *State) Children(path []string) []*ModuleState {
137 return s.children(path)
140 func (s *State) children(path []string) []*ModuleState {
141 result := make([]*ModuleState, 0)
142 for _, m := range s.Modules {
147 if len(m.Path) != len(path)+1 {
150 if !reflect.DeepEqual(path, m.Path[:len(path)]) {
154 result = append(result, m)
160 // AddModule adds the module with the given path to the state.
162 // This should be the preferred method to add module states since it
163 // allows us to optimize lookups later as well as control sorting.
164 func (s *State) AddModule(path addrs.ModuleInstance) *ModuleState {
168 return s.addModule(path)
171 func (s *State) addModule(path addrs.ModuleInstance) *ModuleState {
172 // check if the module exists first
173 m := s.moduleByPath(path)
178 // Lower the new-style address into a legacy-style address.
179 // This requires that none of the steps have instance keys, which is
180 // true for all addresses at the time of implementing this because
181 // "count" and "for_each" are not yet implemented for modules.
182 // For the purposes of state, the legacy address format also includes
183 // a redundant extra prefix element "root". It is important to include
184 // this because the "prune" method will remove any module that has a
185 // path length less than one, and other parts of the state code will
186 // trim off the first element indiscriminately.
187 legacyPath := make([]string, len(path)+1)
188 legacyPath[0] = "root"
189 for i, step := range path {
190 if step.InstanceKey != addrs.NoKey {
191 // FIXME: Once the rest of Terraform is ready to use count and
192 // for_each, remove all of this and just write the addrs.ModuleInstance
193 // value itself into the ModuleState.
194 panic("state cannot represent modules with count or for_each keys")
197 legacyPath[i+1] = step.Name
200 m = &ModuleState{Path: legacyPath}
202 s.Modules = append(s.Modules, m)
207 // ModuleByPath is used to lookup the module state for the given path.
208 // This should be the preferred lookup mechanism as it allows for future
209 // lookup optimizations.
210 func (s *State) ModuleByPath(path addrs.ModuleInstance) *ModuleState {
217 return s.moduleByPath(path)
220 func (s *State) moduleByPath(path addrs.ModuleInstance) *ModuleState {
221 for _, mod := range s.Modules {
226 panic("missing module path")
228 modPath := normalizeModulePath(mod.Path)
229 if modPath.String() == path.String() {
236 // Empty returns true if the state is empty.
237 func (s *State) Empty() bool {
244 return len(s.Modules) == 0
247 // HasResources returns true if the state contains any resources.
249 // This is similar to !s.Empty, but returns true also in the case where the
250 // state has modules but all of them are devoid of resources.
251 func (s *State) HasResources() bool {
256 for _, mod := range s.Modules {
257 if len(mod.Resources) > 0 {
265 // IsRemote returns true if State represents a state that exists and is
267 func (s *State) IsRemote() bool {
277 if s.Remote.Type == "" {
284 // Validate validates the integrity of this state file.
286 // Certain properties of the statefile are expected by Terraform in order
287 // to behave properly. The core of Terraform will assume that once it
288 // receives a State structure that it has been validated. This validation
289 // check should be called to ensure that.
291 // If this returns an error, then the user should be notified. The error
292 // response will include detailed information on the nature of the error.
293 func (s *State) Validate() error {
299 // !!!! FOR DEVELOPERS !!!!
301 // Any errors returned from this Validate function will BLOCK TERRAFORM
302 // from loading a state file. Therefore, this should only contain checks
303 // that are only resolvable through manual intervention.
305 // !!!! FOR DEVELOPERS !!!!
307 // Make sure there are no duplicate module states. We open a new
308 // block here so we can use basic variable names and future validations
311 found := make(map[string]struct{})
312 for _, ms := range s.Modules {
317 key := strings.Join(ms.Path, ".")
318 if _, ok := found[key]; ok {
319 result = multierror.Append(result, fmt.Errorf(
320 strings.TrimSpace(stateValidateErrMultiModule), key))
324 found[key] = struct{}{}
331 // Remove removes the item in the state at the given address, returning
332 // any errors that may have occurred.
334 // If the address references a module state or resource, it will delete
335 // all children as well. To check what will be deleted, use a StateFilter
337 func (s *State) Remove(addr ...string) error {
341 // Filter out what we need to delete
342 filter := &StateFilter{State: s}
343 results, err := filter.Filter(addr...)
348 // If we have no results, just exit early, we're not going to do anything.
349 // While what happens below is fairly fast, this is an important early
350 // exit since the prune below might modify the state more and we don't
351 // want to modify the state if we don't have to.
352 if len(results) == 0 {
356 // Go through each result and grab what we need
357 removed := make(map[interface{}]struct{})
358 for _, r := range results {
359 // Convert the path to our own type
360 path := append([]string{"root"}, r.Path...)
362 // If we removed this already, then ignore
363 if _, ok := removed[r.Value]; ok {
367 // If we removed the parent already, then ignore
369 if _, ok := removed[r.Parent.Value]; ok {
374 // Add this to the removed list
375 removed[r.Value] = struct{}{}
377 switch v := r.Value.(type) {
379 s.removeModule(path, v)
381 s.removeResource(path, v)
383 s.removeInstance(path, r.Parent.Value.(*ResourceState), v)
385 return fmt.Errorf("unknown type to delete: %T", r.Value)
389 // Prune since the removal functions often do the bare minimum to
390 // remove a thing and may leave around dangling empty modules, resources,
391 // etc. Prune will clean that all up.
397 func (s *State) removeModule(path []string, v *ModuleState) {
398 for i, m := range s.Modules {
400 s.Modules, s.Modules[len(s.Modules)-1] = append(s.Modules[:i], s.Modules[i+1:]...), nil
406 func (s *State) removeResource(path []string, v *ResourceState) {
407 // Get the module this resource lives in. If it doesn't exist, we're done.
408 mod := s.moduleByPath(normalizeModulePath(path))
413 // Find this resource. This is a O(N) lookup when if we had the key
414 // it could be O(1) but even with thousands of resources this shouldn't
415 // matter right now. We can easily up performance here when the time comes.
416 for k, r := range mod.Resources {
419 delete(mod.Resources, k)
425 func (s *State) removeInstance(path []string, r *ResourceState, v *InstanceState) {
426 // Go through the resource and find the instance that matches this
427 // (if any) and remove it.
436 lists := [][]*InstanceState{r.Deposed}
437 for _, is := range lists {
438 for i, instance := range is {
440 // Found it, remove it
441 is, is[len(is)-1] = append(is[:i], is[i+1:]...), nil
450 // RootModule returns the ModuleState for the root module
451 func (s *State) RootModule() *ModuleState {
452 root := s.ModuleByPath(addrs.RootModuleInstance)
454 panic("missing root module")
459 // Equal tests if one state is equal to another.
460 func (s *State) Equal(other *State) bool {
461 // If one is nil, we do a direct check
462 if s == nil || other == nil {
468 return s.equal(other)
471 func (s *State) equal(other *State) bool {
472 if s == nil || other == nil {
476 // If the versions are different, they're certainly not equal
477 if s.Version != other.Version {
481 // If any of the modules are not equal, then this state isn't equal
482 if len(s.Modules) != len(other.Modules) {
485 for _, m := range s.Modules {
486 // This isn't very optimal currently but works.
487 otherM := other.moduleByPath(normalizeModulePath(m.Path))
492 // If they're not equal, then we're not equal!
493 if !m.Equal(otherM) {
501 // MarshalEqual is similar to Equal but provides a stronger definition of
502 // "equal", where two states are equal if and only if their serialized form
503 // is byte-for-byte identical.
505 // This is primarily useful for callers that are trying to save snapshots
506 // of state to persistent storage, allowing them to detect when a new
507 // snapshot must be taken.
509 // Note that the serial number and lineage are included in the serialized form,
510 // so it's the caller's responsibility to properly manage these attributes
511 // so that this method is only called on two states that have the same
512 // serial and lineage, unless detecting such differences is desired.
513 func (s *State) MarshalEqual(other *State) bool {
514 if s == nil && other == nil {
516 } else if s == nil || other == nil {
520 recvBuf := &bytes.Buffer{}
521 otherBuf := &bytes.Buffer{}
523 err := WriteState(s, recvBuf)
525 // should never happen, since we're writing to a buffer
529 err = WriteState(other, otherBuf)
531 // should never happen, since we're writing to a buffer
535 return bytes.Equal(recvBuf.Bytes(), otherBuf.Bytes())
538 type StateAgeComparison int
541 StateAgeEqual StateAgeComparison = 0
542 StateAgeReceiverNewer StateAgeComparison = 1
543 StateAgeReceiverOlder StateAgeComparison = -1
546 // CompareAges compares one state with another for which is "older".
548 // This is a simple check using the state's serial, and is thus only as
549 // reliable as the serial itself. In the normal case, only one state
550 // exists for a given combination of lineage/serial, but Terraform
551 // does not guarantee this and so the result of this method should be
554 // Returns an integer that is negative if the receiver is older than
555 // the argument, positive if the converse, and zero if they are equal.
556 // An error is returned if the two states are not of the same lineage,
557 // in which case the integer returned has no meaning.
558 func (s *State) CompareAges(other *State) (StateAgeComparison, error) {
559 // nil states are "older" than actual states
561 case s != nil && other == nil:
562 return StateAgeReceiverNewer, nil
563 case s == nil && other != nil:
564 return StateAgeReceiverOlder, nil
565 case s == nil && other == nil:
566 return StateAgeEqual, nil
569 if !s.SameLineage(other) {
570 return StateAgeEqual, fmt.Errorf(
571 "can't compare two states of differing lineage",
579 case s.Serial < other.Serial:
580 return StateAgeReceiverOlder, nil
581 case s.Serial > other.Serial:
582 return StateAgeReceiverNewer, nil
584 return StateAgeEqual, nil
588 // SameLineage returns true only if the state given in argument belongs
589 // to the same "lineage" of states as the receiver.
590 func (s *State) SameLineage(other *State) bool {
594 // If one of the states has no lineage then it is assumed to predate
595 // this concept, and so we'll accept it as belonging to any lineage
596 // so that a lineage string can be assigned to newer versions
597 // without breaking compatibility with older versions.
598 if s.Lineage == "" || other.Lineage == "" {
602 return s.Lineage == other.Lineage
605 // DeepCopy performs a deep copy of the state structure and returns
607 func (s *State) DeepCopy() *State {
612 copy, err := copystructure.Config{Lock: true}.Copy(s)
620 // FromFutureTerraform checks if this state was written by a Terraform
621 // version from the future.
622 func (s *State) FromFutureTerraform() bool {
626 // No TF version means it is certainly from the past
627 if s.TFVersion == "" {
631 v := version.Must(version.NewVersion(s.TFVersion))
632 return tfversion.SemVer.LessThan(v)
635 func (s *State) Init() {
641 func (s *State) init() {
643 s.Version = StateVersion
646 if s.moduleByPath(addrs.RootModuleInstance) == nil {
647 s.addModule(addrs.RootModuleInstance)
651 for _, mod := range s.Modules {
663 func (s *State) EnsureHasLineage() {
670 func (s *State) ensureHasLineage() {
672 lineage, err := uuid.GenerateUUID()
674 panic(fmt.Errorf("Failed to generate lineage: %v", err))
677 log.Printf("[DEBUG] New state was assigned lineage %q\n", s.Lineage)
679 log.Printf("[TRACE] Preserving existing state lineage %q\n", s.Lineage)
683 // AddModuleState insert this module state and override any existing ModuleState
684 func (s *State) AddModuleState(mod *ModuleState) {
689 s.addModuleState(mod)
692 func (s *State) addModuleState(mod *ModuleState) {
693 for i, m := range s.Modules {
694 if reflect.DeepEqual(m.Path, mod.Path) {
700 s.Modules = append(s.Modules, mod)
704 // prune is used to remove any resources that are no longer required
705 func (s *State) prune() {
710 // Filter out empty modules.
711 // A module is always assumed to have a path, and it's length isn't always
712 // bounds checked later on. Modules may be "emptied" during destroy, but we
713 // never want to store those in the state.
714 for i := 0; i < len(s.Modules); i++ {
715 if s.Modules[i] == nil || len(s.Modules[i].Path) == 0 {
716 s.Modules = append(s.Modules[:i], s.Modules[i+1:]...)
721 for _, mod := range s.Modules {
724 if s.Remote != nil && s.Remote.Empty() {
729 // sort sorts the modules
730 func (s *State) sort() {
731 sort.Sort(moduleStateSort(s.Modules))
733 // Allow modules to be sorted
734 for _, m := range s.Modules {
741 func (s *State) String() string {
749 for _, m := range s.Modules {
752 // If we're the root module, we just write the output directly.
753 if reflect.DeepEqual(m.Path, rootModulePath) {
754 buf.WriteString(mStr + "\n")
758 buf.WriteString(fmt.Sprintf("module.%s:\n", strings.Join(m.Path[1:], ".")))
760 s := bufio.NewScanner(strings.NewReader(mStr))
767 buf.WriteString(fmt.Sprintf("%s\n", text))
771 return strings.TrimSpace(buf.String())
774 // BackendState stores the configuration to connect to a remote backend.
775 type BackendState struct {
776 Type string `json:"type"` // Backend type
777 ConfigRaw json.RawMessage `json:"config"` // Backend raw config
778 Hash uint64 `json:"hash"` // Hash of portion of configuration from config files
781 // Empty returns true if BackendState has no state.
782 func (s *BackendState) Empty() bool {
783 return s == nil || s.Type == ""
786 // Config decodes the type-specific configuration object using the provided
787 // schema and returns the result as a cty.Value.
789 // An error is returned if the stored configuration does not conform to the
791 func (s *BackendState) Config(schema *configschema.Block) (cty.Value, error) {
792 ty := schema.ImpliedType()
794 return cty.NullVal(ty), nil
796 return ctyjson.Unmarshal(s.ConfigRaw, ty)
799 // SetConfig replaces (in-place) the type-specific configuration object using
800 // the provided value and associated schema.
802 // An error is returned if the given value does not conform to the implied
803 // type of the schema.
804 func (s *BackendState) SetConfig(val cty.Value, schema *configschema.Block) error {
805 ty := schema.ImpliedType()
806 buf, err := ctyjson.Marshal(val, ty)
814 // ForPlan produces an alternative representation of the reciever that is
815 // suitable for storing in a plan. The current workspace must additionally
816 // be provided, to be stored alongside the backend configuration.
818 // The backend configuration schema is required in order to properly
819 // encode the backend-specific configuration settings.
820 func (s *BackendState) ForPlan(schema *configschema.Block, workspaceName string) (*plans.Backend, error) {
825 configVal, err := s.Config(schema)
827 return nil, errwrap.Wrapf("failed to decode backend config: {{err}}", err)
829 return plans.NewBackend(s.Type, configVal, schema, workspaceName)
832 // RemoteState is used to track the information about a remote
833 // state store that we push/pull state to.
834 type RemoteState struct {
835 // Type controls the client we use for the remote state
836 Type string `json:"type"`
838 // Config is used to store arbitrary configuration that
840 Config map[string]string `json:"config"`
845 func (s *RemoteState) Lock() { s.mu.Lock() }
846 func (s *RemoteState) Unlock() { s.mu.Unlock() }
848 func (r *RemoteState) init() {
853 r.Config = make(map[string]string)
857 func (r *RemoteState) deepcopy() *RemoteState {
861 confCopy := make(map[string]string, len(r.Config))
862 for k, v := range r.Config {
871 func (r *RemoteState) Empty() bool {
881 func (r *RemoteState) Equals(other *RemoteState) bool {
885 if r.Type != other.Type {
888 if len(r.Config) != len(other.Config) {
891 for k, v := range r.Config {
892 if other.Config[k] != v {
899 // OutputState is used to track the state relevant to a single output.
900 type OutputState struct {
901 // Sensitive describes whether the output is considered sensitive,
902 // which may lead to masking the value on screen in some cases.
903 Sensitive bool `json:"sensitive"`
904 // Type describes the structure of Value. Valid values are "string",
906 Type string `json:"type"`
907 // Value contains the value of the output, in the structure described
908 // by the Type field.
909 Value interface{} `json:"value"`
914 func (s *OutputState) Lock() { s.mu.Lock() }
915 func (s *OutputState) Unlock() { s.mu.Unlock() }
917 func (s *OutputState) String() string {
918 return fmt.Sprintf("%#v", s.Value)
921 // Equal compares two OutputState structures for equality. nil values are
923 func (s *OutputState) Equal(other *OutputState) bool {
924 if s == nil && other == nil {
928 if s == nil || other == nil {
934 if s.Type != other.Type {
938 if s.Sensitive != other.Sensitive {
942 if !reflect.DeepEqual(s.Value, other.Value) {
949 func (s *OutputState) deepcopy() *OutputState {
954 stateCopy, err := copystructure.Config{Lock: true}.Copy(s)
956 panic(fmt.Errorf("Error copying output value: %s", err))
959 return stateCopy.(*OutputState)
962 // ModuleState is used to track all the state relevant to a single
963 // module. Previous to Terraform 0.3, all state belonged to the "root"
965 type ModuleState struct {
966 // Path is the import path from the root module. Modules imports are
967 // always disjoint, so the path represents amodule tree
968 Path []string `json:"path"`
970 // Locals are kept only transiently in-memory, because we can always
972 Locals map[string]interface{} `json:"-"`
974 // Outputs declared by the module and maintained for each module
975 // even though only the root module technically needs to be kept.
976 // This allows operators to inspect values at the boundaries.
977 Outputs map[string]*OutputState `json:"outputs"`
979 // Resources is a mapping of the logically named resource to
980 // the state of the resource. Each resource may actually have
981 // N instances underneath, although a user only needs to think
982 // about the 1:1 case.
983 Resources map[string]*ResourceState `json:"resources"`
985 // Dependencies are a list of things that this module relies on
986 // existing to remain intact. For example: an module may depend
987 // on a VPC ID given by an aws_vpc resource.
989 // Terraform uses this information to build valid destruction
990 // orders and to warn the user if they're destroying a module that
991 // another resource depends on.
993 // Things can be put into this list that may not be managed by
994 // Terraform. If Terraform doesn't find a matching ID in the
995 // overall state, then it assumes it isn't managed and doesn't
997 Dependencies []string `json:"depends_on"`
1002 func (s *ModuleState) Lock() { s.mu.Lock() }
1003 func (s *ModuleState) Unlock() { s.mu.Unlock() }
1005 // Equal tests whether one module state is equal to another.
1006 func (m *ModuleState) Equal(other *ModuleState) bool {
1010 // Paths must be equal
1011 if !reflect.DeepEqual(m.Path, other.Path) {
1015 // Outputs must be equal
1016 if len(m.Outputs) != len(other.Outputs) {
1019 for k, v := range m.Outputs {
1020 if !other.Outputs[k].Equal(v) {
1025 // Dependencies must be equal. This sorts these in place but
1026 // this shouldn't cause any problems.
1027 sort.Strings(m.Dependencies)
1028 sort.Strings(other.Dependencies)
1029 if len(m.Dependencies) != len(other.Dependencies) {
1032 for i, d := range m.Dependencies {
1033 if other.Dependencies[i] != d {
1038 // Resources must be equal
1039 if len(m.Resources) != len(other.Resources) {
1042 for k, r := range m.Resources {
1043 otherR, ok := other.Resources[k]
1048 if !r.Equal(otherR) {
1056 // IsRoot says whether or not this module diff is for the root module.
1057 func (m *ModuleState) IsRoot() bool {
1060 return reflect.DeepEqual(m.Path, rootModulePath)
1063 // IsDescendent returns true if other is a descendent of this module.
1064 func (m *ModuleState) IsDescendent(other *ModuleState) bool {
1069 return len(other.Path) > i && reflect.DeepEqual(other.Path[:i], m.Path)
1072 // Orphans returns a list of keys of resources that are in the State
1073 // but aren't present in the configuration itself. Hence, these keys
1074 // represent the state of resources that are orphans.
1075 func (m *ModuleState) Orphans(c *configs.Module) []addrs.ResourceInstance {
1079 inConfig := make(map[string]struct{})
1081 for _, r := range c.ManagedResources {
1082 inConfig[r.Addr().String()] = struct{}{}
1084 for _, r := range c.DataResources {
1085 inConfig[r.Addr().String()] = struct{}{}
1089 var result []addrs.ResourceInstance
1090 for k := range m.Resources {
1091 // Since we've not yet updated state to use our new address format,
1092 // we need to do some shimming here.
1093 legacyAddr, err := parseResourceAddressInternal(k)
1095 // Suggests that the user tampered with the state, since we always
1096 // generate valid internal addresses.
1097 log.Printf("ModuleState has invalid resource key %q. Ignoring.", k)
1101 addr := legacyAddr.AbsResourceInstanceAddr().Resource
1102 compareKey := addr.Resource.String() // compare by resource address, ignoring instance key
1103 if _, exists := inConfig[compareKey]; !exists {
1104 result = append(result, addr)
1110 // RemovedOutputs returns a list of outputs that are in the State but aren't
1111 // present in the configuration itself.
1112 func (s *ModuleState) RemovedOutputs(outputs map[string]*configs.Output) []addrs.OutputValue {
1114 // If we got no output map at all then we'll just treat our set of
1115 // configured outputs as empty, since that suggests that they've all
1116 // been removed by removing their containing module.
1117 outputs = make(map[string]*configs.Output)
1123 var ret []addrs.OutputValue
1124 for n := range s.Outputs {
1125 if _, declared := outputs[n]; !declared {
1126 ret = append(ret, addrs.OutputValue{
1135 // View returns a view with the given resource prefix.
1136 func (m *ModuleState) View(id string) *ModuleState {
1142 for k, _ := range r.Resources {
1143 if id == k || strings.HasPrefix(k, id+".") {
1147 delete(r.Resources, k)
1153 func (m *ModuleState) init() {
1160 if m.Outputs == nil {
1161 m.Outputs = make(map[string]*OutputState)
1163 if m.Resources == nil {
1164 m.Resources = make(map[string]*ResourceState)
1167 if m.Dependencies == nil {
1168 m.Dependencies = make([]string, 0)
1171 for _, rs := range m.Resources {
1176 func (m *ModuleState) deepcopy() *ModuleState {
1181 stateCopy, err := copystructure.Config{Lock: true}.Copy(m)
1186 return stateCopy.(*ModuleState)
1189 // prune is used to remove any resources that are no longer required
1190 func (m *ModuleState) prune() {
1194 for k, v := range m.Resources {
1195 if v == nil || (v.Primary == nil || v.Primary.ID == "") && len(v.Deposed) == 0 {
1196 delete(m.Resources, k)
1203 for k, v := range m.Outputs {
1204 if v.Value == config.UnknownVariableValue {
1205 delete(m.Outputs, k)
1209 m.Dependencies = uniqueStrings(m.Dependencies)
1212 func (m *ModuleState) sort() {
1213 for _, v := range m.Resources {
1218 func (m *ModuleState) String() string {
1222 var buf bytes.Buffer
1224 if len(m.Resources) == 0 {
1225 buf.WriteString("<no state>")
1228 names := make([]string, 0, len(m.Resources))
1229 for name, _ := range m.Resources {
1230 names = append(names, name)
1233 sort.Sort(resourceNameSort(names))
1235 for _, k := range names {
1236 rs := m.Resources[k]
1238 if rs.Primary != nil {
1242 id = "<not created>"
1246 if rs.Primary.Tainted {
1247 taintStr = " (tainted)"
1251 if len(rs.Deposed) > 0 {
1252 deposedStr = fmt.Sprintf(" (%d deposed)", len(rs.Deposed))
1255 buf.WriteString(fmt.Sprintf("%s:%s%s\n", k, taintStr, deposedStr))
1256 buf.WriteString(fmt.Sprintf(" ID = %s\n", id))
1257 if rs.Provider != "" {
1258 buf.WriteString(fmt.Sprintf(" provider = %s\n", rs.Provider))
1261 var attributes map[string]string
1262 if rs.Primary != nil {
1263 attributes = rs.Primary.Attributes
1265 attrKeys := make([]string, 0, len(attributes))
1266 for ak, _ := range attributes {
1271 attrKeys = append(attrKeys, ak)
1274 sort.Strings(attrKeys)
1276 for _, ak := range attrKeys {
1277 av := attributes[ak]
1278 buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av))
1281 for idx, t := range rs.Deposed {
1284 taintStr = " (tainted)"
1286 buf.WriteString(fmt.Sprintf(" Deposed ID %d = %s%s\n", idx+1, t.ID, taintStr))
1289 if len(rs.Dependencies) > 0 {
1290 buf.WriteString(fmt.Sprintf("\n Dependencies:\n"))
1291 for _, dep := range rs.Dependencies {
1292 buf.WriteString(fmt.Sprintf(" %s\n", dep))
1297 if len(m.Outputs) > 0 {
1298 buf.WriteString("\nOutputs:\n\n")
1300 ks := make([]string, 0, len(m.Outputs))
1301 for k, _ := range m.Outputs {
1307 for _, k := range ks {
1309 switch vTyped := v.Value.(type) {
1311 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped))
1313 buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped))
1314 case map[string]interface{}:
1315 var mapKeys []string
1316 for key, _ := range vTyped {
1317 mapKeys = append(mapKeys, key)
1319 sort.Strings(mapKeys)
1321 var mapBuf bytes.Buffer
1322 mapBuf.WriteString("{")
1323 for _, key := range mapKeys {
1324 mapBuf.WriteString(fmt.Sprintf("%s:%s ", key, vTyped[key]))
1326 mapBuf.WriteString("}")
1328 buf.WriteString(fmt.Sprintf("%s = %s\n", k, mapBuf.String()))
1336 func (m *ModuleState) Empty() bool {
1337 return len(m.Locals) == 0 && len(m.Outputs) == 0 && len(m.Resources) == 0
1340 // ResourceStateKey is a structured representation of the key used for the
1341 // ModuleState.Resources mapping
1342 type ResourceStateKey struct {
1345 Mode config.ResourceMode
1349 // Equal determines whether two ResourceStateKeys are the same
1350 func (rsk *ResourceStateKey) Equal(other *ResourceStateKey) bool {
1351 if rsk == nil || other == nil {
1354 if rsk.Mode != other.Mode {
1357 if rsk.Type != other.Type {
1360 if rsk.Name != other.Name {
1363 if rsk.Index != other.Index {
1369 func (rsk *ResourceStateKey) String() string {
1375 case config.ManagedResourceMode:
1377 case config.DataResourceMode:
1380 panic(fmt.Errorf("unknown resource mode %s", rsk.Mode))
1382 if rsk.Index == -1 {
1383 return fmt.Sprintf("%s%s.%s", prefix, rsk.Type, rsk.Name)
1385 return fmt.Sprintf("%s%s.%s.%d", prefix, rsk.Type, rsk.Name, rsk.Index)
1388 // ParseResourceStateKey accepts a key in the format used by
1389 // ModuleState.Resources and returns a resource name and resource index. In the
1390 // state, a resource has the format "type.name.index" or "type.name". In the
1391 // latter case, the index is returned as -1.
1392 func ParseResourceStateKey(k string) (*ResourceStateKey, error) {
1393 parts := strings.Split(k, ".")
1394 mode := config.ManagedResourceMode
1395 if len(parts) > 0 && parts[0] == "data" {
1396 mode = config.DataResourceMode
1397 // Don't need the constant "data" prefix for parsing
1398 // now that we've figured out the mode.
1401 if len(parts) < 2 || len(parts) > 3 {
1402 return nil, fmt.Errorf("Malformed resource state key: %s", k)
1404 rsk := &ResourceStateKey{
1410 if len(parts) == 3 {
1411 index, err := strconv.Atoi(parts[2])
1413 return nil, fmt.Errorf("Malformed resource state key index: %s", k)
1420 // ResourceState holds the state of a resource that is used so that
1421 // a provider can find and manage an existing resource as well as for
1422 // storing attributes that are used to populate variables of child
1425 // Attributes has attributes about the created resource that are
1426 // queryable in interpolation: "${type.id.attr}"
1428 // Extra is just extra data that a provider can return that we store
1429 // for later, but is not exposed in any way to the user.
1431 type ResourceState struct {
1432 // This is filled in and managed by Terraform, and is the resource
1433 // type itself such as "mycloud_instance". If a resource provider sets
1434 // this value, it won't be persisted.
1435 Type string `json:"type"`
1437 // Dependencies are a list of things that this resource relies on
1438 // existing to remain intact. For example: an AWS instance might
1439 // depend on a subnet (which itself might depend on a VPC, and so
1442 // Terraform uses this information to build valid destruction
1443 // orders and to warn the user if they're destroying a resource that
1444 // another resource depends on.
1446 // Things can be put into this list that may not be managed by
1447 // Terraform. If Terraform doesn't find a matching ID in the
1448 // overall state, then it assumes it isn't managed and doesn't
1450 Dependencies []string `json:"depends_on"`
1452 // Primary is the current active instance for this resource.
1453 // It can be replaced but only after a successful creation.
1454 // This is the instances on which providers will act.
1455 Primary *InstanceState `json:"primary"`
1457 // Deposed is used in the mechanics of CreateBeforeDestroy: the existing
1458 // Primary is Deposed to get it out of the way for the replacement Primary to
1459 // be created by Apply. If the replacement Primary creates successfully, the
1460 // Deposed instance is cleaned up.
1462 // If there were problems creating the replacement Primary, the Deposed
1463 // instance and the (now tainted) replacement Primary will be swapped so the
1464 // tainted replacement will be cleaned up instead.
1466 // An instance will remain in the Deposed list until it is successfully
1467 // destroyed and purged.
1468 Deposed []*InstanceState `json:"deposed"`
1470 // Provider is used when a resource is connected to a provider with an alias.
1471 // If this string is empty, the resource is connected to the default provider,
1472 // e.g. "aws_instance" goes with the "aws" provider.
1473 // If the resource block contained a "provider" key, that value will be set here.
1474 Provider string `json:"provider"`
1479 func (s *ResourceState) Lock() { s.mu.Lock() }
1480 func (s *ResourceState) Unlock() { s.mu.Unlock() }
1482 // Equal tests whether two ResourceStates are equal.
1483 func (s *ResourceState) Equal(other *ResourceState) bool {
1487 if s.Type != other.Type {
1491 if s.Provider != other.Provider {
1495 // Dependencies must be equal
1496 sort.Strings(s.Dependencies)
1497 sort.Strings(other.Dependencies)
1498 if len(s.Dependencies) != len(other.Dependencies) {
1501 for i, d := range s.Dependencies {
1502 if other.Dependencies[i] != d {
1507 // States must be equal
1508 if !s.Primary.Equal(other.Primary) {
1515 // Taint marks a resource as tainted.
1516 func (s *ResourceState) Taint() {
1520 if s.Primary != nil {
1521 s.Primary.Tainted = true
1525 // Untaint unmarks a resource as tainted.
1526 func (s *ResourceState) Untaint() {
1530 if s.Primary != nil {
1531 s.Primary.Tainted = false
1535 // ProviderAddr returns the provider address for the receiver, by parsing the
1536 // string representation saved in state. An error can be returned if the
1537 // value in state is corrupt.
1538 func (s *ResourceState) ProviderAddr() (addrs.AbsProviderConfig, error) {
1539 var diags tfdiags.Diagnostics
1542 traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
1543 diags = diags.Append(travDiags)
1544 if travDiags.HasErrors() {
1545 return addrs.AbsProviderConfig{}, diags.Err()
1548 addr, addrDiags := addrs.ParseAbsProviderConfig(traversal)
1549 diags = diags.Append(addrDiags)
1550 return addr, diags.Err()
1553 func (s *ResourceState) init() {
1557 if s.Primary == nil {
1558 s.Primary = &InstanceState{}
1562 if s.Dependencies == nil {
1563 s.Dependencies = []string{}
1566 if s.Deposed == nil {
1567 s.Deposed = make([]*InstanceState, 0)
1571 func (s *ResourceState) deepcopy() *ResourceState {
1572 copy, err := copystructure.Config{Lock: true}.Copy(s)
1577 return copy.(*ResourceState)
1580 // prune is used to remove any instances that are no longer required
1581 func (s *ResourceState) prune() {
1586 for i := 0; i < n; i++ {
1587 inst := s.Deposed[i]
1588 if inst == nil || inst.ID == "" {
1589 copy(s.Deposed[i:], s.Deposed[i+1:])
1590 s.Deposed[n-1] = nil
1595 s.Deposed = s.Deposed[:n]
1597 s.Dependencies = uniqueStrings(s.Dependencies)
1600 func (s *ResourceState) sort() {
1604 sort.Strings(s.Dependencies)
1607 func (s *ResourceState) String() string {
1611 var buf bytes.Buffer
1612 buf.WriteString(fmt.Sprintf("Type = %s", s.Type))
1616 // InstanceState is used to track the unique state information belonging
1617 // to a given instance.
1618 type InstanceState struct {
1619 // A unique ID for this resource. This is opaque to Terraform
1620 // and is only meant as a lookup mechanism for the providers.
1621 ID string `json:"id"`
1623 // Attributes are basic information about the resource. Any keys here
1624 // are accessible in variable format within Terraform configurations:
1625 // ${resourcetype.name.attribute}.
1626 Attributes map[string]string `json:"attributes"`
1628 // Ephemeral is used to store any state associated with this instance
1629 // that is necessary for the Terraform run to complete, but is not
1630 // persisted to a state file.
1631 Ephemeral EphemeralState `json:"-"`
1633 // Meta is a simple K/V map that is persisted to the State but otherwise
1634 // ignored by Terraform core. It's meant to be used for accounting by
1635 // external client code. The value here must only contain Go primitives
1637 Meta map[string]interface{} `json:"meta"`
1639 // Tainted is used to mark a resource for recreation.
1640 Tainted bool `json:"tainted"`
1645 func (s *InstanceState) Lock() { s.mu.Lock() }
1646 func (s *InstanceState) Unlock() { s.mu.Unlock() }
1648 func (s *InstanceState) init() {
1652 if s.Attributes == nil {
1653 s.Attributes = make(map[string]string)
1656 s.Meta = make(map[string]interface{})
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.
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{
1671 Meta: map[string]interface{}{
1672 "schema_version": schemaVersion,
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.
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.
1684 // This is for shimming from old components only and should not be used in
1686 func (s *InstanceState) AttrsAsObjectValue(ty cty.Type) (cty.Value, error) {
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{}
1693 if s.Attributes == nil {
1694 s.Attributes = map[string]string{}
1697 // make sure ID is included in the attributes. The InstanceState.ID value
1698 // takes precedence.
1700 s.Attributes["id"] = s.ID
1703 return hcl2shim.HCL2ValueFromFlatmap(s.Attributes, ty)
1706 // Copy all the Fields from another InstanceState
1707 func (s *InstanceState) Set(from *InstanceState) {
1715 s.Attributes = from.Attributes
1716 s.Ephemeral = from.Ephemeral
1718 s.Tainted = from.Tainted
1721 func (s *InstanceState) DeepCopy() *InstanceState {
1722 copy, err := copystructure.Config{Lock: true}.Copy(s)
1727 return copy.(*InstanceState)
1730 func (s *InstanceState) Empty() bool {
1740 func (s *InstanceState) Equal(other *InstanceState) bool {
1741 // Short circuit some nil checks
1742 if s == nil || other == nil {
1748 // IDs must be equal
1749 if s.ID != other.ID {
1753 // Attributes must be equal
1754 if len(s.Attributes) != len(other.Attributes) {
1757 for k, v := range s.Attributes {
1758 otherV, ok := other.Attributes[k]
1768 // Meta must be equal
1769 if len(s.Meta) != len(other.Meta) {
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
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)
1781 // marshaling primitives shouldn't ever error out
1784 otherMeta, err := json.Marshal(other.Meta)
1789 if !bytes.Equal(sMeta, otherMeta) {
1794 if s.Tainted != other.Tainted {
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.
1806 // If the diff attribute requires computing the value, and hence
1807 // won't be available until apply, the value is replaced with the
1809 func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState {
1810 result := s.DeepCopy()
1812 result = new(InstanceState)
1819 for k, v := range s.Attributes {
1820 result.Attributes[k] = v
1824 for k, diff := range d.CopyAttributes() {
1825 if diff.NewRemoved {
1826 delete(result.Attributes, k)
1829 if diff.NewComputed {
1830 result.Attributes[k] = config.UnknownVariableValue
1834 result.Attributes[k] = diff.New
1841 func (s *InstanceState) String() string {
1842 notCreated := "<not created>"
1851 var buf bytes.Buffer
1857 buf.WriteString(fmt.Sprintf("ID = %s\n", s.ID))
1859 attributes := s.Attributes
1860 attrKeys := make([]string, 0, len(attributes))
1861 for ak, _ := range attributes {
1866 attrKeys = append(attrKeys, ak)
1868 sort.Strings(attrKeys)
1870 for _, ak := range attrKeys {
1871 av := attributes[ak]
1872 buf.WriteString(fmt.Sprintf("%s = %s\n", ak, av))
1875 buf.WriteString(fmt.Sprintf("Tainted = %t\n", s.Tainted))
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:"-"`
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
1891 Type string `json:"-"`
1894 func (e *EphemeralState) init() {
1895 if e.ConnInfo == nil {
1896 e.ConnInfo = make(map[string]string)
1900 func (e *EphemeralState) DeepCopy() *EphemeralState {
1901 copy, err := copystructure.Config{Lock: true}.Copy(e)
1906 return copy.(*EphemeralState)
1909 type jsonStateVersionIdentifier struct {
1910 Version int `json:"version"`
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"))
1920 return fmt.Errorf("Failed to check for magic bytes: %v", err)
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" +
1932 // ErrNoState is returned by ReadState when the io.Reader contains no data
1933 var ErrNoState = errors.New("no state")
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
1944 buf := bufio.NewReader(src)
1946 if _, err := buf.Peek(1); err != nil {
1948 return nil, ErrNoState
1953 if err := testForV0State(buf); err != nil {
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)
1961 return nil, fmt.Errorf("Reading state file failed: %v", err)
1964 versionIdentifier := &jsonStateVersionIdentifier{}
1965 if err := json.Unmarshal(jsonBytes, versionIdentifier); err != nil {
1966 return nil, fmt.Errorf("Decoding state file version failed: %v", err)
1970 switch versionIdentifier.Version {
1972 return nil, fmt.Errorf("State version 0 is not supported as JSON.")
1974 v1State, err := ReadStateV1(jsonBytes)
1979 v2State, err := upgradeStateV1ToV2(v1State)
1984 v3State, err := upgradeStateV2ToV3(v2State)
1989 // increment the Serial whenever we upgrade state
1993 v2State, err := ReadStateV2(jsonBytes)
1997 v3State, err := upgradeStateV2ToV3(v2State)
2005 v3State, err := ReadStateV3(jsonBytes)
2012 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
2013 tfversion.SemVer.String(), versionIdentifier.Version)
2016 // If we reached this place we must have a result set
2018 panic("resulting state in load not set, assertion failed")
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).
2025 // Validate the state file is valid
2026 if err := result.Validate(); err != nil {
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)
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)
2047 func ReadStateV2(jsonBytes []byte) (*State, error) {
2049 if err := json.Unmarshal(jsonBytes, state); err != nil {
2050 return nil, fmt.Errorf("Decoding state file failed: %v", err)
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)
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.",
2073 // catch any unitialized fields in the state
2082 func ReadStateV3(jsonBytes []byte) (*State, error) {
2084 if err := json.Unmarshal(jsonBytes, state); err != nil {
2085 return nil, fmt.Errorf("Decoding state file failed: %v", err)
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)
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.",
2108 // catch any unitialized fields in the state
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)
2123 if !bytes.Equal(jsonBytes, buf.Bytes()) {
2124 log.Println("[INFO] state modified during read or write. incrementing serial number")
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.
2138 // make sure we have no uninitialized fields
2141 // Make sure it is sorted
2144 // Ensure the version is set
2145 d.Version = StateVersion
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 {
2153 "Error writing state, invalid version: %s\n\n"+
2154 "The Terraform version when writing the state must be a semantic\n"+
2160 // Encode the data in a human-friendly way
2161 data, err := json.MarshalIndent(d, "", " ")
2163 return fmt.Errorf("Failed to encode state: %s", err)
2166 // We append a newline to the data because MarshalIndent doesn't
2167 data = append(data, '\n')
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)
2177 // resourceNameSort implements the sort.Interface to sort name parts lexically for
2178 // strings and numerically for integer indexes.
2179 type resourceNameSort []string
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] }
2184 func (r resourceNameSort) Less(i, j int) bool {
2185 iParts := strings.Split(r[i], ".")
2186 jParts := strings.Split(r[j], ".")
2189 if len(jParts) < end {
2193 for idx := 0; idx < end; idx++ {
2194 if iParts[idx] == jParts[idx] {
2198 // sort on the first non-matching part
2199 iInt, iIntErr := strconv.Atoi(iParts[idx])
2200 jInt, jIntErr := strconv.Atoi(jParts[idx])
2203 case iIntErr == nil && jIntErr == nil:
2204 // sort numerically if both parts are integers
2206 case iIntErr == nil:
2207 // numbers sort before strings
2209 case jIntErr == nil:
2212 return iParts[idx] < jParts[idx]
2219 // moduleStateSort implements sort.Interface to sort module states
2220 type moduleStateSort []*ModuleState
2222 func (s moduleStateSort) Len() int {
2226 func (s moduleStateSort) Less(i, j int) bool {
2230 // If either is nil, then the nil one is "less" than
2231 if a == nil || b == nil {
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)
2240 // Otherwise, compare lexically
2241 return strings.Join(a.Path, ".") < strings.Join(b.Path, ".")
2244 func (s moduleStateSort) Swap(i, j int) {
2245 s[i], s[j] = s[j], s[i]
2248 const stateValidateErrMultiModule = `
2249 Multiple modules with the same path: %s
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.