-
Notifications
You must be signed in to change notification settings - Fork 385
/
Copy pathfunctions.sh
executable file
·303 lines (278 loc) · 9.12 KB
/
functions.sh
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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# Functions for setting up Trillian integration tests
if [[ -z "${TMPDIR}" ]]; then
TMPDIR=/tmp
fi
readonly TMPDIR
declare -a RPC_SERVER_PIDS
declare -a LOG_SIGNER_PIDS
declare -a TO_KILL
declare -a TO_DELETE
HTTP_SERVER_1=''
RPC_SERVER_1=''
RPC_SERVERS=''
ETCD_OPTS=''
ETCD_PID=''
ETCD_DB_DIR=''
readonly TRILLIAN_PATH=$(go list -f '{{.Dir}}' github.com/google/trillian)
# run_test runs the given test with additional output messages.
run_test() {
local name=$1
shift
echo "=== RUN ${name}"
"$@"
rc=$?
if [ $rc -ne 0 ]; then
echo "--- FAIL: ${name}"
else
echo "--- PASS: ${name}"
fi
return $rc
}
# wait_for_server_startup pauses until there is a response on the given port.
wait_for_server_startup() {
# The server will 404 the request as there's no handler for it. This error doesn't matter
# as the test will fail if the server is really not up.
local port=$1
set +e
wget -q --spider --retry-connrefused --waitretry=2 -t 20 localhost:${port}
# Wait a bit more to give it a chance to become actually available, e.g. if CI
# environment is slow.
sleep 5
wget -q --spider -t 1 localhost:${port}
local rc=$?
set -e
# wget emits rc=8 for server issuing an error response (e.g. 404)
if [ ${rc} != 0 -a ${rc} != 8 ]; then
echo "Failed to get response on localhost:${port}"
exit 1
fi
}
# pick_unused_port selects an apparently unused port.
pick_unused_port() {
local avoid=${1:-0}
local base=6962
local port
for (( port = "${base}" ; port <= 61000 ; port++ )); do
if [[ $port == $avoid ]]; then
continue
fi
if ! lsof -i :$port > /dev/null; then
echo $port
break
fi
done
}
# kill_pid tries to kill the given pid(s), first softly then more aggressively.
kill_pid() {
local pids=$@
set +e
local count=0
while kill -INT ${pids} > /dev/null 2>&1; do
sleep 1
((count++))
local im_still_alive=""
for pid in ${pids}; do
if ps -p ${pid} > /dev/null ; then
# https://www.youtube.com/watch?time_continue=1&v=VuLktUzq23c
im_still_alive+=" ${pid}"
fi
done
pids="${im_still_alive}"
if [ -z "${pids}" ]; then
# all gone!
break
fi
if [ $count -gt 5 ]; then
echo "Now do kill -KILL ${pids}"
kill -KILL ${pids}
break
fi
echo "Retry kill -INT ${pids}"
done
set -e
}
# log_prep_test prepares a set of running processes for a Trillian log test.
# Parameters:
# - number of log servers to run
# - number of log signers to run
# Env:
# - If TEST_MYSQL_URI is set, uses that for the server --mysql_uri flag.
# Populates:
# - HTTP_SERVER_1 : first HTTP server
# - RPC_SERVER_1 : first RPC server
# - RPC_SERVERS : RPC target, either comma-separated list of RPC addresses or etcd service
# - RPC_SERVER_PIDS : bash array of RPC server pids
# - LOG_SIGNER_PIDS : bash array of signer pids
# - ETCD_OPTS : common option to configure etcd location
# If the ETCD_DIR var points to a valid etcd, also populates:
# - ETCD_PID : etcd pid
# - ETCD_DB_DIR : location of etcd database
# If WITH_PKCS11 is set, also populates:
# - SOFTHSM_CONF : location of the SoftHSM configuration file
#
log_prep_test() {
set -x
# Default to one of each.
local rpc_server_count=${1:-1}
local log_signer_count=${2:-1}
# Wipe the test database
if [[ "${TEST_MYSQL_URI}" != "" ]]; then
yes | bash "${TRILLIAN_PATH}/scripts/resetdb.sh"
elif [[ "${TEST_COCKROACHDB_URI}" != "" ]]; then
yes | bash "${TRILLIAN_PATH}/scripts/resetcrdb.sh"
elif [[ "${TEST_POSTGRESQL_URI}" != "" ]]; then
yes | bash "${TRILLIAN_PATH}/scripts/resetpgdb.sh"
fi
local logserver_opts=''
local logsigner_opts=''
local has_etcd=0
if [[ "${TEST_MYSQL_URI}" != "" ]]; then
logserver_opts+=" --mysql_uri=${TEST_MYSQL_URI}"
logsigner_opts+=" --mysql_uri=${TEST_MYSQL_URI}"
elif [[ "${TEST_COCKROACHDB_URI}" != "" ]]; then
logserver_opts+="--quota_system=crdb --storage_system=crdb --crdb_uri=${TEST_COCKROACHDB_URI}"
logsigner_opts+="--quota_system=crdb --storage_system=crdb --crdb_uri=${TEST_COCKROACHDB_URI}"
elif [[ "${TEST_POSTGRESQL_URI}" != "" ]]; then
logserver_opts+="--quota_system=postgresql --storage_system=postgresql --postgresql_uri=${TEST_POSTGRESQL_URI}"
logsigner_opts+="--quota_system=postgresql --storage_system=postgresql --postgresql_uri=${TEST_POSTGRESQL_URI}"
fi
# Start a local etcd instance (if configured).
if [[ -x "${ETCD_DIR}/etcd" ]]; then
has_etcd=1
local etcd_port=2379
local etcd_server="localhost:${etcd_port}"
echo "Starting local etcd server on ${etcd_server}"
${ETCD_DIR}/etcd &
ETCD_PID=$!
ETCD_OPTS="--etcd_servers=${etcd_server}"
ETCD_DB_DIR=default.etcd
wait_for_server_startup ${etcd_port}
logserver_opts="${logserver_opts} --etcd_http_service=trillian-logserver-http --etcd_service=trillian-logserver --quota_system=etcd"
logsigner_opts="${logsigner_opts} --etcd_http_service=trillian-logsigner-http --quota_system=etcd"
else
if [[ ${log_signer_count} > 1 ]]; then
echo "*** Warning: running multiple signers with no etcd instance ***"
fi
logsigner_opts="${logsigner_opts} --force_master"
fi
if [[ "${WITH_PKCS11}" == "true" ]]; then
export SOFTHSM_CONF=${TMPDIR}/softhsm.conf
local pkcs11_opts="--pkcs11_module_path ${PKCS11_MODULE:-/usr/lib/softhsm/libsofthsm.so}"
fi
# Start a set of Log RPC servers.
for ((i=0; i < rpc_server_count; i++)); do
port=$(pick_unused_port)
RPC_SERVERS="${RPC_SERVERS},localhost:${port}"
http=$(pick_unused_port ${port})
echo "Starting Log RPC server on localhost:${port}, HTTP on localhost:${http}"
go run ${GOFLAGS} github.com/google/trillian/cmd/trillian_log_server \
${ETCD_OPTS} ${pkcs11_opts} ${logserver_opts} \
--rpc_endpoint="localhost:${port}" \
--http_endpoint="localhost:${http}" \
${LOGGING_OPTS} \
&
pid=$!
RPC_SERVER_PIDS+=(${pid})
wait_for_server_startup ${port}
# Use the first Log server as the Admin server (any would do)
if [[ $i -eq 0 ]]; then
HTTP_SERVER_1="localhost:${http}"
RPC_SERVER_1="localhost:${port}"
fi
done
RPC_SERVERS="${RPC_SERVERS:1}"
# Setup etcd quotas, if applicable
if [[ ${has_etcd} -eq 1 ]]; then
setup_etcd_quotas "${RPC_SERVER_1}"
fi
# Start a set of signers.
for ((i=0; i < log_signer_count; i++)); do
port=$(pick_unused_port)
http=$(pick_unused_port ${port})
echo "Starting Log signer, HTTP on localhost:${http}"
go run ${GOFLAGS} github.com/google/trillian/cmd/trillian_log_signer \
${ETCD_OPTS} ${pkcs11_opts} ${logsigner_opts} \
--sequencer_interval="1s" \
--batch_size=500 \
--rpc_endpoint="localhost:${port}" \
--http_endpoint="localhost:${http}" \
--num_sequencers 2 \
${LOGGING_OPTS} \
&
pid=$!
LOG_SIGNER_PIDS+=(${pid})
wait_for_server_startup ${http}
done
if [[ ! -z "${ETCD_OPTS}" ]]; then
RPC_SERVERS="trillian-logserver"
echo "Registered log servers @${RPC_SERVERS}/"
ETCDCTL_API=3 etcdctl get ${RPC_SERVERS}/ --prefix
echo "Registered HTTP endpoints"
ETCDCTL_API=3 etcdctl get trillian-logserver-http/ --prefix
ETCDCTL_API=3 etcdctl get trillian-logsigner-http/ --prefix
fi
}
# log_stop_tests closes down a set of running processes for a log test.
# Assumes the following variables are set:
# - LOG_SIGNER_PIDS : bash array of signer pids
# - RPC_SERVER_PIDS : bash array of RPC server pids
# - ETCD_PID : etcd pid
log_stop_test() {
local pids
echo "Stopping Log signers (pids ${LOG_SIGNER_PIDS[@]})"
pids+=" ${LOG_SIGNER_PIDS[@]}"
echo "Stopping Log RPC servers (pids ${RPC_SERVER_PIDS[@]})"
pids+=" ${RPC_SERVER_PIDS[@]}"
if [[ "${ETCD_PID}" != "" ]]; then
echo "Stopping local etcd server (pid ${ETCD_PID})"
pids+=" ${ETCD_PID}"
fi
kill_pid ${pids}
}
# setup_etcd_quotas creates the etcd quota configurations used by tests.
#
# Parameters:
# - server : GRPC endpoint for the quota API (eg, logserver grpc port)
#
# Outputs:
# DeleteConfig and CreateConfig responses.
#
# Returns:
# 0 if success, non-zero otherwise.
setup_etcd_quotas() {
local server="$1"
local name='quotas/global/write/config'
# Remove the config before creating. It's OK if it doesn't exist.
local delete_output=$(grpcurl -plaintext -d "name: ${name}" ${server} quotapb.Quota.DeleteConfig )
printf 'quotapb.Quota.DeleteConfig %s: %s\n' "${name}" "${delete_output}"
local create_output=$(grpcurl -plaintext -d @ ${server} quotapb.Quota.CreateConfig <<EOF
{
"name": "${name}",
"config": {
"state": "ENABLED",
"max_tokens": 1000,
"sequencing_based": {
}
}
}
EOF
)
printf 'quotapb.Quota.CreateConfig %s: %s\n' "${name}" "${create_output}"
# Success responses have the config name in them
echo "${create_output}" | grep '"name":' > /dev/null
}
# on_exit will clean up anything in ${TO_KILL} and ${TO_DELETE}.
on_exit() {
local pids=
for pid in "${TO_KILL[@]}"; do
echo "Killing ${pid} on exit"
pids+=" ${pid}"
done
kill_pid "${pids}"
local file=""
for file in "${TO_DELETE[@]}"; do
echo "Deleting ${file} on exit"
rm -rf ${file}
done
}
trap on_exit EXIT