properly find orphaned outputs

You can't find orphans by walking the config, because by definition
orphans aren't in the config.

Leaving the broken test for when empty modules are removed from the
state as well.
This commit is contained in:
James Bardin 2017-11-08 14:01:54 -05:00
parent 9283568dca
commit aa2bd0945b
2 changed files with 45 additions and 31 deletions

View File

@ -1089,7 +1089,7 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
defer m.Unlock() defer m.Unlock()
keys := make(map[string]struct{}) keys := make(map[string]struct{})
for k, _ := range m.Resources { for k := range m.Resources {
keys[k] = struct{}{} keys[k] = struct{}{}
} }
@ -1097,7 +1097,7 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
for _, r := range c.Resources { for _, r := range c.Resources {
delete(keys, r.Id()) delete(keys, r.Id())
for k, _ := range keys { for k := range keys {
if strings.HasPrefix(k, r.Id()+".") { if strings.HasPrefix(k, r.Id()+".") {
delete(keys, k) delete(keys, k)
} }
@ -1106,7 +1106,32 @@ func (m *ModuleState) Orphans(c *config.Config) []string {
} }
result := make([]string, 0, len(keys)) result := make([]string, 0, len(keys))
for k, _ := range keys { for k := range keys {
result = append(result, k)
}
return result
}
// OrphanOutputs returns a list of outputs that are in the State but aren't
// present in the configuration itself.
func (m *ModuleState) OrphanOutputs(c *config.Config) []string {
m.Lock()
defer m.Unlock()
keys := make(map[string]struct{})
for k := range m.Outputs {
keys[k] = struct{}{}
}
if c != nil {
for _, o := range c.Outputs {
delete(keys, o.Name)
}
}
result := make([]string, 0, len(keys))
for k := range keys {
result = append(result, k) result = append(result, k)
} }

View File

@ -21,43 +21,32 @@ func (t *OrphanOutputTransformer) Transform(g *Graph) error {
return nil return nil
} }
return t.transform(g, t.Module) for _, ms := range t.State.Modules {
} if err := t.transform(g, ms); err != nil {
func (t *OrphanOutputTransformer) transform(g *Graph, m *module.Tree) error {
// Get our configuration, and recurse into children
var c *config.Config
if m != nil {
c = m.Config()
for _, child := range m.Children() {
if err := t.transform(g, child); err != nil {
return err return err
} }
} }
} return nil
}
// Get the state. If there is no state, then we have no orphans! func (t *OrphanOutputTransformer) transform(g *Graph, ms *ModuleState) error {
path := normalizeModulePath(m.Path()) if ms == nil {
state := t.State.ModuleByPath(path)
if state == nil {
return nil return nil
} }
// Make a map of the valid outputs path := normalizeModulePath(ms.Path)
valid := make(map[string]struct{})
for _, o := range c.Outputs { // Get the config for this path, which is nil if the entire module has been
valid[o.Name] = struct{}{} // removed.
var c *config.Config
if m := t.Module.Child(path[1:]); m != nil {
c = m.Config()
} }
// Go through the outputs and find the ones that aren't in our config. // add all the orphaned outputs to the graph
for n, _ := range state.Outputs { for _, n := range ms.OrphanOutputs(c) {
// If it is in the valid map, then ignore
if _, ok := valid[n]; ok {
continue
}
// Orphan!
g.Add(&NodeOutputOrphan{OutputName: n, PathValue: path}) g.Add(&NodeOutputOrphan{OutputName: n, PathValue: path})
} }
return nil return nil