diff options
author | Anna (cybertailor) Vyalkova <cyber+gentoo@sysrq.in> | 2022-11-04 11:25:56 +0500 |
---|---|---|
committer | Anna (cybertailor) Vyalkova <cyber+gentoo@sysrq.in> | 2022-11-05 19:41:31 +0500 |
commit | f0252164166f2b5005476664dd8c40f75afd9cba (patch) | |
tree | 4a1fc434991284732d0efd5e41b16c4b31a6d322 /eclass | |
parent | x11-misc/sxcs: fix LDFLAGS issue (diff) | |
download | guru-f0252164166f2b5005476664dd8c40f75afd9cba.tar.gz guru-f0252164166f2b5005476664dd8c40f75afd9cba.tar.bz2 guru-f0252164166f2b5005476664dd8c40f75afd9cba.zip |
databases.eclass: new eclass for running databases
Signed-off-by: Anna (cybertailor) Vyalkova <cyber+gentoo@sysrq.in>
Diffstat (limited to 'eclass')
-rw-r--r-- | eclass/databases.eclass | 480 |
1 files changed, 480 insertions, 0 deletions
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 <cyber+gentoo@sysrq.in> +# @AUTHOR: +# Anna <cyber+gentoo@sysrq.in> +# @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 |