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