Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Retry creating wftmpl that references another wftmpl in the same operation #5198

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions cmd/argo/commands/template/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package template
import (
"log"
"os"
"regexp"
"strings"

"github.com/argoproj/pkg/json"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -38,6 +40,17 @@ func NewCreateCommand() *cobra.Command {
return command
}

var templateErrorRegex *regexp.Regexp = nil

// Compiling regex is expensive, only compile this once if we need it
func getTemplateErrorRegex() *regexp.Regexp {
if templateErrorRegex != nil {
return templateErrorRegex
}
templateErrorRegex = regexp.MustCompile(`template reference (.+?) not found`)
return templateErrorRegex
}

func CreateWorkflowTemplates(filePaths []string, cliOpts *cliCreateOpts) {
if cliOpts == nil {
cliOpts = &cliCreateOpts{}
Expand All @@ -61,6 +74,9 @@ func CreateWorkflowTemplates(filePaths []string, cliOpts *cliCreateOpts) {
os.Exit(1)
}

var retryWorkflowTemplates []wfv1.WorkflowTemplate

main:
for _, wftmpl := range workflowTemplates {
if wftmpl.Namespace == "" {
wftmpl.Namespace = client.Namespace()
Expand All @@ -69,6 +85,43 @@ func CreateWorkflowTemplates(filePaths []string, cliOpts *cliCreateOpts) {
Namespace: wftmpl.Namespace,
Template: &wftmpl,
})

if err != nil {

// If we are trying to create a template that references another template that is about to be created with this
// operation (but has not been created yet), that template will fail with a "reference not found" error. If
// a template returns that error, we check to see if the reference is indeed about to be created in this operation.
// If it is, we add this template to a list and then retry to create it once all templates have had a chance
// to be created.
re := getTemplateErrorRegex()
// Check if the error received matches a "reference not found" error.
if referenceNotFoundErrorMatch := re.FindStringSubmatch(err.Error()); len(referenceNotFoundErrorMatch) > 0 {
reference := referenceNotFoundErrorMatch[1]
// Check if the template referenced is indeed in this operation
for _, w := range workflowTemplates {
if strings.HasPrefix(reference, w.Name) || strings.HasSuffix(reference, w.GenerateName) {
// Add this template to the list of references to retry
retryWorkflowTemplates = append(retryWorkflowTemplates, w)
continue main
}
}
}

log.Fatalf("Failed to create workflow template: %v", err)
}
printWorkflowTemplate(created, cliOpts.output)
}

// Retry the workflow templates that were not created due to "reference not found" error (see above). This will usually
// be empty and not run.
for _, wftmpl := range retryWorkflowTemplates {
if wftmpl.Namespace == "" {
wftmpl.Namespace = client.Namespace()
}
created, err := serviceClient.CreateWorkflowTemplate(ctx, &workflowtemplatepkg.WorkflowTemplateCreateRequest{
Namespace: wftmpl.Namespace,
Template: &wftmpl,
})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking for feedback for this solution. If feedback is good, then I will move to clean the code, add it to other similar areas (e.g. ClusterWorkflowTemplates), and add test.

if err != nil {
log.Fatalf("Failed to create workflow template: %v", err)
}
Expand Down