knete
A lightweight Python framework for building Kubernetes controllers and admission webhooks.
Features
- Controllers — watch any Kubernetes resource and react to create/update/delete events
- Validating webhooks — reject requests that violate policy
- Mutating webhooks — patch objects on the way in
- Composite mutating webhooks — fan-out multiple mutators to a single endpoint, accumulating all patches in one round-trip
- Decorator-style webhooks — register plain functions instead of subclasses
- Manifest generator —
python -m knete <file.py>generates all k8s manifests (Deployment, Service, RBAC, WebhookConfigurations) including cert-manager TLS support
Installation
pip install knete
Quick start
Controller
from knete import Controller, Manager
class PodController(Controller):
class Meta:
resource = "v1/pods"
namespace = "default"
def on_create(self, name, namespace, labels, spec):
print(f"Pod created: {namespace}/{name}")
def on_delete(self, name):
print(f"Pod deleted: {name}")
Manager().register(PodController).start()
Validating webhook
from knete import ValidatingWebhook, AdmissionResponse, WebhookServer
class NoLatestTagWebhook(ValidatingWebhook):
class Meta:
resource = "apps/v1/deployments"
operations = ["CREATE", "UPDATE"]
name = "no-latest-tag"
def validate(self, name, spec) -> AdmissionResponse:
for c in spec.get("template", {}).get("spec", {}).get("containers", []):
if c["image"].endswith(":latest") or ":" not in c["image"]:
return AdmissionResponse.deny(f"image {c['image']!r} uses :latest tag")
return AdmissionResponse.allow()
server = WebhookServer(cert_file="tls.crt", key_file="tls.key")
server.register(NoLatestTagWebhook)
server.start()
Mutating webhook
from knete import MutatingWebhook, AdmissionResponse
class InjectLabelWebhook(MutatingWebhook):
class Meta:
resource = "v1/pods"
operations = ["CREATE"]
name = "inject-label"
def mutate(self, labels) -> AdmissionResponse:
if "managed-by" in labels:
return AdmissionResponse.allow()
return AdmissionResponse.patch([
{"op": "add", "path": "/metadata/labels/managed-by", "value": "knete"},
])
Multiple validators
Register each validating webhook separately — Kubernetes calls them in parallel,
so total latency is max(validators) rather than sum(validators):
server.register(NoLatestTagWebhook) # POST /validate/no-latest-tag
server.register(RequiredLabelsWebhook) # POST /validate/required-labels
Decorator style
Skip the class entirely and register plain functions directly on the server:
server = WebhookServer(cert_file="tls.crt", key_file="tls.key")
@server.validate("apps/v1/deployments", operations=["CREATE", "UPDATE"], name="no-latest-tag")
def no_latest_tag(name, spec) -> AdmissionResponse:
for c in spec.get("template", {}).get("spec", {}).get("containers", []):
if c["image"].endswith(":latest") or ":" not in c["image"]:
return AdmissionResponse.deny(f"image {c['image']!r} uses :latest tag")
@server.mutate("v1/pods", operations=["CREATE"], name="inject-label")
def inject_label(labels) -> AdmissionResponse:
if "managed-by" not in labels:
return AdmissionResponse.patch([
{"op": "add", "path": "/metadata/labels/managed-by", "value": "knete"},
])
server.start()
Both styles can be mixed freely. name defaults to the function name if omitted.
Manifest generator
Generate all Kubernetes manifests for your operator or webhook server:
# Operator
python -m knete examples/my_operator.py --name my-operator --image my-operator:v1
# Webhook with cert-manager TLS (generates a self-signed ClusterIssuer)
python -m knete examples/my_webhook.py --name my-webhook --image my-webhook:v1 --cert-manager
# Webhook using an existing ClusterIssuer
python -m knete examples/my_webhook.py --name my-webhook --image my-webhook:v1 --cert-manager my-issuer
This writes k8s/ manifests and a Containerfile ready to build. Apply with:
kubectl apply -f k8s/
Examples
| File | What it shows |
|---|---|
examples/webhook_example.py |
Validating + mutating + composite mutating webhooks |
examples/forbid_reserved_prefixes_decorator.py |
Decorator-style validating + mutating webhooks |
examples/example.py |
Basic pod controller |
examples/kyverno_clusterrolebinding.py |
Controller equivalent of a Kyverno generate rule |
examples/kyverno_clusterrolebinding_webhook.py |
Same policy as a mutating webhook with side-effects |
Requirements
- Python 3.10+
- cert-manager (optional, for webhook TLS)
Release files for knete 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| knete-0.1.0.tar.gz | 2.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| knete-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.4 MB
Release files / knete-0.1.0.tar.gz
| Download URL | knete-0.1.0.tar.gz |
|---|---|
| Size | 2.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cd3c98826838e2bdc32f73471039be9b31380905fe1abf4336403480edc8d719
|
|
BLAKE2b-256 checksum How to use checksums |
6a34a9b3fb5dabc08b13395346015f32eaa6f1ddec9cfc285893fb92d479eff5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / knete-0.1.0-py3-none-any.whl
| Download URL | knete-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
96b05fe45d2f853d654bfb2b91d05ac6bce0c1bcc3275439615df16bc144966b
|
|
BLAKE2b-256 checksum How to use checksums |
3bb5732d76fd467286b0748cbc158af179ff52e6052d0dbc2e753240deaf5bd9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|