Skip to content

Commit d7ed718

Browse files
committed
Add support for connecting to nodes by their hostname
1 parent 45973e0 commit d7ed718

File tree

3 files changed

+36
-26
lines changed

3 files changed

+36
-26
lines changed

lib/dns_cluster.ex

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ defmodule DNSCluster do
5151
differs between nodes, a tuple of `{basename, query}` can be provided as well.
5252
The value `:ignore` can be used to ignore starting the DNSCluster.
5353
* `:resource_types` - the resource record types that are used for node discovery.
54-
Defaults to `[:a, :aaaa]` and also supports the `:srv` type.
54+
Defaults to `[:a, :aaaa]` and also supports `:srv_ips`, `:srv_hostnames` and
55+
`:srv` (deprecated) type.
5556
* `:interval` - the millisec interval between DNS queries. Defaults to `5000`.
5657
* `:connect_timeout` - the millisec timeout to allow discovered nodes to connect.
5758
Defaults to `10_000`.
@@ -68,7 +69,7 @@ defmodule DNSCluster do
6869
GenServer.start_link(__MODULE__, opts, name: Keyword.get(opts, :name, __MODULE__))
6970
end
7071

71-
@valid_resource_types [:a, :aaaa, :srv]
72+
@valid_resource_types [:a, :aaaa, :srv, :srv_ips, :srv_hostnames]
7273

7374
@impl true
7475
def init(opts) do
@@ -161,7 +162,10 @@ defmodule DNSCluster do
161162
{basename, addr}
162163
end
163164
|> Enum.uniq()
164-
|> Enum.map(fn {basename, addr} -> {basename, to_string(:inet.ntoa(addr))} end)
165+
|> Enum.map(fn
166+
{basename, ip} when is_tuple(ip) -> {basename, to_string(:inet.ntoa(ip))}
167+
{basename, hostname} -> {basename, hostname}
168+
end)
165169
end
166170

167171
defp basename_from_query_or_state({basename, _query}, _state), do: basename
@@ -186,7 +190,7 @@ defmodule DNSCluster do
186190
defp validate_resource_types!(resource_types) do
187191
if resource_types == [] or resource_types -- @valid_resource_types != [] do
188192
raise ArgumentError,
189-
"expected :resource_types to be a subset of [:a, :aaaa, :srv], got: #{inspect(resource_types)}"
193+
"expected :resource_types to be a subset of #{inspect(@valid_resource_types)}, got: #{inspect(resource_types)}"
190194
end
191195
end
192196

lib/dns_cluster/resolver.ex

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,34 @@ defmodule DNSCluster.Resolver do
1313

1414
def list_nodes, do: Node.list(:visible)
1515

16-
def lookup(query, type) when is_binary(query) and type in [:a, :aaaa] do
17-
case :inet_res.getbyname(~c"#{query}", type) do
18-
{:ok, hostent(h_addr_list: addr_list)} -> addr_list
19-
{:error, _} -> []
20-
end
16+
def lookup(query, :srv_hostnames = _resource_type), do: lookup_by_name(query, :srv)
17+
18+
def lookup(query, resource_type) when resource_type in [:srv, :srv_ips] do
19+
query
20+
|> lookup_by_name(:srv)
21+
|> Enum.flat_map(&lookup_host_by_name/1)
2122
end
2223

23-
def lookup(query, type) when is_binary(query) and type in [:srv] do
24-
case :inet_res.getbyname(~c"#{query}", type) do
25-
{:ok, hostent(h_addr_list: srv_list)} ->
26-
lookup_hosts(srv_list)
24+
def lookup(query, resource_type), do: lookup_by_name(query, resource_type)
2725

28-
{:error, _} ->
26+
defp lookup_by_name(query, resource_type) do
27+
case :inet_res.getbyname(~c"#{query}", resource_type) do
28+
{:ok, hostent(h_addr_list: addr_list)} ->
29+
if resource_type == :srv do
30+
Enum.map(addr_list, fn {_prio, _weight, _port, address} -> address end)
31+
else
32+
addr_list
33+
end
34+
35+
{:error, _reason} ->
2936
[]
3037
end
3138
end
3239

33-
defp lookup_hosts(srv_list) do
34-
srv_list
35-
|> Enum.flat_map(fn {_prio, _weight, _port, host_name} ->
36-
case :inet.gethostbyname(host_name) do
37-
{:ok, hostent(h_addr_list: addr_list)} -> addr_list
38-
{:error, _} -> []
39-
end
40-
end)
40+
defp lookup_host_by_name(query) do
41+
case :inet_res.gethostbyname(query) do
42+
{:ok, hostent(h_addr_list: addr_list)} -> addr_list
43+
{:error, _reason} -> []
44+
end
4145
end
4246
end

test/dns_cluster_test.exs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ defmodule DNSClusterTest do
141141
end
142142

143143
describe "resource_types" do
144-
test "resource_types can be a subset of [:a, :aaaa, :srv]", config do
144+
test "resource_types can be a subset of [:a, :aaaa, :srv, :srv_ips, :srv_hostnames]",
145+
config do
145146
assert {:ok, _cluster} =
146147
start_supervised(
147148
{DNSCluster,
@@ -152,9 +153,10 @@ defmodule DNSClusterTest do
152153
)
153154
end
154155

155-
test "resource_types can't be outside of [:a, :aaaa, :srv]", config do
156+
test "resource_types can't be outside of [:a, :aaaa, :srv, :srv_ips, :srv_hostnames]",
157+
config do
156158
assert_raise RuntimeError,
157-
~r/expected :resource_types to be a subset of \[:a, :aaaa, :srv\]/,
159+
~r/expected :resource_types to be a subset of \[:a, :aaaa, :srv, :srv_ips, :srv_hostnames\]/,
158160
fn ->
159161
start_supervised!(
160162
{DNSCluster,
@@ -168,7 +170,7 @@ defmodule DNSClusterTest do
168170

169171
test "resource_types can't be empty", config do
170172
assert_raise RuntimeError,
171-
~r/expected :resource_types to be a subset of \[:a, :aaaa, :srv\]/,
173+
~r/expected :resource_types to be a subset of \[:a, :aaaa, :srv, :srv_ips, :srv_hostnames\]/,
172174
fn ->
173175
start_supervised!(
174176
{DNSCluster,

0 commit comments

Comments
 (0)