opa
opa copied to clipboard
Incremental definition of function output
What is the underlying problem you're trying to solve?
I have an OPA policy that applies a per-item policy to a large collection of input.
What I would like to do is something like this
item(i) contains "a is 1" if {
i.a == 1
}
item(i) contains "b is 1" if {
i.b == 1
}
However, this is not allowed. It's possible to write the similar rules
item(i) := ["a is 1"] if {
i.a == 1
}
item(i) := ["b is 1"] if {
i.b == 1
}
but these rules are not the same. If both a and b are 1, instead of yielding ["a is 1", "b is 1"], an eval_conflict_error occurs.
Describe the ideal solution
Functions should be able to contribute to a set the same as regular rules.
Describe a "Good Enough" solution
I found a workaround:
item_workaround contains ["a is 1"] if {
input.item.a == 1
}
item_workaround contains ["b is 1"] if {
input.item.b == 1
}
This can be called using item_workaround with input.item as …. However, there is a performance problem (#5802) when there is a large number of items. If there's some other way to accomplish it that would also be fine.
Additional Context
# example.rego
package example
import future.keywords
item(i) := ["a is 1"] if {
i.a == 1
}
item(i) := ["b is 1"] if {
i.b == 1
}
item_workaround contains ["a is 1"] if {
input.item.a == 1
}
item_workaround contains ["b is 1"] if {
input.item.b == 1
}
# example_test.rego
package example
import future.keywords
test_item_a {
item({"a": 1, "b": 0})
}
test_item_b {
item({"a": 0, "b": 1})
}
test_item_both {
# errors
item({"a": 1, "b": 1})
}
test_item_neither {
not item({"a": 0, "b": 0})
}
test_item_workaround_a {
item_workaround with input.item as {"a": 1, "b": 0}
}
test_item_workaround_b {
item_workaround with input.item as {"a": 0, "b": 1}
}
test_item_workaround_both {
item_workaround with input.item as {"a": 1, "b": 1}
}
test_item_workaround_neither {
result = item_workaround with input.item as {"a": 0, "b": 0}
count(result) == 0
}
Agreed, I would also find this useful in some cases.
This issue has been automatically marked as inactive because it has not had any activity in the last 30 days.
I think in current OPA it's usually possible to get close enough.
All the parameters to item() need to be enumerable. Then the rules can be written as:
item[i] contains "a is 1" if {
some i in input.items
item.a == 1
}
item[i] contains "b is 1" if {
some i in input.items
item.b == 1
}
using a list rule that materializes the results of evaluating the function as indexable data rather than the result of a function call.
This doesn't use with so it shouldn't be affected by the same performance problem as the previous workaround.
This issue has been automatically marked as inactive because it has not had any activity in the last 30 days. Although currently inactive, the issue could still be considered and actively worked on in the future. More details about the use-case this issue attempts to address, the value provided by completing it or possible solutions to resolve it would help to prioritize the issue.