From ae482a1665e528eeaea9ba459191e8f689c6df63 Mon Sep 17 00:00:00 2001 From: Honza Horak Date: Tue, 8 Jul 2025 17:40:16 +0200 Subject: [PATCH] container sources not used for building fedora containers anymore --- .gitignore | 0 6 | 1 - Dockerfile | 80 - Dockerfile.fedora | 1 - README.md | 1 - bot-cfg.yml | 20 - dead.package | 1 + help.md | 1 - root/usr/bin/container-entrypoint | 2 - root/usr/bin/run-redis | 27 - root/usr/bin/usage | 4 - root/usr/libexec/container-setup | 31 - .../share/container-scripts/redis/README.md | 85 - .../redis/base.conf.template | 1 - .../share/container-scripts/redis/common.sh | 26 - .../share/container-scripts/redis/helpers.sh | 24 - .../redis/password.conf.template | 3 - .../container-scripts/redis/post-init.sh | 6 - .../share/container-scripts/redis/scl_enable | 3 - .../redis/validate-variables.sh | 15 - sources | 0 test/examples/redis-ephemeral-template.json | 216 --- test/examples/redis-persistent-template.json | 240 --- test/imagestreams/redis-centos.json | 85 - test/imagestreams/redis-rhel-aarch64.json | 67 - test/imagestreams/redis-rhel.json | 121 -- test/redis-ephemeral-template.json | 216 --- test/run | 359 ----- test/run-openshift | 1 - test/run-openshift-local-cluster | 119 -- test/run-openshift-remote-cluster | 37 - test/test-lib-openshift.sh | 1364 ----------------- test/test-lib-redis.sh | 37 - test/test-lib-remote-openshift.sh | 116 -- test/test-lib.sh | 1072 ------------- 35 files changed, 1 insertion(+), 4381 deletions(-) delete mode 100644 .gitignore delete mode 120000 6 delete mode 100644 Dockerfile delete mode 120000 Dockerfile.fedora delete mode 120000 README.md delete mode 100644 bot-cfg.yml create mode 100644 dead.package delete mode 120000 help.md delete mode 100755 root/usr/bin/container-entrypoint delete mode 100755 root/usr/bin/run-redis delete mode 100755 root/usr/bin/usage delete mode 100755 root/usr/libexec/container-setup delete mode 100644 root/usr/share/container-scripts/redis/README.md delete mode 100644 root/usr/share/container-scripts/redis/base.conf.template delete mode 100644 root/usr/share/container-scripts/redis/common.sh delete mode 100644 root/usr/share/container-scripts/redis/helpers.sh delete mode 100644 root/usr/share/container-scripts/redis/password.conf.template delete mode 100644 root/usr/share/container-scripts/redis/post-init.sh delete mode 100644 root/usr/share/container-scripts/redis/scl_enable delete mode 100644 root/usr/share/container-scripts/redis/validate-variables.sh delete mode 100644 sources delete mode 100644 test/examples/redis-ephemeral-template.json delete mode 100644 test/examples/redis-persistent-template.json delete mode 100644 test/imagestreams/redis-centos.json delete mode 100644 test/imagestreams/redis-rhel-aarch64.json delete mode 100644 test/imagestreams/redis-rhel.json delete mode 100644 test/redis-ephemeral-template.json delete mode 100755 test/run delete mode 120000 test/run-openshift delete mode 100755 test/run-openshift-local-cluster delete mode 100755 test/run-openshift-remote-cluster delete mode 100644 test/test-lib-openshift.sh delete mode 100644 test/test-lib-redis.sh delete mode 100644 test/test-lib-remote-openshift.sh delete mode 100644 test/test-lib.sh diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/6 b/6 deleted file mode 120000 index 945c9b4..0000000 --- a/6 +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index d0941ce..0000000 --- a/Dockerfile +++ /dev/null @@ -1,80 +0,0 @@ -FROM registry.fedoraproject.org/f35/s2i-core:latest - -# Redis image based on Software Collections packages -# -# Volumes: -# * /var/lib/redis/data - Datastore for Redis -# Environment: -# * $REDIS_PASSWORD - Database password - -ENV NAME=redis \ - RELEASE=1 \ - VERSION=6 - -ENV REDIS_VERSION=$VERSION \ - HOME=/var/lib/redis - -ENV SUMMARY="Redis in-memory data structure store, used as database, cache and message broker" \ - DESCRIPTION="Redis $REDIS_VERSION available as container, is an advanced key-value store. \ -It is often referred to as a data structure server since keys can contain strings, hashes, lists, \ -sets and sorted sets. You can run atomic operations on these types, like appending to a string; \ -incrementing the value in a hash; pushing to a list; computing set intersection, union and difference; \ -or getting the member with highest ranking in a sorted set. In order to achieve its outstanding \ -performance, Redis works with an in-memory dataset. Depending on your use case, you can persist \ -it either by dumping the dataset to disk every once in a while, or by appending each command to a log." - -LABEL summary="$SUMMARY" \ - description="$DESCRIPTION" \ - io.k8s.description="$SUMMARY" \ - io.k8s.display-name="Redis 6" \ - io.openshift.expose-services="6379:redis" \ - io.openshift.tags="database,redis,redis6" \ - com.redhat.component="$NAME" \ - name="$FGC/$NAME" \ - version="$VERSION" \ - usage="docker run -d --name redis_database -p 6379:6379 $FGC/$NAME" \ - maintainer="SoftwareCollections.org " - -EXPOSE 6379 - -# Create user for redis that has known UID -# We need to do this before installing the RPMs which would create user with random UID -# The UID is the one used by the default user from the parent layer (1001), -# and since the user exists already, do not create a new one, but only rename -# the existing -# This image must forever use UID 1001 for redis user so our volumes are -# safe in the future. This should *never* change, the last test is there -# to make sure of that. -RUN getent group redis &> /dev/null || groupadd -r redis &> /dev/null && \ - usermod -l redis -aG redis -c 'Redis Server' default &> /dev/null && \ -# Install gettext for envsubst command - dnf install -y yum-utils gettext policycoreutils && \ - INSTALL_PKGS="redis" && \ - dnf install -y --setopt=tsflags=nodocs --nogpgcheck $INSTALL_PKGS && \ - rpm -V $INSTALL_PKGS && \ - dnf clean all && \ - mkdir -p /var/lib/redis/data && chown -R redis.0 /var/lib/redis && \ - [[ "$(id redis)" == "uid=1001(redis)"* ]] - -# Get prefix path and path to scripts rather than hard-code them in scripts -ENV CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/redis \ - REDIS_PREFIX=/usr \ - REDIS_CONF=/etc/redis/redis.conf - -COPY root / - -# this is needed due to issues with squash -# when this directory gets rm'd by the container-setup -# script. -RUN /usr/libexec/container-setup - -VOLUME ["/var/lib/redis/data"] - -# Using a numeric value because of a comment in [1]: -# If your S2I image does not include a USER declaration with a numeric user, -# your builds will fail by default. -# [1] https://docs.openshift.com/container-platform/4.4/openshift_images/create-images.html#images-create-guide-openshift_create-images -USER 1001 - -ENTRYPOINT ["container-entrypoint"] -CMD ["run-redis"] diff --git a/Dockerfile.fedora b/Dockerfile.fedora deleted file mode 120000 index 1d1fe94..0000000 --- a/Dockerfile.fedora +++ /dev/null @@ -1 +0,0 @@ -Dockerfile \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 120000 index 0b7f519..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -root/usr/share/container-scripts/redis/README.md \ No newline at end of file diff --git a/bot-cfg.yml b/bot-cfg.yml deleted file mode 100644 index 3a3b98b..0000000 --- a/bot-cfg.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -version: "1" - -betka: - # is betka enabled for this repository - # optional - defaults to true - enabled: true - notifications: - email_addresses: ["pkubat@redhat.com", "phracek@redhat.com", "hhorak@redhat.com"] - - # Specify if master branch in upstream repository is synced - master_checker: true - # Should pull requests be synced? - pr_checker: false - # Path to directory with dockerfile withing upstream repository - upstream_git_path: "6" - # Github comment message to enforce sync of a pull request - pr_comment_message: "[test]" - # Specify URL to an image used for dist-git source generation. Like - image_url: "quay.io/rhscl/cwt-generator" diff --git a/dead.package b/dead.package new file mode 100644 index 0000000..7290702 --- /dev/null +++ b/dead.package @@ -0,0 +1 @@ +container sources not used for building fedora containers anymore diff --git a/help.md b/help.md deleted file mode 120000 index 42061c0..0000000 --- a/help.md +++ /dev/null @@ -1 +0,0 @@ -README.md \ No newline at end of file diff --git a/root/usr/bin/container-entrypoint b/root/usr/bin/container-entrypoint deleted file mode 100755 index 9d8ad4d..0000000 --- a/root/usr/bin/container-entrypoint +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -exec "$@" diff --git a/root/usr/bin/run-redis b/root/usr/bin/run-redis deleted file mode 100755 index 835a7fb..0000000 --- a/root/usr/bin/run-redis +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -export_vars=$(cgroup-limits); export $export_vars -source ${CONTAINER_SCRIPTS_PATH}/common.sh -set -eu - -[ -f ${CONTAINER_SCRIPTS_PATH}/validate-variables.sh ] && source ${CONTAINER_SCRIPTS_PATH}/validate-variables.sh - -# Process the Redis configuration files -log_info 'Processing Redis configuration files ...' -if [[ -v REDIS_PASSWORD ]]; then - envsubst < ${CONTAINER_SCRIPTS_PATH}/password.conf.template >> "${REDIS_CONF}" -else - log_info 'WARNING: setting REDIS_PASSWORD is recommended' -fi - -# Source post-init source if exists -if [ -f ${CONTAINER_SCRIPTS_PATH}/post-init.sh ]; then - log_info 'Sourcing post-init.sh ...' - source ${CONTAINER_SCRIPTS_PATH}/post-init.sh -fi - -# Restart the Redis server with public IP bindings -unset_env_vars -log_volume_info "${REDIS_DATADIR}" -log_info 'Running final exec -- Only Redis logs after this point' -exec ${REDIS_PREFIX}/bin/redis-server "${REDIS_CONF}" --daemonize no "$@" 2>&1 diff --git a/root/usr/bin/usage b/root/usr/bin/usage deleted file mode 100755 index d204ed2..0000000 --- a/root/usr/bin/usage +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -cat /usr/share/container-scripts/redis/README.md - diff --git a/root/usr/libexec/container-setup b/root/usr/libexec/container-setup deleted file mode 100755 index 4b452f5..0000000 --- a/root/usr/libexec/container-setup +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -source ${CONTAINER_SCRIPTS_PATH}/common.sh -set -eu - -# setup config file -if [ -n "${ENABLED_COLLECTIONS:-}" ] ; then - mv /etc/opt/rh/rh-redis6/redis.conf "${REDIS_CONF}" - ln -s "${REDIS_CONF}" /etc/opt/rh/rh-redis6/redis.conf -fi - -# setup directory for data -chown -R redis:0 "${HOME}" "${REDIS_CONF}" -restorecon -R "${HOME}" "${REDIS_CONF}" - -# create a symlink for SCL datadir, so there is some reasonable content there -if [ -n "${ENABLED_COLLECTIONS:-}" ] ; then - rmdir /var/opt/rh/rh-redis6/lib/redis/ - ln -s /var/lib/redis /var/opt/rh/rh-redis6/lib/redis -fi - -# Loosen permission bits for group to avoid problems running container with -# arbitrary UID -# When only specifying user, group is 0, that's why /var/lib/redis must have -# owner redis.0; that allows to avoid a+rwx for this dir -chmod 0770 "${HOME}" "${REDIS_DATADIR}" -chmod 0660 "${REDIS_CONF}" - -# adjust config with changes we do every-time -clear_config -envsubst < ${CONTAINER_SCRIPTS_PATH}/base.conf.template >> "${REDIS_CONF}" diff --git a/root/usr/share/container-scripts/redis/README.md b/root/usr/share/container-scripts/redis/README.md deleted file mode 100644 index 97db572..0000000 --- a/root/usr/share/container-scripts/redis/README.md +++ /dev/null @@ -1,85 +0,0 @@ -Redis 6 in-memory data structure store container image -====================================================== - -This container image includes Redis 6 in-memory data structure store for OpenShift and general usage. -Users can choose between RHEL, CentOS and Fedora based images. -The RHEL images are available in the [Red Hat Container Catalog](https://access.redhat.com/containers/), -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). - -Note: while the examples in this README are calling `podman`, you can replace any such calls by `docker` with the same arguments - -Description ------------ - -Redis 6 available as container, is an advanced key-value store. -It is often referred to as a data structure server since keys can contain strings, hashes, lists, -sets and sorted sets. You can run atomic operations on these types, like appending to a string; -incrementing the value in a hash; pushing to a list; computing set intersection, union and difference; -or getting the member with highest ranking in a sorted set. In order to achieve its outstanding -performance, Redis works with an in-memory dataset. Depending on your use case, you can persist -it either by dumping the dataset to disk every once in a while, or by appending each command to a log. - - -Usage ------ - -For this, we will assume that you are using the `rhel8/redis-6` image. -If you want to set only the mandatory environment variables and not store -the database in a host directory, execute the following command: - -``` -$ podman run -d --name redis_database -p 6379:6379 rhel8/redis-6 -``` - -This will create a container named `redis_database`. Port 6379 will be exposed and mapped -to the host. - -If you want your database to be persistent across container executions, also add a -`-v /host/db/path:/var/lib/redis/data:Z` argument. This will be the Redis data directory. - -For protecting Redis data by a password, pass `REDIS_PASSWORD` environment variable -to the container like this: - -``` -$ podman run -d --name redis_database -e REDIS_PASSWORD=strongpassword rhel8/redis-6 -``` - -**Warning: since Redis is pretty fast an outside user can try up to -150k passwords per second against a good box. This means that you should -use a very strong password otherwise it will be very easy to break.** - - -Environment variables and volumes ----------------------------------- - -**`REDIS_PASSWORD`** - Password for the server access - - -You can also set the following mount points by passing the `-v /host:/container:Z` flag to podman. - -**`/var/lib/redis/data`** - Redis data directory - - -**Notice: When mouting a directory from the host into the container, ensure that the mounted -directory has the appropriate permissions and that the owner and group of the directory -matches the user UID or name which is running inside the container.** - - -Troubleshooting ---------------- -Redis logs into standard output, so the log is available in the container log. The log can be examined by running: - - podman logs - - -See also --------- -Dockerfile and other sources for this container image are available on -https://github.com/sclorg/redis-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. diff --git a/root/usr/share/container-scripts/redis/base.conf.template b/root/usr/share/container-scripts/redis/base.conf.template deleted file mode 100644 index 9d3f01b..0000000 --- a/root/usr/share/container-scripts/redis/base.conf.template +++ /dev/null @@ -1 +0,0 @@ -dir ${REDIS_DATADIR} diff --git a/root/usr/share/container-scripts/redis/common.sh b/root/usr/share/container-scripts/redis/common.sh deleted file mode 100644 index d131515..0000000 --- a/root/usr/share/container-scripts/redis/common.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -source ${CONTAINER_SCRIPTS_PATH}/helpers.sh - -# Data directory where Redis database files live. The data subdirectory is here -# because .bashrc lives in /var/lib/redis/ and we don't want a -# volume to override it. -export REDIS_DATADIR=/var/lib/redis/data - -# Be paranoid and stricter than we should be. -redis_password_regex='^[a-zA-Z0-9_~!@#$%^&*()-=<>,.?;:|]+$' - -# Make sure env variables don't propagate to redis process. -function unset_env_vars() { - log_info 'Cleaning up environment variable REDIS_PASSWORD ...' - unset REDIS_PASSWORD -} - -# Comment out settings that we'll set in container specifically -function clear_config() { - sed -e "s/^bind/#bind/" \ - -e "s/^logfile/#logfile/" \ - -e "s/^dir /#dir /" \ - -e "/^protected-mode/s/yes/no/" \ - -i "${REDIS_CONF}" -} diff --git a/root/usr/share/container-scripts/redis/helpers.sh b/root/usr/share/container-scripts/redis/helpers.sh deleted file mode 100644 index 4e832fc..0000000 --- a/root/usr/share/container-scripts/redis/helpers.sh +++ /dev/null @@ -1,24 +0,0 @@ -function log_info { - echo "---> `date +%T` $@" -} - -function log_and_run { - log_info "Running $@" - "$@" -} - -function log_volume_info { - CONTAINER_DEBUG=${CONTAINER_DEBUG:-} - if [[ "${CONTAINER_DEBUG,,}" != "true" ]]; then - return - fi - - log_info "Volume info for $@:" - set +e - log_and_run mount - while [ $# -gt 0 ]; do - log_and_run ls -alZ $1 - shift - done - set -e -} diff --git a/root/usr/share/container-scripts/redis/password.conf.template b/root/usr/share/container-scripts/redis/password.conf.template deleted file mode 100644 index bd2eef3..0000000 --- a/root/usr/share/container-scripts/redis/password.conf.template +++ /dev/null @@ -1,3 +0,0 @@ -# password for the server -requirepass "${REDIS_PASSWORD}" - diff --git a/root/usr/share/container-scripts/redis/post-init.sh b/root/usr/share/container-scripts/redis/post-init.sh deleted file mode 100644 index 5ee2c96..0000000 --- a/root/usr/share/container-scripts/redis/post-init.sh +++ /dev/null @@ -1,6 +0,0 @@ -# This file serves for extending the container image, typically by changing -# the configuration, loading some data etc. - -# Feel free to add content to this file or rewrite it at all. -# You may also start redis server locally to load some data for example, -# but do not forget to stop it after it, so it can be restarted after it. diff --git a/root/usr/share/container-scripts/redis/scl_enable b/root/usr/share/container-scripts/redis/scl_enable deleted file mode 100644 index 5a25432..0000000 --- a/root/usr/share/container-scripts/redis/scl_enable +++ /dev/null @@ -1,3 +0,0 @@ -# This will make scl collection binaries work out of box. -unset BASH_ENV PROMPT_COMMAND ENV -source scl_source enable ${ENABLED_COLLECTIONS} diff --git a/root/usr/share/container-scripts/redis/validate-variables.sh b/root/usr/share/container-scripts/redis/validate-variables.sh deleted file mode 100644 index 57138a4..0000000 --- a/root/usr/share/container-scripts/redis/validate-variables.sh +++ /dev/null @@ -1,15 +0,0 @@ -function usage() { - [ $# == 1 ] && echo "error: $1" - echo "You can specify the following environment variables:" - echo " REDIS_PASSWORD (regex: '$redis_password_regex')" - exit 1 -} - -function validate_variables() { - # Check basic sanity of specified variables - if [[ -v REDIS_PASSWORD ]]; then - [[ "$REDIS_PASSWORD" =~ $redis_password_regex ]] || usage "Invalid password" - fi -} - -validate_variables diff --git a/sources b/sources deleted file mode 100644 index e69de29..0000000 diff --git a/test/examples/redis-ephemeral-template.json b/test/examples/redis-ephemeral-template.json deleted file mode 100644 index f00f8e9..0000000 --- a/test/examples/redis-ephemeral-template.json +++ /dev/null @@ -1,216 +0,0 @@ -{ - "kind": "Template", - "apiVersion": "template.openshift.io/v1", - "metadata": { - "name": "redis-ephemeral", - "annotations": { - "openshift.io/display-name": "Redis (Ephemeral)", - "description": "Redis in-memory data structure store, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/5.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing", - "iconClass": "icon-redis", - "tags": "database,redis", - "openshift.io/long-description": "This template provides a standalone Redis server. The data is not stored on persistent storage, so any restart of the service will result in all data being lost.", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "openshift.io/documentation-url": "https://github.com/sclorg/redis-container/tree/master/5", - "openshift.io/support-url": "https://access.redhat.com" - } - }, - "message": "The following service(s) have been created in your project: ${DATABASE_SERVICE_NAME}.\n\n Password: ${REDIS_PASSWORD}\n Connection URL: redis://${DATABASE_SERVICE_NAME}:6379/\n\nFor more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/5.", - "labels": { - "template": "redis-ephemeral-template" - }, - "objects": [ - { - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.openshift.io/expose-password": "{.data['database-password']}" - } - }, - "stringData" : { - "database-password" : "${REDIS_PASSWORD}" - } - }, - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}" - } - }, - "spec": { - "ports": [ - { - "name": "redis", - "protocol": "TCP", - "port": 6379, - "targetPort": 6379, - "nodePort": 0 - } - ], - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "type": "ClusterIP", - "sessionAffinity": "None" - }, - "status": { - "loadBalancer": {} - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "apps.openshift.io/v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.alpha.openshift.io/wait-for-ready": "true" - } - }, - "spec": { - "strategy": { - "type": "Recreate" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "redis" - ], - "from": { - "kind": "ImageStreamTag", - "name": "redis:${REDIS_VERSION}", - "namespace": "${NAMESPACE}" - }, - "lastTriggeredImage": "" - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "template": { - "metadata": { - "labels": { - "name": "${DATABASE_SERVICE_NAME}" - } - }, - "spec": { - "containers": [ - { - "name": "redis", - "image": " ", - "ports": [ - { - "containerPort": 6379, - "protocol": "TCP" - } - ], - "readinessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 5, - "exec": { - "command": [ "/bin/sh", "-i", "-c", "test \"$(redis-cli -h 127.0.0.1 -a $REDIS_PASSWORD ping)\" == \"PONG\""] - } - }, - "livenessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 30, - "tcpSocket": { - "port": 6379 - } - }, - "env": [ - { - "name": "REDIS_PASSWORD", - "valueFrom": { - "secretKeyRef" : { - "name" : "${DATABASE_SERVICE_NAME}", - "key" : "database-password" - } - } - } - ], - "resources": { - "limits": { - "memory": "${MEMORY_LIMIT}" - } - }, - "volumeMounts": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "mountPath": "/var/lib/redis/data" - } - ], - "terminationMessagePath": "/dev/termination-log", - "imagePullPolicy": "IfNotPresent", - "capabilities": {}, - "securityContext": { - "capabilities": {}, - "privileged": false - } - } - ], - "volumes": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "emptyDir": { - "medium": "" - } - } - ], - "restartPolicy": "Always", - "dnsPolicy": "ClusterFirst" - } - } - }, - "status": {} - } - ], - "parameters": [ - { - "name": "MEMORY_LIMIT", - "displayName": "Memory Limit", - "description": "Maximum amount of memory the container can use.", - "value": "512Mi", - "required": true - }, - { - "name": "NAMESPACE", - "displayName": "Namespace", - "description": "The OpenShift Namespace where the ImageStream resides.", - "value": "openshift" - }, - { - "name": "DATABASE_SERVICE_NAME", - "displayName": "Database Service Name", - "description": "The name of the OpenShift Service exposed for the database.", - "value": "redis", - "required": true - }, - { - "name": "REDIS_PASSWORD", - "displayName": "Redis Connection Password", - "description": "Password for the Redis connection user.", - "generate": "expression", - "from": "[a-zA-Z0-9]{16}", - "required": true - }, - { - "name": "REDIS_VERSION", - "displayName": "Version of Redis Image", - "description": "Version of Redis image to be used (5-el7, 5-el8, 6-el7, 6-el8, or latest).", - "value": "6-el8", - "required": true - } - ] -} diff --git a/test/examples/redis-persistent-template.json b/test/examples/redis-persistent-template.json deleted file mode 100644 index f4815cf..0000000 --- a/test/examples/redis-persistent-template.json +++ /dev/null @@ -1,240 +0,0 @@ -{ - "kind": "Template", - "apiVersion": "template.openshift.io/v1", - "metadata": { - "name": "redis-persistent", - "annotations": { - "openshift.io/display-name": "Redis", - "description": "Redis in-memory data structure store, with persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/5.\n\nNOTE: You must have persistent volumes available in your cluster to use this template.", - "iconClass": "icon-redis", - "tags": "database,redis", - "openshift.io/long-description": "This template provides a standalone Redis server. The data is stored on persistent storage.", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "openshift.io/documentation-url": "https://github.com/sclorg/redis-container/tree/master/5", - "openshift.io/support-url": "https://access.redhat.com" - } - }, - "message": "The following service(s) have been created in your project: ${DATABASE_SERVICE_NAME}.\n\n Password: ${REDIS_PASSWORD}\n Connection URL: redis://${DATABASE_SERVICE_NAME}:6379/\n\nFor more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/5.", - "labels": { - "template": "redis-persistent-template" - }, - "objects": [ - { - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.openshift.io/expose-password": "{.data['database-password']}" - } - }, - "stringData" : { - "database-password" : "${REDIS_PASSWORD}" - } - }, - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}" - } - }, - "spec": { - "ports": [ - { - "name": "redis", - "protocol": "TCP", - "port": 6379, - "targetPort": 6379, - "nodePort": 0 - } - ], - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "type": "ClusterIP", - "sessionAffinity": "None" - }, - "status": { - "loadBalancer": {} - } - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "${VOLUME_CAPACITY}" - } - } - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "apps.openshift.io/v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.alpha.openshift.io/wait-for-ready": "true" - } - }, - "spec": { - "strategy": { - "type": "Recreate" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "redis" - ], - "from": { - "kind": "ImageStreamTag", - "name": "redis:${REDIS_VERSION}", - "namespace": "${NAMESPACE}" - }, - "lastTriggeredImage": "" - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "template": { - "metadata": { - "labels": { - "name": "${DATABASE_SERVICE_NAME}" - } - }, - "spec": { - "containers": [ - { - "name": "redis", - "image": " ", - "ports": [ - { - "containerPort": 6379, - "protocol": "TCP" - } - ], - "readinessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 5, - "exec": { - "command": [ "/bin/sh", "-i", "-c", "test \"$(redis-cli -h 127.0.0.1 -a $REDIS_PASSWORD ping)\" == \"PONG\""] - } - }, - "livenessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 30, - "tcpSocket": { - "port": 6379 - } - }, - "env": [ - { - "name": "REDIS_PASSWORD", - "valueFrom": { - "secretKeyRef" : { - "name" : "${DATABASE_SERVICE_NAME}", - "key" : "database-password" - } - } - } - ], - "resources": { - "limits": { - "memory": "${MEMORY_LIMIT}" - } - }, - "volumeMounts": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "mountPath": "/var/lib/redis/data" - } - ], - "terminationMessagePath": "/dev/termination-log", - "imagePullPolicy": "IfNotPresent", - "capabilities": {}, - "securityContext": { - "capabilities": {}, - "privileged": false - } - } - ], - "volumes": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "persistentVolumeClaim": { - "claimName": "${DATABASE_SERVICE_NAME}" - } - } - ], - "restartPolicy": "Always", - "dnsPolicy": "ClusterFirst" - } - } - }, - "status": {} - } - ], - "parameters": [ - { - "name": "MEMORY_LIMIT", - "displayName": "Memory Limit", - "description": "Maximum amount of memory the container can use.", - "value": "512Mi", - "required": true - }, - { - "name": "NAMESPACE", - "displayName": "Namespace", - "description": "The OpenShift Namespace where the ImageStream resides.", - "value": "openshift" - }, - { - "name": "DATABASE_SERVICE_NAME", - "displayName": "Database Service Name", - "description": "The name of the OpenShift Service exposed for the database.", - "value": "redis", - "required": true - }, - { - "name": "REDIS_PASSWORD", - "displayName": "Redis Connection Password", - "description": "Password for the Redis connection user.", - "generate": "expression", - "from": "[a-zA-Z0-9]{16}", - "required": true - }, - { - "name": "VOLUME_CAPACITY", - "displayName": "Volume Capacity", - "description": "Volume space available for data, e.g. 512Mi, 2Gi.", - "value": "1Gi", - "required": true - }, - { - "name": "REDIS_VERSION", - "displayName": "Version of Redis Image", - "description": "Version of Redis image to be used (5-el7, 5-el8, 6-el7, 6-el8, or latest).", - "value": "6-el8", - "required": true - } - ] -} diff --git a/test/imagestreams/redis-centos.json b/test/imagestreams/redis-centos.json deleted file mode 100644 index 27875a0..0000000 --- a/test/imagestreams/redis-centos.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "apiVersion": "image.openshift.io/v1", - "kind": "ImageStream", - "metadata": { - "annotations": { - "openshift.io/display-name": "Redis" - }, - "name": "redis" - }, - "spec": { - "tags": [ - { - "annotations": { - "description": "Provides a Redis database on CentOS. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Redis available on OpenShift, including major version updates.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis (Latest)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis" - }, - "from": { - "kind": "ImageStreamTag", - "name": "5-el8" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "latest" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on CentOS 8. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5 (CentOS 8)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "docker.io/centos/redis-5-centos8:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5-el8" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on CentOS 7. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5 (CentOS 7)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "quay.io/centos7/redis-5-centos7:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5-el7" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on CentOS 7. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis,hidden", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "quay.io/centos7/redis-5-centos7:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5" - } - ] - } -} diff --git a/test/imagestreams/redis-rhel-aarch64.json b/test/imagestreams/redis-rhel-aarch64.json deleted file mode 100644 index 309351b..0000000 --- a/test/imagestreams/redis-rhel-aarch64.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "apiVersion": "image.openshift.io/v1", - "kind": "ImageStream", - "metadata": { - "annotations": { - "openshift.io/display-name": "Redis" - }, - "name": "redis" - }, - "spec": { - "tags": [ - { - "annotations": { - "description": "Provides a Redis database on RHEL. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/6/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Redis available on OpenShift, including major version updates.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis (Latest)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis" - }, - "from": { - "kind": "ImageStreamTag", - "name": "6-el8" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "latest" - }, - { - "annotations": { - "description": "Provides a Redis 6 database on RHEL 8. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/6/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 6 (RHEL 8)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "6" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhel8/redis-6:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "6-el8" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on RHEL 8. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5 (RHEL 8)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhel8/redis-5:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5-el8" - } - ] - } -} diff --git a/test/imagestreams/redis-rhel.json b/test/imagestreams/redis-rhel.json deleted file mode 100644 index c9906b2..0000000 --- a/test/imagestreams/redis-rhel.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "apiVersion": "image.openshift.io/v1", - "kind": "ImageStream", - "metadata": { - "annotations": { - "openshift.io/display-name": "Redis" - }, - "name": "redis" - }, - "spec": { - "tags": [ - { - "annotations": { - "description": "Provides a Redis database on RHEL. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/6/README.md.\n\nWARNING: By selecting this tag, your application will automatically update to use the latest version of Redis available on OpenShift, including major version updates.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis (Latest)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis" - }, - "from": { - "kind": "ImageStreamTag", - "name": "6-el8" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "latest" - }, - { - "annotations": { - "description": "Provides a Redis 6 database on RHEL 8. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/6/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 6 (RHEL 8)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "6" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhel8/redis-6:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "6-el8" - }, - { - "annotations": { - "description": "Provides a Redis 6 database on RHEL 7. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/6/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 6 (RHEL 7)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "6" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhscl/redis-6-rhel7:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "6-el7" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on RHEL 8. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5 (RHEL 8)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhel8/redis-5:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5-el8" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on RHEL 7. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5 (RHEL 7)", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhscl/redis-5-rhel7:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5-el7" - }, - { - "annotations": { - "description": "Provides a Redis 5 database on RHEL 7. For more information about using this database image, including OpenShift considerations, see https://github.com/sclorg/redis-container/tree/master/5/README.md.", - "iconClass": "icon-redis", - "openshift.io/display-name": "Redis 5", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "tags": "redis,hidden", - "version": "5" - }, - "from": { - "kind": "DockerImage", - "name": "registry.redhat.io/rhscl/redis-5-rhel7:latest" - }, - "referencePolicy": { - "type": "Local" - }, - "name": "5" - } - ] - } -} diff --git a/test/redis-ephemeral-template.json b/test/redis-ephemeral-template.json deleted file mode 100644 index f00f8e9..0000000 --- a/test/redis-ephemeral-template.json +++ /dev/null @@ -1,216 +0,0 @@ -{ - "kind": "Template", - "apiVersion": "template.openshift.io/v1", - "metadata": { - "name": "redis-ephemeral", - "annotations": { - "openshift.io/display-name": "Redis (Ephemeral)", - "description": "Redis in-memory data structure store, without persistent storage. For more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/5.\n\nWARNING: Any data stored will be lost upon pod destruction. Only use this template for testing", - "iconClass": "icon-redis", - "tags": "database,redis", - "openshift.io/long-description": "This template provides a standalone Redis server. The data is not stored on persistent storage, so any restart of the service will result in all data being lost.", - "openshift.io/provider-display-name": "Red Hat, Inc.", - "openshift.io/documentation-url": "https://github.com/sclorg/redis-container/tree/master/5", - "openshift.io/support-url": "https://access.redhat.com" - } - }, - "message": "The following service(s) have been created in your project: ${DATABASE_SERVICE_NAME}.\n\n Password: ${REDIS_PASSWORD}\n Connection URL: redis://${DATABASE_SERVICE_NAME}:6379/\n\nFor more information about using this template, including OpenShift considerations, see https://github.com/sclorg/redis-container/blob/master/5.", - "labels": { - "template": "redis-ephemeral-template" - }, - "objects": [ - { - "kind": "Secret", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.openshift.io/expose-password": "{.data['database-password']}" - } - }, - "stringData" : { - "database-password" : "${REDIS_PASSWORD}" - } - }, - { - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.openshift.io/expose-uri": "redis://{.spec.clusterIP}:{.spec.ports[?(.name==\"redis\")].port}" - } - }, - "spec": { - "ports": [ - { - "name": "redis", - "protocol": "TCP", - "port": 6379, - "targetPort": 6379, - "nodePort": 0 - } - ], - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "type": "ClusterIP", - "sessionAffinity": "None" - }, - "status": { - "loadBalancer": {} - } - }, - { - "kind": "DeploymentConfig", - "apiVersion": "apps.openshift.io/v1", - "metadata": { - "name": "${DATABASE_SERVICE_NAME}", - "annotations": { - "template.alpha.openshift.io/wait-for-ready": "true" - } - }, - "spec": { - "strategy": { - "type": "Recreate" - }, - "triggers": [ - { - "type": "ImageChange", - "imageChangeParams": { - "automatic": true, - "containerNames": [ - "redis" - ], - "from": { - "kind": "ImageStreamTag", - "name": "redis:${REDIS_VERSION}", - "namespace": "${NAMESPACE}" - }, - "lastTriggeredImage": "" - } - }, - { - "type": "ConfigChange" - } - ], - "replicas": 1, - "selector": { - "name": "${DATABASE_SERVICE_NAME}" - }, - "template": { - "metadata": { - "labels": { - "name": "${DATABASE_SERVICE_NAME}" - } - }, - "spec": { - "containers": [ - { - "name": "redis", - "image": " ", - "ports": [ - { - "containerPort": 6379, - "protocol": "TCP" - } - ], - "readinessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 5, - "exec": { - "command": [ "/bin/sh", "-i", "-c", "test \"$(redis-cli -h 127.0.0.1 -a $REDIS_PASSWORD ping)\" == \"PONG\""] - } - }, - "livenessProbe": { - "timeoutSeconds": 1, - "initialDelaySeconds": 30, - "tcpSocket": { - "port": 6379 - } - }, - "env": [ - { - "name": "REDIS_PASSWORD", - "valueFrom": { - "secretKeyRef" : { - "name" : "${DATABASE_SERVICE_NAME}", - "key" : "database-password" - } - } - } - ], - "resources": { - "limits": { - "memory": "${MEMORY_LIMIT}" - } - }, - "volumeMounts": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "mountPath": "/var/lib/redis/data" - } - ], - "terminationMessagePath": "/dev/termination-log", - "imagePullPolicy": "IfNotPresent", - "capabilities": {}, - "securityContext": { - "capabilities": {}, - "privileged": false - } - } - ], - "volumes": [ - { - "name": "${DATABASE_SERVICE_NAME}-data", - "emptyDir": { - "medium": "" - } - } - ], - "restartPolicy": "Always", - "dnsPolicy": "ClusterFirst" - } - } - }, - "status": {} - } - ], - "parameters": [ - { - "name": "MEMORY_LIMIT", - "displayName": "Memory Limit", - "description": "Maximum amount of memory the container can use.", - "value": "512Mi", - "required": true - }, - { - "name": "NAMESPACE", - "displayName": "Namespace", - "description": "The OpenShift Namespace where the ImageStream resides.", - "value": "openshift" - }, - { - "name": "DATABASE_SERVICE_NAME", - "displayName": "Database Service Name", - "description": "The name of the OpenShift Service exposed for the database.", - "value": "redis", - "required": true - }, - { - "name": "REDIS_PASSWORD", - "displayName": "Redis Connection Password", - "description": "Password for the Redis connection user.", - "generate": "expression", - "from": "[a-zA-Z0-9]{16}", - "required": true - }, - { - "name": "REDIS_VERSION", - "displayName": "Version of Redis Image", - "description": "Version of Redis image to be used (5-el7, 5-el8, 6-el7, 6-el8, or latest).", - "value": "6-el8", - "required": true - } - ] -} diff --git a/test/run b/test/run deleted file mode 100755 index 567ed16..0000000 --- a/test/run +++ /dev/null @@ -1,359 +0,0 @@ -#!/bin/bash -# -# Test the Redis image. -# -# IMAGE_NAME specifies the name of the candidate image used for testing. -# The image has to be available before this script is executed. -# - -set -o errexit -set -o nounset -shopt -s nullglob - -[ "${DEBUG:-0}" -eq 1 ] && set -x - -test -n "${IMAGE_NAME-}" || { echo 'make sure $IMAGE_NAME is defined' && false ;} -test -n "${VERSION-}" || { echo 'make sure $VERSION is defined' && false; } -test -n "${OS-}" || { echo 'make sure $OS is defined' && false; } - -test_short_summary='' -TESTSUITE_RESULT=0 - -TEST_LIST="\ -run_container_creation_tests -run_tests_no_root -run_tests_no_pass -run_tests_no_pass_altuid -run_tests_no_root_altuid -run_change_password_test -run_doc_test -" - -CIDFILE_DIR=$(mktemp --suffix=redis_test_cidfiles -d) - -function cleanup() { - local cidfile - for cidfile in $CIDFILE_DIR/* ; do - local CONTAINER - CONTAINER=$(cat $cidfile) - - echo "Stopping and removing container $CONTAINER..." - docker stop $CONTAINER >/dev/null - local exit_status - exit_status=$(docker inspect -f '{{.State.ExitCode}}' $CONTAINER) - if [ "$exit_status" != "0" ]; then - echo "Inspecting container $CONTAINER" - docker inspect $CONTAINER - echo "Dumping logs for $CONTAINER" - docker logs $CONTAINER - fi - docker rm -v $CONTAINER >/dev/null - rm $cidfile - echo "Done." - done - rmdir $CIDFILE_DIR - - 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 -} -trap cleanup EXIT SIGINT - -check_result() { - local result="$1" - if [[ "$result" != "0" ]]; then - TESTCASE_RESULT=1 - fi - return $result -} - -function get_cid() { - local id="$1" ; shift || return 1 - echo $(cat "$CIDFILE_DIR/$id") -} - -function get_container_ip() { - local id="$1" ; shift - docker inspect --format='{{.NetworkSettings.IPAddress}}' $(get_cid "$id") -} - -function connection_works() { - local container_ip="$1"; shift - local password="$1"; shift - if [ "$(redis_cmd "$container_ip" "$password" ping)" == "PONG" ] ; then - return 0 - fi - return 1 -} - -function redis_cmd() { - local container_ip="$1"; shift - local password="$1"; shift - # if empty password is given, then no password will be specified - docker run --rm "$IMAGE_NAME" redis-cli -h "$container_ip" ${password:+-a "$password"} "$@" -} - -function test_connection() { - local name=$1 ; shift - local password=$1 ; shift - local ip - ip=$(get_container_ip $name) - echo " Testing Redis connection to $ip (password='${password:-}')..." - local max_attempts=10 - local sleep_time=2 - local i - for i in $(seq $max_attempts); do - echo " Trying to connect..." - if connection_works "$ip" "$password" ; then - echo " Success!" - echo - return 0 - fi - sleep $sleep_time - done - echo " Giving up: Failed to connect. Logs:" - docker logs $(get_cid $name) - return 1 -} - -function test_redis() { - local container_ip="$1" - local password="$2" - - echo " Testing Redis (password='${password:-}')" - redis_cmd "$container_ip" "$password" set a 1 >/dev/null - check_result $? - redis_cmd "$container_ip" "$password" set b 2 >/dev/null - check_result $? - test "$(redis_cmd "$container_ip" "$password" get b)" == '2' - echo " Success!" - echo -} - -function create_container() { - local name=$1 ; shift - cidfile="$CIDFILE_DIR/$name" - # create container with a cidfile in a directory for cleanup - local container_id - [ "${DEBUG:-0}" -eq 1 ] && echo "DEBUG: docker run ${DOCKER_ARGS:-} --cidfile $cidfile -d \"$@\" $IMAGE_NAME ${CONTAINER_ARGS:-}" >&2 - container_id="$(docker run ${DOCKER_ARGS:-} --cidfile $cidfile -d "$@" $IMAGE_NAME ${CONTAINER_ARGS:-})" - [ "${DEBUG:-0}" -eq 1 ] && echo "Created container $container_id" - [ x"$container_id" == "x" ] && return 1 || return 0 -} - -function run_change_password_test() { - local tmpdir=$(mktemp -d) - mkdir "${tmpdir}/data" && chmod -R a+rwx "${tmpdir}" - - # Create Redis container with persistent volume and set the initial password - create_container "testpass1" -e REDIS_PASSWORD=foo \ - -v ${tmpdir}:/var/lib/redis/data:Z - check_result $? - test_connection testpass1 foo - check_result $? - docker stop $(get_cid testpass1) >/dev/null - - # Create second container with changed password - create_container "testpass2" -e REDIS_PASSWORD=bar \ - -v ${tmpdir}:/var/lib/redis/data:Z - check_result $? - test_connection testpass2 bar - check_result $? - # The old password should not work anymore - container_ip="$(get_container_ip testpass2)" - connection_works "$container_ip" foo - check_result $? -} - -function assert_login_access() { - local container_ip=$1; shift - local PASS=$1 ; shift - local success=$1 ; shift - - if connection_works "$container_ip" "$PASS" ; then - if $success ; then - echo " Connection ($PASS) access granted as expected" - return 0 - fi - else - if ! $success ; then - echo " Connection ($PASS) access denied as expected" - return 0 - fi - fi - echo " Connection ($PASS) login assertion failed" - return 1 -} - -function assert_local_access() { - local id="$1" ; shift - docker exec $(get_cid "$id") bash -c 'redis-cli ping' -} - -# Make sure the invocation of docker run fails. -function assert_container_creation_fails() { - - # Time the docker run command. It should fail. If it doesn't fail, - # redis will keep running so we kill it with SIGKILL to make sure - # timeout returns a non-zero value. - local ret=0 - timeout -s 9 --preserve-status 60s docker run --rm "$@" $IMAGE_NAME >/dev/null || ret=$? - - # Timeout will exit with a high number. - if [ $ret -gt 10 ]; then - return 1 - fi -} - -function try_image_invalid_combinations() { - assert_container_creation_fails -e REDIS_PASSWORD="pass with space" "$@" - check_result $? -} - -function run_container_creation_tests() { - local ret - echo " Testing image entrypoint usage" - try_image_invalid_combinations - ret=$? - if [ $ret -eq 0 ]; then - echo " Success!" - else - echo " Failed!" - fi - echo - return $ret -} - -test_scl_usage() { - local name="$1" - local run_cmd="$2" - local expected="$3" - - echo " Testing the image SCL enable" - local out - out=$(docker run --rm ${IMAGE_NAME} /bin/bash -c "${run_cmd}") - if ! echo "${out}" | grep -q "${expected}"; then - echo "ERROR[/bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'" - return 1 - fi - out=$(docker exec $(get_cid $name) /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 $(get_cid $name) /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 -} - -run_doc_test() { - local tmpdir=$(mktemp -d) - local f - echo " Testing documentation in the container image" - # Extract the help.1 file from the container - docker run --rm ${IMAGE_NAME} /bin/bash -c "cat /help.1" >${tmpdir}/help.1 - # Check whether the help.1 file includes some important information - for term in 6379 "REDIS\_PASSWORD" volume; do - if ! cat ${tmpdir}/help.1 | grep -F -q -e "${term}" ; then - echo "ERROR: File /help.1 does not include '${term}'." - return 1 - fi - done - # Check whether the file uses the correct format - if ! file ${tmpdir}/help.1 | grep -q roff ; then - echo "ERROR: /help.1 is not in troff or groff format" - return 1 - fi - echo " Success!" - echo -} - -function run_tests() { - local name=$1 ; shift - local ret - envs=${PASS:+"-e REDIS_PASSWORD=$PASS"} - PASS=${PASS:-} - create_container $name $envs - ret=$? - check_result $ret - test_connection "$name" "$PASS" - ret=$? - check_result $ret - # Only check version on rhel/centos builds - if [ "$OS" != "fedora" ]; then - echo " Testing scl usage" - test_scl_usage $name 'redis-server --version' "$VERSION" - check_result $? - fi - echo " Testing login accesses" - local container_ip - container_ip=$(get_container_ip $name) - assert_login_access "$container_ip" "$PASS" true - ret=$? - check_result $ret - if [ -n "$PASS" ] ; then - assert_login_access "$container_ip" "${PASS}_foo" false - check_result $? - fi - assert_local_access "$name" - ret=$? - check_result $ret - if [ $ret -ne 0 ]; then - echo " Local access FAILED." - else - echo " Local access SUCCESS." - fi - echo - test_redis "$container_ip" "$PASS" - check_result $? -} - -function run_tests_no_root() { - # Normal tests with password - PASS=pass run_tests no_root -} - -function run_tests_no_pass() { - # Normal tests without password - run_tests no_pass -} - -function run_tests_no_pass_altuid() { - # Test with arbitrary uid for the container without password - DOCKER_ARGS="-u 12345" run_tests no_pass_altuid -} - -function run_tests_no_root_altuid() { - # Test with arbitrary uid for the container with password - DOCKER_ARGS="-u 12345" PASS=pass run_tests no_root_altuid -} - -function run_all_tests() { - for test_case in $TEST_SET; do - echo "Running test $test_case ...." - TESTCASE_RESULT=0 - $test_case - check_result $? - local test_msg - if [ $TESTCASE_RESULT -eq 0 ]; then - test_msg="[PASSED]" - else - test_msg="[FAILED]" - TESTSUITE_RESULT=1 - fi - printf -v test_short_summary "%s %s for '%s' %s\n" "${test_short_summary}" "${test_msg}" "$test_case" - [ -n "${FAIL_QUICKLY:-}" ] && cleanup "${APP_NAME}" && return 1 - done; -} - -TEST_SET=${TESTS:-$TEST_LIST} run_all_tests - -echo "Success!" -cleanup diff --git a/test/run-openshift b/test/run-openshift deleted file mode 120000 index d84575f..0000000 --- a/test/run-openshift +++ /dev/null @@ -1 +0,0 @@ -run-openshift-local-cluster \ No newline at end of file diff --git a/test/run-openshift-local-cluster b/test/run-openshift-local-cluster deleted file mode 100755 index e4dbbc1..0000000 --- a/test/run-openshift-local-cluster +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash -# -# Test the Redis image in OpenShift. -# -# IMAGE_NAME specifies a name of the candidate image used for testing. -# The image has to be available before this script is executed. -# - -THISDIR=$(dirname ${BASH_SOURCE[0]}) - -source "$THISDIR"/test-lib-openshift.sh -source ${THISDIR}/test-lib-redis.sh - -set -eo nounset - -trap ct_os_cleanup EXIT SIGINT - -ct_os_check_compulsory_vars - -ct_os_enable_print_logs - -function check_redis_os_service_connection() { - local util_image_name=$1 ; shift - local service_name=$1 ; shift - local pass=$1 ; shift - local timeout=${1:-60} ; shift || : - local pod_ip=$(ct_os_get_service_ip ${service_name}) - - : " Service ${service_name} check ..." - - local cmd="timeout 15 redis-cli -h $pod_ip -a $pass ping" - local expected_value="PONG" - local output - local ret - SECONDS=0 - - echo -n "Waiting for ${service_name} service becoming ready ..." - while true ; do - output=$(docker run --rm ${util_image_name} bash -c "${cmd}" || :) - echo "${output}" | grep -qe "${expected_value}" && ret=0 || ret=1 - if [ ${ret} -eq 0 ] ; then - echo " PASS" - return 0 - fi - echo -n "." - [ ${SECONDS} -gt ${timeout} ] && break - sleep 3 - done - echo " FAIL" - return 1 -} - -function test_redis_pure_image() { - local image_name=$1 - local image_name_no_namespace=${image_name##*/} - local service_name="${image_name_no_namespace%%:*}-testing" - - ct_os_new_project - # Create a specific imagestream tag for the image so that oc cannot use anything else - ct_os_upload_image "${image_name}" "$image_name_no_namespace" - - ct_os_deploy_pure_image "$image_name_no_namespace" \ - --name "${service_name}" \ - --env REDIS_PASSWORD=pass - - ct_os_wait_pod_ready "${service_name}" 60 - check_redis_os_service_connection "${image_name}" "${service_name}" pass - - ct_os_delete_project -} - -function test_redis_template() { - local image_name=${1:-quay.io/centos7/redis-5-centos7} - local image_name_no_namespace=${image_name##*/} - local service_name="${image_name_no_namespace%%:*}-testing" - - ct_os_new_project - ct_os_upload_image "${image_name}" "redis:$VERSION" - - ct_os_deploy_template_image "$THISDIR/redis-ephemeral-template.json" \ - NAMESPACE="$(oc project -q)" \ - REDIS_VERSION="$VERSION" \ - DATABASE_SERVICE_NAME="${service_name}" \ - REDIS_PASSWORD=pass - - ct_os_wait_pod_ready "${service_name}" 60 - check_redis_os_service_connection "${image_name}" "${service_name}" pass - - ct_os_delete_project -} - -ct_os_cluster_up -test_redis_pure_image "${IMAGE_NAME}" -test_redis_template "${IMAGE_NAME}" - -# test with the just built image and an integrated template -test_redis_integration "${IMAGE_NAME}" - -# test with a released image and an integrated template -PUBLIC_IMAGE_NAME=${PUBLIC_IMAGE_NAME:-$(ct_get_public_image_name "${OS}" "${BASE_IMAGE_NAME}" "${VERSION}")} - -# Try pulling the image first to see if it is accessible -if ct_check_image_availability "$PUBLIC_IMAGE_NAME"; then - test_redis_integration "${PUBLIC_IMAGE_NAME}" -else - echo "Warning: ${PUBLIC_IMAGE_NAME} could not be downloaded via 'docker'" - # ignore possible failure of this test for centos images - [ "${OS}" == "rhel7" ] && false "ERROR: Failed to pull image" -fi - -# Check the imagestream -test_redis_imagestream - -OS_TESTSUITE_RESULT=0 - -ct_os_cluster_down - -# vim: set tabstop=2:shiftwidth=2:expandtab: - diff --git a/test/run-openshift-remote-cluster b/test/run-openshift-remote-cluster deleted file mode 100755 index 2199f48..0000000 --- a/test/run-openshift-remote-cluster +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# Test the Redis image in OpenShift (remote cluster) -# -# IMAGE_NAME specifies a name of the candidate image used for testing. -# The image has to be available before this script is executed. -# VERSION specifies the major version of the Redis in format of X.Y -# OS specifies RHEL version (e.g. OS=rhel7) -# - -THISDIR=$(dirname ${BASH_SOURCE[0]}) - -source ${THISDIR}/test-lib-redis.sh - -set -eo nounset - -trap ct_os_cleanup EXIT SIGINT - -ct_os_set_ocp4 - -ct_os_check_compulsory_vars - -oc status || false "It looks like oc is not properly logged in." - -# For testing on OpenShift 4 we use external registry -export CT_EXTERNAL_REGISTRY=true - -# Check the template -test_redis_integration "${IMAGE_NAME}" - -# Check the imagestream -test_redis_imagestream - -OS_TESTSUITE_RESULT=0 - -# vim: set tabstop=2:shiftwidth=2:expandtab: - diff --git a/test/test-lib-openshift.sh b/test/test-lib-openshift.sh deleted file mode 100644 index 624a391..0000000 --- a/test/test-lib-openshift.sh +++ /dev/null @@ -1,1364 +0,0 @@ -# shellcheck shell=bash -# some functions are used from test-lib.sh, that is usually in the same dir -# shellcheck source=/dev/null -source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh - -# Set of functions for testing docker images in OpenShift using 'oc' command - -# A variable containing the overall test result; must be changed to 0 in the end -# of the testing script: -# OS_TESTSUITE_RESULT=0 -# And the following trap must be set, in the beginning of the test script: -# trap ct_os_cleanup EXIT SIGINT -OS_TESTSUITE_RESULT=1 -OS_CLUSTER_STARTED_BY_TEST=0 - -function ct_os_cleanup() { - if [ $OS_TESTSUITE_RESULT -eq 0 ] ; then - # shellcheck disable=SC2153 - echo "OpenShift tests for ${IMAGE_NAME} succeeded." - else - # shellcheck disable=SC2153 - echo "OpenShift tests for ${IMAGE_NAME} failed." - fi -} - -# ct_os_check_compulsory_vars -# --------------------------- -# Check the compulsory variables: -# * IMAGE_NAME specifies a name of the candidate image used for testing. -# * VERSION specifies the major version of the MariaDB in format of X.Y -# * OS specifies RHEL version (e.g. OS=rhel7) -function ct_os_check_compulsory_vars() { - # shellcheck disable=SC2016 - test -n "${IMAGE_NAME-}" || ( echo 'make sure $IMAGE_NAME is defined' >&2 ; exit 1) - # shellcheck disable=SC2016 - test -n "${VERSION-}" || ( echo 'make sure $VERSION is defined' >&2 ; exit 1) - # shellcheck disable=SC2016 - test -n "${OS-}" || ( echo 'make sure $OS is defined' >&2 ; exit 1) -} - -# ct_os_get_status -# -------------------- -# Returns status of all objects to make debugging easier. -function ct_os_get_status() { - oc get all - oc status -} - -# ct_os_print_logs -# -------------------- -# Returns status of all objects and logs from all pods. -function ct_os_print_logs() { - ct_os_get_status - while read -r pod_name; do - echo "INFO: printing logs for pod ${pod_name}" - oc logs "${pod_name}" - done < <(oc get pods --no-headers=true -o custom-columns=NAME:.metadata.name) -} - -# ct_os_enable_print_logs -# -------------------- -# Enables automatic printing of pod logs on ERR. -function ct_os_enable_print_logs() { - set -E - trap ct_os_print_logs ERR -} - -# ct_get_public_ip -# -------------------- -# Returns best guess for the IP that the node is accessible from other computers. -# This is a bit funny heuristic, simply goes through all IPv4 addresses that -# hostname -I returns and de-prioritizes IP addresses commonly used for local -# addressing. The rest of addresses are taken as public with higher probability. -function ct_get_public_ip() { - local hostnames - local public_ip='' - local found_ip - hostnames=$(hostname -I) - for guess_exp in '127\.0\.0\.1' '192\.168\.[0-9\.]*' '172\.[0-9\.]*' \ - '10\.[0-9\.]*' '[0-9\.]*' ; do - found_ip=$(echo "${hostnames}" | grep -oe "${guess_exp}") - if [ -n "${found_ip}" ] ; then - # shellcheck disable=SC2001 - hostnames=$(echo "${hostnames}" | sed -e "s/${found_ip}//") - public_ip="${found_ip}" - fi - done - if [ -z "${public_ip}" ] ; then - echo "ERROR: public IP could not be guessed." >&2 - return 1 - fi - echo "${public_ip}" -} - -# ct_os_run_in_pod POD_NAME CMD -# -------------------- -# Runs [cmd] in the pod specified by prefix [pod_prefix]. -# Arguments: pod_name - full name of the pod -# Arguments: cmd - command to be run in the pod -function ct_os_run_in_pod() { - local pod_name="$1" ; shift - - oc exec "$pod_name" -- "$@" -} - -# ct_os_get_service_ip SERVICE_NAME -# -------------------- -# Returns IP of the service specified by [service_name]. -# Arguments: service_name - name of the service -function ct_os_get_service_ip() { - local service_name="${1}" ; shift - oc get "svc/${service_name}" -o yaml | grep clusterIP | \ - cut -d':' -f2 | grep -oe '172\.30\.[0-9\.]*' -} - - -# ct_os_get_all_pods_status -# -------------------- -# Returns status of all pods. -function ct_os_get_all_pods_status() { - oc get pods -o custom-columns=Ready:status.containerStatuses[0].ready,NAME:.metadata.name -} - -# ct_os_get_all_pods_name -# -------------------- -# Returns the full name of all pods. -function ct_os_get_all_pods_name() { - oc get pods --no-headers -o custom-columns=NAME:.metadata.name -} - -# ct_os_get_pod_status POD_PREFIX -# -------------------- -# Returns status of the pod specified by prefix [pod_prefix]. -# Note: Ignores -build and -deploy pods -# Arguments: pod_prefix - prefix or whole ID of the pod -function ct_os_get_pod_status() { - local pod_prefix="${1}" ; shift - ct_os_get_all_pods_status | grep -e "${pod_prefix}" | grep -Ev "(build|deploy)$" \ - | awk '{print $1}' | head -n 1 -} - -# ct_os_get_build_pod_status POD_PREFIX -# -------------------- -# Returns status of the build pod specified by prefix [pod_prefix]. -# Arguments: pod_prefix - prefix or whole ID of the pod -function ct_os_get_build_pod_status() { - local pod_prefix="${1}" ; shift - local query="custom-columns=NAME:.metadata.name,Ready:status.phase" - oc get pods -o "$query" | grep -e "${pod_prefix}" | grep -E "\-build\s" \ - | sort -u | awk '{print $2}' | tail -n 1 -} - -# ct_os_get_buildconfig_pod_name POD_PREFIX -# ---------------------------- -# Returns status of the buildconfig pod specified by prefix [pod_prefix]. -# Argument: pod_prefix - prefix -function ct_os_get_buildconfig_pod_name() { - local pod_prefix="${1}" ; shift - local query="custom-columns=NAME:.metadata.name" - oc get bc -o "$query" | grep -e "${pod_prefix}" | sort -u | tail -n 1 -} - -# ct_os_get_pod_name POD_PREFIX -# -------------------- -# Returns the full name of pods specified by prefix [pod_prefix]. -# Note: Ignores -build and -deploy pods -# Arguments: pod_prefix - prefix or whole ID of the pod -function ct_os_get_pod_name() { - local pod_prefix="${1}" ; shift - ct_os_get_all_pods_name | grep -e "^${pod_prefix}" | grep -Ev "(build|deploy)$" -} - -# ct_os_get_pod_ip POD_NAME -# -------------------- -# Returns the ip of the pod specified by [pod_name]. -# Arguments: pod_name - full name of the pod -function ct_os_get_pod_ip() { - local pod_name="${1}" - oc get pod "$pod_name" --no-headers -o custom-columns=IP:status.podIP -} - -# ct_os_get_sti_build_logs -# ----------------- -# Return logs from sti_build -# Arguments: pod_name -function ct_os_get_sti_build_logs() { - local pod_prefix="${1}" - pod_name=$(ct_os_get_buildconfig_pod_name "${pod_prefix}") - # Print logs but do not failed. Just for traces - if [ x"${pod_name}" != "x" ]; then - oc logs "bc/$pod_name" || return 0 - else - echo "Build config bc/$pod_name does not exist for some reason." - echo "Import probably failed." - fi -} - -# ct_os_check_pod_readiness POD_PREFIX STATUS -# -------------------- -# Checks whether the pod is ready. -# Arguments: pod_prefix - prefix or whole ID of the pod -# Arguments: status - expected status (true, false) -function ct_os_check_pod_readiness() { - local pod_prefix="${1}" ; shift - local status="${1}" ; shift - test "$(ct_os_get_pod_status "${pod_prefix}")" == "${status}" -} - -# ct_os_wait_pod_ready POD_PREFIX TIMEOUT -# -------------------- -# Wait maximum [timeout] for the pod becomming ready. -# Arguments: pod_prefix - prefix or whole ID of the pod -# Arguments: timeout - how many seconds to wait seconds -function ct_os_wait_pod_ready() { - local pod_prefix="${1}" ; shift - local timeout="${1}" ; shift - # If there is a build pod - wait for it to finish first - sleep 3 - if ct_os_get_all_pods_name | grep -E "${pod_prefix}.*-build"; then - SECONDS=0 - echo -n "Waiting for ${pod_prefix} build pod to finish ..." - while ! [ "$(ct_os_get_build_pod_status "${pod_prefix}")" == "Succeeded" ] ; do - echo -n "." - if [ "${SECONDS}" -gt "${timeout}0" ]; then - echo " FAIL" - ct_os_print_logs || : - ct_os_get_sti_build_logs "${pod_prefix}" || : - return 1 - fi - sleep 3 - done - echo " DONE" - fi - SECONDS=0 - echo -n "Waiting for ${pod_prefix} pod becoming ready ..." - while ! ct_os_check_pod_readiness "${pod_prefix}" "true" ; do - echo -n "." - if [ "${SECONDS}" -gt "${timeout}" ]; then - echo " FAIL"; - ct_os_print_logs || : - ct_os_get_sti_build_logs "${pod_prefix}" || : - return 1 - fi - sleep 3 - done - echo " DONE" -} - -# ct_os_wait_rc_ready POD_PREFIX TIMEOUT -# -------------------- -# Wait maximum [timeout] for the rc having desired number of replicas ready. -# Arguments: pod_prefix - prefix of the replication controller -# Arguments: timeout - how many seconds to wait seconds -function ct_os_wait_rc_ready() { - local pod_prefix="${1}" ; shift - local timeout="${1}" ; shift - SECONDS=0 - echo -n "Waiting for ${pod_prefix} having desired numbers of replicas ..." - while ! test "$( (oc get --no-headers statefulsets; oc get --no-headers rc) 2>/dev/null \ - | grep "^${pod_prefix}" | awk '$2==$3 {print "ready"}')" == "ready" ; do - echo -n "." - if [ "${SECONDS}" -gt "${timeout}" ]; then - echo " FAIL"; - ct_os_print_logs || : - ct_os_get_sti_build_logs "${pod_prefix}" || : - return 1 - fi - sleep 3 - done - echo " DONE" -} - -# ct_os_deploy_pure_image IMAGE [ENV_PARAMS, ...] -# -------------------- -# Runs [image] in the openshift and optionally specifies env_params -# as environment variables to the image. -# Arguments: image - prefix or whole ID of the pod to run the cmd in -# Arguments: env_params - environment variables parameters for the images. -function ct_os_deploy_pure_image() { - local image="${1}" ; shift - # ignore error exit code, because oc new-app returns error when image exists - oc new-app "${image}" "$@" || : - # let openshift cluster to sync to avoid some race condition errors - sleep 3 -} - -# ct_os_deploy_s2i_image IMAGE APP [ENV_PARAMS, ... ] -# -------------------- -# Runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. -# Arguments: image - prefix or whole ID of the pod to run the cmd in -# Arguments: app - url or local path to git repo with the application sources. -# Arguments: env_params - environment variables parameters for the images. -function ct_os_deploy_s2i_image() { - local image="${1}" ; shift - local app="${1}" ; shift - # ignore error exit code, because oc new-app returns error when image exists - oc new-app "${image}~${app}" --strategy=source "$@" || : - - # let openshift cluster to sync to avoid some race condition errors - sleep 3 -} - -# ct_os_deploy_template_image TEMPLATE [ENV_PARAMS, ...] -# -------------------- -# Runs template in the openshift and optionally gives env_params to use -# specific values in the template. -# Arguments: template - prefix or whole ID of the pod to run the cmd in -# Arguments: env_params - environment variables parameters for the template. -# Example usage: ct_os_deploy_template_image mariadb-ephemeral-template.yaml \ -# DATABASE_SERVICE_NAME=mysql-57-centos7 \ -# DATABASE_IMAGE=mysql-57-centos7 \ -# MYSQL_USER=testu \ -# MYSQL_PASSWORD=testp \ -# MYSQL_DATABASE=testdb -function ct_os_deploy_template_image() { - local template="${1}" ; shift - oc process -f "${template}" "$@" | oc create -f - - # let openshift cluster to sync to avoid some race condition errors - sleep 3 -} - -# _ct_os_get_uniq_project_name -# -------------------- -# Returns a uniq name of the OpenShift project. -function _ct_os_get_uniq_project_name() { - local r - while true ; do - r=${RANDOM} - mkdir /var/tmp/sclorg-test-${r} &>/dev/null && echo sclorg-test-${r} && break - done -} - -# ct_os_new_project [PROJECT] -# -------------------- -# Creates a new project in the openshfit using 'os' command. -# Arguments: project - project name, uses a new random name if omitted -# Expects 'os' command that is properly logged in to the OpenShift cluster. -# Not using mktemp, because we cannot use uppercase characters. -# The OPENSHIFT_CLUSTER_PULLSECRET_PATH environment variable can be set -# to contain a path to a k8s secret definition which will be used -# to authenticate to image registries. -# shellcheck disable=SC2120 -function ct_os_new_project() { - if [ "${CVP:-0}" -eq "1" ]; then - echo "Testing in CVP environment. No need to create OpenShift project. This is done by CVP pipeline" - return - fi - if [ "${CT_SKIP_NEW_PROJECT:-false}" == 'true' ] ; then - echo "Creating project skipped." - return - fi - local project_name="${1:-$(_ct_os_get_uniq_project_name)}" ; shift || : - oc new-project "${project_name}" - # let openshift cluster to sync to avoid some race condition errors - sleep 3 - if test -n "${OPENSHIFT_CLUSTER_PULLSECRET_PATH:-}" -a -e "${OPENSHIFT_CLUSTER_PULLSECRET_PATH:-}"; then - oc create -f "$OPENSHIFT_CLUSTER_PULLSECRET_PATH" - # add registry pullsecret to the serviceaccount if provided - secret_name=$(grep '^\s*name:' "$OPENSHIFT_CLUSTER_PULLSECRET_PATH" | awk '{ print $2 }') - oc secrets link --for=pull default "$secret_name" - fi -} - -# ct_os_delete_project [PROJECT] -# -------------------- -# Deletes the specified project in the openshfit -# Arguments: project - project name, uses the current project if omitted -# shellcheck disable=SC2120 -function ct_os_delete_project() { - if [ "${CT_SKIP_NEW_PROJECT:-false}" == 'true' ] || [ "${CVP:-0}" -eq "1" ]; then - echo "Deleting project skipped, cleaning objects only." - # when not having enough privileges (remote cluster), it might fail and - # it is not a big problem, so ignore failure in this case - ct_delete_all_objects || : - return - fi - local project_name="${1:-$(oc project -q)}" ; shift || : - if oc delete project "${project_name}" ; then - echo "Project ${project_name} was deleted properly" - else - echo "Project ${project_name} was not delete properly. But it does not block CI." - fi - -} - -# ct_delete_all_objects -# ----------------- -# Deletes all objects within the project. -# Handy when we have one project and want to run more tests. -function ct_delete_all_objects() { - for x in bc builds dc is isimage istag po pv pvc rc routes secrets svc ; do - oc delete "$x" --all - done - # for some objects it takes longer to be really deleted, so a dummy sleep - # to avoid some races when other test can see not-yet-deleted objects and can fail - sleep 10 -} - -# ct_os_docker_login -# -------------------- -# Logs in into docker daemon -# Uses global REGISRTY_ADDRESS environment variable for arbitrary registry address. -# Does not do anything if REGISTRY_ADDRESS is set. -function ct_os_docker_login() { - [ -n "${REGISTRY_ADDRESS:-}" ] && "REGISTRY_ADDRESS set, not trying to docker login." && return 0 - # docker login fails with "404 page not found" error sometimes, just try it more times - # shellcheck disable=SC2034 - for i in $(seq 12) ; do - # shellcheck disable=SC2015 - docker login -u developer -p "$(oc whoami -t)" "${REGISRTY_ADDRESS:-172.30.1.1:5000}" && return 0 || : - sleep 5 - done - return 1 -} - -# ct_os_upload_image IMAGE [IMAGESTREAM] -# -------------------- -# Uploads image from local registry to the OpenShift internal registry. -# Arguments: image - image name to upload -# Arguments: imagestream - name and tag to use for the internal registry. -# In the format of name:tag ($image_name:latest by default) -# Uses global REGISRTY_ADDRESS environment variable for arbitrary registry address. -function ct_os_upload_image() { - local input_name="${1}" ; shift - local image_name=${input_name##*/} - local imagestream=${1:-$image_name:latest} - local output_name - - output_name="${REGISRTY_ADDRESS:-172.30.1.1:5000}/$(oc project -q)/$imagestream" - - ct_os_docker_login - docker tag "${input_name}" "${output_name}" - docker push "${output_name}" -} - -# ct_os_is_tag_exists IS_NAME TAG -# -------------------- -# Checks whether the specified tag exists for an image stream -# Arguments: is_name - name of the image stream -# Arguments: tag - name of the tag (usually version) -function ct_os_is_tag_exists() { - local is_name=$1 ; shift - local tag=$1 ; shift - oc get is "${is_name}" -n openshift -o=jsonpath='{.spec.tags[*].name}' | grep -qw "${tag}" -} - -# ct_os_template_exists T_NAME -# -------------------- -# Checks whether the specified template exists for an image stream -# Arguments: t_name - template name of the image stream -function ct_os_template_exists() { - local t_name=$1 ; shift - oc get templates -n openshift | grep -q "^${t_name}\s" -} - -# ct_os_install_in_centos -# -------------------- -# Installs os cluster in CentOS -function ct_os_install_in_centos() { - yum install -y centos-release-openshift-origin - yum install -y wget git net-tools bind-utils iptables-services bridge-utils\ - bash-completion origin-clients docker origin-clients -} - - -# ct_os_cluster_up [DIR, IS_PUBLIC, CLUSTER_VERSION] -# -------------------- -# Runs the local OpenShift cluster using 'oc cluster up' and logs in as developer. -# Arguments: dir - directory to keep configuration data in, random if omitted -# Arguments: is_public - sets either private or public hostname for web-UI, -# use "true" for allow remote access to the web-UI, -# "false" is default -# Arguments: cluster_version - version of the OpenShift cluster to use, empty -# means default version of `oc`; example value: 3.7; -# also can be specified outside by OC_CLUSTER_VERSION -function ct_os_cluster_up() { - ct_os_cluster_running && echo "Cluster already running. Nothing is done." && return 0 - ct_os_logged_in && echo "Already logged in to a cluster. Nothing is done." && return 0 - - mkdir -p /var/tmp/openshift - local dir="${1:-$(mktemp -d /var/tmp/openshift/os-data-XXXXXX)}" ; shift || : - local is_public="${1:-'false'}" ; shift || : - local default_cluster_version=${OC_CLUSTER_VERSION:-} - local cluster_version=${1:-${default_cluster_version}} ; shift || : - if ! grep -qe '--insecure-registry.*172\.30\.0\.0' /etc/sysconfig/docker ; then - sed -i "s|OPTIONS='|OPTIONS='--insecure-registry 172.30.0.0/16 |" /etc/sysconfig/docker - fi - - systemctl stop firewalld || : - setenforce 0 - iptables -F - - systemctl restart docker - local cluster_ip="127.0.0.1" - [ "${is_public}" == "true" ] && cluster_ip=$(ct_get_public_ip) - - if [ -n "${cluster_version}" ] ; then - # if $cluster_version is not set, we simply use oc that is available - ct_os_set_path_oc "${cluster_version}" - fi - - mkdir -p "${dir}"/{config,data,pv} - case $(oc version| head -n 1) in - "oc v3.1"?.*) - oc cluster up --base-dir="${dir}/data" --public-hostname="${cluster_ip}" - ;; - "oc v3."*) - oc cluster up --host-data-dir="${dir}/data" --host-config-dir="${dir}/config" \ - --host-pv-dir="${dir}/pv" --use-existing-config --public-hostname="${cluster_ip}" - ;; - *) - echo "ERROR: Unexpected oc version." >&2 - return 1 - ;; - esac - oc version - oc login -u system:admin - oc project default - ct_os_wait_rc_ready docker-registry 180 - ct_os_wait_rc_ready router 30 - oc login -u developer -p developer - OS_CLUSTER_STARTED_BY_TEST=1 - # let openshift cluster to sync to avoid some race condition errors - sleep 3 -} - -# ct_os_cluster_down -# -------------------- -# Shuts down the local OpenShift cluster using 'oc cluster down' -function ct_os_cluster_down() { - if [ ${OS_CLUSTER_STARTED_BY_TEST:-0} -eq 1 ] ; then - echo "Cluster started by the test, shutting down." - oc cluster down - else - echo "Cluster not started by the test, shutting down skipped." - fi -} - -# ct_os_cluster_running -# -------------------- -# Returns 0 if oc cluster is running -function ct_os_cluster_running() { - oc cluster status &>/dev/null -} - -# ct_os_logged_in -# --------------- -# Returns 0 if logged in to a cluster (remote or local) -function ct_os_logged_in() { - oc whoami >/dev/null -} - -# ct_os_set_path_oc OC_VERSION -# -------------------- -# This is a trick that helps using correct version of the `oc`: -# The input is version of the openshift in format v3.6.0 etc. -# If the currently available version of oc is not of this version, -# it first takes a look into /usr/local/oc-/bin directory, -# and if not found there it downloads the community release from github. -# In the end the PATH variable is changed, so the other tests can still use just 'oc'. -# Arguments: oc_version - X.Y part of the version of OSE (e.g. 3.9) -function ct_os_set_path_oc() { - local oc_version - local oc_path - - oc_version=$(ct_os_get_latest_ver "$1") - - if oc version | grep -q "oc ${oc_version%.*}." ; then - echo "Binary oc found already available in version ${oc_version}: $(command -v oc) Doing noting." - return 0 - fi - - # first check whether we already have oc available in /usr/local - local installed_oc_path="/usr/local/oc-${oc_version%.*}/bin" - - if [ -x "${installed_oc_path}/oc" ] ; then - oc_path="${installed_oc_path}" - echo "Binary oc found in ${installed_oc_path}" >&2 - else - # oc not available in /usr/local, try to download it from github (community release) - oc_path="/tmp/oc-${oc_version}-bin" - ct_os_download_upstream_oc "${oc_version}" "${oc_path}" - fi - if [ -z "${oc_path}" ] ; then - echo "ERROR: oc not found installed, nor downloaded" >&1 - return 1 - fi - export PATH="${oc_path}:${PATH}" - if ! oc version | grep -q "oc ${oc_version%.*}." ; then - echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${oc_version} not found in PATH ($PATH)" >&1 - return 1 - else - echo "PATH set correctly, binary oc found in version ${oc_version}: $(command -v oc)" - fi -} - -# ct_os_get_latest_ver VERSION_PART_X -# -------------------- -# Returns full version (vX.Y.Z) from part of the version (X.Y) -# Arguments: vxy - X.Y part of the version -# Returns vX.Y.Z variant of the version -function ct_os_get_latest_ver(){ - local vxy="v$1" - for vz in {3..0} ; do - curl -sif "https://github.com/openshift/origin/releases/tag/${vxy}.${vz}" >/dev/null && echo "${vxy}.${vz}" && return 0 - done - echo "ERROR: version ${vxy} not found in https://github.com/openshift/origin/tags" >&2 - return 1 -} - -# ct_os_download_upstream_oc OC_VERSION OUTPUT_DIR -# -------------------- -# Downloads a particular version of openshift-origin-client-tools from -# github into specified output directory -# Arguments: oc_version - version of OSE (e.g. v3.7.2) -# Arguments: output_dir - output directory -function ct_os_download_upstream_oc() { - local oc_version=$1 - local output_dir=$2 - - # check whether we already have the binary in place - [ -x "${output_dir}/oc" ] && return 0 - - mkdir -p "${output_dir}" - # using html output instead of https://api.github.com/repos/openshift/origin/releases/tags/${oc_version}, - # because API is limited for number of queries if not authenticated - tarball=$(curl -si "https://github.com/openshift/origin/releases/tag/${oc_version}" | grep -o -e "openshift-origin-client-tools-${oc_version}-[a-f0-9]*-linux-64bit.tar.gz" | head -n 1) - - # download, unpack the binaries and then put them into output directory - echo "Downloading https://github.com/openshift/origin/releases/download/${oc_version}/${tarball} into ${output_dir}/" >&2 - curl -sL https://github.com/openshift/origin/releases/download/"${oc_version}"/"${tarball}" | tar -C "${output_dir}" -xz - mv -f "${output_dir}"/"${tarball%.tar.gz}"/* "${output_dir}/" - - rmdir "${output_dir}"/"${tarball%.tar.gz}" -} - - -# ct_os_test_s2i_app_func IMAGE APP CONTEXT_DIR CHECK_CMD [OC_ARGS] -# -------------------- -# Runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. Then check the container by arbitrary -# function given as argument (such an argument may include string, -# that will be replaced with actual IP). -# Arguments: image - prefix or whole ID of the pod to run the cmd in (compulsory) -# Arguments: app - url or local path to git repo with the application sources (compulsory) -# Arguments: context_dir - sub-directory inside the repository with the application sources (compulsory) -# Arguments: check_command - CMD line that checks whether the container works (compulsory; '' will be replaced with actual IP) -# Arguments: oc_args - all other arguments are used as additional parameters for the `oc new-app` -# command, typically environment variables (optional) -function ct_os_test_s2i_app_func() { - local image_name=${1} - local app=${2} - local context_dir=${3} - local check_command=${4} - local oc_args=${5:-} - local image_name_no_namespace=${image_name##*/} - local service_name="${image_name_no_namespace%%:*}-testing" - local namespace - - if [ $# -lt 4 ] || [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ] || [ -z "${4}" ]; then - echo "ERROR: ct_os_test_s2i_app_func() requires at least 4 arguments that cannot be emtpy." >&2 - return 1 - fi - - # shellcheck disable=SC2119 - ct_os_new_project - - namespace=${CT_NAMESPACE:-"$(oc project -q)"} - local image_tagged="${image_name_no_namespace%:*}:${VERSION}" - - if [ "${CVP:-0}" -eq "0" ]; then - if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ] ; then - ct_os_import_image_ocp4 "${image_name}" "${image_tagged}" - else - # Create a specific imagestream tag for the image so that oc cannot use anything else - if [ "${CT_SKIP_UPLOAD_IMAGE:-false}" == 'true' ] ; then - echo "Importing image ${image_name} as ${namespace}/${image_tagged}" - # Use --reference-policy=local to pull remote image content to the cluster - # Works around the issue of builder pods not having access to registry.redhat.io - oc tag --source=docker "${image_name}" "${namespace}/${image_tagged}" --insecure=true --reference-policy=local - ct_os_wait_stream_ready "${image_tagged}" "${namespace}" - else - echo "Uploading image ${image_name} as ${image_tagged}" - ct_os_upload_image "${image_name}" "${image_tagged}" - fi - fi - else - echo "Testing image ${image_name} in CVP pipeline." - fi - - local app_param="${app}" - if [ -d "${app}" ] ; then - # for local directory, we need to copy the content, otherwise too smart os command - # pulls the git remote repository instead - app_param=$(ct_obtain_input "${app}") - fi - - # shellcheck disable=SC2086 - ct_os_deploy_s2i_image "${image_tagged}" "${app_param}" \ - --context-dir="${context_dir}" \ - --name "${service_name}" \ - ${oc_args} - - if [ -d "${app}" ] ; then - # in order to avoid weird race seen sometimes, let's wait shortly - # before starting the build explicitly - sleep 5 - oc start-build "${service_name}" --from-dir="${app_param}" - fi - - ct_os_wait_pod_ready "${service_name}" 300 - - local ip - local check_command_exp - local image_id - - # get image ID from the deployment config - image_id=$(oc get "deploymentconfig.apps.openshift.io/${service_name}" -o custom-columns=IMAGE:.spec.template.spec.containers[*].image | tail -n 1) - - ip=$(ct_os_get_service_ip "${service_name}") - # shellcheck disable=SC2001 - check_command_exp=$(echo "$check_command" | sed -e "s//$ip/g" -e "s||${image_id}|g") - - echo " Checking APP using $check_command_exp ..." - local result=0 - eval "$check_command_exp" || result=1 - - ct_os_service_image_info "${service_name}" - - if [ $result -eq 0 ] ; then - echo " Check passed." - else - echo " Check failed." - fi - - # shellcheck disable=SC2119 - ct_os_delete_project - return $result -} - -# ct_os_test_s2i_app IMAGE APP CONTEXT_DIR EXPECTED_OUTPUT [PORT, PROTOCOL, RESPONSE_CODE, OC_ARGS, ... ] -# -------------------- -# Runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. Then check the http response. -# Arguments: image - prefix or whole ID of the pod to run the cmd in (compulsory) -# Arguments: app - url or local path to git repo with the application sources (compulsory) -# Arguments: context_dir - sub-directory inside the repository with the application sources (compulsory) -# Arguments: expected_output - PCRE regular expression that must match the response body (compulsory) -# Arguments: port - which port to use (optional; default: 8080) -# Arguments: protocol - which protocol to use (optional; default: http) -# Arguments: response_code - what http response code to expect (optional; default: 200) -# Arguments: oc_args - all other arguments are used as additional parameters for the `oc new-app` -# command, typically environment variables (optional) -function ct_os_test_s2i_app() { - local image_name=${1} - local app=${2} - local context_dir=${3} - local expected_output=${4} - local port=${5:-8080} - local protocol=${6:-http} - local response_code=${7:-200} - local oc_args=${8:-} - - if [ $# -lt 4 ] || [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ] || [ -z "${4}" ]; then - echo "ERROR: ct_os_test_s2i_app() requires at least 4 arguments that cannot be emtpy." >&2 - return 1 - fi - - ct_os_test_s2i_app_func "${image_name}" \ - "${app}" \ - "${context_dir}" \ - "ct_os_test_response_internal '${protocol}://:${port}' '${response_code}' '${expected_output}'" \ - "${oc_args}" -} - -# ct_os_test_template_app_func IMAGE APP IMAGE_IN_TEMPLATE CHECK_CMD [OC_ARGS] -# -------------------- -# Runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. Then check the container by arbitrary -# function given as argument (such an argument may include string, -# that will be replaced with actual IP). -# Arguments: image_name - prefix or whole ID of the pod to run the cmd in (compulsory) -# Arguments: template - url or local path to a template to use (compulsory) -# Arguments: name_in_template - image name used in the template -# Arguments: check_command - CMD line that checks whether the container works (compulsory; '' will be replaced with actual IP) -# Arguments: oc_args - all other arguments are used as additional parameters for the `oc new-app` -# command, typically environment variables (optional) -# Arguments: other_images - some templates need other image to be pushed into the OpenShift registry, -# specify them in this parameter as "|", where "" is a full image name -# (including registry if needed) and "" is a tag under which the image should be available -# in the OpenShift registry. -function ct_os_test_template_app_func() { - local image_name=${1} - local template=${2} - local name_in_template=${3} - local check_command=${4} - local oc_args=${5:-} - local other_images=${6:-} - - if [ $# -lt 4 ] || [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ] || [ -z "${4}" ]; then - echo "ERROR: ct_os_test_template_app_func() requires at least 4 arguments that cannot be emtpy." >&2 - return 1 - fi - - local service_name="${name_in_template}-testing" - local image_tagged="${name_in_template}:${VERSION}" - local namespace - - # shellcheck disable=SC2119 - ct_os_new_project - - namespace=${CT_NAMESPACE:-"$(oc project -q)"} - # Upload main image is already done by CVP pipeline. No need to do it twice. - if [ "${CVP:-0}" -eq "0" ]; then - # Create a specific imagestream tag for the image so that oc cannot use anything else - if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ] ; then - ct_os_import_image_ocp4 "${image_name}" "${image_tagged}" - else - if [ "${CT_SKIP_UPLOAD_IMAGE:-false}" == 'true' ] ; then - echo "Importing image ${image_name} as ${image_tagged}" - # Use --reference-policy=local to pull remote image content to the cluster - # Works around the issue of builder pods not having access to registry.redhat.io - oc tag --source=docker "${image_name}" "${namespace}/${image_tagged}" --insecure=true --reference-policy=local - ct_os_wait_stream_ready "${image_tagged}" "${namespace}" - else - echo "Uploading image ${image_name} as ${image_tagged}" - ct_os_upload_image "${image_name}" "${image_tagged}" - fi - fi - else - echo "Import is already done by CVP pipeline." - fi - # Other images are not uploaded by CVP pipeline. We need to do it. - if [ "${CT_SKIP_UPLOAD_IMAGE:-false}" == 'false' ] ; then - # upload also other images, that template might need (list of pairs in the format | - local image_tag_a - local i_t - for i_t in ${other_images} ; do - echo "${i_t}" - IFS='|' read -ra image_tag_a <<< "${i_t}" - if [[ "$(docker images -q "$image_name" 2>/dev/null)" == "" ]]; then - echo "ERROR: Image $image_name is not pulled yet." - docker images - echo "Add to the beginning of scripts run-openshift-remote-cluster and run-openshift row" - echo "'ct_pull_image $image_name true'." - exit 1 - fi - - if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ] ; then - ct_os_import_image_ocp4 "${image_tag_a[0]}" "${image_tag_a[1]}" - else - ct_os_upload_image "${image_tag_a[0]}" "${image_tag_a[1]}" - fi - done - fi - - # get the template file from remote or local location; if not found, it is - # considered an internal template name, like 'mysql', so use the name - # explicitly - local local_template - - local_template=$(ct_obtain_input "${template}" 2>/dev/null || echo "--template=${template}") - - echo "Creating a new-app with name ${name_in_template} in namespace ${namespace} with args ${oc_args}." - # shellcheck disable=SC2086 - oc new-app "${local_template}" \ - --name "${name_in_template}" \ - -p NAMESPACE="${namespace}" \ - ${oc_args} - - ct_os_wait_pod_ready "${service_name}" 300 - - local ip - local check_command_exp - local image_id - - # get image ID from the deployment config - image_id=$(oc get "deploymentconfig.apps.openshift.io/${service_name}" -o custom-columns=IMAGE:.spec.template.spec.containers[*].image | tail -n 1) - - ip=$(ct_os_get_service_ip "${service_name}") - # shellcheck disable=SC2001 - check_command_exp=$(echo "$check_command" | sed -e "s//$ip/g" -e "s||${image_id}|g") - - echo " Checking APP using $check_command_exp ..." - local result=0 - eval "$check_command_exp" || result=1 - - ct_os_service_image_info "${service_name}" - - if [ $result -eq 0 ] ; then - echo " Check passed." - else - echo " Check failed." - fi - - # shellcheck disable=SC2119 - ct_os_delete_project - return $result -} - -# params: -# ct_os_test_template_app IMAGE APP IMAGE_IN_TEMPLATE EXPECTED_OUTPUT [PORT, PROTOCOL, RESPONSE_CODE, OC_ARGS, ... ] -# -------------------- -# Runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. Then check the http response. -# Arguments: image_name - prefix or whole ID of the pod to run the cmd in (compulsory) -# Arguments: template - url or local path to a template to use (compulsory) -# Arguments: name_in_template - image name used in the template -# Arguments: expected_output - PCRE regular expression that must match the response body (compulsory) -# Arguments: port - which port to use (optional; default: 8080) -# Arguments: protocol - which protocol to use (optional; default: http) -# Arguments: response_code - what http response code to expect (optional; default: 200) -# Arguments: oc_args - all other arguments are used as additional parameters for the `oc new-app` -# command, typically environment variables (optional) -# Arguments: other_images - some templates need other image to be pushed into the OpenShift registry, -# specify them in this parameter as "|", where "" is a full image name -# (including registry if needed) and "" is a tag under which the image should be available -# in the OpenShift registry. -function ct_os_test_template_app() { - local image_name=${1} - local template=${2} - local name_in_template=${3} - local expected_output=${4} - local port=${5:-8080} - local protocol=${6:-http} - local response_code=${7:-200} - local oc_args=${8:-} - local other_images=${9:-} - - if [ $# -lt 4 ] || [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ] || [ -z "${4}" ]; then - echo "ERROR: ct_os_test_template_app() requires at least 4 arguments that cannot be emtpy." >&2 - return 1 - fi - - ct_os_test_template_app_func "${image_name}" \ - "${template}" \ - "${name_in_template}" \ - "ct_os_test_response_internal '${protocol}://:${port}' '${response_code}' '${expected_output}'" \ - "${oc_args}" \ - "${other_images}" -} - -# ct_os_test_image_update IMAGE_NAME OLD_IMAGE ISTAG CHECK_FUNCTION OC_ARGS -# -------------------- -# Runs an image update test with [image] uploaded to [is] imagestream -# and checks the services using an arbitrary function provided in [check_function]. -# Arguments: image_name - prefix or whole ID of the pod to run the cmd in (compulsory) -# Arguments: old_image - valid name of the image from the registry -# Arguments: istag - imagestream to upload the images into (compulsory) -# Arguments: check_function - command to be run to check functionality of created services (compulsory) -# Arguments: oc_args - arguments to use during oc new-app (compulsory) -ct_os_test_image_update() { - local image_name=$1; shift - local old_image=$1; shift - local istag=$1; shift - local check_function=$1; shift - local service_name=${image_name##*/} - local ip="" check_command_exp="" - - echo "Running image update test for: $image_name" - # shellcheck disable=SC2119 - ct_os_new_project - - # Get current image from repository and create an imagestream - docker pull "$old_image:latest" 2>/dev/null - ct_os_upload_image "$old_image" "$istag" - - # Setup example application with curent image - oc new-app "$@" --name "$service_name" - ct_os_wait_pod_ready "$service_name" 60 - - # Check application output - ip=$(ct_os_get_service_ip "$service_name") - check_command_exp=${check_function///$ip} - ct_assert_cmd_success "$check_command_exp" - - # Tag built image into the imagestream and wait for rebuild - ct_os_upload_image "$image_name" "$istag" - ct_os_wait_pod_ready "${service_name}-2" 60 - - # Check application output - ip=$(ct_os_get_service_ip "$service_name") - check_command_exp=${check_function///$ip} - ct_assert_cmd_success "$check_command_exp" - - # shellcheck disable=SC2119 - ct_os_delete_project -} - -# ct_os_deploy_cmd_image IMAGE_NAME -# -------------------- -# Runs a special command pod, a pod that does nothing, but includes utilities for testing. -# A typical usage is a mysql pod that includes mysql commandline, that we need for testing. -# Running commands inside this command pod is done via ct_os_cmd_image_run function. -# The pod is not run again if already running. -# Arguments: image_name - image to be used as a command pod -function ct_os_deploy_cmd_image() { - local image_name=${1} - oc get pod command-app &>/dev/null && echo "command POD already running" && return 0 - echo "command POD not running yet, will start one called command-app ${image_name}" - oc create -f - <" - local sleep_time=3 - local attempt=1 - local result=1 - local status - local response_code - local response_file - local util_image_name='registry.access.redhat.com/ubi7/ubi' - - response_file=$(mktemp /tmp/ct_test_response_XXXXXX) - ct_os_deploy_cmd_image "${util_image_name}" - - while [ "${attempt}" -le "${max_attempts}" ]; do - ct_os_cmd_image_run "curl --connect-timeout 10 -s -w '%{http_code}' '${url}'" >"${response_file}" && status=0 || status=1 - if [ "${status}" -eq 0 ]; then - response_code=$(tail -c 3 "${response_file}") - if [ "${response_code}" -eq "${expected_code}" ]; then - result=0 - fi - grep -qP -e "${body_regexp}" "${response_file}" || result=1; - # Some services return 40x code until they are ready, so let's give them - # some chance and not end with failure right away - # Do not wait if we already have expected outcome though - if [ "${result}" -eq 0 ] || [ "${attempt}" -gt "${ignore_error_attempts}" ] || [ "${attempt}" -eq "${max_attempts}" ] ; then - break - fi - fi - attempt=$(( attempt + 1 )) - sleep "${sleep_time}" - done - rm -f "${response_file}" - return "${result}" -} - -# ct_os_get_image_from_pod -# ------------------------ -# Print image identifier from an existing pod to stdout -# Argument: pod_prefix - prefix or full name of the pod to get image from -ct_os_get_image_from_pod() { - local pod_prefix=$1 ; shift - local pod_name - pod_name=$(ct_os_get_pod_name "$pod_prefix") - oc get "po/${pod_name}" -o yaml | sed -ne 's/^\s*image:\s*\(.*\)\s*$/\1/ p' | head -1 -} - -# ct_os_check_cmd_internal -# ---------------- -# Runs a specified command, checks exit code and compares the output with expected regexp. -# That all is done inside an image in the cluster, so the function is used -# typically in clusters that are not accessible outside. -# The check is repeated until timeout. -# Argument: util_image_name - name of the image in the cluster that is used for running the cmd -# Argument: service_name - kubernetes' service name to work with (IP address is taken from this one) -# Argument: check_command - command that is run within the util_image_name container -# Argument: expected_content_match - regexp that must be in the output (use .* to ignore check) -# Argument: timeout - number of seconds to wait till the check succeeds -function ct_os_check_cmd_internal() { - local util_image_name=$1 ; shift - local service_name=$1 ; shift - local check_command=$1 ; shift - local expected_content_match=${1:-.*} ; shift - local timeout=${1:-60} ; shift || : - - : " Service ${service_name} check ..." - - local output - local ret - local ip - local check_command_exp - - ip=$(ct_os_get_service_ip "${service_name}") - # shellcheck disable=SC2001 - check_command_exp=$(echo "$check_command" | sed -e "s//$ip/g") - - ct_os_deploy_cmd_image "${util_image_name}" - SECONDS=0 - - echo -n "Waiting for ${service_name} service becoming ready ..." - while true ; do - output=$(ct_os_cmd_image_run "$check_command_exp") - ret=$? - echo "${output}" | grep -qe "${expected_content_match}" || ret=1 - if [ ${ret} -eq 0 ] ; then - echo " PASS" - return 0 - fi - echo -n "." - [ ${SECONDS} -gt "${timeout}" ] && break - sleep 3 - done - echo " FAIL" - return 1 -} - -# ct_os_test_image_stream_template IMAGE_STREAM_FILE TEMPLATE_FILE SERVICE NAME [TEMPLATE_PARAMS] -# ------------------------ -# Creates an image stream and deploys a specified template. Then checks that a pod runs. -# Argument: image_stream_file - local or remote file with the image stream definition -# Argument: template_file - local file name with a template -# Argument: service_name - how the pod will be named (prefix) -# Argument: template_params (optional) - parameters for the template, like image stream version -function ct_os_test_image_stream_template() { - local image_stream_file=${1} - local template_file=${2} - local service_name=${3} - local template_params=${4:-} - local local_image_stream_file - local local_template_file - - if [ $# -lt 3 ] || [ -z "${1}" ] || [ -z "${2}" ] || [ -z "${3}" ]; then - echo "ERROR: ct_os_test_image_stream() requires at least 3 arguments that cannot be empty." >&2 - return 1 - fi - - echo "Running image stream test for stream ${image_stream_file} and template ${template_file}" - # shellcheck disable=SC2119 - ct_os_new_project - - local_image_stream_file=$(ct_obtain_input "${image_stream_file}") - local_template_file=$(ct_obtain_input "${template_file}") - oc create -f "${local_image_stream_file}" - - # shellcheck disable=SC2086 - if ! ct_os_deploy_template_image "${local_template_file}" -p NAMESPACE="${CT_NAMESPACE:-$(oc project -q)}" ${template_params} ; then - echo "ERROR: ${template_file} could not be loaded" - return 1 - # Deliberately not runnig ct_os_delete_project here because user either - # might want to investigate or the cleanup is done with the cleanup trap. - # Most functions depend on the set -e anyway at this point. - fi - ct_os_wait_pod_ready "${service_name}" 120 - - # shellcheck disable=SC2119 - ct_os_delete_project -} - -# ct_os_wait_stream_ready IMAGE_STREAM_FILE NAMESPACE [ TIMEOUT ] -# ------------------------ -# Waits max timeout seconds till a [stream] is available in the [namespace]. -# Arguments: image_stream - stream name (usuallly :) -# Arguments: namespace - namespace name -# Arguments: timeout - how many seconds to wait -function ct_os_wait_stream_ready() { - local image_stream=${1} - local namespace=${2} - local timeout=${3:-60} - # It takes some time for the first time before the image is pulled in - SECONDS=0 - echo -n "Waiting for ${namespace}/${image_stream} to become available ..." - while ! oc get -n "${namespace}" istag "${image_stream}" &>/dev/null; do - if [ "$SECONDS" -gt "${timeout}" ] ; then - echo "FAIL: ${namespace}/${image_stream} not available after ${timeout}s:" - echo "oc get -n ${namespace} istag ${image_stream}" - oc get -n "${namespace}" istag "${image_stream}" - return 1 - fi - sleep 3 - echo -n . - done - echo " DONE" -} - -# ct_os_test_image_stream_s2i IMAGE_STREAM_FILE IMAGE_NAME APP CONTEXT_DIR EXPECTED_OUTPUT [PORT, PROTOCOL, RESPONSE_CODE, OC_ARGS, ... ] -# -------------------- -# Check the imagestream with an s2i app check. First it imports the given image stream, then -# it runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. Then check the http response. -# Argument: image_stream_file - local or remote file with the image stream definition -# Argument: image_name - container image we test (or name of the existing image stream in : format) -# Argument: app - url or local path to git repo with the application sources (compulsory) -# Argument: context_dir - sub-directory inside the repository with the application sources (compulsory) -# Argument: expected_output - PCRE regular expression that must match the response body (compulsory) -# Argument: port - which port to use (optional; default: 8080) -# Argument: protocol - which protocol to use (optional; default: http) -# Argument: response_code - what http response code to expect (optional; default: 200) -# Argument: oc_args - all other arguments are used as additional parameters for the `oc new-app` -# command, typically environment variables (optional) -function ct_os_test_image_stream_s2i() { - local image_stream_file=${1} - local image_name=${2} - local app=${3} - local context_dir=${4} - local expected_output=${5} - local port=${6:-8080} - local protocol=${7:-http} - local response_code=${8:-200} - local oc_args=${9:-} - local result - local local_image_stream_file - - echo "Running image stream test for stream ${image_stream_file} and application ${app} with context ${context_dir}" - - # shellcheck disable=SC2119 - ct_os_new_project - - local_image_stream_file=$(ct_obtain_input "${image_stream_file}") - oc create -f "${local_image_stream_file}" - - # ct_os_test_s2i_app creates a new project, but we already need - # it before for the image stream import, so tell it to skip this time - CT_SKIP_NEW_PROJECT=true \ - ct_os_test_s2i_app "${IMAGE_NAME}" "${app}" "${context_dir}" "${expected_output}" \ - "${port}" "${protocol}" "${response_code}" "${oc_args}" - result=$? - - # shellcheck disable=SC2119 - ct_os_delete_project - - return $result -} - -# ct_os_test_image_stream_quickstart IMAGE_STREAM_FILE TEMPLATE IMAGE_NAME NAME_IN_TEMPLATE EXPECTED_OUTPUT [PORT, PROTOCOL, RESPONSE_CODE, OC_ARGS, OTHER_IMAGES ] -# -------------------- -# Check the imagestream with an s2i app check. First it imports the given image stream, then -# it runs [image] and [app] in the openshift and optionally specifies env_params -# as environment variables to the image. Then check the http response. -# Argument: image_stream_file - local or remote file with the image stream definition -# Argument: template_file - local file name with a template -# Argument: image_name - container image we test (or name of the existing image stream in : format) -# Argument: name_in_template - image name used in the template -# Argument: expected_output - PCRE regular expression that must match the response body (compulsory) -# Argument: port - which port to use (optional; default: 8080) -# Argument: protocol - which protocol to use (optional; default: http) -# Argument: response_code - what http response code to expect (optional; default: 200) -# Argument: oc_args - all other arguments are used as additional parameters for the `oc new-app` -# command, typically environment variables (optional) -# Argument: other_images - some templates need other image to be pushed into the OpenShift registry, -# specify them in this parameter as "|", where "" is a full image name -# (including registry if needed) and "" is a tag under which the image should be available -# in the OpenShift registry. -function ct_os_test_image_stream_quickstart() { - local image_stream_file=${1} - local template_file=${2} - local image_name=${3} - local name_in_template=${4} - local expected_output=${5} - local port=${6:-8080} - local protocol=${7:-http} - local response_code=${8:-200} - local oc_args=${9:-} - local other_images=${10:-} - local result - local local_image_stream_file - local local_template_file - - echo "Running image stream test for stream ${image_stream_file} and quickstart template ${template_file}" - echo "Image name is ${IMAGE_NAME}" - # shellcheck disable=SC2119 - ct_os_new_project - - local_image_stream_file=$(ct_obtain_input "${image_stream_file}") - local_template_file=$(ct_obtain_input "${template_file}") - # ct_os_test_template_app creates a new project, but we already need - # it before for the image stream import, so tell it to skip this time - namespace=${CT_NAMESPACE:-"$(oc project -q)"} - - # Add namespace into openshift arguments - if [[ $oc_args != *"NAMESPACE"* ]]; then - oc_args="${oc_args} -p NAMESPACE=${namespace}" - fi - oc create -f "${local_image_stream_file}" - - # In case we are testing on OpenShift 4 export variable for mirror image - # which means, that image is going to be mirrored from an internal registry into OpenShift 4 - if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ]; then - export CT_TAG_IMAGE=true - fi - # ct_os_test_template_app creates a new project, but we already need - # it before for the image stream import, so tell it to skip this time - - CT_SKIP_NEW_PROJECT=true \ - ct_os_test_template_app "${image_name}" \ - "${local_template_file}" \ - "${name_in_template}" \ - "${expected_output}" \ - "${port}" "${protocol}" "${response_code}" "${oc_args}" "${other_images}" - - result=$? - - # shellcheck disable=SC2119 - ct_os_delete_project - - return $result -} - -# ct_os_service_image_info SERVICE_NAME -# -------------------- -# Shows information about the image used by a specified service. -# Argument: service_name - Service name (uesd for deployment config) -function ct_os_service_image_info() { - local service_name=$1 - local image_id - local namespace - - # get image ID from the deployment config - image_id=$(oc get "deploymentconfig.apps.openshift.io/${service_name}" -o custom-columns=IMAGE:.spec.template.spec.containers[*].image | tail -n 1) - namespace=${CT_NAMESPACE:-"$(oc project -q)"} - - echo " Information about the image we work with:" - oc get deploymentconfig.apps.openshift.io/"${service_name}" -o yaml | grep lastTriggeredImage - # for s2i builds, the resulting image is actually in the current namespace, - # so if the specified namespace does not succeed, try the current namespace - oc get isimage -n "${namespace}" "${image_id##*/}" -o yaml || oc get isimage "${image_id##*/}" -o yaml -} -# vim: set tabstop=2:shiftwidth=2:expandtab: diff --git a/test/test-lib-redis.sh b/test/test-lib-redis.sh deleted file mode 100644 index 698abe8..0000000 --- a/test/test-lib-redis.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# Functions for tests for the Redis image in OpenShift. -# -# IMAGE_NAME specifies a name of the candidate image used for testing. -# 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-remote-openshift.sh - -function test_redis_integration() { - local image_name=$1 - local service_name=redis - ct_os_test_template_app_func "${image_name}" \ - "https://raw.githubusercontent.com/openshift/origin/master/examples/db-templates/redis-ephemeral-template.json" \ - "${service_name}" \ - "ct_os_check_cmd_internal '' '${service_name}-testing' 'timeout 15 redis-cli -h -a testp ping' 'PONG'" \ - "-p REDIS_VERSION=${VERSION} \ - -p DATABASE_SERVICE_NAME="${service_name}-testing" \ - -p REDIS_PASSWORD=testp" -} - -# Check the imagestream -function test_redis_imagestream() { - case ${OS} in - rhel7|centos7) ;; - *) echo "Imagestream testing not supported for $OS environment." ; return 0 ;; - esac - - ct_os_test_image_stream_template "${THISDIR}/../imagestreams/redis-${OS%[0-9]*}.json" "${THISDIR}/../examples/redis-ephemeral-template.json" redis "-p REDIS_VERSION=${VERSION}" -} - -# vim: set tabstop=2:shiftwidth=2:expandtab: diff --git a/test/test-lib-remote-openshift.sh b/test/test-lib-remote-openshift.sh deleted file mode 100644 index bda03f6..0000000 --- a/test/test-lib-remote-openshift.sh +++ /dev/null @@ -1,116 +0,0 @@ -# shellcheck shell=bash -# some functions are used from test-lib.sh, that is usually in the same dir -# shellcheck source=/dev/null -source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh - -# Set of functions for testing docker images in OpenShift using 'oc' command - -# A variable containing the overall test result; must be changed to 0 in the end -# of the testing script: -# OS_TESTSUITE_RESULT=0 -# And the following trap must be set, in the beginning of the test script: -# trap ct_os_cleanup EXIT SIGINT - -# ct_os_set_path_oc_4 OC_VERSION -# -------------------- -# This is a trick that helps using correct version 4 of the `oc`: -# The input is version of the openshift in format 4.4 etc. -# If the currently available version of oc is not of this version, -# it first takes a look into /usr/local/oc-/bin directory, - -# Arguments: oc_version - X.Y part of the version of OSE (e.g. 3.9) -function ct_os_set_path_oc_4() { - echo "Setting OCP4 client" - local oc_version=$1 - local installed_oc_path="/usr/local/oc-v${oc_version}/bin" - echo "PATH ${installed_oc_path}" - if [ -x "${installed_oc_path}/oc" ] ; then - oc_path="${installed_oc_path}" - echo "Binary oc found in ${installed_oc_path}" >&2 - else - echo "OCP4 not found" - return 1 - fi - export PATH="${oc_path}:${PATH}" - oc version - if ! oc version | grep -q "Client Version: ${oc_version}." ; then - echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${oc_version} not found in PATH ($PATH)" >&1 - return 1 - else - echo "PATH set correctly, binary oc found in version ${oc_version}: $(command -v oc)" - fi -} - -# ct_os_prepare_ocp4 -# ------------------ -# Prepares environment for testing images in OpenShift 4 environment -# -# -function ct_os_set_ocp4() { - if [ "${CVP:-0}" -eq "1" ]; then - echo "Testing in CVP environment. No need to login to OpenShift cluster. This is already done by CVP pipeline." - return - fi - local login - OS_OC_CLIENT_VERSION=${OS_OC_CLIENT_VERSION:-4.4} - ct_os_set_path_oc_4 "${OS_OC_CLIENT_VERSION}" - - oc version - - login=$(cat "$KUBEPASSWORD") - oc login -u kubeadmin -p "$login" - echo "Login to OpenShift ${OS_OC_CLIENT_VERSION} is DONE" - # let openshift cluster to sync to avoid some race condition errors - sleep 3 -} - -function ct_os_upload_image_external_registry() { - local input_name="${1}" ; shift - local image_name=${input_name##*/} - local imagestream=${1:-$image_name:latest} - local output_name - - ct_os_login_external_registry - - output_name="${INTERNAL_DOCKER_REGISTRY}/rhscl-ci-testing/$imagestream" - - docker images - docker tag "${input_name}" "${output_name}" - docker push "${output_name}" -} - - -function ct_os_login_external_registry() { - local docker_token - # docker login fails with "404 page not found" error sometimes, just try it more times - # shellcheck disable=SC2034 - echo "loging" - [ -z "${INTERNAL_DOCKER_REGISTRY:-}" ] && "INTERNAL_DOCKER_REGISTRY has to be set for working with Internal registry" && return 1 - # shellcheck disable=SC2034 - for i in $(seq 12) ; do - # shellcheck disable=SC2015 - docker_token=$(cat "$DOCKER_UPSHIFT_TOKEN") - # shellcheck disable=SC2015 - docker login -u rhscl-ci-testing -p "$docker_token" "${INTERNAL_DOCKER_REGISTRY}" && return 0 || : - sleep 5 - done - return 1 -} - -function ct_os_import_image_ocp4() { - local image_name="${1}"; shift - local imagestream=${1:-$image_name:latest} - local namespace - - namespace=${CT_NAMESPACE:-"$(oc project -q)"} - deploy_image_name="${INTERNAL_DOCKER_REGISTRY}/rhscl-ci-testing/${imagestream}" - echo "Uploading image ${image_name} as ${deploy_image_name} , ${imagestream} into external registry." - ct_os_upload_image_external_registry "${image_name}" "${imagestream}" - if [ "${CT_TAG_IMAGE:-false}" == 'true' ]; then - echo "Tag ${deploy_image_name} to ${namespace}/${imagestream}" - oc tag --source=docker "${deploy_image_name}" "${namespace}/${imagestream}" --insecure=true --reference-policy=local - else - echo "Import image into OpenShift 4 environment ${namespace}/${imagestream} from ${deploy_image_name}" - oc import-image "${namespace}/${imagestream}" --from="${deploy_image_name}" --confirm --reference-policy=local - fi -} diff --git a/test/test-lib.sh b/test/test-lib.sh deleted file mode 100644 index 42f22ba..0000000 --- a/test/test-lib.sh +++ /dev/null @@ -1,1072 +0,0 @@ -# shellcheck shell=bash -# -# Test a container image. -# -# Always use sourced from a specific container testfile -# -# reguires definition of CID_FILE_DIR -# CID_FILE_DIR=$(mktemp --suffix=_test_cidfiles -d) -# reguires definition of TEST_LIST -# TEST_LIST="\ -# ctest_container_creation -# ctest_doc_content" - -# Container CI tests -# abbreviated as "ct" - -# may be redefined in the specific container testfile -EXPECTED_EXIT_CODE=0 - -# ct_cleanup -# -------------------- -# Cleans up containers used during tests. Stops and removes all containers -# referenced by cid_files in CID_FILE_DIR. Dumps logs if a container exited -# unexpectedly. Removes the cid_files and CID_FILE_DIR as well. -# Uses: $CID_FILE_DIR - path to directory containing cid_files -# Uses: $EXPECTED_EXIT_CODE - expected container exit code -function ct_cleanup() { - ct_show_resources - for cid_file in "$CID_FILE_DIR"/* ; do - [ -f "$cid_file" ] || continue - local container - container=$(cat "$cid_file") - - : "Stopping and removing container $container..." - docker stop "$container" - exit_status=$(docker inspect -f '{{.State.ExitCode}}' "$container") - if [ "$exit_status" != "$EXPECTED_EXIT_CODE" ]; then - : "Dumping logs for $container" - docker logs "$container" - fi - docker rm -v "$container" - rm "$cid_file" - done - rmdir "$CID_FILE_DIR" - : "Done." -} - -# ct_enable_cleanup -# -------------------- -# Enables automatic container cleanup after tests. -function ct_enable_cleanup() { - trap ct_cleanup EXIT SIGINT -} - -# ct_pull_image -# ------------- -# Function pull an image before tests execution -# Argument: image_name - string containing the public name of the image to pull -# Argument: exit - in case "true" is defined and pull failed, then script has to exit with 1 and no tests are executed -# Argument: loops - how many times to pull image in case of failure -# Function returns either 0 in case of pull was successful -# Or the test suite exit with 1 in case of pull error -function ct_pull_image() { - local image_name="$1"; shift - local exit=${1:-"false"}; shift - local loops=${1:-10}; shift - local loop=0 - - # Let's try to pull image. - echo "-> Pulling image $image_name ..." - # Sometimes in Fedora case it fails with HTTP 50X - # Check if the image is available locally and try to pull it if it is not - if [[ "$(docker images -q "$image_name" 2>/dev/null)" != "" ]]; then - echo "The image $image_name is already pulled." - return 0 - fi - - # Try pulling the image to see if it is accessible - # WORKAROUND: Since Fedora registry sometimes fails randomly, let's try it more times - while ! docker pull "$image_name"; do - ((loop++)) || : - echo "Pulling image $image_name failed." - if [ "$loop" -gt "$loops" ]; then - echo "Pulling of image $image_name failed $loops times in a row. Giving up." - echo "!!! ERROR with pulling image $image_name !!!!" - # shellcheck disable=SC2268 - if [[ x"$exit" == x"false" ]]; then - return 1 - else - exit 1 - fi - fi - echo "Let's wait $((loop*5)) seconds and try again." - sleep "$((loop*5))" - done -} - - -# ct_check_envs_set env_filter check_envs loop_envs [env_format] -# -------------------- -# Compares values from one list of environment variable definitions against such list, -# checking if the values are present and have a specific format. -# Argument: env_filter - optional string passed to grep used for -# choosing which variables to filter out in env var lists. -# Argument: check_envs - list of env var definitions to check values against -# Argument: loop_envs - list of env var definitions to check values for -# Argument: env_format (optional) - format string for bash substring deletion used -# for checking whether the value is contained in check_envs. -# Defaults to: "*VALUE*", VALUE string gets replaced by actual value from loop_envs -function ct_check_envs_set { - local env_filter check_envs env_format - env_filter=$1; shift - check_envs=$1; shift - loop_envs=$1; shift - env_format=${1:-"*VALUE*"} - while read -r variable; do - [ -z "$variable" ] && continue - var_name=$(echo "$variable" | awk -F= '{ print $1 }') - stripped=$(echo "$variable" | awk -F= '{ print $2 }') - filtered_envs=$(echo "$check_envs" | grep "^$var_name=") - [ -z "$filtered_envs" ] && { echo "$var_name not found during \` docker exec\`"; return 1; } - old_IFS=$IFS - # For each such variable compare its content with the `docker exec` result, use `:` as delimiter - IFS=: - for value in $stripped; do - # If the falue checked does not go through env_filter we do not care about it - echo "$value" | grep -q "$env_filter" || continue - if [ -n "${filtered_envs##${env_format//VALUE/$value}}" ]; then - echo " Value $value is missing from variable $var_name" - echo "$filtered_envs" - IFS=$old_IFS - return 1 - fi - done - IFS=$old_IFS - done <<< "$(echo "$loop_envs" | grep "$env_filter" | grep -v "^PWD=")" -} - -# ct_get_cid [name] -# -------------------- -# Prints container id from cid_file based on the name of the file. -# Argument: name - name of cid_file where the container id will be stored -# Uses: $CID_FILE_DIR - path to directory containing cid_files -function ct_get_cid() { - local name="$1" ; shift || return 1 - cat "$CID_FILE_DIR/$name" -} - -# ct_get_cip [id] -# -------------------- -# Prints container ip address based on the container id. -# Argument: id - container id -function ct_get_cip() { - local id="$1" ; shift - docker inspect --format='{{.NetworkSettings.IPAddress}}' "$(ct_get_cid "$id")" -} - -# ct_wait_for_cid [cid_file] -# -------------------- -# Holds the execution until the cid_file is created. Usually run after container -# creation. -# Argument: cid_file - name of the cid_file that should be created -function ct_wait_for_cid() { - local cid_file=$1 - local max_attempts=10 - local sleep_time=1 - local attempt=1 - local result=1 - while [ $attempt -le $max_attempts ]; do - [ -f "$cid_file" ] && [ -s "$cid_file" ] && return 0 - : "Waiting for container start..." - attempt=$(( attempt + 1 )) - sleep $sleep_time - done - return 1 -} - -# ct_assert_container_creation_fails [container_args] -# -------------------- -# The invocation of docker run should fail based on invalid container_args -# passed to the function. Returns 0 when container fails to start properly. -# Argument: container_args - all arguments are passed directly to dokcer run -# Uses: $CID_FILE_DIR - path to directory containing cid_files -function ct_assert_container_creation_fails() { - local ret=0 - local max_attempts=10 - local attempt=1 - local cid_file=assert - set +e - local old_container_args="${CONTAINER_ARGS-}" - # we really work with CONTAINER_ARGS as with a string - # shellcheck disable=SC2124 - CONTAINER_ARGS="$@" - if ct_create_container "$cid_file" ; then - local cid - cid=$(ct_get_cid "$cid_file") - - while [ "$(docker inspect -f '{{.State.Running}}' "$cid")" == "true" ] ; do - sleep 2 - attempt=$(( attempt + 1 )) - if [ "$attempt" -gt "$max_attempts" ]; then - docker stop "$cid" - ret=1 - break - fi - done - exit_status=$(docker inspect -f '{{.State.ExitCode}}' "$cid") - if [ "$exit_status" == "0" ]; then - ret=1 - fi - docker rm -v "$cid" - rm "$CID_FILE_DIR/$cid_file" - fi - [ -n "$old_container_args" ] && CONTAINER_ARGS="$old_container_args" - set -e - return "$ret" -} - -# ct_create_container [name, command] -# -------------------- -# Creates a container using the IMAGE_NAME and CONTAINER_ARGS variables. Also -# stores the container id to a cid_file located in the CID_FILE_DIR, and waits -# for the creation of the file. -# Argument: name - name of cid_file where the container id will be stored -# Argument: command - optional command to be executed in the container -# Uses: $CID_FILE_DIR - path to directory containing cid_files -# Uses: $CONTAINER_ARGS - optional arguments passed directly to docker run -# Uses: $IMAGE_NAME - name of the image being tested -function ct_create_container() { - local cid_file="$CID_FILE_DIR/$1" ; shift - # create container with a cidfile in a directory for cleanup - # shellcheck disable=SC2086,SC2153 - docker run --cidfile="$cid_file" -d ${CONTAINER_ARGS:-} "$IMAGE_NAME" "$@" - ct_wait_for_cid "$cid_file" || return 1 - : "Created container $(cat "$cid_file")" -} - -# ct_scl_usage_old [name, command, expected] -# -------------------- -# Tests three ways of running the SCL, by looking for an expected string -# in the output of the command -# Argument: name - name of cid_file where the container id will be stored -# Argument: command - executed inside the container -# Argument: expected - string that is expected to be in the command output -# Uses: $CID_FILE_DIR - path to directory containing cid_files -# Uses: $IMAGE_NAME - name of the image being tested -function ct_scl_usage_old() { - local name="$1" - local command="$2" - local expected="$3" - local out="" - : " Testing the image SCL enable" - out=$(docker run --rm "${IMAGE_NAME}" /bin/bash -c "${command}") - if ! echo "${out}" | grep -q "${expected}"; then - echo "ERROR[/bin/bash -c \"${command}\"] Expected '${expected}', got '${out}'" >&2 - return 1 - fi - out=$(docker exec "$(ct_get_cid "$name")" /bin/bash -c "${command}" 2>&1) - if ! echo "${out}" | grep -q "${expected}"; then - echo "ERROR[exec /bin/bash -c \"${command}\"] Expected '${expected}', got '${out}'" >&2 - return 1 - fi - out=$(docker exec "$(ct_get_cid "$name")" /bin/sh -ic "${command}" 2>&1) - if ! echo "${out}" | grep -q "${expected}"; then - echo "ERROR[exec /bin/sh -ic \"${command}\"] Expected '${expected}', got '${out}'" >&2 - return 1 - fi -} - -# ct_doc_content_old [strings] -# -------------------- -# Looks for occurence of stirngs in the documentation files and checks -# the format of the files. Files examined: help.1 -# Argument: strings - strings expected to appear in the documentation -# Uses: $IMAGE_NAME - name of the image being tested -function ct_doc_content_old() { - local tmpdir - tmpdir=$(mktemp -d) - local f - : " Testing documentation in the container image" - # Extract the help files from the container - # shellcheck disable=SC2043 - for f in help.1 ; do - docker run --rm "${IMAGE_NAME}" /bin/bash -c "cat /${f}" >"${tmpdir}/$(basename "${f}")" - # Check whether the files contain some important information - for term in "$@" ; do - if ! grep -F -q -e "${term}" "${tmpdir}/$(basename "${f}")" ; then - echo "ERROR: File /${f} does not include '${term}'." >&2 - return 1 - fi - done - # Check whether the files use the correct format - for term in TH PP SH ; do - if ! grep -q "^\.${term}" "${tmpdir}/help.1" ; then - echo "ERROR: /help.1 is probably not in troff or groff format, since '${term}' is missing." >&2 - return 1 - fi - done - done - : " Success!" -} - -# full_ca_file_path -# Return string for full path to CA file -function full_ca_file_path() -{ - echo "/etc/pki/ca-trust/source/anchors/RH-IT-Root-CA.crt" -} -# ct_mount_ca_file -# ------------------ -# Check if /etc/pki/certs/RH-IT-Root-CA.crt file exists -# return mount string for containers or empty string -function ct_mount_ca_file() -{ - # mount CA file only if NPM_REGISTRY variable is present. - local mount_parameter="" - if [ -n "$NPM_REGISTRY" ] && [ -f "$(full_ca_file_path)" ]; then - mount_parameter="-v $(full_ca_file_path):$(full_ca_file_path):Z" - fi - echo "$mount_parameter" -} - -# ct_build_s2i_npm_variables URL_TO_NPM_JS_SERVER -# ------------------------------------------ -# Function returns -e NPM_MIRROR and -v MOUNT_POINT_FOR_CAFILE -# or empty string -function ct_build_s2i_npm_variables() -{ - npm_variables="" - if [ -n "$NPM_REGISTRY" ] && [ -f "$(full_ca_file_path)" ]; then - npm_variables="-e NPM_MIRROR=$NPM_REGISTRY $(ct_mount_ca_file)" - fi - echo "$npm_variables" -} - -# ct_npm_works -# -------------------- -# Checks existance of the npm tool and runs it. -function ct_npm_works() { - local tmpdir - tmpdir=$(mktemp -d) - : " Testing npm in the container image" - local cid_file="${tmpdir}/cid" - if ! docker run --rm "${IMAGE_NAME}" /bin/bash -c "npm --version" >"${tmpdir}/version" ; then - echo "ERROR: 'npm --version' does not work inside the image ${IMAGE_NAME}." >&2 - return 1 - fi - - # shellcheck disable=SC2046 - docker run -d $(ct_mount_ca_file) --rm --cidfile="$cid_file" "${IMAGE_NAME}-testapp" - - # Wait for the container to write it's CID file - ct_wait_for_cid "$cid_file" || return 1 - - if ! docker exec "$(cat "$cid_file")" /bin/bash -c "npm --verbose install jquery && test -f node_modules/jquery/src/jquery.js" >"${tmpdir}/jquery" 2>&1 ; then - echo "ERROR: npm could not install jquery inside the image ${IMAGE_NAME}." >&2 - cat "${tmpdir}/jquery" - return 1 - fi - - if [ -n "$NPM_REGISTRY" ] && [ -f "$(full_ca_file_path)" ]; then - if ! grep -qo "$NPM_REGISTRY" "${tmpdir}/jquery"; then - echo "ERROR: Internal repository is NOT set. Even it is requested." - return 1 - fi - fi - - if [ -f "$cid_file" ]; then - docker stop "$(cat "$cid_file")" - rm "$cid_file" - fi - : " Success!" -} - -# ct_binary_found_from_df binary [path] -# -------------------- -# Checks if a binary can be found in PATH during Dockerfile build -# Argument: binary - name of the binary to test accessibility for -# Argument: path - optional path in which the binary should reside in -# /opt/rh by default -function ct_binary_found_from_df() { - local tmpdir - local binary=$1; shift - local binary_path=${1:-"^/opt/rh"} - tmpdir=$(mktemp -d) - : " Testing $binary in build from Dockerfile" - - # Create Dockerfile that looks for the binary - cat <"$tmpdir/Dockerfile" -FROM $IMAGE_NAME -RUN command -v $binary | grep "$binary_path" -EOF - # Build an image, looking for expected path in the output - if ! docker build -f "$tmpdir/Dockerfile" --no-cache "$tmpdir"; then - echo " ERROR: Failed to find $binary in Dockerfile!" >&2 - return 1 - fi - : " Success!" -} - -# ct_check_exec_env_vars [env_filter] -# -------------------- -# Checks if all relevant environment variables from `docker run` -# can be found in `docker exec` as well. -# Argument: env_filter - optional string passed to grep used for -# choosing which variables to check in the test case. -# Defaults to X_SCLS and variables containing /opt/app-root, /opt/rh -# Uses: $CID_FILE_DIR - path to directory containing cid_files -# Uses: $IMAGE_NAME - name of the image being tested -function ct_check_exec_env_vars() { - local tmpdir exec_envs cid old_IFS env_filter - local var_name stripped filtered_envs run_envs - env_filter=${1:-"^X_SCLS=\|/opt/rh\|/opt/app-root"} - tmpdir=$(mktemp -d) - CID_FILE_DIR=${CID_FILE_DIR:-$(mktemp -d)} - # Get environment variables from `docker run` - run_envs=$(docker run --rm "$IMAGE_NAME" /bin/bash -c "env") - # Get environment variables from `docker exec` - ct_create_container "test_exec_envs" bash -c "sleep 1000" >/dev/null - cid=$(ct_get_cid "test_exec_envs") - exec_envs=$(docker exec "$cid" env) - # Filter out variables we are not interested in - # Always check X_SCLS, ignore PWD - # Check variables from `docker run` that have alternative paths inside (/opt/rh, /opt/app-root) - ct_check_envs_set "$env_filter" "$exec_envs" "$run_envs" "*VALUE*" || return 1 - echo " All values present in \`docker exec\`" - return 0 -} - -# ct_check_scl_enable_vars [env_filter] -# -------------------- -# Checks if all relevant environment variables from `docker run` -# are set twice after a second call of `scl enable $SCLS`. -# Argument: env_filter - optional string passed to grep used for -# choosing which variables to check in the test case. -# Defaults to paths containing enabled SCLS in the image -# Uses: $IMAGE_NAME - name of the image being tested -function ct_check_scl_enable_vars() { - local tmpdir exec_envs cid old_IFS env_filter enabled_scls - local var_name stripped filtered_envs loop_envs - env_filter=$1 - tmpdir=$(mktemp -d) - enabled_scls=$(docker run --rm "$IMAGE_NAME" /bin/bash -c "echo \$X_SCLS") - if [ -z "$env_filter" ]; then - for scl in $enabled_scls; do - [ -z "$env_filter" ] && env_filter="/$scl" && continue - # env_filter not empty, append to the existing list - env_filter="$env_filter|/$scl" - done - fi - # Get environment variables from `docker run` - loop_envs=$(docker run --rm "$IMAGE_NAME" /bin/bash -c "env") - run_envs=$(docker run --rm "$IMAGE_NAME" /bin/bash -c "X_SCLS= scl enable $enabled_scls env") - # Check if the values are set twice in the second set of envs - ct_check_envs_set "$env_filter" "$run_envs" "$loop_envs" "*VALUE*VALUE*" || return 1 - echo " All scl_enable values present" - return 0 -} - -# ct_path_append PATH_VARNAME DIRECTORY -# ------------------------------------- -# Append DIRECTORY to VARIABLE of name PATH_VARNAME, the VARIABLE must consist -# of colon-separated list of directories. -ct_path_append () -{ - if eval "test -n \"\${$1-}\""; then - eval "$1=\$2:\$$1" - else - eval "$1=\$2" - fi -} - - -# ct_path_foreach PATH ACTION [ARGS ...] -# -------------------------------------- -# For each DIR in PATH execute ACTION (path is colon separated list of -# directories). The particular calls to ACTION will look like -# '$ ACTION directory [ARGS ...]' -ct_path_foreach () -{ - local dir dirlist action save_IFS - save_IFS=$IFS - IFS=: - dirlist=$1 - action=$2 - shift 2 - for dir in $dirlist; do "$action" "$dir" "$@" ; done - IFS=$save_IFS -} - - -# ct_run_test_list -# -------------------- -# Execute the tests specified by TEST_LIST -# Uses: $TEST_LIST - list of test names -function ct_run_test_list() { - for test_case in $TEST_LIST; do - : "Running test $test_case" - # shellcheck source=/dev/null - [ -f "test/$test_case" ] && source "test/$test_case" - # shellcheck source=/dev/null - [ -f "../test/$test_case" ] && source "../test/$test_case" - $test_case - done; -} - -# ct_gen_self_signed_cert_pem -# --------------------------- -# Generates a self-signed PEM certificate pair into specified directory. -# Argument: output_dir - output directory path -# Argument: base_name - base name of the certificate files -# Resulted files will be those: -# /-cert-selfsigned.pem -- public PEM cert -# /-key.pem -- PEM private key -ct_gen_self_signed_cert_pem() { - local output_dir=$1 ; shift - local base_name=$1 ; shift - mkdir -p "${output_dir}" - openssl req -newkey rsa:2048 -nodes -keyout "${output_dir}"/"${base_name}"-key.pem -subj '/C=GB/ST=Berkshire/L=Newbury/O=My Server Company' > "${base_name}"-req.pem - openssl req -new -x509 -nodes -key "${output_dir}"/"${base_name}"-key.pem -batch > "${output_dir}"/"${base_name}"-cert-selfsigned.pem -} - -# ct_obtain_input FILE|DIR|URL -# -------------------- -# Either copies a file or a directory to a tmp location for local copies, or -# downloads the file from remote location. -# Resulted file path is printed, so it can be later used by calling function. -# Arguments: input - local file, directory or remote URL -function ct_obtain_input() { - local input=$1 - local extension="${input##*.}" - - # Try to use same extension for the temporary file if possible - [[ "${extension}" =~ ^[a-z0-9]*$ ]] && extension=".${extension}" || extension="" - - local output - output=$(mktemp "/var/tmp/test-input-XXXXXX$extension") - if [ -f "${input}" ] ; then - cp -f "${input}" "${output}" - elif [ -d "${input}" ] ; then - rm -f "${output}" - cp -r -LH "${input}" "${output}" - elif echo "${input}" | grep -qe '^http\(s\)\?://' ; then - curl "${input}" > "${output}" - else - echo "ERROR: file type not known: ${input}" >&2 - return 1 - fi - echo "${output}" -} - -# ct_test_response -# ---------------- -# Perform GET request to the application container, checks output with -# a reg-exp and HTTP response code. -# Argument: url - request URL path -# Argument: expected_code - expected HTTP response code -# Argument: body_regexp - PCRE regular expression that must match the response body -# Argument: max_attempts - Optional number of attempts (default: 20), three seconds sleep between -# Argument: ignore_error_attempts - Optional number of attempts when we ignore error output (default: 10) -ct_test_response() { - local url="$1" - local expected_code="$2" - local body_regexp="$3" - local max_attempts=${4:-20} - local ignore_error_attempts=${5:-10} - - : " Testing the HTTP(S) response for <${url}>" - local sleep_time=3 - local attempt=1 - local result=1 - local status - local response_code - local response_file - response_file=$(mktemp /tmp/ct_test_response_XXXXXX) - while [ "${attempt}" -le "${max_attempts}" ]; do - curl --connect-timeout 10 -s -w '%{http_code}' "${url}" >"${response_file}" && status=0 || status=1 - if [ "${status}" -eq 0 ]; then - response_code=$(tail -c 3 "${response_file}") - if [ "${response_code}" -eq "${expected_code}" ]; then - result=0 - fi - grep -qP -e "${body_regexp}" "${response_file}" || result=1; - # Some services return 40x code until they are ready, so let's give them - # some chance and not end with failure right away - # Do not wait if we already have expected outcome though - if [ "${result}" -eq 0 ] || [ "${attempt}" -gt "${ignore_error_attempts}" ] || [ "${attempt}" -eq "${max_attempts}" ] ; then - break - fi - fi - attempt=$(( attempt + 1 )) - sleep "${sleep_time}" - done - rm -f "${response_file}" - return "${result}" -} - -# ct_registry_from_os OS -# ---------------- -# Transform operating system string [os] into registry url -# Argument: OS - string containing the os version -ct_registry_from_os() { - local registry="" - case $1 in - rhel*) - registry=registry.redhat.io - ;; - *) - registry=quay.io - ;; - esac - echo "$registry" -} - - # ct_get_public_image_name OS BASE_IMAGE_NAME VERSION -# ---------------- -# Transform the arguments into public image name -# Argument: OS - string containing the os version -# Argument: BASE_IMAGE_NAME - string containing the base name of the image as defined in the Makefile -# Argument: VERSION - string containing the version of the image as defined in the Makefile -ct_get_public_image_name() { - local os=$1; shift - local base_image_name=$1; shift - local version=$1; shift - - local public_image_name - local registry - - registry=$(ct_registry_from_os "$os") - if [ "$os" == "rhel7" ]; then - public_image_name=$registry/rhscl/$base_image_name-${version//./}-rhel7 - elif [ "$os" == "rhel8" ]; then - public_image_name=$registry/rhel8/$base_image_name-${version//./} - elif [ "$os" == "centos7" ]; then - public_image_name=$registry/centos7/$base_image_name-${version//./}-centos7 - elif [ "$os" == "centos8" ]; then - public_image_name=$registry/centos8/$base_image_name-${version//./}-centos8 - fi - - echo "$public_image_name" -} - -# ct_assert_cmd_success CMD -# ---------------- -# Evaluates [cmd] and fails if it does not succeed. -# Argument: CMD - Command to be run -function ct_assert_cmd_success() { - echo "Checking '$*' for success ..." - if ! eval "$@" &>/dev/null; then - echo " FAIL" - return 1 - fi - echo " PASS" - return 0 -} - -# ct_assert_cmd_failure CMD -# ---------------- -# Evaluates [cmd] and fails if it succeeds. -# Argument: CMD - Command to be run -function ct_assert_cmd_failure() { - echo "Checking '$*' for failure ..." - if eval "$@" &>/dev/null; then - echo " FAIL" - return 1 - fi - echo " PASS" - return 0 -} - - -# ct_random_string [LENGTH=10] -# ---------------------------- -# Generate pseudorandom alphanumeric string of LENGTH bytes, the -# default length is 10. The string is printed on stdout. -ct_random_string() -( - export LC_ALL=C - dd if=/dev/urandom count=1 bs=10k 2>/dev/null \ - | tr -dc 'a-z0-9' \ - | fold -w "${1-10}" \ - | head -n 1 -) - -# ct_s2i_usage IMG_NAME [S2I_ARGS] -# ---------------------------- -# Create a container and run the usage script inside -# Argument: IMG_NAME - name of the image to be used for the container run -# Argument: S2I_ARGS - Additional list of source-to-image arguments, currently unused. -ct_s2i_usage() -{ - local img_name=$1; shift - local s2i_args="$*"; - local usage_command="/usr/libexec/s2i/usage" - docker run --rm "$img_name" bash -c "$usage_command" -} - -# ct_s2i_build_as_df APP_PATH SRC_IMAGE DST_IMAGE [S2I_ARGS] -# ---------------------------- -# Create a new s2i app image from local sources in a similar way as source-to-image would have used. -# Argument: APP_PATH - local path to the app sources to be used in the test -# Argument: SRC_IMAGE - image to be used as a base for the s2i build -# Argument: DST_IMAGE - image name to be used during the tagging of the s2i build result -# Argument: S2I_ARGS - Additional list of source-to-image arguments. -# Only used to check for pull-policy=never and environment variable definitions. -ct_s2i_build_as_df() -{ - local app_path=$1; shift - local src_image=$1; shift - local dst_image=$1; shift - local s2i_args="$*"; - local local_app=upload/src/ - local local_scripts=upload/scripts/ - local user_id= - local df_name= - local tmpdir= - local incremental=false - local mount_options=() - - # Run the entire thing inside a subshell so that we do not leak shell options outside of the function - ( - # Error out if any part of the build fails - set -e - - # Use /tmp to not pollute cwd - tmpdir=$(mktemp -d) - df_name=$(mktemp -p "$tmpdir" Dockerfile.XXXX) - cd "$tmpdir" - # Check if the image is available locally and try to pull it if it is not - docker images "$src_image" &>/dev/null || echo "$s2i_args" | grep -q "pull-policy=never" || docker pull "$src_image" - user=$(docker inspect -f "{{.Config.User}}" "$src_image") - # Default to root if no user is set by the image - user=${user:-0} - # run the user through the image in case it is non-numeric or does not exist - if ! user_id=$(ct_get_uid_from_image "$user" "$src_image"); then - echo "Terminating s2i build." - return 1 - fi - - echo "$s2i_args" | grep -q "\-\-incremental" && incremental=true - if $incremental; then - inc_tmp=$(mktemp -d --tmpdir incremental.XXXX) - setfacl -m "u:$user_id:rwx" "$inc_tmp" - # Check if the image exists, build should fail (for testing use case) if it does not - docker images "$dst_image" &>/dev/null || (echo "Image $dst_image not found."; false) - # Run the original image with a mounted in volume and get the artifacts out of it - cmd="if [ -s /usr/libexec/s2i/save-artifacts ]; then /usr/libexec/s2i/save-artifacts > \"$inc_tmp/artifacts.tar\"; else touch \"$inc_tmp/artifacts.tar\"; fi" - docker run --rm -v "$inc_tmp:$inc_tmp:Z" "$dst_image" bash -c "$cmd" - # Move the created content into the $tmpdir for the build to pick it up - mv "$inc_tmp/artifacts.tar" "$tmpdir/" - fi - # Strip file:// from APP_PATH and copy its contents into current context - mkdir -p "$local_app" - cp -r "${app_path/file:\/\//}/." "$local_app" - [ -d "$local_app/.s2i/bin/" ] && mv "$local_app/.s2i/bin" "$local_scripts" - # Create a Dockerfile named df_name and fill it with proper content - #FIXME: Some commands could be combined into a single layer but not sure if worth the trouble for testing purposes - cat <"$df_name" -FROM $src_image -LABEL "io.openshift.s2i.build.image"="$src_image" \\ - "io.openshift.s2i.build.source-location"="$app_path" -USER root -COPY $local_app /tmp/src -EOF - [ -d "$local_scripts" ] && echo "COPY $local_scripts /tmp/scripts" >> "$df_name" && - echo "RUN chown -R $user_id:0 /tmp/scripts" >>"$df_name" - echo "RUN chown -R $user_id:0 /tmp/src" >>"$df_name" - # Check for custom environment variables inside .s2i/ folder - if [ -e "$local_app/.s2i/environment" ]; then - # Remove any comments and add the contents as ENV commands to the Dockerfile - sed '/^\s*#.*$/d' "$local_app/.s2i/environment" | while read -r line; do - echo "ENV $line" >>"$df_name" - done - fi - # Filter out env var definitions from $s2i_args and create Dockerfile ENV commands out of them - echo "$s2i_args" | grep -o -e '\(-e\|--env\)[[:space:]=]\S*=\S*' | sed -e 's/-e /ENV /' -e 's/--env[ =]/ENV /' >>"$df_name" - # Check if CA autority is present on host and add it into Dockerfile - [ -f "$(full_ca_file_path)" ] && echo "RUN cd /etc/pki/ca-trust/source/anchors && update-ca-trust extract" >>"$df_name" - - # Add in artifacts if doing an incremental build - if $incremental; then - { echo "RUN mkdir /tmp/artifacts" - echo "ADD artifacts.tar /tmp/artifacts" - echo "RUN chown -R $user_id:0 /tmp/artifacts" ; } >>"$df_name" - fi - - echo "USER $user_id" >>"$df_name" - # If exists, run the custom assemble script, else default to /usr/libexec/s2i/assemble - if [ -x "$local_scripts/assemble" ]; then - echo "RUN /tmp/scripts/assemble" >>"$df_name" - else - echo "RUN /usr/libexec/s2i/assemble" >>"$df_name" - fi - # If exists, set the custom run script as CMD, else default to /usr/libexec/s2i/run - if [ -x "$local_scripts/run" ]; then - echo "CMD /tmp/scripts/run" >>"$df_name" - else - echo "CMD /usr/libexec/s2i/run" >>"$df_name" - fi - - # Check if -v parameter is present in s2i_args and add it into docker build command - read -ra mount_options <<< "$(echo "$s2i_args" | grep -o -e '\(-v\)[[:space:]]\.*\S*' || true)" - - # Run the build and tag the result - docker build ${mount_options[@]+"${mount_options[@]}"} -f "$df_name" --no-cache=true -t "$dst_image" . - ) -} - -# ct_s2i_multistage_build APP_PATH SRC_IMAGE DST_IMAGE SEC_IMAGE [S2I_ARGS] -# ---------------------------- -# Create a new s2i app image from local sources in a similar way as source-to-image would have used. -# Argument: APP_PATH - local path to the app sources to be used in the test -# Argument: SRC_IMAGE - image to be used as a base for the s2i build process -# Argument: SEC_IMAGE - image to be used as the base for the result of the build process -# Argument: DST_IMAGE - image name to be used during the tagging of the s2i build result -# Argument: S2I_ARGS - Additional list of source-to-image arguments. -# Only used to check for environment variable definitions. -ct_s2i_multistage_build() { - - local app_path=$1; shift - local src_image=$1; shift - local sec_image=$1; shift - local dst_image=$1; shift - local s2i_args=$*; - local local_app="app-src" - local user_id= - local mount_options=() - - - # Run the entire thing inside a subshell so that we do not leak shell options outside of the function - ( - # Error out if any part of the build fails - set -e - - user=$(docker inspect -f "{{.Config.User}}" "$src_image") - # Default to root if no user is set by the image - user=${user:-0} - # run the user through the image in case it is non-numeric or does not exist - if ! user_id=$(ct_get_uid_from_image "$user" "$src_image"); then - echo "Terminating s2i build." - return 1 - fi - - # Use /tmp to not pollute cwd - tmpdir=$(mktemp -d) - df_name=$(mktemp -p "$tmpdir" Dockerfile.XXXX) - cd "$tmpdir" - - # If the path exists on the local host, copy it into the directory for the build - # Otherwise handle it as a link to a git repository - if [ -e "${app_path/file:\/\//}/." ] ; then - mkdir -p "$local_app" - # Strip file:// from APP_PATH and copy its contents into current context - cp -r "${app_path/file:\/\//}/." "$local_app" - - else - ct_clone_git_repository "$app_path" "$local_app" - fi - - cat <"$df_name" -# First stage builds the application -FROM $src_image as builder -# Add application sources to a directory that the assemble script expects them -# and set permissions so that the container runs without root access -USER 0 -ADD app-src /tmp/src -RUN chown -R 1001:0 /tmp/src -$(echo "$s2i_args" | grep -o -e '\(-e\|--env\)[[:space:]=]\S*=\S*' | sed -e 's/-e /ENV /' -e 's/--env[ =]/ENV /') -# Check if CA autority is present on host and add it into Dockerfile -$([ -f "$(full_ca_file_path)" ] && echo "RUN cd /etc/pki/ca-trust/source/anchors && update-ca-trust extract") -USER $user_id -# Install the dependencies -RUN /usr/libexec/s2i/assemble -# Second stage copies the application to the minimal image -FROM $sec_image -# Copy the application source and build artifacts from the builder image to this one -COPY --from=builder \$HOME \$HOME -# Set the default command for the resulting image -CMD /usr/libexec/s2i/run -EOF - - # Check if -v parameter is present in s2i_args and add it into docker build command - read -ra mount_options <<< "$(echo "$s2i_args" | grep -o -e '\(-v\)[[:space:]]\.*\S*' || true)" - - docker build ${mount_options[@]+"${mount_options[@]}"} -f "$df_name" --no-cache=true -t "$dst_image" . - ) -} - -# ct_check_image_availability PUBLIC_IMAGE_NAME -# ---------------------------- -# Pull an image from the public repositories to see if the image is already available. -# Argument: PUBLIC_IMAGE_NAME - string containing the public name of the image to pull -ct_check_image_availability() { - local public_image_name=$1; - - # Try pulling the image to see if it is accessible - if ! ct_pull_image "$public_image_name" &>/dev/null; then - echo "$public_image_name could not be downloaded via 'docker'" - return 1 - fi -} - -# ct_check_latest_imagestreams -# ----------------------------- -# Check if the latest version present in Makefile in the variable VERSIONS -# is present in all imagestreams. -# Also the latest tag in the imagestreams has to contain the latest version -ct_check_latest_imagestreams() { - local latest_version= - local test_lib_dir= - - # We only maintain imagestreams for RHEL and CentOS (Community) - if [[ "$OS" =~ ^fedora.* ]] ; then - echo "Imagestreams for Fedora are not maintained, skipping ct_check_latest_imagestreams" - return 0 - fi - - # Check only lines which starts with VERSIONS - latest_version=$(grep '^VERSIONS' Makefile | rev | cut -d ' ' -f 1 | rev ) - # Fall back to previous version if the latest is excluded for this OS - [ -f "$latest_version/.exclude-$OS" ] && latest_version=$(grep '^VERSIONS' Makefile | rev | cut -d ' ' -f 2 | rev ) - # Only test the imagestream once, when the version matches - # ignore the SC warning, $VERSION is always available - # shellcheck disable=SC2153 - if [ "$latest_version" == "$VERSION" ]; then - test_lib_dir=$(dirname "$(readlink -f "$0")") - python3 "${test_lib_dir}/check_imagestreams.py" "$latest_version" - else - echo "Image version $VERSION is not latest, skipping ct_check_latest_imagestreams" - fi -} - -# ct_show_resources -# ---------------- -# Prints the available resources -ct_show_resources() -{ - echo "Resources info:" - echo "Memory:" - free -h - echo "Storage:" - df -h || : - echo "CPU" - lscpu -} - -# ct_clone_git_repository -# ----------------------------- -# Argument: app_url - git URI pointing to a repository, supports "@" to indicate a different branch -# Argument: app_dir (optional) - name of the directory to clone the repository into -ct_clone_git_repository() -{ - local app_url=$1; shift - local app_dir=$1 - - # If app_url contains @, the string after @ is considered - # as a name of a branch to clone instead of the main/master branch - IFS='@' read -ra git_url_parts <<< "${app_url}" - - if [ -n "${git_url_parts[1]}" ]; then - git_clone_cmd="git clone --branch ${git_url_parts[1]} ${git_url_parts[0]} ${app_dir}" - else - git_clone_cmd="git clone ${app_url} ${app_dir}" - fi - - if ! $git_clone_cmd ; then - echo "ERROR: Git repository ${app_url} cannot be cloned into ${app_dir}." - return 1 - fi -} - -# ct_get_uid_from_image -# ----------------------------- -# Argument: user - user to get uid for inside the image -# Argument: src_image - image to use for user information -ct_get_uid_from_image() -{ - local user=$1; shift - local src_image=$1 - local user_id= - - # NOTE: The '-eq' test is used to check if $user is numeric as it will fail if $user is not an integer - if ! [ "$user" -eq "$user" ] 2>/dev/null && ! user_id=$(docker run --rm "$src_image" bash -c "id -u $user 2>/dev/null"); then - echo "ERROR: id of user $user not found inside image $src_image." - return 1 - else - echo "${user_id:-$user}" - fi -} - -# ct_test_app_dockerfile -# ----------------------------- -# Argument: dockerfile - path to a Dockerfile that will be used for building an image -# (must work with an application directory called 'app-src') -# Argument: app_url - git or local URI with a testing application, supports "@" to indicate a different branch -# Argument: body_regexp - PCRE regular expression that must match the response body -# Argument: app_dir - name of the application directory that is used in the Dockerfile -# Argument: port - Optional port number (default: 8080) -ct_test_app_dockerfile() { - local dockerfile=$1 - local app_url=$2 - local expected_text=$3 - local app_dir=$4 # this is a directory that must match with the name in the Dockerfile - local port=${5:-8080} - local app_image_name=myapp - local ret - local cname=app_dockerfile - - if [ -z "$app_dir" ] ; then - echo "ERROR: Option app_dir not set. Terminating the Dockerfile build." - return 1 - fi - - if ! [ -r "${dockerfile}" ] || ! [ -s "${dockerfile}" ] ; then - echo "ERROR: Dockerfile ${dockerfile} does not exist or is empty." - echo "Terminating the Dockerfile build." - return 1 - fi - - CID_FILE_DIR=${CID_FILE_DIR:-$(mktemp -d)} - local dockerfile_abs - dockerfile_abs=$(readlink -f "${dockerfile}") - tmpdir=$(mktemp -d) - pushd "$tmpdir" >/dev/null - cp "${dockerfile_abs}" Dockerfile - - # Rewrite the source image to what we test - sed -i -e "s|^FROM.*$|FROM $IMAGE_NAME|" Dockerfile - # a bit more verbose, but should help debugging failures - echo "Using this Dockerfile:" - cat Dockerfile - - if [ -d "$app_url" ] ; then - echo "Copying local folder: $app_url -> $app_dir." - cp -Lr "$app_url" "$app_dir" - else - if ! ct_clone_git_repository "$app_url" "$app_dir" ; then - echo "Terminating the Dockerfile build." - return 1 - fi - fi - - echo "Building '${app_image_name}' image using docker build" - if ! docker build --no-cache=true -t "${app_image_name}" . ; then - echo "ERROR: The image cannot be built from ${dockerfile} and application ${app_url}." - echo "Terminating the Dockerfile build." - return 1 - fi - - if ! docker run -d --cidfile="${CID_FILE_DIR}/app_dockerfile" --rm "${app_image_name}" ; then - echo "ERROR: The image ${app_image_name} cannot be run for ${dockerfile} and application ${app_url}." - echo "Terminating the Dockerfile build." - return 1 - fi - echo "Waiting for ${app_image_name} to start" - ct_wait_for_cid "${CID_FILE_DIR}/app_dockerfile" - - ip="$(ct_get_cip "${cname}")" - ct_test_response "http://$ip:${port}" 200 "${expected_text}" - ret=$? - - # cleanup - docker kill "$(ct_get_cid "${cname}")" - sleep 2 - docker rmi "${app_image_name}" - popd >/dev/null - rm -rf "${tmpdir}" - rm -f "${CID_FILE_DIR}/${cname}" - return $ret -} - -# vim: set tabstop=2:shiftwidth=2:expandtab: