mongo 2.9.2 → 2.10.0.rc0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/mongo.rb +1 -0
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/bulk_write.rb +14 -8
- data/lib/mongo/bulk_write/result.rb +1 -1
- data/lib/mongo/bulk_write/result_combiner.rb +2 -2
- data/lib/mongo/bulk_write/transformable.rb +17 -9
- data/lib/mongo/client.rb +107 -16
- data/lib/mongo/cluster.rb +47 -25
- data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
- data/lib/mongo/cluster_time.rb +139 -0
- data/lib/mongo/collection.rb +84 -25
- data/lib/mongo/collection/view.rb +7 -3
- data/lib/mongo/collection/view/aggregation.rb +4 -4
- data/lib/mongo/collection/view/builder/aggregation.rb +31 -6
- data/lib/mongo/collection/view/builder/find_command.rb +4 -1
- data/lib/mongo/collection/view/builder/map_reduce.rb +4 -1
- data/lib/mongo/collection/view/change_stream.rb +54 -66
- data/lib/mongo/collection/view/iterable.rb +2 -2
- data/lib/mongo/collection/view/map_reduce.rb +6 -4
- data/lib/mongo/collection/view/readable.rb +36 -16
- data/lib/mongo/collection/view/writable.rb +68 -22
- data/lib/mongo/cursor.rb +87 -20
- data/lib/mongo/database.rb +47 -43
- data/lib/mongo/database/view.rb +54 -11
- data/lib/mongo/error.rb +13 -4
- data/lib/mongo/error/invalid_write_concern.rb +2 -2
- data/lib/mongo/error/operation_failure.rb +65 -11
- data/lib/mongo/error/parser.rb +41 -8
- data/lib/mongo/grid/fs_bucket.rb +26 -6
- data/lib/mongo/grid/stream/read.rb +9 -2
- data/lib/mongo/grid/stream/write.rb +21 -5
- data/lib/mongo/index/view.rb +3 -3
- data/lib/mongo/lint.rb +10 -3
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/operation/aggregate/result.rb +19 -6
- data/lib/mongo/operation/collections_info.rb +1 -1
- data/lib/mongo/operation/get_more/result.rb +9 -0
- data/lib/mongo/operation/list_collections/command.rb +1 -3
- data/lib/mongo/operation/list_collections/op_msg.rb +1 -2
- data/lib/mongo/operation/parallel_scan/command.rb +4 -1
- data/lib/mongo/operation/parallel_scan/op_msg.rb +4 -1
- data/lib/mongo/operation/result.rb +27 -4
- data/lib/mongo/operation/shared/executable.rb +19 -5
- data/lib/mongo/operation/shared/executable_no_validate.rb +1 -2
- data/lib/mongo/operation/shared/executable_transaction_label.rb +0 -9
- data/lib/mongo/operation/shared/polymorphic_result.rb +9 -1
- data/lib/mongo/operation/shared/result/aggregatable.rb +2 -2
- data/lib/mongo/operation/shared/sessions_supported.rb +42 -32
- data/lib/mongo/operation/shared/specifiable.rb +40 -0
- data/lib/mongo/operation/shared/unpinnable.rb +39 -0
- data/lib/mongo/operation/shared/write.rb +1 -1
- data/lib/mongo/protocol/update.rb +6 -2
- data/lib/mongo/retryable.rb +79 -39
- data/lib/mongo/server/connection.rb +10 -3
- data/lib/mongo/server/description.rb +25 -1
- data/lib/mongo/server/monitor/connection.rb +1 -1
- data/lib/mongo/server_selector.rb +10 -0
- data/lib/mongo/server_selector/selectable.rb +172 -32
- data/lib/mongo/session.rb +654 -581
- data/lib/mongo/session/session_pool.rb +1 -1
- data/lib/mongo/socket.rb +7 -28
- data/lib/mongo/socket/ssl.rb +26 -1
- data/lib/mongo/socket/tcp.rb +3 -0
- data/lib/mongo/socket/unix.rb +3 -0
- data/lib/mongo/uri.rb +112 -265
- data/lib/mongo/uri/srv_protocol.rb +4 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern.rb +10 -29
- data/lib/mongo/write_concern/acknowledged.rb +12 -0
- data/lib/mongo/write_concern/base.rb +17 -13
- data/lib/mongo/write_concern/unacknowledged.rb +12 -0
- data/spec/atlas/atlas_connectivity_spec.rb +7 -37
- data/spec/atlas/operations_spec.rb +25 -0
- data/spec/integration/change_stream_examples_spec.rb +45 -31
- data/spec/integration/change_stream_spec.rb +305 -5
- data/spec/integration/client_spec.rb +44 -0
- data/spec/integration/command_monitoring_spec.rb +1 -0
- data/spec/integration/command_spec.rb +7 -1
- data/spec/integration/mmapv1_spec.rb +28 -0
- data/spec/integration/mongos_pinning_spec.rb +34 -0
- data/spec/integration/operation_failure_code_spec.rb +2 -2
- data/spec/integration/{read_concern.rb → read_concern_spec.rb} +7 -1
- data/spec/integration/read_preference_spec.rb +485 -0
- data/spec/integration/retryable_writes_spec.rb +8 -19
- data/spec/integration/sdam_error_handling_spec.rb +1 -1
- data/spec/integration/sdam_events_spec.rb +2 -2
- data/spec/integration/server_description_spec.rb +14 -17
- data/spec/integration/server_selector_spec.rb +7 -3
- data/spec/integration/server_spec.rb +48 -0
- data/spec/integration/ssl_uri_options_spec.rb +1 -1
- data/spec/integration/step_down_spec.rb +10 -4
- data/spec/integration/transactions_examples_spec.rb +11 -10
- data/spec/lite_spec_helper.rb +19 -16
- data/spec/mongo/auth/scram/negotiation_spec.rb +11 -8
- data/spec/mongo/bulk_write/ordered_combiner_spec.rb +6 -6
- data/spec/mongo/bulk_write/unordered_combiner_spec.rb +4 -4
- data/spec/mongo/bulk_write_spec.rb +12 -2
- data/spec/mongo/client_construction_spec.rb +160 -8
- data/spec/mongo/client_spec.rb +5 -4
- data/spec/mongo/cluster_spec.rb +6 -6
- data/spec/mongo/cluster_time_spec.rb +148 -0
- data/spec/mongo/collection/view/aggregation_spec.rb +34 -15
- data/spec/mongo/collection/view/change_stream_spec.rb +62 -3
- data/spec/mongo/collection/view/map_reduce_spec.rb +7 -5
- data/spec/mongo/collection/view/readable_spec.rb +4 -4
- data/spec/mongo/collection_spec.rb +331 -14
- data/spec/mongo/cursor_spec.rb +117 -5
- data/spec/mongo/database_spec.rb +240 -8
- data/spec/mongo/error/operation_failure_spec.rb +47 -1
- data/spec/mongo/error/parser_spec.rb +160 -23
- data/spec/mongo/operation/insert/bulk_spec.rb +2 -1
- data/spec/mongo/operation/result_spec.rb +27 -0
- data/spec/mongo/operation/update/bulk_spec.rb +1 -0
- data/spec/mongo/retryable_spec.rb +2 -0
- data/spec/mongo/server/app_metadata_spec.rb +2 -2
- data/spec/mongo/server/connection_spec.rb +13 -17
- data/spec/mongo/server/monitor/connection_spec.rb +13 -10
- data/spec/mongo/server_selector_spec.rb +34 -2
- data/spec/mongo/session/session_pool_spec.rb +14 -3
- data/spec/mongo/session_spec.rb +3 -3
- data/spec/mongo/session_transaction_spec.rb +4 -3
- data/spec/mongo/socket/ssl_spec.rb +19 -5
- data/spec/mongo/socket_spec.rb +1 -62
- data/spec/mongo/uri/srv_protocol_spec.rb +14 -20
- data/spec/mongo/uri_option_parsing_spec.rb +94 -8
- data/spec/mongo/uri_spec.rb +23 -10
- data/spec/mongo/write_concern_spec.rb +56 -3
- data/spec/spec_tests/change_streams_spec.rb +2 -1
- data/spec/spec_tests/cmap_spec.rb +1 -1
- data/spec/spec_tests/crud_spec.rb +12 -2
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +24 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +172 -3
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +1 -1
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -2
- data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -5
- data/spec/spec_tests/data/crud/read/aggregate-out.yml +0 -6
- data/spec/spec_tests/data/crud/read/count-empty.yml +29 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-arrayFilters.yml +1 -0
- data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +101 -0
- data/spec/spec_tests/data/crud/write/bulkWrite.yml +401 -0
- data/spec/spec_tests/data/crud/write/insertMany.yml +58 -2
- data/spec/spec_tests/data/crud/write/updateMany-arrayFilters.yml +3 -0
- data/spec/spec_tests/data/crud/write/updateOne-arrayFilters.yml +6 -1
- data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +103 -0
- data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +110 -0
- data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +81 -0
- data/spec/spec_tests/data/crud_v2/db-aggregate.yml +38 -0
- data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +92 -0
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +2 -2
- data/spec/spec_tests/data/transactions/abort.yml +3 -0
- data/spec/spec_tests/data/transactions/bulk.yml +3 -8
- data/spec/spec_tests/data/transactions/causal-consistency.yml +3 -8
- data/spec/spec_tests/data/transactions/commit.yml +3 -1
- data/spec/spec_tests/data/transactions/count.yml +3 -0
- data/spec/spec_tests/data/transactions/delete.yml +3 -0
- data/spec/spec_tests/data/transactions/error-labels.yml +4 -1
- data/spec/spec_tests/data/transactions/errors-client.yml +56 -0
- data/spec/spec_tests/data/transactions/errors.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndDelete.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndReplace.yml +3 -0
- data/spec/spec_tests/data/transactions/findOneAndUpdate.yml +3 -0
- data/spec/spec_tests/data/transactions/insert.yml +3 -0
- data/spec/spec_tests/data/transactions/isolation.yml +3 -0
- data/spec/spec_tests/data/transactions/mongos-pin-auto.yml +1671 -0
- data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +347 -0
- data/spec/spec_tests/data/transactions/pin-mongos.yml +557 -0
- data/spec/spec_tests/data/transactions/read-concern.yml +3 -0
- data/spec/spec_tests/data/transactions/read-pref.yml +3 -0
- data/spec/spec_tests/data/transactions/reads.yml +3 -0
- data/spec/spec_tests/data/transactions/retryable-abort.yml +5 -2
- data/spec/spec_tests/data/transactions/retryable-commit.yml +4 -1
- data/spec/spec_tests/data/transactions/retryable-writes.yml +3 -0
- data/spec/spec_tests/data/transactions/run-command.yml +3 -0
- data/spec/spec_tests/data/transactions/transaction-options.yml +6 -0
- data/spec/spec_tests/data/transactions/update.yml +3 -8
- data/spec/spec_tests/data/transactions/write-concern.yml +348 -38
- data/spec/spec_tests/data/transactions_api/callback-aborts.yml +6 -0
- data/spec/spec_tests/data/transactions_api/callback-commits.yml +5 -0
- data/spec/spec_tests/data/transactions_api/callback-retry.yml +7 -2
- data/spec/spec_tests/data/transactions_api/commit-retry.yml +70 -15
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror-4.2.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-transienttransactionerror.yml +3 -0
- data/spec/spec_tests/data/transactions_api/commit-writeconcernerror.yml +59 -109
- data/spec/spec_tests/data/transactions_api/commit.yml +5 -0
- data/spec/spec_tests/data/transactions_api/transaction-options.yml +10 -0
- data/spec/spec_tests/retryable_reads_spec.rb +5 -2
- data/spec/spec_tests/retryable_writes_spec.rb +5 -2
- data/spec/spec_tests/sdam_monitoring_spec.rb +3 -3
- data/spec/spec_tests/sdam_spec.rb +2 -2
- data/spec/spec_tests/transactions_api_spec.rb +1 -67
- data/spec/spec_tests/transactions_spec.rb +2 -66
- data/spec/support/authorization.rb +4 -0
- data/spec/support/change_streams.rb +30 -10
- data/spec/support/change_streams/operation.rb +27 -0
- data/spec/support/client_registry.rb +44 -25
- data/spec/support/cluster_config.rb +25 -14
- data/spec/support/cluster_tools.rb +32 -10
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/common_shortcuts.rb +30 -0
- data/spec/support/connection_string.rb +8 -3
- data/spec/support/constraints.rb +34 -0
- data/spec/support/crud.rb +31 -16
- data/spec/support/crud/context.rb +23 -0
- data/spec/support/crud/operation.rb +311 -14
- data/spec/support/crud/spec.rb +2 -1
- data/spec/support/crud/test.rb +24 -27
- data/spec/support/crud/test_base.rb +22 -0
- data/spec/support/crud/verifier.rb +15 -1
- data/spec/support/event_subscriber.rb +12 -0
- data/spec/support/sdam_formatter_integration.rb +12 -6
- data/spec/support/shared/server_selector.rb +10 -0
- data/spec/support/shared/session.rb +13 -12
- data/spec/support/spec_config.rb +32 -22
- data/spec/support/spec_setup.rb +2 -2
- data/spec/support/transactions.rb +87 -0
- data/spec/support/transactions/context.rb +33 -0
- data/spec/support/transactions/operation.rb +99 -349
- data/spec/support/transactions/spec.rb +1 -3
- data/spec/support/transactions/test.rb +110 -49
- data/spec/support/utils.rb +74 -1
- metadata +52 -10
- metadata.gz.sig +0 -0
- data/spec/support/crud/read.rb +0 -265
- data/spec/support/crud/write.rb +0 -284
data/lib/mongo/socket.rb
CHANGED
@@ -49,9 +49,6 @@ module Mongo
|
|
49
49
|
# @return [ Hash ] The options.
|
50
50
|
attr_reader :options
|
51
51
|
|
52
|
-
# @return [ Float ] timeout The socket timeout.
|
53
|
-
attr_reader :timeout
|
54
|
-
|
55
52
|
# Is the socket connection alive?
|
56
53
|
#
|
57
54
|
# @example Is the socket alive?
|
@@ -126,14 +123,10 @@ module Mongo
|
|
126
123
|
def read(length)
|
127
124
|
handle_errors do
|
128
125
|
data = read_from_socket(length)
|
129
|
-
unless (data.length > 0 || length == 0)
|
130
|
-
raise IOError, "Expected to read > 0 bytes but read 0 bytes"
|
131
|
-
end
|
126
|
+
raise IOError unless (data.length > 0 || length == 0)
|
132
127
|
while data.length < length
|
133
128
|
chunk = read_from_socket(length - data.length)
|
134
|
-
unless (chunk.length > 0 || length == 0)
|
135
|
-
raise IOError, "Expected to read > 0 bytes but read 0 bytes"
|
136
|
-
end
|
129
|
+
raise IOError unless (chunk.length > 0 || length == 0)
|
137
130
|
data << chunk
|
138
131
|
end
|
139
132
|
data
|
@@ -192,9 +185,7 @@ module Mongo
|
|
192
185
|
return ''.force_encoding('BINARY')
|
193
186
|
end
|
194
187
|
|
195
|
-
|
196
|
-
deadline = Time.now + _timeout
|
197
|
-
end
|
188
|
+
deadline = (Time.now + timeout) if timeout
|
198
189
|
|
199
190
|
# We want to have a fixed and reasonably small size buffer for reads
|
200
191
|
# because, for example, OpenSSL reads in 16 kb chunks max.
|
@@ -241,22 +232,10 @@ module Mongo
|
|
241
232
|
data[retrieved, chunk.length] = chunk
|
242
233
|
retrieved += chunk.length
|
243
234
|
end
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
select_timeout = deadline - Time.now
|
249
|
-
if select_timeout <= 0
|
250
|
-
raise Errno::ETIMEDOUT, "Took more than #{_timeout} seconds to receive data"
|
251
|
-
end
|
252
|
-
end
|
253
|
-
if exc.is_a?(IO::WaitReadable)
|
254
|
-
select_args = [[@socket], nil, [@socket], select_timeout]
|
255
|
-
else
|
256
|
-
select_args = [nil, [@socket], [@socket], select_timeout]
|
257
|
-
end
|
258
|
-
unless Kernel::select(*select_args)
|
259
|
-
raise Errno::ETIMEDOUT, "Took more than #{_timeout} seconds to receive data"
|
235
|
+
rescue IO::WaitReadable
|
236
|
+
select_timeout = (deadline - Time.now) if deadline
|
237
|
+
if (select_timeout && select_timeout <= 0) || !Kernel::select([@socket], nil, [@socket], select_timeout)
|
238
|
+
raise Timeout::Error.new("Took more than #{timeout} seconds to receive data.")
|
260
239
|
end
|
261
240
|
retry
|
262
241
|
end
|
data/lib/mongo/socket/ssl.rb
CHANGED
@@ -33,6 +33,9 @@ module Mongo
|
|
33
33
|
# @return [ Integer ] port The port to connect to.
|
34
34
|
attr_reader :port
|
35
35
|
|
36
|
+
# @return [ Float ] timeout The socket timeout.
|
37
|
+
attr_reader :timeout
|
38
|
+
|
36
39
|
# Establishes a socket connection.
|
37
40
|
#
|
38
41
|
# @example Connect the socket.
|
@@ -125,10 +128,32 @@ module Mongo
|
|
125
128
|
|
126
129
|
def create_context(options)
|
127
130
|
OpenSSL::SSL::SSLContext.new.tap do |context|
|
131
|
+
if OpenSSL::SSL.const_defined?(:OP_NO_RENEGOTIATION)
|
132
|
+
context.options = context.options | OpenSSL::SSL::OP_NO_RENEGOTIATION
|
133
|
+
end
|
134
|
+
|
135
|
+
if context.respond_to?(:renegotiation_cb=)
|
136
|
+
# Disable renegotiation for older Ruby versions per the sample code at
|
137
|
+
# https://rubydocs.org/d/ruby-2-6-0/classes/OpenSSL/SSL/SSLContext.html
|
138
|
+
# In JRuby we must allow one call as this callback is invoked for
|
139
|
+
# the initial connection also, not just for renegotiations -
|
140
|
+
# https://github.com/jruby/jruby-openssl/issues/180
|
141
|
+
if BSON::Environment.jruby?
|
142
|
+
allowed_calls = 1
|
143
|
+
else
|
144
|
+
allowed_calls = 0
|
145
|
+
end
|
146
|
+
context.renegotiation_cb = lambda do |ssl|
|
147
|
+
if allowed_calls <= 0
|
148
|
+
raise RuntimeError, 'Client renegotiation disabled'
|
149
|
+
end
|
150
|
+
allowed_calls -= 1
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
128
154
|
set_cert(context, options)
|
129
155
|
set_key(context, options)
|
130
156
|
|
131
|
-
|
132
157
|
if verify_certificate?
|
133
158
|
context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
134
159
|
set_cert_verification(context, options)
|
data/lib/mongo/socket/tcp.rb
CHANGED
data/lib/mongo/socket/unix.rb
CHANGED
data/lib/mongo/uri.rb
CHANGED
@@ -115,6 +115,7 @@ module Mongo
|
|
115
115
|
# The character delimiting multiple options.
|
116
116
|
#
|
117
117
|
# @since 2.1.0
|
118
|
+
# @deprecated
|
118
119
|
INDIV_URI_OPTS_DELIM = '&'.freeze
|
119
120
|
|
120
121
|
# The character delimiting an option and its value.
|
@@ -188,21 +189,21 @@ module Mongo
|
|
188
189
|
#
|
189
190
|
# @since 2.0.0
|
190
191
|
AUTH_MECH_MAP = {
|
191
|
-
'
|
192
|
+
'GSSAPI' => :gssapi,
|
192
193
|
# MONGODB-CR is deprecated and will be removed in driver version 3.0
|
193
194
|
'MONGODB-CR' => :mongodb_cr,
|
194
|
-
'GSSAPI' => :gssapi,
|
195
195
|
'MONGODB-X509' => :mongodb_x509,
|
196
|
+
'PLAIN' => :plain,
|
196
197
|
'SCRAM-SHA-1' => :scram,
|
197
198
|
'SCRAM-SHA-256' => :scram256
|
198
199
|
}.freeze
|
199
200
|
|
200
201
|
# Options that are allowed to appear more than once in the uri.
|
201
202
|
#
|
202
|
-
# In order to follow the URI options spec requirement that all instances
|
203
|
-
# the same value, we need to keep track of all
|
204
|
-
#
|
205
|
-
# parsing the URI.
|
203
|
+
# In order to follow the URI options spec requirement that all instances
|
204
|
+
# of 'tls' and 'ssl' have the same value, we need to keep track of all
|
205
|
+
# of the values passed in for those options. Assuming they don't conflict,
|
206
|
+
# they will be condensed to a single value immediately after parsing the URI.
|
206
207
|
#
|
207
208
|
# @since 2.1.0
|
208
209
|
REPEATABLE_OPTIONS = [ :tag_sets, :ssl ]
|
@@ -349,7 +350,19 @@ module Mongo
|
|
349
350
|
end
|
350
351
|
end
|
351
352
|
|
352
|
-
|
353
|
+
unless hosts.length > 0
|
354
|
+
raise_invalid_error!("Missing host; at least one must be provided")
|
355
|
+
end
|
356
|
+
|
357
|
+
@servers = hosts.split(',').map do |host|
|
358
|
+
if host.empty?
|
359
|
+
raise_invalid_error!('Empty host given in the host list')
|
360
|
+
end
|
361
|
+
decode(host).tap do |host|
|
362
|
+
validate_host!(host)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
353
366
|
@user = parse_user!(creds)
|
354
367
|
@password = parse_password!(creds)
|
355
368
|
@uri_options = Options::Redacted.new(parse_uri_options!(options))
|
@@ -368,20 +381,26 @@ module Mongo
|
|
368
381
|
end
|
369
382
|
|
370
383
|
def parse_uri_options!(string)
|
371
|
-
|
372
|
-
string
|
373
|
-
|
384
|
+
uri_options = {}
|
385
|
+
unless string
|
386
|
+
return uri_options
|
387
|
+
end
|
388
|
+
string.split('&').each do |option_str|
|
389
|
+
if option_str.empty?
|
390
|
+
next
|
391
|
+
end
|
392
|
+
key, value = option_str.split('=', 2)
|
374
393
|
if value.nil?
|
375
394
|
raise_invalid_error!("Option #{key} has no value")
|
376
395
|
end
|
377
396
|
if value.index('=')
|
378
397
|
raise_invalid_error!("Value for option #{key} contains the key/value delimiter (=): #{value}")
|
379
398
|
end
|
380
|
-
key =
|
381
|
-
value =
|
399
|
+
key = decode(key)
|
400
|
+
value = decode(value)
|
382
401
|
add_uri_option(key, value, uri_options)
|
383
|
-
uri_options
|
384
402
|
end
|
403
|
+
uri_options
|
385
404
|
end
|
386
405
|
|
387
406
|
def parse_user!(string)
|
@@ -421,23 +440,44 @@ module Mongo
|
|
421
440
|
end
|
422
441
|
end
|
423
442
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
elsif host.index(HOST_PORT_DELIM)
|
433
|
-
h, _, p = host.partition(HOST_PORT_DELIM)
|
434
|
-
raise_invalid_error!(INVALID_HOST) unless h.size > 0
|
435
|
-
validate_port_string!(p)
|
436
|
-
elsif host =~ UNIX_SOCKET
|
437
|
-
raise_invalid_error!(UNESCAPED_UNIX_SOCKET) if host =~ UNSAFE
|
438
|
-
host = decode(host)
|
443
|
+
# Takes a host in ipv4/ipv6/hostname/socket path format and validates
|
444
|
+
# its format.
|
445
|
+
def validate_host!(host)
|
446
|
+
case host
|
447
|
+
when /\A\[[\d:]+\](?::(\d+))?\z/
|
448
|
+
# ipv6 with optional port
|
449
|
+
if port_str = $1
|
450
|
+
validate_port_string!(port_str)
|
439
451
|
end
|
440
|
-
|
452
|
+
when /\A\//, /\.sock\z/
|
453
|
+
# Unix socket path.
|
454
|
+
# Spec requires us to validate that the path has no unescaped
|
455
|
+
# slashes, but if this were to be the case, parsing would have
|
456
|
+
# already failed elsewhere because the URI would've been split in
|
457
|
+
# a weird place.
|
458
|
+
# The spec also allows relative socket paths and requires that
|
459
|
+
# socket paths end in ".sock". We accept all paths but special case
|
460
|
+
# the .sock extension to avoid relative paths falling into the
|
461
|
+
# host:port case below.
|
462
|
+
when /[\/\[\]]/
|
463
|
+
# Not a host:port nor an ipv4 address with optional port.
|
464
|
+
# Possibly botched ipv6 address with e.g. port delimiter present and
|
465
|
+
# port missing, or extra junk before or after.
|
466
|
+
raise_invalid_error!("Invalid hostname: #{host}")
|
467
|
+
when /:.*:/m
|
468
|
+
raise_invalid_error!("Multiple port delimiters are not allowed: #{host}")
|
469
|
+
else
|
470
|
+
# host:port or ipv4 address with optional port number
|
471
|
+
host, port = host.split(':')
|
472
|
+
if host.empty?
|
473
|
+
raise_invalid_error!("Host is empty: #{host}")
|
474
|
+
end
|
475
|
+
|
476
|
+
if port && port.empty?
|
477
|
+
raise_invalid_error!("Port is empty: #{port}")
|
478
|
+
end
|
479
|
+
|
480
|
+
validate_port_string!(port)
|
441
481
|
end
|
442
482
|
end
|
443
483
|
|
@@ -472,21 +512,21 @@ module Mongo
|
|
472
512
|
end
|
473
513
|
|
474
514
|
# Replica Set Options
|
475
|
-
uri_option 'replicaset', :replica_set
|
515
|
+
uri_option 'replicaset', :replica_set
|
476
516
|
|
477
517
|
# Timeout Options
|
478
|
-
uri_option 'connecttimeoutms', :connect_timeout, :type => :
|
479
|
-
uri_option 'sockettimeoutms', :socket_timeout, :type => :
|
480
|
-
uri_option 'serverselectiontimeoutms', :server_selection_timeout, :type => :
|
481
|
-
uri_option 'localthresholdms', :local_threshold, :type => :
|
482
|
-
uri_option 'heartbeatfrequencyms', :heartbeat_frequency, :type => :
|
483
|
-
uri_option 'maxidletimems', :max_idle_time, :type => :
|
518
|
+
uri_option 'connecttimeoutms', :connect_timeout, :type => :ms
|
519
|
+
uri_option 'sockettimeoutms', :socket_timeout, :type => :ms
|
520
|
+
uri_option 'serverselectiontimeoutms', :server_selection_timeout, :type => :ms
|
521
|
+
uri_option 'localthresholdms', :local_threshold, :type => :ms
|
522
|
+
uri_option 'heartbeatfrequencyms', :heartbeat_frequency, :type => :ms
|
523
|
+
uri_option 'maxidletimems', :max_idle_time, :type => :ms
|
484
524
|
|
485
525
|
# Write Options
|
486
|
-
uri_option 'w', :w, :group => :
|
487
|
-
uri_option 'journal', :j, :group => :
|
488
|
-
uri_option 'fsync', :fsync, :group => :
|
489
|
-
uri_option 'wtimeoutms', :wtimeout, :group => :
|
526
|
+
uri_option 'w', :w, :group => :write_concern, type: :w
|
527
|
+
uri_option 'journal', :j, :group => :write_concern, :type => :bool
|
528
|
+
uri_option 'fsync', :fsync, :group => :write_concern, type: :bool
|
529
|
+
uri_option 'wtimeoutms', :wtimeout, :group => :write_concern, :type => :integer
|
490
530
|
|
491
531
|
# Read Options
|
492
532
|
uri_option 'readpreference', :mode, :group => :read, :type => :read_mode
|
@@ -494,21 +534,21 @@ module Mongo
|
|
494
534
|
uri_option 'maxstalenessseconds', :max_staleness, :group => :read, :type => :max_staleness
|
495
535
|
|
496
536
|
# Pool options
|
497
|
-
uri_option 'minpoolsize', :min_pool_size, :type => :
|
498
|
-
uri_option 'maxpoolsize', :max_pool_size, :type => :
|
499
|
-
uri_option 'waitqueuetimeoutms', :wait_queue_timeout, :type => :
|
537
|
+
uri_option 'minpoolsize', :min_pool_size, :type => :integer
|
538
|
+
uri_option 'maxpoolsize', :max_pool_size, :type => :integer
|
539
|
+
uri_option 'waitqueuetimeoutms', :wait_queue_timeout, :type => :ms
|
500
540
|
|
501
541
|
# Security Options
|
502
|
-
uri_option 'ssl', :ssl, :type => :
|
503
|
-
uri_option 'tls', :ssl, :type => :
|
542
|
+
uri_option 'ssl', :ssl, :type => :repeated_bool
|
543
|
+
uri_option 'tls', :ssl, :type => :repeated_bool
|
504
544
|
uri_option 'tlsallowinvalidcertificates', :ssl_verify_certificate,
|
505
|
-
:type => :
|
545
|
+
:type => :inverse_bool
|
506
546
|
uri_option 'tlsallowinvalidhostnames', :ssl_verify_hostname,
|
507
|
-
:type => :
|
547
|
+
:type => :inverse_bool
|
508
548
|
uri_option 'tlscafile', :ssl_ca_cert
|
509
549
|
uri_option 'tlscertificatekeyfile', :ssl_cert
|
510
550
|
uri_option 'tlscertificatekeyfilepassword', :ssl_key_pass_phrase
|
511
|
-
uri_option 'tlsinsecure', :ssl_verify, :type => :
|
551
|
+
uri_option 'tlsinsecure', :ssl_verify, :type => :inverse_bool
|
512
552
|
|
513
553
|
# Topology options
|
514
554
|
uri_option 'connect', :connect, type: :symbol
|
@@ -521,9 +561,9 @@ module Mongo
|
|
521
561
|
# Client Options
|
522
562
|
uri_option 'appname', :app_name
|
523
563
|
uri_option 'compressors', :compressors, :type => :array
|
524
|
-
uri_option 'readconcernlevel', :level, group: :read_concern
|
525
|
-
uri_option 'retryreads', :retry_reads, :type => :
|
526
|
-
uri_option 'retrywrites', :retry_writes, :type => :
|
564
|
+
uri_option 'readconcernlevel', :level, group: :read_concern, type: :symbol
|
565
|
+
uri_option 'retryreads', :retry_reads, :type => :bool
|
566
|
+
uri_option 'retrywrites', :retry_writes, :type => :bool
|
527
567
|
uri_option 'zlibcompressionlevel', :zlib_compression_level, :type => :zlib_compression_level
|
528
568
|
|
529
569
|
# Applies URI value transformation by either using the default cast
|
@@ -602,15 +642,6 @@ module Mongo
|
|
602
642
|
merge_uri_option(target, value, strategy[:name])
|
603
643
|
end
|
604
644
|
|
605
|
-
# Replica set transformation, avoid converting to Symbol.
|
606
|
-
#
|
607
|
-
# @param value [String] Replica set name.
|
608
|
-
#
|
609
|
-
# @return [String] Same value to avoid cast to Symbol.
|
610
|
-
def replica_set(value)
|
611
|
-
decode(value)
|
612
|
-
end
|
613
|
-
|
614
645
|
# Auth source transformation, either db string or :external.
|
615
646
|
#
|
616
647
|
# @param value [String] Authentication source.
|
@@ -618,7 +649,7 @@ module Mongo
|
|
618
649
|
# @return [String] If auth source is database name.
|
619
650
|
# @return [:external] If auth source is external authentication.
|
620
651
|
def auth_source(value)
|
621
|
-
value == '$external' ? :external :
|
652
|
+
value == '$external' ? :external : value
|
622
653
|
end
|
623
654
|
|
624
655
|
# Authentication mechanism transformation.
|
@@ -627,7 +658,7 @@ module Mongo
|
|
627
658
|
#
|
628
659
|
# @return [Symbol] The transformed authentication mechanism.
|
629
660
|
def auth_mech(value)
|
630
|
-
AUTH_MECH_MAP[value.upcase].tap do |mech|
|
661
|
+
(AUTH_MECH_MAP[value.upcase] || value).tap do |mech|
|
631
662
|
log_warn("#{value} is not a valid auth mechanism") unless mech
|
632
663
|
end
|
633
664
|
end
|
@@ -638,7 +669,7 @@ module Mongo
|
|
638
669
|
#
|
639
670
|
# @return [Symbol] The read mode symbol.
|
640
671
|
def read_mode(value)
|
641
|
-
READ_MODE_MAP[value.downcase]
|
672
|
+
READ_MODE_MAP[value.downcase] || value
|
642
673
|
end
|
643
674
|
|
644
675
|
# Read preference tags transformation.
|
@@ -668,7 +699,7 @@ module Mongo
|
|
668
699
|
properties = hash_extractor('authMechanismProperties', value)
|
669
700
|
if properties[:canonicalize_host_name]
|
670
701
|
properties.merge!(canonicalize_host_name:
|
671
|
-
|
702
|
+
properties[:canonicalize_host_name].downcase == 'true')
|
672
703
|
end
|
673
704
|
properties
|
674
705
|
end
|
@@ -692,118 +723,15 @@ module Mongo
|
|
692
723
|
nil
|
693
724
|
end
|
694
725
|
|
695
|
-
#
|
696
|
-
#
|
697
|
-
# @param value [ String ] The max pool size string.
|
698
|
-
#
|
699
|
-
# @return [ Integer | nil ] The min pool size if it is valid, otherwise nil (and a warning will)
|
700
|
-
# be logged.
|
701
|
-
def max_pool_size(value)
|
702
|
-
if /\A\d+\z/ =~ value
|
703
|
-
return value.to_i
|
704
|
-
end
|
705
|
-
|
706
|
-
log_warn("#{value} is not a valid maxPoolSize")
|
707
|
-
nil
|
708
|
-
end
|
709
|
-
|
710
|
-
|
711
|
-
# Parses the min pool size.
|
712
|
-
#
|
713
|
-
# @param value [ String ] The min pool size string.
|
714
|
-
#
|
715
|
-
# @return [ Integer | nil ] The min pool size if it is valid, otherwise nil (and a warning will
|
716
|
-
# be logged).
|
717
|
-
def min_pool_size(value)
|
718
|
-
if /\A\d+\z/ =~ value
|
719
|
-
return value.to_i
|
720
|
-
end
|
721
|
-
|
722
|
-
log_warn("#{value} is not a valid minPoolSize")
|
723
|
-
nil
|
724
|
-
end
|
725
|
-
|
726
|
-
# Parses the journal value.
|
727
|
-
#
|
728
|
-
# @param value [ String ] The journal value.
|
729
|
-
#
|
730
|
-
# @return [ true | false | nil ] The journal value parsed out, otherwise nil (and a warning
|
731
|
-
# will be logged).
|
732
|
-
def journal(value)
|
733
|
-
convert_bool('journal', value)
|
734
|
-
end
|
735
|
-
|
736
|
-
# Parses the ssl value from the URI.
|
737
|
-
#
|
738
|
-
# @param value [ String ] The ssl value.
|
739
|
-
#
|
740
|
-
# @return [ Array<true | false> ] The ssl value parsed out (stored in an array to facilitate
|
741
|
-
# keeping track of all values).
|
742
|
-
def ssl(value)
|
743
|
-
[convert_bool('ssl', value)]
|
744
|
-
end
|
745
|
-
|
746
|
-
# Parses the tls value from the URI.
|
747
|
-
#
|
748
|
-
# @param value [ String ] The tls value.
|
749
|
-
#
|
750
|
-
# @return [ Array<true | false> ] The tls value parsed out (stored in an array to facilitate
|
751
|
-
# keeping track of all values).
|
752
|
-
def tls(value)
|
753
|
-
[convert_bool('tls', value)]
|
754
|
-
end
|
755
|
-
|
756
|
-
# Parses the ssl_verify value from the tlsInsecure URI value. Note that this will be the inverse
|
757
|
-
# of the value of tlsInsecure (if present).
|
758
|
-
#
|
759
|
-
# @param value [ String ] The tlsInsecure value.
|
760
|
-
#
|
761
|
-
# @return [ true | false | nil ] The ssl_verify value parsed out, otherwise nil (and a warning
|
762
|
-
# will be logged).
|
763
|
-
def ssl_verify(value)
|
764
|
-
inverse_bool('tlsAllowInvalidCertificates', value)
|
765
|
-
end
|
766
|
-
|
767
|
-
# Parses the ssl_verify_certificate value from the tlsAllowInvalidCertificates URI value. Note
|
768
|
-
# that this will be the inverse of the value of tlsInsecure (if present).
|
769
|
-
#
|
770
|
-
# @param value [ String ] The tlsAllowInvalidCertificates value.
|
771
|
-
#
|
772
|
-
# @return [ true | false | nil ] The ssl_verify_certificate value parsed out, otherwise nil
|
773
|
-
# (and a warning will be logged).
|
774
|
-
def ssl_verify_certificate(value)
|
775
|
-
inverse_bool('tlsAllowInvalidCertificates', value)
|
776
|
-
end
|
777
|
-
|
778
|
-
# Parses the ssl_verify_hostname value from the tlsAllowInvalidHostnames URI value. Note that
|
779
|
-
# this will be the inverse of the value of tlsAllowInvalidHostnames (if present).
|
780
|
-
#
|
781
|
-
# @param value [ String ] The tlsAllowInvalidHostnames value.
|
782
|
-
#
|
783
|
-
# @return [ true | false | nil ] The ssl_verify_hostname value parsed out, otherwise nil
|
784
|
-
# (and a warning will be logged).
|
785
|
-
def ssl_verify_hostname(value)
|
786
|
-
inverse_bool('tlsAllowInvalidHostnames', value)
|
787
|
-
end
|
788
|
-
|
789
|
-
# Parses the retryReads value.
|
726
|
+
# Converts the value into a boolean and returns it wrapped in an array.
|
790
727
|
#
|
791
|
-
# @param
|
792
|
-
#
|
793
|
-
# @return [ true | false | nil ] The boolean value parsed out, otherwise nil (and a warning
|
794
|
-
# will be logged).
|
795
|
-
def retry_reads(value)
|
796
|
-
convert_bool('retryReads', value)
|
797
|
-
end
|
798
|
-
|
799
|
-
# Parses the retryWrites value.
|
800
|
-
#
|
801
|
-
# @param value [ String ] The retryWrites value.
|
728
|
+
# @param name [ String ] Name of the URI option being processed.
|
729
|
+
# @param value [ String ] URI option value.
|
802
730
|
#
|
803
|
-
# @return [ true | false
|
804
|
-
#
|
805
|
-
def
|
806
|
-
convert_bool(
|
731
|
+
# @return [ Array<true | false> ] The boolean value parsed and wraped
|
732
|
+
# in an array.
|
733
|
+
def convert_repeated_bool(name, value)
|
734
|
+
[convert_bool(name, value)]
|
807
735
|
end
|
808
736
|
|
809
737
|
# Converts +value+ into an integer.
|
@@ -880,7 +808,7 @@ module Mongo
|
|
880
808
|
#
|
881
809
|
# @return [ true | false | nil ] The inverse of the boolean value parsed out, otherwise nil
|
882
810
|
# (and a warning will be logged).
|
883
|
-
|
811
|
+
def convert_inverse_bool(name, value)
|
884
812
|
b = convert_bool(name, value)
|
885
813
|
|
886
814
|
if b.nil?
|
@@ -897,11 +825,15 @@ module Mongo
|
|
897
825
|
# @return [ Integer | nil ] The max staleness integer parsed out if it is valid, otherwise nil
|
898
826
|
# (and a warning will be logged).
|
899
827
|
def max_staleness(value)
|
900
|
-
if /\A
|
828
|
+
if /\A-?\d+\z/ =~ value
|
901
829
|
int = value.to_i
|
902
830
|
|
903
|
-
if int
|
904
|
-
|
831
|
+
if int == -1
|
832
|
+
int = nil
|
833
|
+
end
|
834
|
+
|
835
|
+
if int && (int >= 0 && int < 90 || int < 0)
|
836
|
+
log_warn("max staleness should be either 0 or greater than 90: #{value}")
|
905
837
|
end
|
906
838
|
|
907
839
|
return int
|
@@ -911,91 +843,6 @@ module Mongo
|
|
911
843
|
nil
|
912
844
|
end
|
913
845
|
|
914
|
-
# Parses the connectTimeoutMS value.
|
915
|
-
#
|
916
|
-
# @param value [ String ] The connectTimeoutMS value.
|
917
|
-
#
|
918
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
919
|
-
# logged).
|
920
|
-
def connect_timeout(value)
|
921
|
-
ms_convert('connectTimeoutMS', value)
|
922
|
-
end
|
923
|
-
|
924
|
-
# Parses the localThresholdMS value.
|
925
|
-
#
|
926
|
-
# @param value [ String ] The localThresholdMS value.
|
927
|
-
#
|
928
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
929
|
-
# logged).
|
930
|
-
def local_threshold(value)
|
931
|
-
ms_convert('localThresholdMS', value)
|
932
|
-
end
|
933
|
-
|
934
|
-
# Parses the heartbeatFrequencyMS value.
|
935
|
-
#
|
936
|
-
# @param value [ String ] The heartbeatFrequencyMS value.
|
937
|
-
#
|
938
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
939
|
-
# logged).
|
940
|
-
def heartbeat_frequency(value)
|
941
|
-
ms_convert('heartbeatFrequencyMS', value)
|
942
|
-
end
|
943
|
-
|
944
|
-
# Parses the maxIdleTimeMS value.
|
945
|
-
#
|
946
|
-
# @param value [ String ] The maxIdleTimeMS value.
|
947
|
-
#
|
948
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
949
|
-
# logged).
|
950
|
-
def max_idle_time(value)
|
951
|
-
ms_convert('maxIdleTimeMS', value)
|
952
|
-
end
|
953
|
-
|
954
|
-
# Parses the serverSelectionMS value.
|
955
|
-
#
|
956
|
-
# @param value [ String ] The serverSelectionMS value.
|
957
|
-
#
|
958
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
959
|
-
# logged).
|
960
|
-
def server_selection_timeout(value)
|
961
|
-
ms_convert('serverSelectionTimeoutMS', value)
|
962
|
-
end
|
963
|
-
|
964
|
-
# Parses the socketTimeoutMS value.
|
965
|
-
#
|
966
|
-
# @param value [ String ] The socketTimeoutMS value.
|
967
|
-
#
|
968
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
969
|
-
# logged).
|
970
|
-
def socket_timeout(value)
|
971
|
-
ms_convert('socketTimeoutMS', value)
|
972
|
-
end
|
973
|
-
|
974
|
-
# Parses the waitQueueTimeoutMS value.
|
975
|
-
#
|
976
|
-
# @param value [ String ] The waitQueueTimeoutMS value.
|
977
|
-
#
|
978
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
979
|
-
# logged).
|
980
|
-
def wait_queue_timeout(value)
|
981
|
-
ms_convert('MS', value)
|
982
|
-
end
|
983
|
-
|
984
|
-
# Parses the wtimeoutMS value.
|
985
|
-
#
|
986
|
-
# @param value [ String ] The wtimeoutMS value.
|
987
|
-
#
|
988
|
-
# @return [ Integer | nil ] The integer parsed out, otherwise nil (and a warning will be
|
989
|
-
# logged).
|
990
|
-
def wtimeout(value)
|
991
|
-
unless /\A\d+\z/ =~ value
|
992
|
-
log_warn("Invalid wtimeoutMS value: #{value}")
|
993
|
-
return nil
|
994
|
-
end
|
995
|
-
|
996
|
-
value.to_i
|
997
|
-
end
|
998
|
-
|
999
846
|
# Ruby's convention is to provide timeouts in seconds, not milliseconds and
|
1000
847
|
# to use fractions where more precision is necessary. The connection string
|
1001
848
|
# options are always in MS so we provide an easy conversion type.
|
@@ -1005,7 +852,7 @@ module Mongo
|
|
1005
852
|
# @return [ Float ] The seconds value.
|
1006
853
|
#
|
1007
854
|
# @since 2.0.0
|
1008
|
-
def
|
855
|
+
def convert_ms(name, value)
|
1009
856
|
unless /\A-?\d+(\.\d+)?\z/ =~ value
|
1010
857
|
log_warn("Invalid ms value for #{name}: #{value}")
|
1011
858
|
return nil
|
@@ -1032,7 +879,7 @@ module Mongo
|
|
1032
879
|
return nil
|
1033
880
|
end
|
1034
881
|
|
1035
|
-
set.merge(
|
882
|
+
set.merge(k.downcase.to_sym => v)
|
1036
883
|
end
|
1037
884
|
end
|
1038
885
|
|