Skip to content

Commit

Permalink
Added New Docs
Browse files Browse the repository at this point in the history
Signed-off-by: Adithya Krishna <[email protected]>
  • Loading branch information
Adithya Krishna committed Aug 8, 2023
1 parent 30e0037 commit b5ddfed
Show file tree
Hide file tree
Showing 34 changed files with 3,589 additions and 12 deletions.
2 changes: 1 addition & 1 deletion docs/develop/deploy/cri-runtime/containerd.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
sidebar_position: 1
---

# 8.6.1 Deploy with containerd's runwasi
# Deploy with containerd's runwasi

<!-- prettier-ignore -->
:::info
Expand Down
97 changes: 93 additions & 4 deletions docs/embed/c++/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,96 @@ sidebar_position: 1

# WasmEdge C++ SDK Introduction

<!-- prettier-ignore -->
:::info
Work in Progress
:::
The WasmEdge C++ SDK is a collection of headers and libraries that allow you to build and deploy WebAssembly (Wasm) modules for execution on WasmEdge devices. It includes a CMake project and a set of command-line tools that you can use to build and deploy your Wasm modules.

## Quick Start Guide

To get started with WasmEdge, follow these steps:

Install the WasmEdge C/C++ SDK: Download C++ SDK from the WasmEdge [website](https://wasmedge.org/docs/embed/quick-start/install) and follow the instructions to install it on your development machine

```cpp
#include <wasmedge/wasmedge.h>
#include <iostream>

int main(int argc, char** argv) {
/* Create the configure context and add the WASI support. */
/* This step is not necessary unless you need WASI support. */
WasmEdge_ConfigureContext* conf_cxt = WasmEdge_ConfigureCreate();
WasmEdge_ConfigureAddHostRegistration(conf_cxt, WasmEdge_HostRegistration_Wasi);
/* The configure and store context to the VM creation can be NULL. */
WasmEdge_VMContext* vm_cxt = WasmEdge_VMCreate(conf_cxt, nullptr);

/* The parameters and returns arrays. */
WasmEdge_Value params[1] = { WasmEdge_ValueGenI32(40) };
WasmEdge_Value returns[1];
/* Function name. */
WasmEdge_String func_name = WasmEdge_StringCreateByCString("fib");
/* Run the WASM function from file. */
WasmEdge_Result res = WasmEdge_VMRunWasmFromFile(vm_cxt, argv[1], func_name, params, 1, returns, 1);

if (WasmEdge_ResultOK(res)) {
std::cout << "Get result: " << WasmEdge_ValueGetI32(returns[0]) << std::endl;
} else {
std::cout << "Error message: " << WasmEdge_ResultGetMessage(res) << std::endl;
}

/* Resources deallocations. */
WasmEdge_VMDelete(vm_cxt);
WasmEdge_ConfigureDelete(conf_cxt);
WasmEdge_StringDelete(func_name);
return 0;
}
```
You can use the -I flag to specify the include directories and the -L and -l flags to specify the library directories and library names, respectively.
Then you can compile the code and run: ( the 40th fibonacci number is 102334155)
```bash
gcc example.cpp -x c++ -I/path/to/wasmedge/include -L/path/to/wasmedge/lib -lwasmedge -o example
```

To run the `example` executable that was created in the previous step, you can use the following command

```bash
./example
```

## Quick Start Guide in AOT compiler

```cpp
#include <wasmedge/wasmedge.h>
#include <stdio.h>

int main(int argc, const char* argv[]) {
// Create the configure context and add the WASI support.
// This step is not necessary unless you need WASI support.
wasmedge_configure_context* conf_cxt = wasmedge_configure_create();
wasmedge_configure_add_host_registration(conf_cxt, WASMEDGE_HOST_REGISTRATION_WASI);

// Create the VM context in AOT mode.
wasmedge_vm_context* vm_cxt = wasmedge_vm_create_aot(conf_cxt, NULL);

// The parameters and returns arrays.
wasmedge_value params[1] = { wasmedge_value_gen_i32(32) };
wasmedge_value returns[1];
// Function name.
wasmedge_string func_name = wasmedge_string_create_by_cstring("fib");
// Run the WASM function from file.
wasmedge_result res = wasmedge_vm_run_wasm_from_file(vm_cxt, argv[1], func_name, params, 1, returns, 1);

if (wasmedge_result_ok(res)) {
printf("Get result: %d\n", wasmedge_value_get_i32(returns[0]));
} else {
printf("Error message: %s\n", wasmedge_result_get_message(res));
}

// Resources deallocations.
wasmedge_vm_delete(vm_cxt);
wasmedge_configure_delete(conf_cxt);
wasmedge_string_delete(func_name);
return 0;
}
```
In this example, the wasmedge_vm_create_aot function is used to create a wasmedge_vm_context object in AOT mode, which is then passed as the second argument to the wasmedge_vm_run_wasm_from_file function to execute the Wasm module in AOT mode.
8 changes: 8 additions & 0 deletions docs/embed/use-case/mesh/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Service mesh and Runtimes",
"position": 8,
"link": {
"type": "generated-index",
"description": "WasmEdge could be a lightweight runtime for sidecar microservices and the API proxy as the Docker alternative."
}
}
263 changes: 263 additions & 0 deletions docs/embed/use-case/mesh/dapr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
---
sidebar_position: 1
---

# Dapr

In this article, I will demonstrate how to use WasmEdge as a sidecar application runtime for Dapr. There are two ways to do this:

* **Standalone WasmEdge** is the **recommended approach** is to write a microservice using [Rust](../../../write_wasm/rust/networking-nonblocking.md) or [JavaScript](../../../write_wasm/js/networking.md), and run it in WasmEdge. The WasmEdge application serves web requests and communicates with the sidecar via sockets using the Dapr API. In this case, we can [run WasmEdge as a managed container in k8s](../../kubernetes/quickstart.md).
* Alternatively, Embedded WasmEdge is to create a simple microservice in Rust or Go to listen for web requests and communicate with the Dapr sidecar. It passes the request data to a WasmEdge runtime for processing. The business logic of the microservice is a WebAssembly function created and deployed by an application developer.

> While the first approach (running the entire microservice in WasmEdge) is much preferred, we are still working on a fully fledged Dapr SDKs for WasmEdge. You can track their progress in GitHub issues -- [Rust](https://github.com/WasmEdge/WasmEdge/issues/1571) and [JavaScript](https://github.com/WasmEdge/WasmEdge/issues/1572).
## Quick start

First you need to install [Dapr](https://docs.dapr.io/getting-started/install-dapr-cli) and [WasmEdge](../../../quick_start/install.md). [Go](https://golang.org/doc/install) and [Rust](https://www.rust-lang.org/tools/install) are optional for the standalone WasmEdge approach. However, they are required for the demo app since it showcases both standalone and embedded WasmEdge approaches.

Fork or clone the demo application from Github. You can use this repo as your own application template.

```bash
git clone https://github.com/second-state/dapr-wasm
````

The demo has 4 Dapr sidecar applications. The [web-port](https://github.com/second-state/dapr-wasm/tree/main/web-port) project provides a public web service for a static HTML page. This is the application’s UI. From the static HTML page, the user can select a microservice to turn an input image into grayscale. All 3 microsoervices below perform the same function. They are just implemented using different approaches.

* **Standalone WasmEdge approach:** The [image-api-wasi-socket-rs](https://github.com/second-state/dapr-wasm/tree/main/image-api-wasi-socket-rs) project provides a standalone WasmEdge sidecar microservice that takes the input image and returns the grayscale image. The microservice is written in Rust and compiled into WebAssembly bytecode to run in WasmEdge.
* Embedded WasmEdge approach #1: The [image-api-rs](https://github.com/second-state/dapr-wasm/tree/main/image-api-rs) project provides a simple Rust-based microservice. It embeds a [WasmEdge function](https://github.com/second-state/dapr-wasm/tree/main/functions/grayscale) to turn an input image into a grayscale image.
* Embedded WasmEdge approach #2: The [image-api-go](https://github.com/second-state/dapr-wasm/tree/main/image-api-go) project provides a simple Go-based microservice. It embeds a [WasmEdge function](https://github.com/second-state/dapr-wasm/tree/main/functions/grayscale) to turn an input image into a grayscale image.

You can follow the instructions in the [README](https://github.com/second-state/dapr-wasm/blob/main/README.md) to start the sidecar services. Here are commands to build the WebAssembly functions and start the sidecar services. The first set of commands deploy the static web page service and the standalone WasmEdge service written in Rust. It forms a complete application to turn an input image into grayscale.

```bash
# Build and start the static HTML web page service for the UI and router for sending the uploaded image to the grayscale microservice
cd web-port
go build
./run_web.sh
cd ../
# Build the standalone image grayscale web service for WasmEdge
cd image-api-wasi-socket-rs
cargo build --target wasm32-wasi
cd ../
# Run the microservice as a Dapr sidecar app
cd image-api-wasi-socket-rs
./run_api_wasi_socket_rs.sh
cd ../
```

The second set of commands create the alternative microservices for the embedded WasmEdge function.

```bash
# Build the grayscale WebAssembly functions, and deploy them to the sidecar projects
cd functions/grayscale
./build.sh
cd ../../
# Build and start the Rust-based microservice for embedding the grayscale WasmEdge function
cd image-api-rs
cargo build --release
./run_api_rs.sh
cd ../
# Build and start the Go-based microservice for embedding the grayscale WasmEdge function
cd image-api-go
go build
./run_api_go.sh
cd ../
```

Finally, you should be able to see the web UI in your browser.

## Recommended: The standalone WasmEdge microservice in Rust

The [standalone WasmEdge microservice](https://github.com/second-state/dapr-wasm/blob/main/image-api-wasi-socket-rs/src/main.rs) starts a non-blocking TCP server inside WasmEdge. The TCP server passes incoming requests to `handle_client()`, which passes HTTP requests to `handle_http()`, which calls `grayscale()` to process the image data in the request.
```rust
fn main() -> std::io::Result<()> {
let port = std::env::var("PORT").unwrap_or(9005.to_string());
println!("new connection at {}", port);
let listener = TcpListener::bind(format!("127.0.0.1:{}", port))?;
loop {
let _ = handle_client(listener.accept()?.0);
}
}

fn handle_client(mut stream: TcpStream) -> std::io::Result<()> {
... ...
}

fn handle_http(req: Request<Vec<u8>>) -> bytecodec::Result<Response<String>> {
... ...
}

fn grayscale(image: &[u8]) -> Vec<u8> {
let detected = image::guess_format(&image);
let mut buf = vec![];
if detected.is_err() {
return buf;
}

let image_format_detected = detected.unwrap();
let img = image::load_from_memory(&image).unwrap();
let filtered = img.grayscale();
match image_format_detected {
ImageFormat::Gif => {
filtered.write_to(&mut buf, ImageOutputFormat::Gif).unwrap();
}
_ => {
filtered.write_to(&mut buf, ImageOutputFormat::Png).unwrap();
}
};
return buf;
}
```
> Work in progress: It will soon interact with the Dapr sidecar through the [WasmEdge Dapr SDK in Rust](https://github.com/WasmEdge/WasmEdge/issues/1571).
Now, you can build the microservice. It is a simple matter of compiling from Rust to WebAssembly.
```bash
cd image-api-wasi-socket-rs
cargo build --target wasm32-wasi
```
Deploy the WasmEdge microservice in Dapr as follows.
```bash
dapr run --app-id image-api-wasi-socket-rs \
--app-protocol http \
--app-port 9005 \
--dapr-http-port 3503 \
--components-path ../config \
--log-level debug \
wasmedge ./target/wasm32-wasi/debug/image-api-wasi-socket-rs.wasm
```
## Alternative: The embedded WasmEdge microservices
The embedded WasmEdge approach requires us to create a WebAssembly function for the business logic (image processing) first, and then embed it into simple Dapr microservices.
### Rust function for image processing
The [Rust function](https://github.com/second-state/dapr-wasm/blob/main/functions/grayscale/src/lib.rs) is simple. It uses the [wasmedge_bindgen](../../../write_wasm/rust/bindgen.md) macro to makes it easy to call the function from a Go or Rust host embedding the WebAssembly function. It takes and returns base64 encoded image data for the web.
```rust
#[wasmedge_bindgen]
pub fn grayscale(image_data: String) -> String {
let image_bytes = image_data.split(",").map(|x| x.parse::<u8>().unwrap()).collect::<Vec<u8>>();
return grayscale::grayscale_internal(&image_bytes);
}
```
The Rust function that actually performs the task is as follows.
```rust
pub fn grayscale_internal(image_data: &[u8]) -> String {
let image_format_detected: ImageFormat = image::guess_format(&image_data).unwrap();
let img = image::load_from_memory(&image_data).unwrap();
let filtered = img.grayscale();
let mut buf = vec![];
match image_format_detected {
ImageFormat::Gif => {
filtered.write_to(&mut buf, ImageOutputFormat::Gif).unwrap();
}
_ => {
filtered.write_to(&mut buf, ImageOutputFormat::Png).unwrap();
}
};
let mut base64_encoded = String::new();
base64::encode_config_buf(&buf, base64::STANDARD, &mut base64_encoded);
return base64_encoded.to_string();
}
```
### The Go host wrapper for microservice
The [Go-based microservice](https://github.com/second-state/dapr-wasm/tree/main/image-api-go) embeds the above imaging processing function in WasmEdge. The [microservice itself](https://github.com/second-state/dapr-wasm/blob/main/image-api-go/image_api.go) is a web server and utilizes the Dapr Go SDK.
```go
func main() {
s := daprd.NewService(":9003")

if err := s.AddServiceInvocationHandler("/api/image", imageHandlerWASI); err != nil {
log.Fatalf("error adding invocation handler: %v", err)
}

if err := s.Start(); err != nil && err != http.ErrServerClosed {
log.Fatalf("error listening: %v", err)
}
}
```
The `imageHandlerWASI()` function [starts a WasmEdge instance](../../../sdk/go/function.md) and calls the image processing (grayscale) function in it via [wasmedge_bindgen](../../../write_wasm/rust/bindgen.md).
Build and deploy the Go microservice to Dapr as follows.
```bash
cd image-api-go
go build
dapr run --app-id image-api-go \
--app-protocol http \
--app-port 9003 \
--dapr-http-port 3501 \
--log-level debug \
--components-path ../config \
./image-api-go
```
### The Rust host wrapper for microservice
The [Rust-based microservice](https://github.com/second-state/dapr-wasm/tree/main/image-api-rs) embeds the above imaging processing function in WasmEdge. The [microservice itself](https://github.com/second-state/dapr-wasm/blob/main/image-api-rs/src/main.rs) is a Tokio and Warp based web server.
```rust
#[tokio::main]
pub async fn run_server(port: u16) {
pretty_env_logger::init();
let home = warp::get().map(warp::reply);

let image = warp::post()
.and(warp::path("api"))
.and(warp::path("image"))
.and(warp::body::bytes())
.map(|bytes: bytes::Bytes| {
let v: Vec<u8> = bytes.iter().map(|&x| x).collect();
let res = image_process_wasmedge_sys(&v);
let _encoded = base64::encode(&res);
Response::builder()
.header("content-type", "image/png")
.body(res)
});

let routes = home.or(image);
let routes = routes.with(warp::cors().allow_any_origin());

let log = warp::log("dapr_wasm");
let routes = routes.with(log);
warp::serve(routes).run((Ipv4Addr::UNSPECIFIED, port)).await
}
```
The `image_process_wasmedge_sys()` function [starts a WasmEdge instance](../../../sdk/rust/sys_run_host_func.md) and calls the image processing (grayscale) function in it via [wasmedge_bindgen](../../../write_wasm/rust/bindgen.md).
Build and deploy the Rust microservice to Dapr as follows.
```bash
cd image-api-rs
cargo build --release
dapr stop image-api-rs

# Change this to your own path for WasmEdge
export LD_LIBRARY_PATH=/home/coder/.wasmedge/lib64/

dapr run --app-id image-api-rs \
--app-protocol http \
--app-port 9004 \
--dapr-http-port 3502 \
--components-path ../config \
--log-level debug \
./target/release/image-api-rs
```
That's it! [Let us know](https://github.com/WasmEdge/WasmEdge/discussions) your cool Dapr microservices in WebAssembly!
10 changes: 10 additions & 0 deletions docs/embed/use-case/mesh/eventmesh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
sidebar_position: 2
---

# Apache Eventmesh

<!-- prettier-ignore -->
:::info
Coming Soon or you can [help out](https://github.com/WasmEdge/WasmEdge/issues/632)
:::
Loading

0 comments on commit b5ddfed

Please sign in to comment.