-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(example): add blank slate rust provider
Signed-off-by: Brooks Townsend <brooksmtownsend@gmail.com>
- Loading branch information
1 parent
c354c57
commit 73ad00a
Showing
24 changed files
with
621 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "wasmcloud-example-blank-slate" | ||
version = "0.1.0" | ||
edition = "2021" | ||
description = """ | ||
A blank slate capability provider built for quick implementation of custom capabilities. | ||
""" | ||
|
||
[workspace] | ||
|
||
[badges.maintenance] | ||
status = "actively-developed" | ||
|
||
[dependencies] | ||
anyhow = "1.0.82" | ||
async-nats = "0.33.0" | ||
serde = { version = "1.0.197" , features = ["derive"] } | ||
serde_json = "1.0.115" | ||
tokio = { version = "1.37.0", features = [ "full" ] } | ||
tracing = "0.1" | ||
wasmcloud-provider-sdk = "0.5.0" | ||
wit-bindgen-wrpc = "0.3.7" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Blank Slate Capability Provider | ||
|
||
This capability provider is a blank slate for creating providers with custom capabilities. It uses the [wasmcloud-provider-sdk](https://crates.io/crates/wasmcloud-provider-sdk) and implements the [Provider](https://docs.rs/wasmcloud-provider-sdk/0.5.0/wasmcloud_provider_sdk/trait.Provider.html) trait with an example handler that will persist the links that target the provider (target links) and links where the provider is the source and targets a component (source links). | ||
|
||
The purpose of this example is to provide comprehensive comments on the usage of our wasmCloud provider SDK, from serving RPC exports to invoking component imports. The code is informative to read through and provides a base for extending wasmCloud with custom capabilities. | ||
|
||
## Building | ||
|
||
Prerequisites: | ||
|
||
1. [Rust toolchain](https://www.rust-lang.org/tools/install) | ||
1. [wash](https://wasmcloud.com/docs/installation) | ||
|
||
You can build this capability provider by running `wash build`. You can build the included test component with `wash build -p ./component`. | ||
|
||
## Running to test | ||
|
||
Prerequisites: | ||
|
||
1. [Rust toolchain](https://www.rust-lang.org/tools/install) | ||
1. [nats-server](https://github.com/nats-io/nats-server) | ||
1. [nats-cli](https://github.com/nats-io/natscli) | ||
|
||
You can run this capability provider as a binary by passing a simple base64 encoded [HostData](https://docs.rs/wasmcloud-core/0.6.0/wasmcloud_core/host/struct.HostData.html) struct, in order to do basic testing. For example: | ||
|
||
```bash | ||
nats-server -js & | ||
echo '{"lattice_rpc_url": "0.0.0.0:4222", "lattice_rpc_prefix": "default", "provider_key": "blank-slate", "config": {"foo": "bar"}, "env_values": {}, "link_definitions": [], "otel_config": {"enable_observability": false}}' | base64 | cargo run | ||
``` | ||
|
||
And in another terminal, you can request the health of the provider using the NATS CLI | ||
|
||
```bash | ||
nats req "wasmbus.rpc.default.blank-slate.default.health '{}' | ||
``` | ||
Additionally, you can invoke the provider directly which will send test data to each linked component | ||
```bash | ||
wash call blank-slate wasmcloud:example/system-info.call | ||
``` | ||
## Running as an application | ||
You can deploy this provider, along with a [prebuilt component](./component/) for testing, by deploying the [wadm.yaml](./wadm.yaml) application. | ||
```bash | ||
# Launch wasmCloud in the background | ||
wash up -d | ||
# Deploy the application | ||
wash app deploy ./wadm.yaml | ||
``` | ||
## Customizing | ||
Customizing this provider to meet your needs of a custom capability takes just a few steps. | ||
1. Update the [wit/world.wit](./wit/world.wit) to include the data types and functions that model your custom capability. You can use the example as a base and the [component model WIT reference](https://component-model.bytecodealliance.org/design/wit.html) as a guide for types and keywords. | ||
1. Implement any provider `export`s in [src/provider.rs](./src/provider.rs) inside of the `impl Handler {}` block. | ||
1. Use the methods inside of the `impl Provider {}` block to handle invoking components. For inspiration, take a look at our other capability providers that implement various capabilities like HTTP, Messaging, Key-Value in the [crates/provider-\*](../../../../crates/) folder. | ||
Have any questions? Please feel free to [file an issue](https://github.com/wasmCloud/wasmCloud/issues/new/choose) and/or join us on the [wasmCloud slack](https://slack.wasmcloud.com)! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Rust build artifacts | ||
Cargo.lock | ||
|
||
# Wash build artifacts | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "blank-slate-test-component" | ||
edition = "2021" | ||
version = "0.1.0" | ||
|
||
[workspace] | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
wit-bindgen = { version = "0.24", features = ["default"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Blank slate test component | ||
|
||
This component is meant to test the [blank slate capability provider](../) by an implementation of the interface on the component. | ||
|
||
## Build | ||
|
||
Use `wash build` to build this component. A prebuilt component is included for easy deployment of the provider. | ||
|
||
## Deploy | ||
|
||
Use the [wadm.yaml](../wadm.yaml) in the parent directory to deploy this component alongside the provider. |
Binary file added
BIN
+1.38 MB
examples/rust/providers/blank-slate/component/build/blank_slate_test_component.wasm
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
wit_bindgen::generate!(); | ||
|
||
use crate::exports::wasmcloud::example::process_data::Data; | ||
use crate::exports::wasmcloud::example::process_data::Guest; | ||
use crate::wasi::logging::logging::*; | ||
use crate::wasmcloud::example::system_info::Kind; | ||
|
||
struct BlankSlateComponent; | ||
|
||
impl Guest for BlankSlateComponent { | ||
fn process(data: Data) -> String { | ||
log(Level::Info, "", &format!("Data received: {:?}", data)); | ||
// Request OS and architecture information | ||
let os = crate::wasmcloud::example::system_info::request_info(Kind::Os); | ||
let arch = crate::wasmcloud::example::system_info::request_info(Kind::Arch); | ||
format!("Provider is running on {os}-{arch}").to_string() | ||
} | ||
} | ||
|
||
export!(BlankSlateComponent); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
name = "Blank slate test component" | ||
language = "rust" | ||
type = "component" | ||
|
||
[component] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[blankslate] | ||
path = "../../wit" | ||
sha256 = "3af8ebbb348273a8a541440c4fbad2c739d03257903ab172d6722c68a694f86c" | ||
sha512 = "2d83b11fd3ac592c4ed87a05feefae1d26803b626f5a425a109202196b6d951bfb407cb4f97c6209891ef70aeb3b86b8b8338c880d46fc1976fa7a9b5ca7201b" | ||
|
||
[logging] | ||
url = "https://github.com/WebAssembly/wasi-logging/archive/main.tar.gz" | ||
sha256 = "9676b482485bb0fd2751a390374c1108865a096b7037f4b5dbe524f066bfb06e" | ||
sha512 = "30a621a6d48a0175e8047c062e618523a85f69c45a7c31918da2b888f7527fce1aca67fa132552222725d0f6cdcaed95be7f16c28488d9468c0fad00cb7450b9" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
blankslate = "../../wit" | ||
logging = "https://github.com/WebAssembly/wasi-logging/archive/main.tar.gz" |
39 changes: 39 additions & 0 deletions
39
examples/rust/providers/blank-slate/component/wit/deps/blankslate/world.wit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package wasmcloud:example; | ||
|
||
// This interface is generic and includes a function to process some | ||
// data, returning a string result. | ||
// We'll use this to send structured data to a component for processing. | ||
interface process-data { | ||
record data { | ||
name: string, | ||
count: u32, | ||
} | ||
|
||
// Send structured data to the component for processing | ||
process: func(data: data) -> string; | ||
} | ||
|
||
// While processing data, sometimes a component may need to request | ||
// information about the system it's running on. The component isn't | ||
// allowed to access this information directly, so it can request it | ||
// from the provider. | ||
interface system-info { | ||
enum kind { | ||
OS, | ||
ARCH, | ||
} | ||
|
||
// Request information about the system the provider is running on | ||
request-info: func(kind: kind) -> string; | ||
|
||
// Example export to call from the provider for testing | ||
call: func() -> string; | ||
} | ||
|
||
// The `world` defines all of the imports and exports our provider can use / must implement. | ||
world provider { | ||
// Providers `import` functions that it can call on a component | ||
import process-data; | ||
// Providers `export` functions that a component can call | ||
export system-info; | ||
} |
35 changes: 35 additions & 0 deletions
35
examples/rust/providers/blank-slate/component/wit/deps/logging/logging.wit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/// WASI Logging is a logging API intended to let users emit log messages with | ||
/// simple priority levels and context values. | ||
interface logging { | ||
/// A log level, describing a kind of message. | ||
enum level { | ||
/// Describes messages about the values of variables and the flow of | ||
/// control within a program. | ||
trace, | ||
|
||
/// Describes messages likely to be of interest to someone debugging a | ||
/// program. | ||
debug, | ||
|
||
/// Describes messages likely to be of interest to someone monitoring a | ||
/// program. | ||
info, | ||
|
||
/// Describes messages indicating hazardous situations. | ||
warn, | ||
|
||
/// Describes messages indicating serious errors. | ||
error, | ||
|
||
/// Describes messages indicating fatal errors. | ||
critical, | ||
} | ||
|
||
/// Emit a log message. | ||
/// | ||
/// A log message has a `level` describing what kind of message is being | ||
/// sent, a context, which is an uninterpreted string meant to help | ||
/// consumers group similar messages, and a string containing the message | ||
/// text. | ||
log: func(level: level, context: string, message: string); | ||
} |
5 changes: 5 additions & 0 deletions
5
examples/rust/providers/blank-slate/component/wit/deps/logging/world.wit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package wasi:logging; | ||
|
||
world imports { | ||
import logging; | ||
} |
12 changes: 12 additions & 0 deletions
12
examples/rust/providers/blank-slate/component/wit/world.wit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package wasmcloud:blankslate; | ||
|
||
world component { | ||
// Import logging for processing data | ||
import wasi:logging/logging; | ||
|
||
// Notice here the component has the inverse direction for importing/exporting interfaces | ||
// compared to the provider. This allows us to compose the component with the provider, each | ||
// import linking up to an export. | ||
import wasmcloud:example/system-info; | ||
export wasmcloud:example/process-data; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[template] | ||
|
||
raw = [ | ||
"*.par.gz", | ||
"*.par", | ||
] | ||
exclude = [ | ||
"target/", | ||
"keys/", | ||
"build/", | ||
"*.lock", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
use std::collections::HashMap; | ||
|
||
use serde::{Deserialize, Serialize}; | ||
|
||
/// Configuration for this provider, which is passed to the provider from the host. | ||
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)] | ||
pub struct ProviderConfig { | ||
values: HashMap<String, String>, | ||
} | ||
|
||
impl From<&HashMap<String, String>> for ProviderConfig { | ||
/// Construct configuration struct from the passed config values. | ||
/// | ||
/// For this example, we just store the values directly for any later reference. | ||
/// You can use this as a base to create your own strongly typed configuration struct. | ||
fn from(values: &HashMap<String, String>) -> ProviderConfig { | ||
ProviderConfig { | ||
values: values.clone(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//! A blank slate provider that's meant to inform developers how to build a capability provider. | ||
//! The implementation in `./provider.rs` uses the `wasmcloud-provider-sdk` to provide a scaffold | ||
//! for building a capability provider with a custom interface. Take note of the documentation | ||
//! comments in the code to understand how to build a capability provider. | ||
|
||
mod config; | ||
mod provider; | ||
|
||
use provider::BlankSlateProvider; | ||
|
||
/// Capability providers are native executables, so the entrypoint is the same as any other Rust | ||
/// binary, `main()`. Typically the `main` function is kept simple and the provider logic is | ||
/// implemented in a separate module. Head to the `provider.rs` file to see the implementation of | ||
/// the `BlankSlateProvider`. | ||
#[tokio::main] | ||
async fn main() -> anyhow::Result<()> { | ||
BlankSlateProvider::run().await?; | ||
eprintln!("Blank slate provider exiting"); | ||
Ok(()) | ||
} |
Oops, something went wrong.