forked from sclorg/redis-container
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun
executable file
·291 lines (253 loc) · 8.3 KB
/
run
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
#!/bin/bash
#
# Test the Redis image.
#
# IMAGE_NAME specifies the name of the candidate image used for testing.
# The image has to be available before this script is executed.
#
set -o errexit
set -o nounset
shopt -s nullglob
[ "${DEBUG:-0}" -eq 1 ] && set -x
test -n "${IMAGE_NAME-}" || { echo 'make sure $IMAGE_NAME is defined' && false ;}
test -n "${VERSION-}" || { echo 'make sure $VERSION is defined' && false; }
test -n "${OS-}" || { echo 'make sure $OS is defined' && false; }
test -n "${OCI_RUNTIME_TOOL-}" || { podman --version &>/dev/null && export OCI_RUNTIME_TOOL=podman || export OCI_RUNTIME_TOOL=docker; }
test_exit=1
CIDFILE_DIR=$(mktemp --suffix=redis_test_cidfiles -d)
function cleanup() {
local cidfile
for cidfile in $CIDFILE_DIR/* ; do
local CONTAINER
CONTAINER=$(cat $cidfile)
echo "Stopping and removing container $CONTAINER..."
$OCI_RUNTIME_TOOL stop $CONTAINER >/dev/null
local exit_status
exit_status=$($OCI_RUNTIME_TOOL inspect -f '{{.State.ExitCode}}' $CONTAINER)
if [ "$exit_status" != "0" ]; then
echo "Inspecting container $CONTAINER"
$OCI_RUNTIME_TOOL inspect $CONTAINER
echo "Dumping logs for $CONTAINER"
$OCI_RUNTIME_TOOL logs $CONTAINER
fi
$OCI_RUNTIME_TOOL rm -v $CONTAINER >/dev/null
rm $cidfile
echo "Done."
done
rmdir $CIDFILE_DIR
# Report whole test result
if [ "$test_exit" -eq 0 ] ; then
echo "Test succeeded."
else
echo "Test failed."
fi
exit $test_exit
}
trap cleanup EXIT SIGINT
function get_cid() {
local id="$1" ; shift || return 1
echo $(cat "$CIDFILE_DIR/$id")
}
function get_container_ip() {
local id="$1" ; shift
$OCI_RUNTIME_TOOL inspect --format='{{.NetworkSettings.IPAddress}}' $(get_cid "$id")
}
function connection_works() {
local container_ip="$1"; shift
local password="$1"; shift
if [ "$(redis_cmd "$container_ip" "$password" ping)" == "PONG" ] ; then
return 0
fi
return 1
}
function redis_cmd() {
local container_ip="$1"; shift
local password="$1"; shift
# if empty password is given, then no password will be specified
$OCI_RUNTIME_TOOL run --rm "$IMAGE_NAME" redis-cli -h "$container_ip" ${password:+-a "$password"} "$@"
}
function test_connection() {
local name=$1 ; shift
local password=$1 ; shift
local ip
ip=$(get_container_ip $name)
echo " Testing Redis connection to $ip (password='${password:-}')..."
local max_attempts=10
local sleep_time=2
local i
for i in $(seq $max_attempts); do
echo " Trying to connect..."
if connection_works "$ip" "$password" ; then
echo " Success!"
echo
return 0
fi
sleep $sleep_time
done
echo " Giving up: Failed to connect. Logs:"
$OCI_RUNTIME_TOOL logs $(get_cid $name)
return 1
}
function test_redis() {
local container_ip="$1"
local password="$2"
echo " Testing Redis (password='${password:-}')"
redis_cmd "$container_ip" "$password" set a 1 >/dev/null
redis_cmd "$container_ip" "$password" set b 2 >/dev/null
test "$(redis_cmd "$container_ip" "$password" get b)" == '2'
echo " Success!"
echo
}
function create_container() {
local name=$1 ; shift
cidfile="$CIDFILE_DIR/$name"
# create container with a cidfile in a directory for cleanup
local container_id
[ "${DEBUG:-0}" -eq 1 ] && echo "DEBUG: $OCI_RUNTIME_TOOL run ${DOCKER_ARGS:-} --cidfile $cidfile -d \"$@\" $IMAGE_NAME ${CONTAINER_ARGS:-}" >&2
container_id="$($OCI_RUNTIME_TOOL run ${DOCKER_ARGS:-} --cidfile $cidfile -d "$@" $IMAGE_NAME ${CONTAINER_ARGS:-})"
[ "${DEBUG:-0}" -eq 1 ] && echo "Created container $container_id"
return 0
}
function run_change_password_test() {
local tmpdir=$(mktemp -d)
mkdir "${tmpdir}/data" && chmod -R a+rwx "${tmpdir}"
# Create Redis container with persistent volume and set the initial password
create_container "testpass1" -e REDIS_PASSWORD=foo \
-v ${tmpdir}:/var/lib/redis/data:Z
test_connection testpass1 foo
$OCI_RUNTIME_TOOL stop $(get_cid testpass1) >/dev/null
# Create second container with changed password
create_container "testpass2" -e REDIS_PASSWORD=bar \
-v ${tmpdir}:/var/lib/redis/data:Z
test_connection testpass2 bar
# The old password should not work anymore
container_ip="$(get_container_ip testpass2)"
if connection_works "$container_ip" foo ; then
return 1
fi
}
function assert_login_access() {
local container_ip=$1; shift
local PASS=$1 ; shift
local success=$1 ; shift
if connection_works "$container_ip" "$PASS" ; then
if $success ; then
echo " Connection ($PASS) access granted as expected"
return
fi
else
if ! $success ; then
echo " Connection ($PASS) access denied as expected"
return
fi
fi
echo " Connection ($PASS) login assertion failed"
exit 1
}
function assert_local_access() {
local id="$1" ; shift
$OCI_RUNTIME_TOOL exec $(get_cid "$id") bash -c 'redis-cli ping'
}
# Make sure the invocation of $OCI_RUNTIME_TOOL run fails.
function assert_container_creation_fails() {
# Time the $OCI_RUNTIME_TOOL run command. It should fail. If it doesn't fail,
# redis will keep running so we kill it with SIGKILL to make sure
# timeout returns a non-zero value.
local ret=0
timeout -s 9 --preserve-status 60s $OCI_RUNTIME_TOOL run --rm "$@" $IMAGE_NAME >/dev/null || ret=$?
# Timeout will exit with a high number.
if [ $ret -gt 10 ]; then
return 1
fi
}
function try_image_invalid_combinations() {
assert_container_creation_fails -e REDIS_PASSWORD="pass with space" "$@"
}
function run_container_creation_tests() {
echo " Testing image entrypoint usage"
try_image_invalid_combinations
echo " Success!"
echo
}
test_scl_usage() {
local name="$1"
local run_cmd="$2"
local expected="$3"
echo " Testing the image SCL enable"
local out
out=$($OCI_RUNTIME_TOOL run --rm ${IMAGE_NAME} /bin/bash -c "${run_cmd}")
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[/bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
return 1
fi
out=$($OCI_RUNTIME_TOOL exec $(get_cid $name) /bin/bash -c "${run_cmd}" 2>&1)
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[exec /bin/bash -c "${run_cmd}"] Expected '${expected}', got '${out}'"
return 1
fi
out=$($OCI_RUNTIME_TOOL exec $(get_cid $name) /bin/sh -ic "${run_cmd}" 2>&1)
if ! echo "${out}" | grep -q "${expected}"; then
echo "ERROR[exec /bin/sh -ic "${run_cmd}"] Expected '${expected}', got '${out}'"
return 1
fi
}
run_doc_test() {
local tmpdir=$(mktemp -d)
local f
echo " Testing documentation in the container image"
# Extract the help.1 file from the container
$OCI_RUNTIME_TOOL run --rm ${IMAGE_NAME} /bin/bash -c "cat /help.1" >${tmpdir}/help.1
# Check whether the help.1 file includes some important information
for term in 6379 "REDIS\_PASSWORD" volume; do
if ! cat ${tmpdir}/help.1 | grep -F -q -e "${term}" ; then
echo "ERROR: File /help.1 does not include '${term}'."
return 1
fi
done
# Check whether the file uses the correct format
if ! file ${tmpdir}/help.1 | grep -q roff ; then
echo "ERROR: /help.1 is not in troff or groff format"
return 1
fi
echo " Success!"
echo
}
function run_tests() {
local name=$1 ; shift
envs=${PASS:+"-e REDIS_PASSWORD=$PASS"}
PASS=${PASS:-}
create_container $name $envs
test_connection "$name" "$PASS"
# Only check version on rhel/centos builds
if [ "$OS" != "fedora" ]; then
echo " Testing scl usage"
test_scl_usage $name 'redis-server --version' "$VERSION"
fi
echo " Testing login accesses"
local container_ip
container_ip=$(get_container_ip $name)
assert_login_access "$container_ip" "$PASS" true
if [ -n "$PASS" ] ; then
assert_login_access "$container_ip" "${PASS}_foo" false
fi
assert_local_access "$name"
echo " Success!"
echo
test_redis "$container_ip" "$PASS"
}
# Tests.
# Test whether documentation is part of the image
run_container_creation_tests
# Normal tests without password
run_tests no_pass
# Normal tests with password
PASS=pass run_tests no_root
# Test with arbitrary uid for the container without password
DOCKER_ARGS="-u 12345" run_tests no_pass_altuid
# Test with arbitrary uid for the container with password
DOCKER_ARGS="-u 12345" PASS=pass run_tests no_root_altuid
# Test the password change
run_change_password_test
# Test whether documentation is part of the image
run_doc_test
test_exit=0