From 6e529a937e6dc13d171932b9ab27091086bb5e3a Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Thu, 15 Dec 2022 06:09:13 +0000 Subject: [PATCH 01/11] make yml file for current g8r licenses Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .github/license-lint-config.yml | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/license-lint-config.yml diff --git a/.github/license-lint-config.yml b/.github/license-lint-config.yml new file mode 100644 index 00000000000..17d6c13caa5 --- /dev/null +++ b/.github/license-lint-config.yml @@ -0,0 +1,81 @@ +unrestricted_licenses: + - Apache-2.0 + - CC-BY-3.0 + - ISC + - AFL-2.1 + - AFL-3.0 + - Artistic-1.0 + - Artistic-2.0 + - Apache-1.1 + - BSD-1-Clause + - BSD-2-Clause + - BSD-3-Clause + - 0BSD + - FTL + - LPL-1.02 + - MS-PL + - MIT + - NCSA + - OpenSSL + - PHP-3.0 + - TCP-wrappers + - W3C + - Xnet + - Zlib + +reciprocal_licenses: + - CC0-1.0 + - APSL-2.0 + - CDDL-1.0 + - CDDL-1.1 + - CPL-1.0 + - EPL-1.0 + - IPL-1.0 + - MPL-1.0 + - MPL-1.1 + - MPL-2.0 + - MPL-2.0-no-copyleft-exception + - Ruby + +restricted_licenses: + - GPL-1.0-only + - GPL-1.0-or-later + - GPL-2.0-only + - GPL-2.0-or-later + - GPL-3.0-only + - GPL-3.0-or-later + - LGPL-2.0-only + - LGPL-2.0-or-later + - LGPL-2.1-only + - LGPL-2.1-or-later + - LGPL-3.0-only + - LGPL-3.0-or-later + - NPL-1.0 + - NPL-1.1 + - OSL-1.0 + - OSL-1.1 + - OSL-2.0 + - OSL-2.1 + - OSL-3.0 + - QPL-1.0 + - Sleepycat + +allowlisted_modules: + # MIT: https://github.com/ghodss/yaml/blob/master/LICENSE + - github.com/ghodss/yaml + # BSD: https://github.com/gogo/protobuf/blob/master/LICENSE + - github.com/gogo/protobuf + + # Apache 2.0 + - github.com/spf13/cobra + + # https://github.com/xeipuuv/gojsonpointer/blob/master/LICENSE-APACHE-2.0.txt + - github.com/xeipuuv/gojsonpointer + # https://github.com/xeipuuv/gojsonreference/blob/master/LICENSE-APACHE-2.0.txt + - github.com/xeipuuv/gojsonreference + + # MIT: https://github.com/kubernetes-sigs/yaml/blob/master/LICENSE + - sigs.k8s.io/yaml + + # BSD-2-Clause-FreeBSD + - github.com/rcrowley/go-metrics From dbfbc1d146a3b0ac363bed994d82c9fb25927c86 Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Thu, 15 Dec 2022 06:13:25 +0000 Subject: [PATCH 02/11] add gh wf for license-lint Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .github/workflows/license-lint.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/license-lint.yaml diff --git a/.github/workflows/license-lint.yaml b/.github/workflows/license-lint.yaml new file mode 100644 index 00000000000..f9336bcaeef --- /dev/null +++ b/.github/workflows/license-lint.yaml @@ -0,0 +1,26 @@ +name: license-lint +on: [push, pull_request] + +jobs: + license-lint: + name: "license-lint" + runs-on: ubuntu-22.04 + timeout-minutes: 5 + permissions: + contents: read + steps: + - name: Set up Go 1.19 + uses: actions/setup-go@v3 + with: + go-version: 1.19 + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: license-lint + run: | + export GOPATH="$HOME/go" + PATH="$GOPATH/bin:$PATH" + go install istio.io/tools/cmd/license-lint@1.16.0 + + license-lint --config ./.github/license-lint-config.yml 2>&1 From 31425d7da83ac3868a0645bb0dc4343644f9be97 Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Tue, 20 Dec 2022 03:30:56 +0000 Subject: [PATCH 03/11] cncf aligned config for lgk Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .github/license-lint-config.yml | 63 +++++++++++++-------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/.github/license-lint-config.yml b/.github/license-lint-config.yml index 17d6c13caa5..74572806705 100644 --- a/.github/license-lint-config.yml +++ b/.github/license-lint-config.yml @@ -1,57 +1,46 @@ unrestricted_licenses: - Apache-2.0 - - CC-BY-3.0 - - ISC - - AFL-2.1 - - AFL-3.0 - - Artistic-1.0 - - Artistic-2.0 - - Apache-1.1 - - BSD-1-Clause - BSD-2-Clause - BSD-3-Clause - 0BSD - - FTL - - LPL-1.02 - - MS-PL - MIT - - NCSA - - OpenSSL - - PHP-3.0 - - TCP-wrappers - - W3C - - Xnet - - Zlib - -reciprocal_licenses: - - CC0-1.0 - - APSL-2.0 - - CDDL-1.0 - - CDDL-1.1 - - CPL-1.0 - - EPL-1.0 - - IPL-1.0 - - MPL-1.0 - - MPL-1.1 - - MPL-2.0 - - MPL-2.0-no-copyleft-exception - - Ruby restricted_licenses: + - bzip2-1.0.5 + - AGPL-1.0 + - AGPL-3.0 + - BSD-2-Clause-FreeBSD + - BSD-2-Clause-NetBSD + - eCos-2.0 + - GFDL-1.1 + - GFDL-1.2 + - GFDL-1.3 - GPL-1.0-only - GPL-1.0-or-later + - GPL-2.0+ - GPL-2.0-only - GPL-2.0-or-later + - GPL-2.0-with-autoconf-exception + - GPL-2.0-with-bison-exception + - GPL-2.0-with-classpath-exception + - GPL-2.0-with-GCC-exception + - GPL-2.0-with-font-exception - GPL-3.0-only - GPL-3.0-or-later + - GPL-3.0+ + - GPL-3.0-with-autoconf-exception + - GPL-3.0-with-GCC-exception - LGPL-2.0-only + - LGPL-2.0+ - LGPL-2.0-or-later - LGPL-2.1-only - LGPL-2.1-or-later - LGPL-3.0-only - LGPL-3.0-or-later + - LGPL-3.0+ - NPL-1.0 - NPL-1.1 + - Nunit - OSL-1.0 - OSL-1.1 - OSL-2.0 @@ -59,23 +48,21 @@ restricted_licenses: - OSL-3.0 - QPL-1.0 - Sleepycat + - StandardML-NJ + - wxWindows allowlisted_modules: # MIT: https://github.com/ghodss/yaml/blob/master/LICENSE - github.com/ghodss/yaml # BSD: https://github.com/gogo/protobuf/blob/master/LICENSE - github.com/gogo/protobuf - # Apache 2.0 - github.com/spf13/cobra - # https://github.com/xeipuuv/gojsonpointer/blob/master/LICENSE-APACHE-2.0.txt - github.com/xeipuuv/gojsonpointer # https://github.com/xeipuuv/gojsonreference/blob/master/LICENSE-APACHE-2.0.txt - github.com/xeipuuv/gojsonreference - # MIT: https://github.com/kubernetes-sigs/yaml/blob/master/LICENSE - sigs.k8s.io/yaml - - # BSD-2-Clause-FreeBSD - - github.com/rcrowley/go-metrics + # BSD-2-Clause: https://github.com/rcrowley/go-metrics/blob/master/LICENSE + - github.com/rcrowley/go-metrics \ No newline at end of file From 4e73471bf050c80fb765a7c63ff50fd10cf00e5c Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Wed, 4 Jan 2023 05:55:13 +0000 Subject: [PATCH 04/11] cherry pick script at 124fd62ad25 Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .../k8s.io/kubernetes/hack/lib/etcd.sh | 183 ++++ .../k8s.io/kubernetes/hack/lib/golang.sh | 919 ++++++++++++++++++ .../k8s.io/kubernetes/hack/lib/init.sh | 212 ++++ .../k8s.io/kubernetes/hack/lib/logging.sh | 171 ++++ .../k8s.io/kubernetes/hack/lib/util.sh | 890 +++++++++++++++++ .../k8s.io/kubernetes/hack/lib/version.sh | 185 ++++ .../k8s.io/kubernetes/hack/verify-licenses.sh | 155 +++ 7 files changed, 2715 insertions(+) create mode 100755 third_party/k8s.io/kubernetes/hack/lib/etcd.sh create mode 100755 third_party/k8s.io/kubernetes/hack/lib/golang.sh create mode 100755 third_party/k8s.io/kubernetes/hack/lib/init.sh create mode 100644 third_party/k8s.io/kubernetes/hack/lib/logging.sh create mode 100755 third_party/k8s.io/kubernetes/hack/lib/util.sh create mode 100644 third_party/k8s.io/kubernetes/hack/lib/version.sh create mode 100755 third_party/k8s.io/kubernetes/hack/verify-licenses.sh diff --git a/third_party/k8s.io/kubernetes/hack/lib/etcd.sh b/third_party/k8s.io/kubernetes/hack/lib/etcd.sh new file mode 100755 index 00000000000..44ceb46af05 --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/lib/etcd.sh @@ -0,0 +1,183 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# A set of helpers for starting/running etcd for tests + +ETCD_VERSION=${ETCD_VERSION:-3.5.5} +ETCD_HOST=${ETCD_HOST:-127.0.0.1} +ETCD_PORT=${ETCD_PORT:-2379} +# This is intentionally not called ETCD_LOG_LEVEL: +# etcd checks that and compains when it is set in addition +# to the command line argument, even when both have the same value. +ETCD_LOGLEVEL=${ETCD_LOGLEVEL:-warn} +export KUBE_INTEGRATION_ETCD_URL="http://${ETCD_HOST}:${ETCD_PORT}" + +kube::etcd::validate() { + # validate if in path + command -v etcd >/dev/null || { + kube::log::usage "etcd must be in your PATH" + kube::log::info "You can use 'hack/install-etcd.sh' to install a copy in third_party/." + exit 1 + } + + # validate etcd port is free + local port_check_command + if command -v ss &> /dev/null && ss -Version | grep 'iproute2' &> /dev/null; then + port_check_command="ss" + elif command -v netstat &>/dev/null; then + port_check_command="netstat" + else + kube::log::usage "unable to identify if etcd is bound to port ${ETCD_PORT}. unable to find ss or netstat utilities." + exit 1 + fi + if ${port_check_command} -nat | grep "LISTEN" | grep "[\.:]${ETCD_PORT:?}" >/dev/null 2>&1; then + kube::log::usage "unable to start etcd as port ${ETCD_PORT} is in use. please stop the process listening on this port and retry." + kube::log::usage "$(netstat -nat | grep "[\.:]${ETCD_PORT:?} .*LISTEN")" + exit 1 + fi + + # need set the env of "ETCD_UNSUPPORTED_ARCH" on unstable arch. + arch=$(uname -m) + if [[ $arch =~ aarch* ]]; then + export ETCD_UNSUPPORTED_ARCH=arm64 + elif [[ $arch =~ arm* ]]; then + export ETCD_UNSUPPORTED_ARCH=arm + fi + # validate installed version is at least equal to minimum + version=$(etcd --version | grep Version | head -n 1 | cut -d " " -f 3) + if [[ $(kube::etcd::version "${ETCD_VERSION}") -gt $(kube::etcd::version "${version}") ]]; then + export PATH=${KUBE_ROOT}/third_party/etcd:${PATH} + hash etcd + echo "${PATH}" + version=$(etcd --version | grep Version | head -n 1 | cut -d " " -f 3) + if [[ $(kube::etcd::version "${ETCD_VERSION}") -gt $(kube::etcd::version "${version}") ]]; then + kube::log::usage "etcd version ${ETCD_VERSION} or greater required." + kube::log::info "You can use 'hack/install-etcd.sh' to install a copy in third_party/." + exit 1 + fi + fi +} + +kube::etcd::version() { + printf '%s\n' "${@}" | awk -F . '{ printf("%d%03d%03d\n", $1, $2, $3) }' +} + +kube::etcd::start() { + # validate before running + kube::etcd::validate + + # Start etcd + ETCD_DIR=${ETCD_DIR:-$(mktemp -d 2>/dev/null || mktemp -d -t test-etcd.XXXXXX)} + if [[ -d "${ARTIFACTS:-}" ]]; then + ETCD_LOGFILE="${ARTIFACTS}/etcd.$(uname -n).$(id -un).log.DEBUG.$(date +%Y%m%d-%H%M%S).$$" + else + ETCD_LOGFILE=${ETCD_LOGFILE:-"/dev/null"} + fi + kube::log::info "etcd --advertise-client-urls ${KUBE_INTEGRATION_ETCD_URL} --data-dir ${ETCD_DIR} --listen-client-urls http://${ETCD_HOST}:${ETCD_PORT} --log-level=${ETCD_LOGLEVEL} 2> \"${ETCD_LOGFILE}\" >/dev/null" + etcd --advertise-client-urls "${KUBE_INTEGRATION_ETCD_URL}" --data-dir "${ETCD_DIR}" --listen-client-urls "${KUBE_INTEGRATION_ETCD_URL}" --log-level="${ETCD_LOGLEVEL}" 2> "${ETCD_LOGFILE}" >/dev/null & + ETCD_PID=$! + + echo "Waiting for etcd to come up." + kube::util::wait_for_url "${KUBE_INTEGRATION_ETCD_URL}/health" "etcd: " 0.25 80 + curl -fs -X POST "${KUBE_INTEGRATION_ETCD_URL}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}' +} + +kube::etcd::start_scraping() { + if [[ -d "${ARTIFACTS:-}" ]]; then + ETCD_SCRAPE_DIR="${ARTIFACTS}/etcd-scrapes" + else + ETCD_SCRAPE_DIR=$(mktemp -d -t test.XXXXXX)/etcd-scrapes + fi + kube::log::info "Periodically scraping etcd to ${ETCD_SCRAPE_DIR} ." + mkdir -p "${ETCD_SCRAPE_DIR}" + ( + while sleep 30; do + kube::etcd::scrape + done + ) & + ETCD_SCRAPE_PID=$! +} + +kube::etcd::scrape() { + curl -s -S "${KUBE_INTEGRATION_ETCD_URL}/metrics" > "${ETCD_SCRAPE_DIR}/next" && mv "${ETCD_SCRAPE_DIR}/next" "${ETCD_SCRAPE_DIR}/$(date +%s).scrape" +} + + +kube::etcd::stop() { + if [[ -n "${ETCD_SCRAPE_PID:-}" ]] && [[ -n "${ETCD_SCRAPE_DIR:-}" ]] ; then + kill "${ETCD_SCRAPE_PID}" &>/dev/null || : + wait "${ETCD_SCRAPE_PID}" &>/dev/null || : + kube::etcd::scrape || : + ( + # shellcheck disable=SC2015 + cd "${ETCD_SCRAPE_DIR}"/.. && \ + tar czf etcd-scrapes.tgz etcd-scrapes && \ + rm -rf etcd-scrapes || : + ) + fi + if [[ -n "${ETCD_PID-}" ]]; then + kill "${ETCD_PID}" &>/dev/null || : + wait "${ETCD_PID}" &>/dev/null || : + fi +} + +kube::etcd::clean_etcd_dir() { + if [[ -n "${ETCD_DIR-}" ]]; then + rm -rf "${ETCD_DIR}" + fi +} + +kube::etcd::cleanup() { + kube::etcd::stop + kube::etcd::clean_etcd_dir +} + +kube::etcd::install() { + ( + local os + local arch + + os=$(kube::util::host_os) + arch=$(kube::util::host_arch) + + cd "${KUBE_ROOT}/third_party" || return 1 + if [[ $(readlink etcd) == etcd-v${ETCD_VERSION}-${os}-* ]]; then + kube::log::info "etcd v${ETCD_VERSION} already installed. To use:" + kube::log::info "export PATH=\"$(pwd)/etcd:\${PATH}\"" + return #already installed + fi + + if [[ ${os} == "darwin" ]]; then + download_file="etcd-v${ETCD_VERSION}-${os}-${arch}.zip" + url="https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/${download_file}" + kube::util::download_file "${url}" "${download_file}" + unzip -o "${download_file}" + ln -fns "etcd-v${ETCD_VERSION}-${os}-${arch}" etcd + rm "${download_file}" + elif [[ ${os} == "linux" ]]; then + url="https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-${os}-${arch}.tar.gz" + download_file="etcd-v${ETCD_VERSION}-${os}-${arch}.tar.gz" + kube::util::download_file "${url}" "${download_file}" + tar xzf "${download_file}" + ln -fns "etcd-v${ETCD_VERSION}-${os}-${arch}" etcd + rm "${download_file}" + else + kube::log::info "${os} is NOT supported." + fi + kube::log::info "etcd v${ETCD_VERSION} installed. To use:" + kube::log::info "export PATH=\"$(pwd)/etcd:\${PATH}\"" + ) +} diff --git a/third_party/k8s.io/kubernetes/hack/lib/golang.sh b/third_party/k8s.io/kubernetes/hack/lib/golang.sh new file mode 100755 index 00000000000..fb97ee76783 --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/lib/golang.sh @@ -0,0 +1,919 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# shellcheck disable=SC2034 # Variables sourced in other scripts. + +# The golang package that we are building. +readonly KUBE_GO_PACKAGE=k8s.io/kubernetes +readonly KUBE_GOPATH="${KUBE_OUTPUT}/go" + +# The server platform we are building on. +readonly KUBE_SUPPORTED_SERVER_PLATFORMS=( + linux/amd64 + linux/arm + linux/arm64 + linux/s390x + linux/ppc64le +) + +# The node platforms we build for +readonly KUBE_SUPPORTED_NODE_PLATFORMS=( + linux/amd64 + linux/arm + linux/arm64 + linux/s390x + linux/ppc64le + windows/amd64 +) + +# If we update this we should also update the set of platforms whose standard +# library is precompiled for in build/build-image/cross/Dockerfile +readonly KUBE_SUPPORTED_CLIENT_PLATFORMS=( + linux/amd64 + linux/386 + linux/arm + linux/arm64 + linux/s390x + linux/ppc64le + darwin/amd64 + darwin/arm64 + windows/amd64 + windows/386 + windows/arm64 +) + +# Which platforms we should compile test targets for. +# Not all client platforms need these tests +readonly KUBE_SUPPORTED_TEST_PLATFORMS=( + linux/amd64 + linux/arm + linux/arm64 + linux/s390x + linux/ppc64le + darwin/amd64 + darwin/arm64 + windows/amd64 + windows/arm64 +) + +# The set of server targets that we are only building for Linux +kube::golang::server_targets() { + local targets=( + cmd/kube-proxy + cmd/kube-apiserver + cmd/kube-controller-manager + cmd/kubelet + cmd/kubeadm + cmd/kube-scheduler + vendor/k8s.io/component-base/logs/kube-log-runner + vendor/k8s.io/kube-aggregator + vendor/k8s.io/apiextensions-apiserver + cluster/gce/gci/mounter + ) + echo "${targets[@]}" +} + +IFS=" " read -ra KUBE_SERVER_TARGETS <<< "$(kube::golang::server_targets)" +readonly KUBE_SERVER_TARGETS +readonly KUBE_SERVER_BINARIES=("${KUBE_SERVER_TARGETS[@]##*/}") + +# The set of server targets we build docker images for +kube::golang::server_image_targets() { + # NOTE: this contains cmd targets for kube::build::get_docker_wrapped_binaries + local targets=( + cmd/kube-apiserver + cmd/kube-controller-manager + cmd/kube-scheduler + cmd/kube-proxy + ) + echo "${targets[@]}" +} + +IFS=" " read -ra KUBE_SERVER_IMAGE_TARGETS <<< "$(kube::golang::server_image_targets)" +readonly KUBE_SERVER_IMAGE_TARGETS +readonly KUBE_SERVER_IMAGE_BINARIES=("${KUBE_SERVER_IMAGE_TARGETS[@]##*/}") + +# The set of conformance targets we build docker image for +kube::golang::conformance_image_targets() { + # NOTE: this contains cmd targets for kube::release::build_conformance_image + local targets=( + ginkgo + test/e2e/e2e.test + test/conformance/image/go-runner + cmd/kubectl + ) + echo "${targets[@]}" +} + +IFS=" " read -ra KUBE_CONFORMANCE_IMAGE_TARGETS <<< "$(kube::golang::conformance_image_targets)" +readonly KUBE_CONFORMANCE_IMAGE_TARGETS + +# The set of server targets that we are only building for Kubernetes nodes +kube::golang::node_targets() { + local targets=( + cmd/kube-proxy + cmd/kubeadm + cmd/kubelet + vendor/k8s.io/component-base/logs/kube-log-runner + ) + echo "${targets[@]}" +} + +IFS=" " read -ra KUBE_NODE_TARGETS <<< "$(kube::golang::node_targets)" +readonly KUBE_NODE_TARGETS +readonly KUBE_NODE_BINARIES=("${KUBE_NODE_TARGETS[@]##*/}") +readonly KUBE_NODE_BINARIES_WIN=("${KUBE_NODE_BINARIES[@]/%/.exe}") + +# ------------ +# NOTE: All functions that return lists should use newlines. +# bash functions can't return arrays, and spaces are tricky, so newline +# separators are the preferred pattern. +# To transform a string of newline-separated items to an array, use kube::util::read-array: +# kube::util::read-array FOO < <(kube::golang::dups a b c a) +# +# ALWAYS remember to quote your subshells. Not doing so will break in +# bash 4.3, and potentially cause other issues. +# ------------ + +# Returns a sorted newline-separated list containing only duplicated items. +kube::golang::dups() { + # We use printf to insert newlines, which are required by sort. + printf "%s\n" "$@" | sort | uniq -d +} + +# Returns a sorted newline-separated list with duplicated items removed. +kube::golang::dedup() { + # We use printf to insert newlines, which are required by sort. + printf "%s\n" "$@" | sort -u +} + +# Depends on values of user-facing KUBE_BUILD_PLATFORMS, KUBE_FASTBUILD, +# and KUBE_BUILDER_OS. +# Configures KUBE_SERVER_PLATFORMS, KUBE_NODE_PLATFOMRS, +# KUBE_TEST_PLATFORMS, and KUBE_CLIENT_PLATFORMS, then sets them +# to readonly. +# The configured vars will only contain platforms allowed by the +# KUBE_SUPPORTED* vars at the top of this file. +declare -a KUBE_SERVER_PLATFORMS +declare -a KUBE_CLIENT_PLATFORMS +declare -a KUBE_NODE_PLATFORMS +declare -a KUBE_TEST_PLATFORMS +kube::golang::setup_platforms() { + if [[ -n "${KUBE_BUILD_PLATFORMS:-}" ]]; then + # KUBE_BUILD_PLATFORMS needs to be read into an array before the next + # step, or quoting treats it all as one element. + local -a platforms + IFS=" " read -ra platforms <<< "${KUBE_BUILD_PLATFORMS}" + + # Deduplicate to ensure the intersection trick with kube::golang::dups + # is not defeated by duplicates in user input. + kube::util::read-array platforms < <(kube::golang::dedup "${platforms[@]}") + + # Use kube::golang::dups to restrict the builds to the platforms in + # KUBE_SUPPORTED_*_PLATFORMS. Items should only appear at most once in each + # set, so if they appear twice after the merge they are in the intersection. + kube::util::read-array KUBE_SERVER_PLATFORMS < <(kube::golang::dups \ + "${platforms[@]}" \ + "${KUBE_SUPPORTED_SERVER_PLATFORMS[@]}" \ + ) + readonly KUBE_SERVER_PLATFORMS + + kube::util::read-array KUBE_NODE_PLATFORMS < <(kube::golang::dups \ + "${platforms[@]}" \ + "${KUBE_SUPPORTED_NODE_PLATFORMS[@]}" \ + ) + readonly KUBE_NODE_PLATFORMS + + kube::util::read-array KUBE_TEST_PLATFORMS < <(kube::golang::dups \ + "${platforms[@]}" \ + "${KUBE_SUPPORTED_TEST_PLATFORMS[@]}" \ + ) + readonly KUBE_TEST_PLATFORMS + + kube::util::read-array KUBE_CLIENT_PLATFORMS < <(kube::golang::dups \ + "${platforms[@]}" \ + "${KUBE_SUPPORTED_CLIENT_PLATFORMS[@]}" \ + ) + readonly KUBE_CLIENT_PLATFORMS + + elif [[ "${KUBE_FASTBUILD:-}" == "true" ]]; then + host_arch=$(kube::util::host_arch) + if [[ "${host_arch}" != "amd64" && "${host_arch}" != "arm64" && "${host_arch}" != "ppc64le" && "${host_arch}" != "s390x" ]]; then + # on any platform other than amd64, arm64, ppc64le and s390x, we just default to amd64 + host_arch="amd64" + fi + KUBE_SERVER_PLATFORMS=("linux/${host_arch}") + readonly KUBE_SERVER_PLATFORMS + KUBE_NODE_PLATFORMS=("linux/${host_arch}") + readonly KUBE_NODE_PLATFORMS + if [[ "${KUBE_BUILDER_OS:-}" == "darwin"* ]]; then + KUBE_TEST_PLATFORMS=( + "darwin/${host_arch}" + "linux/${host_arch}" + ) + readonly KUBE_TEST_PLATFORMS + KUBE_CLIENT_PLATFORMS=( + "darwin/${host_arch}" + "linux/${host_arch}" + ) + readonly KUBE_CLIENT_PLATFORMS + else + KUBE_TEST_PLATFORMS=("linux/${host_arch}") + readonly KUBE_TEST_PLATFORMS + KUBE_CLIENT_PLATFORMS=("linux/${host_arch}") + readonly KUBE_CLIENT_PLATFORMS + fi + else + KUBE_SERVER_PLATFORMS=("${KUBE_SUPPORTED_SERVER_PLATFORMS[@]}") + readonly KUBE_SERVER_PLATFORMS + + KUBE_NODE_PLATFORMS=("${KUBE_SUPPORTED_NODE_PLATFORMS[@]}") + readonly KUBE_NODE_PLATFORMS + + KUBE_CLIENT_PLATFORMS=("${KUBE_SUPPORTED_CLIENT_PLATFORMS[@]}") + readonly KUBE_CLIENT_PLATFORMS + + KUBE_TEST_PLATFORMS=("${KUBE_SUPPORTED_TEST_PLATFORMS[@]}") + readonly KUBE_TEST_PLATFORMS + fi +} + +kube::golang::setup_platforms + +# The set of client targets that we are building for all platforms +readonly KUBE_CLIENT_TARGETS=( + cmd/kubectl + cmd/kubectl-convert +) +readonly KUBE_CLIENT_BINARIES=("${KUBE_CLIENT_TARGETS[@]##*/}") +readonly KUBE_CLIENT_BINARIES_WIN=("${KUBE_CLIENT_BINARIES[@]/%/.exe}") + +# The set of test targets that we are building for all platforms +kube::golang::test_targets() { + local targets=( + cmd/gendocs + cmd/genkubedocs + cmd/genman + cmd/genyaml + cmd/genswaggertypedocs + ginkgo + test/e2e/e2e.test + test/conformance/image/go-runner + ) + echo "${targets[@]}" +} +IFS=" " read -ra KUBE_TEST_TARGETS <<< "$(kube::golang::test_targets)" +readonly KUBE_TEST_TARGETS +readonly KUBE_TEST_BINARIES=("${KUBE_TEST_TARGETS[@]##*/}") +readonly KUBE_TEST_BINARIES_WIN=("${KUBE_TEST_BINARIES[@]/%/.exe}") +readonly KUBE_TEST_PORTABLE=( + test/e2e/testing-manifests + test/kubemark + hack/e2e-internal + hack/get-build.sh + hack/ginkgo-e2e.sh + hack/lib +) + +# Test targets which run on the Kubernetes clusters directly, so we only +# need to target server platforms. +# These binaries will be distributed in the kubernetes-test tarball. +kube::golang::server_test_targets() { + local targets=( + cmd/kubemark + ginkgo + ) + + if [[ "${OSTYPE:-}" == "linux"* ]]; then + targets+=( test/e2e_node/e2e_node.test ) + fi + + echo "${targets[@]}" +} + +IFS=" " read -ra KUBE_TEST_SERVER_TARGETS <<< "$(kube::golang::server_test_targets)" +readonly KUBE_TEST_SERVER_TARGETS +readonly KUBE_TEST_SERVER_BINARIES=("${KUBE_TEST_SERVER_TARGETS[@]##*/}") +readonly KUBE_TEST_SERVER_PLATFORMS=("${KUBE_SERVER_PLATFORMS[@]:+"${KUBE_SERVER_PLATFORMS[@]}"}") + +# Gigabytes necessary for parallel platform builds. +# As of March 2021 (go 1.16/amd64), the RSS usage is 2GiB by using cached +# memory of 15GiB. +# This variable can be overwritten at your own risk. +# It's defaulting to 20G to provide some headroom. +readonly KUBE_PARALLEL_BUILD_MEMORY=${KUBE_PARALLEL_BUILD_MEMORY:-20} + +readonly KUBE_ALL_TARGETS=( + "${KUBE_SERVER_TARGETS[@]}" + "${KUBE_CLIENT_TARGETS[@]}" + "${KUBE_TEST_TARGETS[@]}" + "${KUBE_TEST_SERVER_TARGETS[@]}" +) +readonly KUBE_ALL_BINARIES=("${KUBE_ALL_TARGETS[@]##*/}") + +readonly KUBE_STATIC_LIBRARIES=( + kube-apiserver + kube-controller-manager + kube-scheduler + kube-proxy + kube-log-runner + kubeadm + kubectl + kubemark +) + +# Fully-qualified package names that we want to instrument for coverage information. +readonly KUBE_COVERAGE_INSTRUMENTED_PACKAGES=( + k8s.io/kubernetes/cmd/kube-apiserver + k8s.io/kubernetes/cmd/kube-controller-manager + k8s.io/kubernetes/cmd/kube-scheduler + k8s.io/kubernetes/cmd/kube-proxy + k8s.io/kubernetes/cmd/kubelet +) + +# KUBE_CGO_OVERRIDES is a space-separated list of binaries which should be built +# with CGO enabled, assuming CGO is supported on the target platform. +# This overrides any entry in KUBE_STATIC_LIBRARIES. +IFS=" " read -ra KUBE_CGO_OVERRIDES_LIST <<< "${KUBE_CGO_OVERRIDES:-}" +readonly KUBE_CGO_OVERRIDES_LIST +# KUBE_STATIC_OVERRIDES is a space-separated list of binaries which should be +# built with CGO disabled. This is in addition to the list in +# KUBE_STATIC_LIBRARIES. +IFS=" " read -ra KUBE_STATIC_OVERRIDES_LIST <<< "${KUBE_STATIC_OVERRIDES:-}" +readonly KUBE_STATIC_OVERRIDES_LIST + +kube::golang::is_statically_linked_library() { + local e + # Explicitly enable cgo when building kubectl for darwin from darwin. + [[ "$(go env GOHOSTOS)" == "darwin" && "$(go env GOOS)" == "darwin" && + "$1" == *"/kubectl" ]] && return 1 + if [[ -n "${KUBE_CGO_OVERRIDES_LIST:+x}" ]]; then + for e in "${KUBE_CGO_OVERRIDES_LIST[@]}"; do [[ "${1}" == *"/${e}" ]] && return 1; done; + fi + for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "${1}" == *"/${e}" ]] && return 0; done; + if [[ -n "${KUBE_STATIC_OVERRIDES_LIST:+x}" ]]; then + for e in "${KUBE_STATIC_OVERRIDES_LIST[@]}"; do [[ "${1}" == *"/${e}" ]] && return 0; done; + fi + return 1; +} + +# kube::binaries_from_targets take a list of build targets and return the +# full go package to be built +kube::golang::binaries_from_targets() { + local target + for target; do + if [ "${target}" = "ginkgo" ] || + [ "${target}" = "github.com/onsi/ginkgo/ginkgo" ] || + [ "${target}" = "vendor/github.com/onsi/ginkgo/ginkgo" ]; then + # Aliases that build the ginkgo CLI for hack/ginkgo-e2e.sh. + # "ginkgo" is the one that is documented in the Makefile. The others + # are for backwards compatibility. + echo "github.com/onsi/ginkgo/v2/ginkgo" + elif [[ "${target}" =~ ^([[:alnum:]]+".")+[[:alnum:]]+"/" ]]; then + # If the target starts with what looks like a domain name, assume it has a + # fully-qualified package name rather than one that needs the Kubernetes + # package prepended. + echo "${target}" + elif [[ "${target}" =~ ^vendor/ ]]; then + # Strip vendor/ prefix, since we're building in gomodule mode. + echo "${target#"vendor/"}" + else + echo "${KUBE_GO_PACKAGE}/${target}" + fi + done +} + +# Asks golang what it thinks the host platform is. The go tool chain does some +# slightly different things when the target platform matches the host platform. +kube::golang::host_platform() { + echo "$(go env GOHOSTOS)/$(go env GOHOSTARCH)" +} + +# Takes the platform name ($1) and sets the appropriate golang env variables +# for that platform. +kube::golang::set_platform_envs() { + [[ -n ${1-} ]] || { + kube::log::error_exit "!!! Internal error. No platform set in kube::golang::set_platform_envs" + } + + export GOOS=${platform%/*} + export GOARCH=${platform##*/} + + # Do not set CC when building natively on a platform, only if cross-compiling + if [[ $(kube::golang::host_platform) != "$platform" ]]; then + # Dynamic CGO linking for other server architectures than host architecture goes here + # If you want to include support for more server platforms than these, add arch-specific gcc names here + case "${platform}" in + "linux/amd64") + export CGO_ENABLED=1 + export CC=${KUBE_LINUX_AMD64_CC:-x86_64-linux-gnu-gcc} + ;; + "linux/arm") + export CGO_ENABLED=1 + export CC=${KUBE_LINUX_ARM_CC:-arm-linux-gnueabihf-gcc} + ;; + "linux/arm64") + export CGO_ENABLED=1 + export CC=${KUBE_LINUX_ARM64_CC:-aarch64-linux-gnu-gcc} + ;; + "linux/ppc64le") + export CGO_ENABLED=1 + export CC=${KUBE_LINUX_PPC64LE_CC:-powerpc64le-linux-gnu-gcc} + ;; + "linux/s390x") + export CGO_ENABLED=1 + export CC=${KUBE_LINUX_S390X_CC:-s390x-linux-gnu-gcc} + ;; + esac + fi + + # if CC is defined for platform then always enable it + ccenv=$(echo "$platform" | awk -F/ '{print "KUBE_" toupper($1) "_" toupper($2) "_CC"}') + if [ -n "${!ccenv-}" ]; then + export CGO_ENABLED=1 + export CC="${!ccenv}" + fi +} + +# Create the GOPATH tree under $KUBE_OUTPUT +kube::golang::create_gopath_tree() { + local go_pkg_dir="${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}" + local go_pkg_basedir + go_pkg_basedir=$(dirname "${go_pkg_dir}") + + mkdir -p "${go_pkg_basedir}" + + # TODO: This symlink should be relative. + if [[ ! -e "${go_pkg_dir}" || "$(readlink "${go_pkg_dir}")" != "${KUBE_ROOT}" ]]; then + ln -snf "${KUBE_ROOT}" "${go_pkg_dir}" + fi +} + +# Ensure the go tool exists and is a viable version. +kube::golang::verify_go_version() { + if [[ -z "$(command -v go)" ]]; then + kube::log::usage_from_stdin <`, but it's subtle when it comes + # to cross-compiles and whether the is a file or a directory, + # and EVERY caller has to get it *just* right. + # * We could leave GOPATH alone and let `go install` write binaries + # wherever the user's GOPATH says (or doesn't say). + # + # Instead we set it to a phony local path and process the results ourselves. + # In particular, GOPATH[0]/bin will be used for `go install`, with + # cross-compiles adding an extra directory under that. + # + # Eventually, when we no longer rely on run-in-gopath.sh we may be able to + # simplify this some. + kube::golang::create_gopath_tree + export GOPATH="${KUBE_GOPATH}" + + export GOCACHE="${KUBE_GOPATH}/cache" + + # Make sure our own Go binaries are in PATH. + export PATH="${KUBE_GOPATH}/bin:${PATH}" + + # Change directories so that we are within the GOPATH. Some tools get really + # upset if this is not true. We use a whole fake GOPATH here to collect the + # resultant binaries. + local subdir + subdir=$(kube::realpath . | sed "s|${KUBE_ROOT}||") + cd "${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}/${subdir}" || return 1 + + # Set GOROOT so binaries that parse code can work properly. + GOROOT=$(go env GOROOT) + export GOROOT + + # Unset GOBIN in case it already exists in the current session. + # Cross-compiles will not work with it set. + unset GOBIN + + # This seems to matter to some tools + export GO15VENDOREXPERIMENT=1 +} + +# This will take binaries from $GOPATH/bin and copy them to the appropriate +# place in ${KUBE_OUTPUT_BINDIR} +# +# Ideally this wouldn't be necessary and we could just set GOBIN to +# KUBE_OUTPUT_BINDIR but that won't work in the face of cross compilation. 'go +# install' will place binaries that match the host platform directly in $GOBIN +# while placing cross compiled binaries into `platform_arch` subdirs. This +# complicates pretty much everything else we do around packaging and such. +kube::golang::place_bins() { + local host_platform + host_platform=$(kube::golang::host_platform) + + V=2 kube::log::status "Placing binaries" + + local platform + for platform in "${KUBE_CLIENT_PLATFORMS[@]}"; do + # The substitution on platform_src below will replace all slashes with + # underscores. It'll transform darwin/amd64 -> darwin_amd64. + local platform_src="/${platform//\//_}" + if [[ "${platform}" == "${host_platform}" ]]; then + platform_src="" + rm -f "${THIS_PLATFORM_BIN}" + ln -s "${KUBE_OUTPUT_BINPATH}/${platform}" "${THIS_PLATFORM_BIN}" + fi + + local full_binpath_src="${KUBE_GOPATH}/bin${platform_src}" + if [[ -d "${full_binpath_src}" ]]; then + mkdir -p "${KUBE_OUTPUT_BINPATH}/${platform}" + find "${full_binpath_src}" -maxdepth 1 -type f -exec \ + rsync -pc {} "${KUBE_OUTPUT_BINPATH}/${platform}" \; + fi + done +} + +# Try and replicate the native binary placement of go install without +# calling go install. +kube::golang::outfile_for_binary() { + local binary=$1 + local platform=$2 + local output_path="${KUBE_GOPATH}/bin" + local bin + bin=$(basename "${binary}") + if [[ "${platform}" != "${host_platform}" ]]; then + output_path="${output_path}/${platform//\//_}" + fi + if [[ ${GOOS} == "windows" ]]; then + bin="${bin}.exe" + fi + echo "${output_path}/${bin}" +} + +# Argument: the name of a Kubernetes package. +# Returns 0 if the binary can be built with coverage, 1 otherwise. +# NB: this ignores whether coverage is globally enabled or not. +kube::golang::is_instrumented_package() { + if kube::util::array_contains "$1" "${KUBE_COVERAGE_INSTRUMENTED_PACKAGES[@]}"; then + return 0 + fi + # Some cases, like `make kubectl`, pass $1 as "./cmd/kubectl" rather than + # "k8s.io/kubernetes/kubectl". Try to normalize and handle that. We don't + # do this always because it is a bit slow. + pkg=$(go list -find "$1") + if kube::util::array_contains "${pkg}" "${KUBE_COVERAGE_INSTRUMENTED_PACKAGES[@]}"; then + return 0 + fi + return 1 +} + +# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler) +# Echos the path to a dummy test used for coverage information. +kube::golang::path_for_coverage_dummy_test() { + local package="$1" + local path="${KUBE_GOPATH}/src/${package}" + local name + name=$(basename "${package}") + echo "${path}/zz_generated_${name}_test.go" +} + +# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler). +# Creates a dummy unit test on disk in the source directory for the given package. +# This unit test will invoke the package's standard entry point when run. +kube::golang::create_coverage_dummy_test() { + local package="$1" + local name + name="$(basename "${package}")" + cat < "$(kube::golang::path_for_coverage_dummy_test "${package}")" +package main +import ( + "testing" + "k8s.io/kubernetes/pkg/util/coverage" +) + +func TestMain(m *testing.M) { + // Get coverage running + coverage.InitCoverage("${name}") + + // Go! + main() + + // Make sure we actually write the profiling information to disk, if we make it here. + // On long-running services, or anything that calls os.Exit(), this is insufficient, + // so we also flush periodically with a default period of five seconds (configurable by + // the KUBE_COVERAGE_FLUSH_INTERVAL environment variable). + coverage.FlushCoverage() +} +EOF +} + +# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler). +# Deletes a test generated by kube::golang::create_coverage_dummy_test. +# It is not an error to call this for a nonexistent test. +kube::golang::delete_coverage_dummy_test() { + local package="$1" + rm -f "$(kube::golang::path_for_coverage_dummy_test "${package}")" +} + +# Arguments: a list of kubernetes packages to build. +# Expected variables: ${build_args} should be set to an array of Go build arguments. +# In addition, ${package} and ${platform} should have been set earlier, and if +# ${KUBE_BUILD_WITH_COVERAGE} is set, coverage instrumentation will be enabled. +# +# Invokes Go to actually build some packages. If coverage is disabled, simply invokes +# go install. If coverage is enabled, builds covered binaries using go test, temporarily +# producing the required unit test files and then cleaning up after itself. +# Non-covered binaries are then built using go install as usual. +# +# See comments in kube::golang::setup_env regarding where built binaries go. +kube::golang::build_some_binaries() { + if [[ -n "${KUBE_BUILD_WITH_COVERAGE:-}" ]]; then + local -a uncovered=() + for package in "$@"; do + if kube::golang::is_instrumented_package "${package}"; then + V=2 kube::log::info "Building ${package} with coverage..." + + kube::golang::create_coverage_dummy_test "${package}" + kube::util::trap_add "kube::golang::delete_coverage_dummy_test \"${package}\"" EXIT + + go test -c -o "$(kube::golang::outfile_for_binary "${package}" "${platform}")" \ + -covermode count \ + -coverpkg k8s.io/...,k8s.io/kubernetes/vendor/k8s.io/... \ + "${build_args[@]}" \ + -tags coverage \ + "${package}" + else + uncovered+=("${package}") + fi + done + if [[ "${#uncovered[@]}" != 0 ]]; then + V=2 kube::log::info "Building ${uncovered[*]} without coverage..." + GO111MODULE=on GOPROXY=off go install "${build_args[@]}" "${uncovered[@]}" + else + V=2 kube::log::info "Nothing to build without coverage." + fi + else + V=2 kube::log::info "Coverage is disabled." + GO111MODULE=on GOPROXY=off go install "${build_args[@]}" "$@" + fi +} + +# Args: +# $1: platform (e.g. darwin/amd64) +kube::golang::build_binaries_for_platform() { + # This is for sanity. Without it, user umasks can leak through. + umask 0022 + + local platform=$1 + + local -a statics=() + local -a nonstatics=() + local -a tests=() + + for binary in "${binaries[@]}"; do + if [[ "${binary}" =~ ".test"$ ]]; then + tests+=("${binary}") + kube::log::info " ${binary} (test)" + elif kube::golang::is_statically_linked_library "${binary}"; then + statics+=("${binary}") + kube::log::info " ${binary} (static)" + else + nonstatics+=("${binary}") + kube::log::info " ${binary} (non-static)" + fi + done + + V=2 kube::log::info "Env for ${platform}: GOOS=${GOOS-} GOARCH=${GOARCH-} GOROOT=${GOROOT-} CGO_ENABLED=${CGO_ENABLED-} CC=${CC-}" + V=3 kube::log::info "Building binaries with GCFLAGS=${gogcflags} ASMFLAGS=${goasmflags} LDFLAGS=${goldflags}" + + local -a build_args + if [[ "${#statics[@]}" != 0 ]]; then + build_args=( + -installsuffix=static + ${goflags:+"${goflags[@]}"} + -gcflags="${gogcflags}" + -asmflags="${goasmflags}" + -ldflags="${goldflags}" + -tags="${gotags:-}" + ) + CGO_ENABLED=0 kube::golang::build_some_binaries "${statics[@]}" + fi + + if [[ "${#nonstatics[@]}" != 0 ]]; then + build_args=( + ${goflags:+"${goflags[@]}"} + -gcflags="${gogcflags}" + -asmflags="${goasmflags}" + -ldflags="${goldflags}" + -tags="${gotags:-}" + ) + kube::golang::build_some_binaries "${nonstatics[@]}" + fi + + for test in "${tests[@]:+${tests[@]}}"; do + local outfile testpkg + outfile=$(kube::golang::outfile_for_binary "${test}" "${platform}") + testpkg=$(dirname "${test}") + + mkdir -p "$(dirname "${outfile}")" + go test -c \ + ${goflags:+"${goflags[@]}"} \ + -gcflags="${gogcflags}" \ + -asmflags="${goasmflags}" \ + -ldflags="${goldflags}" \ + -tags="${gotags:-}" \ + -o "${outfile}" \ + "${testpkg}" + done +} + +# Return approximate physical memory available in gigabytes. +kube::golang::get_physmem() { + local mem + + # Linux kernel version >=3.14, in kb + if mem=$(grep MemAvailable /proc/meminfo | awk '{ print $2 }'); then + echo $(( mem / 1048576 )) + return + fi + + # Linux, in kb + if mem=$(grep MemTotal /proc/meminfo | awk '{ print $2 }'); then + echo $(( mem / 1048576 )) + return + fi + + # OS X, in bytes. Note that get_physmem, as used, should only ever + # run in a Linux container (because it's only used in the multiple + # platform case, which is a Dockerized build), but this is provided + # for completeness. + if mem=$(sysctl -n hw.memsize 2>/dev/null); then + echo $(( mem / 1073741824 )) + return + fi + + # If we can't infer it, just give up and assume a low memory system + echo 1 +} + +# Build binaries targets specified +# +# Input: +# $@ - targets and go flags. If no targets are set then all binaries targets +# are built. +# KUBE_BUILD_PLATFORMS - Incoming variable of targets to build for. If unset +# then just the host architecture is built. +kube::golang::build_binaries() { + # Create a sub-shell so that we don't pollute the outer environment + ( + # Check for `go` binary and set ${GOPATH}. + kube::golang::setup_env + V=2 kube::log::info "Go version: $(GOFLAGS='' go version)" + + local host_platform + host_platform=$(kube::golang::host_platform) + + # These are "local" but are visible to and relied on by functions this + # function calls. They are effectively part of the calling API to + # build_binaries_for_platform. + local goflags goldflags goasmflags gogcflags gotags + + # This is $(pwd) because we use run-in-gopath to build. Once that is + # excised, this can become ${KUBE_ROOT}. + local trimroot # two lines to appease shellcheck SC2155 + trimroot=$(pwd) + + goasmflags="all=-trimpath=${trimroot}" + + gogcflags="all=-trimpath=${trimroot} ${GOGCFLAGS:-}" + if [[ "${DBG:-}" == 1 ]]; then + # Debugging - disable optimizations and inlining and trimPath + gogcflags="${GOGCFLAGS:-} all=-N -l" + goasmflags="" + fi + + goldflags="all=$(kube::version::ldflags) ${GOLDFLAGS:-}" + if [[ "${DBG:-}" != 1 ]]; then + # Not debugging - disable symbols and DWARF. + goldflags="${goldflags} -s -w" + fi + + # Extract tags if any specified in GOFLAGS + gotags="selinux,notest,$(echo "${GOFLAGS:-}" | sed -ne 's|.*-tags=\([^-]*\).*|\1|p')" + + local -a targets=() + local arg + + for arg; do + if [[ "${arg}" == -* ]]; then + # Assume arguments starting with a dash are flags to pass to go. + goflags+=("${arg}") + else + targets+=("${arg}") + fi + done + + if [[ ${#targets[@]} -eq 0 ]]; then + targets=("${KUBE_ALL_TARGETS[@]}") + fi + + local -a platforms + IFS=" " read -ra platforms <<< "${KUBE_BUILD_PLATFORMS:-}" + if [[ ${#platforms[@]} -eq 0 ]]; then + platforms=("${host_platform}") + fi + + local -a binaries + while IFS="" read -r binary; do binaries+=("$binary"); done < <(kube::golang::binaries_from_targets "${targets[@]}") + + local parallel=false + if [[ ${#platforms[@]} -gt 1 ]]; then + local gigs + gigs=$(kube::golang::get_physmem) + + if [[ ${gigs} -ge ${KUBE_PARALLEL_BUILD_MEMORY} ]]; then + kube::log::status "Multiple platforms requested and available ${gigs}G >= threshold ${KUBE_PARALLEL_BUILD_MEMORY}G, building platforms in parallel" + parallel=true + else + kube::log::status "Multiple platforms requested, but available ${gigs}G < threshold ${KUBE_PARALLEL_BUILD_MEMORY}G, building platforms in serial" + parallel=false + fi + fi + + if [[ "${parallel}" == "true" ]]; then + kube::log::status "Building go targets for {${platforms[*]}} in parallel (output will appear in a burst when complete):" "${targets[@]}" + local platform + for platform in "${platforms[@]}"; do ( + kube::golang::set_platform_envs "${platform}" + kube::log::status "${platform}: build started" + kube::golang::build_binaries_for_platform "${platform}" + kube::log::status "${platform}: build finished" + ) &> "/tmp//${platform//\//_}.build" & + done + + local fails=0 + for job in $(jobs -p); do + wait "${job}" || (( fails+=1 )) + done + + for platform in "${platforms[@]}"; do + cat "/tmp//${platform//\//_}.build" + done + + exit "${fails}" + else + for platform in "${platforms[@]}"; do + kube::log::status "Building go targets for ${platform}" + ( + kube::golang::set_platform_envs "${platform}" + kube::golang::build_binaries_for_platform "${platform}" + ) + done + fi + ) +} diff --git a/third_party/k8s.io/kubernetes/hack/lib/init.sh b/third_party/k8s.io/kubernetes/hack/lib/init.sh new file mode 100755 index 00000000000..51e3d1db195 --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/lib/init.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +# Unset CDPATH so that path interpolation can work correctly +# https://github.com/kubernetes/kubernetes/issues/52255 +unset CDPATH + +# Until all GOPATH references are removed from all build scripts as well, +# explicitly disable module mode to avoid picking up user-set GO111MODULE preferences. +# As individual scripts (like hack/update-vendor.sh) make use of go modules, +# they can explicitly set GO111MODULE=on +export GO111MODULE=off + +# The root of the build/dist directory +KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" + +KUBE_OUTPUT_SUBPATH="${KUBE_OUTPUT_SUBPATH:-_output/local}" +KUBE_OUTPUT="${KUBE_ROOT}/${KUBE_OUTPUT_SUBPATH}" +KUBE_OUTPUT_BINPATH="${KUBE_OUTPUT}/bin" + +# This controls rsync compression. Set to a value > 0 to enable rsync +# compression for build container +KUBE_RSYNC_COMPRESS="${KUBE_RSYNC_COMPRESS:-0}" + +# Set no_proxy for localhost if behind a proxy, otherwise, +# the connections to localhost in scripts will time out +export no_proxy="127.0.0.1,localhost${no_proxy:+,${no_proxy}}" + +# This is a symlink to binaries for "this platform", e.g. build tools. +export THIS_PLATFORM_BIN="${KUBE_ROOT}/_output/bin" + +source "${KUBE_ROOT}/hack/lib/util.sh" +source "${KUBE_ROOT}/hack/lib/logging.sh" + +kube::log::install_errexit +kube::util::ensure-bash-version + +source "${KUBE_ROOT}/hack/lib/version.sh" +source "${KUBE_ROOT}/hack/lib/golang.sh" +source "${KUBE_ROOT}/hack/lib/etcd.sh" + +KUBE_OUTPUT_HOSTBIN="${KUBE_OUTPUT_BINPATH}/$(kube::util::host_platform)" +export KUBE_OUTPUT_HOSTBIN + +# list of all available group versions. This should be used when generated code +# or when starting an API server that you want to have everything. +# most preferred version for a group should appear first +KUBE_AVAILABLE_GROUP_VERSIONS="${KUBE_AVAILABLE_GROUP_VERSIONS:-\ +v1 \ +admissionregistration.k8s.io/v1 \ +admissionregistration.k8s.io/v1alpha1 \ +admissionregistration.k8s.io/v1beta1 \ +admission.k8s.io/v1 \ +admission.k8s.io/v1beta1 \ +apps/v1 \ +apps/v1beta1 \ +apps/v1beta2 \ +authentication.k8s.io/v1 \ +authentication.k8s.io/v1alpha1 \ +authentication.k8s.io/v1beta1 \ +authorization.k8s.io/v1 \ +authorization.k8s.io/v1beta1 \ +autoscaling/v1 \ +autoscaling/v2 \ +autoscaling/v2beta1 \ +autoscaling/v2beta2 \ +batch/v1 \ +batch/v1beta1 \ +certificates.k8s.io/v1 \ +certificates.k8s.io/v1beta1 \ +coordination.k8s.io/v1beta1 \ +coordination.k8s.io/v1 \ +discovery.k8s.io/v1 \ +discovery.k8s.io/v1beta1 \ +extensions/v1beta1 \ +events.k8s.io/v1 \ +events.k8s.io/v1beta1 \ +imagepolicy.k8s.io/v1alpha1 \ +networking.k8s.io/v1 \ +networking.k8s.io/v1alpha1 \ +networking.k8s.io/v1beta1 \ +node.k8s.io/v1 \ +node.k8s.io/v1alpha1 \ +node.k8s.io/v1beta1 \ +policy/v1 \ +policy/v1beta1 \ +rbac.authorization.k8s.io/v1 \ +rbac.authorization.k8s.io/v1beta1 \ +rbac.authorization.k8s.io/v1alpha1 \ +scheduling.k8s.io/v1alpha1 \ +scheduling.k8s.io/v1beta1 \ +scheduling.k8s.io/v1 \ +storage.k8s.io/v1beta1 \ +storage.k8s.io/v1 \ +storage.k8s.io/v1alpha1 \ +flowcontrol.apiserver.k8s.io/v1alpha1 \ +flowcontrol.apiserver.k8s.io/v1beta1 \ +flowcontrol.apiserver.k8s.io/v1beta2 \ +flowcontrol.apiserver.k8s.io/v1beta3 \ +internal.apiserver.k8s.io/v1alpha1 \ +}" + +# not all group versions are exposed by the server. This list contains those +# which are not available so we don't generate clients or swagger for them +KUBE_NONSERVER_GROUP_VERSIONS=" + abac.authorization.kubernetes.io/v0 \ + abac.authorization.kubernetes.io/v1beta1 \ + apidiscovery.k8s.io/v2beta1 \ + componentconfig/v1alpha1 \ + imagepolicy.k8s.io/v1alpha1\ + admission.k8s.io/v1\ + admission.k8s.io/v1beta1\ +" +export KUBE_NONSERVER_GROUP_VERSIONS + +# This emulates "readlink -f" which is not available on MacOS X. +# Test: +# T=/tmp/$$.$RANDOM +# mkdir $T +# touch $T/file +# mkdir $T/dir +# ln -s $T/file $T/linkfile +# ln -s $T/dir $T/linkdir +# function testone() { +# X=$(readlink -f $1 2>&1) +# Y=$(kube::readlinkdashf $1 2>&1) +# if [ "$X" != "$Y" ]; then +# echo readlinkdashf $1: expected "$X", got "$Y" +# fi +# } +# testone / +# testone /tmp +# testone $T +# testone $T/file +# testone $T/dir +# testone $T/linkfile +# testone $T/linkdir +# testone $T/nonexistant +# testone $T/linkdir/file +# testone $T/linkdir/dir +# testone $T/linkdir/linkfile +# testone $T/linkdir/linkdir +function kube::readlinkdashf { + # run in a subshell for simpler 'cd' + ( + if [[ -d "${1}" ]]; then # This also catch symlinks to dirs. + cd "${1}" + pwd -P + else + cd "$(dirname "${1}")" + local f + f=$(basename "${1}") + if [[ -L "${f}" ]]; then + readlink "${f}" + else + echo "$(pwd -P)/${f}" + fi + fi + ) +} + +# This emulates "realpath" which is not available on MacOS X +# Test: +# T=/tmp/$$.$RANDOM +# mkdir $T +# touch $T/file +# mkdir $T/dir +# ln -s $T/file $T/linkfile +# ln -s $T/dir $T/linkdir +# function testone() { +# X=$(realpath $1 2>&1) +# Y=$(kube::realpath $1 2>&1) +# if [ "$X" != "$Y" ]; then +# echo realpath $1: expected "$X", got "$Y" +# fi +# } +# testone / +# testone /tmp +# testone $T +# testone $T/file +# testone $T/dir +# testone $T/linkfile +# testone $T/linkdir +# testone $T/nonexistant +# testone $T/linkdir/file +# testone $T/linkdir/dir +# testone $T/linkdir/linkfile +# testone $T/linkdir/linkdir +kube::realpath() { + if [[ ! -e "${1}" ]]; then + echo "${1}: No such file or directory" >&2 + return 1 + fi + kube::readlinkdashf "${1}" +} diff --git a/third_party/k8s.io/kubernetes/hack/lib/logging.sh b/third_party/k8s.io/kubernetes/hack/lib/logging.sh new file mode 100644 index 00000000000..8a175b3af4e --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/lib/logging.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Controls verbosity of the script output and logging. +KUBE_VERBOSE="${KUBE_VERBOSE:-2}" + +# Handler for when we exit automatically on an error. +# Borrowed from https://gist.github.com/ahendrix/7030300 +kube::log::errexit() { + local err="${PIPESTATUS[*]}" + + # If the shell we are in doesn't have errexit set (common in subshells) then + # don't dump stacks. + set +o | grep -qe "-o errexit" || return + + set +o xtrace + local code="${1:-1}" + # Print out the stack trace described by $function_stack + if [ ${#FUNCNAME[@]} -gt 2 ] + then + kube::log::error "Call tree:" + for ((i=1;i<${#FUNCNAME[@]}-1;i++)) + do + kube::log::error " ${i}: ${BASH_SOURCE[${i}+1]}:${BASH_LINENO[${i}]} ${FUNCNAME[${i}]}(...)" + done + fi + kube::log::error_exit "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${BASH_COMMAND}' exited with status ${err}" "${1:-1}" 1 +} + +kube::log::install_errexit() { + # trap ERR to provide an error handler whenever a command exits nonzero this + # is a more verbose version of set -o errexit + trap 'kube::log::errexit' ERR + + # setting errtrace allows our ERR trap handler to be propagated to functions, + # expansions and subshells + set -o errtrace +} + +# Print out the stack trace +# +# Args: +# $1 The number of stack frames to skip when printing. +kube::log::stack() { + local stack_skip=${1:-0} + stack_skip=$((stack_skip + 1)) + if [[ ${#FUNCNAME[@]} -gt ${stack_skip} ]]; then + echo "Call stack:" >&2 + local i + for ((i=1 ; i <= ${#FUNCNAME[@]} - stack_skip ; i++)) + do + local frame_no=$((i - 1 + stack_skip)) + local source_file=${BASH_SOURCE[${frame_no}]} + local source_lineno=${BASH_LINENO[$((frame_no - 1))]} + local funcname=${FUNCNAME[${frame_no}]} + echo " ${i}: ${source_file}:${source_lineno} ${funcname}(...)" >&2 + done + fi +} + +# Log an error and exit. +# Args: +# $1 Message to log with the error +# $2 The error code to return +# $3 The number of stack frames to skip when printing. +kube::log::error_exit() { + local message="${1:-}" + local code="${2:-1}" + local stack_skip="${3:-0}" + stack_skip=$((stack_skip + 1)) + + if [[ ${KUBE_VERBOSE} -ge 4 ]]; then + local source_file=${BASH_SOURCE[${stack_skip}]} + local source_line=${BASH_LINENO[$((stack_skip - 1))]} + echo "!!! Error in ${source_file}:${source_line}" >&2 + [[ -z ${1-} ]] || { + echo " ${1}" >&2 + } + + kube::log::stack ${stack_skip} + + echo "Exiting with status ${code}" >&2 + fi + + exit "${code}" +} + +# Log an error but keep going. Don't dump the stack or exit. +kube::log::error() { + timestamp=$(date +"[%m%d %H:%M:%S]") + echo "!!! ${timestamp} ${1-}" >&2 + shift + for message; do + echo " ${message}" >&2 + done +} + +# Print an usage message to stderr. The arguments are printed directly. +kube::log::usage() { + echo >&2 + local message + for message; do + echo "${message}" >&2 + done + echo >&2 +} + +kube::log::usage_from_stdin() { + local messages=() + while read -r line; do + messages+=("${line}") + done + + kube::log::usage "${messages[@]}" +} + +# Print out some info that isn't a top level status line +kube::log::info() { + local V="${V:-0}" + if [[ ${KUBE_VERBOSE} < ${V} ]]; then + return + fi + + for message; do + echo "${message}" + done +} + +# Just like kube::log::info, but no \n, so you can make a progress bar +kube::log::progress() { + for message; do + echo -e -n "${message}" + done +} + +kube::log::info_from_stdin() { + local messages=() + while read -r line; do + messages+=("${line}") + done + + kube::log::info "${messages[@]}" +} + +# Print a status line. Formatted to show up in a stream of output. +kube::log::status() { + local V="${V:-0}" + if [[ ${KUBE_VERBOSE} < ${V} ]]; then + return + fi + + timestamp=$(date +"[%m%d %H:%M:%S]") + echo "+++ ${timestamp} ${1}" + shift + for message; do + echo " ${message}" + done +} diff --git a/third_party/k8s.io/kubernetes/hack/lib/util.sh b/third_party/k8s.io/kubernetes/hack/lib/util.sh new file mode 100755 index 00000000000..ad284906209 --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/lib/util.sh @@ -0,0 +1,890 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +function kube::util::sourced_variable { + # Call this function to tell shellcheck that a variable is supposed to + # be used from other calling context. This helps quiet an "unused + # variable" warning from shellcheck and also document your code. + true +} + +kube::util::sortable_date() { + date "+%Y%m%d-%H%M%S" +} + +# arguments: target, item1, item2, item3, ... +# returns 0 if target is in the given items, 1 otherwise. +kube::util::array_contains() { + local search="$1" + local element + shift + for element; do + if [[ "${element}" == "${search}" ]]; then + return 0 + fi + done + return 1 +} + +kube::util::wait_for_url() { + local url=$1 + local prefix=${2:-} + local wait=${3:-1} + local times=${4:-30} + local maxtime=${5:-1} + + command -v curl >/dev/null || { + kube::log::usage "curl must be installed" + exit 1 + } + + local i + for i in $(seq 1 "${times}"); do + local out + if out=$(curl --max-time "${maxtime}" -gkfs "${@:6}" "${url}" 2>/dev/null); then + kube::log::status "On try ${i}, ${prefix}: ${out}" + return 0 + fi + sleep "${wait}" + done + kube::log::error "Timed out waiting for ${prefix} to answer at ${url}; tried ${times} waiting ${wait} between each" + return 1 +} + +kube::util::wait_for_url_with_bearer_token() { + local url=$1 + local token=$2 + local prefix=${3:-} + local wait=${4:-1} + local times=${5:-30} + local maxtime=${6:-1} + + kube::util::wait_for_url "${url}" "${prefix}" "${wait}" "${times}" "${maxtime}" -H "Authorization: Bearer ${token}" +} + +# Example: kube::util::wait_for_success 120 5 "kubectl get nodes|grep localhost" +# arguments: wait time, sleep time, shell command +# returns 0 if the shell command get output, 1 otherwise. +kube::util::wait_for_success(){ + local wait_time="$1" + local sleep_time="$2" + local cmd="$3" + while [ "$wait_time" -gt 0 ]; do + if eval "$cmd"; then + return 0 + else + sleep "$sleep_time" + wait_time=$((wait_time-sleep_time)) + fi + done + return 1 +} + +# Example: kube::util::trap_add 'echo "in trap DEBUG"' DEBUG +# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal +kube::util::trap_add() { + local trap_add_cmd + trap_add_cmd=$1 + shift + + for trap_add_name in "$@"; do + local existing_cmd + local new_cmd + + # Grab the currently defined trap commands for this trap + existing_cmd=$(trap -p "${trap_add_name}" | awk -F"'" '{print $2}') + + if [[ -z "${existing_cmd}" ]]; then + new_cmd="${trap_add_cmd}" + else + new_cmd="${trap_add_cmd};${existing_cmd}" + fi + + # Assign the test. Disable the shellcheck warning telling that trap + # commands should be single quoted to avoid evaluating them at this + # point instead evaluating them at run time. The logic of adding new + # commands to a single trap requires them to be evaluated right away. + # shellcheck disable=SC2064 + trap "${new_cmd}" "${trap_add_name}" + done +} + +# Opposite of kube::util::ensure-temp-dir() +kube::util::cleanup-temp-dir() { + rm -rf "${KUBE_TEMP}" +} + +# Create a temp dir that'll be deleted at the end of this bash session. +# +# Vars set: +# KUBE_TEMP +kube::util::ensure-temp-dir() { + if [[ -z ${KUBE_TEMP-} ]]; then + KUBE_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t kubernetes.XXXXXX) + kube::util::trap_add kube::util::cleanup-temp-dir EXIT + fi +} + +kube::util::host_os() { + local host_os + case "$(uname -s)" in + Darwin) + host_os=darwin + ;; + Linux) + host_os=linux + ;; + *) + kube::log::error "Unsupported host OS. Must be Linux or Mac OS X." + exit 1 + ;; + esac + echo "${host_os}" +} + +kube::util::host_arch() { + local host_arch + case "$(uname -m)" in + x86_64*) + host_arch=amd64 + ;; + i?86_64*) + host_arch=amd64 + ;; + amd64*) + host_arch=amd64 + ;; + aarch64*) + host_arch=arm64 + ;; + arm64*) + host_arch=arm64 + ;; + arm*) + host_arch=arm + ;; + i?86*) + host_arch=x86 + ;; + s390x*) + host_arch=s390x + ;; + ppc64le*) + host_arch=ppc64le + ;; + *) + kube::log::error "Unsupported host arch. Must be x86_64, 386, arm, arm64, s390x or ppc64le." + exit 1 + ;; + esac + echo "${host_arch}" +} + +# This figures out the host platform without relying on golang. We need this as +# we don't want a golang install to be a prerequisite to building yet we need +# this info to figure out where the final binaries are placed. +kube::util::host_platform() { + echo "$(kube::util::host_os)/$(kube::util::host_arch)" +} + +# looks for $1 in well-known output locations for the platform ($2) +# $KUBE_ROOT must be set +kube::util::find-binary-for-platform() { + local -r lookfor="$1" + local -r platform="$2" + local locations=( + "${KUBE_ROOT}/_output/bin/${lookfor}" + "${KUBE_ROOT}/_output/dockerized/bin/${platform}/${lookfor}" + "${KUBE_ROOT}/_output/local/bin/${platform}/${lookfor}" + "${KUBE_ROOT}/platforms/${platform}/${lookfor}" + ) + + # if we're looking for the host platform, add local non-platform-qualified search paths + if [[ "${platform}" = "$(kube::util::host_platform)" ]]; then + locations+=( + "${KUBE_ROOT}/_output/local/go/bin/${lookfor}" + "${KUBE_ROOT}/_output/dockerized/go/bin/${lookfor}" + ); + fi + + # looks for $1 in the $PATH + if which "${lookfor}" >/dev/null; then + local -r local_bin="$(which "${lookfor}")" + locations+=( "${local_bin}" ); + fi + + # List most recently-updated location. + local -r bin=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 ) + + if [[ -z "${bin}" ]]; then + kube::log::error "Failed to find binary ${lookfor} for platform ${platform}" + return 1 + fi + + echo -n "${bin}" +} + +# looks for $1 in well-known output locations for the host platform +# $KUBE_ROOT must be set +kube::util::find-binary() { + kube::util::find-binary-for-platform "$1" "$(kube::util::host_platform)" +} + +# Run all known doc generators (today gendocs and genman for kubectl) +# $1 is the directory to put those generated documents +kube::util::gen-docs() { + local dest="$1" + + # Find binary + gendocs=$(kube::util::find-binary "gendocs") + genkubedocs=$(kube::util::find-binary "genkubedocs") + genman=$(kube::util::find-binary "genman") + genyaml=$(kube::util::find-binary "genyaml") + + mkdir -p "${dest}/docs/user-guide/kubectl/" + "${gendocs}" "${dest}/docs/user-guide/kubectl/" + mkdir -p "${dest}/docs/admin/" + "${genkubedocs}" "${dest}/docs/admin/" "kube-apiserver" + "${genkubedocs}" "${dest}/docs/admin/" "kube-controller-manager" + "${genkubedocs}" "${dest}/docs/admin/" "kube-proxy" + "${genkubedocs}" "${dest}/docs/admin/" "kube-scheduler" + "${genkubedocs}" "${dest}/docs/admin/" "kubelet" + "${genkubedocs}" "${dest}/docs/admin/" "kubeadm" + + mkdir -p "${dest}/docs/man/man1/" + "${genman}" "${dest}/docs/man/man1/" "kube-apiserver" + "${genman}" "${dest}/docs/man/man1/" "kube-controller-manager" + "${genman}" "${dest}/docs/man/man1/" "kube-proxy" + "${genman}" "${dest}/docs/man/man1/" "kube-scheduler" + "${genman}" "${dest}/docs/man/man1/" "kubelet" + "${genman}" "${dest}/docs/man/man1/" "kubectl" + "${genman}" "${dest}/docs/man/man1/" "kubeadm" + + mkdir -p "${dest}/docs/yaml/kubectl/" + "${genyaml}" "${dest}/docs/yaml/kubectl/" + + # create the list of generated files + pushd "${dest}" > /dev/null || return 1 + touch docs/.generated_docs + find . -type f | cut -sd / -f 2- | LC_ALL=C sort > docs/.generated_docs + popd > /dev/null || return 1 +} + +# Removes previously generated docs-- we don't want to check them in. $KUBE_ROOT +# must be set. +kube::util::remove-gen-docs() { + if [ -e "${KUBE_ROOT}/docs/.generated_docs" ]; then + # remove all of the old docs; we don't want to check them in. + while read -r file; do + rm "${KUBE_ROOT}/${file}" 2>/dev/null || true + done <"${KUBE_ROOT}/docs/.generated_docs" + # The docs/.generated_docs file lists itself, so we don't need to explicitly + # delete it. + fi +} + +# Takes a group/version and returns the path to its location on disk, sans +# "pkg". E.g.: +# * default behavior: extensions/v1beta1 -> apis/extensions/v1beta1 +# * default behavior for only a group: experimental -> apis/experimental +# * Special handling for empty group: v1 -> api/v1, unversioned -> api/unversioned +# * Special handling for groups suffixed with ".k8s.io": foo.k8s.io/v1 -> apis/foo/v1 +# * Very special handling for when both group and version are "": / -> api +# +# $KUBE_ROOT must be set. +kube::util::group-version-to-pkg-path() { + local group_version="$1" + + while IFS=$'\n' read -r api; do + if [[ "${api}" = "${group_version/.*k8s.io/}" ]]; then + echo "vendor/k8s.io/api/${group_version/.*k8s.io/}" + return + fi + done < <(cd "${KUBE_ROOT}/staging/src/k8s.io/api" && find . -name types.go -exec dirname {} \; | sed "s|\./||g" | sort) + + # "v1" is the API GroupVersion + if [[ "${group_version}" == "v1" ]]; then + echo "vendor/k8s.io/api/core/v1" + return + fi + + # Special cases first. + # TODO(lavalamp): Simplify this by moving pkg/api/v1 and splitting pkg/api, + # moving the results to pkg/apis/api. + case "${group_version}" in + # both group and version are "", this occurs when we generate deep copies for internal objects of the legacy v1 API. + __internal) + echo "pkg/apis/core" + ;; + meta/v1) + echo "vendor/k8s.io/apimachinery/pkg/apis/meta/v1" + ;; + meta/v1beta1) + echo "vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1" + ;; + internal.apiserver.k8s.io/v1alpha1) + echo "vendor/k8s.io/api/apiserverinternal/v1alpha1" + ;; + *.k8s.io) + echo "pkg/apis/${group_version%.*k8s.io}" + ;; + *.k8s.io/*) + echo "pkg/apis/${group_version/.*k8s.io/}" + ;; + *) + echo "pkg/apis/${group_version%__internal}" + ;; + esac +} + +# Takes a group/version and returns the swagger-spec file name. +# default behavior: extensions/v1beta1 -> extensions_v1beta1 +# special case for v1: v1 -> v1 +kube::util::gv-to-swagger-name() { + local group_version="$1" + case "${group_version}" in + v1) + echo "v1" + ;; + *) + echo "${group_version%/*}_${group_version#*/}" + ;; + esac +} + +# Returns the name of the upstream remote repository name for the local git +# repo, e.g. "upstream" or "origin". +kube::util::git_upstream_remote_name() { + git remote -v | grep fetch |\ + grep -E 'github.com[/:]kubernetes/kubernetes|k8s.io/kubernetes' |\ + head -n 1 | awk '{print $1}' +} + +# Exits script if working directory is dirty. If it's run interactively in the terminal +# the user can commit changes in a second terminal. This script will wait. +kube::util::ensure_clean_working_dir() { + while ! git diff HEAD --exit-code &>/dev/null; do + echo -e "\nUnexpected dirty working directory:\n" + if tty -s; then + git status -s + else + git diff -a # be more verbose in log files without tty + exit 1 + fi | sed 's/^/ /' + echo -e "\nCommit your changes in another terminal and then continue here by pressing enter." + read -r + done 1>&2 +} + +# Find the base commit using: +# $PULL_BASE_SHA if set (from Prow) +# current ref from the remote upstream branch +kube::util::base_ref() { + local -r git_branch=$1 + + if [[ -n ${PULL_BASE_SHA:-} ]]; then + echo "${PULL_BASE_SHA}" + return + fi + + full_branch="$(kube::util::git_upstream_remote_name)/${git_branch}" + + # make sure the branch is valid, otherwise the check will pass erroneously. + if ! git describe "${full_branch}" >/dev/null; then + # abort! + exit 1 + fi + + echo "${full_branch}" +} + +# Checks whether there are any files matching pattern $2 changed between the +# current branch and upstream branch named by $1. +# Returns 1 (false) if there are no changes +# 0 (true) if there are changes detected. +kube::util::has_changes() { + local -r git_branch=$1 + local -r pattern=$2 + local -r not_pattern=${3:-totallyimpossiblepattern} + + local base_ref + base_ref=$(kube::util::base_ref "${git_branch}") + echo "Checking for '${pattern}' changes against '${base_ref}'" + + # notice this uses ... to find the first shared ancestor + if git diff --name-only "${base_ref}...HEAD" | grep -v -E "${not_pattern}" | grep "${pattern}" > /dev/null; then + return 0 + fi + # also check for pending changes + if git status --porcelain | grep -v -E "${not_pattern}" | grep "${pattern}" > /dev/null; then + echo "Detected '${pattern}' uncommitted changes." + return 0 + fi + echo "No '${pattern}' changes detected." + return 1 +} + +kube::util::download_file() { + local -r url=$1 + local -r destination_file=$2 + + rm "${destination_file}" 2&> /dev/null || true + + for i in $(seq 5) + do + if ! curl -fsSL --retry 3 --keepalive-time 2 "${url}" -o "${destination_file}"; then + echo "Downloading ${url} failed. $((5-i)) retries left." + sleep 1 + else + echo "Downloading ${url} succeed" + return 0 + fi + done + return 1 +} + +# Test whether openssl is installed. +# Sets: +# OPENSSL_BIN: The path to the openssl binary to use +function kube::util::test_openssl_installed { + if ! openssl version >& /dev/null; then + echo "Failed to run openssl. Please ensure openssl is installed" + exit 1 + fi + + OPENSSL_BIN=$(command -v openssl) +} + +# Query the API server for client certificate authentication capabilities +function kube::util::test_client_certificate_authentication_enabled { + local output + kube::util::test_openssl_installed + + output=$(echo \ + | "${OPENSSL_BIN}" s_client -connect "127.0.0.1:${SECURE_API_PORT}" 2> /dev/null \ + | grep -A3 'Acceptable client certificate CA names') + + if [[ "${output}" != *"/CN=127.0.0.1"* ]] && [[ "${output}" != *"CN = 127.0.0.1"* ]]; then + echo "API server not configured for client certificate authentication" + echo "Output of from acceptable client certificate check: ${output}" + exit 1 + fi +} + +# creates a client CA, args are sudo, dest-dir, ca-id, purpose +# purpose is dropped in after "key encipherment", you usually want +# '"client auth"' +# '"server auth"' +# '"client auth","server auth"' +function kube::util::create_signing_certkey { + local sudo=$1 + local dest_dir=$2 + local id=$3 + local purpose=$4 + # Create client ca + ${sudo} /usr/bin/env bash -e < "${dest_dir}/${id}-ca-config.json" +EOF +} + +# signs a client certificate: args are sudo, dest-dir, CA, filename (roughly), username, groups... +function kube::util::create_client_certkey { + local sudo=$1 + local dest_dir=$2 + local ca=$3 + local id=$4 + local cn=${5:-$4} + local groups="" + local SEP="" + shift 5 + while [ -n "${1:-}" ]; do + groups+="${SEP}{\"O\":\"$1\"}" + SEP="," + shift 1 + done + ${sudo} /usr/bin/env bash -e < /dev/null +apiVersion: v1 +kind: Config +clusters: + - cluster: + certificate-authority: ${ca_file} + server: https://${api_host}:${api_port}/ + name: local-up-cluster +users: + - user: + token: ${token} + client-certificate: ${dest_dir}/client-${client_id}.crt + client-key: ${dest_dir}/client-${client_id}.key + name: local-up-cluster +contexts: + - context: + cluster: local-up-cluster + user: local-up-cluster + name: local-up-cluster +current-context: local-up-cluster +EOF + + # flatten the kubeconfig files to make them self contained + username=$(whoami) + ${sudo} /usr/bin/env bash -e < "/tmp/${client_id}.kubeconfig" + mv -f "/tmp/${client_id}.kubeconfig" "${dest_dir}/${client_id}.kubeconfig" + chown ${username} "${dest_dir}/${client_id}.kubeconfig" +EOF +} + +# list_staging_repos outputs a sorted list of repos in staging/src/k8s.io +# each entry will just be the $repo portion of staging/src/k8s.io/$repo/... +# $KUBE_ROOT must be set. +function kube::util::list_staging_repos() { + ( + cd "${KUBE_ROOT}/staging/src/k8s.io" && \ + find . -mindepth 1 -maxdepth 1 -type d | cut -c 3- | sort + ) +} + + +# Determines if docker can be run, failures may simply require that the user be added to the docker group. +function kube::util::ensure_docker_daemon_connectivity { + DOCKER_OPTS=${DOCKER_OPTS:-""} + IFS=" " read -ra docker_opts <<< "${DOCKER_OPTS}" + if ! docker "${docker_opts[@]:+"${docker_opts[@]}"}" info > /dev/null 2>&1 ; then + cat <<'EOF' >&2 +Can't connect to 'docker' daemon. please fix and retry. + +Possible causes: + - Docker Daemon not started + - Linux: confirm via your init system + - macOS w/ Docker for Mac: Check the menu bar and start the Docker application + - DOCKER_HOST hasn't been set or is set incorrectly + - Linux: domain socket is used, DOCKER_* should be unset. In Bash run `unset ${!DOCKER_*}` + - macOS w/ Docker for Mac: domain socket is used, DOCKER_* should be unset. In Bash run `unset ${!DOCKER_*}` + - Other things to check: + - Linux: User isn't in 'docker' group. Add and relogin. + - Something like 'sudo usermod -a -G docker ${USER}' + - RHEL7 bug and workaround: https://bugzilla.redhat.com/show_bug.cgi?id=1119282#c8 +EOF + return 1 + fi +} + +# Wait for background jobs to finish. Return with +# an error status if any of the jobs failed. +kube::util::wait-for-jobs() { + local fail=0 + local job + for job in $(jobs -p); do + wait "${job}" || fail=$((fail + 1)) + done + return ${fail} +} + +# kube::util::join +# Concatenates the list elements with the delimiter passed as first parameter +# +# Ex: kube::util::join , a b c +# -> a,b,c +function kube::util::join { + local IFS="$1" + shift + echo "$*" +} + +# Downloads cfssl/cfssljson into $1 directory if they do not already exist in PATH +# +# Assumed vars: +# $1 (cfssl directory) (optional) +# +# Sets: +# CFSSL_BIN: The path of the installed cfssl binary +# CFSSLJSON_BIN: The path of the installed cfssljson binary +# +# shellcheck disable=SC2120 # optional parameters +function kube::util::ensure-cfssl { + if command -v cfssl &>/dev/null && command -v cfssljson &>/dev/null; then + CFSSL_BIN=$(command -v cfssl) + CFSSLJSON_BIN=$(command -v cfssljson) + return 0 + fi + + host_arch=$(kube::util::host_arch) + + if [[ "${host_arch}" != "amd64" ]]; then + echo "Cannot download cfssl on non-amd64 hosts and cfssl does not appear to be installed." + echo "Please install cfssl and cfssljson and verify they are in \$PATH." + echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go install github.com/cloudflare/cfssl/cmd/...@latest" + exit 1 + fi + + # Create a temp dir for cfssl if no directory was given + local cfssldir=${1:-} + if [[ -z "${cfssldir}" ]]; then + kube::util::ensure-temp-dir + cfssldir="${KUBE_TEMP}/cfssl" + fi + + mkdir -p "${cfssldir}" + pushd "${cfssldir}" > /dev/null || return 1 + + echo "Unable to successfully run 'cfssl' from ${PATH}; downloading instead..." + kernel=$(uname -s) + case "${kernel}" in + Linux) + curl --retry 10 -L -o cfssl https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_linux_amd64 + curl --retry 10 -L -o cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_linux_amd64 + ;; + Darwin) + curl --retry 10 -L -o cfssl https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_darwin_amd64 + curl --retry 10 -L -o cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_darwin_amd64 + ;; + *) + echo "Unknown, unsupported platform: ${kernel}." >&2 + echo "Supported platforms: Linux, Darwin." >&2 + exit 2 + esac + + chmod +x cfssl || true + chmod +x cfssljson || true + + CFSSL_BIN="${cfssldir}/cfssl" + CFSSLJSON_BIN="${cfssldir}/cfssljson" + if [[ ! -x ${CFSSL_BIN} || ! -x ${CFSSLJSON_BIN} ]]; then + echo "Failed to download 'cfssl'. Please install cfssl and cfssljson and verify they are in \$PATH." + echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go install github.com/cloudflare/cfssl/cmd/...@latest" + exit 1 + fi + popd > /dev/null || return 1 +} + +# kube::util::ensure-docker-buildx +# Check if we have "docker buildx" commands available +# +function kube::util::ensure-docker-buildx { + if docker buildx --help >/dev/null 2>&1; then + return 0 + else + echo "ERROR: docker buildx not available. Docker 19.03 or higher is required with experimental features enabled" + exit 1 + fi +} + +# kube::util::ensure-bash-version +# Check if we are using a supported bash version +# +function kube::util::ensure-bash-version { + # shellcheck disable=SC2004 + if ((${BASH_VERSINFO[0]}<4)) || ( ((${BASH_VERSINFO[0]}==4)) && ((${BASH_VERSINFO[1]}<2)) ); then + echo "ERROR: This script requires a minimum bash version of 4.2, but got version of ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}" + if [ "$(uname)" = 'Darwin' ]; then + echo "On macOS with homebrew 'brew install bash' is sufficient." + fi + exit 1 + fi +} + +# kube::util::ensure-gnu-sed +# Determines which sed binary is gnu-sed on linux/darwin +# +# Sets: +# SED: The name of the gnu-sed binary +# +function kube::util::ensure-gnu-sed { + # NOTE: the echo below is a workaround to ensure sed is executed before the grep. + # see: https://github.com/kubernetes/kubernetes/issues/87251 + sed_help="$(LANG=C sed --help 2>&1 || true)" + if echo "${sed_help}" | grep -q "GNU\|BusyBox"; then + SED="sed" + elif command -v gsed &>/dev/null; then + SED="gsed" + else + kube::log::error "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2 + return 1 + fi + kube::util::sourced_variable "${SED}" +} + +# kube::util::ensure-gnu-date +# Determines which date binary is gnu-date on linux/darwin +# +# Sets: +# DATE: The name of the gnu-date binary +# +function kube::util::ensure-gnu-date { + # NOTE: the echo below is a workaround to ensure date is executed before the grep. + # see: https://github.com/kubernetes/kubernetes/issues/87251 + date_help="$(LANG=C date --help 2>&1 || true)" + if echo "${date_help}" | grep -q "GNU\|BusyBox"; then + DATE="date" + elif command -v gdate &>/dev/null; then + DATE="gdate" + else + kube::log::error "Failed to find GNU date as date or gdate. If you are on Mac: brew install coreutils." >&2 + return 1 + fi + kube::util::sourced_variable "${DATE}" +} + +# kube::util::check-file-in-alphabetical-order +# Check that the file is in alphabetical order +# +function kube::util::check-file-in-alphabetical-order { + local failure_file="$1" + if ! diff -u "${failure_file}" <(LC_ALL=C sort "${failure_file}"); then + { + echo + echo "${failure_file} is not in alphabetical order. Please sort it:" + echo + echo " LC_ALL=C sort -o ${failure_file} ${failure_file}" + echo + } >&2 + false + fi +} + +# kube::util::require-jq +# Checks whether jq is installed. +function kube::util::require-jq { + if ! command -v jq &>/dev/null; then + kube::log::error "jq not found. Please install." + return 1 + fi +} + +# outputs md5 hash of $1, works on macOS and Linux +function kube::util::md5() { + if which md5 >/dev/null 2>&1; then + md5 -q "$1" + else + md5sum "$1" | awk '{ print $1 }' + fi +} + +# kube::util::read-array +# Reads in stdin and adds it line by line to the array provided. This can be +# used instead of "mapfile -t", and is bash 3 compatible. If the named array +# exists and is an array, it will be used. Otherwise it will be unset and +# recreated. +# +# Assumed vars: +# $1 (name of array to create/modify) +# +# Example usage: +# kube::util::read-array files < <(ls -1) +# +# When in doubt: +# $ W=abc # a string +# $ X=(a b c) # an array +# $ declare -A Y # an associative array +# $ unset Z # not set at all +# $ declare -p W X Y Z +# declare -- W="abc" +# declare -a X=([0]="a" [1]="b" [2]="c") +# declare -A Y +# bash: line 26: declare: Z: not found +# $ kube::util::read-array W < <(echo -ne "1 1\n2 2\n3 3\n") +# bash: W is defined but isn't an array +# $ kube::util::read-array X < <(echo -ne "1 1\n2 2\n3 3\n") +# $ kube::util::read-array Y < <(echo -ne "1 1\n2 2\n3 3\n") +# bash: Y is defined but isn't an array +# $ kube::util::read-array Z < <(echo -ne "1 1\n2 2\n3 3\n") +# $ declare -p W X Y Z +# declare -- W="abc" +# declare -a X=([0]="1 1" [1]="2 2" [2]="3 3") +# declare -A Y +# declare -a Z=([0]="1 1" [1]="2 2" [2]="3 3") +function kube::util::read-array { + if [[ -z "$1" ]]; then + echo "usage: ${FUNCNAME[0]} " >&2 + return 1 + fi + if [[ -n $(declare -p "$1" 2>/dev/null) ]]; then + if ! declare -p "$1" 2>/dev/null | grep -q '^declare -a'; then + echo "${FUNCNAME[0]}: $1 is defined but isn't an array" >&2 + return 2 + fi + fi + # shellcheck disable=SC2034 # this variable _is_ used + local __read_array_i=0 + while IFS= read -r "$1[__read_array_i++]"; do :; done + if ! eval "[[ \${$1[--__read_array_i]} ]]"; then + unset "$1[__read_array_i]" # ensures last element isn't empty + fi +} + +# Some useful colors. +if [[ -z "${color_start-}" ]]; then + declare -r color_start="\033[" + declare -r color_red="${color_start}0;31m" + declare -r color_yellow="${color_start}0;33m" + declare -r color_green="${color_start}0;32m" + declare -r color_blue="${color_start}1;34m" + declare -r color_cyan="${color_start}1;36m" + declare -r color_norm="${color_start}0m" + + kube::util::sourced_variable "${color_start}" + kube::util::sourced_variable "${color_red}" + kube::util::sourced_variable "${color_yellow}" + kube::util::sourced_variable "${color_green}" + kube::util::sourced_variable "${color_blue}" + kube::util::sourced_variable "${color_cyan}" + kube::util::sourced_variable "${color_norm}" +fi + +# ex: ts=2 sw=2 et filetype=sh diff --git a/third_party/k8s.io/kubernetes/hack/lib/version.sh b/third_party/k8s.io/kubernetes/hack/lib/version.sh new file mode 100644 index 00000000000..f8dcc7b1ba8 --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/lib/version.sh @@ -0,0 +1,185 @@ +#!/usr/bin/env bash + +# Copyright 2014 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ----------------------------------------------------------------------------- +# Version management helpers. These functions help to set, save and load the +# following variables: +# +# KUBE_GIT_COMMIT - The git commit id corresponding to this +# source code. +# KUBE_GIT_TREE_STATE - "clean" indicates no changes since the git commit id +# "dirty" indicates source code changes after the git commit id +# "archive" indicates the tree was produced by 'git archive' +# KUBE_GIT_VERSION - "vX.Y" used to indicate the last release version. +# KUBE_GIT_MAJOR - The major part of the version +# KUBE_GIT_MINOR - The minor component of the version + +# Grovels through git to set a set of env variables. +# +# If KUBE_GIT_VERSION_FILE, this function will load from that file instead of +# querying git. +kube::version::get_version_vars() { + if [[ -n ${KUBE_GIT_VERSION_FILE-} ]]; then + kube::version::load_version_vars "${KUBE_GIT_VERSION_FILE}" + return + fi + + # If the kubernetes source was exported through git archive, then + # we likely don't have a git tree, but these magic values may be filled in. + # shellcheck disable=SC2016,SC2050 + # Disabled as we're not expanding these at runtime, but rather expecting + # that another tool may have expanded these and rewritten the source (!) + if [[ '$Format:%%$' == "%" ]]; then + KUBE_GIT_COMMIT='$Format:%H$' + KUBE_GIT_TREE_STATE="archive" + # When a 'git archive' is exported, the '$Format:%D$' below will look + # something like 'HEAD -> release-1.8, tag: v1.8.3' where then 'tag: ' + # can be extracted from it. + if [[ '$Format:%D$' =~ tag:\ (v[^ ,]+) ]]; then + KUBE_GIT_VERSION="${BASH_REMATCH[1]}" + fi + fi + + local git=(git --work-tree "${KUBE_ROOT}") + + if [[ -n ${KUBE_GIT_COMMIT-} ]] || KUBE_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then + if [[ -z ${KUBE_GIT_TREE_STATE-} ]]; then + # Check if the tree is dirty. default to dirty + if git_status=$("${git[@]}" status --porcelain 2>/dev/null) && [[ -z ${git_status} ]]; then + KUBE_GIT_TREE_STATE="clean" + else + KUBE_GIT_TREE_STATE="dirty" + fi + fi + + # Use git describe to find the version based on tags. + if [[ -n ${KUBE_GIT_VERSION-} ]] || KUBE_GIT_VERSION=$("${git[@]}" describe --tags --match='v*' --abbrev=14 "${KUBE_GIT_COMMIT}^{commit}" 2>/dev/null); then + # This translates the "git describe" to an actual semver.org + # compatible semantic version that looks something like this: + # v1.1.0-alpha.0.6+84c76d1142ea4d + # + # TODO: We continue calling this "git version" because so many + # downstream consumers are expecting it there. + # + # These regexes are painful enough in sed... + # We don't want to do them in pure shell, so disable SC2001 + # shellcheck disable=SC2001 + DASHES_IN_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/[^-]//g") + if [[ "${DASHES_IN_VERSION}" == "---" ]] ; then + # shellcheck disable=SC2001 + # We have distance to subversion (v1.1.0-subversion-1-gCommitHash) + KUBE_GIT_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\+\2/") + elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then + # shellcheck disable=SC2001 + # We have distance to base tag (v1.1.0-1-gCommitHash) + KUBE_GIT_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/") + fi + if [[ "${KUBE_GIT_TREE_STATE}" == "dirty" ]]; then + # git describe --dirty only considers changes to existing files, but + # that is problematic since new untracked .go files affect the build, + # so use our idea of "dirty" from git status instead. + KUBE_GIT_VERSION+="-dirty" + fi + + + # Try to match the "git describe" output to a regex to try to extract + # the "major" and "minor" versions and whether this is the exact tagged + # version or whether the tree is between two tagged versions. + if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then + KUBE_GIT_MAJOR=${BASH_REMATCH[1]} + KUBE_GIT_MINOR=${BASH_REMATCH[2]} + if [[ -n "${BASH_REMATCH[4]}" ]]; then + KUBE_GIT_MINOR+="+" + fi + fi + + # If KUBE_GIT_VERSION is not a valid Semantic Version, then refuse to build. + if ! [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then + kube::log::error "KUBE_GIT_VERSION should be a valid Semantic Version. Current value: ${KUBE_GIT_VERSION}" + kube::log::error "Please see more details here: https://semver.org" + exit 1 + fi + fi + fi +} + +# Saves the environment flags to $1 +kube::version::save_version_vars() { + local version_file=${1-} + [[ -n ${version_file} ]] || { + echo "!!! Internal error. No file specified in kube::version::save_version_vars" + return 1 + } + + cat <"${version_file}" +KUBE_GIT_COMMIT='${KUBE_GIT_COMMIT-}' +KUBE_GIT_TREE_STATE='${KUBE_GIT_TREE_STATE-}' +KUBE_GIT_VERSION='${KUBE_GIT_VERSION-}' +KUBE_GIT_MAJOR='${KUBE_GIT_MAJOR-}' +KUBE_GIT_MINOR='${KUBE_GIT_MINOR-}' +EOF +} + +# Loads up the version variables from file $1 +kube::version::load_version_vars() { + local version_file=${1-} + [[ -n ${version_file} ]] || { + echo "!!! Internal error. No file specified in kube::version::load_version_vars" + return 1 + } + + source "${version_file}" +} + +# Prints the value that needs to be passed to the -ldflags parameter of go build +# in order to set the Kubernetes based on the git tree status. +# IMPORTANT: if you update any of these, also update the lists in +# hack/print-workspace-status.sh. +kube::version::ldflags() { + kube::version::get_version_vars + + local -a ldflags + function add_ldflag() { + local key=${1} + local val=${2} + ldflags+=( + "-X '${KUBE_GO_PACKAGE}/vendor/k8s.io/client-go/pkg/version.${key}=${val}'" + "-X '${KUBE_GO_PACKAGE}/vendor/k8s.io/component-base/version.${key}=${val}'" + "-X 'k8s.io/client-go/pkg/version.${key}=${val}'" + "-X 'k8s.io/component-base/version.${key}=${val}'" + ) + } + + kube::util::ensure-gnu-date + + add_ldflag "buildDate" "$(${DATE} ${SOURCE_DATE_EPOCH:+"--date=@${SOURCE_DATE_EPOCH}"} -u +'%Y-%m-%dT%H:%M:%SZ')" + if [[ -n ${KUBE_GIT_COMMIT-} ]]; then + add_ldflag "gitCommit" "${KUBE_GIT_COMMIT}" + add_ldflag "gitTreeState" "${KUBE_GIT_TREE_STATE}" + fi + + if [[ -n ${KUBE_GIT_VERSION-} ]]; then + add_ldflag "gitVersion" "${KUBE_GIT_VERSION}" + fi + + if [[ -n ${KUBE_GIT_MAJOR-} && -n ${KUBE_GIT_MINOR-} ]]; then + add_ldflag "gitMajor" "${KUBE_GIT_MAJOR}" + add_ldflag "gitMinor" "${KUBE_GIT_MINOR}" + fi + + # The -ldflags parameter takes a single string, so join the output. + echo "${ldflags[*]-}" +} diff --git a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh new file mode 100755 index 00000000000..0987e714ea3 --- /dev/null +++ b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash + +# Copyright 2016 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Usage: `hack/verify-licenses.sh`. + + +set -o errexit +set -o nounset +set -o pipefail + + +KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +source "${KUBE_ROOT}/hack/lib/init.sh" +source "${KUBE_ROOT}/hack/lib/util.sh" + + +kube::golang::verify_go_version +kube::util::ensure-temp-dir + + +# Creating a new repository tree +# Deleting vendor directory to make go-licenses fetch license URLs from go-packages source repository +git worktree add -f "${KUBE_TEMP}"/tmp_test_licenses/kubernetes HEAD >/dev/null 2>&1 || true +cd "${KUBE_TEMP}"/tmp_test_licenses/kubernetes && rm -rf vendor + + +# Ensure that we find the binaries we build before anything else. +export GOBIN="${KUBE_OUTPUT_BINPATH}" +PATH="${GOBIN}:${PATH}" + + +# Explicitly opt into go modules, even though we're inside a GOPATH directory +export GO111MODULE=on + + +allowed_licenses=() +packages_flagged=() +packages_url_missing=() +exit_code=0 + +# Install go-licenses +echo '[INFO] Installing go-licenses...' +go install github.com/google/go-licenses@latest + +# Fetching CNCF Approved List Of Licenses +# Refer: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md +curl -s 'https://spdx.org/licenses/licenses.json' -o "${KUBE_TEMP}"/licenses.json + +number_of_licenses=$(jq '.licenses | length' "${KUBE_TEMP}"/licenses.json) +loop_index_length=$(( number_of_licenses - 1 )) + + +echo '[INFO] Fetching current list of CNCF approved licenses...' +for index in $(seq 0 $loop_index_length); +do + licenseID=$(jq ".licenses[$index] .licenseId" "${KUBE_TEMP}"/licenses.json) + if [[ $(jq ".licenses[$index] .isDeprecatedLicenseId" "${KUBE_TEMP}"/licenses.json) == false ]] + then + allowed_licenses+=("${licenseID}") + fi +done + + +# Scanning go-packages under the project & verifying against the CNCF approved list of licenses +echo '[INFO] Starting license scan on go-packages...' +go-licenses report ./... >> "${KUBE_TEMP}"/licenses.csv + +echo -e 'PACKAGE_NAME LICENSE_NAME LICENSE_URL\n' >> "${KUBE_TEMP}"/approved_licenses.dump +while IFS=, read -r GO_PACKAGE LICENSE_URL LICENSE_NAME +do + FORMATTED_LICENSE_URL= + if [[ " ${allowed_licenses[*]} " == *"${LICENSE_NAME}"* ]]; + then + if [[ "${LICENSE_URL}" == 'Unknown' ]]; + then + if [[ "${GO_PACKAGE}" != k8s.io/* ]]; + then + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses_with_missing_urls.dump + packages_url_missing+=("${GO_PACKAGE}") + else + LICENSE_URL='https://github.com/kubernetes/kubernetes/blob/master/LICENSE' + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses.dump + fi + elif curl -Is "${LICENSE_URL}" | head -1 | grep -q 404; + then + # Check whether the License URL is incorrectly formed + # TODO: Remove this workaround check once PR https://github.com/google/go-licenses/pull/110 is merged + IFS='/' read -r -a split_license_url <<< ${LICENSE_URL} + for part_of_url in "${split_license_url[@]}" + do + if [[ ${part_of_url} == '' ]] + then + continue + elif [[ ${part_of_url} == 'https:' ]] + then + FORMATTED_LICENSE_URL+='https://' + else + if [[ ${part_of_url} =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]] + then + FORMATTED_LICENSE_URL+="${part_of_url}/${split_license_url[-1]}" + break + else + FORMATTED_LICENSE_URL+="${part_of_url}/" + fi + fi + done + if curl -Is "${FORMATTED_LICENSE_URL}" | head -1 | grep -q 404; + then + packages_url_missing+=("${GO_PACKAGE}") + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses_with_missing_urls.dump + else + echo "${GO_PACKAGE} ${LICENSE_NAME} ${FORMATTED_LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses.dump + fi + else + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses.dump + fi + else + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/notapproved_licenses.dump + packages_flagged+=("${GO_PACKAGE}") + fi +done < "${KUBE_TEMP}"/licenses.csv +awk '{ printf "%-100s : %-20s : %s\n", $1, $2, $3 }' "${KUBE_TEMP}"/approved_licenses.dump + + +if [[ ${#packages_url_missing[@]} -gt 0 ]]; then + echo -e '\n[ERROR] The following go-packages in the project have unknown or unreachable license URL:' + awk '{ printf "%-100s : %-20s : %s\n", $1, $2, $3 }' "${KUBE_TEMP}"/approved_licenses_with_missing_urls.dump + exit_code=1 +fi + + +if [[ ${#packages_flagged[@]} -gt 0 ]]; then + kube::log::error "[ERROR] The following go-packages in the project are using non-CNCF approved licenses. Please refer to the CNCF's approved licence list for further information: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md" + awk '{ printf "%-100s : %-20s : %s\n", $1, $2, $3 }' "${KUBE_TEMP}"/notapproved_licenses.dump + exit_code=1 +elif [[ "${exit_code}" -eq 1 ]]; then + kube::log::status "[ERROR] Project is using go-packages with unknown or unreachable license URLs. Please refer to the CNCF's approved licence list for further information: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md" +else + kube::log::status "[SUCCESS] Scan complete! All go-packages under the project are using current CNCF approved licenses!" +fi + +exit "${exit_code}" From c5102055d7c5f2515b3beaf1840ec4af52b6d694 Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:25:22 +0000 Subject: [PATCH 05/11] replace some k8s references, fix path Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- third_party/k8s.io/kubernetes/hack/verify-licenses.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh index 0987e714ea3..837875e31ab 100755 --- a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh +++ b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh @@ -33,8 +33,8 @@ kube::util::ensure-temp-dir # Creating a new repository tree # Deleting vendor directory to make go-licenses fetch license URLs from go-packages source repository -git worktree add -f "${KUBE_TEMP}"/tmp_test_licenses/kubernetes HEAD >/dev/null 2>&1 || true -cd "${KUBE_TEMP}"/tmp_test_licenses/kubernetes && rm -rf vendor +git worktree add -f "${KUBE_TEMP}"/tmp_test_licenses/gatekeeper HEAD >/dev/null 2>&1 || true +cd "${KUBE_TEMP}"/tmp_test_licenses/gatekeeper && rm -rf vendor # Ensure that we find the binaries we build before anything else. From 6236261f1ea3df983ad629c11f451c797ed9972d Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Thu, 5 Jan 2023 01:32:03 +0000 Subject: [PATCH 06/11] swap out license linter Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .github/workflows/license-lint.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/license-lint.yaml b/.github/workflows/license-lint.yaml index f9336bcaeef..132fd0a3d0e 100644 --- a/.github/workflows/license-lint.yaml +++ b/.github/workflows/license-lint.yaml @@ -21,6 +21,4 @@ jobs: run: | export GOPATH="$HOME/go" PATH="$GOPATH/bin:$PATH" - go install istio.io/tools/cmd/license-lint@1.16.0 - - license-lint --config ./.github/license-lint-config.yml 2>&1 + ./third_party/k8s.io/kubernetes/hack/verify-licenses.sh From 3e5fc32f7f6653dcc0768ce9a598397e97d53fad Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Thu, 5 Jan 2023 02:04:26 +0000 Subject: [PATCH 07/11] delete license-lint config Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .github/license-lint-config.yml | 68 --------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 .github/license-lint-config.yml diff --git a/.github/license-lint-config.yml b/.github/license-lint-config.yml deleted file mode 100644 index 74572806705..00000000000 --- a/.github/license-lint-config.yml +++ /dev/null @@ -1,68 +0,0 @@ -unrestricted_licenses: - - Apache-2.0 - - BSD-2-Clause - - BSD-3-Clause - - 0BSD - - MIT - -restricted_licenses: - - bzip2-1.0.5 - - AGPL-1.0 - - AGPL-3.0 - - BSD-2-Clause-FreeBSD - - BSD-2-Clause-NetBSD - - eCos-2.0 - - GFDL-1.1 - - GFDL-1.2 - - GFDL-1.3 - - GPL-1.0-only - - GPL-1.0-or-later - - GPL-2.0+ - - GPL-2.0-only - - GPL-2.0-or-later - - GPL-2.0-with-autoconf-exception - - GPL-2.0-with-bison-exception - - GPL-2.0-with-classpath-exception - - GPL-2.0-with-GCC-exception - - GPL-2.0-with-font-exception - - GPL-3.0-only - - GPL-3.0-or-later - - GPL-3.0+ - - GPL-3.0-with-autoconf-exception - - GPL-3.0-with-GCC-exception - - LGPL-2.0-only - - LGPL-2.0+ - - LGPL-2.0-or-later - - LGPL-2.1-only - - LGPL-2.1-or-later - - LGPL-3.0-only - - LGPL-3.0-or-later - - LGPL-3.0+ - - NPL-1.0 - - NPL-1.1 - - Nunit - - OSL-1.0 - - OSL-1.1 - - OSL-2.0 - - OSL-2.1 - - OSL-3.0 - - QPL-1.0 - - Sleepycat - - StandardML-NJ - - wxWindows - -allowlisted_modules: - # MIT: https://github.com/ghodss/yaml/blob/master/LICENSE - - github.com/ghodss/yaml - # BSD: https://github.com/gogo/protobuf/blob/master/LICENSE - - github.com/gogo/protobuf - # Apache 2.0 - - github.com/spf13/cobra - # https://github.com/xeipuuv/gojsonpointer/blob/master/LICENSE-APACHE-2.0.txt - - github.com/xeipuuv/gojsonpointer - # https://github.com/xeipuuv/gojsonreference/blob/master/LICENSE-APACHE-2.0.txt - - github.com/xeipuuv/gojsonreference - # MIT: https://github.com/kubernetes-sigs/yaml/blob/master/LICENSE - - sigs.k8s.io/yaml - # BSD-2-Clause: https://github.com/rcrowley/go-metrics/blob/master/LICENSE - - github.com/rcrowley/go-metrics \ No newline at end of file From d2fb3cdfd55b536b72ecbb7faa4e1988503aafeb Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Fri, 6 Jan 2023 16:17:09 +0000 Subject: [PATCH 08/11] designer commits: specify CF url, add exception, include tests Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .../k8s.io/kubernetes/hack/verify-licenses.sh | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh index 837875e31ab..279e9721c88 100755 --- a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh +++ b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh @@ -76,7 +76,7 @@ done # Scanning go-packages under the project & verifying against the CNCF approved list of licenses echo '[INFO] Starting license scan on go-packages...' -go-licenses report ./... >> "${KUBE_TEMP}"/licenses.csv +go-licenses report ./... --include_tests >> "${KUBE_TEMP}"/licenses.csv echo -e 'PACKAGE_NAME LICENSE_NAME LICENSE_URL\n' >> "${KUBE_TEMP}"/approved_licenses.dump while IFS=, read -r GO_PACKAGE LICENSE_URL LICENSE_NAME @@ -96,6 +96,14 @@ do fi elif curl -Is "${LICENSE_URL}" | head -1 | grep -q 404; then + # For gatekeeper, the script won't find the constraint frameworks's license atm. + if [[ "${GO_PACKAGE}" == github.com/open-policy-agent/frameworks/* ]]; + then + LICENSE_URL='https://github.com/open-policy-agent/frameworks/blob/master/LICENSE' + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses.dump + continue + fi + # Check whether the License URL is incorrectly formed # TODO: Remove this workaround check once PR https://github.com/google/go-licenses/pull/110 is merged IFS='/' read -r -a split_license_url <<< ${LICENSE_URL} @@ -128,8 +136,18 @@ do echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses.dump fi else - echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/notapproved_licenses.dump - packages_flagged+=("${GO_PACKAGE}") + # Not all packages at this point should go to the not approved dump. + # there are a few exceptions approved by CNCF as per: https://github.com/cncf/foundation/tree/main/license-exceptions + # Currently gatekeeper uses just one of those so we are not going to do a general solution. + + if [[ "${GO_PACKAGE}" == "github.com/rcrowley/go-metrics" ]] && [[ "${LICENSE_NAME}" == "BSD-2-Clause-FreeBSD" ]]; + then + # as per https://github.com/cncf/foundation/blob/main/license-exceptions/cncf-exceptions-2019-11-01.json#L723-L726 + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/approved_licenses.dump + else + echo "${GO_PACKAGE} ${LICENSE_NAME} ${LICENSE_URL}" >> "${KUBE_TEMP}"/notapproved_licenses.dump + packages_flagged+=("${GO_PACKAGE}") + fi fi done < "${KUBE_TEMP}"/licenses.csv awk '{ printf "%-100s : %-20s : %s\n", $1, $2, $3 }' "${KUBE_TEMP}"/approved_licenses.dump From 46e88a8503048e3662273c903b4ea674b3624167 Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:52:31 +0000 Subject: [PATCH 09/11] add wf paths Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .github/workflows/license-lint.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/license-lint.yaml b/.github/workflows/license-lint.yaml index 132fd0a3d0e..1e6113084fb 100644 --- a/.github/workflows/license-lint.yaml +++ b/.github/workflows/license-lint.yaml @@ -1,5 +1,15 @@ name: license-lint -on: [push, pull_request] +on: + push: + paths: + - "go.mod" + - "go.sum" + - "vendor/**" + pull_request: + paths: + - "go.mod" + - "go.sum" + - "vendor/**" jobs: license-lint: From ac84f2ce2e6ae76ff1b759e7f0c8a81c2a9fca6a Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Wed, 18 Jan 2023 23:55:12 +0000 Subject: [PATCH 10/11] add readme Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- third_party/k8s.io/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 third_party/k8s.io/README.md diff --git a/third_party/k8s.io/README.md b/third_party/k8s.io/README.md new file mode 100644 index 00000000000..d1ddd4c7802 --- /dev/null +++ b/third_party/k8s.io/README.md @@ -0,0 +1,7 @@ +# k8s.io/kubernetes + +Forked from k8s.io/kubernetes@124fd62ad253f8362d78d5710d8d363aa1b376df + +This is a light fork to use scripts from kubernetes/kubernetes for gatekeeper's use cases. + +The original code can be found at https://github.com/kubernetes/kubernetes/tree/124fd62ad253f8362d78d5710d8d363aa1b376df . From 16f7cb57731fc70f9903d32c788a0a90b752b3d3 Mon Sep 17 00:00:00 2001 From: Alex Pana <8968914+acpana@users.noreply.github.com> Date: Thu, 19 Jan 2023 20:58:07 +0000 Subject: [PATCH 11/11] remove dependencies Signed-off-by: Alex Pana <8968914+acpana@users.noreply.github.com> --- .../k8s.io/kubernetes/hack/lib/etcd.sh | 183 ---- .../k8s.io/kubernetes/hack/lib/golang.sh | 919 ------------------ .../k8s.io/kubernetes/hack/lib/init.sh | 212 ---- .../k8s.io/kubernetes/hack/lib/logging.sh | 171 ---- .../k8s.io/kubernetes/hack/lib/util.sh | 890 ----------------- .../k8s.io/kubernetes/hack/lib/version.sh | 185 ---- .../k8s.io/kubernetes/hack/verify-licenses.sh | 20 +- 7 files changed, 4 insertions(+), 2576 deletions(-) delete mode 100755 third_party/k8s.io/kubernetes/hack/lib/etcd.sh delete mode 100755 third_party/k8s.io/kubernetes/hack/lib/golang.sh delete mode 100755 third_party/k8s.io/kubernetes/hack/lib/init.sh delete mode 100644 third_party/k8s.io/kubernetes/hack/lib/logging.sh delete mode 100755 third_party/k8s.io/kubernetes/hack/lib/util.sh delete mode 100644 third_party/k8s.io/kubernetes/hack/lib/version.sh diff --git a/third_party/k8s.io/kubernetes/hack/lib/etcd.sh b/third_party/k8s.io/kubernetes/hack/lib/etcd.sh deleted file mode 100755 index 44ceb46af05..00000000000 --- a/third_party/k8s.io/kubernetes/hack/lib/etcd.sh +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# A set of helpers for starting/running etcd for tests - -ETCD_VERSION=${ETCD_VERSION:-3.5.5} -ETCD_HOST=${ETCD_HOST:-127.0.0.1} -ETCD_PORT=${ETCD_PORT:-2379} -# This is intentionally not called ETCD_LOG_LEVEL: -# etcd checks that and compains when it is set in addition -# to the command line argument, even when both have the same value. -ETCD_LOGLEVEL=${ETCD_LOGLEVEL:-warn} -export KUBE_INTEGRATION_ETCD_URL="http://${ETCD_HOST}:${ETCD_PORT}" - -kube::etcd::validate() { - # validate if in path - command -v etcd >/dev/null || { - kube::log::usage "etcd must be in your PATH" - kube::log::info "You can use 'hack/install-etcd.sh' to install a copy in third_party/." - exit 1 - } - - # validate etcd port is free - local port_check_command - if command -v ss &> /dev/null && ss -Version | grep 'iproute2' &> /dev/null; then - port_check_command="ss" - elif command -v netstat &>/dev/null; then - port_check_command="netstat" - else - kube::log::usage "unable to identify if etcd is bound to port ${ETCD_PORT}. unable to find ss or netstat utilities." - exit 1 - fi - if ${port_check_command} -nat | grep "LISTEN" | grep "[\.:]${ETCD_PORT:?}" >/dev/null 2>&1; then - kube::log::usage "unable to start etcd as port ${ETCD_PORT} is in use. please stop the process listening on this port and retry." - kube::log::usage "$(netstat -nat | grep "[\.:]${ETCD_PORT:?} .*LISTEN")" - exit 1 - fi - - # need set the env of "ETCD_UNSUPPORTED_ARCH" on unstable arch. - arch=$(uname -m) - if [[ $arch =~ aarch* ]]; then - export ETCD_UNSUPPORTED_ARCH=arm64 - elif [[ $arch =~ arm* ]]; then - export ETCD_UNSUPPORTED_ARCH=arm - fi - # validate installed version is at least equal to minimum - version=$(etcd --version | grep Version | head -n 1 | cut -d " " -f 3) - if [[ $(kube::etcd::version "${ETCD_VERSION}") -gt $(kube::etcd::version "${version}") ]]; then - export PATH=${KUBE_ROOT}/third_party/etcd:${PATH} - hash etcd - echo "${PATH}" - version=$(etcd --version | grep Version | head -n 1 | cut -d " " -f 3) - if [[ $(kube::etcd::version "${ETCD_VERSION}") -gt $(kube::etcd::version "${version}") ]]; then - kube::log::usage "etcd version ${ETCD_VERSION} or greater required." - kube::log::info "You can use 'hack/install-etcd.sh' to install a copy in third_party/." - exit 1 - fi - fi -} - -kube::etcd::version() { - printf '%s\n' "${@}" | awk -F . '{ printf("%d%03d%03d\n", $1, $2, $3) }' -} - -kube::etcd::start() { - # validate before running - kube::etcd::validate - - # Start etcd - ETCD_DIR=${ETCD_DIR:-$(mktemp -d 2>/dev/null || mktemp -d -t test-etcd.XXXXXX)} - if [[ -d "${ARTIFACTS:-}" ]]; then - ETCD_LOGFILE="${ARTIFACTS}/etcd.$(uname -n).$(id -un).log.DEBUG.$(date +%Y%m%d-%H%M%S).$$" - else - ETCD_LOGFILE=${ETCD_LOGFILE:-"/dev/null"} - fi - kube::log::info "etcd --advertise-client-urls ${KUBE_INTEGRATION_ETCD_URL} --data-dir ${ETCD_DIR} --listen-client-urls http://${ETCD_HOST}:${ETCD_PORT} --log-level=${ETCD_LOGLEVEL} 2> \"${ETCD_LOGFILE}\" >/dev/null" - etcd --advertise-client-urls "${KUBE_INTEGRATION_ETCD_URL}" --data-dir "${ETCD_DIR}" --listen-client-urls "${KUBE_INTEGRATION_ETCD_URL}" --log-level="${ETCD_LOGLEVEL}" 2> "${ETCD_LOGFILE}" >/dev/null & - ETCD_PID=$! - - echo "Waiting for etcd to come up." - kube::util::wait_for_url "${KUBE_INTEGRATION_ETCD_URL}/health" "etcd: " 0.25 80 - curl -fs -X POST "${KUBE_INTEGRATION_ETCD_URL}/v3/kv/put" -d '{"key": "X3Rlc3Q=", "value": ""}' -} - -kube::etcd::start_scraping() { - if [[ -d "${ARTIFACTS:-}" ]]; then - ETCD_SCRAPE_DIR="${ARTIFACTS}/etcd-scrapes" - else - ETCD_SCRAPE_DIR=$(mktemp -d -t test.XXXXXX)/etcd-scrapes - fi - kube::log::info "Periodically scraping etcd to ${ETCD_SCRAPE_DIR} ." - mkdir -p "${ETCD_SCRAPE_DIR}" - ( - while sleep 30; do - kube::etcd::scrape - done - ) & - ETCD_SCRAPE_PID=$! -} - -kube::etcd::scrape() { - curl -s -S "${KUBE_INTEGRATION_ETCD_URL}/metrics" > "${ETCD_SCRAPE_DIR}/next" && mv "${ETCD_SCRAPE_DIR}/next" "${ETCD_SCRAPE_DIR}/$(date +%s).scrape" -} - - -kube::etcd::stop() { - if [[ -n "${ETCD_SCRAPE_PID:-}" ]] && [[ -n "${ETCD_SCRAPE_DIR:-}" ]] ; then - kill "${ETCD_SCRAPE_PID}" &>/dev/null || : - wait "${ETCD_SCRAPE_PID}" &>/dev/null || : - kube::etcd::scrape || : - ( - # shellcheck disable=SC2015 - cd "${ETCD_SCRAPE_DIR}"/.. && \ - tar czf etcd-scrapes.tgz etcd-scrapes && \ - rm -rf etcd-scrapes || : - ) - fi - if [[ -n "${ETCD_PID-}" ]]; then - kill "${ETCD_PID}" &>/dev/null || : - wait "${ETCD_PID}" &>/dev/null || : - fi -} - -kube::etcd::clean_etcd_dir() { - if [[ -n "${ETCD_DIR-}" ]]; then - rm -rf "${ETCD_DIR}" - fi -} - -kube::etcd::cleanup() { - kube::etcd::stop - kube::etcd::clean_etcd_dir -} - -kube::etcd::install() { - ( - local os - local arch - - os=$(kube::util::host_os) - arch=$(kube::util::host_arch) - - cd "${KUBE_ROOT}/third_party" || return 1 - if [[ $(readlink etcd) == etcd-v${ETCD_VERSION}-${os}-* ]]; then - kube::log::info "etcd v${ETCD_VERSION} already installed. To use:" - kube::log::info "export PATH=\"$(pwd)/etcd:\${PATH}\"" - return #already installed - fi - - if [[ ${os} == "darwin" ]]; then - download_file="etcd-v${ETCD_VERSION}-${os}-${arch}.zip" - url="https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/${download_file}" - kube::util::download_file "${url}" "${download_file}" - unzip -o "${download_file}" - ln -fns "etcd-v${ETCD_VERSION}-${os}-${arch}" etcd - rm "${download_file}" - elif [[ ${os} == "linux" ]]; then - url="https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-${os}-${arch}.tar.gz" - download_file="etcd-v${ETCD_VERSION}-${os}-${arch}.tar.gz" - kube::util::download_file "${url}" "${download_file}" - tar xzf "${download_file}" - ln -fns "etcd-v${ETCD_VERSION}-${os}-${arch}" etcd - rm "${download_file}" - else - kube::log::info "${os} is NOT supported." - fi - kube::log::info "etcd v${ETCD_VERSION} installed. To use:" - kube::log::info "export PATH=\"$(pwd)/etcd:\${PATH}\"" - ) -} diff --git a/third_party/k8s.io/kubernetes/hack/lib/golang.sh b/third_party/k8s.io/kubernetes/hack/lib/golang.sh deleted file mode 100755 index fb97ee76783..00000000000 --- a/third_party/k8s.io/kubernetes/hack/lib/golang.sh +++ /dev/null @@ -1,919 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# shellcheck disable=SC2034 # Variables sourced in other scripts. - -# The golang package that we are building. -readonly KUBE_GO_PACKAGE=k8s.io/kubernetes -readonly KUBE_GOPATH="${KUBE_OUTPUT}/go" - -# The server platform we are building on. -readonly KUBE_SUPPORTED_SERVER_PLATFORMS=( - linux/amd64 - linux/arm - linux/arm64 - linux/s390x - linux/ppc64le -) - -# The node platforms we build for -readonly KUBE_SUPPORTED_NODE_PLATFORMS=( - linux/amd64 - linux/arm - linux/arm64 - linux/s390x - linux/ppc64le - windows/amd64 -) - -# If we update this we should also update the set of platforms whose standard -# library is precompiled for in build/build-image/cross/Dockerfile -readonly KUBE_SUPPORTED_CLIENT_PLATFORMS=( - linux/amd64 - linux/386 - linux/arm - linux/arm64 - linux/s390x - linux/ppc64le - darwin/amd64 - darwin/arm64 - windows/amd64 - windows/386 - windows/arm64 -) - -# Which platforms we should compile test targets for. -# Not all client platforms need these tests -readonly KUBE_SUPPORTED_TEST_PLATFORMS=( - linux/amd64 - linux/arm - linux/arm64 - linux/s390x - linux/ppc64le - darwin/amd64 - darwin/arm64 - windows/amd64 - windows/arm64 -) - -# The set of server targets that we are only building for Linux -kube::golang::server_targets() { - local targets=( - cmd/kube-proxy - cmd/kube-apiserver - cmd/kube-controller-manager - cmd/kubelet - cmd/kubeadm - cmd/kube-scheduler - vendor/k8s.io/component-base/logs/kube-log-runner - vendor/k8s.io/kube-aggregator - vendor/k8s.io/apiextensions-apiserver - cluster/gce/gci/mounter - ) - echo "${targets[@]}" -} - -IFS=" " read -ra KUBE_SERVER_TARGETS <<< "$(kube::golang::server_targets)" -readonly KUBE_SERVER_TARGETS -readonly KUBE_SERVER_BINARIES=("${KUBE_SERVER_TARGETS[@]##*/}") - -# The set of server targets we build docker images for -kube::golang::server_image_targets() { - # NOTE: this contains cmd targets for kube::build::get_docker_wrapped_binaries - local targets=( - cmd/kube-apiserver - cmd/kube-controller-manager - cmd/kube-scheduler - cmd/kube-proxy - ) - echo "${targets[@]}" -} - -IFS=" " read -ra KUBE_SERVER_IMAGE_TARGETS <<< "$(kube::golang::server_image_targets)" -readonly KUBE_SERVER_IMAGE_TARGETS -readonly KUBE_SERVER_IMAGE_BINARIES=("${KUBE_SERVER_IMAGE_TARGETS[@]##*/}") - -# The set of conformance targets we build docker image for -kube::golang::conformance_image_targets() { - # NOTE: this contains cmd targets for kube::release::build_conformance_image - local targets=( - ginkgo - test/e2e/e2e.test - test/conformance/image/go-runner - cmd/kubectl - ) - echo "${targets[@]}" -} - -IFS=" " read -ra KUBE_CONFORMANCE_IMAGE_TARGETS <<< "$(kube::golang::conformance_image_targets)" -readonly KUBE_CONFORMANCE_IMAGE_TARGETS - -# The set of server targets that we are only building for Kubernetes nodes -kube::golang::node_targets() { - local targets=( - cmd/kube-proxy - cmd/kubeadm - cmd/kubelet - vendor/k8s.io/component-base/logs/kube-log-runner - ) - echo "${targets[@]}" -} - -IFS=" " read -ra KUBE_NODE_TARGETS <<< "$(kube::golang::node_targets)" -readonly KUBE_NODE_TARGETS -readonly KUBE_NODE_BINARIES=("${KUBE_NODE_TARGETS[@]##*/}") -readonly KUBE_NODE_BINARIES_WIN=("${KUBE_NODE_BINARIES[@]/%/.exe}") - -# ------------ -# NOTE: All functions that return lists should use newlines. -# bash functions can't return arrays, and spaces are tricky, so newline -# separators are the preferred pattern. -# To transform a string of newline-separated items to an array, use kube::util::read-array: -# kube::util::read-array FOO < <(kube::golang::dups a b c a) -# -# ALWAYS remember to quote your subshells. Not doing so will break in -# bash 4.3, and potentially cause other issues. -# ------------ - -# Returns a sorted newline-separated list containing only duplicated items. -kube::golang::dups() { - # We use printf to insert newlines, which are required by sort. - printf "%s\n" "$@" | sort | uniq -d -} - -# Returns a sorted newline-separated list with duplicated items removed. -kube::golang::dedup() { - # We use printf to insert newlines, which are required by sort. - printf "%s\n" "$@" | sort -u -} - -# Depends on values of user-facing KUBE_BUILD_PLATFORMS, KUBE_FASTBUILD, -# and KUBE_BUILDER_OS. -# Configures KUBE_SERVER_PLATFORMS, KUBE_NODE_PLATFOMRS, -# KUBE_TEST_PLATFORMS, and KUBE_CLIENT_PLATFORMS, then sets them -# to readonly. -# The configured vars will only contain platforms allowed by the -# KUBE_SUPPORTED* vars at the top of this file. -declare -a KUBE_SERVER_PLATFORMS -declare -a KUBE_CLIENT_PLATFORMS -declare -a KUBE_NODE_PLATFORMS -declare -a KUBE_TEST_PLATFORMS -kube::golang::setup_platforms() { - if [[ -n "${KUBE_BUILD_PLATFORMS:-}" ]]; then - # KUBE_BUILD_PLATFORMS needs to be read into an array before the next - # step, or quoting treats it all as one element. - local -a platforms - IFS=" " read -ra platforms <<< "${KUBE_BUILD_PLATFORMS}" - - # Deduplicate to ensure the intersection trick with kube::golang::dups - # is not defeated by duplicates in user input. - kube::util::read-array platforms < <(kube::golang::dedup "${platforms[@]}") - - # Use kube::golang::dups to restrict the builds to the platforms in - # KUBE_SUPPORTED_*_PLATFORMS. Items should only appear at most once in each - # set, so if they appear twice after the merge they are in the intersection. - kube::util::read-array KUBE_SERVER_PLATFORMS < <(kube::golang::dups \ - "${platforms[@]}" \ - "${KUBE_SUPPORTED_SERVER_PLATFORMS[@]}" \ - ) - readonly KUBE_SERVER_PLATFORMS - - kube::util::read-array KUBE_NODE_PLATFORMS < <(kube::golang::dups \ - "${platforms[@]}" \ - "${KUBE_SUPPORTED_NODE_PLATFORMS[@]}" \ - ) - readonly KUBE_NODE_PLATFORMS - - kube::util::read-array KUBE_TEST_PLATFORMS < <(kube::golang::dups \ - "${platforms[@]}" \ - "${KUBE_SUPPORTED_TEST_PLATFORMS[@]}" \ - ) - readonly KUBE_TEST_PLATFORMS - - kube::util::read-array KUBE_CLIENT_PLATFORMS < <(kube::golang::dups \ - "${platforms[@]}" \ - "${KUBE_SUPPORTED_CLIENT_PLATFORMS[@]}" \ - ) - readonly KUBE_CLIENT_PLATFORMS - - elif [[ "${KUBE_FASTBUILD:-}" == "true" ]]; then - host_arch=$(kube::util::host_arch) - if [[ "${host_arch}" != "amd64" && "${host_arch}" != "arm64" && "${host_arch}" != "ppc64le" && "${host_arch}" != "s390x" ]]; then - # on any platform other than amd64, arm64, ppc64le and s390x, we just default to amd64 - host_arch="amd64" - fi - KUBE_SERVER_PLATFORMS=("linux/${host_arch}") - readonly KUBE_SERVER_PLATFORMS - KUBE_NODE_PLATFORMS=("linux/${host_arch}") - readonly KUBE_NODE_PLATFORMS - if [[ "${KUBE_BUILDER_OS:-}" == "darwin"* ]]; then - KUBE_TEST_PLATFORMS=( - "darwin/${host_arch}" - "linux/${host_arch}" - ) - readonly KUBE_TEST_PLATFORMS - KUBE_CLIENT_PLATFORMS=( - "darwin/${host_arch}" - "linux/${host_arch}" - ) - readonly KUBE_CLIENT_PLATFORMS - else - KUBE_TEST_PLATFORMS=("linux/${host_arch}") - readonly KUBE_TEST_PLATFORMS - KUBE_CLIENT_PLATFORMS=("linux/${host_arch}") - readonly KUBE_CLIENT_PLATFORMS - fi - else - KUBE_SERVER_PLATFORMS=("${KUBE_SUPPORTED_SERVER_PLATFORMS[@]}") - readonly KUBE_SERVER_PLATFORMS - - KUBE_NODE_PLATFORMS=("${KUBE_SUPPORTED_NODE_PLATFORMS[@]}") - readonly KUBE_NODE_PLATFORMS - - KUBE_CLIENT_PLATFORMS=("${KUBE_SUPPORTED_CLIENT_PLATFORMS[@]}") - readonly KUBE_CLIENT_PLATFORMS - - KUBE_TEST_PLATFORMS=("${KUBE_SUPPORTED_TEST_PLATFORMS[@]}") - readonly KUBE_TEST_PLATFORMS - fi -} - -kube::golang::setup_platforms - -# The set of client targets that we are building for all platforms -readonly KUBE_CLIENT_TARGETS=( - cmd/kubectl - cmd/kubectl-convert -) -readonly KUBE_CLIENT_BINARIES=("${KUBE_CLIENT_TARGETS[@]##*/}") -readonly KUBE_CLIENT_BINARIES_WIN=("${KUBE_CLIENT_BINARIES[@]/%/.exe}") - -# The set of test targets that we are building for all platforms -kube::golang::test_targets() { - local targets=( - cmd/gendocs - cmd/genkubedocs - cmd/genman - cmd/genyaml - cmd/genswaggertypedocs - ginkgo - test/e2e/e2e.test - test/conformance/image/go-runner - ) - echo "${targets[@]}" -} -IFS=" " read -ra KUBE_TEST_TARGETS <<< "$(kube::golang::test_targets)" -readonly KUBE_TEST_TARGETS -readonly KUBE_TEST_BINARIES=("${KUBE_TEST_TARGETS[@]##*/}") -readonly KUBE_TEST_BINARIES_WIN=("${KUBE_TEST_BINARIES[@]/%/.exe}") -readonly KUBE_TEST_PORTABLE=( - test/e2e/testing-manifests - test/kubemark - hack/e2e-internal - hack/get-build.sh - hack/ginkgo-e2e.sh - hack/lib -) - -# Test targets which run on the Kubernetes clusters directly, so we only -# need to target server platforms. -# These binaries will be distributed in the kubernetes-test tarball. -kube::golang::server_test_targets() { - local targets=( - cmd/kubemark - ginkgo - ) - - if [[ "${OSTYPE:-}" == "linux"* ]]; then - targets+=( test/e2e_node/e2e_node.test ) - fi - - echo "${targets[@]}" -} - -IFS=" " read -ra KUBE_TEST_SERVER_TARGETS <<< "$(kube::golang::server_test_targets)" -readonly KUBE_TEST_SERVER_TARGETS -readonly KUBE_TEST_SERVER_BINARIES=("${KUBE_TEST_SERVER_TARGETS[@]##*/}") -readonly KUBE_TEST_SERVER_PLATFORMS=("${KUBE_SERVER_PLATFORMS[@]:+"${KUBE_SERVER_PLATFORMS[@]}"}") - -# Gigabytes necessary for parallel platform builds. -# As of March 2021 (go 1.16/amd64), the RSS usage is 2GiB by using cached -# memory of 15GiB. -# This variable can be overwritten at your own risk. -# It's defaulting to 20G to provide some headroom. -readonly KUBE_PARALLEL_BUILD_MEMORY=${KUBE_PARALLEL_BUILD_MEMORY:-20} - -readonly KUBE_ALL_TARGETS=( - "${KUBE_SERVER_TARGETS[@]}" - "${KUBE_CLIENT_TARGETS[@]}" - "${KUBE_TEST_TARGETS[@]}" - "${KUBE_TEST_SERVER_TARGETS[@]}" -) -readonly KUBE_ALL_BINARIES=("${KUBE_ALL_TARGETS[@]##*/}") - -readonly KUBE_STATIC_LIBRARIES=( - kube-apiserver - kube-controller-manager - kube-scheduler - kube-proxy - kube-log-runner - kubeadm - kubectl - kubemark -) - -# Fully-qualified package names that we want to instrument for coverage information. -readonly KUBE_COVERAGE_INSTRUMENTED_PACKAGES=( - k8s.io/kubernetes/cmd/kube-apiserver - k8s.io/kubernetes/cmd/kube-controller-manager - k8s.io/kubernetes/cmd/kube-scheduler - k8s.io/kubernetes/cmd/kube-proxy - k8s.io/kubernetes/cmd/kubelet -) - -# KUBE_CGO_OVERRIDES is a space-separated list of binaries which should be built -# with CGO enabled, assuming CGO is supported on the target platform. -# This overrides any entry in KUBE_STATIC_LIBRARIES. -IFS=" " read -ra KUBE_CGO_OVERRIDES_LIST <<< "${KUBE_CGO_OVERRIDES:-}" -readonly KUBE_CGO_OVERRIDES_LIST -# KUBE_STATIC_OVERRIDES is a space-separated list of binaries which should be -# built with CGO disabled. This is in addition to the list in -# KUBE_STATIC_LIBRARIES. -IFS=" " read -ra KUBE_STATIC_OVERRIDES_LIST <<< "${KUBE_STATIC_OVERRIDES:-}" -readonly KUBE_STATIC_OVERRIDES_LIST - -kube::golang::is_statically_linked_library() { - local e - # Explicitly enable cgo when building kubectl for darwin from darwin. - [[ "$(go env GOHOSTOS)" == "darwin" && "$(go env GOOS)" == "darwin" && - "$1" == *"/kubectl" ]] && return 1 - if [[ -n "${KUBE_CGO_OVERRIDES_LIST:+x}" ]]; then - for e in "${KUBE_CGO_OVERRIDES_LIST[@]}"; do [[ "${1}" == *"/${e}" ]] && return 1; done; - fi - for e in "${KUBE_STATIC_LIBRARIES[@]}"; do [[ "${1}" == *"/${e}" ]] && return 0; done; - if [[ -n "${KUBE_STATIC_OVERRIDES_LIST:+x}" ]]; then - for e in "${KUBE_STATIC_OVERRIDES_LIST[@]}"; do [[ "${1}" == *"/${e}" ]] && return 0; done; - fi - return 1; -} - -# kube::binaries_from_targets take a list of build targets and return the -# full go package to be built -kube::golang::binaries_from_targets() { - local target - for target; do - if [ "${target}" = "ginkgo" ] || - [ "${target}" = "github.com/onsi/ginkgo/ginkgo" ] || - [ "${target}" = "vendor/github.com/onsi/ginkgo/ginkgo" ]; then - # Aliases that build the ginkgo CLI for hack/ginkgo-e2e.sh. - # "ginkgo" is the one that is documented in the Makefile. The others - # are for backwards compatibility. - echo "github.com/onsi/ginkgo/v2/ginkgo" - elif [[ "${target}" =~ ^([[:alnum:]]+".")+[[:alnum:]]+"/" ]]; then - # If the target starts with what looks like a domain name, assume it has a - # fully-qualified package name rather than one that needs the Kubernetes - # package prepended. - echo "${target}" - elif [[ "${target}" =~ ^vendor/ ]]; then - # Strip vendor/ prefix, since we're building in gomodule mode. - echo "${target#"vendor/"}" - else - echo "${KUBE_GO_PACKAGE}/${target}" - fi - done -} - -# Asks golang what it thinks the host platform is. The go tool chain does some -# slightly different things when the target platform matches the host platform. -kube::golang::host_platform() { - echo "$(go env GOHOSTOS)/$(go env GOHOSTARCH)" -} - -# Takes the platform name ($1) and sets the appropriate golang env variables -# for that platform. -kube::golang::set_platform_envs() { - [[ -n ${1-} ]] || { - kube::log::error_exit "!!! Internal error. No platform set in kube::golang::set_platform_envs" - } - - export GOOS=${platform%/*} - export GOARCH=${platform##*/} - - # Do not set CC when building natively on a platform, only if cross-compiling - if [[ $(kube::golang::host_platform) != "$platform" ]]; then - # Dynamic CGO linking for other server architectures than host architecture goes here - # If you want to include support for more server platforms than these, add arch-specific gcc names here - case "${platform}" in - "linux/amd64") - export CGO_ENABLED=1 - export CC=${KUBE_LINUX_AMD64_CC:-x86_64-linux-gnu-gcc} - ;; - "linux/arm") - export CGO_ENABLED=1 - export CC=${KUBE_LINUX_ARM_CC:-arm-linux-gnueabihf-gcc} - ;; - "linux/arm64") - export CGO_ENABLED=1 - export CC=${KUBE_LINUX_ARM64_CC:-aarch64-linux-gnu-gcc} - ;; - "linux/ppc64le") - export CGO_ENABLED=1 - export CC=${KUBE_LINUX_PPC64LE_CC:-powerpc64le-linux-gnu-gcc} - ;; - "linux/s390x") - export CGO_ENABLED=1 - export CC=${KUBE_LINUX_S390X_CC:-s390x-linux-gnu-gcc} - ;; - esac - fi - - # if CC is defined for platform then always enable it - ccenv=$(echo "$platform" | awk -F/ '{print "KUBE_" toupper($1) "_" toupper($2) "_CC"}') - if [ -n "${!ccenv-}" ]; then - export CGO_ENABLED=1 - export CC="${!ccenv}" - fi -} - -# Create the GOPATH tree under $KUBE_OUTPUT -kube::golang::create_gopath_tree() { - local go_pkg_dir="${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}" - local go_pkg_basedir - go_pkg_basedir=$(dirname "${go_pkg_dir}") - - mkdir -p "${go_pkg_basedir}" - - # TODO: This symlink should be relative. - if [[ ! -e "${go_pkg_dir}" || "$(readlink "${go_pkg_dir}")" != "${KUBE_ROOT}" ]]; then - ln -snf "${KUBE_ROOT}" "${go_pkg_dir}" - fi -} - -# Ensure the go tool exists and is a viable version. -kube::golang::verify_go_version() { - if [[ -z "$(command -v go)" ]]; then - kube::log::usage_from_stdin <`, but it's subtle when it comes - # to cross-compiles and whether the is a file or a directory, - # and EVERY caller has to get it *just* right. - # * We could leave GOPATH alone and let `go install` write binaries - # wherever the user's GOPATH says (or doesn't say). - # - # Instead we set it to a phony local path and process the results ourselves. - # In particular, GOPATH[0]/bin will be used for `go install`, with - # cross-compiles adding an extra directory under that. - # - # Eventually, when we no longer rely on run-in-gopath.sh we may be able to - # simplify this some. - kube::golang::create_gopath_tree - export GOPATH="${KUBE_GOPATH}" - - export GOCACHE="${KUBE_GOPATH}/cache" - - # Make sure our own Go binaries are in PATH. - export PATH="${KUBE_GOPATH}/bin:${PATH}" - - # Change directories so that we are within the GOPATH. Some tools get really - # upset if this is not true. We use a whole fake GOPATH here to collect the - # resultant binaries. - local subdir - subdir=$(kube::realpath . | sed "s|${KUBE_ROOT}||") - cd "${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}/${subdir}" || return 1 - - # Set GOROOT so binaries that parse code can work properly. - GOROOT=$(go env GOROOT) - export GOROOT - - # Unset GOBIN in case it already exists in the current session. - # Cross-compiles will not work with it set. - unset GOBIN - - # This seems to matter to some tools - export GO15VENDOREXPERIMENT=1 -} - -# This will take binaries from $GOPATH/bin and copy them to the appropriate -# place in ${KUBE_OUTPUT_BINDIR} -# -# Ideally this wouldn't be necessary and we could just set GOBIN to -# KUBE_OUTPUT_BINDIR but that won't work in the face of cross compilation. 'go -# install' will place binaries that match the host platform directly in $GOBIN -# while placing cross compiled binaries into `platform_arch` subdirs. This -# complicates pretty much everything else we do around packaging and such. -kube::golang::place_bins() { - local host_platform - host_platform=$(kube::golang::host_platform) - - V=2 kube::log::status "Placing binaries" - - local platform - for platform in "${KUBE_CLIENT_PLATFORMS[@]}"; do - # The substitution on platform_src below will replace all slashes with - # underscores. It'll transform darwin/amd64 -> darwin_amd64. - local platform_src="/${platform//\//_}" - if [[ "${platform}" == "${host_platform}" ]]; then - platform_src="" - rm -f "${THIS_PLATFORM_BIN}" - ln -s "${KUBE_OUTPUT_BINPATH}/${platform}" "${THIS_PLATFORM_BIN}" - fi - - local full_binpath_src="${KUBE_GOPATH}/bin${platform_src}" - if [[ -d "${full_binpath_src}" ]]; then - mkdir -p "${KUBE_OUTPUT_BINPATH}/${platform}" - find "${full_binpath_src}" -maxdepth 1 -type f -exec \ - rsync -pc {} "${KUBE_OUTPUT_BINPATH}/${platform}" \; - fi - done -} - -# Try and replicate the native binary placement of go install without -# calling go install. -kube::golang::outfile_for_binary() { - local binary=$1 - local platform=$2 - local output_path="${KUBE_GOPATH}/bin" - local bin - bin=$(basename "${binary}") - if [[ "${platform}" != "${host_platform}" ]]; then - output_path="${output_path}/${platform//\//_}" - fi - if [[ ${GOOS} == "windows" ]]; then - bin="${bin}.exe" - fi - echo "${output_path}/${bin}" -} - -# Argument: the name of a Kubernetes package. -# Returns 0 if the binary can be built with coverage, 1 otherwise. -# NB: this ignores whether coverage is globally enabled or not. -kube::golang::is_instrumented_package() { - if kube::util::array_contains "$1" "${KUBE_COVERAGE_INSTRUMENTED_PACKAGES[@]}"; then - return 0 - fi - # Some cases, like `make kubectl`, pass $1 as "./cmd/kubectl" rather than - # "k8s.io/kubernetes/kubectl". Try to normalize and handle that. We don't - # do this always because it is a bit slow. - pkg=$(go list -find "$1") - if kube::util::array_contains "${pkg}" "${KUBE_COVERAGE_INSTRUMENTED_PACKAGES[@]}"; then - return 0 - fi - return 1 -} - -# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler) -# Echos the path to a dummy test used for coverage information. -kube::golang::path_for_coverage_dummy_test() { - local package="$1" - local path="${KUBE_GOPATH}/src/${package}" - local name - name=$(basename "${package}") - echo "${path}/zz_generated_${name}_test.go" -} - -# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler). -# Creates a dummy unit test on disk in the source directory for the given package. -# This unit test will invoke the package's standard entry point when run. -kube::golang::create_coverage_dummy_test() { - local package="$1" - local name - name="$(basename "${package}")" - cat < "$(kube::golang::path_for_coverage_dummy_test "${package}")" -package main -import ( - "testing" - "k8s.io/kubernetes/pkg/util/coverage" -) - -func TestMain(m *testing.M) { - // Get coverage running - coverage.InitCoverage("${name}") - - // Go! - main() - - // Make sure we actually write the profiling information to disk, if we make it here. - // On long-running services, or anything that calls os.Exit(), this is insufficient, - // so we also flush periodically with a default period of five seconds (configurable by - // the KUBE_COVERAGE_FLUSH_INTERVAL environment variable). - coverage.FlushCoverage() -} -EOF -} - -# Argument: the name of a Kubernetes package (e.g. k8s.io/kubernetes/cmd/kube-scheduler). -# Deletes a test generated by kube::golang::create_coverage_dummy_test. -# It is not an error to call this for a nonexistent test. -kube::golang::delete_coverage_dummy_test() { - local package="$1" - rm -f "$(kube::golang::path_for_coverage_dummy_test "${package}")" -} - -# Arguments: a list of kubernetes packages to build. -# Expected variables: ${build_args} should be set to an array of Go build arguments. -# In addition, ${package} and ${platform} should have been set earlier, and if -# ${KUBE_BUILD_WITH_COVERAGE} is set, coverage instrumentation will be enabled. -# -# Invokes Go to actually build some packages. If coverage is disabled, simply invokes -# go install. If coverage is enabled, builds covered binaries using go test, temporarily -# producing the required unit test files and then cleaning up after itself. -# Non-covered binaries are then built using go install as usual. -# -# See comments in kube::golang::setup_env regarding where built binaries go. -kube::golang::build_some_binaries() { - if [[ -n "${KUBE_BUILD_WITH_COVERAGE:-}" ]]; then - local -a uncovered=() - for package in "$@"; do - if kube::golang::is_instrumented_package "${package}"; then - V=2 kube::log::info "Building ${package} with coverage..." - - kube::golang::create_coverage_dummy_test "${package}" - kube::util::trap_add "kube::golang::delete_coverage_dummy_test \"${package}\"" EXIT - - go test -c -o "$(kube::golang::outfile_for_binary "${package}" "${platform}")" \ - -covermode count \ - -coverpkg k8s.io/...,k8s.io/kubernetes/vendor/k8s.io/... \ - "${build_args[@]}" \ - -tags coverage \ - "${package}" - else - uncovered+=("${package}") - fi - done - if [[ "${#uncovered[@]}" != 0 ]]; then - V=2 kube::log::info "Building ${uncovered[*]} without coverage..." - GO111MODULE=on GOPROXY=off go install "${build_args[@]}" "${uncovered[@]}" - else - V=2 kube::log::info "Nothing to build without coverage." - fi - else - V=2 kube::log::info "Coverage is disabled." - GO111MODULE=on GOPROXY=off go install "${build_args[@]}" "$@" - fi -} - -# Args: -# $1: platform (e.g. darwin/amd64) -kube::golang::build_binaries_for_platform() { - # This is for sanity. Without it, user umasks can leak through. - umask 0022 - - local platform=$1 - - local -a statics=() - local -a nonstatics=() - local -a tests=() - - for binary in "${binaries[@]}"; do - if [[ "${binary}" =~ ".test"$ ]]; then - tests+=("${binary}") - kube::log::info " ${binary} (test)" - elif kube::golang::is_statically_linked_library "${binary}"; then - statics+=("${binary}") - kube::log::info " ${binary} (static)" - else - nonstatics+=("${binary}") - kube::log::info " ${binary} (non-static)" - fi - done - - V=2 kube::log::info "Env for ${platform}: GOOS=${GOOS-} GOARCH=${GOARCH-} GOROOT=${GOROOT-} CGO_ENABLED=${CGO_ENABLED-} CC=${CC-}" - V=3 kube::log::info "Building binaries with GCFLAGS=${gogcflags} ASMFLAGS=${goasmflags} LDFLAGS=${goldflags}" - - local -a build_args - if [[ "${#statics[@]}" != 0 ]]; then - build_args=( - -installsuffix=static - ${goflags:+"${goflags[@]}"} - -gcflags="${gogcflags}" - -asmflags="${goasmflags}" - -ldflags="${goldflags}" - -tags="${gotags:-}" - ) - CGO_ENABLED=0 kube::golang::build_some_binaries "${statics[@]}" - fi - - if [[ "${#nonstatics[@]}" != 0 ]]; then - build_args=( - ${goflags:+"${goflags[@]}"} - -gcflags="${gogcflags}" - -asmflags="${goasmflags}" - -ldflags="${goldflags}" - -tags="${gotags:-}" - ) - kube::golang::build_some_binaries "${nonstatics[@]}" - fi - - for test in "${tests[@]:+${tests[@]}}"; do - local outfile testpkg - outfile=$(kube::golang::outfile_for_binary "${test}" "${platform}") - testpkg=$(dirname "${test}") - - mkdir -p "$(dirname "${outfile}")" - go test -c \ - ${goflags:+"${goflags[@]}"} \ - -gcflags="${gogcflags}" \ - -asmflags="${goasmflags}" \ - -ldflags="${goldflags}" \ - -tags="${gotags:-}" \ - -o "${outfile}" \ - "${testpkg}" - done -} - -# Return approximate physical memory available in gigabytes. -kube::golang::get_physmem() { - local mem - - # Linux kernel version >=3.14, in kb - if mem=$(grep MemAvailable /proc/meminfo | awk '{ print $2 }'); then - echo $(( mem / 1048576 )) - return - fi - - # Linux, in kb - if mem=$(grep MemTotal /proc/meminfo | awk '{ print $2 }'); then - echo $(( mem / 1048576 )) - return - fi - - # OS X, in bytes. Note that get_physmem, as used, should only ever - # run in a Linux container (because it's only used in the multiple - # platform case, which is a Dockerized build), but this is provided - # for completeness. - if mem=$(sysctl -n hw.memsize 2>/dev/null); then - echo $(( mem / 1073741824 )) - return - fi - - # If we can't infer it, just give up and assume a low memory system - echo 1 -} - -# Build binaries targets specified -# -# Input: -# $@ - targets and go flags. If no targets are set then all binaries targets -# are built. -# KUBE_BUILD_PLATFORMS - Incoming variable of targets to build for. If unset -# then just the host architecture is built. -kube::golang::build_binaries() { - # Create a sub-shell so that we don't pollute the outer environment - ( - # Check for `go` binary and set ${GOPATH}. - kube::golang::setup_env - V=2 kube::log::info "Go version: $(GOFLAGS='' go version)" - - local host_platform - host_platform=$(kube::golang::host_platform) - - # These are "local" but are visible to and relied on by functions this - # function calls. They are effectively part of the calling API to - # build_binaries_for_platform. - local goflags goldflags goasmflags gogcflags gotags - - # This is $(pwd) because we use run-in-gopath to build. Once that is - # excised, this can become ${KUBE_ROOT}. - local trimroot # two lines to appease shellcheck SC2155 - trimroot=$(pwd) - - goasmflags="all=-trimpath=${trimroot}" - - gogcflags="all=-trimpath=${trimroot} ${GOGCFLAGS:-}" - if [[ "${DBG:-}" == 1 ]]; then - # Debugging - disable optimizations and inlining and trimPath - gogcflags="${GOGCFLAGS:-} all=-N -l" - goasmflags="" - fi - - goldflags="all=$(kube::version::ldflags) ${GOLDFLAGS:-}" - if [[ "${DBG:-}" != 1 ]]; then - # Not debugging - disable symbols and DWARF. - goldflags="${goldflags} -s -w" - fi - - # Extract tags if any specified in GOFLAGS - gotags="selinux,notest,$(echo "${GOFLAGS:-}" | sed -ne 's|.*-tags=\([^-]*\).*|\1|p')" - - local -a targets=() - local arg - - for arg; do - if [[ "${arg}" == -* ]]; then - # Assume arguments starting with a dash are flags to pass to go. - goflags+=("${arg}") - else - targets+=("${arg}") - fi - done - - if [[ ${#targets[@]} -eq 0 ]]; then - targets=("${KUBE_ALL_TARGETS[@]}") - fi - - local -a platforms - IFS=" " read -ra platforms <<< "${KUBE_BUILD_PLATFORMS:-}" - if [[ ${#platforms[@]} -eq 0 ]]; then - platforms=("${host_platform}") - fi - - local -a binaries - while IFS="" read -r binary; do binaries+=("$binary"); done < <(kube::golang::binaries_from_targets "${targets[@]}") - - local parallel=false - if [[ ${#platforms[@]} -gt 1 ]]; then - local gigs - gigs=$(kube::golang::get_physmem) - - if [[ ${gigs} -ge ${KUBE_PARALLEL_BUILD_MEMORY} ]]; then - kube::log::status "Multiple platforms requested and available ${gigs}G >= threshold ${KUBE_PARALLEL_BUILD_MEMORY}G, building platforms in parallel" - parallel=true - else - kube::log::status "Multiple platforms requested, but available ${gigs}G < threshold ${KUBE_PARALLEL_BUILD_MEMORY}G, building platforms in serial" - parallel=false - fi - fi - - if [[ "${parallel}" == "true" ]]; then - kube::log::status "Building go targets for {${platforms[*]}} in parallel (output will appear in a burst when complete):" "${targets[@]}" - local platform - for platform in "${platforms[@]}"; do ( - kube::golang::set_platform_envs "${platform}" - kube::log::status "${platform}: build started" - kube::golang::build_binaries_for_platform "${platform}" - kube::log::status "${platform}: build finished" - ) &> "/tmp//${platform//\//_}.build" & - done - - local fails=0 - for job in $(jobs -p); do - wait "${job}" || (( fails+=1 )) - done - - for platform in "${platforms[@]}"; do - cat "/tmp//${platform//\//_}.build" - done - - exit "${fails}" - else - for platform in "${platforms[@]}"; do - kube::log::status "Building go targets for ${platform}" - ( - kube::golang::set_platform_envs "${platform}" - kube::golang::build_binaries_for_platform "${platform}" - ) - done - fi - ) -} diff --git a/third_party/k8s.io/kubernetes/hack/lib/init.sh b/third_party/k8s.io/kubernetes/hack/lib/init.sh deleted file mode 100755 index 51e3d1db195..00000000000 --- a/third_party/k8s.io/kubernetes/hack/lib/init.sh +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -o errexit -set -o nounset -set -o pipefail - -# Unset CDPATH so that path interpolation can work correctly -# https://github.com/kubernetes/kubernetes/issues/52255 -unset CDPATH - -# Until all GOPATH references are removed from all build scripts as well, -# explicitly disable module mode to avoid picking up user-set GO111MODULE preferences. -# As individual scripts (like hack/update-vendor.sh) make use of go modules, -# they can explicitly set GO111MODULE=on -export GO111MODULE=off - -# The root of the build/dist directory -KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" - -KUBE_OUTPUT_SUBPATH="${KUBE_OUTPUT_SUBPATH:-_output/local}" -KUBE_OUTPUT="${KUBE_ROOT}/${KUBE_OUTPUT_SUBPATH}" -KUBE_OUTPUT_BINPATH="${KUBE_OUTPUT}/bin" - -# This controls rsync compression. Set to a value > 0 to enable rsync -# compression for build container -KUBE_RSYNC_COMPRESS="${KUBE_RSYNC_COMPRESS:-0}" - -# Set no_proxy for localhost if behind a proxy, otherwise, -# the connections to localhost in scripts will time out -export no_proxy="127.0.0.1,localhost${no_proxy:+,${no_proxy}}" - -# This is a symlink to binaries for "this platform", e.g. build tools. -export THIS_PLATFORM_BIN="${KUBE_ROOT}/_output/bin" - -source "${KUBE_ROOT}/hack/lib/util.sh" -source "${KUBE_ROOT}/hack/lib/logging.sh" - -kube::log::install_errexit -kube::util::ensure-bash-version - -source "${KUBE_ROOT}/hack/lib/version.sh" -source "${KUBE_ROOT}/hack/lib/golang.sh" -source "${KUBE_ROOT}/hack/lib/etcd.sh" - -KUBE_OUTPUT_HOSTBIN="${KUBE_OUTPUT_BINPATH}/$(kube::util::host_platform)" -export KUBE_OUTPUT_HOSTBIN - -# list of all available group versions. This should be used when generated code -# or when starting an API server that you want to have everything. -# most preferred version for a group should appear first -KUBE_AVAILABLE_GROUP_VERSIONS="${KUBE_AVAILABLE_GROUP_VERSIONS:-\ -v1 \ -admissionregistration.k8s.io/v1 \ -admissionregistration.k8s.io/v1alpha1 \ -admissionregistration.k8s.io/v1beta1 \ -admission.k8s.io/v1 \ -admission.k8s.io/v1beta1 \ -apps/v1 \ -apps/v1beta1 \ -apps/v1beta2 \ -authentication.k8s.io/v1 \ -authentication.k8s.io/v1alpha1 \ -authentication.k8s.io/v1beta1 \ -authorization.k8s.io/v1 \ -authorization.k8s.io/v1beta1 \ -autoscaling/v1 \ -autoscaling/v2 \ -autoscaling/v2beta1 \ -autoscaling/v2beta2 \ -batch/v1 \ -batch/v1beta1 \ -certificates.k8s.io/v1 \ -certificates.k8s.io/v1beta1 \ -coordination.k8s.io/v1beta1 \ -coordination.k8s.io/v1 \ -discovery.k8s.io/v1 \ -discovery.k8s.io/v1beta1 \ -extensions/v1beta1 \ -events.k8s.io/v1 \ -events.k8s.io/v1beta1 \ -imagepolicy.k8s.io/v1alpha1 \ -networking.k8s.io/v1 \ -networking.k8s.io/v1alpha1 \ -networking.k8s.io/v1beta1 \ -node.k8s.io/v1 \ -node.k8s.io/v1alpha1 \ -node.k8s.io/v1beta1 \ -policy/v1 \ -policy/v1beta1 \ -rbac.authorization.k8s.io/v1 \ -rbac.authorization.k8s.io/v1beta1 \ -rbac.authorization.k8s.io/v1alpha1 \ -scheduling.k8s.io/v1alpha1 \ -scheduling.k8s.io/v1beta1 \ -scheduling.k8s.io/v1 \ -storage.k8s.io/v1beta1 \ -storage.k8s.io/v1 \ -storage.k8s.io/v1alpha1 \ -flowcontrol.apiserver.k8s.io/v1alpha1 \ -flowcontrol.apiserver.k8s.io/v1beta1 \ -flowcontrol.apiserver.k8s.io/v1beta2 \ -flowcontrol.apiserver.k8s.io/v1beta3 \ -internal.apiserver.k8s.io/v1alpha1 \ -}" - -# not all group versions are exposed by the server. This list contains those -# which are not available so we don't generate clients or swagger for them -KUBE_NONSERVER_GROUP_VERSIONS=" - abac.authorization.kubernetes.io/v0 \ - abac.authorization.kubernetes.io/v1beta1 \ - apidiscovery.k8s.io/v2beta1 \ - componentconfig/v1alpha1 \ - imagepolicy.k8s.io/v1alpha1\ - admission.k8s.io/v1\ - admission.k8s.io/v1beta1\ -" -export KUBE_NONSERVER_GROUP_VERSIONS - -# This emulates "readlink -f" which is not available on MacOS X. -# Test: -# T=/tmp/$$.$RANDOM -# mkdir $T -# touch $T/file -# mkdir $T/dir -# ln -s $T/file $T/linkfile -# ln -s $T/dir $T/linkdir -# function testone() { -# X=$(readlink -f $1 2>&1) -# Y=$(kube::readlinkdashf $1 2>&1) -# if [ "$X" != "$Y" ]; then -# echo readlinkdashf $1: expected "$X", got "$Y" -# fi -# } -# testone / -# testone /tmp -# testone $T -# testone $T/file -# testone $T/dir -# testone $T/linkfile -# testone $T/linkdir -# testone $T/nonexistant -# testone $T/linkdir/file -# testone $T/linkdir/dir -# testone $T/linkdir/linkfile -# testone $T/linkdir/linkdir -function kube::readlinkdashf { - # run in a subshell for simpler 'cd' - ( - if [[ -d "${1}" ]]; then # This also catch symlinks to dirs. - cd "${1}" - pwd -P - else - cd "$(dirname "${1}")" - local f - f=$(basename "${1}") - if [[ -L "${f}" ]]; then - readlink "${f}" - else - echo "$(pwd -P)/${f}" - fi - fi - ) -} - -# This emulates "realpath" which is not available on MacOS X -# Test: -# T=/tmp/$$.$RANDOM -# mkdir $T -# touch $T/file -# mkdir $T/dir -# ln -s $T/file $T/linkfile -# ln -s $T/dir $T/linkdir -# function testone() { -# X=$(realpath $1 2>&1) -# Y=$(kube::realpath $1 2>&1) -# if [ "$X" != "$Y" ]; then -# echo realpath $1: expected "$X", got "$Y" -# fi -# } -# testone / -# testone /tmp -# testone $T -# testone $T/file -# testone $T/dir -# testone $T/linkfile -# testone $T/linkdir -# testone $T/nonexistant -# testone $T/linkdir/file -# testone $T/linkdir/dir -# testone $T/linkdir/linkfile -# testone $T/linkdir/linkdir -kube::realpath() { - if [[ ! -e "${1}" ]]; then - echo "${1}: No such file or directory" >&2 - return 1 - fi - kube::readlinkdashf "${1}" -} diff --git a/third_party/k8s.io/kubernetes/hack/lib/logging.sh b/third_party/k8s.io/kubernetes/hack/lib/logging.sh deleted file mode 100644 index 8a175b3af4e..00000000000 --- a/third_party/k8s.io/kubernetes/hack/lib/logging.sh +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Controls verbosity of the script output and logging. -KUBE_VERBOSE="${KUBE_VERBOSE:-2}" - -# Handler for when we exit automatically on an error. -# Borrowed from https://gist.github.com/ahendrix/7030300 -kube::log::errexit() { - local err="${PIPESTATUS[*]}" - - # If the shell we are in doesn't have errexit set (common in subshells) then - # don't dump stacks. - set +o | grep -qe "-o errexit" || return - - set +o xtrace - local code="${1:-1}" - # Print out the stack trace described by $function_stack - if [ ${#FUNCNAME[@]} -gt 2 ] - then - kube::log::error "Call tree:" - for ((i=1;i<${#FUNCNAME[@]}-1;i++)) - do - kube::log::error " ${i}: ${BASH_SOURCE[${i}+1]}:${BASH_LINENO[${i}]} ${FUNCNAME[${i}]}(...)" - done - fi - kube::log::error_exit "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${BASH_COMMAND}' exited with status ${err}" "${1:-1}" 1 -} - -kube::log::install_errexit() { - # trap ERR to provide an error handler whenever a command exits nonzero this - # is a more verbose version of set -o errexit - trap 'kube::log::errexit' ERR - - # setting errtrace allows our ERR trap handler to be propagated to functions, - # expansions and subshells - set -o errtrace -} - -# Print out the stack trace -# -# Args: -# $1 The number of stack frames to skip when printing. -kube::log::stack() { - local stack_skip=${1:-0} - stack_skip=$((stack_skip + 1)) - if [[ ${#FUNCNAME[@]} -gt ${stack_skip} ]]; then - echo "Call stack:" >&2 - local i - for ((i=1 ; i <= ${#FUNCNAME[@]} - stack_skip ; i++)) - do - local frame_no=$((i - 1 + stack_skip)) - local source_file=${BASH_SOURCE[${frame_no}]} - local source_lineno=${BASH_LINENO[$((frame_no - 1))]} - local funcname=${FUNCNAME[${frame_no}]} - echo " ${i}: ${source_file}:${source_lineno} ${funcname}(...)" >&2 - done - fi -} - -# Log an error and exit. -# Args: -# $1 Message to log with the error -# $2 The error code to return -# $3 The number of stack frames to skip when printing. -kube::log::error_exit() { - local message="${1:-}" - local code="${2:-1}" - local stack_skip="${3:-0}" - stack_skip=$((stack_skip + 1)) - - if [[ ${KUBE_VERBOSE} -ge 4 ]]; then - local source_file=${BASH_SOURCE[${stack_skip}]} - local source_line=${BASH_LINENO[$((stack_skip - 1))]} - echo "!!! Error in ${source_file}:${source_line}" >&2 - [[ -z ${1-} ]] || { - echo " ${1}" >&2 - } - - kube::log::stack ${stack_skip} - - echo "Exiting with status ${code}" >&2 - fi - - exit "${code}" -} - -# Log an error but keep going. Don't dump the stack or exit. -kube::log::error() { - timestamp=$(date +"[%m%d %H:%M:%S]") - echo "!!! ${timestamp} ${1-}" >&2 - shift - for message; do - echo " ${message}" >&2 - done -} - -# Print an usage message to stderr. The arguments are printed directly. -kube::log::usage() { - echo >&2 - local message - for message; do - echo "${message}" >&2 - done - echo >&2 -} - -kube::log::usage_from_stdin() { - local messages=() - while read -r line; do - messages+=("${line}") - done - - kube::log::usage "${messages[@]}" -} - -# Print out some info that isn't a top level status line -kube::log::info() { - local V="${V:-0}" - if [[ ${KUBE_VERBOSE} < ${V} ]]; then - return - fi - - for message; do - echo "${message}" - done -} - -# Just like kube::log::info, but no \n, so you can make a progress bar -kube::log::progress() { - for message; do - echo -e -n "${message}" - done -} - -kube::log::info_from_stdin() { - local messages=() - while read -r line; do - messages+=("${line}") - done - - kube::log::info "${messages[@]}" -} - -# Print a status line. Formatted to show up in a stream of output. -kube::log::status() { - local V="${V:-0}" - if [[ ${KUBE_VERBOSE} < ${V} ]]; then - return - fi - - timestamp=$(date +"[%m%d %H:%M:%S]") - echo "+++ ${timestamp} ${1}" - shift - for message; do - echo " ${message}" - done -} diff --git a/third_party/k8s.io/kubernetes/hack/lib/util.sh b/third_party/k8s.io/kubernetes/hack/lib/util.sh deleted file mode 100755 index ad284906209..00000000000 --- a/third_party/k8s.io/kubernetes/hack/lib/util.sh +++ /dev/null @@ -1,890 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -function kube::util::sourced_variable { - # Call this function to tell shellcheck that a variable is supposed to - # be used from other calling context. This helps quiet an "unused - # variable" warning from shellcheck and also document your code. - true -} - -kube::util::sortable_date() { - date "+%Y%m%d-%H%M%S" -} - -# arguments: target, item1, item2, item3, ... -# returns 0 if target is in the given items, 1 otherwise. -kube::util::array_contains() { - local search="$1" - local element - shift - for element; do - if [[ "${element}" == "${search}" ]]; then - return 0 - fi - done - return 1 -} - -kube::util::wait_for_url() { - local url=$1 - local prefix=${2:-} - local wait=${3:-1} - local times=${4:-30} - local maxtime=${5:-1} - - command -v curl >/dev/null || { - kube::log::usage "curl must be installed" - exit 1 - } - - local i - for i in $(seq 1 "${times}"); do - local out - if out=$(curl --max-time "${maxtime}" -gkfs "${@:6}" "${url}" 2>/dev/null); then - kube::log::status "On try ${i}, ${prefix}: ${out}" - return 0 - fi - sleep "${wait}" - done - kube::log::error "Timed out waiting for ${prefix} to answer at ${url}; tried ${times} waiting ${wait} between each" - return 1 -} - -kube::util::wait_for_url_with_bearer_token() { - local url=$1 - local token=$2 - local prefix=${3:-} - local wait=${4:-1} - local times=${5:-30} - local maxtime=${6:-1} - - kube::util::wait_for_url "${url}" "${prefix}" "${wait}" "${times}" "${maxtime}" -H "Authorization: Bearer ${token}" -} - -# Example: kube::util::wait_for_success 120 5 "kubectl get nodes|grep localhost" -# arguments: wait time, sleep time, shell command -# returns 0 if the shell command get output, 1 otherwise. -kube::util::wait_for_success(){ - local wait_time="$1" - local sleep_time="$2" - local cmd="$3" - while [ "$wait_time" -gt 0 ]; do - if eval "$cmd"; then - return 0 - else - sleep "$sleep_time" - wait_time=$((wait_time-sleep_time)) - fi - done - return 1 -} - -# Example: kube::util::trap_add 'echo "in trap DEBUG"' DEBUG -# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal -kube::util::trap_add() { - local trap_add_cmd - trap_add_cmd=$1 - shift - - for trap_add_name in "$@"; do - local existing_cmd - local new_cmd - - # Grab the currently defined trap commands for this trap - existing_cmd=$(trap -p "${trap_add_name}" | awk -F"'" '{print $2}') - - if [[ -z "${existing_cmd}" ]]; then - new_cmd="${trap_add_cmd}" - else - new_cmd="${trap_add_cmd};${existing_cmd}" - fi - - # Assign the test. Disable the shellcheck warning telling that trap - # commands should be single quoted to avoid evaluating them at this - # point instead evaluating them at run time. The logic of adding new - # commands to a single trap requires them to be evaluated right away. - # shellcheck disable=SC2064 - trap "${new_cmd}" "${trap_add_name}" - done -} - -# Opposite of kube::util::ensure-temp-dir() -kube::util::cleanup-temp-dir() { - rm -rf "${KUBE_TEMP}" -} - -# Create a temp dir that'll be deleted at the end of this bash session. -# -# Vars set: -# KUBE_TEMP -kube::util::ensure-temp-dir() { - if [[ -z ${KUBE_TEMP-} ]]; then - KUBE_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t kubernetes.XXXXXX) - kube::util::trap_add kube::util::cleanup-temp-dir EXIT - fi -} - -kube::util::host_os() { - local host_os - case "$(uname -s)" in - Darwin) - host_os=darwin - ;; - Linux) - host_os=linux - ;; - *) - kube::log::error "Unsupported host OS. Must be Linux or Mac OS X." - exit 1 - ;; - esac - echo "${host_os}" -} - -kube::util::host_arch() { - local host_arch - case "$(uname -m)" in - x86_64*) - host_arch=amd64 - ;; - i?86_64*) - host_arch=amd64 - ;; - amd64*) - host_arch=amd64 - ;; - aarch64*) - host_arch=arm64 - ;; - arm64*) - host_arch=arm64 - ;; - arm*) - host_arch=arm - ;; - i?86*) - host_arch=x86 - ;; - s390x*) - host_arch=s390x - ;; - ppc64le*) - host_arch=ppc64le - ;; - *) - kube::log::error "Unsupported host arch. Must be x86_64, 386, arm, arm64, s390x or ppc64le." - exit 1 - ;; - esac - echo "${host_arch}" -} - -# This figures out the host platform without relying on golang. We need this as -# we don't want a golang install to be a prerequisite to building yet we need -# this info to figure out where the final binaries are placed. -kube::util::host_platform() { - echo "$(kube::util::host_os)/$(kube::util::host_arch)" -} - -# looks for $1 in well-known output locations for the platform ($2) -# $KUBE_ROOT must be set -kube::util::find-binary-for-platform() { - local -r lookfor="$1" - local -r platform="$2" - local locations=( - "${KUBE_ROOT}/_output/bin/${lookfor}" - "${KUBE_ROOT}/_output/dockerized/bin/${platform}/${lookfor}" - "${KUBE_ROOT}/_output/local/bin/${platform}/${lookfor}" - "${KUBE_ROOT}/platforms/${platform}/${lookfor}" - ) - - # if we're looking for the host platform, add local non-platform-qualified search paths - if [[ "${platform}" = "$(kube::util::host_platform)" ]]; then - locations+=( - "${KUBE_ROOT}/_output/local/go/bin/${lookfor}" - "${KUBE_ROOT}/_output/dockerized/go/bin/${lookfor}" - ); - fi - - # looks for $1 in the $PATH - if which "${lookfor}" >/dev/null; then - local -r local_bin="$(which "${lookfor}")" - locations+=( "${local_bin}" ); - fi - - # List most recently-updated location. - local -r bin=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 ) - - if [[ -z "${bin}" ]]; then - kube::log::error "Failed to find binary ${lookfor} for platform ${platform}" - return 1 - fi - - echo -n "${bin}" -} - -# looks for $1 in well-known output locations for the host platform -# $KUBE_ROOT must be set -kube::util::find-binary() { - kube::util::find-binary-for-platform "$1" "$(kube::util::host_platform)" -} - -# Run all known doc generators (today gendocs and genman for kubectl) -# $1 is the directory to put those generated documents -kube::util::gen-docs() { - local dest="$1" - - # Find binary - gendocs=$(kube::util::find-binary "gendocs") - genkubedocs=$(kube::util::find-binary "genkubedocs") - genman=$(kube::util::find-binary "genman") - genyaml=$(kube::util::find-binary "genyaml") - - mkdir -p "${dest}/docs/user-guide/kubectl/" - "${gendocs}" "${dest}/docs/user-guide/kubectl/" - mkdir -p "${dest}/docs/admin/" - "${genkubedocs}" "${dest}/docs/admin/" "kube-apiserver" - "${genkubedocs}" "${dest}/docs/admin/" "kube-controller-manager" - "${genkubedocs}" "${dest}/docs/admin/" "kube-proxy" - "${genkubedocs}" "${dest}/docs/admin/" "kube-scheduler" - "${genkubedocs}" "${dest}/docs/admin/" "kubelet" - "${genkubedocs}" "${dest}/docs/admin/" "kubeadm" - - mkdir -p "${dest}/docs/man/man1/" - "${genman}" "${dest}/docs/man/man1/" "kube-apiserver" - "${genman}" "${dest}/docs/man/man1/" "kube-controller-manager" - "${genman}" "${dest}/docs/man/man1/" "kube-proxy" - "${genman}" "${dest}/docs/man/man1/" "kube-scheduler" - "${genman}" "${dest}/docs/man/man1/" "kubelet" - "${genman}" "${dest}/docs/man/man1/" "kubectl" - "${genman}" "${dest}/docs/man/man1/" "kubeadm" - - mkdir -p "${dest}/docs/yaml/kubectl/" - "${genyaml}" "${dest}/docs/yaml/kubectl/" - - # create the list of generated files - pushd "${dest}" > /dev/null || return 1 - touch docs/.generated_docs - find . -type f | cut -sd / -f 2- | LC_ALL=C sort > docs/.generated_docs - popd > /dev/null || return 1 -} - -# Removes previously generated docs-- we don't want to check them in. $KUBE_ROOT -# must be set. -kube::util::remove-gen-docs() { - if [ -e "${KUBE_ROOT}/docs/.generated_docs" ]; then - # remove all of the old docs; we don't want to check them in. - while read -r file; do - rm "${KUBE_ROOT}/${file}" 2>/dev/null || true - done <"${KUBE_ROOT}/docs/.generated_docs" - # The docs/.generated_docs file lists itself, so we don't need to explicitly - # delete it. - fi -} - -# Takes a group/version and returns the path to its location on disk, sans -# "pkg". E.g.: -# * default behavior: extensions/v1beta1 -> apis/extensions/v1beta1 -# * default behavior for only a group: experimental -> apis/experimental -# * Special handling for empty group: v1 -> api/v1, unversioned -> api/unversioned -# * Special handling for groups suffixed with ".k8s.io": foo.k8s.io/v1 -> apis/foo/v1 -# * Very special handling for when both group and version are "": / -> api -# -# $KUBE_ROOT must be set. -kube::util::group-version-to-pkg-path() { - local group_version="$1" - - while IFS=$'\n' read -r api; do - if [[ "${api}" = "${group_version/.*k8s.io/}" ]]; then - echo "vendor/k8s.io/api/${group_version/.*k8s.io/}" - return - fi - done < <(cd "${KUBE_ROOT}/staging/src/k8s.io/api" && find . -name types.go -exec dirname {} \; | sed "s|\./||g" | sort) - - # "v1" is the API GroupVersion - if [[ "${group_version}" == "v1" ]]; then - echo "vendor/k8s.io/api/core/v1" - return - fi - - # Special cases first. - # TODO(lavalamp): Simplify this by moving pkg/api/v1 and splitting pkg/api, - # moving the results to pkg/apis/api. - case "${group_version}" in - # both group and version are "", this occurs when we generate deep copies for internal objects of the legacy v1 API. - __internal) - echo "pkg/apis/core" - ;; - meta/v1) - echo "vendor/k8s.io/apimachinery/pkg/apis/meta/v1" - ;; - meta/v1beta1) - echo "vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1" - ;; - internal.apiserver.k8s.io/v1alpha1) - echo "vendor/k8s.io/api/apiserverinternal/v1alpha1" - ;; - *.k8s.io) - echo "pkg/apis/${group_version%.*k8s.io}" - ;; - *.k8s.io/*) - echo "pkg/apis/${group_version/.*k8s.io/}" - ;; - *) - echo "pkg/apis/${group_version%__internal}" - ;; - esac -} - -# Takes a group/version and returns the swagger-spec file name. -# default behavior: extensions/v1beta1 -> extensions_v1beta1 -# special case for v1: v1 -> v1 -kube::util::gv-to-swagger-name() { - local group_version="$1" - case "${group_version}" in - v1) - echo "v1" - ;; - *) - echo "${group_version%/*}_${group_version#*/}" - ;; - esac -} - -# Returns the name of the upstream remote repository name for the local git -# repo, e.g. "upstream" or "origin". -kube::util::git_upstream_remote_name() { - git remote -v | grep fetch |\ - grep -E 'github.com[/:]kubernetes/kubernetes|k8s.io/kubernetes' |\ - head -n 1 | awk '{print $1}' -} - -# Exits script if working directory is dirty. If it's run interactively in the terminal -# the user can commit changes in a second terminal. This script will wait. -kube::util::ensure_clean_working_dir() { - while ! git diff HEAD --exit-code &>/dev/null; do - echo -e "\nUnexpected dirty working directory:\n" - if tty -s; then - git status -s - else - git diff -a # be more verbose in log files without tty - exit 1 - fi | sed 's/^/ /' - echo -e "\nCommit your changes in another terminal and then continue here by pressing enter." - read -r - done 1>&2 -} - -# Find the base commit using: -# $PULL_BASE_SHA if set (from Prow) -# current ref from the remote upstream branch -kube::util::base_ref() { - local -r git_branch=$1 - - if [[ -n ${PULL_BASE_SHA:-} ]]; then - echo "${PULL_BASE_SHA}" - return - fi - - full_branch="$(kube::util::git_upstream_remote_name)/${git_branch}" - - # make sure the branch is valid, otherwise the check will pass erroneously. - if ! git describe "${full_branch}" >/dev/null; then - # abort! - exit 1 - fi - - echo "${full_branch}" -} - -# Checks whether there are any files matching pattern $2 changed between the -# current branch and upstream branch named by $1. -# Returns 1 (false) if there are no changes -# 0 (true) if there are changes detected. -kube::util::has_changes() { - local -r git_branch=$1 - local -r pattern=$2 - local -r not_pattern=${3:-totallyimpossiblepattern} - - local base_ref - base_ref=$(kube::util::base_ref "${git_branch}") - echo "Checking for '${pattern}' changes against '${base_ref}'" - - # notice this uses ... to find the first shared ancestor - if git diff --name-only "${base_ref}...HEAD" | grep -v -E "${not_pattern}" | grep "${pattern}" > /dev/null; then - return 0 - fi - # also check for pending changes - if git status --porcelain | grep -v -E "${not_pattern}" | grep "${pattern}" > /dev/null; then - echo "Detected '${pattern}' uncommitted changes." - return 0 - fi - echo "No '${pattern}' changes detected." - return 1 -} - -kube::util::download_file() { - local -r url=$1 - local -r destination_file=$2 - - rm "${destination_file}" 2&> /dev/null || true - - for i in $(seq 5) - do - if ! curl -fsSL --retry 3 --keepalive-time 2 "${url}" -o "${destination_file}"; then - echo "Downloading ${url} failed. $((5-i)) retries left." - sleep 1 - else - echo "Downloading ${url} succeed" - return 0 - fi - done - return 1 -} - -# Test whether openssl is installed. -# Sets: -# OPENSSL_BIN: The path to the openssl binary to use -function kube::util::test_openssl_installed { - if ! openssl version >& /dev/null; then - echo "Failed to run openssl. Please ensure openssl is installed" - exit 1 - fi - - OPENSSL_BIN=$(command -v openssl) -} - -# Query the API server for client certificate authentication capabilities -function kube::util::test_client_certificate_authentication_enabled { - local output - kube::util::test_openssl_installed - - output=$(echo \ - | "${OPENSSL_BIN}" s_client -connect "127.0.0.1:${SECURE_API_PORT}" 2> /dev/null \ - | grep -A3 'Acceptable client certificate CA names') - - if [[ "${output}" != *"/CN=127.0.0.1"* ]] && [[ "${output}" != *"CN = 127.0.0.1"* ]]; then - echo "API server not configured for client certificate authentication" - echo "Output of from acceptable client certificate check: ${output}" - exit 1 - fi -} - -# creates a client CA, args are sudo, dest-dir, ca-id, purpose -# purpose is dropped in after "key encipherment", you usually want -# '"client auth"' -# '"server auth"' -# '"client auth","server auth"' -function kube::util::create_signing_certkey { - local sudo=$1 - local dest_dir=$2 - local id=$3 - local purpose=$4 - # Create client ca - ${sudo} /usr/bin/env bash -e < "${dest_dir}/${id}-ca-config.json" -EOF -} - -# signs a client certificate: args are sudo, dest-dir, CA, filename (roughly), username, groups... -function kube::util::create_client_certkey { - local sudo=$1 - local dest_dir=$2 - local ca=$3 - local id=$4 - local cn=${5:-$4} - local groups="" - local SEP="" - shift 5 - while [ -n "${1:-}" ]; do - groups+="${SEP}{\"O\":\"$1\"}" - SEP="," - shift 1 - done - ${sudo} /usr/bin/env bash -e < /dev/null -apiVersion: v1 -kind: Config -clusters: - - cluster: - certificate-authority: ${ca_file} - server: https://${api_host}:${api_port}/ - name: local-up-cluster -users: - - user: - token: ${token} - client-certificate: ${dest_dir}/client-${client_id}.crt - client-key: ${dest_dir}/client-${client_id}.key - name: local-up-cluster -contexts: - - context: - cluster: local-up-cluster - user: local-up-cluster - name: local-up-cluster -current-context: local-up-cluster -EOF - - # flatten the kubeconfig files to make them self contained - username=$(whoami) - ${sudo} /usr/bin/env bash -e < "/tmp/${client_id}.kubeconfig" - mv -f "/tmp/${client_id}.kubeconfig" "${dest_dir}/${client_id}.kubeconfig" - chown ${username} "${dest_dir}/${client_id}.kubeconfig" -EOF -} - -# list_staging_repos outputs a sorted list of repos in staging/src/k8s.io -# each entry will just be the $repo portion of staging/src/k8s.io/$repo/... -# $KUBE_ROOT must be set. -function kube::util::list_staging_repos() { - ( - cd "${KUBE_ROOT}/staging/src/k8s.io" && \ - find . -mindepth 1 -maxdepth 1 -type d | cut -c 3- | sort - ) -} - - -# Determines if docker can be run, failures may simply require that the user be added to the docker group. -function kube::util::ensure_docker_daemon_connectivity { - DOCKER_OPTS=${DOCKER_OPTS:-""} - IFS=" " read -ra docker_opts <<< "${DOCKER_OPTS}" - if ! docker "${docker_opts[@]:+"${docker_opts[@]}"}" info > /dev/null 2>&1 ; then - cat <<'EOF' >&2 -Can't connect to 'docker' daemon. please fix and retry. - -Possible causes: - - Docker Daemon not started - - Linux: confirm via your init system - - macOS w/ Docker for Mac: Check the menu bar and start the Docker application - - DOCKER_HOST hasn't been set or is set incorrectly - - Linux: domain socket is used, DOCKER_* should be unset. In Bash run `unset ${!DOCKER_*}` - - macOS w/ Docker for Mac: domain socket is used, DOCKER_* should be unset. In Bash run `unset ${!DOCKER_*}` - - Other things to check: - - Linux: User isn't in 'docker' group. Add and relogin. - - Something like 'sudo usermod -a -G docker ${USER}' - - RHEL7 bug and workaround: https://bugzilla.redhat.com/show_bug.cgi?id=1119282#c8 -EOF - return 1 - fi -} - -# Wait for background jobs to finish. Return with -# an error status if any of the jobs failed. -kube::util::wait-for-jobs() { - local fail=0 - local job - for job in $(jobs -p); do - wait "${job}" || fail=$((fail + 1)) - done - return ${fail} -} - -# kube::util::join -# Concatenates the list elements with the delimiter passed as first parameter -# -# Ex: kube::util::join , a b c -# -> a,b,c -function kube::util::join { - local IFS="$1" - shift - echo "$*" -} - -# Downloads cfssl/cfssljson into $1 directory if they do not already exist in PATH -# -# Assumed vars: -# $1 (cfssl directory) (optional) -# -# Sets: -# CFSSL_BIN: The path of the installed cfssl binary -# CFSSLJSON_BIN: The path of the installed cfssljson binary -# -# shellcheck disable=SC2120 # optional parameters -function kube::util::ensure-cfssl { - if command -v cfssl &>/dev/null && command -v cfssljson &>/dev/null; then - CFSSL_BIN=$(command -v cfssl) - CFSSLJSON_BIN=$(command -v cfssljson) - return 0 - fi - - host_arch=$(kube::util::host_arch) - - if [[ "${host_arch}" != "amd64" ]]; then - echo "Cannot download cfssl on non-amd64 hosts and cfssl does not appear to be installed." - echo "Please install cfssl and cfssljson and verify they are in \$PATH." - echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go install github.com/cloudflare/cfssl/cmd/...@latest" - exit 1 - fi - - # Create a temp dir for cfssl if no directory was given - local cfssldir=${1:-} - if [[ -z "${cfssldir}" ]]; then - kube::util::ensure-temp-dir - cfssldir="${KUBE_TEMP}/cfssl" - fi - - mkdir -p "${cfssldir}" - pushd "${cfssldir}" > /dev/null || return 1 - - echo "Unable to successfully run 'cfssl' from ${PATH}; downloading instead..." - kernel=$(uname -s) - case "${kernel}" in - Linux) - curl --retry 10 -L -o cfssl https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_linux_amd64 - curl --retry 10 -L -o cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_linux_amd64 - ;; - Darwin) - curl --retry 10 -L -o cfssl https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_darwin_amd64 - curl --retry 10 -L -o cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_darwin_amd64 - ;; - *) - echo "Unknown, unsupported platform: ${kernel}." >&2 - echo "Supported platforms: Linux, Darwin." >&2 - exit 2 - esac - - chmod +x cfssl || true - chmod +x cfssljson || true - - CFSSL_BIN="${cfssldir}/cfssl" - CFSSLJSON_BIN="${cfssldir}/cfssljson" - if [[ ! -x ${CFSSL_BIN} || ! -x ${CFSSLJSON_BIN} ]]; then - echo "Failed to download 'cfssl'. Please install cfssl and cfssljson and verify they are in \$PATH." - echo "Hint: export PATH=\$PATH:\$GOPATH/bin; go install github.com/cloudflare/cfssl/cmd/...@latest" - exit 1 - fi - popd > /dev/null || return 1 -} - -# kube::util::ensure-docker-buildx -# Check if we have "docker buildx" commands available -# -function kube::util::ensure-docker-buildx { - if docker buildx --help >/dev/null 2>&1; then - return 0 - else - echo "ERROR: docker buildx not available. Docker 19.03 or higher is required with experimental features enabled" - exit 1 - fi -} - -# kube::util::ensure-bash-version -# Check if we are using a supported bash version -# -function kube::util::ensure-bash-version { - # shellcheck disable=SC2004 - if ((${BASH_VERSINFO[0]}<4)) || ( ((${BASH_VERSINFO[0]}==4)) && ((${BASH_VERSINFO[1]}<2)) ); then - echo "ERROR: This script requires a minimum bash version of 4.2, but got version of ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}" - if [ "$(uname)" = 'Darwin' ]; then - echo "On macOS with homebrew 'brew install bash' is sufficient." - fi - exit 1 - fi -} - -# kube::util::ensure-gnu-sed -# Determines which sed binary is gnu-sed on linux/darwin -# -# Sets: -# SED: The name of the gnu-sed binary -# -function kube::util::ensure-gnu-sed { - # NOTE: the echo below is a workaround to ensure sed is executed before the grep. - # see: https://github.com/kubernetes/kubernetes/issues/87251 - sed_help="$(LANG=C sed --help 2>&1 || true)" - if echo "${sed_help}" | grep -q "GNU\|BusyBox"; then - SED="sed" - elif command -v gsed &>/dev/null; then - SED="gsed" - else - kube::log::error "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2 - return 1 - fi - kube::util::sourced_variable "${SED}" -} - -# kube::util::ensure-gnu-date -# Determines which date binary is gnu-date on linux/darwin -# -# Sets: -# DATE: The name of the gnu-date binary -# -function kube::util::ensure-gnu-date { - # NOTE: the echo below is a workaround to ensure date is executed before the grep. - # see: https://github.com/kubernetes/kubernetes/issues/87251 - date_help="$(LANG=C date --help 2>&1 || true)" - if echo "${date_help}" | grep -q "GNU\|BusyBox"; then - DATE="date" - elif command -v gdate &>/dev/null; then - DATE="gdate" - else - kube::log::error "Failed to find GNU date as date or gdate. If you are on Mac: brew install coreutils." >&2 - return 1 - fi - kube::util::sourced_variable "${DATE}" -} - -# kube::util::check-file-in-alphabetical-order -# Check that the file is in alphabetical order -# -function kube::util::check-file-in-alphabetical-order { - local failure_file="$1" - if ! diff -u "${failure_file}" <(LC_ALL=C sort "${failure_file}"); then - { - echo - echo "${failure_file} is not in alphabetical order. Please sort it:" - echo - echo " LC_ALL=C sort -o ${failure_file} ${failure_file}" - echo - } >&2 - false - fi -} - -# kube::util::require-jq -# Checks whether jq is installed. -function kube::util::require-jq { - if ! command -v jq &>/dev/null; then - kube::log::error "jq not found. Please install." - return 1 - fi -} - -# outputs md5 hash of $1, works on macOS and Linux -function kube::util::md5() { - if which md5 >/dev/null 2>&1; then - md5 -q "$1" - else - md5sum "$1" | awk '{ print $1 }' - fi -} - -# kube::util::read-array -# Reads in stdin and adds it line by line to the array provided. This can be -# used instead of "mapfile -t", and is bash 3 compatible. If the named array -# exists and is an array, it will be used. Otherwise it will be unset and -# recreated. -# -# Assumed vars: -# $1 (name of array to create/modify) -# -# Example usage: -# kube::util::read-array files < <(ls -1) -# -# When in doubt: -# $ W=abc # a string -# $ X=(a b c) # an array -# $ declare -A Y # an associative array -# $ unset Z # not set at all -# $ declare -p W X Y Z -# declare -- W="abc" -# declare -a X=([0]="a" [1]="b" [2]="c") -# declare -A Y -# bash: line 26: declare: Z: not found -# $ kube::util::read-array W < <(echo -ne "1 1\n2 2\n3 3\n") -# bash: W is defined but isn't an array -# $ kube::util::read-array X < <(echo -ne "1 1\n2 2\n3 3\n") -# $ kube::util::read-array Y < <(echo -ne "1 1\n2 2\n3 3\n") -# bash: Y is defined but isn't an array -# $ kube::util::read-array Z < <(echo -ne "1 1\n2 2\n3 3\n") -# $ declare -p W X Y Z -# declare -- W="abc" -# declare -a X=([0]="1 1" [1]="2 2" [2]="3 3") -# declare -A Y -# declare -a Z=([0]="1 1" [1]="2 2" [2]="3 3") -function kube::util::read-array { - if [[ -z "$1" ]]; then - echo "usage: ${FUNCNAME[0]} " >&2 - return 1 - fi - if [[ -n $(declare -p "$1" 2>/dev/null) ]]; then - if ! declare -p "$1" 2>/dev/null | grep -q '^declare -a'; then - echo "${FUNCNAME[0]}: $1 is defined but isn't an array" >&2 - return 2 - fi - fi - # shellcheck disable=SC2034 # this variable _is_ used - local __read_array_i=0 - while IFS= read -r "$1[__read_array_i++]"; do :; done - if ! eval "[[ \${$1[--__read_array_i]} ]]"; then - unset "$1[__read_array_i]" # ensures last element isn't empty - fi -} - -# Some useful colors. -if [[ -z "${color_start-}" ]]; then - declare -r color_start="\033[" - declare -r color_red="${color_start}0;31m" - declare -r color_yellow="${color_start}0;33m" - declare -r color_green="${color_start}0;32m" - declare -r color_blue="${color_start}1;34m" - declare -r color_cyan="${color_start}1;36m" - declare -r color_norm="${color_start}0m" - - kube::util::sourced_variable "${color_start}" - kube::util::sourced_variable "${color_red}" - kube::util::sourced_variable "${color_yellow}" - kube::util::sourced_variable "${color_green}" - kube::util::sourced_variable "${color_blue}" - kube::util::sourced_variable "${color_cyan}" - kube::util::sourced_variable "${color_norm}" -fi - -# ex: ts=2 sw=2 et filetype=sh diff --git a/third_party/k8s.io/kubernetes/hack/lib/version.sh b/third_party/k8s.io/kubernetes/hack/lib/version.sh deleted file mode 100644 index f8dcc7b1ba8..00000000000 --- a/third_party/k8s.io/kubernetes/hack/lib/version.sh +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# ----------------------------------------------------------------------------- -# Version management helpers. These functions help to set, save and load the -# following variables: -# -# KUBE_GIT_COMMIT - The git commit id corresponding to this -# source code. -# KUBE_GIT_TREE_STATE - "clean" indicates no changes since the git commit id -# "dirty" indicates source code changes after the git commit id -# "archive" indicates the tree was produced by 'git archive' -# KUBE_GIT_VERSION - "vX.Y" used to indicate the last release version. -# KUBE_GIT_MAJOR - The major part of the version -# KUBE_GIT_MINOR - The minor component of the version - -# Grovels through git to set a set of env variables. -# -# If KUBE_GIT_VERSION_FILE, this function will load from that file instead of -# querying git. -kube::version::get_version_vars() { - if [[ -n ${KUBE_GIT_VERSION_FILE-} ]]; then - kube::version::load_version_vars "${KUBE_GIT_VERSION_FILE}" - return - fi - - # If the kubernetes source was exported through git archive, then - # we likely don't have a git tree, but these magic values may be filled in. - # shellcheck disable=SC2016,SC2050 - # Disabled as we're not expanding these at runtime, but rather expecting - # that another tool may have expanded these and rewritten the source (!) - if [[ '$Format:%%$' == "%" ]]; then - KUBE_GIT_COMMIT='$Format:%H$' - KUBE_GIT_TREE_STATE="archive" - # When a 'git archive' is exported, the '$Format:%D$' below will look - # something like 'HEAD -> release-1.8, tag: v1.8.3' where then 'tag: ' - # can be extracted from it. - if [[ '$Format:%D$' =~ tag:\ (v[^ ,]+) ]]; then - KUBE_GIT_VERSION="${BASH_REMATCH[1]}" - fi - fi - - local git=(git --work-tree "${KUBE_ROOT}") - - if [[ -n ${KUBE_GIT_COMMIT-} ]] || KUBE_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then - if [[ -z ${KUBE_GIT_TREE_STATE-} ]]; then - # Check if the tree is dirty. default to dirty - if git_status=$("${git[@]}" status --porcelain 2>/dev/null) && [[ -z ${git_status} ]]; then - KUBE_GIT_TREE_STATE="clean" - else - KUBE_GIT_TREE_STATE="dirty" - fi - fi - - # Use git describe to find the version based on tags. - if [[ -n ${KUBE_GIT_VERSION-} ]] || KUBE_GIT_VERSION=$("${git[@]}" describe --tags --match='v*' --abbrev=14 "${KUBE_GIT_COMMIT}^{commit}" 2>/dev/null); then - # This translates the "git describe" to an actual semver.org - # compatible semantic version that looks something like this: - # v1.1.0-alpha.0.6+84c76d1142ea4d - # - # TODO: We continue calling this "git version" because so many - # downstream consumers are expecting it there. - # - # These regexes are painful enough in sed... - # We don't want to do them in pure shell, so disable SC2001 - # shellcheck disable=SC2001 - DASHES_IN_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/[^-]//g") - if [[ "${DASHES_IN_VERSION}" == "---" ]] ; then - # shellcheck disable=SC2001 - # We have distance to subversion (v1.1.0-subversion-1-gCommitHash) - KUBE_GIT_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\+\2/") - elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then - # shellcheck disable=SC2001 - # We have distance to base tag (v1.1.0-1-gCommitHash) - KUBE_GIT_VERSION=$(echo "${KUBE_GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/") - fi - if [[ "${KUBE_GIT_TREE_STATE}" == "dirty" ]]; then - # git describe --dirty only considers changes to existing files, but - # that is problematic since new untracked .go files affect the build, - # so use our idea of "dirty" from git status instead. - KUBE_GIT_VERSION+="-dirty" - fi - - - # Try to match the "git describe" output to a regex to try to extract - # the "major" and "minor" versions and whether this is the exact tagged - # version or whether the tree is between two tagged versions. - if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then - KUBE_GIT_MAJOR=${BASH_REMATCH[1]} - KUBE_GIT_MINOR=${BASH_REMATCH[2]} - if [[ -n "${BASH_REMATCH[4]}" ]]; then - KUBE_GIT_MINOR+="+" - fi - fi - - # If KUBE_GIT_VERSION is not a valid Semantic Version, then refuse to build. - if ! [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then - kube::log::error "KUBE_GIT_VERSION should be a valid Semantic Version. Current value: ${KUBE_GIT_VERSION}" - kube::log::error "Please see more details here: https://semver.org" - exit 1 - fi - fi - fi -} - -# Saves the environment flags to $1 -kube::version::save_version_vars() { - local version_file=${1-} - [[ -n ${version_file} ]] || { - echo "!!! Internal error. No file specified in kube::version::save_version_vars" - return 1 - } - - cat <"${version_file}" -KUBE_GIT_COMMIT='${KUBE_GIT_COMMIT-}' -KUBE_GIT_TREE_STATE='${KUBE_GIT_TREE_STATE-}' -KUBE_GIT_VERSION='${KUBE_GIT_VERSION-}' -KUBE_GIT_MAJOR='${KUBE_GIT_MAJOR-}' -KUBE_GIT_MINOR='${KUBE_GIT_MINOR-}' -EOF -} - -# Loads up the version variables from file $1 -kube::version::load_version_vars() { - local version_file=${1-} - [[ -n ${version_file} ]] || { - echo "!!! Internal error. No file specified in kube::version::load_version_vars" - return 1 - } - - source "${version_file}" -} - -# Prints the value that needs to be passed to the -ldflags parameter of go build -# in order to set the Kubernetes based on the git tree status. -# IMPORTANT: if you update any of these, also update the lists in -# hack/print-workspace-status.sh. -kube::version::ldflags() { - kube::version::get_version_vars - - local -a ldflags - function add_ldflag() { - local key=${1} - local val=${2} - ldflags+=( - "-X '${KUBE_GO_PACKAGE}/vendor/k8s.io/client-go/pkg/version.${key}=${val}'" - "-X '${KUBE_GO_PACKAGE}/vendor/k8s.io/component-base/version.${key}=${val}'" - "-X 'k8s.io/client-go/pkg/version.${key}=${val}'" - "-X 'k8s.io/component-base/version.${key}=${val}'" - ) - } - - kube::util::ensure-gnu-date - - add_ldflag "buildDate" "$(${DATE} ${SOURCE_DATE_EPOCH:+"--date=@${SOURCE_DATE_EPOCH}"} -u +'%Y-%m-%dT%H:%M:%SZ')" - if [[ -n ${KUBE_GIT_COMMIT-} ]]; then - add_ldflag "gitCommit" "${KUBE_GIT_COMMIT}" - add_ldflag "gitTreeState" "${KUBE_GIT_TREE_STATE}" - fi - - if [[ -n ${KUBE_GIT_VERSION-} ]]; then - add_ldflag "gitVersion" "${KUBE_GIT_VERSION}" - fi - - if [[ -n ${KUBE_GIT_MAJOR-} && -n ${KUBE_GIT_MINOR-} ]]; then - add_ldflag "gitMajor" "${KUBE_GIT_MAJOR}" - add_ldflag "gitMinor" "${KUBE_GIT_MINOR}" - fi - - # The -ldflags parameter takes a single string, so join the output. - echo "${ldflags[*]-}" -} diff --git a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh index 279e9721c88..7aec68fd5f2 100755 --- a/third_party/k8s.io/kubernetes/hack/verify-licenses.sh +++ b/third_party/k8s.io/kubernetes/hack/verify-licenses.sh @@ -21,14 +21,7 @@ set -o errexit set -o nounset set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. -source "${KUBE_ROOT}/hack/lib/init.sh" -source "${KUBE_ROOT}/hack/lib/util.sh" - - -kube::golang::verify_go_version -kube::util::ensure-temp-dir +KUBE_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t kubernetes.XXXXXX) # Creating a new repository tree @@ -37,11 +30,6 @@ git worktree add -f "${KUBE_TEMP}"/tmp_test_licenses/gatekeeper HEAD >/dev/null cd "${KUBE_TEMP}"/tmp_test_licenses/gatekeeper && rm -rf vendor -# Ensure that we find the binaries we build before anything else. -export GOBIN="${KUBE_OUTPUT_BINPATH}" -PATH="${GOBIN}:${PATH}" - - # Explicitly opt into go modules, even though we're inside a GOPATH directory export GO111MODULE=on @@ -161,13 +149,13 @@ fi if [[ ${#packages_flagged[@]} -gt 0 ]]; then - kube::log::error "[ERROR] The following go-packages in the project are using non-CNCF approved licenses. Please refer to the CNCF's approved licence list for further information: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md" + echo "[ERROR] The following go-packages in the project are using non-CNCF approved licenses. Please refer to the CNCF's approved licence list for further information: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md" awk '{ printf "%-100s : %-20s : %s\n", $1, $2, $3 }' "${KUBE_TEMP}"/notapproved_licenses.dump exit_code=1 elif [[ "${exit_code}" -eq 1 ]]; then - kube::log::status "[ERROR] Project is using go-packages with unknown or unreachable license URLs. Please refer to the CNCF's approved licence list for further information: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md" + echo "[ERROR] Project is using go-packages with unknown or unreachable license URLs. Please refer to the CNCF's approved licence list for further information: https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md" else - kube::log::status "[SUCCESS] Scan complete! All go-packages under the project are using current CNCF approved licenses!" + echo "[SUCCESS] Scan complete! All go-packages under the project are using current CNCF approved licenses!" fi exit "${exit_code}"