{"id":51168015,"url":"https://github.com/bartvanbenthem/koprs","last_synced_at":"2026-06-26T21:30:27.378Z","repository":{"id":358461884,"uuid":"1241415788","full_name":"bartvanbenthem/koprs","owner":"bartvanbenthem","description":"A collection of reusable Rust libraries for Kubernetes operator development, enabling operators built with significantly less code.","archived":false,"fork":false,"pushed_at":"2026-06-12T10:51:54.000Z","size":330,"stargazers_count":16,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T11:11:25.124Z","etag":null,"topics":["controllers","kube-rs","kubernetes","operator-sdk","operators","rust","rust-lang"],"latest_commit_sha":null,"homepage":"https://docs.rs/crate/koprs/latest","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bartvanbenthem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T11:10:29.000Z","updated_at":"2026-06-12T10:51:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bartvanbenthem/koprs","commit_stats":null,"previous_names":["bartvanbenthem/kube-genops","bartvanbenthem/operator-framework-rs","bartvanbenthem/operator-sdk-rs","bartvanbenthem/koprs"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/bartvanbenthem/koprs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartvanbenthem%2Fkoprs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartvanbenthem%2Fkoprs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartvanbenthem%2Fkoprs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartvanbenthem%2Fkoprs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bartvanbenthem","download_url":"https://codeload.github.com/bartvanbenthem/koprs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bartvanbenthem%2Fkoprs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34834415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["controllers","kube-rs","kubernetes","operator-sdk","operators","rust","rust-lang"],"created_at":"2026-06-26T21:30:26.821Z","updated_at":"2026-06-26T21:30:27.371Z","avatar_url":"https://github.com/bartvanbenthem.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kubernetes Operators in Rust\n\n[`koprs`](./crates/koprs) is a high-level Kubernetes operator library for Rust. [`koprs-external`](./crates/koprs-external) bridges HTTP endpoints and object stores (S3) into the same channel-based event model. [`koprs-admission`](./crates/koprs-admission) provides a typed validating admission webhook server.\n\nOperators simplify managing complex stateful applications on Kubernetes, but writing them remains difficult: low-level APIs, boilerplate, and poor modularity all add friction. Koprs is a Rust framework built on [`kube`](https://github.com/kube-rs/kube) and [`kube-runtime`](https://crates.io/crates/kube-runtime) that addresses this with high-level abstractions and extensions for common Operator use cases.\n\nThis repository contains the core framework, external polling helpers, admission webhook support, and example operators.\n\n## Crates\n\n| Crate | Description | Docs |\n|-------|-------------|------|\n| [`koprs`](./crates/koprs) | Core Kubernetes operator framework | [![docs.rs](https://img.shields.io/docsrs/koprs)](https://docs.rs/koprs) [![crates.io](https://img.shields.io/crates/v/koprs)](https://crates.io/crates/koprs) |\n| [`koprs-external`](./crates/koprs-external) | HTTP and object-store polling watchers | [![docs.rs](https://img.shields.io/docsrs/koprs-external)](https://docs.rs/koprs-external) [![crates.io](https://img.shields.io/crates/v/koprs-external)](https://crates.io/crates/koprs-external) |\n| [`koprs-admission`](./crates/koprs-admission) | Validating admission webhook server | [![docs.rs](https://img.shields.io/docsrs/koprs-admission)](https://docs.rs/koprs-admission) [![crates.io](https://img.shields.io/crates/v/koprs-admission)](https://crates.io/crates/koprs-admission) |\n\n## Workspace layout\n\n```\nkoprs/\n├── Cargo.toml                  # workspace manifest\n├── Cargo.lock\n├── crates/\n│   ├── koprs/                  # core Kubernetes operator framework\n│   ├── koprs-external/         # HTTP and object-store polling watchers\n│   └── koprs-admission/        # validating admission webhook server\n└── examples/\n    ├── configmapsync/          # single CRD, single controller\n    └── multicontroller/        # multiple CRDs, multiple controllers in one operator\n```\n\n## Getting started\n\nIf you are here to build a Kubernetes operator, you want [`koprs`](./crates/koprs). Start there.\n\nFor working end-to-end examples, see:\n\n* [configmapsync](./examples/configmapsync/README.md) — a single CRD reconciled by one controller; the best starting point.\n* [multicontroller](./examples/multicontroller/README.md) — multiple CRDs (`SecretSync`, `ServiceAccountSync`) each reconciled by its own controller, run side by side in one operator binary.\n\n### Minimal example\n\nA `koprs` operator boils down to three pieces: a CRD type, a [`Reconciler`](./crates/koprs/src/controller.rs),\nand a [`ControllerBuilder`](./crates/koprs/src/controller.rs) that wires it all together.\n\n```rust,no_run\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse kube::{Api, Client, CustomResource, ResourceExt};\nuse schemars::JsonSchema;\nuse serde::{Deserialize, Serialize};\n\nuse koprs::controller::{Action, Context, ControllerBuilder, Reconciler};\nuse koprs::error::KubeGenericError;\nuse koprs::status::patch_status_namespaced;\n\n/// The `Greeting` CRD — `kube::CustomResource` derives the type, its CRD spec,\n/// and the generated `Greeting` struct (spec + status + metadata) in one go.\n#[derive(CustomResource, Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]\n#[kube(\n    group = \"example.io\",\n    version = \"v1alpha1\",\n    kind = \"Greeting\",\n    namespaced,\n    status = \"GreetingStatus\"\n)]\npub struct GreetingSpec {\n    pub message: String,\n}\n\n#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]\npub struct GreetingStatus {\n    pub ready: bool,\n}\n\nstruct GreetingReconciler;\n\nimpl Reconciler\u003cGreeting\u003e for GreetingReconciler {\n    type Error = KubeGenericError;\n\n    async fn reconcile(\u0026self, cr: Arc\u003cGreeting\u003e, ctx: Arc\u003cContext\u003e) -\u003e Result\u003cAction, Self::Error\u003e {\n        let name = cr.name_any();\n        let namespace = cr\n            .namespace()\n            .ok_or(KubeGenericError::MissingMetadata(\"namespace\".into()))?;\n\n        // Mark the resource ready — replace with your own reconciliation logic.\n        patch_status_namespaced::\u003cGreeting, GreetingStatus\u003e(\n            ctx.client.clone(),\n            \u0026namespace,\n            \u0026name,\n            GreetingStatus { ready: true },\n            \"greeting-operator\",\n        )\n        .await?;\n\n        Ok(Action::requeue(Duration::from_secs(300)))\n    }\n    // error_policy defaults to requeue(30s) — override it for custom backoff\n}\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let client = Client::try_default().await?;\n    let api: Api\u003cGreeting\u003e = Api::all(client.clone());\n    let ctx = Context::new(client);\n\n    ControllerBuilder::new(api)\n        .health_port(8080)\n        .graceful_shutdown()\n        .run(GreetingReconciler, ctx)\n        .await?;\n\n    Ok(())\n}\n```\n\nFor finalizers, owned-resource reconciliation, garbage collection, events, and leader\nelection, see the [configmapsync operator](./examples/configmapsync/README.md), it\nwalks through the same building blocks in a complete, runnable operator. To see how to\nrun several CRDs and controllers from a single operator binary, see\n[multicontroller](./examples/multicontroller/README.md).\n\n## Contributing\n\nContributions are welcome. Please open an issue before submitting a pull request for \nanything beyond small fixes, so the approach can be agreed on first.\n\n### Prerequisites\n\n- Rust stable toolchain\n- A local Kubernetes cluster for integration tests ([kind](https://kind.sigs.k8s.io/) recommended)\n\n### Build\n\n```bash\n# build all crates\ncargo build\n\n# build a specific crate\ncargo build -p koprs\n```\n\n### Test\n\n```bash\n# unit tests (no cluster required)\ncargo test\n\n# integration tests\nkind create cluster --name koprs-test\n\ncargo test --features integration --test integration\n\nkind delete cluster --name koprs-test\n```\n\n### CI\n\n[![CI](https://github.com/bartvanbenthem/koprs/actions/workflows/ci.yml/badge.svg)](https://github.com/bartvanbenthem/koprs/actions/workflows/ci.yml)\n\n`cargo-ci.sh` runs all quality checks in sequence — format, type-check,\nunit tests, integration tests, coverage, release build, docs, and audit.\n\n```bash\n./scripts/cargo-ci.sh                           # run all steps\n./scripts/cargo-ci.sh --fast                    # fmt + check + unit tests only (no coverage)\n./scripts/cargo-ci.sh --no-audit                # skip cargo-audit\n./scripts/cargo-ci.sh --no-integration          # skip integration tests\n./scripts/cargo-ci.sh --no-doc                  # skip cargo doc\n./scripts/cargo-ci.sh --no-coverage             # skip llvm-cov coverage report\n./scripts/cargo-ci.sh --bench                   # also compile benchmarks (slow, opt-in)\n./scripts/cargo-ci.sh --coverage-fail-under=80  # fail if line coverage drops below N%\n```\n\n### Publishing\n\n`publish.sh` handles the full pre-flight and publishes the crate to crates.io.\n\n```bash\n./scripts/publish.sh                    # full pre-flight + publish\n./scripts/publish.sh --dry-run          # stop before cargo publish\n./scripts/publish.sh --skip-ci          # skip CI checks, publish only\n./scripts/publish.sh --crate koprs      # publish a single crate\n```\n\nSee the [CI script docs](./scripts/cargo-ci.sh) for the full list of flags.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbartvanbenthem%2Fkoprs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbartvanbenthem%2Fkoprs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbartvanbenthem%2Fkoprs/lists"}