File Coverage

blib/lib/FusionInventory/Agent/Config.pm
Criterion Covered Total %
statement 85 130 65.3
branch 32 70 45.7
condition 5 12 41.6
subroutine 15 16 93.7
pod 1 3 33.3
total 138 231 59.7


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