NAME
Kubernetes::REST - A Perl REST Client for the Kubernetes API
VERSION
version 1.000
SYNOPSIS
use Kubernetes::REST;
my $api = Kubernetes::REST->new(
server => {
endpoint => 'https://kubernetes.local:6443',
ssl_verify_server => 1,
ssl_ca_file => '/path/to/ca.crt',
},
credentials => { token => $token },
);
# List all namespaces
my $namespaces = $api->list('Namespace');
for my $ns ($namespaces->items->@*) {
say $ns->metadata->name;
}
# List pods in a namespace
my $pods = $api->list('Pod', namespace => 'default');
# Get a specific pod
my $pod = $api->get('Pod', name => 'my-pod', namespace => 'default');
# Create a namespace
my $ns = $api->new_object(Namespace => {
metadata => { name => 'my-namespace' },
});
my $created = $api->create($ns);
# Create multiple namespaces
for my $i (1..10) {
$api->create($api->new_object(Namespace =>
metadata => { name => "test-ns-$i" },
));
}
# Update a resource (full replacement)
$pod->metadata->labels({ app => 'updated' });
my $updated = $api->update($pod);
# Patch a resource (partial update)
my $patched = $api->patch('Pod', 'my-pod',
namespace => 'default',
patch => { metadata => { labels => { env => 'staging' } } },
);
# Delete a resource
$api->delete($pod);
# or by name:
$api->delete('Pod', name => 'my-pod', namespace => 'default');
DESCRIPTION
This module provides a simple REST client for the Kubernetes API using IO::K8s resource classes. The IO::K8s classes know their own metadata (API version, kind, whether they're namespaced), so URL building is automatic.
server
Required. Kubernetes::REST::Server instance or hashref with server connection configuration.
server => { endpoint => 'https://kubernetes.local:6443' }
Automatically coerces hashrefs to Kubernetes::REST::Server objects.
credentials
Required. Authentication credentials. Can be a hashref, Kubernetes::REST::AuthToken, or any object with a token() method.
credentials => { token => $bearer_token }
Automatically coerces hashrefs to Kubernetes::REST::AuthToken objects.
io
HTTP backend for making requests. Must consume Kubernetes::REST::Role::IO. Defaults to Kubernetes::REST::LWPIO (LWP::UserAgent).
To use HTTP::Tiny instead:
use Kubernetes::REST::HTTPTinyIO;
my $api = Kubernetes::REST->new(
...,
io => Kubernetes::REST::HTTPTinyIO->new(...),
);
See "PLUGGABLE IO ARCHITECTURE" for custom backends.
k8s
IO::K8s instance configured with the same resource map. Automatically created when needed.
Provides delegated methods: new_object, inflate, json_to_object, struct_to_object, expand_class.
resource_map_from_cluster
Boolean. If true, dynamically loads the resource map from the cluster's OpenAPI spec. Defaults to 1.
Set to 0 to use IO::K8s built-in resource map instead (faster startup, but may not match your cluster version).
cluster_version
Read-only. The Kubernetes cluster version string (e.g., v1.31.0). Fetched automatically from the /version endpoint when first accessed.
resource_map
Hashref mapping short resource names to IO::K8s class paths. By default loads dynamically from the cluster (if resource_map_from_cluster is true) or uses IO::K8s built-in map.
Override for custom resources:
resource_map => {
%{ IO::K8s->default_resource_map },
MyResource => '+My::K8s::V1::MyResource',
}
The + prefix tells IO::K8s that this is a custom class (not in the IO::K8s:: namespace).
fetch_resource_map
my $map = $api->fetch_resource_map;
Fetch the resource map from the cluster's OpenAPI spec (/openapi/v2 endpoint). Returns a hashref mapping short resource names (e.g., Pod) to full IO::K8s class paths.
Called automatically if resource_map_from_cluster is enabled.
schema_for
my $schema = $api->schema_for('Pod');
Get the OpenAPI schema definition for a resource type from the cluster. Accepts short names (Pod), full class names (IO::K8s::Api::Core::V1::Pod), or OpenAPI definition names (io.k8s.api.core.v1.Pod).
Returns a hashref with the OpenAPI v2 schema definition.
compare_schema
my $result = $api->compare_schema('Pod');
Compare the local IO::K8s class definition against the cluster's OpenAPI schema. Useful for detecting version skew between your IO::K8s installation and the cluster.
Returns the comparison result from IO::K8s::Resource->compare_to_schema.
list
my $list = $api->list('Pod', namespace => 'default');
List resources. Returns an IO::K8s::List object.
Accepts short class names (Pod) or full class paths. For namespaced resources, pass namespace parameter. Omit namespace to list cluster-scoped resources.
get
my $pod = $api->get('Pod', name => 'my-pod', namespace => 'default');
# or shorthand:
my $pod = $api->get('Pod', 'my-pod', namespace => 'default');
Get a single resource by name. Returns a typed IO::K8s object.
create
my $created = $api->create($pod);
Create a resource from an IO::K8s object. Returns the created object with server-assigned fields (UID, resourceVersion, etc.).
update
my $updated = $api->update($pod);
Update an existing resource. Replaces the entire object server-side. Returns the updated object.
For partial updates, use "patch" instead.
patch
my $patched = $api->patch('Pod', 'my-pod',
namespace => 'default',
patch => { metadata => { labels => { env => 'staging' } } },
);
# Or with an object:
my $patched = $api->patch($pod,
patch => { metadata => { labels => { env => 'staging' } } },
);
Partially update a resource. Unlike update() which replaces the entire object, patch() only modifies specified fields.
Supports three patch strategies via the type parameter:
strategic(default) - Strategic Merge Patch (Kubernetes-native, understands array merge semantics)merge- JSON Merge Patch (RFC 7396, simple recursive merge)json- JSON Patch (RFC 6902, array of operations)
See "patch" in Kubernetes::REST for detailed examples.
delete
$api->delete($pod);
# or by name:
$api->delete('Pod', name => 'my-pod', namespace => 'default');
# or shorthand:
$api->delete('Pod', 'my-pod', namespace => 'default');
Delete a resource. Returns true on success.
watch
my $last_rv = $api->watch('Pod',
namespace => 'default',
on_event => sub {
my ($event) = @_;
say $event->type . ": " . $event->object->metadata->name;
},
timeout => 300,
resourceVersion => '12345',
labelSelector => 'app=web',
fieldSelector => 'status.phase=Running',
);
Watch for changes to resources. Uses the Kubernetes Watch API with chunked transfer encoding to stream events. The call blocks until the server-side timeout expires.
Returns the last resourceVersion seen. Croaks on 410 Gone (resourceVersion too old).
See "watch" in Kubernetes::REST for detailed documentation and resumable watch patterns.
NAME
Kubernetes::REST - A Perl REST Client for the Kubernetes API
UPGRADING FROM 0.02
WARNING: Version 1.00 contains breaking changes!
This version has been completely rewritten. Key changes that may affect your code:
New simplified API
The old method-per-operation API (e.g.,
$api->Core->ListNamespacedPod(...)) has been replaced with a simple API:list,get,create,update,patch,delete,watch.Old API still works but deprecated
The old API is still available for backwards compatibility but will emit deprecation warnings. Set
$ENV{HIDE_KUBERNETES_REST_V0_API_WARNING}to suppress warnings.Uses IO::K8s classes
Results are now returned as typed IO::K8s objects instead of raw hashrefs. Lists are returned as IO::K8s::List objects.
Note: IO::K8s has also been completely rewritten (Moose to Moo, updated to Kubernetes v1.31 API). See "UPGRADING FROM 0.04" in IO::K8s for details.
Short resource names
You can now use short names like
'Pod'instead of full class paths. Theresource_mapattribute controls this mapping.Dynamic resource map
Use
resource_map_from_cluster => 1to load the resource map from the cluster's OpenAPI spec, ensuring compatibility with any Kubernetes version.
ATTRIBUTES
server
Required. Connection details for the Kubernetes API server. Can be a hashref or a Kubernetes::REST::Server object.
server => { endpoint => 'https://kubernetes.local:6443' }
credentials
Required. Authentication credentials. Can be a hashref or a Kubernetes::REST::AuthToken object.
credentials => { token => $bearer_token }
io
Optional. HTTP backend for making requests. Must consume the Kubernetes::REST::Role::IO role (i.e. implement call($req) and call_streaming($req, $callback)). Defaults to Kubernetes::REST::LWPIO (LWP::UserAgent), which supports LWP::ConsoleLogger for HTTP debugging.
To use the lighter HTTP::Tiny backend instead:
use Kubernetes::REST::HTTPTinyIO;
my $api = Kubernetes::REST->new(
server => ...,
credentials => ...,
io => Kubernetes::REST::HTTPTinyIO->new(
ssl_verify_server => 1,
),
);
To use an async event loop, provide your own IO backend:
my $api = Kubernetes::REST->new(
server => ...,
credentials => ...,
io => My::AsyncIO->new(loop => $loop),
);
k8s
Optional. IO::K8s instance configured with the same resource map as this client. Automatically created when needed.
resource_map_from_cluster
Optional boolean. If true, loads the resource map dynamically from the cluster's OpenAPI spec. Defaults to true (loads from cluster).
resource_map_from_cluster => 1
resource_map
Optional hashref. Maps short resource names to IO::K8s class paths. By default loads dynamically from the cluster (if resource_map_from_cluster is true) or uses IO::K8s built-in map. Can be overridden for custom resources.
resource_map => { MyResource => 'Custom::V1::MyResource' }
cluster_version
Read-only. The Kubernetes cluster version string (e.g., "v1.31.0"). Fetched automatically from the /version endpoint when first accessed.
METHODS
new_object($class, \%attrs) or new_object($class, %attrs)
Create a new IO::K8s object. Accepts short class names (e.g., 'Pod', 'Namespace') and either a hashref or a hash of attributes.
# With hashref
my $ns = $api->new_object(Namespace => { metadata => { name => 'foo' } });
# With hash
my $ns = $api->new_object(Namespace => metadata => { name => 'foo' });
list($class, %args)
List resources. Returns an IO::K8s::List.
my $pods = $api->list('Pod', namespace => 'default');
get($class, %args)
Get a single resource by name.
my $pod = $api->get('Pod', name => 'my-pod', namespace => 'default');
create($object)
Create a resource from an IO::K8s object.
my $created = $api->create($pod);
update($object)
Update an existing resource.
my $updated = $api->update($pod);
patch($class_or_object, %args)
Partially update a resource. Unlike update() which replaces the entire object, patch() only modifies the fields you specify.
# Add a label (strategic merge patch - default)
my $patched = $api->patch('Pod', 'my-pod',
namespace => 'default',
patch => { metadata => { labels => { env => 'staging' } } },
);
# Same thing with an object reference
my $patched = $api->patch($pod,
patch => { metadata => { labels => { env => 'staging' } } },
);
# Explicit patch type
my $patched = $api->patch('Deployment', 'my-app',
namespace => 'default',
type => 'merge',
patch => { spec => { replicas => 5 } },
);
Required arguments:
- patch
-
A hashref (or arrayref for JSON Patch) describing the changes to apply.
- name
-
The resource name (when using class name, not object reference).
Optional arguments:
- type
-
The patch strategy. One of:
strategic(default)-
Strategic Merge Patch. The Kubernetes-native patch type that understands array merge semantics (e.g., adding a container to a pod spec without removing existing containers).
merge-
JSON Merge Patch (RFC 7396). Simple recursive merge where
nullvalues delete keys. Arrays are replaced entirely. json-
JSON Patch (RFC 6902). An array of operations:
patch => [ { op => 'replace', path => '/spec/replicas', value => 3 }, { op => 'add', path => '/metadata/labels/env', value => 'prod' }, ]
- namespace
-
For namespaced resources, the namespace.
Returns the full updated object from the server.
delete($class_or_object, %args)
Delete a resource.
$api->delete($pod);
$api->delete('Pod', name => 'my-pod', namespace => 'default');
watch($class, %args)
Watch for changes to resources. Uses the Kubernetes Watch API with chunked transfer encoding to stream events. The call blocks until the server-side timeout expires.
my $last_rv = $api->watch('Pod',
namespace => 'default',
on_event => sub {
my ($event) = @_;
say $event->type; # ADDED, MODIFIED, DELETED
say $event->object->metadata->name; # inflated IO::K8s object
},
timeout => 300, # server-side timeout (default: 300)
resourceVersion => '12345', # resume from this version
labelSelector => 'app=web', # optional label filter
fieldSelector => 'status.phase=Running', # optional field filter
);
# $last_rv is the last resourceVersion seen - use it to resume watching
Required arguments:
- on_event
-
Callback called for each watch event with a Kubernetes::REST::WatchEvent object.
Optional arguments:
- timeout
-
Server-side timeout in seconds (default: 300). The API server will close the connection after this many seconds.
- resourceVersion
-
Resume watching from a specific resource version. Use the return value from a previous
watch()call to avoid missing events. - labelSelector
-
Filter by label selector (e.g.,
'app=web,env=prod'). - fieldSelector
-
Filter by field selector (e.g.,
'status.phase=Running'). - namespace
-
For namespaced resources, the namespace to watch.
Resumable watch pattern:
my $rv;
while (1) {
$rv = eval {
$api->watch('Pod',
namespace => 'default',
resourceVersion => $rv,
on_event => \&handle_event,
);
};
if ($@ && $@ =~ /410 Gone/) {
# resourceVersion expired, re-list to get fresh version
my $list = $api->list('Pod', namespace => 'default');
$rv = undef; # start fresh
}
}
Returns the last resourceVersion seen. Croaks on 410 Gone with a message to re-list.
fetch_resource_map()
Fetch the resource map from the cluster's OpenAPI spec (/openapi/v2 endpoint). Returns a hashref mapping short resource names (e.g., "Pod") to full IO::K8s class paths. This method is called automatically if resource_map_from_cluster is enabled.
PLUGGABLE IO ARCHITECTURE
The HTTP transport is decoupled from request preparation and response processing. This makes it possible to swap the default LWP::UserAgent backend for HTTP::Tiny or an async backend (e.g. Net::Async::HTTP) without changing any API logic.
The pipeline for each API call:
1. _prepare_request() - builds HTTPRequest (method, url, headers, body)
2. io->call() - executes request (pluggable backend)
3. _check_response() - validates HTTP status
4. _inflate_object/list - decodes JSON + inflates IO::K8s objects
For watch, step 2 uses io->call_streaming() and step 4 uses _process_watch_chunk() which parses NDJSON and inflates each event.
To implement a custom IO backend, consume Kubernetes::REST::Role::IO and implement call($req) and call_streaming($req, $callback). See Kubernetes::REST::LWPIO and Kubernetes::REST::HTTPTinyIO for reference implementations.
SEE ALSO
Related Modules
IO::K8s - Kubernetes resource classes (required dependency)
Net::Async::Kubernetes - Async Kubernetes client for IO::Async
Configuration and Authentication
Kubernetes::REST::Kubeconfig - Load settings from kubeconfig
Kubernetes::REST::Server - Server connection configuration
Kubernetes::REST::AuthToken - Authentication credentials
HTTP Backends
Kubernetes::REST::Role::IO - IO interface role
Kubernetes::REST::LWPIO - LWP::UserAgent backend (default)
Kubernetes::REST::HTTPTinyIO - HTTP::Tiny backend
LWP::ConsoleLogger - HTTP debugging for LWPIO
Data Objects
Kubernetes::REST::WatchEvent - Watch event object
Kubernetes::REST::HTTPRequest - HTTP request object
Kubernetes::REST::HTTPResponse - HTTP response object
CLI Tools
Kubernetes::REST::CLI - CLI base class
Kubernetes::REST::CLI::Watch - kube_watch CLI tool
Kubernetes::REST::CLI::Role::Connection - Shared CLI options
Examples and Documentation
Kubernetes::REST::Example - Comprehensive examples with Minikube/K3s
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/ - Kubernetes API reference
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/pplu/kubernetes-rest/issues.
IRC
Join #kubernetes on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHORS
Torsten Raudssus <torsten@raudssus.de>
Jose Luis Martinez Torres <jlmartin@cpan.org> (JLMARTIN, original author, inactive)
COPYRIGHT AND LICENSE
This software is Copyright (c) 2019 by Jose Luis Martinez.
This is free software, licensed under:
The Apache License, Version 2.0, January 2004