Kubernetes-REST
view release on metacpan or search on metacpan
t/22_exec.t view on Meta::CPAN
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use Test::Exception;
use FindBin;
use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/../lib";
use Kubernetes::REST;
use Kubernetes::REST::Server;
use Kubernetes::REST::AuthToken;
use Kubernetes::REST::HTTPResponse;
{
package Test::Exec::BasicIO;
use Moo;
with 'Kubernetes::REST::Role::IO';
sub call {
return Kubernetes::REST::HTTPResponse->new(status => 200, content => '{}');
}
sub call_streaming {
return Kubernetes::REST::HTTPResponse->new(status => 200, content => '');
}
}
{
package Test::Exec::DuplexIO;
use Moo;
with 'Kubernetes::REST::Role::IO';
has last_req => (is => 'rw');
has last_opts => (is => 'rw');
sub call {
return Kubernetes::REST::HTTPResponse->new(status => 200, content => '{}');
}
sub call_streaming {
return Kubernetes::REST::HTTPResponse->new(status => 200, content => '');
}
sub call_duplex {
my ($self, $req, %opts) = @_;
$self->last_req($req);
$self->last_opts(\%opts);
return { ok => 1, type => 'duplex-session' };
}
}
sub make_api {
my ($io) = @_;
return Kubernetes::REST->new(
server => Kubernetes::REST::Server->new(endpoint => 'https://mock.local'),
credentials => Kubernetes::REST::AuthToken->new(token => 'MockToken'),
resource_map_from_cluster => 0,
io => $io,
);
}
subtest 'exec requires name and command' => sub {
my $api = make_api(Test::Exec::DuplexIO->new);
throws_ok {
$api->exec('Pod', namespace => 'default', command => ['sh']);
} qr/name required for exec/, 'name is required';
throws_ok {
$api->exec('Pod', 'nginx', namespace => 'default');
} qr/command required for exec/, 'command is required';
};
subtest 'exec validates command' => sub {
my $api = make_api(Test::Exec::DuplexIO->new);
throws_ok {
$api->exec('Pod', 'nginx', namespace => 'default', command => []);
} qr/command required for exec/, 'empty command rejected';
throws_ok {
$api->exec('Pod', 'nginx', namespace => 'default', command => [undef]);
} qr/invalid command element/, 'undefined element rejected';
throws_ok {
$api->exec('Pod', 'nginx', namespace => 'default', command => [{ bad => 1 }]);
} qr/invalid command element/, 'non-scalar element rejected';
};
subtest 'exec fails when backend has no duplex transport' => sub {
my $api = make_api(Test::Exec::BasicIO->new);
throws_ok {
$api->exec('Pod', 'nginx', namespace => 'default', command => ['sh']);
} qr/missing call_duplex/, 'clear error for unsupported backend';
};
subtest 'exec builds request and forwards callbacks' => sub {
my $io = Test::Exec::DuplexIO->new;
my $api = make_api($io);
my $open_called = 0;
my $frame_cb = sub { };
my $close_cb = sub { };
my $error_cb = sub { };
my $session = $api->exec('Pod', 'nginx',
namespace => 'default',
command => ['sh', '-c', 'echo hello'],
container => 'app',
stdin => 1,
stdout => 1,
stderr => 0,
tty => 1,
on_open => sub { $open_called = 1 },
( run in 0.578 second using v1.01-cache-2.11-cpan-524268b4103 )