(ctx context.Context, nodeName string, tmplCtx *templateresolution.TemplateContext, templateScope string, tmpl *wfv1.Template, orgTmpl wfv1.TemplateReferenceHolder, opts *executeTemplateOpts)
| 39 | } |
| 40 | |
| 41 | func (woc *wfOperationCtx) executeSteps(ctx context.Context, nodeName string, tmplCtx *templateresolution.TemplateContext, templateScope string, tmpl *wfv1.Template, orgTmpl wfv1.TemplateReferenceHolder, opts *executeTemplateOpts) (*wfv1.NodeStatus, error) { |
| 42 | node, err := woc.wf.GetNodeByName(nodeName) |
| 43 | if err != nil { |
| 44 | node = woc.initializeExecutableNode(ctx, nodeName, wfv1.NodeTypeSteps, templateScope, tmpl, orgTmpl, opts.boundaryID, wfv1.NodeRunning, opts.nodeFlag, true) |
| 45 | } |
| 46 | |
| 47 | defer func() { |
| 48 | nodePhase, err := woc.wf.Status.Nodes.GetPhase(node.ID) |
| 49 | if err != nil { |
| 50 | woc.log.WithField("nodeID", node.ID).WithFatal().Error(ctx, "was unable to obtain nodePhase for nodeID") |
| 51 | panic(fmt.Sprintf("unable to obtain nodePhase for %s", node.ID)) |
| 52 | } |
| 53 | if nodePhase.Fulfilled(node.TaskResultSynced) { |
| 54 | woc.killDaemonedChildren(ctx, node.ID) |
| 55 | } |
| 56 | }() |
| 57 | |
| 58 | // The template scope of this step. |
| 59 | stepTemplateScope := tmplCtx.GetTemplateScope() |
| 60 | |
| 61 | stepsCtx := stepsContext{ |
| 62 | boundaryID: node.ID, |
| 63 | scope: createScope(tmpl), |
| 64 | tmplCtx: tmplCtx, |
| 65 | onExitTemplate: opts.onExitTemplate, |
| 66 | } |
| 67 | woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, stepsCtx.scope) |
| 68 | |
| 69 | for i, stepGroup := range tmpl.Steps { |
| 70 | sgNodeName := fmt.Sprintf("%s[%d]", nodeName, i) |
| 71 | { |
| 72 | sgNode, err := woc.wf.GetNodeByName(sgNodeName) |
| 73 | if err != nil { |
| 74 | _ = woc.initializeNode(ctx, sgNodeName, wfv1.NodeTypeStepGroup, stepTemplateScope, &wfv1.WorkflowStep{}, stepsCtx.boundaryID, wfv1.NodeRunning, &wfv1.NodeFlag{}, true) |
| 75 | } else if !sgNode.Fulfilled() { |
| 76 | _ = woc.markNodePhase(ctx, sgNodeName, wfv1.NodeRunning) |
| 77 | } |
| 78 | } |
| 79 | // The following will connect the step group node to its parents. |
| 80 | if i == 0 { |
| 81 | // If this is the first step group, the boundary node is the parent |
| 82 | woc.addChildNode(ctx, nodeName, sgNodeName) |
| 83 | } else { |
| 84 | // Otherwise connect all the outbound nodes of the previous step group as parents to |
| 85 | // the current step group node. |
| 86 | prevStepGroupName := fmt.Sprintf("%s[%d]", nodeName, i-1) |
| 87 | prevStepGroupNode, err := woc.wf.GetNodeByName(prevStepGroupName) |
| 88 | if err != nil { |
| 89 | return nil, err |
| 90 | } |
| 91 | if len(prevStepGroupNode.Children) == 0 { |
| 92 | // corner case which connects an empty StepGroup (e.g. due to empty withParams) to |
| 93 | // the previous StepGroup node |
| 94 | woc.addChildNode(ctx, prevStepGroupName, sgNodeName) |
| 95 | } else { |
| 96 | for _, childID := range prevStepGroupNode.Children { |
| 97 | outboundNodeIDs := woc.getOutboundNodes(ctx, childID) |
| 98 | woc.log.WithFields(logging.Fields{"childID": childID, "outboundNodeIDs": outboundNodeIDs}).Info(ctx, "SG Outbound nodes") |
no test coverage detected