remote: refactor for ReadLocalState

This commit is contained in:
Armon Dadgar 2014-10-08 10:48:46 -07:00 committed by Mitchell Hashimoto
parent bec1dfcd68
commit 220d496f9c
1 changed files with 36 additions and 45 deletions

View File

@ -178,6 +178,30 @@ func validConfig(conf *terraform.RemoteState) error {
return nil
}
// ReadLocalState is used to read and parse the local state file
func ReadLocalState() (*terraform.State, []byte, error) {
path, err := HiddenStatePath()
if err != nil {
return nil, nil, err
}
// Open the existing file
raw, err := ioutil.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil, nil
}
return nil, nil, fmt.Errorf("Failed to open state file '%s': %s", path, err)
}
// Decode the state
state, err := terraform.ReadState(bytes.NewReader(raw))
if err != nil {
return nil, nil, fmt.Errorf("Failed to read state file '%s': %v", path, err)
}
return state, raw, nil
}
// ValidateConfig is used to take a remote state configuration,
// ensure the local directory exists and that the remote state
// does not conflict with an existing state file.
@ -193,39 +217,28 @@ func ValidateConfig(conf *terraform.RemoteState) error {
"Remote state setup failed: %s", err)
}
// Get the path to the state file
path, err := HiddenStatePath()
// Check for local state
local, _, err := ReadLocalState()
if err != nil {
return err
}
// Open the existing file
f, err := os.Open(path)
if err != nil {
if !os.IsNotExist(err) {
return fmt.Errorf("Failed to open state file '%s': %s", path, err)
}
// Nothing to check if no local state yet
if local == nil {
return nil
}
defer f.Close()
// Decode the state
state, err := terraform.ReadState(f)
if err != nil {
return fmt.Errorf("Failed to read state file '%s': %v", path, err)
}
// If the hidden state file has no remote info, something
// is definitely wrong...
if state.Remote == nil {
return fmt.Errorf(`State file '%s' missing remote storage information.
if local.Remote == nil {
return fmt.Errorf(`Local state file missing remote storage information.
This is likely a bug, please report it.`)
}
// Check if there is a conflict
if !state.Remote.Equals(conf) {
if !local.Remote.Equals(conf) {
return fmt.Errorf(
"Conflicting definitions for remote storage in existing state file '%s'", path)
"Conflicting definitions for remote storage in existing state file")
}
return nil
}
@ -258,28 +271,12 @@ func RefreshState(conf *terraform.RemoteState) (StateChangeResult, error) {
}
}
// Get the path to the state file
path, err := HiddenStatePath()
// Decode the state
localState, raw, err := ReadLocalState()
if err != nil {
return StateChangeNoop, err
}
// Get the existing state file
raw, err := ioutil.ReadFile(path)
if err != nil && !os.IsNotExist(err) {
return StateChangeNoop, fmt.Errorf("Failed to read local state: %v", err)
}
// Decode the state
var localState *terraform.State
if raw != nil {
localState, err = terraform.ReadState(bytes.NewReader(raw))
if err != nil {
return StateChangeNoop,
fmt.Errorf("Failed to decode state file '%s': %v", path, err)
}
}
// We need to handle the matrix of cases in reconciling
// the local and remote state. Primarily the concern is
// around the Serial number which should grow monotonically.
@ -335,18 +332,12 @@ func RefreshState(conf *terraform.RemoteState) (StateChangeResult, error) {
// can be 'forced' to override any conflict detection
// on the server-side.
func PushState(conf *terraform.RemoteState, force bool) (StateChangeResult, error) {
// Get the path to the state file
path, err := HiddenStatePath()
// Read the local state
_, raw, err := ReadLocalState()
if err != nil {
return StateChangeNoop, err
}
// Get the existing state file
raw, err := ioutil.ReadFile(path)
if err != nil && !os.IsNotExist(err) {
return StateChangeNoop, fmt.Errorf("Failed to read local state: %v", err)
}
// Check if there is no local state
if raw == nil {
return StateChangeNoop, fmt.Errorf("No local state to push")