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.67k stars 1.34k forks source link

Chained function calls fail in WebAssembly build #5590

Open robertgartman opened 1 year ago

robertgartman commented 1 year ago

Short description

Nested function calls works with opa eval but fails with opa build -t wasm

Output from opa version:

Version: 0.48.0
Build Commit:
Build Timestamp:
Build Hostname:
Go Version: go1.19.4
Platform: darwin/arm64
WebAssembly: unavailable

Steps To Reproduce

Save file as test.rego

# METADATA
# entrypoint: true
package test

import future.keywords

inner(txt) := res if {
    res := concat(" ", [txt, "indeed!"])
}

outer(txt) := res if {
    res := inner(txt)
}

rule := outer("works")

Running: opa eval -d test.rego 'data.test.rule' works fine, with output:

{
  "result": [
    {
      "expressions": [
        {
          "value": "works indeed!",
          "text": "data.test.rule",
          "location": {
            "row": 1,
            "col": 1
          }
        }
      ]
    }
  ]
}

Running opa build -t wasm test.rego -o /tmp/bundle.tar.gz fails, with output

error: 1 error occurred: test.rego:3: rego_type_error: undefined ref: data.test.outer
    data.test.outer
    ^^^^^^^^^^^^^^^
    have: (string) => string

Expected behavior

wasm build should work

anderseknert commented 1 year ago

Hi Robert! And thanks for yet another great report. I believe this very issue was the original cause for the addition of the --prune-unused flag provided for opa build, and using that seems like it would solve your issue too. See the original issue and discussion over here.

It would definitely be an improvement if the error message could hint at that, but I'm not sure if this condition is easy to detect. I believe @johanfylling is working on code and docs close to this topic, so he might be able to tell us more.

robertgartman commented 1 year ago

@anderseknert noted! The --prune-unused solves the issue. Re-reading the docs on --prune-unused does not reveal why. Even if @johanfylling will fill the gaps in the docs there is still a considerable risk that users will miss that part. Could it even be an option to make --prune-unused the default behaviour? Or as a workaround, if the build ends in error then have the build re-run with --prune-unused´enabled. If the re-run succeeds the user could be informed about the flag and the consequences.

johanfylling commented 1 year ago

Documentation around when to use, and when not to use, the --prune-unused flag is pretty sparse at the moment, and clearly needs some TLC. I'm looking into if the default behavior can be changed, but this might cause more issues than it solves; in which case we should attempt doing something about the error message to provide more context and a nudge in the right direction.

stale[bot] commented 1 year ago

This issue has been automatically marked as inactive because it has not had any activity in the last 30 days.