configuration, state generation, centralised gatherer
Robert 'phaylon' Sedlacek [Thu, 24 May 2012 02:41:49 +0000 (02:41 +0000)]
lib/System/Introspector/Config.pm [new file with mode: 0644]
lib/System/Introspector/Gatherer.pm [new file with mode: 0644]
lib/System/Introspector/State.pm [new file with mode: 0644]

diff --git a/lib/System/Introspector/Config.pm b/lib/System/Introspector/Config.pm
new file mode 100644 (file)
index 0000000..8b51c31
--- /dev/null
@@ -0,0 +1,22 @@
+package System::Introspector::Config;
+use Moo;
+use Config::General;
+
+has config => (is => 'lazy');
+
+has config_file => (is => 'ro', required => 1);
+
+sub _build_config {
+    my ($self) = @_;
+    my $reader = Config::General->new($self->config_file);
+    my %config = $reader->getall;
+    return \%config;
+}
+
+sub groups { keys %{ $_[0]->config->{group} || {} } }
+
+sub has_group { exists $_[0]->config->{group}{ $_[1] } }
+
+sub config_for_group { $_[0]->config->{group}{ $_[1] } }
+
+1;
diff --git a/lib/System/Introspector/Gatherer.pm b/lib/System/Introspector/Gatherer.pm
new file mode 100644 (file)
index 0000000..17ac433
--- /dev/null
@@ -0,0 +1,12 @@
+package System::Introspector::Gatherer;
+use Moo;
+use Module::Runtime qw( use_module );
+
+sub gather {
+    my ($self, $class, $args) = @_;
+    return use_module("System::Introspector::$class")
+        ->new($args)
+        ->gather;
+}
+
+1;
diff --git a/lib/System/Introspector/State.pm b/lib/System/Introspector/State.pm
new file mode 100644 (file)
index 0000000..fae866e
--- /dev/null
@@ -0,0 +1,90 @@
+package System::Introspector::State;
+use Moo;
+use Data::YAML::Writer;
+use Object::Remote;
+use Object::Remote::Future;
+use System::Introspector::Gatherer;
+
+has config => (is => 'ro', required => 1);
+
+has introspectors => (is => 'lazy');
+
+has host => (is => 'ro');
+
+has storage => (is => 'ro', required => 1);
+
+has node_path => (is => 'lazy');
+
+sub fetch {
+    my ($self) = @_;
+    my $gatherer = $self->_create_gatherer;
+    my $spec     = $self->introspectors;
+    my %report;
+    for my $class_base (sort keys %$spec) {
+        $report{ $class_base } = $gatherer
+            ->gather($class_base, $spec->{ $class_base });
+    }
+    return \%report;
+}
+
+sub fetch_and_store {
+    my ($self) = @_;
+    return $self->_store($self->fetch);
+}
+
+sub _build_node_path {
+    my ($self) = @_;
+    return defined($self->host)
+        ? sprintf('host/%s', $self->host)
+        : 'local';
+}
+
+sub _build_introspectors {
+    my ($self) = @_;
+    return $self->config->{introspect};
+}
+
+sub _store {
+    my ($self, $data) = @_;
+    my $yaml    = Data::YAML::Writer->new;
+    my $storage = $self->storage;
+    my @files;
+    for my $class (sort keys %$data) {
+        my $file = sprintf '%s.yml', join '/',
+            node => $self->node_path,
+            map lc, map {
+                s{([a-z0-9])([A-Z])}{${1}_${2}}g;
+                $_;
+            } split m{::}, $class;
+        my $fh = $storage->open('>:utf8', $file, mkpath => 1);
+        print "Writing $file\n";
+        $yaml->write($data->{$class}, $fh);
+        push @files, $storage->file($file);
+    }
+    $self->_cleanup(\@files);
+    return 1;
+}
+
+sub _cleanup {
+    my ($self, $known_files) = @_;
+    my %known = map { ($_ => 1) } @$known_files;
+    my $data_dir = $self->storage->file(node => $self->node_path);
+    my @files = $self->storage->find_files('yml', node =>  $self->node_path);
+    for my $file (@files) {
+        next if $known{$file};
+        print "Removing $file\n";
+        unlink($file)
+            or die "Unable to remove '$file': $!\n";
+    }
+    return 1;
+}
+
+sub _create_gatherer {
+    my ($self) = @_;
+    if (defined( my $host = $self->host )) {
+        return System::Introspector::Gatherer->new::on($host);
+    }
+    return System::Introspector::Gatherer->new;
+}
+
+1;