Added JWT handling to a1pms
[nonrtric.git] / test / common / testcase_common.sh
index a94d3e2..47d8ced 100755 (executable)
@@ -29,7 +29,8 @@ __print_args() {
        echo "      [--use-staging-image <app-nam>+] [--use-release-image <app-nam>+] [--image-repo <repo-address>]"
        echo "      [--repo-policy local|remote] [--cluster-timeout <timeout-in seconds>] [--print-stats]"
        echo "      [--override <override-environment-filename>] [--pre-clean] [--gen-stats] [--delete-namespaces]"
-       echo "      [--delete-containers] [--endpoint-stats] [--kubeconfig <config-file>]"
+       echo "      [--delete-containers] [--endpoint-stats] [--kubeconfig <config-file>] [--host-path-dir <local-host-dir>]"
+       echo "      [--kubecontext <context-name>] [--docker-host <docker-host-url>] [--docker-proxy <host-or-ip>]"
 }
 
 if [ $# -eq 1 ] && [ "$1" == "help" ]; then
@@ -65,6 +66,10 @@ if [ $# -eq 1 ] && [ "$1" == "help" ]; then
        echo "--delete-containers   -  Delete docker containers before starting tests - but only those created by the test scripts. Docker mode only."
        echo "--endpoint-stats      -  Collect endpoint statistics"
        echo "--kubeconfig          -  Configure kubectl to use cluster specific cluster config file"
+       echo "--host-path-dir       -  (Base-)path on local-hostmounted to all VMs (nodes), for hostpath volumes in kube"
+       echo "--kubecontext         -  Configure kubectl to use a certain context, e.g 'minikube'"
+       echo "--docker-host         -  Configure docker to use docker in e.g. a VM"
+       echo "--docker-proxy        -  Configure ip/host to docker when docker is running in a VM"
        echo ""
        echo "List of app short names supported: "$APP_SHORT_NAMES
        exit 0
@@ -100,11 +105,6 @@ TEST_ENV_VAR_FILE_OVERRIDE=""
 
 echo "Test case started as: ${BASH_SOURCE[$i+1]} "$@
 
-#Localhost constants
-LOCALHOST_NAME="localhost"
-LOCALHOST_HTTP="http://localhost"
-LOCALHOST_HTTPS="https://localhost"
-
 # Var to hold 'auto' in case containers shall be stopped when test case ends
 AUTO_CLEAN=""
 
@@ -135,7 +135,7 @@ IMAGE_CATEGORY="DEV"
 #Var to indicate docker-compose version, V1 or V2
 #V1 names replicated containers <proj-name>_<service-name>_<index>
 #V2 names replicated containers <proj-name>-<service-name>-<index>
-DOCKER_COMPOSE_VERION="V1"
+DOCKER_COMPOSE_VERSION="V1"
 
 # Function to indent cmd output with one space
 indent1() { sed 's/^/ /'; }
@@ -267,9 +267,25 @@ DELETE_KUBE_NAMESPACES=0
 #Var to control if containers shall be delete before test setup
 DELETE_CONTAINERS=0
 
-#Var to configure kubectl from a config file.
+#Var to configure kubectl from a config file or context
 KUBECONF=""
 
+#Localhost, may be set to another host/ip by cmd parameter
+LOCALHOST_NAME="localhost"
+
+#Reseting vars related to token/keys used by kubeproxy when istio is enabled
+#The vars are populated if istio is used in the testcase
+KUBE_PROXY_CURL_JWT=""
+KUBE_PROXY_ISTIO_JWKS_KEYS=""
+
+#Var pointing to dir mounted to each kubernetes node (master and workers)
+#Persistent volumes using "hostpath" are allocated beneath the point.
+#Typically it is a dir on local host mounted to each VM running the master and worker.
+#So the intention is make this dir available so the PODs can be restarted on any
+#node and still access the persistent data
+#If not set from cmd line, the path is defaults to "/tmp"
+HOST_PATH_BASE_DIR=""
+
 #File to keep deviation messages
 DEVIATION_FILE=".tmp_deviations"
 rm $DEVIATION_FILE &> /dev/null
@@ -441,7 +457,7 @@ __collect_endpoint_stats_image_info() {
                return
        fi
        ENDPOINT_STAT_FILE=$TESTLOGS/$ATC/imageinfo_$ATC_$1".log"
-       echo $POLICY_AGENT_IMAGE > $ENDPOINT_STAT_FILE
+       echo $A1PMS_IMAGE > $ENDPOINT_STAT_FILE
 }
 
 #Var for measuring execution time
@@ -824,10 +840,17 @@ while [ $paramerror -eq 0 ] && [ $foundparm -eq 0 ]; do
                                fi
                        else
                            if [ -f  $1 ]; then
-                                       KUBECONF="--kubeconfig $1"
-                                       echo "Option set - Kubeconfig path: "$1
-                                       shift;
-                                       foundparm=0
+                                       if [ ! -z "$KUBECONF" ]; then
+                                               paramerror=1
+                                               if [ -z "$paramerror_str" ]; then
+                                                       paramerror_str="Only one of --kubeconfig/--kubecontext can be set"
+                                               fi
+                                       else
+                                               KUBECONF="--kubeconfig $1"
+                                               echo "Option set - Kubeconfig path: "$1
+                                               shift;
+                                               foundparm=0
+                                       fi
                                else
                                        paramerror=1
                                        if [ -z "$paramerror_str" ]; then
@@ -837,6 +860,93 @@ while [ $paramerror -eq 0 ] && [ $foundparm -eq 0 ]; do
                        fi
                fi
        fi
+       if [ $paramerror -eq 0 ]; then
+               if [ "$1" == "--kubecontext" ]; then
+                       shift;
+                       if [ -z "$1" ]; then
+                               paramerror=1
+                               if [ -z "$paramerror_str" ]; then
+                                       paramerror_str="No context-name found for : '--kubecontext'"
+                               fi
+                       else
+                               if [ ! -z "$KUBECONF" ]; then
+                                       paramerror=1
+                                       if [ -z "$paramerror_str" ]; then
+                                               paramerror_str="Only one of --kubeconfig or --kubecontext can be set"
+                                       fi
+                               else
+                                       KUBECONF="--context $1"
+                                       echo "Option set - Kubecontext name: "$1
+                                       shift;
+                                       foundparm=0
+                               fi
+                       fi
+               fi
+       fi
+       if [ $paramerror -eq 0 ]; then
+               if [ "$1" == "--host-path-dir" ]; then
+                       shift;
+                       if [ -z "$1" ]; then
+                               paramerror=1
+                               if [ -z "$paramerror_str" ]; then
+                                       paramerror_str="No path found for : '--host-path-dir'"
+                               fi
+                       else
+                               HOST_PATH_BASE_DIR=$1
+                               echo "Option set - Host path for kube set to: "$1
+                               shift
+                               foundparm=0
+                       fi
+               fi
+       fi
+       if [ $paramerror -eq 0 ]; then
+               if [ "$1" == "--docker-host" ]; then
+                       shift;
+                       if [ -z "$1" ]; then
+                               paramerror=1
+                               if [ -z "$paramerror_str" ]; then
+                                       paramerror_str="No url found for : '--docker-host'"
+                               fi
+                       else
+                               export DOCKER_HOST="$1"
+                               echo "Option set - DOCKER_HOST set to: "$1
+                               shift
+                               foundparm=0
+                       fi
+               fi
+       fi
+       if [ $paramerror -eq 0 ]; then
+               if [ "$1" == "--docker-host" ]; then
+                       shift;
+                       if [ -z "$1" ]; then
+                               paramerror=1
+                               if [ -z "$paramerror_str" ]; then
+                                       paramerror_str="No url found for : '--docker-host'"
+                               fi
+                       else
+                               export DOCKER_HOST="$1"
+                               echo "Option set - DOCKER_HOST set to: "$1
+                               shift
+                               foundparm=0
+                       fi
+               fi
+       fi
+       if [ $paramerror -eq 0 ]; then
+               if [ "$1" == "--docker-proxy" ]; then
+                       shift;
+                       if [ -z "$1" ]; then
+                               paramerror=1
+                               if [ -z "$paramerror_str" ]; then
+                                       paramerror_str="No ip/host found for : '--docker-proxy'"
+                               fi
+                       else
+                               export LOCALHOST_NAME=$1
+                               echo "Option set - docker proxy set to: "$1
+                               shift
+                               foundparm=0
+                       fi
+               fi
+       fi
 done
 echo ""
 
@@ -854,6 +964,9 @@ if [ $paramerror -eq 1 ]; then
        exit 1
 fi
 
+LOCALHOST_HTTP="http://$LOCALHOST_NAME"
+LOCALHOST_HTTPS="https://$LOCALHOST_NAME"
+
 # sourcing the selected env variables for the test case
 if [ -f "$TEST_ENV_VAR_FILE" ]; then
        echo -e $BOLD"Sourcing env vars from: "$TEST_ENV_VAR_FILE$EBOLD
@@ -998,29 +1111,27 @@ fi
 echo " docker is installed and using versions:"
 echo  "  $(docker version --format 'Client version {{.Client.Version}} Server version {{.Server.Version}}')"
 
-tmp=$(which docker-compose)
-if [ $? -ne 0 ] || [ -z "$tmp" ]; then
-       if [ $RUNMODE == "DOCKER" ]; then
+if [ $RUNMODE == "DOCKER" ]; then
+       tmp=$(which docker-compose)
+       if [ $? -ne 0 ] || [ -z "$tmp" ]; then
                echo -e $RED"docker-compose is required to run the test environment, pls install"$ERED
                exit 1
+       else
+               tmp=$(docker-compose version)
+               echo " docker-compose installed and using version $tmp"
+               if [[ "$tmp" == *'v2'* ]]; then
+                       DOCKER_COMPOSE_VERSION="V2"
+               fi
        fi
 fi
-tmp=$(docker-compose version --short)
-echo " docker-compose installed and using version $tmp"
-if [[ "$tmp" == *'v2'* ]]; then
-       DOCKER_COMPOSE_VERION="V2"
-fi
-
-tmp=$(which kubectl)
-if [ $? -ne 0 ] || [ -z tmp ]; then
-       if [ $RUNMODE == "KUBE" ]; then
+if [ $RUNMODE == "KUBE" ]; then
+       tmp=$(which kubectl)
+       if [ $? -ne 0 ] || [ -z tmp ]; then
                echo -e $RED"kubectl is required to run the test environment in kubernetes mode, pls install"$ERED
                exit 1
-       fi
-else
-       if [ $RUNMODE == "KUBE" ]; then
+       else
                echo " kubectl is installed and using versions:"
-               echo $(kubectl version --short=true) | indent2
+               echo $(kubectl $KUBECONF version --short=true) | indent2
                res=$(kubectl $KUBECONF cluster-info 2>&1)
                if [ $? -ne 0 ]; then
                        echo -e "$BOLD$RED############################################# $ERED$EBOLD"
@@ -1052,6 +1163,16 @@ else
                fi
                echo " Node(s) and container runtime config"
                kubectl $KUBECONF get nodes -o wide | indent2
+               echo ""
+               if [ -z "$HOST_PATH_BASE_DIR" ]; then
+                       HOST_PATH_BASE_DIR="/tmp"
+                       echo " Persistent volumes will be mounted to $HOST_PATH_BASE_DIR on applicable node"
+                       echo " No guarantee that persistent volume data is available on all nodes in the cluster"
+               else
+                       echo "Persistent volumes will be mounted to base dir: $HOST_PATH_BASE_DIR"
+                       echo "Assuming this dir is mounted from each node to a dir on the localhost or other"
+                       echo "file system available to all nodes"
+               fi
        fi
 fi
 
@@ -1709,8 +1830,8 @@ setup_testenvironment() {
                        echo -e " Pulling remote snapshot or staging images my in some case result in pulling newer image versions outside the control of the test engine"
                        export KUBE_IMAGE_PULL_POLICY="Always"
                fi
-               CLUSTER_IP=$(kubectl $KUBECONF config view -o jsonpath={.clusters[0].cluster.server} | awk -F[/:] '{print $4}')
-               echo -e $YELLOW" The cluster hostname/ip is: $CLUSTER_IP"$EYELLOW
+               #CLUSTER_IP=$(kubectl $KUBECONF config view -o jsonpath={.clusters[0].cluster.server} | awk -F[/:] '{print $4}')
+               #echo -e $YELLOW" The cluster hostname/ip is: $CLUSTER_IP"$EYELLOW
 
                echo "================================================================================="
                echo "================================================================================="
@@ -2226,7 +2347,7 @@ __kube_delete_all_resources() {
        namespace=$1
        labelname=$2
        labelid=$3
-       resources="deployments replicaset statefulset services pods configmaps persistentvolumeclaims persistentvolumes serviceaccounts clusterrolebindings"
+       resources="deployments replicaset statefulset services pods configmaps persistentvolumeclaims persistentvolumes serviceaccounts clusterrolebindings secrets authorizationpolicies requestauthentications"
        deleted_resourcetypes=""
        for restype in $resources; do
                ns_flag="-n $namespace"
@@ -2239,7 +2360,7 @@ __kube_delete_all_resources() {
                        ns_flag=""
                        ns_text=""
                fi
-               result=$(kubectl $KUBECONF get $restype $ns_flag -o jsonpath='{.items[?(@.metadata.labels.'$labelname'=="'$labelid'")].metadata.name}')
+               result=$(kubectl $KUBECONF get $restype $ns_flag -o jsonpath='{.items[?(@.metadata.labels.'$labelname'=="'$labelid'")].metadata.name}' 2> /dev/null)
                if [ $? -eq 0 ] && [ ! -z "$result" ]; then
                        deleted_resourcetypes=$deleted_resourcetypes" "$restype
                        for resid in $result; do
@@ -2309,7 +2430,7 @@ __kube_create_namespace() {
                        echo "  Message: $(<./tmp/kubeerr)"
                        return 1
                else
-                       kubectl $KUBECONF label ns $1 autotest=engine
+                       kubectl $KUBECONF label ns $1 autotest=engine > /dev/null
                        echo -e " Creating namespace $1 $GREEN$BOLD OK $EBOLD$EGREEN"
                fi
        else
@@ -2342,7 +2463,7 @@ __kube_delete_namespace() {
        return 0
 }
 
-# Removes a namespace
+# Removes and re-create a namespace
 # args: <namespace>
 # (Not for test scripts)
 clean_and_create_namespace() {
@@ -2360,7 +2481,22 @@ clean_and_create_namespace() {
        if [ $? -ne 0 ]; then
                return 1
        fi
+}
 
+# Add/remove label on non-namespaced kube object
+# args: <api> <instance> <label>
+# (Not for test scripts)
+__kube_label_non_ns_instance() {
+       kubectl $KUBECONF label $1 $2 "$3" 1> /dev/null 2> ./tmp/kubeerr
+       return $?
+}
+
+# Add/remove label on namespaced kube object
+# args: <api> <instance> <namespace> <label>
+# (Not for test scripts)
+__kube_label_ns_instance() {
+       kubectl $KUBECONF label $1 $2 -n $3 "$4" 1> /dev/null 2> ./tmp/kubeerr
+       return $?
 }
 
 # Find the host ip of an app (using the service resource)
@@ -2595,6 +2731,17 @@ __clean_kube() {
                fi
        done
 
+       # Remove istio label on namespaces
+       test_env_namespaces=$(kubectl $KUBECONF get ns  --no-headers -o custom-columns=":metadata.name" -l autotest=engine -l istio-injection=enabled) #Get list of ns created by the test env
+       if [ $? -ne 0 ]; then
+               echo " Cannot get list of namespaces...continues.."
+       else
+               for test_env_ns in $test_env_namespaces; do
+                       echo " Removing istio label on ns: "$test_env_ns
+                       __kube_label_non_ns_instance ns $test_env_ns "istio-injection-"
+               done
+       fi
+
        echo ""
 }
 
@@ -2606,14 +2753,14 @@ clean_environment() {
                __clean_kube
                if [ $PRE_CLEAN -eq 1 ]; then
                        echo " Cleaning docker resouces to free up resources, may take time..."
-                       ../common/clean_docker.sh 2>&1 /dev/null
+                       ../common/clean_docker.sh 2>&1 /dev/null
                        echo ""
                fi
        else
                __clean_containers
                if [ $PRE_CLEAN -eq 1 ]; then
                        echo " Cleaning kubernetes resouces to free up resources, may take time..."
-                       ../common/clean_kube.sh $KUBECONF 2>&1 /dev/null
+                       ../common/clean_kube.sh $KUBECONF 2>&1 /dev/null
                        echo ""
                fi
        fi
@@ -2717,7 +2864,7 @@ __start_container() {
 
        envsubst < $compose_file > "gen_"$compose_file
        compose_file="gen_"$compose_file
-       if [ $DOCKER_COMPOSE_VERION == "V1" ]; then
+       if [ $DOCKER_COMPOSE_VERSION == "V1" ]; then
                docker_compose_cmd="docker-compose"
        else
                docker_compose_cmd="docker compose"
@@ -2790,7 +2937,7 @@ __check_service_start() {
        echo -ne " Container $BOLD${appname}$EBOLD starting${SAMELINE}"
 
 
-       pa_st=false
+       a1pmsst=false
        echo -ne " Waiting for ${ENTITY} ${appname} service status...${SAMELINE}"
        TSTART=$SECONDS
        loop_ctr=0
@@ -2803,7 +2950,7 @@ __check_service_start() {
                        fi
                        echo -ne " Waiting for {ENTITY} $BOLD${appname}$EBOLD service status on ${3}, result: $result${SAMELINE}"
                        echo -ne " The ${ENTITY} $BOLD${appname}$EBOLD$GREEN is alive$EGREEN, responds to service status:$GREEN $result $EGREEN on ${url} after $(($SECONDS-$TSTART)) seconds"
-                       pa_st=true
+                       a1pmsst=true
                        break
                else
                        TS_TMP=$SECONDS
@@ -2819,7 +2966,7 @@ __check_service_start() {
                let loop_ctr=loop_ctr+1
        done
 
-       if [ "$pa_st" = "false"  ]; then
+       if [ "$a1pmsst" = "false"  ]; then
                ((RES_CONF_FAIL++))
                echo -e $RED" The ${ENTITY} ${appname} did not respond to service status on ${url} in $(($SECONDS-$TSTART)) seconds"$ERED
                return 1
@@ -2851,7 +2998,7 @@ __check_container_logs() {
 
        #tmp=$(docker ps | grep $appname)
        tmp=$(docker ps -q --filter name=$appname) #get the container id
-       if [ -z "$tmp" ]; then  #Only check logs for running Policy Agent apps
+       if [ -z "$tmp" ]; then  #Only check logs for running A1PMS apps
                echo " "$dispname" is not running, no check made"
                return
        fi
@@ -2929,6 +3076,7 @@ store_logs() {
 ## Generic curl
 ###############
 # Generic curl function, assumes all 200-codes are ok
+# Used proxy, set
 # args: <valid-curl-args-including full url>
 # returns: <returned response (without respose code)>  or "<no-response-from-server>" or "<not found, <http-code>>""
 # returns: The return code is 0 for ok and 1 for not ok
@@ -2942,7 +3090,57 @@ __do_curl() {
                        proxyflag=" --proxy-insecure --proxy $KUBE_PROXY_PATH"
                fi
        fi
-       curlString="curl -skw %{http_code} $proxyflag $@"
+
+       if [ ! -z "$KUBE_PROXY_CURL_JWT" ]; then
+               jwt="-H "\""Authorization: Bearer $KUBE_PROXY_CURL_JWT"\"
+               curlString="curl -skw %{http_code} $proxyflag $@"
+               echo " CMD: $curlString $jwt" >> $HTTPLOG
+               res=$($curlString -H "Authorization: Bearer $KUBE_PROXY_CURL_JWT")
+               retcode=$?
+       else
+               curlString="curl -skw %{http_code} $proxyflag $@"
+               echo " CMD: $curlString" >> $HTTPLOG
+               res=$($curlString)
+               retcode=$?
+       fi
+       echo " RESP: $res" >> $HTTPLOG
+       echo " RETCODE: $retcode" >> $HTTPLOG
+       if [ $retcode -ne 0 ]; then
+               echo "<no-response-from-server>"
+               return 1
+       fi
+       http_code="${res:${#res}-3}"
+       if [ ${#res} -eq 3 ]; then
+               if [ $http_code -lt 200 ] || [ $http_code -gt 299 ]; then
+                       echo "<no-response-from-server>"
+                       return 1
+               else
+                       return 0
+               fi
+       else
+               if [ $http_code -lt 200 ] || [ $http_code -gt 299 ]; then
+                       echo "<not found, resp:${http_code}>"
+                       return 1
+               fi
+               if [ $# -eq 2 ]; then
+                       echo "${res:0:${#res}-3}" | xargs
+               else
+                       echo "${res:0:${#res}-3}"
+               fi
+
+               return 0
+       fi
+
+}
+
+# Generic curl function, assumes all 200-codes are ok
+# Uses no proxy, even if it is set
+# args: <valid-curl-args-including full url>
+# returns: <returned response (without respose code)>  or "<no-response-from-server>" or "<not found, <http-code>>""
+# returns: The return code is 0 for ok and 1 for not ok
+__do_curl_no_proxy() {
+       echo ${FUNCNAME[1]} "line: "${BASH_LINENO[1]} >> $HTTPLOG
+       curlString="curl -skw %{http_code} $@"
        echo " CMD: $curlString" >> $HTTPLOG
        res=$($curlString)
        retcode=$?
@@ -2966,9 +3164,9 @@ __do_curl() {
                        return 1
                fi
                if [ $# -eq 2 ]; then
-                       echo "${res:0:${#res}-3}" | xargs
+                       echo "${res:0:${#res}-3}" | xargs
                else
-                       echo "${res:0:${#res}-3}"
+                       echo "${res:0:${#res}-3}"
                fi
 
                return 0