New standard GO project layout
[ric-plt/appmgr.git] / scripts / appmgrcli
diff --git a/scripts/appmgrcli b/scripts/appmgrcli
new file mode 100755 (executable)
index 0000000..ac00485
--- /dev/null
@@ -0,0 +1,363 @@
+#!/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 <<EOF1
+usage: $myname [-h host] [-p port] [-v] command params...
+- command is one of deploy, undeploy, status, subscriptions, health, help
+- (abbreviations dep, undep, stat, subs, heal allowed)
+- Parameters of the commands that may have parameters:
+-- deploy: name of the xapp to deploy
+-- undeploy: name of the xapp to undeploy
+-- status:
+---- No parameters: Lists information about all deployed xapps
+---- xapp name as parameter: Prints information about the given xapp
+---- xapp name and instance: Lists information about the given instance only
+-- subscriptions is followed by sub-command list, add, delete, or modify
+---(abbreviations del and mod for delete and modify are allowed):
+---- list without parameters lists all subscriptions
+---- list with subscription id prints that subscription
+---- add URL eventType maxRetry retryTimer
+------- URL is the URL to notify
+------- eventType one of created,deleted,all
+------- maxRetry and retryTimer are positive decimal numbers
+---- modify id URL eventType maxRetry retryTimer
+------- id is the subscription id (find out with the list command)
+--------the rest of the parameters are like in add
+---- delete id
+------- id is the subscription id to delete (find out with the list command)
+- Default values for host and port can be set in environment
+- variables APPMGR_HOST and APPMGR_PORT
+- Option -v sets verbose mode.
+EOF1
+}
+
+# Defaults
+
+host=localhost
+port=8080
+verbose=0
+
+# Check for environment override
+if [ "x$APPMGR_HOST" != "x" ]; then
+    host="$APPMGR_HOST"
+fi
+if [ "x$APPMGR_PORT" != "x" ]; then
+    port="$APPMGR_PORT"
+fi
+
+# Proper shell option parsing:
+while getopts  "h:p:v" flag
+do
+  # Curiously, getopts does not guard against an argument-requiring option
+  # eating the next option. It also does not handle the -- convention.
+  # Here is how to fix that.
+  if [ "X$OPTARG" = 'X--' ]; then
+    break # Explicit end of options
+  fi
+  if expr -- "$OPTARG" : '-.*' > /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
+    ;;
+  (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
+
+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
+}
+
+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"
+    ;;
+  (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: