diff --git a/terraform/context.go b/terraform/context.go index e63f26ae4..d0777142a 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -121,6 +121,10 @@ func (c *Context) Apply() (*State, error) { // Set our state right away. No matter what, this IS our new state, // even if there is an error below. c.state = c.state.deepcopy() + if c.state == nil { + c.state = &State{} + } + c.state.init() // Walk 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 // we replace it back with our old state. old := c.state - c.state = old.deepcopy() + if old == nil { + c.state = &State{} + c.state.init() + } else { + c.state = old.deepcopy() + } defer func() { c.state = old }() @@ -780,16 +789,21 @@ func (c *Context) planWalkFn(result *Plan) depgraph.WalkFunc { 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 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 diff.init() diff.Attributes["id"] = &ResourceAttrDiff{ - Old: r.State.Primary.Attributes["id"], + Old: oldID, NewComputed: true, RequiresNew: true, Type: DiffAttrOutput, diff --git a/terraform/state.go b/terraform/state.go index f7b3067f4..2a201a5a7 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -38,6 +38,9 @@ type State struct { // This should be the prefered lookup mechanism as it allows for future // lookup optimizations. func (s *State) ModuleByPath(path []string) *ModuleState { + if s == nil { + return nil + } for _, mod := range s.Modules { if reflect.DeepEqual(mod.Path, path) { return mod @@ -111,7 +114,10 @@ func (s *State) String() string { for _, k := range names { rs := mod.Resources[k] - id := rs.Primary.ID + var id string + if rs.Primary != nil { + id = rs.Primary.ID + } if id == "" { id = "" } @@ -124,8 +130,12 @@ func (s *State) String() string { buf.WriteString(fmt.Sprintf("%s:%s\n", k, taintStr)) buf.WriteString(fmt.Sprintf(" ID = %s\n", id)) - attrKeys := make([]string, 0, len(rs.Primary.Attributes)) - for ak, _ := range rs.Primary.Attributes { + var attributes map[string]string + if rs.Primary != nil { + attributes = rs.Primary.Attributes + } + attrKeys := make([]string, 0, len(attributes)) + for ak, _ := range attributes { if ak == "id" { continue } @@ -135,7 +145,7 @@ func (s *State) String() string { sort.Strings(attrKeys) for _, ak := range attrKeys { - av := rs.Primary.Attributes[ak] + av := attributes[ak] buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) } @@ -302,8 +312,8 @@ type ResourceState struct { func (r *ResourceState) init() { if r.Primary == nil { r.Primary = &InstanceState{} - r.Primary.init() } + r.Primary.init() } func (r *ResourceState) deepcopy() *ResourceState {