From fdf8f9b03563c5268d51960f3b4734d95f521ed5 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 7 Apr 2021 08:44:42 +0200 Subject: [PATCH] Update from the upstream Github repository --- README.md | 32 ++++- s2i/bin/usage | 12 +- test/check_imagestreams.py | 22 +++ test/from-dockerfile/Dockerfile.tpl | 2 +- test/from-dockerfile/Dockerfile_no_s2i.tpl | 16 +++ test/imagestreams/python-centos.json | 2 +- test/npm-virtualenv-uwsgi-test-app/app.sh | 2 +- test/run | 150 +++++++++++++++------ test/run-openshift | 4 +- test/test-lib-openshift.sh | 43 ++++-- test/test-lib-python.sh | 4 +- test/test-lib.sh | 19 ++- 12 files changed, 238 insertions(+), 70 deletions(-) create mode 100644 test/from-dockerfile/Dockerfile_no_s2i.tpl diff --git a/README.md b/README.md index fb03f55..1ab7d2a 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ To use the Python image in a Dockerfile, follow these steps: #### 1. Pull a base builder image to build on ``` -podman pull +podman pull registry.fedoraproject.org/f33/python3 ``` #### 2. Pull and application code @@ -105,18 +105,44 @@ prepared for a future flawless switch to a newer or different platform. To use the Source-to-Image scripts and build an image using a Dockerfile, create a Dockerfile with this content: ``` -FROM +FROM registry.fedoraproject.org/f33/python3 + # 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 +RUN /usr/bin/fix-permissions /tmp/src USER 1001 + # Install the dependencies RUN /usr/libexec/s2i/assemble + # Set the default command for the resulting image CMD /usr/libexec/s2i/run ``` + +If you decide not to use the Source-to-Image scripts, you will need to manually tailor the Dockerfile to your application and its needs. +Example Dockerfile for a simple Django application: + +``` +FROM registry.fedoraproject.org/f33/python3 + +# Add application sources with correct permissions for OpenShift +USER 0 +ADD app-src . +RUN chown -R 1001:0 ./ +USER 1001 + +# Install the dependencies +RUN pip install -U "pip>=19.3.1" && \ + pip install -r requirements.txt && \ + python manage.py collectstatic --noinput && \ + python manage.py migrate + +# Run the application +CMD python manage.py runserver 0.0.0.0:8080 +``` + #### 4. Build a new image from a Dockerfile prepared in the previous step ``` diff --git a/s2i/bin/usage b/s2i/bin/usage index a433615..a45027f 100755 --- a/s2i/bin/usage +++ b/s2i/bin/usage @@ -6,13 +6,13 @@ NAMESPACE=centos cat < -- curl 127.0.0.1:8080 EOF diff --git a/test/check_imagestreams.py b/test/check_imagestreams.py index 6da0f63..b0eb11b 100755 --- a/test/check_imagestreams.py +++ b/test/check_imagestreams.py @@ -1,5 +1,27 @@ #!/bin/env python3 +# MIT License +# +# Copyright (c) 2018-2019 Red Hat, Inc. + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + import sys import json import logging diff --git a/test/from-dockerfile/Dockerfile.tpl b/test/from-dockerfile/Dockerfile.tpl index 2a12b8c..a44d41d 100644 --- a/test/from-dockerfile/Dockerfile.tpl +++ b/test/from-dockerfile/Dockerfile.tpl @@ -4,7 +4,7 @@ FROM #IMAGE_NAME# # Replaced by sed in tests, see test_from_dockerfile in test/r # 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 +RUN /usr/bin/fix-permissions /tmp/src USER 1001 # Install the dependencies diff --git a/test/from-dockerfile/Dockerfile_no_s2i.tpl b/test/from-dockerfile/Dockerfile_no_s2i.tpl new file mode 100644 index 0000000..7f073a6 --- /dev/null +++ b/test/from-dockerfile/Dockerfile_no_s2i.tpl @@ -0,0 +1,16 @@ +FROM #IMAGE_NAME# # Replaced by sed in tests, see test_from_dockerfile in test/run + +# Add application sources with correct permissions for OpenShift +USER 0 +ADD app-src . +RUN chown -R 1001:0 ./ +USER 1001 + +# Install the dependencies +RUN pip install -U "pip>=19.3.1" && \ + pip install -r requirements.txt && \ + python manage.py collectstatic --noinput && \ + python manage.py migrate + +# Run the application +CMD python manage.py runserver 0.0.0.0:8080 diff --git a/test/imagestreams/python-centos.json b/test/imagestreams/python-centos.json index 0f6aeae..b965fde 100644 --- a/test/imagestreams/python-centos.json +++ b/test/imagestreams/python-centos.json @@ -142,7 +142,7 @@ }, "from": { "kind": "DockerImage", - "name": "docker.io/centos/python-27-centos7:latest" + "name": "quay.io/centos7/python-27-centos7:latest" }, "referencePolicy": { "type": "Local" diff --git a/test/npm-virtualenv-uwsgi-test-app/app.sh b/test/npm-virtualenv-uwsgi-test-app/app.sh index f34357a..5b7a273 100755 --- a/test/npm-virtualenv-uwsgi-test-app/app.sh +++ b/test/npm-virtualenv-uwsgi-test-app/app.sh @@ -13,7 +13,7 @@ packages=("pip" "setuptools" "wheel") for pkg in ${packages[@]}; do # grep returns exit code 1 if the output contains only one line starting # with "Requirement already …" which means that the package is updated - python -m pip install -U --no-deps --no-python-version-warning $pkg 2>&1 | grep -v "^Requirement already up-to-date: " + python -m pip install -U --no-deps --no-python-version-warning $pkg 2>&1 | grep -Ev "^Requirement already (up-to-date|satisfied): " if [ $? -eq 0 ]; then echo "ERROR: Failed to upgrade '$pkg' to the latest version." exit 1 diff --git a/test/run b/test/run index 42a52d5..c972458 100755 --- a/test/run +++ b/test/run @@ -12,6 +12,22 @@ declare -a WEB_APPS=({standalone,setup,setup-requirements,django,numpy,app-home, test_dir="$(readlink -zf $(dirname "${BASH_SOURCE[0]}"))" image_dir=$(readlink -zf ${test_dir}/..) +test_short_summary='' +TESTSUITE_RESULT=0 + +TEST_LIST="\ +test_s2i_usage +test_docker_run_usage +test_application +test_application_with_user +test_application_enable_init_wrapper +" + +TEST_VAR_DOCKER="\ +test_scl_variables_in_dockerfile +test_from_dockerfile +" + if [[ -z $VERSION ]]; then echo "ERROR: The VERSION variable must be set." exit 1 @@ -82,7 +98,7 @@ cleanup() { rm -rf ${test_dir}/${1}/.git } -check_result() { +check_type() { # positive test & non-zero exit status = ERROR # negative test & zero exit status = ERROR local result="$1" @@ -90,12 +106,22 @@ check_result() { if [[ "$type" == "positive" && "$result" != "0" ]]; then info "TEST FAILED (${type}), EXPECTED:0 GOT:${result}" cleanup - exit $result + return $result elif [[ "$type" == "negative" && "$result" == "0" ]]; then info "TEST FAILED (${type}), EXPECTED: non-zero GOT:${result}" cleanup - exit 1 + return 1 fi + +} +check_result() { + # Function sets if test suite failed or not + # If return value is not 0 then mark test case as TESTCASE_RESULT=1 + local result="$1" + if [[ "$result" != "0" ]]; then + TESTCASE_RESULT=1 + fi + return $result } wait_for_cid() { @@ -189,65 +215,113 @@ test_application() { test_from_dockerfile(){ info "Test from Dockerfile" + # The latest LTS release of Django does not work on RHEL 7 (due to an old version of SQLite), + # and no longer supports Python 2. So on all CentOS/RHEL 7 images and all Python 2 images, + # we're using the old Django LTS version 1.11.x from the main git branch of the django-ex project. + # In all other cases we're using the newer Django LTS version 2.2.x from the corresponding git branch. + if [[ ${VERSION} == "2.7" ]] || [[ ${IMAGE_NAME} =~ "centos7" ]] || [[ ${IMAGE_NAME} =~ "rhel7" ]] || [[ ${IMAGE_NAME} =~ "ubi7" ]]; then + django_example_repo_url="https://github.com/sclorg/django-ex.git" + else + django_example_repo_url="https://github.com/sclorg/django-ex.git@2.2.x" + fi + sed "s@#IMAGE_NAME#@${IMAGE_NAME}@" $test_dir/from-dockerfile/Dockerfile.tpl > $test_dir/from-dockerfile/Dockerfile - ct_test_app_dockerfile $test_dir/from-dockerfile/Dockerfile 'https://github.com/sclorg/django-ex.git' 'Welcome to your Django application on OpenShift' app-src + ct_test_app_dockerfile $test_dir/from-dockerfile/Dockerfile $django_example_repo_url 'Welcome to your Django application on OpenShift' app-src + check_result $? + + info "Test from Dockerfile with no s2i scripts used" + sed "s@#IMAGE_NAME#@${IMAGE_NAME}@" $test_dir/from-dockerfile/Dockerfile_no_s2i.tpl > $test_dir/from-dockerfile/Dockerfile + ct_test_app_dockerfile $test_dir/from-dockerfile/Dockerfile $django_example_repo_url 'Welcome to your Django application on OpenShift' app-src check_result $? } -# Since we built the candidate image locally, we don't want S2I attempt to pull -# it from Docker hub -s2i_args="--pull-policy=never" +test_application_with_user() { + # test application with random user + CONTAINER_ARGS="--user 12345" test_application -# Verify the 'usage' script is working properly when running the base image with 's2i usage ...' -test_s2i_usage -check_result $? +} -# Verify the 'usage' script is working properly when running the base image with 'docker run ...' -test_docker_run_usage -check_result $? +test_application_enable_init_wrapper() { + # test application with init wrapper + CONTAINER_ARGS="-e ENABLE_INIT_WRAPPER=true" test_application +} + +test_scl_variables_in_dockerfile() { + if [ "$OS" == "rhel7" ] || [ "$OS" == "centos7" ]; then + TESTCASE_RESULT=0 + # autocleanup only enabled here as only the following tests so far use it + CID_FILE_DIR=$(mktemp -d) + ct_enable_cleanup + + info "Testing variable presence during \`docker exec\`" + ct_check_exec_env_vars + check_result $? + + info "Checking if all scl variables are defined in Dockerfile" + ct_check_scl_enable_vars + check_result $? + fi +} + +function run_all_tests() { + local APP_NAME=${1:-undefined} + for test_case in $TEST_SET; do + info "Running test $test_case ... " + TESTCASE_RESULT=0 + $test_case + local test_msg + if [ $TESTCASE_RESULT -eq 0 ]; then + test_msg="[PASSED]" + else + test_msg="[FAILED]" + TESTSUITE_RESULT=1 + fi + test "$APP_NAME" == "undefined" && msg_app="" || msg_app="'$APP_NAME'" + printf -v test_short_summary "%s %s for %s %s\n" "${test_short_summary}" "${test_msg}" "${msg_app}" "$test_case" + [ -n "${FAIL_QUICKLY:-}" ] && { + cleanup "${APP_NAME}" + return 1 + } + done; +} # For debugging purposes, this script can be run with one or more arguments # those arguments list is a sub-set of values in the WEB_APPS array defined above # Example: ./run app-home-test-app pipenv-test-app for app in ${@:-${WEB_APPS[@]}}; do + # Since we built the candidate image locally, we don't want S2I attempt to pull + # it from Docker hub + s2i_args="--pull-policy=never" + prepare ${app} run_s2i_build ${app} RESULT=$? + msg_run_s2i_build="'${app}' run_s2i_build" if [[ "$app" == *"-should-fail-"* ]]; then # Tests with '-should-fail-' in their name should fail during a build, expecting non-zero exit status - check_result $RESULT "negative" + check_type $RESULT "negative" + test "$?" == "0" && test_msg="[PASSED]" || test_msg="[FAILED]" + printf -v test_short_summary "%s %s for %s\n" "${test_short_summary}" "$test_msg" "$msg_run_s2i_build" continue else - check_result $RESULT + check_type $RESULT + test "$?" != "0" && test_msg="[FAILED]" || test_msg="[PASSED]" + printf -v test_short_summary "%s %s for %s\n" "${test_short_summary}" "$test_msg" "$msg_run_s2i_build" fi + echo "" + TEST_SET=${TESTS:-$TEST_LIST} run_all_tests "${app}" - # test application with default user - test_application - - # test application with random user - CONTAINER_ARGS="--user 12345" test_application - - # test application with init wrapper - CONTAINER_ARGS="-e ENABLE_INIT_WRAPPER=true" test_application - - info "All tests for the ${app} finished successfully." cleanup ${app} done -if [ "$OS" == "rhel7" ] || [ "$OS" == "centos7" ]; then - # autocleanup only enabled here as only the following tests so far use it - CID_FILE_DIR=$(mktemp -d) - ct_enable_cleanup +TEST_SET=${TESTS:-$TEST_VAR_DOCKER} run_all_tests - info "Testing variable presence during \`docker exec\`" - ct_check_exec_env_vars - check_result $? +echo "$test_short_summary" - info "Checking if all scl variables are defined in Dockerfile" - ct_check_scl_enable_vars - check_result $? +if [ $TESTSUITE_RESULT -eq 0 ] ; then + echo "Tests for ${IMAGE_NAME} succeeded." +else + echo "Tests for ${IMAGE_NAME} failed." fi -test_from_dockerfile - -info "All tests finished successfully." +exit $TESTSUITE_RESULT diff --git a/test/run-openshift b/test/run-openshift index 35d3b7d..76d36e8 100755 --- a/test/run-openshift +++ b/test/run-openshift @@ -46,8 +46,8 @@ for template in $EPHEMERAL_TEMPLATES; do "$template" \ python \ 'Welcome to your Django application on OpenShift' \ - 8080 http 200 "-p SOURCE_REPOSITORY_REF=master -p PYTHON_VERSION=${VERSION} -p POSTGRESQL_VERSION=9.6 -p NAME=python-testing" \ - "centos/postgresql-96-centos7|postgresql:9.6" + 8080 http 200 "-p SOURCE_REPOSITORY_REF=master -p PYTHON_VERSION=${VERSION} -p POSTGRESQL_VERSION=10 -p NAME=python-testing" \ + "quay.io/centos7/postgresql-10-centos7|postgresql:10" done # Check the imagestream diff --git a/test/test-lib-openshift.sh b/test/test-lib-openshift.sh index c11a025..5405926 100644 --- a/test/test-lib-openshift.sh +++ b/test/test-lib-openshift.sh @@ -617,20 +617,21 @@ function ct_os_test_s2i_app_func() { ct_os_new_project namespace=${CT_NAMESPACE:-"$(oc project -q)"} + local image_tagged="${image_name_no_namespace%:*}:${VERSION}" if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ] ; then - ct_os_import_image_ocp4 "${image_name}" "${image_name_no_namespace}" + ct_os_import_image_ocp4 "${image_name}" "${image_tagged}" else # Create a specific imagestream tag for the image so that oc cannot use anything else if [ "${CT_SKIP_UPLOAD_IMAGE:-false}" == 'true' ] ; then - echo "Importing image ${image_name} as ${namespace}/${image_name_no_namespace}" + echo "Importing image ${image_name} as ${namespace}/${image_tagged}" # Use --reference-policy=local to pull remote image content to the cluster # Works around the issue of builder pods not having access to registry.redhat.io - oc tag --source=docker "${image_name}" "${namespace}/${image_name_no_namespace}" --insecure=true --reference-policy=local - ct_os_wait_stream_ready "${image_name_no_namespace}" "${namespace}" + oc tag --source=docker "${image_name}" "${namespace}/${image_tagged}" --insecure=true --reference-policy=local + ct_os_wait_stream_ready "${image_tagged}" "${namespace}" else - echo "Uploading image ${image_name} as ${image_name_no_namespace}" - ct_os_upload_image "${image_name}" "${image_name_no_namespace}" + echo "Uploading image ${image_name} as ${image_tagged}" + ct_os_upload_image "${image_name}" "${image_tagged}" fi fi @@ -642,7 +643,7 @@ function ct_os_test_s2i_app_func() { fi # shellcheck disable=SC2086 - ct_os_deploy_s2i_image "${image_name_no_namespace}" "${app_param}" \ + ct_os_deploy_s2i_image "${image_tagged}" "${app_param}" \ --context-dir="${context_dir}" \ --name "${service_name}" \ ${oc_args} @@ -793,6 +794,8 @@ function ct_os_test_template_app_func() { local local_template local_template=$(ct_obtain_input "${template}" 2>/dev/null || echo "--template=${template}") + + echo "Creating a new-app with name ${name_in_template} in namespace ${namespace} with args ${oc_args}." # shellcheck disable=SC2086 oc new-app "${local_template}" \ --name "${name_in_template}" \ @@ -928,7 +931,7 @@ ct_os_test_image_update() { function ct_os_deploy_cmd_image() { local image_name=${1} oc get pod command-app &>/dev/null && echo "command POD already running" && return 0 - echo "command POD not running yet, will start one called command-app" + echo "command POD not running yet, will start one called command-app ${image_name}" oc create -f - <