commit:     f0252164166f2b5005476664dd8c40f75afd9cba
Author:     Anna (cybertailor) Vyalkova <cyber+gentoo <AT> sysrq <DOT> in>
AuthorDate: Fri Nov  4 06:25:56 2022 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Sat Nov  5 14:41:31 2022 +0000
URL:        https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=f0252164

databases.eclass: new eclass for running databases

Signed-off-by: Anna (cybertailor) Vyalkova <cyber+gentoo <AT> sysrq.in>

 eclass/databases.eclass | 480 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 480 insertions(+)

diff --git a/eclass/databases.eclass b/eclass/databases.eclass
new file mode 100644
index 000000000..fbf653435
--- /dev/null
+++ b/eclass/databases.eclass
@@ -0,0 +1,480 @@
+# Copyright 2022 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: databases.eclass
+# @MAINTAINER:
+# Anna <[email protected]>
+# @AUTHOR:
+# Anna <[email protected]>
+# @SUPPORTED_EAPIS: 8
+# @BLURB: eclass to test packages against databases
+# @DESCRIPTION:
+# A utility eclass providing functions for running databases.
+#
+# This eclass does not set any metadata variables nor export any phase, so it
+# can be inherited safely.
+#
+# @SUBSECTION Supported databases
+#
+# - memcached (via "ememcached" helper)
+#
+# - MongoDB (via "emongod" helper)
+#
+# - MySQL/MariaDB/ (via "emysql" helper)
+#
+# - PostgreSQL (via "epostgres" helper)
+#
+# - Redis (via "eredis" helper)
+#
+# @SUBSECTION Helper usage
+#
+# --die [msg...]
+#
+#      Prints the path to the server's log file to the console and aborts the
+#      current merge process with the given message.
+#
+# --get-dbpath
+#
+#      Returns the directory where the server stores database files.
+#
+# --get-depend
+#
+#      Returns a dependency string (to be included in BDEPEND).
+#
+# --get-logfile
+#
+#      Returns the path to the server's log file.
+#
+# --get-pidfile
+#
+#      Returns the path to the server's PID file.
+#
+# --get-sockdir
+#
+#      Returns the directory where the server's sockets are located.
+#
+# --get-sockfile
+#
+#      Returns the path to the server's socket file.
+#
+# --start
+#
+#      Starts the server on the default port.
+#
+# --start <port>
+#
+#      Starts the server on the given port.
+#
+# --stop
+#
+#      Stops the server.
+#
+# @EXAMPLE:
+#
+# @CODE
+# EAPI=8
+#
+# ...
+#
+# inherit databases distutils-r1
+#
+# ...
+#
+# BDEPEND="$(eredis --get-depend)"
+#
+# distutils_enable_tests pytest
+#
+# src_test() {
+#      eredis --start 16739
+#      distutils-r1_src_test
+#      eredis --stop
+# }
+# @CODE
+
+case ${EAPI} in
+       8) ;;
+       *) die "${ECLASS}: EAPI ${EAPI} unsupported."
+esac
+
+if [[ ! ${_DATABASES_ECLASS} ]]; then
+_DATABASES_ECLASS=1
+
+# 
==============================================================================
+# GENERIC FUNCTIONS
+# 
==============================================================================
+
+# @FUNCTION: _databases_gen_depend
+# @USAGE: <funcname>
+# @INTERNAL
+# @DESCRIPTION:
+# Get a dependency string for the given helper function.
+_databases_gen_depend() {
+       local srvname=${1:1}
+       case ${srvname} in
+               memcached)
+                       echo "net-misc/memcached"
+                       ;;
+               mongod)
+                       echo "dev-db/mongodb"
+                       ;;
+               mysql)
+                       echo "virtual/mysql[server]"
+                       ;;
+               postgres)
+                       echo "dev-db/postgresql[server]"
+                       ;;
+               redis)
+                       echo "dev-db/redis"
+                       ;;
+               *)
+                       die "${ECLASS}: unknown database: ${srvname}"
+       esac
+}
+
+# @FUNCTION: _databases_die
+# @USAGE: <funcname> [msg]
+# @INTERNAL
+# @DESCRIPTION:
+# Print the given message and the path to the server's log file to the console
+# and die.
+#
+# This function supports being called via "nonfatal".
+_databases_die() {
+       local funcname=${1?}
+       shift
+
+       eerror "See the server log for details:"
+       eerror "        $(${funcname} --get-logfile)"
+       die -n "${@}"
+}
+
+# @FUNCTION: _databases_stop_service
+# @USAGE: <funcname>
+# @INTERNAL
+# @DESCRIPTION:
+# Default function to stop servers.  Reads PID from a file and sends the TERM
+# signal.
+_databases_stop_service() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local funcname=${1?}
+       local srvname=${funcname:1}
+       local pidfile="$(${funcname} --get-pidfile)"
+
+       ebegin "Stopping ${srvname}"
+       kill "$(<"${pidfile}")"
+       eend $? || ${funcname} --die "Stopping ${srvname} failed"
+}
+
+# @FUNCTION: _databases_dispatch
+# @USAGE: <funcname> <cmd> [args...]
+# @INTERNAL
+# @DESCRIPTION:
+# Process the given command with its options.
+#
+# If "--start" command is used, `_${funcname}_start` function must be defined.
+# Note that directories will be created automatically.
+#
+# If `_${funcname}_stop` function is not declared, the internal
+# `_databases_stop_service` function will be used instead.
+#
+# No `--get` function can be overloaded.
+_databases_dispatch() {
+       local funcname=${1?}
+       local cmd=${2?}
+       shift; shift
+
+       case ${cmd} in
+               --die)
+                       _databases_die ${funcname} "${@}"
+                       ;;
+               --get-depend)
+                       _databases_gen_depend ${funcname}
+                       ;;
+               --get-dbpath)
+                       echo "${T}"/${funcname}/db/
+                       ;;
+               --get-logfile)
+                       echo "${T}"/${funcname}/${funcname}.log
+                       ;;
+               --get-pidfile)
+                       echo "${T}"/${funcname}/${funcname}.pid
+                       ;;
+               --get-sockdir)
+                       echo "${T}"/${funcname}/
+                       ;;
+               --get-sockfile)
+                       echo "${T}"/${funcname}/${funcname}.sock
+                       ;;
+               --start)
+                       local port=${1}
+                       local start_fn=( _${funcname}_start ${port} )
+                       if ! declare -f "${start_fn[0]}" >/dev/null; then
+                               die "${ECLASS}: function not declared: 
${start_fn[0]}"
+                       fi
+
+                       mkdir -p "${T}"/${funcname}/db/ || die "Creating 
database directory failed"
+                       "${start_fn[@]}"
+                       ;;
+               --stop)
+                       local stop_fn=( _${funcname}_stop )
+                       if ! declare -f "${stop_fn[0]}" >/dev/null; then
+                               # fall back to the default implementation
+                               stop_fn=( _databases_stop_service ${funcname} )
+                       fi
+
+                       "${stop_fn[@]}"
+                       ;;
+               *) die "${funcname}: invalid command: ${cmd}" ;;
+       esac
+}
+
+# 
==============================================================================
+# MEMCACHED
+# 
==============================================================================
+
+# @FUNCTION: _ememcached_start
+# @USAGE: [port]
+# @INTERNAL
+# @DESCRIPTION:
+# Start memcached server.
+_ememcached_start() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local port=${1:-11211}
+
+       local myargs=(
+               --daemon
+               --port=${port}
+               --user=nobody
+               --listen=127.0.0.1
+               --pidfile=$(ememcached --get-pidfile)
+       )
+
+       ebegin "Spawning memcached"
+       memcached "${myargs[@]}" &>> $(ememcached --get-logfile)
+       eend $? || ememcached --die "Spawning memcached failed"
+}
+
+# @FUNCTION: ememcached
+# @USAGE: <cmd> [args...]
+# @DESCRIPTION:
+# Manage memcached server on the given port (default: 11211).
+ememcached() {
+       _databases_dispatch "${FUNCNAME}" "${@}"
+}
+
+# 
==============================================================================
+# MONGODB
+# 
==============================================================================
+
+# @FUNCTION: _emongod_start
+# @USAGE: [port]
+# @INTERNAL
+# @DESCRIPTION:
+# Start MongoDB server.
+_emongod_start() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local port=${1:-27017}
+       local logfile=$(emongod --get-logfile)
+
+       local myargs=(
+               --dbpath="$(emongod --get-dbpath)"
+               --nojournal
+               --bind-ip=127.0.0.1
+               --port=${port}
+               --unixSocketPrefix="$(emongod --get-sockdir)"
+               --logpath="${logfile}"
+               --fork
+       )
+
+       ebegin "Spawning mongodb"
+       LC_ALL=C mongod "${myargs[@]}" &>> "${logfile}"
+       eend $? || emongod --die "Spawning mongod failed"
+}
+
+# @FUNCTION: _emongod_stop
+# @INTERNAL
+# @DESCRIPTION:
+# Stop MongoDB server.
+_emongod_stop() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local myargs=(
+               --dbpath="$(emongod --get-dbpath)"
+               --shutdown
+       )
+
+       ebegin "Stopping mongodb"
+       mongod "${myargs[@]}" &>> "${logfile}"
+       eend $? || emongod --die "Stopping mongod failed"
+}
+
+# @FUNCTION: emongod
+# @USAGE: <cmd> [args...]
+# @DESCRIPTION:
+# Manage MongoDB server on the given port (default: 27017).
+emongod() {
+       _databases_dispatch "${FUNCNAME}" "${@}"
+}
+
+# 
==============================================================================
+# MYSQL
+# 
==============================================================================
+
+# @FUNCTION: _emysql_start
+# @USAGE: [port]
+# @INTERNAL
+# @DESCRIPTION:
+# Create a new MySQL database and start MySQL server.
+_emysql_start() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local port=${1:-3306}
+       local dbpath=$(emysql --get-dbpath)
+       local logfile=$(emysql --get-logfile)
+       local sockfile=$(emysql --get-sockfile)
+
+       local myinstallargs=(
+               --no-defaults
+               --auth-root-authentication-method=normal
+               --basedir="${BROOT}/usr"
+               --datadir="${dbpath}"
+       )
+
+       ebegin "Initializing mysql database"
+       mysql_install_db "${myinstallargs[@]}" &>> "${logfile}"
+       eend $? || emysql --die "Initializing mysql database failed"
+
+       local myargs=(
+               --no-defaults
+               --character-set-server=utf8
+               --pid-file="$(emysql --get-pidfile)"
+               --socket="${sockfile}"
+               --bind-address=127.0.0.1
+               --port=${port}
+               --datadir="${dbpath}"
+               --general-log-file="${logfile}"
+               --log-error="${logfile}"
+       )
+
+       einfo "Spawning mysql"
+       mysqld "${myargs[@]}" &>> "${logfile}" &
+
+       einfo "Waiting for mysqld to accept connections"
+       local timeout=30
+       while ! mysqladmin ping --socket="${sockfile}" --silent; do
+               sleep 1
+               let timeout-=1
+               [[ ${timeout} -eq 0 ]] && emysql --die "Timed out"
+       done
+}
+
+# @FUNCTION: emysql
+# @USAGE: <cmd> [args...]
+# @DESCRIPTION:
+# Manage MySQL server on the given port (default: 3306).
+emysql() {
+       _databases_dispatch "${FUNCNAME}" "${@}"
+}
+
+# 
==============================================================================
+# POSTGRESQL
+# 
==============================================================================
+
+# @FUNCTION: _epostgres_start
+# @USAGE: [port]
+# @INTERNAL
+# @DESCRIPTION:
+# Create a new PostgreSQL database and start PostgreSQL server.
+_epostgres_start() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local port=${1:-5432}
+       local dbpath=$(epostgres --get-dbpath)
+       local logfile=$(epostgres --get-logfile)
+
+       local myinstallargs=(
+               --pgdata="${dbpath}"
+               --user=postgres
+       )
+
+       ebegin "Initializing postgresql database"
+       initdb "${myinstallargs[@]}" &>> "${logfile}"
+       eend $? || epostgres --die "Initializing postgresql database failed"
+
+       local myargs=(
+               --pgdata="${dbpath}"
+               --log="${logfile}"
+               --options="-h '127.0.0.1' -p ${port} -k '$(epostgres 
--get-sockdir)'"
+               --wait
+       )
+
+       ebegin "Spawning postgresql"
+       pg_ctl "${myargs[@]}" start &>> "${logfile}"
+       eend $? || epostgres --die "Spawning postgresql failed"
+}
+
+# @FUNCTION: _epostgres_stop
+# @INTERNAL
+# @DESCRIPTION:
+# Stop PosgreSQL server.
+_epostgres_stop() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local myargs=(
+               --pgdata="$(epostgres --get-dbpath)"
+               --wait
+       )
+
+       ebegin "Stopping postgresql"
+       pg_ctl "${myargs[@]}" stop &>> "$(epostgres --get-logfile)"
+       eend $? || epostgres --die "Stopping postgresql failed"
+}
+
+# @FUNCTION: epostgres
+# @USAGE: <cmd> [args...]
+# @DESCRIPTION:
+# Manage PostgreSQL server on the given port (default: 5432).
+epostgres() {
+       _databases_dispatch "${FUNCNAME}" "${@}"
+}
+
+# 
==============================================================================
+# REDIS
+# 
==============================================================================
+
+# @FUNCTION: _eredis_start
+# @USAGE: [args...]
+# @INTERNAL
+# @DESCRIPTION:
+# Start Redis server.
+_eredis_start() {
+       debug-print-function "${FUNCNAME}" "${@}"
+
+       local port=${1:-6379}
+       local logfile="$(eredis --get-logfile)"
+
+       ebegin "Spawning redis"
+       redis-server - <<- EOF &>> "${logfile}"
+               daemonize yes
+               pidfile "$(eredis --get-pidfile)"
+               port ${port}
+               bind 127.0.0.1
+               unixsocket "$(eredis --get-sockfile)"
+               dir "$(eredis --get-dbpath)"
+               logfile "${logfile}"
+       EOF
+       eend $? || eredis --die "Spawning redis failed"
+}
+
+# @FUNCTION: eredis
+# @USAGE: <cmd> [args...]
+# @DESCRIPTION:
+# Manage Redis server on the given port (default: 6379).
+eredis() {
+       _databases_dispatch "${FUNCNAME}" "${@}"
+}
+
+fi

Reply via email to