diff --git a/3.9 b/3.9 new file mode 120000 index 0000000..945c9b4 --- /dev/null +++ b/3.9 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/Dockerfile.fedora b/Dockerfile.fedora new file mode 120000 index 0000000..1d1fe94 --- /dev/null +++ b/Dockerfile.fedora @@ -0,0 +1 @@ +Dockerfile \ No newline at end of file diff --git a/README.md b/README.md index 1ab7d2a..425d199 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 registry.fedoraproject.org/f33/python3 +podman pull registry.access.redhat.com/ubi8/python-39 ``` #### 2. Pull and application code @@ -105,7 +105,7 @@ 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 registry.fedoraproject.org/f33/python3 +FROM registry.access.redhat.com/ubi8/python-39 # Add application sources to a directory that the assemble script expects them # and set permissions so that the container runs without root access @@ -125,7 +125,7 @@ If you decide not to use the Source-to-Image scripts, you will need to manually Example Dockerfile for a simple Django application: ``` -FROM registry.fedoraproject.org/f33/python3 +FROM registry.access.redhat.com/ubi8/python-39 # Add application sources with correct permissions for OpenShift USER 0 diff --git a/help.md b/help.md new file mode 120000 index 0000000..42061c0 --- /dev/null +++ b/help.md @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/s2i/bin/run b/s2i/bin/run index ee1e1d3..b5c2441 100755 --- a/s2i/bin/run +++ b/s2i/bin/run @@ -48,25 +48,36 @@ APP_HOME=$(readlink -f "${APP_HOME:-.}") PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}" cd "$APP_HOME" -app_script_check="${APP_SCRIPT-}" -APP_SCRIPT="${APP_SCRIPT-app.sh}" -if [[ -f "$APP_SCRIPT" ]]; then - echo "---> Running application from script ($APP_SCRIPT) ..." - if [[ "$APP_SCRIPT" != /* ]]; then - APP_SCRIPT="./$APP_SCRIPT" - fi - maybe_run_in_init_wrapper "$APP_SCRIPT" -else - test -n "$app_script_check" && (>&2 echo "ERROR: file '$app_script_check' not found.") && exit 1 +if [ -z "$APP_SCRIPT" ] && [ -z "$APP_FILE" ] && [ -z "$APP_MODULE" ]; then + # Set default values for APP_SCRIPT and APP_FILE only when all three APP_ + # variables are not defined by user. This prevents a situation when + # APP_MODULE is defined to app:application but the app.py file is found as the + # APP_FILE and then executed by Python instead of gunicorn. + APP_SCRIPT="app.sh" + APP_SCRIPT_DEFAULT=1 + APP_FILE="app.py" + APP_FILE_DEFAULT=1 fi -app_file_check="${APP_FILE-}" -APP_FILE="${APP_FILE-app.py}" -if [[ -f "$APP_FILE" ]]; then - echo "---> Running application from Python script ($APP_FILE) ..." - maybe_run_in_init_wrapper python "$APP_FILE" -else - test -n "$app_file_check" && (>&2 echo "ERROR: file '$app_file_check' not found.") && exit 1 +if [ ! -z "$APP_SCRIPT" ]; then + if [[ -f "$APP_SCRIPT" ]]; then + echo "---> Running application from script ($APP_SCRIPT) ..." + if [[ "$APP_SCRIPT" != /* ]]; then + APP_SCRIPT="./$APP_SCRIPT" + fi + maybe_run_in_init_wrapper "$APP_SCRIPT" + elif [[ -z "$APP_SCRIPT_DEFAULT" ]]; then + echo "ERROR: file '$APP_SCRIPT' not found." && exit 1 + fi +fi + +if [ ! -z "$APP_FILE" ]; then + if [[ -f "$APP_FILE" ]]; then + echo "---> Running application from Python script ($APP_FILE) ..." + maybe_run_in_init_wrapper python "$APP_FILE" + elif [[ -z "$APP_FILE_DEFAULT" ]]; then + echo "ERROR: file '$APP_FILE' not found." && exit 1 + fi fi # Look for 'manage.py' in the current directory diff --git a/test/app-module-test-app/.gitignore b/test/app-module-test-app/.gitignore new file mode 100644 index 0000000..ba74660 --- /dev/null +++ b/test/app-module-test-app/.gitignore @@ -0,0 +1,57 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ diff --git a/test/app-module-test-app/.s2i/environment b/test/app-module-test-app/.s2i/environment new file mode 100644 index 0000000..ac798d7 --- /dev/null +++ b/test/app-module-test-app/.s2i/environment @@ -0,0 +1 @@ +APP_MODULE=app:application diff --git a/test/app-module-test-app/app.py b/test/app-module-test-app/app.py new file mode 100644 index 0000000..09fee1b --- /dev/null +++ b/test/app-module-test-app/app.py @@ -0,0 +1,4 @@ + +def application(environ, start_response): + start_response('200 OK', [('Content-Type','text/plain')]) + return [b"Hello from gunicorn WSGI application!"] diff --git a/test/app-module-test-app/requirements.txt b/test/app-module-test-app/requirements.txt new file mode 100644 index 0000000..268bd60 --- /dev/null +++ b/test/app-module-test-app/requirements.txt @@ -0,0 +1,2 @@ +gunicorn<20.0.0; python_version < '3.5' +gunicorn>=20.0.0; python_version >= '3.5' \ No newline at end of file diff --git a/test/imagestreams/python-centos.json b/test/imagestreams/python-centos.json index b965fde..1be8538 100644 --- a/test/imagestreams/python-centos.json +++ b/test/imagestreams/python-centos.json @@ -14,7 +14,7 @@ "annotations": { "openshift.io/display-name": "Python (Latest)", "openshift.io/provider-display-name": "Red Hat, Inc.", - "description": "Build and run Python applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.8/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Python available on OpenShift, including major version updates.", + "description": "Build and run Python applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.9/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Python available on OpenShift, including major version updates.", "iconClass": "icon-python", "tags": "builder,python", "supports":"python", @@ -22,7 +22,27 @@ }, "from": { "kind": "ImageStreamTag", - "name": "3.8-ubi8" + "name": "3.9-ubi8" + }, + "referencePolicy": { + "type": "Local" + } + }, + { + "name": "3.9-ubi8", + "annotations": { + "openshift.io/display-name": "Python 3.9 (UBI 8)", + "openshift.io/provider-display-name": "Red Hat, Inc.", + "description": "Build and run Python 3.9 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.9/README.md.", + "iconClass": "icon-python", + "tags": "builder,python", + "supports":"python:3.9,python", + "version": "3.9", + "sampleRepo": "https://github.com/sclorg/django-ex.git" + }, + "from": { + "kind": "DockerImage", + "name": "registry.access.redhat.com/ubi8/python-39:latest" }, "referencePolicy": { "type": "Local" diff --git a/test/imagestreams/python-rhel-aarch64.json b/test/imagestreams/python-rhel-aarch64.json index 1c2ed27..a390935 100644 --- a/test/imagestreams/python-rhel-aarch64.json +++ b/test/imagestreams/python-rhel-aarch64.json @@ -14,7 +14,7 @@ "annotations": { "openshift.io/display-name": "Python (Latest)", "openshift.io/provider-display-name": "Red Hat, Inc.", - "description": "Build and run Python applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.8/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Python available on OpenShift, including major version updates.", + "description": "Build and run Python applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.9/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Python available on OpenShift, including major version updates.", "iconClass": "icon-python", "tags": "builder,python", "supports":"python", @@ -22,7 +22,27 @@ }, "from": { "kind": "ImageStreamTag", - "name": "3.8-ubi8" + "name": "3.9-ubi8" + }, + "referencePolicy": { + "type": "Local" + } + }, + { + "name": "3.9-ubi8", + "annotations": { + "openshift.io/display-name": "Python 3.9 (UBI 8)", + "openshift.io/provider-display-name": "Red Hat, Inc.", + "description": "Build and run Python 3.9 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.9/README.md.", + "iconClass": "icon-python", + "tags": "builder,python", + "supports":"python:3.9,python", + "version": "3.9", + "sampleRepo": "https://github.com/sclorg/django-ex.git" + }, + "from": { + "kind": "DockerImage", + "name": "registry.redhat.io/ubi8/python-39:latest" }, "referencePolicy": { "type": "Local" diff --git a/test/imagestreams/python-rhel.json b/test/imagestreams/python-rhel.json index ce2e080..7522c80 100644 --- a/test/imagestreams/python-rhel.json +++ b/test/imagestreams/python-rhel.json @@ -14,7 +14,7 @@ "annotations": { "openshift.io/display-name": "Python (Latest)", "openshift.io/provider-display-name": "Red Hat, Inc.", - "description": "Build and run Python applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.8/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Python available on OpenShift, including major version updates.", + "description": "Build and run Python applications on UBI. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.9/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Python available on OpenShift, including major version updates.", "iconClass": "icon-python", "tags": "builder,python", "supports":"python", @@ -22,7 +22,27 @@ }, "from": { "kind": "ImageStreamTag", - "name": "3.8-ubi8" + "name": "3.9-ubi8" + }, + "referencePolicy": { + "type": "Local" + } + }, + { + "name": "3.9-ubi8", + "annotations": { + "openshift.io/display-name": "Python 3.9 (UBI 8)", + "openshift.io/provider-display-name": "Red Hat, Inc.", + "description": "Build and run Python 3.9 applications on UBI 8. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.9/README.md.", + "iconClass": "icon-python", + "tags": "builder,python", + "supports":"python:3.9,python", + "version": "3.9", + "sampleRepo": "https://github.com/sclorg/django-ex.git" + }, + "from": { + "kind": "DockerImage", + "name": "registry.redhat.io/ubi8/python-39:latest" }, "referencePolicy": { "type": "Local" diff --git a/test/run b/test/run index c972458..d14e9a7 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=({standalone,setup,setup-requirements,django,numpy,app-home,npm-virtualenv-uwsgi,locale,mod-wsgi,pipenv,pipenv-and-micropipenv-should-fail,pin-pipenv-version,micropipenv,micropipenv-requirements}-test-app) +declare -a WEB_APPS=({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) # TODO: Make command compatible for Mac users test_dir="$(readlink -zf $(dirname "${BASH_SOURCE[0]}"))" @@ -219,7 +219,8 @@ test_from_dockerfile(){ # 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 + + if [[ ${VERSION} == "2.7" ]] || docker inspect ${IMAGE_NAME} --format "{{.Config.Env}}" | tr " " "\n" | grep -q "^PLATFORM=el7"; 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" diff --git a/test/run-openshift-remote-cluster b/test/run-openshift-remote-cluster new file mode 100755 index 0000000..b810752 --- /dev/null +++ b/test/run-openshift-remote-cluster @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Test the Python image in the OpenShift. +# +# IMAGE_NAME specifies a name of the candidate image used for testing. +# VERSION specifies a version of the python in the candidate image. +# The image has to be available before this script is executed. + +THISDIR=$(dirname ${BASH_SOURCE[0]}) + +source "${THISDIR}/test-lib.sh" +source "${THISDIR}/test-lib-openshift.sh" +source "${THISDIR}/test-lib-python.sh" +source "${THISDIR}/test-lib-remote-openshift.sh" + +set -eo nounset +ct_os_set_ocp4 + + +trap ct_os_cleanup EXIT SIGINT + +ct_os_check_compulsory_vars + +oc status || false "It looks like oc is not properly logged in." + +# For testing on OpenShift 4 we use internal registry +export CT_EXTERNAL_REGISTRY=true + +test -n "${IMAGE_NAME-}" || false 'make sure $IMAGE_NAME is defined' +test -n "${VERSION-}" || false 'make sure $VERSION is defined' + +if [ -z "${EPHEMERAL_TEMPLATES:-}" ]; then + EPHEMERAL_TEMPLATES=" +https://raw.githubusercontent.com/sclorg/django-ex/master/openshift/templates/django-postgresql.json \ +https://raw.githubusercontent.com/openshift/origin/master/examples/quickstarts/django-postgresql.json" +fi + +ct_os_test_s2i_app "${IMAGE_NAME}" "https://github.com/sclorg/s2i-python-container.git" "examples/standalone-test-app" "Hello World from standalone WSGI application!" +ct_os_test_s2i_app "${IMAGE_NAME}" "https://github.com/sclorg/django-ex.git" . 'Welcome to your Django application on OpenShift' + +for template in $EPHEMERAL_TEMPLATES; do + ct_os_test_template_app "$IMAGE_NAME" \ + "$template" \ + python \ + 'Welcome to your Django application on OpenShift' \ + 8080 http 200 "-p SOURCE_REPOSITORY_REF=master -p PYTHON_VERSION=${VERSION} -p POSTGRESQL_VERSION=10 -p NAME=python-testing" \ + "rhscl/postgresql-10-rhel7|postgresql:10" +done + +# Check the imagestream +test_python_imagestream + +OS_TESTSUITE_RESULT=0 + +# vim: set tabstop=2:shiftwidth=2:expandtab: + diff --git a/test/test-lib-openshift.sh b/test/test-lib-openshift.sh index 5405926..1135ad7 100644 --- a/test/test-lib-openshift.sh +++ b/test/test-lib-openshift.sh @@ -1255,7 +1255,7 @@ function ct_os_test_image_stream_quickstart() { # In case we are testing on OpenShift 4 export variable for mirror image # which means, that image is going to be mirrored from an internal registry into OpenShift 4 if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ]; then - export CT_MIRROR_IMAGE=true + export CT_TAG_IMAGE=true fi # ct_os_test_template_app creates a new project, but we already need # it before for the image stream import, so tell it to skip this time diff --git a/test/test-lib-python.sh b/test/test-lib-python.sh index 09f0baf..25a9c1e 100644 --- a/test/test-lib-python.sh +++ b/test/test-lib-python.sh @@ -24,7 +24,7 @@ function test_python_imagestream() { 'python' \ 'Welcome to your Django application on OpenShift' \ 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" + "rhscl/postgresql-10-rhel7|postgresql:10" } # vim: set tabstop=2:shiftwidth=2:expandtab: diff --git a/test/test-lib-remote-openshift.sh b/test/test-lib-remote-openshift.sh new file mode 100644 index 0000000..fd9a684 --- /dev/null +++ b/test/test-lib-remote-openshift.sh @@ -0,0 +1,112 @@ +# shellcheck shell=bash +# some functions are used from test-lib.sh, that is usually in the same dir +# shellcheck source=/dev/null +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 +# And the following trap must be set, in the beginning of the test script: +# trap ct_os_cleanup EXIT SIGINT + +# ct_os_set_path_oc_4 OC_VERSION +# -------------------- +# This is a trick that helps using correct version 4 of the `oc`: +# The input is version of the openshift in format 4.4 etc. +# If the currently available version of oc is not of this version, +# it first takes a look into /usr/local/oc-/bin directory, + +# Arguments: oc_version - X.Y part of the version of OSE (e.g. 3.9) +function ct_os_set_path_oc_4() { + echo "Setting OCP4 client" + local oc_version=$1 + local installed_oc_path="/usr/local/oc-v${oc_version}/bin" + echo "PATH ${installed_oc_path}" + if [ -x "${installed_oc_path}/oc" ] ; then + oc_path="${installed_oc_path}" + echo "Binary oc found in ${installed_oc_path}" >&2 + else + echo "OCP4 not found" + 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 +# ------------------ +# Prepares environment for testing images in OpenShift 4 environment +# +# +function ct_os_set_ocp4() { + local login + 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" + echo "Login to OpenShift ${OS_OC_CLIENT_VERSION} is DONE" + # let openshift cluster to sync to avoid some race condition errors + sleep 3 +} + +function ct_os_upload_image_external_registry() { + local input_name="${1}" ; shift + local image_name=${input_name##*/} + local imagestream=${1:-$image_name:latest} + local output_name + + ct_os_login_external_registry + + output_name="${INTERNAL_DOCKER_REGISTRY}/rhscl-ci-testing/$imagestream" + + docker images + docker tag "${input_name}" "${output_name}" + docker push "${output_name}" +} + + +function ct_os_login_external_registry() { + local docker_token + # docker login fails with "404 page not found" error sometimes, just try it more times + # shellcheck disable=SC2034 + echo "loging" + [ -z "${INTERNAL_DOCKER_REGISTRY:-}" ] && "INTERNAL_DOCKER_REGISTRY has to be set for working with Internal registry" && return 1 + # shellcheck disable=SC2034 + for i in $(seq 12) ; do + # shellcheck disable=SC2015 + docker_token=$(cat "$DOCKER_UPSHIFT_TOKEN") + # shellcheck disable=SC2015 + docker login -u rhscl-ci-testing -p "$docker_token" "${INTERNAL_DOCKER_REGISTRY}" && return 0 || : + sleep 5 + done + return 1 +} + +function ct_os_import_image_ocp4() { + local image_name="${1}"; shift + local imagestream=${1:-$image_name:latest} + local namespace + + namespace=${CT_NAMESPACE:-"$(oc project -q)"} + deploy_image_name="${INTERNAL_DOCKER_REGISTRY}/rhscl-ci-testing/${imagestream}" + echo "Uploading image ${image_name} as ${deploy_image_name} , ${imagestream} into external registry." + ct_os_upload_image_external_registry "${image_name}" "${imagestream}" + if [ "${CT_TAG_IMAGE:-false}" == 'true' ]; then + echo "Tag ${deploy_image_name} to ${namespace}/${imagestream}" + oc tag --source=docker "${deploy_image_name}" "${namespace}/${imagestream}" --insecure=true --reference-policy=local + else + echo "Import image into OpenShift 4 environment ${namespace}/${imagestream} from ${deploy_image_name}" + oc import-image "${namespace}/${imagestream}" --from="${deploy_image_name}" --confirm --reference-policy=local + fi +}