Use ENV["MONGODB_URI"] if available.
This commit is contained in:
parent
351eeb65a2
commit
1454210d9f
@ -173,6 +173,14 @@ Certain Ruby application servers work by forking, and it has long been necessary
|
|||||||
re-establish the child process's connection to the database after fork. But with the release
|
re-establish the child process's connection to the database after fork. But with the release
|
||||||
of v1.3.0, the Ruby driver detects forking and reconnects automatically.
|
of v1.3.0, the Ruby driver detects forking and reconnects automatically.
|
||||||
|
|
||||||
|
## Environment variable `MONGODB_URI`
|
||||||
|
|
||||||
|
`Mongo::Connection.new` and `Mongo::ReplSetConnection.new` will use <code>ENV["MONGODB_URI"]</code> if no other args are provided.
|
||||||
|
|
||||||
|
The URI must fit this specification:
|
||||||
|
|
||||||
|
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
|
||||||
|
|
||||||
## String Encoding
|
## String Encoding
|
||||||
|
|
||||||
The BSON ("Binary JSON") format used to communicate with Mongo requires that
|
The BSON ("Binary JSON") format used to communicate with Mongo requires that
|
||||||
|
@ -32,6 +32,7 @@ module Mongo
|
|||||||
|
|
||||||
Thread.abort_on_exception = true
|
Thread.abort_on_exception = true
|
||||||
|
|
||||||
|
DEFAULT_HOST = 'localhost'
|
||||||
DEFAULT_PORT = 27017
|
DEFAULT_PORT = 27017
|
||||||
GENERIC_OPTS = [:ssl, :auths, :pool_size, :pool_timeout, :timeout, :op_timeout, :connect_timeout, :safe, :logger, :connect]
|
GENERIC_OPTS = [:ssl, :auths, :pool_size, :pool_timeout, :timeout, :op_timeout, :connect_timeout, :safe, :logger, :connect]
|
||||||
CONNECTION_OPTS = [:slave_ok]
|
CONNECTION_OPTS = [:slave_ok]
|
||||||
@ -44,6 +45,8 @@ module Mongo
|
|||||||
|
|
||||||
# Create a connection to single MongoDB instance.
|
# Create a connection to single MongoDB instance.
|
||||||
#
|
#
|
||||||
|
# If no args are provided, it will check <code>ENV["MONGODB_URI"]</code>.
|
||||||
|
#
|
||||||
# You may specify whether connection to slave is permitted.
|
# You may specify whether connection to slave is permitted.
|
||||||
# In all cases, the default host is "localhost" and the default port is 27017.
|
# In all cases, the default host is "localhost" and the default port is 27017.
|
||||||
#
|
#
|
||||||
@ -76,7 +79,7 @@ module Mongo
|
|||||||
# connection attempt.
|
# connection attempt.
|
||||||
# @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
|
# @option opts [Boolean] :ssl (false) If true, create the connection to the server using SSL.
|
||||||
#
|
#
|
||||||
# @example localhost, 27017
|
# @example localhost, 27017 (or <code>ENV["MONGODB_URI"]</code> if available)
|
||||||
# Mongo::Connection.new
|
# Mongo::Connection.new
|
||||||
#
|
#
|
||||||
# @example localhost, 27017
|
# @example localhost, 27017
|
||||||
@ -93,9 +96,22 @@ module Mongo
|
|||||||
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
|
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
|
||||||
# driver fails to connect to a replica set with that name.
|
# driver fails to connect to a replica set with that name.
|
||||||
#
|
#
|
||||||
|
# @raise [MongoArgumentError] If called with no arguments and <code>ENV["MONGODB_URI"]</code> implies a replica set.
|
||||||
|
#
|
||||||
# @core self.connections
|
# @core self.connections
|
||||||
def initialize(host=nil, port=nil, opts={})
|
def initialize(host=nil, port=nil, opts={})
|
||||||
@host_to_try = format_pair(host, port)
|
if host.nil? and ENV.has_key?('MONGODB_URI')
|
||||||
|
parser = URIParser.new ENV['MONGODB_URI'], opts
|
||||||
|
if parser.replicaset?
|
||||||
|
raise MongoArgumentError, "Mongo::Connection.new called with no arguments, but ENV['MONGODB_URI'] implies a replica set."
|
||||||
|
end
|
||||||
|
opts = parser.connection_options
|
||||||
|
@host_to_try = [parser.host, parser.port]
|
||||||
|
elsif host.is_a?(String)
|
||||||
|
@host_to_try = [host, (port || DEFAULT_PORT).to_i]
|
||||||
|
else
|
||||||
|
@host_to_try = [DEFAULT_HOST, DEFAULT_PORT]
|
||||||
|
end
|
||||||
|
|
||||||
# Host and port of current master.
|
# Host and port of current master.
|
||||||
@host = @port = nil
|
@host = @port = nil
|
||||||
@ -143,8 +159,7 @@ module Mongo
|
|||||||
def self.multi(nodes, opts={})
|
def self.multi(nodes, opts={})
|
||||||
warn "Connection.multi is now deprecated and will be removed in v2.0. Please use ReplSetConnection.new instead."
|
warn "Connection.multi is now deprecated and will be removed in v2.0. Please use ReplSetConnection.new instead."
|
||||||
|
|
||||||
nodes << opts
|
ReplSetConnection.new(*(nodes+[opts]))
|
||||||
ReplSetConnection.new(*nodes)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initialize a connection to MongoDB using the MongoDB URI spec:
|
# Initialize a connection to MongoDB using the MongoDB URI spec:
|
||||||
@ -155,21 +170,9 @@ module Mongo
|
|||||||
# @param opts Any of the options available for Connection.new
|
# @param opts Any of the options available for Connection.new
|
||||||
#
|
#
|
||||||
# @return [Mongo::Connection, Mongo::ReplSetConnection]
|
# @return [Mongo::Connection, Mongo::ReplSetConnection]
|
||||||
def self.from_uri(string, extra_opts={})
|
def self.from_uri(uri, extra_opts={})
|
||||||
uri = URIParser.new(string)
|
parser = URIParser.new uri, extra_opts
|
||||||
opts = uri.connection_options
|
parser.connection
|
||||||
opts.merge!(extra_opts)
|
|
||||||
|
|
||||||
if uri.nodes.length == 1
|
|
||||||
opts.merge!({:auths => uri.auths})
|
|
||||||
Connection.new(uri.nodes[0][0], uri.nodes[0][1], opts)
|
|
||||||
elsif uri.nodes.length > 1
|
|
||||||
nodes = uri.nodes.clone
|
|
||||||
nodes_with_opts = nodes << opts
|
|
||||||
ReplSetConnection.new(*nodes_with_opts)
|
|
||||||
else
|
|
||||||
raise MongoArgumentError, "No nodes specified. Please ensure that you've provided at least one node."
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# The host name used for this connection.
|
# The host name used for this connection.
|
||||||
@ -337,7 +340,7 @@ module Mongo
|
|||||||
# @param [String] from_host host of the 'from' database.
|
# @param [String] from_host host of the 'from' database.
|
||||||
# @param [String] username username for authentication against from_db (>=1.3.x).
|
# @param [String] username username for authentication against from_db (>=1.3.x).
|
||||||
# @param [String] password password for authentication against from_db (>=1.3.x).
|
# @param [String] password password for authentication against from_db (>=1.3.x).
|
||||||
def copy_database(from, to, from_host="localhost", username=nil, password=nil)
|
def copy_database(from, to, from_host=DEFAULT_HOST, username=nil, password=nil)
|
||||||
oh = BSON::OrderedHash.new
|
oh = BSON::OrderedHash.new
|
||||||
oh[:copydb] = 1
|
oh[:copydb] = 1
|
||||||
oh[:fromhost] = from_host
|
oh[:fromhost] = from_host
|
||||||
@ -585,23 +588,8 @@ module Mongo
|
|||||||
write_logging_startup_message
|
write_logging_startup_message
|
||||||
end
|
end
|
||||||
|
|
||||||
should_connect = opts.fetch(:connect, true)
|
if opts.fetch(:connect, true)
|
||||||
connect if should_connect
|
connect
|
||||||
end
|
|
||||||
|
|
||||||
## Configuration helper methods
|
|
||||||
|
|
||||||
# Returns a host-port pair.
|
|
||||||
#
|
|
||||||
# @return [Array]
|
|
||||||
#
|
|
||||||
# @private
|
|
||||||
def format_pair(host, port)
|
|
||||||
case host
|
|
||||||
when String
|
|
||||||
[host, port ? port.to_i : DEFAULT_PORT]
|
|
||||||
when nil
|
|
||||||
['localhost', DEFAULT_PORT]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ module Mongo
|
|||||||
|
|
||||||
# Create a connection to a MongoDB replica set.
|
# Create a connection to a MongoDB replica set.
|
||||||
#
|
#
|
||||||
|
# If no args are provided, it will check <code>ENV["MONGODB_URI"]</code>.
|
||||||
|
#
|
||||||
# Once connected to a replica set, you can find out which nodes are primary, secondary, and
|
# Once connected to a replica set, you can find out which nodes are primary, secondary, and
|
||||||
# arbiters with the corresponding accessors: Connection#primary, Connection#secondaries, and
|
# arbiters with the corresponding accessors: Connection#primary, Connection#secondaries, and
|
||||||
# Connection#arbiters. This is useful if your application needs to connect manually to nodes other
|
# Connection#arbiters. This is useful if your application needs to connect manually to nodes other
|
||||||
@ -78,6 +80,8 @@ module Mongo
|
|||||||
#
|
#
|
||||||
# @see http://api.mongodb.org/ruby/current/file.REPLICA_SETS.html Replica sets in Ruby
|
# @see http://api.mongodb.org/ruby/current/file.REPLICA_SETS.html Replica sets in Ruby
|
||||||
#
|
#
|
||||||
|
# @raise [MongoArgumentError] If called with no arguments and <code>ENV["MONGODB_URI"]</code> implies a direct connection.
|
||||||
|
#
|
||||||
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
|
# @raise [ReplicaSetConnectionError] This is raised if a replica set name is specified and the
|
||||||
# driver fails to connect to a replica set with that name.
|
# driver fails to connect to a replica set with that name.
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
@ -87,21 +91,30 @@ module Mongo
|
|||||||
opts = {}
|
opts = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
unless args.length > 0
|
nodes = args
|
||||||
|
|
||||||
|
if nodes.empty? and ENV.has_key?('MONGODB_URI')
|
||||||
|
parser = URIParser.new ENV['MONGODB_URI'], opts
|
||||||
|
if parser.direct?
|
||||||
|
raise MongoArgumentError, "Mongo::ReplSetConnection.new called with no arguments, but ENV['MONGODB_URI'] implies a direct connection."
|
||||||
|
end
|
||||||
|
opts = parser.connection_options
|
||||||
|
nodes = parser.nodes
|
||||||
|
end
|
||||||
|
|
||||||
|
unless nodes.length > 0
|
||||||
raise MongoArgumentError, "A ReplSetConnection requires at least one seed node."
|
raise MongoArgumentError, "A ReplSetConnection requires at least one seed node."
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is temporary until support for the old format is dropped
|
# This is temporary until support for the old format is dropped
|
||||||
@seeds = []
|
if nodes.first.last.is_a?(Integer)
|
||||||
if args.first.last.is_a?(Integer)
|
|
||||||
warn "Initiating a ReplSetConnection with seeds passed as individual [host, port] array arguments is deprecated."
|
warn "Initiating a ReplSetConnection with seeds passed as individual [host, port] array arguments is deprecated."
|
||||||
warn "Please specify hosts as an array of 'host:port' strings; the old format will be removed in v2.0"
|
warn "Please specify hosts as an array of 'host:port' strings; the old format will be removed in v2.0"
|
||||||
@seeds = args
|
@seeds = nodes
|
||||||
else
|
else
|
||||||
args.first.map do |host_port|
|
@seeds = nodes.first.map do |host_port|
|
||||||
seed = host_port.split(":")
|
host, port = host_port.split(":")
|
||||||
seed[1] = seed[1].to_i
|
[ host, port.to_i ]
|
||||||
seeds << seed
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
# ++
|
# ++
|
||||||
|
|
||||||
|
require 'uri'
|
||||||
|
|
||||||
module Mongo
|
module Mongo
|
||||||
class URIParser
|
class URIParser
|
||||||
|
|
||||||
DEFAULT_PORT = 27017
|
|
||||||
|
|
||||||
USER_REGEX = /([-.\w:]+)/
|
USER_REGEX = /([-.\w:]+)/
|
||||||
PASS_REGEX = /([^@,]+)/
|
PASS_REGEX = /([^@,]+)/
|
||||||
AUTH_REGEX = /(#{USER_REGEX}:#{PASS_REGEX}@)?/
|
AUTH_REGEX = /(#{USER_REGEX}:#{PASS_REGEX}@)?/
|
||||||
@ -37,7 +37,7 @@ module Mongo
|
|||||||
SPEC_ATTRS = [:nodes, :auths]
|
SPEC_ATTRS = [:nodes, :auths]
|
||||||
OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync, :journal, :connecttimeoutms, :sockettimeoutms, :wtimeoutms]
|
OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync, :journal, :connecttimeoutms, :sockettimeoutms, :wtimeoutms]
|
||||||
|
|
||||||
OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset'].include?(arg)},
|
OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset', 'true', 'false', true, false].include?(arg)},
|
||||||
:replicaset => lambda {|arg| arg.length > 0},
|
:replicaset => lambda {|arg| arg.length > 0},
|
||||||
:slaveok => lambda {|arg| ['true', 'false'].include?(arg)},
|
:slaveok => lambda {|arg| ['true', 'false'].include?(arg)},
|
||||||
:safe => lambda {|arg| ['true', 'false'].include?(arg)},
|
:safe => lambda {|arg| ['true', 'false'].include?(arg)},
|
||||||
@ -50,7 +50,7 @@ module Mongo
|
|||||||
:wtimeoutms => lambda {|arg| arg =~ /^\d+$/ }
|
:wtimeoutms => lambda {|arg| arg =~ /^\d+$/ }
|
||||||
}
|
}
|
||||||
|
|
||||||
OPT_ERR = {:connect => "must be 'direct' or 'replicaset'",
|
OPT_ERR = {:connect => "must be 'direct', 'replicaset', 'true', or 'false'",
|
||||||
:replicaset => "must be a string containing the name of the replica set to connect to",
|
:replicaset => "must be a string containing the name of the replica set to connect to",
|
||||||
:slaveok => "must be 'true' or 'false'",
|
:slaveok => "must be 'true' or 'false'",
|
||||||
:safe => "must be 'true' or 'false'",
|
:safe => "must be 'true' or 'false'",
|
||||||
@ -63,7 +63,7 @@ module Mongo
|
|||||||
:wtimeoutms => "must be an integer specifying milliseconds"
|
:wtimeoutms => "must be an integer specifying milliseconds"
|
||||||
}
|
}
|
||||||
|
|
||||||
OPT_CONV = {:connect => lambda {|arg| arg},
|
OPT_CONV = {:connect => lambda {|arg| arg == 'false' ? false : arg}, # be sure to convert 'false' to FalseClass
|
||||||
:replicaset => lambda {|arg| arg},
|
:replicaset => lambda {|arg| arg},
|
||||||
:slaveok => lambda {|arg| arg == 'true' ? true : false},
|
:slaveok => lambda {|arg| arg == 'true' ? true : false},
|
||||||
:safe => lambda {|arg| arg == 'true' ? true : false},
|
:safe => lambda {|arg| arg == 'true' ? true : false},
|
||||||
@ -81,22 +81,73 @@ module Mongo
|
|||||||
# Parse a MongoDB URI. This method is used by Connection.from_uri.
|
# Parse a MongoDB URI. This method is used by Connection.from_uri.
|
||||||
# Returns an array of nodes and an array of db authorizations, if applicable.
|
# Returns an array of nodes and an array of db authorizations, if applicable.
|
||||||
#
|
#
|
||||||
# Note: passwords can contain any character except for a ','.
|
# @note Passwords can contain any character except for ','
|
||||||
|
#
|
||||||
|
# @param [String] uri The MongoDB URI string.
|
||||||
|
# @param [Hash,nil] extra_opts Extra options. Will override anything already specified in the URI.
|
||||||
#
|
#
|
||||||
# @core connections
|
# @core connections
|
||||||
def initialize(string)
|
def initialize(uri, extra_opts={})
|
||||||
if string =~ /^mongodb:\/\//
|
if uri.start_with?('mongodb://')
|
||||||
string = string[10..-1]
|
uri = uri[10..-1]
|
||||||
else
|
else
|
||||||
raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
|
raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
|
||||||
end
|
end
|
||||||
|
|
||||||
hosts, opts = string.split('?')
|
hosts, opts = uri.split('?')
|
||||||
parse_hosts(hosts)
|
parse_hosts(hosts)
|
||||||
parse_options(opts)
|
parse_options(opts, extra_opts)
|
||||||
configure_connect
|
validate_connect
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create a Mongo::Connection or a Mongo::ReplSetConnection based on the URI.
|
||||||
|
#
|
||||||
|
# @note Don't confuse this with attribute getter method #connect.
|
||||||
|
#
|
||||||
|
# @return [Connection,ReplSetConnection]
|
||||||
|
def connection
|
||||||
|
if replicaset?
|
||||||
|
ReplSetConnection.new(*(nodes+[connection_options]))
|
||||||
|
else
|
||||||
|
Connection.new(host, port, connection_options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Whether this represents a replica set.
|
||||||
|
# @return [true,false]
|
||||||
|
def replicaset?
|
||||||
|
replicaset.is_a?(String) || nodes.length > 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Whether to immediately connect to the MongoDB node[s]. Defaults to true.
|
||||||
|
# @return [true, false]
|
||||||
|
def connect?
|
||||||
|
connect != false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Whether this represents a direct connection.
|
||||||
|
#
|
||||||
|
# @note Specifying :connect => 'direct' has no effect... other than to raise an exception if other variables suggest a replicaset.
|
||||||
|
#
|
||||||
|
# @return [true,false]
|
||||||
|
def direct?
|
||||||
|
!replicaset?
|
||||||
|
end
|
||||||
|
|
||||||
|
# For direct connections, the host of the (only) node.
|
||||||
|
# @return [String]
|
||||||
|
def host
|
||||||
|
nodes[0][0]
|
||||||
|
end
|
||||||
|
|
||||||
|
# For direct connections, the port of the (only) node.
|
||||||
|
# @return [Integer]
|
||||||
|
def port
|
||||||
|
nodes[0][1].to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
# Options that can be passed to Mongo::Connection.new or Mongo::ReplSetConnection.new
|
||||||
|
# @return [Hash]
|
||||||
def connection_options
|
def connection_options
|
||||||
opts = {}
|
opts = {}
|
||||||
|
|
||||||
@ -136,14 +187,22 @@ module Mongo
|
|||||||
end
|
end
|
||||||
|
|
||||||
if @slaveok
|
if @slaveok
|
||||||
if @connect == 'direct'
|
if direct?
|
||||||
opts[:slave_ok] = true
|
opts[:slave_ok] = true
|
||||||
else
|
else
|
||||||
opts[:read] = :secondary
|
opts[:read] = :secondary
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
opts[:name] = @replicaset if @replicaset
|
if direct?
|
||||||
|
opts[:auths] = auths
|
||||||
|
end
|
||||||
|
|
||||||
|
if replicaset.is_a?(String)
|
||||||
|
opts[:name] = replicaset
|
||||||
|
end
|
||||||
|
|
||||||
|
opts[:connect] = connect?
|
||||||
|
|
||||||
opts
|
opts
|
||||||
end
|
end
|
||||||
@ -167,7 +226,7 @@ module Mongo
|
|||||||
|
|
||||||
hosturis.each do |hosturi|
|
hosturis.each do |hosturi|
|
||||||
# If port is present, use it, otherwise use default port
|
# If port is present, use it, otherwise use default port
|
||||||
host, port = hosturi.split(':') + [DEFAULT_PORT]
|
host, port = hosturi.split(':') + [Connection::DEFAULT_PORT]
|
||||||
|
|
||||||
if !(port.to_s =~ /^\d+$/)
|
if !(port.to_s =~ /^\d+$/)
|
||||||
raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
|
raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
|
||||||
@ -178,6 +237,10 @@ module Mongo
|
|||||||
@nodes << [host, port]
|
@nodes << [host, port]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @nodes.empty?
|
||||||
|
raise MongoArgumentError, "No nodes specified. Please ensure that you've provided at least one node."
|
||||||
|
end
|
||||||
|
|
||||||
if uname && pwd && db
|
if uname && pwd && db
|
||||||
auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
|
auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
|
||||||
elsif uname || pwd
|
elsif uname || pwd
|
||||||
@ -191,40 +254,37 @@ module Mongo
|
|||||||
|
|
||||||
# This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate
|
# This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate
|
||||||
# and convert the given options.
|
# and convert the given options.
|
||||||
def parse_options(opts)
|
def parse_options(string_opts, extra_opts={})
|
||||||
# initialize instance variables for available options
|
# initialize instance variables for available options
|
||||||
OPT_VALID.keys.each { |k| instance_variable_set("@#{k}", nil) }
|
OPT_VALID.keys.each { |k| instance_variable_set("@#{k}", nil) }
|
||||||
|
|
||||||
return unless opts
|
string_opts ||= ''
|
||||||
|
|
||||||
separator = opts.include?('&') ? '&' : ';'
|
return if string_opts.empty? && extra_opts.empty?
|
||||||
opts.split(separator).each do |attr|
|
|
||||||
key, value = attr.split('=')
|
opts = URI.decode_www_form(string_opts).inject({}) do |memo, (key, value)|
|
||||||
key = key.downcase.to_sym
|
memo[key.downcase.to_sym] = value.strip.downcase
|
||||||
value = value.strip.downcase
|
memo
|
||||||
|
end
|
||||||
|
|
||||||
|
opts.merge! extra_opts
|
||||||
|
|
||||||
|
opts.each do |key, value|
|
||||||
if !OPT_ATTRS.include?(key)
|
if !OPT_ATTRS.include?(key)
|
||||||
raise MongoArgumentError, "Invalid Mongo URI option #{key}"
|
raise MongoArgumentError, "Invalid Mongo URI option #{key}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if OPT_VALID[key].call(value)
|
if OPT_VALID[key].call(value)
|
||||||
instance_variable_set("@#{key}", OPT_CONV[key].call(value))
|
instance_variable_set("@#{key}", OPT_CONV[key].call(value))
|
||||||
else
|
else
|
||||||
raise MongoArgumentError, "Invalid value for #{key}: #{OPT_ERR[key]}"
|
raise MongoArgumentError, "Invalid value #{value.inspect} for #{key}: #{OPT_ERR[key]}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_connect
|
def validate_connect
|
||||||
if !@connect
|
if replicaset? and @connect == 'direct'
|
||||||
if @nodes.length > 1
|
# Make sure the user doesn't specify something contradictory
|
||||||
@connect = 'replicaset'
|
raise MongoArgumentError, "connect=direct conflicts with setting a replicaset name"
|
||||||
else
|
|
||||||
@connect = 'direct'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if @connect == 'direct' && @replicaset
|
|
||||||
raise MongoArgumentError, "If specifying a replica set name, please also specify that connect=replicaset"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -58,6 +58,18 @@ class TestConnection < Test::Unit::TestCase
|
|||||||
assert_equal mongo_port, con.primary_pool.port
|
assert_equal mongo_port, con.primary_pool.port
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_env_mongodb_uri
|
||||||
|
begin
|
||||||
|
old_mongodb_uri = ENV['MONGODB_URI']
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{host_port}"
|
||||||
|
con = Connection.new
|
||||||
|
assert_equal mongo_host, con.primary_pool.host
|
||||||
|
assert_equal mongo_port, con.primary_pool.port
|
||||||
|
ensure
|
||||||
|
ENV['MONGODB_URI'] = old_mongodb_uri
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_server_version
|
def test_server_version
|
||||||
assert_match(/\d\.\d+(\.\d+)?/, @conn.server_version.to_s)
|
assert_match(/\d\.\d+(\.\d+)?/, @conn.server_version.to_s)
|
||||||
end
|
end
|
||||||
|
@ -105,6 +105,20 @@ class ConnectTest < Test::Unit::TestCase
|
|||||||
assert @conn.is_a?(ReplSetConnection)
|
assert @conn.is_a?(ReplSetConnection)
|
||||||
assert @conn.connected?
|
assert @conn.connected?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_connect_with_connection_string_in_env_var
|
||||||
|
begin
|
||||||
|
old_mongodb_uri = ENV['MONGODB_URI']
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{@rs.host}:#{@rs.ports[0]},#{@rs.host}:#{@rs.ports[1]}?replicaset=#{@rs.name}"
|
||||||
|
silently do
|
||||||
|
@conn = ReplSetConnection.new
|
||||||
|
end
|
||||||
|
assert @conn.is_a?(ReplSetConnection)
|
||||||
|
assert @conn.connected?
|
||||||
|
ensure
|
||||||
|
ENV['MONGODB_URI'] = old_mongodb_uri
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_connect_with_new_seed_format
|
def test_connect_with_new_seed_format
|
||||||
@conn = ReplSetConnection.new build_seeds(3)
|
@conn = ReplSetConnection.new build_seeds(3)
|
||||||
@ -128,4 +142,21 @@ class ConnectTest < Test::Unit::TestCase
|
|||||||
assert @conn.safe[:fsync]
|
assert @conn.safe[:fsync]
|
||||||
assert @conn.read_pool
|
assert @conn.read_pool
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_connect_with_full_connection_string_in_env_var
|
||||||
|
begin
|
||||||
|
old_mongodb_uri = ENV['MONGODB_URI']
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{@rs.host}:#{@rs.ports[0]},#{@rs.host}:#{@rs.ports[1]}?replicaset=#{@rs.name};safe=true;w=2;fsync=true;slaveok=true"
|
||||||
|
silently do
|
||||||
|
@conn = ReplSetConnection.new
|
||||||
|
end
|
||||||
|
assert @conn.is_a?(ReplSetConnection)
|
||||||
|
assert @conn.connected?
|
||||||
|
assert_equal 2, @conn.safe[:w]
|
||||||
|
assert @conn.safe[:fsync]
|
||||||
|
assert @conn.read_pool
|
||||||
|
ensure
|
||||||
|
ENV['MONGODB_URI'] = old_mongodb_uri
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -130,5 +130,93 @@ class ConnectionTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "initializing with ENV['MONGODB_URI']" do
|
||||||
|
setup do
|
||||||
|
@old_mongodb_uri = ENV['MONGODB_URI']
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
ENV['MONGODB_URI'] = @old_mongodb_uri
|
||||||
|
end
|
||||||
|
|
||||||
|
should "parse a simple uri" do
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://localhost?connect=false"
|
||||||
|
@conn = Connection.new
|
||||||
|
assert_equal ['localhost', 27017], @conn.host_to_try
|
||||||
|
end
|
||||||
|
|
||||||
|
should "allow a complex host names" do
|
||||||
|
host_name = "foo.bar-12345.org"
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{host_name}?connect=false"
|
||||||
|
@conn = Connection.new
|
||||||
|
assert_equal [host_name, 27017], @conn.host_to_try
|
||||||
|
end
|
||||||
|
|
||||||
|
should "allow db without username and password" do
|
||||||
|
host_name = "foo.bar-12345.org"
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{host_name}/foo?connect=false"
|
||||||
|
@conn = Connection.new
|
||||||
|
assert_equal [host_name, 27017], @conn.host_to_try
|
||||||
|
end
|
||||||
|
|
||||||
|
should "set safe options on connection" do
|
||||||
|
host_name = "localhost"
|
||||||
|
opts = "safe=true&w=2&wtimeoutMS=1000&fsync=true&journal=true&connect=false"
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{host_name}/foo?#{opts}"
|
||||||
|
@conn = Connection.new
|
||||||
|
assert_equal({:w => 2, :wtimeout => 1000, :fsync => true, :j => true}, @conn.safe)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "set timeout options on connection" do
|
||||||
|
host_name = "localhost"
|
||||||
|
opts = "connectTimeoutMS=1000&socketTimeoutMS=5000&connect=false"
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://#{host_name}/foo?#{opts}"
|
||||||
|
@conn = Connection.new
|
||||||
|
assert_equal 1, @conn.connect_timeout
|
||||||
|
assert_equal 5, @conn.op_timeout
|
||||||
|
end
|
||||||
|
|
||||||
|
should "parse a uri with a hyphen & underscore in the username or password" do
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://hyphen-user_name:p-s_s@localhost:27017/db?connect=false"
|
||||||
|
@conn = Connection.new
|
||||||
|
assert_equal ['localhost', 27017], @conn.host_to_try
|
||||||
|
auth_hash = { 'db_name' => 'db', 'username' => 'hyphen-user_name', "password" => 'p-s_s' }
|
||||||
|
assert_equal auth_hash, @conn.auths[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
should "attempt to connect" do
|
||||||
|
TCPSocket.stubs(:new).returns(new_mock_socket)
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://localhost?connect=false" # connect=false ??
|
||||||
|
@conn = Connection.new
|
||||||
|
|
||||||
|
admin_db = new_mock_db
|
||||||
|
admin_db.expects(:command).returns({'ok' => 1, 'ismaster' => 1})
|
||||||
|
@conn.expects(:[]).with('admin').returns(admin_db)
|
||||||
|
@conn.connect
|
||||||
|
end
|
||||||
|
|
||||||
|
should "raise an error on invalid uris" do
|
||||||
|
ENV['MONGODB_URI'] = "mongo://localhost"
|
||||||
|
assert_raise MongoArgumentError do
|
||||||
|
Connection.new
|
||||||
|
end
|
||||||
|
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://localhost:abc"
|
||||||
|
assert_raise MongoArgumentError do
|
||||||
|
Connection.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "require all of username, if password and db are specified" do
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://kyle:jones@localhost/db?connect=false"
|
||||||
|
assert Connection.new
|
||||||
|
|
||||||
|
ENV['MONGODB_URI'] = "mongodb://kyle:password@localhost"
|
||||||
|
assert_raise MongoArgumentError do
|
||||||
|
Connection.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -63,9 +63,10 @@ class URITest < Test::Unit::TestCase
|
|||||||
assert_equal "test", parser.auths[1]["db_name"]
|
assert_equal "test", parser.auths[1]["db_name"]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_opts_basic
|
def test_opts_with_semincolon_separator
|
||||||
parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=direct;slaveok=true;safe=true')
|
parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=direct;slaveok=true;safe=true')
|
||||||
assert_equal 'direct', parser.connect
|
assert_equal 'direct', parser.connect
|
||||||
|
assert parser.direct?
|
||||||
assert parser.slaveok
|
assert parser.slaveok
|
||||||
assert parser.safe
|
assert parser.safe
|
||||||
end
|
end
|
||||||
@ -73,10 +74,17 @@ class URITest < Test::Unit::TestCase
|
|||||||
def test_opts_with_amp_separator
|
def test_opts_with_amp_separator
|
||||||
parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=direct&slaveok=true&safe=true')
|
parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=direct&slaveok=true&safe=true')
|
||||||
assert_equal 'direct', parser.connect
|
assert_equal 'direct', parser.connect
|
||||||
|
assert parser.direct?
|
||||||
assert parser.slaveok
|
assert parser.slaveok
|
||||||
assert parser.safe
|
assert parser.safe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_opts_made_invalid_by_mixed_separators
|
||||||
|
assert_raise_error ArgumentError, "invalid data of application/x-www-form-urlencoded (replicaset=foo;bar&slaveok=true&safe=true)" do
|
||||||
|
Mongo::URIParser.new('mongodb://localhost:27018?replicaset=foo;bar&slaveok=true&safe=true')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_opts_safe
|
def test_opts_safe
|
||||||
parser = Mongo::URIParser.new('mongodb://localhost:27018?safe=true;w=2;journal=true;fsync=true;wtimeoutMS=200')
|
parser = Mongo::URIParser.new('mongodb://localhost:27018?safe=true;w=2;journal=true;fsync=true;wtimeoutMS=200')
|
||||||
assert parser.safe
|
assert parser.safe
|
||||||
@ -93,12 +101,16 @@ class URITest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_opts_replica_set
|
def test_opts_replica_set
|
||||||
assert_raise_error MongoArgumentError, "specify that connect=replicaset" do
|
|
||||||
Mongo::URIParser.new('mongodb://localhost:27018?replicaset=foo')
|
|
||||||
end
|
|
||||||
parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=replicaset;replicaset=foo')
|
parser = Mongo::URIParser.new('mongodb://localhost:27018?connect=replicaset;replicaset=foo')
|
||||||
assert_equal 'foo', parser.replicaset
|
assert_equal 'foo', parser.replicaset
|
||||||
assert_equal 'replicaset', parser.connect
|
assert_equal 'replicaset', parser.connect
|
||||||
|
assert parser.replicaset?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_opts_conflicting_replica_set
|
||||||
|
assert_raise_error MongoArgumentError, "connect=direct conflicts with setting a replicaset name" do
|
||||||
|
Mongo::URIParser.new('mongodb://localhost:27018?connect=direct;replicaset=foo')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_case_insensitivity
|
def test_case_insensitivity
|
||||||
|
Loading…
Reference in New Issue
Block a user