RUBY-424 Authenticating with only secondary fails
Authentication command now prefers to use primary node but will fall back on secondary if no primary is available
This commit is contained in:
parent
7fd0b8dfce
commit
ec86275b60
|
@ -480,6 +480,12 @@ module Mongo
|
||||||
@max_bson_size
|
@max_bson_size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Prefer primary pool but fall back to secondary
|
||||||
|
def checkout_best
|
||||||
|
connect unless connected?
|
||||||
|
@primary_pool.checkout
|
||||||
|
end
|
||||||
|
|
||||||
# Checkout a socket for reading (i.e., a secondary node).
|
# Checkout a socket for reading (i.e., a secondary node).
|
||||||
# Note: this is overridden in ReplSetConnection.
|
# Note: this is overridden in ReplSetConnection.
|
||||||
def checkout_reader
|
def checkout_reader
|
||||||
|
@ -513,6 +519,19 @@ module Mongo
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Excecutes block with the best available socket
|
||||||
|
def best_available_socket
|
||||||
|
socket = nil
|
||||||
|
begin
|
||||||
|
socket = checkout_best
|
||||||
|
yield socket
|
||||||
|
ensure
|
||||||
|
if socket
|
||||||
|
socket.pool.checkin(socket)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def valid_opts
|
def valid_opts
|
||||||
|
|
|
@ -111,10 +111,13 @@ module Mongo
|
||||||
if !save_auth
|
if !save_auth
|
||||||
raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
|
raise MongoArgumentError, "If using connection pooling, :save_auth must be set to true."
|
||||||
end
|
end
|
||||||
@connection.authenticate_pools
|
|
||||||
end
|
end
|
||||||
|
|
||||||
issue_authentication(username, password, save_auth)
|
@connection.best_available_socket do |socket|
|
||||||
|
issue_authentication(username, password, save_auth, :socket => socket)
|
||||||
|
end
|
||||||
|
|
||||||
|
@connection.authenticate_pools
|
||||||
end
|
end
|
||||||
|
|
||||||
def issue_authentication(username, password, save_auth=true, opts={})
|
def issue_authentication(username, password, save_auth=true, opts={})
|
||||||
|
|
|
@ -287,14 +287,18 @@ module Mongo
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate_pools
|
def authenticate_pools
|
||||||
primary_pool.authenticate_existing
|
if primary_pool
|
||||||
|
primary_pool.authenticate_existing
|
||||||
|
end
|
||||||
secondary_pools.each do |pool|
|
secondary_pools.each do |pool|
|
||||||
pool.authenticate_existing
|
pool.authenticate_existing
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def logout_pools(db)
|
def logout_pools(db)
|
||||||
primary_pool.logout_existing(db)
|
if primary_pool
|
||||||
|
primary_pool.logout_existing(db)
|
||||||
|
end
|
||||||
secondary_pools.each do |pool|
|
secondary_pools.each do |pool|
|
||||||
pool.logout_existing(db)
|
pool.logout_existing(db)
|
||||||
end
|
end
|
||||||
|
@ -323,6 +327,19 @@ module Mongo
|
||||||
raise ConnectionFailure.new("Could not checkout a socket.")
|
raise ConnectionFailure.new("Could not checkout a socket.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Checkout best available socket by trying primary
|
||||||
|
# pool first and then falling back to secondary.
|
||||||
|
def checkout_best
|
||||||
|
checkout do
|
||||||
|
socket = get_socket_from_pool(:primary)
|
||||||
|
if !socket
|
||||||
|
connect
|
||||||
|
socket = get_socket_from_pool(:secondary)
|
||||||
|
end
|
||||||
|
socket
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Checkout a socket for reading (i.e., a secondary node).
|
# Checkout a socket for reading (i.e., a secondary node).
|
||||||
# Note that @read_pool might point to the primary pool
|
# Note that @read_pool might point to the primary pool
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||||
require './test/test_helper'
|
require './test/test_helper'
|
||||||
require './test/tools/auth_repl_set_manager'
|
require './test/tools/auth_repl_set_manager'
|
||||||
|
require './test/replica_sets/rs_test_helper'
|
||||||
|
|
||||||
class AuthTest < Test::Unit::TestCase
|
class AuthTest < Test::Unit::TestCase
|
||||||
include Mongo
|
include Mongo
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@manager = AuthReplSetManager.new(:start_port => 40000)
|
@rs = AuthReplSetManager.new(:start_port => 40000)
|
||||||
@manager.start_set
|
@rs.start_set
|
||||||
end
|
end
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
@manager.cleanup_set
|
#@rs.cleanup_set
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_repl_set_auth
|
def test_repl_set_auth
|
||||||
@conn = ReplSetConnection.new(build_seeds(3), :name => @manager.name)
|
@conn = ReplSetConnection.new(build_seeds(3), :name => @rs.name)
|
||||||
|
|
||||||
# Add an admin user
|
# Add an admin user
|
||||||
@conn['admin'].add_user("me", "secret")
|
@conn['admin'].add_user("me", "secret")
|
||||||
|
@ -51,7 +52,20 @@ class AuthTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
# But not when authenticated
|
# But not when authenticated
|
||||||
@slave1['admin'].authenticate("me", "secret")
|
assert @slave1['admin'].authenticate("me", "secret")
|
||||||
assert @slave1['foo']['stuff'].find_one
|
assert @slave1['foo']['stuff'].find_one
|
||||||
|
|
||||||
|
# Same should apply when using :secondary_only
|
||||||
|
@second_only = ReplSetConnection.new(build_seeds(3),
|
||||||
|
:require_primary => false, :read => :secondary_only)
|
||||||
|
|
||||||
|
# Find should fail
|
||||||
|
assert_raise_error Mongo::OperationFailure, "unauthorized" do
|
||||||
|
@second_only['foo']['stuff'].find_one
|
||||||
|
end
|
||||||
|
|
||||||
|
# But not when authenticated
|
||||||
|
assert @second_only['admin'].authenticate("me", "secret")
|
||||||
|
assert @second_only['foo']['stuff'].find_one
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue