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