ctdb-tools: Improve printing of multi-line event script output
authorMartin Schwenke <mschwenke@ddn.com>
Wed, 12 Jul 2023 00:39:06 +0000 (10:39 +1000)
committerStefan Metzmacher <metze@samba.org>
Fri, 28 Jul 2023 10:48:33 +0000 (10:48 +0000)
Multi-line output currently prints like this:

  OUTPUT: aaa
bbb
ccc

This is less beautiful than it could be.

Instead, print multi-line output with no inlining and each line
indented:

  OUTPUT:
    aaa
    bbb
    ccc

However, continue to inline single line output:

  OUTPUT: foo

Signed-off-by: Martin Schwenke <mschwenke@ddn.com>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/event/event_tool.c
ctdb/tests/UNIT/eventd/etc-ctdb/events/random/02.enabled.script
ctdb/tests/UNIT/eventd/eventd_008.sh

index 5e94af1d9bcdac9acc4c3aac9f408088a6672fa3..e6d5261c217929828615031082dfabe00a32eda5 100644 (file)
@@ -199,8 +199,62 @@ static void print_status_one(struct ctdb_event_script *script)
 
        if ((script->result != 0 && script->result != -ENOEXEC) ||
            script->output != NULL) {
-               printf("  OUTPUT: %s\n",
-                      script->output == NULL ? "" : script->output);
+               /* Empty output is informative so always print it on failure */
+               const char *t = script->output == NULL ? "" : script->output;
+               size_t len = strlen(t);
+               char output[len+1];
+               size_t p;
+               char *t1, *t2;
+
+               strlcpy(output, t, sizeof(output));
+
+               /*
+                * Strip trailing newlines, they are clutter and
+                * interfere with multi-line detection
+                */
+               p = len - 1;
+               while (p >= 0 && output[p] == '\n') {
+                       output[p] = '\0';
+                       p--;
+               }
+
+               /* If the output is a single line then print it inline */
+               t2 = strchr(output, '\n');
+               if (t2 == NULL) {
+                       printf("  OUTPUT: %s\n", output);
+                       return;
+               }
+
+               /*
+                * More than 1 line.  Print a header and then each
+                * line, with suitable indent.  There are more general
+                * ways to do this, but let's maintain intermediate
+                * blank lines (e.g. strv_split() loses blank lines).
+                */
+               printf("  OUTPUT:\n");
+               t1 = output;
+               do {
+                       /*
+                        * Points to newline character. t2 initially
+                        * set non-NULL outside loop because this loop
+                        * only covers multi-line output.
+                        */
+                       *t2 = '\0';
+
+
+                       printf("    %s\n", t1);
+                       t1 = t2 + 1;
+
+                       if (t1 >= output + len) {
+                               break;
+                       }
+
+                       /* strchrnul() would be awesome, but isn't portable */
+                       t2 = strchr(t1, '\n');
+                       if (t2 == NULL) {
+                               t2 = output + len;
+                       }
+               } while (true);
        }
 }
 
index a59c58bf692dec9295085579e32dac1a95626c4a..90df5218a9d9a3e5ae8989d9bc97fe8784a7fa4d 100755 (executable)
@@ -15,6 +15,15 @@ There are multiple output lines
 EOF
        exit 0
        ;;
+"verbosemultilinenonl")
+       cat <<EOF
+Running event $1
+Multiple output lines
+
+EOF
+       printf 'No trailing newline'
+       exit 0
+       ;;
 "verbosefailure") echo "args: $*"; exit 1 ;;
 "verbosemultilinefailure")
        cat <<EOF
index f2e3cb1dbee1517829369c6ebd72c0dec08682d5..c52caa0e25eb5e3b163673106c15c1907e918b88 100755 (executable)
@@ -34,13 +34,28 @@ simple_test run 10 random verbosemultiline
 ok <<EOF
 01.disabled          DISABLED  
 02.enabled           OK         DURATION DATETIME
-  OUTPUT: Running event verbosemultiline
-There are multiple output lines
-
-^^^ including blank lines...
+  OUTPUT:
+    Running event verbosemultiline
+    There are multiple output lines
+    
+    ^^^ including blank lines...
 EOF
 simple_test status random verbosemultiline
 
+ok_null
+simple_test run 10 random verbosemultilinenonl
+
+ok <<EOF
+01.disabled          DISABLED  
+02.enabled           OK         DURATION DATETIME
+  OUTPUT:
+    Running event verbosemultilinenonl
+    Multiple output lines
+    
+    No trailing newline
+EOF
+simple_test status random verbosemultilinenonl
+
 required_result 8 <<EOF
 Event verbosemultilinefailure in random failed
 EOF
@@ -49,9 +64,10 @@ simple_test run 10 random verbosemultilinefailure with some args
 required_result 2 <<EOF
 01.disabled          DISABLED  
 02.enabled           ERROR      DURATION DATETIME
-  OUTPUT: Failing event verbosemultilinefailure
-There are multiple output lines
-
-args: verbosemultilinefailure with some args
+  OUTPUT:
+    Failing event verbosemultilinefailure
+    There are multiple output lines
+    
+    args: verbosemultilinefailure with some args
 EOF
 simple_test status random verbosemultilinefailure