mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-25 16:16:29 +00:00
Enable a conninfo string to be passed to repmgr in the -d/--dbname parameter
This matches the behaviour of other PostgreSQL utilities such as pg_basebackup, psql et al. Note that unlike psql, but like pg_basebackup, repmgr does not accept a "left-over" parameter as a conninfo string; this could be added later. Parameters specified in the conninfo string will override any parameters supplied correcly (e.g. `-d "host=foo"` will override `-h bar`).
This commit is contained in:
169
repmgr.c
169
repmgr.c
@@ -124,6 +124,8 @@ static bool copy_file(const char *old_filename, const char *new_filename);
|
|||||||
static bool read_backup_label(const char *local_data_directory, struct BackupLabel *out_backup_label);
|
static bool read_backup_label(const char *local_data_directory, struct BackupLabel *out_backup_label);
|
||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
|
static PQconninfoOption *opts = NULL;
|
||||||
|
|
||||||
static const char *keywords[6];
|
static const char *keywords[6];
|
||||||
static const char *values[6];
|
static const char *values[6];
|
||||||
static bool config_file_required = true;
|
static bool config_file_required = true;
|
||||||
@@ -199,7 +201,9 @@ main(int argc, char **argv)
|
|||||||
bool check_upstream_config = false;
|
bool check_upstream_config = false;
|
||||||
bool config_file_parsed = false;
|
bool config_file_parsed = false;
|
||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
const char *env;
|
|
||||||
|
PQconninfoOption *defs = NULL;
|
||||||
|
PQconninfoOption *def;
|
||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
@@ -216,43 +220,39 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise some defaults */
|
/*
|
||||||
|
* Set default values for any parameters not provided
|
||||||
|
*/
|
||||||
|
|
||||||
/* set default user */
|
defs = PQconndefaults();
|
||||||
env = getenv("PGUSER");
|
for (def = defs; def->keyword; def++)
|
||||||
if (!env)
|
|
||||||
{
|
{
|
||||||
struct passwd *pw = NULL;
|
if (strcmp(def->keyword, "host") == 0 &&
|
||||||
pw = getpwuid(geteuid());
|
(def->val != NULL && def->val[0] != '\0'))
|
||||||
if (pw)
|
|
||||||
{
|
{
|
||||||
env = pw->pw_name;
|
strncpy(runtime_options.host, def->val, MAXLEN);
|
||||||
}
|
}
|
||||||
else
|
else if (strcmp(def->keyword, "hostaddr") == 0 &&
|
||||||
|
(def->val != NULL && def->val[0] != '\0'))
|
||||||
{
|
{
|
||||||
fprintf(stderr, _("could not get current user name: %s\n"), strerror(errno));
|
strncpy(runtime_options.host, def->val, MAXLEN);
|
||||||
exit(ERR_BAD_CONFIG);
|
}
|
||||||
|
else if (strcmp(def->keyword, "port") == 0 &&
|
||||||
|
(def->val != NULL && def->val[0] != '\0'))
|
||||||
|
{
|
||||||
|
strncpy(runtime_options.masterport, def->val, MAXLEN);
|
||||||
|
}
|
||||||
|
else if (strcmp(def->keyword, "dbname") == 0 &&
|
||||||
|
(def->val != NULL && def->val[0] != '\0'))
|
||||||
|
{
|
||||||
|
strncpy(runtime_options.dbname, def->val, MAXLEN);
|
||||||
|
}
|
||||||
|
else if (strcmp(def->keyword, "user") == 0 &&
|
||||||
|
(def->val != NULL && def->val[0] != '\0'))
|
||||||
|
{
|
||||||
|
strncpy(runtime_options.username, def->val, MAXLEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strncpy(runtime_options.username, env, MAXLEN);
|
|
||||||
|
|
||||||
/* set default database */
|
|
||||||
env = getenv("PGDATABASE");
|
|
||||||
if (!env)
|
|
||||||
{
|
|
||||||
env = runtime_options.username;
|
|
||||||
}
|
|
||||||
strncpy(runtime_options.dbname, env, MAXLEN);
|
|
||||||
|
|
||||||
/* set default port */
|
|
||||||
|
|
||||||
env = getenv("PGPORT");
|
|
||||||
if (!env)
|
|
||||||
{
|
|
||||||
env = DEF_PGPORT_STR;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(runtime_options.masterport, env, MAXLEN);
|
|
||||||
|
|
||||||
/* Prevent getopt_long() from printing an error message */
|
/* Prevent getopt_long() from printing an error message */
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
@@ -443,6 +443,57 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If -d/--dbname appears to be a conninfo string, validate by attempting
|
||||||
|
* to parse it (and if successful, store the result so we can check for the
|
||||||
|
* presence of required parameters)
|
||||||
|
*/
|
||||||
|
if (runtime_options.dbname &&
|
||||||
|
(strncmp(runtime_options.dbname, "postgresql://", 13) == 0 ||
|
||||||
|
strncmp(runtime_options.dbname, "postgres://", 11) == 0 ||
|
||||||
|
strchr(runtime_options.dbname, '=') != NULL))
|
||||||
|
{
|
||||||
|
char *errmsg = NULL;
|
||||||
|
|
||||||
|
opts = PQconninfoParse(runtime_options.dbname, &errmsg);
|
||||||
|
|
||||||
|
if (opts == NULL)
|
||||||
|
{
|
||||||
|
PQExpBufferData conninfo_error;
|
||||||
|
initPQExpBuffer(&conninfo_error);
|
||||||
|
appendPQExpBuffer(&conninfo_error, _("error parsing conninfo:\n%s"), errmsg);
|
||||||
|
error_list_append(&cli_errors, conninfo_error.data);
|
||||||
|
|
||||||
|
termPQExpBuffer(&conninfo_error);
|
||||||
|
free(errmsg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set runtime_options.(host|port|username) values, if provided, to prevent these
|
||||||
|
* being overwritten by the defaults
|
||||||
|
*/
|
||||||
|
PQconninfoOption *opt;
|
||||||
|
for (opt = opts; opt->keyword != NULL; opt++)
|
||||||
|
{
|
||||||
|
if (strcmp(opt->keyword, "host") == 0 &&
|
||||||
|
(opt->val != NULL && opt->val[0] != '\0'))
|
||||||
|
{
|
||||||
|
strncpy(runtime_options.host, opt->val, MAXLEN);
|
||||||
|
}
|
||||||
|
else if (strcmp(opt->keyword, "port") == 0 &&
|
||||||
|
(opt->val != NULL && opt->val[0] != '\0'))
|
||||||
|
{
|
||||||
|
strncpy(runtime_options.masterport, opt->val, MAXLEN);
|
||||||
|
}
|
||||||
|
else if (strcmp(opt->keyword, "user") == 0 &&
|
||||||
|
(opt->val != NULL && opt->val[0] != '\0'))
|
||||||
|
{
|
||||||
|
strncpy(runtime_options.username, opt->val, MAXLEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Exit here already if errors in command line options found */
|
/* Exit here already if errors in command line options found */
|
||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
@@ -451,6 +502,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (check_upstream_config == true)
|
if (check_upstream_config == true)
|
||||||
{
|
{
|
||||||
do_check_upstream_config();
|
do_check_upstream_config();
|
||||||
@@ -2620,17 +2672,6 @@ do_standby_follow(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* set the host and masterport variables with the master ones before
|
|
||||||
* closing the connection because we will need them to recreate the
|
|
||||||
* recovery.conf file
|
|
||||||
*/
|
|
||||||
// ZZZ not any more?
|
|
||||||
strncpy(runtime_options.host, PQhost(master_conn), MAXLEN);
|
|
||||||
strncpy(runtime_options.masterport, PQport(master_conn), MAXLEN);
|
|
||||||
strncpy(runtime_options.username, PQuser(master_conn), MAXLEN);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If 9.4 or later, and replication slots in use, we'll need to create a
|
* If 9.4 or later, and replication slots in use, we'll need to create a
|
||||||
* slot on the new master
|
* slot on the new master
|
||||||
@@ -4172,8 +4213,6 @@ do_witness_create(void)
|
|||||||
static void
|
static void
|
||||||
do_help(void)
|
do_help(void)
|
||||||
{
|
{
|
||||||
const char *host;
|
|
||||||
|
|
||||||
printf(_("%s: replication management tool for PostgreSQL\n"), progname());
|
printf(_("%s: replication management tool for PostgreSQL\n"), progname());
|
||||||
printf(_("\n"));
|
printf(_("\n"));
|
||||||
printf(_("Usage:\n"));
|
printf(_("Usage:\n"));
|
||||||
@@ -4193,8 +4232,7 @@ do_help(void)
|
|||||||
printf(_("\n"));
|
printf(_("\n"));
|
||||||
printf(_("Connection options:\n"));
|
printf(_("Connection options:\n"));
|
||||||
printf(_(" -d, --dbname=DBNAME database to connect to (default: \"%s\")\n"), runtime_options.dbname);
|
printf(_(" -d, --dbname=DBNAME database to connect to (default: \"%s\")\n"), runtime_options.dbname);
|
||||||
host = getenv("PGHOST");
|
printf(_(" -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n"), runtime_options.host[0] == '\0' ? _("local socket") : runtime_options.host);
|
||||||
printf(_(" -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n"), host ? host : _("local socket"));
|
|
||||||
printf(_(" -p, --port=PORT database server port (default: \"%s\")\n"), runtime_options.masterport);
|
printf(_(" -p, --port=PORT database server port (default: \"%s\")\n"), runtime_options.masterport);
|
||||||
printf(_(" -U, --username=USERNAME database user name to connect as (default: \"%s\")\n"), runtime_options.username);
|
printf(_(" -U, --username=USERNAME database user name to connect as (default: \"%s\")\n"), runtime_options.username);
|
||||||
printf(_("\n"));
|
printf(_("\n"));
|
||||||
@@ -4491,11 +4529,25 @@ run_basebackup(const char *data_dir, int server_version)
|
|||||||
|
|
||||||
appendPQExpBuffer(¶ms, " -D %s", data_dir);
|
appendPQExpBuffer(¶ms, " -D %s", data_dir);
|
||||||
|
|
||||||
|
if (opts != NULL && strlen(runtime_options.dbname))
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(¶ms, " -d '%s'", runtime_options.dbname);
|
||||||
|
}
|
||||||
|
|
||||||
if (strlen(runtime_options.host))
|
if (strlen(runtime_options.host))
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(¶ms, " -h %s", runtime_options.host);
|
appendPQExpBuffer(¶ms, " -h %s", runtime_options.host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX -p and -U will be duplicated if provided in conninfo string
|
||||||
|
* but not as explict repmgr command line parameters, e.g.:
|
||||||
|
*
|
||||||
|
* pg_basebackup -l "repmgr base backup" -d 'host=localhost port=5501 dbname=repmgr user=repmgr' -p 5501 -U repmgr -X stream
|
||||||
|
*
|
||||||
|
* this is ugly but harmless; we should fix it some time
|
||||||
|
*
|
||||||
|
*/
|
||||||
if (strlen(runtime_options.masterport))
|
if (strlen(runtime_options.masterport))
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(¶ms, " -p %s", runtime_options.masterport);
|
appendPQExpBuffer(¶ms, " -p %s", runtime_options.masterport);
|
||||||
@@ -4668,7 +4720,23 @@ check_parameters_for_action(const int action)
|
|||||||
|
|
||||||
if (strcmp(runtime_options.host, "") == 0)
|
if (strcmp(runtime_options.host, "") == 0)
|
||||||
{
|
{
|
||||||
error_list_append(&cli_errors, _("master hostname (-h/--host) required when executing STANDBY CLONE"));
|
bool conninfo_host_provided = false;
|
||||||
|
PQconninfoOption *opt;
|
||||||
|
for (opt = opts; opt->keyword != NULL; opt++)
|
||||||
|
{
|
||||||
|
if (strcmp(opt->keyword, "host") == 0 ||
|
||||||
|
strcmp(opt->keyword, "hostaddr") == 0)
|
||||||
|
{
|
||||||
|
if (opt->val != NULL && opt->val[0] != '\0')
|
||||||
|
{
|
||||||
|
conninfo_host_provided = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conninfo_host_provided == false)
|
||||||
|
error_list_append(&cli_errors, _("master hostname (-h/--host) required when executing STANDBY CLONE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.fast_checkpoint && runtime_options.rsync_only)
|
if (runtime_options.fast_checkpoint && runtime_options.rsync_only)
|
||||||
@@ -4680,12 +4748,14 @@ check_parameters_for_action(const int action)
|
|||||||
case STANDBY_SWITCHOVER:
|
case STANDBY_SWITCHOVER:
|
||||||
/* allow all parameters to be supplied */
|
/* allow all parameters to be supplied */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STANDBY_ARCHIVE_CONFIG:
|
case STANDBY_ARCHIVE_CONFIG:
|
||||||
if (strcmp(runtime_options.config_archive_dir, "") == 0)
|
if (strcmp(runtime_options.config_archive_dir, "") == 0)
|
||||||
{
|
{
|
||||||
error_list_append(&cli_errors, _("--config-archive-dir required when executing STANDBY ARCHIVE_CONFIG"));
|
error_list_append(&cli_errors, _("--config-archive-dir required when executing STANDBY ARCHIVE_CONFIG"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STANDBY_RESTORE_CONFIG:
|
case STANDBY_RESTORE_CONFIG:
|
||||||
if (strcmp(runtime_options.config_archive_dir, "") == 0)
|
if (strcmp(runtime_options.config_archive_dir, "") == 0)
|
||||||
{
|
{
|
||||||
@@ -4699,6 +4769,7 @@ check_parameters_for_action(const int action)
|
|||||||
|
|
||||||
config_file_required = false;
|
config_file_required = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WITNESS_CREATE:
|
case WITNESS_CREATE:
|
||||||
/* Require data directory */
|
/* Require data directory */
|
||||||
if (strcmp(runtime_options.dest_dir, "") == 0)
|
if (strcmp(runtime_options.dest_dir, "") == 0)
|
||||||
@@ -4707,9 +4778,11 @@ check_parameters_for_action(const int action)
|
|||||||
}
|
}
|
||||||
/* allow all parameters to be supplied */
|
/* allow all parameters to be supplied */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUSTER_SHOW:
|
case CLUSTER_SHOW:
|
||||||
/* allow all parameters to be supplied */
|
/* allow all parameters to be supplied */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLUSTER_CLEANUP:
|
case CLUSTER_CLEANUP:
|
||||||
/* allow all parameters to be supplied */
|
/* allow all parameters to be supplied */
|
||||||
break;
|
break;
|
||||||
@@ -5057,8 +5130,6 @@ create_schema(PGconn *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function uses global variables to determine connection settings. Special
|
|
||||||
* usage of the PGPASSWORD variable is handled, but strongly discouraged */
|
|
||||||
static void
|
static void
|
||||||
write_primary_conninfo(char *line, PGconn *primary_conn)
|
write_primary_conninfo(char *line, PGconn *primary_conn)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user