Building WASM Filters in AssemblyScript
In this tutorial we will write an Envoy filter in AssemblyScript and build it using wasme
.
Creating an AssemblyScript WASM module
Refer to the installation guide for installing wasme
, the WebAssembly Hub CLI.
Let’s create a new filter called assemblyscript-filter
:
wasme init assemblyscript-filter
You’ll be asked with an interactive prompt which language platform you are building for. At time of writing, the AssemblyScript Filter base is compatible with both Istio 1.5.x and Gloo 1.3.x:
? What language do you wish to use for the filter:
cpp
▸ assemblyscript
? With which platforms do you wish to use the filter?:
▸ gloo:1.3.x, istio:1.5.x
INFO[0014] extracting 1973 bytes to /Users/ilackarms/go/src/github.com/solo-io/wasm/assemblyscript-filter
The init
command will place our base filter into the assemblyscript-filter
directory:
cd assemblyscript-filter
tree .
.
├── assembly
│ ├── index.ts
│ └── tsconfig.json
├── package-lock.json
├── package.json
└── runtime-config.json
The runtime-config.json
file present in WASM filter modules is required by wasme
to build the filter.
At least must one valid root_id
matching the WASM Filter must be present in the rootIds
field.
Open this project in your favorite IDE. The source code is AssemblyScript (a subset of Typescript) and we’ll make some changes to customize our new filter.
Making changes to the base filter
The new directory contains all files necessary to build and deploy a WASM filter with wasme
. A brief description of each file is found below:
File | Description |
---|---|
assembly/index.ts |
The source code for the filter, written in AssemblyScript. |
assembly/tsconfig.json |
Typescript config file (AssemblyScript is a subset of Typescript). |
package.json |
Used by to import npm modules during build time. |
package-lock.json |
Locked npm modules. |
runtime-config.json |
Config stored with the filter image used to load the filter at runtime. |
Open assembly/index.ts
in your favorite text editor. The source code is AssemblyScript and we’ll make some changes to customize our new filter.
Navigate to the onResponseHeaders
method defined near the top of the file. Let’s add a new header that we can use to verify our module was executed correctly (later down in the tutorial). Let’s add a new response header hello: world!
:
stream_context.headers.response.add("hello", "world!");
Your method should look like this:
onResponseHeaders(a: u32): FilterHeadersStatusValues {
// add the hello: world! response header
stream_context.headers.response.add("hello", "world!");
// continue execution of the filter chain
return FilterHeadersStatusValues.Continue;
}
Building the filter
Now, let’s build a WASM image from our filter with wasme
. The filter will be tagged and stored in a local registry, similar to how Docker stores images.
Images tagged with wasme
have the following format:
<registry address>/<registry username|org>/<image name>:<version tag>
-
<registry address>
specifies the address of the remote OCI registry where the image will be pushed by thewasme push
command. The project authors maintain a free public registry atwebassemblyhub.io
. -
<registry username|org>
either your username for the remote OCI registry, or a valid org name with which you are registered.
See the wasme push
documentation for instructions on pushing filters built with wasme
.
In this example we’ll include the registry address webassemblyhub.io
so our image can be pushed to the remote registry, along with GitHub username which will be used to authenticate to the registry.
Build and tag our image like so:
wasme build assemblyscript -t webassemblyhub.io/$YOUR_USERNAME/add-header:v0.1 .
wasme build
runs a build container inside of Docker which may run into issues due to SELinux (on Linux environments). To disable, run sudo setenforce 0
The module will take up to a few minutes to build. In the background, wasme
has launched a Docker container to run the necessary
build steps.
When the build has finished, you’ll be able to see the image with wasme list
:
wasme list
NAME SHA UPDATED SIZE TAGS
webassemblyhub.io/ilackarms/add-header bbfdf674 26 Jan 20 10:45 EST 1.0 MB v0.1
Next Steps
Now that we’ve successfully built our image, we can try running it locally or pushing it to a remote registry so it can be pulled and deployed in a Kubernetes environment.