terraform: save/restore dependency info for orphans
This commit is contained in:
parent
31653fcbcb
commit
c14a17f39b
|
@ -131,6 +131,10 @@ func (c *Context) Apply() (*State, error) {
|
||||||
err = g.Walk(c.applyWalkFn())
|
err = g.Walk(c.applyWalkFn())
|
||||||
log.Printf("[INFO] Apply walk complete")
|
log.Printf("[INFO] Apply walk complete")
|
||||||
|
|
||||||
|
// Encode the dependencies, this pushes the logical dependencies
|
||||||
|
// into the state so that we can recover it later.
|
||||||
|
EncodeDependencies(g)
|
||||||
|
|
||||||
// Prune the state so that we have as clean a state as possible
|
// Prune the state so that we have as clean a state as possible
|
||||||
c.state.prune()
|
c.state.prune()
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,45 @@ func Graph(opts *GraphOpts) (*depgraph.Graph, error) {
|
||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EncodeDependencies is used to walk the graph and encode the
|
||||||
|
// logical dependency information into the resource state. This
|
||||||
|
// allows the dependency tree to be recovered from the state file
|
||||||
|
// such that orphaned resources will still be destroyed in the
|
||||||
|
// proper order.
|
||||||
|
func EncodeDependencies(g *depgraph.Graph) {
|
||||||
|
for _, n := range g.Nouns {
|
||||||
|
// Ignore any non-resource nodes
|
||||||
|
rn, ok := n.Meta.(*GraphNodeResource)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip only if the resource has state
|
||||||
|
rs := rn.Resource
|
||||||
|
state := rs.State
|
||||||
|
if state == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the dependencies
|
||||||
|
var inject []string
|
||||||
|
for _, dep := range n.Deps {
|
||||||
|
switch target := dep.Target.Meta.(type) {
|
||||||
|
case *GraphNodeResource:
|
||||||
|
inject = append(inject, target.Resource.Id)
|
||||||
|
// TODO: case *GraphNodeResourceMeta?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject any of the missing depedencies
|
||||||
|
for _, dep := range inject {
|
||||||
|
if !strSliceContains(state.Dependencies, dep) {
|
||||||
|
state.Dependencies = append(state.Dependencies, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// configGraph turns a configuration structure into a dependency graph.
|
// configGraph turns a configuration structure into a dependency graph.
|
||||||
func graphAddConfigResources(
|
func graphAddConfigResources(
|
||||||
g *depgraph.Graph, c *config.Config, s *State) {
|
g *depgraph.Graph, c *config.Config, s *State) {
|
||||||
|
@ -513,6 +552,7 @@ func graphAddOrphans(g *depgraph.Graph, c *config.Config, s *State) {
|
||||||
if mod == nil {
|
if mod == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var nlist []*depgraph.Noun
|
||||||
for _, k := range mod.Orphans(c) {
|
for _, k := range mod.Orphans(c) {
|
||||||
rs := mod.Resources[k]
|
rs := mod.Resources[k]
|
||||||
noun := &depgraph.Noun{
|
noun := &depgraph.Noun{
|
||||||
|
@ -528,7 +568,45 @@ func graphAddOrphans(g *depgraph.Graph, c *config.Config, s *State) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
g.Nouns = append(g.Nouns, noun)
|
|
||||||
|
// Append it to the list so we handle it later
|
||||||
|
nlist = append(nlist, noun)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the nouns to the graph
|
||||||
|
g.Nouns = append(g.Nouns, nlist...)
|
||||||
|
|
||||||
|
// Handle the orphan dependencies after adding them
|
||||||
|
// to the graph because there may be depedencies between the
|
||||||
|
// orphans that otherwise cannot be handled
|
||||||
|
for _, n := range nlist {
|
||||||
|
rn := n.Meta.(*GraphNodeResource)
|
||||||
|
|
||||||
|
// If we have no dependencies, then just continue
|
||||||
|
deps := rn.Resource.State.Dependencies
|
||||||
|
if len(deps) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n2 := range nlist {
|
||||||
|
rn2 := n2.Meta.(*GraphNodeResource)
|
||||||
|
// Don't ever depend on ourselves
|
||||||
|
if rn2 == rn {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, depName := range rn.Resource.State.Dependencies {
|
||||||
|
if rn2.Resource.Id != depName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dep := &depgraph.Dependency{
|
||||||
|
Name: depName,
|
||||||
|
Source: n,
|
||||||
|
Target: n2,
|
||||||
|
}
|
||||||
|
n.Deps = append(n.Deps, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue