#!/usr/bin/env bash
set -e
# Source common without doing any bootstrap work at this stage
# Bootstrapping should be done inside the build container
source $(dirname "$0")/common.sh
if [ "${KUBEVIRT_RUN_UNNESTED}" == "true" ]; then
/bin/bash -c "$@"
exit $?
fi
fail_if_cri_bin_missing
kubevirt_builder_version="2510281240-82d14f4b41"
default_kubevirt_builder_image="quay.io/kubevirt/builder:${kubevirt_builder_version}"
kubevirt_cross_compile_image="quay.io/kubevirt/builder-cross:${kubevirt_builder_version}"
KUBEVIRT_BUILDER_IMAGE=${KUBEVIRT_BUILDER_IMAGE:-"${default_kubevirt_builder_image}"}
# As long as KUBEVIRT_BUILDER_IMAGE is using the default builder, check if cross-compilation is needed and
# switch to bigger cross-compile image instead.
# Should KUBEVIRT_BUILDER_IMAGE be modified by the user, do not change it. It is assumed that the user knows
# what they are doing.
if [ "${KUBEVIRT_BUILDER_IMAGE}" == "${default_kubevirt_builder_image}" ] && [ -n "${BUILD_ARCH}" ]; then
for arch in ${BUILD_ARCH//,/ }; do
arch=$(format_archname "${arch}")
if [[ ${arch} =~ ^cross-* ]]; then
KUBEVIRT_BUILDER_IMAGE="${kubevirt_cross_compile_image}"
fi
done
fi
SYNC_OUT=${SYNC_OUT:-true}
BUILDER=${job_prefix}
SYNC_VENDOR=${SYNC_VENDOR:-false}
TEMPFILE=".rsynctemp"
CONTAINER_ENV="--env HTTP_PROXY=${HTTP_PROXY} --env HTTPS_PROXY=${HTTP_PROXY} --env NO_PROXY=${NO_PROXY} --env KUBEVIRT_NO_BAZEL=${KUBEVIRT_NO_BAZEL}"
# Create the persistent container volume
if [ -z "$($KUBEVIRT_CRI volume list | grep ${BUILDER})" ]; then
$KUBEVIRT_CRI volume create ${BUILDER}
fi
selinux_bind_options=",z"
# Using Podman and MacOS and 'z' bind option may not work correctly.
# See: https://github.com/containers/podman/issues/13631
if [[ $KUBEVIRT_CRI = podman* ]] && [[ "$(uname -s)" == "Darwin" ]]; then
selinux_bind_options=""
fi
# Make sure that the output directory exists on both sides
$KUBEVIRT_CRI run ${CONTAINER_ENV} -v "${BUILDER}:/root:rw${selinux_bind_options}" --security-opt "label=disable" --rm ${KUBEVIRT_BUILDER_IMAGE} mkdir -p /root/go/src/kubevirt.io/kubevirt/_out
mkdir -p ${OUT_DIR}
# Start an rsyncd instance and make sure it gets stopped after the script exits
RSYNC_CID=$($KUBEVIRT_CRI run ${CONTAINER_ENV} -d -v "${BUILDER}:/root:rw${selinux_bind_options}" --security-opt "label=disable" --cap-add SYS_CHROOT --expose 873 -P ${KUBEVIRT_BUILDER_IMAGE} /usr/bin/rsync --no-detach --daemon --verbose)
function finish() {
$KUBEVIRT_CRI stop --time 1 ${RSYNC_CID} >/dev/null 2>&1
$KUBEVIRT_CRI rm -f ${RSYNC_CID} >/dev/null 2>&1
}
trap finish EXIT
RSYNCD_PORT=$($KUBEVIRT_CRI port $RSYNC_CID 873 | cut -d':' -f2)
rsynch_fail_count=0
while ! rsync ${KUBEVIRT_DIR}/${RSYNCTEMP} "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/${RSYNCTEMP}" &>/dev/null; do
if [[ "$rsynch_fail_count" -eq 0 ]]; then
printf "Waiting for rsyncd to be ready"
sleep .1
elif [[ "$rsynch_fail_count" -lt 30 ]]; then
printf "."
sleep 1
else
printf "failed"
break
fi
rsynch_fail_count=$((rsynch_fail_count + 1))
done
printf "\n"
rsynch_fail_count=0
_rsync() {
rsync -al "$@"
}
# Copy kubevirt into the persistent container volume
_rsync \
--delete \
--exclude 'bazel-bin' \
--exclude 'bazel-genfiles' \
--exclude 'bazel-kubevirt' \
--exclude 'bazel-out' \
--exclude 'bazel-testlogs' \
--exclude 'kubevirtci/cluster-up/cluster/**/.kubectl' \
--exclude 'kubevirtci/cluster-up/cluster/**/.oc' \
--exclude 'kubevirtci/cluster-up/cluster/**/.kubeconfig' \
--exclude "_out" \
--exclude ".vagrant" \
--exclude ".bazeldnf" \
${KUBEVIRT_DIR}/ \
"rsync://root@127.0.0.1:${RSYNCD_PORT}/build"
volumes="-v ${BUILDER}:/root:rw${selinux_bind_options}"
# append .docker secrets directory as volume
mkdir -p "${HOME}/.docker/secrets"
volumes="$volumes -v ${HOME}/.docker/secrets:/root/.docker/secrets:ro${selinux_bind_options}"
# Use a bind-mount to expose docker/podman auth file to the container
if [[ $KUBEVIRT_CRI = podman* ]] && [[ -f "${XDG_RUNTIME_DIR}/containers/auth.json" ]]; then
volumes="$volumes --mount type=bind,source=${XDG_RUNTIME_DIR}/containers/auth.json,target=/root/.docker/config.json,readonly"
elif [[ -f "${HOME}/.docker/config.json" && "$(cat ${HOME}/.docker/config.json | jq 'has("credHelpers")')" != "true" ]]; then
volumes="$volumes --mount type=bind,source=${HOME}/.docker/config.json,target=/root/.docker/config.json,readonly"
fi
# add custom docker certs, if needed
if [ -n "$DOCKER_CA_CERT_FILE" ] && [ -f "$DOCKER_CA_CERT_FILE" ]; then
volumes="$volumes -v ${DOCKER_CA_CERT_FILE}:${DOCKERIZED_CUSTOM_CA_PATH}:ro${selinux_bind_options}"
fi
# if defined, append the ARTIFACTS directory
if [ -n "$ARTIFACTS" ]; then
mkdir -p "$ARTIFACTS"
if [[ "$ARTIFACTS" = /* ]]; then
volumes="$volumes -v ${ARTIFACTS}:${ARTIFACTS}:rw${selinux_bind_options}"
else
echo "ARTIFACTS directory is specified, but it is not an absolute directory"
exit 1
fi
fi
# Ensure that a bazel server which is running is the correct one
if [ -n "$($KUBEVIRT_CRI ps --format '{{.Names}}' | grep ${BUILDER}-bazel-server)" ]; then
# check if the image is correct
builder_id=$($KUBEVIRT_CRI inspect --format='{{.Id}}' ${KUBEVIRT_BUILDER_IMAGE})
bazel_server_id=$($KUBEVIRT_CRI inspect --format='{{.Image}}' ${BUILDER}-bazel-server)
if [ "${builder_id}" != "${bazel_server_id}" ]; then
echo "Bazel server is outdated, restarting ..."
$KUBEVIRT_CRI stop ${BUILDER}-bazel-server
fi
fi
# Ensure that a bazel server is running
if [ -z "$($KUBEVIRT_CRI ps --format '{{.Names}}' | grep ${BUILDER}-bazel-server)" ]; then
$KUBEVIRT_CRI run ${CONTAINER_ENV} --ulimit nofile=10000:10000 --network host -d ${volumes} --security-opt "label=disable" --name ${BUILDER}-bazel-server -w "/root/go/src/kubevirt.io/kubevirt" --rm ${KUBEVIRT_BUILDER_IMAGE} hack/bazel-server.sh
fi
# Update cert trust, if custom is provided
if [ -n "$DOCKER_CA_CERT_FILE" ] && [ -f "$DOCKER_CA_CERT_FILE" ]; then
$KUBEVIRT_CRI exec ${CONTAINER_ENV} ${BUILDER}-bazel-server /entrypoint.sh "/usr/bin/update-ca-trust"
fi
# Run the command
test -t 1 && USE_TTY="-it"
if ! $KUBEVIRT_CRI exec ${CONTAINER_ENV} ${USE_TTY} ${BUILDER}-bazel-server /entrypoint.sh "$@"; then
# Copy the build output out of the container, make sure that _out exactly matches the build result
if [ "$SYNC_OUT" = "true" ]; then
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/out" ${OUT_DIR}
fi
exit 1
fi
# Copy the whole kubevirt data out to get generated sources and formatting changes
_rsync \
--exclude 'bazel-bin' \
--exclude 'bazel-genfiles' \
--exclude 'bazel-kubevirt' \
--exclude 'bazel-out' \
--exclude 'bazel-testlogs' \
--exclude 'kubevirtci/cluster-up/cluster/**/.kubectl' \
--exclude 'kubevirtci/cluster-up/cluster/**/.oc' \
--exclude 'kubevirtci/cluster-up/cluster/**/.kubeconfig' \
--exclude "_out" \
--exclude "vendor" \
--exclude ".vagrant" \
--exclude ".git" \
--exclude ".bazeldnf" \
"rsync://root@127.0.0.1:${RSYNCD_PORT}/build" \
${KUBEVIRT_DIR}/
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/manifests/generated/" "${KUBEVIRT_DIR}/manifests/generated"
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/staging/src/kubevirt.io/client-go/containerizeddataimporter/" "${KUBEVIRT_DIR}/staging/src/kubevirt.io/client-go/containerizeddataimporter"
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/staging/src/kubevirt.io/client-go/externalsnapshotter/" "${KUBEVIRT_DIR}/staging/src/kubevirt.io/client-go/externalsnapshotter"
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/staging/src/kubevirt.io/client-go/kubevirt/" "${KUBEVIRT_DIR}/staging/src/kubevirt.io/client-go/kubevirt"
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/staging/src/kubevirt.io/client-go/networkattachmentdefinitionclient/" "${KUBEVIRT_DIR}/staging/src/kubevirt.io/client-go/networkattachmentdefinitionclient"
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/staging/src/kubevirt.io/client-go/prometheusoperator/" "${KUBEVIRT_DIR}/staging/src/kubevirt.io/client-go/prometheusoperator"
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/build/examples/" "${KUBEVIRT_DIR}/examples"
if [ "$SYNC_VENDOR" = "true" ]; then
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/vendor" "${VENDOR_DIR}/"
fi
# Copy the build output out of the container, make sure that _out exactly matches the build result
if [ "$SYNC_OUT" = "true" ]; then
_rsync --delete "rsync://root@127.0.0.1:${RSYNCD_PORT}/out" ${OUT_DIR}
fi