diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/state.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/state.go | 108 |
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 | ||
25 | const ( | 28 | const ( |
@@ -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 | ||
670 | func (s *State) Init() { | 673 | func (s *State) Init() { |
@@ -704,7 +707,11 @@ func (s *State) EnsureHasLineage() { | |||
704 | 707 | ||
705 | func (s *State) ensureHasLineage() { | 708 | func (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. | ||
1123 | func (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 | ||
1347 | func (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 |
1313 | type ResourceStateKey struct { | 1353 | type 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. |
1826 | func ReadState(src io.Reader) (*State, error) { | 1879 | func 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. | ||
2192 | func 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 | |||
2129 | const stateValidateErrMultiModule = ` | 2203 | const stateValidateErrMultiModule = ` |
2130 | Multiple modules with the same path: %s | 2204 | Multiple 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 | |||
2134 | to behave in unexpected and error prone ways and is invalid. Please back up | 2208 | to behave in unexpected and error prone ways and is invalid. Please back up |
2135 | and modify your state file manually to resolve this. | 2209 | and modify your state file manually to resolve this. |
2136 | ` | 2210 | ` |
2211 | |||
2212 | const stateInvalidTerraformVersionErr = ` | ||
2213 | Terraform doesn't allow running any operations against a state | ||
2214 | that was written by a future Terraform version. The state is | ||
2215 | reporting it is written by Terraform '%s' | ||
2216 | |||
2217 | Please run at least that version of Terraform to continue. | ||
2218 | ` | ||