1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#!/bin/bash -x
# Basic integration tests with postgres. Requires docker to work.
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
METRICS_DIR=$(pwd)
# Read the absolute path to the exporter
postgres_exporter="$1"
test_binary="$2"
export POSTGRES_PASSWORD=postgres
exporter_port=9187
echo "Exporter Binary: $postgres_exporter" 1>&2
echo "Test Binary: $test_binary" 1>&2
[ -z "$postgres_exporter" ] && echo "Missing exporter binary" && exit 1
[ -z "$test_binary" ] && echo "Missing test binary" && exit 1
cd "$DIR" || exit 1
VERSIONS=( \
9.4 \
9.5 \
9.6 \
10 \
11 \
)
wait_for_postgres(){
local container=$1
local ip=$2
local port=$3
if [ -z "$ip" ]; then
echo "No IP specified." 1>&2
exit 1
fi
if [ -z "$port" ]; then
echo "No port specified." 1>&2
exit 1
fi
local wait_start
wait_start=$(date +%s) || exit 1
echo "Waiting for postgres to start listening..."
while ! docker exec "$container" pg_isready --host="$ip" --port="$port" &> /dev/null; do
if [ $(( $(date +%s) - wait_start )) -gt "$TIMEOUT" ]; then
echo "Timed out waiting for postgres to start!" 1>&2
exit 1
fi
sleep 1
done
echo "Postgres is online at $ip:$port"
}
wait_for_exporter() {
local wait_start
wait_start=$(date +%s) || exit 1
echo "Waiting for exporter to start..."
while ! nc -z localhost "$exporter_port" ; do
if [ $(( $(date +%s) - wait_start )) -gt "$TIMEOUT" ]; then
echo "Timed out waiting for exporter!" 1>&2
exit 1
fi
sleep 1
done
echo "Exporter is online at localhost:$exporter_port"
}
smoketest_postgres() {
local version=$1
local CONTAINER_NAME=postgres_exporter-test-smoke
local TIMEOUT=30
local IMAGE_NAME=postgres
local CUR_IMAGE=$IMAGE_NAME:$version
echo "#######################"
echo "Standalone Postgres $version"
echo "#######################"
local docker_cmd="docker run -d -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD $CUR_IMAGE"
echo "Docker Cmd: $docker_cmd"
CONTAINER_NAME=$($docker_cmd)
standalone_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $CONTAINER_NAME)
# shellcheck disable=SC2064
trap "docker logs $CONTAINER_NAME ; docker kill $CONTAINER_NAME ; docker rm -v $CONTAINER_NAME; exit 1" EXIT INT TERM
wait_for_postgres "$CONTAINER_NAME" "$standalone_ip" 5432
# Run the test binary.
DATA_SOURCE_NAME="postgresql://postgres:$POSTGRES_PASSWORD@$standalone_ip:5432/?sslmode=disable" $test_binary || exit $?
# Extract a raw metric list.
DATA_SOURCE_NAME="postgresql://postgres:$POSTGRES_PASSWORD@$standalone_ip:5432/?sslmode=disable" $postgres_exporter \
--log.level=debug --web.listen-address=:$exporter_port &
exporter_pid=$!
# shellcheck disable=SC2064
trap "docker logs $CONTAINER_NAME ; docker kill $CONTAINER_NAME ; docker rm -v $CONTAINER_NAME; kill $exporter_pid; exit 1" EXIT INT TERM
wait_for_exporter
# Dump the metrics to a file.
if ! wget -q -O - http://localhost:$exporter_port/metrics 1> "$METRICS_DIR/.metrics.single.$version.prom" ; then
echo "Failed on postgres $version (standalone $DOCKER_IMAGE)" 1>&2
kill $exporter_pid
exit 1
fi
# HACK test: check pg_up is a 1 - TODO: expand integration tests to include metric consumption
if ! grep 'pg_up.* 1' $METRICS_DIR/.metrics.single.$version.prom ; then
echo "pg_up metric was not 1 despite exporter and database being up"
kill $exporter_pid
exit 1
fi
kill $exporter_pid
docker kill "$CONTAINER_NAME"
docker rm -v "$CONTAINER_NAME"
trap - EXIT INT TERM
echo "#######################"
echo "Replicated Postgres $version"
echo "#######################"
old_pwd=$(pwd)
cd docker-postgres-replication || exit 1
if ! VERSION="$version" p2 -t Dockerfile.p2 -o Dockerfile ; then
echo "Templating failed" 1>&2
exit 1
fi
trap "docker-compose logs; docker-compose down ; docker-compose rm -v; exit 1" EXIT INT TERM
local compose_cmd="POSTGRES_PASSWORD=$POSTGRES_PASSWORD docker-compose up -d --force-recreate --build"
echo "Compose Cmd: $compose_cmd"
eval "$compose_cmd"
master_container=$(docker-compose ps -q pg-master)
slave_container=$(docker-compose ps -q pg-slave)
master_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$master_container")
slave_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$slave_container")
echo "Got master IP: $master_ip"
wait_for_postgres "$master_container" "$master_ip" 5432
wait_for_postgres "$slave_container" "$slave_ip" 5432
DATA_SOURCE_NAME="postgresql://postgres:$POSTGRES_PASSWORD@$master_ip:5432/?sslmode=disable" $test_binary || exit $?
DATA_SOURCE_NAME="postgresql://postgres:$POSTGRES_PASSWORD@$master_ip:5432/?sslmode=disable" $postgres_exporter \
--log.level=debug --web.listen-address=:$exporter_port &
exporter_pid=$!
# shellcheck disable=SC2064
trap "docker-compose logs; docker-compose down ; docker-compose rm -v ; kill $exporter_pid; exit 1" EXIT INT TERM
wait_for_exporter
if ! wget -q -O - http://localhost:$exporter_port/metrics 1> "$METRICS_DIR/.metrics.replicated.$version.prom" ; then
echo "Failed on postgres $version (replicated $DOCKER_IMAGE)" 1>&2
exit 1
fi
kill $exporter_pid
docker-compose down
docker-compose rm -v
trap - EXIT INT TERM
cd "$old_pwd" || exit 1
}
# Start pulling the docker images in advance
for version in "${VERSIONS[@]}"; do
docker pull "postgres:$version" > /dev/null &
done
for version in "${VERSIONS[@]}"; do
echo "Testing postgres version $version"
smoketest_postgres "$version"
done
|