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  }