ensure, better scripting infrastructure
[scpubgit/Tak.git] / lib / Tak / Script.pm
index 6868fe4..52ec0f1 100644 (file)
@@ -3,6 +3,9 @@ package Tak::Script;
 use Getopt::Long qw(GetOptionsFromArray :config posix_defaults bundling);
 use Config::Settings;
 use IO::Handle;
+use Tak::Client::Router;
+use Tak::Client::RemoteRouter;
+use Tak::Router;
 use Moo;
 
 has options => (is => 'ro', required => 1);
@@ -20,9 +23,19 @@ has config => (is => 'lazy');
 
 sub _build_config {
   my ($self) = @_;
-  Config::Settings->new->parse_file(
-    $self->options->{config} || '.tak/default.conf'
-  );
+  my $file = $self->options->{config} || '.tak/default.conf';
+  if (-e $file) {
+    Config::Settings->new->parse_file($file);
+  } else {
+    {};
+  }
+}
+
+has local_client => (is => 'lazy');
+
+sub _build_local_client {
+  my ($self) = @_;
+  Tak::Client::Router->new(service => Tak::Router->new);
 }
 
 sub BUILD {
@@ -32,8 +45,12 @@ sub BUILD {
 sub setup_logger { }
 
 sub _parse_options {
-  my ($self, $string, \@argv) = @_;
+  my ($self, $string, $argv) = @_;
   my @spec = split ';', $string;
+  my %opt;
+  GetOptionsFromArray($argv, \%opt, @spec);
+  return \%opt;
+}
 
 sub run {
   my ($self) = @_;
@@ -61,16 +78,59 @@ sub local_help {
   $self->stderr->print("Help unimplemented\n");
 }
 
+sub _maybe_parse_options {
+  my ($self, $code, $argv) = @_;
+  if (my $proto = prototype($code)) {
+    $self->_parse_options($proto, $argv);
+  } else {
+    {};
+  }
+}
+
 sub _run_local {
   my ($self, $cmd, $code, @argv) = @_;
-  my $opt = do {
-    if (my $proto = prototype($code)) {
-      $self->_parse_options($proto, \@argv);
-    } else {
-      {};
-    }
-  };
+  my $opt = $self->_maybe_parse_options($code, \@argv);
   $self->$code($opt, @argv);
 }
 
+sub _run_each {
+  my ($self, $cmd, $code, @argv) = @_;
+  my @targets = $self->_host_list_for($cmd);
+  unless (@targets) {
+    $self->stderr->print("No targets for ${cmd}\n");
+    return;
+  }
+  my $opt = $self->_maybe_parse_options($code, \@argv);
+  if (my $prepare = $self->can("prepare_$cmd")) {
+    $self->$prepare($opt, @argv);
+  }
+  $self->local_client->ensure(connector => 'Tak::ConnectorService');
+  foreach my $target (@targets) {
+    my $remote = $self->_connection_to($target);
+    $self->$code($remote, $opt, @argv);
+  }
+}
+
+sub _host_list_for {
+  my ($self, $command) = @_;
+  my @host_spec = map split(' ', $_), @{$self->options->{host}};
+}
+
+sub _connection_to {
+  my ($self, $target) = @_;
+  my @path = $self->local_client->do(connector => create => $target);
+  my ($local, $remote) =
+    map $self->local_client->curry(connector => connection => @path => $_),
+      qw(local remote);
+  $local->ensure(module_sender => 'Tak::ModuleSender');
+  $remote->ensure(
+    module_loader => 'Tak::ModuleLoader',
+    expose => { module_sender => [ 'remote', 'module_sender' ] }
+  );
+  $remote->do(module_loader => 'enable');
+  Tak::Client::RemoteRouter->new(
+    %$remote, host => $target
+  );
+}
+
 1;