summaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorLiam Crilly <liam.crilly@nginx.com>2024-06-06 10:02:53 +0100
committerAndrew Clayton <a.clayton@nginx.com>2024-06-12 21:33:18 +0100
commita7e3686aacc3ced28670b6e6c69508072e101e69 (patch)
treeed1045cc4d0f678e5f7fc2341b3b88827636d70f /tools
parent98983f3f3b9dae111471043792dd24e5c834a6d3 (diff)
downloadunit-a7e3686aacc3ced28670b6e6c69508072e101e69.tar.gz
unit-a7e3686aacc3ced28670b6e6c69508072e101e69.tar.bz2
Tools: improved error handling for unitc
This patch does a number of things to help when failing to apply a new configuration. * The error body from the Unit control API is displayed which can have useful troubleshooting information (when the version of curl supports it). * When using the EDIT option, the temporary file with unapplied changes is preserved so that the user can edit it again without losing their work. * Editing JavaScript modules no longer requires that module to have been enabled. * Failure to apply edited JavaScript modules now rolls-back to the previous configuration instead of deleting the module. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/unitc76
1 files changed, 52 insertions, 24 deletions
diff --git a/tools/unitc b/tools/unitc
index 9fba4c6d..332b2311 100755
--- a/tools/unitc
+++ b/tools/unitc
@@ -249,41 +249,58 @@ else
NOLOG=1
fi
+# Set the base curl command after testing for newer features
+#
+$RPC_CMD curl --fail-with-body --version > /dev/null
+if [ $? -eq 0 ]; then
+ CURL_CMD="$RPC_CMD curl --silent --fail-with-body"
+else
+ CURL_CMD="$RPC_CMD curl --silent --fail"
+fi
+
# Adjust HTTP method and curl params based on presence of stdin payload
#
if [ -t 0 ] && [ ${#CONF_FILES[@]} -eq 0 ]; then
if [ "$METHOD" = "DELETE" ]; then
- $RPC_CMD curl -X $METHOD $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ $CURL_CMD -X $METHOD $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
elif [ "$METHOD" = "EDIT" ]; then
EDITOR=$(test "$EDITOR" && printf '%s' "$EDITOR" || command -v editor || command -v vim || echo vi)
EDIT_FILENAME=/tmp/${0##*/}.$$${URI//\//_}
- $RPC_CMD curl -fsS $UNIT_CTRL$URI > $EDIT_FILENAME || exit 2
+ $CURL_CMD -S $UNIT_CTRL$URI > $EDIT_FILENAME || exit 2
if [ "${URI:0:12}" = "/js_modules/" ]; then
if ! hash jq 2> /dev/null; then
echo "${0##*/}: ERROR: jq(1) is required to edit JavaScript modules; install at <https://stedolan.github.io/jq/>"
exit 1
fi
jq -r < $EDIT_FILENAME > $EDIT_FILENAME.js # Unescape linebreaks for a better editing experience
+ cp $EDIT_FILENAME.js /tmp/${0##*/}.$$bak
EDIT_FILE=$EDIT_FILENAME.js
$EDITOR $EDIT_FILENAME.js || exit 2
- # Remove the references, delete old config, push new config+reference
- $RPC_CMD curl -fsS $UNIT_CTRL/config/settings/js_module > /tmp/${0##*/}.$$_js_module && \
- $RPC_CMD curl -X DELETE $UNIT_CTRL/config/settings/js_module && \
- $RPC_CMD curl -fsSX DELETE $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
- printf "%s" "$(< $EDIT_FILENAME.js)" | $RPC_CMD curl -fX PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
- cat /tmp/${0##*/}.$$_js_module | $RPC_CMD curl -X PUT --data-binary @- $UNIT_CTRL/config/settings/js_module 2> /tmp/${0##*/}.$$
+ # Test if this module is enabled
+ $CURL_CMD $UNIT_CTRL/config/settings/js_module > /tmp/${0##*/}.$$_js_module
+ if [ $? -eq 0 ]; then
+ # Remove the references, delete old module, push new module+reference
+ $CURL_CMD -X DELETE $UNIT_CTRL/config/settings/js_module && \
+ $CURL_CMD -X DELETE $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
+ printf "%s" "$(< $EDIT_FILENAME.js)" | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
+ cat /tmp/${0##*/}.$$_js_module | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL/config/settings/js_module 2> /tmp/${0##*/}.$$
+ else
+ # Delete then re-apply the module
+ $CURL_CMD -X DELETE $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ && \
+ printf "%s" "$(< $EDIT_FILENAME.js)" | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL$URI 2>&1 2> /tmp/${0##*/}.$$
+ fi
elif [ $CONVERT -eq 1 ]; then
$CONVERT_FROM_JSON < $EDIT_FILENAME > $EDIT_FILENAME.yaml
$EDITOR $EDIT_FILENAME.yaml || exit 2
- $CONVERT_TO_JSON < $EDIT_FILENAME.yaml | $RPC_CMD curl -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ $CONVERT_TO_JSON < $EDIT_FILENAME.yaml | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
else
tr -d '\r' < $EDIT_FILENAME > $EDIT_FILENAME.json # Remove carriage-return from newlines
$EDITOR $EDIT_FILENAME.json || exit 2
- cat $EDIT_FILENAME.json | $RPC_CMD curl -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ cat $EDIT_FILENAME.json | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
fi
else
SHOW_LOG=$(echo $URI | grep -c ^/control/)
- $RPC_CMD curl $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ $CURL_CMD $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
fi
else
if [ "$METHOD" = "INSERT" ]; then
@@ -293,9 +310,9 @@ else
fi
NEW_ELEMENT=$(cat ${CONF_FILES[@]})
echo $NEW_ELEMENT | jq > /dev/null || exit $? # Test the input is valid JSON before proceeding
- OLD_ARRAY=$($RPC_CMD curl -s $UNIT_CTRL$URI)
+ OLD_ARRAY=$($CURL_CMD -s $UNIT_CTRL$URI)
if [ "$(echo $OLD_ARRAY | jq -r type)" = "array" ]; then
- echo $OLD_ARRAY | jq ". |= [$NEW_ELEMENT] + ." | $RPC_CMD curl -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ echo $OLD_ARRAY | jq ". |= [$NEW_ELEMENT] + ." | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
else
echo "${0##*/}: ERROR: the INSERT method expects an array"
exit 3
@@ -305,12 +322,31 @@ else
cat ${CONF_FILES[@]} | $CONVERT_TO_JSON > /tmp/${0##*/}.$$_json
CONF_FILES=(/tmp/${0##*/}.$$_json)
fi
- cat ${CONF_FILES[@]} | $RPC_CMD curl -X $METHOD --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
+ cat ${CONF_FILES[@]} | $CURL_CMD -X $METHOD --data-binary @- $UNIT_CTRL$URI 2> /tmp/${0##*/}.$$ | $OUTPUT
fi
fi
-CURL_STATUS=${PIPESTATUS[0]}
-if [ $CURL_STATUS -ne 0 ]; then
+CURL_STATUS=${PIPESTATUS[1]}
+if [ $CURL_STATUS -eq 0 ]; then
+ rm -f /tmp/${0##*/}.$$* 2> /dev/null
+ if [ $SHOW_LOG -gt 0 ] && [ $NOLOG -eq 0 ] && [ $QUIET -eq 0 ]; then
+ echo -n "${0##*/}: Waiting for log..."
+ sleep $SHOW_LOG
+ echo ""
+ sed -n $((LOG_LEN+1)),\$p $ERROR_LOG
+ fi
+elif [ $CURL_STATUS -eq 22 ]; then
+ echo "${0##*/}: ERROR: configuration not applied"
+ if [ "$METHOD" = "EDIT" ]; then
+ if [ -f /tmp/${0##*/}.$$_js_module ]; then
+ echo "${0##*/}: NOTICE: restoring previous configuration"
+ printf "%s" "$(< /tmp/${0##*/}.$$bak)" | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL$URI && \
+ cat /tmp/${0##*/}.$$_js_module | $CURL_CMD -X PUT --data-binary @- $UNIT_CTRL/config/settings/js_module 2> /tmp/${0##*/}.$$
+ fi
+ echo "${0##*/}: NOTICE: $(ls $EDIT_FILENAME.*) contains unapplied edits"
+ rm /tmp/${0##*/}.$$ $EDIT_FILENAME
+ fi
+else
echo "${0##*/}: ERROR: curl(1) exited with an error ($CURL_STATUS)"
if [ $CURL_STATUS -eq 7 ] && [ $REMOTE -eq 0 ]; then
echo "${0##*/}: Check that you have permission to access the Unit control socket, or try again with sudo(8)"
@@ -320,11 +356,3 @@ if [ $CURL_STATUS -ne 0 ]; then
fi
exit 4
fi
-rm -f /tmp/${0##*/}.$$* 2> /dev/null
-
-if [ $SHOW_LOG -gt 0 ] && [ $NOLOG -eq 0 ] && [ $QUIET -eq 0 ]; then
- echo -n "${0##*/}: Waiting for log..."
- sleep $SHOW_LOG
- echo ""
- sed -n $((LOG_LEN+1)),\$p $ERROR_LOG
-fi