question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Nested conditions are wrongly getting unnested

See original GitHub issue

/kind bug

What steps did you take and what happened: A modified flip coin example in three variants to compare the results:

def flipcoin1(forced_result1: str = 'heads', forced_result2: str = 'heads'):
    flip1 = FlipCoinOp('flip1', str(forced_result1))
    flip2 = FlipCoinOp('flip2', str(forced_result2))

    with dsl.Condition(flip1.output == 'heads'):
        PrintOp('print', "{} {}".format(flip1.output, flip2.output))
def flipcoin2(forced_result1: str = 'heads', forced_result2: str = 'heads'):
    flip1 = FlipCoinOp('flip1', str(forced_result1))
    flip2 = FlipCoinOp('flip2', str(forced_result2))

    with dsl.Condition(flip1.output == 'heads'):
        with dsl.Condition(flip2.output == 'heads'):
            PrintOp('print', "{} {}".format(flip1.output, flip2.output))
def flipcoin3(forced_result1: str = 'heads', forced_result2: str = 'heads'):
    flip1 = FlipCoinOp('flip1', str(forced_result1))
    flip2 = FlipCoinOp('flip2', str(forced_result2))

    with dsl.Condition(flip1.output == 'heads'):
        PrintOp('print-debug', "debug!")
        with dsl.Condition(flip2.output == 'heads'):
            PrintOp('print', "{} {}".format(flip1.output, flip2.output))

For Argo target, it looks as expected:

|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1 (deps: flip1, flip2), when flip1.output == "heads"
      |- print

condition2.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1 (deps: flip1, flip2), when flip1.output == "heads"
      |- condition-2, when flip2.output == "heads"
         |- print

condition3.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1 (deps: flip1, flip2), when flip1.output == "heads"
      |- debug-print
      |- condition-2, when flip2.output == "heads"
         |- print

For Tekton backend, though, the following is happening:

condition1.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1: flip1.output == "heads"
      |- print, when condition-1.status in "true"

condition2.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1: flip1.output == "heads"
   |- condition-2: flip2.output == "heads"
      |- print, when condition-2.status in "true"

condition3.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1: flip1.output == "heads"
      |- print-debug, when condition-1.status in "true"
   |- condition-2: flip2.output == "heads"
      |- print, when condition-2.status in "true"

What did you expect to happen:

condition1.py looks fine to me

condition2.py looks like condition-1 is simply ignored instead of making a chain of dependency. I’d expect it to be sth like (it should be possible, now that the conditions’ templates aren’t limited to a single super-condition resource):

condition2.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1: flip1.output == "heads"
      |- condition-2: flip2.output == "heads", when condition-1.status in "true"
         |- print, when condition-2.status in "true"

condition3.py looks like condition-1 is only applied to ContainerOps that are directly under it with no other group in-between, thus making the two conditions independent of each other. I’d expect it looked like that instead:

condition3.py
|- flip-coin-example-pipeline
   |- flip1
   |- flip2
   |- condition-1: flip1.output == "heads"
      |- print-debug, when condition-1.status is "true"
      |- condition-2: flip2.output == "heads", when condition-1.status in "true"
         |- print, when condition-2.status in "true"

Both condition2.py and condition3.py look like conditions are simply factored out of any nesting:

def flipcoin2(forced_result1: str = 'heads', forced_result2: str = 'heads'):
    flip1 = FlipCoinOp('flip1', str(forced_result1))
    flip2 = FlipCoinOp('flip2', str(forced_result2))

    with dsl.Condition(flip1.output == 'heads'):
        pass
    with dsl.Condition(flip2.output == 'heads'):
        PrintOp('print', "{} {}".format(flip1.output, flip2.output))
def flipcoin3(forced_result1: str = 'heads', forced_result2: str = 'heads'):
    flip1 = FlipCoinOp('flip1', str(forced_result1))
    flip2 = FlipCoinOp('flip2', str(forced_result2))

    with dsl.Condition(flip1.output == 'heads'):
        PrintOp('print-debug', "debug!")
    with dsl.Condition(flip2.output == 'heads'):
        PrintOp('print', "{} {}".format(flip1.output, flip2.output))

Additional information: It looks like only tasks get the when at all, as I can only see it in looping over task_refs directly in _create_pipeline_workflow:

    # add task dependencies and add condition refs to the task ref that depends on the condition
    op_name_to_parent_groups = self._get_groups_for_ops(pipeline.groups[0])
    for task in task_refs:
      op = pipeline.ops.get(task['name'])
      parent_group = op_name_to_parent_groups.get(task['name'], [])
      if parent_group:
        if condition_refs.get(parent_group[-2], []):
          task['when'] = condition_refs.get(op_name_to_parent_groups[task['name']][-2], [])

Environment:

  • Python Version (use python --version): 3.9.0 (although it should be irrelevant)
  • SDK Version: 0.5.0
  • Tekton Version (use tkn version):
  • Kubernetes Version (use kubectl version):
  • OS (e.g. from /etc/os-release):

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
Tomclicommented, Jan 4, 2021

Thanks @Udiknedormin, I just came back from the holidays. I will try to address it in our SDK.

0reactions
Udiknedormincommented, Jan 6, 2021

Great, that is exactly how I imagined it to be working, seems to cover all of the use-cases. Thank you!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Replacing nested if statements - Stack Overflow
This gets really ugly when there's lots of conditions. Plus, readability is lost because the actual conditions are hidden behind the boolean ...
Read more >
What is the difference between “nested if” and “unnested if” (if ...
Unnested if statements simply checked the first if statement in the loop (in your case) then ... Nested if statements mean that the...
Read more >
How would you refactor nested IF Statements? [duplicate]
The first refactoring is not quite correct, you can get to check2 without check1 being true, and it seems that both have to...
Read more >
IF function – nested formulas and avoiding pitfalls
The IF function allows you to make a logical comparison between a value and what you expect by testing for a condition and...
Read more >
Denesting Radicals (or Unnesting Radicals) - BrownMath.com
Can these be simplified to avoid nesting radicals? ... the second equation by the first, and get rid of three of the four...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found