sdk-container: add scripts for containerised SDK

This change introduces a containerised SDK as a replacement for cork SDK
operations. It also simplifies versioning by removing the need for
manifest repos as well as usage of the "repo" tool by use of git
submodules for coreos-overlay and portage-stable.

The following feature scripts are added:
- run_sdk_container: Run a command in an SDK container, using the
        current scripts repo + ebuild submodules.
        current scripts repo + ebuild submodules.
- bootstrap_sdk_container / build_sdk_container_image: Bootstrap a new
        SDK and create an SDK container from the resulting SDK tarball.

The following additions have been made to SDK scripts:
- setup_board: add --pkgdir parameter to use a custom binary packge
  directory.

Signed-off-by: Thilo Fromm <thilo@kinvolk.io>
This commit is contained in:
Thilo Fromm 2021-10-12 11:03:44 +02:00 committed by flatcar-ci
parent 7a0c0028b5
commit b567344234
19 changed files with 992 additions and 1 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
__build__
sdk_container/.cache

13
.gitignore vendored
View File

@ -8,3 +8,16 @@
*.pyc *.pyc
*~ *~
/cbuildbot_package.list /cbuildbot_package.list
# Flatcar SDK tarballs
*.tar.bz2
# SDK container env passing helpers
sdk_container/.env
sdk_container/.sdkenv
# build cache / artefacts directories
__build__/
sdk_container/.cache
sdk_container/.config
sdk_container/.lock

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "sdk_container/src/third_party/coreos-overlay"]
path = sdk_container/src/third_party/coreos-overlay
url = https://github.com/flatcar-linux/coreos-overlay.git
[submodule "sdk_container/src/third_party/portage-stable"]
path = sdk_container/src/third_party/portage-stable
url = https://github.com/flatcar-linux/portage-stable.git

View File

@ -2,4 +2,93 @@
Welcome to the scripts repo, your starting place for most things here in the Flatcar Container Linux SDK. To get started you can find our documentation on [the Flatcar docs website][flatcar-docs]. Welcome to the scripts repo, your starting place for most things here in the Flatcar Container Linux SDK. To get started you can find our documentation on [the Flatcar docs website][flatcar-docs].
The SDK can be used to
* patch or update applications or libraries included in the Flatcar OS image
* add or remove applications and / or libraries
* Modify the kernel configuration and add or remove kernel modules included with Flatcar
* Build OS images for a variety of targets (qemu, bare metal, AWS, Azure, VMWare, etc.)
* And lastly, the SDK can be used to upgrade SDK packages and to build new SDKs
[flatcar-docs]: https://docs.flatcar-linux.org/os/sdk-modifying-flatcar/ [flatcar-docs]: https://docs.flatcar-linux.org/os/sdk-modifying-flatcar/
# Using the SDK container
We provide a containerised SDK via https://github.com/orgs/flatcar-linux/packages. The container comes in 3 flavours:
* Full SDK initialised with both architectures supported by Flatcar (amd64 and arm64). This is the largest container, it's about 7GB in size.
* AMD64 SDK initialised for building AMD64 OS images. About 5.5GB in size.
* ARM64 SDK initialised for building ARM64 OS images on AMD64 hosts. Also about 5.5GB in size. (While work on a ARM64 native SDK is ongoing, it's unfortunately not ready yet).
The container can be run in one of two ways - "standalone", or integrated with the Scripts repo.
Standalone mode will use no host volumes and will allow you to play with the SDK in a sandboxed throw-away environment. In standalone mode, you interface with Docker directly to use the SDK container.
Integrated mode will closely integrate with the Scripts directory and bind-mount it as well as the portage-stable and coreos-overlay gitmodules into the container. Integrated mode uses wrapper scripts to interact with the SDK container.
## Standalone mode
In standalone mode, the SDK is just another Docker container. Interaction with the container happens via use of `docker` directly. Use for experimenting and for throw-away work only, otherwise please use ingetrated mode (see below).
* Check the list of available versions and pick a version to use. The SDK Major versions correspond to Flatcar Major release versions.
List of images: `https://github.com/orgs/flatcar-linux/packages/container/package/flatcar-sdk-all`
For the purpose of this example we'll use version `3005.0.0`.
* Fetch the container image: `docker pull ghcr.io/flatcar-linux/flatcar-sdk-all:3005.0.0`
* Start the image in interactive (tty) mode: `docker run -ti ghcr.io/flatcar-linux/flatcar-sdk-all:3005.0.0`
You are now inside the SDK container:
`sdk@f236fda982a4 ~/trunk/src/scripts $`
* Initialise the SDK in self-contained mode. This needs to be done once per container and will check out the scripts, coreos-overlay, and portage-stable repositories into the container.
`sdk@f236fda982a4 ../sdk_init_selfcontained.sh`
You can now work with the SDK container.
### Privileged mode when building images
In order to build OS images (via `./build_image` and `./image_to_vm`) the SDK tooling requires privileged access to `/dev`.
This is necessary because the SDK currently employs loop devices to create and to partition OS images.
To start a container in privileged mode with `/dev` available use:
* `docker run -ti --privileged -v /dev:/dev ghcr.io/flatcar-linux/flatcar-sdk-all:3005.0.0`
## Integrated mode
This is the preferred mode of working with the SDK.
Interaction with the container happnes via wrapper scripts from the Scripts repository.
Both the host's scripts repo as well as its submodules (portage-stable and coreos-overlay) are made available in the container, allowing for work on these repos directly.
The wrapper scripts will re-use existing containers instead of creating new ones to preserve your work in the container, enabling consistency.
To clone the scripts repo and pick a version:
* Clone the scripts repo: `git clone https://github.com/flatcar-linux/scripts.git`
* Optionally, check out a release tag to base your work on
* list releases (e.g. all Alpha releases): `git tag -l alpha-*`
* check out the release version, e.g. `3005.0.0`: `git checkout 3005.0.0`
* Update the overlay submodules: `git submodules update`
To use the SDK container:
* Fetch image and start the SDK container: `./run_sdk_container -t`
This will fetch the container image of the "scripts" repo's release version you checked out.
The `-t` command line flag will allocate a TTY, which is preferred for interactive use.
The command will put you into the SDK container:
`sdk@sdk-container ~/trunk/src/scripts $`
* Alternatively, you can run individual commands in the SDK container using `./run_sdk_container <command>` (e.g. `./run_sdk_container ./build_packages`).
Subsequent calls to `./run_sdk_container` will re-use the container (as long as the local release version check-out the scripts repo does not change).
Check out `docker container ls --all` and you'll see something like
```
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
19ea3b6d00ad ghcr.io/flatcar-linux/flatcar-sdk-all:3005.0.0 "/bin/sh -c /home/sd…" 4 hours ago Exited (0) About an hour ago flatcar-sdk-all-3005.0.0_os-3005.0.0
```
Re-use of containers happens on a per-name basis. The above example's container name `flatcar-sdk-all-3005.0.0_os-3005.0.0` is generated automatically. Using `docker container rm` the container can be discarded - a subsequent call to `./run_sdk_container` will create a new one. Custom containers can be created by use of the `-n <name>` command line option; these will be re-used in subsequent calls to `./run_sdk_container` when using the same `<name>`.
The local sourcetree can also be used with an entirely custom SDK container image. Users must ensure that the image is either fetch-able or present locally. The custom image can be specified using `-C <custom-image>`. This option is useful e.g. for building the local sourcetree with different SDK versions.
Check out `./run_sdk_container -h` for more information on command line options.
# Building a new SDK container
Building an SDK container is done using `./build_sdk_container_image`.
The SDK container is based on an SDK tarball which the script will fetch.
By default, the current git tree's release version will be built; this can be changed with the `-v` flag.
When using `-v`, the corresponding release version of the Scripts repository is checked out (unless suppressed by `-c`) before the container is generated.
# Bootstrapping a new SDK tarball using the SDK container
THe script `./bootstrap_sdk_container` bootstraps a new SDK tarball using an existing SDK container and seed tarball. Specifying the seed version is required for this script.

76
bootstrap_sdk_container Executable file
View File

@ -0,0 +1,76 @@
#!/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 -eu
cd $(dirname "$0")
source sdk_lib/sdk_container_common.sh
seed_version=""
target_version=""
vernum="$(strip_version_prefix "$target_version")"
if is_official "$vernum" ; then
official="true"
else
official="false"
fi
cleanup=""
# --
usage() {
echo " Usage:"
echo " $0 <seed-sdk-version> <new-sdk-version> [-x <cleanup-script>]"
echo
echo " This script will bootstrap a new SDK tarball using an SDK container."
echo " '$sdk_container_common_versionfile' will be updated to the target version."
echo
echo " <seed-sdk-vernum> - SDK version number (e.g. '3005.0.0') to use for bootstrapping."
echo " The SDK container will be pulled and the tarball"
echo " downloaded if necessary."
echo " <new-sdk-vernum> - SDK version number (e.g. '3027.0.0') of the new SDK."
echo " -x <cleanup-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 " -h Print this help."
echo
}
# --
while [ 0 -lt $# ] ; do
case "$1" in
-h) usage; exit 0;;
-x) cleanup="-x $2"; shift; shift;;
*) if [ -z "$seed_version" ] ; then
seed_version="$1"
elif [ -z "$target_version" ] ; then
target_version="$1"
else
echo "ERROR: Spurious positional parameter '$1'"
usage; exit 1;
fi
shift;;
esac
done
if [ -z "$seed_version" -o -z "$target_version" ] ; then
echo "ERROR: Missing seed and /or target SDK version."
usage
exit 1
fi
# --
yell "\n######\n###### Bootstrapping SDK version $target_version from seed ($seed_version)"
if $official; then
export COREOS_OFFICIAL=1
fi
# bootstrap_sdk needs FLATCAR_SDK_VERSION set to the seed version
./run_sdk_container $cleanup -V "$seed_version" -v "$target_version" \
sudo -E ./bootstrap_sdk
# Update versionfile to the actual SDK version
create_versionfile "${target_version}"

245
build_sdk_container_image Executable file
View File

@ -0,0 +1,245 @@
#!/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.
# This script will generate an SDK container image from an SDK tarball
# (which in turn is generated by bootstrap_sdk[_container]).
#
# It uses a number of intermediate build steps:
# 1. Import the SDK tarball into a "tarball" container image.
# 2. Build a "plain" SDK container image which creates the "sdk" user
# and runs "update_chroot" to initialise the x86 and aarch64 SDK cross env.
# This step uses sdk_lib/Dockerfile.sdk-import.
# 3. Using the "plain" SDK image, start a temporary "toolchain" container
# to build toolchain binary packages.
# 4. Inheriting from the "plain" SDK image and using the toolchain packages,
# build a "full" SDK container image, with board support for both amd64-usr and arm64-usr.
# A temporary HTTP server on the Docker interface IP is spun up in this step
# to serve the toolchain binpkgs to the build container.
# This step uses sdk_lib/Dockerfile.sdk-build.
# 5. In a last step, all unnecessary binaries are removed from the "full" image and 3
# output SDK images are produced:
# - "all", with both amd64 and arm64 target support, and
# - "amd64" and "arm64, with only amd64 or arm64 target support respectively.
# This step uses sdk_lib/Dockerfile.lean-arch.
set -eu
cd $(dirname "$0")
source sdk_lib/sdk_container_common.sh
arch="amd64"
official="0"
tarball=""
os_version=""
keep="false"
cleanup=""
usage() {
echo " $0 - Create SDK container image from an SDK tarball"
echo " This script will set up a new SDK container from a tarball."
echo " The resulting container comes in 3 flavours:"
echo " 1. flatcar-sdk-all - includes both ARM64 and AMD64 support"
echo " 2.+3. flatcar-sdk-(amd64|arm64) - only includes suport for one target."
echo " Usage:"
echo " $0 <tarball>] [-k] [-v <os-version>] [-x <script>]"
echo
echo " <tarball> - Local tarball to build SDK from."
echo " The tarball must follow the format"
echo " flatcar-sdk-(amd64|arm64)-<version>.tar.bz2."
echo " -v <version> - Use custom OS version (defaults to tarball's SDK version)."
echo " -k - Keep intermediate build containers (sdk-import / sdk-tarball)."
echo " (Useful for sdk container build script development.)"
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 " -h - Print this help."
echo
}
# --
while [ 0 -lt $# ] ; do
case "$1" in
-h) usage; exit 0;;
-k) keep="true"; shift;;
-v) os_version="$2"; shift; shift;;
-x) cleanup="$2"; shift; shift;;
*) if [ -z "$tarball" ] ; then
tarball="$1"; shift
else
echo "ERROR: spurious positional parameter '$@'."
usage
exit 1
fi;;
esac
done
if [ -z "$tarball" -o ! -f "$tarball" ] ; then
echo "ERROR: missing / invalid SDK tarball argument"
exit 1
fi
# --
# Grok version / arch from tarball name, set official if version is a release version
version="$(echo "$tarball" | sed -n 's/.*flatcar-sdk-\(arm64\|amd64\)-\(.\+\)\.tar\.bz2/\2/p')"
arch="$(echo "$tarball" | sed -n 's/.*flatcar-sdk-\(arm64\|amd64\)-.*\.tar\.bz2/\1/p')"
if [ -z "$version" -o -z "$arch" ]; then
echo "ERROR: Unable to determine version / arch from '$tarball'"
exit 1
fi
if [ -z "${os_version}" ] ; then
os_version="${version}"
fi
if is_official "$version" && [ "${version}" = "${os_version}" ] ; then
official="1"
else
official="0"
fi
# --
# import tarball
#
yell "\n######\n###### Building SDK container for version $version from '$tarball'"
create_versionfile "$version" "${os_version}"
docker_vernum="$(vernum_to_docker_image_version "${version}")"
import_tarball="flatcar-sdk-tarball:${docker_vernum}"
image_present="$(docker image ls "$import_tarball" --format '{{.Repository}}:{{.Tag}}')"
if [ "${image_present}" = "${import_tarball}" ] ; then
yell "Using existing SDK tarball image '${import_tarball}'"
else
yell "Importing SDK tarball"
if [ -n "$cleanup" ] ; then
echo "docker image rm -f '${import_tarball}'" >> "$cleanup"
fi
docker import "${tarball}" "${import_tarball}"
fi
# --
# build plain SDK container w/o board support
#
import_image="flatcar-sdk-import:${docker_vernum}"
image_present="$(docker image ls "${import_image}" --format '{{.Repository}}:{{.Tag}}')"
if [ "$image_present" = "${import_image}" ] ; then
yell "Using existing SDK import image '${import_image}'"
else
yell "Building plain SDK import image"
if [ -n "$cleanup" ] ; then
echo "docker image rm -f '${import_image}'" >> "$cleanup"
fi
docker build -t "$import_image" \
--build-arg VERSION="${docker_vernum}" \
-f sdk_lib/Dockerfile.sdk-import \
.
fi
# --
# build full SDK container w/ board support.
# This uses the SDK import container to first build toolchain binpkgs.
# Then, the import container and toolchain packages are used
# to build a full SDK container w/ amd64 and arm64 board support.
#
sdk_build_image="flatcar-sdk-build:${docker_vernum}"
image_present="$(docker image ls "${sdk_build_image}" --format '{{.Repository}}:{{.Tag}}')"
if [ "$image_present" = "${sdk_build_image}" ] ; then
yell "Using existing SDK build image '${sdk_build_image}'"
else
# --- Toolchains build ---
yell "Building toolchains in a temporary container."
# We need to use run_sdk_container instead of building from a Dockerfile
# since toolchains build uses catalyst which requires privileged access.
tarball_copied=""
if [ "$(basename "${tarball}")" != "${tarball}" ] ; then
cp "${tarball}" ./
tarball="$(basename "${tarball}")"
tarball_copied="${tarball}"
fi
toolchains_container="flatcar-sdk-toolchains-build-${docker_vernum}"
if [ -n "$cleanup" ] ; then
echo "docker container rm -f '${toolchains_container}'" >> "$cleanup"
fi
./run_sdk_container -C "${import_image}" -n "${toolchains_container}" \
sudo ./build_toolchains --seed_tarball="./${tarball}"
# remove sdk tarball from scripts root so it's not part of the SDK container build context
if [ -f "${tarball_copied}" ] ; then
rm "${tarball_copied}"
fi
docker container rm "${toolchains_container}"
host_ip="$(ip addr show docker0 | grep -Po 'inet \K[\d.]+')"
binhost_port="$((1000 + (RANDOM % 55000) ))"
binhost="${host_ip}:${binhost_port}"
binhost_container="${toolchains_container}-binhost-${binhost_port}"
yell "Building SDK container + board support, toolchain packages served at http://${binhost} by ${binhost_container}"
# Spin up temporary toolchains package binhost
if [ -n "$cleanup" ] ; then
echo "docker container rm -f '${binhost_container}'" >> "$cleanup"
fi
docker run --rm -d -p "${binhost}":80 \
--name ${binhost_container} \
-v "$(pwd)/__build__/images/catalyst/packages/coreos-toolchains/target":/usr/share/caddy \
caddy caddy file-server \
--root /usr/share/caddy --browse
# --- Full SDK container build ---
yell "Initialising the SDK container and building board packages"
if [ -n "$cleanup" ] ; then
echo "docker image rm -f '${sdk_build_image}'" >> "$cleanup"
fi
docker build -t "${sdk_build_image}" \
--build-arg VERSION="${docker_vernum}" \
--build-arg BINHOST="http://${binhost}" \
--build-arg OFFICIAL="${official}" \
-f sdk_lib/Dockerfile.sdk-build \
.
docker stop "${binhost_container}"
fi
# --
# Derive "lean" SDK containers from full build. Main purpose
# of this step is to remove "white-outs", i.e. files which have been
# deleted in the full image but are still present in an intermediate layer.
#
for a in all arm64 amd64; do
yell "Creating '$a' arch SDK image"
rmarch=""; rmcross=""
case $a in
arm64) rmarch="amd64-usr"; rmcross="x86_64-cros-linux-gnu";;
amd64) rmarch="arm64-usr"; rmcross="aarch64-cros-linux-gnu";;
esac
docker build -t "$sdk_container_common_registry/flatcar-sdk-${a}:${docker_vernum}" \
--build-arg VERSION="${docker_vernum}" \
--build-arg RMARCH="${rmarch}" \
--build-arg RMCROSS="${rmcross}" \
-f sdk_lib/Dockerfile.lean-arch \
.
done
# --
# Cleanup
#
if ! $keep; then
yell "Cleaning up intermediate containers"
docker rmi flatcar-sdk-build:"${docker_vernum}"
docker rmi flatcar-sdk-import:"${docker_vernum}"
docker rmi flatcar-sdk-tarball:"${docker_vernum}"
fi

125
run_sdk_container Executable file
View File

@ -0,0 +1,125 @@
#!/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 -eu
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=""
cleanup=""
usage() {
echo " Usage:"
echo " $0 [-t] [-v <version>] [-V sdk version] [-a arch] [-n <name> ] [-x <script>] [-C custom-container] [-F] [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 (also see -F)."
echo " -V <SDK ver> - 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 " -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 - 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 " -h Print this help."
echo
}
# --
while [ 0 -lt $# ] ; do
case "$1" in
-h) 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;;
-x) cleanup="$2"; shift; shift;;
-C) custom_image="$2"; shift; shift;;
*) 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
create_versionfile "$sdk_version" "$os_version"
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
stat="$(docker ps --all --no-trunc --filter name="$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 container rm -f '${name}'" >> "$cleanup"
fi
if [ -z "$stat" ] ; then
yell "Creating a new container '$name'"
gpg_volumes=$(gnupg_ssh_gcloud_mount_opts)
docker create $tty -i \
-v /dev:/dev \
-v "$(pwd)/sdk_container:/mnt/host/source/" \
-v "$(pwd)/__build__/images:/mnt/host/source/src/build" \
-v "$(pwd):/mnt/host/source/src/scripts" \
$gpg_volumes \
--privileged \
--network host \
-e SDK_USER_ID="$(id -u)" \
-e SDK_GROUP_ID="$(id -g)" \
--name="$name" \
--hostname="$hostname" \
"${container_image_name}"
fi
if [ "$stat" != "Up" ] ; then
yell "Starting stopped container '$name'"
trap "docker stop $name" EXIT
docker start "$name"
fi
docker exec $tty -i "$name" /home/sdk/sdk_entry.sh "$@"

View File

@ -0,0 +1,6 @@
NAME="Flatcar Container Linux by Kinvolk"
ID=flatcar
ID_LIKE=coreos
ANSI_COLOR="38;5;75"
HOME_URL="https://flatcar-linux.org/"
BUG_REPORT_URL="https://issues.flatcar-linux.org"

View File

@ -0,0 +1,4 @@
FLATCAR_VERSION=3033.0.0
FLATCAR_VERSION_ID=3033.0.0
FLATCAR_BUILD_ID=""
FLATCAR_SDK_VERSION=3033.0.0

@ -0,0 +1 @@
Subproject commit 2bfaded1b177b29d56ffea2675cc85ede709da78

@ -0,0 +1 @@
Subproject commit 62c29140f521718e29831eb195dcb1f1924c2769

8
sdk_lib/90_env_keep Normal file
View File

@ -0,0 +1,8 @@
Defaults env_keep += "FLATCAR_BUILD_ID COREOS_OFFICIAL \
EMAIL GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME \
GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME \
GIT_PROXY_COMMAND GIT_SSH RSYNC_PROXY \
GNUPGHOME GPG_AGENT_INFO SSH_AUTH_SOCK \
BOTO_PATH GOOGLE_APPLICATION_CREDENTIALS \
USE FEATURES PORTAGE_USERNAME FORCE_STAGES \
all_proxy ftp_proxy http_proxy https_proxy no_proxy"

View File

@ -0,0 +1,29 @@
ARG VERSION
FROM flatcar-sdk-build:${VERSION} as meta
ARG RMARCH
ARG RMCROSS
RUN if [ -n "$RMCROSS" ]; then \
sudo crossdev --clean --force "$RMCROSS"; \
fi
RUN if [ -n "$RMARCH" ]; then \
sudo rm -rf /build/$RMARCH; \
sudo rm -f /usr/local/bin/*-$RMARCH; \
fi
# Note: .repo/manifests/version.txt will survive this. That's intended.
RUN sudo rm -rf /mnt/host/source/*
FROM scratch
COPY --from=meta / /
COPY --from=meta --chown=sdk:sdk /home/sdk /home/sdk
RUN chown -R sdk:sdk /mnt/host/source
# This is not used when starting the container via ./run_sdk_container
# but it's useful fir standalone container use.
RUN mkdir -p /mnt/host/source/src/scripts
COPY --chown=sdk:sdk sdk_lib/sdk_init_selfcontained.sh /mnt/host/source/src/
ENTRYPOINT /home/sdk/sdk_entry.sh

View File

@ -0,0 +1,17 @@
ARG VERSION
FROM flatcar-sdk-import:${VERSION}
ARG BINHOST
ARG OFFICIAL=0
# mark build as official where appropriate
RUN echo "export COREOS_OFFICIAL=$OFFICIAL" > /mnt/host/source/.env
RUN /home/sdk/sdk_entry.sh ./setup_board --board="arm64-usr" --binhost="${BINHOST}/arm64-usr"
RUN /home/sdk/sdk_entry.sh ./setup_board --board="arm64-usr" --regen_configs
RUN /home/sdk/sdk_entry.sh ./setup_board --board="amd64-usr" --binhost="${BINHOST}/amd64-usr"
RUN /home/sdk/sdk_entry.sh ./setup_board --board="amd64-usr" --regen_configs
RUN rm /mnt/host/source/.env
RUN rm -rf /home/sdk/toolchain-pkgs

View File

@ -0,0 +1,52 @@
ARG VERSION
FROM flatcar-sdk-tarball:${VERSION}
RUN touch /etc/debian_chroot
RUN chmod 644 /etc/passwd
RUN chmod 644 /etc/group
RUN if ! grep -q portage /etc/group ; then \
echo "portage::250:portage" >>/etc/group; \
fi
RUN if ! grep -q portage /etc/passwd; then \
echo "portage:x:250:250:portage:/var/tmp/portage:/bin/false" >>/etc/passwd; \
fi
# fix "Unable to unshare: EPERM ..." in containers
# (see https://github.com/gentoo/gentoo-docker-images/issues/81)
RUN echo 'export FEATURES="-ipc-sandbox -network-sandbox -pid-sandbox"' \
>> /etc/skel/.bashrc
RUN groupadd sdk
RUN useradd -g sdk -G portage sdk
RUN echo "sdk ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/sdk-user
RUN rm -rf /mnt/host/source
COPY --chown=sdk:sdk sdk_container/ /mnt/host/source
COPY --chown=sdk:sdk . /mnt/host/source/src/scripts
RUN chown sdk:sdk /mnt/host/source
COPY sdk_lib/90_env_keep /etc/sudoers.d/90_env_keep
RUN chmod 0440 /etc/sudoers.d/90_env_keep
USER sdk:sdk
RUN mkdir -p /mnt/host/source/src/scripts /mnt/host/source/src/build
RUN ln -s /mnt/host/source /home/sdk/trunk
RUN rm /home/sdk/.bashrc
RUN cp /etc/skel/.bashrc /home/sdk
RUN echo "cd /home/sdk/trunk/src/scripts" >> /home/sdk/.bashrc
RUN echo 'export PATH="$PATH:/usr/local/bin:/usr/local/sbin"' >> /home/sdk/.bashrc
# user and SDK environment variables pass-through into container
RUN echo "if [ -f /mnt/host/source/.env ]; then source /mnt/host/source/.env; fi" >> /home/sdk/.bashrc
RUN echo "if [ -f /mnt/host/source/.sdkenv ]; then source /mnt/host/source/.sdkenv; fi" >> /home/sdk/.bashrc
COPY --chown=sdk:sdk sdk_lib/sdk_entry.sh /home/sdk
RUN chmod 755 /home/sdk/sdk_entry.sh
# This should be a NOP; if you see packages being rebuilt
# it's likely that submodules and SDK tarball are out of sync
RUN /home/sdk/sdk_entry.sh ./update_chroot --toolchain_boards="amd64-usr arm64-usr"
ENTRYPOINT /home/sdk/sdk_entry.sh

View File

@ -0,0 +1,239 @@
# 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.
#
# This file contains common functions used across SDK container scripts.
#
# globals
#
sdk_container_common_versionfile="sdk_container/.repo/manifests/version.txt"
sdk_container_common_registry="ghcr.io/flatcar-linux"
sdk_container_common_env_file="sdk_container/.sdkenv"
# Common "echo" function
function yell() {
echo -e "\n###### $@ ######"
}
# --
# Guess the SDK version from the current git commit.
#
function get_git_version() {
local tag="$(git tag --points-at HEAD)"
if [ -z "$tag" ] ; then
git describe --tags
else
echo "$tag"
fi
}
# --
function get_sdk_version_from_versionfile() {
( source "$sdk_container_common_versionfile"; echo "$FLATCAR_SDK_VERSION"; )
}
# --
# return true if a given version number is an official build
#
function is_official() {
local vernum="$1"
official="$(echo "$vernum" | sed -n 's/^[0-9]\+\.[0-9]\+\.[0-9]\+$/true/p')"
test -n "$official"
}
# --
# extract the build ID suffix from a version string ("alpha-3244.0.1-nightly2" => "nightly2")
#
function build_id_from_version() {
local version="$1"
# support vernums and versions ("alpha-"... is optional)
echo "${version}" | sed -n 's/^\([a-z]\+-\)\?[0-9.]\+[-+]\(.*\)$/\2/p'
}
# --
# extract the version number (w/o build ID) from a version string ("alpha-3244.0.1-nightly2" => "3244.0.1")
#
function vernum_from_version() {
local version="$1"
# support vernums and versions ("alpha-"... is optional)
echo "${version}" | sed -n 's/^\([a-z]\+-\)\?\([0-9.]\+\).*/\2/p'
}
# --
# Strip prefix from version string if present ("alpha-3233.0.0[-...]" => "3233.0.0[-...]")
#
function strip_version_prefix() {
local version="$1"
local build_id="$(build_id_from_version "${version}")"
local version_id="$(vernum_from_version "${version}")"
if [ -n "${build_id}" ] ; then
echo "${version_id}+${build_id}"
else
echo "${version_id}"
fi
}
# --
# Derive docker-safe image version string from vernum.
#
function vernum_to_docker_image_version() {
local vernum="$1"
echo "$vernum" | sed 's/[+]/-/g'
}
# --
# Creates the Flatcar build / SDK version file.
# Must be called from the script root.
#
# In the versionfile, FLATCAR_VERSION is the OS image version _number_ plus a build ID if this is no
# official build. The FLATCAR_VERSION_ID is the plain vernum w/o build ID - it's the same as FLATCAR_VERSION
# for official builds. The FLATCAR_BUILD_ID is the build ID suffix for non-official builds.
# Lastly, the FLATCAR_SDK_VERSION is the full version number (including build ID if no official SDK release)
# the OS image is to be built with.
#
function create_versionfile() {
local sdk_version="$1"
local os_version="${2:-$sdk_version}"
local build_id="$(build_id_from_version "${os_version}")"
local version_id="$(vernum_from_version "${os_version}")"
sdk_version="$(strip_version_prefix "${sdk_version}")"
os_version="$(strip_version_prefix "${os_version}")"
yell "Writing versionfile '$sdk_container_common_versionfile' to SDK '$sdk_version', OS '$os_version'."
cat >"$sdk_container_common_versionfile" <<EOF
FLATCAR_VERSION=${os_version}
FLATCAR_VERSION_ID=${version_id}
FLATCAR_BUILD_ID="${build_id}"
FLATCAR_SDK_VERSION=${sdk_version}
EOF
}
# --
#
# Set up SDK environment variables.
# Environment vars are put in a file that is sourced by the container's
# .bashrc (if present). GNUPGHOME and SSH_AUTH_SOCK are set
# to container-specific paths if applicable.
function setup_sdk_env() {
local var
rm -f "$sdk_container_common_env_file"
# conditionally set up gnupg, ssh socket, and gcloud auth / boto
# depending on availability on the host
GNUPGHOME="${GNUPGHOME:-$HOME/.gnupg}"
if [ -d "${GNUPGHOME}" ] ; then
echo "GNUPGHOME=\"/home/sdk/.gnupg\"" >> "$sdk_container_common_env_file"
echo "export GNUPGHOME" >> "$sdk_container_common_env_file"
export GNUPGHOME
fi
if [ -e "${SSH_AUTH_SOCK:-}" ] ; then
local sockname="$(basename "${SSH_AUTH_SOCK}")"
echo "SSH_AUTH_SOCK=\"/run/sdk/ssh/$sockname\"" >> "$sdk_container_common_env_file"
echo "export SSH_AUTH_SOCK" >> "$sdk_container_common_env_file"
fi
# keep in sync with 90_env_keep
for var in FLATCAR_BUILD_ID COREOS_OFFICIAL \
EMAIL GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME \
GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME \
GIT_PROXY_COMMAND GIT_SSH RSYNC_PROXY \
GPG_AGENT_INFO FORCE_STAGES \
all_proxy ftp_proxy http_proxy https_proxy no_proxy; do
if [ -n "${!var:-}" ] ; then
echo "${var}=\"${!var}\"" >> "$sdk_container_common_env_file"
echo "export ${var}" >> "$sdk_container_common_env_file"
fi
done
}
# --
# Set up gcloud legacy creds (via GOOGLE_APPLICATION_CREDENTIALS)
# for the SDK container.
# This will also create a boto config right next to the
# GOOGLE_APPLICATION_CREDENTIALS json file.
function setup_gsutil() {
local creds="${GOOGLE_APPLICATION_CREDENTIALS:-$HOME/.config/gcloud/application_default_credentials.json}"
if [ ! -e "$creds" ]; then
return
fi
local creds_dir="$(dirname "$creds")"
local botofile="$creds_dir/boto-flatcar-sdk"
# TODO t-lo: move generation of boto file to sdk_entry so
# it's onyl created inside the container.
# read creds file and create boto file for gsutil
local tmp="$(mktemp)"
trap "rm -f '$tmp'" EXIT
local oauth_refresh="$(jq -r '.refresh_token' "$creds")"
local client_id="$(jq -r '.client_id' "$creds")"
local client_secret="$(jq -r '.client_secret' "$creds")"
cat >>"$tmp" <<EOF
[Credentials]
gs_oauth2_refresh_token = $oauth_refresh
[OAuth2]
client_id = $client_id
client_secret = $client_secret
EOF
mv "$tmp" "$botofile"
echo "BOTO_PATH=\"$botofile\"" >> "$sdk_container_common_env_file"
echo "export BOTO_PATH" >> "$sdk_container_common_env_file"
echo "GOOGLE_APPLICATION_CREDENTIALS=\"$creds\"" >> "$sdk_container_common_env_file"
echo "export GOOGLE_APPLICATION_CREDENTIALS" >> "$sdk_container_common_env_file"
BOTO_PATH="$botofile"
GOOGLE_APPLICATION_CREDENTIALS="$creds"
export BOTO_PATH
export GOOGLE_APPLICATION_CREDENTIALS
}
# --
# Generate volume mount command line options for docker
# to pass gpg, ssh, and gcloud auth host directories
# into the SDK container.
function gnupg_ssh_gcloud_mount_opts() {
local sdk_gnupg_home="/home/sdk/.gnupg"
local gpgagent_dir="/run/user/$(id -u)/gnupg"
# pass host GPG home and Agent directories to container
if [ -d "$GNUPGHOME" ] ; then
echo "-v $GNUPGHOME:$sdk_gnupg_home"
fi
if [ -d "$gpgagent_dir" ] ; then
echo "-v $gpgagent_dir:$gpgagent_dir"
fi
if [ -e "${SSH_AUTH_SOCK:-}" ] ; then
local sshsockdir="$(dirname "$SSH_AUTH_SOCK")"
echo "-v $sshsockdir:/run/sdk/ssh"
fi
if [ -e "${GOOGLE_APPLICATION_CREDENTIALS:-}" ] ; then
local creds_dir="$(dirname "${GOOGLE_APPLICATION_CREDENTIALS}")"
if [ -d "$creds_dir" ] ; then
echo "-v $creds_dir:$creds_dir"
fi
fi
}

37
sdk_lib/sdk_entry.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
if [ -n "${SDK_USER_ID:-}" ] ; then
usermod -u $SDK_USER_ID sdk
fi
if [ -n "${SDK_GROUP_ID:-}" ] ; then
groupmod -g $SDK_GROUP_ID sdk
fi
chown -R sdk:sdk /home/sdk
# This is ugly.
# We need to sudo su - sdk -c so the SDK user gets a fresh login.
# 'sdk' is member of multiple groups, and plain docker USER only
# allows specifying membership of a single group.
# When a command is passed to the container, we run, respectively:
# sudo su - sdk -c "<command>".
# Then, we need to preserve whitespaces in arguments of commands
# passed to the container, e.g.
# ./update_chroot --toolchain_boards="amd64-usr arm64-usr".
# This is done via a separate ".cmd" file since we have used up
# our quotes for su -c "<cmd>" already.
if [ $# -gt 0 ] ; then
cmd="/home/sdk/.cmd"
echo -n "exec bash -i -c '" >"$cmd"
for arg in "$@"; do
echo -n "\"$arg\" " >>"$cmd"
done
echo "'" >>"$cmd"
chmod 755 "$cmd"
sudo su sdk -c "$cmd"
rc=$?
rm -f "$cmd"
exit $rc
else
exec sudo su sdk
fi

View File

@ -0,0 +1,38 @@
#!/bin/bash
echo "This script will initialise your Flatcar SDK container as a self-contained SDK."
echo "Please note that the preferred way of using the Flatcar SDK container is by cloning"
echo " https://github.com/flatcar-linux/scripts"
echo "and using the ./run_sdk_container script."
echo
echo "Press [RETURN] to continue, CTRL+C to abort"
echo
read junk
# --
function clone_version() {
local repo="$1"
local dest="$2"
local version="$3"
git clone https://github.com/flatcar-linux/$repo "$dest"
(
cd "$dest"
git fetch --all
local tag=$(git tag -l | grep "${version}")
git checkout "$tag"
)
}
# --
version="$(source /mnt/host/source/.repo/manifests/version.txt; echo $FLATCAR_VERSION)"
mkdir -p /home/sdk/trunk/src/third_party/
clone_version scripts /home/sdk/trunk/src/scripts "$version"
clone_version portage-stable /home/sdk/trunk/src/third_party/portage-stable "$version"
clone_version coreos-overlay /home/sdk/trunk/src/third_party/coreos-overlay "$version"

View File

@ -27,6 +27,8 @@ DEFINE_boolean getbinpkg "${FLAGS_TRUE}" \
"Download binary packages from remote repository." "Download binary packages from remote repository."
DEFINE_string getbinpkgver "" \ DEFINE_string getbinpkgver "" \
"Use binary packages from a specific version." "Use binary packages from a specific version."
DEFINE_string pkgdir "" \
"Use binary packages from a custom directory instead of /build/[ARCH]/var/lib/portage/pkgs/."
DEFINE_string binhost "" \ DEFINE_string binhost "" \
"Use binary packages from a specific location instead of $FLATCAR_DEV_BUILDS/... " "Use binary packages from a specific location instead of $FLATCAR_DEV_BUILDS/... "
DEFINE_boolean toolchainpkgonly "${FLAGS_FALSE}" \ DEFINE_boolean toolchainpkgonly "${FLAGS_FALSE}" \
@ -160,6 +162,7 @@ BOARD_ARCH=$(get_board_arch "$BOARD")
BOARD_CHOST=$(get_board_chost ${BOARD}) BOARD_CHOST=$(get_board_chost ${BOARD})
PORTAGE_PROFILE=$(get_board_profile "$BOARD") PORTAGE_PROFILE=$(get_board_profile "$BOARD")
BOARD_BINHOST="$FLAGS_binhost $(generate_binhost_list)" BOARD_BINHOST="$FLAGS_binhost $(generate_binhost_list)"
BOARD_PKGDIR="${FLAGS_pkgdir:-${BOARD_ROOT}/var/lib/portage/pkgs}"
if [[ ${FLAGS_regen_configs_only} -eq ${FLAGS_TRUE} ]]; then if [[ ${FLAGS_regen_configs_only} -eq ${FLAGS_TRUE} ]]; then
FLAGS_regen_configs=${FLAGS_TRUE} FLAGS_regen_configs=${FLAGS_TRUE}
@ -257,7 +260,7 @@ PORTAGE_USERNAME="$(portageq envvar PORTAGE_USERNAME)"
# Board specific settings # Board specific settings
CHOST="${BOARD_CHOST}" CHOST="${BOARD_CHOST}"
ROOT="${BOARD_ROOT}/" ROOT="${BOARD_ROOT}/"
PKGDIR="${BOARD_ROOT}/var/lib/portage/pkgs" PKGDIR="${BOARD_PKGDIR}"
PORT_LOGDIR="${BOARD_ROOT}/var/log/portage" PORT_LOGDIR="${BOARD_ROOT}/var/log/portage"
PORTAGE_TMPDIR="${BOARD_ROOT}/var/tmp" PORTAGE_TMPDIR="${BOARD_ROOT}/var/tmp"
PORTAGE_BINHOST="${BOARD_BINHOST}" PORTAGE_BINHOST="${BOARD_BINHOST}"