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