Replace virtlet with kubevirt in plugin_fw_v2
[multicloud/k8s.git] / kud / tests / _functions.sh
1 #!/bin/bash
2 # SPDX-license-identifier: Apache-2.0
3 ##############################################################################
4 # Copyright (c) 2018
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10
11 set -o errexit
12 set -o nounset
13 set -o pipefail
14
15 FUNCTIONS_DIR="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")"
16
17 # Do not overwrite any user modifications to PATH when sourcing
18 # /etc/environment
19 USER_PATH=$PATH
20 source /etc/environment
21 PATH=$USER_PATH:$PATH
22 source $FUNCTIONS_DIR/_common_test.sh
23
24 function print_msg {
25     local msg=$1
26     local RED='\033[0;31m'
27     local NC='\033[0m'
28
29     echo -e "${RED} $msg ---------------------------------------${NC}"
30 }
31
32 function ssh_cluster {
33     master_ip=$(kubectl cluster-info | grep "Kubernetes master" | awk -F '[:/]' '{print $4}')
34     ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${master_ip} -- "$@"
35 }
36
37 function get_ovn_central_address {
38     #Reuse OVN_CENTRAL_ADDRESS if available (bypassable by --force flag)
39     if [[ "${1:-}" != "--force" ]] && [[ -n "${OVN_CENTRAL_ADDRESS:-}" ]]; then
40         echo "${OVN_CENTRAL_ADDRESS}"
41         return 0
42     fi
43
44     local remote_command="ip address show dev $OVN_CENTRAL_INTERFACE primary"
45     declare -a ansible_command=(ansible ovn-central[0] -i \
46                 "${FUNCTIONS_DIR}/../hosting_providers/vagrant/inventory/hosts.ini")
47     declare -a filter=(awk -F '[ \t/]+' \
48                 'BEGIN {r=1} {for (i=1; i<=NF; i++) if ($i == "inet") {print $(i+1); r=0}} END {exit r}')
49     local result
50
51     #Determine OVN_CENTRAL_INTERFACE address
52     if ! result="$("${ansible_command[@]}" -a "${remote_command}")"; then
53         echo "Ansible error for remote host ovn-central[0]" >&2
54         return 1
55     else
56         if [[ "${result}" != *CHANGED* ]]; then
57             echo "Failed to execute command on remote host ovn-central[0]" >&2
58             return 2
59         else
60             if ! result="$("${filter[@]}" <<< "${result}")"; then
61                 echo "Failed to retrieve interface address from command output" >&2
62                 return 3
63             else
64                 echo "${result}:6641"
65             fi
66         fi
67     fi
68 }
69
70 function call_api {
71     #Runs curl with passed flags and provides
72     #additional error handling and debug information
73
74     #Function outputs server response body
75     #and performs validation of http_code
76
77     local status
78     local curl_response_file="$(mktemp -p /tmp)"
79     local curl_common_flags=(-s -w "%{http_code}" -o "${curl_response_file}")
80     local command=(curl "${curl_common_flags[@]}" "$@")
81
82     echo "[INFO] Running '${command[@]}'" >&2
83     if ! status="$("${command[@]}")"; then
84         echo "[ERROR] Internal curl error! '$status'" >&2
85         cat "${curl_response_file}"
86         rm "${curl_response_file}"
87         return 2
88     else
89         echo "[INFO] Server replied with status: ${status}" >&2
90         cat "${curl_response_file}"
91         rm "${curl_response_file}"
92         if [[ "${status:0:1}" =~ [45] ]]; then
93             return 1
94         else
95             return 0
96         fi
97     fi
98 }
99
100 function call_api_nox {
101     # this version doesn't exit the script if there's
102     # an error.
103
104     #Runs curl with passed flags and provides
105     #additional error handling and debug information
106
107     #Function outputs server response body
108     #and performs validation of http_code
109
110     local status
111     local curl_response_file="$(mktemp -p /tmp)"
112     local curl_common_flags=(-s -w "%{http_code}" -o "${curl_response_file}")
113     local command=(curl "${curl_common_flags[@]}" "$@")
114
115     echo "[INFO] Running '${command[@]}'" >&2
116     if ! status="$("${command[@]}")"; then
117         echo "[ERROR] Internal curl error! '$status'" >&2
118         cat "${curl_response_file}"
119         rm "${curl_response_file}"
120     else
121         echo "[INFO] Server replied with status: ${status}" >&2
122         if [[ "${status:0:1}" =~ [45] ]]; then
123             cat "${curl_response_file}"
124         else
125             cat "${curl_response_file}" | jq .
126         fi
127         rm "${curl_response_file}"
128     fi
129 }
130
131 function delete_resource {
132     #Issues DELETE http call to provided endpoint
133     #and further validates by following GET request
134
135     call_api -X DELETE "$1"
136     ! call_api -X GET "$1" >/dev/null
137 }
138
139 # init_network() - This function creates the OVN resouces required by the test
140 function init_network {
141     local fname=$1
142     local router_name="ovn4nfv-master"
143
144     name=$(cat $fname | yq '.spec.name' | xargs)
145     subnet=$(cat $fname  | yq '.spec.subnet' | xargs)
146     gateway=$(cat $fname  | yq '.spec.gateway' | xargs)
147     ovn_central_address=$(get_ovn_central_address)
148
149     router_mac=$(printf '00:00:00:%02X:%02X:%02X' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))
150     ovn-nbctl --may-exist --db tcp:$ovn_central_address ls-add $name -- set logical_switch $name other-config:subnet=$subnet external-ids:gateway_ip=$gateway
151     ovn-nbctl --may-exist --db tcp:$ovn_central_address lrp-add $router_name rtos-$name $router_mac $gateway
152     ovn-nbctl --may-exist --db tcp:$ovn_central_address lsp-add $name stor-$name -- set logical_switch_port stor-$name type=router options:router-port=rtos-$name addresses=\"$router_mac\"
153 }
154
155 # cleanup_network() - This function removes the OVN resources created for the test
156 function cleanup_network {
157     local fname=$1
158
159     name=$(cat $fname | yq '.spec.name' | xargs)
160     ovn_central_address=$(get_ovn_central_address)
161
162     for cmd in "ls-del $name" "lrp-del rtos-$name" "lsp-del stor-$name"; do
163         ovn-nbctl --if-exist --db tcp:$ovn_central_address $cmd
164     done
165 }
166
167 function _checks_args {
168     if [[ -z $1 ]]; then
169         echo "Missing CSAR ID argument"
170         exit 1
171     fi
172     if [[ -z $CSAR_DIR ]]; then
173         echo "CSAR_DIR global environment value is empty"
174         exit 1
175     fi
176     mkdir -p ${CSAR_DIR}/${1}
177 }
178
179 function _destroy {
180     local type=$1
181     local name=$2
182
183     echo "$(date +%H:%M:%S) - $name : Destroying $type"
184     kubectl delete $type $name --ignore-not-found=true --now
185     while kubectl get $type $name &>/dev/null; do
186         echo "$(date +%H:%M:%S) - $name : Destroying $type"
187     done
188 }
189
190 # destroy_deployment() - This function ensures that a specific deployment is
191 # destroyed in Kubernetes
192 function destroy_deployment {
193     local deployment_name=$1
194
195     _destroy "deployment" $deployment_name
196 }
197
198 function _recreate {
199     local type=$1
200     local name=$2
201
202     _destroy $type $name
203     kubectl create -f $name.yaml
204 }
205
206 # wait_deployment() - Wait process to Running status on the Deployment's pods
207 function wait_deployment {
208     local deployment_name=$1
209
210     status_phase=""
211     while [[ $status_phase != "Running" ]]; do
212         new_phase=$(kubectl get pods | grep  $deployment_name | awk '{print $3}')
213         if [[ $new_phase != $status_phase ]]; then
214             echo "$(date +%H:%M:%S) - $deployment_name : $new_phase"
215             status_phase=$new_phase
216         fi
217         if [[ $new_phase == "Err"* ]]; then
218             exit 1
219         fi
220     done
221 }
222
223 # wait_for_pod() - Wait until first pod matched by kubectl filters is in running status
224 function wait_for_pod {
225     #Example usage:
226     # wait_for_pods example_pod
227     # wait_for_pods --namespace test different_pod
228     # wait_for_pods -n test -l app=plugin_test
229
230     status_phase=""
231     while [[ "$status_phase" != "Running" ]]; do
232         new_phase="$(kubectl get pods -o 'go-template={{ index .items 0 "status" "phase" }}' "$@" )"
233         if [[ "$new_phase" != "$status_phase" ]]; then
234             echo "$(date +%H:%M:%S) - Filter=[$*] : $new_phase"
235             status_phase="$new_phase"
236         fi
237         if [[ "$new_phase" == "Err"* ]]; then
238             exit 1
239         fi
240     done
241 }
242
243 # wait_for_deployment() - Wait until the deployment is ready
244 function wait_for_deployment {
245     #Example usage:
246     # wait_for_deployment $DEPLOYMENT_NAME $REPLICAS
247     # wait_for_deployment example_deployment 2
248
249     status="0/"
250
251     while [[ "$status" != $2* ]]; do
252         new_status=`kubectl get deployment -A | grep $1 | awk '{print $3}'`
253         if [[ "$new_status" != "$status" ]]; then
254             status="$new_status"
255         fi
256
257         pod_status=`kubectl get pods -A | grep $1 | awk '{print $4}'`
258         if [[ $pod_status =~ "Err" ]]; then
259             echo "Deployment $1 error"
260             exit 1
261         fi
262     done
263 }
264
265 # wait_for_deployment_status() - Wait until the deployment intent group is the specified status
266 function wait_for_deployment_status {
267     #Example usage:
268     # wait_for_deployment_status {base-url-orchestrator}/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/status Instantiated
269     if [ "$#" -ne 2 ]; then
270         echo "Usage: wait_for_deployment_status URL STATUS"
271         exit 1
272     fi
273     for try in {0..59}; do
274         sleep 1
275         new_phase="$(call_api $1 | jq -r .status)"
276         echo "$(date +%H:%M:%S) - Filter=[$*] : $new_phase"
277         if [[ "$new_phase" == "$2" ]]; then
278             return 0
279         fi
280     done
281     exit 1
282 }
283
284 function setup_type {
285     local type=$1
286     shift;
287
288     if ! $(kubectl version &>/dev/null); then
289         echo "This funtional test requires kubectl client"
290         exit 1
291     fi
292     for name in $@; do
293         _recreate $type $name
294     done
295     sleep 5
296     for name in $@; do
297         wait_deployment $name
298     done
299 }
300
301 function teardown_type {
302     local type=$1
303     shift;
304
305     for name in $@; do
306         _destroy $type $name
307     done
308 }
309
310 # setup() - Base testing setup shared among functional tests
311 function setup {
312     setup_type "deployment" $@
313 }
314
315 # teardown() - Base testing teardown function
316 function teardown {
317     teardown_type "deployment" $@
318 }
319
320 # check_ip_range() - Verifying IP address in address range
321 function check_ip_range {
322     local IP=$1
323     local MASK=$2
324
325     install_ipcalc
326
327     if [[ ! -e /usr/bin/ipcalc ]]; then
328         echo -e "Command 'ipcalc' not found"
329         return 0
330     fi
331
332     if [[ -z ${IP} ]] || [[ -z ${MASK} ]]; then
333             return 1
334     fi
335     min=`/usr/bin/ipcalc $MASK|awk '/HostMin:/{print $2}'`
336     max=`/usr/bin/ipcalc $MASK|awk '/HostMax:/{print $2}'`
337     MIN=`echo $min|awk -F"." '{printf"%.0f\n",$1*256*256*256+$2*256*256+$3*256+$4}'`
338     MAX=`echo $max|awk -F"." '{printf"%.0f\n",$1*256*256*256+$2*256*256+$3*256+$4}'`
339     IPvalue=`echo $IP|awk -F"." '{printf"%.0f\n",$1*256*256*256+$2*256*256+$3*256+$4}'`
340     if [[ "$IPvalue" -gt "$MIN" ]] && [[ "$IPvalue" -lt "$MAX" ]]; then
341         echo -e "$IP in ipset $MASK"
342         return 0
343     fi
344     echo -e "$IP not in ipset $MASK"
345     return 1
346 }
347
348 test_folder=${FUNCTIONS_DIR}