mongo 2.18.0.beta1 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongo/bulk_write.rb +8 -2
  4. data/lib/mongo/client.rb +19 -5
  5. data/lib/mongo/client_encryption.rb +86 -4
  6. data/lib/mongo/cluster.rb +6 -4
  7. data/lib/mongo/collection/view/aggregation.rb +3 -0
  8. data/lib/mongo/collection/view/change_stream.rb +9 -0
  9. data/lib/mongo/collection/view/iterable.rb +1 -0
  10. data/lib/mongo/collection/view/readable.rb +11 -3
  11. data/lib/mongo/collection.rb +9 -1
  12. data/lib/mongo/config.rb +11 -0
  13. data/lib/mongo/crypt/auto_encrypter.rb +49 -21
  14. data/lib/mongo/crypt/binding.rb +73 -48
  15. data/lib/mongo/crypt/data_key_context.rb +6 -1
  16. data/lib/mongo/crypt/encryption_io.rb +66 -0
  17. data/lib/mongo/crypt/explicit_encrypter.rb +116 -5
  18. data/lib/mongo/crypt/explicit_encryption_context.rb +3 -8
  19. data/lib/mongo/crypt/handle.rb +26 -8
  20. data/lib/mongo/crypt/kms/aws.rb +11 -3
  21. data/lib/mongo/crypt/kms/azure.rb +14 -6
  22. data/lib/mongo/crypt/kms/gcp.rb +12 -5
  23. data/lib/mongo/crypt/kms/kmip.rb +15 -9
  24. data/lib/mongo/crypt/kms/local.rb +9 -1
  25. data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
  26. data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
  27. data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
  28. data/lib/mongo/crypt/status.rb +8 -2
  29. data/lib/mongo/crypt.rb +2 -0
  30. data/lib/mongo/database.rb +10 -27
  31. data/lib/mongo/error/missing_file_chunk.rb +8 -2
  32. data/lib/mongo/grid/stream/read.rb +6 -0
  33. data/lib/mongo/index/view.rb +1 -0
  34. data/lib/mongo/operation/create/op_msg.rb +1 -13
  35. data/lib/mongo/operation/distinct/op_msg.rb +4 -1
  36. data/lib/mongo/protocol/msg.rb +0 -16
  37. data/lib/mongo/server/connection_pool.rb +5 -4
  38. data/lib/mongo/server/monitor/connection.rb +10 -4
  39. data/lib/mongo/server/monitor.rb +4 -0
  40. data/lib/mongo/server/push_monitor.rb +4 -0
  41. data/lib/mongo/version.rb +1 -1
  42. data/lib/mongo.rb +2 -0
  43. data/spec/README.md +14 -0
  44. data/spec/integration/change_stream_spec.rb +1 -1
  45. data/spec/integration/client_construction_spec.rb +73 -7
  46. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +165 -164
  47. data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
  48. data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +5 -5
  49. data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +50 -8
  50. data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
  51. data/spec/integration/ocsp_verifier_spec.rb +1 -1
  52. data/spec/integration/reconnect_spec.rb +2 -0
  53. data/spec/integration/sdam_events_spec.rb +40 -0
  54. data/spec/integration/srv_monitoring_spec.rb +1 -0
  55. data/spec/integration/srv_spec.rb +1 -0
  56. data/spec/lite_spec_helper.rb +5 -4
  57. data/spec/mongo/bulk_write_spec.rb +13 -0
  58. data/spec/mongo/client_construction_spec.rb +45 -2
  59. data/spec/mongo/client_encryption_spec.rb +0 -12
  60. data/spec/mongo/client_spec.rb +1 -1
  61. data/spec/mongo/collection/view/aggregation_spec.rb +119 -0
  62. data/spec/mongo/collection/view/readable_spec.rb +630 -5
  63. data/spec/mongo/collection_spec.rb +32 -0
  64. data/spec/mongo/crypt/auto_encrypter_spec.rb +110 -0
  65. data/spec/mongo/crypt/binding/context_spec.rb +3 -35
  66. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  67. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +8 -3
  68. data/spec/mongo/crypt/handle_spec.rb +39 -3
  69. data/spec/mongo/crypt/kms/credentials_spec.rb +0 -47
  70. data/spec/mongo/index/view_spec.rb +56 -0
  71. data/spec/mongo/operation/create/op_msg_spec.rb +0 -42
  72. data/spec/mongo/server/connection_pool_spec.rb +26 -4
  73. data/spec/mongo/socket/ssl_spec.rb +3 -3
  74. data/spec/runners/crud/requirement.rb +6 -1
  75. data/spec/runners/crud/test.rb +1 -1
  76. data/spec/runners/transactions/spec.rb +2 -2
  77. data/spec/runners/transactions/test.rb +4 -20
  78. data/spec/runners/transactions.rb +2 -2
  79. data/spec/runners/unified/assertions.rb +32 -2
  80. data/spec/runners/unified/change_stream_operations.rb +3 -0
  81. data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
  82. data/spec/runners/unified/crud_operations.rb +17 -2
  83. data/spec/runners/unified/ddl_operations.rb +27 -2
  84. data/spec/runners/unified/grid_fs_operations.rb +21 -0
  85. data/spec/runners/unified/test.rb +59 -1
  86. data/spec/shared/lib/mrss/docker_runner.rb +2 -0
  87. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  88. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  89. data/spec/shared/shlib/set_env.sh +3 -0
  90. data/spec/solo/clean_exit_spec.rb +5 -0
  91. data/spec/spec_tests/client_side_encryption_spec.rb +1 -1
  92. data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
  93. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
  94. data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
  95. data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +1 -1
  96. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +1 -1
  97. data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +2 -2
  98. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +1 -1
  99. data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +2 -2
  100. data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
  101. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
  102. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
  103. data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
  104. data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
  105. data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
  106. data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
  107. data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
  108. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
  109. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
  110. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
  111. data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
  112. data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
  113. data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
  114. data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
  115. data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
  116. data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
  117. data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
  118. data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
  119. data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
  120. data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
  121. data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
  122. data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
  123. data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
  124. data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
  125. data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
  126. data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
  127. data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
  128. data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
  129. data/spec/stress/connection_pool_timing_spec.rb +2 -2
  130. data/spec/support/background_thread_registry.rb +3 -13
  131. data/spec/support/certificates/atlas-ocsp-ca.crt +40 -47
  132. data/spec/support/certificates/atlas-ocsp.crt +101 -106
  133. data/spec/support/crypt.rb +57 -13
  134. data/spec/support/macros.rb +10 -0
  135. data/spec/support/spec_config.rb +4 -0
  136. data.tar.gz.sig +0 -0
  137. metadata +1271 -1219
  138. metadata.gz.sig +0 -0
  139. data/spec/spec_tests/command_monitoring_spec.rb +0 -71
  140. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
  141. data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
  142. data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
  143. data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
  144. data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
  145. data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
  146. data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
  147. data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
  148. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
  149. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -90
@@ -24,11 +24,15 @@ module Mongo
24
24
  #
25
25
  # @api private
26
26
  class Credentials
27
+ extend Forwardable
27
28
  include KMS::Validations
28
29
 
29
30
  # @return [ String ] KMIP KMS endpoint with optional port.
30
31
  attr_reader :endpoint
31
32
 
33
+ # @api private
34
+ def_delegator :@opts, :empty?
35
+
32
36
  FORMAT_HINT = "KMIP KMS provider options must be in the format: " +
33
37
  "{ endpoint: 'ENDPOINT' }"
34
38
 
@@ -41,13 +45,17 @@ module Mongo
41
45
  # @raise [ ArgumentError ] If required options are missing or incorrectly
42
46
  # formatted.
43
47
  def initialize(opts)
44
- @endpoint = validate_param(:endpoint, opts, FORMAT_HINT)
48
+ @opts = opts
49
+ unless empty?
50
+ @endpoint = validate_param(:endpoint, opts, FORMAT_HINT)
51
+ end
45
52
  end
46
53
 
47
54
  # Convert credentials object to a BSON document in libmongocrypt format.
48
55
  #
49
56
  # @return [ BSON::Document ] Local KMS credentials in libmongocrypt format.
50
57
  def to_document
58
+ return BSON::Document.new({}) if empty?
51
59
  BSON::Document.new({
52
60
  endpoint: endpoint,
53
61
  })
@@ -74,17 +82,17 @@ module Mongo
74
82
  #
75
83
  # @param [ Hash ] opts A hash that contains master key options for
76
84
  # KMIP KMS provider
77
- # @option opts [ String ] :key_id KMIP Unique Identifier to
85
+ # @option opts [ String | nil ] :key_id KMIP Unique Identifier to
78
86
  # a 96 byte KMIP Secret Data managed object, optional. If key_id
79
87
  # is omitted, the driver creates a random 96 byte identifier.
80
- # @option opts [ String ] :endpoint KMIP endpoint, optional.
88
+ # @option opts [ String | nil ] :endpoint KMIP endpoint, optional.
81
89
  #
82
90
  # @raise [ ArgumentError ] If required options are missing or incorrectly
83
91
  # formatted.
84
- def initialize(opts)
92
+ def initialize(opts = {})
85
93
  @key_id = validate_param(
86
94
  :key_id, opts, FORMAT_HINT, required: false
87
- ) || SecureRandom.alphanumeric(96)
95
+ )
88
96
  @endpoint = validate_param(
89
97
  :endpoint, opts, FORMAT_HINT, required: false
90
98
  )
@@ -96,11 +104,9 @@ module Mongo
96
104
  def to_document
97
105
  BSON::Document.new({
98
106
  provider: 'kmip',
99
- keyId: key_id
100
107
  }).tap do |bson|
101
- unless endpoint.nil?
102
- bson.update({ endpoint: endpoint })
103
- end
108
+ bson.update({ endpoint: endpoint }) unless endpoint.nil?
109
+ bson.update({ keyId: key_id }) unless key_id.nil?
104
110
  end
105
111
  end
106
112
  end
@@ -23,11 +23,15 @@ module Mongo
23
23
  #
24
24
  # @api private
25
25
  class Credentials
26
+ extend Forwardable
26
27
  include KMS::Validations
27
28
 
28
29
  # @return [ String ] Master key.
29
30
  attr_reader :key
30
31
 
32
+ # @api private
33
+ def_delegator :@opts, :empty?
34
+
31
35
  FORMAT_HINT = "Local KMS provider options must be in the format: " +
32
36
  "{ key: 'MASTER-KEY' }"
33
37
 
@@ -40,11 +44,15 @@ module Mongo
40
44
  # @raise [ ArgumentError ] If required options are missing or incorrectly
41
45
  # formatted.
42
46
  def initialize(opts)
43
- @key = validate_param(:key, opts, FORMAT_HINT)
47
+ @opts = opts
48
+ unless empty?
49
+ @key = validate_param(:key, opts, FORMAT_HINT)
50
+ end
44
51
  end
45
52
 
46
53
  # @return [ BSON::Document ] Local KMS credentials in libmongocrypt format.
47
54
  def to_document
55
+ return BSON::Document.new({}) if empty?
48
56
  BSON::Document.new({
49
57
  key: BSON::Binary.new(@key, :generic),
50
58
  })
@@ -41,7 +41,7 @@ module Mongo
41
41
  if options.nil?
42
42
  raise ArgumentError.new('Key document options must not be nil')
43
43
  end
44
- master_key = options[:master_key]
44
+ master_key = options.fetch(:master_key, {})
45
45
  @key_document = case kms_provider.to_s
46
46
  when 'aws' then KMS::AWS::MasterKeyDocument.new(master_key)
47
47
  when 'azure' then KMS::Azure::MasterKeyDocument.new(master_key)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2019-2020 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Mongo
19
+ module Crypt
20
+
21
+ # A Context object initialized specifically for the purpose of rewrapping
22
+ # data keys (decrypting and re-rencryting using a new KEK).
23
+ #
24
+ # @api private
25
+ class RewrapManyDataKeyContext < Context
26
+
27
+ # Create a new RewrapManyDataKeyContext object
28
+ #
29
+ # @param [ Mongo::Crypt::Handle ] mongocrypt a Handle that
30
+ # wraps a mongocrypt_t object used to create a new mongocrypt_ctx_t
31
+ # @param [ Mongo::Crypt::EncryptionIO ] io An object that performs all
32
+ # driver I/O on behalf of libmongocrypt
33
+ # @param [ Hash ] filter Filter used to find keys to be updated.
34
+ # alternate names for the new data key.
35
+ # @param [ Mongo::Crypt::KMS::MasterKeyDocument | nil ] master_key_document The optional master
36
+ # key document that contains master encryption key parameters.
37
+ def initialize(mongocrypt, io, filter, master_key_document)
38
+ super(mongocrypt, io)
39
+ if master_key_document
40
+ Binding.ctx_setopt_key_encryption_key(self, master_key_document.to_document)
41
+ end
42
+ Binding.ctx_rewrap_many_datakey_init(self, filter)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2019-2022 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Mongo
19
+ module Crypt
20
+ # Represent result of the rewrap many data ke operation.
21
+ #
22
+ # @api semiprivate
23
+ class RewrapManyDataKeyResult
24
+
25
+ # @returns [ BulkWrite::Result ] the result of the bulk write operation
26
+ # used to update the key vault collection with rewrapped data keys.
27
+ attr_reader :bulk_write_result
28
+
29
+ # @param [ BulkWrite::Result | nil ] bulk_write_result The result of the
30
+ # bulk write operation used to update the key vault collection
31
+ # with rewrapped data keys.
32
+ def initialize(bulk_write_result)
33
+ @bulk_write_result = bulk_write_result
34
+ end
35
+ end
36
+ end
37
+ end
@@ -118,10 +118,16 @@ module Mongo
118
118
  # information stored in this status
119
119
  #
120
120
  # Does nothing if self.ok? is true
121
- def raise_crypt_error
121
+ #
122
+ # @param kms [ true | false ] Whether the operation was against the KMS.
123
+ #
124
+ # @note If kms parameter is false, the error may still have come from a
125
+ # KMS. The kms parameter simply forces all errors to be treated as
126
+ # KMS errors.
127
+ def raise_crypt_error(kms: false)
122
128
  return if ok?
123
129
 
124
- if label == :error_kms
130
+ if kms || label == :error_kms
125
131
  error = Error::KmsError.new(message, code: code)
126
132
  else
127
133
  error = Error::CryptError.new(message, code: code)
data/lib/mongo/crypt.rb CHANGED
@@ -29,6 +29,8 @@ module Mongo
29
29
  autoload(:AutoEncryptionContext, 'mongo/crypt/auto_encryption_context')
30
30
  autoload(:ExplicitDecryptionContext, 'mongo/crypt/explicit_decryption_context')
31
31
  autoload(:AutoDecryptionContext, 'mongo/crypt/auto_decryption_context')
32
+ autoload(:RewrapManyDataKeyContext, 'mongo/crypt/rewrap_many_data_key_context')
33
+ autoload(:RewrapManyDataKeyResult, 'mongo/crypt/rewrap_many_data_key_result')
32
34
  autoload(:EncryptionIO, 'mongo/crypt/encryption_io')
33
35
  autoload(:ExplicitEncrypter, 'mongo/crypt/explicit_encrypter')
34
36
  autoload(:AutoEncrypter, 'mongo/crypt/auto_encrypter')
@@ -225,33 +225,8 @@ module Mongo
225
225
 
226
226
  client.send(:with_session, opts) do |session|
227
227
  server = selector.select_server(cluster, nil, session)
228
- # This code MUST be removed as soon as server starts accepting
229
- # contention as int32.
230
- _operation = operation.dup
231
- if _operation['encryptedFields'] && _operation['encryptedFields'].key?('fields')
232
- _operation['encryptedFields']['fields'] = _operation['encryptedFields']['fields'].map do |field|
233
- if field['queries'] && field['queries'].key?('contention')
234
- field['queries']['contention'] = BSON::Int64.new(field['queries']['contention'])
235
- end
236
- field
237
- end
238
- end
239
- if schema = _operation.dig('encryptionInformation', 'schema')
240
- _operation['encryptionInformation']['schema'] = schema.map do |coll, params|
241
- if params['fields']
242
- params['fields'] = params['fields'].map do |field|
243
- if contention = field.dig('queries', 'contention')
244
- field['queries']['contention'] = BSON::Int64.new(contention)
245
- end
246
- field
247
- end
248
- end
249
- [coll, params]
250
- end.to_h
251
- end
252
- # End of code to be removed
253
228
  op = Operation::Command.new(
254
- :selector => _operation,
229
+ :selector => operation,
255
230
  :db_name => name,
256
231
  :read => selector,
257
232
  :session => session
@@ -481,6 +456,11 @@ module Mongo
481
456
  # Only recognized by server versions 4.0+.
482
457
  # @option options [ Object ] :comment A user-provided
483
458
  # comment to attach to this command.
459
+ # @option options [ Boolean ] :show_expanded_events Enables the server to
460
+ # send the 'expanded' list of change stream events. The list of additional
461
+ # events included with this flag set are: createIndexes, dropIndexes,
462
+ # modify, create, shardCollection, reshardCollection,
463
+ # refineCollectionShardKey.
484
464
  #
485
465
  # @note A change stream only allows 'majority' read concern.
486
466
  # @note This helper method is preferable to running a raw aggregation with a $changeStream
@@ -490,8 +470,11 @@ module Mongo
490
470
  #
491
471
  # @since 2.6.0
492
472
  def watch(pipeline = [], options = {})
473
+ view_options = options.dup
474
+ view_options[:await_data] = true if options[:max_await_time_ms]
475
+
493
476
  Mongo::Collection::View::ChangeStream.new(
494
- Mongo::Collection::View.new(collection("#{COMMAND}.aggregate")),
477
+ Mongo::Collection::View.new(collection("#{COMMAND}.aggregate"), {}, view_options),
495
478
  pipeline,
496
479
  Mongo::Collection::View::ChangeStream::DATABASE,
497
480
  options)
@@ -30,11 +30,17 @@ module Mongo
30
30
  # Mongo::Error::MissingFileChunk.new(expected_n, chunk)
31
31
  #
32
32
  # @param [ Integer ] expected_n The expected index value.
33
- # @param [ Grid::File::Chunk ] chunk The chunk read from GridFS.
33
+ # @param [ Grid::File::Chunk | Integer ] chunk The chunk read from GridFS.
34
34
  #
35
35
  # @since 2.1.0
36
+ #
37
+ # @api private
36
38
  def initialize(expected_n, chunk)
37
- super("Unexpected chunk in sequence. Expected next chunk to have index #{expected_n} but it has index #{chunk.n}")
39
+ if chunk.is_a?(Integer)
40
+ super("Missing chunk(s). Expected #{expected_n} chunks but got #{chunk}.")
41
+ else
42
+ super("Unexpected chunk in sequence. Expected next chunk to have index #{expected_n} but it has index #{chunk.n}")
43
+ end
38
44
  end
39
45
  end
40
46
  end
@@ -79,13 +79,19 @@ module Mongo
79
79
  ensure_readable!
80
80
  info = file_info
81
81
  num_chunks = (info.length + info.chunk_size - 1) / info.chunk_size
82
+ num_read = 0
82
83
  if block_given?
83
84
  view.each_with_index.reduce(0) do |length_read, (doc, index)|
84
85
  chunk = Grid::File::Chunk.new(doc)
85
86
  validate!(index, num_chunks, chunk, length_read)
86
87
  data = chunk.data.data
87
88
  yield data
89
+ num_read += 1
88
90
  length_read += data.size
91
+ end.tap do
92
+ if num_read < num_chunks
93
+ raise Error::MissingFileChunk.new(num_chunks, num_read)
94
+ end
89
95
  end
90
96
  else
91
97
  view.to_enum
@@ -71,6 +71,7 @@ module Mongo
71
71
  :weights => :weights,
72
72
  :collation => :collation,
73
73
  :comment => :comment,
74
+ :wildcard_projection => :wildcardProjection,
74
75
  }.freeze
75
76
 
76
77
  # Drop an index by its name.
@@ -34,19 +34,7 @@ module Mongo
34
34
  spec[:selector].merge(
35
35
  collation: spec[:collation],
36
36
  encryptedFields: spec[:encrypted_fields],
37
- ).compact.tap do |sel|
38
- # This code MUST be removed as soon as server starts accepting
39
- # contention as int32.
40
- if sel[:encryptedFields] && sel[:encryptedFields].key?('fields')
41
- sel[:encryptedFields]['fields'] = sel[:encryptedFields]['fields'].map do |field|
42
- if field['queries'] && field['queries'].key?('contention')
43
- field['queries']['contention'] = BSON::Int64.new(field['queries']['contention'])
44
- end
45
- field
46
- end
47
- end
48
- # End of code to be removed
49
- end
37
+ ).compact
50
38
  end
51
39
  end
52
40
  end
@@ -32,7 +32,10 @@ module Mongo
32
32
 
33
33
  def selector(connection)
34
34
  # Collation is always supported on 3.6+ servers that would use OP_MSG.
35
- spec[:selector].merge(collation: spec[:collation]).compact
35
+ spec[:selector].merge(
36
+ collation: spec[:collation],
37
+ comment: spec[:comment],
38
+ ).compact
36
39
  end
37
40
  end
38
41
  end
@@ -229,22 +229,6 @@ module Mongo
229
229
  if cmd.key?('$db') && !enc_cmd.key?('$db')
230
230
  enc_cmd['$db'] = cmd['$db']
231
231
  end
232
- # This code MUST be removed as soon as server starts accepting
233
- # contention as int32.
234
- if schema = enc_cmd.dig('encryptionInformation', 'schema')
235
- enc_cmd['encryptionInformation']['schema'] = schema.map do |coll, params|
236
- if params['fields']
237
- params['fields'] = params['fields'].map do |field|
238
- if contention = field.dig('queries', 'contention')
239
- field['queries']['contention'] = BSON::Int64.new(contention)
240
- end
241
- field
242
- end
243
- end
244
- [coll, params]
245
- end.to_h
246
- end
247
- # End of code to be removed
248
232
 
249
233
  Msg.new(@flags, @options, enc_cmd)
250
234
  else
@@ -29,7 +29,7 @@ module Mongo
29
29
  # The default max size for the connection pool.
30
30
  #
31
31
  # @since 2.9.0
32
- DEFAULT_MAX_SIZE = 5.freeze
32
+ DEFAULT_MAX_SIZE = 20.freeze
33
33
 
34
34
  # The default min size for the connection pool.
35
35
  #
@@ -59,7 +59,8 @@ module Mongo
59
59
  # @param [ Server ] server The server which this connection pool is for.
60
60
  # @param [ Hash ] options The connection pool options.
61
61
  #
62
- # @option options [ Integer ] :max_size The maximum pool size.
62
+ # @option options [ Integer ] :max_size The maximum pool size. Setting
63
+ # this option to zero creates an unlimited connection pool.
63
64
  # @option options [ Integer ] :max_pool_size Deprecated.
64
65
  # The maximum pool size. If max_size is also given, max_size and
65
66
  # max_pool_size must be identical.
@@ -98,7 +99,7 @@ module Mongo
98
99
  options[:max_size] ||= options[:max_pool_size]
99
100
  options.delete(:max_pool_size)
100
101
  if options[:min_size] && options[:max_size] &&
101
- options[:min_size] > options[:max_size]
102
+ (options[:max_size] != 0 && options[:min_size] > options[:max_size])
102
103
  then
103
104
  raise ArgumentError, "Cannot have min size #{options[:min_size]} exceed max size #{options[:max_size]}"
104
105
  end
@@ -377,7 +378,7 @@ module Mongo
377
378
  #
378
379
  # Ruby does not allow a thread to lock a mutex which it already
379
380
  # holds.
380
- if unsynchronized_size < max_size
381
+ if max_size == 0 || unsynchronized_size < max_size
381
382
  connection = create_connection
382
383
  @pending_connections << connection
383
384
  throw(:done)
@@ -228,15 +228,21 @@ module Mongo
228
228
  # @api private
229
229
  def check_document
230
230
  server_api = @app_metadata.server_api || options[:server_api]
231
- if hello_ok? || server_api
232
- doc = HELLO_DOC
231
+ doc = if hello_ok? || server_api
232
+ _doc = HELLO_DOC
233
233
  if server_api
234
- doc = doc.merge(Utils.transform_server_api(server_api))
234
+ _doc = _doc.merge(Utils.transform_server_api(server_api))
235
235
  end
236
- doc
236
+ _doc
237
237
  else
238
238
  LEGACY_HELLO_DOC
239
239
  end
240
+ # compressors must be set to maintain correct compression status
241
+ # in the server description. See RUBY-2427
242
+ if compressors = options[:compressors]
243
+ doc = doc.merge(compression: compressors)
244
+ end
245
+ doc
240
246
  end
241
247
 
242
248
  private
@@ -268,6 +268,10 @@ module Mongo
268
268
  end
269
269
  end
270
270
 
271
+ def to_s
272
+ "#<#{self.class.name}:#{object_id} #{server.address}>"
273
+ end
274
+
271
275
  private
272
276
 
273
277
  def pre_stop
@@ -196,6 +196,10 @@ module Mongo
196
196
  end
197
197
  end
198
198
 
199
+ def to_s
200
+ "#<#{self.class.name}:#{object_id} #{server.address}>"
201
+ end
202
+
199
203
  end
200
204
  end
201
205
  end
data/lib/mongo/version.rb CHANGED
@@ -20,5 +20,5 @@ module Mongo
20
20
  # The current version of the driver.
21
21
  #
22
22
  # @since 2.0.0
23
- VERSION = '2.18.0.beta1'.freeze
23
+ VERSION = '2.18.0'.freeze
24
24
  end
data/lib/mongo.rb CHANGED
@@ -94,6 +94,8 @@ module Mongo
94
94
  # Take all the public instance methods from the Config singleton and allow
95
95
  # them to be accessed through the Mongo module directly.
96
96
  def_delegators Config, :options=
97
+ delegate_option Config, :broken_view_aggregate
98
+ delegate_option Config, :broken_view_options
97
99
  delegate_option Config, :validate_update_replace
98
100
  end
99
101
 
data/spec/README.md CHANGED
@@ -713,3 +713,17 @@ To break into the debugger on JRuby, call:
713
713
 
714
714
  require 'ruby-debug'
715
715
  debugger
716
+
717
+ ## Testing against load balancer locally
718
+
719
+ 1. Install mongodb server v5.2+.
720
+ 2. Install haproxy.
721
+ 3. Install mongo-orchestration - https://github.com/10gen/mongo-orchestration/
722
+ 4. Install drivers-evergreen-tools - https://github.com/mongodb-labs/drivers-evergreen-tools. In ruby driver it is installed as git submodule under `.mod/drivers-evergreen-tools/`.
723
+ 5. Start mongo-orchestration: `mongo-orchestration start`.
724
+ 6. Start the cluster: `http PUT http://localhost:8889/v1/sharded_clusters/myCluster @.mod/drivers-evergreen-tools/.evergreen/orchestration/configs/sharded_clusters/basic-load-balancer.json` (this example uses httpie client, can be done with curl).
725
+ 7. Start load balancer: `MONGODB_URI="mongodb://localhost:27017,localhost:27018/" .mod/drivers-evergreen-tools/.evergreen/run-load-balancer.sh start`.
726
+ 8. Run tests: `TOPOLOGY=load-balanced MONGODB_URI='mongodb://127.0.0.1:8000/?loadBalanced=true' be rspec spec/`.
727
+ 9. Stop load balancer: `MONGODB_URI="mongodb://localhost:27017,localhost:27018/" .mod/drivers-evergreen-tools/.evergreen/run-load-balancer.sh stop`.
728
+ 10. Stop the cluster: `http DELETE http://localhost:8889/v1/sharded_clusters/myCluster`
729
+ 11. Stop mongo-orchestration: `mongo-orchestration stop`.
@@ -4,7 +4,7 @@
4
4
  require 'spec_helper'
5
5
 
6
6
  describe 'Change stream integration' do
7
- retry_test 4
7
+ retry_test tries: 4
8
8
  require_mri
9
9
  max_example_run_time 7
10
10
  min_server_fcv '3.6'
@@ -191,16 +191,82 @@ describe 'Client construction' do
191
191
  context 'with default key vault client' do
192
192
  let(:key_vault_client) { nil }
193
193
 
194
- it 'creates a working key vault client' do
195
- key_vault_client = client.encrypter.key_vault_client
194
+ shared_examples 'creates a working key vault client' do
195
+ it 'creates a working key vault client' do
196
+ key_vault_client = client.encrypter.key_vault_client
196
197
 
197
- result = key_vault_client[:test].insert_one(test: 1)
198
- expect(result).to be_ok
198
+ result = key_vault_client[:test].insert_one(test: 1)
199
+ expect(result).to be_ok
200
+ end
199
201
  end
200
202
 
201
- it 'creates a key vault client with the same cluster as the existing client' do
202
- key_vault_client = client.encrypter.key_vault_client
203
- expect(key_vault_client.cluster).to eq(client.cluster)
203
+ context 'when top-level max pool size is not 0' do
204
+ include_examples 'creates a working key vault client'
205
+
206
+ shared_examples 'limited connection pool' do
207
+ it 'creates a key vault client with a different cluster than the existing client' do
208
+ key_vault_client = client.encrypter.key_vault_client
209
+ expect(key_vault_client.cluster).not_to eq(client.cluster)
210
+ end
211
+
212
+ # min pool size for the key vault client can be greater than 0
213
+ # when the key vault client is the same as the top-level client.
214
+ # This is OK because we aren't making any more connections for FLE,
215
+ # the minimum was requested by application for its own needs.
216
+ it 'uses min pool size 0 for key vault client' do
217
+ key_vault_client = client.encrypter.key_vault_client
218
+ key_vault_client.options[:min_pool_size].should be 0
219
+ end
220
+ end
221
+
222
+ context 'when top-level max pool size is not specified' do
223
+ before do
224
+ client.options[:max_pool_size].should be nil
225
+ end
226
+
227
+ include_examples 'limited connection pool'
228
+
229
+ it 'uses unspecified max pool size for key vault client' do
230
+ key_vault_client = client.encrypter.key_vault_client
231
+ key_vault_client.options[:max_pool_size].should be nil
232
+ end
233
+ end
234
+
235
+ context 'when top-level max pool size is specified' do
236
+ let(:options) do
237
+ {
238
+ auto_encryption_options: auto_encryption_options,
239
+ max_pool_size: 42,
240
+ }
241
+ end
242
+
243
+ include_examples 'limited connection pool'
244
+
245
+ it 'uses the same max pool size for key vault client' do
246
+ key_vault_client = client.encrypter.key_vault_client
247
+ key_vault_client.options[:max_pool_size].should be 42
248
+ end
249
+ end
250
+ end
251
+
252
+ context 'when top-level max pool size is 0' do
253
+ let(:options) do
254
+ {
255
+ auto_encryption_options: auto_encryption_options,
256
+ max_pool_size: 0,
257
+ }
258
+ end
259
+
260
+ before do
261
+ client.options[:max_pool_size].should be 0
262
+ end
263
+
264
+ include_examples 'creates a working key vault client'
265
+
266
+ it 'creates a key vault client with the same cluster as the existing client' do
267
+ key_vault_client = client.encrypter.key_vault_client
268
+ expect(key_vault_client.cluster).to eq(client.cluster)
269
+ end
204
270
  end
205
271
  end
206
272
  end