From: Robert 'phaylon' Sedlacek Date: Thu, 31 May 2012 00:16:02 +0000 (+0000) Subject: reworked gatherer to be more flexible, added sudo support X-Git-Tag: v0.001_001~54 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a5e1e1c610a2ab8f8e7c0a4301020aa0506b5793;p=scpubgit%2FSystem-Introspector.git reworked gatherer to be more flexible, added sudo support --- diff --git a/bin/system-introspector b/bin/system-introspector index 0c16443..1f09084 100644 --- a/bin/system-introspector +++ b/bin/system-introspector @@ -11,6 +11,7 @@ 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, @@ -20,6 +21,9 @@ 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 @@ -31,6 +35,8 @@ $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"; @@ -42,12 +48,15 @@ for my $group (@update_groups) { $storage->create unless $storage->exists; my $state = System::Introspector::State->new( - defined($hostname) ? (host => $hostname) : (), + 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 { diff --git a/lib/System/Introspector/Config.pm b/lib/System/Introspector/Config.pm index 8b51c31..4ebb33f 100644 --- a/lib/System/Introspector/Config.pm +++ b/lib/System/Introspector/Config.pm @@ -13,10 +13,38 @@ sub _build_config { return \%config; } +sub sudo_user { $_[0]->config->{sudo_user} } + sub groups { keys %{ $_[0]->config->{group} || {} } } sub has_group { exists $_[0]->config->{group}{ $_[1] } } -sub config_for_group { $_[0]->config->{group}{ $_[1] } } +my $_get_inherited = sub { + my $data = shift; + $data ||= {}; + return + map { ($_ => $data->{$_}) } + grep { exists $data->{$_} } + qw( sudo ); +}; + +sub config_for_group { + my ($self, $name) = @_; + my %common; + my $config = $self->config; + %common = (%common, $config->$_get_inherited); + my $group = $config->{group}{ $name }; + %common = (%common, $group->$_get_inherited); + return { + introspect => { + map { + ($_ => { + %common, + %{ $group->{introspect}{ $_ } || {} }, + }); + } keys %{ $group->{introspect} || {} }, + }, + }; +} 1; diff --git a/lib/System/Introspector/Gatherer.pm b/lib/System/Introspector/Gatherer.pm index 17ac433..43ffff4 100644 --- a/lib/System/Introspector/Gatherer.pm +++ b/lib/System/Introspector/Gatherer.pm @@ -1,12 +1,51 @@ package System::Introspector::Gatherer; use Moo; +use Object::Remote; +use Object::Remote::Future; +use System::Introspector::Gatherer::Bridge; use Module::Runtime qw( use_module ); sub gather { my ($self, $class, $args) = @_; - return use_module("System::Introspector::$class") + return use_module("System::Introspector::Probe::$class") ->new($args) ->gather; } +sub _new_direct { + my ($class, $remote) = @_; + return $class->new::on($remote); +} + +sub _new_bridged { + my ($class, $bridge, $remote) = @_; + return System::Introspector::Gatherer::Bridge->new::on($bridge, + remote_spec => $remote, + remote_class => $class, + ); +} + +sub new_from_spec { + my ($class, %arg) = @_; + my ($user, $host, $sudo_user) = @arg{qw( user host sudo_user )}; + my $sudo = defined($sudo_user) ? sprintf('%s@', $sudo_user) : undef; + if (defined $host) { + my $remote = join '@', grep defined, $user, $host; + if (defined $sudo_user) { + return $class->_new_bridged($remote, $sudo); + } + else { + return $class->_new_direct($remote); + } + } + else { + if (defined $sudo_user) { + return $class->_new_direct($sudo); + } + else { + return $class->new; + } + } +} + 1; diff --git a/lib/System/Introspector/Gatherer/Bridge.pm b/lib/System/Introspector/Gatherer/Bridge.pm new file mode 100644 index 0000000..dd6cd19 --- /dev/null +++ b/lib/System/Introspector/Gatherer/Bridge.pm @@ -0,0 +1,17 @@ +package System::Introspector::Gatherer::Bridge; +use Object::Remote; +use Object::Remote::Future; +use Moo; + +has remote_spec => (is => 'ro', required => 1); +has remote_class => (is => 'ro', required => 1); +has remote => (is => 'lazy'); + +sub _build_remote { + my ($self) = @_; + return $self->remote_class->new::on($self->remote_spec); +} + +sub gather { (shift)->remote->gather(@_) } + +1; diff --git a/lib/System/Introspector/State.pm b/lib/System/Introspector/State.pm index 3506a1c..2d423b1 100644 --- a/lib/System/Introspector/State.pm +++ b/lib/System/Introspector/State.pm @@ -1,8 +1,5 @@ package System::Introspector::State; use Moo; -use Data::YAML::Writer; -use Object::Remote; -use Object::Remote::Future; use System::Introspector::Gatherer; use JSON::Diffable qw( encode_json ); @@ -13,25 +10,49 @@ has introspectors => (is => 'lazy'); has host => (is => 'ro'); +has user => (is => 'ro'); + +has sudo_user => (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 $spec = $self->introspectors; + my (@sudo, @nosudo); + push(@{ $spec->{$_}{sudo} ? \@sudo : \@nosudo}, [$_, $spec->{$_}]) + for sort keys %$spec; my %report; - for my $class_base (sort keys %$spec) { + if (@nosudo) { + my $gatherer = $self->_create_gatherer; + %report = %{ $self->_fetch_with_gatherer($gatherer, @nosudo) || {} }; + } + if (@sudo) { + my $gatherer = $self->_create_gatherer(sudo => 1); + %report = (%report, %{ $self->_fetch_with_gatherer($gatherer, @sudo) || {} }); + } + return \%report; +} + +sub _fetch_with_gatherer { + my ($self, $gatherer, @spec) = @_; + my %report; + for my $class_spec (@spec) { + my ($class_base, $args) = @$class_spec; + print "Gathering $class_base data\n"; $report{ $class_base } = $gatherer - ->gather($class_base, $spec->{ $class_base }); + ->gather($class_base, $args); } + print "All gathered\n"; return \%report; } sub fetch_and_store { my ($self) = @_; - return $self->_store($self->fetch); + my $data = $self->fetch; + return $self->_store($data); } sub _build_node_path { @@ -81,11 +102,12 @@ sub _cleanup { } sub _create_gatherer { - my ($self) = @_; - if (defined( my $host = $self->host )) { - return System::Introspector::Gatherer->new::on($host); - } - return System::Introspector::Gatherer->new; + my ($self, %arg) = @_; + return System::Introspector::Gatherer->new_from_spec( + user => $self->user, + host => $self->host, + sudo_user => $arg{sudo} && $self->sudo_user, + ); } 1;