Skip to content

Commit 9aa0596

Browse files
Merge pull request #11450 from rabbitmq/mergify/bp/v3.13.x/pr-11449
peer_discovery_tmp_hidden_node_SUITE: Use IP address to simulate a ng node name (backport #11449)
2 parents 2fa8620 + 5a618cf commit 9aa0596

File tree

1 file changed

+20
-113
lines changed

1 file changed

+20
-113
lines changed

deps/rabbit/test/peer_discovery_tmp_hidden_node_SUITE.erl

Lines changed: 20 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -221,134 +221,41 @@ start_test_nodes(Testcase, NodeNumber, NodeCount, PeerOptions, Peers)
221221
when NodeNumber =< NodeCount ->
222222
PeerName0 = rabbit_misc:format("~s-~b", [Testcase, NodeNumber]),
223223
PeerOptions1 = PeerOptions#{name => PeerName0},
224-
ct:pal("Starting peer with options: ~p", [PeerOptions1]),
225-
case catch peer:start(PeerOptions1) of
224+
PeerOptions2 = case PeerOptions1 of
225+
#{host := _} ->
226+
PeerOptions1;
227+
#{longnames := true} ->
228+
%% To simulate Erlang long node names, we use a
229+
%% hard-coded IP address that is likely to exist.
230+
%%
231+
%% We can't rely on the host proper network
232+
%% configuration because it appears that several
233+
%% hosts are half-configured (at least some random
234+
%% GitHub workers and Broadcom-managed OSX laptops
235+
%% in the team).
236+
PeerOptions1#{host => "127.0.0.1"};
237+
_ ->
238+
PeerOptions1
239+
end,
240+
ct:pal("Starting peer with options: ~p", [PeerOptions2]),
241+
case catch peer:start(PeerOptions2) of
226242
{ok, PeerPid, PeerName} ->
227243
ct:pal("Configuring peer '~ts'", [PeerName]),
228-
setup_test_node(PeerPid, PeerOptions1),
244+
setup_test_node(PeerPid, PeerOptions2),
229245
Peers1 = Peers#{PeerName => PeerPid},
230246
start_test_nodes(
231247
Testcase, NodeNumber + 1, NodeCount, PeerOptions, Peers1);
232-
Error1 when not is_map_key(host, PeerOptions1) ->
233-
ct:pal("Failed to started peer node:~n"
234-
"Options: ~p~n"
235-
"Error: ~p", [PeerOptions1, Error1]),
236-
%% At least when running from a Buildbuddy CI worker, the network
237-
%% configuration is incomplete and the host lacks an FQDN. This
238-
%% breaks the start of an Erlang node with long names.
239-
%%
240-
%% To work around that, we mess with the network configuration (the
241-
%% Erlang node runs as root) and try to determine a hostname we can
242-
%% use. We then try again to start the node.
243-
case determine_hostname(PeerOptions1) of
244-
{ok, Host} ->
245-
PeerOptions2 = PeerOptions1#{host => Host},
246-
start_test_nodes(
247-
Testcase, NodeNumber, NodeCount, PeerOptions2, Peers);
248-
{error, _} = Error2 ->
249-
ct:pal("Failed to determine a usable hostname:~n"
250-
"Options: ~p~n"
251-
"Error: ~p", [PeerOptions1, Error2]),
252-
stop_test_nodes(Peers),
253-
erlang:throw(Error2)
254-
end;
255248
Error ->
256249
ct:pal("Failed to started peer node:~n"
257250
"Options: ~p~n"
258-
"Error: ~p", [PeerOptions1, Error]),
251+
"Error: ~p", [PeerOptions2, Error]),
259252
stop_test_nodes(Peers),
260253
erlang:throw(Error)
261254
end;
262255
start_test_nodes(_Testcase, _NodeNumber, _Count, _PeerOptions, Peers) ->
263256
ct:pal("Peers: ~p", [Peers]),
264257
Peers.
265258

266-
determine_hostname(PeerOptions) ->
267-
%% Please wear eye protection glasses to read what's next!
268-
%%
269-
%% The Buildbuddy CI worker network configuration lacks an FQDN and we need
270-
%% one to start an Erlang node with a long name. To work around this, we
271-
%% modify `/etc/hosts' to add an FQDN for 127.0.0.1 and ::1.
272-
%%
273-
%% 1. We read the existing file
274-
%% 2. We modify it to add the FQDN
275-
%% 3. We write the modified file
276-
%% 4. We put a coin in the swear jar
277-
HostsFilename = "/etc/hosts",
278-
case file:read_file(HostsFilename) of
279-
{ok, HostsFile} ->
280-
HostsFile1 = re:replace(
281-
HostsFile,
282-
"^(127\\.0\\.0\\.1|::1)\\s+.*",
283-
"& localhost.my.domain",
284-
[{return, binary}, multiline, global]),
285-
ct:pal(
286-
"Changing ~s from:~n"
287-
"---8<---~n"
288-
"~s"
289-
"---8<---~n"
290-
"to:~n"
291-
"---8<---~n"
292-
"~s"
293-
"---8<---~n",
294-
[HostsFilename, HostsFile, HostsFile1]),
295-
case file:write_file(HostsFilename, HostsFile1) of
296-
ok -> determine_hostname1(PeerOptions);
297-
{error, _} = Error -> Error
298-
end;
299-
{error, _} = Error ->
300-
Error
301-
end.
302-
303-
determine_hostname1(PeerOptions) ->
304-
%% Now that we proudly have an FQDN, we query the IP
305-
%% addresses and get the hostname(s) associated with each.
306-
%%
307-
%% In the end, we return the first hostname that matches
308-
%% the short/long name criteria.
309-
case inet:getifaddrs() of
310-
{ok, IFaces} ->
311-
ct:pal("Network interfaces: ~p", [IFaces]),
312-
IPv4Addrs = [IPv4Addr
313-
|| {_Name, Props} <- IFaces,
314-
{addr, IPv4Addr} <- Props,
315-
is_tuple(IPv4Addr) andalso size(IPv4Addr) =:= 4],
316-
ct:pal("IPv4 addresses: ~p", [IPv4Addrs]),
317-
determine_hostname2(IPv4Addrs, PeerOptions);
318-
{error, _} = Error ->
319-
Error
320-
end.
321-
322-
determine_hostname2([IPv4Addr | Rest], PeerOptions) ->
323-
WantFQDN = maps:get(longnames, PeerOptions, false),
324-
case inet:gethostbyaddr(IPv4Addr) of
325-
{ok, #hostent{h_name = FQDN, h_aliases = ShortDNs}} ->
326-
AllDNs = [FQDN | ShortDNs],
327-
ct:pal(
328-
"All domain names for IPv4 address ~p: ~p",
329-
[IPv4Addr, AllDNs]),
330-
ValidDNs = lists:filter(
331-
fun(DN) ->
332-
lists:member($., DN) =:= WantFQDN
333-
end, AllDNs),
334-
ct:pal(
335-
"Valid domain names for IPv4 address ~p: ~p",
336-
[IPv4Addr, ValidDNs]),
337-
case ValidDNs of
338-
[DN | _] ->
339-
{ok, DN};
340-
[] ->
341-
ct:pal(
342-
"No valid hostnames found for IPv4 ~p: ~p",
343-
[IPv4Addr, AllDNs]),
344-
determine_hostname2(Rest, PeerOptions)
345-
end;
346-
{error, _} = Error ->
347-
Error
348-
end;
349-
determine_hostname2([], _PeerOptions) ->
350-
{error, no_valid_hostnames_found}.
351-
352259
setup_test_node(PeerPid, PeerOptions) ->
353260
peer:call(PeerPid, ?MODULE, do_setup_test_node, [PeerOptions]).
354261

0 commit comments

Comments
 (0)