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  }