opa: opa-wasm compile error
Describe the bug
A compile bug related with opa.OPA
struct initialization.
A clear and concise description of what the bug is
I tried to use this SDK to realize a simple policy center but to find a very strange compile error:
/usr/local/Cellar/go/1.16.5/libexec/pkg/tool/darwin_amd64/link:
running clang failed: exit status 1 Undefined symbols for architecture x86_64:
"_wasi_config_arg", referenced from:
__cgo_cbbfd67d0eb3_Cfunc_wasi_config_arg in 000042.o
(maybe you meant: __cgo_cbbfd67d0eb3_Cfunc_wasi_config_arg)
"_wasi_config_capture_stderr", referenced from:
__cgo_cbbfd67d0eb3_Cfunc_wasi_config_capture_stderr in 000042.o
(maybe you meant: __cgo_cbbfd67d0eb3_Cfunc_wasi_config_capture_stderr)
... errors like the above...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
After debug I found this error is related with the reference of opa.OPA
in different packages. However, I failed to reproduce this error in a new project.
Steps to reproduce
The followings are probably the codes that trigger the error.
I wrote the policycenter.go
to realize a rules:
package policycenter
import (
"context"
"encoding/json"
"fmt"
"github.com/open-policy-agent/golang-opa-wasm/opa"
)
type PolicyCenter interface {
Eval(entity *PolicyEntity, rego *opa.OPA) (*Result, error)
}
type Result struct {
Result interface{}
}
type PolicyEntity struct {
ctx context.Context
PolicyName string
InputQuery interface{}
}
func NewPolicyEntity(ctx context.Context, policyName string, inputQuery interface{}) *PolicyEntity {
return &PolicyEntity{
ctx: ctx,
PolicyName: policyName,
InputQuery: inputQuery,
}
}
func Eval(entity *PolicyEntity, rego *opa.OPA) (*Result, error) {
result, err := rego.Eval(entity.ctx, &entity.InputQuery)
if err != nil {
return nil, err
}
return &Result{result.Result}, nil
}
Then I wrote a main function in different packages and execute to check if it works:
package main
import (
"goplayground/pkg/policycenter"
"context"
"fmt"
"github.com/open-policy-agent/golang-opa-wasm/opa"
"io/ioutil"
)
func main() {
input := map[string]interface{}{"Field1": "false", "Field2": "true"}
wasmBytes, err := ioutil.ReadFile("policy.wasm")
if err != nil {
fmt.Printf("error: %v", err)
return
}
rego, err := opa.New().WithPolicyBytes(wasmBytes).Init()
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
defer rego.Close()
ctx := context.Background()
entity := policycenter.NewPolicyEntity(
ctx, "PA", input)
result, _ := policycenter.Eval(entity, rego)
res := result.Result.([]interface{})[0].(map[string]interface{})["result"].(string)
fmt.Println(res)
}
Then the error occuered:
I found out that I cannot declare
*opa.OPA
and policycenter.go
at the same time in the main function I wrote above, if I only init opa.OPA
or something in policycenter.go
, the error won’t occur.
Here is the example error occurring:
func main() {
wasmBytes, _ := ioutil.ReadFile("policy.wasm")
rego, _ := opa.New().WithPolicyBytes(wasmBytes).Init()
defer rego.Close()
}
func launchEval(rego *opa.OPA, entity *policycenter.PolicyEntity) {
result, err := policycenter.Eval(entity, rego)
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
res := result.Result.([]interface{})[0].(map[string]interface{})["result"].(string)
fmt.Println(res)
}
If I delete anything related with policycenter
, the error will disappear.
Additional context
I wrote a policycenter_test.go
in the same package of policycenter.go
and it works well, it seems this compile error is related with opa.OPA reference and declaration in different packages. Here is the code:
package policycenter
import (
"context"
"fmt"
"github.com/open-policy-agent/golang-opa-wasm/opa"
"io/ioutil"
"reflect"
"sync"
"testing"
)
var(
cases = []interface{}{map[string]interface{}{"Fields1": "false", "Fields2": "true"},
map[string]interface{}{"Fields1": "true", "Fields2": "true"},
map[string]interface{}{"Fields1": "false", "Fields2": "false"},
}
ctx = context.Background()
entity0 = NewPolicyEntity(ctx, "Policy", cases[0])
entity1 = NewPolicyEntity(ctx, "Policy, cases[1])
entity2 = NewPolicyEntity(ctx, "Policy", cases[2])
input = []*PolicyEntity{entity0, entity1, entity2}
)
func TestEval(t *testing.T) {
var
wasmBytes, err := ioutil.ReadFile("../../policy.wasm")
if err != nil {
fmt.Printf("error: %v", err)
return
}
rego, err := opa.New().WithPolicyBytes(wasmBytes).Init()
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
defer rego.Close()
var wg sync.WaitGroup
wg.Add(100)
for i := 0; i < 100; i++ {
go func() {
t := i % 3
launchEval(t, rego, input[t])
wg.Done()
}()
}
wg.Wait()
}
func launchEval(flag int, rego *opa.OPA, entity *PolicyEntity) {
result, err := Eval(entity, rego)
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
res := result.Result.([]interface{})[0].(map[string]interface{})["result"].(string)
switch flag {
case 0:
if res != "1P" {
fmt.Println("failure occurs, expected 1P while get" + res)
}
case 1:
if res != "2P" {
fmt.Println("failure occurs, expected 2P while get" + res)
}
case 2:
if res != "3P" {
fmt.Println("failure occurs, expected 3P while get" + res)
}
}
}
and the test passed:
this complie error confuses me a lot, why this error occurs?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 27 (14 by maintainers)
Though the compile error still confuses me, it is enough for this issue, thanks srenatus.
That works! I found the
OPA
used in this workflow is referenced fromnop.go
, that is the reason why this error occurred. Thanks srenatus!OK so that binary looks OK. The build hostname is not a confidential property, it’s the same for me, it’s where the binary was built (some github actions’ runner).
Back one step, what did you do or run that got you this error message? https://github.com/open-policy-agent/opa/issues/3707#issuecomment-894088369
Sorry this was meant as a hint what to do 😅 But I’ll try to play with this a bit tomorrow anyways.
Oh sorry I must have misunderstood you earlier. To generate Wasm modules from your Rego policies, you don’t need the golang-opa-wasm sdk; it’ll work out of the box with
opa
,opa build -t wasm
, and the wasm file will be in that bundle. You can use that file with any Wasm engine available to your host language.