-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PYTHON-2676 Add load balancer tests in EVG #625
Changes from all commits
241f400
492421c
e3a8c88
f557b6c
5e7aaef
a51b4e6
d0b8f4a
cbce828
a35b2aa
fe91291
16c251f
dc940cc
e08c68f
dc3eb57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -411,6 +411,11 @@ functions: | |
if [ -n "${SETDEFAULTENCODING}" ]; then | ||
export SETDEFAULTENCODING="${SETDEFAULTENCODING}" | ||
fi | ||
if [ -n "${test_loadbalancer}" ]; then | ||
export TEST_LOADBALANCER=1 | ||
export SINGLE_MONGOS_LB_URI="${SINGLE_MONGOS_LB_URI}" | ||
export MULTI_MONGOS_LB_URI="${MULTI_MONGOS_LB_URI}" | ||
fi | ||
|
||
PYTHON_BINARY=${PYTHON_BINARY} \ | ||
GREEN_FRAMEWORK=${GREEN_FRAMEWORK} \ | ||
|
@@ -788,6 +793,22 @@ functions: | |
-v \ | ||
--fault revoked | ||
|
||
"run load-balancer": | ||
- command: shell.exec | ||
params: | ||
script: | | ||
DRIVERS_TOOLS=${DRIVERS_TOOLS} MONGODB_URI=${MONGODB_URI} bash ${DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh start | ||
- command: expansions.update | ||
params: | ||
file: lb-expansion.yml | ||
|
||
"stop load-balancer": | ||
- command: shell.exec | ||
params: | ||
script: | | ||
cd ${DRIVERS_TOOLS}/.evergreen | ||
DRIVERS_TOOLS=${DRIVERS_TOOLS} bash ${DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh stop | ||
|
||
"teardown_docker": | ||
- command: shell.exec | ||
params: | ||
|
@@ -1537,6 +1558,13 @@ tasks: | |
- func: "run aws auth test with aws EC2 credentials" | ||
- func: "run aws ECS auth test" | ||
|
||
- name: load-balancer-test | ||
commands: | ||
- func: "bootstrap mongo-orchestration" | ||
vars: | ||
TOPOLOGY: "sharded_cluster" | ||
- func: "run load-balancer" | ||
- func: "run tests" | ||
# }}} | ||
- name: "coverage-report" | ||
tags: ["coverage"] | ||
|
@@ -1941,6 +1969,16 @@ axes: | |
variables: | ||
ORCHESTRATION_FILE: "versioned-api-testing.json" | ||
|
||
# Run load balancer tests? | ||
- id: loadbalancer | ||
display_name: "Load Balancer" | ||
values: | ||
- id: "enabled" | ||
display_name: "Load Balancer" | ||
variables: | ||
test_loadbalancer: true | ||
batchtime: 10080 # 7 days | ||
|
||
buildvariants: | ||
- matrix_name: "tests-all" | ||
matrix_spec: | ||
|
@@ -2463,6 +2501,17 @@ buildvariants: | |
- name: "aws-auth-test-4.4" | ||
- name: "aws-auth-test-latest" | ||
|
||
- matrix_name: "load-balancer" | ||
matrix_spec: | ||
platform: ubuntu-18.04 | ||
mongodb-version: ["latest"] | ||
auth-ssl: "*" | ||
python-version: ["3.6", "3.9"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whats the reason for only testing these Pythons? What about pypy? We needn't change it, but a comment with the rationale will be useful and maybe an accompanying ticket if the testing needs to be expanded at a later point. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now it's just for simplicity. I opened: https://jira.mongodb.org/browse/PYTHON-2731 I might just add all python versions while doing that ticket. |
||
loadbalancer: "*" | ||
display_name: "Load Balancer ${platform} ${python-version} ${mongodb-version} ${auth-ssl}" | ||
tasks: | ||
- name: "load-balancer-test" | ||
|
||
- matrix_name: "Release" | ||
matrix_spec: | ||
platform: [ubuntu-20.04, windows-64-vsMulti-small, macos-1014] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,11 @@ fi | |
if [ "$SSL" != "nossl" ]; then | ||
export CLIENT_PEM="$DRIVERS_TOOLS/.evergreen/x509gen/client.pem" | ||
export CA_PEM="$DRIVERS_TOOLS/.evergreen/x509gen/ca.pem" | ||
|
||
if [ -n "$TEST_LOADBALANCER" ]; then | ||
export SINGLE_MONGOS_LB_URI="${SINGLE_MONGOS_LB_URI}&tls=true" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I cribbed this from the Java driver. I think the underlying issue is that MO does not yet add SSL/TLS parameters to the uri it reports: 10gen/mongo-orchestration#287 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. |
||
export MULTI_MONGOS_LB_URI="${MULTI_MONGOS_LB_URI}&tls=true" | ||
fi | ||
fi | ||
|
||
# For createvirtualenv. | ||
|
@@ -191,7 +196,12 @@ if [ -z "$GREEN_FRAMEWORK" ]; then | |
# causing this script to exit. | ||
$PYTHON -c "from bson import _cbson; from pymongo import _cmessage" | ||
fi | ||
$PYTHON $COVERAGE_ARGS setup.py $C_EXTENSIONS test $TEST_ARGS $OUTPUT | ||
|
||
if [ -n "$TEST_LOADBALANCER" ]; then | ||
$PYTHON -m xmlrunner discover -s test/load_balancer -v --locals -o $XUNIT_DIR | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It prints each function's local variables in stack traces: https://docs.python.org/3/library/unittest.html#cmdoption-unittest-locals So this opaque trace: FAIL: test_a_connection_can_be_shared_by_a_transaction_and_a_cursor (test_load_balancer.TestUnifiedTransactions)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 1087, in test_case
self.run_scenario(spec)
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 1074, in run_scenario
self.check_events(spec.get('expectEvents', []))
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 1026, in check_events
self.match_evaluator.match_event(
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 581, in match_event
self.test.assertIsInstance(actual, ConnectionCheckedInEvent)
AssertionError: ConnectionReadyEvent(('127.0.0.1', 8001), 2) is not an instance of <class 'pymongo.monitoring.ConnectionCheckedInEvent'> Becomes much more diagnosable: FAIL: test_a_connection_can_be_shared_by_a_transaction_and_a_cursor (test_load_balancer.TestUnifiedTransactions)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 1087, in test_case
self.run_scenario(spec)
self = <test_load_balancer.TestUnifiedTransactions testMethod=test_a_connection_can_be_shared_by_a_transaction_and_a_cursor>
spec = {'description': 'a connection can be shared by a transaction and a cursor', 'operations': [{'name': 'startTransaction', 'object': 'session0'}, {'name': 'insertOne', 'object': 'collection0', 'arguments': {'document': {'x': 1}, 'session': 'session0'}}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 1}}, {'name': 'createFindCursor', 'object': 'collection0', 'arguments': {'filter': {}, 'batchSize': 2, 'session': 'session0'}, 'saveResultAsEntity': 'cursor0'}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 1}}, {'name': 'close', 'object': 'cursor0'}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 1}}, {'name': 'abortTransaction', 'object': 'session0'}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 0}}], 'expectEvents': [{'client': 'client0', 'events': [{'commandStartedEvent': {'commandName': 'insert'}}, {'commandStartedEvent': {'commandName': 'find'}}, {'commandStartedEvent': {'commandName': 'killCursors'}}, {'commandStartedEvent': {'commandName': 'abortTransaction'}}]}, {'client': 'client0', 'eventType': 'cmap', 'events': [{'connectionReadyEvent': {}}, {'connectionCheckedOutEvent': {}}, {'connectionCheckedInEvent': {}}]}]}
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 1074, in run_scenario
self.check_events(spec.get('expectEvents', []))
run_on_spec = []
self = <test_load_balancer.TestUnifiedTransactions testMethod=test_a_connection_can_be_shared_by_a_transaction_and_a_cursor>
skip_reason = None
spec = {'description': 'a connection can be shared by a transaction and a cursor', 'operations': [{'name': 'startTransaction', 'object': 'session0'}, {'name': 'insertOne', 'object': 'collection0', 'arguments': {'document': {'x': 1}, 'session': 'session0'}}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 1}}, {'name': 'createFindCursor', 'object': 'collection0', 'arguments': {'filter': {}, 'batchSize': 2, 'session': 'session0'}, 'saveResultAsEntity': 'cursor0'}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 1}}, {'name': 'close', 'object': 'cursor0'}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 1}}, {'name': 'abortTransaction', 'object': 'session0'}, {'name': 'assertNumberConnectionsCheckedOut', 'object': 'testRunner', 'arguments': {'client': 'client0', 'connections': 0}}], 'expectEvents': [{'client': 'client0', 'events': [{'commandStartedEvent': {'commandName': 'insert'}}, {'commandStartedEvent': {'commandName': 'find'}}, {'commandStartedEvent': {'commandName': 'killCursors'}}, {'commandStartedEvent': {'commandName': 'abortTransaction'}}]}, {'client': 'client0', 'eventType': 'cmap', 'events': [{'connectionReadyEvent': {}}, {'connectionCheckedOutEvent': {}}, {'connectionCheckedInEvent': {}}]}]}
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 1026, in check_events
self.match_evaluator.match_event(
actual_events = [ConnectionReadyEvent(('127.0.0.1', 8001), 1), ConnectionCheckedOutEvent(('127.0.0.1', 8001), 1), ConnectionReadyEvent(('127.0.0.1', 8001), 2), ConnectionCheckedOutEvent(('127.0.0.1', 8001), 2), ConnectionCheckedInEvent(('127.0.0.1', 8001), 2), ConnectionCheckedInEvent(('127.0.0.1', 8001), 1)]
client_name = 'client0'
event_spec = {'client': 'client0', 'eventType': 'cmap', 'events': [{'connectionReadyEvent': {}}, {'connectionCheckedOutEvent': {}}, {'connectionCheckedInEvent': {}}]}
event_type = 'cmap'
events = [{'connectionReadyEvent': {}}, {'connectionCheckedOutEvent': {}}, {'connectionCheckedInEvent': {}}]
expected_event = {'connectionCheckedInEvent': {}}
idx = 2
listener = <test.unified_format.EventListenerUtil object at 0x7fc94603f3a0>
self = <test_load_balancer.TestUnifiedTransactions testMethod=test_a_connection_can_be_shared_by_a_transaction_and_a_cursor>
spec = [{'client': 'client0', 'events': [{'commandStartedEvent': {'commandName': 'insert'}}, {'commandStartedEvent': {'commandName': 'find'}}, {'commandStartedEvent': {'commandName': 'killCursors'}}, {'commandStartedEvent': {'commandName': 'abortTransaction'}}]}, {'client': 'client0', 'eventType': 'cmap', 'events': [{'connectionReadyEvent': {}}, {'connectionCheckedOutEvent': {}}, {'connectionCheckedInEvent': {}}]}]
File "/Users/shane/git/mongo-python-driver/test/unified_format.py", line 581, in match_event
self.test.assertIsInstance(actual, ConnectionCheckedInEvent)
actual = ConnectionReadyEvent(('127.0.0.1', 8001), 2)
event_type = 'cmap'
expectation = {'connectionCheckedInEvent': {}}
name = 'connectionCheckedInEvent'
self = <test.unified_format.MatchEvaluatorUtil object at 0x7fc945968cd0>
spec = {}
AssertionError: ConnectionReadyEvent(('127.0.0.1', 8001), 2) is not an instance of <class 'pymongo.monitoring.ConnectionCheckedInEvent'> |
||
else | ||
$PYTHON $COVERAGE_ARGS setup.py $C_EXTENSIONS test $TEST_ARGS $OUTPUT | ||
fi | ||
else | ||
# --no_ext has to come before "test" so there is no way to toggle extensions here. | ||
$PYTHON green_framework_test.py $GREEN_FRAMEWORK $OUTPUT | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1197,15 +1197,16 @@ def _select_server(self, server_selector, session, address=None): | |
server = topology.select_server(server_selector) | ||
# Pin this session to the selected server if it's performing a | ||
# sharded transaction. | ||
if server.description.mongos and (session and | ||
session.in_transaction): | ||
session._pin_mongos(server) | ||
if (server.description.server_type in ( | ||
SERVER_TYPE.Mongos, SERVER_TYPE.LoadBalancer) | ||
and session and session.in_transaction): | ||
session._pin(server) | ||
return server | ||
except PyMongoError as exc: | ||
# Server selection errors in a transaction are transient. | ||
if session and session.in_transaction: | ||
exc._add_error_label("TransientTransactionError") | ||
session._unpin_mongos() | ||
session._unpin() | ||
raise | ||
|
||
def _socket_for_writes(self, session): | ||
|
@@ -1350,7 +1351,7 @@ def is_retrying(): | |
_add_retryable_write_error(exc, max_wire_version) | ||
retryable_error = exc.has_error_label("RetryableWriteError") | ||
if retryable_error: | ||
session._unpin_mongos() | ||
session._unpin() | ||
if is_retrying() or not retryable_error: | ||
raise | ||
if bulk: | ||
|
@@ -1965,7 +1966,7 @@ def _add_retryable_write_error(exc, max_wire_version): | |
class _MongoClientErrorHandler(object): | ||
"""Handle errors raised when executing an operation.""" | ||
__slots__ = ('client', 'server_address', 'session', 'max_wire_version', | ||
'sock_generation', 'completed_handshake') | ||
'sock_generation', 'completed_handshake', 'service_id') | ||
|
||
def __init__(self, client, server, session): | ||
self.client = client | ||
|
@@ -1978,11 +1979,13 @@ def __init__(self, client, server, session): | |
# of the pool at the time the connection attempt was started." | ||
self.sock_generation = server.pool.generation | ||
self.completed_handshake = False | ||
self.service_id = None | ||
|
||
def contribute_socket(self, sock_info): | ||
"""Provide socket information to the error handler.""" | ||
self.max_wire_version = sock_info.max_wire_version | ||
self.sock_generation = sock_info.generation | ||
self.service_id = sock_info.service_id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's always |
||
self.completed_handshake = True | ||
|
||
def __enter__(self): | ||
|
@@ -2001,9 +2004,9 @@ def __exit__(self, exc_type, exc_val, exc_tb): | |
if issubclass(exc_type, PyMongoError): | ||
if (exc_val.has_error_label("TransientTransactionError") or | ||
exc_val.has_error_label("RetryableWriteError")): | ||
self.session._unpin_mongos() | ||
self.session._unpin() | ||
|
||
err_ctx = _ErrorContext( | ||
exc_val, self.max_wire_version, self.sock_generation, | ||
self.completed_handshake) | ||
self.completed_handshake, self.service_id) | ||
self.client._topology.handle_error(self.server_address, err_ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How/where is this being used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
run-load-balancer.sh creates this file, see: https://github.com/mongodb/specifications/blob/master/source/load-balancers/tests/README.rst