mongo 2.12.0.rc0 → 2.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +2 -1
  5. data/lib/mongo/client.rb +23 -9
  6. data/lib/mongo/client_encryption.rb +1 -1
  7. data/lib/mongo/cluster.rb +6 -2
  8. data/lib/mongo/crypt/auto_decryption_context.rb +3 -5
  9. data/lib/mongo/crypt/auto_encrypter.rb +17 -7
  10. data/lib/mongo/crypt/binding.rb +446 -379
  11. data/lib/mongo/crypt/context.rb +4 -4
  12. data/lib/mongo/crypt/encryption_io.rb +16 -10
  13. data/lib/mongo/crypt/explicit_encrypter.rb +3 -3
  14. data/lib/mongo/crypt/explicit_encryption_context.rb +1 -1
  15. data/lib/mongo/crypt/handle.rb +26 -4
  16. data/lib/mongo/crypt/hooks.rb +1 -1
  17. data/lib/mongo/database.rb +11 -1
  18. data/lib/mongo/error/bulk_write_error.rb +16 -14
  19. data/lib/mongo/error/notable.rb +0 -15
  20. data/lib/mongo/error/parser.rb +1 -1
  21. data/lib/mongo/grid/file/info.rb +1 -1
  22. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
  23. data/lib/mongo/operation/insert/command.rb +3 -2
  24. data/lib/mongo/operation/insert/legacy.rb +2 -1
  25. data/lib/mongo/operation/insert/op_msg.rb +1 -1
  26. data/lib/mongo/operation/shared/executable.rb +9 -9
  27. data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
  28. data/lib/mongo/operation/shared/read_preference_supported.rb +68 -19
  29. data/lib/mongo/operation/shared/response_handling.rb +1 -1
  30. data/lib/mongo/operation/shared/sessions_supported.rb +44 -3
  31. data/lib/mongo/protocol/bit_vector.rb +2 -1
  32. data/lib/mongo/protocol/message.rb +22 -7
  33. data/lib/mongo/protocol/msg.rb +2 -5
  34. data/lib/mongo/protocol/serializers.rb +32 -11
  35. data/lib/mongo/retryable.rb +1 -1
  36. data/lib/mongo/server/connection.rb +1 -1
  37. data/lib/mongo/server/connection_base.rb +9 -4
  38. data/lib/mongo/server/connection_pool/populator.rb +1 -1
  39. data/lib/mongo/session.rb +1 -1
  40. data/lib/mongo/srv/monitor.rb +73 -42
  41. data/lib/mongo/srv/result.rb +0 -1
  42. data/lib/mongo/uri.rb +1 -1
  43. data/lib/mongo/uri/srv_protocol.rb +1 -1
  44. data/lib/mongo/version.rb +1 -1
  45. data/mongo.gemspec +0 -2
  46. data/spec/README.md +106 -12
  47. data/spec/integration/client_construction_spec.rb +29 -5
  48. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +6 -4
  49. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +19 -17
  50. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +5 -4
  51. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +11 -8
  52. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +14 -9
  53. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +46 -45
  54. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +11 -7
  55. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +13 -9
  56. data/spec/integration/client_side_encryption/client_close_spec.rb +10 -6
  57. data/spec/integration/client_side_encryption/corpus_spec.rb +19 -14
  58. data/spec/integration/client_side_encryption/data_key_spec.rb +10 -8
  59. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +12 -8
  60. data/spec/integration/client_side_encryption/views_spec.rb +6 -4
  61. data/spec/integration/client_update_spec.rb +36 -2
  62. data/spec/integration/crud_spec.rb +89 -0
  63. data/spec/integration/read_preference_spec.rb +26 -0
  64. data/spec/integration/srv_monitoring_spec.rb +2 -2
  65. data/spec/kerberos/kerberos_spec.rb +87 -0
  66. data/spec/lite_spec_helper.rb +4 -8
  67. data/spec/mongo/bulk_write/result_spec.rb +11 -7
  68. data/spec/mongo/client_encryption_spec.rb +3 -6
  69. data/spec/mongo/crypt/auto_encrypter_spec.rb +8 -3
  70. data/spec/mongo/crypt/handle_spec.rb +38 -4
  71. data/spec/mongo/error/bulk_write_error_spec.rb +49 -0
  72. data/spec/mongo/error/notable_spec.rb +59 -0
  73. data/spec/mongo/operation/find/legacy_spec.rb +1 -0
  74. data/spec/mongo/operation/read_preference_legacy_spec.rb +351 -0
  75. data/spec/mongo/operation/read_preference_op_msg_spec.rb +194 -0
  76. data/spec/mongo/srv/monitor_spec.rb +88 -69
  77. data/spec/runners/transactions.rb +5 -7
  78. data/spec/spec_tests/client_side_encryption_spec.rb +0 -5
  79. data/spec/spec_tests/data/client_side_encryption/bulk.yml +3 -0
  80. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +4 -1
  81. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +3 -0
  82. data/spec/support/cluster_tools.rb +6 -1
  83. data/spec/support/crypt.rb +14 -0
  84. data/spec/support/lite_constraints.rb +3 -1
  85. data/spec/support/spec_config.rb +10 -0
  86. data/spec/support/utils.rb +9 -1
  87. metadata +15 -14
  88. metadata.gz.sig +0 -0
  89. data/lib/mongo/cluster/srv_monitor.rb +0 -127
  90. data/lib/mongo/srv/warning_result.rb +0 -35
  91. data/spec/enterprise_auth/kerberos_spec.rb +0 -58
  92. data/spec/mongo/cluster/srv_monitor_spec.rb +0 -214
  93. data/spec/mongo/operation/read_preference_spec.rb +0 -245
@@ -7,6 +7,95 @@ describe 'CRUD operations' do
7
7
  collection.delete_many
8
8
  end
9
9
 
10
+ describe 'insert' do
11
+ context 'inserting a BSON::Int64' do
12
+ before do
13
+ collection.insert_one(int64: BSON::Int64.new(42))
14
+ end
15
+
16
+ it 'is stored as the correct type' do
17
+ # 18 is the number that represents the Int64 type for the $type
18
+ # operator; string aliases in the $type operator are only supported on
19
+ # server versions 3.2 and newer.
20
+ result = collection.find(int64: { '$type' => 18 }).first
21
+ expect(result).not_to be_nil
22
+ expect(result['int64']).to eq(42)
23
+ end
24
+ end
25
+
26
+ context 'inserting a BSON::Int32' do
27
+ before do
28
+ collection.insert_one(int32: BSON::Int32.new(42))
29
+ end
30
+
31
+ it 'is stored as the correct type' do
32
+ # 16 is the number that represents the Int32 type for the $type
33
+ # operator; string aliases in the $type operator are only supported on
34
+ # server versions 3.2 and newer.
35
+ result = collection.find(int32: { '$type' => 16 }).first
36
+ expect(result).not_to be_nil
37
+ expect(result['int32']).to eq(42)
38
+ end
39
+ end
40
+
41
+ context 'with automatic encryption' do
42
+ require_libmongocrypt
43
+ require_enterprise
44
+ min_server_fcv '4.2'
45
+
46
+ include_context 'define shared FLE helpers'
47
+ include_context 'with local kms_providers'
48
+
49
+ let(:encrypted_collection) do
50
+ new_local_client(
51
+ SpecConfig.instance.addresses,
52
+ SpecConfig.instance.test_options.merge(
53
+ auto_encryption_options: {
54
+ kms_providers: kms_providers,
55
+ key_vault_namespace: key_vault_namespace,
56
+ schema_map: { 'auto_encryption.users' => schema_map },
57
+ # Spawn mongocryptd on non-default port for sharded cluster tests
58
+ extra_options: extra_options,
59
+ },
60
+ database: 'auto_encryption'
61
+ )
62
+ )['users']
63
+ end
64
+
65
+ let(:collection) { authorized_client.use('auto_encryption')['users'] }
66
+
67
+ context 'inserting a BSON::Int64' do
68
+ before do
69
+ encrypted_collection.insert_one(ssn: '123-456-7890', int64: BSON::Int64.new(42))
70
+ end
71
+
72
+ it 'is stored as the correct type' do
73
+ # 18 is the number that represents the Int64 type for the $type
74
+ # operator; string aliases in the $type operator are only supported on
75
+ # server versions 3.2 and newer.
76
+ result = collection.find(int64: { '$type' => 18 }).first
77
+ expect(result).not_to be_nil
78
+ expect(result['int64']).to eq(42)
79
+ end
80
+ end
81
+
82
+ context 'inserting a BSON::Int32' do
83
+ before do
84
+ encrypted_collection.insert_one(ssn: '123-456-7890', int32: BSON::Int32.new(42))
85
+ end
86
+
87
+ it 'is stored as the correct type' do
88
+ # 16 is the number that represents the Int32 type for the $type
89
+ # operator; string aliases in the $type operator are only supported on
90
+ # server versions 3.2 and newer.
91
+ result = collection.find(int32: { '$type' => 16 }).first
92
+ expect(result).not_to be_nil
93
+ expect(result['int32']).to eq(42)
94
+ end
95
+ end
96
+ end
97
+ end
98
+
10
99
  describe 'upsert' do
11
100
  context 'with default write concern' do
12
101
  it 'upserts' do
@@ -482,4 +482,30 @@ describe 'Read preference' do
482
482
  end
483
483
  end
484
484
  end
485
+
486
+ context 'secondary read with direct connection' do
487
+ require_topology :replica_set
488
+
489
+ let(:address_str) do
490
+ Mongo::ServerSelector.get(mode: :secondary).
491
+ select_server(authorized_client.cluster).address.seed
492
+ end
493
+
494
+ let(:secondary_client) do
495
+ new_local_client([address_str],
496
+ SpecConfig.instance.all_test_options.merge(connect: :direct))
497
+ end
498
+
499
+ it 'succeeds without read preference' do
500
+ secondary_client['foo'].find.to_a
501
+ end
502
+
503
+ it 'succeeds with read preference: secondary' do
504
+ secondary_client['foo', {read: {mode: :secondary}}].find.to_a
505
+ end
506
+
507
+ it 'succeeds with read preference: primary' do
508
+ secondary_client['foo', {read: {mode: :primary}}].find.to_a
509
+ end
510
+ end
485
511
  end
@@ -53,7 +53,7 @@ describe 'SRV Monitoring' do
53
53
 
54
54
  expect(client.cluster.topology).to be_a(Mongo::Cluster::Topology::Sharded)
55
55
 
56
- expect(client.cluster.instance_variable_get('@srv_monitor')).to be_a(Mongo::Cluster::SrvMonitor)
56
+ expect(client.cluster.instance_variable_get('@srv_monitor')).to be_a(Mongo::Srv::Monitor)
57
57
 
58
58
  # Close the client in the test rather than allowing our post-test cleanup
59
59
  # to take care of it, since the client references test doubles.
@@ -101,7 +101,7 @@ describe 'SRV Monitoring' do
101
101
 
102
102
  before do
103
103
  # Expedite the polling process
104
- allow_any_instance_of(Mongo::Cluster::SrvMonitor).to receive(:scan_interval).and_return(1)
104
+ allow_any_instance_of(Mongo::Srv::Monitor).to receive(:scan_interval).and_return(1)
105
105
  end
106
106
 
107
107
  context 'sharded cluster' do
@@ -0,0 +1,87 @@
1
+ require 'lite_spec_helper'
2
+
3
+ describe 'kerberos authentication' do
4
+ require_mongo_kerberos
5
+
6
+ before(:all) do
7
+ unless %w(1 yes true).include?(ENV['MONGO_RUBY_DRIVER_KERBEROS_INTEGRATION']&.downcase)
8
+ skip "Set MONGO_RUBY_DRIVER_KERBEROS_INTEGRATION=1 in environment to run the Kerberos integration tests"
9
+ end
10
+ end
11
+
12
+ def require_env_value(key)
13
+ ENV[key].tap do |value|
14
+ if value.nil? || value.empty?
15
+ raise "Value for key #{key} is not present in environment as required"
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:user) do
21
+ "#{require_env_value('SASL_USER')}%40#{require_env_value('SASL_HOST').upcase}"
22
+ end
23
+
24
+ let(:host) do
25
+ "#{require_env_value('SASL_HOST')}"
26
+ end
27
+
28
+ let(:kerberos_db) do
29
+ "#{require_env_value('KERBEROS_DB')}"
30
+ end
31
+
32
+ let(:auth_source) do
33
+ "#{require_env_value('SASL_DB')}"
34
+ end
35
+
36
+ let(:uri) do
37
+ uri = "mongodb://#{user}@#{host}/#{kerberos_db}?authMechanism=GSSAPI&authSource=#{auth_source}"
38
+ end
39
+
40
+ let(:client) do
41
+ Mongo::Client.new(uri, server_selection_timeout: 6.31)
42
+ end
43
+
44
+ let(:doc) do
45
+ client.database[:test].find.first
46
+ end
47
+
48
+ shared_examples_for 'correctly authenticates' do
49
+ it 'correctly authenticates' do
50
+ expect(doc['kerberos']).to eq(true)
51
+ expect(doc['authenticated']).to eq('yeah')
52
+ end
53
+ end
54
+
55
+ it_behaves_like 'correctly authenticates'
56
+
57
+ context 'when host is lowercased' do
58
+ let(:host) do
59
+ "#{require_env_value('SASL_HOST').downcase}"
60
+ end
61
+
62
+ it_behaves_like 'correctly authenticates'
63
+ end
64
+
65
+ context 'when host is uppercased' do
66
+ let(:host) do
67
+ "#{require_env_value('SASL_HOST').upcase}"
68
+ end
69
+
70
+ it_behaves_like 'correctly authenticates'
71
+ end
72
+
73
+ context 'when canonicalize_host_name is true' do
74
+ let(:host) do
75
+ "#{require_env_value('IP_ADDR')}"
76
+ end
77
+
78
+ let(:uri) do
79
+ uri = "mongodb://#{user}@#{host}/#{kerberos_db}?authMechanism=GSSAPI&authSource=#{auth_source}&authMechanismProperties=CANONICALIZE_HOST_NAME:true"
80
+ end
81
+
82
+ it 'correctly authenticates when using the IP' do
83
+ expect(doc['kerberos']).to eq(true)
84
+ expect(doc['authenticated']).to eq('yeah')
85
+ end
86
+ end
87
+ end
@@ -23,16 +23,12 @@ AUTH_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/auth/*.yml").sort
23
23
  CLIENT_SIDE_ENCRYPTION_TESTS = Dir.glob("#{CURRENT_PATH}/spec_tests/data/client_side_encryption/*.yml").sort
24
24
 
25
25
  unless ENV['CI']
26
+ # Load debuggers before loading the driver code, so that breakpoints
27
+ # can be placed in the driver code on file/class level.
26
28
  begin
27
29
  require 'byebug'
28
30
  rescue LoadError
29
- # jruby - try pry
30
- begin
31
- require 'pry'
32
- # jruby likes to raise random error classes, in this case
33
- # NameError in addition to LoadError
34
- rescue Exception
35
- end
31
+ require 'ruby-debug'
36
32
  end
37
33
  end
38
34
 
@@ -40,8 +36,8 @@ require 'mongo'
40
36
  require 'pp'
41
37
 
42
38
  autoload :Benchmark, 'benchmark'
43
- autoload :Timecop, 'timecop'
44
39
  autoload :IceNine, 'ice_nine'
40
+ autoload :Timecop, 'timecop'
45
41
 
46
42
  if BSON::Environment.jruby?
47
43
  require 'concurrent-ruby'
@@ -84,19 +84,23 @@ describe Mongo::BulkWrite::Result do
84
84
 
85
85
  context 'with top level error' do
86
86
  let(:results_document) do
87
- {'writeErrors' => {
88
- 'ok' => 0,
89
- 'errmsg' => 'not master',
90
- 'code' => 10107,
91
- 'codeName' => 'NotMaster',
92
- }}
87
+ {
88
+ 'writeErrors' => [
89
+ {
90
+ 'ok' => 0,
91
+ 'errmsg' => 'not master',
92
+ 'code' => 10107,
93
+ 'codeName' => 'NotMaster',
94
+ }
95
+ ]
96
+ }
93
97
  end
94
98
 
95
99
  it 'raises BulkWriteError' do
96
100
  expect do
97
101
  subject.validate!
98
102
  # BulkWriteErrors don't have any messages on them
99
- end.to raise_error(Mongo::Error::BulkWriteError, nil)
103
+ end.to raise_error(Mongo::Error::BulkWriteError, /not master/)
100
104
  end
101
105
  end
102
106
 
@@ -1,6 +1,4 @@
1
- require 'mongo'
2
- require 'base64'
3
- require 'lite_spec_helper'
1
+ require 'spec_helper'
4
2
 
5
3
  describe Mongo::ClientEncryption do
6
4
  require_libmongocrypt
@@ -8,7 +6,8 @@ describe Mongo::ClientEncryption do
8
6
 
9
7
  let(:client) do
10
8
  ClientRegistry.instance.new_local_client(
11
- [SpecConfig.instance.addresses.first]
9
+ SpecConfig.instance.addresses,
10
+ SpecConfig.instance.test_options
12
11
  )
13
12
  end
14
13
 
@@ -345,9 +344,7 @@ describe Mongo::ClientEncryption do
345
344
  let(:encrypted_value) { encrypted_ssn }
346
345
 
347
346
  before do
348
- key_vault_collection = client.use(key_vault_db)[key_vault_coll]
349
347
  key_vault_collection.drop
350
-
351
348
  key_vault_collection.insert_one(data_key)
352
349
  end
353
350
 
@@ -9,7 +9,13 @@ describe Mongo::Crypt::AutoEncrypter do
9
9
  include_context 'define shared FLE helpers'
10
10
 
11
11
  let(:auto_encrypter) do
12
- described_class.new(auto_encryption_options.merge(client: authorized_client.use(:auto_encryption)))
12
+ described_class.new(
13
+ auto_encryption_options.merge(
14
+ client: authorized_client.use(:auto_encryption),
15
+ # Spawn mongocryptd on non-default port for sharded cluster tests
16
+ extra_options: extra_options
17
+ )
18
+ )
13
19
  end
14
20
 
15
21
  let(:client) { authorized_client }
@@ -81,7 +87,6 @@ describe Mongo::Crypt::AutoEncrypter do
81
87
  end
82
88
 
83
89
  before do
84
- key_vault_collection = client.use(key_vault_db)[key_vault_coll]
85
90
  key_vault_collection.drop
86
91
  key_vault_collection.insert_one(data_key)
87
92
  end
@@ -97,7 +102,7 @@ describe Mongo::Crypt::AutoEncrypter do
97
102
  {
98
103
  kms_providers: kms_providers,
99
104
  key_vault_namespace: key_vault_namespace,
100
- schema_map: { "#{db_name}.#{collection_name}": schema_map }
105
+ schema_map: { "#{db_name}.#{collection_name}": schema_map },
101
106
  }
102
107
  end
103
108
 
@@ -134,7 +134,7 @@ describe Mongo::Crypt::Handle do
134
134
  it 'raises an exception' do
135
135
  expect do
136
136
  handle
137
- end.to raise_error(ArgumentError, /The specified aws kms_providers option is invalid/)
137
+ end.to raise_error(ArgumentError, /The aws access_key_id option must be a String with at least one character; currently have nil/)
138
138
  end
139
139
  end
140
140
 
@@ -151,7 +151,24 @@ describe Mongo::Crypt::Handle do
151
151
  it 'raises an exception' do
152
152
  expect do
153
153
  handle
154
- end.to raise_error(ArgumentError, /The specified aws kms_providers option is invalid/)
154
+ end.to raise_error(ArgumentError, /The aws access_key_id option must be a String with at least one character; currently have 5/)
155
+ end
156
+ end
157
+
158
+ context 'with empty string AWS access_key_id' do
159
+ let(:kms_providers) {
160
+ {
161
+ aws: {
162
+ access_key_id: '',
163
+ secret_access_key: SpecConfig.instance.fle_aws_secret
164
+ }
165
+ }
166
+ }
167
+
168
+ it 'raises an exception' do
169
+ expect do
170
+ handle
171
+ end.to raise_error(ArgumentError, /The aws access_key_id option must be a String with at least one character; it is currently an empty string/)
155
172
  end
156
173
  end
157
174
 
@@ -169,7 +186,7 @@ describe Mongo::Crypt::Handle do
169
186
  it 'raises an exception' do
170
187
  expect do
171
188
  handle
172
- end.to raise_error(ArgumentError, /The specified aws kms_providers option is invalid/)
189
+ end.to raise_error(ArgumentError, /The aws secret_access_key option must be a String with at least one character; currently have nil/)
173
190
  end
174
191
  end
175
192
 
@@ -186,7 +203,24 @@ describe Mongo::Crypt::Handle do
186
203
  it 'raises an exception' do
187
204
  expect do
188
205
  handle
189
- end.to raise_error(ArgumentError, /The specified aws kms_providers option is invalid/)
206
+ end.to raise_error(ArgumentError, /The aws secret_access_key option must be a String with at least one character; currently have 5/)
207
+ end
208
+ end
209
+
210
+ context 'with empty string AWS secret_access_key' do
211
+ let(:kms_providers) {
212
+ {
213
+ aws: {
214
+ access_key_id: SpecConfig.instance.fle_aws_key,
215
+ secret_access_key: ''
216
+ }
217
+ }
218
+ }
219
+
220
+ it 'raises an exception' do
221
+ expect do
222
+ handle
223
+ end.to raise_error(ArgumentError, /The aws secret_access_key option must be a String with at least one character; it is currently an empty string/)
190
224
  end
191
225
  end
192
226
 
@@ -0,0 +1,49 @@
1
+ require 'lite_spec_helper'
2
+
3
+ describe Mongo::Error::BulkWriteError do
4
+ let(:result) do
5
+ {
6
+ 'writeErrors' => [
7
+ { 'code' => 1, 'errmsg' => 'message1' },
8
+ { 'code' => 2, 'errmsg' => 'message2' },
9
+ ]
10
+ }
11
+ end
12
+
13
+ let(:error) { described_class.new(result) }
14
+
15
+ before do
16
+ error.add_note('note1')
17
+ error.add_note('note2')
18
+ end
19
+
20
+ describe '#result' do
21
+ it 'returns the result' do
22
+ expect(error.result).to eq(result)
23
+ end
24
+ end
25
+
26
+ describe '#labels' do
27
+ it 'returns an empty array' do
28
+ expect(error.labels).to eq([])
29
+ end
30
+ end
31
+
32
+ describe '#message' do
33
+ it 'is correct' do
34
+ expect(error.message).to eq("message1 (1), message2 (2) (note1, note2)")
35
+ end
36
+ end
37
+
38
+ describe '#to_s' do
39
+ it 'is correct' do
40
+ expect(error.to_s).to eq("message1 (1), message2 (2) (note1, note2)")
41
+ end
42
+ end
43
+
44
+ describe '#inspect' do
45
+ it 'is correct' do
46
+ expect(error.inspect).to eq("#<Mongo::Error::BulkWriteError: message1 (1), message2 (2) (note1, note2)>")
47
+ end
48
+ end
49
+ end