PYTHON-2791 Ignore erroneous serviceId field for non-LB connections (#663)

This commit is contained in:
Shane Harvey 2021-06-30 18:31:00 -07:00 committed by GitHub
parent 853155dd6a
commit b823b95de1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 4 deletions

View File

@ -616,6 +616,8 @@ class SocketInfo(object):
if self.opts.load_balanced and _MOCK_SERVICE_ID:
process_id = doc.get('topologyVersion', {}).get('processId')
doc.setdefault('serviceId', process_id)
if not self.opts.load_balanced:
doc.pop('serviceId', None)
ismaster = IsMaster(doc, awaitable=awaitable)
self.is_writable = ismaster.is_writable
self.max_wire_version = ismaster.max_wire_version
@ -653,6 +655,9 @@ class SocketInfo(object):
unpacked_docs = reply.unpack_response()
response_doc = unpacked_docs[0]
helpers._check_command_response(response_doc, self.max_wire_version)
# Remove after PYTHON-2712.
if not self.opts.load_balanced:
response_doc.pop('serviceId', None)
return response_doc
def command(self, dbname, spec, slave_ok=False,

View File

@ -361,7 +361,7 @@ def updated_topology_description(topology_description, server_description):
topology_description._topology_settings)
if topology_type == TOPOLOGY_TYPE.Unknown:
if server_type == SERVER_TYPE.Standalone:
if server_type in (SERVER_TYPE.Standalone, SERVER_TYPE.LoadBalancer):
if len(topology_description._topology_settings.seeds) == 1:
topology_type = TOPOLOGY_TYPE.Single
else:

View File

@ -18,6 +18,8 @@ import sys
sys.path[0:0] = [""]
from bson.objectid import ObjectId
from pymongo import common
from pymongo.read_preferences import ReadPreference, Secondary
from pymongo.server_type import SERVER_TYPE
@ -276,7 +278,7 @@ class TestMultiServerTopology(TopologyTest):
'setName': 'rs',
'hosts': ['a', 'b']})
self.assertTrue(
self.assertEqual(
t.description.topology_type_name, 'ReplicaSetWithPrimary')
self.assertTrue(t.description.has_writable_server())
self.assertTrue(t.description.has_readable_server())
@ -301,7 +303,7 @@ class TestMultiServerTopology(TopologyTest):
'setName': 'rs',
'hosts': ['a', 'b']})
self.assertTrue(
self.assertEqual(
t.description.topology_type_name, 'ReplicaSetNoPrimary')
self.assertFalse(t.description.has_writable_server())
self.assertFalse(t.description.has_readable_server())
@ -326,7 +328,7 @@ class TestMultiServerTopology(TopologyTest):
'hosts': ['a', 'b'],
'tags': {'tag': 'exists'}})
self.assertTrue(
self.assertEqual(
t.description.topology_type_name, 'ReplicaSetWithPrimary')
self.assertTrue(t.description.has_writable_server())
self.assertTrue(t.description.has_readable_server())
@ -621,6 +623,26 @@ class TestMultiServerTopology(TopologyTest):
"<ServerDescription ('c', 27017) server_type: Unknown,"
" rtt: None>]>" % (t._topology_id,))
def test_unexpected_load_balancer(self):
# Note: This behavior should not be reachable in practice but we
# should handle it gracefully nonetheless. See PYTHON-2791.
# Load balancers are included in topology with a single seed.
t = create_mock_topology(seeds=['a'])
mock_lb_response = {'ok': 1, 'msg': 'isdbgrid',
'serviceId': ObjectId(), 'maxWireVersion': 13}
got_ismaster(t, ('a', 27017), mock_lb_response)
sds = t.description.server_descriptions()
self.assertIn(('a', 27017), sds)
self.assertEqual(sds[('a', 27017)].server_type_name, 'LoadBalancer')
self.assertEqual(t.description.topology_type_name, 'Single')
self.assertTrue(t.description.has_writable_server())
# Load balancers are removed from a topology with multiple seeds.
t = create_mock_topology(seeds=['a', 'b'])
got_ismaster(t, ('a', 27017), mock_lb_response)
self.assertNotIn(('a', 27017), t.description.server_descriptions())
self.assertEqual(t.description.topology_type_name, 'Unknown')
def wait_for_master(topology):
"""Wait for a Topology to discover a writable server.