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