From f05931d91dcc7af5557352e8f81e31e044d2ca2e Mon Sep 17 00:00:00 2001 From: kaidaguerre Date: Fri, 17 Jun 2022 15:12:13 +0100 Subject: [PATCH] 'check all' should not runs controls/benchmarks from dependency mods #2182 --- .../direct_children_mod_decorator.go | 56 ++++++ control/controlexecute/execution_tree.go | 13 +- steampipeconfig/modconfig/interfaces.go | 166 +++++++++--------- 3 files changed, 146 insertions(+), 89 deletions(-) create mode 100644 control/controlexecute/direct_children_mod_decorator.go diff --git a/control/controlexecute/direct_children_mod_decorator.go b/control/controlexecute/direct_children_mod_decorator.go new file mode 100644 index 000000000..f1f88355e --- /dev/null +++ b/control/controlexecute/direct_children_mod_decorator.go @@ -0,0 +1,56 @@ +package controlexecute + +import "github.com/turbot/steampipe/steampipeconfig/modconfig" + +// DirectChildrenModDecorator is a struct used to wrap a Mod but modify the results of GetChildren to only return +// immediate mod children (as opposed to all resources in dependency mods as well) +// This is needed when running 'check all' for a mod which has dependency mopds' +type DirectChildrenModDecorator struct { + Mod *modconfig.Mod +} + +func (r DirectChildrenModDecorator) AddParent(item modconfig.ModTreeItem) error { + return nil +} + +func (r DirectChildrenModDecorator) GetChildren() []modconfig.ModTreeItem { + var res []modconfig.ModTreeItem + for _, child := range r.Mod.GetChildren() { + if child.GetMod().Name() == r.Mod.Name() { + res = append(res) + } + } + return res +} + +func (r DirectChildrenModDecorator) Name() string { + return r.Mod.Name() +} + +func (r DirectChildrenModDecorator) GetUnqualifiedName() string { + return r.Mod.GetUnqualifiedName() +} + +func (r DirectChildrenModDecorator) GetTitle() string { + return r.Mod.GetTitle() +} + +func (r DirectChildrenModDecorator) GetDescription() string { + return r.Mod.GetDescription() +} + +func (r DirectChildrenModDecorator) GetTags() map[string]string { + return r.Mod.GetTags() +} + +func (r DirectChildrenModDecorator) GetPaths() []modconfig.NodePath { + return r.Mod.GetPaths() +} + +func (r DirectChildrenModDecorator) SetPaths() { + r.Mod.SetPaths() +} + +func (r DirectChildrenModDecorator) GetMod() *modconfig.Mod { + return r.Mod +} diff --git a/control/controlexecute/execution_tree.go b/control/controlexecute/execution_tree.go index 33226f833..b05de26a6 100644 --- a/control/controlexecute/execution_tree.go +++ b/control/controlexecute/execution_tree.go @@ -207,14 +207,19 @@ func (e *ExecutionTree) ShouldIncludeControl(controlName string) bool { func (e *ExecutionTree) getExecutionRootFromArg(arg string) (modconfig.ModTreeItem, error) { // special case handling for the string "all" if arg == "all" { - // return the workspace mod as root - return e.workspace.Mod, nil + // if the arg is "all", we want to execute all _direct_ children of the Mod + // but NOT children which come from dependency mods + + // to achieve this, use a DirectChildrenModDecorator + + return DirectChildrenModDecorator{e.workspace.Mod}, nil } - // if the arg is the name of one of the workjspace dependen + // if the arg is the name of one of the workspace dependendencies, wrap it in DirectChildrenModDecorator + // so we only execute _its_ direct children for _, mod := range e.workspace.Mods { if mod.ShortName == arg { - return mod, nil + return DirectChildrenModDecorator{mod}, nil } } diff --git a/steampipeconfig/modconfig/interfaces.go b/steampipeconfig/modconfig/interfaces.go index 8a380f031..68c63a312 100644 --- a/steampipeconfig/modconfig/interfaces.go +++ b/steampipeconfig/modconfig/interfaces.go @@ -5,88 +5,84 @@ import ( "github.com/zclconf/go-cty/cty" ) -// MappableResource must be implemented by resources which can be created -// directly from a content file (e.g. sql, markdown) -type MappableResource interface { - // InitialiseFromFile creates a mappable resource from a file path - // It returns the resource, and the raw file data - InitialiseFromFile(modPath, filePath string) (MappableResource, []byte, error) - Name() string - GetUnqualifiedName() string - GetMetadata() *ResourceMetadata - SetMetadata(*ResourceMetadata) - GetDeclRange() *hcl.Range -} - -// ModTreeItem must be implemented by elements of the mod resource hierarchy -// i.e. Control, Benchmark, Dashboard -type ModTreeItem interface { - AddParent(ModTreeItem) error - GetChildren() []ModTreeItem - Name() string - GetUnqualifiedName() string - GetTitle() string - GetDescription() string - GetTags() map[string]string - // GetPaths returns an array resource paths - GetPaths() []NodePath - SetPaths() - GetMod() *Mod -} - -// HclResource must be implemented by resources defined in HCL -type HclResource interface { - Name() string - GetUnqualifiedName() string - CtyValue() (cty.Value, error) - OnDecoded(*hcl.Block, ModResourcesProvider) hcl.Diagnostics - AddReference(ref *ResourceReference) - GetReferences() []*ResourceReference - GetDeclRange() *hcl.Range -} - -// ResourceWithMetadata must be implemented by resources which supports reflection metadata -type ResourceWithMetadata interface { - Name() string - GetMetadata() *ResourceMetadata - SetMetadata(metadata *ResourceMetadata) - SetAnonymous(block *hcl.Block) - IsAnonymous() bool -} - -// QueryProvider must be implemented by resources which supports prepared statements, i.e. Control and Query -type QueryProvider interface { - Name() string - GetArgs() *QueryArgs - GetParams() []*ParamDef - GetSQL() *string - GetQuery() *Query - SetArgs(*QueryArgs) - SetParams([]*ParamDef) - GetPreparedStatementName() string - GetPreparedStatementExecuteSQL(*QueryArgs) (*ResolvedQuery, error) - // implemented by QueryProviderBase - AddRuntimeDependencies([]*RuntimeDependency) - GetRuntimeDependencies() map[string]*RuntimeDependency - RequiresExecution(QueryProvider) bool - VerifyQuery(QueryProvider) error -} - -// DashboardLeafNode must be implemented by resources may be a leaf node in the dashboard execution tree -type DashboardLeafNode interface { - Name() string - GetUnqualifiedName() string - GetTitle() string - GetDisplay() string - GetDescription() string - GetDocumentation() string - GetType() string - GetTags() map[string]string - GetWidth() int - GetPaths() []NodePath - GetMetadata() *ResourceMetadata -} - -type ModResourcesProvider interface { - GetResourceMaps() *ModResources -} +type ( + // MappableResource must be implemented by resources which can be created + // directly from a content file (e.g. sql, markdown) + MappableResource interface { + // InitialiseFromFile creates a mappable resource from a file path + // It returns the resource, and the raw file data + InitialiseFromFile(modPath, filePath string) (MappableResource, []byte, error) + Name() string + GetUnqualifiedName() string + GetMetadata() *ResourceMetadata + SetMetadata(*ResourceMetadata) + GetDeclRange() *hcl.Range + } + // ModTreeItem must be implemented by elements of the mod resource hierarchy + // i.e. Control, Benchmark, Dashboard + ModTreeItem interface { + AddParent(ModTreeItem) error + GetChildren() []ModTreeItem + Name() string + GetUnqualifiedName() string + GetTitle() string + GetDescription() string + GetTags() map[string]string + // GetPaths returns an array resource paths + GetPaths() []NodePath + SetPaths() + GetMod() *Mod + } + // HclResource must be implemented by resources defined in HCL + HclResource interface { + Name() string + GetUnqualifiedName() string + CtyValue() (cty.Value, error) + OnDecoded(*hcl.Block, ModResourcesProvider) hcl.Diagnostics + AddReference(ref *ResourceReference) + GetReferences() []*ResourceReference + GetDeclRange() *hcl.Range + } + // ResourceWithMetadata must be implemented by resources which supports reflection metadata + ResourceWithMetadata interface { + Name() string + GetMetadata() *ResourceMetadata + SetMetadata(metadata *ResourceMetadata) + SetAnonymous(block *hcl.Block) + IsAnonymous() bool + } + // QueryProvider must be implemented by resources which supports prepared statements, i.e. Control and Query + QueryProvider interface { + Name() string + GetArgs() *QueryArgs + GetParams() []*ParamDef + GetSQL() *string + GetQuery() *Query + SetArgs(*QueryArgs) + SetParams([]*ParamDef) + GetPreparedStatementName() string + GetPreparedStatementExecuteSQL(*QueryArgs) (*ResolvedQuery, error) + // implemented by QueryProviderBase + AddRuntimeDependencies([]*RuntimeDependency) + GetRuntimeDependencies() map[string]*RuntimeDependency + RequiresExecution(QueryProvider) bool + VerifyQuery(QueryProvider) error + } + // DashboardLeafNode must be implemented by resources may be a leaf node in the dashboard execution tree + DashboardLeafNode interface { + Name() string + GetUnqualifiedName() string + GetTitle() string + GetDisplay() string + GetDescription() string + GetDocumentation() string + GetType() string + GetTags() map[string]string + GetWidth() int + GetPaths() []NodePath + GetMetadata() *ResourceMetadata + } + ModResourcesProvider interface { + GetResourceMaps() *ModResources + } +)