Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

133
build/lib/init.sh Normal file
View File

@@ -0,0 +1,133 @@
#!/bin/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/kratosrnetes/kratosrnetes/issues/52255
unset CDPATH
# The root of the build/dist directory
KRATOS_ROOT="$(cd "$(dirname "${BASH_SOURCE}")/../.." && pwd -P)"
KRATOS_OUTPUT_SUBPATH="${KRATOS_OUTPUT_SUBPATH:-_output/local}"
KRATOS_OUTPUT="${KRATOS_ROOT}/${KRATOS_OUTPUT_SUBPATH}"
KRATOS_OUTPUT_BINPATH="${KRATOS_OUTPUT}/bin"
# This controls rsync compression. Set to a value > 0 to enable rsync
# compression for build container
KRATOS_RSYNC_COMPRESS="${KRATOS_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
export bazel_version="0.20.0"
# This is a symlink to binaries for "this platform", e.g. build tools.
THIS_PLATFORM_BIN="${KRATOS_ROOT}/_output/bin"
source "${KRATOS_ROOT}/build/lib/util.sh"
source "${KRATOS_ROOT}/build/lib/logging.sh"
#kratos::log::install_errexit
#source "${KRATOS_ROOT}/build/lib/version.sh"
#source "${KRATOS_ROOT}/build/lib/golang.sh"
#source "${KRATOS_ROOT}/build/lib/etcd.sh"
# 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=$(kratos::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 kratos::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=$(kratos::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
kratos::realpath() {
if [[ ! -e "$1" ]]; then
echo "$1: No such file or directory" >&2
return 1
fi
kratos::readlinkdashf "$1"
}

13
build/lib/lib.sh Normal file
View File

@@ -0,0 +1,13 @@
set -o errexit
set -o nounset
set -o pipefail
# Unset CDPATH so that path interpolation can work correctly
# https://github.com/kratosrnetes/kratosrnetes/issues/52255
unset CDPATH
# The root of the build/dist directory
if [ -z "$KRATOS_ROOT" ]
then
KRATOS_ROOT="$(cd "$(dirname "${BASH_SOURCE}")/../.." && pwd -P)"
if

171
build/lib/logging.sh Normal file
View File

@@ -0,0 +1,171 @@
#!/bin/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.
KRATOS_VERBOSE="${KRATOS_VERBOSE:-5}"
# Handler for when we exit automatically on an error.
# Borrowed from https://gist.github.com/ahendrix/7030300
kratos::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
kratos::log::error "Call tree:"
for ((i=1;i<${#FUNCNAME[@]}-1;i++))
do
kratos::log::error " $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]} ${FUNCNAME[$i]}(...)"
done
fi
kratos::log::error_exit "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${BASH_COMMAND}' exited with status $err" "${1:-1}" 1
}
kratos::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 'kratos::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.
kratos::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.
kratos::log::error_exit() {
local message="${1:-}"
local code="${2:-1}"
local stack_skip="${3:-0}"
stack_skip=$((stack_skip + 1))
if [[ ${KRATOS_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
}
kratos::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.
kratos::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.
kratos::log::usage() {
echo >&2
local message
for message; do
echo "$message" >&2
done
echo >&2
}
kratos::log::usage_from_stdin() {
local messages=()
while read -r line; do
messages+=("$line")
done
kratos::log::usage "${messages[@]}"
}
# Print out some info that isn't a top level status line
kratos::log::info() {
local V="${V:-0}"
if [[ $KRATOS_VERBOSE < $V ]]; then
return
fi
for message; do
echo "$message"
done
}
# Just like kratos::log::info, but no \n, so you can make a progress bar
kratos::log::progress() {
for message; do
echo -e -n "$message"
done
}
kratos::log::info_from_stdin() {
local messages=()
while read -r line; do
messages+=("$line")
done
kratos::log::info "${messages[@]}"
}
# Print a status line. Formatted to show up in a stream of output.
kratos::log::status() {
local V="${V:-0}"
if [[ $KRATOS_VERBOSE < $V ]]; then
return
fi
timestamp=$(date +"[%m%d %H:%M:%S]")
echo "+++ $timestamp $1"
shift
for message; do
echo " $message"
done
}

825
build/lib/util.sh Normal file
View File

@@ -0,0 +1,825 @@
#!/bin/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.
kratos::util::sortable_date() {
date "+%Y%m%d-%H%M%S"
}
kratos::util::wait_for_url() {
local url=$1
local prefix=${2:-}
local wait=${3:-1}
local times=${4:-30}
which curl >/dev/null || {
kratos::log::usage "curl must be installed"
exit 1
}
local i
for i in $(seq 1 "$times"); do
local out
if out=$(curl --max-time 1 -gkfs "$url" 2>/dev/null); then
kratos::log::status "On try ${i}, ${prefix}: ${out}"
return 0
fi
sleep "${wait}"
done
kratos::log::error "Timed out waiting for ${prefix} to answer at ${url}; tried ${times} waiting ${wait} between each"
return 1
}
# Example: kratos::util::trap_add 'echo "in trap DEBUG"' DEBUG
# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal
kratos::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
trap "${new_cmd}" "${trap_add_name}"
done
}
# Opposite of kratos::util::ensure-temp-dir()
kratos::util::cleanup-temp-dir() {
rm -rf "${KRATOS_TEMP}"
}
# Create a temp dir that'll be deleted at the end of this bash session.
#
# Vars set:
# KRATOS_TEMP
kratos::util::ensure-temp-dir() {
if [[ -z ${KRATOS_TEMP-} ]]; then
KRATOS_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t kratosrnetes.XXXXXX)
kratos::util::trap_add kratos::util::cleanup-temp-dir EXIT
fi
}
# 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.
kratos::util::host_platform() {
local host_os
local host_arch
case "$(uname -s)" in
Darwin)
host_os=darwin
;;
Linux)
host_os=linux
;;
*)
kratos::log::error "Unsupported host OS. Must be Linux or Mac OS X."
exit 1
;;
esac
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
;;
*)
kratos::log::error "Unsupported host arch. Must be x86_64, 386, arm, arm64, s390x or ppc64le."
exit 1
;;
esac
echo "${host_os}/${host_arch}"
}
kratos::util::find-binary-for-platform() {
local -r lookfor="$1"
local -r platform="$2"
local locations=(
"${KRATOS_ROOT}/_output/bin/${lookfor}"
"${KRATOS_ROOT}/_output/dockerized/bin/${platform}/${lookfor}"
"${KRATOS_ROOT}/_output/local/bin/${platform}/${lookfor}"
"${KRATOS_ROOT}/platforms/${platform}/${lookfor}"
)
# Also search for binary in bazel build tree.
# The bazel go rules place binaries in subtrees like
# "bazel-bin/source/path/linux_amd64_pure_stripped/binaryname", so make sure
# the platform name is matched in the path.
locations+=($(find "${KRATOS_ROOT}/bazel-bin/" -type f -executable \
-path "*/${platform/\//_}*/${lookfor}" 2>/dev/null || true) )
# List most recently-updated location.
local -r bin=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
echo -n "${bin}"
}
kratos::util::find-binary() {
kratos::util::find-binary-for-platform "$1" "$(kratos::util::host_platform)"
}
# Run all known doc generators (today gendocs and genman for kratosctl)
# $1 is the directory to put those generated documents
kratos::util::gen-docs() {
local dest="$1"
# Find binary
gendocs=$(kratos::util::find-binary "gendocs")
genkratosdocs=$(kratos::util::find-binary "genkratosdocs")
genman=$(kratos::util::find-binary "genman")
genyaml=$(kratos::util::find-binary "genyaml")
genfeddocs=$(kratos::util::find-binary "genfeddocs")
mkdir -p "${dest}/docs/user-guide/kratosctl/"
"${gendocs}" "${dest}/docs/user-guide/kratosctl/"
mkdir -p "${dest}/docs/admin/"
"${genkratosdocs}" "${dest}/docs/admin/" "kratos-apiserver"
"${genkratosdocs}" "${dest}/docs/admin/" "kratos-controller-manager"
"${genkratosdocs}" "${dest}/docs/admin/" "cloud-controller-manager"
"${genkratosdocs}" "${dest}/docs/admin/" "kratos-proxy"
"${genkratosdocs}" "${dest}/docs/admin/" "kratos-scheduler"
"${genkratosdocs}" "${dest}/docs/admin/" "kratoslet"
"${genkratosdocs}" "${dest}/docs/admin/" "kratosadm"
mkdir -p "${dest}/docs/man/man1/"
"${genman}" "${dest}/docs/man/man1/" "kratos-apiserver"
"${genman}" "${dest}/docs/man/man1/" "kratos-controller-manager"
"${genman}" "${dest}/docs/man/man1/" "cloud-controller-manager"
"${genman}" "${dest}/docs/man/man1/" "kratos-proxy"
"${genman}" "${dest}/docs/man/man1/" "kratos-scheduler"
"${genman}" "${dest}/docs/man/man1/" "kratoslet"
"${genman}" "${dest}/docs/man/man1/" "kratosctl"
"${genman}" "${dest}/docs/man/man1/" "kratosadm"
mkdir -p "${dest}/docs/yaml/kratosctl/"
"${genyaml}" "${dest}/docs/yaml/kratosctl/"
# create the list of generated files
pushd "${dest}" > /dev/null
touch docs/.generated_docs
find . -type f | cut -sd / -f 2- | LC_ALL=C sort > docs/.generated_docs
popd > /dev/null
}
# Puts a placeholder for every generated doc. This makes the link checker work.
kratos::util::set-placeholder-gen-docs() {
local list_file="${KRATOS_ROOT}/docs/.generated_docs"
if [[ -e "${list_file}" ]]; then
# remove all of the old docs; we don't want to check them in.
while read file; do
if [[ "${list_file}" != "${KRATOS_ROOT}/${file}" ]]; then
cp "${KRATOS_ROOT}/build/autogenerated_placeholder.txt" "${KRATOS_ROOT}/${file}"
fi
done <"${list_file}"
# The docs/.generated_docs file lists itself, so we don't need to explicitly
# delete it.
fi
}
# Removes previously generated docs-- we don't want to check them in. $KRATOS_ROOT
# must be set.
kratos::util::remove-gen-docs() {
if [ -e "${KRATOS_ROOT}/docs/.generated_docs" ]; then
# remove all of the old docs; we don't want to check them in.
while read file; do
rm "${KRATOS_ROOT}/${file}" 2>/dev/null || true
done <"${KRATOS_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
kratos::util::group-version-to-pkg-path() {
staging_apis=(
$(
cd "${KRATOS_ROOT}/staging/src/k8s.io/api" &&
find . -name types.go -exec dirname {} \; | sed "s|\./||g" | sort
))
local group_version="$1"
if [[ " ${staging_apis[@]} " =~ " ${group_version/.*k8s.io/} " ]]; then
echo "vendor/k8s.io/api/${group_version/.*k8s.io/}"
return
fi
# "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"
;;
unversioned)
echo "pkg/api/unversioned"
;;
*.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
kratos::util::gv-to-swagger-name() {
local group_version="$1"
case "${group_version}" in
v1)
echo "v1"
;;
*)
echo "${group_version%/*}_${group_version#*/}"
;;
esac
}
# Fetches swagger spec from apiserver.
# Assumed vars:
# SWAGGER_API_PATH: Base path for swaggerapi on apiserver. Ex:
# http://localhost:8080/swaggerapi.
# SWAGGER_ROOT_DIR: Root dir where we want to to save the fetched spec.
# VERSIONS: Array of group versions to include in swagger spec.
kratos::util::fetch-swagger-spec() {
for ver in ${VERSIONS}; do
if [[ " ${KRATOS_NONSERVER_GROUP_VERSIONS} " == *" ${ver} "* ]]; then
continue
fi
# fetch the swagger spec for each group version.
if [[ ${ver} == "v1" ]]; then
SUBPATH="api"
else
SUBPATH="apis"
fi
SUBPATH="${SUBPATH}/${ver}"
SWAGGER_JSON_NAME="$(kratos::util::gv-to-swagger-name ${ver}).json"
curl -w "\n" -fs "${SWAGGER_API_PATH}${SUBPATH}" > "${SWAGGER_ROOT_DIR}/${SWAGGER_JSON_NAME}"
# fetch the swagger spec for the discovery mechanism at group level.
if [[ ${ver} == "v1" ]]; then
continue
fi
SUBPATH="apis/"${ver%/*}
SWAGGER_JSON_NAME="${ver%/*}.json"
curl -w "\n" -fs "${SWAGGER_API_PATH}${SUBPATH}" > "${SWAGGER_ROOT_DIR}/${SWAGGER_JSON_NAME}"
done
# fetch swagger specs for other discovery mechanism.
curl -w "\n" -fs "${SWAGGER_API_PATH}" > "${SWAGGER_ROOT_DIR}/resourceListing.json"
curl -w "\n" -fs "${SWAGGER_API_PATH}version" > "${SWAGGER_ROOT_DIR}/version.json"
curl -w "\n" -fs "${SWAGGER_API_PATH}api" > "${SWAGGER_ROOT_DIR}/api.json"
curl -w "\n" -fs "${SWAGGER_API_PATH}apis" > "${SWAGGER_ROOT_DIR}/apis.json"
curl -w "\n" -fs "${SWAGGER_API_PATH}logs" > "${SWAGGER_ROOT_DIR}/logs.json"
}
# Returns the name of the upstream remote repository name for the local git
# repo, e.g. "upstream" or "origin".
kratos::util::git_upstream_remote_name() {
git remote -v | grep fetch |\
grep -E 'github.com[/:]kratosrnetes/kratosrnetes|k8s.io/kratosrnetes' |\
head -n 1 | awk '{print $1}'
}
# Ensures the current directory is a git tree for doing things like restoring or
# validating godeps
kratos::util::create-fake-git-tree() {
local -r target_dir=${1:-$(pwd)}
pushd "${target_dir}" >/dev/null
git init >/dev/null
git config --local user.email "nobody@k8s.io"
git config --local user.name "$0"
git add . >/dev/null
git commit -q -m "Snapshot" >/dev/null
if (( ${KRATOS_VERBOSE:-5} >= 6 )); then
kratos::log::status "${target_dir} is now a git tree."
fi
popd >/dev/null
}
# Checks whether godep restore was run in the current GOPATH, i.e. that all referenced repos exist
# and are checked out to the referenced rev.
kratos::util::godep_restored() {
local -r godeps_json=${1:-Godeps/Godeps.json}
local -r gopath=${2:-${GOPATH%:*}}
if ! which jq &>/dev/null; then
echo "jq not found. Please install." 1>&2
return 1
fi
local root
local old_rev=""
while read path rev; do
rev=$(echo "${rev}" | sed "s/['\"]//g") # remove quotes which are around revs sometimes
if [[ "${rev}" == "${old_rev}" ]] && [[ "${path}" == "${root}"* ]]; then
# avoid checking the same git/hg root again
continue
fi
root="${path}"
while [ "${root}" != "." -a ! -d "${gopath}/src/${root}/.git" -a ! -d "${gopath}/src/${root}/.hg" ]; do
root=$(dirname "${root}")
done
if [ "${root}" == "." ]; then
echo "No checkout of ${path} found in GOPATH \"${gopath}\"." 1>&2
return 1
fi
local head
if [ -d "${gopath}/src/${root}/.git" ]; then
head="$(cd "${gopath}/src/${root}" && git rev-parse HEAD)"
else
head="$(cd "${gopath}/src/${root}" && hg parent --template '{node}')"
fi
if [ "${head}" != "${rev}" ]; then
echo "Unexpected HEAD '${head}' at ${gopath}/src/${root}, expected '${rev}'." 1>&2
return 1
fi
old_rev="${rev}"
done < <(jq '.Deps|.[]|.ImportPath + " " + .Rev' -r < "${godeps_json}")
return 0
}
# 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.
kratos::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
done 1>&2
}
# Ensure that the given godep version is installed and in the path. Almost
# nobody should use any version but the default.
kratos::util::ensure_godep_version() {
GODEP_VERSION=${1:-"v79"} # this version is known to work
if [[ "$(godep version 2>/dev/null)" == *"godep ${GODEP_VERSION}"* ]]; then
return
fi
kratos::log::status "Installing godep version ${GODEP_VERSION}"
go install ./vendor/github.com/tools/godep/
GP="$(echo $GOPATH | cut -f1 -d:)"
hash -r # force bash to clear PATH cache
PATH="${GP}/bin:${PATH}"
if [[ "$(godep version 2>/dev/null)" != *"godep ${GODEP_VERSION}"* ]]; then
kratos::log::error "Expected godep ${GODEP_VERSION}, got $(godep version)"
return 1
fi
}
# Ensure that none of the staging repos is checked out in the GOPATH because this
# easily confused godep.
kratos::util::ensure_no_staging_repos_in_gopath() {
kratos::util::ensure_single_dir_gopath
local error=0
for repo_file in "${KRATOS_ROOT}"/staging/src/k8s.io/*; do
if [[ ! -d "$repo_file" ]]; then
# not a directory or there were no files
continue;
fi
repo="$(basename "$repo_file")"
if [ -e "${GOPATH}/src/k8s.io/${repo}" ]; then
echo "k8s.io/${repo} exists in GOPATH. Remove before running godep-save.sh." 1>&2
error=1
fi
done
if [ "${error}" = "1" ]; then
exit 1
fi
}
# Installs the specified go package at a particular commit.
kratos::util::go_install_from_commit() {
local -r pkg=$1
local -r commit=$2
kratos::util::ensure-temp-dir
mkdir -p "${KRATOS_TEMP}/go/src"
GOPATH="${KRATOS_TEMP}/go" go get -d -u "${pkg}"
(
cd "${KRATOS_TEMP}/go/src/${pkg}"
git checkout -q "${commit}"
GOPATH="${KRATOS_TEMP}/go" go install "${pkg}"
)
PATH="${KRATOS_TEMP}/go/bin:${PATH}"
hash -r # force bash to clear PATH cache
}
# Checks that the GOPATH is simple, i.e. consists only of one directory, not multiple.
kratos::util::ensure_single_dir_gopath() {
if [[ "${GOPATH}" == *:* ]]; then
echo "GOPATH must consist of a single directory." 1>&2
exit 1
fi
}
# 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.
kratos::util::has_changes_against_upstream_branch() {
local -r git_branch=$1
local -r pattern=$2
local -r not_pattern=${3:-totallyimpossiblepattern}
local full_branch
full_branch="$(kratos::util::git_upstream_remote_name)/${git_branch}"
echo "Checking for '${pattern}' changes against '${full_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
# notice this uses ... to find the first shared ancestor
if git diff --name-only "${full_branch}...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
}
kratos::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 kratos::util::test_openssl_installed {
openssl version >& /dev/null
if [ "$?" != "0" ]; then
echo "Failed to run openssl. Please ensure openssl is installed"
exit 1
fi
OPENSSL_BIN=$(command -v openssl)
}
# 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 kratos::util::create_signing_certkey {
local sudo=$1
local dest_dir=$2
local id=$3
local purpose=$4
# Create client ca
${sudo} /bin/bash -e <<EOF
rm -f "${dest_dir}/${id}-ca.crt" "${dest_dir}/${id}-ca.key"
${OPENSSL_BIN} req -x509 -sha256 -new -nodes -days 365 -newkey rsa:2048 -keyout "${dest_dir}/${id}-ca.key" -out "${dest_dir}/${id}-ca.crt" -subj "/C=xx/ST=x/L=x/O=x/OU=x/CN=ca/emailAddress=x/"
echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment",${purpose}]}}}' > "${dest_dir}/${id}-ca-config.json"
EOF
}
# signs a client certificate: args are sudo, dest-dir, CA, filename (roughly), username, groups...
function kratos::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} /bin/bash -e <<EOF
cd ${dest_dir}
echo '{"CN":"${cn}","names":[${groups}],"hosts":[""],"key":{"algo":"rsa","size":2048}}' | ${CFSSL_BIN} gencert -ca=${ca}.crt -ca-key=${ca}.key -config=${ca}-config.json - | ${CFSSLJSON_BIN} -bare client-${id}
mv "client-${id}-key.pem" "client-${id}.key"
mv "client-${id}.pem" "client-${id}.crt"
rm -f "client-${id}.csr"
EOF
}
# signs a serving certificate: args are sudo, dest-dir, ca, filename (roughly), subject, hosts...
function kratos::util::create_serving_certkey {
local sudo=$1
local dest_dir=$2
local ca=$3
local id=$4
local cn=${5:-$4}
local hosts=""
local SEP=""
shift 5
while [ -n "${1:-}" ]; do
hosts+="${SEP}\"$1\""
SEP=","
shift 1
done
${sudo} /bin/bash -e <<EOF
cd ${dest_dir}
echo '{"CN":"${cn}","hosts":[${hosts}],"key":{"algo":"rsa","size":2048}}' | ${CFSSL_BIN} gencert -ca=${ca}.crt -ca-key=${ca}.key -config=${ca}-config.json - | ${CFSSLJSON_BIN} -bare serving-${id}
mv "serving-${id}-key.pem" "serving-${id}.key"
mv "serving-${id}.pem" "serving-${id}.crt"
rm -f "serving-${id}.csr"
EOF
}
# creates a self-contained kratosconfig: args are sudo, dest-dir, ca file, host, port, client id, token(optional)
function kratos::util::write_client_kratosconfig {
local sudo=$1
local dest_dir=$2
local ca_file=$3
local api_host=$4
local api_port=$5
local client_id=$6
local token=${7:-}
cat <<EOF | ${sudo} tee "${dest_dir}"/${client_id}.kratosconfig > /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 kratosconfig files to make them self contained
username=$(whoami)
${sudo} /bin/bash -e <<EOF
$(kratos::util::find-binary kratosctl) --kratosconfig="${dest_dir}/${client_id}.kratosconfig" config view --minify --flatten > "/tmp/${client_id}.kratosconfig"
mv -f "/tmp/${client_id}.kratosconfig" "${dest_dir}/${client_id}.kratosconfig"
chown ${username} "${dest_dir}/${client_id}.kratosconfig"
EOF
}
# Determines if docker can be run, failures may simply require that the user be added to the docker group.
function kratos::util::ensure_docker_daemon_connectivity {
DOCKER=(docker ${DOCKER_OPTS})
if ! "${DOCKER[@]}" 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-machine: run `docker-machine ls` and `docker-machine start <name>`
- 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-machine: run `eval "$(docker-machine env <name>)"`
- 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.
kratos::util::wait-for-jobs() {
local fail=0
local job
for job in $(jobs -p); do
wait "${job}" || fail=$((fail + 1))
done
return ${fail}
}
# kratos::util::join <delim> <list...>
# Concatenates the list elements with the delimiter passed as first parameter
#
# Ex: kratos::util::join , a b c
# -> a,b,c
function kratos::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
#
function kratos::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
# Create a temp dir for cfssl if no directory was given
local cfssldir=${1:-}
if [[ -z "${cfssldir}" ]]; then
kratos::util::ensure-temp-dir
cfssldir="${KRATOS_TEMP}/cfssl"
fi
mkdir -p "${cfssldir}"
pushd "${cfssldir}" > /dev/null
echo "Unable to successfully run 'cfssl' from $PATH; downloading instead..."
kernel=$(uname -s)
case "${kernel}" in
Linux)
curl --retry 10 -L -o cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
curl --retry 10 -L -o cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
;;
Darwin)
curl --retry 10 -L -o cfssl https://pkg.cfssl.org/R1.2/cfssl_darwin-amd64
curl --retry 10 -L -o cfssljson https://pkg.cfssl.org/R1.2/cfssljson_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 get -u github.com/cloudflare/cfssl/cmd/..."
exit 1
fi
popd > /dev/null
}
# kratos::util::ensure_dockerized
# Confirms that the script is being run inside a kratos-build image
#
function kratos::util::ensure_dockerized {
if [[ -f /kratos-build-image ]]; then
return 0
else
echo "ERROR: This script is designed to be run inside a kratos-build container"
exit 1
fi
}
# kratos::util::ensure-gnu-sed
# Determines which sed binary is gnu-sed on linux/darwin
#
# Sets:
# SED: The name of the gnu-sed binary
#
function kratos::util::ensure-gnu-sed {
if LANG=C sed --help 2>&1 | grep -q GNU; then
SED="sed"
elif which gsed &>/dev/null; then
SED="gsed"
else
kratos::log::error "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2
return 1
fi
}
function kratos::util::ensure-homebrew {
if ! brew --version > /dev/null ; then
echo "install homebrew..."
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi
}
function kratos::util::ensure-homebrew-bazel {
if ! brew ls --versions bazel > /dev/null ; then
echo "install bazel..."
brew install bazel
fi
}
function kratos::util::ensure-bazel {
if ! bazel version > /dev/null ; then
echo "Please install bazel by being compiled from code."
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_norm="${color_start}0m"
fi
# ex: ts=2 sw=2 et filetype=sh

176
build/lib/version.sh Normal file
View File

@@ -0,0 +1,176 @@
#!/bin/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:
#
# KRATOS_GIT_COMMIT - The git commit id corresponding to this
# source code.
# KRATOS_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'
# KRATOS_GIT_VERSION - "vX.Y" used to indicate the last release version.
# KRATOS_GIT_MAJOR - The major part of the version
# KRATOS_GIT_MINOR - The minor component of the version
# Grovels through git to set a set of env variables.
#
# If KRATOS_GIT_VERSION_FILE, this function will load from that file instead of
# querying git.
kratos::version::get_version_vars() {
KRATOS_BUILD_TIME=`date +%Y.%m.%d-%H:%M:%S%Z`
if [[ -n ${KRATOS_GIT_VERSION_FILE-} ]]; then
kratos::version::load_version_vars "${KRATOS_GIT_VERSION_FILE}"
return
fi
# If the kratosrnetes source was exported through git archive, then
# we likely don't have a git tree, but these magic values may be filled in.
if [[ '$Format:%%$' == "%" ]]; then
KRATOS_GIT_COMMIT='$Format:%H$'
KRATOS_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
KRATOS_GIT_VERSION="${BASH_REMATCH[1]}"
fi
fi
local git=(git --work-tree "${KRATOS_ROOT}")
if [[ -n ${KRATOS_GIT_COMMIT-} ]] || KRATOS_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then
if [[ -z ${KRATOS_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
KRATOS_GIT_TREE_STATE="clean"
else
KRATOS_GIT_TREE_STATE="dirty"
fi
fi
# Use git describe to find the version based on tags.
if [[ -n ${KRATOS_GIT_VERSION-} ]] || KRATOS_GIT_VERSION=$("${git[@]}" describe --tags --abbrev=14 "${KRATOS_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.
DASHES_IN_VERSION=$(echo "${KRATOS_GIT_VERSION}" | sed "s/[^-]//g")
if [[ "${DASHES_IN_VERSION}" == "---" ]] ; then
# We have distance to subversion (v1.1.0-subversion-1-gCommitHash)
KRATOS_GIT_VERSION=$(echo "${KRATOS_GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\+\2/")
elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then
# We have distance to base tag (v1.1.0-1-gCommitHash)
KRATOS_GIT_VERSION=$(echo "${KRATOS_GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/")
fi
if [[ "${KRATOS_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.
KRATOS_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 [[ "${KRATOS_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then
KRATOS_GIT_MAJOR=${BASH_REMATCH[1]}
KRATOS_GIT_MINOR=${BASH_REMATCH[2]}
if [[ -n "${BASH_REMATCH[4]}" ]]; then
KRATOS_GIT_MINOR+="+"
fi
fi
# If KRATOS_GIT_VERSION is not a valid Semantic Version, then refuse to build.
#if ! [[ "${KRATOS_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
# echo "KRATOS_GIT_VERSION should be a valid Semantic Version"
# echo "Please see more details here: https://semver.org"
# exit 1
#fi
fi
fi
}
# Saves the environment flags to $1
kratos::version::save_version_vars() {
local version_file=${1-}
[[ -n ${version_file} ]] || {
echo "!!! Internal error. No file specified in kratos::version::save_version_vars"
return 1
}
cat <<EOF >"${version_file}"
KRATOS_GIT_COMMIT='${KRATOS_GIT_COMMIT-}'
KRATOS_GIT_TREE_STATE='${KRATOS_GIT_TREE_STATE-}'
KRATOS_GIT_VERSION='${KRATOS_GIT_VERSION-}'
KRATOS_GIT_MAJOR='${KRATOS_GIT_MAJOR-}'
KRATOS_GIT_MINOR='${KRATOS_GIT_MINOR-}'
EOF
}
# Loads up the version variables from file $1
kratos::version::load_version_vars() {
local version_file=${1-}
[[ -n ${version_file} ]] || {
echo "!!! Internal error. No file specified in kratos::version::load_version_vars"
return 1
}
source "${version_file}"
}
kratos::version::ldflag() {
local key=${1}
local val=${2}
# If you update these, also update the list pkg/version/def.bzl.
echo "-X '${KRATOS_GO_PACKAGE}/pkg/version.${key}=${val}'"
echo "-X '${KRATOS_GO_PACKAGE}/vendor/k8s.io/client-go/pkg/version.${key}=${val}'"
}
# 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
# pkg/version/def.bzl and .build/print-workspace-status.sh.
kratos::version::ldflags() {
kratos::version::get_version_vars
local buildDate=
[[ -z ${SOURCE_DATE_EPOCH-} ]] || buildDate="--date=@${SOURCE_DATE_EPOCH}"
local -a ldflags=($(kratos::version::ldflag "buildDate" "$(date ${buildDate} -u +'%Y-%m-%dT%H:%M:%SZ')"))
if [[ -n ${KRATOS_GIT_COMMIT-} ]]; then
ldflags+=($(kratos::version::ldflag "gitCommit" "${KRATOS_GIT_COMMIT}"))
ldflags+=($(kratos::version::ldflag "gitTreeState" "${KRATOS_GIT_TREE_STATE}"))
fi
if [[ -n ${KRATOS_GIT_VERSION-} ]]; then
ldflags+=($(kratos::version::ldflag "gitVersion" "${KRATOS_GIT_VERSION}"))
fi
if [[ -n ${KRATOS_GIT_MAJOR-} && -n ${KRATOS_GIT_MINOR-} ]]; then
ldflags+=(
$(kratos::version::ldflag "gitMajor" "${KRATOS_GIT_MAJOR}")
$(kratos::version::ldflag "gitMinor" "${KRATOS_GIT_MINOR}")
)
fi
# The -ldflags parameter takes a single string, so join the output.
echo "${ldflags[*]-}"
}