Skip to content

Commit

Permalink
feat: add spin-dapr example (#136)
Browse files Browse the repository at this point in the history
Signed-off-by: Sven Pfennig <[email protected]>
  • Loading branch information
0xE282B0 authored Nov 23, 2023
1 parent 30e42fe commit 4682b1a
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 0 deletions.
5 changes: 5 additions & 0 deletions images/spin-dapr/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target/debug
target/release
target/wasm32-wasi/build
target/wasm32-wasi/deps
.spin/
2 changes: 2 additions & 0 deletions images/spin-dapr/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
.spin/
20 changes: 20 additions & 0 deletions images/spin-dapr/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "spin-dapr"
authors = ["Sven Pfennig <[email protected]>"]
description = "Example application to use Dapr with Spin"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = [ "cdylib" ]

[dependencies]
anyhow = "1"
# Crate to simplify working with bytes.
bytes = "1"
# General-purpose crate with common HTTP types.
http = "0.2"
# The Spin SDK.
spin-sdk = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" }

[workspace]
4 changes: 4 additions & 0 deletions images/spin-dapr/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM scratch
COPY ./spin.toml .
COPY --chmod=0755 ./target/wasm32-wasi/release/spin_dapr.wasm /target/wasm32-wasi/release/spin_dapr.wasm
ENTRYPOINT ["/target/wasm32-wasi/release/spin_dapr.wasm"]
45 changes: 45 additions & 0 deletions images/spin-dapr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Spin Dapr Demo

## Description
This demo application is a simple Spin app that is triggered by the daprs [kubernetes input binding](https://docs.dapr.io/reference/components-reference/supported-bindings/kubernetes-binding/) when it is called with the path `/kevents` it writes the body to a redis running at `redis://localhost:6379` to the key `lastEvent`. All other paths just return the value of the `lastEvent` key.

### Prerequisites
Install dapr cli
```sh
curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | bash
```

Install spin cli:
```sh
curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash
sudo mv ./spin /usr/local/bin/
```

### Run example with K3d:
```sh
# start the K3d cluster
k3d cluster create wasm-cluster --image ghcr.io/deislabs/containerd-wasm-shims/examples/k3d:v0.10.0 -p "8081:80@loadbalancer"
# Install Dapr
dapr init -k --wait
# or via helm
# helm repo add dapr https://dapr.github.io/helm-charts/
# helm repo update
# helm upgrade --install dapr dapr/dapr --namespace dapr-system --create-namespace --wait

# build the application
cd images/spin-dapr
spin build
cd -
# create an image and load it into K3d
docker build images/spin-dapr -t spin-dapr:latest --load
mkdir -p test/out_spin-dapr/
docker save spin-dapr:latest -o test/out_spin-dapr/img.tar
k3d image load -c wasm-cluster spin-dapr:latest test/out_spin-dapr/img.tar
# Apply the manifest
kubectl apply -f https://github.com/deislabs/containerd-wasm-shims/raw/main/deployments/workloads/runtime.yaml
kubectl apply -f images/spin-dapr/deploy.yaml

# When everythin is up, forward the port and get the last kubernetes event
kubectl port-forward svc/spin-dapr 8080:80 &
curl localhost:8080 | jq
```
95 changes: 95 additions & 0 deletions images/spin-dapr/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: spin-dapr
spec:
replicas: 1
selector:
matchLabels:
app: spin-dapr
template:
metadata:
labels:
app: spin-dapr
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "spin-dapr"
dapr.io/app-port: "80"
dapr.io/log-level: "debug"
spec:
runtimeClassName: wasmtime-spin
containers:
- image: redis
name: redis
- name: spin-dapr
image: spin-dapr:latest
imagePullPolicy: Never
---
apiVersion: v1
kind: Service
metadata:
name: spin-dapr
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
app: spin-dapr
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: spin-dapr
annotations:
ingress.kubernetes.io/ssl-redirect: "false"
kubernetes.io/ingress.class: traefik
spec:
rules:
- http:
paths:
- path: /spin-dapr
pathType: Prefix
backend:
service:
name: spin-dapr
port:
number: 80
---
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: kevents
namespace: default
spec:
type: bindings.kubernetes
version: v1
metadata:
- name: namespace
value: "default"
- name: resyncPeriodInSec
value: "1"
- name: direction
value: "input"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: spin-dapr
rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: spin-dapr
subjects:
- kind: ServiceAccount
name: default # or as need be, can be changed
roleRef:
kind: Role
name: spin-dapr # same as the one above
apiGroup: ""
17 changes: 17 additions & 0 deletions images/spin-dapr/spin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
spin_manifest_version = "1"
authors = ["Sven Pfennig <[email protected]>"]
description = "Example application to use Dapr with Spin"
name = "spin-dapr"
trigger = { type = "http", base = "/" }
version = "0.1.0"

[[component]]
id = "spin-dapr"
source = "target/wasm32-wasi/release/spin_dapr.wasm"
allowed_http_hosts = []
[component.trigger]
route = "/..."

[component.build]
command = "cargo build --target wasm32-wasi --release"
watch = ["src/**/*.rs", "Cargo.toml"]
30 changes: 30 additions & 0 deletions images/spin-dapr/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use anyhow::{anyhow, Result};
use spin_sdk::{
http::{Request, Response},
http_component, redis,
};

// Expect redis running on localhost or in the same pod
const ADDRESS: &str = "redis://localhost:6379";
const KEY: &str = "lastEvent";


#[http_component]
fn handle_spin_dapr(req: Request) -> Result<Response> {
println!("{:?}\n", req);

if req.uri().path().ends_with("kevents"){
let value = req.body().clone().unwrap();
println!("Set: {:?}", value);
redis::set(ADDRESS, KEY, &value)
.map_err(|_| anyhow!("Error executing Redis set command"))?;
}

let value = redis::get(ADDRESS, KEY)
.map_err(|_| anyhow!("Error executing Redis get command"))?;

Ok(http::Response::builder()
.status(200)
.header("foo", "bar")
.body(Some(value.into()))?)
}

0 comments on commit 4682b1a

Please sign in to comment.