IO-K8s
view release on metacpan or search on metacpan
From source:
```bash
cpanm --installdeps .
dzil build
dzil test
dzil install
```
## Usage
```perl
use IO::K8s;
my $k8s = IO::K8s->new;
# Create objects with short names
my $pod = $k8s->new_object('Pod',
metadata => { name => 'my-pod', namespace => 'default' },
spec => { containers => [{ name => 'app', image => 'nginx' }] }
);
# Load and validate YAML manifests
my $resources = $k8s->load_yaml('deployment.yaml');
# Save to YAML file
$pod->save('pod.yaml');
# Inflate JSON/struct into typed objects (auto-detect class from 'kind')
my $svc = $k8s->json_to_object('Service', '{"kind":"Service"}');
my $obj = $k8s->inflate({ kind => 'Pod', metadata => { name => 'test' } });
# Serialize back to JSON
my $json = $k8s->object_to_json($svc);
my $struct = $k8s->object_to_struct($pod);
```
## Bundled CRD Providers
IO::K8s ships with CRD classes for popular Kubernetes ecosystem projects. None are loaded by default - opt in at construction:
```perl
my $k8s = IO::K8s->new(with => [
'IO::K8s::Cilium',
'IO::K8s::Traefik',
'IO::K8s::CertManager',
'IO::K8s::K3s',
'IO::K8s::GatewayAPI',
'IO::K8s::AgentSandbox',
]);
```
### Cilium (21 CRDs)
`IO::K8s::Cilium` covers `cilium.io/v2` and `cilium.io/v2alpha1` (upstream v1.19.2):
```perl
my $k8s = IO::K8s->new(with => ['IO::K8s::Cilium']);
my $cnp = $k8s->new_object('CiliumNetworkPolicy',
metadata => { name => 'allow-dns', namespace => 'kube-system' },
spec => { endpointSelector => {} },
);
```
### Traefik (10 CRDs)
`IO::K8s::Traefik` covers `traefik.io/v1alpha1`:
```perl
my $k8s = IO::K8s->new(with => ['IO::K8s::Traefik']);
my $ir = $k8s->new_object('IngressRoute',
metadata => { name => 'my-route', namespace => 'default' },
spec => { entryPoints => ['web'], routes => [{ match => 'Host(`example.com`)' }] },
);
```
### cert-manager (6 CRDs)
`IO::K8s::CertManager` covers `cert-manager.io/v1` and `acme.cert-manager.io/v1`:
```perl
my $k8s = IO::K8s->new(with => ['IO::K8s::CertManager']);
my $cert = $k8s->new_object('Certificate',
metadata => { name => 'my-cert', namespace => 'default' },
spec => { secretName => 'my-cert-tls', issuerRef => { name => 'letsencrypt' } },
);
```
### K3s (4 CRDs)
`IO::K8s::K3s` covers `helm.cattle.io/v1` and `k3s.cattle.io/v1` (upstream v1.35.1+k3s1):
```perl
my $k8s = IO::K8s->new(with => ['IO::K8s::K3s']);
my $hc = $k8s->new_object('HelmChart',
metadata => { name => 'traefik', namespace => 'kube-system' },
spec => { chart => 'traefik' },
);
```
### Gateway API (5 CRDs)
`IO::K8s::GatewayAPI` covers `gateway.networking.k8s.io/v1` and `gateway.networking.k8s.io/v1beta1`:
```perl
my $k8s = IO::K8s->new(with => ['IO::K8s::GatewayAPI']);
my $gw = $k8s->new_object('Gateway',
metadata => { name => 'my-gateway', namespace => 'default' },
spec => { gatewayClassName => 'istio', listeners => [{ name => 'http', port => 80 }] },
);
```
### AgentSandbox (4 CRDs)
`IO::K8s::AgentSandbox` covers `agents.x-k8s.io/v1alpha1` and `extensions.agents.x-k8s.io/v1alpha1` (upstream v0.2.1):
```perl
my $k8s = IO::K8s->new(with => ['IO::K8s::AgentSandbox']);
my $sandbox = $k8s->new_object('Sandbox',
metadata => { name => 'my-sandbox', namespace => 'default' },
spec => { replicas => 1, shutdownPolicy => 'Retain' },
->add_backend('api-v1', port => 8080, weight => 90)
->add_path_match('/api', type => 'Prefix');
# cert-manager
$cert->for_domains('example.com', '*.example.com')
->with_issuer('letsencrypt-prod', kind => 'ClusterIssuer')
->store_in_secret('example-tls');
# K3s Helm charts
$chart->from_repo('https://traefik.github.io/charts', 'traefik')
->set_version('25.0.0')
->set_values(replicas => 3);
# Traefik middleware
$mw->rate_limit(average => 100, burst => 200)
->strip_prefix('/api')
->redirect_https;
```
### IP Type Validation
`IO::K8s::Types::Net` provides Net::IP-backed type constraints:
```perl
use IO::K8s::Types::Net qw( IPv4 IPv6 IPAddress CIDR NetIP );
use IO::K8s::Types::Net qw( parse_ip cidr_contains is_rfc1918 );
cidr_contains('10.0.0.0/8', '10.1.2.3'); # true
is_rfc1918('192.168.1.1'); # true
```
## External Resource Maps
Merge resource maps from external packages (e.g. `IO::K8s::Cilium` or your own CRD packages):
```perl
# At construction time
my $k8s = IO::K8s->new(with => ['IO::K8s::Cilium']);
# Or at runtime
$k8s->add('IO::K8s::Cilium');
# Disambiguate colliding kind names with domain-qualified strings
$k8s->new_object('cilium.io/v2/CiliumNetworkPolicy', { ... });
# Or with api_version parameter
$k8s->new_object('CiliumNetworkPolicy', { ... }, 'cilium.io/v2');
# inflate() auto-uses apiVersion from JSON data
$k8s->inflate('{"kind":"CiliumNetworkPolicy","apiVersion":"cilium.io/v2",...}');
```
### pk8s DSL
In `.pk8s` manifest files, Cilium kinds work directly:
```perl
CiliumNetworkPolicy {
name => 'allow-dns',
namespace => 'kube-system',
spec => { endpointSelector => {} },
};
CiliumNode {
name => 'worker-1',
spec => { addresses => [{ type => 'InternalIP', ip => '10.0.0.1' }] },
};
```
## Custom Resource Definitions (CRDs)
Write your own CRD classes using `IO::K8s::APIObject`:
```perl
package My::StaticWebSite;
use IO::K8s::APIObject
api_version => 'homelab.example.com/v1',
resource_plural => 'staticwebsites';
with 'IO::K8s::Role::Namespaced';
k8s spec => { Str => 1 };
k8s status => { Str => 1 };
1;
```
Or generate them dynamically from an OpenAPI schema using `IO::K8s::AutoGen`.
See the full POD documentation for details on the class architecture and CRD support.
## Features
- Support for Kubernetes v1.31 API objects
- Type-safe object creation and serialization
- Lightweight Moo-based implementation
- Handles all Kubernetes resource types (Pods, Services, Deployments, etc.)
- Custom Resource Definition (CRD) support with `IO::K8s::APIObject` import parameters
- External resource map support with collision handling (`add()`, `with` constructor param)
- Domain-qualified resource names for disambiguation (`api_version/Kind`)
- Dynamic class generation from OpenAPI schemas via `IO::K8s::AutoGen`
- Convenience methods: labels, annotations, conditions, owner references on all API objects
- Deep-path spec manipulation for CRD classes via `SpecBuilder`
- Domain-specific builder roles for network policies, routing, certificates, Helm, and more
- Net::IP-backed IP/CIDR type constraints (`IO::K8s::Types::Net`)
- Proper handling of namespaced resources
- Canonical JSON output for consistent API requests
## Links
- CPAN: https://metacpan.org/pod/IO::K8s
- GitHub: https://github.com/pplu/io-k8s-p5
- Issues: https://github.com/pplu/io-k8s-p5/issues
- Kubernetes API Reference: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/
## Authors
- Torsten Raudssus <torsten@raudssus.de>
- Jose Luis Martinez <jlmartin@cpan.org> (original author, inactive)
## License
Copyright (c) 2018 by Jose Luis Martinez
( run in 0.606 second using v1.01-cache-2.11-cpan-524268b4103 )