From b3f64987cbfd97c160b8df1f637f2c4599da037f Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Fri, 13 Jul 2018 11:19:12 +0900 Subject: [PATCH] repmgr: add --csv output to "cluster event" Implements GitHub #471. --- HISTORY | 33 ++++++------ doc/appendix-release-notes.sgml | 13 +++-- doc/repmgr-cluster-event.sgml | 16 ++++++ repmgr-action-cluster.c | 92 +++++++++++++++++++++------------ 4 files changed, 101 insertions(+), 53 deletions(-) diff --git a/HISTORY b/HISTORY index 57b22526..fb643deb 100644 --- a/HISTORY +++ b/HISTORY @@ -1,34 +1,35 @@ 4.1.0 2018-??-?? repmgr: change default log_level to INFO, add documentation; GitHub #470 (Ian) - repmgr: add "--missing-slots" check to "repmgr node check" (Ian) + repmgr: add "--missing-slots" check to "repmgr node check" (Ian) repmgr: improve command line error handling; GitHub #464 (Ian) repmgr: fix "standby register --wait-sync" when no timeout provided (Ian) repmgr: "cluster show" returns non-zero value if an issue encountered; GitHub #456 (Ian) repmgr: "node check" and "node status" returns non-zero value if an issue encountered (Ian) + repmgr: add CSV output mode to "cluster event"; GitHub #471 (Ian) repmgr: "node status" returns non-zero value if an issue encountered (Ian) repmgrd: create a PID file by default; GitHub #457 (Ian) - repmgrd: daemonize process by default; GitHub #458 (Ian) + repmgrd: daemonize process by default; GitHub #458 (Ian) 4.0.6 2018-06-14 repmgr: (witness register) prevent registration of a witness server with the - same name as an existing node (Ian) - repmgr: (standby follow) check node has actually connected to new primary - before reporting success; GitHub #444 (Ian) - repmgr: (standby clone) improve handling of external configuration file copying, - including consideration in --dry-run check; GitHub #443 (Ian) - repmgr: (standby clone) don't require presence of "user" parameter in - conninfo string; GitHub #437 (Ian) - repmgr: (standby clone) improve documentation of --recovery-conf-only - mode; GitHub #438 (Ian) - repmgr: (node rejoin) fix bug when parsing --config-files parameter; - GitHub #442 (Ian) - repmgr: when using --dry-run, force log level to INFO to ensure output - will always be displayed; GitHub #441 (Ian) + same name as an existing node (Ian) + repmgr: (standby follow) check node has actually connected to new primary + before reporting success; GitHub #444 (Ian) + repmgr: (standby clone) improve handling of external configuration file copying, + including consideration in --dry-run check; GitHub #443 (Ian) + repmgr: (standby clone) don't require presence of "user" parameter in + conninfo string; GitHub #437 (Ian) + repmgr: (standby clone) improve documentation of --recovery-conf-only + mode; GitHub #438 (Ian) + repmgr: (node rejoin) fix bug when parsing --config-files parameter; + GitHub #442 (Ian) + repmgr: when using --dry-run, force log level to INFO to ensure output + will always be displayed; GitHub #441 (Ian) repmgr: (cluster matrix/crosscheck) return non-zero exit code if node connection issues detected; GitHub #447 (Ian) - repmgrd: ensure local node is counted as quorum member; GitHub #439 (Ian) + repmgrd: ensure local node is counted as quorum member; GitHub #439 (Ian) 4.0.5 2018-05-02 repmgr: poll demoted primary after restart as a standby during a diff --git a/doc/appendix-release-notes.sgml b/doc/appendix-release-notes.sgml index 4399d861..63f147eb 100644 --- a/doc/appendix-release-notes.sgml +++ b/doc/appendix-release-notes.sgml @@ -68,14 +68,21 @@ - repmgr cluster-show, + repmgr cluster show, repmgr node check and repmgr node status return non-zero exit code if node status issues detected. (GitHub #456). - - + + + + Add output option for + repmgr cluster event. + (GitHub #471). + + + diff --git a/doc/repmgr-cluster-event.sgml b/doc/repmgr-cluster-event.sgml index 0f1d9ec7..0ee8e221 100644 --- a/doc/repmgr-cluster-event.sgml +++ b/doc/repmgr-cluster-event.sgml @@ -49,6 +49,22 @@ + + Output format + + + + + + --csv: generate output in CSV format. Note that the Details + column will currently not be emitted in CSV format. + + + + + + + Example diff --git a/repmgr-action-cluster.c b/repmgr-action-cluster.c index b6bc06a5..2cbda76b 100644 --- a/repmgr-action-cluster.c +++ b/repmgr-action-cluster.c @@ -463,6 +463,7 @@ do_cluster_show(void) * --all * --node-[id|name] * --event + * --csv */ void @@ -507,8 +508,12 @@ do_cluster_event(void) strncpy(headers_event[EV_TIMESTAMP].title, _("Timestamp"), MAXLEN); strncpy(headers_event[EV_DETAILS].title, _("Details"), MAXLEN); - /* if --terse provided, simply omit the "Details" column */ - if (runtime_options.terse == true) + /* + * If --terse or --csv provided, simply omit the "Details" column. + * In --csv mode we'd need to quote/escape the contents "Details" column, + * which is doable but which will remain a TODO for now. + */ + if (runtime_options.terse == true || runtime_options.output_mode == OM_CSV) column_count --; for (i = 0; i < column_count; i++) @@ -531,47 +536,64 @@ do_cluster_event(void) } - for (i = 0; i < column_count; i++) + if (runtime_options.output_mode == OM_TEXT) { - if (i == 0) - printf(" "); - else - printf(" | "); + for (i = 0; i < column_count; i++) + { + if (i == 0) + printf(" "); + else + printf(" | "); - printf("%-*s", - headers_event[i].max_length, - headers_event[i].title); + printf("%-*s", + headers_event[i].max_length, + headers_event[i].title); + } + printf("\n"); + printf("-"); + for (i = 0; i < column_count; i++) + { + int j; + + for (j = 0; j < headers_event[i].max_length; j++) + printf("-"); + + if (i < (column_count - 1)) + printf("-+-"); + else + printf("-"); + } + + printf("\n"); } - printf("\n"); - printf("-"); - for (i = 0; i < column_count; i++) - { - int j; - - for (j = 0; j < headers_event[i].max_length; j++) - printf("-"); - - if (i < (column_count - 1)) - printf("-+-"); - else - printf("-"); - } - - printf("\n"); for (i = 0; i < PQntuples(res); i++) { int j; - printf(" "); - for (j = 0; j < column_count; j++) + if (runtime_options.output_mode == OM_CSV) { - printf("%-*s", - headers_event[j].max_length, - PQgetvalue(res, i, j)); + for (j = 0; j < column_count; j++) + { + printf("%s", PQgetvalue(res, i, j)); + if ((j + 1) < column_count) + { + printf(","); + } + } + } + else + { + printf(" "); + for (j = 0; j < column_count; j++) + { + printf("%-*s", + headers_event[j].max_length, + PQgetvalue(res, i, j)); - if (j < (column_count - 1)) - printf(" | "); + if (j < (column_count - 1)) + printf(" | "); + } } printf("\n"); @@ -581,7 +603,8 @@ do_cluster_event(void) PQfinish(conn); - puts(""); + if (runtime_options.output_mode == OM_TEXT) + puts(""); } @@ -1414,6 +1437,7 @@ do_cluster_help(void) printf(_(" --event filter specific event\n")); printf(_(" --node-id restrict entries to node with this ID\n")); printf(_(" --node-name restrict entries to node with this name\n")); + printf(_(" --csv emit output as CSV\n")); puts(""); printf(_("CLUSTER CLEANUP\n"));