| Crates.io | seppo |
| lib.rs | seppo |
| version | 0.1.0 |
| created_at | 2025-12-27 19:00:18.663369+00 |
| updated_at | 2025-12-27 19:00:18.663369+00 |
| description | Kubernetes testing framework with multi-cloud cluster management |
| homepage | |
| repository | https://github.com/yairfalse/seppo |
| max_upload_size | |
| id | 2007675 |
| size | 520,160 |
Kubernetes SDK for Rust. No YAML. No CLI. Just code.
This is a learning project - exploring Kubernetes SDK patterns in Rust.
use seppo::Context;
let ctx = Context::new().await?;
ctx.apply(&deployment).await?;
ctx.wait_ready("deployment/myapp").await?;
The problem: Kubernetes tooling is fragmented. You write YAML, shell out to kubectl, maintain bash scripts, and wrestle with templating engines. Your "infrastructure as code" isn't really code—it's configuration files with code-like aspirations.
The vision: What if Kubernetes operations were just... code? Real code. In your language. With types, IDE support, and compile-time checks.
Seppo makes Kubernetes a library call:
// This is your deployment. No YAML.
let deployment = DeploymentFixture::new("myapp")
.image("myapp:v1")
.replicas(3)
.port(8080)
.build();
ctx.apply(&deployment).await?;
ctx.wait_ready("deployment/myapp").await?;
No YAML. No kubectl. No templating. Just Rust.
The goal: you should never need to write YAML again.
┌──────────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Context::new() │────▶│ Context │────▶│ Kubernetes │
│ (your code) │ │ (namespace) │ │ (any cluster)│
└──────────────────┘ └─────────────────┘ └──────────────┘
│ │
│ ├── apply() → create resources
│ ├── get/list() → read resources
│ ├── delete() → remove resources
│ ├── wait_ready() → poll until ready
│ ├── port_forward() → port forward
│ ├── exec() → run commands
│ └── logs() → stream logs
Each Context manages a namespace. Resources are created via kube-rs. The optional #[seppo::test] macro adds automatic cleanup and failure diagnostics.
[dependencies]
seppo = "0.1"
Requires a Kubernetes cluster (Kind, Minikube, EKS, GKE, etc.)
use seppo::Context;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ctx = Context::new().await?;
ctx.apply(&my_deployment).await?;
ctx.wait_ready("deployment/myapp").await?;
// Your operations here...
ctx.cleanup().await?;
Ok(())
}
use seppo::Context;
#[seppo::test]
async fn test_my_app(ctx: Context) {
ctx.apply(&deployment).await?;
ctx.wait_ready("deployment/myapp").await?;
let pf = ctx.port_forward("svc/myapp", 8080).await?;
assert!(pf.get("/health").await?.contains("ok"));
}
// Cleanup automatic on success, diagnostics on failure
use seppo::deployment;
let deploy = deployment("myapp")
.image("nginx:latest")
.replicas(3)
.port(80)
.env("LOG_LEVEL", "debug")
.label("tier", "frontend")
.build();
ctx.apply(&deploy).await?;
use seppo::stack;
let s = stack()
.service("frontend")
.image("fe:v1")
.replicas(2)
.port(80)
.service("backend")
.image("be:v1")
.replicas(3)
.port(8080)
.service("db")
.image("postgres:15")
.port(5432)
.build();
ctx.up(&s).await?;
use seppo::eventually;
eventually(|| async {
let pods: Vec<Pod> = ctx.list().await?;
Ok(pods.len() >= 3)
})
.timeout(Duration::from_secs(60))
.await?;
When tests fail, Seppo keeps the namespace and dumps diagnostics:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SEPPO TEST FAILED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Namespace: seppo-test-a1b2c3d4 (kept for debugging)
─── Pod Logs ───────────────────────────────────────────────────
[myapp-xyz123]
ERROR: Connection refused to postgres:5432
─── Events ─────────────────────────────────────────────────────
• 10:42:00 Pod/myapp Scheduled Assigned to node-1
• 10:42:01 Pod/myapp BackOff Image pull error
─── Debug ──────────────────────────────────────────────────────
kubectl -n seppo-test-a1b2c3d4 get all
kubectl delete ns seppo-test-a1b2c3d4
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
| Category | Features |
|---|---|
| Core | Context, apply/get/list/delete, wait_ready |
| Network | Port forwarding, exec, logs |
| Builders | DeploymentFixture, PodFixture, ServiceFixture, Stack |
| Testing | #[seppo::test], eventually/consistently, assertions |
| Diagnostics | Pod logs, events, failure reports |
| Providers | Kind, Minikube, existing clusters |
| Assertions | Semantic assertions on pods, deployments, services |
| Phase | Goal |
|---|---|
| 0 | Rebrand as SDK, expose Context::new() standalone |
| 1 | Complete primitives: patch, watch, copy, diff |
| 2 | Helm/Kustomize import, migration CLI |
| 3 | Operational: scale, rollback, restart, drain |
| 4 | Multi-cluster, impersonation, audit |
Seppo (Finnish smith god from Kalevala) - Part of a Finnish tool naming theme:
Apache-2.0