mongo 2.18.0.beta1 → 2.18.0
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/bulk_write.rb +8 -2
- data/lib/mongo/client.rb +19 -5
- data/lib/mongo/client_encryption.rb +86 -4
- data/lib/mongo/cluster.rb +6 -4
- data/lib/mongo/collection/view/aggregation.rb +3 -0
- data/lib/mongo/collection/view/change_stream.rb +9 -0
- data/lib/mongo/collection/view/iterable.rb +1 -0
- data/lib/mongo/collection/view/readable.rb +11 -3
- data/lib/mongo/collection.rb +9 -1
- data/lib/mongo/config.rb +11 -0
- data/lib/mongo/crypt/auto_encrypter.rb +49 -21
- data/lib/mongo/crypt/binding.rb +73 -48
- data/lib/mongo/crypt/data_key_context.rb +6 -1
- data/lib/mongo/crypt/encryption_io.rb +66 -0
- data/lib/mongo/crypt/explicit_encrypter.rb +116 -5
- data/lib/mongo/crypt/explicit_encryption_context.rb +3 -8
- data/lib/mongo/crypt/handle.rb +26 -8
- data/lib/mongo/crypt/kms/aws.rb +11 -3
- data/lib/mongo/crypt/kms/azure.rb +14 -6
- data/lib/mongo/crypt/kms/gcp.rb +12 -5
- data/lib/mongo/crypt/kms/kmip.rb +15 -9
- data/lib/mongo/crypt/kms/local.rb +9 -1
- data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
- data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
- data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
- data/lib/mongo/crypt/status.rb +8 -2
- data/lib/mongo/crypt.rb +2 -0
- data/lib/mongo/database.rb +10 -27
- data/lib/mongo/error/missing_file_chunk.rb +8 -2
- data/lib/mongo/grid/stream/read.rb +6 -0
- data/lib/mongo/index/view.rb +1 -0
- data/lib/mongo/operation/create/op_msg.rb +1 -13
- data/lib/mongo/operation/distinct/op_msg.rb +4 -1
- data/lib/mongo/protocol/msg.rb +0 -16
- data/lib/mongo/server/connection_pool.rb +5 -4
- data/lib/mongo/server/monitor/connection.rb +10 -4
- data/lib/mongo/server/monitor.rb +4 -0
- data/lib/mongo/server/push_monitor.rb +4 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +2 -0
- data/spec/README.md +14 -0
- data/spec/integration/change_stream_spec.rb +1 -1
- data/spec/integration/client_construction_spec.rb +73 -7
- data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +165 -164
- data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
- data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +5 -5
- data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +50 -8
- data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
- data/spec/integration/ocsp_verifier_spec.rb +1 -1
- data/spec/integration/reconnect_spec.rb +2 -0
- data/spec/integration/sdam_events_spec.rb +40 -0
- data/spec/integration/srv_monitoring_spec.rb +1 -0
- data/spec/integration/srv_spec.rb +1 -0
- data/spec/lite_spec_helper.rb +5 -4
- data/spec/mongo/bulk_write_spec.rb +13 -0
- data/spec/mongo/client_construction_spec.rb +45 -2
- data/spec/mongo/client_encryption_spec.rb +0 -12
- data/spec/mongo/client_spec.rb +1 -1
- data/spec/mongo/collection/view/aggregation_spec.rb +119 -0
- data/spec/mongo/collection/view/readable_spec.rb +630 -5
- data/spec/mongo/collection_spec.rb +32 -0
- data/spec/mongo/crypt/auto_encrypter_spec.rb +110 -0
- data/spec/mongo/crypt/binding/context_spec.rb +3 -35
- data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +8 -3
- data/spec/mongo/crypt/handle_spec.rb +39 -3
- data/spec/mongo/crypt/kms/credentials_spec.rb +0 -47
- data/spec/mongo/index/view_spec.rb +56 -0
- data/spec/mongo/operation/create/op_msg_spec.rb +0 -42
- data/spec/mongo/server/connection_pool_spec.rb +26 -4
- data/spec/mongo/socket/ssl_spec.rb +3 -3
- data/spec/runners/crud/requirement.rb +6 -1
- data/spec/runners/crud/test.rb +1 -1
- data/spec/runners/transactions/spec.rb +2 -2
- data/spec/runners/transactions/test.rb +4 -20
- data/spec/runners/transactions.rb +2 -2
- data/spec/runners/unified/assertions.rb +32 -2
- data/spec/runners/unified/change_stream_operations.rb +3 -0
- data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
- data/spec/runners/unified/crud_operations.rb +17 -2
- data/spec/runners/unified/ddl_operations.rb +27 -2
- data/spec/runners/unified/grid_fs_operations.rb +21 -0
- data/spec/runners/unified/test.rb +59 -1
- data/spec/shared/lib/mrss/docker_runner.rb +2 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
- data/spec/shared/shlib/set_env.sh +3 -0
- data/spec/solo/clean_exit_spec.rb +5 -0
- data/spec/spec_tests/client_side_encryption_spec.rb +1 -1
- data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
- data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
- data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
- data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +2 -2
- data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +2 -2
- data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
- data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
- data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
- data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
- data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
- data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
- data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
- data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
- data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
- data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
- data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
- data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
- data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
- data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
- data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
- data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
- data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
- data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
- data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
- data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
- data/spec/stress/connection_pool_timing_spec.rb +2 -2
- data/spec/support/background_thread_registry.rb +3 -13
- data/spec/support/certificates/atlas-ocsp-ca.crt +40 -47
- data/spec/support/certificates/atlas-ocsp.crt +101 -106
- data/spec/support/crypt.rb +57 -13
- data/spec/support/macros.rb +10 -0
- data/spec/support/spec_config.rb +4 -0
- data.tar.gz.sig +0 -0
- metadata +1271 -1219
- metadata.gz.sig +0 -0
- data/spec/spec_tests/command_monitoring_spec.rb +0 -71
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
- data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
- data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
- data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
- data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
- data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
- data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
- data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
- data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -90
data/lib/mongo/crypt/kms/kmip.rb
CHANGED
|
@@ -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
|
-
@
|
|
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
|
-
)
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
|
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
|
data/lib/mongo/crypt/status.rb
CHANGED
|
@@ -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
|
-
|
|
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')
|
data/lib/mongo/database.rb
CHANGED
|
@@ -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 =>
|
|
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
|
-
|
|
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
|
data/lib/mongo/index/view.rb
CHANGED
|
@@ -34,19 +34,7 @@ module Mongo
|
|
|
34
34
|
spec[:selector].merge(
|
|
35
35
|
collation: spec[:collation],
|
|
36
36
|
encryptedFields: spec[:encrypted_fields],
|
|
37
|
-
).compact
|
|
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(
|
|
35
|
+
spec[:selector].merge(
|
|
36
|
+
collation: spec[:collation],
|
|
37
|
+
comment: spec[:comment],
|
|
38
|
+
).compact
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
41
|
end
|
data/lib/mongo/protocol/msg.rb
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
231
|
+
doc = if hello_ok? || server_api
|
|
232
|
+
_doc = HELLO_DOC
|
|
233
233
|
if server_api
|
|
234
|
-
|
|
234
|
+
_doc = _doc.merge(Utils.transform_server_api(server_api))
|
|
235
235
|
end
|
|
236
|
-
|
|
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
|
data/lib/mongo/server/monitor.rb
CHANGED
data/lib/mongo/version.rb
CHANGED
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`.
|
|
@@ -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
|
-
|
|
195
|
-
|
|
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
|
-
|
|
198
|
-
|
|
198
|
+
result = key_vault_client[:test].insert_one(test: 1)
|
|
199
|
+
expect(result).to be_ok
|
|
200
|
+
end
|
|
199
201
|
end
|
|
200
202
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|