From f75ad6d5c2f1a30c1b72c31fa1ec78280938d0b0 Mon Sep 17 00:00:00 2001
From: Ed Santiago <santiago@redhat.com>
Date: Sun, 24 May 2020 08:10:54 -0600
Subject: podman-registry helper script: handle errors

My initial revision of the podman-registry helper script
was written in haste, with an enormous tradeoff: no
visibility into any errors. We are now paying for this
in #6366: the script is failing on Ubuntu and we
have no way of knowing why.

This PR adds a must_pass() function used for critical
steps. This runs the action silently; if the command
fails, it displays the failing command name with
full output logs, cleans up the temporary workdir,
and exits with error status.

As a reminder, the reason this is necessary is that
our script convention is to output a series of
environment variables to stdout -- we must therefore
take pains not to emit anything else to stdout.
And, unfortunately, podman and openssl tend to be
rather verbose.

Signed-off-by: Ed Santiago <santiago@redhat.com>
---
 hack/podman-registry | 71 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 42 insertions(+), 29 deletions(-)

(limited to 'hack')

diff --git a/hack/podman-registry b/hack/podman-registry
index e7708ce6a..79dff8b70 100755
--- a/hack/podman-registry
+++ b/hack/podman-registry
@@ -104,6 +104,24 @@ function podman() {
               "$@"
 }
 
+###############
+#  must_pass  #  Run a command quietly; abort with error on failure
+###############
+function must_pass() {
+    local log=${PODMAN_REGISTRY_WORKDIR}/log
+
+    "$@" &> $log
+    if [ $? -ne 0 ]; then
+        echo "$ME: Command failed: $*" >&2
+        cat $log                       >&2
+
+        # If we ever get here, it's a given that the registry is not running.
+        # Clean up after ourselves.
+        rm -rf ${PODMAN_REGISTRY_WORKDIR}
+        exit 1
+    fi
+}
+
 # END   helper functions
 ###############################################################################
 # BEGIN action processing
@@ -132,7 +150,7 @@ function do_start() {
         PODMAN_REGISTRY_PASS=$(random_string 15)
     fi
 
-    # Die on any error
+    # For the next few commands, die on any error
     set -e
 
     mkdir -p ${PODMAN_REGISTRY_WORKDIR}
@@ -140,50 +158,45 @@ function do_start() {
     local AUTHDIR=${PODMAN_REGISTRY_WORKDIR}/auth
     mkdir -p $AUTHDIR
 
-    # We have to be silent; our only output must be env. vars. Log output here.
-    local log=${PODMAN_REGISTRY_WORKDIR}/log
-    touch $log
-
     # Pull registry image, but into a separate container storage
     mkdir -p ${PODMAN_REGISTRY_WORKDIR}/root
     mkdir -p ${PODMAN_REGISTRY_WORKDIR}/runroot
 
+    set +e
+
     # Give it three tries, to compensate for flakes
-    podman pull ${PODMAN_REGISTRY_IMAGE}      &>> $log  ||
-        podman pull ${PODMAN_REGISTRY_IMAGE}  &>> $log  ||
-        podman pull ${PODMAN_REGISTRY_IMAGE}  &>> $log
+    podman pull ${PODMAN_REGISTRY_IMAGE}      &>/dev/null ||
+        podman pull ${PODMAN_REGISTRY_IMAGE}  &>/dev/null ||
+        must_pass podman pull ${PODMAN_REGISTRY_IMAGE}
 
     # Registry image needs a cert. Self-signed is good enough.
     local CERT=$AUTHDIR/domain.crt
-    # FIXME: if this fails, we fail silently! It'd be more helpful
-    # to say 'openssl failed' and cat the logfile
-    openssl req -newkey rsa:4096 -nodes -sha256                      \
-            -keyout ${AUTHDIR}/domain.key -x509 -days 2              \
-            -out ${AUTHDIR}/domain.crt                               \
-            -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"  \
-        &>> $log
+    must_pass openssl req -newkey rsa:4096 -nodes -sha256              \
+              -keyout ${AUTHDIR}/domain.key -x509 -days 2              \
+              -out ${AUTHDIR}/domain.crt                               \
+              -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
 
     # Store credentials where container will see them
-    podman run --rm                                               \
-           --entrypoint htpasswd ${PODMAN_REGISTRY_IMAGE}         \
-           -Bbn ${PODMAN_REGISTRY_USER} ${PODMAN_REGISTRY_PASS}   \
-           > $AUTHDIR/htpasswd
+    must_pass podman run --rm                                        \
+              --entrypoint htpasswd ${PODMAN_REGISTRY_IMAGE}         \
+              -Bbn ${PODMAN_REGISTRY_USER} ${PODMAN_REGISTRY_PASS}   \
+              > $AUTHDIR/htpasswd
 
     # In case someone needs to debug
     echo "${PODMAN_REGISTRY_USER}:${PODMAN_REGISTRY_PASS}" \
          > $AUTHDIR/htpasswd-plaintext
 
     # Run the registry container.
-    podman run --quiet -d                                            \
-           -p ${PODMAN_REGISTRY_PORT}:5000                           \
-           --name registry                                           \
-           -v $AUTHDIR:/auth:Z                                       \
-           -e "REGISTRY_AUTH=htpasswd"                               \
-           -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"          \
-           -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd"           \
-           -e "REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt"       \
-           -e "REGISTRY_HTTP_TLS_KEY=/auth/domain.key"               \
-           registry:2 &>> $log
+    must_pass podman run --quiet -d                                     \
+              -p ${PODMAN_REGISTRY_PORT}:5000                           \
+              --name registry                                           \
+              -v $AUTHDIR:/auth:Z                                       \
+              -e "REGISTRY_AUTH=htpasswd"                               \
+              -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"          \
+              -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd"           \
+              -e "REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt"       \
+              -e "REGISTRY_HTTP_TLS_KEY=/auth/domain.key"               \
+              registry:2
 
     # Dump settings. Our caller will use these to access the registry.
     for v in IMAGE PORT USER PASS; do
-- 
cgit v1.2.3-54-g00ecf