| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Chef::Knife::Cmd; |
|
2
|
6
|
|
|
6
|
|
591946
|
use feature qw/say/; |
|
|
6
|
|
|
|
|
9
|
|
|
|
6
|
|
|
|
|
558
|
|
|
3
|
6
|
|
|
6
|
|
2774
|
use Moo; |
|
|
6
|
|
|
|
|
58835
|
|
|
|
6
|
|
|
|
|
26
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
6
|
|
|
6
|
|
9306
|
use Chef::Knife::Cmd::Client; |
|
|
6
|
|
|
|
|
18
|
|
|
|
6
|
|
|
|
|
192
|
|
|
6
|
6
|
|
|
6
|
|
2623
|
use Chef::Knife::Cmd::EC2; |
|
|
6
|
|
|
|
|
17
|
|
|
|
6
|
|
|
|
|
167
|
|
|
7
|
6
|
|
|
6
|
|
2487
|
use Chef::Knife::Cmd::Node; |
|
|
6
|
|
|
|
|
16
|
|
|
|
6
|
|
|
|
|
189
|
|
|
8
|
6
|
|
|
6
|
|
2618
|
use Chef::Knife::Cmd::Vault; |
|
|
6
|
|
|
|
|
13
|
|
|
|
6
|
|
|
|
|
194
|
|
|
9
|
6
|
|
|
6
|
|
2477
|
use Chef::Knife::Cmd::Search; |
|
|
6
|
|
|
|
|
16
|
|
|
|
6
|
|
|
|
|
193
|
|
|
10
|
6
|
|
|
6
|
|
2525
|
use Chef::Knife::Cmd::DataBag; |
|
|
6
|
|
|
|
|
85
|
|
|
|
6
|
|
|
|
|
158
|
|
|
11
|
6
|
|
|
6
|
|
2549
|
use Shell::Carapace; |
|
|
6
|
|
|
|
|
2004
|
|
|
|
6
|
|
|
|
|
157
|
|
|
12
|
6
|
|
|
6
|
|
2417
|
use String::ShellQuote; |
|
|
6
|
|
|
|
|
4354
|
|
|
|
6
|
|
|
|
|
394
|
|
|
13
|
6
|
|
|
6
|
|
2135
|
use JSON::MaybeXS; |
|
|
6
|
|
|
|
|
27202
|
|
|
|
6
|
|
|
|
|
3594
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = "0.15"; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Chef::Knife::Cmd - A small wrapper around the Chef 'knife' command line utility |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Chef::Knife::Cmd; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# See Shell::Carapace for details about the callback attribute |
|
26
|
|
|
|
|
|
|
my $knife = Chef::Knife::Cmd->new( |
|
27
|
|
|
|
|
|
|
callback => sub { ... }, # optional. useful for logging realtime output; |
|
28
|
|
|
|
|
|
|
); |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# knife bootstrap |
|
31
|
|
|
|
|
|
|
$knife->bootstrap($fqdn, %options); |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# knife client |
|
34
|
|
|
|
|
|
|
$knife->client->delete($client, %options); |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# knife ec2 |
|
37
|
|
|
|
|
|
|
$knife->ec2->server->list(%options); |
|
38
|
|
|
|
|
|
|
$knife->ec2->server->create(%options); |
|
39
|
|
|
|
|
|
|
$knife->ec2->server->delete(\@nodes, %options); |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# knife node |
|
42
|
|
|
|
|
|
|
$knife->node->show($node, %options); |
|
43
|
|
|
|
|
|
|
$knife->node->list($node, %options); |
|
44
|
|
|
|
|
|
|
$knife->node->create($node, %options); |
|
45
|
|
|
|
|
|
|
$knife->node->delete($node, %options); |
|
46
|
|
|
|
|
|
|
$knife->node->flip($node, $environment, %options); |
|
47
|
|
|
|
|
|
|
$knife->node->from->file($file, %options); |
|
48
|
|
|
|
|
|
|
$knife->node->run_list->add($node, \@entries, %options); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# knife vault commands |
|
51
|
|
|
|
|
|
|
# hint: use $knife->vault->item() instead of $knife->vault->show() |
|
52
|
|
|
|
|
|
|
$knife->vault->list(%options); |
|
53
|
|
|
|
|
|
|
$knife->vault->show($vault, $item_name, %options); |
|
54
|
|
|
|
|
|
|
$knife->vault->create($vault, $item, $values, %options); |
|
55
|
|
|
|
|
|
|
$knife->vault->update($vault, $item, $values, %options); |
|
56
|
|
|
|
|
|
|
$knife->vault->delete($vault, $item, %options); |
|
57
|
|
|
|
|
|
|
$knife->vault->remove($vault, $item, $values, %options); |
|
58
|
|
|
|
|
|
|
$knife->vault->download($vault, $item, $path, %options); |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# knife search commands |
|
61
|
|
|
|
|
|
|
$knife->search->node($query, %options); |
|
62
|
|
|
|
|
|
|
$knife->search->client($query, %options); |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# knife data bag commands |
|
65
|
|
|
|
|
|
|
$knife->data_bag->show($data_bag, %options); |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# All methods return the output of the cmd as a string |
|
68
|
|
|
|
|
|
|
my $out = $knife->node->show('mynode'); |
|
69
|
|
|
|
|
|
|
# => |
|
70
|
|
|
|
|
|
|
# Node Name: mynode |
|
71
|
|
|
|
|
|
|
# Environment: production |
|
72
|
|
|
|
|
|
|
# FQDN: |
|
73
|
|
|
|
|
|
|
# IP: 12.34.56.78 |
|
74
|
|
|
|
|
|
|
# Run List: ... |
|
75
|
|
|
|
|
|
|
# ... |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# All methods return the output of the cmd as a hashref when '--format json' is used |
|
78
|
|
|
|
|
|
|
my $hashref = $knife->node->show('mynode', format => 'json'); |
|
79
|
|
|
|
|
|
|
# => |
|
80
|
|
|
|
|
|
|
# { |
|
81
|
|
|
|
|
|
|
# name => "mynode", |
|
82
|
|
|
|
|
|
|
# chef_environment => "production", |
|
83
|
|
|
|
|
|
|
# run_list => [...], |
|
84
|
|
|
|
|
|
|
# ... |
|
85
|
|
|
|
|
|
|
# } |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
This module is a small wrapper around the Chef 'knife' command line utility. |
|
91
|
|
|
|
|
|
|
It would be awesome if this module used the Chef server API, but this module is |
|
92
|
|
|
|
|
|
|
not that awesome. |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Some things worth knowing about this module: |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=over 4 |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item Return vaules |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
All commands return the output of the knife command. |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=item Logging |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
If you wish to log output, you should do so via the 'callback' attribute. See |
|
105
|
|
|
|
|
|
|
Shell::Carapace for more details. |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=item Exceptions |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
If a knife command fails, an exception is thrown. |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=back |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=cut |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
has noop => (is => 'rw', default => sub { 0 }); |
|
116
|
|
|
|
|
|
|
has shell => (is => 'lazy'); |
|
117
|
|
|
|
|
|
|
has format => (is => 'rw'); |
|
118
|
|
|
|
|
|
|
has _json_flag => (is => 'rw'); |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
has callback => (is => 'rw'); |
|
121
|
|
|
|
|
|
|
has output => (is => 'rw'); |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
has client => (is => 'lazy'); |
|
124
|
|
|
|
|
|
|
has ec2 => (is => 'lazy'); |
|
125
|
|
|
|
|
|
|
has node => (is => 'lazy'); |
|
126
|
|
|
|
|
|
|
has vault => (is => 'lazy'); |
|
127
|
|
|
|
|
|
|
has search => (is => 'lazy'); |
|
128
|
|
|
|
|
|
|
has data_bag => (is => 'lazy'); |
|
129
|
|
|
|
|
|
|
|
|
130
|
1
|
|
|
1
|
|
1619
|
sub _build_client { Chef::Knife::Cmd::Client->new(knife => shift) } |
|
131
|
1
|
|
|
1
|
|
1624
|
sub _build_ec2 { Chef::Knife::Cmd::EC2->new(knife => shift) } |
|
132
|
1
|
|
|
1
|
|
1829
|
sub _build_node { Chef::Knife::Cmd::Node->new(knife => shift) } |
|
133
|
1
|
|
|
1
|
|
1586
|
sub _build_vault { Chef::Knife::Cmd::Vault->new(knife => shift) } |
|
134
|
0
|
|
|
0
|
|
0
|
sub _build_search { Chef::Knife::Cmd::Search->new(knife => shift) } |
|
135
|
0
|
|
|
0
|
|
0
|
sub _build_data_bag { Chef::Knife::Cmd::DataBag->new(knife => shift) } |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub _build_shell { |
|
138
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
139
|
|
|
|
|
|
|
my $cb = sub { |
|
140
|
0
|
|
|
0
|
|
0
|
my ($type, $message) = @_; |
|
141
|
0
|
0
|
|
|
|
0
|
if ($type ne 'error') { |
|
142
|
0
|
0
|
|
|
|
0
|
if ($type eq 'command') { |
|
143
|
0
|
|
|
|
|
0
|
$self->output(''); |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
else { |
|
146
|
0
|
|
|
|
|
0
|
my $output = ''; |
|
147
|
0
|
0
|
|
|
|
0
|
$output .= $self->output . "\n" if $self->output; |
|
148
|
0
|
|
|
|
|
0
|
$output .= $message; |
|
149
|
0
|
|
|
|
|
0
|
$self->output($output); |
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
} |
|
152
|
0
|
0
|
|
|
|
0
|
$self->callback->(@_) if $self->callback; |
|
153
|
0
|
|
|
|
|
0
|
}; |
|
154
|
|
|
|
|
|
|
|
|
155
|
0
|
|
|
|
|
0
|
return Shell::Carapace->shell(callback => $cb); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub bootstrap { |
|
159
|
1
|
|
|
1
|
|
1735
|
my ($self, $fqdn, %options) = @_; |
|
160
|
1
|
|
|
|
|
6
|
my @opts = $self->handle_options(%options); |
|
161
|
1
|
|
|
|
|
5
|
my @cmd = (qw/knife bootstrap/, $fqdn, @opts); |
|
162
|
1
|
|
|
|
|
3
|
$self->run(@cmd); |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub handle_options { |
|
166
|
19
|
|
|
19
|
0
|
458
|
my ($self, %options) = @_; |
|
167
|
|
|
|
|
|
|
|
|
168
|
19
|
50
|
0
|
|
|
99
|
$options{format} //= $self->format if $self->format; |
|
169
|
|
|
|
|
|
|
|
|
170
|
19
|
50
|
33
|
|
|
77
|
$options{format} && $options{format} eq 'json' |
|
171
|
|
|
|
|
|
|
? $self->_json_flag(1) |
|
172
|
|
|
|
|
|
|
: $self->_json_flag(0); |
|
173
|
|
|
|
|
|
|
|
|
174
|
19
|
|
|
|
|
16
|
my @opts; |
|
175
|
19
|
|
|
|
|
50
|
for my $option (sort keys %options) { |
|
176
|
19
|
|
|
|
|
23
|
my $value = $options{$option}; |
|
177
|
19
|
|
|
|
|
32
|
$option =~ s/_/-/g; |
|
178
|
|
|
|
|
|
|
|
|
179
|
19
|
|
|
|
|
27
|
push @opts, "--$option"; |
|
180
|
19
|
100
|
|
|
|
41
|
push @opts, $value if $value ne "1"; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
|
|
183
|
19
|
|
|
|
|
62
|
return @opts; |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub run { |
|
187
|
19
|
|
|
19
|
0
|
439
|
my ($self, @cmds) = @_; |
|
188
|
19
|
50
|
|
|
|
96
|
return shell_quote @cmds if $self->noop; |
|
189
|
0
|
|
|
|
|
|
$self->shell->run(@cmds); |
|
190
|
0
|
|
|
|
|
|
my $out = $self->output; |
|
191
|
0
|
0
|
|
|
|
|
return JSON->new->utf8->decode($out) if $self->_json_flag; |
|
192
|
0
|
|
|
|
|
|
return $out; |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
1; |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=over 4 |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=item L<Capture::Tiny::Extended> |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item L<Capture::Tiny> |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item L<IPC::System::Simple> |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=back |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head1 LICENSE |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
|
212
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head1 AUTHOR |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Eric Johnson E<lt>eric.git@iijo.orgE<gt> |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=cut |