Skip to content

Repository files navigation

zig-klient

A Kubernetes client library for Zig — 65 resource types across 20 API groups with full CRUD, current through Kubernetes 1.36. Native WebSocket support for Pod exec/attach/port-forward, and Protobuf serialization via zig-protobuf.

Build Zig 0.16.0
Coverage 65 resource types / 20 API groups, current through K8s 1.36
Tested Live CRUD verified on Rancher Desktop K8s 1.36.1 (incl. MutatingAdmissionPolicy); every type unit-tested
Deps zig-yaml, zig-protobuf
License MIT

Contents: Features · Installation · Quick Start · Resource Operations · Testing · Architecture · Requirements · Roadmap

Connecting & TLS. Custom CA certificates are supported via tls_config.ca_cert_data / tls_config.ca_cert_path, and client-certificate auth via client_cert_data / client_key_data. Against clusters with self-signed certificates the direct TLS path may currently fail with error.TlsInitializationFailed (a std.crypto.tls limitation). Workaround: use connectWithFallback(), or run kubectl proxy and connect to http://127.0.0.1:8080.

Features

Resource Coverage (65 Resources Across 20 API Groups)

Core API (v1) - 17 resources
Pod, Service, ConfigMap, Secret, Namespace, Node, PersistentVolume, PersistentVolumeClaim, ServiceAccount, Endpoints, Event, ReplicationController, PodTemplate, ResourceQuota, LimitRange, Binding, ComponentStatus

Workloads (apps/v1) - 5 resources
Deployment, ReplicaSet, StatefulSet, DaemonSet, ControllerRevision

Batch (batch/v1) - 2 resources
Job, CronJob

Networking (networking.k8s.io/v1) - 6 resources
Ingress, IngressClass, NetworkPolicy, EndpointSlice, IPAddress, ServiceCIDR

Gateway API (gateway.networking.k8s.io/v1, v1beta1) - 5 resources
GatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant

RBAC (rbac.authorization.k8s.io/v1) - 4 resources
Role, RoleBinding, ClusterRole, ClusterRoleBinding

Storage (storage.k8s.io/v1) - 6 resources
StorageClass, VolumeAttachment, CSIDriver, CSINode, CSIStorageCapacity, VolumeAttributesClass

Dynamic Resource Allocation (resource.k8s.io/v1) - 4 resources
ResourceClaim, ResourceClaimTemplate, ResourceSlice, DeviceClass

Policy (policy/v1) - 1 resource
PodDisruptionBudget

Auto-scaling (autoscaling/v2) - 1 resource
HorizontalPodAutoscaler

Scheduling (scheduling.k8s.io/v1) - 1 resource
PriorityClass

Coordination (coordination.k8s.io/v1) - 1 resource
Lease

Certificates (certificates.k8s.io/v1) - 1 resource
CertificateSigningRequest

Admission Control (admissionregistration.k8s.io/v1) - 6 resources
ValidatingWebhookConfiguration, MutatingWebhookConfiguration, ValidatingAdmissionPolicy, ValidatingAdmissionPolicyBinding, MutatingAdmissionPolicy, MutatingAdmissionPolicyBinding

MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding graduated to GA in Kubernetes 1.36.

API Registration (apiregistration.k8s.io/v1) - 1 resource
APIService

Flow Control (flowcontrol.apiserver.k8s.io/v1) - 2 resources
FlowSchema, PriorityLevelConfiguration

Node (node.k8s.io/v1) - 1 resource RuntimeClass

Storage Migration (storagemigration.k8s.io/v1beta1) - 1 resource StorageVersionMigration

Core Capabilities

  • 65 Resource Types: Kubernetes resource types across 20 API groups, current through K8s 1.36
  • Full CRUD Operations: Create, Read, Update, Delete, Patch on all resources
  • Advanced Delete: Grace period, propagation policy, preconditions, delete collection
  • Advanced Create/Update: Field manager, field validation, dry-run support
  • WebSocket Operations: Pod exec, attach, port-forward
  • Gateway API: GatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant
  • Dynamic Resource Allocation: ResourceClaim, DeviceClass, ResourceSlice support
  • Generic Resource Client: Type-safe operations with ResourceClient<T> pattern
  • JSON Serialization: Built-in support for Kubernetes JSON API
  • Cluster-Scoped Resources: 30 cluster-scoped resources (namespacing handled automatically by the registry)

Authentication

  • Bearer token — static token or in-cluster service-account token
  • mTLS — client certificate authentication
  • Exec credential plugins — AWS EKS, GCP GKE, Azure AKS, generic OIDC
  • In-cluster config — automatic service-account detection inside a pod
  • Kubeconfig is parsed natively (YAML; no kubectl required). HTTP basic auth (username/password) is not supported — it was removed from Kubernetes in 1.19+.

Operational Features (k9s-inspired)

  • Enhanced Pod Logs: Container selection, previous container, tail lines, timestamps, sinceSeconds
  • Rollout Restart: Deployments, StatefulSets, DaemonSets rolling restart
  • Image Update: Set container image on deployments (setImage)
  • Pod Eviction: Graceful eviction via Eviction API
  • Node Cordon/Uncordon: Mark nodes as schedulable/unschedulable
  • Metrics Server API: CPU/memory metrics for pods and nodes (metrics.k8s.io/v1beta1)
  • RBAC CanI: SelfSubjectAccessReview permission checks

Advanced Features

  • Retry Logic: Exponential backoff with jitter, status-code-aware retries (429, 500, 502, 503, 504)
  • Watch API: Real-time resource updates with streaming support
  • Informers: Local list-then-watch cache with automatic relist on 410 Gone
  • CRD Support: Dynamic client for Custom Resource Definitions
  • Predefined CRDs: Cert-Manager, Istio, Prometheus, Argo, Knative
  • In-Cluster Config: Automatic service account detection and configuration
  • Field/Label Selectors: Advanced filtering and search capabilities
  • Pagination: Efficient handling of large result sets
  • Server-Side Apply: Declarative resource management with field ownership
  • Structured API Errors: K8s API error responses parsed into status/message/reason/code
  • Response Size Limits: Configurable max response size (default 16MB) to prevent OOM

Quality

  • Comprehensive unit suite (zig build test) plus live integration entrypoints; the migration probe force-compiles the whole public API surface
  • Memory safe with explicit allocator management
  • Type safe with Zig's compile-time type system
  • Two dependencies: zig-yaml (YAML parsing) and zig-protobuf (Protocol Buffers)
  • Live CRUD verified against Kubernetes 1.36.1 (Rancher Desktop)

Installation

As a Zig Package

Add to your build.zig.zon:

.{
    .name = .myapp,
    .version = "0.1.0",
    .dependencies = .{
        .klient = .{
            .url = "https://github.com/guanchzhou/zig-klient/archive/main.tar.gz",
            .hash = "...", // zig will provide this
        },
    },
}

In your build.zig:

const klient_dep = b.dependency("klient", .{
    .target = target,
    .optimize = optimize,
});

exe.root_module.addImport("klient", klient_dep.module("klient"));

Manual Integration

Copy the src/ directory into your project and import as a module.

Quick Start

Basic Usage

const std = @import("std");
const klient = @import("klient");

pub fn main() !void {
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Zig 0.16 threads all I/O through std.Io.
    var threaded = std.Io.Threaded.init(allocator, .{});
    defer threaded.deinit();
    const io = threaded.io();

    // Initialize client (note the io parameter)
    var client = try klient.K8sClient.init(allocator, io, .{
        .server = "https://kubernetes.default.svc",
        .token = "your-bearer-token",
    });
    defer client.deinit();

    // List all pods
    var pods = klient.Pods.init(&client);
    const pod_list = try pods.client.listAll();
    defer pod_list.deinit();
    
    for (pod_list.value.items) |pod| {
        std.debug.print("Pod: {s}\n", .{pod.metadata.name});
    }
}

The snippets below assume allocator, io, and (where used) client from the setup above.

With mTLS Authentication

var client = try klient.K8sClient.init(allocator, io, .{
    .server = "https://kubernetes.example.com",
    .tls_config = .{
        .client_cert_data = client_cert_pem, // or .client_cert_path = "/path/to/client.crt"
        .client_key_data = client_key_pem, //  or .client_key_path  = "/path/to/client.key"
        .ca_cert_data = ca_cert_pem, //         or .ca_cert_path     = "/path/to/ca.crt"
    },
});
defer client.deinit();

Note: against clusters with self-signed certificates the direct TLS path may fail with error.TlsInitializationFailed (a current std.crypto.tls limitation); use connectWithFallback() or kubectl proxy (see Connecting & TLS).

With AWS EKS Authentication

const aws_config = try klient.awsEksConfig(allocator, "my-cluster");
// Returns a std.json.Parsed(ExecCredential) — it owns the token memory.
var cred = try klient.exec_credential.executeCredentialPlugin(allocator, io, aws_config);
defer cred.deinit();

var client = try klient.K8sClient.init(allocator, io, .{
    .server = "https://xxx.eks.amazonaws.com",
    .token = cred.value.status.?.token,
});
defer client.deinit();

With Retry Logic

var client = try klient.K8sClient.init(allocator, io, .{
    .server = "https://kubernetes.example.com",
    .token = "token",
    .retry_config = klient.aggressiveConfig, // or: defaultConfig, conservativeConfig
});
defer client.deinit();
// Idempotent operations (GET/PUT/DELETE/PATCH) retry automatically on transport
// errors and 429/5xx; POST (create) is sent once.

Using Watch API

const PodWatcher = klient.Watcher(klient.Pod);
// init(client, api_path, resource, namespace, options)
var watcher = PodWatcher.init(&client, "/api/v1", "pods", "default", .{
    .allow_watch_bookmarks = true,
});

// watch() is callback-driven and blocks, dispatching each event. The callback owns
// the event and must call event.deinit() when done.
const handler = struct {
    fn onEvent(event: *klient.watch.WatchEvent(klient.Pod)) anyerror!void {
        defer event.deinit();
        switch (event.type_) {
            .ADDED => std.debug.print("Pod added: {s}\n", .{event.object.metadata.name}),
            .MODIFIED => std.debug.print("Pod modified: {s}\n", .{event.object.metadata.name}),
            .DELETED => std.debug.print("Pod deleted: {s}\n", .{event.object.metadata.name}),
            else => {},
        }
    }
}.onEvent;

try watcher.watch(handler);

Using Informer Pattern

const PodInformer = klient.Informer(klient.Pod);
// init(allocator, client, api_path, resource, namespace)
var informer = PodInformer.init(allocator, &client, "/api/v1", "pods", "default");
defer informer.deinit();

// start() does the initial list then watches, blocking until stop() — run it on its
// own thread. It relists automatically on a 410 Gone (expired resourceVersion).
try informer.start();

// From another thread, read the local cache (thread-safe):
if (informer.get("my-pod")) |pod| {
    std.debug.print("Found: {s}\n", .{pod.metadata.name});
}

Custom Resource Definitions

// Use predefined CRD
var cert_client = klient.DynamicClient.init(&client, klient.CertManagerCertificate);
const certs = try cert_client.list("production");
defer certs.deinit();

// Or define custom CRD
const my_crd = klient.CRDInfo{
    .group = "mycompany.io",
    .version = "v1alpha1",
    .kind = "CustomApp",
    .plural = "customapps",
    .namespaced = true,
};

var custom = klient.DynamicClient.init(&client, my_crd);
const apps = try custom.list("default");
defer apps.deinit();

Advanced Delete Operations

// Delete with grace period and propagation policy
const delete_opts = klient.DeleteOptions{
    .grace_period_seconds = 30,
    .propagation_policy = klient.PropagationPolicy.foreground.toString(),
    .dry_run = "All", // Test without actually deleting
};

var deployments = klient.Deployments.init(&client);
try deployments.client.deleteWithOptions("my-app", null, delete_opts);

// Delete collection by label selector
const list_opts = klient.ListOptions{
    .label_selector = "app=nginx,env=staging",
};
try deployments.client.deleteCollection(null, list_opts, delete_opts);

Advanced Create/Update Operations

// Create with field manager and validation
const create_opts = klient.CreateOptions{
    .field_manager = "my-controller",
    .field_validation = klient.FieldValidation.strict.toString(),
    .dry_run = "All", // Dry run to validate
};

var pods = klient.Pods.init(&client);
const pod = try pods.client.createWithOptions(my_pod, null, create_opts);
defer pod.deinit();

// Update with field ownership tracking
const update_opts = klient.UpdateOptions{
    .field_manager = "deployment-controller",
    .field_validation = klient.FieldValidation.warn.toString(),
};

const updated = try deployments.client.updateWithOptions(deployment, null, update_opts);
defer updated.deinit();

List with Filtering and Pagination

// Filter by field and label selectors
const list_opts = klient.ListOptions{
    .field_selector = "status.phase=Running",
    .label_selector = "app=nginx,tier=frontend",
    .limit = 50,
    .resource_version = "12345",
};

var pods = klient.Pods.init(&client);
const filtered_pods = try pods.client.listWithOptions(null, list_opts);
defer filtered_pods.deinit();

for (filtered_pods.value.items) |pod| {
    std.debug.print("Pod: {s}\n", .{pod.metadata.name});
}

// Handle pagination with continue tokens
if (filtered_pods.value.metadata.@"continue") |continue_token| {
    const next_opts = klient.ListOptions{
        .continue_token = continue_token,
        .limit = 50,
    };
    const next_page = try pods.client.listWithOptions(null, next_opts);
    defer next_page.deinit();
}

In-Cluster Configuration

// Automatically detect and load in-cluster config
if (klient.isInCluster(io)) {
    var in_cluster = try klient.loadInClusterConfig(io, allocator);
    defer in_cluster.deinit();

    var client = try klient.K8sClient.init(allocator, io, .{
        .server = in_cluster.server,
        .token = in_cluster.token,
        .tls_config = .{
            .ca_cert_data = in_cluster.ca_cert_data,
        },
    });
    defer client.deinit();

    // Now you can use the client from within a pod
    var pods = klient.Pods.init(&client);
    const pod_list = try pods.client.listAll();
    defer pod_list.deinit();
}

Pod Exec (WebSocket)

// Initialize WebSocket client. init(allocator, io, api_server, token, ca_cert_data).
// Over a self-signed cluster, point this at a `kubectl proxy` (http://127.0.0.1:8080)
// with token/ca null — see the integration tests.
var ws_client = try klient.WebSocketClient.init(
    allocator,
    io,
    "https://kubernetes.default.svc",
    bearer_token,
    ca_cert_data,
);
defer ws_client.deinit();

// Execute command in pod
var exec_client = klient.ExecClient.init(allocator, &ws_client);

const result = try exec_client.exec("my-pod", "default", .{
    .command = &[_][]const u8{ "ls", "-la", "/app" },
    .stdout = true,
    .stderr = true,
});
defer result.deinit();

std.debug.print("Output:\n{s}\n", .{result.stdout()});
std.debug.print("Exit code: {d}\n", .{result.exit_code});

Pod Attach (WebSocket)

// Attach to running container
var attach_client = klient.AttachClient.init(allocator, &ws_client);

var session = try attach_client.attach("my-pod", "default", .{
    .stdin = true,
    .stdout = true,
    .tty = true,
});
defer session.deinit();

// Send command via stdin
try session.writeStdin("echo hello\n");

// Read output
const msg = try session.read();
defer msg.deinit(allocator);

std.debug.print("Output: {s}\n", .{msg.data});

// Detach from container
session.detach();

Port Forward (WebSocket)

// Forward local ports to pod
var forwarder = klient.PortForwarder.init(allocator, &ws_client);

var forward_session = try forwarder.forward("my-pod", "default", .{
    .ports = &[_]klient.PortMapping{
        .{ .local = 8080, .remote = 80 },
        .{ .local = 5432, .remote = 5432 },
    },
});
defer forward_session.deinit();

// Ports are now forwarded
// Access pod's port 80 via localhost:8080
// Access pod's port 5432 via localhost:5432

// Keep session alive
while (forward_session.isActive()) {
    std.time.sleep(1 * std.time.ns_per_s);
}

Field and Label Selectors

var pods = klient.Pods.init(&client);

// Using field selectors
const options = klient.ListOptions{
    .field_selector = "status.phase=Running,metadata.name=my-pod",
    .limit = 100,
};
const filtered_pods = try pods.client.listWithOptions("default", options);
defer filtered_pods.deinit();

// Using label selector builder
var label_selector = try klient.LabelSelector.init(allocator);
defer label_selector.deinit();

try label_selector.addEquals("app", "nginx");
try label_selector.addIn("env", &[_][]const u8{ "prod", "staging" });
const selector_str = try label_selector.build();
defer allocator.free(selector_str);

const labeled_options = klient.ListOptions{
    .label_selector = selector_str,
};
const labeled_pods = try pods.client.listWithOptions("default", labeled_options);
defer labeled_pods.deinit();

Server-Side Apply

var deployments = klient.Deployments.init(&client);

const deployment_manifest =
    \\{
    \\  "apiVersion": "apps/v1",
    \\  "kind": "Deployment",
    \\  "metadata": {
    \\    "name": "my-deployment",
    \\    "namespace": "default"
    \\  },
    \\  "spec": {
    \\    "replicas": 3,
    \\    "selector": {
    \\      "matchLabels": {"app": "myapp"}
    \\    },
    \\    "template": {
    \\      "metadata": {"labels": {"app": "myapp"}},
    \\      "spec": {
    \\        "containers": [{
    \\          "name": "nginx",
    \\          "image": "nginx:latest"
    \\        }]
    \\      }
    \\    }
    \\  }
    \\}
;

const apply_options = klient.ApplyOptions{
    .field_manager = "my-controller",
    .force = false,
};

const applied = try deployments.client.apply(
    "my-deployment",
    deployment_manifest,
    "default",
    apply_options,
);
defer applied.deinit();

JSON Patch

var json_patch = klient.JsonPatch.init(allocator);
defer json_patch.deinit();

try json_patch.replace("/spec/replicas", .{ .integer = 5 });
try json_patch.add("/metadata/labels/version", .{ .string = "v2" });

const patch_json = try json_patch.build();
defer allocator.free(patch_json);

const patched = try deployments.client.patchWithType(
    "my-deployment",
    patch_json,
    "default",
    klient.PatchType.json,
);
defer patched.deinit();

Resource Operations

All resource types support the same operations:

// Pods
var pods = klient.Pods.init(&client);

// List operations (return std.json.Parsed - caller must call .deinit())
const pod_list = try pods.client.list("namespace");
defer pod_list.deinit();

const all_pods = try pods.client.listAll();
defer all_pods.deinit();

// Get operation (returns Parsed(T) - caller must call .deinit())
const pod = try pods.client.get("pod-name", "namespace");
defer pod.deinit();
std.debug.print("Pod: {s}\n", .{pod.value.metadata.name});

// Create/Update (return Parsed(T) - caller must call .deinit())
const created = try pods.client.create(pod_spec, "namespace");
defer created.deinit();

const updated = try pods.client.update(updated_spec, "namespace");
defer updated.deinit();

// Delete (returns void)
try pods.client.delete("namespace", "pod-name", null);

// Patch (returns Parsed(T) - caller must call .deinit())
const patched = try pods.client.patch("pod-name", patch_json, "namespace");
defer patched.deinit();

// Pod-specific: Get logs
const logs = try pods.logs("pod-name", "namespace");
defer allocator.free(logs);

// Same pattern for: Deployments, Services, ConfigMaps, Secrets, Namespaces, Nodes,
// ReplicaSets, StatefulSets, DaemonSets, Jobs, CronJobs, PVs, PVCs

Testing

Unit Tests

Run all unit tests (isolated functionality):

zig build test

Run specific test suites:

zig build test-retry      # Retry logic tests
zig build test-advanced   # TLS + CRD tests

Integration Tests

Integration tests run against a real Kubernetes cluster. Because the direct TLS path currently fails against self-signed clusters (see Connecting & TLS), the entrypoints connect through kubectl proxy:

kubectl proxy --port=8080 &           # expose the API without TLS
zig build test-mutating-admission-policy   # K8s 1.36 MutatingAdmissionPolicy CRUD round-trip
zig build test-via-proxy                   # pods/namespaces/nodes + pod CRUD

The test-mutating-admission-policy entrypoint was verified against Rancher Desktop running Kubernetes 1.36.1 — list → create → get → delete all succeed. See docs/TESTING.md for the full guide.

Documentation

Architecture

zig-klient/
├── src/
│   ├── klient.zig              # Main library entry point
│   └── k8s/
│       ├── client.zig          # Core HTTP client
│       ├── types.zig           # Resource type definitions
│       ├── resources.zig       # Resource operations
│       ├── retry.zig           # Retry logic
│       ├── watch.zig           # Watch API & Informers
│       ├── tls.zig             # mTLS support
│       ├── crd.zig             # CRD support
│       ├── exec_credential.zig # Cloud auth
│       └── kubeconfig_json.zig # Config parsing
├── tests/                      # Unit tests (isolated)
│   ├── entrypoints/            # Live integration tests (via kubectl proxy)
│   └── comprehensive/          # Larger live scenarios
└── docs/                       # Documentation

Feature Parity Status

Tested against: Rancher Desktop (Kubernetes 1.36.1)

Feature Kubernetes 1.36 zig-klient Coverage
HTTP Operations All methods All methods 100%
K8s Resource Types 65 modeled 65 100%
API Groups 20 20 100%
Auth Methods 5 4 80% (no HTTP basic auth — removed from K8s 1.19+)
In-Cluster Config Yes Yes Yes
Delete Options Yes Yes Yes
Create/Update Options Yes Yes Yes
Delete Collection Yes Yes Yes
Retry Logic Basic Advanced Yes
Watch API Yes Yes Yes
Field/Label Selectors Yes Yes Yes
Pagination Yes Yes Yes
Server-Side Apply Yes Yes Yes
WebSocket Support Yes Yes (native) Yes
Protobuf Support Yes Yes (zig-protobuf) Yes
Gateway API Yes Yes Yes
Dynamic Resource Allocation Yes (GA 1.36) Yes Yes
Mutating Admission Policy Yes (GA 1.36) Yes Yes

Coverage: 65 Kubernetes resource types across 20 API groups, current through K8s 1.36 - workloads, networking, Gateway API, storage, security, auto-scaling, dynamic resource allocation, admission control (incl. 1.36 MutatingAdmissionPolicy), certificates, API management, storage migration, WebSocket, and Protobuf.

See FEATURE_PARITY_STATUS.md for detailed breakdown.

Requirements

  • Zig 0.16.0 or newer
  • kubectl (for kubeconfig parsing)
  • Cloud CLI tools (optional, for exec credential plugins):
    • aws CLI for EKS
    • gke-gcloud-auth-plugin for GKE
    • kubelogin for AKS

Stability

zig-klient is pre-1.0, so the API may change between minor versions. Following SemVer for 0.x:

  • minor (0.2 → 0.3) may include breaking changes (signatures, removed symbols);
  • patch (0.2.1 → 0.2.2) is backward-compatible bug/security fixes.

The 1.0 line will stabilize the public surface once the resource API and the streaming/TLS paths have soaked. Each release's breaking changes are called out in CHANGELOG.md. Targets Zig 0.16.0 and Kubernetes through 1.36.

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass (zig build test)
  5. Submit a pull request

Roadmap

Implemented

  • 65 Kubernetes resource types across 20 API groups (current through K8s 1.36)
  • All HTTP methods (GET, POST, PUT, DELETE, PATCH)
  • Bearer token auth
  • mTLS auth
  • Exec credential plugins (AWS, GCP, Azure)
  • In-cluster configuration with service account
  • Delete options (grace period, propagation policy, preconditions)
  • Delete collection operations
  • Create/Update options (field manager, field validation, dry-run)
  • List filtering (field selectors, label selectors)
  • Pagination support (limit, continue tokens, resource version)
  • Retry logic with exponential backoff and jitter
  • Watch API for streaming updates
  • Informers with local caching
  • CRD support with dynamic client
  • Server-side apply
  • JSON Patch and Strategic Merge Patch
  • Scale subresources
  • WebSocket operations (pod exec, attach, port-forward)
  • Protobuf serialization via zig-protobuf
  • Gateway API (GatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant)
  • Dynamic Resource Allocation (ResourceClaim, DeviceClass, ResourceSlice)
  • Metrics Server API (pod and node CPU/memory metrics)
  • RBAC CanI (SelfSubjectAccessReview permission checks)
  • Operational features: rollout restart, image update, pod eviction, node cordon
  • Enhanced pod logs (container, previous, tail, timestamps, sinceSeconds)
  • Structured K8s API error responses
  • Response size limits and 4x larger HTTP buffers
  • Status-code-aware retry logic (429, 500, 502, 503, 504)
  • Comprehensive unit test suite + live integration entrypoints (kind/Rancher Desktop)
  • Migration probe force-compiles the entire public API surface

About

Zig Kubernetes client

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages