mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Add remote process shim.
Run the remote process inside a forked child process instead of exec'ing it. This allows coverage to accumulate in the remote process rather than needing to test the remote protocol functions directly, resulting in better end-to-end testing and less test duplication. Another advantage is that the pgbackrest binary does not need to be built for the test and the test does not need to run in a container.
This commit is contained in:
parent
441c000b5c
commit
58369c02df
@ -457,6 +457,7 @@ unit:
|
||||
protocol/helper:
|
||||
function:
|
||||
- protocolLocalExec
|
||||
- protocolRemoteExec
|
||||
containerReq: true
|
||||
binReq: true
|
||||
|
||||
|
@ -29,6 +29,11 @@ static struct
|
||||
bool localShim;
|
||||
const ProtocolServerHandler *localHandlerList;
|
||||
unsigned int localHandlerListSize;
|
||||
|
||||
// Remote process shim
|
||||
bool remoteShim;
|
||||
const ProtocolServerHandler *remoteHandlerList;
|
||||
unsigned int remoteHandlerListSize;
|
||||
} hrnProtocolStatic;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -127,3 +132,100 @@ hrnProtocolLocalShimUninstall(void)
|
||||
|
||||
FUNCTION_HARNESS_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Shim protocolRemoteExec() to provide coverage as detailed in the hrnProtocolRemoteShimInstall() documentation.
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
protocolRemoteExec(
|
||||
ProtocolHelperClient *helper, ProtocolStorageType protocolStorageType, unsigned int hostIdx, unsigned int processId)
|
||||
{
|
||||
// Call the shim when installed
|
||||
if (hrnProtocolStatic.remoteShim)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM_P(VOID, helper);
|
||||
FUNCTION_LOG_PARAM(STRING_ID, protocolStorageType);
|
||||
FUNCTION_LOG_PARAM(UINT, hostIdx);
|
||||
FUNCTION_LOG_PARAM(UINT, processId);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
// Create pipes to communicate with the subprocess. The names of the pipes are from the perspective of the parent process
|
||||
// since the child process will use them only briefly before exec'ing.
|
||||
int pipeRead[2];
|
||||
int pipeWrite[2];
|
||||
|
||||
THROW_ON_SYS_ERROR(pipe(pipeRead) == -1, KernelError, "unable to create read pipe");
|
||||
THROW_ON_SYS_ERROR(pipe(pipeWrite) == -1, KernelError, "unable to create write pipe");
|
||||
|
||||
// Exec command in the child process
|
||||
if (forkSafe() == 0)
|
||||
{
|
||||
// Load configuration
|
||||
StringList *const paramList = protocolRemoteParam(protocolStorageType, hostIdx);
|
||||
strLstInsert(paramList, 0, cfgExe());
|
||||
harnessCfgLoadRaw(strLstSize(paramList), strLstPtr(paramList));
|
||||
|
||||
// Change log process id to aid in debugging
|
||||
hrnLogProcessIdSet(processId);
|
||||
|
||||
// Run server with provided handlers
|
||||
String *name = strNewFmt(PROTOCOL_SERVICE_REMOTE "-shim-%u", processId);
|
||||
IoRead *read = ioFdReadNew(name, pipeWrite[0], 5000);
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioFdWriteNew(name, pipeRead[1], 5000);
|
||||
ioWriteOpen(write);
|
||||
|
||||
ProtocolServer *server = protocolServerNew(name, PROTOCOL_SERVICE_REMOTE_STR, read, write);
|
||||
protocolServerProcess(server, NULL, hrnProtocolStatic.remoteHandlerList, hrnProtocolStatic.remoteHandlerListSize);
|
||||
|
||||
// Exit when done
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Close the unused file descriptors
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
|
||||
// Create protocol object
|
||||
IoRead *read = ioFdReadNew(strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u shim protocol read", processId), pipeRead[0], 5000);
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioFdWriteNew(strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u shim protocol write", processId), pipeWrite[1], 5000);
|
||||
ioWriteOpen(write);
|
||||
|
||||
helper->client = protocolClientNew(
|
||||
strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u shim protocol", processId), PROTOCOL_SERVICE_REMOTE_STR, read, write);
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
// Else call the base function
|
||||
else
|
||||
protocolRemoteExec_SHIMMED(helper, protocolStorageType, hostIdx, processId);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnProtocolRemoteShimInstall(const ProtocolServerHandler *const handlerList, const unsigned int handlerListSize)
|
||||
{
|
||||
FUNCTION_HARNESS_BEGIN();
|
||||
FUNCTION_HARNESS_PARAM_P(VOID, handlerList);
|
||||
FUNCTION_HARNESS_PARAM(UINT, handlerListSize);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
hrnProtocolStatic.remoteShim = true;
|
||||
hrnProtocolStatic.remoteHandlerList = handlerList;
|
||||
hrnProtocolStatic.remoteHandlerListSize = handlerListSize;
|
||||
|
||||
FUNCTION_HARNESS_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnProtocolRemoteShimUninstall(void)
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
hrnProtocolStatic.remoteShim = false;
|
||||
|
||||
FUNCTION_HARNESS_RETURN_VOID();
|
||||
}
|
||||
|
@ -11,3 +11,8 @@ Functions
|
||||
// functions should be required. A side benefit is that the pgbackrest binary does not need to be built since there is no exec.
|
||||
void hrnProtocolLocalShimInstall(const ProtocolServerHandler *const handlerList, const unsigned int handlerListSize);
|
||||
void hrnProtocolLocalShimUninstall(void);
|
||||
|
||||
// Install/uninstall the shim that allows protocalRemoteGet() to start a remote in a forked process rather than being exec'd via
|
||||
// SSH. The benefits are the same as hrnProtocolLocalShimInstall().
|
||||
void hrnProtocolRemoteShimInstall(const ProtocolServerHandler *const handlerList, const unsigned int handlerListSize);
|
||||
void hrnProtocolRemoteShimUninstall(void);
|
||||
|
Loading…
Reference in New Issue
Block a user