blob: 8057d525442e4c98ae9218a33f27eedc7c7fda2a (
plain)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
#!/bin/bash
# Create a throw-away PostgreSQL environment for running regression tests.
# This does not interfere with existing clusters.
#
# (C) 2005-2012 Martin Pitt <mpitt@debian.org>
# (C) 2012-2020 Christoph Berg <myon@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
set -e # no -u here as that breaks PGCONF_OPTS[@]
# wrap ourselves in newpid if requested
if [ "$PG_VIRTUALENV_NEWPID" ]; then
unset PG_VIRTUALENV_NEWPID
exec newpid $0 "$@"
fi
# wrap ourselves in unshare if requested
if [ "$PG_VIRTUALENV_UNSHARE" ]; then
export _PG_VIRTUALENV_UNSHARE="$PG_VIRTUALENV_UNSHARE"
unset PG_VIRTUALENV_UNSHARE
exec unshare $_PG_VIRTUALENV_UNSHARE -- $0 "$@"
fi
if [ "$_PG_VIRTUALENV_UNSHARE" ]; then
unset _PG_VIRTUALENV_UNSHARE
# start localhost interface
if [ -x /bin/ip ]; then
ip link set dev lo up || true
else
ifconfig lo up || true
fi
fi
disable_fakeroot ()
{
case ${LD_PRELOAD:-} in
*fakeroot*) LD_PRELOAD=$(echo "$LD_PRELOAD" | sed -e 's/[^ ]*fakeroot[^ ]*//g') ;;
esac
}
help ()
{
echo "pg_virtualenv: Create throw-away PostgreSQL environment for regression tests"
echo "Syntax: $0 [options] [command]"
echo " -a use all installed server versions"
echo " -v 'version ...' list of PostgreSQL versions to run [default: latest]"
echo " -c 'options' extra options to pass to pg_createcluster"
echo " -i 'initdb opts' extra initdb options to pass to pg_createcluster"
echo " -o 'guc=value' postgresql.conf options to pass to pg_createcluster"
echo " -p 'package' set options to find extension files in debian/package/"
echo " -s open a shell when command fails"
echo " -t use a temporary cluster directory even as root"
exit ${1:-0}
}
# option parsing
PGBINROOT="/usr/lib/postgresql/"
#redhat# PGBINROOT="/usr/pgsql-"
PG_VERSIONS=""
PGCONF_OPTS=()
while getopts "ac:i:ho:p:stv:" opt ; do
case $opt in
a) for d in $PGBINROOT*/bin/pg_ctl; do
# prepend version so latest ends up first (i.e. on port 5432)
dir=${d%%/bin/pg_ctl}
PG_VERSIONS="${dir#$PGBINROOT} ${PG_VERSIONS:-}"
done ;;
c) CREATE_OPTS="$OPTARG" ;;
i) INITDB_OPTS="$OPTARG" ;;
h) help ;;
o) PGCONF_OPTS+=("--pgoption" "$OPTARG") ;;
p) PACKAGE="$OPTARG" ;;
s) run_shell=1 ;;
t) NONROOT=1 ;;
v) PG_VERSIONS="$OPTARG" ;;
*) help 1 ;;
esac
done
if [ -z "$PG_VERSIONS" ]; then
# use latest version
d=$(ls -v $PGBINROOT*/bin/pg_ctl 2> /dev/null | tail -1)
if [ -z "$d" ]; then
echo "Could not determine PostgreSQL version, are any PostgreSQL server packages installed?" >&2
exit 2
fi
dir=${d%%/bin/pg_ctl}
PG_VERSIONS="${dir#$PGBINROOT}"
fi
# shift away args
shift $(($OPTIND - 1))
# if no command is given, open a shell
[ "${1:-}" ] || set -- ${SHELL:-/bin/sh}
# generate a password
if [ -x /usr/bin/pwgen ]; then
export PGPASSWORD=$(pwgen 20 1)
else
export PGPASSWORD=$(dd if=/dev/urandom bs=1k count=1 2>/dev/null | md5sum - | awk '{ print $1 }')
fi
# we are not root
if [ "$(id -u)" != 0 ]; then
NONROOT=1
fi
# we aren't really root in fakeroot (but leave it enabled for commands spawned)
case ${LD_PRELOAD:-} in
*fakeroot*) NONROOT=1 ;;
esac
# non-root operation: create a temp dir where we store everything
if [ "${NONROOT:-}" ]; then
WORKDIR=$(mktemp -d -t pg_virtualenv.XXXXXX)
if [ $(id -u) = 0 ]; then
chown postgres:postgres $WORKDIR
umask 022
fi
export PG_CLUSTER_CONF_ROOT="$WORKDIR/postgresql"
export PGUSER="${USER:-${LOGNAME:-$(id -un)}}"
[ "$PGUSER" = "root" ] && PGUSER="postgres"
PGSYSCONFDIR="$WORKDIR/postgresql-common" # no export yet so pg_createcluster uses the original createcluster.conf
mkdir "$PGSYSCONFDIR" "$WORKDIR/log"
PWFILE="$PGSYSCONFDIR/pwfile"
LOGDIR="$WORKDIR/log"
echo "$PGPASSWORD" > "$PWFILE"
# stats_temp_directory in /var/run/postgresql needs root (or postgres), disable it
PGCONF_OPTS+=("--pgoption" "stats_temp_directory=")
cleanup () {
set +e
disable_fakeroot
for v in $PG_VERSIONS; do
# don't drop existing clusters named "regress"
[ -f $PG_CLUSTER_CONF_ROOT/$v/regress/.by_pg_virtualenv ] || continue
echo "Dropping cluster $v/regress ..."
pg_ctlcluster --mode immediate $v regress stop
pg_dropcluster $v regress
done
rm -rf $WORKDIR
}
trap cleanup 0 HUP INT QUIT ILL ABRT PIPE TERM
# root: keep everything in the standard locations
else
for v in $PG_VERSIONS; do
if [ -d /etc/postgresql/$v/regress ]; then
echo "Cluster $v/regress exists, refusing to overwrite" >&2
exit 2
fi
done
: ${PGSYSCONFDIR:=/etc/postgresql-common}
pg_service="$PGSYSCONFDIR/pg_service.conf"
export PGUSER="postgres"
PWFILE=$(mktemp -t pgpassword.XXXXXX)
echo "$PGPASSWORD" > "$PWFILE" # write password before chowning the file
chown postgres:postgres "$PWFILE"
cleanup () {
set +e
rm -f $PWFILE $pg_service
if [ -f $pg_service.pg_virtualenv-save.$$ ]; then
mv -f $pg_service.pg_virtualenv-save.$$ $pg_service
fi
for v in $PG_VERSIONS; do
# don't drop existing clusters named "regress"
[ -f /etc/postgresql/$v/regress/.by_pg_virtualenv ] || continue
echo "Dropping cluster $v/regress ..."
rm -f /etc/postgresql/$v/regress/.by_pg_virtualenv
pg_ctlcluster --mode immediate $v regress stop
pg_dropcluster $v regress
done
}
trap cleanup 0 HUP INT QUIT ILL ABRT PIPE TERM
if [ -f $pg_service ]; then
mv --no-clobber $pg_service $pg_service.pg_virtualenv-save.$$
fi
fi
# create postgres environments
for v in $PG_VERSIONS; do
# create temporary cluster
if [ "${PACKAGE:-}" ]; then
if ! grep -q 'extension_destdir' /usr/share/postgresql/$v/postgresql.conf.sample; then
echo "$0: This PostgreSQL $v installation does not support 'extension_destdir', skipping this version"
[ "$PG_VERSIONS" = "$v" ] && exit 0 # only one version requested
continue
fi
PKGARGS="--pgoption extension_destdir=$PWD/debian/$PACKAGE --pgoption dynamic_library_path=$PWD/debian/$PACKAGE/usr/lib/postgresql/$v/lib:/usr/lib/postgresql/$v/lib"
fi
# we chdir to / so programs don't throw "could not change directory to ..."
(
cd /
case $v in
8*|9.0|9.1|9.2) : ;;
*) NOSYNC="--nosync" ;;
esac
# disable fakeroot here because we really can't run as root
# (and still switch to postgres when using fakeroot as root user)
disable_fakeroot
pg_createcluster --quiet \
${PGPORT:+-p "$PGPORT"} \
${NONROOT:+-d "$WORKDIR/data/$v/regress"} \
${NONROOT:+-l "$WORKDIR/log/postgresql-$v-regress.log"} \
${CREATE_OPTS:-} --pgoption fsync=off ${PKGARGS:-} "${PGCONF_OPTS[@]}" \
$v regress -- \
--username="$PGUSER" --pwfile="$PWFILE" $NOSYNC ${INITDB_OPTS:-}
# in fakeroot, the username will likely default to "postgres" otherwise
echo "This is a temporary throw-away cluster" > ${PG_CLUSTER_CONF_ROOT:-/etc/postgresql}/$v/regress/.by_pg_virtualenv
# start cluster with coredumps enabled
[ $v != 8.2 ] && ENABLE_COREDUMPS="-c"
pg_ctlcluster $v regress start -- ${ENABLE_COREDUMPS:-}
)
port=$(pg_conftool -s $v regress show port)
# record cluster information in service file
cat >> $PGSYSCONFDIR/pg_service.conf <<EOF
[$v]
host=localhost
port=$port
dbname=postgres
user=$PGUSER
password=$PGPASSWORD
EOF
done
export PGSYSCONFDIR
export PGHOST="localhost"
export PGDATABASE="postgres"
case $PG_VERSIONS in
*\ *) ;; # multiple versions: do not set PGPORT because that breaks --cluster
*)
export PGPORT="$port"
export PG_CONFIG="$PGBINROOT$PG_VERSIONS/bin/pg_config"
export PGVERSION="$PG_VERSIONS"
;;
esac
# run program
"$@" || EXIT="$?"
if [ ${EXIT:-0} -gt 0 ]; then
for log in ${LOGDIR:-/var/log/postgresql}/*.log; do
echo "*** $log (last 100 lines) ***"
tail -100 $log
done
if which gdb > /dev/null; then
for v in $PG_VERSIONS; do
PGDATA=$(pg_conftool -s $v regress show data_directory)
for core in $PGDATA/core*; do
[ -f "$core" ] || continue
echo "*** $core ***"
gdb -batch -ex "bt full" /usr/lib/postgresql/$v/bin/postgres "$core"
done
done
fi
if [ "${run_shell:-}" ]; then
echo "pg_virtualenv: command exited with status $EXIT, dropping you into a shell"
${SHELL:-/bin/sh}
fi
fi
exit ${EXIT:-0}
|