Announcing Spin 2.6
Mikkel Mørk Hegnhøj
spin
webassembly
wasi
component model
release
wasmtime
Today we’re happy to announce the release of Spin 2.6, which includes several enhancements to Spin.
In this blog post, we’ll dive into a few features of this release, which center around experimenting with WebAssembly Components, WASI 0.2.0, and registries.
If you want to skip ahead to the official Release Notes, you can find them here.
Experimenting With WebAssembly Components, WASI 0.2.0, and Registries
Since Spin 2.2, we’ve supported WASI 0.2.0. Building on what the Component Model allows us to do with building applications, we’ve started experimenting with various ways of using components with Spin. In this release, two features were added for this purpose.
The first one is the ability to run a WASI-HTTP incoming-handler component without having to provide a Spin application’s manifest (spin.toml
).
Building a WASI-HTTP component typically relies on WIT bindings being generated by wit-bindgen. However, with most programming languages it is not easy or intuitive to write directly against the bindings. The SDKs provided as part of the Spin project is an easy way to write these components, as Spin SDKs generate WASI-HTTP compliant components.
It may seem a bit silly to use the Spin SDKs and not the Spin app model (through the Spin app manifest spin.toml
), but bear with us for now. In future releases of Spin, there are plans to help you define what WIT worlds you’re targeting when writing applications and whether the dependencies you are using are supported within those worlds. See this SIP PR for more info. As that SIP PR illustrates, we want to make it easy to write components using Spin, regardless of whether you’re using the full set of features provided by the Spin framework, like Spin-as-a-CLI, SpinKube, Fermyon Platform for Kubernetes, or Fermyon Cloud.
Building a WASI-HTTP Component Using the Rust Spin SDK
Let’s have a look at how we can build a WASI-HTTP component, using the Spin Rust SDK.
You’ll need the Rust tool chain for building wasm32-wasi components - i.e., rustup target install wasm32-wasi
First, create the Rust project and add the required dependencies (crates):
# Create a new Rust library
cargo new --lib wasi-http
cd wasi-http/
# Add the Spin SDK and anyhow crates
cargo add spin-sdk
cargo add anyhow
Next, we’ll implement the handler in src/lib.rs
. You can use the below code for this:
// Import libraries
use spin_sdk::http::{Request, Response, IntoResponse};
use spin_sdk::http_component;
// The Spin SDK macro to turn this into a WASI-HTTP incoming-handler
#[http_component]
async fn handle_hello_rust(_req: Request) -> anyhow::Result<impl IntoResponse> {
// Return a simple http response
Ok(Response::builder()
.status(200)
.header("content-type", "text/plain")
.body("Hello, Fermyon")
.build())
}
This code will produce an incoming-handler, which conforms with wasi:http/proxy@0.2.0
.
We also need to ensure the library gets compiled as a dynamic system library, as this is required to produce a WebAssembly component. This we do by adding the following to Cargo.toml
:
[lib]
crate-type = [ "cdylib" ]
Then we can build the component, and run it using Spin:
cargo build --target wasm32-wasi
spin up -f target/wasm32-wasi/debug/wasi-http.wasm
You can now go ahead and call the endpoint, being served by Spin.
Here is a list of other examples to build wasi:http/proxy components, for you to go explore:
Referencing Components in a Registry
We believe that using existing infrastructure and technology to distribute and run Spin applications, creates a lot less friction for you to start getting to the benefits of using WebAssembly. Therefore, we’ve also added a feature to Spin, which enables you to reference WASI components as packages, to be loaded from OCI-compliant registries.
Let us walk through an example of packaging out WASI-HTTP component from above, push it to a registry, and reference it from a Spin manifest (spin.toml
).
Please note that this is highly experimental, and that the tools you’ll use are under development, and may change at any time.
In this example we’ll be using the Oras CLI to push our component.
The following command will take the component hello_wasi.wasm
and make it available at ttl.sh
using the namespace and package name mikkelhegn:my-wasi
with version 0.0.1
. Note that both namespace and package names are required. Also, the version can only be a valid semantic version:
oras push ttl.sh/mikkelhegn/my-wasi:0.0.1 hello_wasi.wasm:application/wasm
Note: The spin registry push
command will also create a valid WASM OCI package, but it currently requires a spin.toml
file present to be able to push the component.
Spin 2.6.0 will resolve the location of the package using wasm-pkg-tools, which relies on a registry configuration file in ~/.config/wasm-pkg/config.toml
.
Let’s go ahead and create that configuration file, and using ttl.sh as the registry:
default_registry = "ttl.sh"
[registry."ttl.sh"]
type = "oci"
[registry."ttl.sh".oci]
protocol = "https"
Now create an empty Spin application:
spin new -t http-empty
Then add the component to spin.toml
:
[[trigger.http]]
route = "/..."
component = "wasihttp"
[component.wasihttp]
source = { registry = "ttl.sh", package = "mikkelhegn:my-wasi", version = "0.0.1" }
And we can now run the Spin application:
spin up
That’s it!
Remember this is still an experimental feature, based on the maturity in the tool chain involved in pushing and pulling WASM Component packages to/from registries. However we’d love feedback on how this feature could be used, and also hope this early implementation inspires you to engage in the upstream work to make the tools as good as you want them.
Introducing Conformance Tests For Spin
As Spin applications are able to run in multiple runtime implementations: Spin-as-a-CLI, SpinKube, Fermyon Platform for Kubernetes, or Fermyon Cloud, we’ve started a project to ensure conformance across those implementations, and most importantly, to ensure Spin applications work the same way in all those places. You can read more about the project here.
Spin 2.6.0 is the first release of Spin to undergo a set of conformance tests. We expect the conformance to expand over time, as more tests are being added to the project.
Breaking Changes and Upcoming Deprecation
Breaking Change
- The upgrade to Wasmtime 21 includes a breaking change to how headers are handled, which means that Spin app guest modules can no longer set the Host header on outbound requests: #2575
Upcoming Deprecation
- Wasm modules compiled with wasi-sdk version < 19 are likely to contain a critical memory safety bug. Spin has deprecated execution of these modules and they will stop working in a future release. For more information, see: #2552
Thank you!
We would like to thank the over 80 contributors to the Spin project and especially our new contributor brehen. We hope to see you again soon in the commit history! Thank you to everyone in our growing community. Every comment, issue, and pull request helps us improve Spin!
A special mention goes out to the maintainers of the Bytecode Alliance projects, particularly the Wasmtime project and the developers working on WASI and the WebAssembly component model. Their work is instrumental in supporting Spin.
Stay In Touch
Ensure to join our weekly project meetings, chat in the Fermyon Discord server and follow us on X (formerly Twitter) @fermyontech and @spinframework!