Commit | Line | Data |
e367483d |
1 | package Tak::Script; |
2 | |
3 | use Getopt::Long qw(GetOptionsFromArray :config posix_defaults bundling); |
4 | use Config::Settings; |
5 | use IO::Handle; |
e99bc141 |
6 | use Tak::Client::Router; |
7 | use Tak::Client::RemoteRouter; |
8 | use Tak::Router; |
e367483d |
9 | use Moo; |
10 | |
11 | has options => (is => 'ro', required => 1); |
12 | has env => (is => 'ro', required => 1); |
13 | |
14 | has stdin => (is => 'lazy'); |
15 | has stdout => (is => 'lazy'); |
16 | has stderr => (is => 'lazy'); |
17 | |
18 | sub _build_stdin { shift->env->{stdin} } |
19 | sub _build_stdout { shift->env->{stdout} } |
20 | sub _build_stderr { shift->env->{stderr} } |
21 | |
22 | has config => (is => 'lazy'); |
23 | |
24 | sub _build_config { |
25 | my ($self) = @_; |
e99bc141 |
26 | my $file = $self->options->{config} || '.tak/default.conf'; |
27 | if (-e $file) { |
28 | Config::Settings->new->parse_file($file); |
29 | } else { |
30 | {}; |
31 | } |
32 | } |
33 | |
34 | has local_client => (is => 'lazy'); |
35 | |
36 | sub _build_local_client { |
37 | my ($self) = @_; |
38 | Tak::Client::Router->new(service => Tak::Router->new); |
e367483d |
39 | } |
40 | |
41 | sub BUILD { |
42 | shift->setup_logger; |
43 | } |
44 | |
45 | sub setup_logger { } |
46 | |
47 | sub _parse_options { |
e99bc141 |
48 | my ($self, $string, $argv) = @_; |
e367483d |
49 | my @spec = split ';', $string; |
e99bc141 |
50 | my %opt; |
51 | GetOptionsFromArray($argv, \%opt, @spec); |
52 | return \%opt; |
53 | } |
e367483d |
54 | |
55 | sub run { |
56 | my ($self) = @_; |
57 | my @argv = @{$self->env->{argv}}; |
58 | unless (@argv && $argv[0]) { |
59 | return $self->local_help; |
60 | } |
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); |
66 | } |
67 | $self->stderr->print("No such command: ${cmd}\n"); |
68 | return $self->local_help; |
69 | } |
70 | |
71 | sub _load_file { |
72 | my ($self, $file) = @_; |
73 | $self->_load_file_in_my_script($file); |
74 | } |
75 | |
76 | sub local_help { |
77 | my ($self) = @_; |
78 | $self->stderr->print("Help unimplemented\n"); |
79 | } |
80 | |
e99bc141 |
81 | sub _maybe_parse_options { |
82 | my ($self, $code, $argv) = @_; |
83 | if (my $proto = prototype($code)) { |
84 | $self->_parse_options($proto, $argv); |
85 | } else { |
86 | {}; |
87 | } |
88 | } |
89 | |
e367483d |
90 | sub _run_local { |
91 | my ($self, $cmd, $code, @argv) = @_; |
e99bc141 |
92 | my $opt = $self->_maybe_parse_options($code, \@argv); |
e367483d |
93 | $self->$code($opt, @argv); |
94 | } |
95 | |
e99bc141 |
96 | sub _run_each { |
97 | my ($self, $cmd, $code, @argv) = @_; |
98 | my @targets = $self->_host_list_for($cmd); |
99 | unless (@targets) { |
100 | $self->stderr->print("No targets for ${cmd}\n"); |
101 | return; |
102 | } |
103 | my $opt = $self->_maybe_parse_options($code, \@argv); |
104 | if (my $prepare = $self->can("prepare_$cmd")) { |
105 | $self->$prepare($opt, @argv); |
106 | } |
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); |
111 | } |
112 | } |
113 | |
114 | sub _host_list_for { |
115 | my ($self, $command) = @_; |
116 | my @host_spec = map split(' ', $_), @{$self->options->{host}}; |
117 | } |
118 | |
119 | sub _connection_to { |
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 => $_), |
124 | qw(local remote); |
125 | $local->ensure(module_sender => 'Tak::ModuleSender'); |
126 | $remote->ensure( |
127 | module_loader => 'Tak::ModuleLoader', |
128 | expose => { module_sender => [ 'remote', 'module_sender' ] } |
129 | ); |
130 | $remote->do(module_loader => 'enable'); |
131 | Tak::Client::RemoteRouter->new( |
132 | %$remote, host => $target |
133 | ); |
134 | } |
135 | |
e367483d |
136 | 1; |