Merge pull request #485 from phracek/support_push_minimal_container_to_quay
Build and push python minimal image to quay.io/sclorg
This commit is contained in:
parent
b3bc61b518
commit
9a3b04f941
7 changed files with 280 additions and 69 deletions
214
test/test-lib.sh
214
test/test-lib.sh
|
|
@ -2,11 +2,11 @@
|
|||
#
|
||||
# Test a container image.
|
||||
#
|
||||
# Always use sourced from a specific container testfile
|
||||
# Always use sourced from a specific container testfile
|
||||
#
|
||||
# reguires definition of CID_FILE_DIR
|
||||
# CID_FILE_DIR=$(mktemp --suffix=<container>_test_cidfiles -d)
|
||||
# reguires definition of TEST_LIST
|
||||
# reguires definition of TEST_LIST
|
||||
# TEST_LIST="\
|
||||
# ctest_container_creation
|
||||
# ctest_doc_content"
|
||||
|
|
@ -52,6 +52,50 @@ function ct_enable_cleanup() {
|
|||
trap ct_cleanup EXIT SIGINT
|
||||
}
|
||||
|
||||
# ct_pull_image
|
||||
# -------------
|
||||
# Function pull an image before tests execution
|
||||
# Argument: image_name - string containing the public name of the image to pull
|
||||
# Argument: exit - in case "true" is defined and pull failed, then script has to exit with 1 and no tests are executed
|
||||
# Argument: loops - how many times to pull image in case of failure
|
||||
# Function returns either 0 in case of pull was successful
|
||||
# Or the test suite exit with 1 in case of pull error
|
||||
function ct_pull_image() {
|
||||
local image_name="$1"; shift
|
||||
local exit=${1:-"false"}; shift
|
||||
local loops=${1:-10}; shift
|
||||
local loop=0
|
||||
|
||||
# Let's try to pull image.
|
||||
echo "-> Pulling image $image_name ..."
|
||||
# Sometimes in Fedora case it fails with HTTP 50X
|
||||
# Check if the image is available locally and try to pull it if it is not
|
||||
if [[ "$(docker images -q "$image_name" 2>/dev/null)" != "" ]]; then
|
||||
echo "The image $image_name is already pulled."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Try pulling the image to see if it is accessible
|
||||
# WORKAROUND: Since Fedora registry sometimes fails randomly, let's try it more times
|
||||
while ! docker pull "$image_name"; do
|
||||
((loop++)) || :
|
||||
echo "Pulling image $image_name failed."
|
||||
if [ "$loop" -gt "$loops" ]; then
|
||||
echo "Pulling of image $image_name failed $loops times in a row. Giving up."
|
||||
echo "!!! ERROR with pulling image $image_name !!!!"
|
||||
# shellcheck disable=SC2268
|
||||
if [[ x"$exit" == x"false" ]]; then
|
||||
return 1
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "Let's wait $((loop*5)) seconds and try again."
|
||||
sleep "$((loop*5))"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# ct_check_envs_set env_filter check_envs loop_envs [env_format]
|
||||
# --------------------
|
||||
# Compares values from one list of environment variable definitions against such list,
|
||||
|
|
@ -185,7 +229,7 @@ function ct_assert_container_creation_fails() {
|
|||
function ct_create_container() {
|
||||
local cid_file="$CID_FILE_DIR/$1" ; shift
|
||||
# create container with a cidfile in a directory for cleanup
|
||||
# shellcheck disable=SC2086
|
||||
# shellcheck disable=SC2086,SC2153
|
||||
docker run --cidfile="$cid_file" -d ${CONTAINER_ARGS:-} "$IMAGE_NAME" "$@"
|
||||
ct_wait_for_cid "$cid_file" || return 1
|
||||
: "Created container $(cat "$cid_file")"
|
||||
|
|
@ -310,6 +354,7 @@ function ct_npm_works() {
|
|||
|
||||
if ! docker exec "$(cat "$cid_file")" /bin/bash -c "npm --verbose install jquery && test -f node_modules/jquery/src/jquery.js" >"${tmpdir}/jquery" 2>&1 ; then
|
||||
echo "ERROR: npm could not install jquery inside the image ${IMAGE_NAME}." >&2
|
||||
cat "${tmpdir}/jquery"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
@ -582,13 +627,13 @@ ct_get_public_image_name() {
|
|||
local registry
|
||||
|
||||
registry=$(ct_registry_from_os "$os")
|
||||
if [ "x$os" == "xrhel7" ]; then
|
||||
if [ "$os" == "rhel7" ]; then
|
||||
public_image_name=$registry/rhscl/$base_image_name-${version//./}-rhel7
|
||||
elif [ "x$os" == "xrhel8" ]; then
|
||||
elif [ "$os" == "rhel8" ]; then
|
||||
public_image_name=$registry/rhel8/$base_image_name-${version//./}
|
||||
elif [ "x$os" == "xcentos7" ]; then
|
||||
elif [ "$os" == "centos7" ]; then
|
||||
public_image_name=$registry/centos7/$base_image_name-${version//./}-centos7
|
||||
elif [ "x$os" == "xcentos8" ]; then
|
||||
elif [ "$os" == "centos8" ]; then
|
||||
public_image_name=$registry/centos8/$base_image_name-${version//./}-centos8
|
||||
fi
|
||||
|
||||
|
|
@ -670,7 +715,7 @@ ct_s2i_build_as_df()
|
|||
local df_name=
|
||||
local tmpdir=
|
||||
local incremental=false
|
||||
local mount_options=""
|
||||
local mount_options=()
|
||||
|
||||
# Run the entire thing inside a subshell so that we do not leak shell options outside of the function
|
||||
(
|
||||
|
|
@ -687,14 +732,11 @@ ct_s2i_build_as_df()
|
|||
# Default to root if no user is set by the image
|
||||
user=${user:-0}
|
||||
# run the user through the image in case it is non-numeric or does not exist
|
||||
# NOTE: The '-eq' test is used to check if $user is numeric as it will fail if $user is not an integer
|
||||
if ! [ "$user" -eq "$user" ] 2>/dev/null && ! user_id=$(docker run --rm "$src_image" bash -c "id -u $user 2>/dev/null"); then
|
||||
echo "ERROR: id of user $user not found inside image $src_image."
|
||||
if ! user_id=$(ct_get_uid_from_image "$user" "$src_image"); then
|
||||
echo "Terminating s2i build."
|
||||
return 1
|
||||
else
|
||||
user_id=${user_id:-$user}
|
||||
fi
|
||||
|
||||
echo "$s2i_args" | grep -q "\-\-incremental" && incremental=true
|
||||
if $incremental; then
|
||||
inc_tmp=$(mktemp -d --tmpdir incremental.XXXX)
|
||||
|
|
@ -757,14 +799,93 @@ EOF
|
|||
fi
|
||||
|
||||
# Check if -v parameter is present in s2i_args and add it into docker build command
|
||||
mount_options=$(echo "$s2i_args" | grep -o -e '\(-v\)[[:space:]]\.*\S*' || true)
|
||||
read -ra mount_options <<< "$(echo "$s2i_args" | grep -o -e '\(-v\)[[:space:]]\.*\S*' || true)"
|
||||
|
||||
# Run the build and tag the result
|
||||
# shellcheck disable=SC2086
|
||||
docker build $mount_options -f "$df_name" --no-cache=true -t "$dst_image" .
|
||||
docker build ${mount_options[@]+"${mount_options[@]}"} -f "$df_name" --no-cache=true -t "$dst_image" .
|
||||
)
|
||||
}
|
||||
|
||||
# ct_s2i_multistage_build APP_PATH SRC_IMAGE DST_IMAGE SEC_IMAGE [S2I_ARGS]
|
||||
# ----------------------------
|
||||
# Create a new s2i app image from local sources in a similar way as source-to-image would have used.
|
||||
# Argument: APP_PATH - local path to the app sources to be used in the test
|
||||
# Argument: SRC_IMAGE - image to be used as a base for the s2i build process
|
||||
# Argument: SEC_IMAGE - image to be used as the base for the result of the build process
|
||||
# Argument: DST_IMAGE - image name to be used during the tagging of the s2i build result
|
||||
# Argument: S2I_ARGS - Additional list of source-to-image arguments.
|
||||
# Only used to check for environment variable definitions.
|
||||
ct_s2i_multistage_build() {
|
||||
|
||||
local app_path=$1; shift
|
||||
local src_image=$1; shift
|
||||
local sec_image=$1; shift
|
||||
local dst_image=$1; shift
|
||||
local s2i_args=$*;
|
||||
local local_app="app-src"
|
||||
local user_id=
|
||||
local mount_options=()
|
||||
|
||||
|
||||
# Run the entire thing inside a subshell so that we do not leak shell options outside of the function
|
||||
(
|
||||
# Error out if any part of the build fails
|
||||
set -e
|
||||
|
||||
user=$(docker inspect -f "{{.Config.User}}" "$src_image")
|
||||
# Default to root if no user is set by the image
|
||||
user=${user:-0}
|
||||
# run the user through the image in case it is non-numeric or does not exist
|
||||
if ! user_id=$(ct_get_uid_from_image "$user" "$src_image"); then
|
||||
echo "Terminating s2i build."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Use /tmp to not pollute cwd
|
||||
tmpdir=$(mktemp -d)
|
||||
df_name=$(mktemp -p "$tmpdir" Dockerfile.XXXX)
|
||||
cd "$tmpdir"
|
||||
|
||||
# If the path exists on the local host, copy it into the directory for the build
|
||||
# Otherwise handle it as a link to a git repository
|
||||
if [ -e "${app_path/file:\/\//}/." ] ; then
|
||||
mkdir -p "$local_app"
|
||||
# Strip file:// from APP_PATH and copy its contents into current context
|
||||
cp -r "${app_path/file:\/\//}/." "$local_app"
|
||||
|
||||
else
|
||||
ct_clone_git_repository "$app_path" "$local_app"
|
||||
fi
|
||||
|
||||
cat <<EOF >"$df_name"
|
||||
# First stage builds the application
|
||||
FROM $src_image as builder
|
||||
# Add application sources to a directory that the assemble script expects them
|
||||
# and set permissions so that the container runs without root access
|
||||
USER 0
|
||||
ADD app-src /tmp/src
|
||||
RUN chown -R 1001:0 /tmp/src
|
||||
$(echo "$s2i_args" | grep -o -e '\(-e\|--env\)[[:space:]=]\S*=\S*' | sed -e 's/-e /ENV /' -e 's/--env[ =]/ENV /')
|
||||
# Check if CA autority is present on host and add it into Dockerfile
|
||||
$([ -f "$(full_ca_file_path)" ] && echo "RUN cd /etc/pki/ca-trust/source/anchors && update-ca-trust extract")
|
||||
USER $user_id
|
||||
# Install the dependencies
|
||||
RUN /usr/libexec/s2i/assemble
|
||||
# Second stage copies the application to the minimal image
|
||||
FROM $sec_image
|
||||
# Copy the application source and build artifacts from the builder image to this one
|
||||
COPY --from=builder \$HOME \$HOME
|
||||
# Set the default command for the resulting image
|
||||
CMD /usr/libexec/s2i/run
|
||||
EOF
|
||||
|
||||
# Check if -v parameter is present in s2i_args and add it into docker build command
|
||||
read -ra mount_options <<< "$(echo "$s2i_args" | grep -o -e '\(-v\)[[:space:]]\.*\S*' || true)"
|
||||
|
||||
docker build ${mount_options[@]+"${mount_options[@]}"} -f "$df_name" --no-cache=true -t "$dst_image" .
|
||||
)
|
||||
}
|
||||
|
||||
# ct_check_image_availability PUBLIC_IMAGE_NAME
|
||||
# ----------------------------
|
||||
# Pull an image from the public repositories to see if the image is already available.
|
||||
|
|
@ -773,7 +894,7 @@ ct_check_image_availability() {
|
|||
local public_image_name=$1;
|
||||
|
||||
# Try pulling the image to see if it is accessible
|
||||
if ! docker pull "$public_image_name" &>/dev/null; then
|
||||
if ! ct_pull_image "$public_image_name" &>/dev/null; then
|
||||
echo "$public_image_name could not be downloaded via 'docker'"
|
||||
return 1
|
||||
fi
|
||||
|
|
@ -823,6 +944,50 @@ ct_show_resources()
|
|||
lscpu
|
||||
}
|
||||
|
||||
# ct_clone_git_repository
|
||||
# -----------------------------
|
||||
# Argument: app_url - git URI pointing to a repository, supports "@" to indicate a different branch
|
||||
# Argument: app_dir (optional) - name of the directory to clone the repository into
|
||||
ct_clone_git_repository()
|
||||
{
|
||||
local app_url=$1; shift
|
||||
local app_dir=$1
|
||||
|
||||
# If app_url contains @, the string after @ is considered
|
||||
# as a name of a branch to clone instead of the main/master branch
|
||||
IFS='@' read -ra git_url_parts <<< "${app_url}"
|
||||
|
||||
if [ -n "${git_url_parts[1]}" ]; then
|
||||
git_clone_cmd="git clone --branch ${git_url_parts[1]} ${git_url_parts[0]} ${app_dir}"
|
||||
else
|
||||
git_clone_cmd="git clone ${app_url} ${app_dir}"
|
||||
fi
|
||||
|
||||
if ! $git_clone_cmd ; then
|
||||
echo "ERROR: Git repository ${app_url} cannot be cloned into ${app_dir}."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ct_get_uid_from_image
|
||||
# -----------------------------
|
||||
# Argument: user - user to get uid for inside the image
|
||||
# Argument: src_image - image to use for user information
|
||||
ct_get_uid_from_image()
|
||||
{
|
||||
local user=$1; shift
|
||||
local src_image=$1
|
||||
local user_id=
|
||||
|
||||
# NOTE: The '-eq' test is used to check if $user is numeric as it will fail if $user is not an integer
|
||||
if ! [ "$user" -eq "$user" ] 2>/dev/null && ! user_id=$(docker run --rm "$src_image" bash -c "id -u $user 2>/dev/null"); then
|
||||
echo "ERROR: id of user $user not found inside image $src_image."
|
||||
return 1
|
||||
else
|
||||
echo "${user_id:-$user}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ct_test_app_dockerfile
|
||||
# -----------------------------
|
||||
# Argument: dockerfile - path to a Dockerfile that will be used for building an image
|
||||
|
|
@ -867,20 +1032,9 @@ ct_test_app_dockerfile() {
|
|||
|
||||
if [ -d "$app_url" ] ; then
|
||||
echo "Copying local folder: $app_url -> $app_dir."
|
||||
cp -Lr $app_url $app_dir
|
||||
cp -Lr "$app_url" "$app_dir"
|
||||
else
|
||||
# If app_url contains @, the string after @ is considered
|
||||
# as a name of a branch to clone instead of the main/master branch
|
||||
IFS='@' read -ra git_url_parts <<< "${app_url}"
|
||||
|
||||
if [ -n "${git_url_parts[1]}" ]; then
|
||||
git_clone_cmd="git clone --branch ${git_url_parts[1]} ${git_url_parts[0]} ${app_dir}"
|
||||
else
|
||||
git_clone_cmd="git clone ${app_url} ${app_dir}"
|
||||
fi
|
||||
|
||||
if ! $git_clone_cmd ; then
|
||||
echo "ERROR: Git repository ${app_url} cannot be cloned into ${app_dir}."
|
||||
if ! ct_clone_git_repository "$app_url" "$app_dir" ; then
|
||||
echo "Terminating the Dockerfile build."
|
||||
return 1
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue