mirror of https://github.com/hashicorp/terraform
This is REALLY heavy and would be really hard to maintain any sort of compatibility with, but it is what we're going to do during dev initially (if we don't ship with it) in order to just get stuff working.pull/5/head
parent
dc193f5f33
commit
d2001275dc
@ -0,0 +1,63 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
)
|
||||
|
||||
// Plan represents a single Terraform execution plan, which contains
|
||||
// all the information necessary to make an infrastructure change.
|
||||
type Plan struct {
|
||||
Config *config.Config
|
||||
Diff *Diff
|
||||
State *State
|
||||
Vars map[string]string
|
||||
}
|
||||
|
||||
// The format byte is prefixed into the plan file format so that we have
|
||||
// the ability in the future to change the file format if we want for any
|
||||
// reason.
|
||||
const planFormatByte byte = 1
|
||||
|
||||
// ReadPlan reads a plan structure out of a reader in the format that
|
||||
// was written by WritePlan.
|
||||
func ReadPlan(src io.Reader) (*Plan, error) {
|
||||
var result *Plan
|
||||
|
||||
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 plan version byte")
|
||||
}
|
||||
|
||||
if formatByte[0] != planFormatByte {
|
||||
return nil, fmt.Errorf("unknown plan file version: %d", formatByte[0])
|
||||
}
|
||||
|
||||
dec := gob.NewDecoder(src)
|
||||
if err := dec.Decode(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// WritePlan writes a plan somewhere in a binary format.
|
||||
func WritePlan(d *Plan, dst io.Writer) error {
|
||||
n, err := dst.Write([]byte{planFormatByte})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != 1 {
|
||||
return errors.New("failed to write plan version byte")
|
||||
}
|
||||
|
||||
return gob.NewEncoder(dst).Encode(d)
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadWritePlan(t *testing.T) {
|
||||
tf := testTerraform(t, "new-good")
|
||||
plan := &Plan{
|
||||
Config: tf.config,
|
||||
Diff: &Diff{
|
||||
Resources: map[string]*ResourceDiff{
|
||||
"nodeA": &ResourceDiff{
|
||||
Attributes: map[string]*ResourceAttrDiff{
|
||||
"foo": &ResourceAttrDiff{
|
||||
Old: "foo",
|
||||
New: "bar",
|
||||
},
|
||||
"bar": &ResourceAttrDiff{
|
||||
Old: "foo",
|
||||
NewComputed: true,
|
||||
},
|
||||
"longfoo": &ResourceAttrDiff{
|
||||
Old: "foo",
|
||||
New: "bar",
|
||||
RequiresNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
State: &State{
|
||||
Resources: map[string]*ResourceState{
|
||||
"foo": &ResourceState{
|
||||
ID: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Vars: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := WritePlan(plan, buf); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual, err := ReadPlan(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, plan) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue