File Coverage

blib/lib/Tak/Script.pm
Criterion Covered Total %
statement 27 110 24.5
branch 0 18 0.0
condition 0 9 0.0
subroutine 9 29 31.0
pod 0 4 0.0
total 36 170 21.1


line stmt bran cond sub pod time code
1             package Tak::Script;
2              
3 1     1   1704 use Getopt::Long qw(GetOptionsFromArray :config posix_defaults bundling);
  1         11128  
  1         4  
4 1     1   1031 use Config::Settings;
  1         95114  
  1         39  
5 1     1   12 use IO::Handle;
  1         3  
  1         42  
6 1     1   7 use Tak::Client::Router;
  1         1  
  1         36  
7 1     1   5 use Tak::Client::RemoteRouter;
  1         3  
  1         25  
8 1     1   5 use Tak::Router;
  1         2  
  1         25  
9 1     1   5 use Log::Contextual qw(:log);
  1         3  
  1         10  
10 1     1   2378 use Log::Contextual::SimpleLogger;
  1         534  
  1         28  
11 1     1   6 use Moo;
  1         2  
  1         8  
12              
13             with 'Tak::Role::ScriptActions';
14              
15             has options => (is => 'ro', required => 1);
16             has env => (is => 'ro', required => 1);
17              
18             has log_level => (is => 'rw');
19              
20             has stdin => (is => 'lazy');
21             has stdout => (is => 'lazy');
22             has stderr => (is => 'lazy');
23              
24 0     0     sub _build_stdin { shift->env->{stdin} }
25 0     0     sub _build_stdout { shift->env->{stdout} }
26 0     0     sub _build_stderr { shift->env->{stderr} }
27              
28             has config => (is => 'lazy');
29              
30             sub _build_config {
31 0     0     my ($self) = @_;
32 0   0       my $file = $self->options->{config} || '.tak/default.conf';
33 0 0         if (-e $file) {
34 0           Config::Settings->new->parse_file($file);
35             } else {
36 0           {};
37             }
38             }
39              
40             has local_client => (is => 'lazy');
41              
42             sub _build_local_client {
43 0     0     my ($self) = @_;
44 0           Tak::Client::Router->new(service => Tak::Router->new);
45             }
46              
47             sub BUILD {
48 0     0 0   shift->setup_logger;
49             }
50              
51             sub setup_logger {
52 0     0 0   my ($self) = @_;
53 0           my @level_names = qw(fatal error warn info debug trace);
54 0           my $options = $self->options;
55 0   0       my $level = 2 + ($options->{verbose}||0) - ($options->{quiet}||0);
      0        
56 0           my $upto = $level_names[$level];
57 0           $self->log_level($upto);
58             Log::Contextual::set_logger(
59             Log::Contextual::SimpleLogger->new({
60             levels_upto => $upto,
61 0     0     coderef => sub { print STDERR ' ', @_ },
62             })
63 0           );
64             }
65              
66             sub _parse_options {
67 0     0     my ($self, $string, $argv) = @_;
68 0           my @spec = split ';', $string;
69 0           my %opt;
70 0           GetOptionsFromArray($argv, \%opt, @spec);
71 0           return \%opt;
72             }
73              
74             sub run {
75 0     0 0   my ($self) = @_;
76 0           my @argv = @{$self->env->{argv}};
  0            
77 0 0 0       unless (@argv && $argv[0]) {
78 0           return $self->local_help;
79             }
80 0           my $cmd = shift(@argv);
81 0           $cmd =~ s/-/_/g;
82 0 0         if (my $code = $self->can("local_$cmd")) {
    0          
    0          
83 0           return $self->_run($cmd, $code, @argv);
84             } elsif ($code = $self->can("each_$cmd")) {
85 0           return $self->_run_each($cmd, $code, @argv);
86             } elsif ($code = $self->can("every_$cmd")) {
87 0           return $self->_run_every($cmd, $code, @argv);
88             }
89 0           $self->stderr->print("No such command: ${cmd}\n");
90 0           return $self->local_help;
91             }
92              
93             sub _load_file {
94 0     0     my ($self, $file) = @_;
95 0           $self->_load_file_in_my_script($file);
96             }
97              
98             sub local_help {
99 0     0 0   my ($self) = @_;
100 0           $self->stderr->print("Help unimplemented\n");
101             }
102              
103             sub _maybe_parse_options {
104 0     0     my ($self, $code, $argv) = @_;
105 0 0         if (my $proto = prototype($code)) {
106 0           $self->_parse_options($proto, $argv);
107             } else {
108 0           {};
109             }
110             }
111              
112             sub _run_local {
113 0     0     my ($self, $cmd, $code, @argv) = @_;
114 0           my $opt = $self->_maybe_parse_options($code, \@argv);
115 0           $self->$code($opt, @argv);
116             }
117              
118             sub _run_each {
119 0     0     my ($self, $cmd, $code, @argv) = @_;
120 0           my @targets = $self->_host_list_for($cmd);
121 0 0         unless (@targets) {
122 0           $self->stderr->print("No targets for ${cmd}\n");
123 0           return;
124             }
125 0           my $opt = $self->_maybe_parse_options($code, \@argv);
126 0           $self->local_client->ensure(connector => 'Tak::ConnectorService');
127 0           foreach my $target (@targets) {
128 0           my $remote = $self->_connection_to($target);
129 0           $self->$code($remote, $opt, @argv);
130             }
131             }
132              
133             sub _run_every {
134 0     0     my ($self, $cmd, $code, @argv) = @_;
135 0           my @targets = $self->_host_list_for($cmd);
136 0 0         unless (@targets) {
137 0           $self->stderr->print("No targets for ${cmd}\n");
138 0           return;
139             }
140 0           my $opt = $self->_maybe_parse_options($code, \@argv);
141 0           $self->local_client->ensure(connector => 'Tak::ConnectorService');
142 0           my @remotes = map $self->_connection_to($_), @targets;
143 0           $self->$code(\@remotes, $opt, @argv);
144             }
145              
146             sub _host_list_for {
147 0     0     my ($self, $command) = @_;
148 0           my @host_spec = map split(' ', $_), @{$self->options->{host}};
  0            
149 0 0         unshift(@host_spec, '-') if $self->options->{local};
150 0           return @host_spec;
151             }
152              
153             sub _connection_to {
154 0     0     my ($self, $target) = @_;
155 0     0     log_debug { "Connecting to ${target}" };
  0            
156 0           my @path = $self->local_client->do(
157             connector => create => $target, log_level => $self->log_level
158             );
159 0           my ($local, $remote) =
160             map $self->local_client->curry(connector => connection => @path => $_),
161             qw(local remote);
162 0           $local->ensure(module_sender => 'Tak::ModuleSender');
163 0           $remote->ensure(
164             module_loader => 'Tak::ModuleLoader',
165             expose => { module_sender => [ 'remote', 'module_sender' ] }
166             );
167 0           $remote->do(module_loader => 'enable');
168 0     0     log_debug { "Setup connection to ${target}" };
  0            
169 0           Tak::Client::RemoteRouter->new(
170             %$remote, host => $target
171             );
172             }
173              
174             1;