-
Notifications
You must be signed in to change notification settings - Fork 34
/
test.sh
executable file
·399 lines (366 loc) · 13.7 KB
/
test.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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#!/usr/bin/env bash
# Verifies environment and launches docker to execute test_runner.sh
# 1. I can pick up a brand new laptop, and as long as I have docker installed, everything will just work if I do ./test.sh <fw>
# 2. I want test.sh to default to running _all_ tests for that framework.
# 3. I want to be able to pass -m or -k to pytest
# 4. If I pass `all` instead of a fw name, it will run all frameworks
# 5. test.sh should validate i have the AWS keys, and a CLUSTER_URL set, but it need not verify the azure keys / security / etc
# Exit immediately on errors
set -e
timestamp="$(date +%y%m%d-%H%M%S)"
# Create a temp file for docker env.
# When the script exits (successfully or otherwise), clean up the file automatically.
tmp_aws_creds_path="$(mktemp /tmp/sdk-test-creds-${timestamp}-XXXX.tmp)"
envfile="$(mktemp /tmp/sdk-test-env-${timestamp}-XXXX.tmp)"
function cleanup {
rm -f ${tmp_aws_creds_path}
rm -f ${envfile}
}
trap cleanup EXIT
REPO_ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
WORK_DIR="/build" # where REPO_ROOT_DIR is mounted within the image
# Find out what framework(s) are available.
# - If there's a <REPO>/frameworks directory, get values from there.
# - Otherwise just use the name of the repo directory.
# If there's multiple options, the user needs to pick one. If there's only one option then we'll use that automatically.
if [ -d $REPO_ROOT_DIR/frameworks ]; then
# mono-repo (e.g. dcos-commons)
FRAMEWORK_LIST=$(ls $REPO_ROOT_DIR/frameworks | sort | xargs echo -n)
else
# standalone repo (e.g. spark-build)
FRAMEWORK_LIST=$(basename ${REPO_ROOT_DIR})
fi
if [ -n "$AZURE_DEV_CLIENT_ID" -a -n "$AZURE_DEV_CLIENT_SECRET" -a \
-n "$AZURE_DEV_TENANT_ID" -a -n "$AZURE_DEV_STORAGE_ACCOUNT" -a \
-n "$AZURE_DEV_STORAGE_KEY" ]; then
azure_enabled="true"
fi
# Set default values
security="permissive"
if [ -n "$azure_enabled" ]; then
pytest_m="sanity"
else
pytest_m="sanity and not azure"
fi
gradle_cache="${REPO_ROOT_DIR}/.gradle_cache"
ssh_path="${HOME}/.ssh/ccm.pem"
ssh_user="core"
aws_creds_path="${HOME}/.aws/credentials"
enterprise="true"
headless="false"
interactive="false"
package_registry="false"
docker_command=${DOCKER_COMMAND:="bash /build-tools/test_runner.sh $WORK_DIR"}
docker_image=${DOCKER_IMAGE:-"mesosphere/dcos-commons:latest"}
env_passthrough=
envfile_input=
function usage()
{
echo "Usage: $0 [flags] [framework:$(echo $FRAMEWORK_LIST | sed 's/ /,/g')]"
echo ""
echo "Flags:"
echo " -m $pytest_m"
echo " -k <args>"
echo " Test filters passed through to pytest. Other arguments may be passed with PYTEST_ARGS."
echo " -s"
echo " Using a strict mode cluster: configure/use ACLs."
echo " -o"
echo " Using an Open DC/OS cluster: skip Enterprise-only features."
echo " -p $ssh_path"
echo " Path to cluster SSH key."
echo " -l $ssh_user"
echo " Username to use for SSH commands into the cluster."
echo " -e $env_passthrough"
echo " A comma-separated list of environment variables to pass through to the running docker container"
echo " --envfile $envfile_input"
echo " A path to an envfile to pass to the docker container in addition to those required by the test scripts"
echo " -i/--interactive"
echo " Open a shell prompt in the docker container, without actually running any tests. Equivalent to DOCKER_COMMAND=bash"
echo " --headless"
echo " Run docker command in headless mode, without attaching to stdin. Sometimes needed in CI."
echo " --package-registry"
echo " Enables using a package registry to install packages. Requires \$PACKAGE_REGISTRY_STUB_URL."
echo " --dcos-files-path DIR"
echo " Sets the directory to look for .dcos files. If empty, uses stub universe urls to build .dcos file(s)."
echo " --gradle-cache $gradle_cache"
echo " Sets the gradle build cache to the specified path. Setting this to \"\" disables the cache."
echo " -a/--aws $aws_creds_path"
echo " Path to an AWS credentials file. Overrides any AWS_* env credentials."
echo " --aws-profile ${AWS_PROFILE:=NAME}"
echo " The AWS profile to use. Only required when using an AWS credentials file with multiple profiles."
echo ""
echo "Environment:"
echo " CLUSTER_URL"
echo " URL to cluster. If unset then a cluster will be created using dcos-launch"
echo " STUB_UNIVERSE_URL"
echo " One or more comma-separated stub-universe URLs. If unset then a build will be performed internally."
echo " DCOS_LOGIN_USERNAME/DCOS_LOGIN_PASSWORD"
echo " Custom login credentials to use for the cluster."
echo " AZURE_[CLIENT_ID,CLIENT_SECRET,TENANT_ID,STORAGE_ACCOUNT,STORAGE_KEY]"
echo " Enables Azure tests. The -m default is automatically updated to include any Azure tests."
echo " AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY or AWS_DEV_ACCESS_KEY_ID/AWS_DEV_SECRET_ACCESS_KEY"
echo " AWS credentials to use if the credentials file is unavailable."
echo " S3_BUCKET"
echo " S3 bucket to use for testing."
echo " DOCKER_COMMAND=$docker_command"
echo " Command to be run within the docker image (e.g. 'DOCKER_COMMAND=bash' to just get a prompt)"
echo " PYTEST_ARGS"
echo " Additional arguments (other than -m or -k) to pass to pytest."
echo " TEST_SH_*"
echo " Anything starting with TEST_SH_* will be forwarded to the container with that prefix removed."
echo " For example, 'TEST_SH_FOO=BAR' is included as 'FOO=BAR'."
}
if [ x"${1//-/}" == x"help" -o x"${1//-/}" == x"h" ]; then
usage
exit 1
fi
framework=""
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-m)
pytest_m="$2"
shift
;;
-k)
pytest_k="$2"
shift
;;
-s)
security="strict"
;;
-o|--open)
enterprise="false"
;;
-p)
if [[ ! -f "$2" ]]; then echo "File not found: -p $2"; exit 1; fi
ssh_path="$2"
shift
;;
-l)
ssh_user="$2"
shift
;;
-e)
env_passthrough="$2"
shift
;;
--envfile)
if [[ ! -f "$2" ]]; then echo "File not found: $key $2"; exit 1; fi
envfile_input="$2"
shift
;;
-i|--interactive)
if [[ x"$headless" == x"true" ]]; then echo "Cannot enable both --headless and --interactive: Disallowing background prompt that runs forever."; exit 1; fi
interactive="true"
;;
--headless)
if [[ x"$interactive" == x"true" ]]; then echo "Cannot enable both --headless and --interactive: Disallowing background prompt that runs forever."; exit 1; fi
headless="true"
;;
--package-registry)
package_registry="true"
;;
--dcos-files-path)
if [[ ! -d "$2" ]]; then echo "Directory not found: --dcos-files-path $2"; exit 1; fi
# Resolve abs path:
dcos_files_path="$( cd "$( dirname "$2" )" && pwd )/$(basename "$2")"
shift
;;
--gradle-cache)
if [[ ! -d "$2" ]]; then echo "Directory not found: --gradle-cache $2"; exit 1; fi
gradle_cache="$2"
shift
;;
-a|--aws)
if [[ ! -f "$2" ]]; then echo "File not found: -a/--aws $2"; exit 1; fi
aws_creds_path="$2"
shift
;;
--aws-profile)
aws_profile="$2"
shift
;;
-*)
echo "Unknown option: $key"
usage
exit 1
;;
*)
if [[ -n "$framework" ]]; then echo "Multiple frameworks specified, please only specify one at a time: $framework $@"; exit 1; fi
framework=$key
;;
esac
shift # past argument or value
done
if [ -z "$framework" -a x"$interactive" != x"true" ]; then
# If FRAMEWORK_LIST only has one option, use that. Otherwise complain.
if [ $(echo $FRAMEWORK_LIST | wc -w) == 1 ]; then
framework=$FRAMEWORK_LIST
else
echo "Multiple frameworks in $(basename $REPO_ROOT_DIR)/frameworks/, please specify one to test: $FRAMEWORK_LIST"
exit 1
fi
elif [ "$framework" = "all" ]; then
echo "'all' is no longer supported. Please specify one framework to test: $FRAMEWORK_LIST"
exit 1
fi
volume_args="-v ${REPO_ROOT_DIR}:$WORK_DIR"
if [ -z "$CLUSTER_URL" -a x"$interactive" == x"true" ]; then
CLUSTER_URL="$(dcos config show core.dcos_url)"
echo "CLUSTER_URL not specified. Using attached cluster ${CLUSTER_URL} in interactive mode"
fi
# Configure SSH key for getting into the cluster during tests
if [ -f "$ssh_path" ]; then
volume_args="$volume_args -v $ssh_path:/ssh/key" # pass provided key into docker env
else
if [ -n "$CLUSTER_URL" ]; then
# If the user is providing us with a cluster, we require the SSH key for that cluster.
echo "SSH key not found at $ssh_path. Use -p <path/to/id_rsa> to customize this path."
echo "An SSH key is required for communication with the provided CLUSTER_URL=$CLUSTER_URL"
exit 1
fi
# Don't need ssh key now: test_runner.sh will extract the key after cluster launch
fi
# Configure the AWS credentials profile
if [ -n "${aws_profile}" ]; then
echo "Using provided --aws-profile: ${aws_profile}"
elif [ -n "$AWS_PROFILE" ]; then
echo "Using provided AWS_PROFILE: $AWS_PROFILE"
aws_profile=$AWS_PROFILE
elif [ -f "${aws_creds_path}" ]; then
# Check the creds file. If there's exactly one profile, then use that profile.
available_profiles=$(grep -oE '^\[\S+\]' $aws_creds_path | tr -d '[]') # find line(s) that look like "[profile]", remove "[]"
available_profile_count=$(echo "$available_profiles" | wc -l)
if [ "$available_profile_count" == "1" ]; then
aws_profile=$available_profiles
echo "Using sole profile in $aws_creds_path: $aws_profile"
else
echo "Expected 1 profile in $aws_creds_path, found $available_profile_count: ${available_profiles}"
echo "Please specify --aws-profile or \$AWS_PROFILE to select a profile"
exit 1
fi
else
echo "No AWS profile specified, using 'default'"
aws_profile="default"
fi
# Write the AWS credential file (deleted on script exit)
if [ -f "${aws_creds_path}" ]; then
aws_credential_file_mount_target="${aws_creds_path}"
else
# CI environments may have creds in AWS_DEV_* envvars, map them to AWS_*:
if [ -n "${AWS_DEV_ACCESS_KEY_ID}" -a -n "${AWS_DEV_SECRET_ACCESS_KEY}}" ]; then
AWS_ACCESS_KEY_ID="${AWS_DEV_ACCESS_KEY_ID}"
AWS_SECRET_ACCESS_KEY="${AWS_DEV_SECRET_ACCESS_KEY}"
fi
# Check AWS_* envvars for credentials, create temp creds file using those credentials:
if [ -n "${AWS_ACCESS_KEY_ID}" -a -n "${AWS_SECRET_ACCESS_KEY}}" ]; then
echo "Writing AWS env credentials to temporary file: $tmp_aws_creds_path"
cat > $tmp_aws_creds_path <<EOF
[${aws_profile}]
aws_access_key_id = ${AWS_ACCESS_KEY_ID}
aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}
EOF
else
echo "Missing AWS credentials file (${aws_creds_path}) and AWS env (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY)"
exit 1
fi
aws_credential_file_mount_target="${tmp_aws_creds_path}"
fi
volume_args="$volume_args -v $aws_credential_file_mount_target:/root/.aws/credentials:ro"
if [ -n "$gradle_cache" ]; then
echo "Setting Gradle cache to ${gradle_cache}"
volume_args="$volume_args -v ${gradle_cache}:/root/.gradle"
fi
if [ x"$interactive" == x"true" ]; then
docker_command="bash"
fi
# Some automation contexts (e.g. Jenkins) will be unhappy if STDIN is not available. The --headless command accomodates such contexts.
if [ x"$headless" != x"true" ]; then
docker_interactive_arg="-i"
fi
if [ -n "$pytest_k" ]; then
if [ -n "$PYTEST_ARGS" ]; then
PYTEST_ARGS="$PYTEST_ARGS "
fi
PYTEST_ARGS="$PYTEST_ARGS-k \"$pytest_k\""
fi
if [ -n "$pytest_m" ]; then
if [ -n "$PYTEST_ARGS" ]; then
PYTEST_ARGS="$PYTEST_ARGS "
fi
PYTEST_ARGS="$PYTEST_ARGS-m \"$pytest_m\""
fi
if [ x"$package_registry" == x"true" ]; then
if [ -z "$PACKAGE_REGISTRY_STUB_URL" ]; then
echo "PACKAGE_REGISTRY_STUB_URL not found in environment. Exiting..."
exit 1
fi
fi
if [ -n "$dcos_files_path" ]; then
volume_args="$volume_args -v ${dcos_files_path}:${dcos_files_path}"
fi
if [ -n "$TEAMCITY_VERSION" ]; then
# The teamcity python module treats present-but-empty as enabled.
# We must therefore completely omitted this envvar to disable teamcity handling.
echo "TEAMCITY_VERSION=\"${TEAMCITY_VERSION}\"" >> $envfile
fi
if [ -n "$azure_enabled" ]; then
cat >> $envfile <<EOF
AZURE_CLIENT_ID=$AZURE_DEV_CLIENT_ID
AZURE_CLIENT_SECRET=$AZURE_DEV_CLIENT_SECRET
AZURE_TENANT_ID=$AZURE_DEV_TENANT_ID
AZURE_STORAGE_ACCOUNT=$AZURE_DEV_STORAGE_ACCOUNT
AZURE_STORAGE_KEY=$AZURE_DEV_STORAGE_KEY
EOF
fi
cat >> $envfile <<EOF
AWS_PROFILE=$aws_profile
CLUSTER_URL=$CLUSTER_URL
DCOS_ENTERPRISE=$enterprise
DCOS_FILES_PATH=$dcos_files_path
DCOS_LOGIN_PASSWORD=$DCOS_LOGIN_PASSWORD
DCOS_LOGIN_USERNAME=$DCOS_LOGIN_USERNAME
DCOS_SSH_USERNAME=$ssh_user
FRAMEWORK=$framework
PACKAGE_REGISTRY_ENABLED=$package_registry
PACKAGE_REGISTRY_STUB_URL=$PACKAGE_REGISTRY_STUB_URL
PYTEST_ARGS=$PYTEST_ARGS
S3_BUCKET=$S3_BUCKET
SECURITY=$security
STUB_UNIVERSE_URL=$STUB_UNIVERSE_URL
EOF
while read line; do
# Prefix match, then strip prefix in envfile:
if [[ "${line:0:8}" = "TEST_SH_" ]]; then
echo ${line#TEST_SH_} >> $envfile
fi
done < <(env)
if [ -n "$env_passthrough" ]; then
# If the -e flag is specified, add the ENVVAR lines for the
# comma-separated list of envvars
for envvar_name in ${env_passthrough//,/ }; do
echo "$envvar_name" >> $envfile
done
fi
if [ -n "$envfile_input" ]; then
cat "${envfile_input}" >> $envfile
fi
CMD="docker run --rm \
-t \
${docker_interactive_arg} \
--env-file $envfile \
${volume_args} \
-w $WORK_DIR \
${docker_image} \
${docker_command}"
echo "==="
echo "Docker command:"
echo " $CMD"
echo ""
echo "Environment:"
while read line; do
echo " $line"
done <$envfile
echo "==="
$CMD