#!/bin/bash # # Test the Postgresql 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]}) TEMPLATES="$THISDIR/examples" REMOTE_TEMPLATES="https://raw.githubusercontent.com/openshift/origin/master/examples/db-templates" source "$THISDIR"/pg-test-lib.sh source "$THISDIR"/test-lib-openshift.sh source "$THISDIR"/test-lib-postgresql.sh set -exo nounset trap ct_os_cleanup EXIT SIGINT ct_os_check_compulsory_vars # Populate template variables if not set already if [ -z "${EPHEMERAL_TEMPLATES:-}" ]; then EPHEMERAL_TEMPLATES=" $REMOTE_TEMPLATES/postgresql-ephemeral-template.json $TEMPLATES/postgresql-ephemeral-template.json" fi if [ -z "${PERSISTENT_TEMPLATES:-}" ]; then PERSISTENT_TEMPLATES=" $REMOTE_TEMPLATES/postgresql-persistent-template.json $TEMPLATES/postgresql-persistent-template.json" fi function assert_cmd_fails() { if eval "$@" &>/dev/null; then echo " FAIL" return 1 fi echo " PASS" return 0 } function insert_postgresql_data() { local image_name=$1 ; shift local user=$1 ; shift local pass=$1 ; shift local database=$1 ; shift local pod_ip=$1; shift : "Inserting data into the database" local cmd="PGPASSWORD=$pass psql -c \"CREATE TABLE testing (a integer); INSERT INTO testing VALUES (42);\"" local cmd_args="-h $pod_ip -U $user -d $database" docker run --rm "$image_name" bash -c "$cmd $cmd_args" } function check_postgresql_data() { local image_name=$1 ; shift local user=$1 ; shift local pass=$1 ; shift local database=$1 ; shift local pod_ip=$1; shift local timeout=${1:-60} SECONDS=0 : "Checking whether the data can be accessed" local cmd="PGPASSWORD=$pass psql -c \"select * from testing;\"" local cmd_args="-h $pod_ip -U $user -d $database" while true ; do result=$(docker run --rm "$image_name" bash -c "$cmd -At $cmd_args") if [ "$result" = "42" ]; then echo " PASS" return 0 fi echo -n "." [ $SECONDS -gt $timeout ] && break sleep 3 done echo " FAIL" return 1 } function check_postgresql_os_service_connection() { local util_image_name=$1 ; shift local service_name=$1 ; shift local user=$1 ; shift local pass=$1 ; shift local database=$1 ; shift local timeout=${1:-60} ; shift || : local pod_ip=$(ct_os_get_service_ip ${service_name}) : " Service ${service_name} check ..." local cmd="PGPASSWORD=${pass} pg_isready -t 15 -h ${pod_ip} -U ${user} -d ${database}" local expected_value='accepting connections' 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_postgresql_pure_image() { local image_name=$1 local image_name_no_namespace=${image_name##*/} local service_name=${image_name_no_namespace} ct_os_new_project ct_os_upload_image "${image_name}" # 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 POSTGRESQL_ADMIN_PASSWORD=test ct_os_wait_pod_ready "${service_name}" 60 check_postgresql_os_service_connection "${image_name}" "${service_name}" postgres test postgres ct_os_delete_project } function test_postgresql_template() { local image_name=$1; shift local template=$1 local image_name_no_namespace=${image_name##*/} local service_name=${image_name_no_namespace} ct_os_new_project ct_os_upload_image "${image_name}" "postgresql:$VERSION" ct_os_deploy_template_image "$template" \ NAMESPACE="$(oc project -q)" \ POSTGRESQL_VERSION="$VERSION" \ DATABASE_SERVICE_NAME="${service_name}" \ POSTGRESQL_USER=testu \ POSTGRESQL_PASSWORD=testp \ POSTGRESQL_DATABASE=testdb ct_os_wait_pod_ready "${service_name}" 60 check_postgresql_os_service_connection "${image_name}" "${service_name}" testu testp testdb ct_os_delete_project } function test_postgresql_update() { local image_name=$1; shift local template=$1 local image_name_no_registry=${image_name#*/} local service_name=${image_name_no_registry#*/} local user="testu" pass="testp" db="testdb" local registry="" old_image="" pod_ip="" local version released=: old_image=$(get_image_id "$VERSION:remote") for version in $NOT_RELEASED_VERSIONS; do case $image_name in *$version*) released=false break ;; esac done if docker pull "$old_image" 2>/dev/null; then # Check if we do not have a stale unreleased versions list # Fail only on rhel, on centos the image is likely already released $released || [ "$OS" = "centos7" ] elif $released; then false "image '$old_image' should already be available" else return # not yet released image, skip fi ct_os_new_project ct_os_upload_image "$old_image" "postgresql:$VERSION" ct_os_deploy_template_image "$template" \ NAMESPACE="$(oc project -q)" \ POSTGRESQL_VERSION="$VERSION" \ DATABASE_SERVICE_NAME="$service_name" \ POSTGRESQL_USER="$user" \ POSTGRESQL_PASSWORD="$pass" \ POSTGRESQL_DATABASE="$db" ct_os_wait_pod_ready "${service_name}" 60 check_postgresql_os_service_connection "$image_name" "$service_name" "$user" "$pass" "$db" pod_ip=$(ct_os_get_service_ip "$service_name") insert_postgresql_data "$image_name" "$user" "$pass" "$db" "$pod_ip" ct_os_upload_image "$image_name" "postgresql:$VERSION" : "Waiting for a few seconds while the pods get restarted" sleep 5 ct_os_wait_pod_ready "$service_name" 60 check_postgresql_os_service_connection "$image_name" "$service_name" "$user" "$pass" "$db" check_postgresql_data "$image_name" "$user" "$pass" "$db" "$pod_ip" ct_os_delete_project } function test_postgresql_replication() { local image_name=$1 local image_name_no_namespace=${image_name##*/} local master_service_name=${image_name_no_namespace}-master local slave_service_name=${image_name_no_namespace}-slave local istag="postgresql:$VERSION" local user="testu" pass="testp" db="testdb" local master_name="" master_ip="" slave_name="" slave_ip="" ct_os_new_project ct_os_upload_image "${image_name}" "$istag" ct_os_deploy_template_image "$TEMPLATES/replica/postgresql_replica.json" \ NAMESPACE="$(oc project -q)" \ IMAGESTREAMTAG="$istag" \ POSTGRESQL_MASTER_SERVICE_NAME="$master_service_name" \ POSTGRESQL_SLAVE_SERVICE_NAME="$slave_service_name" \ POSTGRESQL_USER=testu \ POSTGRESQL_PASSWORD=testp \ POSTGRESQL_DATABASE=testdb ct_os_wait_pod_ready "$master_service_name" 60 ct_os_wait_pod_ready "$slave_service_name" 60 # Force unused rc removal as we do not need rollbacks during testing oc patch "dc/$master_service_name" -p '{"spec":{"revisionHistoryLimit":0}}' oc patch "dc/$slave_service_name" -p '{"spec":{"revisionHistoryLimit":0}}' master_name=$(ct_os_get_pod_name "$master_service_name") slave_name=$(ct_os_get_pod_name "$slave_service_name") master_ip=$(ct_os_get_pod_ip "$master_name") slave_ip=$(ct_os_get_pod_ip "$slave_name") insert_postgresql_data "$image_name" "$user" "$pass" "$db" "$master_ip" check_postgresql_data "$image_name" "$user" "$pass" "$db" "$slave_ip" : "Changing POSTGRESQL_PASSWORD for master and slave" pass=redhat oc set env "dc/$master_service_name" -e POSTGRESQL_PASSWORD="$pass" oc set env "dc/$slave_service_name" -e POSTGRESQL_PASSWORD="$pass" ct_os_wait_pod_ready "$master_service_name-2" 60 ct_os_wait_pod_ready "$slave_service_name-2" 60 # We need to get new pod names and IPs master_name=$(ct_os_get_pod_name "$master_service_name") slave_name=$(ct_os_get_pod_name "$slave_service_name") master_ip=$(ct_os_get_pod_ip "$master_name") slave_ip=$(ct_os_get_pod_ip "$slave_name") check_postgresql_data "$image_name" "$user" "$pass" "$db" "$master_ip" check_postgresql_data "$image_name" "$user" "$pass" "$db" "$slave_ip" : "Redeploying slave node" oc rollout latest "$slave_service_name" ct_os_wait_pod_ready "$slave_service_name-3" 60 slave_name=$(ct_os_get_pod_name "$slave_service_name") slave_ip=$(ct_os_get_pod_ip "$slave_name") check_postgresql_data "$image_name" "$user" "$pass" "$db" "$slave_ip" : "Scaling slaves to 2" oc scale --replicas 2 "dc/$slave_service_name" ct_os_wait_rc_ready "$slave_service_name" 60 slave_name=$(ct_os_get_pod_name "$slave_service_name") for slave in $slave_name; do ct_os_wait_pod_ready "$slave" 60 slave_ip=$(ct_os_get_pod_ip "$slave") check_postgresql_data "$image_name" "$user" "$pass" "$db" "$slave_ip" done ct_os_delete_project } function test_postgresql_persistent_redeploy() { local image_name=$1; shift local template=$1 local image_name_no_namespace=${image_name##*/} local service_name=$image_name_no_namespace local user="testu" pass="testp" db="testdb" local registry="" old_image="" pod_ip="" ct_os_new_project ct_os_upload_image "$image_name" "postgresql:$VERSION" ct_os_deploy_template_image "$template" \ NAMESPACE="$(oc project -q)" \ POSTGRESQL_VERSION="$VERSION" \ DATABASE_SERVICE_NAME="$service_name" \ POSTGRESQL_USER="$user" \ POSTGRESQL_PASSWORD="$pass" \ POSTGRESQL_DATABASE="$db" ct_os_wait_pod_ready "$service_name" 60 check_postgresql_os_service_connection "$image_name" "$service_name" testu testp testdb pod_ip=$(ct_os_get_service_ip "$service_name") insert_postgresql_data "$image_name" "$user" "$pass" "$db" "$pod_ip" : "Redeploying pod" oc rollout latest "$service_name" : "Waiting for a few seconds while the pod gets restarted" sleep 5 ct_os_wait_pod_ready "$service_name" 60 check_postgresql_os_service_connection "$image_name" "$service_name" "$user" "$pass" "$db" : "This should succeed" check_postgresql_data "$image_name" "$user" "$pass" "$db" "$pod_ip" 0 ct_os_delete_project } function test_postgresql_ephemeral_redeploy() { local image_name=$1; shift local template=$1 local image_name_no_namespace=${image_name##*/} local service_name=$image_name_no_namespace local user="testu" pass="testp" db="testdb" local registry="" old_image="" pod_ip="" ct_os_new_project ct_os_upload_image "$image_name" "postgresql:$VERSION" ct_os_deploy_template_image "$template" \ NAMESPACE="$(oc project -q)" \ POSTGRESQL_VERSION="$VERSION" \ DATABASE_SERVICE_NAME="$service_name" \ POSTGRESQL_USER="$user" \ POSTGRESQL_PASSWORD="$pass" \ POSTGRESQL_DATABASE="$db" ct_os_wait_pod_ready "$service_name" 60 check_postgresql_os_service_connection "$image_name" "$service_name" testu testp testdb pod_ip=$(ct_os_get_service_ip "$service_name") insert_postgresql_data "$image_name" "$user" "$pass" "$db" "$pod_ip" : "Redeploying pod" oc rollout latest "$service_name" : "Waiting for a few seconds while the pod gets restarted" sleep 5 ct_os_wait_pod_ready "$service_name" 60 check_postgresql_os_service_connection "$image_name" "$service_name" "$user" "$pass" "$db" : "This should fail" assert_cmd_fails check_postgresql_data "$image_name" "$user" "$pass" "$db" "$pod_ip" 0 ct_os_delete_project } function test_postgresql_configmap_start() { local image_name=$1; shift local template="$TEMPLATES/postgresql-ephemeral-template.json" local image_name_no_namespace=${image_name##*/} local service_name=$image_name_no_namespace local user="testu" pass="testp" db="testdb" local registry="" old_image="" pod_ip="" tmpdir="" local test_string="" ct_os_new_project ct_os_upload_image "$image_name" "postgresql:$VERSION" ct_os_deploy_template_image "$template" \ NAMESPACE="$(oc project -q)" \ POSTGRESQL_VERSION="$VERSION" \ DATABASE_SERVICE_NAME="$service_name" \ POSTGRESQL_USER="$user" \ POSTGRESQL_PASSWORD="$pass" \ POSTGRESQL_DATABASE="$db" ct_os_wait_pod_ready "$service_name" 60 check_postgresql_os_service_connection "$image_name" "$service_name" testu testp testdb # Create a simple configMap with a start.sh script tmpdir=$(mktemp -d) test_string="Start is working" echo "echo $test_string" >> "$tmpdir/start.sh" oc create configmap postgresql-start --from-file="$tmpdir/start.sh" oc set volume "dc/$service_name" --add -t configmap --configmap-name=postgresql-start -m /opt/app-root/src/postgresql-start --name postgresql-start # Wait for redeploy ct_os_wait_pod_ready "$service_name-2" 60 check_postgresql_os_service_connection "$image_name" "$service_name" testu testp testdb # Check logs for the test string oc logs "$(ct_os_get_pod_name "$service_name")" | grep "$test_string" ct_os_delete_project } function run_ephemeral_tests() { local image_name=$1 for template in $EPHEMERAL_TEMPLATES; do test_postgresql_ephemeral_redeploy "$image_name" "$template" test_postgresql_template "$image_name" "$template" done } function run_persistent_tests() { local image_name=$1 for template in $PERSISTENT_TEMPLATES; do test_postgresql_persistent_redeploy "$image_name" "$template" test_postgresql_update "$image_name" "$template" done } ct_os_cluster_up # Print oc logs on failure ct_os_enable_print_logs test_postgresql_pure_image "$IMAGE_NAME" test_postgresql_replication "$IMAGE_NAME" run_ephemeral_tests "$IMAGE_NAME" run_persistent_tests "$IMAGE_NAME" test_postgresql_configmap_start "$IMAGE_NAME" # test with the just built image and an integrated template echo "Running test_postgresql_integration with ${IMAGE_NAME}" test_postgresql_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 docker pull "${PUBLIC_IMAGE_NAME}"; then echo "Running test_postgresql_integration with ${PUBLIC_IMAGE_NAME}" test_postgresql_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 echo "Running test_mariadb_imagestream" test_postgresql_imagestream OS_TESTSUITE_RESULT=0 ct_os_cluster_down # vim: set tabstop=2:shiftwidth=2:expandtab: