Skip to content

Commit d715f58

Browse files
committed
PYTHON-3027 Fix server selection when topology type is Unknown (#806)
(cherry picked from commit 5ec4e6c)
1 parent e3d1d6f commit d715f58

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

pymongo/topology_description.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,10 @@ def apply_selector(self, selector, address=None, custom_selector=None):
263263
selector.min_wire_version,
264264
common_wv))
265265

266-
if self.topology_type in (TOPOLOGY_TYPE.Single,
267-
TOPOLOGY_TYPE.LoadBalanced,
268-
TOPOLOGY_TYPE.Unknown):
266+
if self.topology_type == TOPOLOGY_TYPE.Unknown:
267+
return []
268+
elif self.topology_type in (TOPOLOGY_TYPE.Single,
269+
TOPOLOGY_TYPE.LoadBalanced):
269270
# Ignore selectors for standalone and load balancer mode.
270271
return self.known_servers
271272
elif address:

test/mockupdb/test_rsghost.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2021-present MongoDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Test connections to RSGhost nodes."""
16+
17+
import datetime
18+
19+
from mockupdb import going, MockupDB
20+
from pymongo import MongoClient
21+
from pymongo.errors import ServerSelectionTimeoutError
22+
23+
import unittest
24+
25+
26+
class TestRSGhost(unittest.TestCase):
27+
28+
def test_rsghost(self):
29+
rsother_response = {
30+
'ok': 1.0, 'ismaster': False, 'secondary': False,
31+
'info': 'Does not have a valid replica set config',
32+
'isreplicaset': True, 'maxBsonObjectSize': 16777216,
33+
'maxMessageSizeBytes': 48000000, 'maxWriteBatchSize': 100000,
34+
'localTime': datetime.datetime(2021, 11, 30, 0, 53, 4, 99000),
35+
'logicalSessionTimeoutMinutes': 30, 'connectionId': 3,
36+
'minWireVersion': 0, 'maxWireVersion': 15, 'readOnly': False}
37+
server = MockupDB(auto_ismaster=rsother_response)
38+
server.run()
39+
self.addCleanup(server.stop)
40+
# Default auto discovery yields a server selection timeout.
41+
with MongoClient(server.uri, serverSelectionTimeoutMS=250) as client:
42+
with self.assertRaises(ServerSelectionTimeoutError):
43+
client.test.command('ping')
44+
# Direct connection succeeds.
45+
with MongoClient(server.uri, directConnection=True) as client:
46+
with going(client.test.command, 'ping'):
47+
request = server.receives(ping=1)
48+
request.reply()
49+
50+
51+
if __name__ == '__main__':
52+
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"topology_description": {
3+
"type": "Unknown",
4+
"servers": [
5+
{
6+
"address": "a:27017",
7+
"avg_rtt_ms": 5,
8+
"type": "RSGhost"
9+
}
10+
]
11+
},
12+
"operation": "read",
13+
"read_preference": {
14+
"mode": "Nearest"
15+
},
16+
"suitable_servers": [],
17+
"in_latency_window": []
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"topology_description": {
3+
"type": "Unknown",
4+
"servers": [
5+
{
6+
"address": "a:27017",
7+
"avg_rtt_ms": 5,
8+
"type": "RSGhost"
9+
}
10+
]
11+
},
12+
"operation": "write",
13+
"read_preference": {
14+
"mode": "Nearest"
15+
},
16+
"suitable_servers": [],
17+
"in_latency_window": []
18+
}

test/utils_selection_tests.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def make_server_description(server, hosts):
6363
return ServerDescription(clean_node(server['address']), Hello({}))
6464

6565
hello_response = {'ok': True, 'hosts': hosts}
66-
if server_type != "Standalone" and server_type != "Mongos":
66+
if server_type not in ("Standalone", "Mongos", "RSGhost"):
6767
hello_response['setName'] = "rs"
6868

6969
if server_type == "RSPrimary":
@@ -72,6 +72,10 @@ def make_server_description(server, hosts):
7272
hello_response['secondary'] = True
7373
elif server_type == "Mongos":
7474
hello_response['msg'] = 'isdbgrid'
75+
elif server_type == "RSGhost":
76+
hello_response['isreplicaset'] = True
77+
elif server_type == "RSArbiter":
78+
hello_response['arbiterOnly'] = True
7579

7680
hello_response['lastWrite'] = {
7781
'lastWriteDate': make_last_write_date(server)
@@ -149,7 +153,7 @@ def create_topology(scenario_def, **kwargs):
149153

150154
# Assert that descriptions match
151155
assert (scenario_def['topology_description']['type'] ==
152-
topology.description.topology_type_name)
156+
topology.description.topology_type_name), topology.description.topology_type_name
153157

154158
return topology
155159

0 commit comments

Comments
 (0)