terraform: properly discover count orphans

This commit is contained in:
Mitchell Hashimoto 2014-10-02 13:12:53 -07:00
parent 3b89a7bdc7
commit 0f087141e3
1 changed files with 58 additions and 17 deletions

View File

@ -92,12 +92,11 @@ type GraphNodeResource struct {
Resource *Resource Resource *Resource
ResourceProviderNode string ResourceProviderNode string
Diff *ModuleDiff // All the fields below are related to expansion. These are set by
State *ModuleState // the graph but aren't useful individually.
// Expand, if true, indicates that this resource needs to be expanded
// at walk-time to multiple resources.
ExpandMode ResourceExpandMode ExpandMode ResourceExpandMode
Diff *ModuleDiff
State *ModuleState
} }
// GraphNodeResourceProvider is a node type in the graph that represents // GraphNodeResourceProvider is a node type in the graph that represents
@ -1607,7 +1606,7 @@ func (n *GraphNodeResource) Expand() ([]*depgraph.Noun, error) {
// Determine the nodes to create. If we're just looking for the // Determine the nodes to create. If we're just looking for the
// nodes to create, return that. // nodes to create, return that.
n.expandCreate(g, count) n.expand(g, count)
// Add in the diff if we have it // Add in the diff if we have it
if n.Diff != nil { if n.Diff != nil {
@ -1619,7 +1618,7 @@ func (n *GraphNodeResource) Expand() ([]*depgraph.Noun, error) {
// If we're just expanding the apply, then filter those out and // If we're just expanding the apply, then filter those out and
// return them now. // return them now.
if n.ExpandMode == ResourceExpandApply { if n.ExpandMode == ResourceExpandApply {
return n.filterNouns(g, false), nil return n.finalizeNouns(g, false), nil
} }
if n.State != nil { if n.State != nil {
@ -1629,16 +1628,27 @@ func (n *GraphNodeResource) Expand() ([]*depgraph.Noun, error) {
graphAddTainted(g, n.State) graphAddTainted(g, n.State)
} }
return n.filterNouns(g, true), nil return n.finalizeNouns(g, true), nil
} }
// expandCreate expands this resource and adds the resources to the graph. // expand expands this resource and adds the resources to the graph. It
func (n *GraphNodeResource) expandCreate(g *depgraph.Graph, count int) { // adds both create and destroy resources.
// Create the list of nouns that we'd have to create func (n *GraphNodeResource) expand(g *depgraph.Graph, count int) {
create := make([]*depgraph.Noun, 0, count) // Create the list of nouns
result := make([]*depgraph.Noun, 0, count)
// Build the key set so we know what is removed
var keys map[string]struct{}
if n.State != nil {
keys = make(map[string]struct{})
for k, _ := range n.State.Resources {
keys[k] = struct{}{}
}
}
// First thing, expand the counts that we have defined for our // First thing, expand the counts that we have defined for our
// current config into the full set of resources. // current config into the full set of resources that are being
// created.
r := n.Config r := n.Config
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
name := r.Id() name := r.Id()
@ -1656,6 +1666,7 @@ func (n *GraphNodeResource) expandCreate(g *depgraph.Graph, count int) {
// Lookup the resource state // Lookup the resource state
if s, ok := n.State.Resources[name]; ok { if s, ok := n.State.Resources[name]; ok {
state = s state = s
delete(keys, name)
} }
if state == nil { if state == nil {
@ -1665,11 +1676,13 @@ func (n *GraphNodeResource) expandCreate(g *depgraph.Graph, count int) {
// count > 1 to count == 1. // count > 1 to count == 1.
k := r.Id() + ".0" k := r.Id() + ".0"
state = n.State.Resources[k] state = n.State.Resources[k]
delete(keys, k)
} else if i == 0 { } else if i == 0 {
// If count is greater than one, check for state // If count is greater than one, check for state
// with just the ID, which might exist if we go // with just the ID, which might exist if we go
// from count == 1 to count > 1 // from count == 1 to count > 1
state = n.State.Resources[r.Id()] state = n.State.Resources[r.Id()]
delete(keys, r.Id())
} }
} }
} }
@ -1689,10 +1702,9 @@ func (n *GraphNodeResource) expandCreate(g *depgraph.Graph, count int) {
resource := n.copyResource(name) resource := n.copyResource(name)
resource.State = state.Primary resource.State = state.Primary
resource.Flags = flags resource.Flags = flags
// TODO: we need the diff here...
// Add the result // Add the result
create = append(create, &depgraph.Noun{ result = append(result, &depgraph.Noun{
Name: name, Name: name,
Meta: &GraphNodeResource{ Meta: &GraphNodeResource{
Index: index, Index: index,
@ -1702,7 +1714,27 @@ func (n *GraphNodeResource) expandCreate(g *depgraph.Graph, count int) {
}) })
} }
g.Nouns = append(g.Nouns, create...) // Go over the leftover keys which are orphans (decreasing counts)
for k, _ := range keys {
rs := n.State.Resources[k]
resource := n.copyResource(k)
resource.Config = NewResourceConfig(nil)
resource.State = rs.Primary
resource.Flags = FlagOrphan
noun := &depgraph.Noun{
Name: k,
Meta: &GraphNodeResource{
Index: -1,
Resource: resource,
},
}
result = append(result, noun)
}
g.Nouns = append(g.Nouns, result...)
} }
// copyResource copies the Resource structure to assign to a subgraph. // copyResource copies the Resource structure to assign to a subgraph.
@ -1716,7 +1748,7 @@ func (n *GraphNodeResource) copyResource(id string) *Resource {
return &resource return &resource
} }
func (n *GraphNodeResource) filterNouns( func (n *GraphNodeResource) finalizeNouns(
g *depgraph.Graph, destroy bool) []*depgraph.Noun { g *depgraph.Graph, destroy bool) []*depgraph.Noun {
result := make([]*depgraph.Noun, 0, len(g.Nouns)) result := make([]*depgraph.Noun, 0, len(g.Nouns))
for _, n := range g.Nouns { for _, n := range g.Nouns {
@ -1744,6 +1776,15 @@ func (n *GraphNodeResource) filterNouns(
continue continue
} }
// If this is an oprhan, we only care about it if we're destroying.
if rn.Resource.Flags&FlagOrphan != 0 {
if destroy {
result = append(result, n)
}
continue
}
// If we're not destroying, then add it only if we don't // If we're not destroying, then add it only if we don't
// care about deploys. // care about deploys.
if !destroy { if !destroy {