aboutsummaryrefslogtreecommitdiff
blob: 24798158d31de2708475a1cde58c2ab63d77aa63 (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
# Copyright 2022-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

# @ECLASS: daemons.eclass
# @MAINTAINER:
# Anna <cyber+gentoo@sysrq.in>
# @AUTHOR:
# Anna <cyber+gentoo@sysrq.in>
# @SUPPORTED_EAPIS: 8
# @BLURB: eclass to test packages against running daemons
# @DESCRIPTION:
# A utility eclass providing functions for starting and stopping daemons with
# Pifpaf.
#
# This eclass does not set any metadata variables nor export any phase, so it
# can be inherited safely.
#
# @SUBSECTION Supported daemons
#
# - ceph
#
# - consul
#
# - httpbin
#
# - kafka
#
# - memcached
#
# - mysql
#
# - postgresql
#
# - redis
#
# - vault
#
# @EXAMPLE:
#
# @CODE
# EAPI=8
#
# ...
#
# DAEMONS_REQ_USE=(
# 	[postgresql]="xml"
# )
# inherit daemons distutils-r1
#
# ...
#
# distutils_enable_tests pytest
#
# daemons_enable postgresql test
#
# src_test() {
# 	daemons_start postgresql
# 	distutils-r1_src_test
# 	daemons_stop postgresql
# }
# @CODE

case ${EAPI} in
	8) ;;
	*) die "${ECLASS}: EAPI ${EAPI} unsupported."
esac

if [[ ! ${_DAEMONS_ECLASS} ]]; then
_DAEMONS_ECLASS=1

# @ECLASS_VARIABLE: DAEMONS_REQ_USE
# @PRE_INHERIT
# @DEFAULT_UNSET
# @DESCRIPTION:
# Bash associative array of USE flags required to be enabled on daemons,
# formed as a USE-dependency string.

# @ECLASS_VARIABLE: DAEMONS_DEPEND
# @OUTPUT_VARIABLE
# @DESCRIPTION:
# This is an eclass-generated bash associative array of dependency strings for
# daemons.
declare -Ag DAEMONS_DEPEND=()

# @FUNCTION: _daemons_set_globals
# @INTERNAL
# @DESCRIPTION:
# Set the DAEMONS_DEPEND variable.
_daemons_set_globals() {
	local -A pkgs=(
		[ceph]="sys-cluster/ceph"
		[consul]="app-admin/consul"
		[httpbin]="dev-python/httpbin"
		[kafka]="net-misc/kafka-bin"
		[memcached]="net-misc/memcached"
		[mysql]="virtual/mysql"
		[postgresql]="dev-db/postgresql"
		[redis]="dev-db/redis"
		[vault]="app-admin/vault"
	)

	local -A useflags=(
		[mysql]="server"
		[postgresql]="server"
	)

	if declare -p DAEMONS_REQ_USE &>/dev/null; then
		[[ $(declare -p DAEMONS_REQ_USE) == "declare -A"* ]] || \
			die "DAEMONS_REQ_USE must be declared as an associative array"
	fi

	local name dep usestr
	for name in "${!pkgs[@]}"; do
		dep=${pkgs[${name:?}]:?}
		usestr=${useflags[${name:?}]}
		usestr+=",${DAEMONS_REQ_USE[${name:?}]}"
		# strip leading/trailing commas
		usestr=${usestr#,}
		usestr=${usestr%,}

		[[ ${usestr?} ]] && usestr="[${usestr?}]"
		DAEMONS_DEPEND[${name:?}]="dev-util/pifpaf ${dep:?}${usestr?}"
	done

	readonly DAEMONS_DEPEND
}
_daemons_set_globals
unset -f _daemons_set_globals

# @FUNCTION: daemons_enable
# @USAGE: <daemon> <use>
# @DESCRIPTION:
# Add the daemon package to build-time dependencies under the given USE flag
# (IUSE will be set automatically).
daemons_enable() {
	debug-print-function ${FUNCNAME} "${@}"

	local daemon=${1:?}
	local useflag=${2:?}

	IUSE+=" ${useflag:?}"
	BDEPEND+=" ${useflag:?}? ( ${DAEMONS_DEPEND[${daemon:?}]:?} )"
	if [[ ${useflag:?} == "test" ]]; then
		RESTRICT+=" !test? ( test )"
	fi
}

# @FUNCTION: daemons_start
# @USAGE: <daemon> [args...]
# @DESCRIPTION:
# Start the daemon.  All arguments are passes to Pifpaf.
#
# Pifpaf will set some environment variables for you, they will be prefixed by
# uppercase daemon name.  See upstream documentation for details.
daemons_start() {
	debug-print-function ${FUNCNAME} "${@}"

	local daemon=${1:?}
	shift

	local logfile="${T?}/daemon-${daemon:?}.log"
	local tempfile="${T?}/daemon-${daemon:?}.sh"
	local myargs=(
		--env-prefix "${daemon^^}"
		--log-file "${logfile:?}"
		--verbose
	)

	ebegin "Starting ${daemon:?}"
	pifpaf "${myargs[@]}" run "${daemon:?}" "${@}" > "${tempfile:?}" && \
		source "${tempfile:?}" && \
		rm -f "${tempfile:?}"
	eend $? || die "Starting ${daemon:?} failed"
}

# @FUNCTION: daemons_stop
# @USAGE: <daemon>
# @DESCRIPTION:
# Stop a running daemon.
daemons_stop() {
	debug-print-function ${FUNCNAME} "${@}"

	local daemon=${1:?}
	local stop_fn="${daemon:?}_stop"
	declare -f "${stop_fn:?}" >/dev/null || die "${daemon:?} is not running"

	ebegin "Stopping ${daemon:?}"
	"${stop_fn:?}"
	eend $? || die "Stopping ${daemon:?} failed"
}

# @FUNCTION: daemons_death_notice
# @INTERNAL
# @DESCRIPTION:
# Creates archive with daemon logs and prints a log message with its location.
daemons_death_notice() {
	shopt -s nullglob
	local logfiles=( "${T}"/daemon-*.log )
	local logarchive="${T}/daemon-logs.tar.xz"
	shopt -u nullglob

	if [[ "${logfiles[*]}" ]]; then
		pushd "${T}" >/dev/null
		tar -acf "${logarchive}" "${logfiles[@]#${T}/}"
		popd >/dev/null
		eerror
		eerror "Please include ${logarchive} in your bug report."
		eerror
	fi
}
has daemons_death_notice ${EBUILD_DEATH_HOOKS} || EBUILD_DEATH_HOOKS+=" daemons_death_notice"

fi