The "Useless Machine" is a distributed, "Zero-Split-Brain" cloud-native system built to explore modern cloud patterns including WebAssembly (WASM), Kubernetes Operators, and the Spin framework.
A physical "Useless Machine" is a box with a switch; when you flip the switch on, a mechanical finger immediately pops out and flips it back off. This project translates that concept into a resilient, distributed software architecture.
- What it is: The pure, isolated logic core written in Rust.
- How it works: It uses the Extism PDK. It doesn't know about Kubernetes, HTTP, or Spin. It takes in a JSON payload representing the current state of the machine (e.g.,
daily_count,last_pushed) and the current time. It applies pure functional logic:- Push: Increments the daily count and updates the timestamp.
- Status: Checks if you've gone more than 24 hours without pushing the button. If so, it flags
is_nagging: true(because you're neglecting your duties to the useless machine).
- Why it's cool: By compiling this to WASM, the logic is universally portable and executed in a secure, sandboxed environment.
- What it is: A custom Kubernetes controller written in Go using Kubebuilder.
- How it works: It introduces a Custom Resource Definition (CRD) called
UselessMachine. The operator continuously watches the Kubernetes API for changes to this resource.- When it sees a
UselessMachinewhere thespec.actionhas been patched to"push", it spins up the WASM Brain using theextism/go-sdk. - It feeds the current status to the Brain, receives the updated state, updates the
statusblock in Kubernetes, and clears theactionrequest.
- When it sees a
- Why it's cool: It turns the "finger" of the useless machine into an autonomous reconcile loop. Kubernetes itself enforces the desired state (turning the switch back off).
- What it is: A WebAssembly microservice built with the Spin framework.
- How it works: It acts as the HTTP gateway to the machine, exposing
/statusand/pushendpoints. When a user hits/push, the API server makes an authenticated HTTP PATCH request to the Kubernetes API server, setting theUselessMachine'sactionto"push". - Deployment: When running inside Kubernetes, it uses the
Spintainer(Spin container executor) with Spin v4.0.0. This allows it to run as a standard Kubernetes container, mount the Kubernetes ServiceAccount token, and trust the cluster's CA Certificate (cluster-ca), allowing the Spin HTTP client to securely talk to the cluster's internal API. When deployed to Fermyon Cloud, it requires a publicly accessible Kubernetes API URL and token.
- What it is: A Go-based command-line interface for the user.
- How it works: It provides simple commands (
useless push,useless status). It supports swappable backends:--backend k8s: Talks directly to Kubernetes (likekubectl).--backend api: Talks to the Spin API Gateway.
- Why it's cool: It hides all the distributed complexity from the end user, giving them a simple remote control.
When a user executes ./useless push --backend api, the following sequence occurs:
- CLI: Sends an HTTP POST to the Spin API
/pushendpoint. - Spin API: Uses its injected K8s ServiceAccount token (or configured Fermyon Cloud variables) to issue an HTTP PATCH to the K8s API server, setting
spec.action: "push"on theglobalUselessMachine CRD. - K8s API: Accepts the patch and notifies watchers.
- Operator: Detects the change in the CRD. It loads
brain.wasminto the Extism runtime, passing the current count and timestamp. - WASM Brain: Computes the new count (e.g.,
1 -> 2) and returns the state. - Operator: Updates the CRD's
statuswith the new count and resetsspec.actionto empty (flipping the switch back off). - CLI: The user runs
./useless status, which asks the API, which queries K8s, and shows the newly incremented count.
The project uses GitHub Actions for continuous integration and delivery. The pipeline is defined in .github/workflows/main.yml and performs the following:
- Automated Builds: Compiles the Go CLI, Rust WASM Brain, Spin API, and Android app on every push and pull request.
- Testing: Runs unit tests for all components.
- Binary Distribution: On version tags (
v*), the pipeline uploads the CLI binary, WASM modules, and Android APK as release artifacts. - Container Publishing: Builds the
vind-box-operatorOCI image with the embedded Brain and pushes it to the GitHub Container Registry (GHCR). - GitOps Integration: Pushes the
deploy/directory as a Flux OCI artifact to GHCR, enabling automated GitOps deployments.
During the implementation of version 0.0.2, we discovered a gap in the SpinKube ecosystem regarding Kubernetes API authentication.
- The Spintainer Concession: To allow the Spin API (compiled to WASM) to securely communicate with the Kubernetes API, it requires the cluster's internal CA Certificate and a ServiceAccount token. Injecting these via standard Kubernetes volumes into the pure
containerd-shim-spin(Runtime Class Manager) proved difficult. As a concession, we utilize the Spintainer (spintainer-v4) SpinAppExecutor, which runs theghcr.io/spinframework/spin:v4.0.0image as a standard container. This allows us to use native Kubernetes volume mounts for the CA cert and token. - Upstream Goal: We aim to work with the Spin and Kubernetes communities to natively support certificate and OIDC/token injection in the shim, allowing WASM apps to interact with the K8s API seamlessly without needing a containerized executor wrapper.
- WebSockets (The SpinKube Advantage): The v0.1.0 roadmap includes replacing client polling with WebSockets or Server-Sent Events (SSE). While serverless platforms (like Spin Cloud) often discourage or aggressively terminate long-lived connections to scale to zero, deploying our Spin API in SpinKube means we control the infrastructure. We can easily support persistent real-time connections for our clients, demonstrating the flexibility of self-hosted WASM workloads.