#!/bin/sh # # Copyright (c) 2019 AT&T Intellectual Property. # Copyright (c) 2019 Nokia. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # limitations under the License. # ############################# # Simple cli for xapp manager # # In addition to standard shell tools, requires packages "curl" and # "yajl-tools" (the second provides json_reformat on Ubuntu; on Red Hat-style # distributions install "yajl" instead). # myname=appmgrcli usage() { cat < /dev/null ; then echo $myname: Option -$flag has no required value, or value begins with -, echo - which is disallowed. usage exit 1 fi case $flag in (h) host="$OPTARG" ;; (p) port="$OPTARG" ;; (v) verbose=1 ;; (*) echo $myname: Bad option letter or required option argument missing. usage exit 1 ;; esac done # Get rid of the option part shift $((OPTIND-1)) if [ $verbose = 1 ]; then echo "host = $host" echo "port = $port" fi # Verify command case $1 in (deploy|dep) cmd=deploy ;; (undeploy|undep) cmd=undeploy ;; (status|stat) cmd=status ;; (subscriptions|subs) cmd=subscriptions ;; (health|heal) cmd=health ;; (config|upload) cmd=config ;; (help) usage exit 0 ;; (*) if [ "x$1" = "x" ]; then echo "$myname: Missing command" else echo "$myname: Unrecognized command $1" fi usage exit 1 ;; esac if [ $verbose = 1 ]; then echo "Command $cmd params=$2" fi errfile=`mktemp /tmp/appmgr_e.XXXXXXXXXX` resultfile=`mktemp /tmp/appmgr_r.XXXXXXXXXX` # Variable status used for the return value of the whole script. status=0 # Helper for command execution: # Do a rest call with "curl": $1 = method, $2 = path (without host and port # which come from variables), $3 data to POST if needed # returns 0 if OK, and any returned data is in $resultfile # else 1, and error message from curl is in $errfile, which is printed # before returning the 1. # Also sets $status to the return value. # # On curl options: --silent --show-error disables progress bar, but allows # error messages. --connect-timeout 20 limits waiting for connection to # 20 seconds. In practice connection will succeed almost immediately, # or in the case of wrong address not at all. # rest() { local data if [ "x$3" != "x" ]; then data="--data $3" fi if curl --silent --show-error --connect-timeout 20 --header "Content-Type: application/json" -X $1 -o $resultfile "http://${host}:${port}$2" $data 2> $errfile ;then status=0 else cat $errfile status=1 fi return $status } remove_temps () { rm -f $errfile $resultfile } # Execute command ($cmd guaranteed to be valid) # Assumes the API currently implemented. # Functions for each command below (except health which is so simple). base=/ric/v1 base_xapps=$base/xapps base_health=$base/health base_subs=$base/subscriptions base_config=$base/config do_deploy() { if [ "x$1" != "x" ]; then if rest POST $base_xapps \{\"name\":\"$1\"\} ; then json_reformat < $resultfile fi else echo Error: expected the name of xapp to deploy status=1 fi } do_undeploy() { local urlpath urlpath=$base_xapps if [ "x$1" != "x" ]; then urlpath="$urlpath/$1" if rest DELETE $urlpath; then # Currently appmgr returns an empty result if # undeploy is succesfull. Don't reformat file if empty. if [ -s $resultfile ]; then json_reformat < $resultfile else echo "$1 undeployed" fi fi else echo Error: expected the name of xapp to undeploy status=1 fi } do_status() { local urlpath urlpath=$base_xapps if [ "x$1" != "x" ]; then urlpath="$urlpath/$1" fi if [ "x$2" != "x" ]; then urlpath="$urlpath/instances/$2" fi if rest GET $urlpath; then json_reformat < $resultfile fi } # This is a bit more complex. $1 is sub-command: list, add, delete, modify # Validate the subscription data that follows a subscription add or modify # subcommand. $1=URL, $2=eventType, $3=maxRetries, $4=retryTimer # URL must look like URL, event type must be one of created deleted all, # maxRetries and retryTimer must be non-negative numbers. # If errors, sets variable status=1 and prints errors, else leaves # status unchanged. # validate_subscription() { if ! expr "$1" : "^http://.*" \| "$1" : "^https://.*" >/dev/null; then echo "$myname: bad URL $1" status=1 fi if ! [ "$2" = created -o "$2" = deleted -o "$2" = all ]; then echo "$myname: unrecognized event $2" status=1 fi if ! expr "$3" : "^[0-9][0-9]*$" >/dev/null; then echo "$myname: invalid maximum retries count $3" status=1 fi if ! expr "$4" : "^[0-9][0-9]*$" >/dev/null; then echo "$myname: invalid retry time $4" status=1 fi } do_subscriptions() { local urlpath urlpath=$base_subs case $1 in (list) if [ "x$2" != "x" ]; then urlpath="$urlpath/$2" fi if rest GET $urlpath; then json_reformat < $resultfile else status=1 fi ;; (add) validate_subscription "$2" "$3" "$4" "$5" if [ $status = 0 ]; then if rest POST $urlpath \{\"targetUrl\":\"$2\",\"eventType\":\"$3\",\"maxRetries\":$4,\"retryTimer\":$5\} ; then json_reformat < $resultfile else status=1 fi fi ;; (delete|del) if [ "x$2" != "x" ]; then urlpath="$urlpath/$2" else echo "$myname: Subscription id required" status=1 fi if [ $status = 0 ]; then if rest DELETE $urlpath; then # Currently appmgr returns an empty result if # delete is succesfull. Don't reformat file if empty. if [ -s $resultfile ]; then json_reformat < $resultfile else echo "Subscription $2 deleted" fi else status=1 fi fi ;; (modify|mod) if [ "x$2" != "x" ]; then urlpath="$urlpath/$2" else echo "$myname: Subscription id required" status=1 fi if [ $status = 0 ]; then validate_subscription "$3" "$4" "$5" "$6" if [ $status = 0 ]; then if rest PUT $urlpath \{\"targetUrl\":\"$3\",\"eventType\":\"$4\",\"maxRetries\":$5,\"retryTimer\":$6\} ; then json_reformat < $resultfile else status=1 fi fi fi ;; (*) echo "$myname: unrecognized subscriptions subcommand $1" status=1 esac } do_config() { local urlpath urlpath=$base_config case $1 in (get|list) if [ "x$2" != "x" ]; then urlpath="$urlpath/$2" fi if rest GET $urlpath; then json_reformat < $resultfile else status=1 fi ;; (add|update) if rest POST $urlpath "@$2" ; then cat $resultfile else status=1 fi ;; (del|delete|remove|rem) if rest DELETE $urlpath "@$2" ; then cat $resultfile else status=1 fi ;; (*) echo "$myname: unrecognized config subcommand $1" status=1 esac } case $cmd in (deploy) do_deploy "$2" ;; (undeploy) do_undeploy "$2" ;; (status) do_status "$2" "$3" ;; (subscriptions) do_subscriptions "$2" "$3" "$4" "$5" "$6" "$7" ;; (config) do_config "$2" "$3" ;; (health) if rest GET $base_health ; then echo OK else echo NOT OK fi ;; esac remove_temps exit $status # An Emacs hack to set the indentation style of this file # Local Variables: # sh-indentation:2 # End: