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

     1  package dashboardexecute
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  
     8  	"github.com/turbot/steampipe/pkg/dashboard/dashboardtypes"
     9  	"github.com/turbot/steampipe/pkg/steampipeconfig/modconfig"
    10  )
    11  
    12  // DashboardContainerRun is a struct representing a container run
    13  type DashboardContainerRun struct {
    14  	DashboardParentImpl
    15  
    16  	dashboardNode *modconfig.DashboardContainer
    17  }
    18  
    19  func (r *DashboardContainerRun) AsTreeNode() *dashboardtypes.SnapshotTreeNode {
    20  	res := &dashboardtypes.SnapshotTreeNode{
    21  		Name:     r.Name,
    22  		NodeType: r.NodeType,
    23  		Children: make([]*dashboardtypes.SnapshotTreeNode, len(r.children)),
    24  	}
    25  	for i, c := range r.children {
    26  		res.Children[i] = c.AsTreeNode()
    27  	}
    28  	return res
    29  }
    30  
    31  func NewDashboardContainerRun(container *modconfig.DashboardContainer, parent dashboardtypes.DashboardParent, executionTree *DashboardExecutionTree) (*DashboardContainerRun, error) {
    32  	children := container.GetChildren()
    33  
    34  	r := &DashboardContainerRun{dashboardNode: container}
    35  	// create NewDashboardTreeRunImpl
    36  	// (we must create after creating the run as it requires a ref to the run)
    37  	r.DashboardParentImpl = newDashboardParentImpl(container, parent, r, executionTree)
    38  
    39  	if container.Title != nil {
    40  		r.Title = *container.Title
    41  	}
    42  
    43  	if container.Width != nil {
    44  		r.Width = *container.Width
    45  	}
    46  	r.childCompleteChan = make(chan dashboardtypes.DashboardTreeRun, len(children))
    47  	for _, child := range children {
    48  		var childRun dashboardtypes.DashboardTreeRun
    49  		//nolint:golint // using a global var here to maintain parity with definition of childRun
    50  		var err error
    51  		switch i := child.(type) {
    52  		case *modconfig.DashboardContainer:
    53  			childRun, err = NewDashboardContainerRun(i, r, executionTree)
    54  			if err != nil {
    55  				return nil, err
    56  			}
    57  		case *modconfig.Dashboard:
    58  			childRun, err = NewDashboardRun(i, r, executionTree)
    59  			if err != nil {
    60  				return nil, err
    61  			}
    62  		case *modconfig.Benchmark, *modconfig.Control:
    63  			childRun, err = NewCheckRun(i.(modconfig.DashboardLeafNode), r, executionTree)
    64  			if err != nil {
    65  				return nil, err
    66  			}
    67  
    68  		default:
    69  			// ensure this item is a DashboardLeafNode
    70  			leafNode, ok := i.(modconfig.DashboardLeafNode)
    71  			if !ok {
    72  				return nil, fmt.Errorf("child %s does not implement DashboardLeafNode", i.Name())
    73  			}
    74  
    75  			childRun, err = NewLeafRun(leafNode, r, executionTree)
    76  			if err != nil {
    77  				return nil, err
    78  			}
    79  		}
    80  
    81  		// should never happen - container children must be either container or counter
    82  		if childRun == nil {
    83  			continue
    84  		}
    85  
    86  		// if our child has not completed, we have not completed
    87  		if childRun.GetRunStatus() == dashboardtypes.RunInitialized {
    88  			r.Status = dashboardtypes.RunInitialized
    89  		}
    90  		r.children = append(r.children, childRun)
    91  	}
    92  	// add r into execution tree
    93  	executionTree.runs[r.Name] = r
    94  	return r, nil
    95  }
    96  
    97  // Initialise implements DashboardTreeRun
    98  func (r *DashboardContainerRun) Initialise(ctx context.Context) {
    99  	// initialise our children
   100  	if err := r.initialiseChildren(ctx); err != nil {
   101  		r.SetError(ctx, err)
   102  	}
   103  }
   104  
   105  // Execute implements DashboardTreeRun
   106  // execute all children and wait for them to complete
   107  func (r *DashboardContainerRun) Execute(ctx context.Context) {
   108  	// execute all children asynchronously
   109  	r.executeChildrenAsync(ctx)
   110  
   111  	// try to set status as running (will be set to blocked if any children are blocked)
   112  	r.setRunning(ctx)
   113  
   114  	// wait for children to complete
   115  	err := <-r.waitForChildrenAsync(ctx)
   116  	if err == nil {
   117  		log.Printf("[TRACE] %s Execute waitForChildrenAsync returned success", r.Name)
   118  		// set complete status on dashboard
   119  		r.SetComplete(ctx)
   120  	} else {
   121  		log.Printf("[TRACE] %s Execute waitForChildrenAsync returned err %s", r.Name, err.Error())
   122  		r.SetError(ctx, err)
   123  	}
   124  }
   125  
   126  // IsSnapshotPanel implements SnapshotPanel
   127  func (*DashboardContainerRun) IsSnapshotPanel() {}