From af4a56da66e039212cee6bb671ec6a109b2e7e6a Mon Sep 17 00:00:00 2001 From: Didier BONNEFOI Date: Mon, 3 Jul 2017 00:38:10 +0200 Subject: [PATCH] OVH API Lib enhancements: OvhRequestApi() review: - ovh-api-bash-client.sh commandline piped to bash, for correct quotes management - add target support with OVHAPI_TARGET variable Wrappers for JSON.sh enhancements: - JSON nested object managed, key displayed/set with a dot as separator. - getJSONValues() support for object and nested object - getJSONValue() hash support (getJSONString() removed) - remove double quotes from field for getJSONKeys() and getJSONValue() - getJSONArrayLength() removed, result can be calculated from getJSONValues() result Lib debugging: - add _ovhapilib_echo_debug() : redirect arguments to stderr - add OVHAPILIB_DEBUG variable --- README.md | 28 +++--- ovh-api-lib.sh | 156 ++++++++++++++++++++---------- samples/list-domains.sh | 24 +++-- samples/my-informations.sh | 18 ++++ samples/post-domain-TXT-record.sh | 42 ++++++++ 5 files changed, 199 insertions(+), 69 deletions(-) create mode 100755 samples/my-informations.sh create mode 100755 samples/post-domain-TXT-record.sh diff --git a/README.md b/README.md index e5410e3..55c6e79 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Embedded lib for external scripts #### OvhRequestApi -- OvhRequestApi() : wrapper to ovh-api-bash-client.sh +OvhRequestApi() is wrapper to ovh-api-bash-client.sh ``` OvhRequestApi url [method] [post_data] @@ -92,26 +92,26 @@ Embedded lib for external scripts return values in OVHAPI_HTTP_STATUS and OVHAPI_HTTP_RESPONSE -#### JSon stuff -- getJSONString() : unquote string value -- getJSONValue() : get JSON value as is +#### wrappers for JSON.sh + +- getJSONKeys() : get JSON keys, remove first/last double quotes if present +- getJSONValue() : get a JSON key value, remove first/last double quotes if present - getJSONValues() : get all JSON values at once -- getJSONArrayLength() : count array elements ### sample usage Once you've an available OVH API authentication, you can use the library : -To set a profile, define value OVHAPI_BASHCLIENT_PROFILE (can be used inside or outside your script) +- To override profile, set OVHAPI_BASHCLIENT_PROFILE +- To override target, set OVHAPI_TARGET +- For **ovh-api-lib.sh** debug output, set OVHAPILIB_DEBUG to 1 -**sample-script.sh** +This variables can be set in your script or exported from commandline + +You can find some samples scripts in the **samples/** directory + +**sample usage** ``` - source path/to/ovh-api-bash-client/ovh-api-lib.sh || exit 1 - OvhRequestApi /me + OVHAPI_BASHCLIENT_PROFILE=demo samples/list-domains.sh ``` - -**sample** - - -OVHAPI_BASHCLIENT_PROFILE=demo samples/list-domains.sh diff --git a/ovh-api-lib.sh b/ovh-api-lib.sh index 3ec1ab4..3ae172e 100644 --- a/ovh-api-lib.sh +++ b/ovh-api-lib.sh @@ -8,13 +8,41 @@ readonly OVHAPI_BASHCLIENT_LIB="${OVHAPI_BASHCLIENT_DIR}/libs" OVHAPI_HTTP_STATUS= OVHAPI_HTTP_RESPONSE= +# debug output: should be setted to 1 from external script +OVHAPILIB_DEBUG=${OVHAPILIB_DEBUG:-0} + +# use ovh-api-bash-client default target if not set +OVHAPI_TARGET=${OVHAPI_TARGET:-} + # ensure the client is available if [ ! -f "${OVHAPI_BASHCLIENT_BIN}" ]; then echo "${OVHAPI_BASHCLIENT_BIN} not found" exit 1 fi -# to set a profile, define value in the variable OVHAPI_BASHCLIENT_PROFILE +# debug output if wanted +_ovhapilib_echo_debug() +{ + if [ "${OVHAPILIB_DEBUG}" == "1" ]; then + echo "[debug:${FUNCNAME[1]}] $*" >&2 + fi +} + + +# remove first and last double quote from string +_trimDoubleQuotes() +{ + local value="$1" + + [ -z "${value}" ] && return + + value="${value%\"}" + value="${value#\"}" + echo "${value}" +} + +# to override profile, define value in the variable OVHAPI_BASHCLIENT_PROFILE +# to override target, define value in the variable OVHAPI_TARGET # OvhRequestApi url [method] [post_data] # # default method: get @@ -25,90 +53,120 @@ OvhRequestApi() local method=$2 local data=$3 - local client_response= - local quote= local cmd=(${OVHAPI_BASHCLIENT_BIN}) + ## construct arguments array if [ -n "${OVHAPI_BASHCLIENT_PROFILE}" ]; then cmd+=(--profile ${OVHAPI_BASHCLIENT_PROFILE}) fi + if [ -n "${url}" ]; then cmd+=(--url ${url}) fi + if [ -n "${method}" ]; then cmd+=(--method ${method}) fi - if [ "${method}" == "POST" ]; then - local cmdfile=$(mktemp "/tmp/OvhRequestApi.postcmd.sh.XXXXXX") - # best way found to correctly pass quoted argument to a command called via a function - - # if json content has single or double quotes inside, to use the opposite - if echo ${data} | grep -q '"'; then - quote=\' - elif echo ${data} | grep -q "'"; then - quote=\" - fi - - cmd+=(--data ${quote}${data}${quote}) - # inject all command to a temp file, execute and drop the file - echo ${cmd[@]} > ${cmdfile} - client_response=$(bash ${cmdfile}) - rm ${cmdfile} - else - client_response=$(${cmd[@]}) + if [ -n "${OVHAPI_TARGET}" ]; then + cmd+=(--target ${OVHAPI_TARGET}) fi - OVHAPI_HTTP_STATUS=$(echo ${client_response} | cut -d ' ' -f1) - OVHAPI_HTTP_RESPONSE="$(echo ${client_response} | cut -d ' ' -f2-)" + if [ "${method}" == "POST" ]; then + # double-quote data content for bash input + data=$(printf "%q" "${data}") + cmd+=(--data ${data}) + fi - # debug information, go to stderr - echo http_status=${OVHAPI_HTTP_STATUS} >&2 + _ovhapilib_echo_debug "command: ${cmd[*]}" + + # best way found to correctly pass quoted arguments to a command called from a function + client_response=$(echo "${cmd[*]}" | bash) + + OVHAPI_HTTP_STATUS=$(echo "${client_response}" | cut -d ' ' -f1) + OVHAPI_HTTP_RESPONSE="$(echo "${client_response}" | cut -d ' ' -f2-)" + + _ovhapilib_echo_debug "http_status=${OVHAPI_HTTP_STATUS}" } -## vendors's JSON parsing -# usage : getJSONString "json" field -# remove quotes (first and last character) from wanted field -getJSONString() + +## vendor's JSON.sh parsing functions + +# usage : getJSONKeys "json" +# +# return JSON keys list without double quote if present +getJSONKeys() { - local json="$1" - local field="$2" - local result=$(getJSONValue "${json}" "${field}") - echo ${result:1:-1} + local json="$1" + local json_key= + + echo "${json}" \ + | "${OVHAPI_BASHCLIENT_LIB}/JSON.sh" -l \ + | sed -r "s/\[(.+)\]\s+(.*)/\1/" \ + | while read -r json_key + do + # replacement for key with nested object + json_key=${json_key/\",\"/.} + _trimDoubleQuotes "${json_key}" + done } + # usage : getJSONValue "json" field +# +# if field is a string, it can be set with/without double quotes +# if the result is between double quote, only get the value inside getJSONValue() { local json="$1" local field="$2" - echo ${json} | ${OVHAPI_BASHCLIENT_LIB}/JSON.sh -l | grep "\[${field}\]" | sed -r "s/\[${field}\]\s+(.*)/\1/" + local result= + + # if field is not a number and has double quotes remove them, and always add + if [[ ! ${field} =~ ^[0-9]+$ ]]; then + # replacement for key with nested object + field=${field/./\",\"} + field="$(_trimDoubleQuotes "${field}")" + field="\"${field}\"" + _ovhapilib_echo_debug "field: ${field}" + + fi + + result=$(echo "${json}" | "${OVHAPI_BASHCLIENT_LIB}/JSON.sh" -l | grep -F "[${field}]" | sed -r "s/\[${field}\]\s+(.*)/\1/") + + # when result is between double quotes, remove first and last + result=$(_trimDoubleQuotes "${result}") + if [ -n "${result}" ]; then + echo "${result}" + fi } # usage : getJSONValues "json" -# return one value per line +# +# if key is a number, return only values +# if key is a string, return pair of key:value per line getJSONValues() { local json="$1" - local i=0 - local length=$(getJSONArrayLength "${json}") + local json_keys= + local json_key= + local json_value= - while [ $i -lt ${length} ]; + json_keys=$(getJSONKeys "${json}") + + for json_key in ${json_keys} do - getJSONValue "$json" $i - let i+=1 + json_value=$(getJSONValue "${json}" "${json_key}") + # if key is a number, only value is wanted + if [[ ${json_key} =~ ^[0-9]+$ ]]; then + echo "${json_value}" + else + # key is a field, show with value + echo "${json_key}:${json_value}" + fi done - -} - -# usage : getJSONArrayLength "json" -# return the size of json array -getJSONArrayLength() -{ - local json="$1" - echo ${json} | ${OVHAPI_BASHCLIENT_LIB}/JSON.sh -l | wc -l } diff --git a/samples/list-domains.sh b/samples/list-domains.sh index 00d6f98..e9977d8 100755 --- a/samples/list-domains.sh +++ b/samples/list-domains.sh @@ -1,20 +1,32 @@ #!/usr/bin/env bash -HERE=$(dirname "${BASH_SOURCE[0]}") +HERE=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) source ${HERE}/../ovh-api-lib.sh || exit 1 OvhRequestApi "/me" + if [ "${OVHAPI_HTTP_STATUS}" != "200" ]; then echo "profile error:" - echo ${OVHAPI_HTTP_RESPONSE} + echo "${OVHAPI_HTTP_RESPONSE}" exit fi OvhRequestApi "/domain" -if [ ${OVHAPI_HTTP_STATUS} -eq 200 ]; then - domains=$(getJSONValues "${OVHAPI_HTTP_RESPONSE}") - for domain in ${domains} +if [ "${OVHAPI_HTTP_STATUS}" -eq 200 ]; then + domains=($(getJSONValues "${OVHAPI_HTTP_RESPONSE}")) + echo "number of domains=${#domains[@]}" + + # for example, only list for first domain + #for domain in "${domains[@]}" + for domain in "${domains[0]}" do - echo "- ${domain}" + echo -e "\n== informations about ${domain} ==" + OvhRequestApi "/domain/${domain}" + echo "-- single value --" + # key can be passed with/without double quote + getJSONValue "${OVHAPI_HTTP_RESPONSE}" lastUpdate + getJSONValue "${OVHAPI_HTTP_RESPONSE}" '"transferLockStatus"' + echo "-- get all values --" + getJSONValues "${OVHAPI_HTTP_RESPONSE}" done fi diff --git a/samples/my-informations.sh b/samples/my-informations.sh new file mode 100755 index 0000000..9e6d46b --- /dev/null +++ b/samples/my-informations.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +HERE=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +source ${HERE}/../ovh-api-lib.sh || exit 1 + +OvhRequestApi /me + +if [ "${OVHAPI_HTTP_STATUS}" != "200" ]; then + echo "profile error:" + echo "${OVHAPI_HTTP_RESPONSE}" + exit +else + echo "-- all fields --" + getJSONValues "${OVHAPI_HTTP_RESPONSE}" + echo "-- only some fields --" + getJSONValue "${OVHAPI_HTTP_RESPONSE}" "email" + getJSONValue "${OVHAPI_HTTP_RESPONSE}" "currency.code" + getJSONValue "${OVHAPI_HTTP_RESPONSE}" "currency.symbol" +fi diff --git a/samples/post-domain-TXT-record.sh b/samples/post-domain-TXT-record.sh new file mode 100755 index 0000000..e58ae24 --- /dev/null +++ b/samples/post-domain-TXT-record.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +HERE=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +source ${HERE}/../ovh-api-lib.sh || exit 1 + +OvhRequestApi "/me" + +if [ "${OVHAPI_HTTP_STATUS}" != "200" ]; then + echo "profile error:" + echo "${OVHAPI_HTTP_RESPONSE}" + exit +fi + +if [ -z "${OVH_DOMAIN}" ]; then + echo -e "please set one of your domains with :\nOVH_DOMAIN=your_domain.tld" + echo -e "choose in :\n" + + OvhRequestApi "/domain" + getJSONValues "${OVHAPI_HTTP_RESPONSE}" + exit 1 +fi + +txt_field="ovhapilib" + +txt_value="test1: text with space and quo't'es" + +# avoid backslashes :-) : +CUSTOMDATA=$(cat <