exec and repl as standard actions
[scpubgit/Tak.git] / lib / Tak / Role / ScriptActions.pm
1 package Tak::Role::ScriptActions;
2
3 use Moo::Role;
4 no warnings::illegalproto;
5
6 sub every_exec (stream|s) {
7   my ($self, $remotes, $options, @command) = @_;
8
9   my @requests;
10
11   $_->ensure(command_service => 'Tak::CommandService') for @$remotes;
12
13   foreach my $remote (@$remotes) {
14     if ($options->{stream}) {
15       my $stdout = $self->stdout;
16       my $host = $remote->host;
17       push @requests, $remote->start(
18         {
19           on_result => sub { $self->print_exec_result($remote, @_) },
20           on_progress => sub {
21             $stdout->print($host.' '.$_[0].': '.$_[1]);
22             $stdout->print("\n") unless $_[1] =~ /\n\Z/;
23           }
24         },
25         command_service => stream_exec => \@command
26       );
27     } else {
28       push @requests, $remote->start(
29         { on_result => sub { $self->print_exec_result($remote, @_) } },
30         command_service => exec => \@command
31       );
32     }
33   }
34   Tak->await_all(@requests);
35 }
36
37 sub print_exec_result {
38   my ($self, $remote, $result) = @_;
39
40   my $res = eval { $result->get }
41     or do {
42       $self->stderr->print("Host ${\$remote->host}: Error: $@\n");
43       return;
44     };
45
46   my $code = $res->{exit_code};
47   $self->stdout->print(
48     "Host ${\$remote->host}: ".($code ? "NOT OK ${code}" : "OK")."\n"
49   );
50   if ($res->{stderr}) {
51     $self->stdout->print("Stderr:\n${\$res->{stderr}}\n");
52   }
53   if ($res->{stdout}) {
54     $self->stdout->print("Stdout:\n${\$res->{stdout}}\n");
55   }
56 }
57
58 sub each_repl {
59   my ($self, $remote) = @_;
60   require Tak::REPL;
61   $remote->ensure(eval_service => 'Tak::EvalService');
62   Tak::REPL->new(client => $remote->curry('eval_service'))->run;
63 }
64
65 1;