diff --git a/Dockerfile b/Dockerfile index cb3499b..f25d213 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.fedoraproject.org/f34/s2i-core:latest +FROM quay.io/fedora/s2i-core:latest # Redis image based on Software Collections packages # @@ -8,7 +8,6 @@ FROM registry.fedoraproject.org/f34/s2i-core:latest # * $REDIS_PASSWORD - Database password ENV NAME=redis \ - RELEASE=1 \ VERSION=6 ENV REDIS_VERSION=$VERSION \ @@ -30,9 +29,9 @@ LABEL summary="$SUMMARY" \ io.openshift.expose-services="6379:redis" \ io.openshift.tags="database,redis,redis6" \ com.redhat.component="$NAME" \ - name="$FGC/$NAME" \ + name="fedora/$NAME-$VERSION" \ version="$VERSION" \ - usage="docker run -d --name redis_database -p 6379:6379 $FGC/$NAME" \ + usage="docker run -d --name redis_database -p 6379:6379 quay.io/fedora/$NAME-$VERSION" \ maintainer="SoftwareCollections.org " EXPOSE 6379 diff --git a/Dockerfile.c8s b/Dockerfile.c8s new file mode 100644 index 0000000..2494f2d --- /dev/null +++ b/Dockerfile.c8s @@ -0,0 +1,76 @@ +FROM quay.io/sclorg/s2i-core-c8s:c8s + +# Redis image based on Software Collections packages +# +# Volumes: +# * /var/lib/redis/data - Datastore for Redis +# Environment: +# * $REDIS_PASSWORD - Database password + +ENV REDIS_VERSION=6 \ + 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="$DESCRIPTION" \ + io.k8s.display-name="Redis $REDIS_VERSION" \ + io.openshift.expose-services="6379:redis" \ + io.openshift.tags="database,redis,redis$REDIS_VERSION,redis-$REDIS_VERSION" \ + com.redhat.component="redis-$REDIS_VERSION-container" \ + name="sclorg/redis-$REDIS_VERSION-c8s" \ + version="1" \ + usage="podman run -d --name redis_database -p 6379:6379 sclorg/redis-$REDIS_VERSION-c8s" \ + 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 + yum -y module enable redis:$REDIS_VERSION && \ + INSTALL_PKGS="policycoreutils redis" && \ + yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \ + rpm -V $INSTALL_PKGS && \ + yum -y clean all --enablerepo='*' && \ + 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.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.c9s b/Dockerfile.c9s new file mode 100644 index 0000000..5e28550 --- /dev/null +++ b/Dockerfile.c9s @@ -0,0 +1,76 @@ +FROM quay.io/sclorg/s2i-core-c9s:c9s + +# Redis image based on Software Collections packages +# +# Volumes: +# * /var/lib/redis/data - Datastore for Redis +# Environment: +# * $REDIS_PASSWORD - Database password + +ENV REDIS_VERSION=6 \ + 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="$DESCRIPTION" \ + io.k8s.display-name="Redis $REDIS_VERSION" \ + io.openshift.expose-services="6379:redis" \ + io.openshift.tags="database,redis,redis$REDIS_VERSION,redis-$REDIS_VERSION" \ + com.redhat.component="redis-$REDIS_VERSION-container" \ + name="sclorg/redis-$REDIS_VERSION-c9s" \ + version="1" \ + com.redhat.license_terms="https://www.redhat.com/en/about/red-hat-end-user-license-agreements#rhel" \ + usage="podman run -d --name redis_database -p 6379:6379 quay.io/sclorg/redis-$REDIS_VERSION-c9s" \ + 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 + INSTALL_PKGS="policycoreutils redis" && \ + yum install -y --setopt=tsflags=nodocs $INSTALL_PKGS && \ + rpm -V $INSTALL_PKGS && \ + yum -y clean all --enablerepo='*' && \ + 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/root/usr/share/container-scripts/redis/README.md b/root/usr/share/container-scripts/redis/README.md index 97db572..a1a898a 100644 --- a/root/usr/share/container-scripts/redis/README.md +++ b/root/usr/share/container-scripts/redis/README.md @@ -82,4 +82,5 @@ 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. +for RHEL8 it's `Dockerfile.rhel8`, for CentOS Stream 8 it's `Dockerfile.c8s`, +for CentOS Stream 9 it's `Dockerfile.c9s` and the Fedora Dockerfile is called Dockerfile.fedora. diff --git a/test/imagestreams/redis-rhel-aarch64.json b/test/imagestreams/redis-rhel-aarch64.json index 309351b..4b406c7 100644 --- a/test/imagestreams/redis-rhel-aarch64.json +++ b/test/imagestreams/redis-rhel-aarch64.json @@ -26,6 +26,24 @@ }, "name": "latest" }, + { + "annotations": { + "description": "Provides a Redis 6 database on RHEL 9. 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 9)", + "openshift.io/provider-display-name": "Red Hat, Inc.", + "tags": "redis", + "version": "6" + }, + "from": { + "kind": "DockerImage", + "name": "registry.redhat.io/rhel9/redis-6:latest" + }, + "referencePolicy": { + "type": "Local" + }, + "name": "6-el9" + }, { "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.", @@ -43,24 +61,6 @@ "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 index c9906b2..15ffa74 100644 --- a/test/imagestreams/redis-rhel.json +++ b/test/imagestreams/redis-rhel.json @@ -26,6 +26,24 @@ }, "name": "latest" }, + { + "annotations": { + "description": "Provides a Redis 6 database on RHEL 9. 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 9)", + "openshift.io/provider-display-name": "Red Hat, Inc.", + "tags": "redis", + "version": "6" + }, + "from": { + "kind": "DockerImage", + "name": "registry.redhat.io/rhel9/redis-6:latest" + }, + "referencePolicy": { + "type": "Local" + }, + "name": "6-el9" + }, { "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.", @@ -61,60 +79,6 @@ "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/run-openshift-remote-cluster b/test/run-openshift-remote-cluster index 2199f48..0f1cbea 100755 --- a/test/run-openshift-remote-cluster +++ b/test/run-openshift-remote-cluster @@ -12,7 +12,10 @@ THISDIR=$(dirname ${BASH_SOURCE[0]}) source ${THISDIR}/test-lib-redis.sh -set -eo nounset +TEST_LIST="\ +test_redis_integration +test_redis_imagestream +" trap ct_os_cleanup EXIT SIGINT @@ -20,18 +23,15 @@ ct_os_set_ocp4 ct_os_check_compulsory_vars -oc status || false "It looks like oc is not properly logged in." +ct_os_check_login || exit 1 -# For testing on OpenShift 4 we use external registry -export CT_EXTERNAL_REGISTRY=true +set -u -# Check the template -test_redis_integration "${IMAGE_NAME}" +# For testing on OpenShift 4 we use internal registry +export CT_OCP4_TEST=true -# Check the imagestream -test_redis_imagestream - -OS_TESTSUITE_RESULT=0 +TEST_SUMMARY='' +TEST_SET=${TESTS:-$TEST_LIST} ct_run_tests_from_testset "openshift-remote-cluster" # vim: set tabstop=2:shiftwidth=2:expandtab: diff --git a/test/test-lib-openshift.sh b/test/test-lib-openshift.sh index b98e628..1067e46 100644 --- a/test/test-lib-openshift.sh +++ b/test/test-lib-openshift.sh @@ -5,21 +5,23 @@ source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh # Set of functions for testing docker images in OpenShift using 'oc' command -# A variable containing the overall test result; must be changed to 0 in the end -# of the testing script: -# OS_TESTSUITE_RESULT=0 +# A variable containing the overall test result +# TESTSUITE_RESULT=0 # And the following trap must be set, in the beginning of the test script: # trap ct_os_cleanup EXIT SIGINT -OS_TESTSUITE_RESULT=1 +TESTSUITE_RESULT=0 OS_CLUSTER_STARTED_BY_TEST=0 function ct_os_cleanup() { - if [ $OS_TESTSUITE_RESULT -eq 0 ] ; then + echo "${TEST_SUMMARY:-}" + if [ $TESTSUITE_RESULT -eq 0 ] ; then # shellcheck disable=SC2153 echo "OpenShift tests for ${IMAGE_NAME} succeeded." + exit 0 else # shellcheck disable=SC2153 echo "OpenShift tests for ${IMAGE_NAME} failed." + exit 1 fi } @@ -44,6 +46,7 @@ function ct_os_check_compulsory_vars() { function ct_os_get_status() { oc get all oc status + oc status --suggest } # ct_os_print_logs @@ -397,13 +400,13 @@ function ct_delete_all_objects() { sleep 10 } -# ct_os_docker_login +# ct_os_docker_login_v3 # -------------------- # 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 +function ct_os_docker_login_v3() { + [ -n "${REGISTRY_ADDRESS:-}" ] && echo "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 @@ -414,6 +417,26 @@ function ct_os_docker_login() { return 1 } +# ct_os_docker_login_v4 +# -------------------- +# 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_v4() { + OCP4_REGISTER=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}') + echo "OCP4 loging address is $OCP4_REGISTER." + if [ -z "${OCP4_REGISTER}" ]; then + echo "!!!OpenShift 4 registry address not found. This is an error. Check OpenShift 4 cluster!!!" + return 1 + fi + + if docker login -u kubeadmin -p "$(oc whoami -t)" "${OCP4_REGISTER}"; then + echo "Login to $OCP4_REGISTER was successfully." + return 0 + fi + return 1 +} + # ct_os_upload_image IMAGE [IMAGESTREAM] # -------------------- # Uploads image from local registry to the OpenShift internal registry. @@ -422,15 +445,36 @@ function ct_os_docker_login() { # 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 os_version="${1}" ; shift local input_name="${1}" ; shift - local image_name=${input_name##*/} - local imagestream=${1:-$image_name:latest} + local image_name=${1} local output_name + local source_name + local docker_options="" - output_name="${REGISRTY_ADDRESS:-172.30.1.1:5000}/$(oc project -q)/$imagestream" + if [ "${os_version}" != "v3" ] && [ "${os_version}" != "v4" ]; then + echo "You have to specify OpenShift version to upload an image." + echo "Either 'v3' or 'v4' is allowed" + return 1 + fi - ct_os_docker_login - docker tag "${input_name}" "${output_name}" + source_name="${input_name}" + if [ "${os_version}" == "v3" ]; then + output_name="${REGISRTY_ADDRESS:-172.30.1.1:5000}/$(oc project -q)/$image_name" + + if ! ct_os_docker_login_v3; then + return 1 + fi + + fi + if [ "${os_version}" == "v4" ]; then + # Variable OCP4_REGISTER is set in function ct_os_docker_login_v4 + if ! ct_os_docker_login_v4; then + return 1 + fi + output_name="$OCP4_REGISTER/$namespace/$image_name" + fi + docker tag "${source_name}" "${output_name}" docker push "${output_name}" } @@ -672,8 +716,9 @@ function ct_os_test_s2i_app_func() { 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}" + if [ "${CT_OCP4_TEST:-false}" == 'true' ] ; then + echo "Uploading image ${image_name} as ${image_tagged} into OpenShift internal registry." + ct_os_upload_image "v4" "${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 @@ -684,7 +729,7 @@ function ct_os_test_s2i_app_func() { 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}" + ct_os_upload_image "v3" "${image_name}" "${image_tagged}" fi fi else @@ -816,8 +861,9 @@ function ct_os_test_template_app_func() { # 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}" + if [ "${CT_OCP4_TEST:-false}" == 'true' ] ; then + echo "Uploading image ${image_name} as ${image_tagged} into OpenShift internal registry." + ct_os_upload_image "v4" "${image_name}" "${image_tagged}" else if [ "${CT_SKIP_UPLOAD_IMAGE:-false}" == 'true' ] ; then echo "Importing image ${image_name} as ${image_tagged}" @@ -827,7 +873,7 @@ function ct_os_test_template_app_func() { 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}" + ct_os_upload_image "v3" "${image_name}" "${image_tagged}" fi fi else @@ -849,10 +895,11 @@ function ct_os_test_template_app_func() { exit 1 fi - if [ "${CT_EXTERNAL_REGISTRY:-false}" == 'true' ] ; then - ct_os_import_image_ocp4 "${image_tag_a[0]}" "${image_tag_a[1]}" + if [ "${CT_OCP4_TEST:-false}" == 'true' ] ; then + echo "Uploading image ${image_tag_a[0]} as ${image_tag_a[1]} into OpenShift internal registry." + ct_os_upload_image "v4" "${image_name}" "${image_tag_a[1]}" else - ct_os_upload_image "${image_tag_a[0]}" "${image_tag_a[1]}" + ct_os_upload_image "v3" "${image_tag_a[0]}" "${image_tag_a[1]}" fi done fi @@ -957,8 +1004,9 @@ ct_os_test_image_update() { local old_image=$1; shift local istag=$1; shift local check_function=$1; shift - local service_name=${image_name##*/} local ip="" check_command_exp="" + local image_name_no_namespace=${image_name##*/} + local service_name="${image_name_no_namespace%%:*}-testing" echo "Running image update test for: $image_name" # shellcheck disable=SC2119 @@ -966,7 +1014,7 @@ ct_os_test_image_update() { # Get current image from repository and create an imagestream docker pull "$old_image:latest" 2>/dev/null - ct_os_upload_image "$old_image" "$istag" + ct_os_upload_image "v3" "$old_image" "$istag" # Setup example application with curent image oc new-app "$@" --name "$service_name" @@ -978,7 +1026,7 @@ ct_os_test_image_update() { 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_upload_image "v3" "$image_name" "$istag" ct_os_wait_pod_ready "${service_name}-2" 60 # Check application output diff --git a/test/test-lib-redis.sh b/test/test-lib-redis.sh index 8224fdc..9a6a0a6 100644 --- a/test/test-lib-redis.sh +++ b/test/test-lib-redis.sh @@ -13,9 +13,8 @@ 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}" \ + 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'" \ diff --git a/test/test-lib-remote-openshift.sh b/test/test-lib-remote-openshift.sh index bda03f6..e7b9e06 100644 --- a/test/test-lib-remote-openshift.sh +++ b/test/test-lib-remote-openshift.sh @@ -5,9 +5,8 @@ source "$(dirname "${BASH_SOURCE[0]}")"/test-lib.sh # Set of functions for testing docker images in OpenShift using 'oc' command -# A variable containing the overall test result; must be changed to 0 in the end -# of the testing script: -# OS_TESTSUITE_RESULT=0 +# A variable containing the overall test result +# TESTSUITE_RESULT=0 # And the following trap must be set, in the beginning of the test script: # trap ct_os_cleanup EXIT SIGINT @@ -32,13 +31,6 @@ function ct_os_set_path_oc_4() { return 1 fi export PATH="${oc_path}:${PATH}" - oc version - if ! oc version | grep -q "Client Version: ${oc_version}." ; then - echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${oc_version} not found in PATH ($PATH)" >&1 - return 1 - else - echo "PATH set correctly, binary oc found in version ${oc_version}: $(command -v oc)" - fi } # ct_os_prepare_ocp4 @@ -55,10 +47,15 @@ function ct_os_set_ocp4() { OS_OC_CLIENT_VERSION=${OS_OC_CLIENT_VERSION:-4.4} ct_os_set_path_oc_4 "${OS_OC_CLIENT_VERSION}" - oc version - login=$(cat "$KUBEPASSWORD") oc login -u kubeadmin -p "$login" + oc version + if ! oc version | grep -q "Client Version: ${OS_OC_CLIENT_VERSION}." ; then + echo "ERROR: something went wrong, oc located at ${oc_path}, but oc of version ${OS_OC_CLIENT_VERSION} not found in PATH ($PATH)" >&1 + return 1 + else + echo "PATH set correctly, binary oc found in version ${OS_OC_CLIENT_VERSION}: $(command -v oc)" + fi echo "Login to OpenShift ${OS_OC_CLIENT_VERSION} is DONE" # let openshift cluster to sync to avoid some race condition errors sleep 3 @@ -80,37 +77,28 @@ function ct_os_upload_image_external_registry() { } -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 + echo "Uploading image ${image_name} as ${imagestream} into OpenShift internal registry." + ct_os_upload_image_v4 "${image_name}" "${imagestream}" + +} + +# ct_os_check_login +# --------------- +# function checks if the login to openshift was successful +# if successful returns 0 +# if not, write error message, sets test result to 1 +# and exits with non-zero +# Uses: $TESTSUITE_RESULT - overall result of all tests +function ct_os_check_login() { + oc status || { + echo "-------------------------------------------" + echo "It looks like oc is not properly logged in." + # shellcheck disable=SC2034 + TESTSUITE_RESULT=1 + return 1 + } } diff --git a/test/test-lib.sh b/test/test-lib.sh index e954053..e98bf08 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -16,6 +16,11 @@ # may be redefined in the specific container testfile EXPECTED_EXIT_CODE=0 +export TESTSUITE_RESULT=0 + +# define UNSTABLE_TESTS if not already defined, as this variable +# is not mandatory for containers +UNSTABLE_TESTS="${UNSTABLE_TESTS:-""}" # ct_cleanup # -------------------- @@ -24,6 +29,7 @@ EXPECTED_EXIT_CODE=0 # 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 +# Uses: $TESTSUITE_RESULT - overall result of all tests function ct_cleanup() { ct_show_resources for cid_file in "$CID_FILE_DIR"/* ; do @@ -33,16 +39,47 @@ function ct_cleanup() { : "Stopping and removing container $container..." docker stop "$container" - exit_status=$(docker inspect -f '{{.State.ExitCode}}' "$container") - if [ "$exit_status" != "$EXPECTED_EXIT_CODE" ]; then - : "Dumping logs for $container" - docker logs "$container" + + # Container has not been removed by `docker stop` and still exists + if [ "$( docker ps -a -f "id=$container" | wc -l )" -eq 2 ]; then + exit_status=$(docker inspect -f '{{.State.ExitCode}}' "$container") + if [ "$exit_status" != "$EXPECTED_EXIT_CODE" ]; then + : "Dumping logs for $container" + docker logs "$container" + fi + docker rm -v "$container" fi - docker rm -v "$container" + rm "$cid_file" done rmdir "$CID_FILE_DIR" : "Done." + + ct_show_results + exit "${TESTSUITE_RESULT:-0}" +} + +# ct_show_results +# --------------- +# Prints results of all test cases that are stored into TEST_SUMMARY variable. +# Uses: $TEST_SUMMARY - text info about test-cases +# Uses: $TESTSUITE_RESULT - overall result of all tests +function ct_show_results() { + echo + echo "===============================================" + echo "Test cases results:" + echo + echo "${TEST_SUMMARY:-}" + + if [ -n "${TESTSUITE_RESULT:-}" ] ; then + if [ "$TESTSUITE_RESULT" -eq 0 ] ; then + # shellcheck disable=SC2153 + echo "Tests for ${IMAGE_NAME} succeeded." + else + # shellcheck disable=SC2153 + echo "Tests for ${IMAGE_NAME} failed." + fi + fi } # ct_enable_cleanup @@ -125,6 +162,7 @@ function ct_check_envs_set { for value in $stripped; do # If the falue checked does not go through env_filter we do not care about it echo "$value" | grep -q "$env_filter" || continue + # shellcheck disable=SC2295 if [ -n "${filtered_envs##${env_format//VALUE/$value}}" ]; then echo " Value $value is missing from variable $var_name" echo "$filtered_envs" @@ -284,7 +322,7 @@ function ct_doc_content_old() { 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 + if ! grep -E -q -e "${term}" "${tmpdir}/$(basename "${f}")" ; then echo "ERROR: File /${f} does not include '${term}'." >&2 return 1 fi @@ -489,21 +527,6 @@ ct_path_foreach () } -# ct_run_test_list -# -------------------- -# Execute the tests specified by TEST_LIST -# Uses: $TEST_LIST - list of test names -function ct_run_test_list() { - for test_case in $TEST_LIST; do - : "Running test $test_case" - # shellcheck source=/dev/null - [ -f "test/$test_case" ] && source "test/$test_case" - # shellcheck source=/dev/null - [ -f "../test/$test_case" ] && source "../test/$test_case" - $test_case - done; -} - # ct_gen_self_signed_cert_pem # --------------------------- # Generates a self-signed PEM certificate pair into specified directory. @@ -631,10 +654,14 @@ ct_get_public_image_name() { 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" == "rhel9" ]; then + public_image_name=$registry/rhel9/$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 + elif [ "$os" == "c8s" ]; then + public_image_name=$registry/sclorg/$base_image_name-${version//./}-c8s + elif [ "$os" == "c9s" ]; then + public_image_name=$registry/sclorg/$base_image_name-${version//./}-c9s fi echo "$public_image_name" @@ -646,6 +673,7 @@ ct_get_public_image_name() { # Argument: CMD - Command to be run function ct_assert_cmd_success() { echo "Checking '$*' for success ..." + # shellcheck disable=SC2294 if ! eval "$@" &>/dev/null; then echo " FAIL" return 1 @@ -660,6 +688,7 @@ function ct_assert_cmd_success() { # Argument: CMD - Command to be run function ct_assert_cmd_failure() { echo "Checking '$*' for failure ..." + # shellcheck disable=SC2294 if eval "$@" &>/dev/null; then echo " FAIL" return 1 @@ -935,6 +964,7 @@ ct_check_latest_imagestreams() { # Prints the available resources ct_show_resources() { + echo echo "Resources info:" echo "Memory:" free -h @@ -1059,6 +1089,8 @@ ct_test_app_dockerfile() { ct_test_response "http://$ip:${port}" 200 "${expected_text}" ret=$? + [[ $ret -eq 0 ]] || docker logs "$(ct_get_cid "${cname}")" + # cleanup docker kill "$(ct_get_cid "${cname}")" sleep 2 @@ -1069,4 +1101,101 @@ ct_test_app_dockerfile() { return $ret } +# ct_check_testcase_result +# ----------------------------- +# Check if testcase ended in success or error +# Argument: result - testcase result value +# Uses: $TESTCASE_RESULT - result of the testcase +# Uses: $IMAGE_NAME - name of the image being tested +ct_check_testcase_result() { + local result="$1" + if [[ "$result" != "0" ]]; then + echo "Test for image '${IMAGE_NAME}' FAILED (exit code: ${result})" + TESTCASE_RESULT=1 + fi + return "$result" +} + +# ct_run_tests_from_testset +# ----------------------------- +# Runs all tests in $TEST_SET, prints result to +# the $TEST_SUMMARY variable +# Argument: app_name - application name to log +# Uses: $TEST_SET - set of test cases to run +# Uses: $TEST_SUMMARY - variable for storing test results +# Uses: $IMAGE_NAME - name of the image being tested +# Uses: $UNSTABLE_TESTS - set of tests, whose result can be ignored +# Uses: $IGNORE_UNSTABLE_TESTS - flag to ignore unstable tests +ct_run_tests_from_testset() { + local app_name="${1:-appnamenotset}" + local time_beg_pretty + local time_beg + local time_end + local time_diff + local test_msg + local is_unstable + + # Let's store in the log what change do we test + echo + git show -s + echo + + for test_case in $TEST_SET; do + TESTCASE_RESULT=0 + # shellcheck disable=SC2076 + if [[ " ${UNSTABLE_TESTS[*]} " =~ " ${app_name} " ]]; then + is_unstable=1 + else + is_unstable=0 + fi + time_beg_pretty=$(ct_timestamp_pretty) + time_beg=$(ct_timestamp_s) + echo "-----------------------------------------------" + echo "Running test $test_case (starting at $time_beg_pretty) ... " + echo "-----------------------------------------------" + $test_case + ct_check_testcase_result $? + time_end=$(ct_timestamp_s) + if [ $TESTCASE_RESULT -eq 0 ]; then + test_msg="[PASSED]" + else + if [ -n "${IGNORE_UNSTABLE_TESTS:-""}" ] && [ $is_unstable -eq 1 ]; then + test_msg="[FAILED][UNSTABLE-IGNORED]" + else + test_msg="[FAILED]" + TESTSUITE_RESULT=1 + fi + fi + time_diff=$(ct_timestamp_diff "$time_beg" "$time_end") + printf -v TEST_SUMMARY "%s %s for '%s' %s (%s)\n" "${TEST_SUMMARY:-}" "${test_msg}" "${app_name}" "$test_case" "$time_diff" + [ -n "${FAIL_QUICKLY:-}" ] && return 1 + done; +} + +# ct_timestamp_s +# -------------- +# Returns timestamp in seconds since unix era -- a large integer +function ct_timestamp_s() { + date '+%s' +} + +# ct_timestamp_pretty +# ----------------- +# Returns timestamp readable to a human, like 2022-05-18 10:52:44+02:00 +function ct_timestamp_pretty() { + date --rfc-3339=seconds +} + +# ct_timestamp_diff +# ----------------- +# Computes a time diff between two timestamps +# Argument: start_date - Beginning (in seconds since unix era -- a large integer) +# Argument: final_date - End (in seconds since unix era -- a large integer) +# Returns: Time difference in format HH:MM:SS +function ct_timestamp_diff() { + local start_date=$1 + local final_date=$2 + date -u -d "0 $final_date seconds - $start_date seconds" +"%H:%M:%S" +} + # vim: set tabstop=2:shiftwidth=2:expandtab: