ensure, better scripting infrastructure
[scpubgit/Tak.git] / lib / Tak / Script.pm
CommitLineData
e367483d 1package Tak::Script;
2
3use Getopt::Long qw(GetOptionsFromArray :config posix_defaults bundling);
4use Config::Settings;
5use IO::Handle;
e99bc141 6use Tak::Client::Router;
7use Tak::Client::RemoteRouter;
8use Tak::Router;
e367483d 9use Moo;
10
11has options => (is => 'ro', required => 1);
12has env => (is => 'ro', required => 1);
13
14has stdin => (is => 'lazy');
15has stdout => (is => 'lazy');
16has stderr => (is => 'lazy');
17
18sub _build_stdin { shift->env->{stdin} }
19sub _build_stdout { shift->env->{stdout} }
20sub _build_stderr { shift->env->{stderr} }
21
22has config => (is => 'lazy');
23
24sub _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
34has local_client => (is => 'lazy');
35
36sub _build_local_client {
37 my ($self) = @_;
38 Tak::Client::Router->new(service => Tak::Router->new);
e367483d 39}
40
41sub BUILD {
42 shift->setup_logger;
43}
44
45sub setup_logger { }
46
47sub _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
55sub 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
71sub _load_file {
72 my ($self, $file) = @_;
73 $self->_load_file_in_my_script($file);
74}
75
76sub local_help {
77 my ($self) = @_;
78 $self->stderr->print("Help unimplemented\n");
79}
80
e99bc141 81sub _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 90sub _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 96sub _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
114sub _host_list_for {
115 my ($self, $command) = @_;
116 my @host_spec = map split(' ', $_), @{$self->options->{host}};
117}
118
119sub _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 1361;