|
|
|
|
@ -14,6 +14,7 @@ import (
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
|
|
|
"github.com/hashicorp/go-version"
|
|
|
|
|
"github.com/hashicorp/terraform/config"
|
|
|
|
|
"github.com/mitchellh/copystructure"
|
|
|
|
|
@ -247,6 +248,46 @@ func (s *State) IsRemote() bool {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate validates the integrity of this state file.
|
|
|
|
|
//
|
|
|
|
|
// Certain properties of the statefile are expected by Terraform in order
|
|
|
|
|
// to behave properly. The core of Terraform will assume that once it
|
|
|
|
|
// receives a State structure that it has been validated. This validation
|
|
|
|
|
// check should be called to ensure that.
|
|
|
|
|
//
|
|
|
|
|
// If this returns an error, then the user should be notified. The error
|
|
|
|
|
// response will include detailed information on the nature of the error.
|
|
|
|
|
func (s *State) Validate() error {
|
|
|
|
|
var result error
|
|
|
|
|
|
|
|
|
|
// !!!! FOR DEVELOPERS !!!!
|
|
|
|
|
//
|
|
|
|
|
// Any errors returned from this Validate function will BLOCK TERRAFORM
|
|
|
|
|
// from loading a state file. Therefore, this should only contain checks
|
|
|
|
|
// that are only resolvable through manual intervention.
|
|
|
|
|
//
|
|
|
|
|
// !!!! FOR DEVELOPERS !!!!
|
|
|
|
|
|
|
|
|
|
// Make sure there are no duplicate module states. We open a new
|
|
|
|
|
// block here so we can use basic variable names and future validations
|
|
|
|
|
// can do the same.
|
|
|
|
|
{
|
|
|
|
|
found := make(map[string]struct{})
|
|
|
|
|
for _, ms := range s.Modules {
|
|
|
|
|
key := strings.Join(ms.Path, ".")
|
|
|
|
|
if _, ok := found[key]; ok {
|
|
|
|
|
result = multierror.Append(result, fmt.Errorf(
|
|
|
|
|
strings.TrimSpace(stateValidateErrMultiModule), key))
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
found[key] = struct{}{}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove removes the item in the state at the given address, returning
|
|
|
|
|
// any errors that may have occurred.
|
|
|
|
|
//
|
|
|
|
|
@ -1549,6 +1590,7 @@ func ReadState(src io.Reader) (*State, error) {
|
|
|
|
|
return nil, fmt.Errorf("Decoding state file version failed: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var result *State
|
|
|
|
|
switch versionIdentifier.Version {
|
|
|
|
|
case 0:
|
|
|
|
|
return nil, fmt.Errorf("State version 0 is not supported as JSON.")
|
|
|
|
|
@ -1570,7 +1612,7 @@ func ReadState(src io.Reader) (*State, error) {
|
|
|
|
|
|
|
|
|
|
// increment the Serial whenever we upgrade state
|
|
|
|
|
v3State.Serial++
|
|
|
|
|
return v3State, nil
|
|
|
|
|
result = v3State
|
|
|
|
|
case 2:
|
|
|
|
|
v2State, err := ReadStateV2(jsonBytes)
|
|
|
|
|
if err != nil {
|
|
|
|
|
@ -1582,18 +1624,30 @@ func ReadState(src io.Reader) (*State, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v3State.Serial++
|
|
|
|
|
return v3State, nil
|
|
|
|
|
result = v3State
|
|
|
|
|
case 3:
|
|
|
|
|
v3State, err := ReadStateV3(jsonBytes)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return v3State, nil
|
|
|
|
|
|
|
|
|
|
result = v3State
|
|
|
|
|
default:
|
|
|
|
|
return nil, fmt.Errorf("Terraform %s does not support state version %d, please update.",
|
|
|
|
|
SemVersion.String(), versionIdentifier.Version)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we reached this place we must have a result set
|
|
|
|
|
if result == nil {
|
|
|
|
|
panic("resulting state in load not set, assertion failed")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate the state file is valid
|
|
|
|
|
if err := result.Validate(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ReadStateV1(jsonBytes []byte) (*stateV1, error) {
|
|
|
|
|
@ -1758,3 +1812,12 @@ func (s moduleStateSort) Less(i, j int) bool {
|
|
|
|
|
func (s moduleStateSort) Swap(i, j int) {
|
|
|
|
|
s[i], s[j] = s[j], s[i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const stateValidateErrMultiModule = `
|
|
|
|
|
Multiple modules with the same path: %s
|
|
|
|
|
|
|
|
|
|
This means that there are multiple entries in the "modules" field
|
|
|
|
|
in your state file that point to the same module. This will cause Terraform
|
|
|
|
|
to behave in unexpected and error prone ways and is invalid. Please back up
|
|
|
|
|
and modify your state file manually to resolve this.
|
|
|
|
|
`
|
|
|
|
|
|