Skip to content

Commit 31af08a

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

File tree

3 files changed

+39
-26
lines changed

3 files changed

+39
-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` (same as `{:srv, :ips}`) 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: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,37 @@ 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}), do: lookup_by_name(query, :srv)
17+
def lookup(query, {:srv, :ips}), do: lookup(query, :srv)
18+
19+
def lookup(query, :srv) do
20+
query
21+
|> lookup_by_name(:srv)
22+
|> Enum.flat_map(&lookup_host_by_name/1)
2123
end
2224

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)
25+
def lookup(query, resource_type) when resource_type in [:a, :aaaa] do
26+
lookup_by_name(query, resource_type)
27+
end
2728

28-
{:error, _} ->
29+
defp lookup_by_name(query, resource_type) do
30+
case :inet_res.getbyname(~c"#{query}", resource_type) do
31+
{:ok, hostent(h_addr_list: addr_list)} ->
32+
if resource_type == :srv do
33+
for {_prio, _weight, _port, address} <- addr_list, do: address
34+
else
35+
addr_list
36+
end
37+
38+
{:error, _reason} ->
2939
[]
3040
end
3141
end
3242

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)
43+
defp lookup_host_by_name(query) do
44+
case :inet_res.gethostbyname(query) do
45+
{:ok, hostent(h_addr_list: addr_list)} -> addr_list
46+
{:error, _reason} -> []
47+
end
4148
end
4249
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)