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

in comparator does not work when there is only one value inside the parenthesis #4356

Closed
lueenavarro opened this issue Oct 23, 2020 · 5 comments
Assignees
Labels
area/templating Templating with `{{...}}` type/bug

Comments

@lueenavarro
Copy link
Contributor

lueenavarro commented Oct 23, 2020

Summary

"in" is now supported in conditionals but I am getting an error when trying to use it with only one value inside the parenthesis

Here is the error I got:

Failed to evaluate 'when' expresion 'a in (a)': Value 'a' cannot be used with the comparator 'in', it is not a number

However if I use when: "a in (a,b)" then it works.

Diagnostics

What Kubernetes provider are you using?
Kubernetes in IBM cloud

What version of Argo Workflows are you running?
v2.11.6

Here's an example of a workflow that fails

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: scripts-bash-
spec:
  entrypoint: bash-script-example
  templates:
  - name: bash-script-example
    steps:
    - - name: schedule
        template: schedule
    - - name: a
        template: print-message
        when: "a in {{steps.schedule.outputs.result}}"
        arguments:
          parameters:
          - name: message
            value: "I am step A"
      - name: b
        template: print-message
        when: "b in {{steps.schedule.outputs.result}}"
        arguments:
          parameters:
          - name: message
            value: "I am step B"
      - name: c
        template: print-message
        when: "c in {{steps.schedule.outputs.result}}"
        arguments:
          parameters:
          - name: message
            value: "I am step C"

  - name: schedule
    container:
      image: alpine:latest
      command: [sh, -c]
      args: ["echo '(a)'"] # replacing '(a)' with '(a,b)' works
  - name: print-message
    inputs:
      parameters:
      - name: message
    container:
      image: alpine:latest
      command: [sh, -c]
      args: ["echo result was: {{inputs.parameters.message}}"]

Message from the maintainers:

Impacted by this bug? Give it a 👍. We prioritise the issues with the most 👍.

@lueenavarro lueenavarro changed the title in comparactor does not work when there is only one value in comparator does not work when there is only one value inside the parenthesis Oct 23, 2020
@alexec
Copy link
Contributor

alexec commented Oct 23, 2020

Would you like to dig into the code and see if you can find the cause?

@lueenavarro
Copy link
Contributor Author

lueenavarro commented Oct 23, 2020

In workflow/controller/steps.go, there is this function. Its probably line 321 that is causing the error

func shouldExecute(when string) (bool, error) {
	if when == "" {
		return true, nil
	}
	expression, err := govaluate.NewEvaluableExpression(when)
	if err != nil {
		if strings.Contains(err.Error(), "Invalid token") {
			return false, errors.Errorf(errors.CodeBadRequest, "Invalid 'when' expression '%s': %v (hint: try wrapping the affected expression in quotes (\"))", when, err)
		}
		return false, errors.Errorf(errors.CodeBadRequest, "Invalid 'when' expression '%s': %v", when, err)
	}
	// The following loop converts govaluate variables (which we don't use), into strings. This
	// allows us to have expressions like: "foo != bar" without requiring foo and bar to be quoted.
	tokens := expression.Tokens()
	for i, tok := range tokens {
		switch tok.Kind {
		case govaluate.VARIABLE:
			tok.Kind = govaluate.STRING
		default:
			continue
		}
		tokens[i] = tok
	}
	expression, err = govaluate.NewEvaluableExpressionFromTokens(tokens)
	if err != nil {
		return false, errors.InternalWrapErrorf(err, "Failed to parse 'when' expression '%s': %v", when, err)
	}
	result, err := expression.Evaluate(nil) <---- this is the culprit
	if err != nil {
		return false, errors.InternalWrapErrorf(err, "Failed to evaluate 'when' expresion '%s': %v", when, err)
	}
	boolRes, ok := result.(bool)
	if !ok {
		return false, errors.Errorf(errors.CodeBadRequest, "Expected boolean evaluation for '%s'. Got %v", when, result)
	}
	return boolRes, nil
}

@lueenavarro
Copy link
Contributor Author

lueenavarro commented Oct 23, 2020

This does not seem to be a bug in argo but a bug in govaluate. I found this issue in their github.
Knetic/govaluate#79

@simster7
Copy link
Member

Closed as a non-argo issue. As a thought, if you want a in (a) why not simply do a == a?

@lueenavarro
Copy link
Contributor Author

because in my application, the value inside the parenthesis is dynamically generated by another step.

my solution was to add random characters as placeholders to make sure that there are always at least two items.

@agilgur5 agilgur5 added the area/templating Templating with `{{...}}` label Sep 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/templating Templating with `{{...}}` type/bug
Projects
None yet
Development

No branches or pull requests

4 participants