istio.io/istio@v0.0.0-20240520182934-d79c90f27776/prow/lib.sh (about)

     1  #!/bin/bash
     2  
     3  # Copyright 2018 Istio Authors
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #    http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  WD=$(dirname "$0")
    18  WD=$(cd "$WD" || exit; pwd)
    19  ROOT=$(dirname "$WD")
    20  
    21  # shellcheck source=common/scripts/tracing.sh
    22  source "${ROOT}/common/scripts/tracing.sh"
    23  
    24  function date_cmd() {
    25    case "$(uname)" in
    26      "Darwin")
    27        [ -z "$(which gdate)" ] && echo "gdate is required for OSX. Try installing coreutils from MacPorts or Brew."
    28        gdate "$@"
    29        ;;
    30      *)
    31        date "$@"
    32        ;;
    33    esac
    34  }
    35  
    36  # Output a message, with a timestamp matching istio log format
    37  function log() {
    38    echo -e "$(date_cmd -u '+%Y-%m-%dT%H:%M:%S.%NZ')\t$*"
    39  }
    40  
    41  # Trace runs the provided command and records additional timing information
    42  # NOTE: to avoid spamming the logs, we disable xtrace and re-enable it before executing the function
    43  # and after completion. If xtrace was never set, this will result in xtrace being enabled.
    44  # Ideally we would restore the old xtrace setting, but I don't think its possible to do that without also log-spamming
    45  # If we need to call it from a context without xtrace we can just make a new function.
    46  function trace() {
    47    { set +x; } 2>/dev/null
    48    log "Running '${1}'"
    49    start="$(date_cmd -u +%s.%N)"
    50    { set -x; } 2>/dev/null
    51  
    52    tracing::run "$1" "${@:2}"
    53  
    54    { set +x; } 2>/dev/null
    55    elapsed=$(date_cmd +%s.%N --date="$start seconds ago" )
    56    log "Command '${1}' complete in ${elapsed}s"
    57    # Write to YAML file as well for easy reading by tooling
    58    echo "'${1}': $elapsed" >> "${ARTIFACTS}/trace.yaml"
    59    { set -x; } 2>/dev/null
    60  }
    61  
    62  function setup_gcloud_credentials() {
    63    if [[ $(command -v gcloud) ]]; then
    64      gcloud auth configure-docker us-docker.pkg.dev -q
    65    elif [[ $(command -v docker-credential-gcr) ]]; then
    66      docker-credential-gcr configure-docker --registries=-us-docker.pkg.dev
    67    else
    68      echo "No credential helpers found, push to docker may not function properly"
    69    fi
    70  }
    71  
    72  function setup_and_export_git_sha() {
    73    if [[ -n "${CI:-}" ]]; then
    74  
    75      if [ -z "${PULL_PULL_SHA:-}" ]; then
    76        if [ -z "${PULL_BASE_SHA:-}" ]; then
    77          GIT_SHA="$(git rev-parse --verify HEAD)"
    78          export GIT_SHA
    79        else
    80          export GIT_SHA="${PULL_BASE_SHA}"
    81        fi
    82      else
    83        export GIT_SHA="${PULL_PULL_SHA}"
    84      fi
    85    else
    86      # Use the current commit.
    87      GIT_SHA="$(git rev-parse --verify HEAD)"
    88      export GIT_SHA
    89    fi
    90    GIT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
    91    export GIT_BRANCH
    92    setup_gcloud_credentials
    93  }
    94  
    95  # Download and unpack istio release artifacts.
    96  function download_untar_istio_release() {
    97    local url_path=${1}
    98    local tag=${2}
    99    local dir=${3:-.}
   100    # Download artifacts
   101    LINUX_DIST_URL="${url_path}/istio-${tag}-linux.tar.gz"
   102  
   103    wget  -q "${LINUX_DIST_URL}" -P "${dir}"
   104    tar -xzf "${dir}/istio-${tag}-linux.tar.gz" -C "${dir}"
   105  }
   106  
   107  function buildx-create() {
   108    WD=$(dirname "$0")
   109    WD=$(cd "$WD" || exit; pwd)
   110    ROOT=$(dirname "$WD")
   111    "$ROOT/prow/buildx-create"
   112  }
   113  
   114  function build_images() {
   115    SELECT_TEST="${1}"
   116  
   117    # Build just the images needed for tests
   118    targets="docker.pilot docker.proxyv2 "
   119  
   120    # use ubuntu:jammy to test vms by default
   121    nonDistrolessTargets="docker.app docker.app_sidecar_ubuntu_noble docker.ext-authz "
   122    if [[ "${JOB_TYPE:-presubmit}" == "postsubmit" ]]; then
   123      # We run tests across all VM types only in postsubmit
   124      nonDistrolessTargets+="docker.app_sidecar_ubuntu_bionic docker.app_sidecar_debian_12 docker.app_sidecar_rockylinux_9 "
   125    fi
   126    if [[ "${SELECT_TEST}" == "test.integration.operator.kube" || "${SELECT_TEST}" == "test.integration.kube" || "${JOB_TYPE:-postsubmit}" == "postsubmit" ]]; then
   127      targets+="docker.operator "
   128    fi
   129    if [[ "${SELECT_TEST}" == "test.integration.ambient.kube" || "${SELECT_TEST}" == "test.integration.kube" || "${JOB_TYPE:-postsubmit}" == "postsubmit" ]]; then
   130      targets+="docker.ztunnel "
   131    fi
   132    targets+="docker.install-cni "
   133    # Integration tests are always running on local architecture (no cross compiling), so find out what that is.
   134    arch="linux/amd64"
   135    if [[ "$(uname -m)" == "aarch64" ]]; then
   136        arch="linux/arm64"
   137    fi
   138    if [[ "${VARIANT:-default}" == "distroless" ]]; then
   139      DOCKER_ARCHITECTURES="${arch}" DOCKER_BUILD_VARIANTS="distroless" DOCKER_TARGETS="${targets}" make dockerx.pushx
   140      DOCKER_ARCHITECTURES="${arch}" DOCKER_BUILD_VARIANTS="default" DOCKER_TARGETS="${nonDistrolessTargets}" make dockerx.pushx
   141    else
   142     DOCKER_ARCHITECTURES="${arch}"  DOCKER_BUILD_VARIANTS="${VARIANT:-default}" DOCKER_TARGETS="${targets} ${nonDistrolessTargets}" make dockerx.pushx
   143    fi
   144  }
   145  
   146  # Creates a local registry for kind nodes to pull images from. Expects that the "kind" network already exists.
   147  function setup_kind_registry() {
   148    # create a registry container if it not running already
   149    running="$(docker inspect -f '{{.State.Running}}' "${KIND_REGISTRY_NAME}" 2>/dev/null || true)"
   150    if [[ "${running}" != 'true' ]]; then
   151        docker run \
   152          -d --restart=always -p "${KIND_REGISTRY_PORT}:5000" --name "${KIND_REGISTRY_NAME}" \
   153          gcr.io/istio-testing/registry:2
   154  
   155      # Allow kind nodes to reach the registry
   156      docker network connect "kind" "${KIND_REGISTRY_NAME}"
   157    fi
   158  
   159    # https://docs.tilt.dev/choosing_clusters.html#discovering-the-registry
   160    for cluster in $(kind get clusters); do
   161      # TODO get context/config from existing variables
   162      kind export kubeconfig --name="${cluster}"
   163      for node in $(kind get nodes --name="${cluster}"); do
   164        kubectl annotate node "${node}" "kind.x-k8s.io/registry=localhost:${KIND_REGISTRY_PORT}" --overwrite;
   165      done
   166    done
   167  }
   168  
   169  # setup_cluster_reg is used to set up a cluster registry for multicluster testing
   170  function setup_cluster_reg () {
   171      MAIN_CONFIG=""
   172      for context in "${CLUSTERREG_DIR}"/*; do
   173          if [[ -z "${MAIN_CONFIG}" ]]; then
   174              MAIN_CONFIG="${context}"
   175          fi
   176          export KUBECONFIG="${context}"
   177          kubectl delete ns istio-system-multi --ignore-not-found
   178          kubectl delete clusterrolebinding istio-multi-test --ignore-not-found
   179          kubectl create ns istio-system-multi
   180          kubectl create sa istio-multi-test -n istio-system-multi
   181          kubectl create clusterrolebinding istio-multi-test --clusterrole=cluster-admin --serviceaccount=istio-system-multi:istio-multi-test
   182          CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
   183          gen_kubeconf_from_sa istio-multi-test "${context}"
   184      done
   185      export KUBECONFIG="${MAIN_CONFIG}"
   186  }
   187  
   188  function gen_kubeconf_from_sa () {
   189      local service_account=$1
   190      local filename=$2
   191  
   192      SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
   193      SECRET_NAME=$(kubectl get sa "${service_account}" -n istio-system-multi -o jsonpath='{.secrets[].name}')
   194      CA_DATA=$(kubectl get secret "${SECRET_NAME}" -n istio-system-multi -o "jsonpath={.data['ca\\.crt']}")
   195      TOKEN=$(kubectl get secret "${SECRET_NAME}" -n istio-system-multi -o "jsonpath={.data['token']}" | base64 --decode)
   196  
   197      cat <<EOF > "${filename}"
   198        apiVersion: v1
   199        clusters:
   200           - cluster:
   201               certificate-authority-data: ${CA_DATA}
   202               server: ${SERVER}
   203             name: ${CLUSTER_NAME}
   204        contexts:
   205           - context:
   206               cluster: ${CLUSTER_NAME}
   207               user: ${CLUSTER_NAME}
   208             name: ${CLUSTER_NAME}
   209        current-context: ${CLUSTER_NAME}
   210        kind: Config
   211        preferences: {}
   212        users:
   213           - name: ${CLUSTER_NAME}
   214             user:
   215               token: ${TOKEN}
   216  EOF
   217  }
   218  
   219  # gives a copy of a given topology JSON editing the given key on the entry with the given cluster name
   220  function set_topology_value() {
   221      local JSON="$1"
   222      local CLUSTER_NAME="$2"
   223      local KEY="$3"
   224      local VALUE="$4"
   225      VALUE=$(echo "${VALUE}" | awk '{$1=$1};1')
   226  
   227      echo "${JSON}" | jq '(.[] | select(.clusterName =="'"${CLUSTER_NAME}"'") | .'"${KEY}"') |="'"${VALUE}"'"'
   228  }