run.sh 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #!/bin/bash
  2. set -e
  3. image="$1"
  4. cname="mongo-container-$RANDOM-$RANDOM"
  5. mongodRunArgs=( -d --name "$cname" --cap-add SYS_NICE ) # SYS_NICE is for NUMA (needed for MongoDB 3.6 on NUMA-enabled hosts)
  6. mongodCmdArgs=()
  7. mongo='mongo'
  8. mongoArgs=( --host mongo )
  9. countFunc='function count(coll) { return coll.count() }' # count(db.test)
  10. upsertFunc='function upsert(coll, doc) { return coll.save(doc) }' # upsert(db.test, { _id: 'foo', bar: 'baz' })
  11. if docker run --rm --entrypoint sh "$image" -c 'command -v mongosh > /dev/null'; then
  12. mongo='mongosh'
  13. # https://www.mongodb.com/docs/mongodb-shell/reference/compatibility/#std-label-compatibility
  14. countFunc='function count(coll) { return coll.countDocuments() }' # https://www.mongodb.com/docs/manual/reference/method/db.collection.countDocuments/
  15. upsertFunc='function upsert(coll, doc) { return coll.initializeUnorderedBulkOp().find({ _id: doc._id }).upsert().replaceOne(doc).execute() }' # https://www.mongodb.com/docs/manual/reference/method/Bulk.find.upsert/#insert-for-bulk.find.replaceone--
  16. fi
  17. testDir="$(readlink -f "$(dirname "$BASH_SOURCE")")"
  18. testName="$(basename "$testDir")" # "mongo-basics" or "mongo-auth-basics" or "mongo-tls-auth"
  19. if [[ "$testName" == *auth* ]]; then
  20. rootUser="root-$RANDOM"
  21. rootPass="root-$RANDOM-$RANDOM-password"
  22. mongodRunArgs+=(
  23. -e MONGO_INITDB_ROOT_USERNAME="$rootUser"
  24. -e MONGO_INITDB_ROOT_PASSWORD="$rootPass"
  25. )
  26. mongoArgs+=(
  27. --username="$rootUser"
  28. --password="$rootPass"
  29. --authenticationDatabase='admin'
  30. )
  31. fi
  32. if [[ "$testName" == *tls* ]]; then
  33. tlsImage="$("$testDir/../image-name.sh" librarytest/mongo-tls "$image")"
  34. "$testDir/../docker-build.sh" "$testDir" "$tlsImage" <<-EOD
  35. FROM alpine:3.17 AS certs
  36. RUN apk add --no-cache openssl
  37. RUN set -eux; \
  38. mkdir /certs; \
  39. openssl genrsa -out /certs/ca-private.key 8192; \
  40. openssl req -new -x509 \
  41. -key /certs/ca-private.key \
  42. -out /certs/ca.crt \
  43. -days $(( 365 * 30 )) \
  44. -subj '/CN=lolca'; \
  45. openssl genrsa -out /certs/private.key 4096; \
  46. openssl req -new -key /certs/private.key \
  47. -out /certs/cert.csr -subj '/CN=mongo'; \
  48. openssl x509 -req -in /certs/cert.csr \
  49. -CA /certs/ca.crt -CAkey /certs/ca-private.key -CAcreateserial \
  50. -out /certs/cert.crt -days $(( 365 * 30 )); \
  51. openssl verify -CAfile /certs/ca.crt /certs/cert.crt
  52. FROM $image
  53. # gotta be :0 because percona's mongo doesn't have a mongodb group and estesp slayed tianon with https://github.com/moby/moby/pull/34263/files#diff-f157a3a45b3e5d85aadff73bff1f5a7cR170-R171
  54. COPY --from=certs --chown=mongodb:0 /certs /certs
  55. RUN cat /certs/cert.crt /certs/private.key > /certs/both.pem # yeah, what
  56. EOD
  57. image="$tlsImage"
  58. mongodRunArgs+=(
  59. --hostname mongo
  60. )
  61. # test for 4.2+ (where "s/ssl/tls/" was applied to all related options/flags)
  62. # see https://docs.mongodb.com/manual/tutorial/configure-ssl/#procedures-using-net-ssl-settings
  63. if docker run --rm "$image" mongod --help 2>&1 | grep -q -- ' --tlsMode '; then
  64. mongodCmdArgs+=(
  65. --tlsMode requireTLS
  66. --tlsCertificateKeyFile /certs/both.pem
  67. )
  68. mongoArgs+=(
  69. --tls
  70. --tlsCAFile /certs/ca.crt
  71. )
  72. else
  73. mongodCmdArgs+=(
  74. --sslMode requireSSL
  75. --sslPEMKeyFile /certs/both.pem
  76. )
  77. mongoArgs+=(
  78. --ssl
  79. --sslCAFile /certs/ca.crt
  80. )
  81. fi
  82. fi
  83. cid="$(docker run "${mongodRunArgs[@]}" "$image" "${mongodCmdArgs[@]}")"
  84. trap "docker rm -vf $cid > /dev/null" EXIT
  85. mongo() {
  86. docker run --rm -i --cap-add SYS_NICE \
  87. --link "$cname":mongo \
  88. --entrypoint "$mongo" \
  89. "$image" \
  90. "${mongoArgs[@]}" "$@"
  91. }
  92. mongo_eval() {
  93. local eval="$1"; shift
  94. mongo --quiet --eval "$countFunc; $upsertFunc; $eval" "$@"
  95. }
  96. mongo_eval_67788() {
  97. # workaround for https://jira.mongodb.org/browse/SERVER-67788
  98. local -
  99. shopt -s extglob
  100. local out
  101. out="$(mongo_eval "$@")"
  102. echo "${out##+([^0-9]*$'\n')}"
  103. }
  104. . "$testDir/../../retry.sh" "mongo_eval 'quit(db.stats().ok ? 0 : 1);'"
  105. if false; then
  106. tries=10
  107. while ! mongo_eval 'quit(db.stats().ok ? 0 : 1);' &> /dev/null; do
  108. (( tries-- ))
  109. if [ $tries -le 0 ]; then
  110. echo >&2 'mongod failed to accept connections in a reasonable amount of time!'
  111. ( set -x && docker logs "$cid" ) >&2 || true
  112. mongo --eval 'db.stats();' # to hopefully get a useful error message
  113. false
  114. fi
  115. echo >&2 -n .
  116. sleep 2
  117. done
  118. fi
  119. [ "$(mongo_eval_67788 'count(db.test);')" = 0 ]
  120. mongo_eval 'upsert(db.test, { _id: 1, a: 2, b: 3, c: "hello" });' > /dev/null
  121. [ "$(mongo_eval_67788 'count(db.test);')" = 1 ]
  122. mongo_eval 'upsert(db.test, { _id: 1, a: 3, b: 4, c: "hello" });' > /dev/null
  123. [ "$(mongo_eval_67788 'count(db.test);')" = 1 ]
  124. [ "$(mongo_eval_67788 'db.test.findOne().a;')" = 3 ]
  125. [ "$(mongo_eval_67788 'count(db.test2);')" = 0 ]
  126. mongo_eval 'upsert(db.test2, { _id: "abc" });' > /dev/null
  127. [ "$(mongo_eval_67788 'count(db.test2);')" = 1 ]
  128. [ "$(mongo_eval_67788 'count(db.test);')" = 1 ]
  129. mongo_eval 'db.test2.drop();' > /dev/null
  130. [ "$(mongo_eval_67788 'count(db.test2);')" = 0 ]
  131. [ "$(mongo_eval_67788 'count(db.test);')" = 1 ]
  132. [ "$(mongo_eval_67788 'count(db.test);' database-that-does-not-exist)" = 0 ]
  133. mongo_eval 'db.dropDatabase();' > /dev/null
  134. [ "$(mongo_eval_67788 'count(db.test);')" = 0 ]