mongo 2.8.0 → 2.9.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Rakefile +12 -0
- data/lib/mongo.rb +15 -1
- data/lib/mongo/address/ipv6.rb +0 -2
- data/lib/mongo/auth/scram/conversation.rb +0 -3
- data/lib/mongo/bulk_write/result_combiner.rb +12 -2
- data/lib/mongo/client.rb +59 -6
- data/lib/mongo/cluster.rb +19 -8
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +0 -2
- data/lib/mongo/cluster/reapers/socket_reaper.rb +12 -9
- data/lib/mongo/collection.rb +1 -1
- data/lib/mongo/collection/view/aggregation.rb +5 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +30 -10
- data/lib/mongo/collection/view/iterable.rb +13 -6
- data/lib/mongo/collection/view/map_reduce.rb +12 -10
- data/lib/mongo/collection/view/readable.rb +19 -14
- data/lib/mongo/cursor.rb +12 -8
- data/lib/mongo/database.rb +10 -7
- data/lib/mongo/database/view.rb +18 -11
- data/lib/mongo/error.rb +2 -2
- data/lib/mongo/error/connection_check_out_timeout.rb +49 -0
- data/lib/mongo/error/operation_failure.rb +9 -9
- data/lib/mongo/error/parser.rb +25 -3
- data/lib/mongo/error/pool_closed_error.rb +43 -0
- data/lib/mongo/error/sdam_error_detection.rb +18 -0
- data/lib/mongo/grid/file/chunk.rb +0 -2
- data/lib/mongo/grid/fs_bucket.rb +26 -12
- data/lib/mongo/grid/stream/read.rb +36 -21
- data/lib/mongo/index/view.rb +11 -7
- data/lib/mongo/logger.rb +0 -2
- data/lib/mongo/monitoring.rb +31 -0
- data/lib/mongo/monitoring/cmap_log_subscriber.rb +53 -0
- data/lib/mongo/monitoring/event.rb +1 -0
- data/lib/mongo/monitoring/event/cmap.rb +25 -0
- data/lib/mongo/monitoring/event/cmap/base.rb +28 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +78 -0
- data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +56 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +63 -0
- data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +64 -0
- data/lib/mongo/monitoring/event/cmap/connection_closed.rb +103 -0
- data/lib/mongo/monitoring/event/cmap/connection_created.rb +64 -0
- data/lib/mongo/monitoring/event/cmap/connection_ready.rb +64 -0
- data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +57 -0
- data/lib/mongo/monitoring/event/cmap/pool_closed.rb +57 -0
- data/lib/mongo/monitoring/event/cmap/pool_created.rb +63 -0
- data/lib/mongo/monitoring/event/command_started.rb +12 -3
- data/lib/mongo/monitoring/publishable.rb +10 -2
- data/lib/mongo/operation.rb +0 -1
- data/lib/mongo/operation/find/legacy/result.rb +1 -0
- data/lib/mongo/operation/list_collections/result.rb +7 -1
- data/lib/mongo/operation/result.rb +10 -1
- data/lib/mongo/operation/shared/executable.rb +15 -0
- data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +29 -0
- data/lib/mongo/operation/shared/specifiable.rb +0 -16
- data/lib/mongo/operation/update/legacy/result.rb +1 -0
- data/lib/mongo/protocol/compressed.rb +0 -2
- data/lib/mongo/protocol/msg.rb +25 -2
- data/lib/mongo/retryable.rb +171 -33
- data/lib/mongo/server.rb +26 -7
- data/lib/mongo/server/app_metadata.rb +0 -2
- data/lib/mongo/server/connectable.rb +8 -2
- data/lib/mongo/server/connection.rb +83 -13
- data/lib/mongo/server/connection_base.rb +1 -1
- data/lib/mongo/server/connection_pool.rb +439 -43
- data/lib/mongo/server/monitor/connection.rb +4 -1
- data/lib/mongo/session.rb +37 -5
- data/lib/mongo/session/session_pool.rb +2 -2
- data/lib/mongo/socket.rb +0 -2
- data/lib/mongo/socket/ssl.rb +0 -2
- data/lib/mongo/uri.rb +127 -66
- data/lib/mongo/uri/srv_protocol.rb +35 -13
- data/lib/mongo/version.rb +1 -1
- data/spec/README.md +190 -63
- data/spec/integration/change_stream_spec.rb +64 -0
- data/spec/integration/command_spec.rb +0 -7
- data/spec/integration/error_detection_spec.rb +39 -0
- data/spec/integration/read_concern.rb +83 -0
- data/spec/integration/retryable_writes_spec.rb +6 -50
- data/spec/integration/sdam_error_handling_spec.rb +60 -7
- data/spec/integration/ssl_uri_options_spec.rb +24 -0
- data/spec/integration/step_down_spec.rb +197 -0
- data/spec/lite_spec_helper.rb +4 -0
- data/spec/mongo/client_construction_spec.rb +42 -17
- data/spec/mongo/client_spec.rb +32 -1
- data/spec/mongo/cluster/socket_reaper_spec.rb +2 -2
- data/spec/mongo/cluster_spec.rb +36 -2
- data/spec/mongo/collection/view/aggregation_spec.rb +2 -0
- data/spec/mongo/collection/view/change_stream_spec.rb +28 -28
- data/spec/mongo/collection/view/readable_spec.rb +1 -1
- data/spec/mongo/collection/view_spec.rb +3 -1
- data/spec/mongo/cursor_spec.rb +5 -5
- data/spec/mongo/error/parser_spec.rb +61 -1
- data/spec/mongo/grid/stream/read_spec.rb +2 -2
- data/spec/mongo/monitoring/event/cmap/connection_check_out_failed_spec.rb +23 -0
- data/spec/mongo/monitoring/event/cmap/connection_check_out_started_spec.rb +19 -0
- data/spec/mongo/monitoring/event/cmap/connection_checked_in_spec.rb +23 -0
- data/spec/mongo/monitoring/event/cmap/connection_checked_out_spec.rb +23 -0
- data/spec/mongo/monitoring/event/cmap/connection_closed_spec.rb +27 -0
- data/spec/mongo/monitoring/event/cmap/connection_created_spec.rb +24 -0
- data/spec/mongo/monitoring/event/cmap/connection_ready_spec.rb +24 -0
- data/spec/mongo/monitoring/event/cmap/pool_cleared_spec.rb +19 -0
- data/spec/mongo/monitoring/event/cmap/pool_closed_spec.rb +19 -0
- data/spec/mongo/monitoring/event/cmap/pool_created_spec.rb +26 -0
- data/spec/mongo/operation/delete/bulk_spec.rb +1 -6
- data/spec/mongo/operation/delete/command_spec.rb +1 -1
- data/spec/mongo/operation/delete/op_msg_spec.rb +1 -1
- data/spec/mongo/operation/delete_spec.rb +4 -4
- data/spec/mongo/operation/insert/bulk_spec.rb +1 -1
- data/spec/mongo/operation/insert/command_spec.rb +1 -1
- data/spec/mongo/operation/insert/op_msg_spec.rb +1 -1
- data/spec/mongo/operation/update/bulk_spec.rb +1 -1
- data/spec/mongo/operation/update/command_spec.rb +2 -2
- data/spec/mongo/operation/update/op_msg_spec.rb +2 -2
- data/spec/mongo/protocol/msg_spec.rb +11 -0
- data/spec/mongo/retryable_spec.rb +78 -25
- data/spec/mongo/server/connection_pool_spec.rb +661 -126
- data/spec/mongo/server/connection_spec.rb +55 -7
- data/spec/mongo/server_spec.rb +5 -0
- data/spec/mongo/uri/srv_protocol_spec.rb +135 -2
- data/spec/mongo/uri_option_parsing_spec.rb +511 -0
- data/spec/mongo/uri_spec.rb +42 -6
- data/spec/spec_helper.rb +1 -84
- data/spec/spec_tests/cmap_spec.rb +50 -0
- data/spec/spec_tests/command_monitoring_spec.rb +7 -18
- data/spec/spec_tests/crud_spec.rb +3 -49
- data/spec/spec_tests/data/cmap/connection-must-have-id.yml +21 -0
- data/spec/spec_tests/data/cmap/connection-must-order-ids.yml +21 -0
- data/spec/spec_tests/data/cmap/pool-checkin-destroy-closed.yml +24 -0
- data/spec/spec_tests/data/cmap/pool-checkin-destroy-stale.yml +24 -0
- data/spec/spec_tests/data/cmap/pool-checkin-make-available.yml +21 -0
- data/spec/spec_tests/data/cmap/pool-checkin.yml +18 -0
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +13 -0
- data/spec/spec_tests/data/cmap/pool-checkout-error-closed.yml +28 -0
- data/spec/spec_tests/data/cmap/pool-checkout-multiple.yml +34 -0
- data/spec/spec_tests/data/cmap/pool-checkout-no-idle.yml +31 -0
- data/spec/spec_tests/data/cmap/pool-checkout-no-stale.yml +29 -0
- data/spec/spec_tests/data/cmap/pool-close-destroy-conns.yml +26 -0
- data/spec/spec_tests/data/cmap/pool-close.yml +11 -0
- data/spec/spec_tests/data/cmap/pool-create-max-size.yml +56 -0
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +27 -0
- data/spec/spec_tests/data/cmap/pool-create-with-options.yml +20 -0
- data/spec/spec_tests/data/cmap/pool-create.yml +12 -0
- data/spec/spec_tests/data/cmap/wait-queue-fairness.yml +94 -0
- data/spec/spec_tests/data/cmap/wait-queue-timeout.yml +41 -0
- data/spec/spec_tests/data/retryable_reads/aggregate-serverErrors.yml +157 -0
- data/spec/spec_tests/data/retryable_reads/aggregate.yml +87 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch-serverErrors.yml +149 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-client.watch.yml +61 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch-serverErrors.yml +149 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.coll.watch.yml +65 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch-serverErrors.yml +153 -0
- data/spec/spec_tests/data/retryable_reads/changeStreams-db.watch.yml +61 -0
- data/spec/spec_tests/data/retryable_reads/count-serverErrors.yml +150 -0
- data/spec/spec_tests/data/retryable_reads/count.yml +64 -0
- data/spec/spec_tests/data/retryable_reads/countDocuments-serverErrors.yml +150 -0
- data/spec/spec_tests/data/retryable_reads/countDocuments.yml +64 -0
- data/spec/spec_tests/data/retryable_reads/distinct-serverErrors.yml +156 -0
- data/spec/spec_tests/data/retryable_reads/distinct.yml +71 -0
- data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors.yml +148 -0
- data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount.yml +62 -0
- data/spec/spec_tests/data/retryable_reads/find-serverErrors.yml +160 -0
- data/spec/spec_tests/data/retryable_reads/find.yml +86 -0
- data/spec/spec_tests/data/retryable_reads/findOne-serverErrors.yml +154 -0
- data/spec/spec_tests/data/retryable_reads/findOne.yml +68 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-download-serverErrors.yml +173 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-download.yml +79 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName-serverErrors.yml +174 -0
- data/spec/spec_tests/data/retryable_reads/gridfs-downloadByName.yml +79 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionNames-serverErrors.yml +143 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionNames.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionObjects-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listCollectionObjects.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listCollections-serverErrors.yml +143 -0
- data/spec/spec_tests/data/retryable_reads/listCollections.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseNames-serverErrors.yml +143 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseNames.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseObjects-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listDatabaseObjects.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listDatabases-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listDatabases.yml +59 -0
- data/spec/spec_tests/data/retryable_reads/listIndexNames-serverErrors.yml +144 -0
- data/spec/spec_tests/data/retryable_reads/listIndexNames.yml +60 -0
- data/spec/spec_tests/data/retryable_reads/listIndexes-serverErrors.yml +145 -0
- data/spec/spec_tests/data/retryable_reads/listIndexes.yml +60 -0
- data/spec/spec_tests/data/retryable_reads/mapReduce.yml +60 -0
- data/spec/spec_tests/data/retryable_writes/bulkWrite-serverErrors.yml +10 -7
- data/spec/spec_tests/data/retryable_writes/bulkWrite.yml +15 -22
- data/spec/spec_tests/data/retryable_writes/deleteMany.yml +22 -0
- data/spec/spec_tests/data/retryable_writes/deleteOne-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/deleteOne.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/findOneAndDelete-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/findOneAndDelete.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/findOneAndReplace-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/findOneAndReplace.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/findOneAndUpdate.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/insertMany-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/insertMany.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +10 -45
- data/spec/spec_tests/data/retryable_writes/insertOne.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/replaceOne-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/replaceOne.yml +5 -8
- data/spec/spec_tests/data/retryable_writes/updateMany.yml +27 -0
- data/spec/spec_tests/data/retryable_writes/updateOne-serverErrors.yml +8 -7
- data/spec/spec_tests/data/retryable_writes/updateOne.yml +5 -14
- data/spec/spec_tests/data/transactions/abort.yml +7 -2
- data/spec/spec_tests/data/transactions/bulk.yml +7 -2
- data/spec/spec_tests/data/transactions/causal-consistency.yml +11 -4
- data/spec/spec_tests/data/transactions/commit.yml +11 -4
- data/spec/spec_tests/data/transactions/count.yml +64 -0
- data/spec/spec_tests/data/transactions/delete.yml +7 -2
- data/spec/spec_tests/data/transactions/error-labels.yml +8 -2
- data/spec/spec_tests/data/transactions/errors.yml +7 -2
- data/spec/spec_tests/data/transactions/findOneAndDelete.yml +7 -2
- data/spec/spec_tests/data/transactions/findOneAndReplace.yml +7 -2
- data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +7 -2
- data/spec/spec_tests/data/transactions/insert.yml +9 -2
- data/spec/spec_tests/data/transactions/isolation.yml +7 -2
- data/spec/spec_tests/data/transactions/read-concern.yml +15 -6
- data/spec/spec_tests/data/transactions/read-pref.yml +7 -2
- data/spec/spec_tests/data/transactions/reads.yml +8 -48
- data/spec/spec_tests/data/transactions/retryable-abort.yml +7 -2
- data/spec/spec_tests/data/transactions/retryable-commit.yml +7 -2
- data/spec/spec_tests/data/transactions/retryable-writes.yml +7 -2
- data/spec/spec_tests/data/transactions/run-command.yml +7 -2
- data/spec/spec_tests/data/transactions/transaction-options.yml +7 -2
- data/spec/spec_tests/data/transactions/update.yml +7 -2
- data/spec/spec_tests/data/transactions/write-concern.yml +7 -2
- data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -1
- data/spec/spec_tests/data/transactions_api/callback-commits.yml +6 -1
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit-retry.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +6 -3
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +6 -1
- data/spec/spec_tests/data/transactions_api/commit.yml +6 -1
- data/spec/spec_tests/data/transactions_api/transaction-options.yml +6 -1
- data/spec/spec_tests/retryable_reads_spec.rb +11 -0
- data/spec/spec_tests/retryable_writes_spec.rb +4 -69
- data/spec/spec_tests/transactions_api_spec.rb +42 -37
- data/spec/spec_tests/transactions_spec.rb +42 -33
- data/spec/support/authorization.rb +12 -0
- data/spec/support/change_streams/operation.rb +1 -1
- data/spec/support/client_registry.rb +20 -0
- data/spec/support/cluster_config.rb +16 -15
- data/spec/support/cluster_tools.rb +346 -0
- data/spec/support/cmap.rb +367 -0
- data/spec/support/cmap/verifier.rb +46 -0
- data/spec/support/command_monitoring.rb +4 -6
- data/spec/support/common_shortcuts.rb +6 -0
- data/spec/support/connection_string.rb +2 -2
- data/spec/support/crud.rb +171 -184
- data/spec/support/crud/operation.rb +43 -0
- data/spec/support/crud/outcome.rb +53 -0
- data/spec/support/crud/read.rb +102 -12
- data/spec/support/crud/requirement.rb +69 -0
- data/spec/support/crud/spec.rb +68 -0
- data/spec/support/crud/test.rb +141 -0
- data/spec/support/crud/verifier.rb +96 -18
- data/spec/support/crud/write.rb +18 -3
- data/spec/support/event_subscriber.rb +15 -0
- data/spec/support/primary_socket.rb +2 -2
- data/spec/support/spec_config.rb +89 -20
- data/spec/support/transactions.rb +2 -306
- data/spec/support/transactions/operation.rb +7 -7
- data/spec/support/transactions/spec.rb +28 -0
- data/spec/support/transactions/test.rb +191 -0
- data/spec/support/utils.rb +123 -0
- metadata +202 -9
- metadata.gz.sig +0 -0
- data/lib/mongo/server/connection_pool/queue.rb +0 -359
- data/spec/mongo/server/connection_pool/queue_spec.rb +0 -353
- data/spec/support/transactions/verifier.rb +0 -97
@@ -179,10 +179,13 @@ module Mongo
|
|
179
179
|
# @note This method mutates the connection by setting the socket to nil
|
180
180
|
# if the closing succeeded.
|
181
181
|
#
|
182
|
+
# @note This method accepts an options argument for compatibility with
|
183
|
+
# Server::Connections. However, all options are ignored.
|
184
|
+
#
|
182
185
|
# @return [ true ] If the disconnect succeeded.
|
183
186
|
#
|
184
187
|
# @since 2.0.0
|
185
|
-
def disconnect!
|
188
|
+
def disconnect!(options = nil)
|
186
189
|
if socket
|
187
190
|
socket.close
|
188
191
|
@socket = nil
|
data/lib/mongo/session.rb
CHANGED
@@ -443,6 +443,26 @@ module Mongo
|
|
443
443
|
end
|
444
444
|
end
|
445
445
|
|
446
|
+
# Whether reads executed with this session can be retried according to
|
447
|
+
# the modern retryable reads specification.
|
448
|
+
#
|
449
|
+
# If this method returns true, the modern retryable reads have been
|
450
|
+
# requested by the application. If the server selected for a read operation
|
451
|
+
# supports modern retryable reads, they will be used for that particular
|
452
|
+
# operation. If the server selected for a read operation does not support
|
453
|
+
# modern retryable reads, the read will not be retried.
|
454
|
+
#
|
455
|
+
# If this method returns false, legacy retryable reads have been requested
|
456
|
+
# by the application. Legacy retryable read logic will be used regardless
|
457
|
+
# of server version of the server(s) that the client is connected to.
|
458
|
+
# The number of read retries is given by :max_read_retries client option,
|
459
|
+
# which is 1 by default and can be set to 0 to disable legacy read retries.
|
460
|
+
#
|
461
|
+
# @api private
|
462
|
+
def retry_reads?
|
463
|
+
client.options[:retry_reads] != false
|
464
|
+
end
|
465
|
+
|
446
466
|
# Will writes executed with this session be retried.
|
447
467
|
#
|
448
468
|
# @example Will writes be retried.
|
@@ -874,6 +894,23 @@ module Mongo
|
|
874
894
|
@client.cluster
|
875
895
|
end
|
876
896
|
|
897
|
+
protected
|
898
|
+
|
899
|
+
# Get the read concern the session will use when starting a transaction.
|
900
|
+
#
|
901
|
+
# This is a driver style hash with underscore keys.
|
902
|
+
#
|
903
|
+
# @example Get the session's transaction read concern.
|
904
|
+
# session.txn_read_concern
|
905
|
+
#
|
906
|
+
# @return [ Hash ] The read concern used for starting transactions.
|
907
|
+
#
|
908
|
+
# @since 2.9.0
|
909
|
+
def txn_read_concern
|
910
|
+
# Read concern is inherited from client but not db or collection.
|
911
|
+
txn_options && txn_options[:read_concern] || @client.read_concern
|
912
|
+
end
|
913
|
+
|
877
914
|
private
|
878
915
|
|
879
916
|
def within_states?(*states)
|
@@ -891,11 +928,6 @@ module Mongo
|
|
891
928
|
Mongo::Error::InvalidTransactionOperation::NO_TRANSACTION_STARTED)
|
892
929
|
end
|
893
930
|
|
894
|
-
def txn_read_concern
|
895
|
-
# Read concern is inherited from client but not db or collection.
|
896
|
-
txn_options && txn_options[:read_concern] || @client.read_concern
|
897
|
-
end
|
898
|
-
|
899
931
|
def txn_write_concern
|
900
932
|
(txn_options && txn_options[:write_concern]) ||
|
901
933
|
(@client.write_concern && @client.write_concern.options)
|
@@ -64,9 +64,9 @@ module Mongo
|
|
64
64
|
"#<Mongo::Session::SessionPool:0x#{object_id} current_size=#{@queue.size}>"
|
65
65
|
end
|
66
66
|
|
67
|
-
#
|
67
|
+
# Check out a server session from the pool.
|
68
68
|
#
|
69
|
-
# @example
|
69
|
+
# @example Check out a session.
|
70
70
|
# pool.checkout
|
71
71
|
#
|
72
72
|
# @return [ ServerSession ] The server session.
|
data/lib/mongo/socket.rb
CHANGED
data/lib/mongo/socket/ssl.rb
CHANGED
data/lib/mongo/uri.rb
CHANGED
@@ -12,8 +12,6 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require 'uri'
|
16
|
-
|
17
15
|
module Mongo
|
18
16
|
|
19
17
|
# The URI class provides a way for users to parse the MongoDB uri as
|
@@ -260,6 +258,9 @@ module Mongo
|
|
260
258
|
@options = options
|
261
259
|
parsed_scheme, _, remaining = string.partition(SCHEME_DELIM)
|
262
260
|
raise_invalid_error!(INVALID_SCHEME) unless parsed_scheme == scheme
|
261
|
+
if remaining.empty?
|
262
|
+
raise_invalid_error!('No hosts in the URI')
|
263
|
+
end
|
263
264
|
parse!(remaining)
|
264
265
|
|
265
266
|
# The URI options spec requires that we raise an error if there are conflicting values of
|
@@ -283,6 +284,12 @@ module Mongo
|
|
283
284
|
raise_invalid_error_no_fmt!("tlsInsecure' and 'tlsAllowInvalidHostnames' cannot both be specified")
|
284
285
|
end
|
285
286
|
end
|
287
|
+
|
288
|
+
# Since we know that the only URI option that sets :ssl_cert is "tlsCertificateKeyFile", any
|
289
|
+
# value set for :ssl_cert must also be set for :ssl_key.
|
290
|
+
if @uri_options[:ssl_cert]
|
291
|
+
@uri_options[:ssl_key] = @uri_options[:ssl_cert]
|
292
|
+
end
|
286
293
|
end
|
287
294
|
|
288
295
|
# Get the credentials provided in the URI.
|
@@ -317,17 +324,38 @@ module Mongo
|
|
317
324
|
MONGODB_SCHEME
|
318
325
|
end
|
319
326
|
|
320
|
-
def
|
321
|
-
|
327
|
+
def parse!(remaining)
|
328
|
+
hosts_and_db, options = remaining.split('?', 2)
|
329
|
+
if options && options.index('?')
|
330
|
+
raise_invalid_error!("Options contain an unescaped question mark (?), or the database name contains a question mark and was not escaped")
|
331
|
+
end
|
332
|
+
|
333
|
+
if options && !hosts_and_db.index('/')
|
334
|
+
raise_invalid_error!("MongoDB URI must have a slash (/) after the hosts if options are given")
|
335
|
+
end
|
336
|
+
|
337
|
+
hosts, db = hosts_and_db.split('/', 2)
|
338
|
+
if db && db.index('/')
|
339
|
+
raise_invalid_error!("Database name contains an unescaped slash (/): #{db}")
|
340
|
+
end
|
341
|
+
|
342
|
+
if hosts.index('@')
|
343
|
+
creds, hosts = hosts.split('@', 2)
|
344
|
+
if hosts.empty?
|
345
|
+
raise_invalid_error!("Empty hosts list")
|
346
|
+
end
|
347
|
+
if hosts.index('@')
|
348
|
+
raise_invalid_error!("Unescaped @ in auth info")
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
322
352
|
@servers = parse_servers!(hosts)
|
323
353
|
@user = parse_user!(creds)
|
324
354
|
@password = parse_password!(creds)
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
parse_creds_hosts!(creds_hosts)
|
330
|
-
parse_db_opts!(db_opts)
|
355
|
+
@uri_options = Options::Redacted.new(parse_uri_options!(options))
|
356
|
+
if db
|
357
|
+
@database = parse_database!(db)
|
358
|
+
end
|
331
359
|
end
|
332
360
|
|
333
361
|
def extract_db_opts!(string)
|
@@ -339,28 +367,23 @@ module Mongo
|
|
339
367
|
[ creds_hosts, db_opts ].map { |s| s.reverse }
|
340
368
|
end
|
341
369
|
|
342
|
-
def split_creds_hosts(string)
|
343
|
-
hosts, _, creds = string.reverse.partition(AUTH_DELIM)
|
344
|
-
hosts, creds = creds, hosts if hosts.empty?
|
345
|
-
[ hosts, creds ].map { |s| s.reverse }
|
346
|
-
end
|
347
|
-
|
348
|
-
def parse_db_opts!(string)
|
349
|
-
auth_db, _, uri_opts = string.partition(URI_OPTS_DELIM)
|
350
|
-
@uri_options = Options::Redacted.new(parse_uri_options!(uri_opts))
|
351
|
-
@database = parse_database!(auth_db)
|
352
|
-
end
|
353
|
-
|
354
370
|
def parse_uri_options!(string)
|
355
371
|
return {} unless string
|
356
372
|
string.split(INDIV_URI_OPTS_DELIM).reduce({}) do |uri_options, opt|
|
357
|
-
|
358
|
-
|
373
|
+
key, value = opt.split('=', 2)
|
374
|
+
if value.nil?
|
375
|
+
raise_invalid_error!("Option #{key} has no value")
|
376
|
+
end
|
377
|
+
if value.index('=')
|
378
|
+
raise_invalid_error!("Value for option #{key} contains the key/value delimiter (=): #{value}")
|
379
|
+
end
|
380
|
+
key = ::URI.decode(key)
|
359
381
|
strategy = URI_OPTION_MAP[key.downcase]
|
360
382
|
if strategy.nil?
|
361
383
|
log_warn("Unsupported URI option '#{key}' on URI '#{@string}'. It will be ignored.")
|
362
384
|
else
|
363
|
-
|
385
|
+
value = ::URI.decode(value)
|
386
|
+
add_uri_option(key, strategy, value, uri_options)
|
364
387
|
end
|
365
388
|
uri_options
|
366
389
|
end
|
@@ -465,10 +488,10 @@ module Mongo
|
|
465
488
|
uri_option 'maxidletimems', :max_idle_time, :type => :max_idle_time
|
466
489
|
|
467
490
|
# Write Options
|
468
|
-
uri_option 'w', :w, :group => :write
|
491
|
+
uri_option 'w', :w, :group => :write, type: :w
|
469
492
|
uri_option 'journal', :j, :group => :write, :type => :journal
|
470
|
-
uri_option 'fsync', :fsync, :group => :write
|
471
|
-
uri_option 'wtimeoutms', :
|
493
|
+
uri_option 'fsync', :fsync, :group => :write, type: :bool
|
494
|
+
uri_option 'wtimeoutms', :wtimeout, :group => :write, :type => :wtimeout
|
472
495
|
|
473
496
|
# Read Options
|
474
497
|
uri_option 'readpreference', :mode, :group => :read, :type => :read_mode
|
@@ -493,7 +516,7 @@ module Mongo
|
|
493
516
|
uri_option 'tlsinsecure', :ssl_verify, :type => :ssl_verify
|
494
517
|
|
495
518
|
# Topology options
|
496
|
-
uri_option 'connect', :connect
|
519
|
+
uri_option 'connect', :connect, type: :symbol
|
497
520
|
|
498
521
|
# Auth Options
|
499
522
|
uri_option 'authsource', :auth_source, :type => :auth_source
|
@@ -503,38 +526,25 @@ module Mongo
|
|
503
526
|
# Client Options
|
504
527
|
uri_option 'appname', :app_name
|
505
528
|
uri_option 'compressors', :compressors, :type => :array
|
506
|
-
uri_option 'readconcernlevel', :read_concern
|
529
|
+
uri_option 'readconcernlevel', :level, group: :read_concern
|
507
530
|
uri_option 'retrywrites', :retry_writes, :type => :retry_writes
|
508
531
|
uri_option 'zlibcompressionlevel', :zlib_compression_level, :type => :zlib_compression_level
|
509
532
|
|
510
|
-
# Casts option values that do not have a specifically provided
|
511
|
-
# transformation to the appropriate type.
|
512
|
-
#
|
513
|
-
# @param value [String] The value to be cast.
|
514
|
-
#
|
515
|
-
# @return [true, false, Fixnum, Symbol] The cast value.
|
516
|
-
def cast(value)
|
517
|
-
if value == 'true'
|
518
|
-
true
|
519
|
-
elsif value == 'false'
|
520
|
-
false
|
521
|
-
elsif value =~ /\A[\d]\z/
|
522
|
-
value.to_i
|
523
|
-
else
|
524
|
-
decode(value).to_sym
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
533
|
# Applies URI value transformation by either using the default cast
|
529
534
|
# or a transformation appropriate for the given type.
|
530
535
|
#
|
536
|
+
# @param key [String] URI option name.
|
531
537
|
# @param value [String] The value to be transformed.
|
532
538
|
# @param type [Symbol] The transform method.
|
533
|
-
def apply_transform(value, type
|
539
|
+
def apply_transform(key, value, type)
|
534
540
|
if type
|
535
|
-
|
541
|
+
if respond_to?("convert_#{type}", true)
|
542
|
+
send("convert_#{type}", key, value)
|
543
|
+
else
|
544
|
+
send(type, value)
|
545
|
+
end
|
536
546
|
else
|
537
|
-
|
547
|
+
value
|
538
548
|
end
|
539
549
|
end
|
540
550
|
|
@@ -581,12 +591,13 @@ module Mongo
|
|
581
591
|
# Transforms the value.
|
582
592
|
# Merges the option into the target.
|
583
593
|
#
|
594
|
+
# @param key [String] URI option name.
|
584
595
|
# @param strategy [Symbol] The strategy for this option.
|
585
596
|
# @param value [String] The value of the option.
|
586
597
|
# @param uri_options [Hash] The base option target.
|
587
|
-
def add_uri_option(strategy, value, uri_options)
|
598
|
+
def add_uri_option(key, strategy, value, uri_options)
|
588
599
|
target = select_target(uri_options, strategy[:group])
|
589
|
-
value = apply_transform(value, strategy[:type])
|
600
|
+
value = apply_transform(key, value, strategy[:type])
|
590
601
|
merge_uri_option(target, value, strategy[:name])
|
591
602
|
end
|
592
603
|
|
@@ -656,7 +667,7 @@ module Mongo
|
|
656
667
|
properties = hash_extractor('authMechanismProperties', value)
|
657
668
|
if properties[:canonicalize_host_name]
|
658
669
|
properties.merge!(canonicalize_host_name:
|
659
|
-
|
670
|
+
%w(true TRUE).include?(properties[:canonicalize_host_name]))
|
660
671
|
end
|
661
672
|
properties
|
662
673
|
end
|
@@ -718,7 +729,7 @@ module Mongo
|
|
718
729
|
# @return [ true | false | nil ] The journal value parsed out, otherwise nil (and a warning
|
719
730
|
# will be logged).
|
720
731
|
def journal(value)
|
721
|
-
|
732
|
+
convert_bool('journal', value)
|
722
733
|
end
|
723
734
|
|
724
735
|
# Parses the ssl value from the URI.
|
@@ -728,7 +739,7 @@ module Mongo
|
|
728
739
|
# @return [ Array<true | false> ] The ssl value parsed out (stored in an array to facilitate
|
729
740
|
# keeping track of all values).
|
730
741
|
def ssl(value)
|
731
|
-
[
|
742
|
+
[convert_bool('ssl', value)]
|
732
743
|
end
|
733
744
|
|
734
745
|
# Parses the tls value from the URI.
|
@@ -738,7 +749,7 @@ module Mongo
|
|
738
749
|
# @return [ Array<true | false> ] The tls value parsed out (stored in an array to facilitate
|
739
750
|
# keeping track of all values).
|
740
751
|
def tls(value)
|
741
|
-
[
|
752
|
+
[convert_bool('tls', value)]
|
742
753
|
end
|
743
754
|
|
744
755
|
# Parses the ssl_verify value from the tlsInsecure URI value. Note that this will be the inverse
|
@@ -781,20 +792,70 @@ module Mongo
|
|
781
792
|
# @return [ true | false | nil ] The boolean value parsed out, otherwise nil (and a warning
|
782
793
|
# will be logged).
|
783
794
|
def retry_writes(value)
|
784
|
-
|
795
|
+
convert_bool('retryWrites', value)
|
785
796
|
end
|
786
797
|
|
787
|
-
#
|
798
|
+
# Converts +value+ into an integer.
|
788
799
|
#
|
789
|
-
#
|
800
|
+
# If the value is not a valid integer, warns and returns nil.
|
790
801
|
#
|
791
|
-
# @
|
792
|
-
#
|
793
|
-
|
802
|
+
# @param name [ String ] Name of the URI option being processed.
|
803
|
+
# @param value [ String ] URI option value.
|
804
|
+
#
|
805
|
+
# @return [ nil | Integer ] Converted value.
|
806
|
+
def convert_integer(name, value)
|
807
|
+
unless /\A\d+\z/ =~ value
|
808
|
+
log_warn("#{value} is not a valid integer for #{name}")
|
809
|
+
return nil
|
810
|
+
end
|
811
|
+
|
812
|
+
value.to_i
|
813
|
+
end
|
814
|
+
|
815
|
+
# Converts +value+ into a symbol.
|
816
|
+
#
|
817
|
+
# @param name [ String ] Name of the URI option being processed.
|
818
|
+
# @param value [ String ] URI option value.
|
819
|
+
#
|
820
|
+
# @return [ Symbol ] Converted value.
|
821
|
+
def convert_symbol(name, value)
|
822
|
+
value.to_sym
|
823
|
+
end
|
824
|
+
|
825
|
+
# Converts +value+ as a write concern.
|
826
|
+
#
|
827
|
+
# If +value+ is the word "majority", returns the symbol :majority.
|
828
|
+
# If +value+ is a number, returns the number as an integer.
|
829
|
+
# Otherwise returns the string +value+ unchanged.
|
830
|
+
#
|
831
|
+
# @param name [ String ] Name of the URI option being processed.
|
832
|
+
# @param value [ String ] URI option value.
|
833
|
+
#
|
834
|
+
# @return [ Integer | Symbol | String ] Converted value.
|
835
|
+
def convert_w(name, value)
|
836
|
+
case value
|
837
|
+
when 'majority'
|
838
|
+
:majority
|
839
|
+
when /\A[0-9]+\z/
|
840
|
+
value.to_i
|
841
|
+
else
|
842
|
+
value
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
# Converts +value+ to a boolean.
|
847
|
+
#
|
848
|
+
# Returns true for 'true', false for 'false', otherwise nil.
|
849
|
+
#
|
850
|
+
# @param name [ String ] Name of the URI option being processed.
|
851
|
+
# @param value [ String ] URI option value.
|
852
|
+
#
|
853
|
+
# @return [ true | false | nil ] Converted value.
|
854
|
+
def convert_bool(name, value)
|
794
855
|
case value
|
795
|
-
when "true"
|
856
|
+
when "true", 'TRUE'
|
796
857
|
true
|
797
|
-
when "false"
|
858
|
+
when "false", 'FALSE'
|
798
859
|
false
|
799
860
|
else
|
800
861
|
log_warn("invalid boolean option for #{name}: #{value}")
|
@@ -809,7 +870,7 @@ module Mongo
|
|
809
870
|
# @return [ true | false | nil ] The inverse of the boolean value parsed out, otherwise nil
|
810
871
|
# (and a warning will be logged).
|
811
872
|
def inverse_bool(name, value)
|
812
|
-
b =
|
873
|
+
b = convert_bool(name, value)
|
813
874
|
|
814
875
|
if b.nil?
|
815
876
|
nil
|
@@ -12,8 +12,6 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
require 'resolv'
|
16
|
-
|
17
15
|
module Mongo
|
18
16
|
|
19
17
|
class URI
|
@@ -65,6 +63,7 @@ module Mongo
|
|
65
63
|
INVALID_PORT = "It is not allowed to specify a port in a connection string with the " +
|
66
64
|
"'#{MONGODB_SRV_SCHEME}' protocol.".freeze
|
67
65
|
|
66
|
+
# @deprecated
|
68
67
|
INVALID_DOMAIN = "The domain name must consist of at least two parts: the domain name, " +
|
69
68
|
"and a TLD.".freeze
|
70
69
|
|
@@ -93,22 +92,45 @@ module Mongo
|
|
93
92
|
@resolver ||= Resolv::DNS.new
|
94
93
|
end
|
95
94
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
95
|
+
def parse!(remaining)
|
96
|
+
super
|
97
|
+
|
98
|
+
if @servers.length != 1
|
99
|
+
raise_invalid_error!(INVALID_HOST)
|
100
|
+
end
|
101
|
+
hostname = @servers.first
|
102
|
+
validate_hostname(hostname)
|
103
|
+
|
99
104
|
records = get_records(hostname)
|
100
105
|
@txt_options = get_txt_opts(hostname) || {}
|
101
106
|
@servers = parse_servers!(records.join(','))
|
102
|
-
@user = parse_user!(creds)
|
103
|
-
@password = parse_password!(creds)
|
104
107
|
end
|
105
108
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
# Validates the hostname used in an SRV URI.
|
110
|
+
#
|
111
|
+
# The hostname cannot include a port.
|
112
|
+
#
|
113
|
+
# The hostname must not begin with a dot, end with a dot, or have
|
114
|
+
# consecutive dots. The hostname must have a minimum of 3 total
|
115
|
+
# components (foo.bar.tld).
|
116
|
+
#
|
117
|
+
# Raises Error::InvalidURI if validation fails.
|
118
|
+
def validate_hostname(hostname)
|
109
119
|
raise_invalid_error!(INVALID_PORT) if hostname.include?(HOST_PORT_DELIM)
|
110
|
-
|
111
|
-
|
120
|
+
|
121
|
+
if hostname.start_with?('.')
|
122
|
+
raise_invalid_error!("Hostname cannot start with a dot: #{hostname}")
|
123
|
+
end
|
124
|
+
if hostname.end_with?('.')
|
125
|
+
raise_invalid_error!("Hostname cannot end with a dot: #{hostname}")
|
126
|
+
end
|
127
|
+
parts = hostname.split('.')
|
128
|
+
if parts.any?(&:empty?)
|
129
|
+
raise_invalid_error!("Hostname cannot have consecutive dots: #{hostname}")
|
130
|
+
end
|
131
|
+
if parts.length < 3
|
132
|
+
raise_invalid_error!("Hostname must have a minimum of 3 components (foo.bar.tld): #{hostname}")
|
133
|
+
end
|
112
134
|
end
|
113
135
|
|
114
136
|
def get_records(hostname)
|
@@ -149,7 +171,7 @@ module Mongo
|
|
149
171
|
key, value = opt.split(URI_OPTS_VALUE_DELIM)
|
150
172
|
raise Error::InvalidTXTRecord.new(INVALID_TXT_RECORD_OPTION) unless VALID_TXT_OPTIONS.include?(key.downcase)
|
151
173
|
strategy = URI_OPTION_MAP[key.downcase]
|
152
|
-
add_uri_option(strategy, value, txt_options)
|
174
|
+
add_uri_option(key, strategy, value, txt_options)
|
153
175
|
txt_options
|
154
176
|
end
|
155
177
|
end
|