Compare commits
22 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b15883749c | ||
|
|
a90dbdb3b9 | ||
|
|
3e4304f1ee | ||
|
|
edec83e85e | ||
|
|
9e2a157e7c | ||
|
|
b3bc61b518 | ||
|
|
50eeefac49 | ||
|
|
3402cd789a | ||
|
|
fb5763a161 | ||
|
|
fdf8f9b035 | ||
|
|
896a5dcee2 | ||
|
|
61373b3322 | ||
|
|
7d867c91ad | ||
|
|
d86a7a9c0e | ||
|
|
8fb112e5e4 | ||
|
|
72f4f216bb | ||
|
|
b0910418b6 | ||
|
|
584be66e16 | ||
|
|
7bea193d56 | ||
|
|
4fb1f66d7a | ||
|
|
1425f4c95f | ||
|
|
c1cc83f38d |
103 changed files with 6056 additions and 1 deletions
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
1
3.10
Symbolic link
1
3.10
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
./
|
||||
90
Dockerfile
Normal file
90
Dockerfile
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# This image provides a Python 3.10 environment you can use to run your Python
|
||||
# applications.
|
||||
FROM registry.fedoraproject.org/f35/s2i-base:latest
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENV PYTHON_VERSION=3.10 \
|
||||
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 NAME=python3 \
|
||||
VERSION=0 \
|
||||
ARCH=x86_64
|
||||
|
||||
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.10" \
|
||||
io.openshift.expose-services="8080:http" \
|
||||
io.openshift.tags="builder,python,python310,python-310,rh-python310" \
|
||||
com.redhat.component="$NAME" \
|
||||
name="$FGC/$NAME" \
|
||||
version="$VERSION" \
|
||||
usage="s2i build https://github.com/sclorg/s2i-python-container.git --context-dir=3.10/test/setup-test-app/ $FGC/$NAME python-sample-app" \
|
||||
maintainer="SoftwareCollections.org <sclorg@redhat.com>"
|
||||
|
||||
RUN INSTALL_PKGS="python3 python3-devel python3-setuptools python3-pip nss_wrapper \
|
||||
httpd httpd-devel atlas-devel gcc-gfortran libffi-devel \
|
||||
libtool-ltdl enchant redhat-rpm-config" && \
|
||||
dnf -y --setopt=tsflags=nodocs install $INSTALL_PKGS && \
|
||||
rpm -V $INSTALL_PKGS && \
|
||||
dnf -y clean all --enablerepo='*'
|
||||
|
||||
# Copy the S2I scripts from the specific language image to $STI_SCRIPTS_PATH.
|
||||
COPY 3.10/s2i/bin/ $STI_SCRIPTS_PATH
|
||||
|
||||
# Copy extra files to the image.
|
||||
COPY 3.10/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.10/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.10 -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
|
||||
|
||||
# For Fedora scl_enable isn't sourced automatically in s2i-core
|
||||
# so virtualenv needs to be activated this way
|
||||
ENV BASH_ENV="${APP_ROOT}/bin/activate" \
|
||||
ENV="${APP_ROOT}/bin/activate" \
|
||||
PROMPT_COMMAND=". ${APP_ROOT}/bin/activate"
|
||||
|
||||
USER 1001
|
||||
|
||||
# Set the default CMD to print the usage of the language image.
|
||||
CMD $STI_SCRIPTS_PATH/usage
|
||||
1
Dockerfile.fedora
Symbolic link
1
Dockerfile.fedora
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
Dockerfile
|
||||
384
README.md
Normal file
384
README.md
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
Python 3.10 container image
|
||||
=========================
|
||||
|
||||
This container image includes Python 3.10 as a [S2I](https://github.com/openshift/source-to-image) base image for your Python 3.10 applications.
|
||||
Users can choose between RHEL and CentOS based builder images.
|
||||
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
|
||||
[docker](http://docker.io).
|
||||
|
||||
Note: while the examples in this README are calling `podman`, you can replace any such calls by `docker` with the same arguments
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Python 3.10 available as container is a base platform for
|
||||
building and running various Python 3.10 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.
|
||||
|
||||
This container image includes an npm utility
|
||||
(see [base image repository](https://github.com/sclorg/s2i-base-container/tree/master/base)),
|
||||
so users can use it to install JavaScript
|
||||
modules for their web applications. There is no guarantee for any specific npm or nodejs
|
||||
version, that is included in the image; those versions can be changed anytime and
|
||||
the nodejs itself is included just to make the npm work.
|
||||
|
||||
Usage in Openshift
|
||||
------------------
|
||||
|
||||
For this, we will assume that you are using the supported image, available via `python:3.10` imagestream tag in Openshift.
|
||||
Building a simple [python-sample-app](https://github.com/sclorg/django-ex.git) application
|
||||
in Openshift can be achieved with the following step:
|
||||
|
||||
```
|
||||
oc new-app python:3.10~https://github.com/sclorg/django-ex.git
|
||||
```
|
||||
|
||||
**Accessing the application:**
|
||||
```
|
||||
$ oc get pods
|
||||
$ oc exec <pod> -- curl 127.0.0.1:8080
|
||||
```
|
||||
|
||||
Source-to-Image framework and scripts
|
||||
-------------------------------------
|
||||
This image supports the [Source-to-Image](https://docs.openshift.com/container-platform/3.11/creating_images/s2i.html)
|
||||
(S2I) strategy in OpenShift. The Source-to-Image is an OpenShift framework
|
||||
which makes it easy to write images that take application source code as
|
||||
an input, use a builder image like this Python container image, and produce
|
||||
a new image that runs the assembled application as an output.
|
||||
|
||||
To support the Source-to-Image framework, important scripts are included in the builder image:
|
||||
|
||||
* The `/usr/libexec/s2i/assemble` script inside the image is run to produce a new image with the application artifacts.
|
||||
The script takes sources of a given application and places them into appropriate directories inside the image.
|
||||
It utilizes some common patterns in Perl application development (see the **Environment variables** section below).
|
||||
* The `/usr/libexec/s2i/run` script is set as the default command in the resulting container image (the new image with the application artifacts).
|
||||
It runs your application according to settings in `APP_MODULE`, `APP_FILE` or `APP_SCRIPT` environment variables or it tries to detect the best
|
||||
way automatically.
|
||||
|
||||
Building an application using a Dockerfile
|
||||
------------------------------------------
|
||||
Compared to the Source-to-Image strategy, using a Dockerfile is a more
|
||||
flexible way to build a Python container image with an application.
|
||||
Use a Dockerfile when Source-to-Image is not sufficiently flexible for you or
|
||||
when you build the image outside of the OpenShift environment.
|
||||
|
||||
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/f35/python3
|
||||
```
|
||||
|
||||
#### 2. Pull and application code
|
||||
|
||||
An example application available at https://github.com/sclorg/django-ex.git is used here. Feel free to clone the repository for further experiments.
|
||||
You can also take a look at code examples in s2i-python-container repository: https://github.com/sclorg/s2i-python-container/tree/master/examples
|
||||
|
||||
```
|
||||
git clone https://github.com/sclorg/django-ex.git app-src
|
||||
```
|
||||
|
||||
#### 3. Prepare an application inside a container
|
||||
|
||||
This step usually consists of at least these parts:
|
||||
|
||||
* putting the application source into the container
|
||||
* installing the dependencies
|
||||
* setting the default command in the resulting image
|
||||
|
||||
For all these three parts, users can either setup all manually and use commands `python` and `pip` explicitly in the Dockerfile,
|
||||
or users can use the Source-to-Image scripts inside the image.
|
||||
|
||||
The manual way comes with the highest level of flexibility but requires you to know how to work
|
||||
with modules or software collections manually, how to setup virtual environment with the right version
|
||||
of Python and many more. On the other hand, using Source-to-Image scripts makes your Dockerfile
|
||||
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/f35/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 /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/f35/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
|
||||
|
||||
```
|
||||
podman build -t python-app .
|
||||
```
|
||||
|
||||
#### 5. Run the resulting image with final application
|
||||
|
||||
```
|
||||
podman run -d python-app
|
||||
```
|
||||
|
||||
Environment variables
|
||||
---------------------
|
||||
|
||||
To set these environment variables, you can place them as a key value pair into a `.s2i/environment`
|
||||
file inside your source code repository.
|
||||
|
||||
* **APP_SCRIPT**
|
||||
|
||||
Used to run the application from a script file.
|
||||
This should be a path to a script file (defaults to `app.sh` unless set to null) that will be
|
||||
run to start the application.
|
||||
|
||||
* **APP_FILE**
|
||||
|
||||
Used to run the application from a Python script.
|
||||
This should be a path to a Python file (defaults to `app.py` unless set to null) that will be
|
||||
passed to the Python interpreter to start the application.
|
||||
|
||||
* **APP_MODULE**
|
||||
|
||||
Used to run the application with Gunicorn, as documented
|
||||
[here](http://docs.gunicorn.org/en/latest/run.html#gunicorn).
|
||||
This variable specifies a WSGI callable with the pattern
|
||||
`MODULE_NAME:VARIABLE_NAME`, where `MODULE_NAME` is the full dotted path
|
||||
of a module, and `VARIABLE_NAME` refers to a WSGI callable inside the
|
||||
specified module.
|
||||
Gunicorn will look for a WSGI callable named `application` if not specified.
|
||||
|
||||
If `APP_MODULE` is not provided, the `run` script will look for a `wsgi.py`
|
||||
file in your project and use it if it exists.
|
||||
|
||||
If using `setup.py` for installing the application, the `MODULE_NAME` part
|
||||
can be read from there. For an example, see
|
||||
[setup-test-app](https://github.com/sclorg/s2i-python-container/tree/master/3.10/test/setup-test-app).
|
||||
|
||||
* **APP_HOME**
|
||||
|
||||
This variable can be used to specify a sub-directory in which the application to be run is contained.
|
||||
The directory pointed to by this variable needs to contain `wsgi.py` (for Gunicorn) or `manage.py` (for Django).
|
||||
|
||||
If `APP_HOME` is not provided, the `assemble` and `run` scripts will use the application's root
|
||||
directory.
|
||||
|
||||
* **APP_CONFIG**
|
||||
|
||||
Path to a valid Python file with a
|
||||
[Gunicorn configuration](http://docs.gunicorn.org/en/latest/configure.html#configuration-file) file.
|
||||
|
||||
* **DISABLE_MIGRATE**
|
||||
|
||||
Set this variable to a non-empty value to inhibit the execution of 'manage.py migrate'
|
||||
when the produced image is run. This only affects Django projects. See
|
||||
"Handling Database Migrations" section of [Django blogpost on OpenShift blog](
|
||||
https://blog.openshift.com/migrating-django-applications-openshift-3/) on suggestions
|
||||
how/when to run DB migrations in OpenShift environment. Most importantly,
|
||||
note that running DB migrations from two or more pods might corrupt your database.
|
||||
|
||||
* **DISABLE_COLLECTSTATIC**
|
||||
|
||||
Set this variable to a non-empty value to inhibit the execution of
|
||||
'manage.py collectstatic' during the build. This only affects Django projects.
|
||||
|
||||
* **DISABLE_SETUP_PY_PROCESSING**
|
||||
|
||||
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.
|
||||
|
||||
* **ENABLE_PIPENV**
|
||||
|
||||
Set this variable to use [Pipenv](https://github.com/pypa/pipenv),
|
||||
the higher-level Python packaging tool, to manage dependencies of the application.
|
||||
This should be used only if your project contains properly formated Pipfile
|
||||
and Pipfile.lock.
|
||||
* **PIN_PIPENV_VERSION**
|
||||
|
||||
Set this variable together with `ENABLE_PIPENV` to use a specific version of Pipenv.
|
||||
If not set, the latest stable version from PyPI is installed.
|
||||
For example `PIN_PIPENV_VERSION=2018.11.26` installs `pipenv==2018.11.26`.
|
||||
|
||||
* **ENABLE_MICROPIPENV**
|
||||
|
||||
Set this variable to use [micropipenv](https://github.com/thoth-station/micropipenv),
|
||||
a lightweight wrapper for pip to support requirements.txt, Pipenv and Poetry lock
|
||||
files or converting them to pip-tools compatible output. Designed for containerized Python applications.
|
||||
Available only for Python 3 images.
|
||||
|
||||
* **ENABLE_INIT_WRAPPER**
|
||||
|
||||
Set this variable to a non-empty value to make use of an init wrapper.
|
||||
This is useful for servers that are not capable of reaping zombie
|
||||
processes, such as Django development server or Tornado. This option can
|
||||
be used together with **APP_SCRIPT** or **APP_FILE**. It never applies
|
||||
to Gunicorn used through **APP_MODULE** as Gunicorn reaps zombie
|
||||
processes correctly.
|
||||
|
||||
* **PIP_INDEX_URL**
|
||||
|
||||
Set this variable to use a custom index URL or mirror to download required
|
||||
packages during build process. This affects packages listed in
|
||||
requirements.txt. It also affects the installation of pipenv and
|
||||
micropipenv and the update of pip in the container, though if not found in
|
||||
the custom index, the container will try to install/update them from
|
||||
upstream PyPI afterwards.
|
||||
|
||||
* **PORT**
|
||||
|
||||
HTTP(S) port your application should listen on. The default is 8080.
|
||||
`PORT` is used only for Django development server and for Gunicorn
|
||||
with the default configutation (no `APP_CONFIG` or `GUNICORN_CMD_ARGS` specified).
|
||||
|
||||
* **UPGRADE_PIP_TO_LATEST**
|
||||
|
||||
Set this variable to a non-empty value to have the 'pip' program and related
|
||||
python packages (setuptools and wheel) be upgraded to the most recent version
|
||||
before any Python packages are installed. If not set, the container will use
|
||||
the stable pip version this container was built with, taken from a recent Fedora release.
|
||||
|
||||
* **WEB_CONCURRENCY**
|
||||
|
||||
Set this to change the default setting for the number of
|
||||
[workers](http://docs.gunicorn.org/en/stable/settings.html#workers). By
|
||||
default, this is set to the number of available cores times 2, capped
|
||||
at 12.
|
||||
|
||||
|
||||
Source repository layout
|
||||
------------------------
|
||||
|
||||
You do not need to change anything in your existing Python project's repository.
|
||||
However, if these files exist they will affect the behavior of the build process:
|
||||
|
||||
* **requirements.txt**
|
||||
|
||||
List of dependencies to be installed with `pip`. The format is documented
|
||||
[here](https://pip.pypa.io/en/latest/user_guide.html#requirements-files).
|
||||
|
||||
|
||||
* **Pipfile**
|
||||
|
||||
The replacement for requirements.txt, project is currently under active
|
||||
design and development, as documented [here](https://github.com/pypa/pipfile).
|
||||
Set `ENABLE_PIPENV` environment variable to true in order to process this file.
|
||||
|
||||
|
||||
* **setup.py**
|
||||
|
||||
Configures various aspects of the project, including installation of
|
||||
dependencies, as documented
|
||||
[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.
|
||||
|
||||
Run strategies
|
||||
--------------
|
||||
|
||||
The container image produced by s2i-python executes your project in one of the
|
||||
following ways, in precedence order:
|
||||
|
||||
* **Gunicorn**
|
||||
|
||||
The Gunicorn WSGI HTTP server is used to serve your application in the case that it
|
||||
is installed. It can be installed by listing it either in the `requirements.txt`
|
||||
file or in the `install_requires` section of the `setup.py` file.
|
||||
|
||||
If a file named `wsgi.py` is present in your repository, it will be used as
|
||||
the entry point to your application. This can be overridden with the
|
||||
environment variable `APP_MODULE`.
|
||||
This file is present in Django projects by default.
|
||||
|
||||
If you have both Django and Gunicorn in your requirements, your Django project
|
||||
will automatically be served using Gunicorn.
|
||||
|
||||
The default setting for Gunicorn (`--bind=0.0.0.0:$PORT --access-logfile=-`) is applied
|
||||
only if both `$APP_CONFIG` and `$GUNICORN_CMD_ARGS` are not defined.
|
||||
|
||||
* **Django development server**
|
||||
|
||||
If you have Django in your requirements but don't have Gunicorn, then your
|
||||
application will be served using Django's development web server. However, this is not
|
||||
recommended for production environments.
|
||||
|
||||
* **Python script**
|
||||
|
||||
This would be used where you provide a Python code file for running you
|
||||
application. It will be used in the case where you specify a path to a
|
||||
Python script via the `APP_FILE` environment variable, defaulting to a
|
||||
file named `app.py` if it exists. The script is passed to a regular
|
||||
Python interpreter to launch your application.
|
||||
|
||||
* **Application script file**
|
||||
|
||||
This is the most general way of executing your application. It will be
|
||||
used in the case where you specify a path to an executable script file
|
||||
via the `APP_SCRIPT` environment variable, defaulting to a file named
|
||||
`app.sh` if it exists. The script is executed directly to launch your
|
||||
application.
|
||||
|
||||
Hot deploy
|
||||
----------
|
||||
|
||||
If you are using Django, hot deploy will work out of the box.
|
||||
|
||||
To enable hot deploy while using Gunicorn, make sure you have a Gunicorn
|
||||
configuration file inside your repository with the
|
||||
[`reload`](https://gunicorn-docs.readthedocs.org/en/latest/settings.html#reload)
|
||||
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/podman/blob/main/docs/source/markdown/podman-exec.1.md) command:
|
||||
|
||||
```
|
||||
podman exec -it <CONTAINER_ID> /bin/bash
|
||||
```
|
||||
|
||||
After you enter into the running container, your current directory is set
|
||||
to `/opt/app-root/src`, where the source code is located.
|
||||
|
||||
|
||||
See also
|
||||
--------
|
||||
Dockerfile and other sources are available on https://github.com/sclorg/s2i-python-container.
|
||||
In that repository you also can find another versions of Python environment Dockerfiles.
|
||||
Dockerfile for CentOS is called `Dockerfile`, Dockerfile for RHEL7 is called `Dockerfile.rhel7`,
|
||||
for RHEL8 it's `Dockerfile.rhel8` and the Fedora Dockerfile is called `Dockerfile.fedora`.
|
||||
23
bot-cfg.yml
Normal file
23
bot-cfg.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
version: "1"
|
||||
betka:
|
||||
# is betka enabled for this repository
|
||||
# optional - defaults to false
|
||||
enabled: true
|
||||
# optional
|
||||
notifications:
|
||||
email_addresses: [phracek@redhat.com, lbalhar@redhat.com]
|
||||
# Specify if master branch in upstream repository is synced
|
||||
master_checker: true
|
||||
# Should pull requests be synced?
|
||||
# optional
|
||||
pr_checker: false
|
||||
# Either 'upstream_branch_name' or 'upstream_git_path' has to be specified
|
||||
# Branch name which is used for sync
|
||||
upstream_branch_name: master
|
||||
# Path to directory with dockerfile withing upstream repository
|
||||
upstream_git_path: "3.10"
|
||||
# Github comment message to enforce sync of a pull request
|
||||
# required if pr_checker is true otherwise optional
|
||||
pr_comment_message: "[test]"
|
||||
# optional
|
||||
image_url: quay.io/rhscl/cwt-generator
|
||||
|
|
@ -1 +0,0 @@
|
|||
container sources not used for building fedora containers anymore
|
||||
1
help.md
Symbolic link
1
help.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
README.md
|
||||
19
root/opt/app-root/etc/generate_container_user
Normal file
19
root/opt/app-root/etc/generate_container_user
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Set current user in nss_wrapper
|
||||
USER_ID=$(id -u)
|
||||
GROUP_ID=$(id -g)
|
||||
|
||||
if [ x"$USER_ID" != x"0" -a x"$USER_ID" != x"1001" ]; then
|
||||
|
||||
NSS_WRAPPER_PASSWD=/opt/app-root/etc/passwd
|
||||
NSS_WRAPPER_GROUP=/etc/group
|
||||
|
||||
cat /etc/passwd | sed -e 's/^default:/builder:/' > $NSS_WRAPPER_PASSWD
|
||||
|
||||
echo "default:x:${USER_ID}:${GROUP_ID}:Default Application User:${HOME}:/sbin/nologin" >> $NSS_WRAPPER_PASSWD
|
||||
|
||||
export NSS_WRAPPER_PASSWD
|
||||
export NSS_WRAPPER_GROUP
|
||||
|
||||
LD_PRELOAD=libnss_wrapper.so
|
||||
export LD_PRELOAD
|
||||
fi
|
||||
9
root/opt/app-root/etc/scl_enable
Normal file
9
root/opt/app-root/etc/scl_enable
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# IMPORTANT: Do not add more content to this file unless you know what you are
|
||||
# doing. This file is sourced everytime the shell session is opened.
|
||||
# This will make scl collection binaries work out of box.
|
||||
unset BASH_ENV PROMPT_COMMAND ENV
|
||||
if head "/etc/redhat-release" | grep -q "^CentOS Linux release 7" || \
|
||||
head "/etc/redhat-release" | grep -q "^Red Hat Enterprise Linux\( Server\)\? release 7"; then
|
||||
source scl_source enable httpd24 $NODEJS_SCL rh-python310
|
||||
fi
|
||||
source /opt/app-root/bin/activate
|
||||
BIN
root/opt/wheels/pip-21.2.3-py3-none-any.whl
Executable file
BIN
root/opt/wheels/pip-21.2.3-py3-none-any.whl
Executable file
Binary file not shown.
123
s2i/bin/assemble
Executable file
123
s2i/bin/assemble
Executable file
|
|
@ -0,0 +1,123 @@
|
|||
#!/bin/bash
|
||||
|
||||
function is_django_installed() {
|
||||
python -c "import django" &>/dev/null
|
||||
}
|
||||
|
||||
function should_collectstatic() {
|
||||
is_django_installed && [[ -z "$DISABLE_COLLECTSTATIC" ]]
|
||||
}
|
||||
|
||||
function virtualenv_bin() {
|
||||
# New versions of Python (>3.6) should use venv module
|
||||
# from stdlib instead of virtualenv package
|
||||
python3.10 -m venv $1
|
||||
}
|
||||
|
||||
# Install pipenv or micropipenv to the separate virtualenv to isolate it
|
||||
# from system Python packages and packages in the main
|
||||
# virtualenv. Executable is simlinked into ~/.local/bin
|
||||
# to be accessible. This approach is inspired by pipsi
|
||||
# (pip script installer).
|
||||
function install_tool() {
|
||||
echo "---> Installing $1 packaging tool ..."
|
||||
VENV_DIR=$HOME/.local/venvs/$1
|
||||
virtualenv_bin "$VENV_DIR"
|
||||
# First, try to install the tool without --isolated which means that if you
|
||||
# have your own PyPI mirror, it will take it from there. If this try fails, try it
|
||||
# again with --isolated which ignores external pip settings (env vars, config file)
|
||||
# and installs the tool from PyPI (needs internet connetion).
|
||||
# $1$2 combines package name with [extras] or version specifier if is defined as $2```
|
||||
if ! $VENV_DIR/bin/pip install -U $1$2; then
|
||||
echo "WARNING: Installation of $1 failed, trying again from official PyPI with pip --isolated install"
|
||||
$VENV_DIR/bin/pip install --isolated -U $1$2 # Combines package name with [extras] or version specifier if is defined as $2```
|
||||
fi
|
||||
mkdir -p $HOME/.local/bin
|
||||
ln -s $VENV_DIR/bin/$1 $HOME/.local/bin/$1
|
||||
}
|
||||
|
||||
set -e
|
||||
|
||||
# First of all, check that we don't have disallowed combination of ENVs
|
||||
if [[ ! -z "$ENABLE_PIPENV" && ! -z "$ENABLE_MICROPIPENV" ]]; then
|
||||
echo "ERROR: Pipenv and micropipenv cannot be enabled at the same time!"
|
||||
# podman/buildah does not relay this exit code but it will be fixed hopefuly
|
||||
# https://github.com/containers/buildah/issues/2305
|
||||
exit 3
|
||||
fi
|
||||
|
||||
shopt -s dotglob
|
||||
echo "---> Installing application source ..."
|
||||
mv /tmp/src/* "$HOME"
|
||||
|
||||
# set permissions for any installed artifacts
|
||||
fix-permissions /opt/app-root -P
|
||||
|
||||
|
||||
if [[ ! -z "$UPGRADE_PIP_TO_LATEST" ]]; then
|
||||
echo "---> Upgrading pip, setuptools and wheel to latest version ..."
|
||||
if ! pip install -U pip setuptools wheel; then
|
||||
echo "WARNING: Installation of the latest pip, setuptools and wheel failed, trying again from official PyPI with pip --isolated install"
|
||||
pip install --isolated -U pip setuptools wheel
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -z "$ENABLE_PIPENV" ]]; then
|
||||
if [[ ! -z "$PIN_PIPENV_VERSION" ]]; then
|
||||
# Add == as a prefix to pipenv version, if defined
|
||||
PIN_PIPENV_VERSION="==$PIN_PIPENV_VERSION"
|
||||
fi
|
||||
install_tool "pipenv" "$PIN_PIPENV_VERSION"
|
||||
echo "---> Installing dependencies via pipenv ..."
|
||||
if [[ -f Pipfile ]]; then
|
||||
pipenv install --deploy
|
||||
elif [[ -f requirements.txt ]]; then
|
||||
pipenv install -r requirements.txt
|
||||
fi
|
||||
# pipenv check
|
||||
elif [[ ! -z "$ENABLE_MICROPIPENV" ]]; then
|
||||
install_tool "micropipenv" "[toml]"
|
||||
echo "---> Installing dependencies via micropipenv ..."
|
||||
# micropipenv detects Pipfile.lock and requirements.txt in this order
|
||||
micropipenv install --deploy
|
||||
elif [[ -f requirements.txt ]]; then
|
||||
echo "---> Installing dependencies ..."
|
||||
pip install -r requirements.txt
|
||||
fi
|
||||
|
||||
if [[ ( -f setup.py || -f setup.cfg ) && -z "$DISABLE_SETUP_PY_PROCESSING" ]]; then
|
||||
echo "---> Installing application ..."
|
||||
pip install .
|
||||
fi
|
||||
|
||||
if should_collectstatic; then
|
||||
(
|
||||
echo "---> Collecting Django static files ..."
|
||||
|
||||
APP_HOME=$(readlink -f "${APP_HOME:-.}")
|
||||
# Change the working directory to APP_HOME
|
||||
PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
|
||||
cd "$APP_HOME"
|
||||
|
||||
# Look for 'manage.py' in the current directory
|
||||
manage_file=./manage.py
|
||||
|
||||
if [[ ! -f "$manage_file" ]]; then
|
||||
echo "WARNING: seems that you're using Django, but we could not find a 'manage.py' file."
|
||||
echo "'manage.py collectstatic' ignored."
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! python $manage_file collectstatic --dry-run --noinput &> /dev/null; then
|
||||
echo "WARNING: could not run 'manage.py collectstatic'. To debug, run:"
|
||||
echo " $ python $manage_file collectstatic --noinput"
|
||||
echo "Ignore this warning if you're not serving static files with Django."
|
||||
exit
|
||||
fi
|
||||
|
||||
python $manage_file collectstatic --noinput
|
||||
)
|
||||
fi
|
||||
|
||||
# set permissions for any installed artifacts
|
||||
fix-permissions /opt/app-root -P
|
||||
18
s2i/bin/init-wrapper
Executable file
18
s2i/bin/init-wrapper
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Overview of how this script works: http://veithen.io/2014/11/16/sigterm-propagation.html
|
||||
# Set a trap to kill the main app process when this
|
||||
# init script receives SIGTERM or SIGINT
|
||||
trap 'kill -s TERM $PID' TERM INT
|
||||
# Execute the main application in the background
|
||||
"$@" &
|
||||
PID=$!
|
||||
# wait command always terminates when trap is caught, even if the process hasn't finished yet
|
||||
wait $PID
|
||||
# Remove the trap and wait till the app process finishes completely
|
||||
trap - TERM INT
|
||||
# We wait again, since the first wait terminates when trap is caught
|
||||
wait $PID
|
||||
# Exit with the exit code of the app process
|
||||
STATUS=$?
|
||||
exit $STATUS
|
||||
142
s2i/bin/run
Executable file
142
s2i/bin/run
Executable file
|
|
@ -0,0 +1,142 @@
|
|||
#!/bin/bash
|
||||
source /opt/app-root/etc/generate_container_user
|
||||
|
||||
set -e
|
||||
|
||||
function is_gunicorn_installed() {
|
||||
hash gunicorn &>/dev/null
|
||||
}
|
||||
|
||||
function is_django_installed() {
|
||||
python -c "import django" &>/dev/null
|
||||
}
|
||||
|
||||
function should_migrate() {
|
||||
is_django_installed && [[ -z "$DISABLE_MIGRATE" ]]
|
||||
}
|
||||
|
||||
# Guess the number of workers according to the number of cores
|
||||
function get_default_web_concurrency() {
|
||||
limit_vars=$(cgroup-limits)
|
||||
local $limit_vars
|
||||
if [ -z "${NUMBER_OF_CORES:-}" ]; then
|
||||
echo 1
|
||||
return
|
||||
fi
|
||||
|
||||
local max=$((NUMBER_OF_CORES*2))
|
||||
# Require at least 43 MiB and additional 40 MiB for every worker
|
||||
local default=$(((${MEMORY_LIMIT_IN_BYTES:-MAX_MEMORY_LIMIT_IN_BYTES}/1024/1024 - 43) / 40))
|
||||
default=$((default > max ? max : default))
|
||||
default=$((default < 1 ? 1 : default))
|
||||
# According to http://docs.gunicorn.org/en/stable/design.html#how-many-workers,
|
||||
# 12 workers should be enough to handle hundreds or thousands requests per second
|
||||
default=$((default > 12 ? 12 : default))
|
||||
echo $default
|
||||
}
|
||||
|
||||
function maybe_run_in_init_wrapper() {
|
||||
if [[ -z "$ENABLE_INIT_WRAPPER" ]]; then
|
||||
exec "$@"
|
||||
else
|
||||
exec $STI_SCRIPTS_PATH/init-wrapper "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
APP_HOME=$(readlink -f "${APP_HOME:-.}")
|
||||
# Change the working directory to APP_HOME
|
||||
PYTHONPATH="$(pwd)${PYTHONPATH:+:$PYTHONPATH}"
|
||||
cd "$APP_HOME"
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
manage_file=./manage.py
|
||||
|
||||
if should_migrate; then
|
||||
if [[ -f "$manage_file" ]]; then
|
||||
echo "---> Migrating database ..."
|
||||
python "$manage_file" migrate --noinput
|
||||
else
|
||||
echo "WARNING: seems that you're using Django, but we could not find a 'manage.py' file."
|
||||
echo "Skipped 'python manage.py migrate'."
|
||||
fi
|
||||
fi
|
||||
|
||||
# If not set, use 8080 as the default port
|
||||
if [ -z "$PORT" ]; then
|
||||
PORT=8080
|
||||
fi
|
||||
|
||||
if is_gunicorn_installed; then
|
||||
setup_py=$(find "$HOME" -maxdepth 2 -type f -name 'setup.py' -print -quit)
|
||||
# Look for wsgi module in the current directory
|
||||
if [[ -z "$APP_MODULE" && -f "./wsgi.py" ]]; then
|
||||
APP_MODULE=wsgi
|
||||
elif [[ -z "$APP_MODULE" && -f "$setup_py" ]]; then
|
||||
APP_MODULE="$(python "$setup_py" --name)"
|
||||
fi
|
||||
|
||||
if [[ "$APP_MODULE" ]]; then
|
||||
export WEB_CONCURRENCY=${WEB_CONCURRENCY:-$(get_default_web_concurrency)}
|
||||
|
||||
# Default settings for gunicorn if none of the custom are set
|
||||
if [ -z "$APP_CONFIG" ] && [ -z "$GUNICORN_CMD_ARGS" ]; then
|
||||
GUNICORN_CMD_ARGS="--bind=0.0.0.0:$PORT --access-logfile=-"
|
||||
gunicorn_settings_source="default"
|
||||
else
|
||||
gunicorn_settings_source="custom"
|
||||
fi
|
||||
|
||||
# Gunicorn can read GUNICORN_CMD_ARGS as an env variable but because this is not
|
||||
# supported in Gunicorn < 20 we still need for Python 2, we are using arguments directly.
|
||||
echo "---> Serving application with gunicorn ($APP_MODULE) with $gunicorn_settings_source settings ..."
|
||||
exec gunicorn "$APP_MODULE" $GUNICORN_CMD_ARGS --config "$APP_CONFIG"
|
||||
fi
|
||||
fi
|
||||
|
||||
if is_django_installed; then
|
||||
if [[ -f "$manage_file" ]]; then
|
||||
echo "---> Serving application with 'manage.py runserver 0.0.0.0:$PORT' ..."
|
||||
echo "WARNING: this is NOT a recommended way to run you application in production!"
|
||||
echo "Consider using gunicorn or some other production web server."
|
||||
maybe_run_in_init_wrapper python "$manage_file" runserver 0.0.0.0:$PORT
|
||||
else
|
||||
echo "WARNING: seems that you're using Django, but we could not find a 'manage.py' file."
|
||||
echo "Skipped 'python manage.py runserver'."
|
||||
fi
|
||||
fi
|
||||
|
||||
>&2 echo "ERROR: don't know how to run your application."
|
||||
>&2 echo "Please set either APP_MODULE, APP_FILE or APP_SCRIPT environment variables, or create a file 'app.py' to launch your application."
|
||||
exit 1
|
||||
18
s2i/bin/usage
Executable file
18
s2i/bin/usage
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
DISTRO=`cat /etc/*-release | grep ^ID= | grep -Po '".*?"' | tr -d '"'`
|
||||
NAMESPACE=centos
|
||||
[[ $DISTRO =~ rhel* ]] && NAMESPACE=rhscl
|
||||
|
||||
cat <<EOF
|
||||
This is a S2I python-3.10 ${DISTRO} base image:
|
||||
There are multiple ways how to run the image, see documentation at:
|
||||
https://github.com/sclorg/s2i-python-container/blob/master/3.10/README.md
|
||||
|
||||
To use it in Openshift, run:
|
||||
oc new-app python:3.10~https://github.com/sclorg/s2i-python-container.git --context-dir=3.10/test/setup-test-app/
|
||||
|
||||
You can then run the resulting image via:
|
||||
oc get pods
|
||||
oc exec <pod> -- curl 127.0.0.1:8080
|
||||
EOF
|
||||
0
sources
Normal file
0
sources
Normal file
1
test/app-home-test-app/.s2i/environment
Normal file
1
test/app-home-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1 @@
|
|||
APP_HOME=project
|
||||
3
test/app-home-test-app/project/wsgi.py
Normal file
3
test/app-home-test-app/project/wsgi.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello World from app-home WSGI application!"]
|
||||
2
test/app-home-test-app/requirements.txt
Normal file
2
test/app-home-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
57
test/app-module-test-app/.gitignore
vendored
Normal file
57
test/app-module-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
1
test/app-module-test-app/.s2i/environment
Normal file
1
test/app-module-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1 @@
|
|||
APP_MODULE=app:application
|
||||
4
test/app-module-test-app/app.py
Normal file
4
test/app-module-test-app/app.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
2
test/app-module-test-app/requirements.txt
Normal file
2
test/app-module-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
101
test/check_imagestreams.py
Executable file
101
test/check_imagestreams.py
Executable file
|
|
@ -0,0 +1,101 @@
|
|||
#!/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
|
||||
import os
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any
|
||||
|
||||
IMAGESTREAMS_DIR: str = "imagestreams"
|
||||
|
||||
|
||||
class ImageStreamChecker(object):
|
||||
version: str = ""
|
||||
|
||||
def __init__(self, version: str):
|
||||
self.version = version
|
||||
self.results: Dict[Any, Any] = {}
|
||||
|
||||
def load_json_file(self, filename: Path) -> Any:
|
||||
with open(str(filename)) as f:
|
||||
data = json.load(f)
|
||||
isinstance(data, Dict)
|
||||
return data
|
||||
|
||||
def check_version(self, json_dict: Dict[Any, Any]) -> List[str]:
|
||||
res = []
|
||||
for tags in json_dict["spec"]["tags"]:
|
||||
# The name can be"<stream>" or "<stream>-elX" or "<stream>-ubiX"
|
||||
if tags["name"] == self.version or tags["name"].startswith(
|
||||
self.version + "-"
|
||||
):
|
||||
res.append(tags)
|
||||
return res
|
||||
|
||||
def check_latest_tag(self, json_dict: Dict[Any, Any]) -> bool:
|
||||
latest_tag_correct: bool = False
|
||||
for tags in json_dict["spec"]["tags"]:
|
||||
if tags["name"] != "latest":
|
||||
continue
|
||||
# The latest can link to either "<stream>" or "<stream>-elX" or "<stream>-ubiX"
|
||||
if tags["from"]["name"] == self.version or tags["from"]["name"].startswith(
|
||||
self.version + "-"
|
||||
):
|
||||
latest_tag_correct = True
|
||||
return latest_tag_correct
|
||||
|
||||
def check_imagestreams(self) -> int:
|
||||
p = Path(".")
|
||||
json_files = p.glob(f"{IMAGESTREAMS_DIR}/*.json")
|
||||
if not json_files:
|
||||
print(f"No json files present in {IMAGESTREAMS_DIR}.")
|
||||
return 0
|
||||
for f in json_files:
|
||||
if os.environ.get("TARGET") in ("rhel7", "centos7") and "aarch64" in str(f):
|
||||
print("Imagestream aarch64 is not supported on rhel7")
|
||||
continue
|
||||
print(f"Checking file {str(f)}.")
|
||||
json_dict = self.load_json_file(f)
|
||||
if not (self.check_version(json_dict) and self.check_latest_tag(json_dict)):
|
||||
print(
|
||||
f"The latest version is not present in {str(f)} or in latest tag."
|
||||
)
|
||||
self.results[f] = False
|
||||
if self.results:
|
||||
return 1
|
||||
print("Imagestreams contains the latest version.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
logging.fatal("%s: %s", sys.argv[0], "VERSION as an argument was not provided")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Version to check is {sys.argv[1]}.")
|
||||
isc = ImageStreamChecker(version=sys.argv[1])
|
||||
sys.exit(isc.check_imagestreams())
|
||||
61
test/django-different-port-test-app/.gitignore
vendored
Normal file
61
test/django-different-port-test-app/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Django
|
||||
db.sqlite3
|
||||
staticfiles/
|
||||
|
||||
# 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/
|
||||
1
test/django-different-port-test-app/.s2i/environment
Normal file
1
test/django-different-port-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1 @@
|
|||
PORT=8085
|
||||
10
test/django-different-port-test-app/manage.py
Executable file
10
test/django-different-port-test-app/manage.py
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
0
test/django-different-port-test-app/project/__init__.py
Normal file
0
test/django-different-port-test-app/project/__init__.py
Normal file
118
test/django-different-port-test-app/project/settings.py
Normal file
118
test/django-different-port-test-app/project/settings.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
"""
|
||||
Django settings for project project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.8.1.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||
"""
|
||||
|
||||
import django
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'y*b^6p#z&cm2)8rzgbp2i4k*+rg2h%60l*bmf6hg&ro!z0-ael'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
# SECURITY WARNING: do not use '*' on production or use some HTTP(S) proxy
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
)
|
||||
|
||||
# Django 1
|
||||
if django.VERSION[0] == 1:
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
)
|
||||
else:
|
||||
# Django 2+
|
||||
MIDDLEWARE = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'project.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'project.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||
21
test/django-different-port-test-app/project/urls.py
Normal file
21
test/django-different-port-test-app/project/urls.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
"""project URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/1.8/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Add an import: from blog import urls as blog_urls
|
||||
2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
|
||||
"""
|
||||
from django.conf.urls import include, url
|
||||
from django.contrib import admin
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
]
|
||||
16
test/django-different-port-test-app/project/wsgi.py
Normal file
16
test/django-different-port-test-app/project/wsgi.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
WSGI config for project project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
2
test/django-different-port-test-app/requirements.txt
Normal file
2
test/django-different-port-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Django<3; python_version > '3.8'
|
||||
Django<2; python_version <='3.8'
|
||||
61
test/django-test-app/.gitignore
vendored
Normal file
61
test/django-test-app/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Django
|
||||
db.sqlite3
|
||||
staticfiles/
|
||||
|
||||
# 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/
|
||||
10
test/django-test-app/manage.py
Executable file
10
test/django-test-app/manage.py
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
0
test/django-test-app/project/__init__.py
Normal file
0
test/django-test-app/project/__init__.py
Normal file
118
test/django-test-app/project/settings.py
Normal file
118
test/django-test-app/project/settings.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
"""
|
||||
Django settings for project project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.8.1.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||
"""
|
||||
|
||||
import django
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'y*b^6p#z&cm2)8rzgbp2i4k*+rg2h%60l*bmf6hg&ro!z0-ael'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
# SECURITY WARNING: do not use '*' on production or use some HTTP(S) proxy
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
)
|
||||
|
||||
# Django 1
|
||||
if django.VERSION[0] == 1:
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
)
|
||||
else:
|
||||
# Django 2+
|
||||
MIDDLEWARE = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'project.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'project.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||
21
test/django-test-app/project/urls.py
Normal file
21
test/django-test-app/project/urls.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
"""project URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/1.8/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Add an import: from blog import urls as blog_urls
|
||||
2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
|
||||
"""
|
||||
from django.conf.urls import include, url
|
||||
from django.contrib import admin
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
]
|
||||
16
test/django-test-app/project/wsgi.py
Normal file
16
test/django-test-app/project/wsgi.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
WSGI config for project project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
2
test/django-test-app/requirements.txt
Normal file
2
test/django-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Django<3; python_version > '3.8'
|
||||
Django<2; python_version <='3.8'
|
||||
14
test/from-dockerfile/Dockerfile.tpl
Normal file
14
test/from-dockerfile/Dockerfile.tpl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
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
|
||||
USER 0
|
||||
ADD app-src /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
|
||||
16
test/from-dockerfile/Dockerfile_no_s2i.tpl
Normal file
16
test/from-dockerfile/Dockerfile_no_s2i.tpl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
FROM #IMAGE_NAME# # Replaced by sed in ct_test_app_dockerfile
|
||||
|
||||
# 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
|
||||
57
test/gunicorn-config-different-port-test-app/.gitignore
vendored
Normal file
57
test/gunicorn-config-different-port-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
APP_MODULE=app:application
|
||||
APP_CONFIG=./gunicorn.conf.py
|
||||
4
test/gunicorn-config-different-port-test-app/app.py
Normal file
4
test/gunicorn-config-different-port-test-app/app.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import multiprocessing
|
||||
|
||||
bind = "0.0.0.0:8085"
|
||||
workers = multiprocessing.cpu_count() * 2 + 1
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
57
test/gunicorn-different-port-test-app/.gitignore
vendored
Normal file
57
test/gunicorn-different-port-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
2
test/gunicorn-different-port-test-app/.s2i/environment
Normal file
2
test/gunicorn-different-port-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
APP_MODULE=app:application
|
||||
PORT=8085
|
||||
4
test/gunicorn-different-port-test-app/app.py
Normal file
4
test/gunicorn-different-port-test-app/app.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
2
test/gunicorn-different-port-test-app/requirements.txt
Normal file
2
test/gunicorn-different-port-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
173
test/imagestreams/python-centos.json
Normal file
173
test/imagestreams/python-centos.json
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
{
|
||||
"kind": "ImageStream",
|
||||
"apiVersion": "image.openshift.io/v1",
|
||||
"metadata": {
|
||||
"name": "python",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"tags": [
|
||||
{
|
||||
"name": "latest",
|
||||
"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.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",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "ImageStreamTag",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.8-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.8 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.8 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.8/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.8,python",
|
||||
"version": "3.8",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.access.redhat.com/ubi8/python-38:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.8-ubi7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.8 (UBI 7)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.8 applications on UBI 7. 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.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.8,python",
|
||||
"version": "3.8",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.access.redhat.com/ubi7/python-38:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.6-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.6 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.6 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.6/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.6,python",
|
||||
"version": "3.6",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.access.redhat.com/ubi8/python-36:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 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/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.access.redhat.com/ubi8/python-27:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7-ubi7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7 (UBI 7)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 applications on UBI 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.access.redhat.com/ubi7/python-27:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 applications on CentOS 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python,hidden",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "quay.io/centos7/python-27-centos7:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
73
test/imagestreams/python-centos7.json
Normal file
73
test/imagestreams/python-centos7.json
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"kind": "ImageStream",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "python",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"tags": [
|
||||
{
|
||||
"name": "latest",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python (Latest)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python applications on CentOS 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.6/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",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "ImageStreamTag",
|
||||
"name": "3.6"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.6",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.6",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.6 applications on CentOS 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/3.6/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.6,python",
|
||||
"version": "3.6",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "docker.io/centos/python-36-centos7:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 applications on CentOS 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "docker.io/centos/python-27-centos7:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
113
test/imagestreams/python-rhel-aarch64.json
Normal file
113
test/imagestreams/python-rhel-aarch64.json
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
{
|
||||
"kind": "ImageStream",
|
||||
"apiVersion": "image.openshift.io/v1",
|
||||
"metadata": {
|
||||
"name": "python",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"tags": [
|
||||
{
|
||||
"name": "latest",
|
||||
"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.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",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "ImageStreamTag",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.8-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.8 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.8 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.8/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.8,python",
|
||||
"version": "3.8",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi8/python-38:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.6-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.6 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.6 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.6/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.6,python",
|
||||
"version": "3.6",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi8/python-36:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 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/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi8/python-27:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
193
test/imagestreams/python-rhel.json
Normal file
193
test/imagestreams/python-rhel.json
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
{
|
||||
"kind": "ImageStream",
|
||||
"apiVersion": "image.openshift.io/v1",
|
||||
"metadata": {
|
||||
"name": "python",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"tags": [
|
||||
{
|
||||
"name": "latest",
|
||||
"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.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",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "ImageStreamTag",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.8-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.8 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.8 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.8/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.8,python",
|
||||
"version": "3.8",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi8/python-38:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.8-ubi7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.8 (UBI 7)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.8 applications on UBI 7. 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.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.8,python",
|
||||
"version": "3.8",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi7/python-38:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.8",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.8 applications on RHEL 7. 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.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python,hidden",
|
||||
"supports":"python:3.8,python",
|
||||
"version": "3.8",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/rhscl/python-38-rhel7:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.6-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 3.6 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 3.6 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.6/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:3.6,python",
|
||||
"version": "3.6",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi8/python-36:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7-ubi8",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7 (UBI 8)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 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/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi8/python-27:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7-ubi7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7 (UBI 7)",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 applications on UBI 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/ubi7/python-27:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2.7",
|
||||
"annotations": {
|
||||
"openshift.io/display-name": "Python 2.7",
|
||||
"openshift.io/provider-display-name": "Red Hat, Inc.",
|
||||
"description": "Build and run Python 2.7 applications on RHEL 7. For more information about using this builder image, including OpenShift considerations, see https://github.com/sclorg/s2i-python-container/blob/master/2.7/README.md.",
|
||||
"iconClass": "icon-python",
|
||||
"tags": "builder,python,hidden",
|
||||
"supports":"python:2.7,python",
|
||||
"version": "2.7",
|
||||
"sampleRepo": "https://github.com/sclorg/django-ex.git"
|
||||
},
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "registry.redhat.io/rhscl/python-27-rhel7:latest"
|
||||
},
|
||||
"referencePolicy": {
|
||||
"type": "Local"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
3
test/locale-test-app/requirements.txt
Normal file
3
test/locale-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Flask
|
||||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
41
test/locale-test-app/wsgi.py
Normal file
41
test/locale-test-app/wsgi.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import locale
|
||||
import os
|
||||
import sys
|
||||
|
||||
from flask import Flask
|
||||
application = Flask(__name__)
|
||||
|
||||
@application.route('/')
|
||||
def hello():
|
||||
assert os.environ['PYTHONIOENCODING'] == 'UTF-8'
|
||||
assert os.environ['LC_ALL'] == 'en_US.UTF-8'
|
||||
assert os.environ['LANG'] == 'en_US.UTF-8'
|
||||
|
||||
assert locale.getdefaultlocale() == ('en_US', 'UTF-8')
|
||||
assert locale.getpreferredencoding() == 'UTF-8'
|
||||
|
||||
print(u'\u292e')
|
||||
|
||||
return b'Hello World from locale test application!'
|
||||
|
||||
print('-- GLOBAL --')
|
||||
|
||||
for k,v in os.environ.items():
|
||||
print('%r=%r' % (k, v))
|
||||
|
||||
print()
|
||||
|
||||
print(sys.stdout.encoding)
|
||||
print(locale.getlocale())
|
||||
print(locale.getdefaultlocale())
|
||||
print(locale.getpreferredencoding())
|
||||
|
||||
try:
|
||||
print(u'\u292e')
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
print('------------')
|
||||
|
||||
if __name__ == '__main__':
|
||||
application.run()
|
||||
2
test/micropipenv-requirements-test-app/.s2i/environment
Normal file
2
test/micropipenv-requirements-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
ENABLE_MICROPIPENV=true
|
||||
DISABLE_SETUP_PY_PROCESSING=true
|
||||
14
test/micropipenv-requirements-test-app/app.py
Normal file
14
test/micropipenv-requirements-test-app/app.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
import mod_wsgi.server
|
||||
|
||||
mod_wsgi.server.start(
|
||||
'--log-to-terminal',
|
||||
'--port', '8080',
|
||||
'--trust-proxy-header', 'X-Forwarded-For',
|
||||
'--trust-proxy-header', 'X-Forwarded-Port',
|
||||
'--trust-proxy-header', 'X-Forwarded-Proto',
|
||||
'--processes', os.environ.get('MOD_WSGI_PROCESSES', '1'),
|
||||
'--threads', os.environ.get('MOD_WSGI_THREADS', '5'),
|
||||
'--application-type', 'module',
|
||||
'--entry-point', 'wsgi'
|
||||
)
|
||||
2
test/micropipenv-requirements-test-app/requirements.txt
Normal file
2
test/micropipenv-requirements-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
mod_wsgi
|
||||
Flask
|
||||
9
test/micropipenv-requirements-test-app/wsgi.py
Normal file
9
test/micropipenv-requirements-test-app/wsgi.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from flask import Flask
|
||||
application = Flask(__name__)
|
||||
|
||||
@application.route('/')
|
||||
def hello():
|
||||
return b'Hello World from mod_wsgi hosted WSGI application!'
|
||||
|
||||
if __name__ == '__main__':
|
||||
application.run()
|
||||
57
test/micropipenv-test-app/.gitignore
vendored
Normal file
57
test/micropipenv-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
5
test/micropipenv-test-app/.s2i/environment
Normal file
5
test/micropipenv-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ENABLE_MICROPIPENV=true
|
||||
DISABLE_SETUP_PY_PROCESSING=true
|
||||
# This tests second try to install micropipenv with --isolated
|
||||
# because the first one won't work with following setting
|
||||
PIP_INDEX_URL=https://example.com/
|
||||
14
test/micropipenv-test-app/Pipfile
Normal file
14
test/micropipenv-test-app/Pipfile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[[source]]
|
||||
url = "https://pypi.python.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
"e1839a8" = {path = ".", editable = true}
|
||||
requests = "==2.20.0"
|
||||
|
||||
[dev-packages]
|
||||
pytest = ">=2.8.0"
|
||||
|
||||
[requires]
|
||||
python_version = "3.10"
|
||||
138
test/micropipenv-test-app/Pipfile.lock
generated
Normal file
138
test/micropipenv-test-app/Pipfile.lock
generated
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "9a2e94684dd37b09b75b2cefccf407a9b8a22498cbd36cde8afb8ed2eb06fe14"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.10"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.python.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
|
||||
"sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
|
||||
],
|
||||
"version": "==2021.10.8"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"e1839a8": {
|
||||
"editable": true,
|
||||
"path": "."
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
|
||||
"sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==20.1.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
|
||||
"sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
|
||||
],
|
||||
"version": "==2.7"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c",
|
||||
"sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.20.0"
|
||||
},
|
||||
"testapp": {
|
||||
"editable": true,
|
||||
"path": "."
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4",
|
||||
"sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'",
|
||||
"version": "==1.24.3"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"iniconfig": {
|
||||
"hashes": [
|
||||
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
|
||||
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
|
||||
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
|
||||
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
|
||||
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==1.11.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4",
|
||||
"sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.6"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89",
|
||||
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.2.5"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
|
||||
"version": "==0.10.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
test/micropipenv-test-app/setup.py
Normal file
10
test/micropipenv-test-app/setup.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
setup (
|
||||
name = "testapp",
|
||||
version = "0.1",
|
||||
description = "Example application to be deployed.",
|
||||
packages = find_packages(),
|
||||
install_requires = ["gunicorn"],
|
||||
)
|
||||
7
test/micropipenv-test-app/testapp.py
Normal file
7
test/micropipenv-test-app/testapp.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import requests
|
||||
|
||||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
assert requests.__version__ == '2.20.0'
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
14
test/mod-wsgi-test-app/app.py
Normal file
14
test/mod-wsgi-test-app/app.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
import mod_wsgi.server
|
||||
|
||||
mod_wsgi.server.start(
|
||||
'--log-to-terminal',
|
||||
'--port', '8080',
|
||||
'--trust-proxy-header', 'X-Forwarded-For',
|
||||
'--trust-proxy-header', 'X-Forwarded-Port',
|
||||
'--trust-proxy-header', 'X-Forwarded-Proto',
|
||||
'--processes', os.environ.get('MOD_WSGI_PROCESSES', '1'),
|
||||
'--threads', os.environ.get('MOD_WSGI_THREADS', '5'),
|
||||
'--application-type', 'module',
|
||||
'--entry-point', 'wsgi'
|
||||
)
|
||||
2
test/mod-wsgi-test-app/requirements.txt
Normal file
2
test/mod-wsgi-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
mod_wsgi
|
||||
Flask
|
||||
9
test/mod-wsgi-test-app/wsgi.py
Normal file
9
test/mod-wsgi-test-app/wsgi.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from flask import Flask
|
||||
application = Flask(__name__)
|
||||
|
||||
@application.route('/')
|
||||
def hello():
|
||||
return b'Hello World from mod_wsgi hosted WSGI application!'
|
||||
|
||||
if __name__ == '__main__':
|
||||
application.run()
|
||||
1
test/npm-virtualenv-uwsgi-test-app/.s2i/environment
Normal file
1
test/npm-virtualenv-uwsgi-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1 @@
|
|||
UPGRADE_PIP_TO_LATEST=1
|
||||
61
test/npm-virtualenv-uwsgi-test-app/app.sh
Executable file
61
test/npm-virtualenv-uwsgi-test-app/app.sh
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Test virtualenv environment and pip upgrade
|
||||
|
||||
echo "Testing that the virtual environment's Python is being used ..."
|
||||
if [ "$(which python)" != "/opt/app-root/bin/python" ]; then
|
||||
echo "ERROR: Initialization of the virtual environment failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Testing UPGRADE_PIP_TO_LATEST=1 (set in .s2i/environment) ..."
|
||||
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 -Ev "^Requirement already (up-to-date|satisfied): "
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "ERROR: Failed to upgrade '$pkg' to the latest version."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# Test that npm works correctly
|
||||
|
||||
# Create a package.json file so npm doesn't throw off warnings
|
||||
echo "Initializing npm and testing the installation and use of a module ..."
|
||||
npm init -y
|
||||
|
||||
# mkdirp chosen because it's on the list of 'most depended-upon packages':
|
||||
# https://www.npmjs.com/browse/depended
|
||||
npm install mkdirp
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Installation of npm module 'mkdirp' failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use the mkdirp module to create a directory and it's subdirectory
|
||||
node -e "var mkdirp = require('mkdirp'); mkdirp('dir1/dir2')"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Nodejs cannot use the freshly installed 'mkdirp' module."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(ls dir1)" != "dir2" ]; then
|
||||
echo "ERROR: The 'mkdirp' module could not create subdirectories at the current path."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Test the uwsgi server
|
||||
|
||||
exec uwsgi \
|
||||
--http-socket :8080 \
|
||||
--die-on-term \
|
||||
--master \
|
||||
--single-interpreter \
|
||||
--enable-threads \
|
||||
--threads=5 \
|
||||
--thunder-lock \
|
||||
--module wsgi
|
||||
2
test/npm-virtualenv-uwsgi-test-app/requirements.txt
Normal file
2
test/npm-virtualenv-uwsgi-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
uWSGI
|
||||
Flask
|
||||
9
test/npm-virtualenv-uwsgi-test-app/wsgi.py
Normal file
9
test/npm-virtualenv-uwsgi-test-app/wsgi.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from flask import Flask
|
||||
application = Flask(__name__)
|
||||
|
||||
@application.route('/')
|
||||
def hello():
|
||||
return b'Hello World from uWSGI hosted WSGI application!'
|
||||
|
||||
if __name__ == '__main__':
|
||||
application.run()
|
||||
4
test/numpy-test-app/requirements.txt
Normal file
4
test/numpy-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
numpy<1.17.0; python_version < '3.5'
|
||||
numpy>=1.17.0; python_version >= '3.5'
|
||||
7
test/numpy-test-app/wsgi.py
Normal file
7
test/numpy-test-app/wsgi.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import numpy
|
||||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
matrix = numpy.array([[1,2,3],[6,5,4],[7,8,8]])
|
||||
matrix.dot(numpy.linalg.inv(matrix))
|
||||
return [b"Hello World from numpy WSGI application!"]
|
||||
1
test/pin-pipenv-version-test-app
Submodule
1
test/pin-pipenv-version-test-app
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit d805fc9986bc087d2dd6dd6655f96097699c56fb
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ENABLE_PIPENV=true
|
||||
ENABLE_MICROPIPENV=true
|
||||
57
test/pipenv-test-app/.gitignore
vendored
Normal file
57
test/pipenv-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
2
test/pipenv-test-app/.s2i/environment
Normal file
2
test/pipenv-test-app/.s2i/environment
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
ENABLE_PIPENV=true
|
||||
DISABLE_SETUP_PY_PROCESSING=true
|
||||
14
test/pipenv-test-app/Pipfile
Normal file
14
test/pipenv-test-app/Pipfile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[[source]]
|
||||
url = "https://pypi.python.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
"e1839a8" = {path = ".", editable = true}
|
||||
requests = "==2.20.0"
|
||||
|
||||
[dev-packages]
|
||||
pytest = ">=2.8.0"
|
||||
|
||||
[requires]
|
||||
python_version = "3.10"
|
||||
138
test/pipenv-test-app/Pipfile.lock
generated
Normal file
138
test/pipenv-test-app/Pipfile.lock
generated
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "9a2e94684dd37b09b75b2cefccf407a9b8a22498cbd36cde8afb8ed2eb06fe14"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.10"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.python.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
|
||||
"sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
|
||||
],
|
||||
"version": "==2021.10.8"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"e1839a8": {
|
||||
"editable": true,
|
||||
"path": "."
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
|
||||
"sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==20.1.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
|
||||
"sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
|
||||
],
|
||||
"version": "==2.7"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c",
|
||||
"sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.20.0"
|
||||
},
|
||||
"testapp": {
|
||||
"editable": true,
|
||||
"path": "."
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4",
|
||||
"sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'",
|
||||
"version": "==1.24.3"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"iniconfig": {
|
||||
"hashes": [
|
||||
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
|
||||
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
|
||||
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
|
||||
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
|
||||
"sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==1.11.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4",
|
||||
"sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.6"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89",
|
||||
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.2.5"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'",
|
||||
"version": "==0.10.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
test/pipenv-test-app/setup.py
Normal file
10
test/pipenv-test-app/setup.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
setup (
|
||||
name = "testapp",
|
||||
version = "0.1",
|
||||
description = "Example application to be deployed.",
|
||||
packages = find_packages(),
|
||||
install_requires = ["gunicorn"],
|
||||
)
|
||||
7
test/pipenv-test-app/testapp.py
Normal file
7
test/pipenv-test-app/testapp.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import requests
|
||||
|
||||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/plain')])
|
||||
assert requests.__version__ == '2.20.0'
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
330
test/run
Executable file
330
test/run
Executable file
|
|
@ -0,0 +1,330 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# The 'run' performs a simple test that verifies that S2I image.
|
||||
# The main focus here is to excersise the S2I scripts.
|
||||
#
|
||||
# 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-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]}"))"
|
||||
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
|
||||
fi
|
||||
|
||||
IMAGE_NAME=${IMAGE_NAME:-centos/python-${VERSION//./}-centos7}
|
||||
|
||||
. test/test-lib.sh
|
||||
|
||||
info() {
|
||||
echo -e "\n\e[1m[INFO] $@\e[0m\n"
|
||||
}
|
||||
|
||||
image_exists() {
|
||||
docker inspect $1 &>/dev/null
|
||||
}
|
||||
|
||||
container_exists() {
|
||||
image_exists $(cat $cid_file)
|
||||
}
|
||||
|
||||
|
||||
container_ip() {
|
||||
docker inspect --format="{{ .NetworkSettings.IPAddress }}" $(cat $cid_file)
|
||||
}
|
||||
|
||||
run_s2i_build() {
|
||||
info "Building the ${1} application image ..."
|
||||
ct_s2i_build_as_df file://${test_dir}/${1} ${IMAGE_NAME} ${IMAGE_NAME}-testapp ${s2i_args}
|
||||
}
|
||||
|
||||
prepare() {
|
||||
if ! image_exists ${IMAGE_NAME}; then
|
||||
echo "ERROR: The image ${IMAGE_NAME} must exist before this script is executed."
|
||||
exit 1
|
||||
fi
|
||||
# TODO: S2I build require the application is a valid 'GIT' repository, we
|
||||
# should remove this restriction in the future when a file:// is used.
|
||||
info "Preparing to test ${1} ..."
|
||||
pushd ${test_dir}/${1} >/dev/null
|
||||
git init
|
||||
git config user.email "build@localhost" && git config user.name "builder"
|
||||
git add -A && git commit -m "Sample commit"
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
run_test_application() {
|
||||
docker run --user=100001 ${CONTAINER_ARGS} --rm --cidfile=${cid_file} ${IMAGE_NAME}-testapp
|
||||
}
|
||||
|
||||
cleanup_app() {
|
||||
info "Cleaning up app container ..."
|
||||
if [ -f $cid_file ]; then
|
||||
if container_exists; then
|
||||
docker stop $(cat $cid_file)
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
info "Cleaning up the test application image"
|
||||
if image_exists ${IMAGE_NAME}-testapp; then
|
||||
docker rmi -f ${IMAGE_NAME}-testapp
|
||||
fi
|
||||
rm -rf ${test_dir}/${1}/.git
|
||||
}
|
||||
|
||||
check_type() {
|
||||
# positive test & non-zero exit status = ERROR
|
||||
# negative test & zero exit status = ERROR
|
||||
local result="$1"
|
||||
local type=${2:-positive} # if not defined, we expect possitive test type (zero exit code)
|
||||
if [[ "$type" == "positive" && "$result" != "0" ]]; then
|
||||
info "TEST FAILED (${type}), EXPECTED:0 GOT:${result}"
|
||||
cleanup
|
||||
return $result
|
||||
elif [[ "$type" == "negative" && "$result" == "0" ]]; then
|
||||
info "TEST FAILED (${type}), EXPECTED: non-zero GOT:${result}"
|
||||
cleanup
|
||||
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() {
|
||||
local max_attempts=10
|
||||
local sleep_time=1
|
||||
local attempt=1
|
||||
info "Waiting for application container to start $CONTAINER_ARGS ..."
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
[ -f $cid_file ] && [ -s $cid_file ] && return 0
|
||||
attempt=$(( $attempt + 1 ))
|
||||
sleep $sleep_time
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
test_s2i_usage() {
|
||||
info "Testing 's2i usage' ..."
|
||||
ct_s2i_usage ${IMAGE_NAME} ${s2i_args} 1>/dev/null
|
||||
}
|
||||
|
||||
test_docker_run_usage() {
|
||||
info "Testing 'docker run' usage ..."
|
||||
docker run ${IMAGE_NAME} &>/dev/null
|
||||
}
|
||||
|
||||
test_scl_usage() {
|
||||
local run_cmd="$1"
|
||||
local expected="$2"
|
||||
local cid_file="$3"
|
||||
|
||||
info "Testing the image SCL enable"
|
||||
out=$(docker run --rm ${IMAGE_NAME} /bin/bash -c "${run_cmd}" 2>&1)
|
||||
if ! echo "${out}" | grep -q "${expected}"; then
|
||||
echo "ERROR[/bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
|
||||
return 1
|
||||
fi
|
||||
out=$(docker exec $(cat ${cid_file}) /bin/bash -c "${run_cmd}" 2>&1)
|
||||
if ! echo "${out}" | grep -q "${expected}"; then
|
||||
echo "ERROR[exec /bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
|
||||
return 1
|
||||
fi
|
||||
out=$(docker exec $(cat ${cid_file}) /bin/sh -ic "${run_cmd}" 2>&1)
|
||||
if ! echo "${out}" | grep -q "${expected}"; then
|
||||
echo "ERROR[exec /bin/sh -ic "${run_cmd}"] Expected '${expected}', got '${out}'"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_connection() {
|
||||
info "Testing the HTTP connection (http://$(container_ip):${test_port}) ${CONTAINER_ARGS} ..."
|
||||
local max_attempts=30
|
||||
local sleep_time=1
|
||||
local attempt=1
|
||||
local result=1
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
response_code=$(curl -s -w %{http_code} -o /dev/null http://$(container_ip):${test_port}/)
|
||||
status=$?
|
||||
if [ $status -eq 0 ]; then
|
||||
if [ $response_code -eq 200 ]; then
|
||||
result=0
|
||||
fi
|
||||
break
|
||||
fi
|
||||
attempt=$(( $attempt + 1 ))
|
||||
sleep $sleep_time
|
||||
done
|
||||
return $result
|
||||
}
|
||||
|
||||
test_application() {
|
||||
local cid_file=$(mktemp -u --suffix=.cid)
|
||||
# Verify that the HTTP connection can be established to test application container
|
||||
run_test_application &
|
||||
|
||||
# Wait for the container to write it's CID file
|
||||
wait_for_cid
|
||||
# Some test apps have tests in their startup code so we have to check
|
||||
# that the container starts at all
|
||||
check_result $?
|
||||
|
||||
test_scl_usage "python --version" "Python $VERSION." "${cid_file}"
|
||||
check_result $?
|
||||
test_scl_usage "node --version" "^v[0-9]*\.[0-9]*\.[0-9]*" "${cid_file}"
|
||||
check_result $?
|
||||
test_scl_usage "npm --version" "^[0-9]*\.[0-9]*\.[0-9]*" "${cid_file}"
|
||||
check_result $?
|
||||
test_connection
|
||||
check_result $?
|
||||
cleanup_app
|
||||
}
|
||||
|
||||
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" ]] || 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"
|
||||
fi
|
||||
|
||||
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"
|
||||
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 $?
|
||||
}
|
||||
|
||||
test_application_with_user() {
|
||||
# test application with random user
|
||||
CONTAINER_ARGS="--user 12345" test_application
|
||||
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
# Example apps with "-different-port-" in their name don't use the default port 8080
|
||||
if [[ "$app" == *"-different-port-"* ]]; then
|
||||
test_port=8085
|
||||
else
|
||||
test_port=8080
|
||||
fi
|
||||
|
||||
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_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_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}"
|
||||
|
||||
cleanup ${app}
|
||||
done
|
||||
|
||||
TEST_SET=${TESTS:-$TEST_VAR_DOCKER} run_all_tests
|
||||
|
||||
echo "$test_short_summary"
|
||||
|
||||
if [ $TESTSUITE_RESULT -eq 0 ] ; then
|
||||
echo "Tests for ${IMAGE_NAME} succeeded."
|
||||
else
|
||||
echo "Tests for ${IMAGE_NAME} failed."
|
||||
fi
|
||||
|
||||
exit $TESTSUITE_RESULT
|
||||
64
test/run-openshift
Executable file
64
test/run-openshift
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
#!/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]})
|
||||
test_dir="$(readlink -f $(dirname ${BASH_SOURCE[0]}))"
|
||||
|
||||
source "${THISDIR}/test-lib.sh"
|
||||
source "${THISDIR}/test-lib-openshift.sh"
|
||||
source "${THISDIR}/test-lib-python.sh"
|
||||
|
||||
set -eo nounset
|
||||
|
||||
trap ct_os_cleanup EXIT SIGINT
|
||||
|
||||
test_latest_imagestreams() {
|
||||
info "Testing the latest version in imagestreams"
|
||||
# Switch to root directory of a container
|
||||
pushd "${test_dir}/../.." >/dev/null
|
||||
ct_check_latest_imagestreams
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
ct_os_check_compulsory_vars
|
||||
|
||||
ct_os_enable_print_logs
|
||||
|
||||
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_cluster_up
|
||||
|
||||
ct_os_test_s2i_app "${IMAGE_NAME}" "${THISDIR}/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" \
|
||||
"quay.io/centos7/postgresql-10-centos7|postgresql:10"
|
||||
done
|
||||
|
||||
# Check the imagestream
|
||||
test_python_imagestream
|
||||
|
||||
# check if latest imagestream version is correct
|
||||
test_latest_imagestreams
|
||||
|
||||
OS_TESTSUITE_RESULT=0
|
||||
|
||||
ct_os_cluster_down
|
||||
|
||||
# vim: set tabstop=2:shiftwidth=2:expandtab:
|
||||
|
||||
56
test/run-openshift-remote-cluster
Executable file
56
test/run-openshift-remote-cluster
Executable file
|
|
@ -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:
|
||||
|
||||
6
test/setup-cfg-test-app/pyproject.toml
Normal file
6
test/setup-cfg-test-app/pyproject.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=42",
|
||||
"wheel"
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
14
test/setup-cfg-test-app/setup.cfg
Normal file
14
test/setup-cfg-test-app/setup.cfg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[metadata]
|
||||
name = testapp
|
||||
version = 0.1
|
||||
|
||||
[options]
|
||||
install_requires =
|
||||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
package_dir =
|
||||
= .
|
||||
packages = find:
|
||||
|
||||
[options.packages.find]
|
||||
where = .
|
||||
4
test/setup-cfg-test-app/wsgi.py
Normal file
4
test/setup-cfg-test-app/wsgi.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
57
test/setup-requirements-test-app/.gitignore
vendored
Normal file
57
test/setup-requirements-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
3
test/setup-requirements-test-app/requirements.txt
Normal file
3
test/setup-requirements-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
-e .
|
||||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
10
test/setup-requirements-test-app/setup.py
Normal file
10
test/setup-requirements-test-app/setup.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
setup (
|
||||
name = "testapp",
|
||||
version = "0.1",
|
||||
description = "Example application to be deployed.",
|
||||
packages = find_packages(),
|
||||
install_requires = ["gunicorn"],
|
||||
)
|
||||
4
test/setup-requirements-test-app/testapp.py
Normal file
4
test/setup-requirements-test-app/testapp.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
57
test/setup-test-app/.gitignore
vendored
Normal file
57
test/setup-test-app/.gitignore
vendored
Normal file
|
|
@ -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/
|
||||
2
test/setup-test-app/requirements.txt
Normal file
2
test/setup-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
10
test/setup-test-app/setup.py
Normal file
10
test/setup-test-app/setup.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
setup (
|
||||
name = "testapp",
|
||||
version = "0.1",
|
||||
description = "Example application to be deployed.",
|
||||
packages = find_packages(),
|
||||
install_requires = ["gunicorn"],
|
||||
)
|
||||
4
test/setup-test-app/testapp.py
Normal file
4
test/setup-test-app/testapp.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
def application(environ, start_response):
|
||||
start_response('200 OK', [('Content-Type','text/plain')])
|
||||
return [b"Hello from gunicorn WSGI application!"]
|
||||
30
test/standalone-test-app/app.py
Normal file
30
test/standalone-test-app/app.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import os
|
||||
import time
|
||||
|
||||
from gunicorn.app.base import BaseApplication
|
||||
from six import iteritems
|
||||
|
||||
print('LOADING MODULE %s' % __file__)
|
||||
|
||||
def wsgi_handler(environ, start_response):
|
||||
print('HANDLE REQUEST %s' % time.time())
|
||||
start_response('200 OK', [('Content-Type','text/html')])
|
||||
return [b"Hello World from standalone WSGI application!"]
|
||||
|
||||
class StandaloneApplication(BaseApplication):
|
||||
def __init__(self, app, options=None):
|
||||
self.options = options or {}
|
||||
self.application = app
|
||||
super(StandaloneApplication, self).__init__()
|
||||
|
||||
def load_config(self):
|
||||
config = dict([(key, value) for key, value in iteritems(self.options)
|
||||
if key in self.cfg.settings and value is not None])
|
||||
for key, value in iteritems(config):
|
||||
self.cfg.set(key.lower(), value)
|
||||
|
||||
def load(self):
|
||||
return self.application
|
||||
|
||||
if __name__ == '__main__':
|
||||
StandaloneApplication(wsgi_handler, {'bind': ':8080'}).run()
|
||||
3
test/standalone-test-app/requirements.txt
Normal file
3
test/standalone-test-app/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
gunicorn<20.0.0; python_version < '3.5'
|
||||
gunicorn>=20.0.0; python_version >= '3.5'
|
||||
six
|
||||
1368
test/test-lib-openshift.sh
Normal file
1368
test/test-lib-openshift.sh
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue