From 5adc55415b0eebf0a5ef96dc2816e286399a7621 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Thu, 18 Sep 2014 10:51:39 -0700 Subject: [PATCH] terraform: testing new state file format --- terraform/state_test.go | 156 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/terraform/state_test.go b/terraform/state_test.go index 02ecb2c8e..5be330400 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -1,6 +1,7 @@ package terraform import ( + "bytes" "reflect" "testing" @@ -91,3 +92,158 @@ func TestInstanceState_MergeDiff_nilDiff(t *testing.T) { t.Fatalf("bad: %#v", is2.Attributes) } } + +func TestReadUpgradeState(t *testing.T) { + state := &StateV1{ + Resources: map[string]*ResourceStateV1{ + "foo": &ResourceStateV1{ + ID: "bar", + }, + }, + } + buf := new(bytes.Buffer) + if err := testWriteStateV1(state, buf); err != nil { + t.Fatalf("err: %s", err) + } + + // ReadState should transparently detect the old + // version and upgrade up so the latest. + actual, err := ReadState(buf) + if err != nil { + t.Fatalf("err: %s", err) + } + + upgraded, err := upgradeV1State(state) + if err != nil { + t.Fatalf("err: %s", err) + } + + if !reflect.DeepEqual(actual, upgraded) { + t.Fatalf("bad: %#v", actual) + } +} + +func TestReadWriteState(t *testing.T) { + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "foo": &ResourceState{ + Primary: &InstanceState{ + ID: "bar", + Ephemeral: EphemeralState{ + ConnInfo: map[string]string{ + "type": "ssh", + "user": "root", + "password": "supersecret", + }, + }, + }, + }, + }, + }, + }, + } + + // Checksum before the write + chksum := checksumStruct(t, state) + + buf := new(bytes.Buffer) + if err := WriteState(state, buf); err != nil { + t.Fatalf("err: %s", err) + } + + // Checksum after the write + chksumAfter := checksumStruct(t, state) + if chksumAfter != chksum { + t.Fatalf("structure changed during serialization!") + } + + actual, err := ReadState(buf) + if err != nil { + t.Fatalf("err: %s", err) + } + + // ReadState should not restore sensitive information! + mod := state.RootModule() + mod.Resources["foo"].Primary.Ephemeral = EphemeralState{} + + if !reflect.DeepEqual(actual, state) { + t.Fatalf("bad: %#v", actual) + } +} + +func TestUpgradeV1State(t *testing.T) { + old := &StateV1{ + Outputs: map[string]string{ + "ip": "127.0.0.1", + }, + Resources: map[string]*ResourceStateV1{ + "foo": &ResourceStateV1{ + Type: "test_resource", + ID: "bar", + Attributes: map[string]string{ + "key": "val", + }, + }, + "bar": &ResourceStateV1{ + Type: "test_resource", + ID: "1234", + Attributes: map[string]string{ + "a": "b", + }, + }, + }, + Tainted: map[string]struct{}{ + "bar": struct{}{}, + }, + } + state, err := upgradeV1State(old) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(state.Modules) != 1 { + t.Fatalf("should only have root module: %#v", state.Modules) + } + root := state.RootModule() + + if len(root.Outputs) != 1 { + t.Fatalf("bad outputs: %v", root.Outputs) + } + if root.Outputs["ip"] != "127.0.0.1" { + t.Fatalf("bad outputs: %v", root.Outputs) + } + + if len(root.Resources) != 2 { + t.Fatalf("bad resources: %v", root.Resources) + } + + foo := root.Resources["foo"] + if foo.Type != "test_resource" { + t.Fatalf("bad: %#v", foo) + } + if foo.Primary == nil || foo.Primary.ID != "bar" || + foo.Primary.Attributes["key"] != "val" { + t.Fatalf("bad: %#v", foo) + } + if len(foo.Tainted) > 0 { + t.Fatalf("bad: %#v", foo) + } + + bar := root.Resources["bar"] + if bar.Type != "test_resource" { + t.Fatalf("bad: %#v", bar) + } + if bar.Primary != nil { + t.Fatalf("bad: %#v", bar) + } + if len(bar.Tainted) != 1 { + t.Fatalf("bad: %#v", bar) + } + bt := bar.Tainted[0] + if bt.ID != "1234" || bt.Attributes["a"] != "b" { + t.Fatalf("bad: %#v", bt) + } +}