Gentoo Archives: gentoo-commits

From: Anna Vyalkova <cyber+gentoo@×××××.in>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/proj/guru:dev commit in: eclass/
Date: Sat, 05 Nov 2022 14:41:48
Message-Id: 1667659291.f0252164166f2b5005476664dd8c40f75afd9cba.cybertailor@gentoo
1 commit: f0252164166f2b5005476664dd8c40f75afd9cba
2 Author: Anna (cybertailor) Vyalkova <cyber+gentoo <AT> sysrq <DOT> in>
3 AuthorDate: Fri Nov 4 06:25:56 2022 +0000
4 Commit: Anna Vyalkova <cyber+gentoo <AT> sysrq <DOT> in>
5 CommitDate: Sat Nov 5 14:41:31 2022 +0000
6 URL: https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=f0252164
7
8 databases.eclass: new eclass for running databases
9
10 Signed-off-by: Anna (cybertailor) Vyalkova <cyber+gentoo <AT> sysrq.in>
11
12 eclass/databases.eclass | 480 ++++++++++++++++++++++++++++++++++++++++++++++++
13 1 file changed, 480 insertions(+)
14
15 diff --git a/eclass/databases.eclass b/eclass/databases.eclass
16 new file mode 100644
17 index 000000000..fbf653435
18 --- /dev/null
19 +++ b/eclass/databases.eclass
20 @@ -0,0 +1,480 @@
21 +# Copyright 2022 Gentoo Authors
22 +# Distributed under the terms of the GNU General Public License v2
23 +
24 +# @ECLASS: databases.eclass
25 +# @MAINTAINER:
26 +# Anna <cyber+gentoo@×××××.in>
27 +# @AUTHOR:
28 +# Anna <cyber+gentoo@×××××.in>
29 +# @SUPPORTED_EAPIS: 8
30 +# @BLURB: eclass to test packages against databases
31 +# @DESCRIPTION:
32 +# A utility eclass providing functions for running databases.
33 +#
34 +# This eclass does not set any metadata variables nor export any phase, so it
35 +# can be inherited safely.
36 +#
37 +# @SUBSECTION Supported databases
38 +#
39 +# - memcached (via "ememcached" helper)
40 +#
41 +# - MongoDB (via "emongod" helper)
42 +#
43 +# - MySQL/MariaDB/ (via "emysql" helper)
44 +#
45 +# - PostgreSQL (via "epostgres" helper)
46 +#
47 +# - Redis (via "eredis" helper)
48 +#
49 +# @SUBSECTION Helper usage
50 +#
51 +# --die [msg...]
52 +#
53 +# Prints the path to the server's log file to the console and aborts the
54 +# current merge process with the given message.
55 +#
56 +# --get-dbpath
57 +#
58 +# Returns the directory where the server stores database files.
59 +#
60 +# --get-depend
61 +#
62 +# Returns a dependency string (to be included in BDEPEND).
63 +#
64 +# --get-logfile
65 +#
66 +# Returns the path to the server's log file.
67 +#
68 +# --get-pidfile
69 +#
70 +# Returns the path to the server's PID file.
71 +#
72 +# --get-sockdir
73 +#
74 +# Returns the directory where the server's sockets are located.
75 +#
76 +# --get-sockfile
77 +#
78 +# Returns the path to the server's socket file.
79 +#
80 +# --start
81 +#
82 +# Starts the server on the default port.
83 +#
84 +# --start <port>
85 +#
86 +# Starts the server on the given port.
87 +#
88 +# --stop
89 +#
90 +# Stops the server.
91 +#
92 +# @EXAMPLE:
93 +#
94 +# @CODE
95 +# EAPI=8
96 +#
97 +# ...
98 +#
99 +# inherit databases distutils-r1
100 +#
101 +# ...
102 +#
103 +# BDEPEND="$(eredis --get-depend)"
104 +#
105 +# distutils_enable_tests pytest
106 +#
107 +# src_test() {
108 +# eredis --start 16739
109 +# distutils-r1_src_test
110 +# eredis --stop
111 +# }
112 +# @CODE
113 +
114 +case ${EAPI} in
115 + 8) ;;
116 + *) die "${ECLASS}: EAPI ${EAPI} unsupported."
117 +esac
118 +
119 +if [[ ! ${_DATABASES_ECLASS} ]]; then
120 +_DATABASES_ECLASS=1
121 +
122 +# ==============================================================================
123 +# GENERIC FUNCTIONS
124 +# ==============================================================================
125 +
126 +# @FUNCTION: _databases_gen_depend
127 +# @USAGE: <funcname>
128 +# @INTERNAL
129 +# @DESCRIPTION:
130 +# Get a dependency string for the given helper function.
131 +_databases_gen_depend() {
132 + local srvname=${1:1}
133 + case ${srvname} in
134 + memcached)
135 + echo "net-misc/memcached"
136 + ;;
137 + mongod)
138 + echo "dev-db/mongodb"
139 + ;;
140 + mysql)
141 + echo "virtual/mysql[server]"
142 + ;;
143 + postgres)
144 + echo "dev-db/postgresql[server]"
145 + ;;
146 + redis)
147 + echo "dev-db/redis"
148 + ;;
149 + *)
150 + die "${ECLASS}: unknown database: ${srvname}"
151 + esac
152 +}
153 +
154 +# @FUNCTION: _databases_die
155 +# @USAGE: <funcname> [msg]
156 +# @INTERNAL
157 +# @DESCRIPTION:
158 +# Print the given message and the path to the server's log file to the console
159 +# and die.
160 +#
161 +# This function supports being called via "nonfatal".
162 +_databases_die() {
163 + local funcname=${1?}
164 + shift
165 +
166 + eerror "See the server log for details:"
167 + eerror " $(${funcname} --get-logfile)"
168 + die -n "${@}"
169 +}
170 +
171 +# @FUNCTION: _databases_stop_service
172 +# @USAGE: <funcname>
173 +# @INTERNAL
174 +# @DESCRIPTION:
175 +# Default function to stop servers. Reads PID from a file and sends the TERM
176 +# signal.
177 +_databases_stop_service() {
178 + debug-print-function "${FUNCNAME}" "${@}"
179 +
180 + local funcname=${1?}
181 + local srvname=${funcname:1}
182 + local pidfile="$(${funcname} --get-pidfile)"
183 +
184 + ebegin "Stopping ${srvname}"
185 + kill "$(<"${pidfile}")"
186 + eend $? || ${funcname} --die "Stopping ${srvname} failed"
187 +}
188 +
189 +# @FUNCTION: _databases_dispatch
190 +# @USAGE: <funcname> <cmd> [args...]
191 +# @INTERNAL
192 +# @DESCRIPTION:
193 +# Process the given command with its options.
194 +#
195 +# If "--start" command is used, `_${funcname}_start` function must be defined.
196 +# Note that directories will be created automatically.
197 +#
198 +# If `_${funcname}_stop` function is not declared, the internal
199 +# `_databases_stop_service` function will be used instead.
200 +#
201 +# No `--get` function can be overloaded.
202 +_databases_dispatch() {
203 + local funcname=${1?}
204 + local cmd=${2?}
205 + shift; shift
206 +
207 + case ${cmd} in
208 + --die)
209 + _databases_die ${funcname} "${@}"
210 + ;;
211 + --get-depend)
212 + _databases_gen_depend ${funcname}
213 + ;;
214 + --get-dbpath)
215 + echo "${T}"/${funcname}/db/
216 + ;;
217 + --get-logfile)
218 + echo "${T}"/${funcname}/${funcname}.log
219 + ;;
220 + --get-pidfile)
221 + echo "${T}"/${funcname}/${funcname}.pid
222 + ;;
223 + --get-sockdir)
224 + echo "${T}"/${funcname}/
225 + ;;
226 + --get-sockfile)
227 + echo "${T}"/${funcname}/${funcname}.sock
228 + ;;
229 + --start)
230 + local port=${1}
231 + local start_fn=( _${funcname}_start ${port} )
232 + if ! declare -f "${start_fn[0]}" >/dev/null; then
233 + die "${ECLASS}: function not declared: ${start_fn[0]}"
234 + fi
235 +
236 + mkdir -p "${T}"/${funcname}/db/ || die "Creating database directory failed"
237 + "${start_fn[@]}"
238 + ;;
239 + --stop)
240 + local stop_fn=( _${funcname}_stop )
241 + if ! declare -f "${stop_fn[0]}" >/dev/null; then
242 + # fall back to the default implementation
243 + stop_fn=( _databases_stop_service ${funcname} )
244 + fi
245 +
246 + "${stop_fn[@]}"
247 + ;;
248 + *) die "${funcname}: invalid command: ${cmd}" ;;
249 + esac
250 +}
251 +
252 +# ==============================================================================
253 +# MEMCACHED
254 +# ==============================================================================
255 +
256 +# @FUNCTION: _ememcached_start
257 +# @USAGE: [port]
258 +# @INTERNAL
259 +# @DESCRIPTION:
260 +# Start memcached server.
261 +_ememcached_start() {
262 + debug-print-function "${FUNCNAME}" "${@}"
263 +
264 + local port=${1:-11211}
265 +
266 + local myargs=(
267 + --daemon
268 + --port=${port}
269 + --user=nobody
270 + --listen=127.0.0.1
271 + --pidfile=$(ememcached --get-pidfile)
272 + )
273 +
274 + ebegin "Spawning memcached"
275 + memcached "${myargs[@]}" &>> $(ememcached --get-logfile)
276 + eend $? || ememcached --die "Spawning memcached failed"
277 +}
278 +
279 +# @FUNCTION: ememcached
280 +# @USAGE: <cmd> [args...]
281 +# @DESCRIPTION:
282 +# Manage memcached server on the given port (default: 11211).
283 +ememcached() {
284 + _databases_dispatch "${FUNCNAME}" "${@}"
285 +}
286 +
287 +# ==============================================================================
288 +# MONGODB
289 +# ==============================================================================
290 +
291 +# @FUNCTION: _emongod_start
292 +# @USAGE: [port]
293 +# @INTERNAL
294 +# @DESCRIPTION:
295 +# Start MongoDB server.
296 +_emongod_start() {
297 + debug-print-function "${FUNCNAME}" "${@}"
298 +
299 + local port=${1:-27017}
300 + local logfile=$(emongod --get-logfile)
301 +
302 + local myargs=(
303 + --dbpath="$(emongod --get-dbpath)"
304 + --nojournal
305 + --bind-ip=127.0.0.1
306 + --port=${port}
307 + --unixSocketPrefix="$(emongod --get-sockdir)"
308 + --logpath="${logfile}"
309 + --fork
310 + )
311 +
312 + ebegin "Spawning mongodb"
313 + LC_ALL=C mongod "${myargs[@]}" &>> "${logfile}"
314 + eend $? || emongod --die "Spawning mongod failed"
315 +}
316 +
317 +# @FUNCTION: _emongod_stop
318 +# @INTERNAL
319 +# @DESCRIPTION:
320 +# Stop MongoDB server.
321 +_emongod_stop() {
322 + debug-print-function "${FUNCNAME}" "${@}"
323 +
324 + local myargs=(
325 + --dbpath="$(emongod --get-dbpath)"
326 + --shutdown
327 + )
328 +
329 + ebegin "Stopping mongodb"
330 + mongod "${myargs[@]}" &>> "${logfile}"
331 + eend $? || emongod --die "Stopping mongod failed"
332 +}
333 +
334 +# @FUNCTION: emongod
335 +# @USAGE: <cmd> [args...]
336 +# @DESCRIPTION:
337 +# Manage MongoDB server on the given port (default: 27017).
338 +emongod() {
339 + _databases_dispatch "${FUNCNAME}" "${@}"
340 +}
341 +
342 +# ==============================================================================
343 +# MYSQL
344 +# ==============================================================================
345 +
346 +# @FUNCTION: _emysql_start
347 +# @USAGE: [port]
348 +# @INTERNAL
349 +# @DESCRIPTION:
350 +# Create a new MySQL database and start MySQL server.
351 +_emysql_start() {
352 + debug-print-function "${FUNCNAME}" "${@}"
353 +
354 + local port=${1:-3306}
355 + local dbpath=$(emysql --get-dbpath)
356 + local logfile=$(emysql --get-logfile)
357 + local sockfile=$(emysql --get-sockfile)
358 +
359 + local myinstallargs=(
360 + --no-defaults
361 + --auth-root-authentication-method=normal
362 + --basedir="${BROOT}/usr"
363 + --datadir="${dbpath}"
364 + )
365 +
366 + ebegin "Initializing mysql database"
367 + mysql_install_db "${myinstallargs[@]}" &>> "${logfile}"
368 + eend $? || emysql --die "Initializing mysql database failed"
369 +
370 + local myargs=(
371 + --no-defaults
372 + --character-set-server=utf8
373 + --pid-file="$(emysql --get-pidfile)"
374 + --socket="${sockfile}"
375 + --bind-address=127.0.0.1
376 + --port=${port}
377 + --datadir="${dbpath}"
378 + --general-log-file="${logfile}"
379 + --log-error="${logfile}"
380 + )
381 +
382 + einfo "Spawning mysql"
383 + mysqld "${myargs[@]}" &>> "${logfile}" &
384 +
385 + einfo "Waiting for mysqld to accept connections"
386 + local timeout=30
387 + while ! mysqladmin ping --socket="${sockfile}" --silent; do
388 + sleep 1
389 + let timeout-=1
390 + [[ ${timeout} -eq 0 ]] && emysql --die "Timed out"
391 + done
392 +}
393 +
394 +# @FUNCTION: emysql
395 +# @USAGE: <cmd> [args...]
396 +# @DESCRIPTION:
397 +# Manage MySQL server on the given port (default: 3306).
398 +emysql() {
399 + _databases_dispatch "${FUNCNAME}" "${@}"
400 +}
401 +
402 +# ==============================================================================
403 +# POSTGRESQL
404 +# ==============================================================================
405 +
406 +# @FUNCTION: _epostgres_start
407 +# @USAGE: [port]
408 +# @INTERNAL
409 +# @DESCRIPTION:
410 +# Create a new PostgreSQL database and start PostgreSQL server.
411 +_epostgres_start() {
412 + debug-print-function "${FUNCNAME}" "${@}"
413 +
414 + local port=${1:-5432}
415 + local dbpath=$(epostgres --get-dbpath)
416 + local logfile=$(epostgres --get-logfile)
417 +
418 + local myinstallargs=(
419 + --pgdata="${dbpath}"
420 + --user=postgres
421 + )
422 +
423 + ebegin "Initializing postgresql database"
424 + initdb "${myinstallargs[@]}" &>> "${logfile}"
425 + eend $? || epostgres --die "Initializing postgresql database failed"
426 +
427 + local myargs=(
428 + --pgdata="${dbpath}"
429 + --log="${logfile}"
430 + --options="-h '127.0.0.1' -p ${port} -k '$(epostgres --get-sockdir)'"
431 + --wait
432 + )
433 +
434 + ebegin "Spawning postgresql"
435 + pg_ctl "${myargs[@]}" start &>> "${logfile}"
436 + eend $? || epostgres --die "Spawning postgresql failed"
437 +}
438 +
439 +# @FUNCTION: _epostgres_stop
440 +# @INTERNAL
441 +# @DESCRIPTION:
442 +# Stop PosgreSQL server.
443 +_epostgres_stop() {
444 + debug-print-function "${FUNCNAME}" "${@}"
445 +
446 + local myargs=(
447 + --pgdata="$(epostgres --get-dbpath)"
448 + --wait
449 + )
450 +
451 + ebegin "Stopping postgresql"
452 + pg_ctl "${myargs[@]}" stop &>> "$(epostgres --get-logfile)"
453 + eend $? || epostgres --die "Stopping postgresql failed"
454 +}
455 +
456 +# @FUNCTION: epostgres
457 +# @USAGE: <cmd> [args...]
458 +# @DESCRIPTION:
459 +# Manage PostgreSQL server on the given port (default: 5432).
460 +epostgres() {
461 + _databases_dispatch "${FUNCNAME}" "${@}"
462 +}
463 +
464 +# ==============================================================================
465 +# REDIS
466 +# ==============================================================================
467 +
468 +# @FUNCTION: _eredis_start
469 +# @USAGE: [args...]
470 +# @INTERNAL
471 +# @DESCRIPTION:
472 +# Start Redis server.
473 +_eredis_start() {
474 + debug-print-function "${FUNCNAME}" "${@}"
475 +
476 + local port=${1:-6379}
477 + local logfile="$(eredis --get-logfile)"
478 +
479 + ebegin "Spawning redis"
480 + redis-server - <<- EOF &>> "${logfile}"
481 + daemonize yes
482 + pidfile "$(eredis --get-pidfile)"
483 + port ${port}
484 + bind 127.0.0.1
485 + unixsocket "$(eredis --get-sockfile)"
486 + dir "$(eredis --get-dbpath)"
487 + logfile "${logfile}"
488 + EOF
489 + eend $? || eredis --die "Spawning redis failed"
490 +}
491 +
492 +# @FUNCTION: eredis
493 +# @USAGE: <cmd> [args...]
494 +# @DESCRIPTION:
495 +# Manage Redis server on the given port (default: 6379).
496 +eredis() {
497 + _databases_dispatch "${FUNCNAME}" "${@}"
498 +}
499 +
500 +fi