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   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