open-policy-agent / opa

Open Policy Agent (OPA) is an open source, general-purpose policy engine.
https://www.openpolicyagent.org
Apache License 2.0
9.3k stars 1.29k forks source link

fmt: running with `--rego-v1` produced unparseable file #6833

Open anderseknert opened 4 days ago

anderseknert commented 4 days ago

I'm helping a project modernizing their policies, and to prepare them for OPA 1.0. Running opa fmt --rego-v1 on one of their policies resulted in output that opa check later rejected as unparseable. Minimal example to reproduce:

original.rego

package policy

is_array(arr, _) = path {
    not contains(arr, "_")
    path = arr
}

contains(arr, elem) {
    arr[_] = elem
}

formatted.rego

package policy

import rego.v1

is_array(arr, _) := path if {
    not contains(arr, "_")
    path = arr
}

contains(arr, elem) if {
    arr[_] = elem
}

This looks valid, or at least it does to me... but opa check disagrees. If I had to guess, perhaps using contains as a custom function name would be the culprit (and maybe it is), but the error message leaves more questions than it answers:

$ opa check  .
1 error occurred during loading: policy.rego:10: rego_parse_error: unexpected if keyword
    contains(arr, elem) if {
                        ^

That's... not right. Removing the is_array function above resolves the issue, so presumably there's some weird state kept from parsing that? Both function parses fine in isolation though.

Some thoughts:

  1. Why is this a parser error?
  2. Why is the if reported as unexpected?
  3. Should it be possible to name a custom function contains in Rego v1?
  4. Should opa fmt --rego-v1 perhaps do a parse validation of its output to ensure it's valid? I would prefer it if that tool said "can't convert this because of ..." than having it say nothing and discover the issue later.