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

Add support for additional pgBackRest configuration files.

Configuration files are loaded from the directory specified by the --config-include-path option.

Add --config-path option for overriding the default base path of the --config and --config-include-path option.

Contributed by Cynthia Shang.
This commit is contained in:
Cynthia Shang 2018-04-19 11:09:39 -04:00 committed by David Steele
parent 79b7552940
commit 27aa5f756e
19 changed files with 1631 additions and 219 deletions

View File

@ -116,6 +116,10 @@ use constant CFGCMD_VERSION => 'version'
#-----------------------------------------------------------------------------------------------------------------------------------
use constant CFGOPT_CONFIG => 'config';
push @EXPORT, qw(CFGOPT_CONFIG);
use constant CFGOPT_CONFIG_PATH => 'config-path';
push @EXPORT, qw(CFGOPT_CONFIG_PATH);
use constant CFGOPT_CONFIG_INCLUDE_PATH => 'config-include-path';
push @EXPORT, qw(CFGOPT_CONFIG_INCLUDE_PATH);
use constant CFGOPT_DELTA => 'delta';
push @EXPORT, qw(CFGOPT_DELTA);
use constant CFGOPT_FORCE => 'force';
@ -243,6 +247,10 @@ use constant CFGOPT_REPO_HOST_CMD => CFGOPT_RE
push @EXPORT, qw(CFGOPT_REPO_HOST_CMD);
use constant CFGOPT_REPO_HOST_CONFIG => CFGOPT_REPO_HOST . '-config';
push @EXPORT, qw(CFGOPT_REPO_HOST_CONFIG);
use constant CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH => CFGOPT_REPO_HOST_CONFIG . '-include-path';
push @EXPORT, qw(CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH);
use constant CFGOPT_REPO_HOST_CONFIG_PATH => CFGOPT_REPO_HOST_CONFIG . '-path';
push @EXPORT, qw(CFGOPT_REPO_HOST_CONFIG_PATH);
use constant CFGOPT_REPO_HOST_PORT => CFGOPT_REPO_HOST . '-port';
push @EXPORT, qw(CFGOPT_REPO_HOST_PORT);
use constant CFGOPT_REPO_HOST_USER => CFGOPT_REPO_HOST . '-user';
@ -326,6 +334,10 @@ use constant CFGOPT_PG_HOST_CMD => CFGOPT_PG
push @EXPORT, qw(CFGOPT_PG_HOST_CMD);
use constant CFGOPT_PG_HOST_CONFIG => CFGOPT_PG_HOST . '-config';
push @EXPORT, qw(CFGOPT_PG_HOST_CONFIG);
use constant CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH => CFGOPT_PG_HOST_CONFIG . '-include-path';
push @EXPORT, qw(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH);
use constant CFGOPT_PG_HOST_CONFIG_PATH => CFGOPT_PG_HOST_CONFIG . '-path';
push @EXPORT, qw(CFGOPT_PG_HOST_CONFIG_PATH);
use constant CFGOPT_PG_HOST_PORT => CFGOPT_PG_HOST . '-port';
push @EXPORT, qw(CFGOPT_PG_HOST_PORT);
use constant CFGOPT_PG_HOST_USER => CFGOPT_PG_HOST . '-user';
@ -419,7 +431,9 @@ use constant CFGDEF_DEFAULT_BUFFER_SIZE_MIN => 16384;
use constant CFGDEF_DEFAULT_COMPRESS_LEVEL_MIN => 0;
use constant CFGDEF_DEFAULT_COMPRESS_LEVEL_MAX => 9;
use constant CFGDEF_DEFAULT_CONFIG => '/etc/' . BACKREST_CONF;
use constant CFGDEF_DEFAULT_CONFIG_PATH => '/etc/pgbackrest';
use constant CFGDEF_DEFAULT_CONFIG => CFGDEF_DEFAULT_CONFIG_PATH . '/' . BACKREST_CONF;
use constant CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH => CFGDEF_DEFAULT_CONFIG_PATH . '/conf.d';
use constant CFGDEF_DEFAULT_DB_TIMEOUT => 1800;
use constant CFGDEF_DEFAULT_DB_TIMEOUT_MIN => WAIT_TIME_MINIMUM;
@ -659,6 +673,20 @@ my %hConfigDefine =
}
},
&CFGOPT_CONFIG_INCLUDE_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH,
&CFGDEF_NEGATE => false,
},
&CFGOPT_CONFIG_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_PATH,
&CFGDEF_NEGATE => false,
},
&CFGOPT_DELTA =>
{
&CFGDEF_TYPE => CFGDEF_TYPE_BOOLEAN,
@ -1425,6 +1453,18 @@ my %hConfigDefine =
},
},
&CFGOPT_REPO_HOST_CONFIG_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_REPO_HOST_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_PATH,
},
&CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_REPO_HOST_CONFIG,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH,
},
&CFGOPT_REPO_HOST_PORT =>
{
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
@ -2111,6 +2151,18 @@ my %hConfigDefine =
},
},
&CFGOPT_PG_HOST_CONFIG_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_PG_HOST_CMD,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_PATH,
},
&CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH =>
{
&CFGDEF_INHERIT => CFGOPT_PG_HOST_CMD,
&CFGDEF_DEFAULT => CFGDEF_DEFAULT_CONFIG_INCLUDE_PATH,
},
&CFGOPT_PG_HOST_PORT =>
{
&CFGDEF_INHERIT => CFGOPT_PG_HOST_CMD,

View File

@ -239,7 +239,25 @@
<text>Sets the location of the configuration file on the repository host. This is only required if the repository host configuration file is in a different location than the local configuration file.</text>
<example>/etc/pgbackrest_backup.conf</example>
<example>/conf/pgbackrest/pgbackrest.conf</example>
</config-key>
<!-- CONFIG - REPO SECTION - REPO-HOST-CONFIG-INCLUDE-PATH KEY -->
<config-key id="repo-host-config-include-path" name="Repository Host Configuration Include Path">
<summary><backrest/> repository host configuration include path.</summary>
<text>Sets the location of the configuration include path on the repository host. This is only required if the repository host configuration include path is in a different location than the local configuration include path.</text>
<example>/conf/pgbackrest/conf.d</example>
</config-key>
<!-- CONFIG - REPO SECTION - REPO-HOST-CONFIG-PATH KEY -->
<config-key id="repo-host-config-path" name="Repository Host Configuration Path">
<summary><backrest/> repository host configuration path.</summary>
<text>Sets the location of the configuration path on the repository host. This is only required if the repository host configuration path is in a different location than the local configuration path.</text>
<example>/conf/pgbackrest</example>
</config-key>
<!-- CONFIG - REPO SECTION - REPO-HOST-USER KEY -->
@ -674,7 +692,25 @@
<text>Sets the location of the configuration file on the <postgres/> host. This is only required if the <postgres/> host configuration file is in a different location than the local configuration file.</text>
<example>/etc/pgbackrest_db.conf</example>
<example>/conf/pgbackrest/pgbackrest.conf</example>
</config-key>
<!-- CONFIG - STANZA SECTION - PG-HOST-CONFIG-INCLUDE-PATH KEY -->
<config-key id="pg-host-config-include-path" name="PostgreSQL Host Configuration Include Path">
<summary><backrest/> database host configuration include path.</summary>
<text>Sets the location of the configuration include path on the <postgres/> host. This is only required if the <postgres/> host configuration include path is in a different location than the local configuration include path.</text>
<example>/conf/pgbackrest/conf.d</example>
</config-key>
<!-- CONFIG - STANZA SECTION - PG-HOST-CONFIG-PATH KEY -->
<config-key id="pg-host-config-path" name="PostgreSQL Host Configuration Path">
<summary><backrest/> database host configuration path.</summary>
<text>Sets the location of the configuration path on the <postgres/> host. This is only required if the <postgres/> host configuration path is in a different location than the local configuration path.</text>
<example>/conf/pgbackrest</example>
</config-key>
<!-- CONFIG - STANZA SECTION - PG-HOST KEY -->
@ -755,7 +791,27 @@
<text>Use this option to specify a different configuration file than the default.</text>
<example>/var/lib/backrest/pgbackrest.conf</example>
<example>/conf/pgbackrest/pgbackrest.conf</example>
</option>
<!-- OPERATION - GENERAL - CONFIG INCLUDE PATH OPTION -->
<option id="config-include-path" name="Config Include Path">
<summary>Path to additional <backrest/> configuration files.</summary>
<text>Configuration files existing in the specified location with extension <file>.conf</file> will be concatenated with the <backrest/> configuration file, resulting in one configuration file.</text>
<example>/conf/pgbackrest/conf.d</example>
</option>
<!-- OPERATION - GENERAL - CONFIG PATH OPTION -->
<option id="config-path" name="Config Path">
<summary>Base path of <backrest/> configuration files.</summary>
<text>This setting is used to override the default base path setting for the <br-option>--config</br-option> and <br-option>--config-include-path</br-option> options unless they are explicitly set on the command-line.
For example, passing only <code>--config-path=/conf/pgbackrest</code> results in the <br-option>--config</br-option> default being set to <code>/conf/pgbackrest/pgbackrest.conf</code> and the <br-option>--config-include-path</br-option> default being set to <code>/conf/pgbackrest/conf.d</code>.</text>
<example>/conf/pgbackrest</example>
</option>
<!-- OPERATION - GENERAL - STANZA OPTION -->

View File

@ -24,6 +24,16 @@
</release-item>
</release-bug-list>
<release-feature-list>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="shang.cynthia"/>
</release-item-contributor-list>
<p>Add support for additional <backrest/> configuration files in the directory specified by the <br-option>--config-include-path</br-option> option. Add <br-option>--config-path</br-option> option for overriding the default base path of the <br-option>--config</br-option> and <br-option>--config-include-path</br-option> option.</p>
</release-item>
</release-feature-list>
<release-improvement-list>
<release-item>
<p>Make backup directory sync more efficient. Scanning the entire backup directory can be very expensive if there are a lot of small tables. The backup manifest contains the backup directory list so use it to perform syncs instead of scanning the backup directory.</p>

View File

@ -42,7 +42,9 @@
<variable key="br-home-path">/home/{[br-user]}</variable>
<variable key="postgres-cluster-demo">demo</variable>
<variable key="backrest-config-demo">/etc/{[project-exe]}.conf</variable>
<variable key="backrest-config-path">/etc/{[project-exe]}</variable>
<variable key="backrest-config-include-path">{[backrest-config-path]}/conf.d</variable>
<variable key="backrest-config-demo">{[backrest-config-path]}/{[project-exe]}.conf</variable>
<variable key="pg-path-default" keyword="default">/var/lib/postgresql/[version]/[cluster]</variable>
<variable key="pg-path-default" keyword="co6">/var/lib/pgsql/[version]/data</variable>
@ -281,6 +283,12 @@
<execute user="root">
<exe-cmd>chown {[br-install-user]}:{[br-install-group]} /var/log/pgbackrest</exe-cmd>
</execute>
<execute user="root">
<exe-cmd>mkdir {[backrest-config-path]}</exe-cmd>
</execute>
<execute user="root">
<exe-cmd>mkdir {[backrest-config-include-path]}</exe-cmd>
</execute>
<execute user="root">
<exe-cmd>touch {[backrest-config-demo]}</exe-cmd>
</execute>
@ -419,6 +427,8 @@
<list-item>The deprecated <br-option>archive-max-mb</br-option> option is no longer valid. This has been replaced with the <br-option>archive-push-queue-max</br-option> option which has different semantics.</list-item>
<list-item>The default for the <br-option>backup-user</br-option> option has changed from <id>backrest</id> to <id>pgbackrest</id>.</list-item>
<list-item>In <proper>v2.02</proper> the default location of the <backrest/> configuration file has changed from <file>/etc/pgbackrest.conf</file> to <file>/etc/pgbackrest/pgbackrest.conf</file>. If <file>/etc/pgbackrest/pgbackrest.conf</file> does not exist, the <file>/etc/pgbackrest.conf</file> file will be loaded instead, if it exists.</list-item>
</list>
<p>Many option names have changed to improve consistency although the old names from <proper>v1</proper> are still accepted. In general, <id>db-*</id> options have been renamed to <id>pg-*</id> and <id>backup-*</id>/<id>retention-*</id> options have been renamed to <id>repo-*</id> when appropriate.</p>
@ -555,6 +565,26 @@
</backrest-config>
<p><backrest/> configuration files follow the Windows INI convention. Sections are denoted by text in brackets and key/value pairs are contained in each section. Lines beginning with <id>#</id> are ignored and can be used as comments.</p>
<p>There are multiple ways the <backrest/> configuration files can be loaded:</p>
<list>
<list-item><br-option>config</br-option> and <br-option>config-include-path</br-option> are default: the default config file will be loaded, if it exists, and <file>*.conf</file> files in the default config include path will be appended, if they exist.</list-item>
<list-item><br-option>config</br-option> option is specified: only the specified config file will be loaded and is expected to exist.</list-item>
<list-item><br-option>config-include-path</br-option> is specified: <file>*.conf</file> files in the config include path will be loaded and the path is required to exist. The default config file will be be loaded if it exists. If it is desireable to load only the files in the specified config include path, then the <br-option>--no-config</br-option> option can also be passed.</list-item>
<list-item><br-option>config</br-option> and <br-option>config-include-path</br-option> are specified: using the user-specified values, the config file will be loaded and <file>*.conf</file> files in the config include path will be appended. The files are expected to exist.</list-item>
<list-item><br-option>config-path</br-option> is specified: this setting will override the base path for the default location of the config file and/or the base path of the default config-include-path setting unless the config and/or config-incude-path option is explicitly set.</list-item>
</list>
<p>The files are concatenated as if they were one big file; order doesn't matter, but there is precedence based on sections. The precedence (highest to lowest) is:</p>
<list>
<list-item>[<i>stanza</i>:<i>command</i>]</list-item>
<list-item>[<i>stanza</i>]</list-item>
<list-item>[global:<i>command</i>]</list-item>
<list-item>[global]</list-item>
</list>
<p><b>Note:</b> <br-option>--config</br-option>, <br-option>--config-include-path</br-option> and <br-option>--config-path</br-option> are command-line only options.</p>
</section>
<!-- SECTION => QUICKSTART - CREATE REPOSITORY -->

View File

@ -167,6 +167,8 @@ sub protocolParam
# Return the remote when required
my $iOptionIdCmd = CFGOPT_REPO_HOST_CMD;
my $iOptionIdConfig = CFGOPT_REPO_HOST_CONFIG;
my $iOptionIdConfigIncludePath = CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH;
my $iOptionIdConfigPath = CFGOPT_REPO_HOST_CONFIG_PATH;
my $iOptionIdHost = CFGOPT_REPO_HOST;
my $iOptionIdUser = CFGOPT_REPO_HOST_USER;
my $strOptionDbPath = undef;
@ -178,6 +180,8 @@ sub protocolParam
{
$iOptionIdCmd = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, $iRemoteIdx);
$iOptionIdConfig = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, $iRemoteIdx);
$iOptionIdConfigIncludePath = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, $iRemoteIdx);
$iOptionIdConfigPath = cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, $iRemoteIdx);
$iOptionIdHost = cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iRemoteIdx);
$iOptionIdUser = cfgOptionIdFromIndex(CFGOPT_PG_HOST_USER, $iRemoteIdx);
$strOptionSshPort = cfgOptionIdFromIndex(CFGOPT_PG_HOST_PORT, $iRemoteIdx);
@ -215,6 +219,13 @@ sub protocolParam
&CFGOPT_CONFIG =>
{value => cfgOptionValid($iOptionIdConfig) && cfgOptionSource($iOptionIdConfig) eq CFGDEF_SOURCE_DEFAULT ?
undef : cfgOption($iOptionIdConfig)},
&CFGOPT_CONFIG_INCLUDE_PATH =>
{value => cfgOptionValid($iOptionIdConfigIncludePath) &&
cfgOptionSource($iOptionIdConfigIncludePath) eq CFGDEF_SOURCE_DEFAULT ?
undef : cfgOption($iOptionIdConfigIncludePath)},
&CFGOPT_CONFIG_PATH =>
{value => cfgOptionValid($iOptionIdConfigPath) && cfgOptionSource($iOptionIdConfigPath) eq CFGDEF_SOURCE_DEFAULT ?
undef : cfgOption($iOptionIdConfigPath)},
&CFGOPT_TYPE => {value => $strRemoteType},
&CFGOPT_LOG_PATH => {},
&CFGOPT_LOCK_PATH => {},
@ -241,6 +252,8 @@ sub protocolParam
if ($iOptionIdx != 1)
{
$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, $iOptionIdx)} = {};
$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, $iOptionIdx)} = {};
$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, $iOptionIdx)} = {};
$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_HOST, $iOptionIdx)} = {};
$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_PATH, $iOptionIdx)} = {};
$rhCommandOption->{cfgOptionIdFromIndex(CFGOPT_PG_PORT, $iOptionIdx)} = {};

View File

@ -129,6 +129,8 @@ sub libcAutoExportTag
'CFGOPT_COMPRESS_LEVEL',
'CFGOPT_COMPRESS_LEVEL_NETWORK',
'CFGOPT_CONFIG',
'CFGOPT_CONFIG_INCLUDE_PATH',
'CFGOPT_CONFIG_PATH',
'CFGOPT_DB_INCLUDE',
'CFGOPT_DB_TIMEOUT',
'CFGOPT_DELTA',
@ -150,6 +152,8 @@ sub libcAutoExportTag
'CFGOPT_PG_HOST',
'CFGOPT_PG_HOST_CMD',
'CFGOPT_PG_HOST_CONFIG',
'CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH',
'CFGOPT_PG_HOST_CONFIG_PATH',
'CFGOPT_PG_HOST_PORT',
'CFGOPT_PG_HOST_USER',
'CFGOPT_PG_PATH',
@ -165,6 +169,8 @@ sub libcAutoExportTag
'CFGOPT_REPO_HOST',
'CFGOPT_REPO_HOST_CMD',
'CFGOPT_REPO_HOST_CONFIG',
'CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH',
'CFGOPT_REPO_HOST_CONFIG_PATH',
'CFGOPT_REPO_HOST_PORT',
'CFGOPT_REPO_HOST_USER',
'CFGOPT_REPO_PATH',

View File

@ -43,6 +43,8 @@ Option constants
#define CFGOPT_COMPRESS_LEVEL cfgOptCompressLevel
#define CFGOPT_COMPRESS_LEVEL_NETWORK cfgOptCompressLevelNetwork
#define CFGOPT_CONFIG cfgOptConfig
#define CFGOPT_CONFIG_INCLUDE_PATH cfgOptConfigIncludePath
#define CFGOPT_CONFIG_PATH cfgOptConfigPath
#define CFGOPT_DB_INCLUDE cfgOptDbInclude
#define CFGOPT_DB_TIMEOUT cfgOptDbTimeout
#define CFGOPT_DELTA cfgOptDelta
@ -64,6 +66,8 @@ Option constants
#define CFGOPT_PG_HOST cfgOptPgHost
#define CFGOPT_PG_HOST_CMD cfgOptPgHostCmd
#define CFGOPT_PG_HOST_CONFIG cfgOptPgHostConfig
#define CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH cfgOptPgHostConfigIncludePath
#define CFGOPT_PG_HOST_CONFIG_PATH cfgOptPgHostConfigPath
#define CFGOPT_PG_HOST_PORT cfgOptPgHostPort
#define CFGOPT_PG_HOST_USER cfgOptPgHostUser
#define CFGOPT_PG_PATH cfgOptPgPath
@ -79,6 +83,8 @@ Option constants
#define CFGOPT_REPO_HOST cfgOptRepoHost
#define CFGOPT_REPO_HOST_CMD cfgOptRepoHostCmd
#define CFGOPT_REPO_HOST_CONFIG cfgOptRepoHostConfig
#define CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH cfgOptRepoHostConfigIncludePath
#define CFGOPT_REPO_HOST_CONFIG_PATH cfgOptRepoHostConfigPath
#define CFGOPT_REPO_HOST_PORT cfgOptRepoHostPort
#define CFGOPT_REPO_HOST_USER cfgOptRepoHostUser
#define CFGOPT_REPO_PATH cfgOptRepoPath

View File

@ -303,6 +303,22 @@ static ConfigOptionData configOptionData[CFG_OPTION_TOTAL] = CONFIG_OPTION_LIST
CONFIG_OPTION_DEFINE_ID(cfgDefOptConfig)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("config-include-path")
CONFIG_OPTION_INDEX(0)
CONFIG_OPTION_DEFINE_ID(cfgDefOptConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("config-path")
CONFIG_OPTION_INDEX(0)
CONFIG_OPTION_DEFINE_ID(cfgDefOptConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
@ -639,6 +655,134 @@ static ConfigOptionData configOptionData[CFG_OPTION_TOTAL] = CONFIG_OPTION_LIST
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfig)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg1-host-config-include-path")
CONFIG_OPTION_INDEX(0)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg2-host-config-include-path")
CONFIG_OPTION_INDEX(1)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg3-host-config-include-path")
CONFIG_OPTION_INDEX(2)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg4-host-config-include-path")
CONFIG_OPTION_INDEX(3)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg5-host-config-include-path")
CONFIG_OPTION_INDEX(4)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg6-host-config-include-path")
CONFIG_OPTION_INDEX(5)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg7-host-config-include-path")
CONFIG_OPTION_INDEX(6)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg8-host-config-include-path")
CONFIG_OPTION_INDEX(7)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg1-host-config-path")
CONFIG_OPTION_INDEX(0)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg2-host-config-path")
CONFIG_OPTION_INDEX(1)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg3-host-config-path")
CONFIG_OPTION_INDEX(2)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg4-host-config-path")
CONFIG_OPTION_INDEX(3)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg5-host-config-path")
CONFIG_OPTION_INDEX(4)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg6-host-config-path")
CONFIG_OPTION_INDEX(5)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg7-host-config-path")
CONFIG_OPTION_INDEX(6)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("pg8-host-config-path")
CONFIG_OPTION_INDEX(7)
CONFIG_OPTION_DEFINE_ID(cfgDefOptPgHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
@ -1039,6 +1183,22 @@ static ConfigOptionData configOptionData[CFG_OPTION_TOTAL] = CONFIG_OPTION_LIST
CONFIG_OPTION_DEFINE_ID(cfgDefOptRepoHostConfig)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("repo1-host-config-include-path")
CONFIG_OPTION_INDEX(0)
CONFIG_OPTION_DEFINE_ID(cfgDefOptRepoHostConfigIncludePath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(
CONFIG_OPTION_NAME("repo1-host-config-path")
CONFIG_OPTION_INDEX(0)
CONFIG_OPTION_DEFINE_ID(cfgDefOptRepoHostConfigPath)
)
//------------------------------------------------------------------------------------------------------------------------------
CONFIG_OPTION
(

View File

@ -14,7 +14,7 @@ Command constants
/***********************************************************************************************************************************
Option constants
***********************************************************************************************************************************/
#define CFG_OPTION_TOTAL 139
#define CFG_OPTION_TOTAL 159
/***********************************************************************************************************************************
Command enum
@ -59,6 +59,8 @@ typedef enum
cfgOptCompressLevel,
cfgOptCompressLevelNetwork,
cfgOptConfig,
cfgOptConfigIncludePath,
cfgOptConfigPath,
cfgOptDbInclude,
cfgOptDbTimeout,
cfgOptDelta,
@ -78,14 +80,16 @@ typedef enum
cfgOptOutput,
cfgOptPerlOption,
cfgOptPgHost,
cfgOptPgHostCmd = 40,
cfgOptPgHostConfig = 48,
cfgOptPgHostPort = 56,
cfgOptPgHostUser = 64,
cfgOptPgPath = 72,
cfgOptPgPort = 80,
cfgOptPgSocketPath = 88,
cfgOptProcess = 96,
cfgOptPgHostCmd = 42,
cfgOptPgHostConfig = 50,
cfgOptPgHostConfigIncludePath = 58,
cfgOptPgHostConfigPath = 66,
cfgOptPgHostPort = 74,
cfgOptPgHostUser = 82,
cfgOptPgPath = 90,
cfgOptPgPort = 98,
cfgOptPgSocketPath = 106,
cfgOptProcess = 114,
cfgOptProcessMax,
cfgOptProtocolTimeout,
cfgOptRecoveryOption,
@ -95,6 +99,8 @@ typedef enum
cfgOptRepoHost,
cfgOptRepoHostCmd,
cfgOptRepoHostConfig,
cfgOptRepoHostConfigIncludePath,
cfgOptRepoHostConfigPath,
cfgOptRepoHostPort,
cfgOptRepoHostUser,
cfgOptRepoPath,

View File

@ -732,7 +732,7 @@ cfgOptionSource(ConfigOption optionId)
}
/***********************************************************************************************************************************
Is the option set?
Is the option valid for the command and set?
***********************************************************************************************************************************/
bool
cfgOptionTest(ConfigOption optionId)

View File

@ -751,7 +751,98 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest.conf")
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest/pgbackrest.conf")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
CFGDEFDATA_OPTION_NAME("config-include-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionCommandLine)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("general")
CFGDEFDATA_OPTION_HELP_SUMMARY("Path to additional pgBackRest configuration files.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"Configuration files existing in the specified location with extension .conf will be concatenated with the pgBackRest "
"configuration file, resulting in one configuration file."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGet)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePush)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdExpire)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdInfo)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRemote)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaCreate)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaDelete)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaUpgrade)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest/conf.d")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
CFGDEFDATA_OPTION_NAME("config-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionCommandLine)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("general")
CFGDEFDATA_OPTION_HELP_SUMMARY("Base path of pgBackRest configuration files.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"This setting is used to override the default base path setting for the --config and --config-include-path options "
"unless they are explicitly set on the command-line.\n"
"\n"
"For example, passing only --config-path=/conf/pgbackrest results in the --config default being set to "
"/conf/pgbackrest/pgbackrest.conf and the --config-include-path default being set to /conf/pgbackrest/conf.d."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGet)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePush)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdExpire)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdInfo)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRemote)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaCreate)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaDelete)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaUpgrade)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest")
)
)
@ -1740,12 +1831,94 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEPEND(cfgDefOptPgHost)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest.conf")
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest/pgbackrest.conf")
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("pg")
CFGDEFDATA_OPTION_OPTIONAL_HELP_NAME_ALT("db-config")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
CFGDEFDATA_OPTION_NAME("pg-host-config-include-path")
CFGDEFDATA_OPTION_REQUIRED(false)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionStanza)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(8)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("stanza")
CFGDEFDATA_OPTION_HELP_SUMMARY("pgBackRest database host configuration include path.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"Sets the location of the configuration include path on the PostgreSQL host. This is only required if the PostgreSQL "
"host configuration include path is in a different location than the local configuration include path."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdExpire)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaCreate)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaDelete)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaUpgrade)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEPEND(cfgDefOptPgHost)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest/conf.d")
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("pg")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
CFGDEFDATA_OPTION_NAME("pg-host-config-path")
CFGDEFDATA_OPTION_REQUIRED(false)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionStanza)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(8)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("stanza")
CFGDEFDATA_OPTION_HELP_SUMMARY("pgBackRest database host configuration path.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"Sets the location of the configuration path on the PostgreSQL host. This is only required if the PostgreSQL host "
"configuration path is in a different location than the local configuration path."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdExpire)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaCreate)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaDelete)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaUpgrade)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEPEND(cfgDefOptPgHost)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest")
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("pg")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
@ -2437,12 +2610,92 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEPEND(cfgDefOptRepoHost)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest.conf")
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest/pgbackrest.conf")
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("repo")
CFGDEFDATA_OPTION_OPTIONAL_HELP_NAME_ALT("backup-config")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
CFGDEFDATA_OPTION_NAME("repo-host-config-include-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("repository")
CFGDEFDATA_OPTION_HELP_SUMMARY("pgBackRest repository host configuration include path.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"Sets the location of the configuration include path on the repository host. This is only required if the repository "
"host configuration include path is in a different location than the local configuration include path."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGet)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePush)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdInfo)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEPEND(cfgDefOptRepoHost)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest/conf.d")
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("repo")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(
CFGDEFDATA_OPTION_NAME("repo-host-config-path")
CFGDEFDATA_OPTION_REQUIRED(true)
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
CFGDEFDATA_OPTION_INTERNAL(false)
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
CFGDEFDATA_OPTION_SECURE(false)
CFGDEFDATA_OPTION_HELP_SECTION("repository")
CFGDEFDATA_OPTION_HELP_SUMMARY("pgBackRest repository host configuration path.")
CFGDEFDATA_OPTION_HELP_DESCRIPTION
(
"Sets the location of the configuration path on the repository host. This is only required if the repository host "
"configuration path is in a different location than the local configuration path."
)
CFGDEFDATA_OPTION_COMMAND_LIST
(
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGet)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePush)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdInfo)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
)
CFGDEFDATA_OPTION_OPTIONAL_LIST
(
CFGDEFDATA_OPTION_OPTIONAL_DEPEND(cfgDefOptRepoHost)
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("/etc/pgbackrest")
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("repo")
)
)
// -----------------------------------------------------------------------------------------------------------------------------
CFGDEFDATA_OPTION
(

View File

@ -61,6 +61,8 @@ typedef enum
cfgDefOptCompressLevel,
cfgDefOptCompressLevelNetwork,
cfgDefOptConfig,
cfgDefOptConfigIncludePath,
cfgDefOptConfigPath,
cfgDefOptDbInclude,
cfgDefOptDbTimeout,
cfgDefOptDelta,
@ -82,6 +84,8 @@ typedef enum
cfgDefOptPgHost,
cfgDefOptPgHostCmd,
cfgDefOptPgHostConfig,
cfgDefOptPgHostConfigIncludePath,
cfgDefOptPgHostConfigPath,
cfgDefOptPgHostPort,
cfgDefOptPgHostUser,
cfgDefOptPgPath,
@ -97,6 +101,8 @@ typedef enum
cfgDefOptRepoHost,
cfgDefOptRepoHostCmd,
cfgDefOptRepoHostConfig,
cfgDefOptRepoHostConfigIncludePath,
cfgDefOptRepoHostConfigPath,
cfgDefOptRepoHostPort,
cfgDefOptRepoHostUser,
cfgDefOptRepoPath,

View File

@ -200,6 +200,22 @@ static const struct option optionList[] =
.val = PARSE_OPTION_FLAG | PARSE_NEGATE_FLAG | cfgOptConfig,
},
// config-include-path option
// -----------------------------------------------------------------------------------------------------------------------------
{
.name = "config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | cfgOptConfigIncludePath,
},
// config-path option
// -----------------------------------------------------------------------------------------------------------------------------
{
.name = "config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | cfgOptConfigPath,
},
// db-include option
// -----------------------------------------------------------------------------------------------------------------------------
{
@ -766,6 +782,156 @@ static const struct option optionList[] =
.val = PARSE_OPTION_FLAG | PARSE_DEPRECATE_FLAG | (cfgOptPgHostConfig + 7),
},
// pg-host-config-include-path option
// -----------------------------------------------------------------------------------------------------------------------------
{
.name = "pg1-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | cfgOptPgHostConfigIncludePath,
},
{
.name = "reset-pg1-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptPgHostConfigIncludePath,
},
{
.name = "pg2-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 1),
},
{
.name = "reset-pg2-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 1),
},
{
.name = "pg3-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 2),
},
{
.name = "reset-pg3-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 2),
},
{
.name = "pg4-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 3),
},
{
.name = "reset-pg4-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 3),
},
{
.name = "pg5-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 4),
},
{
.name = "reset-pg5-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 4),
},
{
.name = "pg6-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 5),
},
{
.name = "reset-pg6-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 5),
},
{
.name = "pg7-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 6),
},
{
.name = "reset-pg7-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 6),
},
{
.name = "pg8-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigIncludePath + 7),
},
{
.name = "reset-pg8-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigIncludePath + 7),
},
// pg-host-config-path option
// -----------------------------------------------------------------------------------------------------------------------------
{
.name = "pg1-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | cfgOptPgHostConfigPath,
},
{
.name = "reset-pg1-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptPgHostConfigPath,
},
{
.name = "pg2-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 1),
},
{
.name = "reset-pg2-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 1),
},
{
.name = "pg3-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 2),
},
{
.name = "reset-pg3-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 2),
},
{
.name = "pg4-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 3),
},
{
.name = "reset-pg4-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 3),
},
{
.name = "pg5-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 4),
},
{
.name = "reset-pg5-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 4),
},
{
.name = "pg6-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 5),
},
{
.name = "reset-pg6-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 5),
},
{
.name = "pg7-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 6),
},
{
.name = "reset-pg7-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 6),
},
{
.name = "pg8-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | (cfgOptPgHostConfigPath + 7),
},
{
.name = "reset-pg8-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | (cfgOptPgHostConfigPath + 7),
},
// pg-host-port option and deprecations
// -----------------------------------------------------------------------------------------------------------------------------
{
@ -1518,6 +1684,30 @@ static const struct option optionList[] =
.val = PARSE_OPTION_FLAG | PARSE_DEPRECATE_FLAG | cfgOptRepoHostConfig,
},
// repo-host-config-include-path option
// -----------------------------------------------------------------------------------------------------------------------------
{
.name = "repo1-host-config-include-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | cfgOptRepoHostConfigIncludePath,
},
{
.name = "reset-repo1-host-config-include-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptRepoHostConfigIncludePath,
},
// repo-host-config-path option
// -----------------------------------------------------------------------------------------------------------------------------
{
.name = "repo1-host-config-path",
.has_arg = required_argument,
.val = PARSE_OPTION_FLAG | cfgOptRepoHostConfigPath,
},
{
.name = "reset-repo1-host-config-path",
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptRepoHostConfigPath,
},
// repo-host-port option and deprecations
// -----------------------------------------------------------------------------------------------------------------------------
{

View File

@ -12,6 +12,18 @@ Command and Option Parse
#include "common/memContext.h"
#include "config/parse.h"
#include "storage/helper.h"
#include "version.h"
/***********************************************************************************************************************************
Standard config file name and old default path and name
***********************************************************************************************************************************/
#define PGBACKREST_CONFIG_FILE PGBACKREST_BIN ".conf"
#define PGBACKREST_CONFIG_ORIG_PATH_FILE "/etc/" PGBACKREST_CONFIG_FILE
/***********************************************************************************************************************************
Standard config include path name
***********************************************************************************************************************************/
#define PGBACKREST_CONFIG_INCLUDE_PATH "conf.d"
/***********************************************************************************************************************************
Parse option flags
@ -67,6 +79,170 @@ optionFind(const String *option)
return optionIdx;
}
/***********************************************************************************************************************************
Load the configuration file(s)
The parent mem context is used. Defaults are passed to make testing easier.
Rules:
- config and config-include-path are default. In this case, the config file will be loaded, if it exists, and *.conf files in the
config-include-path will be appended, if they exist. A missing/empty dir will be ignored except that the original default
for the config file will be attempted to be loaded if the current default is not found.
- config only is specified. Only the specified config file will be loaded and is required. The default config-include-path will be
ignored.
- config and config-path are specified. The specified config file will be loaded and is required. The overridden default of the
config-include-path (<config-path>/conf.d) will be loaded if exists but is not required.
- config-include-path only is specified. *.conf files in the config-include-path will be loaded and the path is required to exist.
The default config will be be loaded if it exists.
- config-include-path and config-path are specified. The *.conf files in the config-include-path will be loaded and the directory
passed must exist. The overridden default of the config file path (<config-path>/pgbackrest.conf) will be loaded if exists but is
not required.
- If the config and config-include-path are specified. The config file will be loaded and is expected to exist and *.conf files in
the config-include-path will be appended and at least one is expected to exist.
- If --no-config is specified and --config-include-path is specified then only *.conf files in the config-include-path will be
loaded; the directory is required.
- If --no-config is specified and --config-path is specified then only *.conf files in the overriden default config-include-path
(<config-path>/conf.d) will be loaded if exist but not required.
- If --no-config is specified and neither --config-include-path nor --config-path are specified then no configs will be loaded.
- If --config-path only, the defaults for config and config-include-path will be changed to use that as a base path but the files
will not be required to exist since this is a default override.
***********************************************************************************************************************************/
static String *
cfgFileLoad( // NOTE: Passing defaults to enable more complete test coverage
const ParseOption *optionList, // All options and their current settings
const String *optConfigDefault, // Current default for --config option
const String *optConfigIncludePathDefault, // Current default for --config-include-path option
const String *origConfigDefault) // Original --config option default (/etc/pgbackrest.conf)
{
bool loadConfig = true;
bool loadConfigInclude = true;
// If the option is specified on the command line, then found will be true meaning the file is required to exist,
// else it is optional
bool configRequired = optionList[cfgOptConfig].found;
bool configIncludeRequired = optionList[cfgOptConfigIncludePath].found;
// Save default for later determining if must check old original default config path
const String *optConfigDefaultCurrent = optConfigDefault;
// If the config-path option is found on the command line, then its value will override the base path defaults for config and
// config-include-path
if (optionList[cfgOptConfigPath].found)
{
optConfigDefault =
strNewFmt("%s/%s", strPtr(strLstGet(optionList[cfgOptConfigPath].valueList, 0)), strPtr(strBase(optConfigDefault)));
optConfigIncludePathDefault =
strNewFmt("%s/%s", strPtr(strLstGet(optionList[cfgOptConfigPath].valueList, 0)), PGBACKREST_CONFIG_INCLUDE_PATH);
}
// If the --no-config option was passed then do not load the config file
if (optionList[cfgOptConfig].negate)
{
loadConfig = false;
configRequired = false;
}
// If --config option is specified on the command line but neither the --config-include-path nor the config-path are passed,
// then do not attempt to load the include files
if (optionList[cfgOptConfig].found && !(optionList[cfgOptConfigIncludePath].found || optionList[cfgOptConfigPath].found))
{
loadConfigInclude = false;
configIncludeRequired = false;
}
String *result = NULL;
// Load the main config file
if (loadConfig)
{
const String *configFileName = NULL;
// Get the config file name from the command-line if it exists else default
if (optionList[cfgOptConfig].found)
configFileName = strLstGet(optionList[cfgOptConfig].valueList, 0);
else
configFileName = optConfigDefault;
// Load the config file
Buffer *buffer = storageGetNP(storageOpenReadP(storageLocal(), configFileName, .ignoreMissing = !configRequired));
// Convert the contents of the file buffer to the config string object
if (buffer != NULL)
result = strNewBuf(buffer);
else if (strEq(configFileName, optConfigDefaultCurrent))
{
// If confg is current default and it was not found, attempt to load the config file from the old default location
buffer = storageGetNP(storageOpenReadP(storageLocal(), origConfigDefault, .ignoreMissing = !configRequired));
if (buffer != NULL)
result = strNewBuf(buffer);
}
}
// Load *.conf files from the include directory
if (loadConfigInclude)
{
if (result != NULL)
{
// Validate the file by parsing it as an Ini object. If the file is not properly formed, en error will occur.
Ini *ini = iniNew();
iniParse(ini, result);
}
const String *configIncludePath = NULL;
// Get the config include path from the command-line if it exists else default
if (optionList[cfgOptConfigIncludePath].found)
configIncludePath = strLstGet(optionList[cfgOptConfigIncludePath].valueList, 0);
else
configIncludePath = optConfigIncludePathDefault;
// Get a list of conf files from the specified path -error on missing directory if the option was passed on the command line
StringList *list = storageListP(
storageLocal(), configIncludePath, .expression = strNew(".+\\.conf$"), .errorOnMissing = configIncludeRequired);
// If conf files are found, then add them to the config string
if (list != NULL && strLstSize(list) > 0)
{
// Sort the list for reproducibility only -- order does not matter
strLstSort(list, sortOrderAsc);
for (unsigned int listIdx = 0; listIdx < strLstSize(list); listIdx++)
{
Buffer *fileBuffer = storageGetNP(
storageOpenReadP(
storageLocal(), strNewFmt("%s/%s", strPtr(configIncludePath), strPtr(strLstGet(list, listIdx))),
.ignoreMissing = true));
if (fileBuffer != NULL) // {uncovered - NULL can only occur if file is missing after file list is retrieved}
{
// Convert the contents of the file buffer to a string object
String *configPart = strNewBuf(fileBuffer);
// Validate the file by parsing it as an Ini object. If the file is not properly formed, an error will occur.
if (strSize(configPart) > 0)
{
Ini *configPartIni = iniNew();
iniParse(configPartIni, configPart);
// Create the result config file
if (result == NULL)
result = strNew("");
// Else add an LF in case the previous file did not end with one
else
strCat(result, "\n");
// Add the config part to the result config file
strCat(result, strPtr(configPart));
}
}
}
}
}
return result;
}
/***********************************************************************************************************************************
Parse the command-line arguments and config file to produce final config data
@ -244,159 +420,147 @@ configParse(unsigned int argListSize, const char *argList[])
// Get the command definition id
ConfigDefineCommand commandDefId = cfgCommandDefIdFromId(cfgCommand());
if (!parseOptionList[cfgOptConfig].negate)
// Load the configuration file(s)
String *configString = cfgFileLoad(parseOptionList,
strNew(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfig))),
strNew(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfigIncludePath))),
strNew(PGBACKREST_CONFIG_ORIG_PATH_FILE));
if (configString != NULL)
{
// Get the config file name from the command-line if it exists else default
const String *configFile = NULL;
Ini *config = iniNew();
iniParse(config, configString);
// Get the stanza name
String *stanza = NULL;
if (parseOptionList[cfgOptConfig].found)
configFile = strLstGet(parseOptionList[cfgOptConfig].valueList, 0);
else
configFile = strNew(cfgDefOptionDefault(commandDefId, cfgOptionDefIdFromId(cfgOptConfig)));
if (parseOptionList[cfgOptStanza].found)
stanza = strLstGet(parseOptionList[cfgOptStanza].valueList, 0);
// Load the ini file
Buffer *buffer = storageGetNP(
storageOpenReadP(storageLocal(), configFile, .ignoreMissing = !parseOptionList[cfgOptConfig].found));
// Build list of sections to search for options
StringList *sectionList = strLstNew();
// Load the config file if it was found
if (buffer != NULL)
if (stanza != NULL)
{
// Parse the ini file
Ini *config = iniNew();
iniParse(config, strNewBuf(buffer));
strLstAdd(sectionList, strNewFmt("%s:%s", strPtr(stanza), cfgCommandName(cfgCommand())));
strLstAdd(sectionList, stanza);
}
// Get the stanza name
String *stanza = NULL;
strLstAdd(sectionList, strNewFmt(CFGDEF_SECTION_GLOBAL ":%s", cfgCommandName(cfgCommand())));
strLstAdd(sectionList, strNew(CFGDEF_SECTION_GLOBAL));
if (parseOptionList[cfgOptStanza].found)
stanza = strLstGet(parseOptionList[cfgOptStanza].valueList, 0);
// Loop through sections to search for options
for (unsigned int sectionIdx = 0; sectionIdx < strLstSize(sectionList); sectionIdx++)
{
String *section = strLstGet(sectionList, sectionIdx);
StringList *keyList = iniSectionKeyList(config, section);
KeyValue *optionFound = kvNew();
// Build list of sections to search for options
StringList *sectionList = strLstNew();
if (stanza != NULL)
// Loop through keys to search for options
for (unsigned int keyIdx = 0; keyIdx < strLstSize(keyList); keyIdx++)
{
strLstAdd(sectionList, strNewFmt("%s:%s", strPtr(stanza), cfgCommandName(cfgCommand())));
strLstAdd(sectionList, stanza);
}
String *key = strLstGet(keyList, keyIdx);
strLstAdd(sectionList, strNewFmt(CFGDEF_SECTION_GLOBAL ":%s", cfgCommandName(cfgCommand())));
strLstAdd(sectionList, strNew(CFGDEF_SECTION_GLOBAL));
// Find the optionName in the main list
unsigned int optionIdx = optionFind(key);
// Loop through sections to search for options
for (unsigned int sectionIdx = 0; sectionIdx < strLstSize(sectionList); sectionIdx++)
{
String *section = strLstGet(sectionList, sectionIdx);
StringList *keyList = iniSectionKeyList(config, section);
KeyValue *optionFound = kvNew();
// Loop through keys to search for options
for (unsigned int keyIdx = 0; keyIdx < strLstSize(keyList); keyIdx++)
// Warn if the option not found
if (optionList[optionIdx].name == NULL)
{
String *key = strLstGet(keyList, keyIdx);
LOG_WARN("configuration file contains invalid option '%s'", strPtr(key));
continue;
}
// Warn if negate option found in config
else if (optionList[optionIdx].val & PARSE_NEGATE_FLAG)
{
LOG_WARN("configuration file contains negate option '%s'", strPtr(key));
continue;
}
// Warn if reset option found in config
else if (optionList[optionIdx].val & PARSE_RESET_FLAG)
{
LOG_WARN("configuration file contains reset option '%s'", strPtr(key));
continue;
}
// Find the optionName in the main list
unsigned int optionIdx = optionFind(key);
ConfigOption optionId = optionList[optionIdx].val & PARSE_OPTION_MASK;
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Warn if the option not found
if (optionList[optionIdx].name == NULL)
{
LOG_WARN("'%s' contains invalid option '%s'", strPtr(configFile), strPtr(key));
continue;
}
// Warn if negate option found in config
else if (optionList[optionIdx].val & PARSE_NEGATE_FLAG)
{
LOG_WARN("'%s' contains negate option '%s'", strPtr(configFile), strPtr(key));
continue;
}
// Warn if reset option found in config
else if (optionList[optionIdx].val & PARSE_RESET_FLAG)
{
LOG_WARN("'%s' contains reset option '%s'", strPtr(configFile), strPtr(key));
continue;
}
/// Warn if this option should be command-line only
if (cfgDefOptionSection(optionDefId) == cfgDefSectionCommandLine)
{
LOG_WARN("configuration file contains command-line only option '%s'", strPtr(key));
continue;
}
ConfigOption optionId = optionList[optionIdx].val & PARSE_OPTION_MASK;
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Make sure this option does not appear in the same section with an alternate name
Variant *optionFoundKey = varNewInt(optionId);
const Variant *optionFoundName = kvGet(optionFound, optionFoundKey);
/// Warn if this option should be command-line only
if (cfgDefOptionSection(optionDefId) == cfgDefSectionCommandLine)
{
LOG_WARN("'%s' contains command-line only option '%s'", strPtr(configFile), strPtr(key));
continue;
}
if (optionFoundName != NULL)
{
THROW(
OptionInvalidError, "configuration file contains duplicate options ('%s', '%s') in section '[%s]'",
strPtr(key), strPtr(varStr(optionFoundName)), strPtr(section));
}
else
kvPut(optionFound, optionFoundKey, varNewStr(key));
// Make sure this option does not appear in the same section with an alternate name
Variant *optionFoundKey = varNewInt(optionId);
const Variant *optionFoundName = kvGet(optionFound, optionFoundKey);
if (optionFoundName != NULL)
{
THROW(
OptionInvalidError, "'%s' contains duplicate options ('%s', '%s') in section '[%s]'",
strPtr(configFile), strPtr(key), strPtr(varStr(optionFoundName)), strPtr(section));
}
else
kvPut(optionFound, optionFoundKey, varNewStr(key));
// Continue if the option is not valid for this command
if (!cfgDefOptionValid(commandDefId, optionDefId))
{
// Warn if it is in a command section
if (sectionIdx % 2 == 0)
{
LOG_WARN(
"'%s' contains option '%s' invalid for section '%s'", strPtr(configFile), strPtr(key),
strPtr(section));
continue;
}
continue;
}
// Continue if stanza option is in a global section
if (cfgDefOptionSection(optionDefId) == cfgDefSectionStanza &&
strBeginsWithZ(section, CFGDEF_SECTION_GLOBAL))
// Continue if the option is not valid for this command
if (!cfgDefOptionValid(commandDefId, optionDefId))
{
// Warn if it is in a command section
if (sectionIdx % 2 == 0)
{
LOG_WARN(
"'%s' contains stanza-only option '%s' in global section '%s'", strPtr(configFile), strPtr(key),
"configuration file contains option '%s' invalid for section '%s'", strPtr(key),
strPtr(section));
continue;
}
// Continue if this option has already been found in another section
if (parseOptionList[optionId].found)
continue;
// Get the option value
const Variant *value = iniGetDefault(config, section, key, NULL);
if (varType(value) == varTypeString && strSize(varStr(value)) == 0)
THROW(OptionInvalidValueError, "section '%s', key '%s' must have a value", strPtr(section),
strPtr(key));
parseOptionList[optionId].found = true;
parseOptionList[optionId].source = cfgSourceConfig;
// Convert boolean to string
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
{
if (strcasecmp(strPtr(varStr(value)), "n") == 0)
parseOptionList[optionId].negate = true;
else if (strcasecmp(strPtr(varStr(value)), "y") != 0)
THROW(OptionInvalidError, "boolean option '%s' must be 'y' or 'n'", strPtr(key));
}
// Else add the string value
else if (varType(value) == varTypeString)
{
parseOptionList[optionId].valueList = strLstNew();
strLstAdd(parseOptionList[optionId].valueList, varStr(value));
}
// Else add the string list
else
parseOptionList[optionId].valueList = strLstNewVarLst(varVarLst(value));
continue;
}
// Continue if stanza option is in a global section
if (cfgDefOptionSection(optionDefId) == cfgDefSectionStanza &&
strBeginsWithZ(section, CFGDEF_SECTION_GLOBAL))
{
LOG_WARN(
"configuration file contains stanza-only option '%s' in global section '%s'", strPtr(key),
strPtr(section));
continue;
}
// Continue if this option has already been found in another section
if (parseOptionList[optionId].found)
continue;
// Get the option value
const Variant *value = iniGetDefault(config, section, key, NULL);
if (varType(value) == varTypeString && strSize(varStr(value)) == 0)
THROW(OptionInvalidValueError, "section '%s', key '%s' must have a value", strPtr(section),
strPtr(key));
parseOptionList[optionId].found = true;
parseOptionList[optionId].source = cfgSourceConfig;
// Convert boolean to string
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
{
if (strcasecmp(strPtr(varStr(value)), "n") == 0)
parseOptionList[optionId].negate = true;
else if (strcasecmp(strPtr(varStr(value)), "y") != 0)
THROW(OptionInvalidError, "boolean option '%s' must be 'y' or 'n'", strPtr(key));
}
// Else add the string value
else if (varType(value) == varTypeString)
{
parseOptionList[optionId].valueList = strLstNew();
strLstAdd(parseOptionList[optionId].valueList, varStr(value));
}
// Else add the string list
else
parseOptionList[optionId].valueList = strLstNewVarLst(varVarLst(value));
}
}
}

View File

@ -367,7 +367,7 @@ module:
# ----------------------------------------------------------------------------------------------------------------------------
- name: parse
total: 2
total: 3
c: true
coverage:

View File

@ -4731,7 +4731,7 @@ info bogus stanza - bogus stanza (db-master host)
diff backup - config file warning on local (db-master host)
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --log-level-console=info 2>&1 --type=diff --stanza=db backup
------------------------------------------------------------------------------------------------------------------------------------
WARN: '[TEST_PATH]/db-master/pgbackrest.conf' contains invalid option 'bogus'
WARN: configuration file contains invalid option 'bogus'
P00 INFO: backup command begin [BACKREST-VERSION]: --compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=info --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --no-online --pg1-path=[TEST_PATH]/db-master/db/base-2/base --protocol-timeout=60 --repo1-hardlink --repo1-path=[TEST_PATH]/db-master/repo --stanza=db --start-fast --type=diff
P00 WARN: option repo1-retention-full is not set, the repository may run out of space
HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the maximum.

View File

@ -92,13 +92,37 @@ sub run
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PATH, 2), '/db2');
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PORT, 2), '2222');
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CMD, 2), 'pgbackrest2');
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG, 2), '/config2');
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_INCLUDE_PATH, 2), '/config-include2');
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_HOST_CONFIG_PATH, 2), '/config-path2');
$self->configTestLoad(CFGCMD_BACKUP);
$self->testResult(
sub {pgBackRest::Protocol::Helper::protocolParam(cfgCommandName(CFGCMD_BACKUP), CFGOPTVAL_REMOTE_TYPE_DB, 2)},
'(pg-host-2, postgres, [undef], pgbackrest2 --buffer-size=4194304 --command=backup --compress-level=6' .
' --compress-level-network=3 --pg1-path=/db2 --pg1-port=2222 --protocol-timeout=1830 --stanza=db --type=db remote)',
' --compress-level-network=3 --config=/config2 --config-include-path=/config-include2 --config-path=/config-path2' .
' --pg1-path=/db2 --pg1-port=2222 --protocol-timeout=1830 --stanza=db --type=db remote)',
'more than one backup db host');
# --------------------------------------------------------------------------------------------------------------------------
$self->configTestClear();
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
$self->optionTestSet(cfgOptionIdFromIndex(CFGOPT_PG_PATH, 1), '/db1');
$self->optionTestSet(CFGOPT_REPO_HOST, 'repo-host');
$self->optionTestSet(CFGOPT_REPO_PATH, '/repo');
$self->optionTestSet(CFGOPT_REPO_HOST_CMD, 'pgbackrest-repo');
$self->optionTestSet(CFGOPT_REPO_HOST_CONFIG, '/config-repo');
$self->optionTestSet(CFGOPT_REPO_HOST_CONFIG_INCLUDE_PATH, '/config-include-repo');
$self->optionTestSet(CFGOPT_REPO_HOST_CONFIG_PATH, '/config-path-repo');
$self->configTestLoad(CFGCMD_RESTORE);
$self->testResult(
sub {pgBackRest::Protocol::Helper::protocolParam(cfgCommandName(CFGCMD_RESTORE), CFGOPTVAL_REMOTE_TYPE_BACKUP)},
'(repo-host, pgbackrest, [undef], pgbackrest-repo --buffer-size=4194304 --command=restore --compress-level=6' .
' --compress-level-network=3 --config=/config-repo --config-include-path=/config-include-repo' .
' --config-path=/config-path-repo --pg1-path=/db1 --protocol-timeout=1830 --repo1-path=/repo --stanza=db' .
' --type=backup remote)',
'config params to repo host');
}
################################################################################################################################

View File

@ -28,6 +28,430 @@ Test run
void
testRun()
{
// config and config-include-path options
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("cfgFileLoad()"))
{
StringList *argList = NULL;
String *configFile = strNewFmt("%s/test.config", testPath());
String *configIncludePath = strNewFmt("%s/conf.d", testPath());
mkdir(strPtr(configIncludePath), 0750);
// Check old config file constant
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(PGBACKREST_CONFIG_ORIG_PATH_FILE, "/etc/pgbackrest.conf", "check old config path");
// Confirm same behavior with multiple config include files
//--------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew(TEST_BACKREST_EXE));
strLstAdd(argList, strNew("--stanza=db"));
strLstAdd(argList, strNewFmt("--config=%s", strPtr(configFile)));
strLstAdd(argList, strNewFmt("--config-include-path=%s", strPtr(configIncludePath)));
strLstAdd(argList, strNew("--no-online"));
strLstAdd(argList, strNew("--reset-pg1-host"));
strLstAdd(argList, strNew("--reset-backup-standby"));
strLstAdd(argList, strNew(TEST_COMMAND_BACKUP));
storagePut(
storageOpenWriteNP(storageLocalWrite(), configFile), bufNewStr(
strNew(
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n")));
storagePut(
storageOpenWriteNP(
storageLocalWrite(), strNewFmt("%s/global-backup.conf", strPtr(configIncludePath))), bufNewStr(
strNew(
"[global:backup]\n"
"repo1-hardlink=y\n"
"bogus=bogus\n"
"no-compress=y\n"
"reset-compress=y\n"
"archive-copy=y\n"
"online=y\n"
"pg1-path=/not/path/to/db\n"
"backup-standby=y\n"
"buffer-size=65536\n")));
storagePut(
storageOpenWriteNP(storageLocalWrite(), strNewFmt("%s/db-backup.conf", strPtr(configIncludePath))), bufNewStr(
strNew(
"[db:backup]\n"
"compress=n\n"
"recovery-option=a=b\n")));
storagePut(
storageOpenWriteNP(storageLocalWrite(), strNewFmt("%s/stanza.db.conf", strPtr(configIncludePath))), bufNewStr(
strNew(
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n")));
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_BACKUP " command with config-include");
testLogErrResult(
strPtr(
strNew(
"WARN: configuration file contains option 'recovery-option' invalid for section 'db:backup'\n"
"WARN: configuration file contains invalid option 'bogus'\n"
"WARN: configuration file contains negate option 'no-compress'\n"
"WARN: configuration file contains reset option 'reset-compress'\n"
"WARN: configuration file contains command-line only option 'online'\n"
"WARN: configuration file contains stanza-only option 'pg1-path' in global section 'global:backup'")));
TEST_RESULT_BOOL(cfgOptionTest(cfgOptPgHost), false, " pg1-host is not set (command line reset override)");
TEST_RESULT_STR(strPtr(cfgOptionStr(cfgOptPgPath)), "/path/to/db", " pg1-path is set");
TEST_RESULT_INT(cfgOptionSource(cfgOptPgPath), cfgSourceConfig, " pg1-path is source config");
TEST_RESULT_BOOL(cfgOptionBool(cfgOptCompress), false, " compress not is set");
TEST_RESULT_INT(cfgOptionSource(cfgOptCompress), cfgSourceConfig, " compress is source config");
TEST_RESULT_BOOL(cfgOptionTest(cfgOptArchiveCheck), false, " archive-check is not set");
TEST_RESULT_BOOL(cfgOptionTest(cfgOptArchiveCopy), false, " archive-copy is not set");
TEST_RESULT_BOOL(cfgOptionBool(cfgOptRepoHardlink), true, " repo-hardlink is set");
TEST_RESULT_INT(cfgOptionSource(cfgOptRepoHardlink), cfgSourceConfig, " repo-hardlink is source config");
TEST_RESULT_INT(cfgOptionInt(cfgOptCompressLevel), 3, " compress-level is set");
TEST_RESULT_INT(cfgOptionSource(cfgOptCompressLevel), cfgSourceConfig, " compress-level is source config");
TEST_RESULT_BOOL(cfgOptionBool(cfgOptBackupStandby), false, " backup-standby not is set");
TEST_RESULT_INT(cfgOptionSource(cfgOptBackupStandby), cfgSourceDefault, " backup-standby is source default");
TEST_RESULT_BOOL(cfgOptionInt64(cfgOptBufferSize), 65536, " buffer-size is set");
TEST_RESULT_INT(cfgOptionSource(cfgOptBufferSize), cfgSourceConfig, " backup-standby is source config");
// Rename conf files - ensure read of conf extension only is attempted
//--------------------------------------------------------------------------------------------------------------------------
rename(strPtr(strNewFmt("%s/db-backup.conf", strPtr(configIncludePath))),
strPtr(strNewFmt("%s/db-backup.conf.save", strPtr(configIncludePath))));
rename(strPtr(strNewFmt("%s/global-backup.conf", strPtr(configIncludePath))),
strPtr(strNewFmt("%s/global-backup.confsave", strPtr(configIncludePath))));
// Set up defaults
String *backupCmdDefConfigValue = strNew(cfgDefOptionDefault(
cfgCommandDefIdFromId(cfgCommandId(TEST_COMMAND_BACKUP)), cfgOptionDefIdFromId(cfgOptConfig)));
String *backupCmdDefConfigInclPathValue = strNew(cfgDefOptionDefault(
cfgCommandDefIdFromId(cfgCommandId(TEST_COMMAND_BACKUP)), cfgOptionDefIdFromId(cfgOptConfigIncludePath)));
String *oldConfigDefault = strNewFmt("%s%s", testPath(), PGBACKREST_CONFIG_ORIG_PATH_FILE);
// Create the option structure and initialize with 0
ParseOption parseOptionList[CFG_OPTION_TOTAL];
memset(&parseOptionList, 0, sizeof(parseOptionList));
parseOptionList[cfgOptConfig].found = true;
parseOptionList[cfgOptConfig].source = cfgSourceParam;
parseOptionList[cfgOptConfig].valueList = strLstAdd(strLstNew(), configFile);
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config-include-path with .conf files and non-.conf files");
// Pass invalid values
//--------------------------------------------------------------------------------------------------------------------------
// --config valid, --config-include-path invalid (does not exist)
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAddZ(strLstNew(), BOGUS_STR);
TEST_ERROR(
cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault), PathOpenError,
"unable to open path '/BOGUS' for read: [2] No such file or directory");
// --config-include-path valid, --config invalid (does not exist)
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
parseOptionList[cfgOptConfig].valueList = strLstAdd(strLstNew(), strNewFmt("%s/%s", testPath(), BOGUS_STR));
TEST_ERROR(
cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault), FileOpenError,
strPtr(strNewFmt("unable to open '%s/%s' for read: [2] No such file or directory", testPath(), BOGUS_STR)));
strLstFree(parseOptionList[cfgOptConfig].valueList);
strLstFree(parseOptionList[cfgOptConfigIncludePath].valueList);
// Neither config nor config-include-path passed as parameter (defaults but none exist)
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = false;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceDefault;
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
NULL,
"config default, config-include-path default but nothing to read");
// Config not passed as parameter - config does not exist. config-include-path passed as parameter - only include read
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config default and doesn't exist, config-include-path passed read");
// config and config-include-path are "default" with files existing. Config file exists in both currrent default and old
// default location - old location ignored.
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = false;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceDefault;
mkdir(strPtr(strPath(oldConfigDefault)), 0750);
storagePut(
storageOpenWriteNP(
storageLocalWrite(), oldConfigDefault), bufNewStr(
strNew(
"[global:backup]\n"
"buffer-size=65536\n")));
// Pass actual location of config files as "default" - not setting valueList above, so these are the only possible values
// to choose.
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, configFile, configIncludePath,
oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config and config-include-path default, files appended, original config not read");
// Config not passed as parameter - config does not exist in new default but does exist in old default. config-include-path
// passed as parameter - both include and old default read
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global:backup]\n"
"buffer-size=65536\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config old default read, config-include-path passed read");
// --no-config and config-include-path passed as parameter (files read only from include path and not current or old config)
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = true;
parseOptionList[cfgOptConfig].source = cfgSourceParam;
parseOptionList[cfgOptConfig].negate = true;
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"--no-config, only config-include-path read");
// --no-config and config-include-path default exists with files - nothing to read
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = true;
parseOptionList[cfgOptConfig].source = cfgSourceParam;
parseOptionList[cfgOptConfig].negate = true;
parseOptionList[cfgOptConfigIncludePath].found = false;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceDefault;
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
configIncludePath, oldConfigDefault)),
NULL,
"--no-config, config-include-path default, nothing read");
// config passed and config-include-path default exists with files - only config read
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = true;
parseOptionList[cfgOptConfig].source = cfgSourceParam;
parseOptionList[cfgOptConfig].negate = false;
parseOptionList[cfgOptConfig].valueList = strLstAdd(strLstNew(), configFile);
parseOptionList[cfgOptConfigIncludePath].found = false;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceDefault;
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
configIncludePath, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n",
"config param specified, config-include-path default, only config read");
// config new default and config-include-path passed - both exists with files. config-include-path & new config default read
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, configFile,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config new default exists with files, config-include-path passed, defualt config and config-include-path read");
// config and config-include-path are "default".
//--------------------------------------------------------------------------------------------------------------------------
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = false;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceDefault;
// File exists in old default config location but not in current default.
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
configIncludePath, oldConfigDefault)),
"[global:backup]\n"
"buffer-size=65536\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config-path override - config-include-path files and old config default read since no config in current path");
// Pass --config-path
parseOptionList[cfgOptConfigPath].found = true;
parseOptionList[cfgOptConfigPath].source = cfgSourceParam;
parseOptionList[cfgOptConfigPath].valueList = strLstAddZ(strLstNew(), testPath());
// Override default paths for config and config-include-path - but no pgbackrest.conf file in override path only in old
// default so ignored
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config-path override: config-include-path files read but config not read - does not exist");
// Pass --config
parseOptionList[cfgOptConfig].found = true;
parseOptionList[cfgOptConfig].source = cfgSourceParam;
parseOptionList[cfgOptConfig].negate = false;
parseOptionList[cfgOptConfig].valueList = strLstAdd(strLstNew(), configFile);
// Passing --config and --config-path - default config-include-path overwritten and config is required and is loaded and
// config-include-path files will attempt to be loaded but not required
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config-path changed config-include-path default - files exist, config and config includes read");
parseOptionList[cfgOptConfigPath].valueList = strLstAddZ(strLstNew(), BOGUS_STR);
// Passing --config and bogus --config-path - default config-include-path overwritten, config is required and is loaded and
// config-include-path files will attempt to be loaded but doesn't exist - no error since not required
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n",
"config-path changed config-include-path default but directory does not exist - only config read");
// Copy the configFile to pgbackrest.conf (default is /etc/pgbackrest/pgbackrest.conf and new value is testPath so copy the
// config file (that was not read in the previous test) to pgbackrest.conf so it will be read by the override
TEST_RESULT_INT(
system(
strPtr(strNewFmt("cp %s %s", strPtr(configFile), strPtr(strNewFmt("%s/pgbackrest.conf", testPath()))))), 0,
"copy configFile to pgbackrest.conf");
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfig].negate = false;
parseOptionList[cfgOptConfigIncludePath].found = false;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceDefault;
parseOptionList[cfgOptConfigPath].valueList = strLstAddZ(strLstNew(), testPath());
// Override default paths for config and config-include-path with --config-path
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n"
"\n"
"[db]\n"
"pg1-host=db\n"
"pg1-path=/path/to/db\n"
"recovery-option=c=d\n",
"config-path override: config-include-path and config file read");
// Clear config-path
parseOptionList[cfgOptConfigPath].found = false;
parseOptionList[cfgOptConfigPath].source = cfgSourceDefault;
// config default and config-include-path passed - but no config files in the include path - only in the default path
//--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_INT(system(strPtr(strNewFmt("sudo rm -rf %s/*", strPtr(configIncludePath)))), 0, "remove all include files");
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, configFile,
backupCmdDefConfigInclPathValue, oldConfigDefault)),
"[global]\n"
"compress-level=3\n"
"spool-path=/path/to/spool\n",
"config default exists with files but config-include-path path passed is empty - only config read");
// config default and config-include-path passed - only empty file in the include path and nothing in either config defaults
//--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_INT(system(strPtr(strNewFmt("touch %s", strPtr(strNewFmt("%s/empty.conf", strPtr(configIncludePath)))))), 0,
"add empty conf file to include directory");
parseOptionList[cfgOptConfig].found = false;
parseOptionList[cfgOptConfig].source = cfgSourceDefault;
parseOptionList[cfgOptConfigIncludePath].found = true;
parseOptionList[cfgOptConfigIncludePath].source = cfgSourceParam;
parseOptionList[cfgOptConfigIncludePath].valueList = strLstAdd(strLstNew(), configIncludePath);
TEST_RESULT_STR(strPtr(cfgFileLoad(parseOptionList, backupCmdDefConfigValue,
backupCmdDefConfigInclPathValue, backupCmdDefConfigValue)),
NULL,
"config default does not exist, config-include-path passed but only empty conf file - nothing read");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("configParse()"))
{
@ -119,7 +543,7 @@ testRun()
strLstAdd(argList, strNew("--online"));
TEST_ERROR(configParse(strLstSize(argList), strLstPtr(argList)), CommandRequiredError, "no command found");
// Local and remove commands should not modify log levels during parsing
// Local and remote commands should not modify log levels during parsing
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAdd(argList, strNew("pgbackrest"));
@ -181,7 +605,7 @@ testRun()
configParse(strLstSize(argList), strLstPtr(argList)), OptionInvalidError,
"option 'repo1-s3-key' is not allowed on the command-line\n"
"HINT: this option could expose secrets in the process list.\n"
"HINT: specify the option in '/etc/pgbackrest.conf' instead.");
"HINT: specify the option in '/etc/pgbackrest/pgbackrest.conf' instead.");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
@ -362,7 +786,7 @@ testRun()
TEST_ERROR(configParse(
strLstSize(argList), strLstPtr(argList)), OptionInvalidError,
strPtr(strNewFmt("'%s' contains duplicate options ('db-path', 'pg1-path') in section '[db]'", strPtr(configFile))));
strPtr(strNew("configuration file contains duplicate options ('db-path', 'pg1-path') in section '[db]'")));
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
@ -502,15 +926,13 @@ testRun()
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), TEST_COMMAND_BACKUP " command");
testLogErrResult(
strPtr(
strNewFmt(
"WARN: '%s' contains option 'recovery-option' invalid for section 'db:backup'\n"
"WARN: '%s' contains invalid option 'bogus'\n"
"WARN: '%s' contains negate option 'no-compress'\n"
"WARN: '%s' contains reset option 'reset-compress'\n"
"WARN: '%s' contains command-line only option 'online'\n"
"WARN: '%s' contains stanza-only option 'pg1-path' in global section 'global:backup'",
strPtr(configFile), strPtr(configFile), strPtr(configFile), strPtr(configFile), strPtr(configFile),
strPtr(configFile))));
strNew(
"WARN: configuration file contains option 'recovery-option' invalid for section 'db:backup'\n"
"WARN: configuration file contains invalid option 'bogus'\n"
"WARN: configuration file contains negate option 'no-compress'\n"
"WARN: configuration file contains reset option 'reset-compress'\n"
"WARN: configuration file contains command-line only option 'online'\n"
"WARN: configuration file contains stanza-only option 'pg1-path' in global section 'global:backup'")));
TEST_RESULT_BOOL(cfgOptionTest(cfgOptPgHost), false, " pg1-host is not set (command line reset override)");
TEST_RESULT_STR(strPtr(cfgOptionStr(cfgOptPgPath)), "/path/to/db", " pg1-path is set");

View File

@ -91,9 +91,12 @@ testRun()
TEST_RESULT_VOID(configParse(strLstSize(argList), strLstPtr(argList)), "help from help command");
TEST_RESULT_STR(strPtr(helpRender()), generalHelp, " check text");
// This test is broken up into multiple strings because C99 does not require compilers to support const strings > 4095 bytes
// -------------------------------------------------------------------------------------------------------------------------
const char *commandHelp = strPtr(strNewFmt(
"%s - 'archive-push' command help\n"
"%s%s%s",
helpVersion,
" - 'archive-push' command help\n"
"\n"
"Push a WAL segment to the archive.\n"
"\n"
@ -102,74 +105,85 @@ testRun()
"\n"
"Command Options:\n"
"\n"
" --archive-async archive WAL segments asynchronously [default=n]\n"
" --archive-push-queue-max limit size (in bytes) of the PostgreSQL archive\n"
" queue\n"
" --archive-timeout archive timeout [default=60]\n"
" --archive-async archive WAL segments asynchronously\n"
" [default=n]\n"
" --archive-push-queue-max limit size (in bytes) of the PostgreSQL\n"
" archive queue\n"
" --archive-timeout archive timeout [default=60]\n"
"\n"
"General Options:\n"
"\n"
" --buffer-size buffer size for file operations [current=32768,\n"
" default=4194304]\n"
" --cmd-ssh path to ssh client executable [default=ssh]\n"
" --compress use gzip file compression [default=y]\n"
" --compress-level compression level for stored files [default=6]\n"
" --compress-level-network compression level for network transfer when\n"
" compress=n [default=3]\n"
" --config pgBackRest configuration file\n"
" [default=/etc/pgbackrest.conf]\n"
" --db-timeout database query timeout [default=1800]\n"
" --lock-path path where lock files are stored\n"
" [default=/tmp/pgbackrest]\n"
" --neutral-umask use a neutral umask [default=y]\n"
" --process-max max processes to use for compress/transfer\n"
" [default=1]\n"
" --protocol-timeout protocol timeout [default=1830]\n"
" --spool-path path where transient data is stored\n"
" [default=/var/spool/pgbackrest]\n"
" --stanza defines the stanza\n"
" --buffer-size buffer size for file operations\n"
" [current=32768, default=4194304]\n"
" --cmd-ssh path to ssh client executable [default=ssh]\n"
" --compress use gzip file compression [default=y]\n"
" --compress-level compression level for stored files\n"
" [default=6]\n"
" --compress-level-network compression level for network transfer when\n"
" compress=n [default=3]\n"
" --config pgBackRest configuration file\n"
" [default=/etc/pgbackrest/pgbackrest.conf]\n"
" --config-include-path path to additional pgBackRest configuration\n"
" files [default=/etc/pgbackrest/conf.d]\n"
" --config-path base path of pgBackRest configuration files\n"
" [default=/etc/pgbackrest]\n"
" --db-timeout database query timeout [default=1800]\n"
" --lock-path path where lock files are stored\n"
" [default=/tmp/pgbackrest]\n"
" --neutral-umask use a neutral umask [default=y]\n"
" --process-max max processes to use for compress/transfer\n"
" [default=1]\n"
" --protocol-timeout protocol timeout [default=1830]\n"
" --spool-path path where transient data is stored\n"
" [default=/var/spool/pgbackrest]\n"
" --stanza defines the stanza\n"
"\n"
"Log Options:\n"
"\n"
" --log-level-console level for console logging [default=warn]\n"
" --log-level-file level for file logging [default=info]\n"
" --log-level-stderr level for stderr logging [default=warn]\n"
" --log-path path where log files are stored\n"
" [default=/var/log/pgbackrest]\n"
" --log-timestamp enable timestamp in logging [default=y]\n"
" --log-level-console level for console logging [default=warn]\n"
" --log-level-file level for file logging [default=info]\n"
" --log-level-stderr level for stderr logging [default=warn]\n"
" --log-path path where log files are stored\n"
" [default=/var/log/pgbackrest]\n"
" --log-timestamp enable timestamp in logging [default=y]\n"
"\n"
"Repository Options:\n"
"Repository Options:\n",
"\n"
" --repo-cipher-pass repository cipher passphrase\n"
" --repo-cipher-type cipher used to encrypt the repository [default=none]\n"
" --repo-host repository host when operating remotely via SSH\n"
" [current=backup.example.net]\n"
" --repo-host-cmd pgBackRest exe path on the repository host\n"
" --repo-host-config pgBackRest repository host configuration file\n"
" [default=/etc/pgbackrest.conf]\n"
" --repo-host-port repository host port when repo-host is set\n"
" --repo-host-user repository host user when repo-host is set\n"
" [default=pgbackrest]\n"
" --repo-path path where backups and archive are stored\n"
" [default=/var/lib/pgbackrest]\n"
" --repo-s3-bucket s3 repository bucket\n"
" --repo-s3-ca-file s3 SSL CA File\n"
" --repo-s3-ca-path s3 SSL CA Path\n"
" --repo-s3-endpoint s3 repository endpoint\n"
" --repo-s3-host s3 repository host\n"
" --repo-s3-key s3 repository access key\n"
" --repo-s3-key-secret s3 repository secret access key\n"
" --repo-s3-region s3 repository region\n"
" --repo-s3-verify-ssl verify S3 server certificate [default=y]\n"
" --repo-type type of storage used for the repository\n"
" [default=posix]\n"
" --repo-cipher-pass repository cipher passphrase\n"
" --repo-cipher-type cipher used to encrypt the repository\n"
" [default=none]\n"
" --repo-host repository host when operating remotely via\n"
" SSH [current=backup.example.net]\n"
" --repo-host-cmd pgBackRest exe path on the repository host\n"
" --repo-host-config pgBackRest repository host configuration\n"
" file\n"
" [default=/etc/pgbackrest/pgbackrest.conf]\n"
" --repo-host-config-include-path pgBackRest repository host configuration\n"
" include path [default=/etc/pgbackrest/conf.d]\n"
" --repo-host-config-path pgBackRest repository host configuration\n"
" path [default=/etc/pgbackrest]\n"
" --repo-host-port repository host port when repo-host is set\n"
" --repo-host-user repository host user when repo-host is set\n"
" [default=pgbackrest]\n"
" --repo-path path where backups and archive are stored\n"
" [default=/var/lib/pgbackrest]\n"
" --repo-s3-bucket s3 repository bucket\n"
" --repo-s3-ca-file s3 SSL CA File\n"
" --repo-s3-ca-path s3 SSL CA Path\n"
" --repo-s3-endpoint s3 repository endpoint\n"
" --repo-s3-host s3 repository host\n"
" --repo-s3-key s3 repository access key\n"
" --repo-s3-key-secret s3 repository secret access key\n"
" --repo-s3-region s3 repository region\n"
" --repo-s3-verify-ssl verify S3 server certificate [default=y]\n"
" --repo-type type of storage used for the repository\n"
" [default=posix]\n"
"\n"
"Stanza Options:\n"
"\n"
" --pg-path postgreSQL data directory\n"
" --pg-path postgreSQL data directory\n"
"\n"
"Use 'pgbackrest help archive-push [option]' for more information.\n",
helpVersion));
"Use 'pgbackrest help archive-push [option]' for more information.\n"));
argList = strLstNew();
strLstAddZ(argList, "/path/to/pgbackrest");