mongo 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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