terraform: fixing test errors

This commit is contained in:
Armon Dadgar 2014-09-16 15:09:40 -07:00
parent 196991430b
commit 4b0f970659
6 changed files with 463 additions and 205 deletions

View File

@ -71,10 +71,17 @@ func TestContextValidate_orphans(t *testing.T) {
p := testProvider("aws")
config := testConfig(t, "validate-good")
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
@ -348,8 +355,9 @@ func TestContextApply(t *testing.T) {
t.Fatalf("err: %s", err)
}
if len(state.Resources) < 2 {
t.Fatalf("bad: %#v", state.Resources)
mod := state.RootModule()
if len(mod.Resources) < 2 {
t.Fatalf("bad: %#v", mod.Resources)
}
actual := strings.TrimSpace(state.String())
@ -441,10 +449,12 @@ func TestContextApply_cancel(t *testing.T) {
}
return &ResourceState{
Primary: &InstanceState{
ID: "foo",
Attributes: map[string]string{
"num": "2",
},
},
}, nil
}
p.DiffFn = func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) {
@ -474,8 +484,9 @@ func TestContextApply_cancel(t *testing.T) {
state := <-stateCh
if len(state.Resources) != 1 {
t.Fatalf("bad: %#v", state.Resources)
mod := state.RootModule()
if len(mod.Resources) != 1 {
t.Fatalf("bad: %#v", mod.Resources)
}
actual := strings.TrimSpace(state.String())
@ -678,10 +689,17 @@ func TestContextApply_outputDiffVars(t *testing.T) {
c := testConfig(t, "apply-good")
p := testProvider("aws")
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.baz": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
@ -701,7 +719,7 @@ func TestContextApply_outputDiffVars(t *testing.T) {
}
result := s.MergeDiff(d)
result.ID = "foo"
result.Primary.ID = "foo"
return result, nil
}
p.DiffFn = func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) {
@ -732,12 +750,12 @@ func TestContextApply_Provisioner_ConnInfo(t *testing.T) {
pr := testProvisioner()
p.ApplyFn = func(s *ResourceState, d *ResourceDiff) (*ResourceState, error) {
if s.ConnInfo == nil {
if s.Primary.Ephemeral.ConnInfo == nil {
t.Fatalf("ConnInfo not initialized")
}
result, _ := testApplyFn(s, d)
result.ConnInfo = map[string]string{
result.Primary.Ephemeral.ConnInfo = map[string]string{
"type": "ssh",
"host": "127.0.0.1",
"port": "22",
@ -747,7 +765,7 @@ func TestContextApply_Provisioner_ConnInfo(t *testing.T) {
p.DiffFn = testDiffFn
pr.ApplyFn = func(rs *ResourceState, c *ResourceConfig) error {
conn := rs.ConnInfo
conn := rs.Primary.Ephemeral.ConnInfo
if conn["type"] != "telnet" {
t.Fatalf("Bad: %#v", conn)
}
@ -887,8 +905,9 @@ func TestContextApply_destroyOutputs(t *testing.T) {
t.Fatalf("err: %s", err)
}
if len(state.Resources) > 0 {
t.Fatalf("bad: %#v", state)
mod := state.RootModule()
if len(mod.Resources) > 0 {
t.Fatalf("bad: %#v", mod)
}
}
@ -896,10 +915,17 @@ func TestContextApply_destroyOrphan(t *testing.T) {
c := testConfig(t, "apply-error")
p := testProvider("aws")
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.baz": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
@ -917,7 +943,7 @@ func TestContextApply_destroyOrphan(t *testing.T) {
}
result := s.MergeDiff(d)
result.ID = "foo"
result.Primary.ID = "foo"
return result, nil
}
p.DiffFn = func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) {
@ -939,8 +965,9 @@ func TestContextApply_destroyOrphan(t *testing.T) {
t.Fatalf("err: %s", err)
}
if _, ok := state.Resources["aws_instance.baz"]; ok {
t.Fatalf("bad: %#v", state.Resources)
mod := state.RootModule()
if _, ok := mod.Resources["aws_instance.baz"]; ok {
t.Fatalf("bad: %#v", mod.Resources)
}
}
@ -959,17 +986,21 @@ func TestContextApply_error(t *testing.T) {
p.ApplyFn = func(*ResourceState, *ResourceDiff) (*ResourceState, error) {
if errored {
state := &ResourceState{
Primary: &InstanceState{
ID: "bar",
},
}
return state, fmt.Errorf("error")
}
errored = true
return &ResourceState{
Primary: &InstanceState{
ID: "foo",
Attributes: map[string]string{
"num": "2",
},
},
}, nil
}
p.DiffFn = func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) {
@ -1004,10 +1035,17 @@ func TestContextApply_errorPartial(t *testing.T) {
c := testConfig(t, "apply-error")
p := testProvider("aws")
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.bar": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
@ -1026,10 +1064,12 @@ func TestContextApply_errorPartial(t *testing.T) {
errored = true
return &ResourceState{
Primary: &InstanceState{
ID: "foo",
Attributes: map[string]string{
"num": "2",
},
},
}, nil
}
p.DiffFn = func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) {
@ -1051,8 +1091,9 @@ func TestContextApply_errorPartial(t *testing.T) {
t.Fatal("should have error")
}
if len(state.Resources) != 2 {
t.Fatalf("bad: %#v", state.Resources)
mod := state.RootModule()
if len(mod.Resources) != 2 {
t.Fatalf("bad: %#v", mod.Resources)
}
actual := strings.TrimSpace(state.String())
@ -1104,8 +1145,8 @@ func TestContextApply_idAttr(t *testing.T) {
p.ApplyFn = func(s *ResourceState, d *ResourceDiff) (*ResourceState, error) {
result := s.MergeDiff(d)
result.ID = "foo"
result.Attributes = map[string]string{
result.Primary.ID = "foo"
result.Primary.Attributes = map[string]string{
"id": "bar",
}
@ -1130,15 +1171,16 @@ func TestContextApply_idAttr(t *testing.T) {
t.Fatalf("err: %s", err)
}
rs, ok := state.Resources["aws_instance.foo"]
mod := state.RootModule()
rs, ok := mod.Resources["aws_instance.foo"]
if !ok {
t.Fatal("not in state")
}
if rs.ID != "foo" {
t.Fatalf("bad: %#v", rs.ID)
if rs.Primary.ID != "foo" {
t.Fatalf("bad: %#v", rs.Primary.ID)
}
if rs.Attributes["id"] != "foo" {
t.Fatalf("bad: %#v", rs.Attributes)
if rs.Primary.Attributes["id"] != "foo" {
t.Fatalf("bad: %#v", rs.Primary.Attributes)
}
}
@ -1232,18 +1274,24 @@ func TestContextApply_taint(t *testing.T) {
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.bar": &ResourceState{
ID: "baz",
Type: "aws_instance",
Tainted: []*InstanceState{
&InstanceState{
ID: "baz",
Attributes: map[string]string{
"num": "2",
"type": "aws_instance",
},
},
},
Tainted: map[string]struct{}{
"aws_instance.bar": struct{}{},
},
},
},
},
}
ctx := testContext(t, &ContextOpts{
@ -1398,10 +1446,17 @@ func TestContextPlan_nil(t *testing.T) {
"aws": testProviderFuncFixed(p),
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
},
@ -1494,22 +1549,32 @@ func TestContextPlan_countDecreaseToOne(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Resources: map[string]*ResourceState{
"aws_instance.foo.0": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
Attributes: map[string]string{
"foo": "foo",
"type": "aws_instance",
},
},
},
"aws_instance.foo.1": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
"aws_instance.foo.2": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
@ -1538,16 +1603,23 @@ func TestContextPlan_countIncreaseFromNotSet(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
Attributes: map[string]string{
"foo": "foo",
"type": "aws_instance",
},
},
},
},
},
},
}
ctx := testContext(t, &ContextOpts{
Config: c,
@ -1574,16 +1646,23 @@ func TestContextPlan_countIncreaseFromOne(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo.0": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
Attributes: map[string]string{
"foo": "foo",
"type": "aws_instance",
},
},
},
},
},
},
}
ctx := testContext(t, &ContextOpts{
Config: c,
@ -1610,14 +1689,23 @@ func TestContextPlan_destroy(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.one": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
"aws_instance.two": &ResourceState{
ID: "baz",
Type: "aws_instance",
Primary: &InstanceState{
ID: "baz",
},
},
},
},
},
}
@ -1649,14 +1737,21 @@ func TestContextPlan_diffVar(t *testing.T) {
c := testConfig(t, "plan-diffvar")
p := testProvider("aws")
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": &ResourceState{
Primary: &InstanceState{
ID: "bar",
Attributes: map[string]string{
"num": "2",
},
},
},
},
},
},
}
ctx := testContext(t, &ContextOpts{
Config: c,
@ -1668,7 +1763,7 @@ func TestContextPlan_diffVar(t *testing.T) {
p.DiffFn = func(
s *ResourceState, c *ResourceConfig) (*ResourceDiff, error) {
if s.ID != "bar" {
if s.Primary.ID != "bar" {
return testDiffFn(s, c)
}
@ -1725,10 +1820,17 @@ func TestContextPlan_orphan(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.baz": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
@ -1757,11 +1859,18 @@ func TestContextPlan_state(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": &ResourceState{
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
ctx := testContext(t, &ContextOpts{
Config: c,
@ -1792,18 +1901,28 @@ func TestContextPlan_taint(t *testing.T) {
p := testProvider("aws")
p.DiffFn = testDiffFn
s := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": &ResourceState{
ID: "bar",
Type: "aws_instance",
Primary: &InstanceState{
ID: "bar",
Attributes: map[string]string{"num": "2"},
},
},
"aws_instance.bar": &ResourceState{
ID: "baz",
Type: "aws_instance",
Tainted: []*InstanceState{
&InstanceState{
ID: "baz",
},
},
},
},
},
},
Tainted: map[string]struct{}{"aws_instance.bar": struct{}{}},
}
ctx := testContext(t, &ContextOpts{
Config: c,
@ -1857,10 +1976,17 @@ func TestContextRefresh(t *testing.T) {
"aws": testProviderFuncFixed(p),
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
ID: "foo",
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
},
},
},
},
@ -1868,24 +1994,27 @@ func TestContextRefresh(t *testing.T) {
p.RefreshFn = nil
p.RefreshReturn = &ResourceState{
Primary: &InstanceState{
ID: "foo",
},
}
s, err := ctx.Refresh()
mod := s.RootModule()
if err != nil {
t.Fatalf("err: %s", err)
}
if !p.RefreshCalled {
t.Fatal("refresh should be called")
}
if p.RefreshState.ID != "foo" {
if p.RefreshState.Primary.ID != "foo" {
t.Fatalf("bad: %#v", p.RefreshState)
}
if !reflect.DeepEqual(s.Resources["aws_instance.web"], p.RefreshReturn) {
t.Fatalf("bad: %#v", s.Resources["aws_instance.web"])
if !reflect.DeepEqual(mod.Resources["aws_instance.web"], p.RefreshReturn) {
t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"])
}
for _, r := range s.Resources {
for _, r := range mod.Resources {
if r.Type == "" {
t.Fatalf("no type: %#v", r)
}
@ -1901,10 +2030,17 @@ func TestContextRefresh_delete(t *testing.T) {
"aws": testProviderFuncFixed(p),
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
ID: "foo",
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
},
},
},
},
@ -1918,7 +2054,8 @@ func TestContextRefresh_delete(t *testing.T) {
t.Fatalf("err: %s", err)
}
if len(s.Resources) > 0 {
mod := s.RootModule()
if len(mod.Resources) > 0 {
t.Fatal("resources should be empty")
}
}
@ -1936,7 +2073,9 @@ func TestContextRefresh_ignoreUncreated(t *testing.T) {
p.RefreshFn = nil
p.RefreshReturn = &ResourceState{
Primary: &InstanceState{
ID: "foo",
},
}
_, err := ctx.Refresh()
@ -1959,10 +2098,17 @@ func TestContextRefresh_hook(t *testing.T) {
"aws": testProviderFuncFixed(p),
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
ID: "foo",
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
},
},
},
},
@ -1989,11 +2135,18 @@ func TestContextRefresh_state(t *testing.T) {
p := testProvider("aws")
c := testConfig(t, "refresh-basic")
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
}
ctx := testContext(t, &ContextOpts{
Config: c,
@ -2005,21 +2158,24 @@ func TestContextRefresh_state(t *testing.T) {
p.RefreshFn = nil
p.RefreshReturn = &ResourceState{
Primary: &InstanceState{
ID: "foo",
},
}
s, err := ctx.Refresh()
if err != nil {
t.Fatalf("err: %s", err)
}
mod := s.RootModule()
if !p.RefreshCalled {
t.Fatal("refresh should be called")
}
if !reflect.DeepEqual(p.RefreshState, state.Resources["aws_instance.web"]) {
if !reflect.DeepEqual(p.RefreshState, mod.Resources["aws_instance.web"]) {
t.Fatalf("bad: %#v", p.RefreshState)
}
if !reflect.DeepEqual(s.Resources["aws_instance.web"], p.RefreshReturn) {
t.Fatalf("bad: %#v", s.Resources)
if !reflect.DeepEqual(mod.Resources["aws_instance.web"], p.RefreshReturn) {
t.Fatalf("bad: %#v", mod.Resources)
}
}
@ -2032,10 +2188,18 @@ func TestContextRefresh_vars(t *testing.T) {
"aws": testProviderFuncFixed(p),
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.web": &ResourceState{
ID: "foo",
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
},
},
},
},
@ -2043,24 +2207,27 @@ func TestContextRefresh_vars(t *testing.T) {
p.RefreshFn = nil
p.RefreshReturn = &ResourceState{
Primary: &InstanceState{
ID: "foo",
},
}
s, err := ctx.Refresh()
if err != nil {
t.Fatalf("err: %s", err)
}
mod := s.RootModule()
if !p.RefreshCalled {
t.Fatal("refresh should be called")
}
if p.RefreshState.ID != "foo" {
if p.RefreshState.Primary.ID != "foo" {
t.Fatalf("bad: %#v", p.RefreshState)
}
if !reflect.DeepEqual(s.Resources["aws_instance.web"], p.RefreshReturn) {
t.Fatalf("bad: %#v", s.Resources["aws_instance.web"])
if !reflect.DeepEqual(mod.Resources["aws_instance.web"], p.RefreshReturn) {
t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"])
}
for _, r := range s.Resources {
for _, r := range mod.Resources {
if r.Type == "" {
t.Fatalf("no type: %#v", r)
}
@ -2084,7 +2251,9 @@ func testApplyFn(
}
result := &ResourceState{
Primary: &InstanceState{
ID: id,
},
}
if d != nil {
@ -2092,11 +2261,7 @@ func testApplyFn(
}
if depAttr, ok := d.Attributes["dep"]; ok {
result.Dependencies = []ResourceDependency{
ResourceDependency{
ID: depAttr.New,
},
}
result.Dependencies = []string{depAttr.New}
}
return result, nil
@ -2173,7 +2338,7 @@ func testDiffFn(
continue
}
old, ok := s.Attributes[k]
old, ok := s.Primary.Attributes[k]
if !ok {
continue
}

View File

@ -84,10 +84,18 @@ func TestGraph_dependsOnCount(t *testing.T) {
func TestGraph_state(t *testing.T) {
config := testConfig(t, "graph-basic")
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.old": &ResourceState{
ID: "foo",
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
},
},
},
}
@ -289,18 +297,23 @@ func TestGraphAddDiff_destroy(t *testing.T) {
},
}
state := &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": &ResourceState{
ID: "foo",
Type: "aws_instance",
Primary: &InstanceState{
ID: "foo",
},
},
"aws_instance.bar": &ResourceState{
ID: "bar",
Type: "aws_instance",
Dependencies: []ResourceDependency{
ResourceDependency{
ID: "foo",
Dependencies: []string{"foo"},
Primary: &InstanceState{
ID: "bar",
},
},
},
},

View File

@ -32,12 +32,19 @@ func TestReadWritePlan(t *testing.T) {
},
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"foo": &ResourceState{
Primary: &InstanceState{
ID: "bar",
},
},
},
},
},
},
Vars: map[string]string{
"foo": "bar",
},

View File

@ -17,10 +17,12 @@ func TestResource_Vars(t *testing.T) {
r = &Resource{
Id: "key",
State: &ResourceState{
Primary: &InstanceState{
Attributes: map[string]string{
"foo": "bar",
},
},
},
}
expected := map[string]string{

View File

@ -48,7 +48,11 @@ func (s *State) ModuleByPath(path []string) *ModuleState {
// RootModule returns the ModuleState for the root module
func (s *State) RootModule() *ModuleState {
return s.ModuleByPath(rootModulePath)
root := s.ModuleByPath(rootModulePath)
if root == nil {
panic("missing root module")
}
return root
}
func (s *State) init() {
@ -56,7 +60,9 @@ func (s *State) init() {
s.Version = textStateVersion
}
if len(s.Modules) == 0 {
root := &ModuleState{}
root := &ModuleState{
Path: rootModulePath,
}
root.init()
s.Modules = []*ModuleState{root}
}

View File

@ -2,7 +2,11 @@ package terraform
import (
"bytes"
"encoding/gob"
"errors"
"io"
"reflect"
"sync"
"testing"
"github.com/hashicorp/terraform/config"
@ -10,11 +14,13 @@ import (
func TestResourceState_MergeDiff(t *testing.T) {
rs := ResourceState{
Primary: &InstanceState{
ID: "foo",
Attributes: map[string]string{
"foo": "bar",
"port": "8000",
},
},
}
diff := &ResourceDiff{
@ -46,8 +52,8 @@ func TestResourceState_MergeDiff(t *testing.T) {
"baz": config.UnknownVariableValue,
}
if !reflect.DeepEqual(expected, rs2.Attributes) {
t.Fatalf("bad: %#v", rs2.Attributes)
if !reflect.DeepEqual(expected, rs2.Primary.Attributes) {
t.Fatalf("bad: %#v", rs2.Primary.Attributes)
}
}
@ -69,17 +75,19 @@ func TestResourceState_MergeDiff_nil(t *testing.T) {
"foo": "baz",
}
if !reflect.DeepEqual(expected, rs2.Attributes) {
t.Fatalf("bad: %#v", rs2.Attributes)
if !reflect.DeepEqual(expected, rs2.Primary.Attributes) {
t.Fatalf("bad: %#v", rs2.Primary.Attributes)
}
}
func TestResourceState_MergeDiff_nilDiff(t *testing.T) {
rs := ResourceState{
Primary: &InstanceState{
ID: "foo",
Attributes: map[string]string{
"foo": "bar",
},
},
}
rs2 := rs.MergeDiff(nil)
@ -88,15 +96,15 @@ func TestResourceState_MergeDiff_nilDiff(t *testing.T) {
"foo": "bar",
}
if !reflect.DeepEqual(expected, rs2.Attributes) {
t.Fatalf("bad: %#v", rs2.Attributes)
if !reflect.DeepEqual(expected, rs2.Primary.Attributes) {
t.Fatalf("bad: %#v", rs2.Primary.Attributes)
}
}
func TestReadWriteState(t *testing.T) {
state := &State{
Resources: map[string]*ResourceState{
"foo": &ResourceState{
func TestReadWriteStateV1(t *testing.T) {
state := &StateV1{
Resources: map[string]*ResourceStateV1{
"foo": &ResourceStateV1{
ID: "bar",
ConnInfo: map[string]string{
"type": "ssh",
@ -111,7 +119,7 @@ func TestReadWriteState(t *testing.T) {
chksum := checksumStruct(t, state)
buf := new(bytes.Buffer)
if err := WriteState(state, buf); err != nil {
if err := testWriteStateV1(state, buf); err != nil {
t.Fatalf("err: %s", err)
}
@ -121,7 +129,7 @@ func TestReadWriteState(t *testing.T) {
t.Fatalf("structure changed during serialization!")
}
actual, err := ReadState(buf)
actual, err := ReadStateV1(buf)
if err != nil {
t.Fatalf("err: %s", err)
}
@ -133,3 +141,60 @@ func TestReadWriteState(t *testing.T) {
t.Fatalf("bad: %#v", actual)
}
}
// sensitiveState is used to store sensitive state information
// that should not be serialized. This is only used temporarily
// and is restored into the state.
type sensitiveState struct {
ConnInfo map[string]map[string]string
once sync.Once
}
func (s *sensitiveState) init() {
s.once.Do(func() {
s.ConnInfo = make(map[string]map[string]string)
})
}
// testWriteStateV1 writes a state somewhere in a binary format.
// Only for testing now
func testWriteStateV1(d *StateV1, dst io.Writer) error {
// Write the magic bytes so we can determine the file format later
n, err := dst.Write([]byte(stateFormatMagic))
if err != nil {
return err
}
if n != len(stateFormatMagic) {
return errors.New("failed to write state format magic bytes")
}
// Write a version byte so we can iterate on version at some point
n, err = dst.Write([]byte{stateFormatVersion})
if err != nil {
return err
}
if n != 1 {
return errors.New("failed to write state version byte")
}
// Prevent sensitive information from being serialized
sensitive := &sensitiveState{}
sensitive.init()
for name, r := range d.Resources {
if r.ConnInfo != nil {
sensitive.ConnInfo[name] = r.ConnInfo
r.ConnInfo = nil
}
}
// Serialize the state
err = gob.NewEncoder(dst).Encode(d)
// Restore the state
for name, info := range sensitive.ConnInfo {
d.Resources[name].ConnInfo = info
}
return err
}