line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Kubectl::CLIWrapper { |
2
|
1
|
|
|
1
|
|
67529
|
use Moo; |
|
1
|
|
|
|
|
11156
|
|
|
1
|
|
|
|
|
5
|
|
3
|
1
|
|
|
1
|
|
1895
|
use IPC::Open3; |
|
1
|
|
|
|
|
3971
|
|
|
1
|
|
|
|
|
54
|
|
4
|
1
|
|
|
1
|
|
460
|
use JSON::MaybeXS; |
|
1
|
|
|
|
|
7962
|
|
|
1
|
|
|
|
|
62
|
|
5
|
1
|
|
|
1
|
|
430
|
use Kubectl::CLIWrapper::Result; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
38
|
|
6
|
1
|
|
|
1
|
|
521
|
use Type::Tiny::Union; |
|
1
|
|
|
|
|
2168
|
|
|
1
|
|
|
|
|
35
|
|
7
|
1
|
|
|
1
|
|
10
|
use Types::Standard qw/Str CodeRef Bool/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
8
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '0.06'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my $TOKEN_TYPE = Type::Tiny::Union->new( |
12
|
|
|
|
|
|
|
type_constraints => [Str, CodeRef] |
13
|
|
|
|
|
|
|
); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has kubeconfig => (is => 'ro', isa => Str, predicate => 'has_kubeconfig'); |
16
|
|
|
|
|
|
|
has kubectl => (is => 'ro', isa => Str, default => 'kubectl'); |
17
|
|
|
|
|
|
|
has namespace => (is => 'ro', isa => Str, predicate => 'has_namespace'); |
18
|
|
|
|
|
|
|
has password => (is => 'ro', isa => Str, predicate => 'has_password'); |
19
|
|
|
|
|
|
|
has server => (is => 'ro', isa => Str, predicate => 'has_server'); |
20
|
|
|
|
|
|
|
has token => (is => 'ro', isa => $TOKEN_TYPE, predicate => 'has_token'); |
21
|
|
|
|
|
|
|
has username => (is => 'ro', isa => Str, predicate => 'has_username'); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has insecure_tls => (is => 'ro', isa => Bool, default => 0); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub kube_options { |
26
|
12
|
|
|
12
|
0
|
27
|
my $self = shift; |
27
|
12
|
|
|
|
|
47
|
my %options = (); |
28
|
|
|
|
|
|
|
|
29
|
12
|
100
|
|
|
|
100
|
$options{server} = $self->server if $self->has_server; |
30
|
12
|
100
|
|
|
|
63
|
$options{username} = $self->username if $self->has_username; |
31
|
12
|
100
|
|
|
|
67
|
$options{password} = $self->password if $self->has_password; |
32
|
12
|
50
|
|
|
|
58
|
$options{namespace} = $self->namespace if $self->has_namespace; |
33
|
12
|
100
|
|
|
|
39
|
$options{kubeconfig} = $self->kubeconfig if $self->has_kubeconfig; |
34
|
12
|
50
|
|
|
|
38
|
$options{'insecure-skip-tls-verify'} = 'true' if $self->insecure_tls; |
35
|
|
|
|
|
|
|
|
36
|
12
|
100
|
|
|
|
33
|
if ($self->has_token) { |
37
|
|
|
|
|
|
|
$options{token} = ref($self->token) eq 'CODE' |
38
|
3
|
100
|
|
|
|
15
|
? &{$self->token}() |
|
2
|
|
|
|
|
9
|
|
39
|
|
|
|
|
|
|
: $self->token; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
12
|
|
|
|
|
51
|
return [ map { "--$_=$options{ $_ }" } keys %options ]; |
|
22
|
|
|
|
|
136
|
|
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub command_for { |
46
|
12
|
|
|
12
|
0
|
14186
|
my ($self, @params) = @_; |
47
|
12
|
|
|
|
|
46
|
return ($self->kubectl, @{ $self->kube_options }, @params); |
|
12
|
|
|
|
|
88
|
|
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub run { |
51
|
4
|
|
|
4
|
1
|
6349
|
my ($self, @command) = @_; |
52
|
4
|
|
|
|
|
17
|
return $self->input(undef, @command); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub json { |
56
|
1
|
|
|
1
|
1
|
2052
|
my ($self, @command) = @_; |
57
|
|
|
|
|
|
|
|
58
|
1
|
|
|
|
|
8
|
push @command, '-o=json'; |
59
|
|
|
|
|
|
|
|
60
|
1
|
|
|
|
|
18
|
my $result = $self->run(@command); |
61
|
1
|
|
|
|
|
196
|
my $struct = eval { |
62
|
1
|
|
|
|
|
39
|
JSON->new->decode($result->output); |
63
|
|
|
|
|
|
|
}; |
64
|
1
|
50
|
|
|
|
328
|
if ($@) { |
65
|
0
|
|
|
|
|
0
|
return Kubectl::CLIWrapper::Result->new( |
66
|
|
|
|
|
|
|
rc => $result->rc, |
67
|
|
|
|
|
|
|
output => $result->output, |
68
|
|
|
|
|
|
|
success => 0 |
69
|
|
|
|
|
|
|
); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
1
|
|
|
|
|
41
|
return Kubectl::CLIWrapper::Result->new( |
73
|
|
|
|
|
|
|
rc => $result->rc, |
74
|
|
|
|
|
|
|
output => $result->output, |
75
|
|
|
|
|
|
|
json => $struct |
76
|
|
|
|
|
|
|
); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub input { |
80
|
7
|
|
|
7
|
1
|
6039
|
my ($self, $input, @params) = @_; |
81
|
|
|
|
|
|
|
|
82
|
7
|
|
|
|
|
145
|
my @final_command = $self->command_for(@params); |
83
|
|
|
|
|
|
|
|
84
|
7
|
|
|
|
|
19
|
my ($stdin, $stdout, $stderr); |
85
|
7
|
|
|
|
|
35
|
my $pid = open3($stdin, $stdout, $stderr, @final_command); |
86
|
7
|
100
|
|
|
|
27836
|
print $stdin $input if(defined $input); |
87
|
7
|
|
|
|
|
88
|
close $stdin; |
88
|
|
|
|
|
|
|
|
89
|
7
|
|
|
|
|
23046
|
my $out = join '', <$stdout>; |
90
|
7
|
50
|
|
|
|
172
|
my $err = join '', <$stderr> if ($stderr); |
91
|
|
|
|
|
|
|
|
92
|
7
|
50
|
|
|
|
46
|
die "Unexpected contents in stderr $err" if ($err); |
93
|
|
|
|
|
|
|
|
94
|
7
|
|
|
|
|
199
|
waitpid( $pid, 0 ); |
95
|
7
|
|
|
|
|
106
|
my $rc = $? >> 8; |
96
|
|
|
|
|
|
|
|
97
|
7
|
|
|
|
|
879
|
return Kubectl::CLIWrapper::Result->new( |
98
|
|
|
|
|
|
|
rc => $rc, |
99
|
|
|
|
|
|
|
output => $out, |
100
|
|
|
|
|
|
|
); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
1; |
105
|
|
|
|
|
|
|
### main pod documentation begin ### |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=encoding UTF-8 |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head1 NAME |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Kubectl::CLIWrapper - Module to use the Kubernetes API via the kubectl CLI |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head1 SYNOPSIS |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
use Kubectl::CLIWrapper; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
my $kube = Kubectl::CLIWrapper->new( |
118
|
|
|
|
|
|
|
server => 'https://kubernetes.example.org/', |
119
|
|
|
|
|
|
|
username => 'user', |
120
|
|
|
|
|
|
|
password => 'pass', |
121
|
|
|
|
|
|
|
); |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
my $result = $kube->run('explain', 'service'); |
124
|
|
|
|
|
|
|
# $result->success == 1 if the command executed correctly |
125
|
|
|
|
|
|
|
# $result->output contains the output of the command |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
my $result = $kube->json('get', 'pods'); |
128
|
|
|
|
|
|
|
# $result->success == 1 if the command executed correctly |
129
|
|
|
|
|
|
|
# $result->output contains the output of the command |
130
|
|
|
|
|
|
|
# $result->json is a hashref with the result of the parsed JSON output of the command |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
my $result = $kube->input('{"kind":"Service" ... }', 'create', '-f', '-'); |
133
|
|
|
|
|
|
|
# $result->success == 1 if the command executed correctly |
134
|
|
|
|
|
|
|
# $result->output contains the output of the command |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head1 DESCRIPTION |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
This module helps you use the Kubernetes API. It sends all it's commands |
139
|
|
|
|
|
|
|
via the CLI command line tool C. You can find kubectl installation instructions |
140
|
|
|
|
|
|
|
here L. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head1 CREDENTIALS |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Kubectl::CLIWrapper attributes are mainly the options you can pass C to control |
145
|
|
|
|
|
|
|
how it authenticates to the Kubernetes server. Run C to discover what these |
146
|
|
|
|
|
|
|
options do. If you don't initialize any attributes, kubectl will behave just like on the command |
147
|
|
|
|
|
|
|
line (loading ~/.kube/config) which may be already set to point to a Kubernetes server |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head2 kubectl |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
By default initialized to C. It will try to find kubectl in the PATH. You can |
154
|
|
|
|
|
|
|
set it explicitly to specific kubectl excecutable. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=head2 kubeconfig |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
Path to your kube configuration, defaults to C<$HOME/.kube/config> via kubectl. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 server |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
The URL of the Kubernetes service |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=head2 username |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
The username for Basic Authentication |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 password |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
The password for Basic Authentication |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head2 token |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
The Bearer token for authentication. If it's a scalar, that value will be used. If it's |
175
|
|
|
|
|
|
|
a coderef (sub {}), it will be invoked each time kubectl is called and it's return value |
176
|
|
|
|
|
|
|
used as the value of the --token option |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=head2 insecure_tls |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
A Boolean flag that tells kubectl to not verify the certificate of the server it connects to |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=head2 namespace |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
The Kubernetes namespace to operate in. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head1 METHODS |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head2 run(@parameters) |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Will run kubectl with the parameters. Returns a L object |
191
|
|
|
|
|
|
|
with C |
192
|
|
|
|
|
|
|
if the command reported successful execution. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head2 json(@parameters) |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
Will run kubectl with the parameters, and C<'-o=json'>. Returns a L object |
197
|
|
|
|
|
|
|
with C |
198
|
|
|
|
|
|
|
JSON. C will be false if JSON parsing fails. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head2 input($input_to_kubectl, @parameters) |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Will run kubectl with the parametes, sending $input_to_kubectl on it's STDIN. |
203
|
|
|
|
|
|
|
Returns a L object with C |
204
|
|
|
|
|
|
|
C will be set accordingly. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head1 SEE ALSO |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
L |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
L |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
L |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
L |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
waterkip: |
219
|
|
|
|
|
|
|
- adding the possiblity to set a kubeconfig file |
220
|
|
|
|
|
|
|
- helping port to Moose |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
ureesoriano: |
223
|
|
|
|
|
|
|
- fix for token attribute being ignored |
224
|
|
|
|
|
|
|
- dynamic generation of the "token" command-line option |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head1 AUTHOR |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Jose Luis Martinez |
229
|
|
|
|
|
|
|
CAPSiDE |
230
|
|
|
|
|
|
|
jlmartinez@capside.com |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=head1 BUGS and SOURCE |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
The source code is located here: L |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
Please report bugs to: L |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=head1 COPYRIGHT and LICENSE |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Copyright (c) 2018 by CAPSiDE |
241
|
|
|
|
|
|
|
This code is distributed under the Apache 2 License. The full text of the |
242
|
|
|
|
|
|
|
license can be found in the LICENSE file included with this module. |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=cut |