google / cel-go

Fast, portable, non-Turing complete expression evaluation with gradual typing (Go)
https://cel.dev
Apache License 2.0
2.19k stars 218 forks source link

[Policy compiler] Add a way to explicitly indicate a None output in a match block #975

Closed seirl closed 1 month ago

seirl commented 2 months ago

Some policies don't always return a value, for instance if there is no catch-all match block at the end of the policy.

Sometimes, we want to perform an "early return" when a condition matches where we specifically do not want to return an output. This doesn't seem possible with the current API because output blocks are mandatory.

An API like this could work:

rule:
  match:
    - condition: "size(l) == 0"
      no_output: true

    - condition: "size(l) > 10"
      output: "l[0] / 2"

    - output: "l[0]"
TristonianJones commented 1 month ago

I think stating things in the affirmative is likely to be beneficial in the long run. The following is actually equivalent to the early-return case, but more clear.

rule:
  match:
   - condition: "l.size() > 10"
     output: "l[0] / 2"

   - output: "l[?0]"

If the output type of optional is better supported to make sure it's used directly instead of getting wrapped into another optional value, then I think the output type doesn't need to change, just the inspection of the output type by the rule composer. Currently, the composer gets unhappy when there's not type agreement between the output expressions.

TristonianJones commented 1 month ago

On second though, the optional return value from within these kinds of policies is a little tricky given that the rule composition step will use optional to represent an optional return from policy.

rule:
  match:
    - condition: "l.size() > 10"
      output: "l[0] / 2"
    - condition: "l.size() != 0"
      output: "l[0]"

I know it's a bit of a pain, but the above indicates there will be no output in some cases, so I think what exists is probably OK for now.