github.com/zhyoulun/cilium@v1.6.12/tests/helpers.bash (about) 1 #!/usr/bin/env bash 2 3 CILIUM_FILES="cilium-files" 4 DUMP_FILE=$(mktemp) 5 MONITOR_PID="" 6 LAST_LOG_DATE="" 7 TEST_NET=cilium 8 GOPS="/home/vagrant/go/bin/gops" 9 10 # Variables used during Jenkins builds. 11 BUILD_NUM="${BUILD_NUMBER:-0}" 12 JOB_BASE="${JOB_BASE_NAME:-local}" 13 BUILD_ID="${JOB_BASE}-${BUILD_NUM}" 14 15 AGENT_SOCK_PATH=/var/run/cilium/cilium.sock 16 17 # Prefer local build if binary file detected. 18 for bin in "../cilium/cilium" \ 19 "../daemon/cilium-agent" \ 20 "../plugins/cilium-docker/cilium-docker"; do 21 if [ -f $bin ]; then 22 export PATH=$PWD/`dirname $bin`:$PATH 23 fi 24 done 25 26 # Prevent Fedora rules in raw table from affecting the test. 27 ip6tables -t raw -F 2> /dev/null || true 28 29 function log { 30 local save=$- 31 set +u 32 check_num_params "$#" "1" 33 message=$1 34 local stack 35 for (( i=${#FUNCNAME[@]}-1 ; i>0 ; i-- )) ; do 36 if [[ "${stack}" == "" ]]; then 37 stack="$(basename $0): ${FUNCNAME[i]}" 38 else 39 stack="$stack/${FUNCNAME[i]}" 40 fi 41 done 42 echo "----- ${stack}: $message" 43 restore_flag $save "u" 44 } 45 46 # Usage: overwrite $iter 'commands --option --foo bar "quoted args" ' 47 # Executes the commands provided as parameters, moves the cursor back by the 48 # number of lines output by the command, then prints the output of the command. 49 # If $iter is zero, then the cursor is not moved; this is equivalent to 50 # 'shift; eval "$@"'. 51 function overwrite { 52 local iter=$1 53 shift 54 55 local output=$(eval "$@") 56 if [ ! -z $TERM ] && [ $iter -ne 0 ]; then 57 local ERASER=$(tput cuu1 ; tput el) 58 local n_lines=$(echo "$output" | wc -l) 59 for i in $(seq 1 $n_lines); do 60 echo -ne "$ERASER" 61 done 62 fi 63 echo "$output" 64 } 65 66 function get_filename_without_extension { 67 check_num_params "$#" "1" 68 local file=$(basename $1) 69 local filename="${file%.*}" 70 echo $filename 71 } 72 # Note: if you call this, do not change the value of the debug flag - you will make the shell segmentation fault :) 73 function redirect_debug_logs { 74 check_num_params "$#" "1" 75 local LOGS_DIR=$1 76 mkdir -p ${LOGS_DIR} 77 exec {BASH_XTRACEFD}>>${LOGS_DIR}/debug.txt 78 } 79 80 function monitor_start { 81 local save=$- 82 set +e 83 log "starting monitor and dumping contents to $DUMP_FILE" 84 cilium monitor -v $@ > $DUMP_FILE & 85 MONITOR_PID=$! 86 restore_flag $save "e" 87 } 88 89 function monitor_resume { 90 local save=$- 91 set +e 92 log "resuming monitor and dumping contents to $DUMP_FILE" 93 cilium monitor -v $@ >> $DUMP_FILE & 94 MONITOR_PID=$! 95 restore_flag $save "e" 96 } 97 98 function monitor_clear { 99 local save=$- 100 set +e 101 log "clearing monitor" 102 cp /dev/null $DUMP_FILE 103 nstat > /dev/null 104 restore_flag $save "e" 105 } 106 107 function monitor_dump { 108 local save=$- 109 set +e 110 nstat 111 cat $DUMP_FILE 112 restore_flag $save "e" 113 } 114 115 function monitor_stop { 116 local save=$- 117 set +e 118 if [ ! -z "$MONITOR_PID" ]; then 119 kill $MONITOR_PID || true > /dev/null 2>&1 120 fi 121 restore_flag $save "e" 122 } 123 124 function logs_clear { 125 LAST_LOG_DATE="$(date +'%F %T')" 126 } 127 128 function abort { 129 set +e 130 echo "------------------------------------------------------------------------" 131 echo " Test Failed" 132 echo "$*" 133 echo "" 134 echo "------------------------------------------------------------------------" 135 136 if [ ! -z "$DEBUG" ]; then 137 cilium status 138 cilium endpoint list 139 cilium policy get 140 read -n 1 -p "Press any key to continue..." 141 fi 142 143 monitor_dump 144 monitor_stop 145 146 echo "------------------------------------------------------------------------" 147 echo " Cilium logs (last 200 lines)" 148 journalctl --no-pager --since "${LAST_LOG_DATE}" -u cilium | tail -n 200 149 echo "" 150 echo "------------------------------------------------------------------------" 151 152 exit 1 153 } 154 155 function micro_sleep { 156 sleep 0.5 157 } 158 159 function kafka_consumer_delay { 160 # wait for kafka consumer to come up 161 sleep 5 162 } 163 164 function to_services_delay { 165 sleep 5 166 } 167 168 function restore_flag { 169 check_num_params "$#" "2" 170 local save=$1 171 local flag=$2 172 if [[ $save =~ $2 ]]; then 173 set -$2 174 fi 175 } 176 177 function check_num_params { 178 local NUM_PARAMS=$1 179 local NUM_EXPECTED_PARAMS=$2 180 if [ "$NUM_PARAMS" -ne "$NUM_EXPECTED_PARAMS" ]; then 181 echo "${FUNCNAME[ 1 ]}: invalid number of parameters, expected $NUM_EXPECTED_PARAMS parameter(s)" 182 exit 1 183 fi 184 } 185 186 function wait_for_endpoints { 187 local save=$- 188 set +e 189 check_num_params "$#" "1" 190 local NUM_DESIRED="$1" 191 local CMD="cilium endpoint list | grep -v -e \"not-ready\" -e \"reserved\" | grep ready -c || true" 192 local INFO_CMD="cilium endpoint list" 193 local MAX_MINS="2" 194 local ERROR_OUTPUT="Timeout while waiting for $NUM_DESIRED endpoints" 195 log "waiting for up to ${MAX_MINS} mins for ${NUM_DESIRED} endpoints to be in \"ready\" state" 196 wait_for_desired_state "$NUM_DESIRED" "$CMD" "$INFO_CMD" "$MAX_MINS" "$ERROR_OUTPUT" 197 log "done waiting for up to ${MAX_MINS} mins for ${NUM_DESIRED} endpoints to be in \"ready\" state" 198 restore_flag $save "e" 199 } 200 201 function wait_for_endpoints_deletion { 202 local save=$- 203 set +e 204 local NUM_DESIRED="2" # When no endpoints are present there should be two lines only. 205 local CMD="cilium endpoint list | grep -v \"reserved\" | wc -l || true" 206 local INFO_CMD="cilium endpoint list" 207 local MAX_MINS="2" 208 local ERROR_OUTPUT="Timeout while waiting for endpoint removal" 209 log "waiting for up to ${MAX_MINS} mins for all endpoints to be removed" 210 wait_for_desired_state "$NUM_DESIRED" "$CMD" "$INFO_CMD" "$MAX_MINS" "$ERROR_OUTPUT" 211 log "done waiting" 212 restore_flag $save "e" 213 } 214 215 function k8s_num_ready { 216 local save=$- 217 set +e 218 local NAMESPACE=$1 219 local CILIUM_POD=$2 220 local FILTER=$3 221 kubectl -n ${NAMESPACE} exec ${CILIUM_POD} cilium endpoint list | grep $FILTER | grep -v -e 'not-ready' -e 'reserved' | grep -c 'ready' || true 222 restore_flag $save "e" 223 } 224 225 function wait_for_k8s_endpoints { 226 local save=$- 227 set +e 228 check_num_params "$#" "4" 229 local NAMESPACE=$1 230 local CILIUM_POD=$2 231 local NUM=$3 232 local FILTER=$4 233 log "Waiting for $NUM endpoints in namespace $NAMESPACE managed by $CILIUM_POD" 234 235 # Wait some time for at least one endpoint to get into regenerating state 236 # FIXME: Remove when this is reliable 237 sleep 5 238 239 local sleep_time=1 240 local iter=0 241 local found 242 found=$(k8s_num_ready "${NAMESPACE}" "${CILIUM_POD}" "${FILTER}") 243 log "found: $found" 244 while [[ "$found" -ne "$NUM" ]]; do 245 if [[ $iter -gt $((5*60/$sleep_time)) ]]; then 246 echo "" 247 log "Timeout while waiting for $NUM endpoints" 248 restore_flag $save "e" 249 exit 1 250 else 251 overwrite $iter ' 252 kubectl -n ${NAMESPACE} exec ${CILIUM_POD} cilium endpoint list 253 echo -n " [${found}/${NUM}]" 254 ' 255 sleep $sleep_time 256 fi 257 found=$(k8s_num_ready "${NAMESPACE}" "${CILIUM_POD}" "${FILTER}") 258 log "found: $found" 259 ((iter++)) 260 done 261 262 overwrite $iter 'kubectl -n ${NAMESPACE} exec ${CILIUM_POD} cilium endpoint list' 263 restore_flag $save "e" 264 } 265 266 function wait_for_cilium_status { 267 local NUM_DESIRED="1" 268 local CMD="cilium status | grep 'Cilium:' | grep -c OK || true" 269 local INFO_CMD="true" 270 local MAX_MINS="1" 271 local ERROR_OUTPUT="Timeout while waiting for Cilium to be ready" 272 wait_for_desired_state "$NUM_DESIRED" "$CMD" "$INFO_CMD" "$MAX_MINS" "$ERROR_OUTPUT" 273 } 274 275 function wait_for_kubectl_cilium_status { 276 check_num_params "$#" "2" 277 namespace=$1 278 pod=$2 279 local NUM_DESIRED="1" 280 local CMD="kubectl -n ${namespace} exec ${pod} cilium status | grep "Cilium:" | grep -c 'OK' || true" 281 local INFO_CMD="true" 282 local MAX_MINS="2" 283 local ERROR_OUTPUT="Timeout while waiting for Cilium to be ready" 284 wait_for_desired_state "$NUM_DESIRED" "$CMD" "$INFO_CMD" "$MAX_MINS" "$ERROR_OUTPUT" 285 } 286 287 function wait_for_cilium_ep_gen { 288 local save=$- 289 set +e 290 local MODE=$1 291 292 local NAMESPACE 293 local POD 294 local CMD 295 local INFO_CMD 296 297 if [[ "$MODE" == "k8s" ]]; then 298 # Only care about provided params if mode is K8s. 299 check_num_params "$#" "3" 300 log "mode is K8s" 301 NAMESPACE=$2 302 POD=$3 303 CMD="kubectl exec -n ${NAMESPACE} ${POD} -- cilium endpoint list | grep -c regenerat" 304 INFO_CMD="kubectl exec -n ${NAMESPACE} ${POD} -- cilium endpoint list" 305 else 306 CMD="cilium endpoint list | grep -c regenerat" 307 INFO_CMD="cilium endpoint list" 308 fi 309 310 local NUM_DESIRED="0" 311 local MAX_MINS="2" 312 local ERROR_OUTPUT="Timeout while waiting for endpoints to regenerate" 313 local sleep_time=1 314 315 local iter=0 316 local found 317 found=$(eval "$CMD") 318 319 while [[ "$found" -ne "$NUM_DESIRED" ]]; do 320 log "$found endpoints are still regenerating; want $NUM_DESIRED" 321 if [[ $((iter++)) -gt $((${MAX_MINS}*60/$sleep_time)) ]]; then 322 echo "" 323 log "${ERROR_OUTPUT}" 324 exit 1 325 else 326 overwrite $iter ' 327 log "still within time limit for waiting for endpoints to be in 'ready' state; sleeping and checking again" 328 log "output of ${INFO_CMD}" 329 eval "$INFO_CMD" 330 echo -n " [$found/$NUM_DESIRED]" 331 log "sleeping for $sleep_time" 332 ' 333 sleep $sleep_time 334 fi 335 log "evaluating $CMD" 336 found=$(eval "${CMD}") 337 log "found: $found" 338 done 339 set -e 340 restore_flag $save "e" 341 } 342 343 function wait_for_daemon_set_not_ready { 344 local save=$- 345 set +e 346 check_num_params "$#" "2" 347 348 local namespace="${1}" 349 local name="${2}" 350 351 log "Waiting for instances of Cilium daemon $name in namespace $namespace to be clean up" 352 353 local sleep_time=2 354 local iter=0 355 local found="0" 356 until [[ "$found" -eq "1" ]]; do 357 if [[ $iter -gt $((5*60/$sleep_time)) ]]; then 358 echo "" 359 log "Timeout while waiting for cilium agent to be clean up by kubernetes" 360 print_k8s_cilium_logs 361 exit 1 362 else 363 overwrite $iter 'kubectl -n ${namespace} get pods -o wide' 364 sleep $sleep_time 365 fi 366 kubectl get pods -n ${namespace} | grep ${name} -q 367 found=$? 368 ((iter++)) 369 done 370 371 overwrite $iter 'kubectl -n kube-system get pods -o wide' 372 restore_flag $save "e" 373 } 374 375 function wait_for_policy_enforcement { 376 check_num_params "$#" "1" 377 local NUM_DESIRED="$1" 378 local CMD="cilium endpoint list | grep -c Disabled" 379 local INFO_CMD="cilium endpoint list" 380 local MAX_MINS="2" 381 local ERROR_OUTPUT="Timeout while waiting for policy to be enabled for all endpoints" 382 wait_for_desired_state "$NUM_DESIRED" "$CMD" "$INFO_CMD" "$MAX_MINS" "$ERROR_OUTPUT" 383 } 384 385 function count_lines_in_log { 386 echo `wc -l $DUMP_FILE | awk '{ print $1 }'` 387 } 388 389 function wait_for_log_entries { 390 check_num_params "$#" "1" 391 local expected=$(($1 + $(count_lines_in_log))) 392 wait_specified_time_test "test \"\$(count_lines_in_log)\" -ge \"$expected\"" "2" 393 } 394 395 function wait_for_docker_ipv6_addr { 396 check_num_params "$#" "1" 397 name=$1 398 wait_specified_time_test "test \"\$(docker inspect --format '{{ .NetworkSettings.Networks.cilium.GlobalIPv6Address }}' $name)\" != \"\"" "2" 399 } 400 401 function wait_for_running_pod { 402 pod=$1 403 namespace=${2:-default} 404 log "Waiting for ${pod} pod to be Running..." 405 wait_specified_time_test "test \"\$(kubectl get pods -n ${namespace} -o wide | grep ${pod} | grep -c Running)\" -eq \"1\"" "10" 406 } 407 408 function wait_for_no_pods { 409 namespace=${1:-default} 410 log "Waiting for no pods to be Running in namespace ${namespace}" 411 wait_specified_time_test "test \"\$(kubectl get pods -n ${namespace} -o wide 2>&1 | grep -c 'No resources found')\" -eq \"1\"" "5" 412 } 413 414 function wait_for_n_running_pods { 415 local save=$- 416 set +e 417 check_num_params "$#" "1" 418 local NPODS=$1 419 log "Waiting for $NPODS running pods" 420 421 local sleep_time=1 422 local iter=0 423 local found 424 found=$(kubectl get pod | grep Running -c || true) 425 until [[ "$found" -eq "$NPODS" ]]; do 426 if [[ $iter -gt $((5*60/$sleep_time)) ]]; then 427 echo "" 428 log "Timeout while waiting for $NPODS running pods" 429 exit 1 430 else 431 overwrite $iter ' 432 kubectl get pod -o wide 433 echo -n " [${found}/${NPODS}]" 434 ' 435 sleep $sleep_time 436 fi 437 found=$(kubectl get pod | grep Running -c || true) 438 ((iter++)) 439 done 440 441 overwrite $iter 'kubectl get pod -o wide' 442 restore_flag $save "e" 443 } 444 445 # Wait for healthy k8s cluster on $1 nodes 446 function wait_for_healthy_k8s_cluster { 447 local save=$- 448 set +e 449 local NNODES=$1 450 log "Waiting for healthy k8s cluster with $NNODES nodes" 451 452 local sleep_time=2 453 local iter=0 454 local found 455 found=$(kubectl get cs | grep -v "STATUS" | grep -c "Healthy") 456 until [[ "$found" -eq "3" ]]; do 457 if [[ $iter -gt $((1*60/$sleep_time)) ]]; then 458 echo "" 459 log "Timeout while waiting for healthy kubernetes cluster" 460 exit 1 461 else 462 overwrite $iter ' 463 kubectl get cs 464 log "K8S Components ready: [${found}/3]" 465 ' 466 sleep $sleep_time 467 fi 468 found=$(kubectl get cs | grep -v "STATUS" | grep -c "Healthy") 469 ((iter++)) 470 done 471 overwrite $iter 'kubectl get cs' 472 local iter=0 473 local found 474 found=$(kubectl get nodes | grep Ready -c) 475 until [[ "$found" -eq "$NNODES" ]]; do 476 if [[ $iter -gt $((1*60/$sleep_time)) ]]; then 477 echo "" 478 log "Timeout while waiting for all nodes to be Ready" 479 exit 1 480 else 481 overwrite $iter ' 482 kubectl get nodes 483 log "Nodes ready [${found}/${NNODES}]" 484 ' 485 sleep $sleep_time 486 fi 487 found=$(kubectl get nodes | grep Ready -c) 488 ((iter++)) 489 done 490 restore_flag $save "e" 491 } 492 493 function k8s_nodes_policy_status { 494 local save=$- 495 set +e 496 local sleep_time=2 497 local NNODES=$1 498 local policy_ns=$2 499 local policy_name=$3 500 local iter=0 501 local nodes=$(kubectl get ciliumnetworkpolicies -n "${policy_ns}" "${policy_name}" -o go-template --template='{{len .status.nodes}}') 502 until [[ "${nodes}" -eq "${NNODES}" ]]; do 503 if [[ $iter -gt $((1*60/$sleep_time)) ]]; then 504 echo "" 505 log "Timeout while waiting for $NNODES to have policy ${policy_ns}/${policy_name} installed" 506 exit 1 507 else 508 overwrite $iter ' 509 kubectl get nodes 510 log "Nodes with policy accepted [${found}/${NNODES}]" 511 ' 512 sleep $sleep_time 513 fi 514 found=$(kubectl get nodes | grep Ready -c) 515 ((iter++)) 516 done 517 518 kubectl get ciliumnetworkpolicies -n "${policy_ns}" "${policy_name}" -o go-template --template='{{.status.nodes}}' 519 restore_flag $save "e" 520 } 521 522 function gather_files { 523 local TEST_NAME=$1 524 local TEST_SUITE=$2 525 log "gathering files for test $TEST_NAME in test suite $TEST_SUITE" 526 local CILIUM_ROOT="src/github.com/cilium/cilium" 527 if [ -z "${TEST_SUITE}" ]; then 528 TEST_SUITE="runtime-tests" 529 fi 530 if [ -z "${GOPATH}" ]; then 531 local GOPATH="/home/vagrant/go" 532 fi 533 if [[ "${TEST_SUITE}" == "runtime-tests" ]]; then 534 CILIUM_DIR="${GOPATH}/${CILIUM_ROOT}/tests/cilium-files/${TEST_NAME}" 535 elif [[ "${TEST_SUITE}" == "k8s-tests" ]]; then 536 CILIUM_DIR="${GOPATH}/${CILIUM_ROOT}/tests/k8s/tests/cilium-files/${TEST_NAME}" 537 else 538 log "${TEST_SUITE} not a valid value, continuing" 539 CILIUM_DIR="${GOPATH}/${CILIUM_ROOT}/tests/cilium-files/${TEST_NAME}" 540 fi 541 local RUN="/var/run/cilium" 542 local LIB="/var/lib/cilium" 543 local RUN_DIR="${CILIUM_DIR}${RUN}" 544 local LIB_DIR="${CILIUM_DIR}${LIB}" 545 mkdir -p "${CILIUM_DIR}" 546 mkdir -p "${RUN_DIR}" 547 mkdir -p "${LIB_DIR}" 548 if [[ "${TEST_SUITE}" == "runtime-tests" ]]; then 549 local CLI_OUT_DIR="${CILIUM_DIR}/cli" 550 local PROF_OUT_DIR="${CILIUM_DIR}/profiling" 551 mkdir -p "${CLI_OUT_DIR}" 552 dump_cli_output "${CLI_OUT_DIR}" || true 553 dump_gops_output "${PROF_OUT_DIR}" "cilium-agent" || true 554 # Get logs from Consul container. 555 mkdir -p "${CILIUM_DIR}/consul" 556 docker logs cilium-consul > "${CILIUM_DIR}/consul/consul-logs.txt" 2>/dev/null 557 else 558 # Get logs from each Cilium pod. 559 local NAMESPACE="kube-system" 560 local CILIUM_POD_1=$(kubectl -n ${NAMESPACE} get pods -l k8s-app=cilium | awk 'NR==2{ print $1 }') 561 local CILIUM_POD_2=$(kubectl -n ${NAMESPACE} get pods -l k8s-app=cilium | awk 'NR==3{ print $1 }') 562 local CLI_OUT_DIR=${CILIUM_DIR}/cli 563 mkdir -p "${CLI_OUT_DIR}" 564 log "gathering Cilium logs from pod ${CILIUM_POD_1}" 565 dump_cli_output_k8s "${CLI_OUT_DIR}" "${NAMESPACE}" "${CILIUM_POD_1}" || true 566 log "gathering Cilium logs from pod ${CILIUM_POD_2}" 567 dump_cli_output_k8s "${CLI_OUT_DIR}" "${NAMESPACE}" "${CILIUM_POD_2}" || true 568 fi 569 sudo cp -r ${RUN}/state "${RUN_DIR}" || true 570 sudo cp ${RUN}/*.log "${RUN_DIR}" || true 571 sudo cp -r ${LIB}/* "${LIB_DIR}" || true 572 find "${CILIUM_DIR}" -type d -exec sudo chmod 777 {} \; 573 find "${CILIUM_DIR}" -exec sudo chmod a+r {} \; 574 log "finished gathering files for test $TEST_NAME in test suite $TEST_SUITE" 575 } 576 577 function dump_cli_output { 578 check_num_params "$#" "1" 579 local DIR=$1 580 cilium endpoint list > ${DIR}/endpoint_list.txt 581 local EPS=$(cilium endpoint list | tail -n+3 | grep '^[0-9]' | awk '{print $1}') 582 for ep in ${EPS} ; do 583 cilium endpoint get ${ep} > ${DIR}/endpoint_get_${ep}.txt 584 cilium bpf policy get ${ep} > ${DIR}/bpf_policy_list_${ep}.txt 585 done 586 cilium service list > ${DIR}/service_list.txt 587 local SVCS=$(cilium service list | tail -n+2 | awk '{print $1}') 588 for svc in ${SVCS} ; do 589 cilium service get ${svc} > ${DIR}/service_get_${svc}.txt 590 done 591 local IDS=$(cilium endpoint list | tail -n+3 | awk '{print $4}' | grep -o '[0-9]*') 592 for id in ${IDS} ; do 593 cilium identity get ${id} > ${DIR}/identity_get_${id}.txt 594 done 595 cilium config > ${DIR}/config.txt 596 cilium bpf lb list > ${DIR}/bpf_lb_list.txt 597 cilium bpf ct list global > ${DIR}/bpf_ct_list_global.txt 598 cilium bpf tunnel list > ${DIR}/bpf_tunnel_list.txt 599 cilium policy get > ${DIR}/policy_get.txt 600 cilium status > ${DIR}/status.txt 601 cilium debuginfo -f ${DIR}/debuginfo.txt 602 cilium-bugtool -t ${DIR} 603 } 604 605 function dump_cli_output_k8s { 606 check_num_params "$#" "3" 607 local DIR=$1 608 local NAMESPACE=$2 609 local POD=$3 610 kubectl exec -n ${NAMESPACE} ${POD} -- cilium endpoint list > ${DIR}/${POD}_endpoint_list.txt 611 local EPS=$(kubectl exec -n ${NAMESPACE} ${POD} -- cilium endpoint list | tail -n+3 | grep '^[0-9]' | awk '{print $1}') 612 for ep in ${EPS} ; do 613 kubectl exec -n ${NAMESPACE} ${POD} -- cilium endpoint get ${ep} > ${DIR}/${POD}_endpoint_get_${ep}.txt 614 kubectl exec -n ${NAMESPACE} ${POD} -- cilium bpf policy get ${ep} > ${DIR}/${POD}_bpf_policy_list_${ep}.txt 615 done 616 kubectl exec -n ${NAMESPACE} ${POD} -- cilium service list > ${DIR}/${POD}_service_list.txt 617 local SVCS=$(kubectl exec -n ${NAMESPACE} ${POD} -- cilium service list | tail -n+2 | awk '{print $1}') 618 for svc in ${SVCS} ; do 619 kubectl exec -n ${NAMESPACE} ${POD} -- cilium service get ${svc} > ${DIR}/${POD}_service_get_${svc}.txt 620 done 621 local IDS=$(kubectl exec -n ${NAMESPACE} ${POD} -- cilium endpoint list | tail -n+3 | awk '{print $4}' | grep -o '[0-9]*') 622 for id in ${IDS} ; do 623 kubectl exec -n ${NAMESPACE} ${POD} -- cilium identity get ${id} > ${DIR}/${POD}_identity_get_${id}.txt 624 done 625 kubectl exec -n ${NAMESPACE} ${POD} -- cilium config > ${DIR}/${POD}_config.txt 626 kubectl exec -n ${NAMESPACE} ${POD} -- cilium bpf lb list > ${DIR}/${POD}_bpf_lb_list.txt 627 kubectl exec -n ${NAMESPACE} ${POD} -- cilium bpf ct list global > ${DIR}/${POD}_bpf_ct_list_global.txt 628 kubectl exec -n ${NAMESPACE} ${POD} -- cilium bpf tunnel list > ${DIR}/${POD}_bpf_tunnel_list.txt 629 kubectl exec -n ${NAMESPACE} ${POD} -- cilium policy get > ${DIR}/${POD}_policy_get.txt 630 kubectl exec -n ${NAMESPACE} ${POD} -- cilium status > ${DIR}/${POD}_status.txt 631 kubectl exec -n ${NAMESPACE} ${POD} -- cilium debuginfo > ${DIR}/${POD}_debuginfo.txt 632 local DEBUGTOOL_ARCHIVE=`kubectl exec -n ${NAMESPACE} ${POD} -- cilium-bugtool | grep ARCHIVE | awk '{ print $3}'` 633 kubectl cp ${NAMESPACE}/${POD}:${DEBUGTOOL_ARCHIVE} ${DIR}/${POD}_bugtool.tar 634 } 635 636 function dump_gops_output { 637 check_num_params "$#" "2" 638 local DIR="$1" 639 local PROG="$2" 640 local PROG_PROFILING_DIR="${DIR}/${PROG}" 641 mkdir -p "${PROG_PROFILING_DIR}" 642 log "getting gops output for ${PROG} and dumping to dir ${PROG_PROFILING_DIR}" 643 local PROG_PID=$(sudo ${GOPS} | grep "${PROG}" | awk '{print $1}') 644 log "running \"gops stack\" for ${PROG}" 645 sudo ${GOPS} stack ${PROG_PID} > "${PROG_PROFILING_DIR}/${PROG}_stack.txt" 646 log "running \"gops memstats\" for ${PROG}" 647 sudo ${GOPS} memstats ${PROG_PID} > "${PROG_PROFILING_DIR}/${PROG}_memstats.txt" 648 log "running \"gops stats\" for ${PROG}" 649 sudo ${GOPS} stats ${PROG_PID} > "${PROG_PROFILING_DIR}/${PROG}_stats.txt" 650 log "done getting gops output for ${PROG}" 651 } 652 653 function print_k8s_cilium_logs { 654 for pod in $(kubectl -n kube-system get pods -o wide| grep cilium | awk '{print $1}'); do 655 kubectl -n kube-system logs $pod 656 if [ $? -ne 0 ]; then 657 kubectl -n kube-system logs $pod --previous 658 fi 659 done 660 } 661 662 function wait_for_daemon_set_ready { 663 local save=$- 664 set +e 665 check_num_params "$#" "3" 666 667 local namespace="${1}" 668 local name="${2}" 669 local n_ds_expected="${3}" 670 671 log "Waiting for $n_ds_expected instances of Cilium daemon $name in namespace $namespace to become ready" 672 673 local sleep_time=2 674 local iter=0 675 local found="0" 676 until [[ "$found" -eq "$n_ds_expected" ]]; do 677 if [[ $iter -gt $((5*60/$sleep_time)) ]]; then 678 echo "" 679 log "Timeout while waiting for cilium agent" 680 print_k8s_cilium_logs 681 exit 1 682 else 683 overwrite $iter ' 684 kubectl -n kube-system get ds 685 kubectl -n kube-system get pods -o wide 686 echo -n " [${found}/${n_ds_expected}]" 687 ' 688 sleep $sleep_time 689 fi 690 found=$(kubectl get ds -n ${namespace} ${name} 2>&1 | awk 'NR==2{ print $4 }') 691 ((iter++)) 692 done 693 overwrite $iter 'kubectl -n kube-system get pods -o wide' 694 restore_flag $save "e" 695 } 696 697 function k8s_wait_for_cilium_status_ready { 698 local save=$- 699 set +e 700 local pod 701 check_num_params "$#" "1" 702 local namespace=$1 703 local pods=$(kubectl -n $namespace get pods -l k8s-app=cilium | grep cilium- | awk '{print $1}') 704 705 for pod in $pods; do 706 wait_for_kubectl_cilium_status $namespace $pod 707 done 708 restore_flag $save "e" 709 } 710 711 function k8s_count_all_cluster_cilium_eps { 712 local save=$- 713 set +e 714 local total=0 715 check_num_params "$#" "1" 716 local pod 717 local namespace=$1 718 local pods=$(kubectl -n $namespace get pods -l k8s-app=cilium | grep cilium- | awk '{print $1}') 719 720 for pod in $pods; do 721 local n_eps=$(kubectl -n $namespace exec $pod -- cilium endpoint list --no-headers | wc -l) 722 total=$(( $total + $n_eps )) 723 done 724 725 echo "$total" 726 restore_flag $save "e" 727 } 728 729 function wait_for_api_server_ready { 730 log "Waiting for kube-apiserver to spin up" 731 wait_specified_time_test "test \$(kubectl get cs)" "10" 732 } 733 734 function wait_for_service_endpoints_ready { 735 check_num_params "$#" "3" 736 local namespace="${1}" 737 local name="${2}" 738 local port="${3}" 739 740 log "Waiting for ${name} service endpoints to be ready" 741 wait_specified_time_test "test \"\$(kubectl get endpoints -n ${namespace} ${name} | grep -c \":${port}\")\" -eq \"1\"" "10" 742 log "Done waiting for ${name} service endpoints to be ready" 743 kubectl get endpoints -n ${namespace} ${name} 744 } 745 746 function wait_for_service_ready_cilium_pod { 747 check_num_params "$#" "4" 748 local namespace="${1}" 749 local pod="${2}" 750 local fe_port="${3}" 751 # TODO: only works for one backend right now. 752 local be_port="${4}" 753 754 log "Waiting for Cilium pod ${pod} to have services ready with frontend port: ${fe_port} and backend port: ${be_port}" 755 756 wait_specified_time_test "test \"\$(kubectl -n ${namespace} exec ${pod} -- cilium service list | awk '{ print \$2 }' | grep -c \":${fe_port}\")\" -ge \"1\"" "10" 757 wait_specified_time_test "test \"\$(kubectl -n ${namespace} exec ${pod} -- cilium service list | awk '{ print \$5 }' | grep -c \":${be_port}\")\" -ge \"1\"" "10" 758 759 log "Done waiting for Cilium pod ${pod} to have services ready with frontend port: ${fe_port} and backend port: ${be_port}" 760 761 log "Listing all services:" 762 kubectl -n ${namespace} exec ${pod} -- cilium service list 763 } 764 765 function k8s_apply_policy { 766 declare -A currentRevison 767 local i 768 local pod 769 check_num_params "$#" "3" 770 local namespace=$1 771 local action=$2 772 local policy=$3 773 local pods=$(kubectl -n $namespace get pods -l k8s-app=cilium | grep cilium- | awk '{print $1}') 774 775 for pod in $pods; do 776 local rev=$(kubectl -n $namespace exec $pod -- cilium policy get | grep Revision: | awk '{print $2}') 777 currentRevison[$pod]=$rev 778 done 779 780 log "Current policy revisions:" 781 for i in "${!currentRevison[@]}" 782 do 783 echo " $i: ${currentRevison[$i]}" 784 done 785 786 kubectl $action -f $policy 787 788 for pod in $pods; do 789 local nextRev=$(expr ${currentRevison[$pod]} + 1) 790 log "Waiting for agent $pod endpoints to get to revision $nextRev" 791 timeout 180s kubectl -n $namespace exec $pod -- cilium policy wait $nextRev 792 done 793 794 # Adding sleep as workaround for l7 stresstests 795 sleep 10s 796 } 797 798 function policy_delete_and_wait { 799 log "deleting policy $* and waiting up to 120 seconds to complete" 800 rev=$(cilium policy delete $* | grep Revision: | awk '{print $2}') 801 timeout 120s cilium policy wait $rev 802 } 803 804 function policy_import_and_wait { 805 log "importing policy $* and waiting up to 120 seconds to complete" 806 rev=$(cilium policy import $* | grep Revision: | awk '{print $2}') 807 timeout 120s cilium policy wait $rev 808 } 809 810 function get_vm_identity_file { 811 check_num_params "$#" "1" 812 local VM_NAME=$1 813 vagrant ssh-config ${VM_NAME} | grep IdentityFile | awk '{print $2}' 814 } 815 816 function get_vm_ssh_port { 817 check_num_params "$#" "1" 818 local VM_NAME=$1 819 vagrant ssh-config ${VM_NAME} | grep Port | awk '{ print $2 }' 820 } 821 822 function copy_files_vm { 823 check_num_params "$#" "2" 824 local VM_NAME=$1 825 local FILES_DIR=$2 826 local ID_FILE 827 local PORT 828 829 # Check that the VM is running before we try to gather logs from it. 830 check_vm_running $VM_NAME 831 832 log "getting the VM identity file for $VM_NAME" 833 ID_FILE=$(get_vm_identity_file $VM_NAME) 834 log "getting the port for $VM_NAME to SSH" 835 PORT=$(get_vm_ssh_port $VM_NAME) 836 837 log "getting cilium logs from $VM_NAME" 838 vagrant ssh $VM_NAME -c 'sudo -E bash -c "journalctl --no-pager -u cilium > /home/vagrant/go/src/github.com/cilium/cilium/tests/cilium-files/cilium-logs && chmod a+r /home/vagrant/go/src/github.com/cilium/cilium/tests/cilium-files/cilium-logs"' 839 vagrant ssh $VM_NAME -c 'sudo -E bash -c "journalctl --no-pager -u cilium-docker > /home/vagrant/go/src/github.com/cilium/cilium/tests/cilium-files/cilium-docker-logs && chmod a+r /home/vagrant/go/src/github.com/cilium/cilium/tests/cilium-files/cilium-docker-logs"' 840 841 log "listing all logs that will be gathered from $VM_NAME" 842 vagrant ssh $VM_NAME -c 'ls -altr /home/vagrant/go/src/github.com/cilium/cilium/tests/cilium-files' 843 844 log "copying logs from $VM_NAME onto VM host for accessibility after VM is destroyed" 845 scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r -P ${PORT} -i ${ID_FILE} vagrant@127.0.0.1:/home/vagrant/go/src/github.com/cilium/cilium/${FILES_DIR} ${WORKSPACE}/cilium-files-${VM_NAME} 846 } 847 848 function get_k8s_vm_name { 849 check_num_params "$#" "1" 850 local VM_PREFIX=$1 851 852 if [ ! -z ${BUILD_NUMBER} ] ; then 853 local BUILD_ID_NAME="-build-${BUILD_ID}" 854 fi 855 echo "${VM_PREFIX}${BUILD_ID_NAME}" 856 } 857 858 function get_cilium_master_vm_name { 859 if [ ! -z "${K8STAG}" ] ; then 860 local K8S_TAG="${K8STAG:-k8s}" 861 fi 862 863 if [ ! -z "${BUILD_NUMBER}" ] ; then 864 local BUILD_ID_NAME="-build-${BUILD_ID}" 865 fi 866 867 echo "cilium${K8S_TAG}-master${BUILD_ID_NAME}" 868 } 869 870 function check_vm_running { 871 check_num_params "$#" "1" 872 local VM=$1 873 log "getting status of VM ${VM}" 874 vagrant status ${VM} 875 log "done getting status of VM ${VM}" 876 877 local VM_STATUS 878 VM_STATUS=`vagrant status ${VM} | grep ${VM} | awk '{print $2}'` 879 if [[ "${VM_STATUS}" != "running" ]]; then 880 log "$VM is not in \"running\" state; exiting" 881 else 882 log "$VM is \"running\" continuing" 883 fi 884 } 885 886 function wait_for_agent_socket { 887 check_num_params "$#" "1" 888 MAX_WAIT=$1 889 890 log "waiting at most ${MAX_WAIT} iterations for cilium agent socket" 891 local i=0 892 893 while [ "$i" -lt "$MAX_WAIT" ]; do 894 micro_sleep 895 i=$[$i+1] 896 if [ -S $AGENT_SOCK_PATH ]; then 897 return 898 fi 899 done 900 abort "Waiting for agent socket, timed out" 901 } 902 903 function wait_for_kill { 904 check_num_params "$#" "2" 905 TARGET_PID=$1 906 MAX_WAIT=$2 907 908 log "waiting at most ${MAX_WAIT} iterations for PID ${TARGET_PID} to be killed" 909 local i=0 910 911 while [ $i -lt "${MAX_WAIT}" ]; do 912 micro_sleep 913 i=$[$i+1] 914 if ! ps -p $TARGET_PID > /dev/null; then 915 return 916 fi 917 done 918 abort "Waiting for agent process to be killed, timed out" 919 } 920 921 # diff_timeout waits for the output of the commands specified via $1 and $2 to 922 # be identical by comparing the output with `diff -Nru`. The commands are 923 # executed consecutively with a 2 second pause until the output matches or the 924 # timeout of 1 minute is reached. 925 function diff_timeout() { 926 local save=$- 927 set +e 928 local arg1="$1" 929 local arg2="$2" 930 local sleep_time=2 931 local iter=0 932 local found="0" 933 934 until [[ "$found" -eq "1" ]]; do 935 if [[ $((iter++)) -gt $((30)) ]]; then 936 log "Timeout waiting for diff to be empty" 937 abort "$DIFF" 938 fi 939 940 DIFF=$(diff -Nru <(eval "$arg1") <(eval "$arg2") || true) 941 if [[ "$DIFF" == "" ]]; then 942 found="1" 943 else 944 sleep $sleep_time 945 fi 946 done 947 restore_flag $save "e" 948 } 949 950 ####################################### 951 # Waits for MAX_MINS until the output of CMD 952 # reaches NUM_DESIRED. While the state is not 953 # realized, INFO_CMD is emitted. If the state 954 # is not realized after MAX_MINS, ERROR_OUTPUT 955 # is emitted. 956 # Globals: 957 # Arguments: 958 # NUM_DESIRED: desired number output by CMD. 959 # CMD: command to run. 960 # INFO_CMD: command to run while state is not 961 # realized 962 # MAX_MINS: maximum minutes to wait for desired 963 # state 964 # ERROR_OUTPUT: message that is emitted if desired 965 # state is not realized in MAX_MINS. 966 # Returns: 967 # None 968 ####################################### 969 function wait_for_desired_state { 970 971 local save=$- 972 set +e 973 check_num_params "$#" "5" 974 local NUM_DESIRED="$1" 975 local CMD="$2" 976 local INFO_CMD="$3" 977 local MAX_MINS="$4" 978 local ERROR_OUTPUT="$5" 979 local sleep_time=1 980 local iter=0 981 local found 982 found=$(eval "$CMD") 983 log "waiting for at most ${MAX_MINS} minutes for command ${CMD} to succeed" 984 log "found: $found" 985 986 while [[ "$found" -ne "$NUM_DESIRED" ]]; do 987 if [[ $iter -gt $((${MAX_MINS}*60/$sleep_time)) ]]; then 988 echo "" 989 log "$ERROR_OUTPUT" 990 exit 1 991 else 992 overwrite $iter ' 993 log "desired state not realized; will sleep and try again" 994 eval "$INFO_CMD" 995 echo -n " [$found/$NUM_DESIRED]" 996 ' 997 sleep $sleep_time 998 fi 999 found=$(eval "${CMD}") 1000 log "found: $found" 1001 ((iter++)) 1002 done 1003 log "desired state realized for command ${CMD}" 1004 eval "${INFO_CMD}" 1005 restore_flag $save "e" 1006 } 1007 1008 ####################################### 1009 # Waits for MAX_MINS until CMD returns with 1010 # return code 0. If the desired state is 1011 # not realized after MAX_MINS, exits with 1012 # failure. 1013 # Globals: 1014 # Arguments: 1015 # CMD: command to run. 1016 # MAX_MINS: maximum minutes to wait for desired 1017 # state 1018 # Returns: 1019 # None 1020 ####################################### 1021 function wait_specified_time_test { 1022 local save=$- 1023 set +e 1024 local CMD="$1" 1025 local MAX_MINS="$2" 1026 1027 local sleep_time=1 1028 local iter=0 1029 1030 log "waiting for at most ${MAX_MINS} minutes for command ${CMD} to succeed" 1031 while [[ "${iter}" -lt $((${MAX_MINS}*60/$sleep_time)) ]]; do 1032 if eval "${CMD}" ; then 1033 log "${CMD} succeeded" 1034 break 1035 fi 1036 overwrite $iter ' 1037 log "${iter} < $((${MAX_MINS}*60/$sleep_time)) " 1038 log "${CMD} did not succeed; sleeping and testing the command again" 1039 ' 1040 sleep ${sleep_time} 1041 iter=$((iter+1)) 1042 done 1043 if [[ "${iter}" -ge $((${MAX_MINS}*60/$sleep_time)) ]]; then 1044 log "Timeout ${MAX_MINS} minutes exceeded for command \"$CMD\"" 1045 log "Exiting with failure." 1046 exit 1 1047 fi 1048 log "${CMD} succeeded" 1049 restore_flag $save "e" 1050 } 1051 1052 function create_cilium_docker_network { 1053 log "creating Docker network of type Cilium" 1054 docker network inspect $TEST_NET 2> /dev/null || { 1055 docker network create --ipv6 --subnet ::1/112 --ipam-driver cilium --driver cilium $TEST_NET 1056 } 1057 } 1058 1059 function remove_cilium_docker_network { 1060 local save=$- 1061 set +e 1062 log "removing Docker network of type cilium" 1063 docker network rm $TEST_NET > /dev/null 2>&1 1064 restore_flag $save "e" 1065 } 1066 1067 function remove_all_containers { 1068 docker rm -f $(docker ps --format '{{.Names}}' | grep -v cilium-consul) > /dev/null 2>&1 || true 1069 } 1070 1071 function test_succeeded { 1072 check_num_params "$#" "1" 1073 local TEST_NAME="$1" 1074 echo "============================================================" 1075 echo "== ==" 1076 echo "== ==" 1077 echo "== ==" 1078 echo " ${TEST_NAME} succeeded!" 1079 echo "== ==" 1080 echo "== ==" 1081 echo "== ==" 1082 echo "============================================================" 1083 } 1084 1085 function ping_fail { 1086 check_num_params "$#" "2" 1087 C1=$1 1088 C2=$2 1089 log "pinging $C2 from $C1 (expecting failure) " 1090 docker exec -i ${C1} bash -c "ping -c 5 ${C2}" && { 1091 abort "Error: Unexpected success pinging ${C2} from ${C1}" 1092 } 1093 } 1094 1095 function ping_success { 1096 check_num_params "$#" "2" 1097 C1=$1 1098 C2=$2 1099 log "pinging $C2 from $C1 (expecting success) " 1100 docker exec -i ${C1} bash -c "ping -c 5 ${C2}" || { 1101 abort "Error: Could not ping ${C2} from ${C1}" 1102 } 1103 } 1104 1105 function wait_for_cilium_shutdown { 1106 local save=$- 1107 set +e 1108 log "waiting for cilium to shutdown" 1109 i=0 1110 while pgrep cilium-agent; do 1111 micro_sleep 1112 if [[ ${i} -ge 240 ]]; then 1113 log "Timeout while waiting for Cilium to shutdown" 1114 exit 1 1115 fi 1116 ((i++)) 1117 done 1118 log "finished waiting for cilium to shutdown" 1119 restore_flag $save "e" 1120 }