File Coverage

blib/lib/Armadito/Agent/Config.pm
Criterion Covered Total %
statement 18 127 14.1
branch 0 84 0.0
condition 0 12 0.0
subroutine 6 12 50.0
pod n/a
total 24 235 10.2


line stmt bran cond sub pod time code
1             package Armadito::Agent::Config;
2              
3 1     1   4 use strict;
  1         1  
  1         21  
4 1     1   2 use warnings;
  1         1  
  1         19  
5              
6 1     1   2 use English qw(-no_match_vars);
  1         1  
  1         3  
7 1     1   259 use File::Spec;
  1         1  
  1         8  
8 1     1   630 use Getopt::Long;
  1         9182  
  1         4  
9 1     1   97 use UNIVERSAL::require;
  1         1  
  1         5  
10              
11             require FusionInventory::Agent::Tools;
12              
13             my $default_armadito = {
14             'ca-cert-dir' => undef,
15             'ca-cert-file' => undef,
16             'color' => undef,
17             'conf-reload-interval' => 0,
18             'debug' => undef,
19             'force' => undef,
20             'html' => undef,
21             'local' => undef,
22             'logger' => 'Stderr',
23             'logfile' => undef,
24             'logfacility' => 'LOG_USER',
25             'logfile-maxsize' => undef,
26             'no-ssl-check' => undef,
27             'proxy' => undef,
28             'server' => undef,
29             'stdout' => undef,
30             };
31              
32             my $default_fusion = {
33             'additional-content' => undef,
34             'backend-collect-timeout' => 180,
35             'ca-cert-dir' => undef,
36             'ca-cert-file' => undef,
37             'color' => undef,
38             'conf-reload-interval' => 0,
39             'debug' => undef,
40             'delaytime' => 3600,
41             'force' => undef,
42             'html' => undef,
43             'lazy' => undef,
44             'local' => undef,
45             'logger' => 'Stderr',
46             'logfile' => undef,
47             'logfacility' => 'LOG_USER',
48             'logfile-maxsize' => undef,
49             'no-category' => [],
50             'no-httpd' => undef,
51             'no-ssl-check' => undef,
52             'no-task' => [],
53             'no-p2p' => undef,
54             'password' => undef,
55             'proxy' => undef,
56             'httpd-ip' => undef,
57             'httpd-port' => 62354,
58             'httpd-trust' => [],
59             'scan-homedirs' => undef,
60             'scan-profiles' => undef,
61             'server' => undef,
62             'tag' => undef,
63             'tasks' => undef,
64             'timeout' => 180,
65             'user' => undef,
66             # deprecated options
67             'stdout' => undef,
68             };
69              
70             my $deprecated = {
71             'stdout' => {
72             message => 'use --local - option instead',
73             new => { 'local' => '-' }
74             },
75             };
76              
77             my $confReloadIntervalMinValue = 60;
78              
79             sub new {
80 0     0     my ($class, %params) = @_;
81              
82 0           my $self = {
83             fusion => undef,
84             armadito => undef
85             };
86 0           bless $self, $class;
87              
88             # Load fusioninventory configuration
89 0           $self->_loadDefaults("FusionInventory-Agent");
90 0           $self->_loadFromBackend("", $params{options}->{'config-fusion'}, $params{fusion_confdir}, "FusionInventory-Agent");
91              
92             # TODO test on Win32
93             # $self->_loadFromBackend("", "", $params{fusion_confdir}, "FusionInventory-Agent");
94              
95             # Load armadito agent configuration
96 0           $self->_loadDefaults("Armadito-Agent");
97 0           $self->_loadFromBackend($params{options}->{'conf-file'}, $params{options}->{'config'}, $params{armadito_confdir}, "Armadito-Agent");
98              
99 0           _checkContent($self->{fusion});
100 0           _checkContent($self->{armadito});
101              
102 0           return $self;
103             }
104              
105             sub _loadDefaults {
106 0     0     my ($self, $agent_type) = @_;
107              
108 0 0         if($agent_type eq "FusionInventory-Agent"){
    0          
109 0           foreach my $key (keys %$default_fusion) {
110 0           $self->{fusion}->{$key} = $default_fusion->{$key};
111             }
112             }
113             elsif($agent_type eq "Armadito-Agent"){
114 0           foreach my $key (keys %$default_armadito) {
115 0           $self->{armadito}->{$key} = $default_armadito->{$key};
116             }
117             }
118             }
119              
120             sub _loadFromBackend {
121 0     0     my ($self, $confFile, $config, $confdir, $agent_type) = @_;
122              
123 0 0         my $backend =
    0          
    0          
124             $confFile ? 'file' :
125             $config ? $config :
126             $OSNAME eq 'MSWin32' ? 'registry' :
127             'file';
128              
129             SWITCH: {
130 0 0         if ($backend eq 'registry') {
  0            
131 0 0         die "Unavailable configuration backend\n"
132             unless $OSNAME eq 'MSWin32';
133 0           $self->_loadFromRegistry($agent_type);
134 0           last SWITCH;
135             }
136              
137 0 0         if ($backend eq 'file') {
138 0           $self->_loadFromFile({
139             file => $confFile,
140             directory => $confdir,
141             }, $agent_type);
142 0           last SWITCH;
143             }
144              
145 0 0         if ($backend eq 'none') {
146 0           last SWITCH;
147             }
148              
149 0           die "Unknown configuration backend '$backend'\n";
150             }
151             }
152              
153             sub _loadFromRegistry { # TOBETESTED
154 0     0     my ($self, $agent_type) = @_;
155              
156 0           my $Registry;
157 0           Win32::TieRegistry->require();
158 0           Win32::TieRegistry->import(
159             Delimiter => '/',
160             ArrayValues => 0,
161             TiedRef => \$Registry
162             );
163              
164 0 0         my $machKey = $Registry->Open('LMachine', {
165             Access => Win32::TieRegistry::KEY_READ()
166             }) or die "Can't open HKEY_LOCAL_MACHINE key: $EXTENDED_OS_ERROR";
167              
168 0           my $settings = $machKey->{"SOFTWARE/".$agent_type};
169              
170 0           foreach my $rawKey (keys %$settings) {
171 0 0         next unless $rawKey =~ /^\/(\S+)/;
172 0           my $key = lc($1);
173 0           my $val = $settings->{$rawKey};
174             # Remove the quotes
175 0           $val =~ s/\s+$//;
176 0           $val =~ s/^'(.*)'$/$1/;
177 0           $val =~ s/^"(.*)"$/$1/;
178              
179 0 0         if($agent_type eq "FusionInventory-Agent"){
    0          
180 0 0         if (exists $default_fusion->{$key}) {
181 0           $self->{fusion}->{$key} = $val;
182             }
183             }
184             elsif($agent_type eq "Armadito-Agent"){
185 0 0         if (exists $default_armadito->{$key}) {
186 0           $self->{armadito}->{$key} = $val;
187             }
188             } else {
189 0           warn "unknown configuration directive $key";
190             }
191             }
192             }
193              
194             sub _loadFromFile {
195 0     0     my ($self, $params, $agent_type) = @_;
196             my $file = $params->{file} ?
197 0 0         $params->{file} : $params->{directory} . '/agent.cfg';
198              
199 0 0         if ($file) {
200 0 0         die "non-existing file $file" unless -f $file;
201 0 0         die "non-readable file $file" unless -r $file;
202             } else {
203 0           die "no configuration file";
204             }
205              
206 0           my $handle;
207 0 0         if (!open $handle, '<', $file) {
208 0           warn "Config: Failed to open $file: $ERRNO";
209 0           return;
210             }
211              
212 0           while (my $line = <$handle>) {
213 0           $line =~ s/#.+//;
214 0 0         if ($line =~ /([\w-]+)\s*=\s*(.+)/) {
215 0           my $key = $1;
216 0           my $val = $2;
217              
218             # Remove the quotes
219 0           $val =~ s/\s+$//;
220 0           $val =~ s/^'(.*)'$/$1/;
221 0           $val =~ s/^"(.*)"$/$1/;
222              
223 0 0         if($agent_type eq "FusionInventory-Agent"){
    0          
224 0 0         if (exists $default_fusion->{$key}) {
225 0           $self->{fusion}->{$key} = $val;
226             }
227             }
228             elsif($agent_type eq "Armadito-Agent"){
229 0 0         if (exists $default_armadito->{$key}) {
230 0           $self->{armadito}->{$key} = $val;
231             }
232             } else {
233 0           warn "unknown configuration directive $key";
234             }
235             }
236             }
237 0           close $handle;
238             }
239              
240             sub _checkContent {
241 0     0     my ($self) = @_;
242              
243             # check for deprecated options
244 0           foreach my $old (keys %$deprecated) {
245 0 0         next unless defined $self->{$old};
246              
247 0 0 0       next if $old =~ /^no-/ and !$self->{$old};
248              
249 0           my $handler = $deprecated->{$old};
250              
251             # notify user of deprecation
252 0           warn "the '$old' option is deprecated, $handler->{message}\n";
253              
254             # transfer the value to the new option, if possible
255 0 0         if ($handler->{new}) {
256 0 0         if (ref $handler->{new} eq 'HASH') {
    0          
257             # old boolean option replaced by new non-boolean options
258 0           foreach my $key (keys %{$handler->{new}}) {
  0            
259 0           my $value = $handler->{new}->{$key};
260 0 0         if ($value =~ /^\+(\S+)/) {
261             # multiple values: add it to exiting one
262             $self->{$key} = $self->{$key} ?
263 0 0         $self->{$key} . ',' . $1 : $1;
264             } else {
265             # unique value: replace exiting value
266 0           $self->{$key} = $value;
267             }
268             }
269             } elsif (ref $handler->{new} eq 'ARRAY') {
270             # old boolean option replaced by new boolean options
271 0           foreach my $new (@{$handler->{new}}) {
  0            
272 0           $self->{$new} = $self->{$old};
273             }
274             } else {
275             # old non-boolean option replaced by new option
276 0           $self->{$handler->{new}} = $self->{$old};
277             }
278             }
279              
280             # avoid cluttering configuration
281 0           delete $self->{$old};
282             }
283              
284             # a logfile options implies a file logger backend
285 0 0         if ($self->{logfile}) {
286 0           $self->{logger} .= ',File';
287             }
288              
289             # ca-cert-file and ca-cert-dir are antagonists
290 0 0 0       if ($self->{'ca-cert-file'} && $self->{'ca-cert-dir'}) {
291 0           die "use either 'ca-cert-file' or 'ca-cert-dir' option, not both\n";
292             }
293              
294             # logger backend without a logfile isn't enoguh
295 0 0 0       if ($self->{'logger'} =~ /file/i && ! $self->{'logfile'}) {
296 0           die "usage of 'file' logger backend makes 'logfile' option mandatory\n";
297             }
298              
299             # multi-values options, the default separator is a ','
300 0           foreach my $option (qw/
301             logger
302             local
303             server
304             httpd-trust
305             no-task
306             no-category
307             tasks
308             /) {
309              
310             # Check if defined AND SCALAR
311             # to avoid split a ARRAY ref or HASH ref...
312 0 0 0       if ($self->{$option} && ref($self->{$option}) eq '') {
313 0           $self->{$option} = [split(/,/, $self->{$option})];
314             } else {
315 0           $self->{$option} = [];
316             }
317             }
318              
319             # files location
320             $self->{'ca-cert-file'} =
321 0 0         File::Spec->rel2abs($self->{'ca-cert-file'}) if $self->{'ca-cert-file'};
322             $self->{'ca-cert-dir'} =
323 0 0         File::Spec->rel2abs($self->{'ca-cert-dir'}) if $self->{'ca-cert-dir'};
324             $self->{'logfile'} =
325 0 0         File::Spec->rel2abs($self->{'logfile'}) if $self->{'logfile'};
326              
327             # conf-reload-interval option
328             # If value is less than the required minimum, we force it to that
329             # minimum because it's useless to reload the config so often and,
330             # furthermore, it can cause a loss of performance
331 0 0         if ($self->{'conf-reload-interval'} != 0) {
332 0 0         if ($self->{'conf-reload-interval'} < 0) {
    0          
333 0           $self->{'conf-reload-interval'} = 0;
334             } elsif ($self->{'conf-reload-interval'} < $confReloadIntervalMinValue) {
335 0           $self->{'conf-reload-interval'} = $confReloadIntervalMinValue;
336             }
337             }
338             }
339              
340             1;
341             __END__