diff --git a/README.md b/README.md index 2491fae..31c9cc5 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Python 3.9 container image This container image includes Python 3.9 as a [S2I](https://github.com/openshift/source-to-image) base image for your Python 3.9 applications. Users can choose between RHEL and CentOS based builder images. -The RHEL images are available in the [Red Hat Container Catalog](https://access.redhat.com/containers/), +The RHEL images are available in the [Red Hat Container Catalog](https://catalog.redhat.com/software/containers/explore), the CentOS images are available on [Quay.io](https://quay.io/organization/centos7), and the Fedora images are available in [Fedora Registry](https://registry.fedoraproject.org/). The resulting image can be run using [podman](https://github.com/containers/libpod) or @@ -219,7 +219,7 @@ file inside your source code repository. * **DISABLE_SETUP_PY_PROCESSING** - Set this to a non-empty value to skip processing of setup.py script if you + Set this to a non-empty value to skip processing of setup.{py,cfg} script if you use `-e .` in requirements.txt to trigger its processing or you don't want your application to be installed into site-packages directory. @@ -304,7 +304,7 @@ However, if these files exist they will affect the behavior of the build process Configures various aspects of the project, including installation of dependencies, as documented - [here](https://packaging.python.org/en/latest/distributing.html#setup-py). + [here](https://packaging.python.org/guides/distributing-packages-using-setuptools/?highlight=distributing#setup-py). For most projects, it is sufficient to simply use `requirements.txt` or `Pipfile`. Set `DISABLE_SETUP_PY_PROCESSING` environment variable to true in order to skip processing of this file. @@ -366,7 +366,7 @@ option set to `true`. Make sure to specify your config via the `APP_CONFIG` environment variable. To change your source code in running container, use podman's (or docker's) -[exec](https://github.com/containers/libpod/blob/master/docs/podman-exec.1.md) command: +[exec](https://github.com/containers/podman/blob/main/docs/source/markdown/podman-exec.1.md) command: ``` podman exec -it /bin/bash diff --git a/s2i/bin/assemble b/s2i/bin/assemble index 3d36bdd..18c8373 100755 --- a/s2i/bin/assemble +++ b/s2i/bin/assemble @@ -85,7 +85,7 @@ elif [[ -f requirements.txt ]]; then pip install -r requirements.txt fi -if [[ -f setup.py && -z "$DISABLE_SETUP_PY_PROCESSING" ]]; then +if [[ ( -f setup.py || -f setup.cfg ) && -z "$DISABLE_SETUP_PY_PROCESSING" ]]; then echo "---> Installing application ..." pip install . fi diff --git a/test/from-dockerfile/Dockerfile.tpl b/test/from-dockerfile/Dockerfile.tpl index a44d41d..4249e1e 100644 --- a/test/from-dockerfile/Dockerfile.tpl +++ b/test/from-dockerfile/Dockerfile.tpl @@ -1,4 +1,4 @@ -FROM #IMAGE_NAME# # Replaced by sed in tests, see test_from_dockerfile in test/run +FROM #IMAGE_NAME# # Replaced by sed in ct_test_app_dockerfile # Add application sources to a directory that the assemble script expects them # and set permissions so that the container runs without root access diff --git a/test/from-dockerfile/Dockerfile_no_s2i.tpl b/test/from-dockerfile/Dockerfile_no_s2i.tpl index 7f073a6..da2f43f 100644 --- a/test/from-dockerfile/Dockerfile_no_s2i.tpl +++ b/test/from-dockerfile/Dockerfile_no_s2i.tpl @@ -1,4 +1,4 @@ -FROM #IMAGE_NAME# # Replaced by sed in tests, see test_from_dockerfile in test/run +FROM #IMAGE_NAME# # Replaced by sed in ct_test_app_dockerfile # Add application sources with correct permissions for OpenShift USER 0 diff --git a/test/run b/test/run index 291c3df..e374dca 100755 --- a/test/run +++ b/test/run @@ -6,7 +6,7 @@ # IMAGE_NAME specifies a name of the candidate image used for testing. # The image has to be available before this script is executed. # -declare -a WEB_APPS=({gunicorn-config-different-port,gunicorn-different-port,django-different-port,standalone,setup,setup-requirements,django,numpy,app-home,npm-virtualenv-uwsgi,locale,mod-wsgi,pipenv,pipenv-and-micropipenv-should-fail,pin-pipenv-version,app-module,micropipenv,micropipenv-requirements}-test-app) +declare -a WEB_APPS=({gunicorn-config-different-port,gunicorn-different-port,django-different-port,standalone,setup,setup-cfg,setup-requirements,django,numpy,app-home,npm-virtualenv-uwsgi,locale,mod-wsgi,pipenv,pipenv-and-micropipenv-should-fail,pin-pipenv-version,app-module,micropipenv,micropipenv-requirements}-test-app) # TODO: Make command compatible for Mac users test_dir="$(readlink -zf $(dirname "${BASH_SOURCE[0]}"))" @@ -223,13 +223,11 @@ test_from_dockerfile(){ 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 $django_example_repo_url 'Welcome to your Django application on OpenShift' app-src + ct_test_app_dockerfile $test_dir/from-dockerfile/Dockerfile.tpl $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 + ct_test_app_dockerfile $test_dir/from-dockerfile/Dockerfile_no_s2i.tpl $django_example_repo_url 'Welcome to your Django application on OpenShift' app-src check_result $? } diff --git a/test/test-lib-openshift.sh b/test/test-lib-openshift.sh index 1135ad7..fa15eae 100644 --- a/test/test-lib-openshift.sh +++ b/test/test-lib-openshift.sh @@ -150,6 +150,16 @@ function ct_os_get_build_pod_status() { | sort -u | awk '{print $2}' | tail -n 1 } +# ct_os_get_buildconfig_pod_name POD_PREFIX +# ---------------------------- +# Returns status of the buildconfig pod specified by prefix [pod_prefix]. +# Argument: pod_prefix - prefix +function ct_os_get_buildconfig_pod_name() { + local pod_prefix="${1}" ; shift + local query="custom-columns=NAME:.metadata.name" + oc get bc -o "$query" | grep -e "${pod_prefix}" | sort -u | tail -n 1 +} + # ct_os_get_pod_name POD_PREFIX # -------------------- # Returns the full name of pods specified by prefix [pod_prefix]. @@ -169,6 +179,22 @@ function ct_os_get_pod_ip() { oc get pod "$pod_name" --no-headers -o custom-columns=IP:status.podIP } +# ct_os_get_sti_build_logs +# ----------------- +# Return logs from sti_build +# Arguments: pod_name +function ct_os_get_sti_build_logs() { + local pod_prefix="${1}" + pod_name=$(ct_os_get_buildconfig_pod_name "${pod_prefix}") + # Print logs but do not failed. Just for traces + if [ x"${pod_name}" != "x" ]; then + oc logs "bc/$pod_name" || return 0 + else + echo "Build config bc/$pod_name does not exist for some reason." + echo "Import probably failed." + fi +} + # ct_os_check_pod_readiness POD_PREFIX STATUS # -------------------- # Checks whether the pod is ready. @@ -195,7 +221,12 @@ function ct_os_wait_pod_ready() { echo -n "Waiting for ${pod_prefix} build pod to finish ..." while ! [ "$(ct_os_get_build_pod_status "${pod_prefix}")" == "Succeeded" ] ; do echo -n "." - [ "${SECONDS}" -gt "${timeout}0" ] && echo " FAIL" && return 1 + if [ "${SECONDS}" -gt "${timeout}0" ]; then + echo " FAIL" + ct_os_print_logs || : + ct_os_get_sti_build_logs "${pod_prefix}" || : + return 1 + fi sleep 3 done echo " DONE" @@ -204,7 +235,12 @@ function ct_os_wait_pod_ready() { echo -n "Waiting for ${pod_prefix} pod becoming ready ..." while ! ct_os_check_pod_readiness "${pod_prefix}" "true" ; do echo -n "." - [ "${SECONDS}" -gt "${timeout}" ] && echo " FAIL" && return 1 + if [ "${SECONDS}" -gt "${timeout}" ]; then + echo " FAIL"; + ct_os_print_logs || : + ct_os_get_sti_build_logs "${pod_prefix}" || : + return 1 + fi sleep 3 done echo " DONE" @@ -223,7 +259,12 @@ function ct_os_wait_rc_ready() { while ! test "$( (oc get --no-headers statefulsets; oc get --no-headers rc) 2>/dev/null \ | grep "^${pod_prefix}" | awk '$2==$3 {print "ready"}')" == "ready" ; do echo -n "." - [ "${SECONDS}" -gt "${timeout}" ] && echo " FAIL" && return 1 + if [ "${SECONDS}" -gt "${timeout}" ]; then + echo " FAIL"; + ct_os_print_logs || : + ct_os_get_sti_build_logs "${pod_prefix}" || : + return 1 + fi sleep 3 done echo " DONE" @@ -331,7 +372,12 @@ function ct_os_delete_project() { return fi local project_name="${1:-$(oc project -q)}" ; shift || : - oc delete project "${project_name}" + if oc delete project "${project_name}" ; then + echo "Project ${project_name} was deleted properly" + else + echo "Project ${project_name} was not delete properly. But it does not block CI." + fi + } # ct_delete_all_objects diff --git a/test/test-lib.sh b/test/test-lib.sh index cc046a9..b219ffd 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -827,7 +827,7 @@ ct_show_resources() # ----------------------------- # Argument: dockerfile - path to a Dockerfile that will be used for building an image # (must work with an application directory called 'app-src') -# Argument: app_url - git URI with a testing application, supports "@" to indicate a different branch +# Argument: app_url - git or local URI with a testing application, supports "@" to indicate a different branch # Argument: body_regexp - PCRE regular expression that must match the response body # Argument: app_dir - name of the application directory that is used in the Dockerfile # Argument: port - Optional port number (default: 8080) @@ -865,20 +865,25 @@ ct_test_app_dockerfile() { echo "Using this Dockerfile:" cat Dockerfile - # 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}" + if [ -d "$app_url" ] ; then + echo "Copying local folder: $app_url -> $app_dir." + cp -Lr $app_url $app_dir else - git_clone_cmd="git clone ${app_url} ${app_dir}" - fi + # 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 ! $git_clone_cmd ; then - echo "ERROR: Git repository ${app_url} cannot be cloned into ${app_dir}." - echo "Terminating the Dockerfile build." - return 1 + 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}." + echo "Terminating the Dockerfile build." + return 1 + fi fi echo "Building '${app_image_name}' image using docker build"