(ctx context.Context, nodeID string)
| 3205 | } |
| 3206 | |
| 3207 | func (woc *wfOperationCtx) getOutboundNodes(ctx context.Context, nodeID string) []string { |
| 3208 | node, err := woc.wf.Status.Nodes.Get(nodeID) |
| 3209 | if err != nil { |
| 3210 | woc.log.WithPanic().WithField("nodeID", nodeID).Error(ctx, "was unable to obtain node") |
| 3211 | } |
| 3212 | switch node.Type { |
| 3213 | case wfv1.NodeTypeSkipped, wfv1.NodeTypeSuspend, wfv1.NodeTypeHTTP, wfv1.NodeTypePlugin: |
| 3214 | return []string{node.ID} |
| 3215 | case wfv1.NodeTypePod: |
| 3216 | |
| 3217 | // Recover the template that created this pod. If we can't just let the pod be its own outbound node |
| 3218 | scope, name := node.GetTemplateScope() |
| 3219 | tmplCtx, err := woc.createTemplateContext(ctx, scope, name) |
| 3220 | if err != nil { |
| 3221 | return []string{node.ID} |
| 3222 | } |
| 3223 | _, parentTemplate, _, err := tmplCtx.ResolveTemplate(ctx, node) |
| 3224 | if err != nil { |
| 3225 | return []string{node.ID} |
| 3226 | } |
| 3227 | |
| 3228 | // If this pod does not come from a container set, its outbound node is itself |
| 3229 | if parentTemplate.GetType() != wfv1.TemplateTypeContainerSet { |
| 3230 | return []string{node.ID} |
| 3231 | } |
| 3232 | |
| 3233 | // If this pod comes from a container set, it should be treated as a container or task group |
| 3234 | fallthrough |
| 3235 | case wfv1.NodeTypeContainer, wfv1.NodeTypeTaskGroup: |
| 3236 | if len(node.Children) == 0 { |
| 3237 | return []string{node.ID} |
| 3238 | } |
| 3239 | outboundNodes := make([]string, 0) |
| 3240 | for _, child := range node.Children { |
| 3241 | childNode, err := woc.wf.Status.Nodes.Get(child) |
| 3242 | if err != nil { |
| 3243 | woc.log.WithError(err).WithPanic().WithField("child", child).Error(ctx, "was unable to obtain child node for child") |
| 3244 | } |
| 3245 | // child node has different boundaryID meaning current node is the deepest outbound node |
| 3246 | if node.Type == wfv1.NodeTypeContainer && node.BoundaryID != childNode.BoundaryID { |
| 3247 | outboundNodes = append(outboundNodes, node.ID) |
| 3248 | } else { |
| 3249 | outboundNodes = append(outboundNodes, woc.getOutboundNodes(ctx, child)...) |
| 3250 | } |
| 3251 | } |
| 3252 | return outboundNodes |
| 3253 | case wfv1.NodeTypeRetry: |
| 3254 | numChildren := len(node.Children) |
| 3255 | if numChildren > 0 { |
| 3256 | return []string{node.Children[numChildren-1]} |
| 3257 | } |
| 3258 | case wfv1.NodeTypeSteps, wfv1.NodeTypeDAG: |
| 3259 | if node.MemoizationStatus != nil && node.MemoizationStatus.Hit { |
| 3260 | return []string{node.ID} |
| 3261 | } |
| 3262 | } |
| 3263 | outbound := make([]string, 0) |
| 3264 | for _, outboundNodeID := range node.OutboundNodes { |
no test coverage detected