{"id":13489808,"url":"https://github.com/slok/kubewebhook","last_synced_at":"2025-05-14T04:08:44.548Z","repository":{"id":33634660,"uuid":"140163415","full_name":"slok/kubewebhook","owner":"slok","description":"Go framework to create Kubernetes mutating and validating webhooks","archived":false,"fork":false,"pushed_at":"2025-03-13T01:37:30.000Z","size":11855,"stargazers_count":608,"open_issues_count":11,"forks_count":76,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-11T00:44:22.380Z","etag":null,"topics":["admission","apiserver","controller","k8s","kubernetes","mutating","validating","webhooks"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slok.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-07-08T11:54:18.000Z","updated_at":"2025-03-17T23:50:43.000Z","dependencies_parsed_at":"2024-01-14T09:59:13.416Z","dependency_job_id":"fd1e62a8-c31c-49b8-add6-522ef02bb02f","html_url":"https://github.com/slok/kubewebhook","commit_stats":{"total_commits":255,"total_committers":13,"mean_commits":"19.615384615384617","dds":0.1568627450980392,"last_synced_commit":"2574c5e1e275a8c5afa0f68fc336db10144a1178"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fkubewebhook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fkubewebhook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fkubewebhook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fkubewebhook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slok","download_url":"https://codeload.github.com/slok/kubewebhook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254069906,"owners_count":22009558,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","apiserver","controller","k8s","kubernetes","mutating","validating","webhooks"],"created_at":"2024-07-31T19:00:35.692Z","updated_at":"2025-05-14T04:08:39.495Z","avatar_url":"https://github.com/slok.png","language":"Go","funding_links":[],"categories":["Go","Operators vs Controllers"],"sub_categories":["Development Tools"],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"logo/kubewebhook_logo@0,5x.png\" width=\"30%\" align=\"center\" alt=\"kubewebhook\"\u003e\n\u003c/p\u003e\n\n# kubewebhook\n\n[![CI](https://github.com/slok/kubewebhook/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/slok/kubewebhook/actions/workflows/ci.yaml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/slok/kubewebhook)](https://goreportcard.com/report/github.com/slok/kubewebhook)\n[![GoDoc](https://godoc.org/github.com/slok/kubewebhook/v2?status.svg)][godoc-url]\n[![Apache 2 licensed](https://img.shields.io/badge/license-Apache2-blue.svg)](https://raw.githubusercontent.com/slok/kubewebhook/master/LICENSE)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/slok/kubewebhook)](https://github.com/slok/kubewebhook/releases/latest)\n![Kubernetes release](https://img.shields.io/badge/Kubernetes-v1.31-green?logo=Kubernetes\u0026style=flat\u0026color=326CE5\u0026logoColor=white)\n\nKubewebhook is a small Go framework to create [external admission webhooks][aw-url] for Kubernetes.\n\nWith Kubewebhook you can make validating and mutating webhooks in any version, fast, easy, and focusing mainly on the domain logic of the webhook itself.\n\n## Features\n\n- Ready for mutating and validating webhook kinds.\n- Abstracts webhook versioning (compatible with `v1beta1` and `v1`).\n- Resource inference (compatible with `CRD`s and fallbacks to [`Unstructured`][runtime-unstructured]).\n- Easy and testable API.\n- Simple, extensible and flexible.\n- Multiple webhooks on the same server.\n- Webhook metrics ([RED][red-metrics-url]) for [Prometheus][prometheus-url] with [Grafana dashboard][grafana-dashboard] included.\n- Webhook tracing with [Opentelemetry] support.\n- Supports [warnings].\n\n## Getting started\n\n**Use `github.com/slok/kubewebhook/v2` to import Kubewebhook `v2`.**\n\n```go\nfunc run() error {\n    logger := \u0026kwhlog.Std{Debug: true}\n\n    // Create our mutator\n    mt := kwhmutating.MutatorFunc(func(_ context.Context, _ *kwhmodel.AdmissionReview, obj metav1.Object) (*kwhmutating.MutatorResult, error) {\n        pod, ok := obj.(*corev1.Pod)\n        if !ok {\n            return \u0026kwhmutating.MutatorResult{}, nil\n        }\n\n        // Mutate our object with the required annotations.\n        if pod.Annotations == nil {\n            pod.Annotations = make(map[string]string)\n        }\n        pod.Annotations[\"mutated\"] = \"true\"\n        pod.Annotations[\"mutator\"] = \"pod-annotate\"\n\n        return \u0026kwhmutating.MutatorResult{MutatedObject: pod}, nil\n    })\n\n    // Create webhook.\n    wh, err := kwhmutating.NewWebhook(kwhmutating.WebhookConfig{\n        ID:      \"pod-annotate\",\n        Mutator: mt,\n        Logger:  logger,\n    })\n    if err != nil {\n        return fmt.Errorf(\"error creating webhook: %w\", err)\n    }\n\n    // Get HTTP handler from webhook.\n    whHandler, err := kwhhttp.HandlerFor(kwhhttp.HandlerConfig{Webhook: wh, Logger: logger})\n    if err != nil {\n        return fmt.Errorf(\"error creating webhook handler: %w\", err)\n    }\n\n    // Serve.\n    logger.Infof(\"Listening on :8080\")\n    err = http.ListenAndServeTLS(\":8080\", cfg.certFile, cfg.keyFile, whHandler)\n    if err != nil {\n        return fmt.Errorf(\"error serving webhook: %w\", err)\n    }\n\n    return nil\n```\n\nYou can get more examples in [here](examples)\n\n## Production ready example\n\nThis repository is a production ready webhook app: https://github.com/slok/k8s-webhook-example\n\nIt shows, different webhook use cases, app structure, testing domain logic, kubewebhook use case, how to deploy...\n\n## Static and dynamic webhooks\n\nWe have 2 kinds of webhooks:\n\n- Static: Common one, is a single resource type webhook.\n  - Use [`mutating.WebhookConfig.Obj`][mutating-cfg] to configure.\n  - Use [`validating.WebhookConfig.Obj`][validating-cfg] to configure.\n- Dynamic: Used when the same webhook act on multiple types, unknown types and/or is used for generic stuff (e.g labels).\n  - To use this kind of webhook, don't set the type on the configuration or set to `nil`.\n  - If a request for an unknown type is not known by the webhook libraries, it will fallback to [`runtime.Unstructured`][runtime-unstructured] object type.\n  - Very useful to manipulate multiple resources on the same webhook (e.g `Deployments`, `Statefulsets`).\n  - CRDs are unknown types so they will fallback to [`runtime.Unstructured`][runtime-unstructured]`.\n  - If using CRDs, better use `Static` webhooks.\n  - Very useful to maniputale any `metadata` based validation or mutations (e.g `Labels, annotations...`)\n\n## Compatibility matrix\n\nTo know the validated compatibility, check the integration tests on CI.\n\n| Kubewebhook | Kubernetes              | Admission reviews | Dynamic webhooks | [OpenTelemetry] tracing |\n| ----------- | ----------------------- | ----------------- | ---------------- | ----------------------- |\n| v2.7        | 1.31, 1.30, 1.29, 1.28  | v1beta1, v1       | ✔                | ✔                       |\n| v2.6        | 1.29, 1.28, 1.27, 1.26  | v1beta1, v1       | ✔                | ✔                       |\n| v2.5        | 1.25                    | v1beta1, v1       | ✔                | ✔                       |\n| v2.4        | 1.24                    | v1beta1, v1       | ✔                | ✔                       |\n| v2.3        | 1.23                    | v1beta1, v1       | ✔                | ✔                       |\n| v2.2        | 1.22                    | v1beta1, v1       | ✔                | ✔                       |\n| v2.1        | 1.21                    | v1beta1, v1       | ✔                | ✖                       |\n| v2.0        | 1.20                    | v1beta1, v1       | ✔                | ✖                       |\n| v0.11       | 1.19                    | v1beta1           | ✔                | ✖                       |\n| v0.10       | 1.18                    | v1beta1           | ✔                | ✖                       |\n| v0.9        | 1.18                    | v1beta1           | ✖                | ✖                       |\n| v0.8        | 1.17                    | v1beta1           | ✖                | ✖                       |\n| v0.7        | 1.16                    | v1beta1           | ✖                | ✖                       |\n| v0.6        | 1.15                    | v1beta1           | ✖                | ✖                       |\n| v0.5        | 1.14                    | v1beta1           | ✖                | ✖                       |\n| v0.4        | 1.13                    | v1beta1           | ✖                | ✖                       |\n| v0.3        | 1.12                    | v1beta1           | ✖                | ✖                       |\n| v0.2        | 1.11                    | v1beta1           | ✖                | ✖                       |\n| v0.2        | 1.10                    | v1beta1           | ✖                | ✖                       |\n\n## Documentation\n\nYou can access [here][godoc-url].\n\n[godoc-url]: https://pkg.go.dev/github.com/slok/kubewebhook/v2\n[aw-url]: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers\n[docs]: https://slok.github.io/kubewebhook/\n[red-metrics-url]: https://www.weave.works/blog/the-red-method-key-metrics-for-microservices-architecture/\n[prometheus-url]: https://prometheus.io/\n[grafana-dashboard]: https://grafana.com/grafana/dashboards/13685\n[mutating-cfg]: https://pkg.go.dev/github.com/slok/kubewebhook/pkg/webhook/mutating?tab=doc#WebhookConfig\n[validating-cfg]: https://pkg.go.dev/github.com/slok/kubewebhook/pkg/webhook/validating?tab=doc#WebhookConfig\n[runtime-unstructured]: https://pkg.go.dev/k8s.io/apimachinery/pkg/runtime?tab=doc#Unstructured\n[warnings]: https://kubernetes.io/blog/2020/09/03/warnings/\n[opentelemetry]: https://opentelemetry.io/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslok%2Fkubewebhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslok%2Fkubewebhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslok%2Fkubewebhook/lists"}