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