File Coverage

blib/lib/Chef/Knife/Cmd.pm
Criterion Covered Total %
statement 53 71 74.6
branch 5 18 27.7
condition 1 6 16.6
subroutine 18 22 81.8
pod 0 2 0.0
total 77 119 64.7


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