{"id":48581250,"url":"https://github.com/wenisch-tech/chronoreaper","last_synced_at":"2026-05-31T22:00:46.419Z","repository":{"id":349821454,"uuid":"1203935439","full_name":"wenisch-tech/ChronoReaper","owner":"wenisch-tech","description":"A Kubernetes Operator built with Quarkus and the Java Operator SDK (JOSDK) that automatically deletes resources once a timestamp defined as annotation has passed.","archived":false,"fork":false,"pushed_at":"2026-05-31T20:05:10.000Z","size":103,"stargazers_count":0,"open_issues_count":13,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T20:06:10.535Z","etag":null,"topics":["auto-delete","k8s","k8s-operators","operator"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wenisch-tech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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-04-07T14:27:39.000Z","updated_at":"2026-05-31T20:05:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/wenisch-tech/ChronoReaper","commit_stats":null,"previous_names":["wenisch-tech/k8s-ttl-operator","wenisch-tech/chronoreaper"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/wenisch-tech/ChronoReaper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenisch-tech%2FChronoReaper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenisch-tech%2FChronoReaper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenisch-tech%2FChronoReaper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenisch-tech%2FChronoReaper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wenisch-tech","download_url":"https://codeload.github.com/wenisch-tech/ChronoReaper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenisch-tech%2FChronoReaper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33750474,"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-05-31T02:00:06.040Z","response_time":95,"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":["auto-delete","k8s","k8s-operators","operator"],"created_at":"2026-04-08T17:00:52.591Z","updated_at":"2026-05-31T22:00:46.401Z","avatar_url":"https://github.com/wenisch-tech.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ChronoReaper\n\n[![GitHub Release](https://img.shields.io/github/v/release/wenisch-tech/chronoreaper?logo=github)](https://github.com/wenisch-tech/Kairos/releases)\n[![License: AGPL v3](https://img.shields.io/badge/License-AGPLv3-blue.svg)](LICENSE.md)\n[![Container](https://img.shields.io/badge/container-ghcr.io-blue?logo=github)](https://github.com/wenisch-tech/chronoreaper/pkgs/container/chronoreaper)\n[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/kairos)](https://artifacthub.io/packages/helm/jfwenisch/chronoreaper)\n[![Signed](https://img.shields.io/badge/signed-cosign-green?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0xMiAxTDMgNXY2YzAgNS41NSAzLjg0IDEwLjc0IDkgMTIgNS4xNi0xLjI2IDktNi40NSA5LTEyVjVsLTktNHoiLz48L3N2Zz4=)](https://github.com/wenisch-tech/chronoreaper/actions)\n\nChronoReaper is a Kubernetes Operator built with [Quarkus](https://quarkus.io) and the\n[Java Operator SDK (JOSDK)](https://javaoperatorsdk.io) that automatically deletes resources once a timestamp defined as annotation has passed passed.\n\nDeployable via\n[Helm](https://helm.sh) or the\n[Operator Lifecycle Manager (OLM)](https://olm.operatorframework.io) /\n[OperatorHub.io](https://operatorhub.io).\n\n\n\n## How it works\n\nAdd the `wenisch.tech/ttl` annotation to **any** Kubernetes resource. When the\nspecified timestamp is reached, the operator automatically deletes the resource.\n\nThe operator polls all resource types every 60 seconds (configurable).\n\n\n### Annotation format\n\nTwo timestamp formats are supported:\n\n#### ISO-8601 UTC\n\n```yaml\nmetadata:\n  annotations:\n    wenisch.tech/ttl: \"2025-12-31T23:59:59Z\"\n```\n\n#### Unix epoch seconds\n\n```yaml\nmetadata:\n  annotations:\n    wenisch.tech/ttl: \"1775666164\"\n```\n\n\u003e If the value cannot be parsed in either format, an **error** is logged and\n\u003e the resource is left untouched.\n\n---\n\n## Supported resource types\n\n| Category         | Resources |\n|------------------|-----------|\n| **Workloads**    | `Pod`, `Deployment`, `ReplicaSet`, `StatefulSet`, `DaemonSet`, `Job`, `CronJob` |\n| **Networking**   | `Service`, `Ingress` |\n| **Configuration**| `ConfigMap`, `Secret`, `ServiceAccount` |\n| **Cluster-scoped** | `Namespace`, `CustomResourceDefinition`, `ClusterRole`, `ClusterRoleBinding` |\n| **Custom resources** | All installed CRDs are discovered and checked dynamically |\n\n---\n\n## Quick start\n\n### Option 1 — Helm\n\n```bash\nhelm install chronoreaper helm/chronoreaper \\\n  --namespace chronoreaper \\\n  --create-namespace\n```\n\nCommon overrides:\n\n```bash\nhelm install chronoreaper helm/chronoreaper \\\n  --namespace chronoreaper \\\n  --create-namespace \\\n  --set operator.checkInterval=30s \\   # poll every 30 s\n  --set operator.dryRun=true           # log only, no actual deletion\n```\n\n### Option 2 — OLM / OperatorHub\n\n1. Install OLM (if not already present):\n\n   ```bash\n   operator-sdk olm install\n   ```\n\n2. Apply the bundle manifests:\n\n   ```bash\n   kubectl apply -f bundle/manifests/\n   ```\n\n3. Or search for **ChronoReaper** on [OperatorHub.io](https://operatorhub.io)\n   and follow the one-click install.\n\n---\n\n## Example resources\n\n### Pod — expires at a fixed date\n\n```yaml\napiVersion: v1\nkind: Pod\nmetadata:\n  name: temp-pod\n  namespace: default\n  annotations:\n    wenisch.tech/ttl: \"2025-06-30T00:00:00Z\"\nspec:\n  containers:\n    - name: app\n      image: alpine:latest\n      command: [\"sleep\", \"infinity\"]\n```\n\n### Deployment — expires via Unix epoch\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: temp-deploy\n  namespace: default\n  annotations:\n    wenisch.tech/ttl: \"1775666164\"   # 2026-03-06T06:36:04Z\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: temp\n  template:\n    metadata:\n      labels:\n        app: temp\n    spec:\n      containers:\n        - name: app\n          image: nginx:latest\n```\n\n### Namespace — self-destructing sandbox\n\n```yaml\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: sandbox-abc123\n  annotations:\n    wenisch.tech/ttl: \"1800000000\"\n```\n\n---\n\n## Configuration\n\n| Helm value | Env variable | Default | Description |\n|---|---|---|---|\n| `operator.checkInterval` | `TTL_CHECK_INTERVAL` | `60s` | How often to scan all resources (ISO-8601 duration) |\n| `operator.dryRun` | `TTL_DRY_RUN` | `false` | Log deletions without executing them |\n\n### `application.properties` keys\n\n| Key | Default | Description |\n|-----|---------|-------------|\n| `ttl.check.interval` | `60s` | Polling interval |\n| `ttl.dry-run` | `false` | Dry-run mode |\n\n---\n\n## Observability\n\n### Health probes\n\n| Probe | Path | Port |\n|-------|------|------|\n| Liveness | `/q/health/live` | `8081` |\n| Readiness | `/q/health/ready` | `8081` |\n\n### Prometheus metrics (port `8081`, path `/q/metrics`)\n\n| Metric | Description |\n|--------|-------------|\n| `ttl_operator_resources_deleted_total` | Total resources deleted since startup |\n| `ttl_operator_errors_total` | Total errors encountered since startup |\n\n---\n\n## Development\n\n### Prerequisites\n\n| Tool | Minimum version |\n|------|-----------------|\n| Java | 17 |\n| Apache Maven | 3.9 |\n| Docker / Podman | any recent version |\n\n### Build\n\n```bash\nmvn package -DskipTests\n```\n\n### Run tests\n\n```bash\nmvn test\n```\n\n### Run locally (dev mode with live-reload)\n\n```bash\nmvn quarkus:dev\n```\n\n\u003e Requires a reachable kubeconfig (`~/.kube/config`) or an in-cluster\n\u003e `KUBERNETES_SERVICE_HOST`. Outside a cluster, ensure\n\u003e `quarkus.kubernetes-client.devservices.enabled=false` is set (already the\n\u003e default in `%dev` profile).\n\n### Build the container image\n\n```bash\ndocker build -t wenisch-tech/chronoreaper:latest .\ndocker push wenisch-tech/chronoreaper:latest\n```\n\n\n\n## License\n\n[GNU Affero General Public License v3.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenisch-tech%2Fchronoreaper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwenisch-tech%2Fchronoreaper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenisch-tech%2Fchronoreaper/lists"}