From: Robert 'phaylon' Sedlacek Date: Fri, 29 Jun 2012 21:16:41 +0000 (+0000) Subject: moved host iteration into state so host/group storage generation is easy X-Git-Tag: v0.001_001~31 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b079a95d78c18dc74fb650897235ab6b013dcc8c;p=scpubgit%2FSystem-Introspector.git moved host iteration into state so host/group storage generation is easy --- diff --git a/bin/system-introspector b/bin/system-introspector index 1f09084..5e23b39 100755 --- a/bin/system-introspector +++ b/bin/system-introspector @@ -10,9 +10,6 @@ use System::Introspector::Config; GetOptions( 'c|config=s' => \my $config_file, 's|storage=s' => \my $storage_dir, - 'H|host=s' => \my $hostname, - 'U|user=s' => \my $username, - 'allow-empty' => \my $allow_empty, 'a|all' => \my $update_all, 'g|group=s' => \my @update_groups, 'h|help' => sub { pod2usage(0) }, @@ -21,9 +18,6 @@ GetOptions( die "Requires --all or --group option\n" unless $update_all or @update_groups; -die "The --user option also requires a --host to be set\n" - if defined($username) and not defined($hostname); - my $config = System::Introspector::Config->new( config_file => (defined($config_file) ? $config_file @@ -35,34 +29,13 @@ $config->has_group($_) or die "Unknown group '$_'\n" @update_groups = $config->groups if $update_all; - -my $sudo_user = $config->sudo_user; - -for my $group (@update_groups) { - my $group_dir = "$storage_dir/$group"; - print "Group $group at $group_dir\n"; - my $storage = File::Tree::Snapshot->new( - storage_path => $group_dir, - allow_empty => $allow_empty, - ); - $storage->create - unless $storage->exists; - my $state = System::Introspector::State->new( - defined($hostname) ? (host => $hostname) : (), - defined($username) ? (user => $username) : (), - defined($sudo_user) ? (sudo_user => $sudo_user) : (), - storage => $storage, - config => $config->config_for_group($group), - ); - eval { $state->fetch_and_store }; - if (my $error = $@) { - warn "Error: $error\n"; - $storage->reset; - } - else { - $storage->commit; - } -} + +my $state = System::Introspector::State->new( + config => $config, + root => $storage_dir, +); + +$state->gather(@update_groups); __END__ diff --git a/lib/System/Introspector/Config.pm b/lib/System/Introspector/Config.pm index 4ebb33f..98697ab 100644 --- a/lib/System/Introspector/Config.pm +++ b/lib/System/Introspector/Config.pm @@ -19,6 +19,14 @@ sub groups { keys %{ $_[0]->config->{group} || {} } } sub has_group { exists $_[0]->config->{group}{ $_[1] } } +sub hosts { + my ($self) = @_; + my $host_spec = $self->config->{host}; + return ref($host_spec) ? @$host_spec : $host_spec; +} + +sub user { $_[0]->config->{user} } + my $_get_inherited = sub { my $data = shift; $data ||= {}; diff --git a/lib/System/Introspector/State.pm b/lib/System/Introspector/State.pm index 3ea7ad5..3f20876 100644 --- a/lib/System/Introspector/State.pm +++ b/lib/System/Introspector/State.pm @@ -1,36 +1,57 @@ package System::Introspector::State; use Moo; +use File::Tree::Snapshot; use System::Introspector::Gatherer; use JSON::Diffable qw( encode_json ); has config => (is => 'ro', required => 1); -has introspectors => (is => 'lazy'); +has root => (is => 'ro', required => 1); -has host => (is => 'ro'); +sub user { $_[0]->config->user } -has user => (is => 'ro'); +sub sudo_user { $_[0]->config->sudo_user } -has sudo_user => (is => 'ro'); +sub gather { + my ($self, @groups) = @_; + for my $host ($self->config->hosts) { + $self->fetch_and_store($host, @groups); + } + return 1; +} -has storage => (is => 'ro', required => 1); +sub introspectors { + my ($self, $group) = @_; + return $self->config->config_for_group($group)->{introspect}; +} -has node_path => (is => 'lazy'); +sub fetch_and_store { + my ($self, $host, @groups) = @_; + my $data = $self->fetch($host, @groups); + return $self->_store($host, $data); +} sub fetch { - my ($self) = @_; - my $spec = $self->introspectors; + my ($self, $host, @groups) = @_; + return +{ map { + ($_, $self->fetch_group($host, $_)); + } @groups }; +} + +sub fetch_group { + my ($self, $host, $group) = @_; + my $spec = $self->introspectors($group); my (@sudo, @nosudo); push(@{ $spec->{$_}{sudo} ? \@sudo : \@nosudo}, [$_, $spec->{$_}]) for sort keys %$spec; my %report; if (@nosudo) { - my $gatherer = $self->_create_gatherer; + my $gatherer = $self->_create_gatherer(host => $host); %report = %{ $self->_fetch_with_gatherer($gatherer, @nosudo) || {} }; } if (@sudo) { - my $gatherer = $self->_create_gatherer(sudo => 1); + my $gatherer = $self->_create_gatherer(sudo => 1, host => $host); %report = (%report, %{ $self->_fetch_with_gatherer($gatherer, @sudo) || {} }); } return \%report; @@ -49,49 +70,44 @@ sub _fetch_with_gatherer { return \%report; } -sub fetch_and_store { - my ($self) = @_; - my $data = $self->fetch; - return $self->_store($data); -} - -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 storage { + my ($self, @path) = @_; + my $storage = File::Tree::Snapshot->new( + allow_empty => 0, + storage_path => join('/', $self->root, @path), + ); + $storage->create + unless $storage->exists; + return $storage; } sub _store { - my ($self, $data) = @_; - my $storage = $self->storage; - my @files; - for my $class (sort keys %$data) { - my $file = sprintf '%s.json', 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"; - print $fh encode_json($data->{$class}); - push @files, $storage->file($file); + my ($self, $host, $data) = @_; + for my $group (sort keys %$data) { + my $storage = $self->storage($host, $group); + my $gathered = $data->{$group}; + my @files; + for my $class (sort keys %$gathered) { + my $file = sprintf '%s.json', join '/', + 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"; + print $fh encode_json($gathered->{$class}); + push @files, $storage->file($file); + } + $self->_cleanup($storage, [@files]); + $storage->commit; } - $self->_cleanup(\@files); return 1; } sub _cleanup { - my ($self, $known_files) = @_; + my ($self, $storage, $known_files) = @_; my %known = map { ($_ => 1) } @$known_files; - my $data_dir = $self->storage->file(node => $self->node_path); - my @files = $self->storage->find_files('json', node => $self->node_path); + my @files = $storage->find_files('json'); for my $file (@files) { next if $known{$file}; print "Removing $file\n"; @@ -105,7 +121,7 @@ sub _create_gatherer { my ($self, %arg) = @_; return System::Introspector::Gatherer->new_from_spec( user => $self->user, - host => $self->host, + host => $arg{host}, sudo_user => $arg{sudo} && $self->sudo_user, ); }