From fe411e100458d26782b0653b036b78a1a7ead334 Mon Sep 17 00:00:00 2001 From: phracek Date: Fri, 8 Apr 2022 09:43:15 +0000 Subject: [PATCH] Merge pull request #501 from sclorg/support_test_build_push_c9s Support test, build, and push for CentOS Stream 9 --- Dockerfile.c9s | 82 +++++++++++++++++++++++++++++++ test/check_imagestreams.py | 7 +++ test/test-lib-openshift.sh | 13 ++--- test/test-lib-remote-openshift.sh | 21 ++++---- test/test-lib.sh | 73 +++++++++++++++++++-------- 5 files changed, 158 insertions(+), 38 deletions(-) create mode 100644 Dockerfile.c9s diff --git a/Dockerfile.c9s b/Dockerfile.c9s new file mode 100644 index 0000000..af879a1 --- /dev/null +++ b/Dockerfile.c9s @@ -0,0 +1,82 @@ +# This image provides a Python 3.9 environment you can use to run your Python +# applications. +FROM quay.io/sclorg/s2i-base-c9s:c9s + +EXPOSE 8080 + +ENV PYTHON_VERSION=3.9 \ + PATH=$HOME/.local/bin/:$PATH \ + PYTHONUNBUFFERED=1 \ + PYTHONIOENCODING=UTF-8 \ + LC_ALL=en_US.UTF-8 \ + LANG=en_US.UTF-8 \ + PIP_NO_CACHE_DIR=off + + +ENV SUMMARY="Platform for building and running Python $PYTHON_VERSION applications" \ + DESCRIPTION="Python $PYTHON_VERSION available as container is a base platform for \ +building and running various Python $PYTHON_VERSION applications and frameworks. \ +Python is an easy to learn, powerful programming language. It has efficient high-level \ +data structures and a simple but effective approach to object-oriented programming. \ +Python's elegant syntax and dynamic typing, together with its interpreted nature, \ +make it an ideal language for scripting and rapid application development in many areas \ +on most platforms." + +LABEL summary="$SUMMARY" \ + description="$DESCRIPTION" \ + io.k8s.description="$DESCRIPTION" \ + io.k8s.display-name="Python 3.9" \ + io.openshift.expose-services="8080:http" \ + io.openshift.tags="builder,python,python39,python-39,rh-python39" \ + com.redhat.component="python39-container" \ + name="sclorg/python-39" \ + version="1" \ + usage="s2i build https://github.com/sclorg/s2i-python-container.git --context-dir=3.9/test/setup-test-app/ sclorg/python-39 python-sample-app" \ + maintainer="SoftwareCollections.org " + +RUN INSTALL_PKGS="python3 python3-devel python3-setuptools python3-pip nss_wrapper \ + httpd httpd-devel mod_ssl mod_auth_gssapi mod_ldap \ + mod_session atlas-devel gcc-gfortran libffi-devel libtool-ltdl enchant" && \ + yum -y --setopt=tsflags=nodocs install $INSTALL_PKGS && \ + rpm -V $INSTALL_PKGS && \ + yum -y clean all --enablerepo='*' + +# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH. +COPY 3.9/s2i/bin/ $STI_SCRIPTS_PATH + +# Copy extra files to the image. +COPY 3.9/root/ / + +# Python 3 only +# Yes, the directory below is already copied by the previous command. +# The problem here is that the wheels directory is copied as a symlink. +# Only if you specify symlink directly as a source, COPY copies all the +# files from the symlink destination. +COPY 3.9/root/opt/wheels /opt/wheels +# - Create a Python virtual environment for use by any application to avoid +# potential conflicts with Python packages preinstalled in the main Python +# installation. +# - In order to drop the root user, we have to make some directories world +# writable as OpenShift default security model is to run the container +# under random UID. +RUN \ + python3.9 -m venv ${APP_ROOT} && \ + # Python 3 only code, Python 2 installs pip from PyPI in the assemble script. \ + # We have to upgrade pip to a newer verison because: \ + # * pip < 9 does not support different packages' versions for Python 2/3 \ + # * pip < 19.3 does not support manylinux2014 wheels. Only manylinux2014 (and later) wheels \ + # support platforms like ppc64le, aarch64 or armv7 \ + # We are newly using wheel from one of the latest stable Fedora releases (from RPM python-pip-wheel) \ + # because it's tested better then whatever version from PyPI and contains useful patches. \ + # We have to do it here (in the macro) so the permissions are correctly fixed and pip is able \ + # to reinstall itself in the next build phases in the assemble script if user wants the latest version \ + ${APP_ROOT}/bin/pip install /opt/wheels/pip-* && \ + rm -r /opt/wheels && \ + chown -R 1001:0 ${APP_ROOT} && \ + fix-permissions ${APP_ROOT} -P && \ + rpm-file-permissions + +USER 1001 + +# Set the default CMD to print the usage of the language image. +CMD $STI_SCRIPTS_PATH/usage diff --git a/test/check_imagestreams.py b/test/check_imagestreams.py index d759277..a10476b 100755 --- a/test/check_imagestreams.py +++ b/test/check_imagestreams.py @@ -49,6 +49,9 @@ class ImageStreamChecker(object): def check_version(self, json_dict: Dict[Any, Any]) -> List[str]: res = [] for tags in json_dict["spec"]["tags"]: + print( + f"check_version: Compare tags['name']:'{tags['name']}' against version:'{self.version}'" + ) # The name can be"" or "-elX" or "-ubiX" if tags["name"] == self.version or tags["name"].startswith( self.version + "-" @@ -61,11 +64,15 @@ class ImageStreamChecker(object): for tags in json_dict["spec"]["tags"]: if tags["name"] != "latest": continue + print( + f"check_latest_tag: Compare tags['name']:'{tags['name']}' against version:'{self.version}'" + ) # The latest can link to either "" or "-elX" or "-ubiX" if tags["from"]["name"] == self.version or tags["from"]["name"].startswith( self.version + "-" ): latest_tag_correct = True + print(f"Latest tag found.") return latest_tag_correct def check_imagestreams(self) -> int: diff --git a/test/test-lib-openshift.sh b/test/test-lib-openshift.sh index 96cae8d..7cacd10 100644 --- a/test/test-lib-openshift.sh +++ b/test/test-lib-openshift.sh @@ -5,22 +5,23 @@ source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh # Set of functions for testing docker images in OpenShift using 'oc' command -# A variable containing the overall test result; must be changed to 0 in the end -# of the testing script: -# OS_TESTSUITE_RESULT=0 +# A variable containing the overall test result +# TESTSUITE_RESULT=0 # And the following trap must be set, in the beginning of the test script: # trap ct_os_cleanup EXIT SIGINT -OS_TESTSUITE_RESULT=1 +TESTSUITE_RESULT=0 OS_CLUSTER_STARTED_BY_TEST=0 function ct_os_cleanup() { - echo "${test_short_summary:-}" - if [ $OS_TESTSUITE_RESULT -eq 0 ] ; then + echo "${TEST_SUMMARY:-}" + if [ $TESTSUITE_RESULT -eq 0 ] ; then # shellcheck disable=SC2153 echo "OpenShift tests for ${IMAGE_NAME} succeeded." + exit 0 else # shellcheck disable=SC2153 echo "OpenShift tests for ${IMAGE_NAME} failed." + exit 1 fi } diff --git a/test/test-lib-remote-openshift.sh b/test/test-lib-remote-openshift.sh index bda03f6..0c74f78 100644 --- a/test/test-lib-remote-openshift.sh +++ b/test/test-lib-remote-openshift.sh @@ -5,9 +5,8 @@ source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh # Set of functions for testing docker images in OpenShift using 'oc' command -# A variable containing the overall test result; must be changed to 0 in the end -# of the testing script: -# OS_TESTSUITE_RESULT=0 +# A variable containing the overall test result +# TESTSUITE_RESULT=0 # And the following trap must be set, in the beginning of the test script: # trap ct_os_cleanup EXIT SIGINT @@ -32,13 +31,6 @@ function ct_os_set_path_oc_4() { return 1 fi export PATH="${oc_path}:${PATH}" - oc version - if ! oc version | grep -q "Client Version: ${oc_version}." ; then - echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${oc_version} not found in PATH ($PATH)" >&1 - return 1 - else - echo "PATH set correctly, binary oc found in version ${oc_version}: $(command -v oc)" - fi } # ct_os_prepare_ocp4 @@ -55,10 +47,15 @@ function ct_os_set_ocp4() { OS_OC_CLIENT_VERSION=${OS_OC_CLIENT_VERSION:-4.4} ct_os_set_path_oc_4 "${OS_OC_CLIENT_VERSION}" - oc version - login=$(cat "$KUBEPASSWORD") oc login -u kubeadmin -p "$login" + oc version + if ! oc version | grep -q "Client Version: ${OS_OC_CLIENT_VERSION}." ; then + echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${OS_OC_CLIENT_VERSION} not found in PATH ($PATH)" >&1 + return 1 + else + echo "PATH set correctly, binary oc found in version ${OS_OC_CLIENT_VERSION}: $(command -v oc)" + fi echo "Login to OpenShift ${OS_OC_CLIENT_VERSION} is DONE" # let openshift cluster to sync to avoid some race condition errors sleep 3 diff --git a/test/test-lib.sh b/test/test-lib.sh index e954053..a4042c8 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -16,6 +16,7 @@ # may be redefined in the specific container testfile EXPECTED_EXIT_CODE=0 +export TESTSUITE_RESULT=0 # ct_cleanup # -------------------- @@ -33,12 +34,17 @@ function ct_cleanup() { : "Stopping and removing container $container..." docker stop "$container" - exit_status=$(docker inspect -f '{{.State.ExitCode}}' "$container") - if [ "$exit_status" != "$EXPECTED_EXIT_CODE" ]; then - : "Dumping logs for $container" - docker logs "$container" + + # Container has not been removed by `docker stop` and still exists + if [ $( docker ps -a -f id=$container | wc -l ) -eq 2 ]; then + exit_status=$(docker inspect -f '{{.State.ExitCode}}' "$container") + if [ "$exit_status" != "$EXPECTED_EXIT_CODE" ]; then + : "Dumping logs for $container" + docker logs "$container" + fi + docker rm -v "$container" fi - docker rm -v "$container" + rm "$cid_file" done rmdir "$CID_FILE_DIR" @@ -125,6 +131,7 @@ function ct_check_envs_set { for value in $stripped; do # If the falue checked does not go through env_filter we do not care about it echo "$value" | grep -q "$env_filter" || continue + # shellcheck disable=SC2295 if [ -n "${filtered_envs##${env_format//VALUE/$value}}" ]; then echo " Value $value is missing from variable $var_name" echo "$filtered_envs" @@ -489,21 +496,6 @@ ct_path_foreach () } -# ct_run_test_list -# -------------------- -# Execute the tests specified by TEST_LIST -# Uses: $TEST_LIST - list of test names -function ct_run_test_list() { - for test_case in $TEST_LIST; do - : "Running test $test_case" - # shellcheck source=/dev/null - [ -f "test/$test_case" ] && source "test/$test_case" - # shellcheck source=/dev/null - [ -f "../test/$test_case" ] && source "../test/$test_case" - $test_case - done; -} - # ct_gen_self_signed_cert_pem # --------------------------- # Generates a self-signed PEM certificate pair into specified directory. @@ -1069,4 +1061,45 @@ ct_test_app_dockerfile() { return $ret } +# ct_check_testcase_result +# ----------------------------- +# Check if testcase ended in success or error +# Argument: result - testcase result value +# Uses: $TESTCASE_RESULT - result of the testcase +# Uses: $IMAGE_NAME - name of the image being tested +ct_check_testcase_result() { + local result="$1" + if [[ "$result" != "0" ]]; then + echo "Test for image '${IMAGE_NAME}' FAILED (exit code: ${result})" + TESTCASE_RESULT=1 + fi + return "$result" +} + +# ct_run_tests_from_testset +# ----------------------------- +# Runs all tests in $TEST_SET, prints result to +# the $TEST_SUMMARY variable +# Argument: app_name - application name to log +# Uses: $TEST_SET - set of test cases to run +# Uses: $TEST_SUMMARY - variable for storing test results +# Uses: $IMAGE_NAME - name of the image being tested +ct_run_tests_from_testset() { + local app_name="$1" + for test_case in $TEST_SET; do + TESTCASE_RESULT=0 + echo "Running test $test_case ... " + $test_case + ct_check_testcase_result $? + local test_msg + if [ $TESTCASE_RESULT -eq 0 ]; then + test_msg="[PASSED]" + else + test_msg="[FAILED]" + TESTSUITE_RESULT=1 + fi + printf -v TEST_SUMMARY "%s %s for '%s' %s\n" "${TEST_SUMMARY}" "${test_msg}" "${app_name}" "$test_case" + done; +} + # vim: set tabstop=2:shiftwidth=2:expandtab: