flatcar-scripts/run_sdk_container
Krzesimir Nowak 5d11f43472 run_sdk_container: Fix some shellcheck issues
Signed-off-by: Krzesimir Nowak <knowak@microsoft.com>
2025-08-29 12:39:02 +02:00

270 lines
9.4 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2021 The Flatcar Maintainers.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -euo pipefail
cd "$(dirname "$0")"
source sdk_lib/sdk_container_common.sh
arch="all"
name=""
os_version=$(get_git_version)
sdk_version=$(get_sdk_version_from_versionfile)
custom_image=""
tty=()
remove=""
cleanup=""
mounts=()
git_repos=()
usage() {
echo " Usage:"
echo " $0 [-t] [-v <version>] [-V <SDK version>] [-a <amd64|arm64|all>] [-n <name> ] [-x <script>] [-C <custom-container>] [--rm] [-U] [-m <src>:<dest>] [-g <name>:<src>:<dest>] [--] [<container-command>]"
echo " Start an SDK container of a given SDK release version."
echo " This will create the container if it does not exist, otherwise start the existing container."
echo " If the container is already running then it will exec into the container."
echo
echo " <container-command> - Command to be run in the container instead of"
echo " an interactive shell."
echo " -t Attach docker to a TTY (docker -t)."
echo " -v <version> - Sourcetree (OS image) version to use."
echo " Defaults to '$os_version' (current git commit)."
echo " FLATCAR_VERSION[_ID] in '$sdk_container_common_versionfile'"
echo " will be updated accordingly."
echo " -V <SDK version> - SDK version to use. Defaults to '${sdk_version}'"
echo " (FLATCAR_SDK_VERSION from '$sdk_container_common_versionfile')."
echo " -a <amd64|arm64|all> - Target architecture (board support) of the SDK."
echo " 'all' (the default) contains support for both amd64 and arm64."
echo " -n <name> - Custom name to use for the container."
echo " --rm Remove container afterwards."
echo " -x <script> - For each resource generated during build (container etc.)"
echo " add a cleanup line to <script> which, when run, will free"
echo " the resource. Useful for CI."
echo " -C <custom-container> - Use an entirely custom container image instead of the SDK's"
echo " $sdk_container_common_registry/flatcar-sdk-[ARCH]:[SDK VERSION]."
echo " Useful for CI."
echo " -U Do not update the versionfile. Instead, use the version from the versionfile as-is."
echo " -m <src>:<dest> - Mount local file or directory inside the container."
echo " Can be specified multiple times."
echo " -g <name:><src>:<dest> - Mount local git repository inside the container."
echo " Takes care of properly mounting and setting up "
echo " other worktrees of the git repo inside the container."
echo " Can be specified multiple times, but each with different name."
echo " <name> can't be 'scripts'"
echo " -- Stop parsing options at this point, pass the rest as the container command."
echo " -h Print this help."
echo
}
# --
update_versionfile=x
while [[ $# -gt 0 ]] ; do
case "$1" in
-h) usage; exit 0;;
--help) usage; exit 0;;
-t) tty=( -t ); shift;;
-v) os_version=$2; shift; shift;;
-V) sdk_version=$2; shift; shift;;
-a) arch=$2; shift; shift;;
-n) name=$2; shift; shift;;
--rm) remove=x; shift;;
-x) cleanup=$2; shift; shift;;
-C) custom_image=$2; shift; shift;;
-U) sdk_version=$(get_sdk_version_from_versionfile)
os_version=$(get_version_from_versionfile)
update_versionfile=
shift;;
-m) mounts+=( -v "$2" ); shift; shift;;
-g) git_repos+=( "$2" ); shift; shift;;
--) shift; break;;
-*) echo "Unknown flag ${1@Q}, use '-h' or '--help' for usage"; exit 1;;
*) break;;
esac
done
if [[ -n ${custom_image} ]] ; then
container_image_name=${custom_image}
else
docker_sdk_vernum=$(vernum_to_docker_image_version "${sdk_version}")
container_image_name="${sdk_container_common_registry}/flatcar-sdk-${arch}:${docker_sdk_vernum}"
fi
if [[ -n ${update_versionfile} ]] ; then
create_versionfile "$sdk_version" "$os_version"
fi
if [[ -z ${name} ]] ; then
docker_sdk_vernum=$(vernum_to_docker_image_version "${sdk_version}")
docker_os_vernum=$(vernum_to_docker_image_version "${os_version}")
name="flatcar-sdk-${arch}-${docker_sdk_vernum}_os-${docker_os_vernum}"
fi
filter="^/"
if "${is_podman}"; then
filter=""
fi
stat=$(call_docker ps --all --no-trunc --filter name="${filter}${name}\$" --format '{{.Status}}' \
| cut -f1 -d' ')
# pass SDK related environment variables and gcloud auth
# into container
setup_sdk_env
setup_gsutil
mkdir -p "__build__/images"
mkdir -p "sdk_container/.cache/sdks"
hostname=${name:0:63}
hostname=${hostname//./_}
if [[ -n ${cleanup} ]] ; then
echo "${docker_a[*]@Q} container rm -f ${name@Q}" >>"${cleanup}"
fi
function prev_trap_cmd {
local sig=${1}; shift
local cmd
cmd=$(trap -p "${sig}")
if [[ -z ${cmd} ]]; then
echo ':'
fi
cmd=${cmd#'trap -- '}
cmd=${cmd%" ${sig}"}
# This unquotes the trap cmd. So the following:
#
# 'echo '\''foo'\'''
#
# becomes:
#
# echo 'foo'
xargs <<<"${cmd}"
}
function add_trap {
local cmd sig
cmd=${1}; shift
sig=${1}; shift
local full_cmd
full_cmd="$(prev_trap_cmd "${sig}"); ${cmd}"
# shellcheck disable=SC2064 # we want to expand full_cmd right now, not at trap time
trap "${full_cmd}" "${sig}"
}
if [[ -z ${stat} ]] ; then
yell "Creating a new container '$name'"
gpg_volumes=()
gnupg_ssh_gcloud_mount_opts gpg_volumes
if [[ -z ${custom_image} ]]; then
(
source ci-automation/ci_automation_common.sh
docker_image_from_registry_or_buildcache "flatcar-sdk-${arch}" "${docker_sdk_vernum}"
)
else
# We could split the container_image_name in parts to call docker_image_from_registry_or_buildcache
# bur for now just try to ensure that we use the latest image if using a container registry,
# for the tar-ball-imported images we rely on the ci-automation scripts to call
# docker_image_from_registry_or_buildcache explicitly.
call_docker pull "${container_image_name}" || true
fi
source sdk_lib/git_worktree_handling.sh
declare -A linked_repos repo_overrides linked_repos_sdk
declare -a repo_mounts=() fields
for git_repo in "scripts:${PWD}:/mnt/host/source/src/scripts" "${git_repos[@]}"; do
mapfile -t fields <<<"${git_repo//:/$'\n'}"
if [[ ${#fields[@]} -ne 3 ]]; then
echo "invalid -g parameter, should have 3 fields, has ${#fields[@]}: ${git_repo}" >&2
exit 1
fi
main_name=${fields[0]}
path=${fields[1]}
sdk_path=${fields[2]}
main_repo=''
linked_repos=()
discover_repo_layout "${path}" main_repo linked_repos
if [[ ${#linked_repos[@]} -eq 0 ]]; then
repo_mounts+=( -v "${path}:${sdk_path}" )
continue
fi
this_name=''
linked_repo_name "${path}" "${main_repo}" linked_repos this_name
if [[ -z ${this_name} ]]; then
continue;
fi
base_directory="/mnt/host/all-worktrees/${main_name}"
repo_overrides=(["${this_name}"]="${sdk_path}")
main_repo_sdk=''
linked_repos_sdk=()
new_repo_mounts=()
repo_layout_inside_sdk \
"${base_directory}" \
repo_overrides \
main_repo_sdk \
linked_repos_sdk \
"${!linked_repos[@]}"
repo_layouts_to_docker_volumes \
"${main_repo}" \
"${main_repo_sdk}" \
linked_repos \
linked_repos_sdk \
new_repo_mounts
repo_mounts+=( "${new_repo_mounts[@]}" )
# sdk_entry will read this directory and remove it afterwards
mkdir -p .replacements
replacements_file=$(mktemp --tmpdir=.replacements replacements-XXXXXXXXXX)
repo_layout_to_replacements \
"${main_repo_sdk}" \
linked_repos_sdk \
"${replacements_file}"
done
docker_flags=(
"${tty[@]}"
-i
--mount type=tmpfs,destination=/tmp
-v /dev:/dev
-v "${PWD}/sdk_container:/mnt/host/source/"
-v "${PWD}/__build__/images:/mnt/host/source/src/build"
"${repo_mounts[@]}"
"${gpg_volumes[@]}"
"${mounts[@]}"
--privileged
--network host
-e SDK_USER_ID="$(id -u)"
-e SDK_GROUP_ID="$(id -g)"
--name="${name}"
--hostname="${hostname}"
--entrypoint /bin/bash
"${container_image_name}"
-l
)
call_docker create "${docker_flags[@]}"
fi
if [[ ${stat} != "Up" ]] ; then
yell "Starting stopped container '$name'"
add_trap "call_docker stop -t 0 ${name@Q}" EXIT
if [[ -n ${remove} ]]; then
add_trap "call_docker rm -f ${name@Q}" EXIT
fi
call_docker start "${name}"
fi
# Workaround: The SDK expects to be able to write to /etc/hosts
call_docker exec "${name}" sh -c 'cp /etc/hosts /etc/hosts2; umount /etc/hosts ; mv /etc/hosts2 /etc/hosts'
call_docker exec "${tty[@]}" -i "${name}" /mnt/host/source/src/scripts/sdk_lib/sdk_entry.sh "$@"