line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Chef::Knife::Cmd; |
2
|
6
|
|
|
6
|
|
246915
|
use feature qw/say/; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
437
|
|
3
|
6
|
|
|
6
|
|
2533
|
use Moo; |
|
6
|
|
|
|
|
53403
|
|
|
6
|
|
|
|
|
22
|
|
4
|
|
|
|
|
|
|
|
5
|
6
|
|
|
6
|
|
8006
|
use Chef::Knife::Cmd::Client; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
176
|
|
6
|
6
|
|
|
6
|
|
1948
|
use Chef::Knife::Cmd::EC2; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
153
|
|
7
|
6
|
|
|
6
|
|
1929
|
use Chef::Knife::Cmd::Node; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
139
|
|
8
|
6
|
|
|
6
|
|
1939
|
use Chef::Knife::Cmd::Vault; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
151
|
|
9
|
6
|
|
|
6
|
|
1854
|
use Chef::Knife::Cmd::Search; |
|
6
|
|
|
|
|
8
|
|
|
6
|
|
|
|
|
145
|
|
10
|
6
|
|
|
6
|
|
1889
|
use Chef::Knife::Cmd::DataBag; |
|
6
|
|
|
|
|
68
|
|
|
6
|
|
|
|
|
147
|
|
11
|
6
|
|
|
6
|
|
2162
|
use Shell::Carapace; |
|
6
|
|
|
|
|
1648
|
|
|
6
|
|
|
|
|
115
|
|
12
|
6
|
|
|
6
|
|
2104
|
use String::ShellQuote; |
|
6
|
|
|
|
|
3440
|
|
|
6
|
|
|
|
|
326
|
|
13
|
6
|
|
|
6
|
|
2184
|
use JSON::MaybeXS; |
|
6
|
|
|
|
|
22650
|
|
|
6
|
|
|
|
|
3264
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = "0.14"; |
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
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# knife search commands |
60
|
|
|
|
|
|
|
$knife->search->node($query, %options); |
61
|
|
|
|
|
|
|
$knife->search->client($query, %options); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# knife data bag commands |
64
|
|
|
|
|
|
|
$knife->data_bag->show($data_bag, %options); |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# All methods return the output of the cmd as a string |
67
|
|
|
|
|
|
|
my $out = $knife->node->show('mynode'); |
68
|
|
|
|
|
|
|
# => |
69
|
|
|
|
|
|
|
# Node Name: mynode |
70
|
|
|
|
|
|
|
# Environment: production |
71
|
|
|
|
|
|
|
# FQDN: |
72
|
|
|
|
|
|
|
# IP: 12.34.56.78 |
73
|
|
|
|
|
|
|
# Run List: ... |
74
|
|
|
|
|
|
|
# ... |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# All methods return the output of the cmd as a hashref when '--format json' is used |
77
|
|
|
|
|
|
|
my $hashref = $knife->node->show('mynode', format => 'json'); |
78
|
|
|
|
|
|
|
# => |
79
|
|
|
|
|
|
|
# { |
80
|
|
|
|
|
|
|
# name => "mynode", |
81
|
|
|
|
|
|
|
# chef_environment => "production", |
82
|
|
|
|
|
|
|
# run_list => [...], |
83
|
|
|
|
|
|
|
# ... |
84
|
|
|
|
|
|
|
# } |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=head1 DESCRIPTION |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
This module is a small wrapper around the Chef 'knife' command line utility. |
90
|
|
|
|
|
|
|
It would be awesome if this module used the Chef server API, but this module is |
91
|
|
|
|
|
|
|
not that awesome. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Some things worth knowing about this module: |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=over 4 |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item Return vaules |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
All commands return the output of the knife command. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=item Logging |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
If you wish to log output, you should do so via the 'callback' attribute. See |
104
|
|
|
|
|
|
|
Shell::Carapace for more details. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item Exceptions |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
If a knife command fails, an exception is thrown. |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=back |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=cut |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
has noop => (is => 'rw', default => sub { 0 }); |
115
|
|
|
|
|
|
|
has shell => (is => 'lazy'); |
116
|
|
|
|
|
|
|
has format => (is => 'rw'); |
117
|
|
|
|
|
|
|
has _json_flag => (is => 'rw'); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
has callback => (is => 'rw'); |
120
|
|
|
|
|
|
|
has output => (is => 'rw'); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
has client => (is => 'lazy'); |
123
|
|
|
|
|
|
|
has ec2 => (is => 'lazy'); |
124
|
|
|
|
|
|
|
has node => (is => 'lazy'); |
125
|
|
|
|
|
|
|
has vault => (is => 'lazy'); |
126
|
|
|
|
|
|
|
has search => (is => 'lazy'); |
127
|
|
|
|
|
|
|
has data_bag => (is => 'lazy'); |
128
|
|
|
|
|
|
|
|
129
|
1
|
|
|
1
|
|
1610
|
sub _build_client { Chef::Knife::Cmd::Client->new(knife => shift) } |
130
|
1
|
|
|
1
|
|
1547
|
sub _build_ec2 { Chef::Knife::Cmd::EC2->new(knife => shift) } |
131
|
1
|
|
|
1
|
|
1582
|
sub _build_node { Chef::Knife::Cmd::Node->new(knife => shift) } |
132
|
1
|
|
|
1
|
|
1503
|
sub _build_vault { Chef::Knife::Cmd::Vault->new(knife => shift) } |
133
|
0
|
|
|
0
|
|
0
|
sub _build_search { Chef::Knife::Cmd::Search->new(knife => shift) } |
134
|
0
|
|
|
0
|
|
0
|
sub _build_data_bag { Chef::Knife::Cmd::DataBag->new(knife => shift) } |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub _build_shell { |
137
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
138
|
|
|
|
|
|
|
my $cb = sub { |
139
|
0
|
|
|
0
|
|
0
|
my ($type, $message) = @_; |
140
|
0
|
0
|
|
|
|
0
|
if ($type ne 'error') { |
141
|
0
|
0
|
|
|
|
0
|
if ($type eq 'command') { |
142
|
0
|
|
|
|
|
0
|
$self->output(''); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
else { |
145
|
0
|
|
|
|
|
0
|
my $output = ''; |
146
|
0
|
0
|
|
|
|
0
|
$output .= $self->output . "\n" if $self->output; |
147
|
0
|
|
|
|
|
0
|
$output .= $message; |
148
|
0
|
|
|
|
|
0
|
$self->output($output); |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
} |
151
|
0
|
0
|
|
|
|
0
|
$self->callback->(@_) if $self->callback; |
152
|
0
|
|
|
|
|
0
|
}; |
153
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
0
|
return Shell::Carapace->shell(callback => $cb); |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
sub bootstrap { |
158
|
1
|
|
|
1
|
|
1210
|
my ($self, $fqdn, %options) = @_; |
159
|
1
|
|
|
|
|
3
|
my @opts = $self->handle_options(%options); |
160
|
1
|
|
|
|
|
3
|
my @cmd = (qw/knife bootstrap/, $fqdn, @opts); |
161
|
1
|
|
|
|
|
3
|
$self->run(@cmd); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub handle_options { |
165
|
18
|
|
|
18
|
0
|
4077
|
my ($self, %options) = @_; |
166
|
|
|
|
|
|
|
|
167
|
18
|
50
|
0
|
|
|
106
|
$options{format} //= $self->format if $self->format; |
168
|
|
|
|
|
|
|
|
169
|
18
|
50
|
33
|
|
|
68
|
$options{format} && $options{format} eq 'json' |
170
|
|
|
|
|
|
|
? $self->_json_flag(1) |
171
|
|
|
|
|
|
|
: $self->_json_flag(0); |
172
|
|
|
|
|
|
|
|
173
|
18
|
|
|
|
|
15
|
my @opts; |
174
|
18
|
|
|
|
|
50
|
for my $option (sort keys %options) { |
175
|
19
|
|
|
|
|
17
|
my $value = $options{$option}; |
176
|
19
|
|
|
|
|
25
|
$option =~ s/_/-/g; |
177
|
|
|
|
|
|
|
|
178
|
19
|
|
|
|
|
28
|
push @opts, "--$option"; |
179
|
19
|
100
|
|
|
|
41
|
push @opts, $value if $value ne "1"; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
18
|
|
|
|
|
59
|
return @opts; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub run { |
186
|
18
|
|
|
18
|
0
|
2204
|
my ($self, @cmds) = @_; |
187
|
18
|
50
|
|
|
|
82
|
return shell_quote @cmds if $self->noop; |
188
|
0
|
|
|
|
|
|
$self->shell->run(@cmds); |
189
|
0
|
|
|
|
|
|
my $out = $self->output; |
190
|
0
|
0
|
|
|
|
|
return JSON->new->utf8->decode($out) if $self->_json_flag; |
191
|
0
|
|
|
|
|
|
return $out; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
1; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head1 SEE ALSO |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=over 4 |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=item L<Capture::Tiny::Extended> |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item L<Capture::Tiny> |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=item L<IPC::System::Simple> |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=back |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head1 LICENSE |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
211
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 AUTHOR |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
Eric Johnson E<lt>eric.git@iijo.orgE<gt> |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=cut |