github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/steampipeconfig/parse/decode_children.go (about) 1 package parse 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/hcl/v2" 7 "github.com/turbot/go-kit/helpers" 8 "github.com/turbot/pipe-fittings/hclhelpers" 9 "github.com/turbot/steampipe/pkg/steampipeconfig/modconfig" 10 ) 11 12 func resolveChildrenFromNames(childNames []string, block *hcl.Block, supportedChildren []string, parseCtx *ModParseContext) ([]modconfig.ModTreeItem, hcl.Diagnostics) { 13 var diags hcl.Diagnostics 14 diags = checkForDuplicateChildren(childNames, block) 15 if diags.HasErrors() { 16 return nil, diags 17 } 18 19 // find the children in the eval context and populate control children 20 children := make([]modconfig.ModTreeItem, len(childNames)) 21 22 for i, childName := range childNames { 23 parsedName, err := modconfig.ParseResourceName(childName) 24 if err != nil || !helpers.StringSliceContains(supportedChildren, parsedName.ItemType) { 25 diags = append(diags, childErrorDiagnostic(childName, block)) 26 continue 27 } 28 29 // now get the resource from the parent mod 30 // find the mod which owns this resource - it may be either the current mod, or one of it's direct dependencies 31 var mod = parseCtx.GetMod(parsedName.Mod) 32 if mod == nil { 33 diags = append(diags, &hcl.Diagnostic{ 34 Severity: hcl.DiagError, 35 Summary: fmt.Sprintf("Could not resolve mod for child %s", childName), 36 Subject: &block.TypeRange, 37 }) 38 break 39 } 40 41 resource, found := mod.GetResource(parsedName) 42 // ensure this item is a mod tree item 43 child, ok := resource.(modconfig.ModTreeItem) 44 if !found || !ok { 45 diags = append(diags, &hcl.Diagnostic{ 46 Severity: hcl.DiagError, 47 Summary: fmt.Sprintf("Could not resolve child %s", childName), 48 Subject: &block.TypeRange, 49 }) 50 continue 51 } 52 53 children[i] = child 54 } 55 if diags.HasErrors() { 56 return nil, diags 57 } 58 59 return children, nil 60 } 61 62 func checkForDuplicateChildren(names []string, block *hcl.Block) hcl.Diagnostics { 63 var diags hcl.Diagnostics 64 // validate each child name appears only once 65 nameMap := make(map[string]int) 66 for _, n := range names { 67 nameCount := nameMap[n] 68 // raise an error if this name appears more than once (but only raise 1 error per name) 69 if nameCount == 1 { 70 diags = append(diags, &hcl.Diagnostic{ 71 Severity: hcl.DiagError, 72 Summary: fmt.Sprintf("'%s.%s' has duplicate child name '%s'", block.Type, block.Labels[0], n), 73 Subject: hclhelpers.BlockRangePointer(block)}) 74 } 75 nameMap[n] = nameCount + 1 76 } 77 78 return diags 79 } 80 81 func childErrorDiagnostic(childName string, block *hcl.Block) *hcl.Diagnostic { 82 return &hcl.Diagnostic{ 83 Severity: hcl.DiagError, 84 Summary: fmt.Sprintf("Invalid child %s", childName), 85 Subject: &block.TypeRange, 86 } 87 } 88 89 func getChildNameStringsFromModTreeItem(children []modconfig.ModTreeItem) []string { 90 res := make([]string, len(children)) 91 for i, n := range children { 92 res[i] = n.Name() 93 } 94 return res 95 }