Adding string interpolation support to the Rego language.
An interpolated string is composed of a template-string that can contain zero or more template-expressions that interpolates values into the string generated at eval-time.
Requires the `template_strings` capability feature and `internal.template_string` built-in function.
Implements: #4733
And update code to conform to the rule.
- Replace unnecessary fmt.Sprintf with string concatenation
- Replace fmt.Sprint with more efficient strconv.Itoa
- Replace static fmt.Errorf calls with more efficient errors.New
Thanks @srenatus for pushing me down this rabbit hole!
Signed-off-by: Anders Eknert <anders@styra.com>
The previous version has been failing without any good reason for me,
so let's try this.
About the version pick: It's not the latest version (v1.62.0 at the
moment), because that would introduce a new revive rule,
redeclares-builtin-id, and that flags every variable called `min` or
`max` in the code base. I had started addressing these, but they were
just too many.
The new issues related to this version are mostly that it complains
whenever it finds a non-static string that makes its way into a printf-
like function. However, that's a common pattern in some place here, so
I've sprinkled some nolint:govet on it.
Signed-off-by: Stephan Renatus <stephan@styra.com>
Got a few warnings from my IDE about redundant type conversions,
so I decided to look into it. Added the unconvert linter to our
checks, and fixed the violations. Added two ignore comments as I
wasn't sure about whether they'd change the semantics of the code.
Signed-off-by: Anders Eknert <anders@eknert.com>
With the embed directive, we no longer need our custom code that predates
Go 1.16. Also, with the release of 1.19, we no longer desire compatibility
with anything predating 1.16, so this cleanup becomes possible.
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
This package is deprecated, archived, and in maintenance mode, since Go
errors support wrapping natively.
For #2152.
Signed-off-by: Jason Hall <jason@chainguard.dev>
This sets the stage for eventually allowing OPA wasm modules that do NOT
import memory.
With this change, we add the necessary segments to the wasm module that
declare that memory is to be imported, in the wasm compiler. As far as
LLVM and our C base is concerned, the memory is NOT imported.
The test runners have been adapted, `make wasm-lib-test` works without
having imported memory now. `make wasm-rego-test` can deal with both: it
will provide memory in its `imports` for instantiation, but if the wasm
module happens to not want that import, it'll be ignored. The memory used
in the other host methods is the exported one. (Whether that is exported
or re-exported imported doesn't make a difference.)
Some first steps have been included to make OPA's Wasm SDK work without
imported memory. There are a few loose ends around enforcing memory
limits, to be taken care of later.
----
This also addresses a problem we've seen in the wild before: when our
additions to the wasm modules' data segments exceed the number of pages
needed for the memory import, a "data segment overflowing memory" issue
could have happened. That was because the minimal memory size for the
imported memory was determined by LLVM, and we'd just squeeze our added
data segments in, without adjusting that limit.
Now, the limit will be set properly; and if a too small memory was
provided, a more descriptive failure will happen at instantiation time.
Wasmtime, for example, raises
incompatible import type for `env::memory`
Caused by:
memory types incompatible
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
golint is deprecated. The author of the code no longer supports the
codebase. golangci-lint is faster than golint, and is in use by other
opa repositories (e.g. Gatekeeper).
This commit changes tools.go to reference golangci (so it ends up in
vendor) and modifies check-lint to use golangci instead.
Breaking API Changes:
- plugins/rest/rest.go: Fix typo "AllowInsureTLS" -> "AllowInsecureTLS"
- storage/errors.go: Removed unused IndexingNotSupportedErr
Signed-off-by: Will Beason <willbeason@google.com>
* wasm: optimize package access with non-ground refs using call_indrect
We now
1. write an object corresponding to data paths into the module data
2. initialize an opa_object_t from that using `_initialize`, called
as the module's Start function
3. write out CallDynamicStmts in IR when the ref is not all ground,
but its vars have been seen
4. compile those CallDynamicStmts to call_indirect invocations in
WASM, preceded by a lookup using the path in the object prepared
in (2.)
5. if the lookup fails to come up with a result, the eval goes
undefined
What it looks like:
With t.rego as
package t
p {
data.foo[input.x].bar.p
}
and foo.rego as
package foo.a.bar
p = true
when building policy.wasm using `opa build -t wasm -e t/p t.rego foo.rego`,
the body of function `g0.data.t.p` will contain
i32.const 5
call $opa_array_with_cap
local.set $11
local.get $11
local.get $7
call $opa_array_append
local.get $11
local.get $8
call $opa_array_append
local.get $11
local.get $6
call $opa_array_append
local.get $11
local.get $9
call $opa_array_append
local.get $11
local.get $10
call $opa_array_append
local.get $0
local.get $1
local.get $11
call $opa_mapping_lookup
local.tee $12
i32.eqz
br_if $block
local.get $12
call_indirect $29 (type $1)
local.tee $13
i32.eqz
br_if $block
Where the array-related functions build an array of
["g0", "foo", input.x, "bar", "p"]
and pass that to `opa_mapping_lookup` to determine the element index to
pass to `call_indirect`. The lookup function returns 74 from the JSON
blob put into the data section,
(data $38 (i32.const 56485)
"{\"g0\": {\"foo\": {\"a\": {\"bar\": {\"p\": 74}}}, \"t\": {\"p\": 75}}}")
iff input.x happens to be "a". Otherwise, it'll return 0, and the result
will end up being undefined.
Element 74 of the modules func table is, of course, $g0.data.foo.a.bar.p:
(elem $33 (i32.const 74)
$g0.data.foo.a.bar.p $g0.data.t.p)
($33 is some id of that piece of function table, an artifact of the
`wavm disassemble` output.)
* compiler/wasm: add memoization to call_indirect logic
- adds a data segment for mapping element indices (used with call_indirect)
to function indices (as used with opa_memoize_{get,insert})
- emits mapping function elem -> func idx that uses that data segment
- wires up memoization lookup and insert in call_indirect code path
The added test case would cause `make wasm-rego-test` to fail like this
if memoization wasn't happening:
ERROR 019_call_indirect_optimization.json: memoization: should have been memoized
* planner: add debug messages, carry them over into the compiler
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
* wasm: read/write custom sections (incl. dwarf)
I've extended the roundtrip OPA test to have some assertions
on custom sections that work for both debug and non-debug
wasm builds.
Without debugging enabled, we had still been stripping the
`names` and `producers` sections. This changes therefore
increases the size of wasm modules. For a simple policy,
package test
default allow = false
allow {
input.foo == "bar"
}
the size generated is 544K (master) vs 620K (this commit).
With debugging enabled (and the opa binary rebuilt), the
size becomes 6.1M.
* wasm/encoding: treat 'name' custom section separately
This roundtrips module, functions, and locals, as per
https://webassembly.github.io/spec/core/appendix/custom.html#name-section
There is currently no use of module and locals, afaict.
* compiler/wasm: record function names in 'name' custom section
Quality-of-life improvement when dealing with our generated WASM
code.
Before:
local.get 2
local.get 3
call 1172
local.set 6
After:
local.get 2
local.get 3
call $g0.data.foo.p
local.set 6
Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
These sections are required so that we can statically link the policy
and the OPA-WASM library together.
Also, add test case that roundtrips the OPA module for sanity.
Signed-off-by: Torin Sandall <torinsandall@gmail.com>
These changes implement a basic WASM compiler backend for the IR added
in the previous commit. These changes also include a binary-encoding
package that can roundtrip simple WASM modules.
Signed-off-by: Torin Sandall <torinsandall@gmail.com>