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.1

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.1
File Size Uploaded Provenance Actions
knete-0.4.1.tar.gz 25.4 kB Without provenance Details for knete-0.4.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for knete 0.4.1
File Interpreter ABI Platform Actions
knete-0.4.1-py3-none-any.whl Python 3 none any Details for knete-0.4.1-py3-none-any.whl

Total release size: 49.5 kB

Release files / knete-0.4.1.tar.gz

Download URL knete-0.4.1.tar.gz
Size 25.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ea0315fc0fe66d1cdb8f63c4782b95fa0556689338052bc65cec7a88bfe77d1c
BLAKE2b-256 checksum
How to use checksums
aba818e4152bfa94b0f6091937069990a35923b03dad8c3e4a147607985c5c11
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.1-py3-none-any.whl

Download URL knete-0.4.1-py3-none-any.whl
Size 24.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
397b6596fbca9724a56ff527a78fce016fe7c0a8b072fa251426b1d6d07b7bc8
BLAKE2b-256 checksum
How to use checksums
7efda52c79c58a867163be3796bf0878cb028ce9f797d920680f6724f5d8055a
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.1

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