Skip to content

Commit

Permalink
fix: Fix getStepOrDAGTaskName (argoproj#5454)
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Behar <[email protected]>
  • Loading branch information
simster7 authored Mar 18, 2021
1 parent 8d20061 commit 440a689
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 22 deletions.
53 changes: 37 additions & 16 deletions workflow/controller/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2309,36 +2309,57 @@ func getTemplateOutputsFromScope(tmpl *wfv1.Template, scope *wfScope) (*wfv1.Out
return &outputs, nil
}

// hasOutputResultRef will check given template output has any reference
func hasOutputResultRef(name string, parentTmpl *wfv1.Template) bool {
var varRefNamePattern string
func generateOutputResultRegex(name string, parentTmpl *wfv1.Template) (string, string) {
referenceRegex := fmt.Sprintf(`\.%s\.outputs\.result`, name)
expressionRegex := fmt.Sprintf(`\[['\"]%s['\"]\]\.outputs.result`, name)
if parentTmpl.DAG != nil {
varRefNamePattern = "tasks([[.](['\"])?)" + name + "((['\"])?]?).outputs.result"
referenceRegex = "tasks" + referenceRegex
expressionRegex = "tasks" + expressionRegex
} else if parentTmpl.Steps != nil {
varRefNamePattern = "steps([[.](['\"])?)" + name + "((['\"])?]?).outputs.result"
referenceRegex = "steps" + referenceRegex
expressionRegex = "steps" + expressionRegex
}
return referenceRegex, expressionRegex
}

// hasOutputResultRef will check given template output has any reference
func hasOutputResultRef(name string, parentTmpl *wfv1.Template) bool {
jsonValue, err := json.Marshal(parentTmpl)
if err != nil {
log.Warnf("Unable to marshal the template. %v, %v", parentTmpl, err)
log.Warnf("Unable to marshal template %q: %v", parentTmpl, err)
}

contain, err := regexp.MatchString(varRefNamePattern, string(jsonValue))
// First consider usual case (e.g.: `value: "{{steps.generate.outputs.result}}"`)
// This is most common, so should be done first.
referenceRegex, expressionRegex := generateOutputResultRegex(name, parentTmpl)
contains, err := regexp.MatchString(referenceRegex, string(jsonValue))
if err != nil {
log.Warnf("Error in Regex compilation. %s, %v", varRefNamePattern, err)
log.Warnf("Error in regex compilation %q: %v", referenceRegex, err)
}
return contain

if contains {
return true
}

// Next, consider expression case (e.g.: `expression: "steps['generate-random-1'].outputs.result"`)
contains, err = regexp.MatchString(expressionRegex, string(jsonValue))
if err != nil {
log.Warnf("Error in regex compilation %q: %v", expressionRegex, err)
}
return contains
}

// getStepOrDAGTaskName will extract the node from NodeStatus Name
func getStepOrDAGTaskName(nodeName string) string {
if strings.Contains(nodeName, ".") {
name := nodeName[strings.LastIndex(nodeName, ".")+1:]
// Retry, withItems and withParam scenario
if indx := strings.Index(name, "("); indx > 0 {
return name[0:indx]
}
return name
// If our name contains an open parenthesis, this node is a child of a Retry node or an expanded node
// (e.g. withItems, withParams, etc.). Ignore anything after the parenthesis.
if parenthesisIndex := strings.Index(nodeName, "("); parenthesisIndex >= 0 {
nodeName = nodeName[:parenthesisIndex]
}
// If our node contains a dot, we're a child node. We're only interested in the step that called us, so return the
// name of the node after the last dot.
if lastDotIndex := strings.LastIndex(nodeName, "."); lastDotIndex >= 0 {
nodeName = nodeName[lastDotIndex+1:]
}
return nodeName
}
Expand Down
29 changes: 23 additions & 6 deletions workflow/controller/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2861,9 +2861,9 @@ func TestStepWFGetNodeName(t *testing.T) {
assert.NoError(t, err)
for _, node := range wf.Status.Nodes {
if strings.Contains(node.Name, "generate") {
assert.True(t, getStepOrDAGTaskName(node.Name) == "generate")
assert.Equal(t, "generate", getStepOrDAGTaskName(node.Name))
} else if strings.Contains(node.Name, "print-message") {
assert.True(t, getStepOrDAGTaskName(node.Name) == "print-message")
assert.Equal(t, "print-message", getStepOrDAGTaskName(node.Name))
}
}
}
Expand All @@ -2886,10 +2886,10 @@ func TestDAGWFGetNodeName(t *testing.T) {
assert.NoError(t, err)
for _, node := range wf.Status.Nodes {
if strings.Contains(node.Name, ".A") {
assert.True(t, getStepOrDAGTaskName(node.Name) == "A")
assert.Equal(t, "A", getStepOrDAGTaskName(node.Name))
}
if strings.Contains(node.Name, ".B") {
assert.True(t, getStepOrDAGTaskName(node.Name) == "B")
assert.Equal(t, "B", getStepOrDAGTaskName(node.Name))
}
}
}
Expand Down Expand Up @@ -3572,9 +3572,9 @@ func TestContainerOutputsResult(t *testing.T) {

for _, node := range wf.Status.Nodes {
if strings.Contains(node.Name, "hello1") {
assert.True(t, getStepOrDAGTaskName(node.Name) == "hello1")
assert.Equal(t, "hello1", getStepOrDAGTaskName(node.Name))
} else if strings.Contains(node.Name, "hello2") {
assert.True(t, getStepOrDAGTaskName(node.Name) == "hello2")
assert.Equal(t, "hello2", getStepOrDAGTaskName(node.Name))
}
}
}
Expand Down Expand Up @@ -6204,3 +6204,20 @@ func TestStepsFailFast(t *testing.T) {
assert.Equal(t, wfv1.NodeFailed, node.Phase)
}
}

func TestGetStepOrDAGTaskName(t *testing.T) {
assert.Equal(t, "generate-artifact", getStepOrDAGTaskName("data-transformation-gjrt8[0].generate-artifact(2:foo/script.py)"))
assert.Equal(t, "generate-artifact", getStepOrDAGTaskName("data-transformation-gjrt8[0].generate-artifact(2:foo/script(.)py)"))
}

func TestGenerateOutputResultRegex(t *testing.T) {
dagTmpl := &wfv1.Template{DAG: &wfv1.DAGTemplate{}}
ref, expr := generateOutputResultRegex("template-name", dagTmpl)
assert.Equal(t, `tasks\.template-name\.outputs\.result`, ref)
assert.Equal(t, `tasks\[['\"]template-name['\"]\]\.outputs.result`, expr)

stepsTmpl := &wfv1.Template{Steps: []wfv1.ParallelSteps{}}
ref, expr = generateOutputResultRegex("template-name", stepsTmpl)
assert.Equal(t, `steps\.template-name\.outputs\.result`, ref)
assert.Equal(t, `steps\[['\"]template-name['\"]\]\.outputs.result`, expr)
}

0 comments on commit 440a689

Please sign in to comment.