PYTHON-3027 Fix server selection when topology type is Unknown (#806)

This commit is contained in:
Shane Harvey 2021-12-02 13:45:50 -08:00 committed by GitHub
parent 046d789d9f
commit 5ec4e6cc4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 5 deletions

View File

@ -263,9 +263,10 @@ class TopologyDescription(object):
selector.min_wire_version,
common_wv))
if self.topology_type in (TOPOLOGY_TYPE.Single,
TOPOLOGY_TYPE.LoadBalanced,
TOPOLOGY_TYPE.Unknown):
if self.topology_type == TOPOLOGY_TYPE.Unknown:
return []
elif self.topology_type in (TOPOLOGY_TYPE.Single,
TOPOLOGY_TYPE.LoadBalanced):
# Ignore selectors for standalone and load balancer mode.
return self.known_servers
elif address:

View File

@ -0,0 +1,52 @@
# Copyright 2021-present MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test connections to RSGhost nodes."""
import datetime
from mockupdb import going, MockupDB
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError
import unittest
class TestRSGhost(unittest.TestCase):
def test_rsghost(self):
rsother_response = {
'ok': 1.0, 'ismaster': False, 'secondary': False,
'info': 'Does not have a valid replica set config',
'isreplicaset': True, 'maxBsonObjectSize': 16777216,
'maxMessageSizeBytes': 48000000, 'maxWriteBatchSize': 100000,
'localTime': datetime.datetime(2021, 11, 30, 0, 53, 4, 99000),
'logicalSessionTimeoutMinutes': 30, 'connectionId': 3,
'minWireVersion': 0, 'maxWireVersion': 15, 'readOnly': False}
server = MockupDB(auto_ismaster=rsother_response)
server.run()
self.addCleanup(server.stop)
# Default auto discovery yields a server selection timeout.
with MongoClient(server.uri, serverSelectionTimeoutMS=250) as client:
with self.assertRaises(ServerSelectionTimeoutError):
client.test.command('ping')
# Direct connection succeeds.
with MongoClient(server.uri, directConnection=True) as client:
with going(client.test.command, 'ping'):
request = server.receives(ping=1)
request.reply()
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,18 @@
{
"topology_description": {
"type": "Unknown",
"servers": [
{
"address": "a:27017",
"avg_rtt_ms": 5,
"type": "RSGhost"
}
]
},
"operation": "read",
"read_preference": {
"mode": "Nearest"
},
"suitable_servers": [],
"in_latency_window": []
}

View File

@ -0,0 +1,18 @@
{
"topology_description": {
"type": "Unknown",
"servers": [
{
"address": "a:27017",
"avg_rtt_ms": 5,
"type": "RSGhost"
}
]
},
"operation": "write",
"read_preference": {
"mode": "Nearest"
},
"suitable_servers": [],
"in_latency_window": []
}

View File

@ -63,7 +63,7 @@ def make_server_description(server, hosts):
return ServerDescription(clean_node(server['address']), Hello({}))
hello_response = {'ok': True, 'hosts': hosts}
if server_type != "Standalone" and server_type != "Mongos":
if server_type not in ("Standalone", "Mongos", "RSGhost"):
hello_response['setName'] = "rs"
if server_type == "RSPrimary":
@ -72,6 +72,10 @@ def make_server_description(server, hosts):
hello_response['secondary'] = True
elif server_type == "Mongos":
hello_response['msg'] = 'isdbgrid'
elif server_type == "RSGhost":
hello_response['isreplicaset'] = True
elif server_type == "RSArbiter":
hello_response['arbiterOnly'] = True
hello_response['lastWrite'] = {
'lastWriteDate': make_last_write_date(server)
@ -149,7 +153,7 @@ def create_topology(scenario_def, **kwargs):
# Assert that descriptions match
assert (scenario_def['topology_description']['type'] ==
topology.description.topology_type_name)
topology.description.topology_type_name), topology.description.topology_type_name
return topology