switched to JSON::Diffable as file format
[scpubgit/System-Introspector.git] / lib / System / Introspector / State.pm
CommitLineData
60e1cc39 1package System::Introspector::State;
2use Moo;
3use Data::YAML::Writer;
4use Object::Remote;
5use Object::Remote::Future;
6use System::Introspector::Gatherer;
7
0a11cf83 8use JSON::Diffable qw( encode_json );
9
60e1cc39 10has config => (is => 'ro', required => 1);
11
12has introspectors => (is => 'lazy');
13
14has host => (is => 'ro');
15
16has storage => (is => 'ro', required => 1);
17
18has node_path => (is => 'lazy');
19
20sub fetch {
21 my ($self) = @_;
22 my $gatherer = $self->_create_gatherer;
23 my $spec = $self->introspectors;
24 my %report;
25 for my $class_base (sort keys %$spec) {
26 $report{ $class_base } = $gatherer
27 ->gather($class_base, $spec->{ $class_base });
28 }
29 return \%report;
30}
31
32sub fetch_and_store {
33 my ($self) = @_;
34 return $self->_store($self->fetch);
35}
36
37sub _build_node_path {
38 my ($self) = @_;
39 return defined($self->host)
40 ? sprintf('host/%s', $self->host)
41 : 'local';
42}
43
44sub _build_introspectors {
45 my ($self) = @_;
46 return $self->config->{introspect};
47}
48
49sub _store {
50 my ($self, $data) = @_;
60e1cc39 51 my $storage = $self->storage;
52 my @files;
53 for my $class (sort keys %$data) {
0a11cf83 54 my $file = sprintf '%s.json', join '/',
60e1cc39 55 node => $self->node_path,
56 map lc, map {
57 s{([a-z0-9])([A-Z])}{${1}_${2}}g;
58 $_;
59 } split m{::}, $class;
60 my $fh = $storage->open('>:utf8', $file, mkpath => 1);
61 print "Writing $file\n";
0a11cf83 62 print $fh encode_json($data->{$class});
60e1cc39 63 push @files, $storage->file($file);
64 }
65 $self->_cleanup(\@files);
66 return 1;
67}
68
69sub _cleanup {
70 my ($self, $known_files) = @_;
71 my %known = map { ($_ => 1) } @$known_files;
72 my $data_dir = $self->storage->file(node => $self->node_path);
73 my @files = $self->storage->find_files('yml', node => $self->node_path);
74 for my $file (@files) {
75 next if $known{$file};
76 print "Removing $file\n";
77 unlink($file)
78 or die "Unable to remove '$file': $!\n";
79 }
80 return 1;
81}
82
83sub _create_gatherer {
84 my ($self) = @_;
85 if (defined( my $host = $self->host )) {
86 return System::Introspector::Gatherer->new::on($host);
87 }
88 return System::Introspector::Gatherer->new;
89}
90
911;
cd5c3d43 92
93=head1 NAME
94
95System::Introspector::State - Gather system state
96
97=head1 SYNOPSIS
98
99 my $state = System::Introspector::State->new(
100 host => 'foo.example.com',
101 storage => $storage_obj,
102 config => {
103 introspect => [qw( ProbeName )],
104 },
105 );
106
107 my $data = $state->fetch;
108 $state->fetch_and_store;
109
110=head1 DESCRIPTION
111
112Gathers system introspection data based on configuration and stores
113it with a L<File::Tree::Snapshot> object.
114
115=head1 ATTRIBUTES
116
117=head2 config
118
119A hash reference containing a C<introspect> key with an array reference
120value containing a list of probe names without the
121C<System::Introspector::Probe::> prefix. This attribute is required.
122
123=head2 host
124
125An optional hostname. If no hostname is supplied, the local configuration
126data will be fetched.
127
128=head2 storage
129
130A L<File::Tree::Snapshot> object.
131
132=head1 METHODS
133
134=head2 fetch
135
136 my $data = $state->fetch;
137
138Fetches all probe data.
139
140=head2 fetch_and_store
141
142 $state->fetch_and_store;
143
144Fetches all probe data and stores it in the L</storage>.
145
146=cut