3 use Getopt::Long qw(GetOptionsFromArray :config posix_defaults bundling);
6 use Tak::Client::Router;
7 use Tak::Client::RemoteRouter;
11 has options => (is => 'ro', required => 1);
12 has env => (is => 'ro', required => 1);
14 has stdin => (is => 'lazy');
15 has stdout => (is => 'lazy');
16 has stderr => (is => 'lazy');
18 sub _build_stdin { shift->env->{stdin} }
19 sub _build_stdout { shift->env->{stdout} }
20 sub _build_stderr { shift->env->{stderr} }
22 has config => (is => 'lazy');
26 my $file = $self->options->{config} || '.tak/default.conf';
28 Config::Settings->new->parse_file($file);
34 has local_client => (is => 'lazy');
36 sub _build_local_client {
38 Tak::Client::Router->new(service => Tak::Router->new);
48 my ($self, $string, $argv) = @_;
49 my @spec = split ';', $string;
51 GetOptionsFromArray($argv, \%opt, @spec);
57 my @argv = @{$self->env->{argv}};
58 unless (@argv && $argv[0]) {
59 return $self->local_help;
61 my $cmd = shift(@argv);
62 if (my $code = $self->can("local_$cmd")) {
63 return $self->_run($cmd, $code, @argv);
64 } elsif ($code = $self->can("each_$cmd")) {
65 return $self->_run_each($cmd, $code, @argv);
67 $self->stderr->print("No such command: ${cmd}\n");
68 return $self->local_help;
72 my ($self, $file) = @_;
73 $self->_load_file_in_my_script($file);
78 $self->stderr->print("Help unimplemented\n");
81 sub _maybe_parse_options {
82 my ($self, $code, $argv) = @_;
83 if (my $proto = prototype($code)) {
84 $self->_parse_options($proto, $argv);
91 my ($self, $cmd, $code, @argv) = @_;
92 my $opt = $self->_maybe_parse_options($code, \@argv);
93 $self->$code($opt, @argv);
97 my ($self, $cmd, $code, @argv) = @_;
98 my @targets = $self->_host_list_for($cmd);
100 $self->stderr->print("No targets for ${cmd}\n");
103 my $opt = $self->_maybe_parse_options($code, \@argv);
104 if (my $prepare = $self->can("prepare_$cmd")) {
105 $self->$prepare($opt, @argv);
107 $self->local_client->ensure(connector => 'Tak::ConnectorService');
108 foreach my $target (@targets) {
109 my $remote = $self->_connection_to($target);
110 $self->$code($remote, $opt, @argv);
115 my ($self, $command) = @_;
116 my @host_spec = map split(' ', $_), @{$self->options->{host}};
120 my ($self, $target) = @_;
121 my @path = $self->local_client->do(connector => create => $target);
122 my ($local, $remote) =
123 map $self->local_client->curry(connector => connection => @path => $_),
125 $local->ensure(module_sender => 'Tak::ModuleSender');
127 module_loader => 'Tak::ModuleLoader',
128 expose => { module_sender => [ 'remote', 'module_sender' ] }
130 $remote->do(module_loader => 'enable');
131 Tak::Client::RemoteRouter->new(
132 %$remote, host => $target