knete
A lightweight Python framework for building Kubernetes controllers and admission webhooks.
📖 Learn more in The Little Book of Kubernetes Operators.
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)
Metadata
Release files for knete 0.4.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 | Provenance | Actions |
|---|---|---|---|---|
| knete-0.4.0.tar.gz | 25.4 kB | Without provenance | Details for knete-0.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| knete-0.4.0-py3-none-any.whl | Python 3 | none | any | Details for knete-0.4.0-py3-none-any.whl |
Total release size: 49.5 kB
Release files / knete-0.4.0.tar.gz
| Download URL | knete-0.4.0.tar.gz |
|---|---|
| Size | 25.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4b27a629a3694c22895424cce5cff2ccbb3fa88dfe1148929007fab0b8b61330
|
|
BLAKE2b-256 checksum How to use checksums |
91ebae334ea20390c9b40e023d27b0c27620b61e850d176d1eb90ee1de827071
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / knete-0.4.0-py3-none-any.whl
| Download URL | knete-0.4.0-py3-none-any.whl |
|---|---|
| Size | 24.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4eeb473550eb5f2273e8cd17665e610137a4fbb9e83a257cd2600aa2384e7909
|
|
BLAKE2b-256 checksum How to use checksums |
752b93b277ee62f846d5a281f6b99757db4744a166ca02b0ab3a0e2a04457f57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.18
|
Security for knete 0.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.