mongo 2.0.2 → 2.0.3

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo/address.rb +70 -11
  5. data/lib/mongo/address/ipv4.rb +23 -22
  6. data/lib/mongo/address/ipv6.rb +23 -22
  7. data/lib/mongo/address/unix.rb +18 -18
  8. data/lib/mongo/auth.rb +0 -1
  9. data/lib/mongo/auth/cr.rb +21 -2
  10. data/lib/mongo/auth/cr/conversation.rb +7 -4
  11. data/lib/mongo/auth/ldap.rb +14 -1
  12. data/lib/mongo/auth/scram.rb +15 -1
  13. data/lib/mongo/auth/scram/conversation.rb +3 -3
  14. data/lib/mongo/auth/user.rb +1 -1
  15. data/lib/mongo/auth/x509.rb +15 -1
  16. data/lib/mongo/cluster.rb +22 -8
  17. data/lib/mongo/cluster/topology.rb +7 -6
  18. data/lib/mongo/cluster/topology/replica_set.rb +5 -5
  19. data/lib/mongo/cluster/topology/sharded.rb +5 -5
  20. data/lib/mongo/cluster/topology/{standalone.rb → single.rb} +26 -22
  21. data/lib/mongo/cluster/topology/unknown.rb +6 -5
  22. data/lib/mongo/collection.rb +6 -1
  23. data/lib/mongo/collection/view.rb +1 -0
  24. data/lib/mongo/collection/view/readable.rb +5 -0
  25. data/lib/mongo/error.rb +4 -0
  26. data/lib/mongo/error/invalid_document.rb +1 -1
  27. data/lib/mongo/error/invalid_server_preference.rb +36 -0
  28. data/lib/mongo/error/invalid_uri.rb +37 -0
  29. data/lib/mongo/error/invalid_uri_option.rb +38 -0
  30. data/lib/mongo/error/no_server_available.rb +37 -0
  31. data/lib/mongo/operation/read_preferrable.rb +20 -4
  32. data/lib/mongo/protocol/query.rb +14 -1
  33. data/lib/mongo/server.rb +12 -0
  34. data/lib/mongo/server/connectable.rb +5 -1
  35. data/lib/mongo/server/connection.rb +1 -1
  36. data/lib/mongo/server/context.rb +2 -1
  37. data/lib/mongo/server_selector.rb +0 -19
  38. data/lib/mongo/server_selector/selectable.rb +4 -22
  39. data/lib/mongo/uri.rb +9 -55
  40. data/lib/mongo/version.rb +1 -1
  41. data/spec/mongo/address/ipv4_spec.rb +27 -6
  42. data/spec/mongo/address/ipv6_spec.rb +27 -6
  43. data/spec/mongo/address/unix_spec.rb +15 -4
  44. data/spec/mongo/auth/cr_spec.rb +2 -2
  45. data/spec/mongo/auth/ldap_spec.rb +2 -2
  46. data/spec/mongo/auth/scram_spec.rb +2 -2
  47. data/spec/mongo/auth/x509_spec.rb +2 -2
  48. data/spec/mongo/client_spec.rb +8 -0
  49. data/spec/mongo/cluster/topology/replica_set_spec.rb +6 -6
  50. data/spec/mongo/cluster/topology/sharded_spec.rb +5 -5
  51. data/spec/mongo/cluster/topology/{standalone_spec.rb → single_spec.rb} +7 -7
  52. data/spec/mongo/cluster/topology_spec.rb +31 -5
  53. data/spec/mongo/cluster_spec.rb +103 -21
  54. data/spec/mongo/collection/view/readable_spec.rb +18 -7
  55. data/spec/mongo/collection/view_spec.rb +13 -0
  56. data/spec/mongo/collection_spec.rb +7 -0
  57. data/spec/mongo/database_spec.rb +2 -2
  58. data/spec/mongo/protocol/query_spec.rb +29 -0
  59. data/spec/mongo/server/connection_pool_spec.rb +4 -4
  60. data/spec/mongo/server/connection_spec.rb +46 -10
  61. data/spec/mongo/server/monitor_spec.rb +2 -2
  62. data/spec/mongo/server_discovery_and_monitoring_spec.rb +23 -0
  63. data/spec/mongo/server_selection_rtt_spec.rb +2 -1
  64. data/spec/mongo/server_selection_spec.rb +6 -15
  65. data/spec/mongo/server_selector/nearest_spec.rb +1 -1
  66. data/spec/mongo/server_selector_spec.rb +53 -2
  67. data/spec/mongo/server_spec.rb +9 -9
  68. data/spec/mongo/socket/ssl_spec.rb +1 -1
  69. data/spec/mongo/uri_spec.rb +2 -2
  70. data/spec/spec_helper.rb +34 -5
  71. data/spec/support/authorization.rb +32 -46
  72. data/spec/support/server_discovery_and_monitoring.rb +1 -1
  73. data/spec/support/server_selection.rb +1 -25
  74. data/spec/support/shared/operation.rb +3 -0
  75. data/spec/support/shared/server_selector.rb +1 -1
  76. metadata +10 -7
  77. metadata.gz.sig +0 -0
  78. data/lib/mongo/auth/executable.rb +0 -52
@@ -111,7 +111,7 @@ module Mongo
111
111
  def continue(reply)
112
112
  validate_first_message!(reply)
113
113
  Protocol::Query.new(
114
- Database::ADMIN,
114
+ user.auth_source,
115
115
  Database::COMMAND,
116
116
  CLIENT_CONTINUE_MESSAGE.merge(payload: client_final_message, conversationId: id),
117
117
  limit: -1
@@ -133,7 +133,7 @@ module Mongo
133
133
  def finalize(reply)
134
134
  validate_final_message!(reply)
135
135
  Protocol::Query.new(
136
- Database::ADMIN,
136
+ user.auth_source,
137
137
  Database::COMMAND,
138
138
  CLIENT_CONTINUE_MESSAGE.merge(payload: client_empty_message, conversationId: id),
139
139
  limit: -1
@@ -151,7 +151,7 @@ module Mongo
151
151
  # @since 2.0.0
152
152
  def start
153
153
  Protocol::Query.new(
154
- Database::ADMIN,
154
+ user.auth_source,
155
155
  Database::COMMAND,
156
156
  CLIENT_FIRST_MESSAGE.merge(payload: client_first_message, mechanism: SCRAM::MECHANISM),
157
157
  limit: -1
@@ -134,8 +134,8 @@ module Mongo
134
134
  #
135
135
  # @since 2.0.0
136
136
  def initialize(options)
137
- @auth_source = options[:auth_source] || options[:database] || Database::ADMIN
138
137
  @database = options[:database] || Database::ADMIN
138
+ @auth_source = options[:auth_source] || @database
139
139
  @name = options[:user]
140
140
  @password = options[:password] || options[:pwd]
141
141
  @mechanism = options[:auth_mech] || :mongodb_cr
@@ -21,13 +21,27 @@ module Mongo
21
21
  #
22
22
  # @since 2.0.0
23
23
  class X509
24
- include Executable
25
24
 
26
25
  # The authentication mechinism string.
27
26
  #
28
27
  # @since 2.0.0
29
28
  MECHANISM = 'MONGODB-X509'.freeze
30
29
 
30
+ # @return [ Mongo::Auth::User ] The user to authenticate.
31
+ attr_reader :user
32
+
33
+ # Instantiate a new authenticator.
34
+ #
35
+ # @example Create the authenticator.
36
+ # Mongo::Auth::X509.new(user)
37
+ #
38
+ # @param [ Mongo::Auth::User ] user The user to authenticate.
39
+ #
40
+ # @since 2.0.0
41
+ def initialize(user)
42
+ @user = user
43
+ end
44
+
31
45
  # Log the user in on the given connection.
32
46
  #
33
47
  # @example Log the user in.
data/lib/mongo/cluster.rb CHANGED
@@ -34,7 +34,7 @@ module Mongo
34
34
  # @return [ Object ] The cluster topology.
35
35
  attr_reader :topology
36
36
 
37
- def_delegators :topology, :replica_set?, :replica_set_name, :sharded?, :standalone?, :unknown?
37
+ def_delegators :topology, :replica_set?, :replica_set_name, :sharded?, :single?, :unknown?
38
38
 
39
39
  # Determine if this cluster of servers is equal to another object. Checks the
40
40
  # servers currently in the cluster, not what was configured.
@@ -66,12 +66,15 @@ module Mongo
66
66
  # @since 2.0.0
67
67
  def add(host)
68
68
  address = Address.new(host)
69
- unless addresses.include?(address)
70
- log_debug([ "Adding #{address.to_s} to the cluster." ])
71
- addresses.push(address)
72
- server = Server.new(address, event_listeners, options)
73
- @servers.push(server)
74
- server
69
+ if !addresses.include?(address)
70
+ if addition_allowed?(address)
71
+ log_debug([ "Adding #{address.to_s} to the cluster." ])
72
+ addresses.push(address)
73
+ server = Server.new(address, event_listeners,
74
+ options.merge(slave_ok: @slave_ok))
75
+ @servers.push(server)
76
+ server
77
+ end
75
78
  end
76
79
  end
77
80
 
@@ -90,6 +93,7 @@ module Mongo
90
93
  @event_listeners = Event::Listeners.new
91
94
  @options = options.freeze
92
95
  @topology = Topology.initial(seeds, options)
96
+ @slave_ok = @topology.single? unless options[:read]
93
97
 
94
98
  subscribe_to(Event::SERVER_ADDED, Event::ServerAdded.new(self))
95
99
  subscribe_to(Event::SERVER_REMOVED, Event::ServerRemoved.new(self))
@@ -179,7 +183,7 @@ module Mongo
179
183
  #
180
184
  # @since 2.0.0
181
185
  def servers
182
- topology.servers(@servers)
186
+ topology.servers(@servers.compact).compact
183
187
  end
184
188
 
185
189
  # Create a cluster for the provided client, for use when we don't want the
@@ -199,5 +203,15 @@ module Mongo
199
203
  cluster = Cluster.new(client.cluster.addresses.map(&:to_s), client.options)
200
204
  client.instance_variable_set(:@cluster, cluster)
201
205
  end
206
+
207
+ private
208
+
209
+ def direct_connection?(address)
210
+ address.seed == @topology.seed
211
+ end
212
+
213
+ def addition_allowed?(address)
214
+ !@topology.single? || direct_connection?(address)
215
+ end
202
216
  end
203
217
  end
@@ -14,7 +14,7 @@
14
14
 
15
15
  require 'mongo/cluster/topology/replica_set'
16
16
  require 'mongo/cluster/topology/sharded'
17
- require 'mongo/cluster/topology/standalone'
17
+ require 'mongo/cluster/topology/single'
18
18
  require 'mongo/cluster/topology/unknown'
19
19
 
20
20
  module Mongo
@@ -32,7 +32,7 @@ module Mongo
32
32
  OPTIONS = {
33
33
  replica_set: ReplicaSet,
34
34
  sharded: Sharded,
35
- direct: Standalone
35
+ direct: Single
36
36
  }
37
37
 
38
38
  # Get the initial cluster topology for the provided options.
@@ -40,19 +40,20 @@ module Mongo
40
40
  # @example Get the initial cluster topology.
41
41
  # Topology.initial(topology: :replica_set)
42
42
  #
43
+ # @param [ Array<String> ] seeds The addresses of the configured servers.
43
44
  # @param [ Hash ] options The cluster options.
44
45
  #
45
- # @return [ ReplicaSet, Sharded, Standalone ] The topology.
46
+ # @return [ ReplicaSet, Sharded, Single ] The topology.
46
47
  #
47
48
  # @since 2.0.0
48
49
  def initial(seeds, options)
49
50
  if options.has_key?(:connect)
50
- return OPTIONS.fetch(options[:connect]).new(options)
51
+ return OPTIONS.fetch(options[:connect]).new(options, seeds)
51
52
  end
52
53
  if options.has_key?(:replica_set)
53
- ReplicaSet.new(options)
54
+ ReplicaSet.new(options, seeds)
54
55
  else
55
- seeds.size > 1 ? Unknown.new(options) : Standalone.new(options)
56
+ seeds.size > 1 ? Unknown.new(options, seeds) : Single.new(options, seeds)
56
57
  end
57
58
  end
58
59
  end
@@ -82,7 +82,7 @@ module Mongo
82
82
  # @param [ Hash ] options The options.
83
83
  #
84
84
  # @since 2.0.0
85
- def initialize(options)
85
+ def initialize(options, seeds = [])
86
86
  @options = options
87
87
  end
88
88
 
@@ -135,15 +135,15 @@ module Mongo
135
135
  # @since 2.0.0
136
136
  def sharded?; false; end
137
137
 
138
- # A replica set topology is not standalone.
138
+ # A replica set topology is not single.
139
139
  #
140
- # @example Is the topology standalone?
141
- # ReplicaSet.standalone?
140
+ # @example Is the topology single?
141
+ # ReplicaSet.single?
142
142
  #
143
143
  # @return [ false ] Always false.
144
144
  #
145
145
  # @since 2.0.0
146
- def standalone?; false; end
146
+ def single?; false; end
147
147
 
148
148
  # A replica set topology is not unknown.
149
149
  #
@@ -59,7 +59,7 @@ module Mongo
59
59
  # @param [ Hash ] options The options.
60
60
  #
61
61
  # @since 2.0.0
62
- def initialize(options)
62
+ def initialize(options, seeds = [])
63
63
  @options = options
64
64
  end
65
65
 
@@ -107,15 +107,15 @@ module Mongo
107
107
  # @since 2.0.0
108
108
  def sharded?; true; end
109
109
 
110
- # A sharded topology is not standalone.
110
+ # A sharded topology is not single.
111
111
  #
112
- # @example Is the topology standalone?
113
- # Sharded.standalone?
112
+ # @example Is the topology single?
113
+ # Sharded.single?
114
114
  #
115
115
  # @return [ false ] Always false.
116
116
  #
117
117
  # @since 2.0.0
118
- def standalone?; false; end
118
+ def single?; false; end
119
119
 
120
120
  # A sharded topology is not unknown.
121
121
  #
@@ -16,20 +16,23 @@ module Mongo
16
16
  class Cluster
17
17
  module Topology
18
18
 
19
- # Defines behaviour for when a cluster is in standalone topology.
19
+ # Defines behaviour for when a cluster is in single topology.
20
20
  #
21
21
  # @since 2.0.0
22
- class Standalone
22
+ class Single
23
+
24
+ # @return [ String ] seed The seed address.
25
+ attr_reader :seed
23
26
 
24
27
  # The display name for the topology.
25
28
  #
26
29
  # @since 2.0.0
27
- NAME = 'Standalone'.freeze
30
+ NAME = 'Single'.freeze
28
31
 
29
32
  # Get the display name.
30
33
  #
31
34
  # @example Get the display name.
32
- # Standalone.display_name
35
+ # Single.display_name
33
36
  #
34
37
  # @return [ String ] The display name.
35
38
  #
@@ -48,35 +51,36 @@ module Mongo
48
51
  # @param [ Array<Server> ] servers The list of known servers to the
49
52
  # cluster.
50
53
  #
51
- # @return [ Standalone ] The topology.
54
+ # @return [ Single ] The topology.
52
55
  def elect_primary(description, servers); self; end
53
56
 
54
57
  # Initialize the topology with the options.
55
58
  #
56
59
  # @example Initialize the topology.
57
- # Standalone.new(options)
60
+ # Single.new(options)
58
61
  #
59
62
  # @param [ Hash ] options The options.
60
63
  #
61
64
  # @since 2.0.0
62
- def initialize(options)
65
+ def initialize(options, seeds = [])
63
66
  @options = options
67
+ @seed = seeds.first
64
68
  end
65
69
 
66
- # A standalone topology is not a replica set.
70
+ # A single topology is not a replica set.
67
71
  #
68
72
  # @example Is the topology a replica set?
69
- # Sharded.replica_set?
73
+ # Single.replica_set?
70
74
  #
71
75
  # @return [ false ] Always false.
72
76
  #
73
77
  # @since 2.0.0
74
78
  def replica_set?; false; end
75
79
 
76
- # Standalone topologies have no replica set name.
80
+ # Single topologies have no replica set name.
77
81
  #
78
82
  # @example Get the replica set name.
79
- # standalone.replica_set_name
83
+ # single.replica_set_name
80
84
  #
81
85
  # @return [ nil ] Always nil.
82
86
  #
@@ -86,41 +90,41 @@ module Mongo
86
90
  # Select appropriate servers for this topology.
87
91
  #
88
92
  # @example Select the servers.
89
- # Standalone.servers(servers, 'test')
93
+ # Single.servers(servers, 'test')
90
94
  #
91
95
  # @param [ Array<Server> ] servers The known servers.
92
96
  #
93
- # @return [ Array<Server> ] The standalone servers.
97
+ # @return [ Array<Server> ] The single servers.
94
98
  #
95
99
  # @since 2.0.0
96
100
  def servers(servers, name = nil)
97
- [ servers.detect{ |server| server.standalone? } ]
101
+ [ servers.detect { |server| !server.unknown? } ]
98
102
  end
99
103
 
100
- # A standalone topology is not sharded.
104
+ # A single topology is not sharded.
101
105
  #
102
106
  # @example Is the topology sharded?
103
- # Standalone.sharded?
107
+ # Single.sharded?
104
108
  #
105
109
  # @return [ false ] Always false.
106
110
  #
107
111
  # @since 2.0.0
108
112
  def sharded?; false; end
109
113
 
110
- # A standalone topology is standalone.
114
+ # A single topology is single.
111
115
  #
112
- # @example Is the topology standalone?
113
- # Standalone.standalone?
116
+ # @example Is the topology single?
117
+ # Single.single?
114
118
  #
115
119
  # @return [ true ] Always true.
116
120
  #
117
121
  # @since 2.0.0
118
- def standalone?; true; end
122
+ def single?; true; end
119
123
 
120
- # An standalone topology is not unknown.
124
+ # An single topology is not unknown.
121
125
  #
122
126
  # @example Is the topology unknown?
123
- # Standalone.unknown?
127
+ # Single.unknown?
124
128
  #
125
129
  # @return [ false ] Always false.
126
130
  #
@@ -70,7 +70,7 @@ module Mongo
70
70
  # @param [ Hash ] options The options.
71
71
  #
72
72
  # @since 2.0.0
73
- def initialize(options)
73
+ def initialize(options, seeds = [])
74
74
  @options = options
75
75
  end
76
76
 
@@ -106,6 +106,7 @@ module Mongo
106
106
  #
107
107
  # @since 2.0.0
108
108
  def servers(servers)
109
+ []
109
110
  end
110
111
 
111
112
  # An unknown topology is not sharded.
@@ -118,15 +119,15 @@ module Mongo
118
119
  # @since 2.0.0
119
120
  def sharded?; false; end
120
121
 
121
- # An unknown topology is not standalone.
122
+ # An unknown topology is not single.
122
123
  #
123
- # @example Is the topology standalone?
124
- # Unknown.standalone?
124
+ # @example Is the topology single?
125
+ # Unknown.single?
125
126
  #
126
127
  # @return [ true ] Always false.
127
128
  #
128
129
  # @since 2.0.0
129
- def standalone?; false; end
130
+ def single?; false; end
130
131
 
131
132
  # An unknown topology is unknown.
132
133
  #
@@ -84,6 +84,8 @@ module Mongo
84
84
  # Drop the collection. Will also drop all indexes associated with the
85
85
  # collection.
86
86
  #
87
+ # @note An error returned if the collection doesn't exist is suppressed.
88
+ #
87
89
  # @example Drop the collection.
88
90
  # collection.drop
89
91
  #
@@ -92,6 +94,9 @@ module Mongo
92
94
  # @since 2.0.0
93
95
  def drop
94
96
  database.command(:drop => name)
97
+ rescue Error::OperationFailure => ex
98
+ raise ex unless ex.message =~ /ns not found/
99
+ false
95
100
  end
96
101
 
97
102
  # Find documents in the collection.
@@ -215,7 +220,7 @@ module Mongo
215
220
  #
216
221
  # @since 2.0.0
217
222
  def namespace
218
- "#{name}.#{database.name}"
223
+ "#{database.name}.#{name}"
219
224
  end
220
225
  end
221
226
  end
@@ -125,6 +125,7 @@ module Mongo
125
125
  #
126
126
  # @since 2.0.0
127
127
  def initialize(collection, selector = {}, options = {})
128
+ validate_doc!(selector)
128
129
  @collection = collection
129
130
  @selector = selector.dup
130
131
  @options = options.dup
@@ -232,6 +232,7 @@ module Mongo
232
232
  #
233
233
  # @since 2.0.0
234
234
  def projection(document = nil)
235
+ validate_doc!(document) if document
235
236
  configure(:projection, document)
236
237
  end
237
238
 
@@ -357,6 +358,10 @@ module Mongo
357
358
  def to_return
358
359
  [ limit || batch_size, batch_size || limit ].min
359
360
  end
361
+
362
+ def validate_doc!(doc)
363
+ raise Error::InvalidDocument.new unless doc.respond_to?(:keys)
364
+ end
360
365
  end
361
366
  end
362
367
  end