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 }