NAME

IO::K8s::Role::Routable - Role for building HTTP/gRPC routing rules

VERSION

version 1.108

SYNOPSIS

package My::Route;
use IO::K8s::APIObject api_version => 'gateway.networking.k8s.io/v1';
k8s spec => { Str => 1 };
with 'IO::K8s::Role::Routable';

sub _route_format { 'gateway' }   # or 'traefik', 'ingress'

package main;
my $r = My::Route->new;
$r->add_hostname('example.com')
  ->add_backend('api-v1', port => 8080, weight => 90)
  ->add_path_match('/api', type => 'Prefix')
  ->add_header_match('X-Env', 'production');

# An ingress-formatted route gives every path its own backend.
use IO::K8s::Api::Networking::V1::Ingress;
my $ingress = IO::K8s::Api::Networking::V1::Ingress->new(
    metadata => { name => 'web', namespace => 'prod' },
);
$ingress->add_path_match(
    '/api', type => 'Prefix', service => 'api', port => 8080,
);

DESCRIPTION

This role provides fluent HTTP routing builders. A consuming class must declare a spec attribute as well as implement _route_format; the spec declaration in the synopsis permits IO::K8s::Role::SpecBuilder to create the route structure. The role dispatches on _route_format, which must return 'gateway', 'traefik', or 'ingress'.

Gateway API HTTPRoute and Traefik IngressRoute support the generic routing chain in the synopsis. Core Kubernetes Ingress has distinct backend slots: add_backend writes spec.defaultBackend for unmatched requests, while add_path_match requires service and port and writes that path's own backend. Thus an Ingress path must not rely on a preceding add_backend call for its backend.

The three formats produce different wire shapes:

  • 'gateway' writes through IO::K8s::Role::SpecBuilder's spec_* methods into a spec that mirrors the HTTPRoute wire schema (hostnames, rules[].matches[].path, rules[].backendRefs) -- either a plain hash or a typed struct.

  • 'traefik' writes the same way into a spec that mirrors the IngressRoute wire schema (routes[].match as a Traefik expression, routes[].services[]).

  • 'ingress' builds typed IO::K8s::Api::Networking::V1::IngressSpec / IngressRule / HTTPIngressRuleValue / HTTPIngressPath / IngressBackend / IngressServiceBackend / ServiceBackendPort objects. add_path_match adds a typed path-specific backend, and add_backend continues to set only spec.defaultBackend. The nested Ingress classes are loaded when the ingress branch first runs, not at composition time, so composing this role onto a Gateway API or Traefik Kind pulls none of them in.

add_path_match operates on the last rule in spec.rules for Gateway and Ingress, or the last route in spec.routes for Traefik. add_hostname creates an Ingress rule for each hostname; chain calls in declaration order therefore retain their natural top-to-bottom manifest order.

add_hostname

$route->add_hostname('example.com', 'api.example.com');

Adds hostnames the route should match. The role dispatches on _route_format:

  • 'gateway' -- Gateway API HTTPRoute. Appends to spec.hostnames. Each hostname becomes its own entry on the hostnames list.

  • 'traefik' -- Traefik IngressRoute. Adds a new routes entry whose match string combines each hostname with Host(`...`), e.g. match => 'Host(`example.com`), Host(`api.example.com`)'.

  • 'ingress' -- core Kubernetes Ingress. Appends an IO::K8s::Api::Networking::V1::IngressRule per hostname with host => $hostname.

Returns $self for chaining.

$route->add_hostname('example.com');

add_backend

$route->add_backend('api-v1', port => 8080, weight => 90);

Adds a backend the route should dispatch traffic to. name is required; port and weight are optional. Dispatch is per format:

  • 'gateway' -- appends to the last rule's backendRefs as { name, port, weight }.

  • 'traefik' -- appends to the last route's services as { name, port, weight }.

  • 'ingress' -- replaces spec.defaultBackend with a typed IngressBackend / IngressServiceBackend / ServiceBackendPort chain, using the last name and port.

Returns $self for chaining.

$route->add_backend('api-v1', port => 8080, weight => 90);

add_path_match

# Gateway API or Traefik
$route->add_path_match('/api', type => 'Prefix');

# core Kubernetes Ingress
$ingress->add_path_match(
    '/api', type => 'Prefix', service => 'api', port => 8080,
);

Adds a path match to the most recently added routing rule. type defaults to 'Prefix'. For Gateway API and Traefik, the shared vocabulary selects one of:

  • 'Prefix' -- Gateway API { path: { type: 'PathPrefix', value } }, Traefik PathPrefix(`...`).

  • 'Exact' -- Gateway API { path: { type: 'Exact', value } }, Traefik Path(`...`).

  • 'Regex' -- Gateway API { path: { type: 'RegularExpression', value } }, Traefik PathRegexp(`...`).

For 'ingress', this creates a typed IO::K8s::Api::Networking::V1::HTTPIngressPath with its own typed backend. service and port are required; port may be a numeric or named Service port. A numeric port is written as service.port.number, and a named port as service.port.name. Ingress accepts 'Prefix', 'Exact', and 'ImplementationSpecific'. 'Prefix' and 'Exact' require a defined path starting with /. 'ImplementationSpecific' permits an undefined or empty path, but a nonempty path must also start with /.

An Ingress call with a missing service or port, an unsupported path type, or an invalid 'Prefix', 'Exact', or nonempty 'ImplementationSpecific' path croaks before it mutates the object. add_backend remains independent: it writes spec.defaultBackend, the fallback for unmatched requests, and is never reused as a path backend.

Returns $self for chaining.

add_header_match

$route->add_header_match('X-Env', 'production');

Adds a header-based match to the most recently added routing rule. Gateway API appends to the last match's headers array as { name => $header, value => $value }; Traefik extends the route's match string with && Header(`<name>`, `<value>`). Core Ingress does not support header matching natively and the call is a no-op in that mode. Returns $self for chaining.

REQUIRED METHODS

_route_format

Must return 'gateway', 'traefik', or 'ingress'. The role dispatches all method bodies on this answer; a missing or unknown value is treated as a no-op.

SEE ALSO

IO::K8s::GatewayAPI, IO::K8s::Traefik, IO::K8s::Api::Networking::V1::IngressSpec, IO::K8s::APIObject

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/pplu/io-k8s-p5/issues.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHORS

  • Torsten Raudssus <getty@cpan.org>

  • Jose Luis Martinez Torres <jlmartin@cpan.org>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2018-2026 by Jose Luis Martinez Torres <jlmartin@cpan.org>.

This is free software, licensed under:

The Apache License, Version 2.0, January 2004