Skip to main content

knete

Documentation Status

knete logo

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)

Source distribution for knete 0.4.0
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)

Table of built distributions (wheels) for knete 0.4.0
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page