Commit | Line | Data |
afd7c030 |
1 | package System::Introspector::Probe::Packages::Apt; |
97b10529 |
2 | use Moo; |
5413434d |
3 | use File::Basename; |
97b10529 |
4 | |
9ee104cc |
5 | use System::Introspector::Util qw( |
6 | handle_from_command |
7 | transform_exceptions |
5413434d |
8 | output_from_file |
9 | files_from_dir |
9ee104cc |
10 | ); |
11 | |
025e0d3f |
12 | has apt_lists_dir => (is => 'ro', builder => 1); |
13 | has apt_update_after => (is => 'ro', default => sub { 86400 }); |
14 | has apt_update => (is => 'ro'); |
15 | |
5413434d |
16 | has apt_sources => (is => 'ro', builder => 1); |
17 | has apt_sources_dir => (is => 'ro', builder => 1); |
18 | |
19 | sub _build_apt_lists_dir { '/var/lib/apt/lists' } |
20 | sub _build_apt_sources { '/etc/apt/sources.list' } |
21 | sub _build_apt_sources_dir { '/etc/apt/sources.list.d' } |
025e0d3f |
22 | |
97b10529 |
23 | sub 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 |
44 | sub _last_apt_update { |
45 | my ($self) = @_; |
46 | return scalar( (stat($self->apt_lists_dir))[9] ); |
47 | } |
48 | |
49 | sub _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 |
59 | sub _open_dpkg_query_pipe { |
97b10529 |
60 | my ($self) = @_; |
9ee104cc |
61 | return handle_from_command 'dpkg-query --show'; |
3d4ae7f9 |
62 | } |
63 | |
025e0d3f |
64 | sub _open_apt_get_upgrade_simulation_pipe { |
65 | my ($self) = @_; |
66 | return handle_from_command 'apt-get -s upgrade'; |
67 | } |
68 | |
5413434d |
69 | sub _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 | |
82 | sub _fetch_source_list { |
83 | my ($self, $file) = @_; |
84 | return transform_exceptions { |
85 | return { |
1558d0ab |
86 | file_name => $file, |
87 | body => scalar(output_from_file $file), |
5413434d |
88 | }; |
89 | }; |
90 | } |
91 | |
025e0d3f |
92 | sub _gather_upgradable { |
93 | my ($self) = @_; |
94 | my $pipe = $self->_open_apt_get_upgrade_simulation_pipe; |
95 | my %action; |
96 | while (defined( my $line = <$pipe> )) { |
97 | chomp $line; |
98 | if ($line =~ m{^(inst|remv)\s+(\S+)\s+(.+)$}i) { |
99 | $action{ lc($1) }{ $2 } = $3; |
100 | } |
101 | } |
102 | return \%action; |
103 | } |
104 | |
3d4ae7f9 |
105 | sub _gather_installed { |
106 | my ($self) = @_; |
107 | my $pipe = $self->_open_dpkg_query_pipe; |
97b10529 |
108 | my %package; |
109 | while (defined( my $line = <$pipe> )) { |
110 | chomp $line; |
111 | my ($package, $version) = split m{\s+}, $line; |
112 | $package{ $package } = { |
113 | version => $version, |
114 | }; |
115 | } |
116 | return \%package; |
117 | } |
118 | |
119 | 1; |
535e84b6 |
120 | |
121 | __END__ |
122 | |
123 | =head1 NAME |
124 | |
125 | System::Introspector::Packages::Apt - Gather APT package status |
126 | |
127 | =head1 DESCRIPTION |
128 | |
129 | Uses C<dpkg-query> to list all installed packages. |
130 | |
131 | =head1 SEE ALSO |
132 | |
133 | =over |
134 | |
135 | =item L<System::Introspector> |
136 | |
137 | =back |
138 | |
139 | =cut |