apt source loading and tests for Packages::Apt probe
[scpubgit/System-Introspector.git] / lib / System / Introspector / Probe / Packages / Apt.pm
CommitLineData
afd7c030 1package System::Introspector::Probe::Packages::Apt;
97b10529 2use Moo;
5413434d 3use File::Basename;
97b10529 4
9ee104cc 5use System::Introspector::Util qw(
6 handle_from_command
7 transform_exceptions
5413434d 8 output_from_file
9 files_from_dir
9ee104cc 10);
11
025e0d3f 12has apt_lists_dir => (is => 'ro', builder => 1);
13has apt_update_after => (is => 'ro', default => sub { 86400 });
14has apt_update => (is => 'ro');
15
5413434d 16has apt_sources => (is => 'ro', builder => 1);
17has apt_sources_dir => (is => 'ro', builder => 1);
18
19sub _build_apt_lists_dir { '/var/lib/apt/lists' }
20sub _build_apt_sources { '/etc/apt/sources.list' }
21sub _build_apt_sources_dir { '/etc/apt/sources.list.d' }
025e0d3f 22
97b10529 23sub gather {
24 my ($self) = @_;
25 return {
025e0d3f 26 update => {
27 last => $self->_last_apt_update,
28 run => transform_exceptions {
29 return { result => $self->_check_apt_state };
30 },
31 },
9ee104cc 32 installed => transform_exceptions {
33 return { packages => $self->_gather_installed };
34 },
025e0d3f 35 upgradable => transform_exceptions {
36 return { actions => $self->_gather_upgradable };
37 },
5413434d 38 sources => transform_exceptions {
39 return { config => $self->_gather_sources };
40 },
97b10529 41 };
42}
43
025e0d3f 44sub _last_apt_update {
45 my ($self) = @_;
46 return scalar( (stat($self->apt_lists_dir))[9] );
47}
48
49sub _check_apt_state {
50 my ($self) = @_;
51 return 'disabled' unless $self->apt_update;
52 my $threshold = $self->apt_update_after;
53 my $last_change = $self->_last_apt_update;
54 return 'no'if ($last_change + $threshold) > time;
55 handle_from_command 'apt-get update';
56 return 'yes';
57}
58
3d4ae7f9 59sub _open_dpkg_query_pipe {
97b10529 60 my ($self) = @_;
9ee104cc 61 return handle_from_command 'dpkg-query --show';
3d4ae7f9 62}
63
025e0d3f 64sub _open_apt_get_upgrade_simulation_pipe {
65 my ($self) = @_;
66 return handle_from_command 'apt-get -s upgrade';
67}
68
5413434d 69sub _gather_sources {
70 my ($self) = @_;
71 my $sources_dir = $self->apt_sources_dir;
72 return {
73 'sources_list' => $self->_fetch_source_list($self->apt_sources),
74 'sources_list_dir' => (-e $sources_dir) ? transform_exceptions {
75 return +{ files => +{ map {
76 ($_, $self->_fetch_source_list("$sources_dir/$_"));
77 } files_from_dir $sources_dir } };
78 } : {},
79 };
80}
81
82sub _fetch_source_list {
83 my ($self, $file) = @_;
84 return transform_exceptions {
85 return {
86 file => {
87 file_name => $file,
88 body => scalar(output_from_file $file),
89 },
90 };
91 };
92}
93
025e0d3f 94sub _gather_upgradable {
95 my ($self) = @_;
96 my $pipe = $self->_open_apt_get_upgrade_simulation_pipe;
97 my %action;
98 while (defined( my $line = <$pipe> )) {
99 chomp $line;
100 if ($line =~ m{^(inst|remv)\s+(\S+)\s+(.+)$}i) {
101 $action{ lc($1) }{ $2 } = $3;
102 }
103 }
104 return \%action;
105}
106
3d4ae7f9 107sub _gather_installed {
108 my ($self) = @_;
109 my $pipe = $self->_open_dpkg_query_pipe;
97b10529 110 my %package;
111 while (defined( my $line = <$pipe> )) {
112 chomp $line;
113 my ($package, $version) = split m{\s+}, $line;
114 $package{ $package } = {
115 version => $version,
116 };
117 }
118 return \%package;
119}
120
1211;
535e84b6 122
123__END__
124
125=head1 NAME
126
127System::Introspector::Packages::Apt - Gather APT package status
128
129=head1 DESCRIPTION
130
131Uses C<dpkg-query> to list all installed packages.
132
133=head1 SEE ALSO
134
135=over
136
137=item L<System::Introspector>
138
139=back
140
141=cut