root/build-tools/build-docker-images/build-stx-base.sh
Scott Little a4174a1e0a Remove CentOS/OpenSUSE build support
StarlingX stopped supporting CentOS builds in the after release 7.0.
This update will strip CentOS from our code base.  It will also
remove references to the failed OpenSUSE feature as well.

There is still one CentOS based docker image (n3000), so
this update will leave limited CentOS support in download
and docker image building tools.

Verified with a full Jenkins master branch build for Debian.
- download full and incremental
- package build full and incremental
- iso build
- build of base container image
- build all flock container images
- helm chart build.

Story: 2011110
Task: 49939
Change-Id: I57939d2026d7df76091e8658750b4bd0fa8e4f5f
Signed-off-by: Scott Little <scott.little@windriver.com>
2024-08-06 13:43:50 +00:00

454 lines
13 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2018-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# This utility builds the StarlingX base image
#
MY_SCRIPT_DIR=$(dirname $(readlink -f $0))
source ${MY_SCRIPT_DIR}/../utils.sh
source ${MY_SCRIPT_DIR}/../git-utils.sh
# Required env vars
if [ -z "${MY_WORKSPACE}" -o -z "${MY_REPO}" ]; then
echo "Environment not setup for builds" >&2
exit 1
fi
SUPPORTED_OS_ARGS=( 'debian' )
OS= # default: autodetect
OS_VERSION= # default: lookup "ARG RELEASE" in Dockerfile
BUILD_STREAM=stable
IMAGE_VERSION=
PUSH=no
PROXY=""
CONFIG_FILE=""
DEFAULT_CONFIG_FILE_DIR="${MY_REPO}/build-tools/build-docker-images"
DEFAULT_CONFIG_FILE_PREFIX="base-image-build"
DOCKER_USER=${USER}
DOCKER_REGISTRY=
declare -a REPO_LIST
REPO_OPTS=
LOCAL=no
CLEAN=no
TAG_LATEST=no
LATEST_TAG=latest
HOST=${HOSTNAME}
USE_DOCKER_CACHE=no
declare -i MAX_ATTEMPTS=1
declare -i RETRY_DELAY=30
function usage {
cat >&2 <<EOF
Usage:
$(basename $0)
Options:
--os: Specify base OS (valid options: ${SUPPORTED_OS_ARGS[@]})
--os-version: Specify OS version
--version: Specify version for output image
--stream: Build stream, stable or dev (default: stable)
--repo: Software repository, can be specified multiple times
* Debian format: "TYPE [OPTION=VALUE...] URL DISTRO COMPONENTS..."
This will be added to /etc/apt/sources.list as is,
see also sources.list(5) manpage.
--local: Use local build for software repository (cannot be used with --repo)
--push: Push to docker repo
--proxy: Set proxy <URL>:<PORT>
--latest: Add a 'latest' tag when pushing
--latest-tag: Use the provided tag when pushing latest.
--user: Docker repo userid
--registry: Docker registry
--clean: Remove image(s) from local registry
--hostname: build repo host
--attempts <count>
Max attempts, in case of failure (default: 1)
--retry-delay <seconds>
Sleep this many seconds between retries (default: 30)
--config-file:Specify a path to a config file which will specify additional arguments to be passed into the command
--cache: Allow docker to use cached filesystem layers when building
CAUTION: this option may ignore locally-generated packages
and is meant for debugging the build scripts.
EOF
}
function get_args_from_file {
# get additional args from specified file.
local line key value
echo "Get args from file: $1"
while read line
do
# skip comments & empty lines
if echo "$line" | grep -q -E '^\s*(#.*)?$' ; then
continue
fi
key="${line%%=*}"
value=${line#*=}
echo "--$key '$value'"
case "$key" in
version)
if [ -z "${IMAGE_VERSION}" ]; then
IMAGE_VERSION="$value"
fi
;;
user)
if [ -z "${DOCKER_USER}" ]; then
DOCKER_USER="$value"
fi
;;
proxy)
if [ -z "${PROXY}" ]; then
PROXY="$value"
fi
;;
registry)
if [ -z "${DOCKER_REGISTRY}" ]; then
# Add a trailing / if needed
DOCKER_REGISTRY="${value%/}/"
fi
;;
repo)
REPO_LIST+=("$value")
;;
*)
echo "WARNING: $line: ignoring unknown option \"$key\"" >&2
;;
esac
done <"$1"
}
OPTS=$(getopt -o h -l help,os:,os-version:,version:,stream:,release:,repo:,push,proxy:,latest,latest-tag:,user:,registry:,local,clean,cache,hostname:,attempts:,retry-delay:,config-file: -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
eval set -- "${OPTS}"
while true; do
case $1 in
--)
# End of getopt arguments
shift
break
;;
--os)
OS=$2
shift 2
;;
--os-version)
OS_VERSION=$2
shift 2
;;
--version)
IMAGE_VERSION=$2
shift 2
;;
--stream)
BUILD_STREAM=$2
shift 2
;;
--release) # Temporarily keep --release support as an alias for --stream
BUILD_STREAM=$2
shift 2
;;
--repo)
REPO_LIST+=("$2")
shift 2
;;
--local)
LOCAL=yes
shift
;;
--push)
PUSH=yes
shift
;;
--proxy)
PROXY=$2
shift 2
;;
--latest)
TAG_LATEST=yes
shift
;;
--latest-tag)
LATEST_TAG=$2
shift 2
;;
--user)
DOCKER_USER=$2
shift 2
;;
--registry)
# Add a trailing / if needed
DOCKER_REGISTRY="${2%/}/"
shift 2
;;
--clean)
CLEAN=yes
shift
;;
--cache)
USE_DOCKER_CACHE=yes
shift
;;
--hostname)
HOST=$2
shift 2
;;
--attempts)
MAX_ATTEMPTS=$2
shift 2
;;
--retry-delay)
RETRY_DELAY=$2
shift 2
;;
--config-file)
CONFIG_FILE=$2
shift 2
;;
-h | --help )
usage
exit 1
;;
*)
usage
exit 1
;;
esac
done
# Validate the OS option
if [ -z "$OS" ] ; then
OS="$(ID= && source /etc/os-release 2>/dev/null && echo $ID || true)"
if [[ -z "$OS" ]] ; then
echo "Unable to determine OS, please re-run with \`--os' option" >&2
exit 1
fi
fi
VALID_OS=1
for supported_os in ${SUPPORTED_OS_ARGS[@]}; do
if [ "$OS" = "${supported_os}" ]; then
VALID_OS=0
break
fi
done
if [ ${VALID_OS} -ne 0 ]; then
echo "Unsupported OS specified: ${OS}" >&2
echo "Supported OS options: ${SUPPORTED_OS_ARGS[@]}" >&2
exit 1
fi
SRC_DOCKER_DIR="${MY_SCRIPT_DIR}/stx-${OS}"
SRC_DOCKERFILE="${SRC_DOCKER_DIR}"/Dockerfile.${BUILD_STREAM}
if [[ -z "$OS_VERSION" ]]; then
OS_VERSION=$(
sed -n -r 's/^\s*ARG\s+RELEASE\s*=\s*([^ \t#]+).*/\1/ip' $SRC_DOCKERFILE | head -n 1
[[ ${PIPESTATUS[0]} -eq 0 ]]
)
if [[ -z "$OS_VERSION" ]] ; then
echo "$SRC_DOCKERFILE: failed to determine OS_VERSION" >&2
exit 1
fi
fi
if [ -z "${IMAGE_VERSION}" ]; then
IMAGE_VERSION=${OS_VERSION}
fi
DEFAULT_CONFIG_FILE="${DEFAULT_CONFIG_FILE_DIR}/${DEFAULT_CONFIG_FILE_PREFIX}-${OS}-${BUILD_STREAM}.cfg"
# Read additional auguments from config file if it exists.
if [[ -z "$CONFIG_FILE" ]] && [[ -f ${DEFAULT_CONFIG_FILE} ]]; then
CONFIG_FILE=${DEFAULT_CONFIG_FILE}
fi
if [[ ! -z ${CONFIG_FILE} ]]; then
if [[ -f ${CONFIG_FILE} ]]; then
get_args_from_file ${CONFIG_FILE}
else
echo "Config file not found: ${CONFIG_FILE}"
exit 1
fi
fi
if [ ${#REPO_LIST[@]} -eq 0 ]; then
# Either --repo or --local must be specified
if [ "${LOCAL}" != "yes" -a "${BUILD_STREAM}" != "dev" -a "${BUILD_STREAM}" != "master" ]; then
echo "Either --local or --repo must be specified" >&2
exit 1
fi
else
if [ "${LOCAL}" = "yes" ]; then
echo "Cannot specify both --local and --repo" >&2
exit 1
fi
fi
BUILDDIR=${MY_WORKSPACE}/std/build-images/stx-${OS}
if [ -d ${BUILDDIR} ]; then
# Leftover from previous build
rm -rf ${BUILDDIR}
fi
mkdir -p ${BUILDDIR}
if [ $? -ne 0 ]; then
echo "Failed to create ${BUILDDIR}" >&2
exit 1
fi
# Get the Dockerfile
cp ${SRC_DOCKERFILE} ${BUILDDIR}/Dockerfile
# Generate the stx.repo file
if [[ "$OS" == "debian" ]] ; then
# These env vars must be defined in debian builder pods
for var in DEBIAN_SNAPSHOT DEBIAN_SECURITY_SNAPSHOT DEBIAN_DISTRIBUTION REPOMGR_DEPLOY_URL REPOMGR_ORIGIN ; do
if [[ -z "${!var}" ]] ; then
echo "$var must be defined in the environment!" >&2
exit 1
fi
done
unset var
# Replace "@...@" tokens in apt template files
function replace_vars {
sed -e "s!@DEBIAN_SNAPSHOT@!${DEBIAN_SNAPSHOT}!g" \
-e "s!@DEBIAN_SECURITY_SNAPSHOT@!${DEBIAN_SECURITY_SNAPSHOT}!g" \
-e "s!@DEBIAN_DISTRIBUTION@!${DEBIAN_DISTRIBUTION}!g" \
-e "s!@REPOMGR_DEPLOY_URL@!${REPOMGR_DEPLOY_URL}!g" \
-e "s!@REPOMGR_ORIGIN@!${REPOMGR_ORIGIN}!g" \
-e "s!@LAYER@!${LAYER}!g" \
"$@"
}
# create apt/ files for the docker file
mkdir -p "${BUILDDIR}/apt"
# debian.sources.list
replace_vars "${SRC_DOCKER_DIR}/apt/debian.sources.list.in" >"${BUILDDIR}/apt/debian.sources.list"
# <layer>.sources.list
# These can be optionally used if it is necessary to build an image that
# requires dependencies that are in repositories not listed in
# `stx.sources.list`.
layer_cfg_name="${OS}_build_layer.cfg"
layer_cfgs=($(find ${GIT_LIST} -maxdepth 1 -name ${layer_cfg_name}))
LAYERS=($(
for layer_cfg in "${layer_cfgs[@]}"; do
echo $(cat "${layer_cfg}")
done | sort --unique
))
for LAYER in "${LAYERS[@]}"; do
replace_vars "${SRC_DOCKER_DIR}/apt/layer.sources.list.in" >"${BUILDDIR}/apt/${LAYER}.layer.sources.list"
done
# stx.sources: if user provided any --repo's use them instead of the template
if [[ "${#REPO_LIST[@]}" -gt 0 ]] ; then
rm -f "${BUILDDIR}/apt/stx.sources.list"
for repo in "${REPO_LIST[@]}" ; do
echo "$repo" >>"${BUILDDIR}/apt/stx.sources.list"
done
unset repo
# otherwise use the template file
else
replace_vars "${SRC_DOCKER_DIR}/apt/stx.sources.list.in" >"${BUILDDIR}/apt/stx.sources.list"
fi
# preferences: instantiate template with REPOMGR_ORIGIN from environment
replace_vars "${SRC_DOCKER_DIR}/apt/stx.preferences.part.in" >>"${BUILDDIR}/apt/stx.preferences"
unset -f replace_vars
fi
# Check to see if the OS image is already pulled
docker images --format '{{.Repository}}:{{.Tag}}' ${OS}:${OS_VERSION} | grep -q "^${OS}:${OS_VERSION}$"
BASE_IMAGE_PRESENT=$?
# Pull the image anyway, to ensure it is up to date
docker pull ${OS}:${OS_VERSION}
# Build the image
IMAGE_NAME=${DOCKER_REGISTRY}${DOCKER_USER}/stx-${OS}:${IMAGE_VERSION}
IMAGE_NAME_LATEST=${DOCKER_REGISTRY}${DOCKER_USER}/stx-${OS}:${LATEST_TAG}
declare -a BUILD_ARGS
BUILD_ARGS+=(--build-arg RELEASE=${OS_VERSION})
if [[ "$OS" == "debian" ]] ; then
BUILD_ARGS+=(--build-arg "DIST=${DEBIAN_DISTRIBUTION}")
fi
# Add proxy to docker build
if [ ! -z "$PROXY" ]; then
BUILD_ARGS+=(--build-arg http_proxy=$PROXY)
fi
# Don't use docker cache
if [[ "$USE_DOCKER_CACHE" != "yes" ]] ; then
BUILD_ARGS+=("--no-cache")
fi
BUILD_ARGS+=(--tag ${IMAGE_NAME} ${BUILDDIR})
# Build base image
with_retries -d ${RETRY_DELAY} ${MAX_ATTEMPTS} docker build "${BUILD_ARGS[@]}"
if [ $? -ne 0 ]; then
echo "Failed running docker build command" >&2
exit 1
fi
if [ "${PUSH}" = "yes" ]; then
# Push the image
echo "Pushing image: ${IMAGE_NAME}"
with_retries -d ${RETRY_DELAY} ${MAX_ATTEMPTS} docker push ${IMAGE_NAME}
if [ $? -ne 0 ]; then
echo "Failed running docker push command" >&2
exit 1
fi
if [ "$TAG_LATEST" = "yes" ]; then
docker tag ${IMAGE_NAME} ${IMAGE_NAME_LATEST}
echo "Pushing image: ${IMAGE_NAME_LATEST}"
with_retries -d ${RETRY_DELAY} ${MAX_ATTEMPTS} docker push ${IMAGE_NAME_LATEST}
if [ $? -ne 0 ]; then
echo "Failed running docker push command on latest" >&2
exit 1
fi
fi
fi
if [ "${CLEAN}" = "yes" ]; then
# Delete the images
echo "Deleting image: ${IMAGE_NAME}"
docker image rm ${IMAGE_NAME}
if [ $? -ne 0 ]; then
echo "Failed running docker image rm command" >&2
exit 1
fi
if [ "$TAG_LATEST" = "yes" ]; then
echo "Deleting image: ${IMAGE_NAME_LATEST}"
docker image rm ${IMAGE_NAME_LATEST}
if [ $? -ne 0 ]; then
echo "Failed running docker image rm command" >&2
exit 1
fi
fi
if [ ${BASE_IMAGE_PRESENT} -ne 0 ]; then
# The base image was not already present, so delete it
echo "Removing docker image ${OS}:${OS_VERSION}"
docker image rm ${OS}:${OS_VERSION}
if [ $? -ne 0 ]; then
echo "Failed to delete base image from docker" >&2
fi
fi
fi