261 lines
9.6 KiB
Bash
Executable file
261 lines
9.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
if [[ ! -f "/.dockerenv" ]]; then
|
|
repo_root="$(git rev-parse --show-toplevel)";
|
|
else
|
|
repo_root="/srv";
|
|
fi
|
|
|
|
lantern_path="${repo_root}/lantern-build-engine";
|
|
|
|
IMAGEBUILDER_REGISTRY="${IMAGEBUILDER_REGISTRY:-registry.service.mooncarrot.space:5000}";
|
|
export IMAGEBUILDER_REGISTRY;
|
|
|
|
###############################################################################
|
|
|
|
#shellcheck disable=SC1090
|
|
source "${lantern_path}/lantern.sh";
|
|
|
|
if [[ -z "${BASE_PATH}" ]]; then
|
|
subtask_begin "BASE_PATH environment variable not found - setting base path to ${HC}${repo_root}/images${RS}";
|
|
BASE_PATH="${repo_root}/images";
|
|
subtask_end "$?";
|
|
fi
|
|
if [[ ! -d "${BASE_PATH}" ]]; then
|
|
echo "Error: The specified base path '${BASE_PATH}' doesn't exist.";
|
|
exit 1;
|
|
fi
|
|
|
|
# Make sure the current directory is the location of this script to simplify matters
|
|
cd "$(dirname "$(readlink -f "$0")")" || { echo "Error: Failed to cd"; exit 1; };
|
|
|
|
# Check out the lantern git submodule if needed
|
|
if [ ! -f "${lantern_path}/lantern.sh" ]; then git submodule update --init "${lantern_path}"; fi
|
|
|
|
# Create temporary directory
|
|
temp_dir="$(mktemp --tmpdir -d "imagebuilder-XXXXXXX")";
|
|
on_exit() {
|
|
task_begin "Cleaning up temporary directory";
|
|
rm -rf "${temp_dir}";
|
|
task_end "$?";
|
|
}
|
|
trap on_exit EXIT;
|
|
|
|
|
|
###############################################################################
|
|
|
|
subcommand="${1}";
|
|
shift;
|
|
|
|
if [[ -z "${subcommand}" ]]; then
|
|
CHEADING="${HC}${FCYN}";
|
|
CACTION="${FYEL}";#
|
|
CARG="${FMAG}"
|
|
echo -e "${HC}imagebuilder: Docker image (re)builder${RS}" >&2;
|
|
echo -e " By Starbeamrainbowlabs" >&2;
|
|
echo -e "" >&2;
|
|
echo -e "${CHEADING}Usage:${RS}" >&2;
|
|
echo -e " ${HC}${FGRN}./imagebuilder.sh${RS} ${CACTION}{action}${RS} ${LC}[${RS}${CARG}{arguments}${RS}${LC}]${RS}" >&2;
|
|
echo -e "" >&2;
|
|
echo -e "${CHEADING}Actions:${RS}" >&2;
|
|
echo -e " ${CACTION}build${RS} ${CARG}{imagename}${RS} [${CARG}{imagetag}${RS}]" >&2;
|
|
echo -e " Build the given image and upload it to the docker registry, optionally assigning a custom tag name" >&2;
|
|
echo -e " ${CACTION}list${RS}" >&2;
|
|
echo -e " List available images" >&2;
|
|
echo -e "" >&2;
|
|
echo -e "${CHEADING}Environment Variables:${RS}" >&2;
|
|
echo -e " ${CACTION}IMAGEBUILDER_REGISTRY${RS}" >&2;
|
|
echo -e " Set the url of the Docker registry (default: ${HC}registry.service.mooncarrot.space:5000${RS})" >&2;
|
|
echo -e " ${CACTION}BASE_PATH${RS}" >&2;
|
|
echo -e " Base path in which to look for image directories (defaults to the current working directory)" >&2;
|
|
echo -e "" >&2;
|
|
exit 0;
|
|
fi
|
|
|
|
###############################################################################
|
|
|
|
case "${subcommand}" in
|
|
# ██ ██ ███████ ████████
|
|
# ██ ██ ██ ██
|
|
# ██ ██ ███████ ██
|
|
# ██ ██ ██ ██
|
|
# ███████ ██ ███████ ██
|
|
list)
|
|
while read -r filepath; do
|
|
filepath_stripped="${filepath#"${BASE_PATH}"}";
|
|
if [[ -z "${filepath_stripped}" ]] || [[ ! -f "${filepath}/type.txt" ]]; then
|
|
continue;
|
|
fi
|
|
|
|
echo "${filepath_stripped}";
|
|
done < <(find "${BASE_PATH}" -maxdepth 1 -type d);
|
|
;;
|
|
|
|
|
|
# ██████ ██ ██ ██ ██ ██████
|
|
# ██ ██ ██ ██ ██ ██ ██ ██
|
|
# ██████ ██ ██ ██ ██ ██ ██
|
|
# ██ ██ ██ ██ ██ ██ ██ ██
|
|
# ██████ ██████ ██ ███████ ██████
|
|
build)
|
|
imagename="${1}";
|
|
imagetag="${2}";
|
|
|
|
if [[ -z "${imagename}" ]]; then
|
|
echo "Error: No image name specified.":
|
|
exit 1;
|
|
fi
|
|
|
|
imagedir="${BASE_PATH}/${imagename}";
|
|
|
|
if [[ ! -d "${imagedir}" ]]; then
|
|
echo -e "Error: An image with the name ${HC}${imagename}${RS} doesn't exist.";
|
|
exit 2;
|
|
fi
|
|
|
|
if [[ ! -f "${imagedir}/type.txt" ]]; then
|
|
echo -e "Error: No type.txt file was found for the image with the name ${HC}${imagename}${RS}.";
|
|
exit 3;
|
|
fi
|
|
|
|
# Determine the fully qualified tag that we're going to push to
|
|
docker_tag="${IMAGEBUILDER_REGISTRY}/${imagename}";
|
|
if [[ ! -z "${imagetag}" ]]; then
|
|
docker_tag="${docker_tag}:${imagetag}";
|
|
fi
|
|
|
|
echo -e "[${HOSTNAME}:imagebuilder] Fully qualified tag name: ${HC}${FGRN}${docker_tag}${RS}";
|
|
|
|
imagetype="$(tr -d "[:blank:]" <"${imagedir}/type.txt")";
|
|
|
|
case "${imagetype}" in
|
|
# ██████ ██████ ██████ ██ ██ ███████ ██████
|
|
# ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
# ██ ██ ██ ██ ██ █████ █████ ██████
|
|
# ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
# ██████ ██████ ██████ ██ ██ ███████ ██ ██
|
|
docker)
|
|
if [[ ! -f "${imagedir}/Dockerfile" ]]; then
|
|
echo -e "Error: Failed to find a Dockerfile at ${HC}${imagedir}/Dockerfile${RS}.";
|
|
exit 7;
|
|
fi
|
|
|
|
cd "${imagedir}" || { echo -e "Error: Failed to cd into ${HC}${imagedir}${RS}"; exit 1; };
|
|
|
|
if [[ -x "./pre.sh" ]]; then
|
|
task_begin "Executing pre-build hook";
|
|
execute ./pre.sh;
|
|
task_end "$?";
|
|
fi
|
|
|
|
task_begin "Building docker image";
|
|
echo "Tag: ${docker_tag}";
|
|
execute docker build --no-cache --pull --tag "${docker_tag}" --build-arg "REPO_LOCATION=${IMAGEBUILDER_REGISTRY}/" .;
|
|
task_end "$?";
|
|
|
|
task_begin "Pushing resulting docker image";
|
|
execute docker push "${docker_tag}";
|
|
task_end "$?";
|
|
|
|
if [[ -x "./post.sh" ]]; then
|
|
task_begin "Executing post-build hook";
|
|
execute ./post.sh;
|
|
task_end "$?";
|
|
fi
|
|
;;
|
|
|
|
|
|
# ██████ █████ ███████ ███████
|
|
# ██ ██ ██ ██ ██ ██
|
|
# ██████ ███████ ███████ █████
|
|
# ██ ██ ██ ██ ██ ██
|
|
# ██████ ██ ██ ███████ ███████
|
|
base|base-nopush)
|
|
builderscript="${imagedir}/${imagename}.sh";
|
|
if [[ ! -x "${builderscript}" ]]; then
|
|
echo -e "Error: Failed to find the base image builder script at ${HC}${builderscript}${RS} (is it executable?).";
|
|
exit 5;
|
|
fi
|
|
|
|
output_dir="${temp_dir}/${imagename}";
|
|
mkdir -p "${output_dir}";
|
|
|
|
task_begin "Building base image";
|
|
if [[ "${UID}" -ne 0 ]] && which fakeroot && which fakechroot; then
|
|
echo "Non-root user detected - using fakeroot & fakechroot";
|
|
execute fakechroot fakeroot "${builderscript}" "${output_dir}";
|
|
else
|
|
echo "root user or fakeroot & fakechroot not detected";
|
|
execute "${builderscript}" "${output_dir}";
|
|
fi
|
|
task_end "$?";
|
|
|
|
if [[ "${imagetype}" == "base-nopush" ]]; then
|
|
echo -e "${HC}Nopush mode invoked, not checking output directory or pushing to docker registry${RS}";
|
|
exit 0;
|
|
fi
|
|
|
|
if [[ ! -d "${output_dir}" ]]; then
|
|
echo -e "${FRED}${HC}Error: The builder script failed to create the output directory (expecting directory at ${FBLE}${output_dir}${FRED}, but found nothing).${RS}";
|
|
exit 6;
|
|
fi
|
|
|
|
task_begin "Importing resulting image into Docker";
|
|
image_filepath="$(find "${output_dir}" -iname "*.tar.gz" -printf '%p' -quit)";
|
|
docker_tag_local="$(docker import - <"${image_filepath}")";
|
|
task_end "$?";
|
|
|
|
task_begin "Tagging and pushing to registry";
|
|
execute docker tag "${docker_tag_local}" "${docker_tag}";
|
|
execute docker push "${docker_tag}";
|
|
task_end "$?";
|
|
;;
|
|
|
|
import)
|
|
task_begin "Finding remote image name";
|
|
if [[ ! -r "${imagedir}/imagename.txt" ]]; then
|
|
echo "Error: 'import' image type specified, but no imagename.txt file was found containing the (fully qualified) image name to pull from.";
|
|
exit 8;
|
|
fi
|
|
|
|
imagename_remote="$(tr -d "[:blank:]" <"${imagedir}/imagename.txt")"
|
|
|
|
if [[ -z "${imagename_remote}" ]]; then
|
|
echo "Error: An empty image name to pull isn't valid.";
|
|
exit 7;
|
|
fi
|
|
|
|
echo -e "[${HOSTNAME}:imagebuilder] Remote image name is ${FGRN}${HC}${imagename_remote}${RS}";
|
|
task_end "$?";
|
|
|
|
task_begin "Downloading image";
|
|
execute docker pull "${imagename_remote}";
|
|
task_end "$?" "Error: Failed to download image";
|
|
|
|
task_begin "Retagging image";
|
|
execute docker tag "${imagename_remote}" "${docker_tag}";
|
|
task_end "$?";
|
|
|
|
task_begin "Pushing image";
|
|
execute docker push "${docker_tag}";
|
|
task_end "$?";
|
|
|
|
;;
|
|
|
|
|
|
# ██ ██ ███ ██ ██ ██ ███ ██ ██████ ██ ██ ███ ██
|
|
# ██ ██ ████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ████ ██
|
|
# ██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ █ ██ ██ ██ ██
|
|
# ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██
|
|
# ██████ ██ ████ ██ ██ ██ ████ ██████ ███ ███ ██ ████
|
|
*)
|
|
echo -e "Error: The image type ${HC}${imagetype}${RS} was not recognised. Currently recognised types: base, base-nopush, docker";
|
|
exit 4;
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
*)
|
|
echo -e "Unknown subcommand '${HC}${subcommand}${RS}' (try calling imagebuilder.sh without any arguments)";
|
|
;;
|
|
esac
|