From f93949d2e560d4d5022a091ad5d093a264a4a7dc Mon Sep 17 00:00:00 2001 From: Petr Kubat Date: May 05 2020 06:25:35 +0000 Subject: Pull changes from upstream and rebase for: rebuild for latest ubi8 Resolves: #1620520 --- diff --git a/root-common/usr/share/container-scripts/mysql/common.sh b/root-common/usr/share/container-scripts/mysql/common.sh index aa51eb0..9b40035 100644 --- a/root-common/usr/share/container-scripts/mysql/common.sh +++ b/root-common/usr/share/container-scripts/mysql/common.sh @@ -78,6 +78,13 @@ function wait_for_mysql() { done } +function wait_for_mysql_shutdown() { + while pgrep -f "${MYSQL_PREFIX}/libexec/mysqld" >/dev/null; do + log_info "Waiting for MySQL to shutdown ..." + sleep 1 + done +} + # Start local MySQL server with a defaults file function start_local_mysql() { log_info 'Starting MySQL server with disabled networking ...' @@ -92,6 +99,7 @@ function start_local_mysql() { function shutdown_local_mysql() { log_info 'Shutting down MySQL ...' mysqladmin $admin_flags flush-privileges shutdown + wait_for_mysql_shutdown } # Initialize the MySQL database (create user accounts and the initial database) diff --git a/root/usr/share/container-scripts/mysql/README.md b/root/usr/share/container-scripts/mysql/README.md index 9f87288..314cbe1 100644 --- a/root/usr/share/container-scripts/mysql/README.md +++ b/root/usr/share/container-scripts/mysql/README.md @@ -2,12 +2,13 @@ MySQL 8.0 SQL Database Server container image ========================================== This container image includes MySQL 8.0 SQL database server for OpenShift and general usage. -Users can choose between RHEL and CentOS based images. -The RHEL image is available in the [Red Hat Container Catalog](https://access.redhat.com/containers/#/registry.access.redhat.com/rhel8/mysql-80) -as registry.access.redhat.com/rhel8/mysql-80. -The CentOS image is then available on [Docker Hub](https://hub.docker.com/r/centos/mysql-80-centos8/) -as centos/mysql-80-centos8. +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 [Docker Hub](https://hub.docker.com/r/centos/), +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 ----------- @@ -23,12 +24,12 @@ Usage ----- For this, we will assume that you are using the MySQL 8.0 container image from the -Red Hat Container Catalog called `rhel8/mysql-80`. +Red Hat Container Catalog called `rhscl/mysql-80-rhel7`. If you want to set only the mandatory environment variables and not store the database in a host directory, execute the following command: ``` -$ docker run -d --name mysql_database -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e MYSQL_DATABASE=db -p 3306:3306 rhel8/mysql-80 +$ podman run -d --name mysql_database -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e MYSQL_DATABASE=db -p 3306:3306 rhscl/mysql-80-rhel7 ``` This will create a container named `mysql_database` running MySQL with database @@ -41,7 +42,7 @@ If the database directory is not initialized, the entrypoint script will first run [`mysql_install_db`](https://dev.mysql.com/doc/refman/en/mysql-install-db.html) and setup necessary database users and passwords. After the database is initialized, or if it was already present, `mysqld` is executed and will run as PID 1. You can - stop the detached container by running `docker stop mysql_database`. + stop the detached container by running `podman stop mysql_database`. Environment variables and volumes @@ -98,7 +99,7 @@ The following environment variables influence the MySQL configuration file. They **`MYSQL_INNODB_BUFFER_POOL_SIZE (default: 32M or 50% of available memory)`** The size of the buffer pool where InnoDB caches table and index data -**`MYSQL_INNODB_LOG_FILE_SIZE (default: 8M or 15% of available available)`** +**`MYSQL_INNODB_LOG_FILE_SIZE (default: 8M or 15% of available memory)`** The size of each log file in a log group **`MYSQL_INNODB_LOG_BUFFER_SIZE (default: 8M or 15% of available memory)`** @@ -187,16 +188,33 @@ location is `/etc/my.cnf` but you can change it to `/etc/mysql/my.cnf` by settin Extending image --------------- -This image can be extended using [source-to-image](https://github.com/openshift/source-to-image). +This image can be extended in Openshift using the `Source` build strategy or via the standalone +[source-to-image](https://github.com/openshift/source-to-image) application (where available). +For this, we will assume that you are using the `rhscl/mysql-80-rhel7` image, +available via `mysql:8.0` imagestream tag in Openshift. -For example, to build a customized MariaDB database image `my-mysql-rhel8` -with a configuration in `~/image-configuration/` run: + +For example, to build a customized MySQL database image `my-mysql-rhel7` +with a configuration from `https://github.com/sclorg/mysql-container/tree/master/examples/extend-image` run: + +``` +$ oc new-app mysql:8.0~https://github.com/sclorg/mysql-container.git \ + --name my-mysql-rhel7 \ + --context-dir=examples/extend-image \ + --env MYSQL_OPERATIONS_USER=opuser \ + --env MYSQL_OPERATIONS_PASSWORD=oppass \ + --env MYSQL_DATABASE=opdb \ + --env MYSQL_USER=user \ + --env MYSQL_PASSWORD=pass +``` + +or via s2i: ``` -$ s2i build ~/image-configuration/ rhel8/mysql-80 my-mysql-rhel8 +$ s2i build --context-dir=examples/extend-image https://github.com/sclorg/mysql-container.git rhscl/mysql-80-rhel7 my-mysql-rhel7 ``` -The directory passed to `s2i build` can contain these directories: +The directory passed to Openshift can contain these directories: `mysql-cfg/` When starting the container, files from this directory will be used as @@ -227,7 +245,7 @@ Variables that can be used in the scripts provided to s2i: `$MYSQL_DATADIR_FIRST_INIT` variable defined when the container was initialized from the empty data dir -During `s2i build` all provided files are copied into `/opt/app-root/src` +During the s2i build all provided files are copied into `/opt/app-root/src` directory into the resulting image. If some configuration files are present in the destination directory, files with the same name are overwritten. Also only one file with the same name can be used for customization and user @@ -235,7 +253,7 @@ provided files are preferred over default files in `/usr/share/container-scripts/mysql/`- so it is possible to overwrite them. Same configuration directory structure can be used to customize the image -every time the image is started using `docker run`. The directory has to be +every time the image is started using `podman run`. The directory has to be mounted into `/opt/app-root/src/` in the image (`-v ./image-configuration/:/opt/app-root/src/`). This overwrites customization built into the image. @@ -329,12 +347,13 @@ Troubleshooting --------------- The mysqld deamon in the container logs to the standard output, so the log is available in the container log. The log can be examined by running: - docker logs + podman logs See also -------- Dockerfile and other sources for this container image are available on https://github.com/sclorg/mysql-container. -In that repository, Dockerfile for CentOS is called Dockerfile, Dockerfile -for RHEL is called Dockerfile.rhel8. +In that repository, the Dockerfile for CentOS is called Dockerfile, the Dockerfile +for RHEL7 is called Dockerfile.rhel7, the Dockerfile for RHEL8 is called Dockerfile.rhel8, +and the Dockerfile for Fedora is called Dockerfile.fedora. diff --git a/test/run b/test/run index 08119c2..bb0c7e1 100755 --- a/test/run +++ b/test/run @@ -139,7 +139,7 @@ function run_change_password_test() { function run_replication_test() { local cluster_args="-e MYSQL_MASTER_USER=master -e MYSQL_MASTER_PASSWORD=master -e MYSQL_DATABASE=db" - local max_attempts=60 + local max_attempts=120 # Run the MySQL master docker run $cluster_args -e MYSQL_USER=user -e MYSQL_PASSWORD=foo \ @@ -339,7 +339,7 @@ function run_configuration_tests() { container_name=dynamic_config_test - DOCKER_ARGS='--memory=256m' create_container \ + DOCKER_ARGS='--memory=512m' create_container \ "$container_name" \ --env MYSQL_USER=config_test_user \ --env MYSQL_PASSWORD=config_test \ @@ -349,11 +349,11 @@ function run_configuration_tests() { configuration="$(docker exec -t "$(ct_get_cid $container_name)" bash -c 'set +f; shopt -s nullglob; egrep -hv "^(#|\!|\[|$)" /etc/my.cnf /etc/my.cnf.d/* /opt/rh/mysql*/root/etc/my.cnf /opt/rh/mysql*/root/etc/my.cnf.d/*' | sed 's,\(^[[:space:]]\+\|[[:space:]]\+$\),,' | sort -u)" - test_config_option "$container_name" "$configuration" key_buffer_size 25M - test_config_option "$container_name" "$configuration" read_buffer_size 12M - test_config_option "$container_name" "$configuration" innodb_buffer_pool_size 128M - test_config_option "$container_name" "$configuration" innodb_log_file_size 38M - test_config_option "$container_name" "$configuration" innodb_log_buffer_size 38M + test_config_option "$container_name" "$configuration" key_buffer_size 51M + test_config_option "$container_name" "$configuration" read_buffer_size 25M + test_config_option "$container_name" "$configuration" innodb_buffer_pool_size 256M + test_config_option "$container_name" "$configuration" innodb_log_file_size 76M + test_config_option "$container_name" "$configuration" innodb_log_buffer_size 76M docker stop "$(ct_get_cid $container_name)" >/dev/null @@ -444,7 +444,7 @@ gen_self_signed_cert() { 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 -newkey rsa:2048 -nodes -keyout ${output_dir}/${base_name}-key.pem -subj '/C=GB/ST=Berkshire/L=Newbury/O=My Server Company' > ${output_dir}/${base_name}-req.pem openssl req -new -x509 -nodes -key ${output_dir}/${base_name}-key.pem -batch > ${output_dir}/${base_name}-cert-selfsigned.pem } diff --git a/test/run-openshift b/test/run-openshift deleted file mode 100755 index 46747b4..0000000 --- a/test/run-openshift +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -# -# Test the MariaDB 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 - -set -exo nounset - -test -n "${IMAGE_NAME-}" || false 'make sure $IMAGE_NAME is defined' -test -n "${VERSION-}" || false 'make sure $VERSION is defined' - -function check_mysql_os_service_connection() { - local util_image_name="${1}" ; shift - local service_name="${1}" ; shift - local user="${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="echo 'SELECT 42 as testval\g' | mysql --connect-timeout=15 -h ${pod_ip} -u${user} -p${pass}" - local expected_value='^42' - 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_mysql_pure_image() { - local image_name=${1:-centos/mysql-101-centos7} - local image_name_no_namespace=${image_name##*/} - local service_name=${image_name_no_namespace} - - 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:testing" - - ct_os_deploy_pure_image "$image_name_no_namespace:testing" \ - --name "${service_name}" \ - --env MYSQL_ROOT_PASSWORD=test - - ct_os_wait_pod_ready "${service_name}" 60 - check_mysql_os_service_connection "${image_name}" "${service_name}" root test - - ct_os_delete_project -} - -function test_mysql_template() { - local image_name=${1:-centos/mysql-101-centos7} - local image_name_no_namespace=${image_name##*/} - local service_name=${image_name_no_namespace} - - ct_os_new_project - ct_os_upload_image "${image_name}" "mysql:$VERSION" - - ct_os_deploy_template_image ${THISDIR}/mysql-ephemeral-template.json \ - NAMESPACE="$(oc project -q)" \ - MYSQL_VERSION="$VERSION" \ - DATABASE_SERVICE_NAME="${service_name}" \ - MYSQL_USER=testu \ - MYSQL_PASSWORD=testp \ - MYSQL_DATABASE=testdb - - ct_os_wait_pod_ready "${service_name}" 60 - check_mysql_os_service_connection "${image_name}" "${service_name}" testu testp - - ct_os_delete_project -} - -function test_mysql_s2i() { - local image_name=${1:-centos/mysql-101-centos7} - local app=${2:-https://github.com/sclorg/mysql-container.git} - local context_dir=${3:-test/test-app} - 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:testing" - - ct_os_deploy_s2i_image "$image_name_no_namespace:testing" "${app}" \ - --context-dir="${context_dir}" \ - --name "${service_name}" \ - --env MYSQL_ROOT_PASSWORD=test \ - --env MYSQL_OPERATIONS_USER=testo \ - --env MYSQL_OPERATIONS_PASSWORD=testo \ - --env MYSQL_DATABASE=testopdb \ - --env MYSQL_USER=testnormal \ - --env MYSQL_PASSWORD=testnormal - - ct_os_wait_pod_ready "${service_name}" 60 - check_mysql_os_service_connection "${image_name}" "${service_name}" testo testo 120 - - ct_os_delete_project -} - -ct_os_cluster_up -test_mysql_pure_image ${IMAGE_NAME} -test_mysql_template ${IMAGE_NAME} -# TODO: Can we make the build against examples inside the same PR? -test_mysql_s2i ${IMAGE_NAME} "https://github.com/sclorg/mysql-container.git" test/test-app diff --git a/test/run-openshift b/test/run-openshift new file mode 120000 index 0000000..d84575f --- /dev/null +++ b/test/run-openshift @@ -0,0 +1 @@ +run-openshift-local-cluster \ No newline at end of file diff --git a/test/run-openshift-local-cluster b/test/run-openshift-local-cluster new file mode 100755 index 0000000..a1121de --- /dev/null +++ b/test/run-openshift-local-cluster @@ -0,0 +1,46 @@ +#!/bin/bash +# +# Test the MySQL image in OpenShift (local 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 MySQL in format of X.Y +# OS specifies RHEL version (e.g. OS=rhel7) +# + +THISDIR=$(dirname ${BASH_SOURCE[0]}) + +source ${THISDIR}/test-lib-mysql.sh + +set -eo nounset + +trap ct_os_cleanup EXIT SIGINT + +ct_os_check_compulsory_vars + +ct_os_cluster_up + +test_mysql_pure_image "${IMAGE_NAME}" + +test_mysql_template "${IMAGE_NAME}" + +# TODO: Can we make the build against examples inside the same PR? +test_mysql_s2i "${IMAGE_NAME}" "https://github.com/sclorg/mysql-container.git" test/test-app + +# test with the just built image and an integrated template +test_mysql_integration "${IMAGE_NAME}" "${VERSION}" mysql + +# test with a released image and an integrated template +if [ "${OS}" == "rhel7" ] ; then + PUBLIC_IMAGE_NAME=${PUBLIC_IMAGE_NAME:-${REGISTRY:-registry.access.redhat.com/}rhscl/${BASE_IMAGE_NAME}-${VERSION//./}-rhel7} +else + PUBLIC_IMAGE_NAME=${PUBLIC_IMAGE_NAME:-${REGISTRY:-}centos/${BASE_IMAGE_NAME}-${VERSION//./}-centos7} +fi + +export CT_SKIP_UPLOAD_IMAGE=true +test_mysql_integration mysql "${VERSION}" "${PUBLIC_IMAGE_NAME}" + +OS_TESTSUITE_RESULT=0 + +ct_os_cluster_down + diff --git a/test/run-openshift-remote-cluster b/test/run-openshift-remote-cluster new file mode 100755 index 0000000..91568f7 --- /dev/null +++ b/test/run-openshift-remote-cluster @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Test the MySQL 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 MySQL in format of X.Y +# OS specifies RHEL version (e.g. OS=rhel7) +# + +THISDIR=$(dirname ${BASH_SOURCE[0]}) + +source ${THISDIR}/test-lib-mysql.sh + +set -eo nounset + +trap ct_os_cleanup EXIT SIGINT + +ct_os_check_compulsory_vars + +oc status || false "It looks like oc is not properly logged in." + +export CT_SKIP_NEW_PROJECT=true +export CT_SKIP_UPLOAD_IMAGE=true +export CT_NAMESPACE=openshift + +test_mysql_integration mysql ${VERSION} "registry.access.redhat.com/${IMAGE_NAME}" + +OS_TESTSUITE_RESULT=0 + diff --git a/test/test-lib-mysql.sh b/test/test-lib-mysql.sh new file mode 100755 index 0000000..d944d1b --- /dev/null +++ b/test/test-lib-mysql.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Functions for tests for the MySQL 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 + +function check_mysql_os_service_connection() { + local util_image_name="${1}" ; shift + local service_name="${1}" ; shift + local user="${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="echo 'SELECT 42 as testval\g' | mysql --connect-timeout=15 -h ${pod_ip} -u${user} -p${pass}" + local expected_value='^42' + 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_mysql_pure_image() { + local image_name=${1:-centos/mysql-80-centos7} + local image_name_no_namespace=${image_name##*/} + local service_name=${image_name_no_namespace} + + 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:testing" + + ct_os_deploy_pure_image "$image_name_no_namespace:testing" \ + --name "${service_name}" \ + --env MYSQL_ROOT_PASSWORD=test + + ct_os_wait_pod_ready "${service_name}" 60 + check_mysql_os_service_connection "${image_name}" "${service_name}" root test + + ct_os_delete_project +} + +function test_mysql_template() { + local image_name=${1:-centos/mysql-80-centos7} + local image_name_no_namespace=${image_name##*/} + local service_name=${image_name_no_namespace} + + ct_os_new_project + ct_os_upload_image "${image_name}" "mysql:$VERSION" + + ct_os_deploy_template_image ${THISDIR}/mysql-ephemeral-template.json \ + NAMESPACE="$(oc project -q)" \ + MYSQL_VERSION="$VERSION" \ + DATABASE_SERVICE_NAME="${service_name}" \ + MYSQL_USER=testu \ + MYSQL_PASSWORD=testp \ + MYSQL_DATABASE=testdb + + ct_os_wait_pod_ready "${service_name}" 60 + check_mysql_os_service_connection "${image_name}" "${service_name}" testu testp + + ct_os_delete_project +} + +function test_mysql_s2i() { + local image_name=${1:-centos/mysql-80-centos7} + local app=${2:-https://github.com/sclorg/mysql-container.git} + local context_dir=${3:-test/test-app} + 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:testing" + + ct_os_deploy_s2i_image "$image_name_no_namespace:testing" "${app}" \ + --context-dir="${context_dir}" \ + --name "${service_name}" \ + --env MYSQL_ROOT_PASSWORD=test \ + --env MYSQL_OPERATIONS_USER=testo \ + --env MYSQL_OPERATIONS_PASSWORD=testo \ + --env MYSQL_DATABASE=testopdb \ + --env MYSQL_USER=testnormal \ + --env MYSQL_PASSWORD=testnormal + + ct_os_wait_pod_ready "${service_name}" 60 + check_mysql_os_service_connection "${image_name}" "${service_name}" testo testo 120 + + ct_os_delete_project +} + +function test_mysql_integration() { + local image_name=$1 + local VERSION=$2 + local import_image=$3 + local service_name=${import_image##*/} + ct_os_template_exists mysql-ephemeral && t=mysql-ephemeral || t=mysql-persistent + ct_os_test_template_app_func "${image_name}" \ + "${t}" \ + "${service_name}" \ + "ct_os_check_cmd_internal '${import_image}' '${service_name}' \"echo 'SELECT 42 as testval\g' | mysql --connect-timeout=15 -h testdb -utestu -ptestp\" '^42' 120" \ + "-p MYSQL_VERSION=${VERSION} \ + -p DATABASE_SERVICE_NAME="${service_name}-testing" \ + -p MYSQL_USER=testu \ + -p MYSQL_PASSWORD=testp \ + -p MYSQL_DATABASE=testdb" "" "${import_image}" +} +