{"id":47743492,"url":"https://github.com/cocoonstack/cocoon-webhook","last_synced_at":"2026-07-04T12:00:39.031Z","repository":{"id":348486645,"uuid":"1198352240","full_name":"cocoonstack/cocoon-webhook","owner":"cocoonstack","description":"Kubernetes admission webhook for sticky scheduling of VM-backed pods. Derives stable VM names from pod owner chains, looks up previously associated workers, and patches spec.nodeName to keep pods on the same node where snapshots and local state reside. Validates scale-down to prevent accidental state destruction.","archived":false,"fork":false,"pushed_at":"2026-06-29T07:18:08.000Z","size":234,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-29T08:16:45.686Z","etag":null,"topics":["admission-controller","ai","cloud","cocoon","container","kubernetes","microvm","sandbox","scheduling","virtual-machine","vm","webhook"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cocoonstack.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-01T10:46:26.000Z","updated_at":"2026-06-29T06:46:12.000Z","dependencies_parsed_at":"2026-05-25T12:00:49.503Z","dependency_job_id":null,"html_url":"https://github.com/cocoonstack/cocoon-webhook","commit_stats":null,"previous_names":["cocoonstack/cocoon-webhook"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/cocoonstack/cocoon-webhook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoonstack%2Fcocoon-webhook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoonstack%2Fcocoon-webhook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoonstack%2Fcocoon-webhook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoonstack%2Fcocoon-webhook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cocoonstack","download_url":"https://codeload.github.com/cocoonstack/cocoon-webhook/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocoonstack%2Fcocoon-webhook/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35120682,"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-07-04T02:00:05.987Z","response_time":113,"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":["admission-controller","ai","cloud","cocoon","container","kubernetes","microvm","sandbox","scheduling","virtual-machine","vm","webhook"],"created_at":"2026-04-03T00:12:30.783Z","updated_at":"2026-07-04T12:00:39.016Z","avatar_url":"https://github.com/cocoonstack.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cocoon-webhook\n\nKubernetes admission webhook for the [cocoonstack](https://github.com/cocoonstack) VM platform.\n\n## Overview\n\ncocoon-webhook hosts three admission endpoints:\n\n| Endpoint | Type | Resources | What it does |\n|---|---|---|---|\n| `POST /mutate` | Mutating | Pod CREATE | Rejects cocoon-tolerated pods that are not owned by a CocoonSet. CocoonSet-owned pods pass through unmutated. |\n| `POST /validate` | Validating | Deployment / StatefulSet UPDATE | Rejects scale-down on cocoon-tolerated workloads. Bypass path for hand-rolled Deployments/StatefulSets carrying the cocoon toleration — the CocoonSet main flow creates Pods directly and does not traverse this endpoint. |\n| `POST /validate-cocoonset` | Validating | CocoonSet CREATE / UPDATE | Catches the cross-field business rules the CRD's OpenAPI schema cannot express (image required, toolbox name uniqueness, static-mode prerequisites). |\n| `GET /healthz` | Liveness | — | Always 200 once the binary is running. |\n| `GET /readyz` | Readiness | — | Always 200 once the binary is running (liveness-equivalent stub; does not probe apiserver reachability). |\n| `GET /metrics` | Prometheus | — | Plain HTTP on `:9090`, separate from the admission TLS port. |\n\n## CocoonSet validation rules\n\nThe CRD ships with `+kubebuilder` enum / required / default markers, but the webhook adds the cross-field business rules:\n\n- `spec.agent.image` must be set\n- `spec.agent.replicas \u003e= 0`\n- `spec.agent.mode ∈ {clone, run}`\n- `spec.agent.os ∈ {linux, windows, android}`\n- `spec.agent.backend ∈ {cloud-hypervisor, firecracker}`\n- `spec.agent.connType ∈ {ssh, rdp, vnc, adb}`\n- firecracker + `os=windows` is rejected (FC cannot boot Windows guests)\n- firecracker + cloudimg URL image is rejected (FC requires OCI images)\n- firecracker + `mode=clone` is rejected (FC snapshot/restore freezes guest network state; use `mode=run`)\n- `spec.toolboxes[*].name` unique and matches RFC 1123\n- `spec.toolboxes[*]` static mode requires both `staticIP` and `staticVMID`\n- `spec.toolboxes[*]` non-static modes require `image`\n- `spec.toolboxes[*].backend` must match `spec.agent.backend` (static toolboxes skip this check)\n- `spec.toolboxes[*]` static-mode entries must declare a valid `connType` (`ssh` / `rdp` / `vnc` / `adb`)\n- `spec.snapshotPolicy ∈ {always, main-only, never}`\n\n## Configuration\n\n| Variable | Default | Description |\n|---|---|---|\n| `KUBECONFIG` | unset | Path to kubeconfig when running outside the cluster (in-cluster config used otherwise) |\n| `WEBHOOK_LOG_LEVEL` | `info` | `projecteru2/core/log` level |\n| `TLS_CERT` | `/etc/cocoon/webhook/certs/tls.crt` | TLS server certificate |\n| `TLS_KEY` | `/etc/cocoon/webhook/certs/tls.key` | TLS server private key |\n| `LISTEN_ADDR` | `:8443` | Admission listener (HTTPS) |\n| `METRICS_ADDR` | `:9090` | Prometheus listener (HTTP) |\n\n## Installation\n\nThe supported install path is `kubectl apply -k`:\n\n```bash\nkubectl apply -k github.com/cocoonstack/cocoon-webhook/config/default?ref=main\n```\n\nThis installs:\n- `cocoon-system` namespace\n- `ServiceAccount` + `ClusterRole` (read deployments/statefulsets for scale-down validation)\n- cert-manager `Issuer` + `Certificate` (`cocoon-webhook-tls`) — **cert-manager must already be installed in the cluster**\n- `Deployment` (2 replicas) + `Service` (port 443 → 8443, port 9090 → 9090)\n- `MutatingWebhookConfiguration` for Pod CREATE\n- `ValidatingWebhookConfiguration` for Deployment/StatefulSet UPDATE and CocoonSet CREATE/UPDATE\n\nTo override the image tag or replica count, build a kustomize overlay that imports `config/default` as a base.\n\n## Development\n\n```bash\nmake all            # full pipeline: deps + fmt + lint + test + build\nmake build          # build cocoon-webhook binary\nmake test           # vet + race-detected tests\nmake lint           # golangci-lint on linux + darwin\nmake fmt            # gofumpt + goimports\nmake help           # show all targets\n```\n\nThe Makefile detects Go workspace mode (`go env GOWORK`) and skips `go mod tidy` when active so cross-module references resolve through `go.work` without forcing a release of cocoon-common.\n\n## Related projects\n\n| Project | Role |\n|---|---|\n| [cocoon-common](https://github.com/cocoonstack/cocoon-common) | CRD types, annotation contract, shared helpers |\n| [cocoon-operator](https://github.com/cocoonstack/cocoon-operator) | CocoonSet and CocoonHibernation reconcilers |\n| [epoch](https://github.com/cocoonstack/epoch) | Snapshot registry and storage backend |\n| [vk-cocoon](https://github.com/cocoonstack/vk-cocoon) | Virtual kubelet provider managing VM lifecycle |\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcocoonstack%2Fcocoon-webhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcocoonstack%2Fcocoon-webhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcocoonstack%2Fcocoon-webhook/lists"}