This commit adds a config for yamllint, mass-reformats all of
the existing Yaml testcases to pass linting, and adds a Yaml
linting job to the pull-request Github Actions workflow. A few
careful exceptions and ignores were added to the linter's
config to allow keeping our existing Yaml files with minimal
reformatting.
Signed-off-by: Philip Conrad <philipaconrad@gmail.com>
With func1.rego as
package test
r(x) {
data.test.q(x)
}
q(_) = true
q(_) = false
Before:
$ opa eval -fpretty -d func1.rego 'data.test.r(1)'
true
After:
$ opa eval -fpretty -d func1.rego 'data.test.r(1)'
1 error occurred: func1.rego:12: eval_conflict_error: functions must not produce multiple outputs for same inputs
Fixes#3912.
Also adds a CHANGELOG item making the backwards-compat-breaking change
prominent, and sharing an example of how to fix it.
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
There are two kinds of else conflicts in the e2e tests, and one had been failing in WASM (i.e., it didn't fail when it should).
With this change to the planner, the underlying issue is resolved:
With multiple rule bodies for one rule like this, where r1 and r2 both fail,
- r1
- else1
- r2
- else2
previously, else1 and else2 checked if the output variable used for both r1 and r2 was defined, and didn't run it was.
Topdown, however, evaluates both else1 and else2, and checks that they have the same outcome.
The output variable checking in WASM would prohibit else2 from being run when the output variable was set by else1.
Now, each rule and its else branches use an output variable different from the overall output; and an extra block writing that output variable's value into the overall output variable of that rule. The extra layering allows each else block to check its rule body's output, and not the overall rule output.
Also:
* planner+wasm: add nop stmt
Useful for debugging planner->ir->compiler->wasm action
* wasm: reuse local variable for separate function bodies+elses
* wasm-e2e: map multiple wasm errors to eval_conflict_error
* planner: fix functon errors with multiple returns (single)
For rule bodies and their else's, the AssignVarOnceStmt would be
no different from the AssignVarStmt -- since it's zeroed by the
starting ResetLocalStmt.
For function bodies involving ScanStmt, it does make a difference,
since it the AssignVarOnceStmt ends up in a its block:
| | *ir.Func g0.data.p.p (3 params: [0 1 3], 3 blocks)
| | | *ir.Block Block (3 statements)
| | | | *ir.ResetLocalStmt &{Target:4 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | | *ir.AssignVarStmt &{Source:3 Target:5 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | | *ir.ScanStmt &{Source:5 Key:6 Value:7 Block:Block (3 statements) Location:{Index:0 Col:7 Row:4 file:module-0.rego text:y = a[_]}}
| | | | | *ir.Block Block (3 statements)
| | | | | | *ir.AssignVarStmt &{Source:6 Target:8 Location:{Index:0 Col:7 Row:4 file:module-0.rego text:y = a[_]}}
| | | | | | *ir.AssignVarStmt &{Source:7 Target:9 Location:{Index:0 Col:7 Row:4 file:module-0.rego text:y = a[_]}}
|H|E|R|E|>| *ir.AssignVarOnceStmt &{Target:4 Source:9 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | *ir.Block Block (2 statements)
| | | | *ir.IsDefinedStmt &{Source:4 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | | *ir.AssignVarOnceStmt &{Target:2 Source:4 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
| | | *ir.Block Block (1 statements)
| | | | *ir.ReturnLocalStmt &{Source:2 Location:{Index:0 Col:5 Row:3 file:module-0.rego text:p(a) = y}}
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>