aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/terraform/state.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/state.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/state.go108
1 files changed, 95 insertions, 13 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/state.go b/vendor/github.com/hashicorp/terraform/terraform/state.go
index 0c46194..04b14a6 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/state.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/state.go
@@ -9,6 +9,7 @@ import (
9 "io" 9 "io"
10 "io/ioutil" 10 "io/ioutil"
11 "log" 11 "log"
12 "os"
12 "reflect" 13 "reflect"
13 "sort" 14 "sort"
14 "strconv" 15 "strconv"
@@ -16,10 +17,12 @@ import (
16 "sync" 17 "sync"
17 18
18 "github.com/hashicorp/go-multierror" 19 "github.com/hashicorp/go-multierror"
20 "github.com/hashicorp/go-uuid"
19 "github.com/hashicorp/go-version" 21 "github.com/hashicorp/go-version"
20 "github.com/hashicorp/terraform/config" 22 "github.com/hashicorp/terraform/config"
21 "github.com/mitchellh/copystructure" 23 "github.com/mitchellh/copystructure"
22 "github.com/satori/go.uuid" 24
25 tfversion "github.com/hashicorp/terraform/version"
23) 26)
24 27
25const ( 28const (
@@ -664,7 +667,7 @@ func (s *State) FromFutureTerraform() bool {
664 } 667 }
665 668
666 v := version.Must(version.NewVersion(s.TFVersion)) 669 v := version.Must(version.NewVersion(s.TFVersion))
667 return SemVersion.LessThan(v) 670 return tfversion.SemVer.LessThan(v)
668} 671}
669 672
670func (s *State) Init() { 673func (s *State) Init() {
@@ -704,7 +707,11 @@ func (s *State) EnsureHasLineage() {
704 707
705func (s *State) ensureHasLineage() { 708func (s *State) ensureHasLineage() {
706 if s.Lineage == "" { 709 if s.Lineage == "" {
707 s.Lineage = uuid.NewV4().String() 710 lineage, err := uuid.GenerateUUID()
711 if err != nil {
712 panic(fmt.Errorf("Failed to generate lineage: %v", err))
713 }
714 s.Lineage = lineage
708 log.Printf("[DEBUG] New state was assigned lineage %q\n", s.Lineage) 715 log.Printf("[DEBUG] New state was assigned lineage %q\n", s.Lineage)
709 } else { 716 } else {
710 log.Printf("[TRACE] Preserving existing state lineage %q\n", s.Lineage) 717 log.Printf("[TRACE] Preserving existing state lineage %q\n", s.Lineage)
@@ -977,6 +984,10 @@ type ModuleState struct {
977 // always disjoint, so the path represents amodule tree 984 // always disjoint, so the path represents amodule tree
978 Path []string `json:"path"` 985 Path []string `json:"path"`
979 986
987 // Locals are kept only transiently in-memory, because we can always
988 // re-compute them.
989 Locals map[string]interface{} `json:"-"`
990
980 // Outputs declared by the module and maintained for each module 991 // Outputs declared by the module and maintained for each module
981 // even though only the root module technically needs to be kept. 992 // even though only the root module technically needs to be kept.
982 // This allows operators to inspect values at the boundaries. 993 // This allows operators to inspect values at the boundaries.
@@ -1083,7 +1094,7 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
1083 defer m.Unlock() 1094 defer m.Unlock()
1084 1095
1085 keys := make(map[string]struct{}) 1096 keys := make(map[string]struct{})
1086 for k, _ := range m.Resources { 1097 for k := range m.Resources {
1087 keys[k] = struct{}{} 1098 keys[k] = struct{}{}
1088 } 1099 }
1089 1100
@@ -1091,7 +1102,7 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
1091 for _, r := range c.Resources { 1102 for _, r := range c.Resources {
1092 delete(keys, r.Id()) 1103 delete(keys, r.Id())
1093 1104
1094 for k, _ := range keys { 1105 for k := range keys {
1095 if strings.HasPrefix(k, r.Id()+".") { 1106 if strings.HasPrefix(k, r.Id()+".") {
1096 delete(keys, k) 1107 delete(keys, k)
1097 } 1108 }
@@ -1100,7 +1111,32 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
1100 } 1111 }
1101 1112
1102 result := make([]string, 0, len(keys)) 1113 result := make([]string, 0, len(keys))
1103 for k, _ := range keys { 1114 for k := range keys {
1115 result = append(result, k)
1116 }
1117
1118 return result
1119}
1120
1121// RemovedOutputs returns a list of outputs that are in the State but aren't
1122// present in the configuration itself.
1123func (m *ModuleState) RemovedOutputs(c *config.Config) []string {
1124 m.Lock()
1125 defer m.Unlock()
1126
1127 keys := make(map[string]struct{})
1128 for k := range m.Outputs {
1129 keys[k] = struct{}{}
1130 }
1131
1132 if c != nil {
1133 for _, o := range c.Outputs {
1134 delete(keys, o.Name)
1135 }
1136 }
1137
1138 result := make([]string, 0, len(keys))
1139 for k := range keys {
1104 result = append(result, k) 1140 result = append(result, k)
1105 } 1141 }
1106 1142
@@ -1308,6 +1344,10 @@ func (m *ModuleState) String() string {
1308 return buf.String() 1344 return buf.String()
1309} 1345}
1310 1346
1347func (m *ModuleState) Empty() bool {
1348 return len(m.Locals) == 0 && len(m.Outputs) == 0 && len(m.Resources) == 0
1349}
1350
1311// ResourceStateKey is a structured representation of the key used for the 1351// ResourceStateKey is a structured representation of the key used for the
1312// ModuleState.Resources mapping 1352// ModuleState.Resources mapping
1313type ResourceStateKey struct { 1353type ResourceStateKey struct {
@@ -1681,7 +1721,20 @@ func (s *InstanceState) Equal(other *InstanceState) bool {
1681 // We only do the deep check if both are non-nil. If one is nil 1721 // We only do the deep check if both are non-nil. If one is nil
1682 // we treat it as equal since their lengths are both zero (check 1722 // we treat it as equal since their lengths are both zero (check
1683 // above). 1723 // above).
1684 if !reflect.DeepEqual(s.Meta, other.Meta) { 1724 //
1725 // Since this can contain numeric values that may change types during
1726 // serialization, let's compare the serialized values.
1727 sMeta, err := json.Marshal(s.Meta)
1728 if err != nil {
1729 // marshaling primitives shouldn't ever error out
1730 panic(err)
1731 }
1732 otherMeta, err := json.Marshal(other.Meta)
1733 if err != nil {
1734 panic(err)
1735 }
1736
1737 if !bytes.Equal(sMeta, otherMeta) {
1685 return false 1738 return false
1686 } 1739 }
1687 } 1740 }
@@ -1824,11 +1877,19 @@ var ErrNoState = errors.New("no state")
1824// ReadState reads a state structure out of a reader in the format that 1877// ReadState reads a state structure out of a reader in the format that
1825// was written by WriteState. 1878// was written by WriteState.
1826func ReadState(src io.Reader) (*State, error) { 1879func ReadState(src io.Reader) (*State, error) {
1880 // check for a nil file specifically, since that produces a platform
1881 // specific error if we try to use it in a bufio.Reader.
1882 if f, ok := src.(*os.File); ok && f == nil {
1883 return nil, ErrNoState
1884 }
1885
1827 buf := bufio.NewReader(src) 1886 buf := bufio.NewReader(src)
1887
1828 if _, err := buf.Peek(1); err != nil { 1888 if _, err := buf.Peek(1); err != nil {
1829 // the error is either io.EOF or "invalid argument", and both are from 1889 if err == io.EOF {
1830 // an empty state. 1890 return nil, ErrNoState
1831 return nil, ErrNoState 1891 }
1892 return nil, err
1832 } 1893 }
1833 1894
1834 if err := testForV0State(buf); err != nil { 1895 if err := testForV0State(buf); err != nil {
@@ -1891,7 +1952,7 @@ func ReadState(src io.Reader) (*State, error) {
1891 result = v3State 1952 result = v3State
1892 default: 1953 default:
1893 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 1954 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
1894 SemVersion.String(), versionIdentifier.Version) 1955 tfversion.SemVer.String(), versionIdentifier.Version)
1895 } 1956 }
1896 1957
1897 // If we reached this place we must have a result set 1958 // If we reached this place we must have a result set
@@ -1935,7 +1996,7 @@ func ReadStateV2(jsonBytes []byte) (*State, error) {
1935 // version that we don't understand 1996 // version that we don't understand
1936 if state.Version > StateVersion { 1997 if state.Version > StateVersion {
1937 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 1998 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
1938 SemVersion.String(), state.Version) 1999 tfversion.SemVer.String(), state.Version)
1939 } 2000 }
1940 2001
1941 // Make sure the version is semantic 2002 // Make sure the version is semantic
@@ -1970,7 +2031,7 @@ func ReadStateV3(jsonBytes []byte) (*State, error) {
1970 // version that we don't understand 2031 // version that we don't understand
1971 if state.Version > StateVersion { 2032 if state.Version > StateVersion {
1972 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.", 2033 return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
1973 SemVersion.String(), state.Version) 2034 tfversion.SemVer.String(), state.Version)
1974 } 2035 }
1975 2036
1976 // Make sure the version is semantic 2037 // Make sure the version is semantic
@@ -2126,6 +2187,19 @@ func (s moduleStateSort) Swap(i, j int) {
2126 s[i], s[j] = s[j], s[i] 2187 s[i], s[j] = s[j], s[i]
2127} 2188}
2128 2189
2190// StateCompatible returns an error if the state is not compatible with the
2191// current version of terraform.
2192func CheckStateVersion(state *State) error {
2193 if state == nil {
2194 return nil
2195 }
2196
2197 if state.FromFutureTerraform() {
2198 return fmt.Errorf(stateInvalidTerraformVersionErr, state.TFVersion)
2199 }
2200 return nil
2201}
2202
2129const stateValidateErrMultiModule = ` 2203const stateValidateErrMultiModule = `
2130Multiple modules with the same path: %s 2204Multiple modules with the same path: %s
2131 2205
@@ -2134,3 +2208,11 @@ in your state file that point to the same module. This will cause Terraform
2134to behave in unexpected and error prone ways and is invalid. Please back up 2208to behave in unexpected and error prone ways and is invalid. Please back up
2135and modify your state file manually to resolve this. 2209and modify your state file manually to resolve this.
2136` 2210`
2211
2212const stateInvalidTerraformVersionErr = `
2213Terraform doesn't allow running any operations against a state
2214that was written by a future Terraform version. The state is
2215reporting it is written by Terraform '%s'
2216
2217Please run at least that version of Terraform to continue.
2218`