App-Netdisco
view release on metacpan or search on metacpan
lib/App/Netdisco/Util/Configuration.pm view on Meta::CPAN
=item * C<{"value": "unchanged", "with": '{"snmptimeout": 5000000}'}>
=item * C<{"value": "unchanged", "with": 'snmptimeout=5000000'}>
=item * C<{"snmptimeout": 5000000}>
=item * C<'{"snmptimeout": 5000000}'>
=item * C<snmptimeout=5000000>
=item * C<{"value": "unchanged", "with": "FAILS"}> (unsupported)
=item * C<{"value": "unchanged", "with": ["FAILS"]}> (unsupported)
=back
=head1 parse_params_to_config
Takes a defined value, works out what has been provided. If there is
configuration to override it applies that. If there is a residual value
to return, it returns that, otherwise returns undef.
=cut
sub parse_params_to_config {
my $orig_value = shift;
return undef unless defined $orig_value;
# value via "schedule:" deployment.yml would already be a Perl struct
my $struct = (ref $orig_value ne q{})
? $orig_value
: try { from_json($orig_value) };
#Â reminder: from_json of a "" string returns the string, but unquoted throws error
#Â so struct could still be a string, or struct reference, or undef on parse error
my $came_from_json = (((defined $struct)
and (ref $orig_value eq q{}) and ($struct ne $orig_value)) ? true : false);
# case when value is a struct but not config (hashref), just leave it alone
if ((ref $struct ne q{}) and (ref $struct ne ref {})) {
return $orig_value;
}
#Â case when value is an empty string
if (($orig_value eq q{}) or (defined $struct and $struct eq q{})) {
return q{};
}
#Â finally, we have either a lengthy string or a struct
my $value = ((defined $struct)
? $struct
: $orig_value);
#Â if a lengthy string, it could be k=v config
if (ref $value eq q{}) {
if ($value =~ m/^(?:(?:[^=,]+)=(?:[^=,]+))(?:,(?:[^=,]+)=(?:[^=,]+))*$/) {
$value = parse_config_string_to_dict($value);
}
else {
#Â try to decode base64
my $decoded = try { from_json(decode_base64($value)) }; #Â might explode
if (defined $decoded and ref {} eq ref $decoded) {
return parse_params_to_config($decoded);
}
#Â some other use of subaction (file ref, log comment, etc)
else {
return $value;
}
}
}
#Â now value is a hashref, look for with/value setup
my $actual_value = undef;
if (exists $value->{value}) {
#Â if JSON was thawed from the value, refreeze it
my $inner = delete $value->{value};
$actual_value = (((ref $inner ne q{}) and $came_from_json)
? to_json($inner) : $inner);
}
$value = $value->{'with'} if exists $value->{'with'};
if (ref $value eq ref {}) {
merge_into_configuration($value);
}
else {
#Â we can recurse to decode a stringified JSON 'with'
parse_params_to_config($value);
}
return $actual_value;
}
sub parse_config_string_to_dict {
my $extra = shift;
return {} unless
$extra and (ref $extra eq q{}) and $extra =~ m/=/;
#Â must be key1=val1,key2=val2
my $dict = {};
my @kvs = split m/,/, $extra;
foreach my $kv (@kvs) {
next unless $kv;
die "bad syntax for subaction, missing =\n" unless $kv =~ m/=/;
my ($k, $v) = split m/=/, $kv, 2;
$dict->{$k} = $v;
}
return $dict;
}
sub merge_into_configuration {
my $newconfig = shift;
die "bad configuration format\n" unless ref $newconfig eq ref {};
my $SETTINGS = config();
$SETTINGS = Hash::Merge::Simple::merge( $SETTINGS, $newconfig );
set($_ => $SETTINGS->{$_}) for keys %$newconfig;
}
true;
( run in 1.216 second using v1.01-cache-2.11-cpan-302cb4679cc )