diff options
author | Liam Crilly <liam.crilly@nginx.com> | 2024-06-06 10:02:53 +0100 |
---|---|---|
committer | Andrew Clayton <a.clayton@nginx.com> | 2024-06-12 21:33:18 +0100 |
commit | a7e3686aacc3ced28670b6e6c69508072e101e69 (patch) | |
tree | ed1045cc4d0f678e5f7fc2341b3b88827636d70f /tools | |
parent | 98983f3f3b9dae111471043792dd24e5c834a6d3 (diff) | |
download | unit-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-x | tools/unitc | 76 |
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 |