mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
527 lines
20 KiB
Perl
527 lines
20 KiB
Perl
####################################################################################################################################
|
|
# Configuration Rule Interface
|
|
####################################################################################################################################
|
|
package pgBackRest::Config::Rule;
|
|
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
|
|
use Exporter qw(import);
|
|
our @EXPORT = qw();
|
|
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::Config::Data;
|
|
|
|
####################################################################################################################################
|
|
# Copy indexed rules locally
|
|
####################################################################################################################################
|
|
my $rhOptionRuleIndex = cfgdefRuleIndex();
|
|
my $iOptionTotal = scalar(keys(%{$rhOptionRuleIndex}));
|
|
|
|
####################################################################################################################################
|
|
# Create maps to convert option ids to names and vice versa
|
|
####################################################################################################################################
|
|
my $rhOptionNameId;
|
|
my $rhOptionIdName;
|
|
my $rhOptionNameAlt;
|
|
|
|
{
|
|
my $iIndex = 0;
|
|
|
|
foreach my $strOption (sort(keys(%{$rhOptionRuleIndex})))
|
|
{
|
|
$rhOptionNameId->{$strOption} = $iIndex;
|
|
$rhOptionNameAlt->{$strOption} = $strOption;
|
|
$rhOptionIdName->{$iIndex} = $strOption;
|
|
|
|
if (defined(cfgRuleOptionNameAlt($strOption)))
|
|
{
|
|
$rhOptionNameId->{cfgRuleOptionNameAlt($strOption)} = $iIndex;
|
|
$rhOptionNameAlt->{cfgRuleOptionNameAlt($strOption)} = $strOption;
|
|
}
|
|
|
|
$iIndex++;
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# cfgOptionRule - get a rule for the option from a command or default
|
|
####################################################################################################################################
|
|
sub cfgOptionRule
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = shift;
|
|
my $strRule = shift;
|
|
|
|
return
|
|
defined($rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_COMMAND}{$strCommand}{$strRule}) ?
|
|
$rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_COMMAND}{$strCommand}{$strRule} :
|
|
$rhOptionRuleIndex->{$strOption}{$strRule};
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# Functions that are noops in the Perl code since commands/options are always treated as strings
|
|
####################################################################################################################################
|
|
sub cfgCommandId {return shift()}
|
|
sub cfgCommandName {return shift()}
|
|
|
|
sub cfgOptionId
|
|
{
|
|
my $strOptionName = shift;
|
|
|
|
if (!defined($rhOptionNameId->{$strOptionName}))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return $rhOptionNameAlt->{$strOptionName};
|
|
}
|
|
|
|
sub cfgOptionName
|
|
{
|
|
my $strOptionId = shift;
|
|
|
|
if (defined($rhOptionIdName->{$strOptionId}))
|
|
{
|
|
return $rhOptionIdName->{$strOptionId};
|
|
}
|
|
|
|
return $rhOptionNameAlt->{$strOptionId};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgCommandId cfgCommandName cfgOptionId cfgOptionName);
|
|
|
|
####################################################################################################################################
|
|
# cfgOptionTotal - total number of options
|
|
####################################################################################################################################
|
|
sub cfgOptionTotal
|
|
{
|
|
return $iOptionTotal;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgOptionTotal);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowList - does the option have a specific list of allowed values?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowList
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $bError = shift;
|
|
|
|
my $rhAllowList = cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_LIST);
|
|
|
|
if (!defined($rhAllowList) && defined($bError) && $bError)
|
|
{
|
|
confess &log(ASSERT, "allow list not set for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
# The allow list must have values
|
|
if (defined($rhAllowList) && @{$rhAllowList} == 0)
|
|
{
|
|
confess &log(ASSERT, "allow list must have values for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
return defined($rhAllowList) ? true : false;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowList);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowListValue - get an allow list value
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowListValue
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $iValueIdx = shift;
|
|
|
|
# Index shouldn't be greater than the total number of values
|
|
if ($iValueIdx >= cfgRuleOptionAllowListValueTotal($strCommand, $strOption, $iValueIdx))
|
|
{
|
|
confess &log(ASSERT, "invalid allow list value index ${iValueIdx} for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
# Return value
|
|
return cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_LIST)->[$iValueIdx];
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowListValue);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowListValueTotal - how many values are allowed for the option?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowListValueTotal
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
# Make sure the allow list exists
|
|
cfgRuleOptionAllowList($strCommand, $strOption, true);
|
|
|
|
# Return total elements in the list
|
|
return scalar(@{cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_LIST)});
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowListValueTotal);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowListValueValid - is the value valid for this option?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowListValueValid
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $strValue = shift;
|
|
|
|
# Make sure the allow list exists
|
|
cfgRuleOptionAllowList($strCommand, $strOption, true);
|
|
|
|
# Check if the value is valid
|
|
foreach my $strValueMatch (@{cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_LIST)})
|
|
{
|
|
if ($strValue eq $strValueMatch)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowListValueValid);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowRange - does the option have min/max values?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowRange
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $bError = shift;
|
|
|
|
my $rhAllowRange = cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_RANGE);
|
|
|
|
if (!defined($rhAllowRange) && defined($bError) && $bError)
|
|
{
|
|
confess &log(ASSERT, "allow range not set for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
# The allow range must have two values
|
|
if (defined($rhAllowRange) && @{$rhAllowRange} != 2)
|
|
{
|
|
confess &log(ASSERT, "allow range must have two values for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
return defined($rhAllowRange) ? true : false;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowRange);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowRangeMax - get max value in allowed range
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowRangeMax
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
# Make sure the allow range exists
|
|
cfgRuleOptionAllowRange($strCommand, $strOption);
|
|
|
|
# Return value
|
|
return cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_RANGE)->[1];
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowRangeMax);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionAllowRangeMin - get min value in allowed range
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionAllowRangeMin
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
# Make sure the allow range exists
|
|
cfgRuleOptionAllowRange($strCommand, $strOption);
|
|
|
|
# Return value
|
|
return cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_ALLOW_RANGE)->[0];
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionAllowRangeMin);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionDefault - option default, if any
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionDefault
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_DEFAULT);
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionDefault);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionDepend - does the option depend on another option being set or having a certain value?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionDepend
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $bError = shift;
|
|
|
|
my $rhDepend = cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_DEPEND);
|
|
|
|
if (!defined($rhDepend) && defined($bError) && $bError)
|
|
{
|
|
confess &log(ASSERT, "depend rule not set for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
return defined($rhDepend) ? true : false;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionDepend);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionDependOption - name of the option that this option depends on
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionDependOption
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
# Make sure the depend rule exists
|
|
cfgRuleOptionDepend($strCommand, $strOption, true);
|
|
|
|
# Error if the depend option does not exist
|
|
my $rhDepend = cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_DEPEND);
|
|
|
|
if (!defined($rhDepend->{&CFGBLDDEF_RULE_DEPEND_OPTION}))
|
|
{
|
|
confess &log(ASSERT, "depend rule option not set for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
return $rhDepend->{&CFGBLDDEF_RULE_DEPEND_OPTION};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionDependOption);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionDependValue - get a depend option value
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionDependValue
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $iValueIdx = shift;
|
|
|
|
# Index shouldn't be greater than the total number of values
|
|
if ($iValueIdx >= cfgRuleOptionDependValueTotal($strCommand, $strOption, $iValueIdx))
|
|
{
|
|
confess &log(ASSERT, "invalid depend value index ${iValueIdx} for ${strCommand}, ${strOption}");
|
|
}
|
|
|
|
# Return value
|
|
return cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_DEPEND)->{&CFGBLDDEF_RULE_DEPEND_LIST}->[$iValueIdx];
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionDependValue);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionDependValueTotal - how many values are allowed for the depend option?
|
|
#
|
|
# 0 indicates that the value of the depend option doesn't matter, only that is is set.
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionDependValueTotal
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
# Make sure the depend rule exists
|
|
cfgRuleOptionDepend($strCommand, $strOption, true);
|
|
|
|
# It's OK for the list not to be defined
|
|
my $rhDepend = cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_DEPEND);
|
|
|
|
if (!defined($rhDepend->{&CFGBLDDEF_RULE_DEPEND_LIST}))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
# Return total elements in the list
|
|
return scalar(@{$rhDepend->{&CFGBLDDEF_RULE_DEPEND_LIST}});
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionDependValueTotal);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionDependValueValid - is the depend valid valid?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionDependValueValid
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
my $strValue = shift;
|
|
|
|
# Make sure the depend rule exists
|
|
cfgRuleOptionDepend($strCommand, $strOption, true);
|
|
|
|
# Check if the value is valid
|
|
foreach my $strValueMatch (@{cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_DEPEND)->{&CFGBLDDEF_RULE_DEPEND_LIST}})
|
|
{
|
|
if ($strValue eq $strValueMatch)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionDependValueValid);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionHint - option hint, if any
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionHint
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_HINT);
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionHint);
|
|
|
|
####################################################################################################################################
|
|
# cfgOptionIndexTotal - max index for options that are indexed (e.g., db)
|
|
####################################################################################################################################
|
|
sub cfgOptionIndexTotal
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_INDEX};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgOptionIndexTotal);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionNameAlt - alternative or deprecated option name
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionNameAlt
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_ALT_NAME};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionNameAlt);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionNegate - is the boolean option negatable?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionNegate
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_NEGATE};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionNegate);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionPrefix - fixed prefix for indexed options
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionPrefix
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_PREFIX};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionPrefix);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionRequired - is the option required?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionRequired
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
my $rxRule = cfgOptionRule($strCommand, $strOption, CFGBLDDEF_RULE_REQUIRED);
|
|
return defined($rxRule) ? $rxRule : true;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionRequired);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionSection - section to contain optio (global or stanza), all others are command-line only
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionSection
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_SECTION};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionSection);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionSecure - can the option be passed on the command-line?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionSecure
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_SECURE};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionSecure);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionType - data type of the option (e.g. boolean, string)
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionType
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_TYPE};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionType);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionValid - is the option valid for the command?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionValid
|
|
{
|
|
my $strCommand = shift;
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return defined($rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_COMMAND}{$strCommand}) ? true : false;
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionValid);
|
|
|
|
####################################################################################################################################
|
|
# cfgRuleOptionValueHash - is the option a true hash or just a list of keys?
|
|
####################################################################################################################################
|
|
sub cfgRuleOptionValueHash
|
|
{
|
|
my $strOption = cfgOptionName(shift);
|
|
|
|
return $rhOptionRuleIndex->{$strOption}{&CFGBLDDEF_RULE_HASH_VALUE};
|
|
}
|
|
|
|
push @EXPORT, qw(cfgRuleOptionValueHash);
|
|
|
|
1;
|