Compare commits
3 Commits
main
...
feat/with-
Author | SHA1 | Date | |
---|---|---|---|
9676c6aefb | |||
ac246c2d18 | |||
dd80ebb577 |
1340
Cargo.lock
generated
1340
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = ["crates/*"]
|
||||
members = ["crates/*", "examples/*"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
@ -32,6 +32,6 @@ serde_json = "1"
|
||||
reqwest = {version = "0.11.20", features = ["json"]}
|
||||
uuid = {version = "1.4.1", features = ["v4", "serde"]}
|
||||
itertools = {version = "0.11.0"}
|
||||
|
||||
sled = "0.34.7"
|
||||
chrono = {version = "0.4.26", features = ["serde"]}
|
||||
wasmtime = "12.0.1"
|
||||
|
12
adapt.sh
Executable file
12
adapt.sh
Executable 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
|
@ -7,8 +7,6 @@ version= "0.1.0"
|
||||
edition.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
churn-domain.workspace = true
|
||||
|
||||
@ -22,3 +20,4 @@ axum.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
reqwest.workspace = true
|
||||
wasmtime.workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
mod agent;
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::{net::SocketAddr, path::PathBuf};
|
||||
|
||||
use agent::AgentService;
|
||||
use anyhow::Error;
|
||||
@ -14,6 +14,7 @@ use axum::{
|
||||
use churn_domain::AgentEnrollReq;
|
||||
use clap::{Parser, Subcommand};
|
||||
use serde_json::json;
|
||||
use wasmtime::{Caller, Engine, Extern, Func, Linker, Module, Store};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None, subcommand_required = true)]
|
||||
@ -40,6 +41,19 @@ enum Commands {
|
||||
#[arg(env = "CHURN_TOKEN", long)]
|
||||
token: String,
|
||||
},
|
||||
|
||||
Execute {
|
||||
#[arg(env = "CHURN_AGENT_EXE", long)]
|
||||
exe: PathBuf,
|
||||
|
||||
#[command(subcommand)]
|
||||
commands: Option<ExecuteCommands>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum ExecuteCommands {
|
||||
Source,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@ -60,8 +74,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
async fn handle_command(cmd: Command) -> anyhow::Result<()> {
|
||||
match cmd.command {
|
||||
Some(Commands::Daemon { host }) => {
|
||||
match cmd.command.unwrap() {
|
||||
Commands::Daemon { host } => {
|
||||
tracing::info!("Starting churn server");
|
||||
|
||||
let app = Router::new()
|
||||
@ -77,12 +91,60 @@ async fn handle_command(cmd: Command) -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Some(Commands::Connect {
|
||||
Commands::Connect {
|
||||
host: _,
|
||||
token: _,
|
||||
agent_name: _,
|
||||
}) => todo!(),
|
||||
None => todo!(),
|
||||
} => todo!(),
|
||||
Commands::Execute { exe, commands } => match commands {
|
||||
Some(ExecuteCommands::Source) => Ok(()),
|
||||
None => {
|
||||
let engine = Engine::default();
|
||||
let module = Module::from_file(&engine, exe)?;
|
||||
|
||||
let mut linker = Linker::new(&engine);
|
||||
linker.func_wrap(
|
||||
"$root",
|
||||
"print",
|
||||
|mut caller: Caller<'_, ()>, ptr: i32, len: i32| {
|
||||
// Use our `caller` context to learn about the memory export of the
|
||||
// module which called this host function.
|
||||
let mem = match caller.get_export("memory") {
|
||||
Some(Extern::Memory(mem)) => mem,
|
||||
_ => panic!("failed to find host memory"),
|
||||
};
|
||||
|
||||
// Use the `ptr` and `len` values to get a subslice of the wasm-memory
|
||||
// which we'll attempt to interpret as utf-8.
|
||||
let data = mem
|
||||
.data(&caller)
|
||||
.get(ptr as u32 as usize..)
|
||||
.and_then(|arr| arr.get(..len as u32 as usize));
|
||||
let string = match data {
|
||||
Some(data) => match std::str::from_utf8(data) {
|
||||
Ok(s) => s,
|
||||
Err(_) => panic!("invalid utf-8"),
|
||||
},
|
||||
None => panic!("pointer/length out of bounds"),
|
||||
};
|
||||
|
||||
println!("Got {} from WebAssembly", string);
|
||||
},
|
||||
)?;
|
||||
|
||||
// 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, ());
|
||||
let instance = linker.instantiate(&mut store, &module)?;
|
||||
let hello = instance.get_typed_func::<(), ()>(&mut store, "run")?;
|
||||
|
||||
// And finally we can call the wasm!
|
||||
hello.call(&mut store, ())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ async fn build_container(
|
||||
client: Arc<Query>,
|
||||
bin_name: &str,
|
||||
) -> eyre::Result<dagger_sdk::Container> {
|
||||
let crates = &["crates/*", "ci"];
|
||||
let crates = &["crates/*", "ci", "examples/*"];
|
||||
let debian_deps = &[
|
||||
"libssl-dev",
|
||||
"pkg-config",
|
||||
|
2
examples/agent-ping/.cargo/config.toml
Normal file
2
examples/agent-ping/.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[build]
|
||||
target = "wasm32-wasi"
|
15
examples/agent-ping/Cargo.toml
Normal file
15
examples/agent-ping/Cargo.toml
Normal 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" }
|
15
examples/agent-ping/src/lib.rs
Normal file
15
examples/agent-ping/src/lib.rs
Normal file
@ -0,0 +1,15 @@
|
||||
wit_bindgen::generate!({
|
||||
world: "host",
|
||||
|
||||
exports: {
|
||||
world: MyHost,
|
||||
},
|
||||
});
|
||||
|
||||
struct MyHost;
|
||||
|
||||
impl Host for MyHost {
|
||||
fn run() {
|
||||
print("Hello, world!");
|
||||
}
|
||||
}
|
7
examples/agent-ping/wit/host.wit
Normal file
7
examples/agent-ping/wit/host.wit
Normal file
@ -0,0 +1,7 @@
|
||||
package example:host
|
||||
|
||||
world host {
|
||||
import print: func(msg: string)
|
||||
|
||||
export run: func()
|
||||
}
|
16
examples/example-module/Cargo.toml
Normal file
16
examples/example-module/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "example-module"
|
||||
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]
|
||||
|
||||
|
85
examples/example-module/src/lib.rs
Normal file
85
examples/example-module/src/lib.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use std::any::Any;
|
||||
|
||||
pub struct Orchestrator {}
|
||||
|
||||
impl Orchestrator {
|
||||
pub fn cron(&self, cron: impl AsRef<str>) -> Scheduler {
|
||||
Scheduler {}
|
||||
}
|
||||
|
||||
pub fn query(&self, query: Query) -> Response {
|
||||
Response::Tags { list: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn api<A: Any>(&self, request: A) -> Response {
|
||||
Response::Tags { list: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Query {
|
||||
Tags(String),
|
||||
}
|
||||
|
||||
pub enum Response {
|
||||
Tags { list: Vec<String> },
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Scheduler {}
|
||||
|
||||
pub trait Ensure {
|
||||
type EnsureInput;
|
||||
type EnsureOutput;
|
||||
|
||||
fn ensure(&self, input: Self::EnsureInput) -> Self::EnsureOutput;
|
||||
}
|
||||
|
||||
pub trait Action {
|
||||
type Input;
|
||||
type Output;
|
||||
|
||||
fn call(&self, input: Self::Input) -> Self::Output;
|
||||
}
|
||||
|
||||
impl Scheduler {
|
||||
pub fn schedule<A: Action>(&self, action: A) -> Scheduler {
|
||||
return self.clone();
|
||||
}
|
||||
|
||||
pub async fn apply(&self) {}
|
||||
}
|
||||
|
||||
pub struct DebianPkg {}
|
||||
|
||||
impl DebianPkg {
|
||||
pub fn require<'a>(pkgs: impl Into<Vec<&'a str>>) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
impl Ensure for DebianPkg {
|
||||
type EnsureInput = ();
|
||||
type EnsureOutput = ();
|
||||
|
||||
fn ensure(&self, input: Self::EnsureInput) -> Self::EnsureOutput {}
|
||||
}
|
||||
|
||||
impl Action for DebianPkg {
|
||||
type Input = ();
|
||||
type Output = ();
|
||||
|
||||
fn call(&self, input: Self::Input) -> Self::Output {}
|
||||
}
|
||||
|
||||
pub async fn handle(orchestrator: Orchestrator) {
|
||||
orchestrator
|
||||
.cron("* * * * *")
|
||||
.schedule(DebianPkg::require(vec!["openssl", "git"]))
|
||||
.apply()
|
||||
.await;
|
||||
|
||||
orchestrator
|
||||
.cron("* * * * *")
|
||||
.schedule(DebianPkg::require(vec!["openssl", "git"]))
|
||||
.apply()
|
||||
.await;
|
||||
}
|
BIN
includes/wasi_snapshot_preview1.wasm
Executable file
BIN
includes/wasi_snapshot_preview1.wasm
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user