Kubernetes-REST
view release on metacpan or search on metacpan
t/10_watch.t view on Meta::CPAN
#!/usr/bin/env perl
# Tests for the Kubernetes Watch API using mock data.
#
# Run:
# prove -l t/10_watch.t
use strict;
use warnings;
use Test::More;
use Test::Exception;
use FindBin;
use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/../lib";
use Test::Kubernetes::Mock qw(mock_api);
use Kubernetes::REST;
use Kubernetes::REST::Server;
use Kubernetes::REST::AuthToken;
use Kubernetes::REST::WatchEvent;
use IO::K8s;
my $container = { name => 'nginx', image => 'nginx:1.27' };
# Build a mock API with watch-capable IO
my $mock_io = Test::Kubernetes::Mock::IO->new;
my $api = Kubernetes::REST->new(
server => Kubernetes::REST::Server->new(endpoint => 'http://mock.local'),
credentials => Kubernetes::REST::AuthToken->new(token => 'MockToken'),
resource_map_from_cluster => 0,
io => $mock_io,
);
# === Test 1: Watch with ADDED/MODIFIED/DELETED events ===
subtest 'watch pod events' => sub {
$mock_io->add_watch_events('/api/v1/namespaces/default/pods', [
{
type => 'ADDED',
object => {
apiVersion => 'v1',
kind => 'Pod',
metadata => {
name => 'nginx-abc',
namespace => 'default',
resourceVersion => '100',
uid => 'uid-1',
},
spec => { containers => [$container], nodeName => 'node-1' },
status => { phase => 'Running' },
},
},
{
type => 'MODIFIED',
object => {
apiVersion => 'v1',
kind => 'Pod',
metadata => {
name => 'nginx-abc',
namespace => 'default',
resourceVersion => '101',
uid => 'uid-1',
},
spec => { containers => [$container], nodeName => 'node-1' },
status => { phase => 'Succeeded' },
},
},
{
type => 'DELETED',
object => {
apiVersion => 'v1',
kind => 'Pod',
metadata => {
name => 'nginx-abc',
namespace => 'default',
resourceVersion => '102',
uid => 'uid-1',
},
spec => { containers => [$container], nodeName => 'node-1' },
status => { phase => 'Succeeded' },
},
},
]);
my @events;
my $last_rv = $api->watch('Pod',
namespace => 'default',
on_event => sub { push @events, $_[0] },
);
t/10_watch.t view on Meta::CPAN
# Check raw data preserved
is($events[0]->raw->{metadata}{resourceVersion}, '100', 'raw resourceVersion');
};
# === Test 2: Verify last resourceVersion return ===
subtest 'last resourceVersion returned' => sub {
$mock_io->add_watch_events('/api/v1/namespaces/kube-system/pods', [
{
type => 'ADDED',
object => {
apiVersion => 'v1',
kind => 'Pod',
metadata => {
name => 'coredns-xyz',
namespace => 'kube-system',
resourceVersion => '500',
},
spec => { containers => [$container] },
status => { phase => 'Running' },
},
},
{
type => 'MODIFIED',
object => {
apiVersion => 'v1',
kind => 'Pod',
metadata => {
name => 'coredns-xyz',
namespace => 'kube-system',
resourceVersion => '505',
},
spec => { containers => [$container] },
status => { phase => 'Running' },
},
},
]);
my $last_rv = $api->watch('Pod',
namespace => 'kube-system',
on_event => sub {},
);
is($last_rv, '505', 'returns last resourceVersion');
};
# === Test 3: Watch without on_event dies ===
subtest 'watch without on_event dies' => sub {
throws_ok {
$api->watch('Pod', namespace => 'default');
} qr/on_event/, 'dies without on_event callback';
};
# === Test 4: Watch CRD class ===
subtest 'watch CRD class' => sub {
require My::StaticWebSite;
# Build API with CRD registered
my $crd_io = Test::Kubernetes::Mock::IO->new;
my $default_map = IO::K8s->default_resource_map;
my $crd_api = Kubernetes::REST->new(
server => Kubernetes::REST::Server->new(endpoint => 'http://mock.local'),
credentials => Kubernetes::REST::AuthToken->new(token => 'MockToken'),
resource_map_from_cluster => 0,
resource_map => {
%$default_map,
StaticWebSite => '+My::StaticWebSite',
},
io => $crd_io,
);
$crd_io->add_watch_events('/apis/homelab.example.com/v1/namespaces/default/staticwebsites', [
{
type => 'ADDED',
object => {
apiVersion => 'homelab.example.com/v1',
kind => 'StaticWebSite',
metadata => {
name => 'my-blog',
namespace => 'default',
resourceVersion => '200',
},
spec => {
domain => 'blog.example.com',
image => 'nginx:1.27',
replicas => 2,
},
},
},
]);
my @events;
$crd_api->watch('StaticWebSite',
namespace => 'default',
on_event => sub { push @events, $_[0] },
);
is(scalar @events, 1, 'received CRD event');
is($events[0]->type, 'ADDED', 'CRD event type');
is($events[0]->object->metadata->name, 'my-blog', 'CRD object name');
is($events[0]->object->spec->{domain}, 'blog.example.com', 'CRD spec preserved');
};
# === Test 5: ERROR event handling ===
subtest 'ERROR event handling' => sub {
$mock_io->add_watch_events('/api/v1/namespaces/test/pods', [
{
type => 'ADDED',
object => {
apiVersion => 'v1',
kind => 'Pod',
metadata => {
name => 'test-pod',
namespace => 'test',
resourceVersion => '300',
},
spec => { containers => [$container] },
status => { phase => 'Running' },
},
},
{
type => 'ERROR',
( run in 0.491 second using v1.01-cache-2.11-cpan-524268b4103 )