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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,11 @@ package terraform
import ( import (
"bytes" "bytes"
"encoding/gob"
"errors"
"io"
"reflect" "reflect"
"sync"
"testing" "testing"
"github.com/hashicorp/terraform/config" "github.com/hashicorp/terraform/config"
@ -10,10 +14,12 @@ import (
func TestResourceState_MergeDiff(t *testing.T) { func TestResourceState_MergeDiff(t *testing.T) {
rs := ResourceState{ rs := ResourceState{
ID: "foo", Primary: &InstanceState{
Attributes: map[string]string{ ID: "foo",
"foo": "bar", Attributes: map[string]string{
"port": "8000", "foo": "bar",
"port": "8000",
},
}, },
} }
@ -46,8 +52,8 @@ func TestResourceState_MergeDiff(t *testing.T) {
"baz": config.UnknownVariableValue, "baz": config.UnknownVariableValue,
} }
if !reflect.DeepEqual(expected, rs2.Attributes) { if !reflect.DeepEqual(expected, rs2.Primary.Attributes) {
t.Fatalf("bad: %#v", rs2.Attributes) t.Fatalf("bad: %#v", rs2.Primary.Attributes)
} }
} }
@ -69,16 +75,18 @@ func TestResourceState_MergeDiff_nil(t *testing.T) {
"foo": "baz", "foo": "baz",
} }
if !reflect.DeepEqual(expected, rs2.Attributes) { if !reflect.DeepEqual(expected, rs2.Primary.Attributes) {
t.Fatalf("bad: %#v", rs2.Attributes) t.Fatalf("bad: %#v", rs2.Primary.Attributes)
} }
} }
func TestResourceState_MergeDiff_nilDiff(t *testing.T) { func TestResourceState_MergeDiff_nilDiff(t *testing.T) {
rs := ResourceState{ rs := ResourceState{
ID: "foo", Primary: &InstanceState{
Attributes: map[string]string{ ID: "foo",
"foo": "bar", Attributes: map[string]string{
"foo": "bar",
},
}, },
} }
@ -88,15 +96,15 @@ func TestResourceState_MergeDiff_nilDiff(t *testing.T) {
"foo": "bar", "foo": "bar",
} }
if !reflect.DeepEqual(expected, rs2.Attributes) { if !reflect.DeepEqual(expected, rs2.Primary.Attributes) {
t.Fatalf("bad: %#v", rs2.Attributes) t.Fatalf("bad: %#v", rs2.Primary.Attributes)
} }
} }
func TestReadWriteState(t *testing.T) { func TestReadWriteStateV1(t *testing.T) {
state := &State{ state := &StateV1{
Resources: map[string]*ResourceState{ Resources: map[string]*ResourceStateV1{
"foo": &ResourceState{ "foo": &ResourceStateV1{
ID: "bar", ID: "bar",
ConnInfo: map[string]string{ ConnInfo: map[string]string{
"type": "ssh", "type": "ssh",
@ -111,7 +119,7 @@ func TestReadWriteState(t *testing.T) {
chksum := checksumStruct(t, state) chksum := checksumStruct(t, state)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := WriteState(state, buf); err != nil { if err := testWriteStateV1(state, buf); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -121,7 +129,7 @@ func TestReadWriteState(t *testing.T) {
t.Fatalf("structure changed during serialization!") t.Fatalf("structure changed during serialization!")
} }
actual, err := ReadState(buf) actual, err := ReadStateV1(buf)
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -133,3 +141,60 @@ func TestReadWriteState(t *testing.T) {
t.Fatalf("bad: %#v", actual) 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
}