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

Add cfgExecParam() to generate parameters for executing commands.

Parameters for the local/remote commands are based on parameters that are passed to the current command.

Generate parameters for the new command based on the intersection of parameters between the current command and the command to be executed.
This commit is contained in:
David Steele 2019-01-17 22:29:19 +02:00
parent ecd56105e6
commit 06d41b4dc0
5 changed files with 208 additions and 0 deletions

View File

@ -33,6 +33,10 @@
<p>Add <code>IoHandleRead</code> and <code>IoHandleWrite</code> objects.</p>
</release-item>
<release-item>
<p>Add <code>cfgExecParam()</code> to generate parameters for executing commands.</p>
</release-item>
<release-item>
<p>Ignore <id>SIGPIPE</id> signals and check <id>EPIPE</id> result instead.</p>
</release-item>

113
src/config/exec.c Normal file
View File

@ -0,0 +1,113 @@
/***********************************************************************************************************************************
Exec Configuration
***********************************************************************************************************************************/
#include <string.h>
#include "common/debug.h"
#include "common/log.h"
#include "config/exec.h"
/***********************************************************************************************************************************
Load log settings
***********************************************************************************************************************************/
StringList *
cfgExecParam(ConfigCommand commandId, const KeyValue *optionReplace)
{
FUNCTION_DEBUG_BEGIN(logLevelTrace);
FUNCTION_DEBUG_PARAM(ENUM, commandId);
FUNCTION_DEBUG_PARAM(KEY_VALUE, optionReplace);
FUNCTION_DEBUG_END();
StringList *result = NULL;
MEM_CONTEXT_TEMP_BEGIN()
{
// Loop though options and add the ones that apply to the specified command
result = strLstNew();
ConfigDefineCommand commandDefId = cfgCommandDefIdFromId(commandId);
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
{
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Skip the option if it is not valid for the specified command or if is secure
if (!cfgDefOptionValid(commandDefId, optionDefId) || cfgDefOptionSecure(optionDefId))
continue;
// First check for a replacement
const Variant *value = NULL;
if (optionReplace != NULL)
value = kvGet(optionReplace, varNewStr(strNew(cfgOptionName(optionId))));
// If no replacement then see if this option is valid for the current command and is not default
if (value == NULL && cfgOptionValid(optionId))
{
if (cfgOptionNegate(optionId))
value = varNewBool(false);
else if (cfgOptionSource(optionId) != cfgSourceDefault)
value = cfgOption(optionId);
}
// Format the value if found
if (value != NULL)
{
if (varType(value) == varTypeBool)
{
strLstAdd(result, strNewFmt("--%s%s", varBool(value) ? "" : "no-", cfgOptionName(optionId)));
}
else
{
StringList *valueList = NULL;
if (varType(value) == varTypeKeyValue)
{
valueList = strLstNew();
const KeyValue *optionKv = varKv(value);
const VariantList *keyList = kvKeyList(optionKv);
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
{
strLstAdd(
valueList,
strNewFmt(
"%s=%s", strPtr(varStr(varLstGet(keyList, keyIdx))),
strPtr(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx))))));
}
}
else if (varType(value) == varTypeVariantList)
{
valueList = strLstNewVarLst(varVarLst(value));
}
// Else only one value
else
{
valueList = strLstNew();
strLstAdd(valueList, varStrForce(value));
}
// Output options and values
for (unsigned int valueListIdx = 0; valueListIdx < strLstSize(valueList); valueListIdx++)
{
const String *value = strLstGet(valueList, valueListIdx);
if (strchr(strPtr(value), ' ') != NULL)
value = strNewFmt("\"%s\"", strPtr(value));
strLstAdd(result, strNewFmt("--%s=%s", cfgOptionName(optionId), strPtr(value)));
}
}
}
}
// Add the requested command
strLstAddZ(result, cfgCommandName(commandId));
// Move list to the calling context
strLstMove(result, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
FUNCTION_DEBUG_RESULT(STRING_LIST, result);
}

15
src/config/exec.h Normal file
View File

@ -0,0 +1,15 @@
/***********************************************************************************************************************************
Exec Configuration
***********************************************************************************************************************************/
#ifndef CONFIG_EXEC_H
#define CONFIG_EXEC_H
#include "common/type/stringList.h"
#include "config/config.h"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
StringList *cfgExecParam(ConfigCommand commandId, const KeyValue *optionReplace);
#endif

View File

@ -420,6 +420,13 @@ unit:
coverage:
config/load: full
# ----------------------------------------------------------------------------------------------------------------------------
- name: exec
total: 1
coverage:
config/exec: full
# ********************************************************************************************************************************
- name: storage

View File

@ -0,0 +1,69 @@
/***********************************************************************************************************************************
Test Exec Configuration
***********************************************************************************************************************************/
#include "common/harnessConfig.h"
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
FUNCTION_HARNESS_VOID();
// *****************************************************************************************************************************
if (testBegin("cfgExecParam()"))
{
StringList *argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAddZ(argList, "--stanza=test1");
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
strLstAdd(argList, strNewFmt("--pg1-path=%s/db path", testPath()));
strLstAddZ(argList, "--log-subprocess");
strLstAddZ(argList, "--no-config");
strLstAddZ(argList, "--reset-neutral-umask");
strLstAddZ(argList, "--repo-cipher-type=aes-256-cbc");
strLstAddZ(argList, "archive-get");
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
// Set repo1-cipher-pass to make sure it is not passed on the command line
cfgOptionValidSet(cfgOptRepoCipherPass, true);
cfgOptionSet(cfgOptRepoCipherPass, cfgSourceConfig, varNewStrZ("1234"));
TEST_RESULT_STR(
strPtr(strLstJoin(cfgExecParam(cfgCmdLocal, NULL), "|")),
strPtr(
strNewFmt(
"--no-config|--log-subprocess|--pg1-path=\"%s/db path\"|--repo1-cipher-type=aes-256-cbc|--repo1-path=%s/repo"
"|--stanza=test1|local",
testPath(), testPath())),
"exec archive-get -> local");
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAddZ(argList, "--stanza=test1");
strLstAdd(argList, strNewFmt("--repo1-path=%s/repo", testPath()));
strLstAdd(argList, strNewFmt("--pg1-path=%s/db", testPath()));
strLstAddZ(argList, "--db-include=1");
strLstAddZ(argList, "--db-include=2");
strLstAddZ(argList, "--recovery-option=a=b");
strLstAddZ(argList, "--recovery-option=c=d");
strLstAddZ(argList, "restore");
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
KeyValue *optionReplace = kvNew();
kvPut(optionReplace, varNewStr(strNew("repo1-path")), varNewStr(strNew("/replace/path")));
TEST_RESULT_STR(
strPtr(strLstJoin(cfgExecParam(cfgCmdRestore, optionReplace), "|")),
strPtr(
strNewFmt(
"--db-include=1|--db-include=2|--pg1-path=%s/db|--recovery-option=a=b|--recovery-option=c=d"
"|--repo1-path=/replace/path|--stanza=test1|restore",
testPath())),
"exec restore -> restore");
}
FUNCTION_HARNESS_RESULT_VOID();
}