github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/dashboard/dashboardexecute/check_run.go (about) 1 package dashboardexecute 2 3 import ( 4 "context" 5 6 "github.com/turbot/steampipe/pkg/control/controlexecute" 7 "github.com/turbot/steampipe/pkg/control/controlstatus" 8 "github.com/turbot/steampipe/pkg/dashboard/dashboardtypes" 9 "github.com/turbot/steampipe/pkg/statushooks" 10 "github.com/turbot/steampipe/pkg/steampipeconfig/modconfig" 11 "github.com/turbot/steampipe/pkg/utils" 12 ) 13 14 // CheckRun is a struct representing the execution of a control or benchmark 15 type CheckRun struct { 16 DashboardParentImpl 17 18 Summary *controlexecute.GroupSummary `json:"summary"` 19 SessionId string `json:"-"` 20 // if the dashboard node is a control, serialise to json as 'properties' 21 Control *modconfig.Control `json:"properties,omitempty"` 22 Root controlexecute.ExecutionTreeNode `json:"-"` 23 24 controlExecutionTree *controlexecute.ExecutionTree 25 } 26 27 func (r *CheckRun) AsTreeNode() *dashboardtypes.SnapshotTreeNode { 28 return r.Root.AsTreeNode() 29 } 30 31 func NewCheckRun(resource modconfig.DashboardLeafNode, parent dashboardtypes.DashboardParent, executionTree *DashboardExecutionTree) (*CheckRun, error) { 32 c := &CheckRun{SessionId: executionTree.sessionId} 33 // create NewDashboardTreeRunImpl 34 // (we must create after creating the run as it requires a ref to the run) 35 c.DashboardParentImpl = newDashboardParentImpl(resource, parent, c, executionTree) 36 37 c.NodeType = resource.BlockType() 38 // set status to initialized 39 c.Status = dashboardtypes.RunInitialized 40 // add r into execution tree 41 executionTree.runs[c.Name] = c 42 return c, nil 43 } 44 45 // Initialise implements DashboardTreeRun 46 func (r *CheckRun) Initialise(ctx context.Context) { 47 // build control execution tree during init, rather than in Execute, so that it is populated when the ExecutionStarted event is sent 48 controlFilterWhereClause := "" 49 executionTree, err := controlexecute.NewExecutionTree(ctx, r.executionTree.workspace, r.executionTree.client, controlFilterWhereClause, r.resource.Name()) 50 if err != nil { 51 // set the error status on the counter - this will raise counter error event 52 r.SetError(ctx, err) 53 return 54 } 55 r.controlExecutionTree = executionTree 56 r.Root = executionTree.Root.Children[0] 57 } 58 59 // Execute implements DashboardTreeRun 60 func (r *CheckRun) Execute(ctx context.Context) { 61 utils.LogTime("CheckRun.execute start") 62 defer utils.LogTime("CheckRun.execute end") 63 64 // set status to running (this sends update event) 65 r.setRunning(ctx) 66 67 // create a context with a DashboardEventControlHooks to report control execution progress 68 ctx = controlstatus.AddControlHooksToContext(ctx, NewDashboardEventControlHooks(r)) 69 if err := r.controlExecutionTree.Execute(ctx); err != nil { 70 r.SetError(ctx, err) 71 return 72 } 73 74 // set the summary on the CheckRun 75 r.Summary = r.controlExecutionTree.Root.Summary 76 77 // set complete status on counter - this will raise counter complete event 78 r.SetComplete(ctx) 79 } 80 81 // ChildrenComplete implements DashboardTreeRun (override base) 82 func (r *CheckRun) ChildrenComplete() bool { 83 return r.RunComplete() 84 } 85 86 // IsSnapshotPanel implements SnapshotPanel 87 func (*CheckRun) IsSnapshotPanel() {} 88 89 // SetError implements DashboardTreeRun (override to set snapshothook status 90 func (r *CheckRun) SetError(ctx context.Context, err error) { 91 // increment error count for snapshot hook 92 statushooks.SnapshotError(ctx) 93 r.DashboardTreeRunImpl.SetError(ctx, err) 94 } 95 96 // SetComplete implements DashboardTreeRun (override to set snapshothook status 97 func (r *CheckRun) SetComplete(ctx context.Context) { 98 // call snapshot hooks with progress 99 statushooks.UpdateSnapshotProgress(ctx, 1) 100 101 r.DashboardTreeRunImpl.SetComplete(ctx) 102 } 103 104 // BuildSnapshotPanels is a custom implementation of BuildSnapshotPanels - be nice to just use the DashboardExecutionTree but work is needed on common interface types/generics 105 func (r *CheckRun) BuildSnapshotPanels(leafNodeMap map[string]dashboardtypes.SnapshotPanel) map[string]dashboardtypes.SnapshotPanel { 106 // if this check run is for a control, just add the controlRUn 107 if controlRun, ok := r.Root.(*controlexecute.ControlRun); ok { 108 leafNodeMap[controlRun.Control.Name()] = controlRun 109 return leafNodeMap 110 } 111 112 leafNodeMap[r.GetName()] = r 113 114 return r.buildSnapshotPanelsUnder(r.Root, leafNodeMap) 115 } 116 117 func (r *CheckRun) buildSnapshotPanelsUnder(parent controlexecute.ExecutionTreeNode, res map[string]dashboardtypes.SnapshotPanel) map[string]dashboardtypes.SnapshotPanel { 118 for _, c := range parent.GetChildren() { 119 // if this node is a snapshot node, add to map 120 if snapshotNode, ok := c.(dashboardtypes.SnapshotPanel); ok { 121 res[c.GetName()] = snapshotNode 122 } 123 res = r.buildSnapshotPanelsUnder(c, res) 124 } 125 return res 126 }