Kubernetes-REST
view release on metacpan or search on metacpan
t/14_kubeconfig.t view on Meta::CPAN
};
my $config_file = "$tmpdir/kubeconfig";
YAML::XS::DumpFile($config_file, $kubeconfig);
# ============================================================================
# Tests
# ============================================================================
subtest 'construction' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
ok $kc, 'Kubeconfig created';
is $kc->kubeconfig_path, $config_file, 'kubeconfig_path set';
};
subtest 'current_context_name - default' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
is $kc->current_context_name, 'production', 'default context is production';
};
subtest 'current_context_name - override' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(
kubeconfig_path => $config_file,
context_name => 'development',
);
is $kc->current_context_name, 'development', 'context overridden to development';
};
subtest 'contexts - list all' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $contexts = $kc->contexts;
is ref $contexts, 'ARRAY', 'contexts returns arrayref';
is scalar @$contexts, 3, 'three contexts';
is_deeply [sort @$contexts], ['development', 'insecure', 'production'],
'correct context names';
};
subtest 'context - lookup by name' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $ctx = $kc->context('production');
is $ctx->{cluster}, 'prod-cluster', 'production context cluster';
is $ctx->{user}, 'token-user', 'production context user';
is $ctx->{namespace}, 'prod', 'production context namespace';
};
subtest 'context - defaults to current context' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $ctx = $kc->context;
is $ctx->{cluster}, 'prod-cluster', 'default context is production cluster';
};
subtest 'context - not found' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
throws_ok { $kc->context('nonexistent') } qr/Context not found: nonexistent/,
'throws for unknown context';
};
subtest 'cluster - lookup by name' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $cluster = $kc->cluster('prod-cluster');
is $cluster->{server}, 'https://prod.k8s.local:6443', 'cluster server endpoint';
is $cluster->{'certificate-authority'}, $ca_file, 'cluster CA file';
};
subtest 'cluster - not found' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
throws_ok { $kc->cluster('nonexistent') } qr/Cluster not found/,
'throws for unknown cluster';
};
subtest 'user - token user' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $user = $kc->user('token-user');
is $user->{token}, 'my-secret-token-12345', 'token retrieved';
};
subtest 'user - cert user' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $user = $kc->user('cert-user');
is $user->{'client-certificate'}, $cert_file, 'cert file path';
is $user->{'client-key'}, $key_file, 'key file path';
};
subtest 'user - not found' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
throws_ok { $kc->user('nonexistent') } qr/User not found/,
'throws for unknown user';
};
subtest 'api - token auth with CA file' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $api = $kc->api('production');
isa_ok $api, 'Kubernetes::REST';
is $api->server->endpoint, 'https://prod.k8s.local:6443', 'server endpoint';
is $api->server->ssl_verify_server, 1, 'SSL verification enabled';
is $api->server->ssl_ca_file, $ca_file, 'CA file set';
is $api->credentials->token, 'my-secret-token-12345', 'token set';
};
subtest 'api - cert auth with cert file references' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $api = $kc->api('development');
isa_ok $api, 'Kubernetes::REST';
is $api->server->endpoint, 'https://dev.k8s.local:6443', 'dev server endpoint';
is $api->server->ssl_cert_file, $cert_file, 'client cert file set';
is $api->server->ssl_key_file, $key_file, 'client key file set';
# CA from base64 data should be in-memory PEM, not a file
ok $api->server->ssl_ca_pem, 'CA PEM data set (from base64 data)';
ok !$api->server->ssl_ca_file, 'no CA file (in-memory instead)';
};
subtest 'api - insecure skip TLS verify' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $api = $kc->api('insecure');
is $api->server->ssl_verify_server, 0, 'SSL verification disabled';
# No auth user should get empty token
is $api->credentials->token, '', 'empty token for no-auth user';
};
subtest 'api - default context' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
my $api = $kc->api;
is $api->server->endpoint, 'https://prod.k8s.local:6443',
'api() without args uses current-context';
};
subtest 'api - with context_name constructor arg' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(
kubeconfig_path => $config_file,
context_name => 'development',
);
my $api = $kc->api;
is $api->server->endpoint, 'https://dev.k8s.local:6443',
'api() uses context_name from constructor';
};
subtest 'missing kubeconfig file' => sub {
my $kc = Kubernetes::REST::Kubeconfig->new(
kubeconfig_path => '/nonexistent/kubeconfig',
);
throws_ok { $kc->contexts } qr/Kubeconfig not found/,
'throws for missing kubeconfig file';
};
subtest 'in-memory PEM survives kubeconfig destruction' => sub {
my $api;
{
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $config_file);
$api = $kc->api('development');
}
# After $kc goes out of scope, PEM data lives in the API server object
ok $api->server->ssl_ca_pem, 'CA PEM still available after kubeconfig destroyed';
is $api->server->ssl_ca_pem, decode_base64($ca_data), 'PEM data matches original';
};
subtest 'inline cert-data uses PEM attributes, file refs use file attributes' => sub {
# Add a context that uses inline cert-data for user creds
my $inline_config = {
%$kubeconfig,
contexts => [
@{$kubeconfig->{contexts}},
{
name => 'inline-certs',
context => {
cluster => 'dev-cluster',
user => 'cert-data-user',
},
},
],
};
my $inline_file = "$tmpdir/kubeconfig-inline";
YAML::XS::DumpFile($inline_file, $inline_config);
my $kc = Kubernetes::REST::Kubeconfig->new(kubeconfig_path => $inline_file);
my $api = $kc->api('inline-certs');
# User has inline cert-data â PEM attributes
ok $api->server->ssl_cert_pem, 'client cert is PEM (from inline data)';
ok $api->server->ssl_key_pem, 'client key is PEM (from inline data)';
ok !$api->server->ssl_cert_file, 'no cert file (in-memory)';
ok !$api->server->ssl_key_file, 'no key file (in-memory)';
# Cluster has inline CA data â PEM
ok $api->server->ssl_ca_pem, 'CA is PEM (from inline data)';
ok !$api->server->ssl_ca_file, 'no CA file (in-memory)';
# File-based context still uses file attributes
my $api2 = $kc->api('production');
is $api2->server->ssl_ca_file, $ca_file, 'file-based CA uses ssl_ca_file';
ok !$api2->server->ssl_ca_pem, 'no PEM for file-based CA';
};
done_testing;
( run in 0.567 second using v1.01-cache-2.11-cpan-524268b4103 )