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  }