From e561ddc8d3ff03b04880d86eac3605db73454d57 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Mon, 23 Mar 2020 17:07:42 +0900 Subject: [PATCH] node check: accept -S/--superuser option This is mainly useful for the --data-directory-config option, which requires permission to read pg_settings to verify that the data directory configured in "repmgr.conf" matches the data directory actually in use. If pg_settings read permission is not available, repmgr will fall back to a simple check that the data directory configured in "repmgr.conf" is a valid PostgreSQL directory. This is not entirely foolproof, as it's possible PostgreSQL could be using a different data directory. --- HISTORY | 1 + doc/appendix-release-notes.xml | 6 +++ doc/repmgr-node-check.xml | 38 +++++++++++++----- repmgr-action-node.c | 70 +++++++++++++++++++++++++++------- repmgr-client.c | 1 + 5 files changed, 93 insertions(+), 23 deletions(-) diff --git a/HISTORY b/HISTORY index 0951eb7c..6850338f 100644 --- a/HISTORY +++ b/HISTORY @@ -14,6 +14,7 @@ repmgr: consolidate replication connection code (Ian) repmgr: check permissions for "pg_promote()" and fall back to pg_ctl if necessary (Ian) + repmgr: accept option -S/--superuser for "node check"; GitHub #612 (Ian) repmgr: enable "service_promote_command" in PostgreSQL 12 (Ian) 5.0 2019-10-15 diff --git a/doc/appendix-release-notes.xml b/doc/appendix-release-notes.xml index e326985b..e79543ed 100644 --- a/doc/appendix-release-notes.xml +++ b/doc/appendix-release-notes.xml @@ -64,6 +64,12 @@ data directory. + + + repmgr node check: + accept option / GitHub #621. + + diff --git a/doc/repmgr-node-check.xml b/doc/repmgr-node-check.xml index e7d94ce4..5c6a549f 100644 --- a/doc/repmgr-node-check.xml +++ b/doc/repmgr-node-check.xml @@ -57,20 +57,20 @@ - --role: checks if the node has the expected role + : checks if the node has the expected role - --replication-lag: checks if the node is lagging by more than + : checks if the node is lagging by more than replication_lag_warning or replication_lag_critical - --archive-ready: checks for WAL files which have not yet been archived, + : checks for WAL files which have not yet been archived, and returns WARNING or CRITICAL if the number exceeds archive_ready_warning or archive_ready_critical respectively. @@ -78,25 +78,25 @@ - --downstream: checks that the expected downstream nodes are attached + : checks that the expected downstream nodes are attached - --slots: checks there are no inactive physical replication slots + : checks there are no inactive physical replication slots - --missing-slots: checks there are no missing physical replication slots + : checks there are no missing physical replication slots - --data-directory-config: checks the data directory configured in + : checks the data directory configured in repmgr.conf matches the actual data directory. This check is not directly related to replication, but is useful to verify &repmgr; is correctly configured. @@ -108,6 +108,22 @@ + + Connection options + + + + + + /: connect as the + named superuser instead of the &repmgr; user + + + + + + + Output format @@ -115,14 +131,14 @@ - --csv: generate output in CSV format (not available + : generate output in CSV format (not available for individual checks) - --nagios: generate output in a Nagios-compatible format + : generate output in a Nagios-compatible format (for individual checks only) @@ -130,13 +146,15 @@ + + Exit codes When executing repmgr node check with one of the individual checks listed above, &repmgr; will emit one of the following Nagios-style exit codes - (even if --nagios is not supplied): + (even if is not supplied): diff --git a/repmgr-action-node.c b/repmgr-action-node.c index d96d8cd5..6060b607 100644 --- a/repmgr-action-node.c +++ b/repmgr-action-node.c @@ -716,10 +716,45 @@ do_node_check(void) exit(SUCCESS); } - if (strlen(config_file_options.conninfo)) - conn = establish_db_connection(config_file_options.conninfo, true); + + if (config_file_options.conninfo[0] != '\0') + { + t_conninfo_param_list node_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER; + char *errmsg = NULL; + bool parse_success = false; + + initialize_conninfo_params(&node_conninfo, false); + + parse_success = parse_conninfo_string(config_file_options.conninfo, + &node_conninfo, + &errmsg, false); + + if (parse_success == false) + { + log_error(_("unable to parse conninfo string \"%s\" for local node"), + config_file_options.conninfo); + log_detail("%s", errmsg); + + exit(ERR_BAD_CONFIG); + } + + /* + * If --superuser option provided, attempt to connect as the specified user + */ + + if (runtime_options.superuser[0] != '\0') + { + param_set(&node_conninfo, + "user", + runtime_options.superuser); + } + + conn = establish_db_connection_by_params(&node_conninfo, true); + } else + { conn = establish_db_connection_by_params(&source_conninfo, true); + } if (get_node_record(conn, config_file_options.node_id, &node_info) != RECORD_FOUND) { @@ -1846,10 +1881,9 @@ do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_in { log_info(_("connection is not a superuser connection, falling back to simple check")); - /* XXX add -S/--superuser option */ if (PQserverVersion(conn) >= 100000) { - log_hint(_("add the \"%s\" user to group \"pg_read_all_settings\" or \"pg_monitor\""), + log_hint(_("provide a superuser with -S/--superuser, or add the \"%s\" user to role \"pg_read_all_settings\" or \"pg_monitor\""), PQuser(conn)); } } @@ -1870,6 +1904,12 @@ do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_in status = CHECK_STATUS_CRITICAL; } + else + { + appendPQExpBuffer(&details, + _("configured \"data_directory\" is \"%s\""), + config_file_options.data_directory); + } } switch (mode) @@ -3164,17 +3204,21 @@ do_node_help(void) puts(""); printf(_(" Configuration file required, runs on local node only.\n")); puts(""); - printf(_(" --csv emit output as CSV (not available for individual check output)\n")); - printf(_(" --nagios emit output in Nagios format (individual check output only)\n")); + printf(_(" Connection options:\n")); + printf(_(" -S, --superuser=USERNAME superuser to use, if repmgr user is not superuser\n")); + puts(""); + printf(_(" Output options:\n")); + printf(_(" --csv emit output as CSV (not available for individual check output)\n")); + printf(_(" --nagios emit output in Nagios format (individual check output only)\n")); puts(""); printf(_(" Following options check an individual status:\n")); - printf(_(" --archive-ready number of WAL files ready for archiving\n")); - printf(_(" --downstream whether all downstream nodes are connected\n")); - printf(_(" --replication-lag replication lag in seconds (standbys only)\n")); - printf(_(" --role check node has expected role\n")); - printf(_(" --slots check for inactive replication slots\n")); - printf(_(" --missing-slots check for missing replication slots\n")); - printf(_(" --data-directory-config check repmgr's data directory configuration\n")); + printf(_(" --archive-ready number of WAL files ready for archiving\n")); + printf(_(" --downstream whether all downstream nodes are connected\n")); + printf(_(" --replication-lag replication lag in seconds (standbys only)\n")); + printf(_(" --role check node has expected role\n")); + printf(_(" --slots check for inactive replication slots\n")); + printf(_(" --missing-slots check for missing replication slots\n")); + printf(_(" --data-directory-config check repmgr's data directory configuration\n")); puts(""); diff --git a/repmgr-client.c b/repmgr-client.c index 568f00e9..1814814d 100644 --- a/repmgr-client.c +++ b/repmgr-client.c @@ -1691,6 +1691,7 @@ check_cli_parameters(const int action) switch (action) { case STANDBY_CLONE: + case NODE_CHECK: break; default: item_list_append_format(&cli_warnings,