mongo 2.13.3 → 2.14.0.rc1
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/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +1 -1
- data/lib/mongo/address.rb +1 -1
- data/lib/mongo/bulk_write.rb +17 -0
- data/lib/mongo/caching_cursor.rb +74 -0
- data/lib/mongo/client.rb +47 -8
- data/lib/mongo/cluster/topology/single.rb +1 -1
- data/lib/mongo/cluster.rb +3 -3
- data/lib/mongo/collection/view/aggregation.rb +25 -4
- data/lib/mongo/collection/view/builder/find_command.rb +38 -18
- data/lib/mongo/collection/view/explainable.rb +27 -8
- data/lib/mongo/collection/view/iterable.rb +72 -12
- data/lib/mongo/collection/view/readable.rb +12 -2
- data/lib/mongo/collection/view/writable.rb +15 -1
- data/lib/mongo/collection/view.rb +24 -20
- data/lib/mongo/collection.rb +26 -2
- data/lib/mongo/crypt/encryption_io.rb +6 -6
- data/lib/mongo/cursor.rb +1 -0
- data/lib/mongo/database/view.rb +1 -1
- data/lib/mongo/database.rb +8 -14
- data/lib/mongo/error/invalid_read_concern.rb +28 -0
- data/lib/mongo/error/server_certificate_revoked.rb +22 -0
- data/lib/mongo/error/unsupported_option.rb +14 -12
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +37 -37
- data/lib/mongo/lint.rb +2 -1
- data/lib/mongo/logger.rb +3 -3
- data/lib/mongo/operation/aggregate/result.rb +9 -8
- data/lib/mongo/operation/collections_info/command.rb +0 -5
- data/lib/mongo/operation/collections_info/result.rb +3 -16
- data/lib/mongo/operation/delete/bulk_result.rb +2 -0
- data/lib/mongo/operation/delete/result.rb +3 -0
- data/lib/mongo/operation/explain/command.rb +4 -0
- data/lib/mongo/operation/explain/legacy.rb +4 -0
- data/lib/mongo/operation/explain/op_msg.rb +6 -0
- data/lib/mongo/operation/explain/result.rb +3 -0
- data/lib/mongo/operation/find/legacy/result.rb +2 -0
- data/lib/mongo/operation/find/result.rb +3 -0
- data/lib/mongo/operation/get_more/result.rb +3 -0
- data/lib/mongo/operation/indexes/result.rb +5 -0
- data/lib/mongo/operation/insert/bulk_result.rb +5 -0
- data/lib/mongo/operation/insert/result.rb +5 -0
- data/lib/mongo/operation/list_collections/result.rb +5 -0
- data/lib/mongo/operation/map_reduce/result.rb +10 -0
- data/lib/mongo/operation/parallel_scan/command.rb +2 -1
- data/lib/mongo/operation/parallel_scan/result.rb +4 -0
- data/lib/mongo/operation/result.rb +35 -6
- data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
- data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
- data/lib/mongo/operation/shared/executable.rb +1 -0
- data/lib/mongo/operation/shared/idable.rb +2 -1
- data/lib/mongo/operation/shared/limited.rb +1 -0
- data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
- data/lib/mongo/operation/shared/read_preference_supported.rb +36 -38
- data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +3 -3
- data/lib/mongo/operation/shared/specifiable.rb +1 -0
- data/lib/mongo/operation/shared/write.rb +1 -0
- data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
- data/lib/mongo/operation/update/legacy/result.rb +7 -0
- data/lib/mongo/operation/update/result.rb +8 -0
- data/lib/mongo/operation/users_info/result.rb +3 -0
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/protocol/query.rb +11 -11
- data/lib/mongo/query_cache.rb +242 -0
- data/lib/mongo/retryable.rb +8 -1
- data/lib/mongo/server/connection_common.rb +2 -2
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/monitor/connection.rb +3 -3
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/pending_connection.rb +2 -2
- data/lib/mongo/server/push_monitor.rb +1 -1
- data/lib/mongo/server.rb +5 -1
- data/lib/mongo/server_selector/base.rb +5 -1
- data/lib/mongo/server_selector/secondary_preferred.rb +7 -2
- data/lib/mongo/session.rb +3 -0
- data/lib/mongo/socket/ocsp_cache.rb +97 -0
- data/lib/mongo/socket/ocsp_verifier.rb +368 -0
- data/lib/mongo/socket/ssl.rb +45 -24
- data/lib/mongo/socket.rb +6 -4
- data/lib/mongo/srv/monitor.rb +7 -13
- data/lib/mongo/srv/resolver.rb +14 -10
- data/lib/mongo/timeout.rb +2 -0
- data/lib/mongo/uri/options_mapper.rb +582 -0
- data/lib/mongo/uri/srv_protocol.rb +3 -2
- data/lib/mongo/uri.rb +21 -390
- data/lib/mongo/utils.rb +12 -1
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +9 -0
- data/spec/NOTES.aws-auth.md +12 -7
- data/spec/README.md +56 -1
- data/spec/integration/bson_symbol_spec.rb +2 -4
- data/spec/integration/bulk_write_spec.rb +48 -0
- data/spec/integration/client_authentication_options_spec.rb +55 -28
- data/spec/integration/connection_pool_populator_spec.rb +3 -1
- data/spec/integration/cursor_reaping_spec.rb +53 -17
- data/spec/integration/ocsp_connectivity_spec.rb +26 -0
- data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
- data/spec/integration/ocsp_verifier_spec.rb +334 -0
- data/spec/integration/query_cache_spec.rb +1045 -0
- data/spec/integration/query_cache_transactions_spec.rb +179 -0
- data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
- data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
- data/spec/integration/sdam_error_handling_spec.rb +69 -18
- data/spec/integration/sdam_events_spec.rb +7 -8
- data/spec/integration/server_selection_spec.rb +36 -0
- data/spec/integration/srv_monitoring_spec.rb +38 -3
- data/spec/integration/srv_spec.rb +56 -0
- data/spec/lite_spec_helper.rb +4 -2
- data/spec/mongo/address_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +70 -0
- data/spec/mongo/client_construction_spec.rb +54 -1
- data/spec/mongo/client_encryption_spec.rb +10 -16
- data/spec/mongo/client_spec.rb +40 -0
- data/spec/mongo/cluster/topology/single_spec.rb +14 -5
- data/spec/mongo/cluster_spec.rb +3 -0
- data/spec/mongo/collection/view/explainable_spec.rb +87 -4
- data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
- data/spec/mongo/collection_spec.rb +60 -0
- data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
- data/spec/mongo/database_spec.rb +44 -64
- data/spec/mongo/error/no_server_available_spec.rb +1 -1
- data/spec/mongo/index/view_spec.rb +2 -4
- data/spec/mongo/logger_spec.rb +13 -11
- data/spec/mongo/operation/read_preference_legacy_spec.rb +19 -9
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
- data/spec/mongo/query_cache_spec.rb +279 -0
- data/spec/mongo/server/app_metadata_shared.rb +7 -33
- data/spec/mongo/server/connection_pool_spec.rb +7 -3
- data/spec/mongo/server/connection_spec.rb +14 -7
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/socket_spec.rb +1 -1
- data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
- data/spec/mongo/uri_option_parsing_spec.rb +11 -11
- data/spec/mongo/uri_spec.rb +68 -41
- data/spec/mongo/utils_spec.rb +39 -0
- data/spec/runners/auth.rb +3 -0
- data/spec/runners/connection_string.rb +35 -124
- data/spec/runners/transactions/operation.rb +2 -13
- data/spec/spec_tests/cmap_spec.rb +7 -3
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
- data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
- data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
- data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
- data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
- data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
- data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
- data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
- data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
- data/spec/spec_tests/uri_options_spec.rb +31 -33
- data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
- data/spec/support/certificates/atlas-ocsp.crt +41 -0
- data/spec/support/client_registry.rb +4 -8
- data/spec/support/client_registry_macros.rb +4 -4
- data/spec/support/common_shortcuts.rb +45 -0
- data/spec/support/constraints.rb +23 -0
- data/spec/support/lite_constraints.rb +24 -0
- data/spec/support/matchers.rb +16 -0
- data/spec/support/ocsp +1 -0
- data/spec/support/session_registry.rb +52 -0
- data/spec/support/spec_config.rb +22 -12
- data/spec/support/spec_setup.rb +38 -48
- data/spec/support/utils.rb +19 -1
- data.tar.gz.sig +1 -3
- metadata +938 -933
- metadata.gz.sig +0 -0
- data/spec/integration/secondary_reads_spec.rb +0 -102
- data/spec/shared/LICENSE +0 -20
- data/spec/shared/bin/get-mongodb-download-url +0 -17
- data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
- data/spec/shared/lib/mrss/cluster_config.rb +0 -221
- data/spec/shared/lib/mrss/constraints.rb +0 -346
- data/spec/shared/lib/mrss/docker_runner.rb +0 -265
- data/spec/shared/lib/mrss/lite_constraints.rb +0 -191
- data/spec/shared/lib/mrss/server_version_registry.rb +0 -115
- data/spec/shared/lib/mrss/spec_organizer.rb +0 -152
- data/spec/shared/lib/mrss/utils.rb +0 -15
- data/spec/shared/share/Dockerfile.erb +0 -231
- data/spec/shared/shlib/distro.sh +0 -73
- data/spec/shared/shlib/server.sh +0 -290
- data/spec/shared/shlib/set_env.sh +0 -128
data/lib/mongo/uri.rb
CHANGED
@@ -388,6 +388,12 @@ module Mongo
|
|
388
388
|
[ creds_hosts, db_opts ].map { |s| s.reverse }
|
389
389
|
end
|
390
390
|
|
391
|
+
def options_mapper
|
392
|
+
@options_mapper ||= OptionsMapper.new(
|
393
|
+
logger: @options[:logger],
|
394
|
+
)
|
395
|
+
end
|
396
|
+
|
391
397
|
def parse_uri_options!(string)
|
392
398
|
uri_options = {}
|
393
399
|
unless string
|
@@ -403,7 +409,7 @@ module Mongo
|
|
403
409
|
end
|
404
410
|
key = decode(key)
|
405
411
|
value = decode(value)
|
406
|
-
add_uri_option(key, value, uri_options)
|
412
|
+
options_mapper.add_uri_option(key, value, uri_options)
|
407
413
|
end
|
408
414
|
uri_options
|
409
415
|
end
|
@@ -453,393 +459,6 @@ module Mongo
|
|
453
459
|
CGI.escape(value).gsub('+', '%20')
|
454
460
|
end
|
455
461
|
|
456
|
-
# Hash for storing map of URI option parameters to conversion strategies
|
457
|
-
URI_OPTION_MAP = {}
|
458
|
-
|
459
|
-
# Simple internal dsl to register a MongoDB URI option in the URI_OPTION_MAP.
|
460
|
-
#
|
461
|
-
# @param uri_key [String] The MongoDB URI option to register.
|
462
|
-
# @param name [Symbol] The name of the option in the driver.
|
463
|
-
# @param extra [Hash] Extra options.
|
464
|
-
# * :group [Symbol] Nested hash where option will go.
|
465
|
-
# * :type [Symbol] Name of function to transform value.
|
466
|
-
def self.uri_option(uri_key, name, extra = {})
|
467
|
-
URI_OPTION_MAP[uri_key] = { :name => name }.merge(extra)
|
468
|
-
end
|
469
|
-
|
470
|
-
# Replica Set Options
|
471
|
-
uri_option 'replicaset', :replica_set
|
472
|
-
|
473
|
-
# Timeout Options
|
474
|
-
uri_option 'connecttimeoutms', :connect_timeout, :type => :ms
|
475
|
-
uri_option 'sockettimeoutms', :socket_timeout, :type => :ms
|
476
|
-
uri_option 'serverselectiontimeoutms', :server_selection_timeout, :type => :ms
|
477
|
-
uri_option 'localthresholdms', :local_threshold, :type => :ms
|
478
|
-
uri_option 'heartbeatfrequencyms', :heartbeat_frequency, :type => :ms
|
479
|
-
uri_option 'maxidletimems', :max_idle_time, :type => :ms
|
480
|
-
|
481
|
-
# Write Options
|
482
|
-
uri_option 'w', :w, :group => :write_concern, type: :w
|
483
|
-
uri_option 'journal', :j, :group => :write_concern, :type => :bool
|
484
|
-
uri_option 'fsync', :fsync, :group => :write_concern, type: :bool
|
485
|
-
uri_option 'wtimeoutms', :wtimeout, :group => :write_concern, :type => :integer
|
486
|
-
|
487
|
-
# Read Options
|
488
|
-
uri_option 'readpreference', :mode, :group => :read, :type => :read_mode
|
489
|
-
uri_option 'readpreferencetags', :tag_sets, :group => :read, :type => :read_tags
|
490
|
-
uri_option 'maxstalenessseconds', :max_staleness, :group => :read, :type => :max_staleness
|
491
|
-
|
492
|
-
# Pool options
|
493
|
-
uri_option 'minpoolsize', :min_pool_size, :type => :integer
|
494
|
-
uri_option 'maxpoolsize', :max_pool_size, :type => :integer
|
495
|
-
uri_option 'waitqueuetimeoutms', :wait_queue_timeout, :type => :ms
|
496
|
-
|
497
|
-
# Security Options
|
498
|
-
uri_option 'ssl', :ssl, :type => :repeated_bool
|
499
|
-
uri_option 'tls', :ssl, :type => :repeated_bool
|
500
|
-
uri_option 'tlsallowinvalidcertificates', :ssl_verify_certificate,
|
501
|
-
:type => :inverse_bool
|
502
|
-
uri_option 'tlsallowinvalidhostnames', :ssl_verify_hostname,
|
503
|
-
:type => :inverse_bool
|
504
|
-
uri_option 'tlscafile', :ssl_ca_cert
|
505
|
-
uri_option 'tlscertificatekeyfile', :ssl_cert
|
506
|
-
uri_option 'tlscertificatekeyfilepassword', :ssl_key_pass_phrase
|
507
|
-
uri_option 'tlsinsecure', :ssl_verify, :type => :inverse_bool
|
508
|
-
|
509
|
-
# Topology options
|
510
|
-
uri_option 'directconnection', :direct_connection, type: :bool
|
511
|
-
uri_option 'connect', :connect, type: :symbol
|
512
|
-
|
513
|
-
# Auth Options
|
514
|
-
uri_option 'authsource', :auth_source
|
515
|
-
uri_option 'authmechanism', :auth_mech, :type => :auth_mech
|
516
|
-
uri_option 'authmechanismproperties', :auth_mech_properties, :type => :auth_mech_props
|
517
|
-
|
518
|
-
# Client Options
|
519
|
-
uri_option 'appname', :app_name
|
520
|
-
uri_option 'compressors', :compressors, :type => :array
|
521
|
-
uri_option 'readconcernlevel', :level, group: :read_concern, type: :symbol
|
522
|
-
uri_option 'retryreads', :retry_reads, :type => :bool
|
523
|
-
uri_option 'retrywrites', :retry_writes, :type => :bool
|
524
|
-
uri_option 'zlibcompressionlevel', :zlib_compression_level, :type => :zlib_compression_level
|
525
|
-
|
526
|
-
# Applies URI value transformation by either using the default cast
|
527
|
-
# or a transformation appropriate for the given type.
|
528
|
-
#
|
529
|
-
# @param key [String] URI option name.
|
530
|
-
# @param value [String] The value to be transformed.
|
531
|
-
# @param type [Symbol] The transform method.
|
532
|
-
def apply_transform(key, value, type)
|
533
|
-
if type
|
534
|
-
if respond_to?("convert_#{type}", true)
|
535
|
-
send("convert_#{type}", key, value)
|
536
|
-
else
|
537
|
-
send(type, value)
|
538
|
-
end
|
539
|
-
else
|
540
|
-
value
|
541
|
-
end
|
542
|
-
end
|
543
|
-
|
544
|
-
# Selects the output destination for an option.
|
545
|
-
#
|
546
|
-
# @param [Hash] uri_options The base target.
|
547
|
-
# @param [Symbol] group Group subtarget.
|
548
|
-
#
|
549
|
-
# @return [Hash] The target for the option.
|
550
|
-
def select_target(uri_options, group = nil)
|
551
|
-
if group
|
552
|
-
uri_options[group] ||= {}
|
553
|
-
else
|
554
|
-
uri_options
|
555
|
-
end
|
556
|
-
end
|
557
|
-
|
558
|
-
# Merges a new option into the target.
|
559
|
-
#
|
560
|
-
# If the option exists at the target destination the merge will
|
561
|
-
# be an addition.
|
562
|
-
#
|
563
|
-
# Specifically required to append an additional tag set
|
564
|
-
# to the array of tag sets without overwriting the original.
|
565
|
-
#
|
566
|
-
# @param target [Hash] The destination.
|
567
|
-
# @param value [Object] The value to be merged.
|
568
|
-
# @param name [Symbol] The name of the option.
|
569
|
-
def merge_uri_option(target, value, name)
|
570
|
-
if target.key?(name)
|
571
|
-
if REPEATABLE_OPTIONS.include?(name)
|
572
|
-
target[name] += value
|
573
|
-
else
|
574
|
-
log_warn("Repeated option key: #{name}.")
|
575
|
-
end
|
576
|
-
else
|
577
|
-
target.merge!(name => value)
|
578
|
-
end
|
579
|
-
end
|
580
|
-
|
581
|
-
# Adds an option to the uri options hash via the supplied strategy.
|
582
|
-
#
|
583
|
-
# Acquires a target for the option based on group.
|
584
|
-
# Transforms the value.
|
585
|
-
# Merges the option into the target.
|
586
|
-
#
|
587
|
-
# @param key [String] URI option name.
|
588
|
-
# @param value [String] The value of the option.
|
589
|
-
# @param uri_options [Hash] The base option target.
|
590
|
-
def add_uri_option(key, value, uri_options)
|
591
|
-
strategy = URI_OPTION_MAP[key.downcase]
|
592
|
-
if strategy.nil?
|
593
|
-
log_warn("Unsupported URI option '#{key}' on URI '#{@string}'. It will be ignored.")
|
594
|
-
return
|
595
|
-
end
|
596
|
-
|
597
|
-
target = select_target(uri_options, strategy[:group])
|
598
|
-
value = apply_transform(key, value, strategy[:type])
|
599
|
-
merge_uri_option(target, value, strategy[:name])
|
600
|
-
end
|
601
|
-
|
602
|
-
# Authentication mechanism transformation.
|
603
|
-
#
|
604
|
-
# @param value [String] The authentication mechanism.
|
605
|
-
#
|
606
|
-
# @return [Symbol] The transformed authentication mechanism.
|
607
|
-
def auth_mech(value)
|
608
|
-
(AUTH_MECH_MAP[value.upcase] || value).tap do |mech|
|
609
|
-
log_warn("#{value} is not a valid auth mechanism") unless mech
|
610
|
-
end
|
611
|
-
end
|
612
|
-
|
613
|
-
# Read preference mode transformation.
|
614
|
-
#
|
615
|
-
# @param value [String] The read mode string value.
|
616
|
-
#
|
617
|
-
# @return [Symbol] The read mode symbol.
|
618
|
-
def read_mode(value)
|
619
|
-
READ_MODE_MAP[value.downcase] || value
|
620
|
-
end
|
621
|
-
|
622
|
-
# Read preference tags transformation.
|
623
|
-
#
|
624
|
-
# @param value [String] The string representing tag set.
|
625
|
-
#
|
626
|
-
# @return [Array<Hash>] Array with tag set.
|
627
|
-
def read_tags(value)
|
628
|
-
[read_set(value)]
|
629
|
-
end
|
630
|
-
|
631
|
-
# Read preference tag set extractor.
|
632
|
-
#
|
633
|
-
# @param value [String] The tag set string.
|
634
|
-
#
|
635
|
-
# @return [Hash] The tag set hash.
|
636
|
-
def read_set(value)
|
637
|
-
hash_extractor('readPreferenceTags', value)
|
638
|
-
end
|
639
|
-
|
640
|
-
# Auth mechanism properties extractor.
|
641
|
-
#
|
642
|
-
# @param value [ String ] The auth mechanism properties string.
|
643
|
-
#
|
644
|
-
# @return [ Hash ] The auth mechanism properties hash.
|
645
|
-
def auth_mech_props(value)
|
646
|
-
properties = hash_extractor('authMechanismProperties', value)
|
647
|
-
if properties && properties[:canonicalize_host_name]
|
648
|
-
properties.merge!(canonicalize_host_name:
|
649
|
-
properties[:canonicalize_host_name].downcase == 'true')
|
650
|
-
end
|
651
|
-
properties
|
652
|
-
end
|
653
|
-
|
654
|
-
# Parses the zlib compression level.
|
655
|
-
#
|
656
|
-
# @param value [ String ] The zlib compression level string.
|
657
|
-
#
|
658
|
-
# @return [ Integer | nil ] The compression level value if it is between -1 and 9 (inclusive),
|
659
|
-
# otherwise nil (and a warning will be logged).
|
660
|
-
def zlib_compression_level(value)
|
661
|
-
if /\A-?\d+\z/ =~ value
|
662
|
-
i = value.to_i
|
663
|
-
|
664
|
-
if i >= -1 && i <= 9
|
665
|
-
return i
|
666
|
-
end
|
667
|
-
end
|
668
|
-
|
669
|
-
log_warn("#{value} is not a valid zlibCompressionLevel")
|
670
|
-
nil
|
671
|
-
end
|
672
|
-
|
673
|
-
# Converts the value into a boolean and returns it wrapped in an array.
|
674
|
-
#
|
675
|
-
# @param name [ String ] Name of the URI option being processed.
|
676
|
-
# @param value [ String ] URI option value.
|
677
|
-
#
|
678
|
-
# @return [ Array<true | false> ] The boolean value parsed and wraped
|
679
|
-
# in an array.
|
680
|
-
def convert_repeated_bool(name, value)
|
681
|
-
[convert_bool(name, value)]
|
682
|
-
end
|
683
|
-
|
684
|
-
# Converts +value+ into an integer.
|
685
|
-
#
|
686
|
-
# If the value is not a valid integer, warns and returns nil.
|
687
|
-
#
|
688
|
-
# @param name [ String ] Name of the URI option being processed.
|
689
|
-
# @param value [ String ] URI option value.
|
690
|
-
#
|
691
|
-
# @return [ nil | Integer ] Converted value.
|
692
|
-
def convert_integer(name, value)
|
693
|
-
unless /\A\d+\z/ =~ value
|
694
|
-
log_warn("#{value} is not a valid integer for #{name}")
|
695
|
-
return nil
|
696
|
-
end
|
697
|
-
|
698
|
-
value.to_i
|
699
|
-
end
|
700
|
-
|
701
|
-
# Converts +value+ into a symbol.
|
702
|
-
#
|
703
|
-
# @param name [ String ] Name of the URI option being processed.
|
704
|
-
# @param value [ String ] URI option value.
|
705
|
-
#
|
706
|
-
# @return [ Symbol ] Converted value.
|
707
|
-
def convert_symbol(name, value)
|
708
|
-
value.to_sym
|
709
|
-
end
|
710
|
-
|
711
|
-
# Converts +value+ as a write concern.
|
712
|
-
#
|
713
|
-
# If +value+ is the word "majority", returns the symbol :majority.
|
714
|
-
# If +value+ is a number, returns the number as an integer.
|
715
|
-
# Otherwise returns the string +value+ unchanged.
|
716
|
-
#
|
717
|
-
# @param name [ String ] Name of the URI option being processed.
|
718
|
-
# @param value [ String ] URI option value.
|
719
|
-
#
|
720
|
-
# @return [ Integer | Symbol | String ] Converted value.
|
721
|
-
def convert_w(name, value)
|
722
|
-
case value
|
723
|
-
when 'majority'
|
724
|
-
:majority
|
725
|
-
when /\A[0-9]+\z/
|
726
|
-
value.to_i
|
727
|
-
else
|
728
|
-
value
|
729
|
-
end
|
730
|
-
end
|
731
|
-
|
732
|
-
# Converts +value+ to a boolean.
|
733
|
-
#
|
734
|
-
# Returns true for 'true', false for 'false', otherwise nil.
|
735
|
-
#
|
736
|
-
# @param name [ String ] Name of the URI option being processed.
|
737
|
-
# @param value [ String ] URI option value.
|
738
|
-
#
|
739
|
-
# @return [ true | false | nil ] Converted value.
|
740
|
-
def convert_bool(name, value)
|
741
|
-
case value
|
742
|
-
when "true", 'TRUE'
|
743
|
-
true
|
744
|
-
when "false", 'FALSE'
|
745
|
-
false
|
746
|
-
else
|
747
|
-
log_warn("invalid boolean option for #{name}: #{value}")
|
748
|
-
nil
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
# Parses a boolean value and returns its inverse.
|
753
|
-
#
|
754
|
-
# @param value [ String ] The URI option value.
|
755
|
-
#
|
756
|
-
# @return [ true | false | nil ] The inverse of the boolean value parsed out, otherwise nil
|
757
|
-
# (and a warning will be logged).
|
758
|
-
def convert_inverse_bool(name, value)
|
759
|
-
b = convert_bool(name, value)
|
760
|
-
|
761
|
-
if b.nil?
|
762
|
-
nil
|
763
|
-
else
|
764
|
-
!b
|
765
|
-
end
|
766
|
-
end
|
767
|
-
|
768
|
-
# Parses the max staleness value, which must be either "0" or an integer greater or equal to 90.
|
769
|
-
#
|
770
|
-
# @param value [ String ] The max staleness string.
|
771
|
-
#
|
772
|
-
# @return [ Integer | nil ] The max staleness integer parsed out if it is valid, otherwise nil
|
773
|
-
# (and a warning will be logged).
|
774
|
-
def max_staleness(value)
|
775
|
-
if /\A-?\d+\z/ =~ value
|
776
|
-
int = value.to_i
|
777
|
-
|
778
|
-
if int == -1
|
779
|
-
int = nil
|
780
|
-
end
|
781
|
-
|
782
|
-
if int && (int >= 0 && int < 90 || int < 0)
|
783
|
-
log_warn("max staleness should be either 0 or greater than 90: #{value}")
|
784
|
-
end
|
785
|
-
|
786
|
-
return int
|
787
|
-
end
|
788
|
-
|
789
|
-
log_warn("Invalid max staleness value: #{value}")
|
790
|
-
nil
|
791
|
-
end
|
792
|
-
|
793
|
-
# Ruby's convention is to provide timeouts in seconds, not milliseconds and
|
794
|
-
# to use fractions where more precision is necessary. The connection string
|
795
|
-
# options are always in MS so we provide an easy conversion type.
|
796
|
-
#
|
797
|
-
# @param [ Integer ] value The millisecond value.
|
798
|
-
#
|
799
|
-
# @return [ Float ] The seconds value.
|
800
|
-
#
|
801
|
-
# @since 2.0.0
|
802
|
-
def convert_ms(name, value)
|
803
|
-
unless /\A-?\d+(\.\d+)?\z/ =~ value
|
804
|
-
log_warn("Invalid ms value for #{name}: #{value}")
|
805
|
-
return nil
|
806
|
-
end
|
807
|
-
|
808
|
-
if value[0] == '-'
|
809
|
-
log_warn("#{name} cannot be a negative number")
|
810
|
-
return nil
|
811
|
-
end
|
812
|
-
|
813
|
-
value.to_f / 1000
|
814
|
-
end
|
815
|
-
|
816
|
-
# Extract values from the string and put them into a nested hash.
|
817
|
-
#
|
818
|
-
# @param value [ String ] The string to build a hash from.
|
819
|
-
#
|
820
|
-
# @return [ Hash ] The hash built from the string.
|
821
|
-
def hash_extractor(name, value)
|
822
|
-
h = {}
|
823
|
-
value.split(',').each do |tag|
|
824
|
-
k, v = tag.split(':')
|
825
|
-
if v.nil?
|
826
|
-
log_warn("Invalid hash value for #{name}: key `#{k}` does not have a value: #{value}")
|
827
|
-
end
|
828
|
-
|
829
|
-
h[k.downcase.to_sym] = v
|
830
|
-
end
|
831
|
-
h
|
832
|
-
end
|
833
|
-
|
834
|
-
# Extract values from the string and put them into an array.
|
835
|
-
#
|
836
|
-
# @param [ String ] value The string to build an array from.
|
837
|
-
#
|
838
|
-
# @return [ Array ] The array built from the string.
|
839
|
-
def array(value)
|
840
|
-
value.split(',')
|
841
|
-
end
|
842
|
-
|
843
462
|
def validate_uri_options!
|
844
463
|
# The URI options spec requires that we raise an error if there are conflicting values of
|
845
464
|
# 'tls' and 'ssl'. In order to fulfill this, we parse the values of each instance into an
|
@@ -861,10 +480,21 @@ module Mongo
|
|
861
480
|
unless uri_options[:ssl_verify_hostname].nil?
|
862
481
|
raise_invalid_error_no_fmt!("tlsInsecure' and 'tlsAllowInvalidHostnames' cannot both be specified")
|
863
482
|
end
|
483
|
+
|
484
|
+
unless uri_options[:ssl_verify_ocsp_endpoint].nil?
|
485
|
+
raise_invalid_error_no_fmt!("tlsInsecure' and 'tlsDisableOCSPEndpointCheck' cannot both be specified")
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
unless uri_options[:ssl_verify_certificate].nil?
|
490
|
+
unless uri_options[:ssl_verify_ocsp_endpoint].nil?
|
491
|
+
raise_invalid_error_no_fmt!("tlsAllowInvalidCertificates' and 'tlsDisableOCSPEndpointCheck' cannot both be specified")
|
492
|
+
end
|
864
493
|
end
|
865
494
|
|
866
|
-
# Since we know that the only URI option that sets :ssl_cert is
|
867
|
-
# value set for :ssl_cert must also be set
|
495
|
+
# Since we know that the only URI option that sets :ssl_cert is
|
496
|
+
# "tlsCertificateKeyFile", any value set for :ssl_cert must also be set
|
497
|
+
# for :ssl_key.
|
868
498
|
if uri_options[:ssl_cert]
|
869
499
|
uri_options[:ssl_key] = uri_options[:ssl_cert]
|
870
500
|
end
|
@@ -891,4 +521,5 @@ module Mongo
|
|
891
521
|
end
|
892
522
|
end
|
893
523
|
|
524
|
+
require 'mongo/uri/options_mapper'
|
894
525
|
require 'mongo/uri/srv_protocol'
|
data/lib/mongo/utils.rb
CHANGED
@@ -34,7 +34,7 @@ module Mongo
|
|
34
34
|
# @option opts [ Logger ] :logger A custom logger to use.
|
35
35
|
# @option opts [ String ] :log_prefix A custom log prefix to use when
|
36
36
|
# logging.
|
37
|
-
module_function def
|
37
|
+
module_function def warn_bg_exception(msg, exc, **opts)
|
38
38
|
bt_excerpt = excerpt_backtrace(exc, **opts)
|
39
39
|
logger = LocalLogger.new(**opts)
|
40
40
|
logger.log_warn("#{msg}: #{exc.class}: #{exc}#{bt_excerpt}")
|
@@ -55,8 +55,19 @@ module Mongo
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
# Symbolizes the keys in the provided hash.
|
58
59
|
module_function def shallow_symbolize_keys(hash)
|
59
60
|
Hash[hash.map { |k, v| [k.to_sym, v] }]
|
60
61
|
end
|
62
|
+
|
63
|
+
# Stringifies the keys in the provided hash and converts underscore
|
64
|
+
# style keys to camel case style keys.
|
65
|
+
module_function def shallow_camelize_keys(hash)
|
66
|
+
Hash[hash.map { |k, v| [camelize(k), v] }]
|
67
|
+
end
|
68
|
+
|
69
|
+
module_function def camelize(sym)
|
70
|
+
sym.to_s.gsub(/_(\w)/) { $1.upcase }
|
71
|
+
end
|
61
72
|
end
|
62
73
|
end
|
data/lib/mongo/version.rb
CHANGED
data/lib/mongo.rb
CHANGED
@@ -51,6 +51,7 @@ require 'mongo/protocol'
|
|
51
51
|
require 'mongo/background_thread'
|
52
52
|
require 'mongo/cluster'
|
53
53
|
require 'mongo/cursor'
|
54
|
+
require 'mongo/caching_cursor'
|
54
55
|
require 'mongo/collection'
|
55
56
|
require 'mongo/database'
|
56
57
|
require 'mongo/crypt'
|
@@ -60,6 +61,7 @@ require 'mongo/dbref'
|
|
60
61
|
require 'mongo/grid'
|
61
62
|
require 'mongo/index'
|
62
63
|
require 'mongo/lint'
|
64
|
+
require 'mongo/query_cache'
|
63
65
|
require 'mongo/server'
|
64
66
|
require 'mongo/server_selector'
|
65
67
|
require 'mongo/session'
|
@@ -70,3 +72,10 @@ require 'mongo/uri'
|
|
70
72
|
require 'mongo/version'
|
71
73
|
require 'mongo/write_concern'
|
72
74
|
require 'mongo/utils'
|
75
|
+
|
76
|
+
module Mongo
|
77
|
+
# Clears the driver's OCSP response cache.
|
78
|
+
module_function def clear_ocsp_cache
|
79
|
+
Socket::OcspCache.clear
|
80
|
+
end
|
81
|
+
end
|
data/spec/NOTES.aws-auth.md
CHANGED
@@ -145,13 +145,16 @@ problem. Below are some of the puzzling responses I encountered:
|
|
145
145
|
line) but the value is otherwise completely valid. This error has no relation
|
146
146
|
to the "session token" or "security token" as used with temporary AWS
|
147
147
|
credentials.
|
148
|
-
- *The security token included in the request is invalid*: this error
|
149
|
-
produced
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
148
|
+
- *The security token included in the request is invalid*: this error can be
|
149
|
+
produced in several circumstances:
|
150
|
+
- When the AWS access key id, as specified in the scope part of the
|
151
|
+
`Authorization` header, is not a valid access key id. In the case of
|
152
|
+
non-temporary credentials being used for authentication, the error refers to
|
153
|
+
a "security token" but the authentication process does not actually use a
|
154
|
+
security token as this term is used in the AWS documentation describing
|
155
|
+
temporary credentials.
|
156
|
+
- When using temporary credentials and the security token is not provided
|
157
|
+
in the STS request at all (x-amz-security-token header).
|
155
158
|
- *Signature expired: 20200317T000000Z is now earlier than 20200317T222541Z
|
156
159
|
(20200317T224041Z - 15 min.)*: This error happens when `x-amz-date` header
|
157
160
|
value is the formatted date (`YYYYMMDD`) rather than the ISO8601 formatted
|
@@ -168,6 +171,8 @@ problem. Below are some of the puzzling responses I encountered:
|
|
168
171
|
produced when temporary credentials are used and the credentials have
|
169
172
|
expired.
|
170
173
|
|
174
|
+
See also [AWS documentation for STS error messages](https://docs.aws.amazon.com/STS/latest/APIReference/CommonErrors.html).
|
175
|
+
|
171
176
|
### Resources
|
172
177
|
|
173
178
|
Generally I found Amazon's own documentation to be the best for implementing
|
data/spec/README.md
CHANGED
@@ -107,7 +107,7 @@ other tests require a sharded cluster with more than one shard. Tests requiring
|
|
107
107
|
a single shard can be run against a deployment with multiple shards by
|
108
108
|
specifying only one mongos address in MONGODB_URI.
|
109
109
|
|
110
|
-
## Note Regarding SSL
|
110
|
+
## Note Regarding TLS/SSL Arguments
|
111
111
|
|
112
112
|
MongoDB 4.2 (server and shell) added new command line options for setting TLS
|
113
113
|
parameters. These options follow the naming of URI options used by both the
|
@@ -185,6 +185,51 @@ verification, run:
|
|
185
185
|
Note that there are tests in the test suite that cover TLS verification, and
|
186
186
|
they may fail if the test suite is run in this way.
|
187
187
|
|
188
|
+
## OCSP
|
189
|
+
|
190
|
+
There are several types of OCSP tests implemented in the test suite.
|
191
|
+
|
192
|
+
OCSP unit tests are in `spec/integration/ocsp_verifier_spec.rb`. To run
|
193
|
+
these, set `OCSP_VERIFIER=1` in the environment. There must NOT be a process
|
194
|
+
running on the host port 8100 as that port will be used by the OCSP responder
|
195
|
+
launched by the tests.
|
196
|
+
|
197
|
+
For the remaining OCSP tests, the following environment variables must be set
|
198
|
+
to the possible values indicated below:
|
199
|
+
|
200
|
+
OCSP_ALGORITHM=rsa|ecdsa
|
201
|
+
OCSP_STATUS=valid|revoked|unknown
|
202
|
+
OCSP_DELEGATE=0|1
|
203
|
+
OCSP_MUST_STAPLE=0|1
|
204
|
+
|
205
|
+
These tests also require the mock OCSP responder running on the host machine
|
206
|
+
on port 8100 with the configuration that matches the environment variables
|
207
|
+
just described. Please refer to the Docker and Evergreen scripts in the
|
208
|
+
driver repository for further details.
|
209
|
+
|
210
|
+
Additionally, the server must be configured to use the appropriate server
|
211
|
+
certificate and CA certificate from the respective subdirectory of
|
212
|
+
`spec/support/ocsp`. This is easiest to achieve by using the Docker tooling
|
213
|
+
described in `.evergreen/README.md`.
|
214
|
+
|
215
|
+
OCSP connectivity tests are in `spec/integration/ocsp_connectivity.rb`.
|
216
|
+
These test the combinations described
|
217
|
+
[here](https://github.com/mongodb/specifications/blob/master/source/ocsp-support/tests/README.rst#integration-tests-permutations-to-be-tested).
|
218
|
+
To run these tests, set `OCSP_CONNECTIVITY=pass` environment variable if
|
219
|
+
the tests are expected to connect successfully or `OCSP_CONNECTIVITY=fail` if
|
220
|
+
the tests are expected to not connect.
|
221
|
+
Note that some of these configurations require OCSP responder to return
|
222
|
+
the failure response; in such configurations, ONLY the OCSP connectivity tests
|
223
|
+
may pass (since the driver may reject connections to servers when OCSP
|
224
|
+
responder returns the failure response, or OCSP verification otherwise
|
225
|
+
definitively fails).
|
226
|
+
|
227
|
+
When not running either OCSP verifier tests or OCSP connectivity tests but
|
228
|
+
when OCSP algorithm is configured, the test suite will execute normally
|
229
|
+
using the provided `MONGO_URI`. This configuration may be used to exercise
|
230
|
+
OCSP while running the full test suite. In this case, setting `OCSP_STATUS`
|
231
|
+
to `revoked` will generally cause the test suite to fail.
|
232
|
+
|
188
233
|
## Authentication
|
189
234
|
|
190
235
|
mlaunch can configure authentication on the server:
|
@@ -511,6 +556,16 @@ following environment variable:
|
|
511
556
|
|
512
557
|
FORK=1
|
513
558
|
|
559
|
+
OCSP tests require Python 3 with asn1crypto, oscrypto and flask packages
|
560
|
+
installed, and they require the drivers-evergreen-tools submodule to be
|
561
|
+
checked out. To run these tests, set the following environment variable:
|
562
|
+
|
563
|
+
OCSP=1
|
564
|
+
|
565
|
+
To check out the submodule, run:
|
566
|
+
|
567
|
+
git submodule update --init --recursive
|
568
|
+
|
514
569
|
## Debug Logging
|
515
570
|
|
516
571
|
The test suite is run with the driver log level set to `WARN` by default.
|
@@ -25,10 +25,8 @@ describe 'Symbol encoding to BSON' do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'round-trips symbol values using the same byte buffer' do
|
28
|
-
if BSON::Environment.jruby?
|
29
|
-
|
30
|
-
'read and write positions separately in JRuby, as implemented in ' \
|
31
|
-
'bson version 4.11.0. For more information, see https://jira.mongodb.org/browse/RUBY-2128'
|
28
|
+
if BSON::Environment.jruby?
|
29
|
+
pending 'https://jira.mongodb.org/browse/RUBY-2128'
|
32
30
|
end
|
33
31
|
|
34
32
|
Hash.from_bson(hash.to_bson).should == hash
|
@@ -16,4 +16,52 @@ describe 'Bulk writes' do
|
|
16
16
|
end.not_to raise_error
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
context 'when bulk write needs to be split' do
|
21
|
+
let(:subscriber) { EventSubscriber.new }
|
22
|
+
|
23
|
+
let(:max_bson_size) { Mongo::Server::ConnectionBase::DEFAULT_MAX_BSON_OBJECT_SIZE }
|
24
|
+
|
25
|
+
let(:insert_events) do
|
26
|
+
subscriber.command_started_events('insert')
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:failed_events) do
|
30
|
+
subscriber.failed_events
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:operations) do
|
34
|
+
[{ insert_one: { text: 'a' * (max_bson_size/2) } }] * 6
|
35
|
+
end
|
36
|
+
|
37
|
+
before do
|
38
|
+
authorized_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
|
39
|
+
authorized_collection.bulk_write(operations)
|
40
|
+
end
|
41
|
+
|
42
|
+
context '3.6+ server' do
|
43
|
+
min_server_fcv '3.6'
|
44
|
+
|
45
|
+
it 'splits the operations' do
|
46
|
+
# 3.6+ servers can send multiple bulk operations in one message,
|
47
|
+
# with the whole message being limited to 48m.
|
48
|
+
expect(insert_events.length).to eq(2)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'pre-3.6 server' do
|
53
|
+
max_server_version '3.4'
|
54
|
+
|
55
|
+
it 'splits the operations' do
|
56
|
+
# Pre-3.6 servers limit the entire message payload to the size of
|
57
|
+
# a single document which is 16m. Given our test data this means
|
58
|
+
# twice as many messages are sent.
|
59
|
+
expect(insert_events.length).to eq(4)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'does not have a command failed event' do
|
64
|
+
expect(failed_events).to be_empty
|
65
|
+
end
|
66
|
+
end
|
19
67
|
end
|