terraform: fixing tons of panics

This commit is contained in:
Armon Dadgar 2014-09-16 16:21:09 -07:00 committed by Mitchell Hashimoto
parent 95f3e626a5
commit 25a3cc480c
2 changed files with 33 additions and 9 deletions

View File

@ -121,6 +121,10 @@ func (c *Context) Apply() (*State, error) {
// Set our state right away. No matter what, this IS our new state, // Set our state right away. No matter what, this IS our new state,
// even if there is an error below. // even if there is an error below.
c.state = c.state.deepcopy() c.state = c.state.deepcopy()
if c.state == nil {
c.state = &State{}
}
c.state.init()
// Walk // Walk
log.Printf("[INFO] Apply walk starting") log.Printf("[INFO] Apply walk starting")
@ -190,7 +194,12 @@ func (c *Context) Plan(opts *PlanOpts) (*Plan, error) {
// the plan can update a fake state so that variables work, then // the plan can update a fake state so that variables work, then
// we replace it back with our old state. // we replace it back with our old state.
old := c.state old := c.state
c.state = old.deepcopy() if old == nil {
c.state = &State{}
c.state.init()
} else {
c.state = old.deepcopy()
}
defer func() { defer func() {
c.state = old c.state = old
}() }()
@ -780,16 +789,21 @@ func (c *Context) planWalkFn(result *Plan) depgraph.WalkFunc {
diff.Destroy = true diff.Destroy = true
} }
if diff.RequiresNew() && r.State.Primary.ID != "" { if diff.RequiresNew() && r.State.Primary != nil && r.State.Primary.ID != "" {
// This will also require a destroy // This will also require a destroy
diff.Destroy = true diff.Destroy = true
} }
if diff.RequiresNew() || r.State.Primary.ID == "" { if diff.RequiresNew() || r.State.Primary == nil || r.State.Primary.ID == "" {
var oldID string
if r.State.Primary != nil {
oldID = r.State.Primary.Attributes["id"]
}
// Add diff to compute new ID // Add diff to compute new ID
diff.init() diff.init()
diff.Attributes["id"] = &ResourceAttrDiff{ diff.Attributes["id"] = &ResourceAttrDiff{
Old: r.State.Primary.Attributes["id"], Old: oldID,
NewComputed: true, NewComputed: true,
RequiresNew: true, RequiresNew: true,
Type: DiffAttrOutput, Type: DiffAttrOutput,

View File

@ -38,6 +38,9 @@ type State struct {
// This should be the prefered lookup mechanism as it allows for future // This should be the prefered lookup mechanism as it allows for future
// lookup optimizations. // lookup optimizations.
func (s *State) ModuleByPath(path []string) *ModuleState { func (s *State) ModuleByPath(path []string) *ModuleState {
if s == nil {
return nil
}
for _, mod := range s.Modules { for _, mod := range s.Modules {
if reflect.DeepEqual(mod.Path, path) { if reflect.DeepEqual(mod.Path, path) {
return mod return mod
@ -111,7 +114,10 @@ func (s *State) String() string {
for _, k := range names { for _, k := range names {
rs := mod.Resources[k] rs := mod.Resources[k]
id := rs.Primary.ID var id string
if rs.Primary != nil {
id = rs.Primary.ID
}
if id == "" { if id == "" {
id = "<not created>" id = "<not created>"
} }
@ -124,8 +130,12 @@ func (s *State) String() string {
buf.WriteString(fmt.Sprintf("%s:%s\n", k, taintStr)) buf.WriteString(fmt.Sprintf("%s:%s\n", k, taintStr))
buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) buf.WriteString(fmt.Sprintf(" ID = %s\n", id))
attrKeys := make([]string, 0, len(rs.Primary.Attributes)) var attributes map[string]string
for ak, _ := range rs.Primary.Attributes { if rs.Primary != nil {
attributes = rs.Primary.Attributes
}
attrKeys := make([]string, 0, len(attributes))
for ak, _ := range attributes {
if ak == "id" { if ak == "id" {
continue continue
} }
@ -135,7 +145,7 @@ func (s *State) String() string {
sort.Strings(attrKeys) sort.Strings(attrKeys)
for _, ak := range attrKeys { for _, ak := range attrKeys {
av := rs.Primary.Attributes[ak] av := attributes[ak]
buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av))
} }
@ -302,8 +312,8 @@ type ResourceState struct {
func (r *ResourceState) init() { func (r *ResourceState) init() {
if r.Primary == nil { if r.Primary == nil {
r.Primary = &InstanceState{} r.Primary = &InstanceState{}
r.Primary.init()
} }
r.Primary.init()
} }
func (r *ResourceState) deepcopy() *ResourceState { func (r *ResourceState) deepcopy() *ResourceState {