feat: with wasm executor

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-08-28 21:13:50 +02:00
parent 541b9b22d2
commit dd80ebb577
Signed by: kjuulh
GPG Key ID: 9AA7BC13CE474394
11 changed files with 1320 additions and 130 deletions

1336
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["crates/*"] members = ["crates/*", "examples/*"]
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
@ -32,6 +32,6 @@ serde_json = "1"
reqwest = {version = "0.11.20", features = ["json"]} reqwest = {version = "0.11.20", features = ["json"]}
uuid = {version = "1.4.1", features = ["v4", "serde"]} uuid = {version = "1.4.1", features = ["v4", "serde"]}
itertools = {version = "0.11.0"} itertools = {version = "0.11.0"}
sled = "0.34.7" sled = "0.34.7"
chrono = {version = "0.4.26", features = ["serde"]} chrono = {version = "0.4.26", features = ["serde"]}
wasmtime = "12.0.1"

12
adapt.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
crate=$1
cargo build -p "$crate" --target wasm32-wasi --release
crate_target=$(echo $crate | sed "s/-/_/g")
#wasm-tools component new ./target/wasm32-wasi/debug/$crate_target.wasm \
# -o $crate_target.wasm #--adapt ./includes/wasi_snapshot_preview1.wasm

View File

@ -7,8 +7,6 @@ version= "0.1.0"
edition.workspace = true edition.workspace = true
publish.workspace = true publish.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
churn-domain.workspace = true churn-domain.workspace = true
@ -22,3 +20,4 @@ axum.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
reqwest.workspace = true reqwest.workspace = true
wasmtime.workspace = true

View File

@ -1,6 +1,6 @@
mod agent; mod agent;
use std::net::SocketAddr; use std::{net::SocketAddr, path::PathBuf};
use agent::AgentService; use agent::AgentService;
use anyhow::Error; use anyhow::Error;
@ -14,6 +14,7 @@ use axum::{
use churn_domain::AgentEnrollReq; use churn_domain::AgentEnrollReq;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use serde_json::json; use serde_json::json;
use wasmtime::{Caller, Engine, Linker, Module, Store};
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = None, subcommand_required = true)] #[command(author, version, about, long_about = None, subcommand_required = true)]
@ -40,6 +41,19 @@ enum Commands {
#[arg(env = "CHURN_TOKEN", long)] #[arg(env = "CHURN_TOKEN", long)]
token: String, token: String,
}, },
Execute {
#[arg(env = "CHURN_AGENT_EXE", long)]
exe: PathBuf,
#[command(subcommand)]
commands: Option<ExecuteCommands>,
},
}
#[derive(Subcommand)]
enum ExecuteCommands {
Source,
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
@ -60,8 +74,8 @@ async fn main() -> anyhow::Result<()> {
} }
async fn handle_command(cmd: Command) -> anyhow::Result<()> { async fn handle_command(cmd: Command) -> anyhow::Result<()> {
match cmd.command { match cmd.command.unwrap() {
Some(Commands::Daemon { host }) => { Commands::Daemon { host } => {
tracing::info!("Starting churn server"); tracing::info!("Starting churn server");
let app = Router::new() let app = Router::new()
@ -77,12 +91,38 @@ async fn handle_command(cmd: Command) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
Some(Commands::Connect { Commands::Connect {
host: _, host: _,
token: _, token: _,
agent_name: _, agent_name: _,
}) => todo!(), } => todo!(),
None => todo!(), Commands::Execute { exe, commands } => match commands {
Some(ExecuteCommands::Source) => Ok(()),
None => {
let engine = Engine::default();
let module = Module::from_file(&engine, exe)?;
// Create a `Linker` which will be later used to instantiate this module.
// Host functionality is defined by name within the `Linker`.
let mut linker = Linker::new(&engine);
linker.func_wrap("print", "print", |caller: Caller<'_, u32>, param: i32| {
println!("Got {} from WebAssembly", param);
println!("my host state is: {}", caller.data());
})?;
// All wasm objects operate within the context of a "store". Each
// `Store` has a type parameter to store host-specific data, which in
// this case we're using `4` for.
let mut store = Store::new(&engine, 4);
let instance = linker.instantiate(&mut store, &module)?;
let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?;
// And finally we can call the wasm!
hello.call(&mut store, ())?;
Ok(())
}
},
} }
} }

View File

@ -105,7 +105,7 @@ async fn build_container(
client: Arc<Query>, client: Arc<Query>,
bin_name: &str, bin_name: &str,
) -> eyre::Result<dagger_sdk::Container> { ) -> eyre::Result<dagger_sdk::Container> {
let crates = &["crates/*", "ci"]; let crates = &["crates/*", "ci", "examples/*"];
let debian_deps = &[ let debian_deps = &[
"libssl-dev", "libssl-dev",
"pkg-config", "pkg-config",

View File

@ -0,0 +1,2 @@
[build]
target = "wasm32-wasi"

View File

@ -0,0 +1,15 @@
[package]
name = "agent-ping"
repository.workspace = true
description.workspace = true
readme.workspace = true
license-file.workspace = true
authors.workspace = true
version.workspace = true
edition.workspace = true
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", tag = "wit-bindgen-0.10.0" }

View File

@ -0,0 +1,15 @@
wit_bindgen::generate!({
world: "host",
exports: {
world: MyHost,
},
});
struct MyHost;
impl Host for MyHost {
fn run() {
print("Hello, world!");
}
}

View File

@ -0,0 +1,7 @@
package example:host
world host {
import print: func(msg: string)
export run: func()
}

Binary file not shown.