Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-1102

Driver doesn't handle DNS round-robin names

    • Type: Icon: New Feature New Feature
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 12_01_17
    • Affects Version/s: 1.12.5
    • Component/s: None
    • None
    • Environment:
      Linux tested with JRuby
    • Fully Compatible

      Given how the Mongo::URIParser class works, it is currently not possible to provide a single URI like mongodb://foo/bar, where foo is a DNS round-robin name (i.e. with multiple IP addresses) and use this for load balancing/replica set connections.

      (This kind of configuration is convenient, to avoid having to explicitly list all host names in the replica set in the client config. Instead, it is managed by the DNS and can even be made HA with the proper DNS software etc. If the number of applications using a given Mongo replica set is large, not having to reconfigure them all whenever adding/removing nodes from the replica set is seen as preferable.)

      This patch fixes this. Since we are using an older, existing application infrastructure I've only done it towards the 1.x branch; we are not using the 2.x branch yet. Hopefully, it should't be too much work to rebase this on top of the current master.

      Below is the diff:

      diff --git a/lib/mongo/functional/uri_parser.rb b/lib/mongo/functional/uri_parser.rb
      index 9a1cd0f..af97d50 100644
      — a/lib/mongo/functional/uri_parser.rb
      +++ b/lib/mongo/functional/uri_parser.rb
      @@ -13,6 +13,7 @@

      1. limitations under the License.

      require 'cgi'
      +require 'resolv'
      require 'uri'

      module Mongo
      @@ -322,6 +323,8 @@ module Mongo
      "least one node."
      end

      + @nodes = resolve_dns_aliases(@nodes)
      +

      1. no user info to parse, exit here
        return unless user_info

      @@ -405,5 +408,23 @@ module Mongo
      raise MongoArgumentError, "connect=direct conflicts with setting a replicaset name"
      end
      end
      +
      + def resolve_dns_aliases(nodes)
      + resolver = Resolv::DNS.new
      + resolved_nodes = nodes.map { |node|
      + host, port = *node
      + addresses = resolver.getaddresses(host)
      +
      + if addresses.empty? || addresses.count == 1
      + [node]
      + else
      + addresses.map

      { |address| + [address.to_s, port] + }

      + end
      + }.flatten(1)
      +
      + resolved_nodes
      + end
      end
      end

            Assignee:
            emily.stolfo Emily Stolfo
            Reporter:
            perlundberg Per Lundberg
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: