mirror of
https://github.com/turbot/steampipe.git
synced 2026-02-16 16:00:11 -05:00
125 lines
4.3 KiB
Go
125 lines
4.3 KiB
Go
package parse
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/turbot/steampipe/pkg/steampipeconfig/modconfig"
|
|
)
|
|
|
|
// validate the resource
|
|
func validateResource(resource modconfig.HclResource) hcl.Diagnostics {
|
|
var diags hcl.Diagnostics
|
|
if qp, ok := resource.(modconfig.NodeAndEdgeProvider); ok {
|
|
moreDiags := validateNodeAndEdgeProvider(qp)
|
|
diags = append(diags, moreDiags...)
|
|
} else if qp, ok := resource.(modconfig.QueryProvider); ok {
|
|
moreDiags := validateQueryProvider(qp)
|
|
diags = append(diags, moreDiags...)
|
|
}
|
|
|
|
if wp, ok := resource.(modconfig.WithProvider); ok {
|
|
moreDiags := validateRuntimeDependencyProvider(wp)
|
|
diags = append(diags, moreDiags...)
|
|
}
|
|
return diags
|
|
}
|
|
|
|
func validateRuntimeDependencyProvider(wp modconfig.WithProvider) hcl.Diagnostics {
|
|
resource := wp.(modconfig.HclResource)
|
|
var diags hcl.Diagnostics
|
|
if len(wp.GetWiths()) > 0 && !resource.IsTopLevel() {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Only top level resources can have `with` blocks",
|
|
Detail: fmt.Sprintf("%s contains 'with' blocks but is not a top level resource.", resource.Name()),
|
|
Subject: resource.GetDeclRange(),
|
|
})
|
|
}
|
|
return diags
|
|
}
|
|
|
|
// validate that the provider does not contains both edges/nodes and a query/sql
|
|
// enrich the loaded nodes and edges with the fully parsed resources from the resourceMapProvider
|
|
func validateNodeAndEdgeProvider(resource modconfig.NodeAndEdgeProvider) hcl.Diagnostics {
|
|
// TODO [node_reuse] add NodeAndEdgeProviderImpl and move validate there
|
|
// https://github.com/turbot/steampipe/issues/2918
|
|
|
|
var diags hcl.Diagnostics
|
|
containsEdgesOrNodes := len(resource.GetEdges())+len(resource.GetNodes()) > 0
|
|
definesQuery := resource.GetSQL() != nil || resource.GetQuery() != nil
|
|
|
|
// cannot declare both edges/nodes AND sql/query
|
|
if definesQuery && containsEdgesOrNodes {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: fmt.Sprintf("%s contains edges/nodes AND has a query", resource.Name()),
|
|
Subject: resource.GetDeclRange(),
|
|
})
|
|
}
|
|
|
|
// if resource is NOT top level must have either edges/nodes OR sql/query
|
|
if !resource.IsTopLevel() && !definesQuery && !containsEdgesOrNodes {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: fmt.Sprintf("%s does not define a query or SQL, and has no edges/nodes", resource.Name()),
|
|
Subject: resource.GetDeclRange(),
|
|
})
|
|
}
|
|
|
|
diags = append(diags, validateSqlAndQueryNotBothSet(resource)...)
|
|
|
|
diags = append(diags, validateParamAndQueryNotBothSet(resource)...)
|
|
|
|
return diags
|
|
}
|
|
|
|
func validateQueryProvider(resource modconfig.QueryProvider) hcl.Diagnostics {
|
|
var diags hcl.Diagnostics
|
|
|
|
diags = append(diags, resource.ValidateQuery()...)
|
|
|
|
diags = append(diags, validateSqlAndQueryNotBothSet(resource)...)
|
|
|
|
diags = append(diags, validateParamAndQueryNotBothSet(resource)...)
|
|
|
|
return diags
|
|
}
|
|
|
|
func validateParamAndQueryNotBothSet(resource modconfig.QueryProvider) hcl.Diagnostics {
|
|
var diags hcl.Diagnostics
|
|
|
|
// param block cannot be set if a query property is set - it is only valid if inline SQL ids defined
|
|
if len(resource.GetParams()) > 0 {
|
|
if resource.GetQuery() != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagWarning,
|
|
Summary: fmt.Sprintf("Deprecated usage: %s has 'query' property set so should not define 'param' blocks", resource.Name()),
|
|
Subject: resource.GetDeclRange(),
|
|
})
|
|
}
|
|
if !resource.IsTopLevel() && !resource.ParamsInheritedFromBase() {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagWarning,
|
|
Summary: "Deprecated usage: Only top level resources can have 'param' blocks",
|
|
Detail: fmt.Sprintf("%s contains 'param' blocks but is not a top level resource.", resource.Name()),
|
|
Subject: resource.GetDeclRange(),
|
|
})
|
|
}
|
|
}
|
|
return diags
|
|
}
|
|
|
|
func validateSqlAndQueryNotBothSet(resource modconfig.QueryProvider) hcl.Diagnostics {
|
|
var diags hcl.Diagnostics
|
|
// are both sql and query set?
|
|
if resource.GetSQL() != nil && resource.GetQuery() != nil {
|
|
// either Query or SQL property may be set - if Query property already set, error
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: fmt.Sprintf("%s has both 'SQL' and 'query' property set - only 1 of these may be set", resource.Name()),
|
|
Subject: resource.GetDeclRange(),
|
|
})
|
|
}
|
|
return diags
|
|
}
|