Skip to content

Commit 6a7684a

Browse files
committed
PYTHON-2868 Test Serverless behind a load balancer (#742)
(cherry picked from commit 968ee7b)
1 parent d9c63ae commit 6a7684a

File tree

15 files changed

+153
-54
lines changed

15 files changed

+153
-54
lines changed

.evergreen/config.yml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,11 @@ functions:
426426
fi
427427
if [ -n "${test_serverless}" ]; then
428428
export TEST_SERVERLESS=1
429-
export MONGODB_URI="${MONGODB_URI}"
429+
export MONGODB_URI="${SINGLE_ATLASPROXY_SERVERLESS_URI}"
430430
export SERVERLESS_ATLAS_USER="${SERVERLESS_ATLAS_USER}"
431431
export SERVERLESS_ATLAS_PASSWORD="${SERVERLESS_ATLAS_PASSWORD}"
432+
export SINGLE_MONGOS_LB_URI="${SINGLE_ATLASPROXY_SERVERLESS_URI}"
433+
export MULTI_MONGOS_LB_URI="${MULTI_ATLASPROXY_SERVERLESS_URI}"
432434
fi
433435
434436
PYTHON_BINARY=${PYTHON_BINARY} \
@@ -883,10 +885,11 @@ task_groups:
883885
script: |
884886
${PREPARE_SHELL}
885887
set +o xtrace
886-
SERVERLESS_DRIVERS_GROUP=${SERVERLESS_DRIVERS_GROUP} \
887-
SERVERLESS_API_PUBLIC_KEY=${SERVERLESS_API_PUBLIC_KEY} \
888-
SERVERLESS_API_PRIVATE_KEY=${SERVERLESS_API_PRIVATE_KEY} \
889-
PROJECT="mongo-python-driver-312" \
888+
LOADBALANCED=ON \
889+
SERVERLESS_DRIVERS_GROUP=${SERVERLESS_DRIVERS_GROUP} \
890+
SERVERLESS_API_PUBLIC_KEY=${SERVERLESS_API_PUBLIC_KEY} \
891+
SERVERLESS_API_PRIVATE_KEY=${SERVERLESS_API_PRIVATE_KEY} \
892+
PROJECT="mongo-python-driver-312" \
890893
bash ${DRIVERS_TOOLS}/.evergreen/serverless/create-instance.sh
891894
- command: expansions.update
892895
params:
@@ -898,9 +901,9 @@ task_groups:
898901
${PREPARE_SHELL}
899902
set +o xtrace
900903
SERVERLESS_DRIVERS_GROUP=${SERVERLESS_DRIVERS_GROUP} \
901-
SERVERLESS_API_PUBLIC_KEY=${SERVERLESS_API_PUBLIC_KEY} \
902-
SERVERLESS_API_PRIVATE_KEY=${SERVERLESS_API_PRIVATE_KEY} \
903-
SERVERLESS_INSTANCE_NAME=${SERVERLESS_INSTANCE_NAME} \
904+
SERVERLESS_API_PUBLIC_KEY=${SERVERLESS_API_PUBLIC_KEY} \
905+
SERVERLESS_API_PRIVATE_KEY=${SERVERLESS_API_PRIVATE_KEY} \
906+
SERVERLESS_INSTANCE_NAME=${SERVERLESS_INSTANCE_NAME} \
904907
bash ${DRIVERS_TOOLS}/.evergreen/serverless/delete-instance.sh
905908
tasks:
906909
- ".serverless"

test/__init__.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,14 @@
107107
db_user = res['username'] or db_user
108108
db_pwd = res['password'] or db_pwd
109109
elif TEST_SERVERLESS:
110-
res = parse_uri(os.environ["MONGODB_URI"])
111-
host, port = res['nodelist'].pop(0)
112-
additional_serverless_mongoses = res['nodelist']
110+
TEST_LOADBALANCER = True
111+
res = parse_uri(SINGLE_MONGOS_LB_URI)
112+
host, port = res['nodelist'][0]
113113
db_user = res['username'] or db_user
114114
db_pwd = res['password'] or db_pwd
115115
TLS_OPTIONS = {'tls': True}
116+
# Spec says serverless tests must be run with compression.
117+
COMPRESSORS = COMPRESSORS or 'zlib'
116118

117119

118120
def is_server_resolvable():
@@ -226,7 +228,7 @@ def __init__(self):
226228
self.version = Version(-1) # Needs to be comparable with Version
227229
self.auth_enabled = False
228230
self.test_commands_enabled = False
229-
self.server_parameters = None
231+
self.server_parameters = {}
230232
self.is_mongos = False
231233
self.mongoses = []
232234
self.is_rs = False
@@ -241,7 +243,7 @@ def __init__(self):
241243
self.is_data_lake = False
242244
self.load_balancer = TEST_LOADBALANCER
243245
self.serverless = TEST_SERVERLESS
244-
if self.load_balancer:
246+
if self.load_balancer or self.serverless:
245247
self.default_client_options["loadBalanced"] = True
246248
if COMPRESSORS:
247249
self.default_client_options["compressors"] = COMPRESSORS
@@ -381,7 +383,11 @@ def _init_client(self):
381383
self.w = len(hello.get("hosts", [])) or 1
382384
self.version = Version.from_client(self.client)
383385

384-
if TEST_SERVERLESS:
386+
if self.serverless:
387+
self.server_parameters = {
388+
'requireApiVersion': False,
389+
'enableTestCommands': True,
390+
}
385391
self.test_commands_enabled = True
386392
self.has_ipv6 = False
387393
else:
@@ -401,14 +407,11 @@ def _init_client(self):
401407

402408
self.is_mongos = (self.hello.get('msg') == 'isdbgrid')
403409
if self.is_mongos:
404-
if self.serverless:
405-
self.mongoses.append(self.client.address)
406-
self.mongoses.extend(additional_serverless_mongoses)
407-
else:
410+
address = self.client.address
411+
self.mongoses.append(address)
412+
if not self.serverless:
408413
# Check for another mongos on the next port.
409-
address = self.client.address
410414
next_address = address[0], address[1] + 1
411-
self.mongoses.append(address)
412415
mongos_client = self._connect(
413416
*next_address, **self.default_client_options)
414417
if mongos_client:

test/load_balancer/cursors.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,11 @@
902902
},
903903
{
904904
"description": "listCollections pins the cursor to a connection",
905+
"runOnRequirements": [
906+
{
907+
"serverless": "forbid"
908+
}
909+
],
905910
"operations": [
906911
{
907912
"name": "listCollections",
@@ -1151,6 +1156,11 @@
11511156
},
11521157
{
11531158
"description": "change streams pin to a connection",
1159+
"runOnRequirements": [
1160+
{
1161+
"serverless": "forbid"
1162+
}
1163+
],
11541164
"operations": [
11551165
{
11561166
"name": "createChangeStream",

test/load_balancer/sdam-error-handling.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@
127127
"tests": [
128128
{
129129
"description": "only connections for a specific serviceId are closed when pools are cleared",
130+
"runOnRequirements": [
131+
{
132+
"serverless": "forbid"
133+
}
134+
],
130135
"operations": [
131136
{
132137
"name": "createFindCursor",
@@ -255,7 +260,7 @@
255260
]
256261
},
257262
{
258-
"description": "errors during the initial connection hello are ignore",
263+
"description": "errors during the initial connection hello are ignored",
259264
"runOnRequirements": [
260265
{
261266
"minServerVersion": "4.9"
@@ -274,7 +279,9 @@
274279
},
275280
"data": {
276281
"failCommands": [
277-
"isMaster"
282+
"ismaster",
283+
"isMaster",
284+
"hello"
278285
],
279286
"closeConnection": true,
280287
"appName": "lbSDAMErrorTestClient"

test/load_balancer/transactions.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,11 @@
607607
},
608608
{
609609
"description": "pinned connection is released after a transient non-network CRUD error",
610+
"runOnRequirements": [
611+
{
612+
"serverless": "forbid"
613+
}
614+
],
610615
"operations": [
611616
{
612617
"name": "failPoint",
@@ -715,6 +720,11 @@
715720
},
716721
{
717722
"description": "pinned connection is released after a transient network CRUD error",
723+
"runOnRequirements": [
724+
{
725+
"serverless": "forbid"
726+
}
727+
],
718728
"operations": [
719729
{
720730
"name": "failPoint",
@@ -831,6 +841,11 @@
831841
},
832842
{
833843
"description": "pinned connection is released after a transient non-network commit error",
844+
"runOnRequirements": [
845+
{
846+
"serverless": "forbid"
847+
}
848+
],
834849
"operations": [
835850
{
836851
"name": "failPoint",

test/load_balancer/wait-queue-timeouts.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"useMultipleMongoses": true,
1616
"uriOptions": {
1717
"maxPoolSize": 1,
18-
"waitQueueTimeoutMS": 5
18+
"waitQueueTimeoutMS": 50
1919
},
2020
"observeEvents": [
2121
"connectionCheckedOutEvent",

test/test_client.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ def test_auth_from_uri(self):
906906
"pymongo_test", "user", "pass", roles=['userAdmin', 'readWrite'])
907907

908908
with self.assertRaises(OperationFailure):
909-
connected(rs_or_single_client(
909+
connected(rs_or_single_client_noauth(
910910
"mongodb://a:b@%s:%d" % (host, port)))
911911

912912
# No error.
@@ -916,7 +916,7 @@ def test_auth_from_uri(self):
916916
# Wrong database.
917917
uri = "mongodb://admin:pass@%s:%d/pymongo_test" % (host, port)
918918
with self.assertRaises(OperationFailure):
919-
connected(rs_or_single_client(uri))
919+
connected(rs_or_single_client_noauth(uri))
920920

921921
# No error.
922922
connected(rs_or_single_client_noauth(
@@ -940,7 +940,7 @@ def test_username_and_password(self):
940940
client_context.create_user("admin", "ad min", "pa/ss")
941941
self.addCleanup(client_context.drop_user, "admin", "ad min")
942942

943-
c = rs_or_single_client(username="ad min", password="pa/ss")
943+
c = rs_or_single_client_noauth(username="ad min", password="pa/ss")
944944

945945
# Username and password aren't in strings that will likely be logged.
946946
self.assertNotIn("ad min", repr(c))
@@ -952,7 +952,8 @@ def test_username_and_password(self):
952952
c.server_info()
953953

954954
with self.assertRaises(OperationFailure):
955-
rs_or_single_client(username="ad min", password="foo").server_info()
955+
rs_or_single_client_noauth(
956+
username="ad min", password="foo").server_info()
956957

957958
@client_context.require_auth
958959
@ignore_deprecations
@@ -1005,11 +1006,7 @@ def test_unix_socket(self):
10051006
if not os.access(mongodb_socket, os.R_OK):
10061007
raise SkipTest("Socket file is not accessible")
10071008

1008-
if client_context.auth_enabled:
1009-
uri = "mongodb://%s:%s@%s" % (db_user, db_pwd, encoded_socket)
1010-
else:
1011-
uri = "mongodb://%s" % encoded_socket
1012-
1009+
uri = "mongodb://%s" % encoded_socket
10131010
# Confirm we can do operations via the socket.
10141011
client = rs_or_single_client(uri)
10151012
client.pymongo_test.test.insert_one({"dummy": "object"})

test/test_cmap.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
get_pools,
5252
rs_or_single_client,
5353
single_client,
54+
single_client_noauth,
5455
TestCreator,
5556
wait_until)
5657
from test.utils_spec_runner import SpecRunnerThread
@@ -274,7 +275,7 @@ def test_3_uri_connection_pool_options(self):
274275
opts = '&'.join(['%s=%s' % (k, v)
275276
for k, v in self.POOL_OPTIONS.items()])
276277
uri = 'mongodb://%s/?%s' % (client_context.pair, opts)
277-
client = rs_or_single_client(uri, **self.credentials)
278+
client = rs_or_single_client(uri)
278279
self.addCleanup(client.close)
279280
pool_opts = get_pool(client).opts
280281
self.assertEqual(pool_opts.non_default_options, self.POOL_OPTIONS)
@@ -334,8 +335,9 @@ def mock_connect(*args, **kwargs):
334335

335336
def test_5_check_out_fails_auth_error(self):
336337
listener = CMAPListener()
337-
client = single_client(username="notauser", password="fail",
338-
event_listeners=[listener])
338+
client = single_client_noauth(
339+
username="notauser", password="fail",
340+
event_listeners=[listener])
339341
self.addCleanup(client.close)
340342

341343
# Attempt to create a new connection.

test/test_load_balancer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
class TestLB(IntegrationTest):
4040
RUN_ON_LOAD_BALANCER = True
41+
RUN_ON_SERVERLESS = True
4142

4243
def test_connections_are_only_returned_once(self):
4344
pool = get_pool(self.client)
@@ -97,7 +98,6 @@ def _test_no_gc_deadlock(self, create_resource):
9798
"failCommands": [
9899
"find", "aggregate"
99100
],
100-
"errorCode": 91,
101101
"closeConnection": True,
102102
}
103103
}

test/test_unified_format.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
class_name_prefix='UnifiedTestFormat',
3434
expected_failures=[
3535
'Client side error in command starting transaction', # PYTHON-1894
36-
]))
36+
],
37+
RUN_ON_SERVERLESS=False))
3738

3839

3940
globals().update(generate_test_classes(
@@ -43,7 +44,8 @@
4344
bypass_test_generation_errors=True,
4445
expected_failures=[
4546
'.*', # All tests expected to fail
46-
]))
47+
],
48+
RUN_ON_SERVERLESS=False))
4749

4850

4951
class TestMatchEvaluatorUtil(unittest.TestCase):

0 commit comments

Comments
 (0)