forked from openwallet-foundation/owl-agent-test-harness
-
Notifications
You must be signed in to change notification settings - Fork 0
/
manage
executable file
·1536 lines (1338 loc) · 46 KB
/
manage
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
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
# set -x
# Set of valid agents - add new agents here
# added remote as a valid agent to allow for remote agent testing.
export VALID_AGENTS=$(ls aries-backchannels/*/Dockerfile.* | sed "s/^.*file.//" | tr "\n" " " | sort -u)
VALID_AGENTS="${VALID_AGENTS} remote"
export MSYS_NO_PATHCONV=1
# getDockerHost; for details refer to https://github.com/bcgov/DITP-DevOps/tree/main/code/snippets#getdockerhost
. /dev/stdin <<<"$(cat <(curl -s --raw https://raw.githubusercontent.com/bcgov/DITP-DevOps/main/code/snippets/getDockerHost))"
export DOCKERHOST=$(getDockerHost)
SCRIPT_HOME="$( cd "$( dirname "$0" )" && pwd )"
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-aath}"
export AGENT_TIMEOUT=30
export LEDGER_TIMEOUT=60
# these can be overridden via env vars
export LEDGER_URL_CONFIG="${LEDGER_URL_CONFIG}"
export TAILS_SERVER_URL_CONFIG="${TAILS_SERVER_URL_CONFIG}"
export REDIS_CLUSTER_URL_CONFIG="${REDIS_CLUSTER_URL_CONFIG}"
export AGENT_CONFIG_FILE="${AGENT_CONFIG_FILE}"
export GENESIS_URL="${GENESIS_URL}"
export GENESIS_FILE="${GENESIS_FILE}"
# these are derived from the above two
LEDGER_URL_HOST="${LEDGER_URL_CONFIG:-http://localhost:9000}"
LEDGER_URL_INTERNAL="${LEDGER_URL_CONFIG:-http://${DOCKERHOST}:9000}"
TAILS_SERVER_URL_HOST="${TAILS_SERVER_URL_CONFIG:-http://localhost:6543}"
TAILS_SERVER_URL_INTERNAL="${TAILS_SERVER_URL_CONFIG:-http://${DOCKERHOST}:6543}"
# important: inside the internal URLs, we replace "://localhost:" with "://${DOCKERHOST}:"
# so it works inside docker.
LEDGER_URL_INTERNAL="$(echo ${LEDGER_URL_INTERNAL} | sed "s/:\/\/localhost:/:\/\/${DOCKERHOST}:/" )"
TAILS_SERVER_URL_INTERNAL="$(echo ${TAILS_SERVER_URL_INTERNAL} | sed "s/:\/\/localhost:/:\/\/${DOCKERHOST}:/" )"
REDIS_CLUSTER_URL_HOST="${REDIS_CLUSTER_URL_CONFIG:-http://localhost:6377}"
# Define variables for endpoints and ports
declare ACME_ENDPOINT=""
declare BOB_ENDPOINT=""
declare FABER_ENDPOINT=""
declare MALLORY_ENDPOINT=""
declare IS_ACME_REMOTE=0
declare IS_BOB_REMOTE=0
declare IS_FABER_REMOTE=0
declare IS_MALLORY_REMOTE=0
# Running on Windows?
if [[ "$OSTYPE" == "msys" ]]; then
# Prefix interactive terminal commands ...
terminalEmu="winpty"
fi
export INTERACTIVE="-it"
if [[ "$NO_TTY" == "1" ]]; then
unset INTERACTIVE
fi
#Running on Play with Docker?
if [ "${PWD_HOST_FQDN}" != "" ]; then
if [ "${PWD_HOST_FQDN}" == "labs.play-with-docker.com" ]; then
export ETH_CONFIG="eth1"
elif [ "${PWD_HOST_FQDN}" == "play-with-docker.vonx.io" ]; then
export ETH_CONFIG="eth0"
else
export ETH_CONFIG="eth0"
fi
myhost=`ifconfig ${ETH_CONFIG} | grep inet | cut -d':' -f2 | cut -d' ' -f1 | sed 's/\./\-/g'`
if [ "${GENESIS_URL}" == "" ]; then
export GENESIS_URL="http://ip${myhost}-${SESSION_ID}-9000.direct.${PWD_HOST_FQDN}/genesis"
fi
# Check if von-network is running
# Should this be moved out of the Play with Docker section?
if [ "${1}" == "run" ]; then
curl -s ${GENESIS_URL} > /dev/null
res=$?
if test "$res" != "0"; then
echo "Error: Unable to find the genesis file for the Indy Network"
echo "Is von-network running?"
echo GENESIS_URL: ${GENESIS_URL}
exit 1
fi
fi
fi
# Set default platform to linux/amd64 when running on Arm based MAC since there are no arm based images available currently.
if [[ $OSTYPE == 'darwin'* ]]; then
architecture=$(uname -m)
if [[ "${architecture}" == 'arm'* ]] || [[ "${architecture}" == 'aarch'* ]]; then
export DOCKER_DEFAULT_PLATFORM=linux/amd64
fi
fi
# ========================================================================================================
# Check Docker Compose
# --------------------------------------------------------------------------------------------------------
# Default to deprecated V1 'docker-compose'.
dockerCompose="docker-compose --log-level ERROR"
# Prefer 'docker compose' V2 if available
if [[ $(docker compose version 2> /dev/null) == 'Docker Compose'* ]]; then
dockerCompose="docker --log-level error compose"
fi
# echo "Using: ${dockerCompose}"
# =================================================================================================================
# Usage:
# -----------------------------------------------------------------------------------------------------------------
usage () {
cat <<-EOF
Usage: $0 [command] [options]
Commands:
build [ -a agent ]* args
Build the docker images for the agents and the test harness.
You need to do this first.
- "agent" must be one from the supported list: ${VALID_AGENTS}
- multiple agents may be built by specifying multiple -a options
- By default, all agents and the harness will be built
rebuild [ -a agent ]* args
Same as build, but adds the --no-cache option to force building from scratch
run [ -a/b/f/m/d agent ] [-r allure [-e comparison]] [ -i <ini file> ] [ -o <output file> ] [ -n ] [ -v <AIP level> ] [ -t tags ]*
Run the tagged tests using the specified agents for Acme, Bob, Faber and Mallory.
Select the agents for the roles of Acme (-a), Bob (-b), Faber (-f) and Mallory (-m).
- For all to be set to the same, use "-d" for default.
- The value for agent must be one of: ${VALID_AGENTS}
Use -t option(s) to indicate tests with the gives tag(s) are to be executed.
-t options can NOT have spaces, even if the option is quoted; use a behave INI file instead (-i option)
For not running tagged tests, specify a ~ before the tag, e.g. "-t ~@wip" runs tests that don't have the "@wip" tag
Use -v to specify the AIP level, in case the agent needs to customize its startup configuration
"-v 10" or "-v 20"
Use the -i option to use the specified file as the behave.ini file for the run
- Default is the behave.ini file in the "aries-test-harness" folder
Use the -r option to output to allure
(allure is the only supported option)
Use the -e option to compare current results to Known Good Results (KGR)
(comparison is the only supported option)
Use the -n option to start ngrok endpoints for each agent
(this is *required* when testing with a Mobile agent)
Examples:
$0 run -a acapy -b aries-vcx -f aries-vcx -m acapy - Run all the tests using the specified agents per role
$0 run -d aries-vcx - Run all tests for all features using the aries-vcx agent in all roles
$0 run -d acapy -t @SmokeTest -t @P1 - Run the tests tagged @SmokeTest and/or @P1 (priority 1) using all ACA-Py agents
$0 run -d acapy -b mobile -n -t @MobileTest - Run the mobile tests using ngrok endpoints
runset - Run the set of tests for a combination of Test Agents using the parameters in the daily, GitHub Action run "runsets".
To see full set of options for the "runset" command, execute "./manage runset -h"
tags - Get a list of the tags on the features tests
tests -t <tags> [ -md ]
Display selected test scenarios/features filtered by associated tags.
A list of relevant tags can be given as comma seperated list (with no spaces)
Optionaly, the output can be displayed as --markdown table
Examples:
$0 tests -h
$0 tests -t AIP10,AIP20
$0 tests -t critical -md
dry-run [ -i <ini file> ] [ -o <output file> ] [ -t tags ]*
Uses the Behave "dry-run" feature to get a lists of the Features, Scenarios and Tags
that would be run based on the provided the command line arguments. Useful for seeing what tests
a combination of "-t" (tag) arguments will cause to be run.
Accepts all the same parameters as 'run', but ignores -a/b/f/m/d/n/r/e/v
test [-r allure [-e comparison]] [ -i <ini file> ] [ -o <output file> ] [ -n ] [ -v <AIP level> ] [ -t tags ]*
Run the tagged tests using the set of agents that were started with the 'start' command, using all the same parameters as 'run',
except -a/b/f/m/d/n.
scenarios - synonym for tests, but longer and harder to spell
service [build|start|stop|logs|clean] service-name
Run the given service command on the given service. Commands:
- build: build the service (only needed for von-network).
- start: start the service, creating the AATH docker network if necessary.
- stop: stop the service, deleting the AATH docker network if it's now unused.
- logs: print the scrolling logs of the service. Ctrl-C to exit.
- clean: clean up the service containers and build files, if any.
start [ -a/b/f/m/d agent ]* [-n]
Initialize the test harness using the specified agents for Acme, Bob, Faber and Mallory.
Select the agents for the roles of Acme (-a), Bob (-b), Faber (-f) and Mallory (-m).
- For all to be set to the same, use "-d" for default.
- The value for agent must be one of: ${VALID_AGENTS}
Use the -n option to start ngrok endpoints for each agent
(this is *required* when testing with a Mobile agent)
stop - stop the test harness.
rebuild - Rebuild the docker images.
dockerhost - Print the ip address of the Docker Host Adapter as it is seen by containers running in docker.
EOF
exit 1
}
# -----------------------------------------------------------------------------------------------------------------
# Functions:
# -----------------------------------------------------------------------------------------------------------------
toLower() {
echo $(echo ${@} | tr '[:upper:]' '[:lower:]')
}
function echoRed (){
_msg="${@}"
_red='\e[31m'
_nc='\e[0m' # No Color
echo -e "${_red}${_msg}${_nc}"
}
function initDockerBuildArgs() {
dockerBuildArgs=""
# HTTP proxy, prefer lower case
if [[ "${http_proxy}" ]]; then
dockerBuildArgs=" ${dockerBuildArgs} --build-arg http_proxy=${http_proxy}"
else
if [[ "${HTTP_PROXY}" ]]; then
dockerBuildArgs=" ${dockerBuildArgs} --build-arg http_proxy=${HTTP_PROXY}"
fi
fi
# HTTPS proxy, prefer lower case
if [[ "${https_proxy}" ]]; then
dockerBuildArgs=" ${dockerBuildArgs} --build-arg https_proxy=${https_proxy}"
else
if [[ "${HTTPS_PROXY}" ]]; then
dockerBuildArgs=" ${dockerBuildArgs} --build-arg https_proxy=${HTTPS_PROXY}"
fi
fi
echo ${dockerBuildArgs}
}
function initEnv() {
if [ -f .env ]; then
while read line; do
if [[ ! "$line" =~ ^\# ]] && [[ "$line" =~ .*= ]]; then
export ${line//[$'\r\n']}
fi
done <.env
fi
for arg in "$@"; do
# Remove recognized arguments from the list after processing.
shift
case "$arg" in
*=*)
export "${arg}"
;;
*)
# If not recognized, save it for later procesing ...
set -- "$@" "$arg"
;;
esac
done
export LOG_LEVEL=${LOG_LEVEL:-info}
export RUST_LOG=${RUST_LOG:-warning}
}
# setup the docker environment variables to be passed to containers
setDockerEnv() {
# set variables that have a different name to what is being set for the container
DOCKER_ENV="-e AGENT_NAME=${NAME}"
if [[ -n "$BACKCHANNEL_EXTRA_ARGS" ]]; then
DOCKER_ENV="${DOCKER_ENV} -e EXTRA_ARGS=${BACKCHANNEL_EXTRA_ARGS}"
fi
if [[ -n "$LEDGER_URL_INTERNAL" ]]; then
DOCKER_ENV="${DOCKER_ENV} -e LEDGER_URL=${LEDGER_URL_INTERNAL}"
fi
if [[ -n "$TAILS_SERVER_URL_INTERNAL" ]]; then
DOCKER_ENV="${DOCKER_ENV} -e TAILS_SERVER_URL=${TAILS_SERVER_URL_INTERNAL}"
fi
if ! [ -z "$TEST_RETRY_ATTEMPTS_OVERRIDE" ]; then
DOCKER_ENV="${DOCKER_ENV} -e TEST_RETRY_ATTEMPTS_OVERRIDE=${TEST_RETRY_ATTEMPTS_OVERRIDE}"
fi
# variables that have the same variable name as what is being set for the container
declare -a GENERAL_VARIABLES=("DOCKERHOST" "NGROK_NAME" "CONTAINER_NAME" "AIP_CONFIG" "AGENT_CONFIG_FILE" "GENESIS_URL" "GENESIS_FILE" "START_TIMEOUT")
for var in "${GENERAL_VARIABLES[@]}"; do
if [[ -n "${!var}" ]]; then
DOCKER_ENV+=" -e ${var}=${!var}"
fi
done
}
# TODO: set up image builds so you don't need to use `./manage rebuild` to refresh remote source repo
# - image Dockerfile has an ARG for the commit hash,
# - build script grabs the HEAD commit hash from the agent's github repo
# Build images -- add more backchannels here...
# TODO: Define args to build only what's needed
buildImages() {
args=${@}
echo Agents to build: ${BUILD_AGENTS}
for agent in ${BUILD_AGENTS}; do
export BACKCHANNEL_FOLDER=$(dirname "$(find aries-backchannels -name *.${agent})" )
echo Backchannel Folder: ${BACKCHANNEL_FOLDER}
if [ -e "${BACKCHANNEL_FOLDER}/Dockerfile.${agent}" ]; then
echo "Building ${agent}-agent-backchannel ..."
local REPO_ARGS
REPO_ARGS=
if [[ -f "${BACKCHANNEL_FOLDER}/${agent}.repoenv" ]]; then
source "${BACKCHANNEL_FOLDER}/${agent}.repoenv"
if [[ -n "${REPO_URL}" ]]; then
local REPO_COMMIT
if [[ -z ${REPO_BRANCH} ]]; then
REPO_BRANCH=HEAD
fi
REPO_COMMIT=$(git ls-remote ${REPO_URL} ${REPO_BRANCH} | cut -f1)
REPO_ARGS="--build-arg REPO_URL=${REPO_URL} --build-arg REPO_COMMIT=${REPO_COMMIT}"
fi
fi
if ! docker build \
${args} \
$(initDockerBuildArgs) \
${REPO_ARGS} \
-t "${agent}-agent-backchannel" \
-f "${BACKCHANNEL_FOLDER}/Dockerfile.${agent}" "aries-backchannels/"; then
echo "Docker image build failed."
exit 1
fi
else
echo "Unable to find Dockerfile to build agent: ${agent}"
echo "Must be one of: ${VALID_AGENTS}"
fi
done
echo "Building aries-test-harness ..."
if ! docker build \
${args} \
$(initDockerBuildArgs) \
-t 'aries-test-harness' \
-f 'aries-test-harness/Dockerfile.harness' 'aries-test-harness/'; then
echo "Docker image build failed."
exit 1
fi
}
pingLedger(){
ledger_url=${1}
# ping ledger web browser for genesis txns
local rtnCd=$(curl -s --write-out '%{http_code}' --output /dev/null ${ledger_url})
if (( ${rtnCd} == 200 )); then
return 0
else
return 1
fi
}
waitForLedger(){
(
# Wait for ledger server to start or if remote wait for it to respond ...
local startTime=${SECONDS}
local rtnCd=0
# Determine the ping URL based on the ledger variables
local pingUrl=""
if [[ -n "${GENESIS_URL}" ]]; then
pingUrl="${GENESIS_URL}"
else
pingUrl="${LEDGER_URL_HOST}/genesis"
fi
printf "waiting for ledger to start/respond"
# use ledger URL from host
while ! pingLedger "${pingUrl}"; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${LEDGER_TIMEOUT} )); then
echoRed "\nThe Indy Ledger failed to start within ${duration} seconds.\n"
rtnCd=1
break
fi
sleep 1
done
echo
return ${rtnCd}
)
}
pingTailsServer(){
tails_server_url=${1}
# ping tails server (ask for a non-existant registry and should return 404)
local rtnCd=$(curl -s --write-out '%{http_code}' --output /dev/null ${tails_server_url}/404notfound)
if (( ${rtnCd} == 404 )); then
return 0
else
return 1
fi
}
waitForTailsServer(){
(
# Wait for tails server to start ...
local startTime=${SECONDS}
local rtnCd=0
printf "waiting for tails server to start"
# use tails server URL from host
while ! pingTailsServer "$TAILS_SERVER_URL_HOST"; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${LEDGER_TIMEOUT} )); then
echoRed "\nThe tails server failed to start within ${duration} seconds.\n"
rtnCd=1
break
fi
sleep 1
done
echo
return ${rtnCd}
)
}
pingUniresolver(){
# ping uniresolver server
local rtnCd=$(curl -s --write-out '%{http_code}' --output /dev/null http://localhost:8080/actuator/health)
if (( ${rtnCd} == 200 )); then
return 0
else
return 1
fi
}
waitForUniresolver(){
(
# Wait for uniresolver to start ...
local startTime=${SECONDS}
local rtnCd=0
printf "waiting for uniresolver to start"
while ! pingUniresolver ; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${LEDGER_TIMEOUT} )); then
echoRed "\nUniversal Resolver failed to start within ${duration} seconds.\n"
rtnCd=1
break
fi
sleep 1
done
echo
return ${rtnCd}
)
}
pingRedisCluster(){
redis_cluster_url_host=${1}
# ping tails server (ask for a non-existant registry and should return 404)
local rtnCd=$(curl -s --write-out '%{http_code}' --output /dev/null ${redis_cluster_url_host})
if (( ${rtnCd} == 000 )); then
return 0
else
return 1
fi
}
waitForRedisCluster(){
(
# Wait for tails server to start ...
local startTime=${SECONDS}
local rtnCd=0
printf "waiting for redis-cluster to start"
# use tails server URL from host
while ! pingRedisCluster "$REDIS_CLUSTER_URL_HOST"; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${LEDGER_TIMEOUT} )); then
echoRed "\nThe redis cluster failed to start within ${duration} seconds.\n"
rtnCd=1
break
fi
sleep 1
done
echo
return ${rtnCd}
)
}
dockerhost_url_templates() {
# generate acapy plugin config file, writing $DOCKERHOST into URLs
pushd ${SCRIPT_HOME}/aries-backchannels/acapy/ > /dev/null
mkdir -p .build/acapy-main.data
mkdir -p .build/acapy.data
sed "s/REPLACE_WITH_DOCKERHOST/${DOCKERHOST}/g" plugin-config.template | tee > .build/plugin-config.yml
rm -f .build/acapy-main.data/plugin-config.yml .build/acapy.data/plugin-config.yml
cp .build/plugin-config.yml .build/acapy-main.data/plugin-config.yml
mv .build/plugin-config.yml .build/acapy.data/plugin-config.yml
popd > /dev/null
}
pingAgent(){
name=${1}
endpoint=${2}
port=${3}
# ping agent using a backchannel-exposed api
# if port is not provided just use the endpoint
if [[ -z ${port} ]]; then
rtnCd=$(curl -s --write-out '%{http_code}' --output /dev/null ${endpoint}/agent/command/status/)
else
rtnCd=$(curl -s --write-out '%{http_code}' --output /dev/null ${endpoint}:${port}/agent/command/status/)
fi
if (( ${rtnCd} == 200 )); then
return 0
else
return 1
fi
}
waitForAgent(){
(
name=${1}
# Wait for agent to start ...
local startTime=${SECONDS}
rtnCd=0
printf "waiting for ${name} agent to start"
while ! pingAgent ${@}; do
printf "."
local duration=$(($SECONDS - $startTime))
if (( ${duration} >= ${AGENT_TIMEOUT} )); then
echoRed "\nThe agent failed to start within ${duration} seconds.\n"
rtnCd=1
break
fi
sleep 1
done
echo
return ${rtnCd}
)
}
startAgent() {
local NAME=$1
local CONTAINER_NAME=$2
local IMAGE_NAME=$3
local PORT_RANGE=$4
local BACKCHANNEL_PORT=$5
local AGENT_ENDPOINT_PORT=$6
local AIP_CONFIG=$7
local AGENT_NAME=$8
local BACKCHANNEL_DIR=$(dirname "$(find aries-backchannels -name *.${AGENT_NAME})" )
local ENV_PATH="$(find $BACKCHANNEL_DIR -name *${AGENT_NAME}.env)"
local ENV_FILE_ARG=
if [[ -n $ENV_PATH ]]; then
ENV_FILE_ARG="--env-file=$ENV_PATH"
# echo $ENV_FILE_ARG
fi
local DATA_VOLUME_PATH="$(find $BACKCHANNEL_DIR -wholename */${AGENT_NAME}.data)"
local DATA_VOLUME_ARG=
# optional data volume folder
if [[ -n DATA_VOLUME_PATH ]]; then
DATA_VOLUME_ARG="-v $(pwd)/$DATA_VOLUME_PATH:/data-mount:z"
fi
if [ ! "$(docker ps -q -f name=$CONTAINER_NAME)" ]; then
if [[ "${USE_NGROK}" = "true" ]]; then
# Turning off the starting of each ngrok tunnel for each agent. All tunnels are started when the ngrok service starts.
# There was an attempt to just start the service and then only start the tunnels when the agent was started, but
# That is not working. When we call start below, we get an error on the web_addr port in the config file.
# If this can be solved in the future we can re-enable this code, and make sure the ngrok service starts with the --none flag.
# echo "Starting ngrok for ${NAME} Agent ... on port ${AGENT_ENDPOINT_PORT}"
# # call the ngrok container to start the tunnel for the agent
# docker exec "${NGROK_NAME}" ngrok start --config /etc/ngrok.yml "${CONTAINER_NAME}_ngrok"
# if we are using ngrok we will have to export the CONTAINER_NAME to be used by the ngrok_wait script
export CONTAINER_NAME="${CONTAINER_NAME}"
fi
echo "Starting ${NAME} Agent using ${IMAGE_NAME} ..."
export BACKCHANNEL_EXTRA_ARGS_NAME="BACKCHANNEL_EXTRA_${AGENT_NAME//-/_}"
export BACKCHANNEL_EXTRA_ARGS=`echo ${!BACKCHANNEL_EXTRA_ARGS_NAME}`
# set the docker environment that needs to be passed to the test container
setDockerEnv
local container_id=$(docker run -dt --name "${CONTAINER_NAME}" --network aath_network --expose "${PORT_RANGE}" -p "${PORT_RANGE}:${PORT_RANGE}" ${DATA_VOLUME_ARG} ${ENV_FILE_ARG} $DOCKER_ENV "${IMAGE_NAME}" -p "${BACKCHANNEL_PORT}" -i false)
sleep 1
if [[ "${USE_NGROK}" = "true" ]]; then
docker network connect aath_network "${CONTAINER_NAME}"
elif [[ "${AGENT_NAME}" = "afgo-master" || "${AGENT_NAME}" = "afgo-interop" ]]; then
docker network connect aath_network "${CONTAINER_NAME}"
fi
if [[ "${IMAGE_NAME}" = "mobile-agent-backchannel" ]]; then
echo "Tail-ing log files for ${NAME} agent in ${container_id}"
docker logs -f ${container_id} &
fi
else
echo "${NAME} Agent already running, skipping..."
fi
}
writeEnvProperties() {
ACME_VERSION=$(getAgentVersion 9020)
BOB_VERSION=$(getAgentVersion 9030)
FABER_VERSION=$(getAgentVersion 9040)
MALLORY_VERSION=$(getAgentVersion 9050)
env_file="$(pwd)/aries-test-harness/allure/allure-results/environment.properties"
declare -a env_array
env_array+=("role.acme=$ACME_AGENT")
env_array+=("acme.agent.version=$ACME_VERSION")
env_array+=("role.bob=$BOB_AGENT")
env_array+=("bob.agent.version=$BOB_VERSION")
env_array+=("role.faber=$FABER_AGENT")
env_array+=("faber.agent.version=$FABER_VERSION")
env_array+=("role.mallory=$MALLORY_AGENT")
env_array+=("mallory.agent.version=$MALLORY_VERSION")
printf "%s\n" "${env_array[@]}" > $env_file
}
getAgentVersion(){
port=${1}
# get agent version using a backchannel-exposed api
version=$(curl -s http://localhost:${port}/agent/command/version/)
echo "$version"
# if (( ${rtnCd} == 200 )); then
# echo "$version"
# else
# echo "unknown"
# fi
}
createNetwork() {
if [[ -z `docker network ls -q --filter "name=aath_network"` ]]; then
docker network create aath_network --subnet=174.96.0.0/16 > /dev/null
fi
}
cleanupNetwork() {
if [[ -z `docker ps -q --filter "network=aath_network"` && `docker network ls -q --filter "name=aath_network"` ]]; then
docker network rm aath_network > /dev/null
fi
}
auxiliaryService() {
local SERVICE_NAME
local SERVICE_COMMAND
SERVICE_NAME=$1
SERVICE_COMMAND=$2
if [[ -f "./services/${SERVICE_NAME}/wrapper.sh" ]]; then
(./services/${SERVICE_NAME}/wrapper.sh $SERVICE_COMMAND)
else
echo "service ${SERVICE_NAME} doesn't exist"
fi
}
startServices() {
# sets if services this procedure starts should be stopped automatically
if [[ "auto" = $1 ]]; then
export AUTO_CLEANUP=true
else
export AUTO_CLEANUP=false
fi
if [[ "all" = $1 ]]; then
auxiliaryService orb start
# auxiliaryService redis-cluster start
fi
# if we're *not* using an external VON ledger, start the local one
if [[ -z ${LEDGER_URL_CONFIG} && -z ${GENESIS_URL} && -z ${GENESIS_FILE} ]]; then
if [[ -z `docker ps -q --filter="name=von_webserver_1"` ]] && [[ -z $(docker ps -q --filter="name=von-webserver-1") ]]; then
echo "starting local von-network..."
auxiliaryService von-network start
if [[ $AUTO_CLEANUP ]]; then
export STARTED_LOCAL_LEDGER=true
fi
fi
fi
if ! waitForLedger; then
echoRed "\nThe Indy Ledger is not running.\n"
exit 1
fi
if [[ -z `docker ps -q --filter="name=uni-resolver-web.local"` ]]; then
echo "starting local uniresolver..."
auxiliaryService uniresolver start
if [[ $AUTO_CLEANUP ]]; then
export STARTED_LOCAL_UNIRESOLVER=true
fi
fi
# if we're *not* using an external indy tails server, start the local one
if [[ -z ${TAILS_SERVER_URL_CONFIG} ]]; then
if [[ -z `docker ps -q --filter="name=docker_tails-server_1"` ]] && [[ -z $(docker ps -q --filter="name=docker-tails-server-1") ]]; then
echo "starting local indy-tails-server..."
auxiliaryService indy-tails start
if [[ $AUTO_CLEANUP ]]; then
export STARTED_LOCAL_TAILS=true
fi
fi
fi
if ! waitForTailsServer; then
echoRed "\nThe Indy Tails Server is not running.\n"
exit 1
fi
if ! waitForUniresolver; then
echoRed "\nUniversal Resolver is not running.\n"
exit 1
fi
}
stopServices() {
if [[ "auto" = $1 ]]; then
if [[ ${STARTED_LOCAL_UNIRESOLVER} ]]; then
echo "stopping local uniresolver..."
auxiliaryService uniresolver stop
fi
if [[ ${STARTED_LOCAL_TAILS} ]]; then
echo "stopping local indy-tails-server..."
auxiliaryService indy-tails stop
fi
if [[ ${STARTED_LOCAL_LEDGER} ]]; then
echo "stopping local von-network..."
auxiliaryService von-network stop
fi
elif [[ "all" = $1 ]]; then
auxiliaryService uniresolver stop
auxiliaryService orb stop
auxiliaryService indy-tails stop
auxiliaryService von-network stop
auxiliaryService redis-cluster stop
fi
}
serviceCommand() {
local SERVICE_COMMAND
SERVICE_COMMAND=$1
local SERVICE_TARGET
SERVICE_TARGET=$2
# TODO: allow multiple services to be named - but can we handle logs command then?
if [[ "all" = $SERVICE_TARGET ]]; then
case "${SERVICE_COMMAND}" in
start)
createNetwork
startServices all
;;
stop)
stopServices all
cleanupNetwork
;;
*)
echo err: \'start\' and \'stop\' are only valid commands for target \'all\'
;;
esac
return
fi
case "${SERVICE_COMMAND}" in
start)
createNetwork
auxiliaryService ${SERVICE_TARGET} ${SERVICE_COMMAND}
;;
logs)
auxiliaryService ${SERVICE_TARGET} ${SERVICE_COMMAND}
;;
stop|clean)
auxiliaryService ${SERVICE_TARGET} ${SERVICE_COMMAND}
cleanupNetwork
;;
*)
auxiliaryService ${SERVICE_TARGET} ${SERVICE_COMMAND}
;;
esac
}
startHarness(){
echo Agents to be used:
echo " Acme - ${ACME}"
echo " Bob - ${BOB}"
echo " Faber - ${FABER}"
echo " Mallory - ${MALLORY}"
echo ""
createNetwork
startServices auto
dockerhost_url_templates
export AIP_CONFIG=${AIP_CONFIG:-10}
# Standup the ngrok container if we are using ngrok
if [[ "${USE_NGROK}" = "true" ]]; then
echo "Starting ngrok service for test harness ..."
if [[ -n "$NGROK_AUTHTOKEN" ]]; then
NGROK_AUTHTOKEN="${NGROK_AUTHTOKEN}"
else
NGROK_AUTHTOKEN="harness_${NGROK_AUTHTOKEN}"
fi
# start the ngrok container but don't start the tunnels in the config yml file. We will start them later as needed for each agent.
docker run -d --rm -v $(pwd)/aath_ngrok_config.yml:/etc/ngrok.yml -e NGROK_CONFIG=/etc/ngrok.yml -e NGROK_AUTHTOKEN="${NGROK_AUTHTOKEN}" --name agents-ngrok --network aath_network -p 4040:4040 ngrok/ngrok:alpine start --all
export NGROK_NAME="agents-ngrok"
else
# if NGROK_NAME is populated then don't export it to null.
if [[ -z "$NGROK_NAME" ]]; then
export NGROK_NAME=
fi
fi
# Only start agents that are asked for in the ./manage start command
if [[ "$ACME" != "none" ]]; then
if checkAndSetRemote "ACME"; then
echo "ACME is set to remote."
else
export ACME_AGENT=${ACME_AGENT:-${ACME}-agent-backchannel}
startAgent Acme acme_agent "$ACME_AGENT" "9020-9029" 9020 9021 "$AIP_CONFIG" "$ACME"
fi
fi
if [[ "$BOB" != "none" ]]; then
if checkAndSetRemote "BOB"; then
echo "BOB is set to remote."
else
export BOB_AGENT=${BOB_AGENT:-${BOB}-agent-backchannel}
startAgent Bob bob_agent "$BOB_AGENT" "9030-9039" 9030 9031 "$AIP_CONFIG" "$BOB"
fi
fi
if [[ "$FABER" != "none" ]]; then
if checkAndSetRemote "FABER"; then
echo "FABER is set to remote."
else
export FABER_AGENT=${FABER_AGENT:-${FABER}-agent-backchannel}
startAgent Faber faber_agent "$FABER_AGENT" "9040-9049" 9040 9041 "$AIP_CONFIG" "$FABER"
fi
fi
if [[ "$MALLORY" != "none" ]]; then
if checkAndSetRemote "MALLORY"; then
echo "MALLORY is set to remote."
else
export MALLORY_AGENT=${MALLORY_AGENT:-${MALLORY}-agent-backchannel}
startAgent Mallory mallory_agent "$MALLORY_AGENT" "9050-9059" 9050 9051 "$AIP_CONFIG" "$MALLORY"
fi
fi
echo
# Check if agents were successfully started.
if [[ "$ACME" != "none" ]]; then
if [[ IS_ACME_REMOTE -eq 0 ]]; then
waitForAgent Acme http://localhost 9020
else
waitForAgent Acme ${ACME_ENDPOINT}
fi
if [ $? -eq 1 ]; then
return 1
fi
fi
if [[ "$BOB" != "none" ]]; then
if [[ IS_BOB_REMOTE -eq 0 ]]; then
waitForAgent Bob http://localhost 9030
else
waitForAgent Bob ${BOB_ENDPOINT}
fi
if [ $? -eq 1 ]; then
return 1
fi
fi
if [[ "$FABER" != "none" ]]; then
if [[ IS_FABER_REMOTE -eq 0 ]]; then
waitForAgent Faber http://localhost 9040
else
waitForAgent Faber ${FABER_ENDPOINT}
fi
if [ $? -eq 1 ]; then
return 1
fi
fi
if [[ "$MALLORY" != "none" ]]; then
if [[ IS_MALLORY_REMOTE -eq 0 ]]; then
waitForAgent Mallory http://localhost 9050
else
waitForAgent Mallory ${MALLORY_ENDPOINT}
fi
if [ $? -eq 1 ]; then
return 1
fi
fi
echo
export PROJECT_ID=${PROJECT_ID:-general}
echo
# Allure Reports environment.properties file handling
# Only do this if reporting parameter is passed.
if [[ "${REPORT}" = "allure" ]]; then
writeEnvProperties
fi
}
# Check if the agent is remote and set the endpoint and port
checkAndSetRemote() {
local agent_name=$1
local endpoint_var="${agent_name}_ENDPOINT"
local port_var="${agent_name}_PORT"
local is_remote_var="IS_${agent_name}_REMOTE"
if [[ -n "${!endpoint_var}" ]]; then
eval $is_remote_var=1
return 0
else
return 1
fi
}
deleteAgents() {
# Check if agent is remote and delete it
if [[ IS_ACME_REMOTE -eq 0 ]]; then
deleteAgent acme_agent
fi
if [[ IS_BOB_REMOTE -eq 0 ]]; then
deleteAgent bob_agent
fi
if [[ IS_FABER_REMOTE -eq 0 ]]; then
deleteAgent faber_agent
fi
if [[ IS_MALLORY_REMOTE -eq 0 ]]; then
deleteAgent mallory_agent
fi
}
deleteAgent() {
agent=$1
docker rm -f $agent || 1
}
runSetUsage() {
# =================================================================================================================
# runset Usage:
# -----------------------------------------------------------------------------------------------------------------
cat <<-EOF
Usage: $0 runset [run-set-name] [options]
Command: runset
Run the agents and tests for a named "runset", one of the test runs executed nightly via GitHub Actions.
Options:
-b : run a "build" for the runset agents before the "run"
-r : run a "rebuild" for the runset agents before the "run"
-n : dry-run; don't run the commands, just print them
The run-set-name must be one from the following list, each associated with a GHA file in .github/workflows.
In most cases, the first named framework in the runset name runs Acme, Faber and Mallory, and the second, Bob.
EOF
listRunSets | tr '\n' ' '
echo ""
}
listRunSets() {
for runset in .github/workflows/*test-harness-*.yml; do
echo $runset | sed "s/.*test-harness-//" | sed "s/.yml//"
done
}
runRunSet() {
runSets=$(listRunSets)
for i in $runSets; do