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: 截屏2021-08-04 上午11 12 56 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: 截屏2021-08-05 上午10 25 54 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)

Most upvoted comments

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 from nop.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.