mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Build relevant binaries with coverage.
This commit is contained in:
parent
1b3a2dd083
commit
aa2a7d001a
@ -211,6 +211,15 @@ readonly KUBE_STATIC_LIBRARIES=(
|
|||||||
kubectl
|
kubectl
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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
|
# 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.
|
# with CGO enabled, assuming CGO is supported on the target platform.
|
||||||
# This overrides any entry in KUBE_STATIC_LIBRARIES.
|
# This overrides any entry in KUBE_STATIC_LIBRARIES.
|
||||||
@ -441,6 +450,104 @@ kube::golang::outfile_for_binary() {
|
|||||||
echo "${output_path}/${bin}"
|
echo "${output_path}/${bin}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Argument: the name of a Kubernetes package.
|
||||||
|
# Returns 0 if the binary can be built with coverage, 0 otherwise.
|
||||||
|
# NB: this ignores whether coverage is globally enabled or not.
|
||||||
|
kube::golang::is_covered_binary() {
|
||||||
|
return $(kube::util::array_contains "$1" "${KUBE_COVERAGE_INSTRUMENTED_PACKAGES[@]}")
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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=$(basename "$package")
|
||||||
|
echo "$path/zz_autogenerated_${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="$(basename "$package")"
|
||||||
|
cat <<EOF > $(kube::golang::path_for_coverage_dummy_test "$package")
|
||||||
|
package main
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
// We need to pass coverage instructions to the unittest framework, so we hijack os.Args
|
||||||
|
original_args := os.Args
|
||||||
|
now := time.Now().UnixNano()
|
||||||
|
test_args := []string{os.Args[0], "-test.coverprofile=/tmp/k8s-${name}-" + strconv.FormatInt(now, 10) + ".cov"}
|
||||||
|
os.Args = test_args
|
||||||
|
|
||||||
|
// This is sufficient for the unit tests to be set up.
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Restore the original args for use by the program.
|
||||||
|
os.Args = original_args
|
||||||
|
// 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 be sure to call this from inside the binary too.
|
||||||
|
// TODO: actually have some code here.
|
||||||
|
}
|
||||||
|
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_dumy_test.
|
||||||
|
kube::golang::delete_coverage_dummy_test() {
|
||||||
|
local package=$1
|
||||||
|
rm $(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, the standard build globals are assumed.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
kube::golang::build_some_binaries() {
|
||||||
|
if [[ -n "${build_with_coverage:-}" ]]; then
|
||||||
|
local -a uncovered=()
|
||||||
|
for package in "$@"; do
|
||||||
|
if kube::golang::is_covered_binary "$package"; then
|
||||||
|
V=2 kube::log::info "Building $package with coverage..."
|
||||||
|
kube::golang::create_coverage_dummy_test "$package"
|
||||||
|
go test -c -o "$(kube::golang::outfile_for_binary "$package" "$platform")" \
|
||||||
|
-covermode count \
|
||||||
|
-coverpkg k8s.io/... \
|
||||||
|
"${build_args[@]}" \
|
||||||
|
"$package"
|
||||||
|
kube::golang::delete_coverage_dummy_test "$package"
|
||||||
|
else
|
||||||
|
uncovered+=("$package")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "${#uncovered[@]}" != 0 ]]; then
|
||||||
|
V=2 kube::log::info "Building ${uncovered[@]} without coverage..."
|
||||||
|
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."
|
||||||
|
go install "${build_args[@]}" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
kube::golang::build_binaries_for_platform() {
|
kube::golang::build_binaries_for_platform() {
|
||||||
local platform=$1
|
local platform=$1
|
||||||
|
|
||||||
@ -460,18 +567,24 @@ kube::golang::build_binaries_for_platform() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
local -a build_args
|
||||||
if [[ "${#statics[@]}" != 0 ]]; then
|
if [[ "${#statics[@]}" != 0 ]]; then
|
||||||
CGO_ENABLED=0 go install -installsuffix static "${goflags[@]:+${goflags[@]}}" \
|
build_args=(
|
||||||
-gcflags "${gogcflags}" \
|
-installsuffix static
|
||||||
-ldflags "${goldflags}" \
|
${goflags:+"${goflags[@]}"}
|
||||||
"${statics[@]:+${statics[@]}}"
|
-gcflags "${gogcflags:-}"
|
||||||
|
-ldflags "${goldflags:-}"
|
||||||
|
)
|
||||||
|
CGO_ENABLED=0 kube::golang::build_some_binaries "${statics[@]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${#nonstatics[@]}" != 0 ]]; then
|
if [[ "${#nonstatics[@]}" != 0 ]]; then
|
||||||
go install "${goflags[@]:+${goflags[@]}}" \
|
build_args=(
|
||||||
-gcflags "${gogcflags}" \
|
${goflags:+"${goflags[@]}"}
|
||||||
-ldflags "${goldflags}" \
|
-gcflags "${gogcflags:-}"
|
||||||
"${nonstatics[@]:+${nonstatics[@]}}"
|
-ldflags "${goldflags:-}"
|
||||||
|
)
|
||||||
|
kube::golang::build_some_binaries "${nonstatics[@]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for test in "${tests[@]:+${tests[@]}}"; do
|
for test in "${tests[@]:+${tests[@]}}"; do
|
||||||
@ -480,9 +593,9 @@ kube::golang::build_binaries_for_platform() {
|
|||||||
|
|
||||||
mkdir -p "$(dirname ${outfile})"
|
mkdir -p "$(dirname ${outfile})"
|
||||||
go test -c \
|
go test -c \
|
||||||
"${goflags[@]:+${goflags[@]}}" \
|
${goflags:+"${goflags[@]}"} \
|
||||||
-gcflags "${gogcflags}" \
|
-gcflags "${gogcflags:-}" \
|
||||||
-ldflags "${goldflags}" \
|
-ldflags "${goldflags:-}" \
|
||||||
-o "${outfile}" \
|
-o "${outfile}" \
|
||||||
"${testpkg}"
|
"${testpkg}"
|
||||||
done
|
done
|
||||||
@ -535,10 +648,11 @@ kube::golang::build_binaries() {
|
|||||||
host_platform=$(kube::golang::host_platform)
|
host_platform=$(kube::golang::host_platform)
|
||||||
|
|
||||||
# Use eval to preserve embedded quoted strings.
|
# Use eval to preserve embedded quoted strings.
|
||||||
local goflags goldflags gogcflags
|
local goflags goldflags gogcflags build_with_coverage
|
||||||
eval "goflags=(${GOFLAGS:-})"
|
eval "goflags=(${GOFLAGS:-})"
|
||||||
goldflags="${GOLDFLAGS:-} $(kube::version::ldflags)"
|
goldflags="${GOLDFLAGS:-} $(kube::version::ldflags)"
|
||||||
gogcflags="${GOGCFLAGS:-}"
|
gogcflags="${GOGCFLAGS:-}"
|
||||||
|
build_with_coverage="${KUBE_BUILD_WITH_COVERAGE:-}"
|
||||||
|
|
||||||
local -a targets=()
|
local -a targets=()
|
||||||
local arg
|
local arg
|
||||||
|
@ -18,6 +18,20 @@ kube::util::sortable_date() {
|
|||||||
date "+%Y%m%d-%H%M%S"
|
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() {
|
kube::util::wait_for_url() {
|
||||||
local url=$1
|
local url=$1
|
||||||
local prefix=${2:-}
|
local prefix=${2:-}
|
||||||
|
Loading…
Reference in New Issue
Block a user