mongo 2.11.1 → 2.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -1
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +24 -0
  5. data/lib/mongo/auth.rb +30 -10
  6. data/lib/mongo/auth/cr.rb +1 -0
  7. data/lib/mongo/auth/cr/conversation.rb +13 -13
  8. data/lib/mongo/auth/ldap.rb +2 -1
  9. data/lib/mongo/auth/ldap/conversation.rb +9 -12
  10. data/lib/mongo/auth/scram.rb +1 -0
  11. data/lib/mongo/auth/scram/conversation.rb +36 -27
  12. data/lib/mongo/auth/x509.rb +2 -1
  13. data/lib/mongo/auth/x509/conversation.rb +9 -9
  14. data/lib/mongo/client.rb +17 -6
  15. data/lib/mongo/cluster.rb +65 -49
  16. data/lib/mongo/cluster/sdam_flow.rb +87 -3
  17. data/lib/mongo/database.rb +1 -1
  18. data/lib/mongo/server.rb +13 -6
  19. data/lib/mongo/server/connection.rb +12 -4
  20. data/lib/mongo/server/connection_base.rb +7 -4
  21. data/lib/mongo/server/description.rb +34 -21
  22. data/lib/mongo/session.rb +10 -10
  23. data/lib/mongo/version.rb +1 -1
  24. data/spec/README.md +13 -0
  25. data/spec/integration/auth_spec.rb +27 -8
  26. data/spec/integration/client_construction_spec.rb +14 -0
  27. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  28. data/spec/mongo/auth/scram/conversation_spec.rb +23 -14
  29. data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
  30. data/spec/mongo/client_construction_spec.rb +1 -21
  31. data/spec/mongo/cluster_spec.rb +38 -0
  32. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  33. data/spec/mongo/server/connection_spec.rb +67 -0
  34. data/spec/runners/sdam/verifier.rb +6 -3
  35. data/spec/spec_tests/data/sdam/rs/primary_address_change.yml +29 -0
  36. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +27 -23
  37. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +56 -79
  38. data/spec/spec_tests/data/sdam/sharded/primary_address_change.yml +21 -0
  39. data/spec/spec_tests/data/sdam/sharded/primary_mismatched_me.yml +22 -0
  40. data/spec/spec_tests/data/sdam/single/primary_address_change.yml +24 -0
  41. data/spec/spec_tests/data/sdam/single/primary_mismatched_me.yml +25 -0
  42. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +159 -0
  43. data/spec/spec_tests/data/sdam_monitoring/{replica_set_other_seed.yml → replica_set_with_primary_change.yml} +97 -101
  44. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary_removal.yml +22 -18
  45. data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +90 -0
  46. data/spec/support/cluster_config.rb +36 -0
  47. data/spec/support/constraints.rb +18 -18
  48. data/spec/support/server_discovery_and_monitoring.rb +2 -0
  49. metadata +18 -4
  50. metadata.gz.sig +0 -0
@@ -33,6 +33,7 @@ module Mongo
33
33
  # Constant for reading arbiter info from config.
34
34
  #
35
35
  # @since 2.0.0
36
+ # @deprecated
36
37
  ARBITER = 'arbiterOnly'.freeze
37
38
 
38
39
  # Constant for reading arbiters info from config.
@@ -53,16 +54,19 @@ module Mongo
53
54
  # Constant for the key for the message value.
54
55
  #
55
56
  # @since 2.0.0
57
+ # @deprecated
56
58
  MESSAGE = 'msg'.freeze
57
59
 
58
60
  # Constant for the message that indicates a sharded cluster.
59
61
  #
60
62
  # @since 2.0.0
63
+ # @deprecated
61
64
  MONGOS_MESSAGE = 'isdbgrid'.freeze
62
65
 
63
66
  # Constant for determining ghost servers.
64
67
  #
65
68
  # @since 2.0.0
69
+ # @deprecated
66
70
  REPLICA_SET = 'isreplicaset'.freeze
67
71
 
68
72
  # Constant for reading max bson size info from config.
@@ -129,6 +133,7 @@ module Mongo
129
133
  # Constant for reading primary info from config.
130
134
  #
131
135
  # @since 2.0.0
136
+ # @deprecated
132
137
  PRIMARY = 'ismaster'.freeze
133
138
 
134
139
  # Constant for reading primary host field from config.
@@ -139,6 +144,7 @@ module Mongo
139
144
  # Constant for reading secondary info from config.
140
145
  #
141
146
  # @since 2.0.0
147
+ # @deprecated
142
148
  SECONDARY = 'secondary'.freeze
143
149
 
144
150
  # Constant for reading replica set name info from config.
@@ -227,7 +233,7 @@ module Mongo
227
233
  # @return [ Float ] The moving average time the ismaster call took to complete.
228
234
  attr_reader :average_round_trip_time
229
235
 
230
- # Will return true if the server is an arbiter.
236
+ # Returns whether this server is an arbiter, per the SDAM spec.
231
237
  #
232
238
  # @example Is the server an arbiter?
233
239
  # description.arbiter?
@@ -236,7 +242,9 @@ module Mongo
236
242
  #
237
243
  # @since 2.0.0
238
244
  def arbiter?
239
- ok? && !!config[ARBITER] && !replica_set_name.nil?
245
+ ok? &&
246
+ config['arbiterOnly'] == true &&
247
+ !!config['setName']
240
248
  end
241
249
 
242
250
  # Get a list of all arbiters in the replica set.
@@ -251,7 +259,7 @@ module Mongo
251
259
  @arbiters ||= (config[ARBITERS] || []).map { |s| s.downcase }
252
260
  end
253
261
 
254
- # Is the server a ghost in a replica set?
262
+ # Whether this server is a ghost, per the SDAM spec.
255
263
  #
256
264
  # @example Is the server a ghost?
257
265
  # description.ghost?
@@ -260,7 +268,8 @@ module Mongo
260
268
  #
261
269
  # @since 2.0.0
262
270
  def ghost?
263
- ok? && !!config[REPLICA_SET]
271
+ ok? &&
272
+ config['isreplicaset'] == true
264
273
  end
265
274
 
266
275
  # Will return true if the server is hidden.
@@ -431,7 +440,7 @@ module Mongo
431
440
  config[LOGICAL_SESSION_TIMEOUT_MINUTES] if config[LOGICAL_SESSION_TIMEOUT_MINUTES]
432
441
  end
433
442
 
434
- # Is the server a mongos?
443
+ # Returns whether this server is a mongos, per the SDAM spec.
435
444
  #
436
445
  # @example Is the server a mongos?
437
446
  # description.mongos?
@@ -440,10 +449,10 @@ module Mongo
440
449
  #
441
450
  # @since 2.0.0
442
451
  def mongos?
443
- ok? && config[MESSAGE] == MONGOS_MESSAGE
452
+ ok? && config['msg'] == 'isdbgrid'
444
453
  end
445
454
 
446
- # Is the description of type other.
455
+ # Returns whether the server is an other, per the SDAM spec.
447
456
  #
448
457
  # @example Is the description of type other.
449
458
  # description.other?
@@ -455,11 +464,11 @@ module Mongo
455
464
  # The SDAM spec is slightly confusing on what "other" means,
456
465
  # but it's referred to it as "RSOther" which means a non-RS member
457
466
  # cannot be "other".
458
- if unknown? || replica_set_name.nil?
459
- return false
460
- end
461
- (!primary? && !secondary? && !passive? && !arbiter?) ||
462
- (hidden? && !replica_set_name.nil?)
467
+ ok? &&
468
+ !!config['setName'] && (
469
+ config['hidden'] == true ||
470
+ !primary? && !secondary? && !arbiter?
471
+ )
463
472
  end
464
473
 
465
474
  # Will return true if the server is passive.
@@ -498,7 +507,7 @@ module Mongo
498
507
  config[PRIMARY_HOST] && config[PRIMARY_HOST].downcase
499
508
  end
500
509
 
501
- # Will return true if the server is a primary.
510
+ # Returns whether this server is a primary, per the SDAM spec.
502
511
  #
503
512
  # @example Is the server a primary?
504
513
  # description.primary?
@@ -508,9 +517,8 @@ module Mongo
508
517
  # @since 2.0.0
509
518
  def primary?
510
519
  ok? &&
511
- !!config[PRIMARY] &&
512
- (primary_host.nil? || primary_host == address.to_s) &&
513
- !replica_set_name.nil?
520
+ config['ismaster'] == true &&
521
+ !!config['setName']
514
522
  end
515
523
 
516
524
  # Get the name of the replica set the server belongs to, returns nil if
@@ -538,7 +546,7 @@ module Mongo
538
546
  hosts + arbiters + passives
539
547
  end
540
548
 
541
- # Will return true if the server is a secondary.
549
+ # Returns whether this server is a secondary, per the SDAM spec.
542
550
  #
543
551
  # @example Is the server a secondary?
544
552
  # description.secondary?
@@ -547,7 +555,9 @@ module Mongo
547
555
  #
548
556
  # @since 2.0.0
549
557
  def secondary?
550
- ok? && !!config[SECONDARY] && !replica_set_name.nil?
558
+ ok? &&
559
+ config['secondary'] == true &&
560
+ !!config['setName']
551
561
  end
552
562
 
553
563
  # Returns the server type as a symbol.
@@ -569,7 +579,7 @@ module Mongo
569
579
  :unknown
570
580
  end
571
581
 
572
- # Is this server a standalone server?
582
+ # Returns whether this server is a standalone, per the SDAM spec.
573
583
  #
574
584
  # @example Is the server standalone?
575
585
  # description.standalone?
@@ -578,10 +588,13 @@ module Mongo
578
588
  #
579
589
  # @since 2.0.0
580
590
  def standalone?
581
- replica_set_name.nil? && !mongos? && !ghost? && !unknown?
591
+ ok? &&
592
+ config['msg'] != 'isdbgrid' &&
593
+ config['setName'].nil? &&
594
+ config['isreplicaset'] != true
582
595
  end
583
596
 
584
- # Is the server description currently unknown?
597
+ # Returns whether this server is an unknown, per the SDAM spec.
585
598
  #
586
599
  # @example Is the server description unknown?
587
600
  # description.unknown?
@@ -881,21 +881,21 @@ module Mongo
881
881
  end
882
882
  end
883
883
 
884
- # Validate the session.
884
+ # Validate the session for use by the specified client.
885
885
  #
886
- # @example
887
- # session.validate!(cluster)
886
+ # The session must not be ended and must have been created by a client
887
+ # with the same cluster as the client that the session is to be used with.
888
888
  #
889
- # @param [ Cluster ] cluster The cluster the session is attempted to be used with.
889
+ # @param [ Client ] client The client the session is to be used with.
890
890
  #
891
- # @return [ nil ] nil if the session is valid.
891
+ # @return [ Session ] self, if the session is valid.
892
892
  #
893
- # @raise [ Mongo::Error::InvalidSession ] Raise error if the session is not valid.
893
+ # @raise [ Mongo::Error::InvalidSession ] Exception raised if the session is not valid.
894
894
  #
895
895
  # @since 2.5.0
896
896
  # @api private
897
- def validate!(cluster)
898
- check_matching_cluster!(cluster)
897
+ def validate!(client)
898
+ check_matching_cluster!(client)
899
899
  check_if_ended!
900
900
  self
901
901
  end
@@ -1041,8 +1041,8 @@ module Mongo
1041
1041
  raise Mongo::Error::InvalidSession.new(SESSION_ENDED_ERROR_MSG) if ended?
1042
1042
  end
1043
1043
 
1044
- def check_matching_cluster!(cluster)
1045
- if @client.cluster != cluster
1044
+ def check_matching_cluster!(client)
1045
+ if @client.cluster != client.cluster
1046
1046
  raise Mongo::Error::InvalidSession.new(MISMATCHED_CLUSTER_ERROR_MSG)
1047
1047
  end
1048
1048
  end
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.11.1'.freeze
20
+ VERSION = '2.11.2'.freeze
21
21
  end
@@ -74,6 +74,19 @@ configuration is needed:
74
74
 
75
75
  rake
76
76
 
77
+ ### Replica Set With Arbiter
78
+
79
+ Some tests require an arbiter to be present in the replica set. Such a
80
+ deployment can be obtained by providing `--arbiter` argument to mlaunch:
81
+
82
+ mlaunch init --replicaset --arbiter --name ruby-driver-rs \
83
+ --dir /tmp/mdb-rs --setParameter enableTestCommands=1
84
+
85
+ To indicate to the test suite that the deployment contains an arbiter, set
86
+ HAVE_ARBITER environment variable as follows:
87
+
88
+ HAVE_ARBITER=1 rake
89
+
77
90
  ### Sharded Cluster
78
91
 
79
92
  A sharded cluster can be configured with mlaunch:
@@ -41,7 +41,7 @@ describe 'Auth' do
41
41
  it 'indicates scram-sha-1 was used' do
42
42
  expect do
43
43
  connection.connect!
44
- end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram\) is not authorized to access admin.*\(used mechanism: SCRAM-SHA-1\)/)
44
+ end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram\) is not authorized to access admin.*used mechanism: SCRAM-SHA-1/)
45
45
  end
46
46
  end
47
47
 
@@ -53,7 +53,7 @@ describe 'Auth' do
53
53
  it 'indicates scram-sha-1 was used' do
54
54
  expect do
55
55
  connection.connect!
56
- end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram\) is not authorized to access admin.*\(used mechanism: SCRAM-SHA-1\)/)
56
+ end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram\) is not authorized to access admin.*used mechanism: SCRAM-SHA-1/)
57
57
  end
58
58
  end
59
59
  end
@@ -73,7 +73,7 @@ describe 'Auth' do
73
73
  it 'indicates scram-sha-1 was used' do
74
74
  expect do
75
75
  connection.connect!
76
- end.to raise_error(Mongo::Auth::Unauthorized, /User existing_user \(mechanism: scram\) is not authorized to access admin.*\(used mechanism: SCRAM-SHA-1\)/)
76
+ end.to raise_error(Mongo::Auth::Unauthorized, /User existing_user \(mechanism: scram\) is not authorized to access admin.*used mechanism: SCRAM-SHA-1/)
77
77
  end
78
78
  end
79
79
 
@@ -85,7 +85,7 @@ describe 'Auth' do
85
85
  it 'indicates scram-sha-256 was used' do
86
86
  expect do
87
87
  connection.connect!
88
- end.to raise_error(Mongo::Auth::Unauthorized, /User existing_user \(mechanism: scram256\) is not authorized to access admin.*\(used mechanism: SCRAM-SHA-256\)/)
88
+ end.to raise_error(Mongo::Auth::Unauthorized, /User existing_user \(mechanism: scram256\) is not authorized to access admin.*used mechanism: SCRAM-SHA-256/)
89
89
  end
90
90
  end
91
91
  end
@@ -101,7 +101,7 @@ describe 'Auth' do
101
101
  it 'indicates scram-sha-1 was requested and used' do
102
102
  expect do
103
103
  connection.connect!
104
- end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram\) is not authorized to access admin.*\(used mechanism: SCRAM-SHA-1\)/)
104
+ end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram\) is not authorized to access admin.*used mechanism: SCRAM-SHA-1/)
105
105
  end
106
106
  end
107
107
 
@@ -114,7 +114,7 @@ describe 'Auth' do
114
114
  it 'indicates scram-sha-256 was requested and used' do
115
115
  expect do
116
116
  connection.connect!
117
- end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram256\) is not authorized to access admin.*\(used mechanism: SCRAM-SHA-256\)/)
117
+ end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user \(mechanism: scram256\) is not authorized to access admin.*used mechanism: SCRAM-SHA-256/)
118
118
  end
119
119
  end
120
120
  end
@@ -123,10 +123,29 @@ describe 'Auth' do
123
123
  let(:options) { SpecConfig.instance.ssl_options.merge(
124
124
  user: 'nonexistent_user', password: 'foo') }
125
125
 
126
- it 'reports auth source used' do
126
+ it 'reports which server authentication was attempted against' do
127
127
  expect do
128
128
  connection.connect!
129
- end.to raise_error(Mongo::Auth::Unauthorized, /User nonexistent_user.*is not authorized to access admin \(auth source: admin\)/)
129
+ end.to raise_error(Mongo::Auth::Unauthorized, /used server: #{connection.address.to_s}/)
130
+ end
131
+
132
+ context 'with default auth source' do
133
+ it 'reports auth source used' do
134
+ expect do
135
+ connection.connect!
136
+ end.to raise_error(Mongo::Auth::Unauthorized, /auth source: admin/)
137
+ end
138
+ end
139
+
140
+ context 'with custom auth source' do
141
+ let(:options) { SpecConfig.instance.ssl_options.merge(
142
+ user: 'nonexistent_user', password: 'foo', auth_source: 'authdb') }
143
+
144
+ it 'reports auth source used' do
145
+ expect do
146
+ connection.connect!
147
+ end.to raise_error(Mongo::Auth::Unauthorized, /auth source: authdb/)
148
+ end
130
149
  end
131
150
  end
132
151
 
@@ -82,6 +82,20 @@ describe 'Client construction' do
82
82
  expect(client.cluster.topology).to be_a(Mongo::Cluster::Topology::Single)
83
83
  expect(client.options[:connect]).to eq :direct
84
84
  end
85
+
86
+ context 'direct connection with mismached me' do
87
+ let(:address) { ClusterConfig.instance.alternate_address.to_s }
88
+
89
+ let(:client) do
90
+ new_local_client([address], SpecConfig.instance.test_options)
91
+ end
92
+
93
+ let(:server) { client.cluster.next_primary }
94
+
95
+ it 'sets server type to primary' do
96
+ expect(server.description).to be_primary
97
+ end
98
+ end
85
99
  end
86
100
 
87
101
  context 'in sharded topology' do
@@ -17,7 +17,7 @@ describe Mongo::Auth::LDAP::Conversation do
17
17
  describe '#start' do
18
18
 
19
19
  let(:query) do
20
- conversation.start
20
+ conversation.start(nil)
21
21
  end
22
22
 
23
23
  let(:selector) do
@@ -7,6 +7,15 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
7
7
  described_class.new(user, mechanism)
8
8
  end
9
9
 
10
+ let(:connection) do
11
+ double('connection').tap do |connection|
12
+ features = double('features')
13
+ allow(features).to receive(:op_msg_enabled?)
14
+ allow(connection).to receive(:features).and_return(features)
15
+ allow(connection).to receive(:server)
16
+ end
17
+ end
18
+
10
19
  context 'when SCRAM-SHA-1 is used' do
11
20
  min_server_fcv '3.0'
12
21
 
@@ -28,7 +37,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
28
37
  describe '#start' do
29
38
 
30
39
  let(:query) do
31
- conversation.start
40
+ conversation.start(nil)
32
41
  end
33
42
 
34
43
  before do
@@ -85,7 +94,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
85
94
  end
86
95
 
87
96
  let(:query) do
88
- conversation.continue(reply)
97
+ conversation.continue(reply, connection)
89
98
  end
90
99
 
91
100
  let(:selector) do
@@ -117,7 +126,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
117
126
 
118
127
  it 'raises an error' do
119
128
  expect {
120
- conversation.continue(reply)
129
+ conversation.continue(reply, connection)
121
130
  }.to raise_error(Mongo::Error::InvalidNonce)
122
131
  end
123
132
  end
@@ -170,8 +179,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
170
179
  end
171
180
 
172
181
  let(:query) do
173
- conversation.continue(continue_reply)
174
- conversation.finalize(reply)
182
+ conversation.continue(continue_reply, connection)
183
+ conversation.finalize(reply, connection)
175
184
  end
176
185
 
177
186
  let(:selector) do
@@ -199,8 +208,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
199
208
 
200
209
  it 'raises an error' do
201
210
  expect {
202
- conversation.continue(continue_reply)
203
- conversation.finalize(reply)
211
+ conversation.continue(continue_reply, connection)
212
+ conversation.finalize(reply, connection)
204
213
  }.to raise_error(Mongo::Error::InvalidSignature)
205
214
  end
206
215
  end
@@ -226,7 +235,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
226
235
  describe '#start' do
227
236
 
228
237
  let(:query) do
229
- conversation.start
238
+ conversation.start(nil)
230
239
  end
231
240
 
232
241
  before do
@@ -283,7 +292,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
283
292
  end
284
293
 
285
294
  let(:query) do
286
- conversation.continue(reply)
295
+ conversation.continue(reply, connection)
287
296
  end
288
297
 
289
298
  let(:selector) do
@@ -315,7 +324,7 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
315
324
 
316
325
  it 'raises an error' do
317
326
  expect {
318
- conversation.continue(reply)
327
+ conversation.continue(reply, connection)
319
328
  }.to raise_error(Mongo::Error::InvalidNonce)
320
329
  end
321
330
  end
@@ -368,8 +377,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
368
377
  end
369
378
 
370
379
  let(:query) do
371
- conversation.continue(continue_reply)
372
- conversation.finalize(reply)
380
+ conversation.continue(continue_reply, connection)
381
+ conversation.finalize(reply, connection)
373
382
  end
374
383
 
375
384
  let(:selector) do
@@ -397,8 +406,8 @@ describe Mongo::Auth::SCRAM::Conversation, retry: 3 do
397
406
 
398
407
  it 'raises an error' do
399
408
  expect {
400
- conversation.continue(continue_reply)
401
- conversation.finalize(reply)
409
+ conversation.continue(continue_reply, connection)
410
+ conversation.finalize(reply, connection)
402
411
  }.to raise_error(Mongo::Error::InvalidSignature)
403
412
  end
404
413
  end