Wasm Builders

Cover image for Add Wasm plugins to your GoLang CLI with Sat 🚀
Philippe Charrière
Philippe Charrière

Posted on

Add Wasm plugins to your GoLang CLI with Sat 🚀

Since release v0.1.4, Sat is no longer just a "tiny WebAssembly edge compute server"; you can also use it as a Go library.

This new feature means that now you can execute the Runnables ("supercharged" wasm functions) directly in your Go programs!

This new feature brings many possibilities (use cases). The first one I thought of was the possibility of offering plugins (secured by default) for my future applications.

Let me show you this with a straightforward example:

First, let's create two Rust Runnables with the Subo CLI:

subo create runnable hello
subo create runnable morgen
Enter fullscreen mode Exit fullscreen mode

about the Subo CLI

And for each of them, let's change the code of the Runnable interface (look at the lib.rs file):

📝 hello/src/lib.rs

impl Runnable for Hello {
  fn run(&self, input: Vec<u8>) -> Result<Vec<u8>, RunErr> {
      let in_string = String::from_utf8(input).unwrap();

      Ok(String::from(format!("👋 Hello world {} 🌍", in_string)).as_bytes().to_vec())
  }
}
Enter fullscreen mode Exit fullscreen mode

📝 morgen/src/lib.rs

impl Runnable for Morgen {
  fn run(&self, input: Vec<u8>) -> Result<Vec<u8>, RunErr> {
      let in_string = String::from_utf8(input).unwrap();

      Ok(String::from(format!("👋 Hallo Welt {} 🌍", in_string)).as_bytes().to_vec())
  }
}
Enter fullscreen mode Exit fullscreen mode

Now compile the two Runnables and copy them to a plugins directory:

subo build hello
cp hello/hello.wasm plugins/hello.wasm 
subo build morgen
cp morgen/morgen.wasm plugins/morgen.wasm
Enter fullscreen mode Exit fullscreen mode

So, let's create the main code for our CLI that will execute the Runnables:

Create a go.mod file:

module wasm-builders/sat-cli

go 1.18
Enter fullscreen mode Exit fullscreen mode

Create a main.go file:

package main

import (
  "fmt"
  "log"
  "os"
  "strings"
  // 1️⃣
  "github.com/suborbital/sat/sat"
)

func main() {

  argsWithoutCaller := os.Args[1:]
  wasmModulePath := "plugins/" + argsWithoutCaller[0] + ".wasm"
  wasmModuleParameters := argsWithoutCaller[1:]

  // 2️⃣
  wasmModuleConfig, _ := sat.ConfigFromRunnableArg(wasmModulePath)
  // 3️⃣
  satFunction, _ := sat.New(wasmModuleConfig, nil)
  // 4️⃣
  result, err := satFunction.Exec([]byte(strings.Join(wasmModuleParameters, ";")))
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println(string(result.Output))

}
Enter fullscreen mode Exit fullscreen mode
  • 1️⃣ import the sat package
  • 2️⃣ create a sat.Congigobject. 🖐️ The path of the module will be build like this: "plugins/" + name_of_the_wasm_module + ".wasm"
  • 3️⃣ create a new instance of Sat
  • 4️⃣ execute the Runnable function (I joined the parameters array into a string separated by ";", but you can do what you want)

Now, build the CLI: go build.

Using our new CLI is very simple:

Run the CLI with the name of the wasm module as the first parameter

go build
./sat-cli hello Bob
# resutl: 👋 Hello world Bob 🌍
./sat-cli morgen Bob
# result: 👋 Hallo Welt Bob 🌍
Enter fullscreen mode Exit fullscreen mode

Look at the sample project https://github.com/wasm-builders/sat-cli or click on the below button to open it directly in Gitpod: Open in Gitpod.

We saw that it became easier and easier to include Wasm in our Go programs using Sat.
👀 Stay tuned for an upcoming article on Sat.

Photo by SpaceX on Unsplash

Discussion (0)