github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/dashboard/dashboardexecute/dashboard_tree_run_impl.go (about)

     1  package dashboardexecute
     2  
     3  import (
     4  	"context"
     5  	"github.com/turbot/steampipe/pkg/dashboard/dashboardevents"
     6  	"github.com/turbot/steampipe/pkg/dashboard/dashboardtypes"
     7  	"github.com/turbot/steampipe/pkg/error_helpers"
     8  	"github.com/turbot/steampipe/pkg/steampipeconfig/modconfig"
     9  	"log"
    10  )
    11  
    12  type DashboardTreeRunImpl struct {
    13  	DashboardName    string                   `json:"dashboard"`
    14  	Description      string                   `json:"description,omitempty"`
    15  	Display          string                   `cty:"display" hcl:"display" json:"display,omitempty"`
    16  	Documentation    string                   `json:"documentation,omitempty"`
    17  	ErrorString      string                   `json:"error,omitempty"`
    18  	Name             string                   `json:"name"`
    19  	NodeType         string                   `json:"panel_type"`
    20  	SourceDefinition string                   `json:"source_definition"`
    21  	Status           dashboardtypes.RunStatus `json:"status"`
    22  	Tags             map[string]string        `json:"tags,omitempty"`
    23  	Title            string                   `json:"title,omitempty"`
    24  	Type             string                   `json:"display_type,omitempty"`
    25  	Width            int                      `json:"width,omitempty"`
    26  
    27  	err           error
    28  	parent        dashboardtypes.DashboardParent
    29  	executionTree *DashboardExecutionTree
    30  	resource      modconfig.DashboardLeafNode
    31  	// store the top level run which embeds this struct
    32  	// we need this for setStatus which serialises the run for the message payload
    33  	run dashboardtypes.DashboardTreeRun
    34  }
    35  
    36  func NewDashboardTreeRunImpl(resource modconfig.DashboardLeafNode, parent dashboardtypes.DashboardParent, run dashboardtypes.DashboardTreeRun, executionTree *DashboardExecutionTree) DashboardTreeRunImpl {
    37  	// NOTE: we MUST declare children inline - therefore we cannot share children between runs in the tree
    38  	// (if we supported the children property then we could reuse resources)
    39  	// so FOR NOW it is safe to use the container name directly as the run name
    40  	res := DashboardTreeRunImpl{
    41  		Name:             resource.Name(),
    42  		Title:            resource.GetTitle(),
    43  		NodeType:         resource.BlockType(),
    44  		Width:            resource.GetWidth(),
    45  		Display:          resource.GetDisplay(),
    46  		Description:      resource.GetDescription(),
    47  		Documentation:    resource.GetDocumentation(),
    48  		Type:             resource.GetType(),
    49  		Tags:             resource.GetTags(),
    50  		SourceDefinition: resource.GetMetadata().SourceDefinition,
    51  
    52  		// set to complete, optimistically
    53  		// if any children have SQL we will set this to DashboardRunReady instead
    54  		Status:        dashboardtypes.RunComplete,
    55  		parent:        parent,
    56  		executionTree: executionTree,
    57  		resource:      resource,
    58  		run:           run,
    59  	}
    60  
    61  	// TACTICAL if this run was created to create a snapshot output for a control run,
    62  	// there will be no execution tree
    63  	if executionTree != nil {
    64  		res.DashboardName = executionTree.dashboardName
    65  	} else {
    66  		// there is no execution tree - use the resource name as the dashboard name
    67  		res.DashboardName = resource.Name()
    68  	}
    69  	return res
    70  }
    71  
    72  // GetName implements DashboardTreeRun
    73  func (r *DashboardTreeRunImpl) GetName() string {
    74  	return r.Name
    75  }
    76  
    77  // GetRunStatus implements DashboardTreeRun
    78  func (r *DashboardTreeRunImpl) GetRunStatus() dashboardtypes.RunStatus {
    79  	return r.Status
    80  }
    81  
    82  // GetError implements DashboardTreeRun
    83  func (r *DashboardTreeRunImpl) GetError() error {
    84  	return r.err
    85  }
    86  
    87  // RunComplete implements DashboardTreeRun
    88  func (r *DashboardTreeRunImpl) RunComplete() bool {
    89  	return r.Status.IsFinished()
    90  }
    91  
    92  // GetInputsDependingOn implements DashboardTreeRun
    93  // defaults to nothing
    94  func (r *DashboardTreeRunImpl) GetInputsDependingOn(_ string) []string { return nil }
    95  
    96  // GetParent implements DashboardTreeRun
    97  func (r *DashboardTreeRunImpl) GetParent() dashboardtypes.DashboardParent {
    98  	return r.parent
    99  }
   100  
   101  // GetTitle implements DashboardTreeRun
   102  func (r *DashboardTreeRunImpl) GetTitle() string {
   103  	return r.Title
   104  }
   105  
   106  // GetNodeType implements DashboardTreeRun
   107  func (r *DashboardTreeRunImpl) GetNodeType() string {
   108  	return r.NodeType
   109  }
   110  
   111  // Initialise implements DashboardTreeRun
   112  func (r *DashboardTreeRunImpl) Initialise(context.Context) {
   113  	panic("must be implemented by child struct")
   114  }
   115  
   116  // Execute implements DashboardTreeRun
   117  func (r *DashboardTreeRunImpl) Execute(ctx context.Context) {
   118  	panic("must be implemented by child struct")
   119  }
   120  
   121  // AsTreeNode implements DashboardTreeRun
   122  func (r *DashboardTreeRunImpl) AsTreeNode() *dashboardtypes.SnapshotTreeNode {
   123  	panic("must be implemented by child struct")
   124  }
   125  
   126  // GetResource implements DashboardTreeRun
   127  func (r *DashboardTreeRunImpl) GetResource() modconfig.DashboardLeafNode {
   128  	return r.resource
   129  }
   130  
   131  // SetError implements DashboardTreeRun
   132  func (r *DashboardTreeRunImpl) SetError(ctx context.Context, err error) {
   133  	log.Printf("[TRACE] %s SetError err %v", r.Name, err)
   134  	r.err = err
   135  	// error type does not serialise to JSON so copy into a string
   136  	r.ErrorString = err.Error()
   137  	// set status (this sends update event)
   138  	if error_helpers.IsContextCancelledError(err) {
   139  		r.setStatus(ctx, dashboardtypes.RunCanceled)
   140  	} else {
   141  		r.setStatus(ctx, dashboardtypes.RunError)
   142  	}
   143  	// tell parent we are done
   144  	r.notifyParentOfCompletion()
   145  }
   146  
   147  // SetComplete implements DashboardTreeRun
   148  func (r *DashboardTreeRunImpl) SetComplete(ctx context.Context) {
   149  	// set status (this sends update event)
   150  	r.setStatus(ctx, dashboardtypes.RunComplete)
   151  	// tell parent we are done
   152  	r.notifyParentOfCompletion()
   153  }
   154  
   155  func (r *DashboardTreeRunImpl) setStatus(ctx context.Context, status dashboardtypes.RunStatus) {
   156  	r.Status = status
   157  	// notify our parent that our status has changed
   158  	r.parent.ChildStatusChanged(ctx)
   159  
   160  	// raise LeafNodeUpdated event
   161  	// TODO [node_reuse] do this a different way https://github.com/turbot/steampipe/issues/2919
   162  	// TACTICAL: pass the full run struct - 'r.run', rather than ourselves - so we serialize all properties
   163  	e, _ := dashboardevents.NewLeafNodeUpdate(r.run, r.executionTree.sessionId, r.executionTree.id)
   164  	r.executionTree.workspace.PublishDashboardEvent(ctx, e)
   165  
   166  }
   167  
   168  func (r *DashboardTreeRunImpl) notifyParentOfCompletion() {
   169  	r.parent.ChildCompleteChan() <- r
   170  }