From 72970f5f1c2652d89ead4fdc387f83bcba38a49e Mon Sep 17 00:00:00 2001 From: Jakub Martin Date: Mon, 21 Dec 2020 13:10:23 +0100 Subject: [PATCH] Fix showing resources when a module has no resources, only submodules. --- command/jsonstate/state.go | 41 ++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/command/jsonstate/state.go b/command/jsonstate/state.go index fdf2d483fb55..bb5ba6a55929 100644 --- a/command/jsonstate/state.go +++ b/command/jsonstate/state.go @@ -198,14 +198,30 @@ func marshalRootModule(s *states.State, schemas *terraform.Schemas) (module, err return ret, err } - // build a map of module -> [child module addresses] - moduleMap := make(map[string][]addrs.ModuleInstance) + // build a map of module -> set[child module addresses] + moduleChildSet := make(map[string]map[string]struct{}) for _, mod := range s.Modules { if mod.Addr.IsRoot() { continue } else { - parent := mod.Addr.Parent().String() - moduleMap[parent] = append(moduleMap[parent], mod.Addr) + for childAddr := mod.Addr; !childAddr.IsRoot(); childAddr = childAddr.Parent() { + if _, ok := moduleChildSet[childAddr.Parent().String()]; !ok { + moduleChildSet[childAddr.Parent().String()] = map[string]struct{}{} + } + moduleChildSet[childAddr.Parent().String()][childAddr.String()] = struct{}{} + } + } + } + + // transform the previous map into map of module -> [child module addresses] + moduleMap := make(map[string][]addrs.ModuleInstance) + for parent, children := range moduleChildSet { + for child := range children { + childModuleInstance, diags := addrs.ParseModuleInstanceStr(child) + if diags.HasErrors() { + return ret, diags.Err() + } + moduleMap[parent] = append(moduleMap[parent], childModuleInstance) } } @@ -224,14 +240,19 @@ func marshalModules( ) ([]module, error) { var ret []module for _, child := range modules { - stateMod := s.Module(child) // cm for child module, naming things is hard. - cm := module{Address: stateMod.Addr.String()} - rs, err := marshalResources(stateMod.Resources, stateMod.Addr, schemas) - if err != nil { - return nil, err + cm := module{Address: child.String()} + + // the module may be resourceless and contain only submodules, it will then be nil here + stateMod := s.Module(child) + if stateMod != nil { + rs, err := marshalResources(stateMod.Resources, stateMod.Addr, schemas) + if err != nil { + return nil, err + } + cm.Resources = rs } - cm.Resources = rs + if moduleMap[child.String()] != nil { moreChildModules, err := marshalModules(s, schemas, moduleMap[child.String()], moduleMap) if err != nil {