From a7a3e3b196e5e23fbb76c1be5b4428f445063ca4 Mon Sep 17 00:00:00 2001 From: wrongerror Date: Mon, 26 Dec 2022 16:46:31 +0800 Subject: [PATCH] Add WasmEdge sample Signed-off-by: wrongerror --- .../wasmedge/http-server/.cargo/config.toml | 5 ++ .../knative/wasmedge/http-server/Dockerfile | 14 +++++ .../knative/wasmedge/http-server/README.md | 60 +++++++++++++++++++ .../wasmedge/http-server/server/Cargo.toml | 8 +++ .../wasmedge/http-server/server/src/main.rs | 51 ++++++++++++++++ .../http-server/wasmedge-http-server.yaml | 37 ++++++++++++ 6 files changed, 175 insertions(+) create mode 100644 functions/knative/wasmedge/http-server/.cargo/config.toml create mode 100644 functions/knative/wasmedge/http-server/Dockerfile create mode 100644 functions/knative/wasmedge/http-server/README.md create mode 100644 functions/knative/wasmedge/http-server/server/Cargo.toml create mode 100644 functions/knative/wasmedge/http-server/server/src/main.rs create mode 100644 functions/knative/wasmedge/http-server/wasmedge-http-server.yaml diff --git a/functions/knative/wasmedge/http-server/.cargo/config.toml b/functions/knative/wasmedge/http-server/.cargo/config.toml new file mode 100644 index 0000000..50cdadf --- /dev/null +++ b/functions/knative/wasmedge/http-server/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +target="wasm32-wasi" + +[target.wasm32-wasi] +runner = "wasmedge" \ No newline at end of file diff --git a/functions/knative/wasmedge/http-server/Dockerfile b/functions/knative/wasmedge/http-server/Dockerfile new file mode 100644 index 0000000..0864789 --- /dev/null +++ b/functions/knative/wasmedge/http-server/Dockerfile @@ -0,0 +1,14 @@ +FROM --platform=$BUILDPLATFORM rust:1.64 AS buildbase +RUN rustup target add wasm32-wasi +WORKDIR /src + +FROM --platform=$BUILDPLATFORM buildbase AS buildserver +COPY server /src +RUN --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/usr/local/cargo/registry/cache \ + --mount=type=cache,target=/usr/local/cargo/registry/index \ + cargo build --target wasm32-wasi --release + +FROM scratch AS server +ENTRYPOINT [ "wasmedge_hyper_server.wasm" ] +COPY --from=buildserver /src/target/wasm32-wasi/release/wasmedge_hyper_server.wasm wasmedge_hyper_server.wasm diff --git a/functions/knative/wasmedge/http-server/README.md b/functions/knative/wasmedge/http-server/README.md new file mode 100644 index 0000000..6ffa1be --- /dev/null +++ b/functions/knative/wasmedge/http-server/README.md @@ -0,0 +1,60 @@ +# Sample Function WasmEdge ( written in Rust ) + +## Prerequisites + +### OpenFunction + +You can refer to the [Installation Guide](https://github.com/OpenFunction/OpenFunction#install-openfunction) to setup OpenFunction. + +## Run it locally + +1. Build + +```bash +cargo build --target wasm32-wasi --release +``` + +2. Run + +```bash +wasmedge target/wasm32-wasi/release/wasmedge_hyper_server.wasm +``` + +3. Test + +Run the following from another terminal. + +```bash +$ curl http://localhost:8080/echo -X POST -d "WasmEdge" +WasmEdge +``` + +## Deployment + +> To setup `WasmEdge` workload runtime in kubernetes cluster and push images to a container registry, +> please refer to the [prerequisites](../../getting-started/Quickstarts/prerequisites) section for more info. + +1. Create function + +```shell +kubectl apply -f wasmedge-http-server.yaml + ``` + +2. Check the function status + +```shell +kubectl get functions.core.openfunction.io -w +NAME BUILDSTATE SERVINGSTATE BUILDER SERVING ADDRESS AGE +wasmedge-http-server Succeeded Running builder-4p2qq serving-lrd8c http://wasmedge-http-server.default.svc.cluster.local/echo 12m + ``` + +3. Access function + +Once the `BUILDSTATE` becomes `Succeeded` and the `SERVINGSTATE` becomes `Running`, you can access this function through the address in the `ADDRESS` field: +You can observe the process of a function with the following command: + +```shell +kubectl run curl --image=radial/busyboxplus:curl -i --tty +curl http://wasmedge-http-server.default.svc.cluster.local/echo -X POST -d "WasmEdge" +WasmEdge +``` diff --git a/functions/knative/wasmedge/http-server/server/Cargo.toml b/functions/knative/wasmedge/http-server/server/Cargo.toml new file mode 100644 index 0000000..b525353 --- /dev/null +++ b/functions/knative/wasmedge/http-server/server/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "wasmedge_hyper_server" +version = "0.1.0" +edition = "2021" + +[dependencies] +hyper_wasi = { version = "0.15", features = ["full"]} +tokio_wasi = { version = "1.21", features = ["rt", "macros", "net", "time", "io-util"]} diff --git a/functions/knative/wasmedge/http-server/server/src/main.rs b/functions/knative/wasmedge/http-server/server/src/main.rs new file mode 100644 index 0000000..f3e5d48 --- /dev/null +++ b/functions/knative/wasmedge/http-server/server/src/main.rs @@ -0,0 +1,51 @@ +use std::net::SocketAddr; + +use hyper::server::conn::Http; +use hyper::service::service_fn; +use hyper::{Body, Method, Request, Response, StatusCode}; +use tokio::net::TcpListener; + +/// This is our service handler. It receives a Request, routes on its +/// path, and returns a Future of a Response. +async fn echo(req: Request) -> Result, hyper::Error> { + match (req.method(), req.uri().path()) { + // Serve some instructions at / + (&Method::GET, "/") => Ok(Response::new(Body::from( + "Try POSTing data to /echo such as: `curl localhost:8080/echo -XPOST -d 'hello world'`", + ))), + + // Simply echo the body back to the client. + (&Method::POST, "/echo") => Ok(Response::new(req.into_body())), + + (&Method::POST, "/echo/reversed") => { + let whole_body = hyper::body::to_bytes(req.into_body()).await?; + + let reversed_body = whole_body.iter().rev().cloned().collect::>(); + Ok(Response::new(Body::from(reversed_body))) + } + + // Return the 404 Not Found for other routes. + _ => { + let mut not_found = Response::default(); + *not_found.status_mut() = StatusCode::NOT_FOUND; + Ok(not_found) + } + } +} + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<(), Box> { + let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); + + let listener = TcpListener::bind(addr).await?; + println!("Listening on http://{}", addr); + loop { + let (stream, _) = listener.accept().await?; + + tokio::task::spawn(async move { + if let Err(err) = Http::new().serve_connection(stream, service_fn(echo)).await { + println!("Error serving connection: {:?}", err); + } + }); + } +} diff --git a/functions/knative/wasmedge/http-server/wasmedge-http-server.yaml b/functions/knative/wasmedge/http-server/wasmedge-http-server.yaml new file mode 100644 index 0000000..d7c1283 --- /dev/null +++ b/functions/knative/wasmedge/http-server/wasmedge-http-server.yaml @@ -0,0 +1,37 @@ +apiVersion: core.openfunction.io/v1beta1 +kind: Function +metadata: + name: wasmedge-http-server +spec: + workloadRuntime: wasmedge + image: openfunctiondev/wasmedge_http_server:0.1.0 + imageCredentials: + name: push-secret + build: + dockerfile: Dockerfile + srcRepo: + revision: main + sourceSubPath: functions/knative/wasmedge/http-server + url: https://github.com/OpenFunction/samples + port: 8080 + route: + rules: + - matches: + - path: + type: PathPrefix + value: /echo + serving: + runtime: knative + scaleOptions: + minReplicas: 0 + template: + containers: + - command: + - /wasmedge_hyper_server.wasm + imagePullPolicy: IfNotPresent + livenessProbe: + initialDelaySeconds: 3 + periodSeconds: 30 + tcpSocket: + port: 8080 + name: function \ No newline at end of file