Skip to content

Commit ed36c68

Browse files
committed
kubeconfig module
1 parent f38f392 commit ed36c68

File tree

4 files changed

+156
-26
lines changed

4 files changed

+156
-26
lines changed

cpanfile

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
requires 'Carp';
22
requires 'JSON';
3+
requires 'YAML::XS';
34
requires 'DateTime';
45
requires 'Log::Any';
56
requires 'Module::Runtime';
@@ -8,6 +9,7 @@ requires 'Module::Find';
89
requires 'LWP::UserAgent';
910
requires 'LWP::Protocol::https';
1011
requires 'Class::Accessor';
12+
requires 'MIME::Base64';
1113

1214
on 'test' => sub {
1315
requires 'Test::Simple';

examples/load_kubeconfig.pl

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use strict;
2+
use warnings FATAL => 'all';
3+
4+
use Kubernetes::Util::KubeConfig;
5+
6+
use Log::Any::Adapter ('Stdout');
7+
use Log::Any::Adapter ('Stderr');
8+
9+
use Net::SSLeay;
10+
$Net::SSLeay::trace = 2;
11+
12+
my $kubeconfig = Kubernetes::Util::KubeConfig->load_yaml_file();
13+
14+
my $api_factory = $kubeconfig->new_api_factory();
15+
16+
my $corev1_api = $api_factory->get_api('CoreV1');
17+
18+
my $namespaceList = $corev1_api->list_namespace();
19+
20+
printf "found %d namespaces:\n", scalar @{$namespaceList->items};
21+
printf "=====================\n";
22+
foreach my $namespace (@{$namespaceList->items}) {
23+
printf "%s\n", $namespace->metadata->name;
24+
}

examples/ssl_client.pl

-26
This file was deleted.

lib/Kubernetes/Util/KubeConfig.pm

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package Kubernetes::Util::KubeConfig;
2+
3+
use strict;
4+
use warnings FATAL => 'all';
5+
use Carp;
6+
7+
use YAML::XS qw(Load LoadFile);
8+
use MIME::Base64;
9+
use Kubernetes::ApiClient;
10+
use Kubernetes::ApiFactory;
11+
use IO::Socket::SSL;
12+
use Log::Any qw($log);
13+
use IO::Socket::SSL::Utils;
14+
15+
use base 'Exporter';
16+
17+
our @EXPORT = qw(
18+
load_yaml_file
19+
load_yaml
20+
new_api_factory
21+
);
22+
23+
sub load_yaml_file {
24+
my ($self, $yaml_file_path) = @_;
25+
26+
if (not defined $yaml_file_path) {
27+
$log->debugf('Defaulting Kube-Config file path to $HOME/.kube/config');
28+
$yaml_file_path = $ENV{HOME} . '/.kube/config';
29+
}
30+
31+
die "$yaml_file_path doesn't exist!" if not -e $yaml_file_path;
32+
33+
my $kubeconfig = LoadFile($yaml_file_path);
34+
bless $kubeconfig => $self;
35+
36+
$kubeconfig->validate;
37+
38+
return $kubeconfig;
39+
}
40+
41+
sub load_yaml {
42+
my ($self, $yaml_str) = @_;
43+
44+
if (not defined $yaml_str) {
45+
return undef;
46+
}
47+
48+
my $kubeconfig = Load($yaml_str);
49+
bless $kubeconfig => $self;
50+
51+
$kubeconfig->validate;
52+
53+
return $kubeconfig;
54+
}
55+
56+
sub validate {
57+
my ($self) = @_;
58+
if (not defined $self->{apiVersion} || $self->{apiVersion} ne 'v1') {
59+
die "Invalid Kube-Config content: ('apiVersion' is not 'v1')";
60+
}
61+
if (not defined $self->{kind} || $self->{kind} ne 'Config') {
62+
die "Invalid Kube-Config content: ('kind' is not 'v1')";
63+
}
64+
if (not defined $self->{contexts}) {
65+
die "Invalid Kube-Config content: missing 'contexts' section";
66+
}
67+
if (not defined $self->{clusters}) {
68+
die "Invalid Kube-Config content: missing 'clusters' section";
69+
}
70+
if (not defined $self->{users}) {
71+
die "Invalid Kube-Config content: missing 'users' section";
72+
}
73+
if (not defined $self->{'current-context'}) {
74+
die "Invalid Kube-Config content: missing 'current-context' section";
75+
}
76+
}
77+
78+
sub new_api_factory {
79+
my ($self) = @_;
80+
81+
my $context_name = $self->{'current-context'};
82+
my $cluster_name;
83+
my $user_name;
84+
85+
foreach my $ctx (@{$self->{contexts}}) {
86+
if ($context_name eq $ctx->{name}) {
87+
$cluster_name = $ctx->{context}->{cluster};
88+
$user_name = $ctx->{context}->{user};
89+
}
90+
}
91+
92+
93+
my $current_cluster;
94+
foreach my $cluster (@{$self->{clusters}}) {
95+
if ($cluster_name eq $cluster->{name}) {
96+
$current_cluster = $cluster;
97+
}
98+
}
99+
100+
101+
my $current_user;
102+
foreach my $user (@{$self->{users}}) {
103+
if ($user_name eq $user->{name}) {
104+
$current_user = $user;
105+
}
106+
}
107+
108+
my %ssl_opts;
109+
110+
my $skip_tls_verify = $current_cluster->{cluster}->{'insecure-skip-tls-verify'};
111+
112+
if (defined $skip_tls_verify && $skip_tls_verify == 1) {
113+
$ssl_opts{verify_hostname} = 0;
114+
$ssl_opts{SSL_verify_mode} = IO::Socket::SSL::SSL_VERIFY_NONE;
115+
} else {
116+
# print Dumper($current_cluster);
117+
$ssl_opts{SSL_ca} = [PEM_string2cert(decode_base64($current_cluster->{cluster}->{'certificate-authority-data'}))];
118+
$ssl_opts{SSL_use_cert} = 1;
119+
}
120+
121+
$ssl_opts{SSL_cert} = PEM_string2cert(decode_base64($current_user->{user}->{'client-certificate-data'}));
122+
$ssl_opts{SSL_key} = PEM_string2key(decode_base64($current_user->{user}->{'client-key-data'}));
123+
124+
return Kubernetes::ApiFactory->new(
125+
base_url => $current_cluster->{cluster}->{server},
126+
ssl_opts => \%ssl_opts,
127+
);
128+
}
129+
130+
1;

0 commit comments

Comments
 (0)