terraform: read/write state to reader/writer

This commit is contained in:
Mitchell Hashimoto 2014-06-18 20:54:22 -07:00
parent 3b3ea2944c
commit 2dff411679
2 changed files with 72 additions and 0 deletions

View File

@ -2,7 +2,10 @@ package terraform
import (
"bytes"
"encoding/gob"
"errors"
"fmt"
"io"
"sync"
"github.com/hashicorp/terraform/config"
@ -38,6 +41,50 @@ func (s *State) String() string {
return buf.String()
}
// The format byte is prefixed into the state file format so that we have
// the ability in the future to change the file format if we want for any
// reason.
const stateFormatByte byte = 1
// ReadState reads a state structure out of a reader in the format that
// was written by WriteState.
func ReadState(src io.Reader) (*State, error) {
var result *State
var formatByte [1]byte
n, err := src.Read(formatByte[:])
if err != nil {
return nil, err
}
if n != len(formatByte) {
return nil, errors.New("failed to read state version byte")
}
if formatByte[0] != stateFormatByte {
return nil, fmt.Errorf("unknown state file version: %d", formatByte[0])
}
dec := gob.NewDecoder(src)
if err := dec.Decode(&result); err != nil {
return nil, err
}
return result, nil
}
// WriteState writes a state somewhere in a binary format.
func WriteState(d *State, dst io.Writer) error {
n, err := dst.Write([]byte{stateFormatByte})
if err != nil {
return err
}
if n != 1 {
return errors.New("failed to write state version byte")
}
return gob.NewEncoder(dst).Encode(d)
}
// ResourceState holds the state of a resource that is used so that
// a provider can find and manage an existing resource as well as for
// storing attributes that are uesd to populate variables of child

View File

@ -1,6 +1,7 @@
package terraform
import (
"bytes"
"reflect"
"testing"
@ -64,3 +65,27 @@ func TestResourceState_MergeDiff_nil(t *testing.T) {
t.Fatalf("bad: %#v", rs2.Attributes)
}
}
func TestReadWriteState(t *testing.T) {
state := &State{
Resources: map[string]*ResourceState{
"foo": &ResourceState{
ID: "bar",
},
},
}
buf := new(bytes.Buffer)
if err := WriteState(state, buf); err != nil {
t.Fatalf("err: %s", err)
}
actual, err := ReadState(buf)
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(actual, state) {
t.Fatalf("bad: %#v", actual)
}
}