1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00

Added validation of pgbackrest.conf to display warnings if options are not valid or are not in the correct section.

Contributed by Cynthia Shang.
This commit is contained in:
Cynthia Shang 2017-03-22 19:03:28 -04:00 committed by David Steele
parent 5d2e79242d
commit af7e4f4b4b
6 changed files with 211 additions and 2 deletions

View File

@ -154,6 +154,18 @@
<release-list>
<release date="XXXX-XX-XX" version="1.18dev" title="UNDER DEVELOPMENT">
<release-core-list>
<release-feature-list>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="shang.cynthia"/>
</release-item-contributor-list>
<p>Added validation of <setting>pgbackrest.conf</setting> to display warnings if options are not valid or are not in the correct section.</p>
</release-item>
</release-feature-list>
</release-core-list>
<release-test-list>
<release-refactor-list>
<release-item>

View File

@ -2691,8 +2691,104 @@ sub optionValidate
confess &log(ERROR, "option '${strOption}' not valid for command '${strCommand}'", ERROR_OPTION_COMMAND);
}
}
# If a config file was loaded then determine if all options are valid in the config file
if (defined($oConfig))
{
configFileValidate($oConfig);
}
}
####################################################################################################################################
# configFileValidate
#
# Determine if the configuration file contains any invalid options or placements
####################################################################################################################################
sub configFileValidate
{
my $oConfig = shift;
my $bFileValid = true;
foreach my $strSectionKey (keys(%$oConfig))
{
my ($strSection, $strCommand) = ($strSectionKey =~ m/([^:]*):*(\w*-*\w*)/);
foreach my $strOption (keys(%{$$oConfig{$strSectionKey}}))
{
my $strValue = $$oConfig{$strSectionKey}{$strOption};
# Is the option listed as an alternate name for another option? If so, replace it with the recognized option.
my $strOptionAltName = optionAltName($strOption);
if (defined($strOptionAltName))
{
$strOption = $strOptionAltName;
}
# Is the option a valid pgbackrest option?
if (!(exists($oOptionRule{$strOption}) || defined($strOptionAltName)))
{
&log(WARN, optionGet(OPTION_CONFIG) . " file contains invalid option '${strOption}'");
$bFileValid = false;
}
else
{
# Is the option valid for the command section in which it is located?
if (defined($strCommand) && $strCommand ne '')
{
if (!defined($oOptionRule{$strOption}{&OPTION_RULE_COMMAND}{$strCommand}))
{
&log(WARN, optionGet(OPTION_CONFIG) . " valid option '${strOption}' is not valid for command " .
"'$strCommand'");
$bFileValid = false;
}
}
# Is the valid option a stanza-only option and not located in a global section?
if ($oOptionRule{$strOption}{&OPTION_RULE_SECTION} eq CONFIG_SECTION_STANZA &&
$strSection eq CONFIG_SECTION_GLOBAL)
{
&log(WARN, optionGet(OPTION_CONFIG) . " valid option '${strOption}' is a stanza section option and is not " .
"valid in section ${strSection}\n" .
"HINT: global options can be specified in global or stanza sections but not visa-versa");
$bFileValid = false;
}
}
}
}
return $bFileValid;
}
push @EXPORT, qw(configFileValidate);
####################################################################################################################################
# optionAltName
#
# Returns the ALT_NAME for the option if one exists.
####################################################################################################################################
sub optionAltName
{
my $strOption = shift;
my $strOptionAltName = undef;
# Check if the options exists as an alternate name (e.g. db-host has altname db1-host)
foreach my $strKey (keys(%oOptionRule))
{
if (defined($oOptionRule{$strKey}{&OPTION_RULE_ALT_NAME}) &&
$oOptionRule{$strKey}{&OPTION_RULE_ALT_NAME} eq $strOption)
{
$strOptionAltName = $strKey;
}
}
return $strOptionAltName;
}
push @EXPORT, qw(optionAltName);
####################################################################################################################################
# optionCommandRule
#

View File

@ -35,7 +35,7 @@ use constant BACKREST_BIN => abs_path(
# Defines the current version of the BackRest executable. The version number is used to track features but does not affect what
# repositories or manifests can be read - that's the job of the format number.
#-----------------------------------------------------------------------------------------------------------------------------------
use constant BACKREST_VERSION => '1.17';
use constant BACKREST_VERSION => '1.18dev';
push @EXPORT, qw(BACKREST_VERSION);
# Format Format Number

View File

@ -11,7 +11,7 @@ use AutoLoader;
our @ISA = qw(Exporter);
# Library version (add .999 during development)
our $VERSION = '1.17';
our $VERSION = '1.18.999';
sub libCVersion {return $VERSION};

View File

@ -97,6 +97,11 @@ my $oTestDef =
&TESTDEF_TEST =>
[
{
&TESTDEF_TEST_NAME => 'unit',
&TESTDEF_TEST_TOTAL => 7,
&TESTDEF_TEST_INDIVIDUAL => false,
},
{
&TESTDEF_TEST_NAME => 'option',
&TESTDEF_TEST_TOTAL => 34,

View File

@ -0,0 +1,96 @@
####################################################################################################################################
# ConfigUnitTest.pm - Tests code paths
####################################################################################################################################
package pgBackRestTest::Config::ConfigUnitTest;
use parent 'pgBackRestTest::Config::ConfigEnvTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Config::Config;
use pgBackRestTest::Common::RunTest;
####################################################################################################################################
# run
####################################################################################################################################
sub run
{
my $self = shift;
my $oConfig = {};
optionSet(OPTION_CONFIG, $self->testPath() . '/pgbackrest.conf', true);
if ($self->begin('valid option ' . OPTION_DB_PORT . ' under invalid section'))
{
my $oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_BACKUP}{&OPTION_DB_PORT} = 1234;
$self->testResult(sub {configFileValidate($oConfig)}, false,
'valid option ' . OPTION_DB_PORT . ' under invalid section');
}
if ($self->begin('valid option ' . OPTION_DB_PORT . ' under invalid global section command'))
{
my $oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_ARCHIVE_PUSH}{&OPTION_DB_PORT} = 1234;
$self->testResult(sub {configFileValidate($oConfig)}, false,
'valid option ' . OPTION_DB_PORT . ' under invalid global section command');
}
if ($self->begin('valid option ' . OPTION_DB_PORT . ' under invalid stanza section command'))
{
my $oConfig = {};
$$oConfig{$self->stanza() . ':' . &CMD_ARCHIVE_PUSH}{&OPTION_DB_PORT} = 1234;
$self->testResult(sub {configFileValidate($oConfig)}, false,
'valid option ' . OPTION_DB_PORT . ' under invalid stanza section command');
}
if ($self->begin('invalid option'))
{
my $oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&BOGUS} = BOGUS;
$self->testResult(sub {configFileValidate($oConfig)}, false, 'invalid option ' . $$oConfig{&CONFIG_SECTION_GLOBAL}{&BOGUS});
}
if ($self->begin('valid alt name'))
{
my $oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{'thread-max'} = 3;
$self->testResult(sub {configFileValidate($oConfig)}, true, 'valid alt name found');
}
if ($self->begin('valid config file'))
{
my $oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_LEVEL_STDERR} = OPTION_DEFAULT_LOG_LEVEL_STDERR;
$$oConfig{$self->stanza()}{&OPTION_DB_PATH} = '/db';
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_ARCHIVE_PUSH}{&OPTION_PROCESS_MAX} = 2;
$self->testResult(sub {configFileValidate($oConfig)}, true, 'valid config file');
}
if ($self->begin('valid unusual section name'))
{
my $oConfig = {};
$$oConfig{&CONFIG_SECTION_GLOBAL}{&OPTION_LOG_LEVEL_STDERR} = OPTION_DEFAULT_LOG_LEVEL_STDERR;
$$oConfig{&CONFIG_SECTION_GLOBAL . ':' . &CMD_ARCHIVE_PUSH}{&OPTION_PROCESS_MAX} = 2;
$$oConfig{'unusual-section^name!:' . &CMD_CHECK}{&OPTION_DB_PATH} = '/db';
$self->testResult(sub {configFileValidate($oConfig)}, true, 'valid unusual section name');
}
}
1;