6262 env_variable = " AWS_HOSTNAME_PATH" ,
6363 default_value = [" privateDnsName" ]
6464 },
65+ aws_hostname_paths => # peer_discovery_config_entry_meta {
66+ type = list ,
67+ env_variable = " AWS_HOSTNAME_PATHS" ,
68+ default_value = []
69+ },
6570 aws_use_private_ip => # peer_discovery_config_entry_meta {
6671 type = atom ,
6772 env_variable = " AWS_USE_PRIVATE_IP" ,
@@ -318,10 +323,11 @@ get_hostname_name_from_reservation_set([], Accum) -> Accum;
318323get_hostname_name_from_reservation_set ([{" item" , RI }|T ], Accum ) ->
319324 InstancesSet = proplists :get_value (" instancesSet" , RI ),
320325 Items = [Item || {" item" , Item } <- InstancesSet ],
321- HostnamePath = get_hostname_path (),
322- Hostnames = [get_hostname (HostnamePath , Item ) || Item <- Items ],
323- Hostnames2 = [Name || Name <- Hostnames , Name =/= " " ],
324- get_hostname_name_from_reservation_set (T , Accum ++ Hostnames2 ).
326+ HostnamePaths = get_hostname_paths (),
327+ ? LOG_DEBUG (" AWS peer discovery: processing reservation with ~p instances using hostname paths: ~tp " ,
328+ [length (Items ), HostnamePaths ]),
329+ UniqueHostnames = extract_unique_hostnames (HostnamePaths , Items ),
330+ get_hostname_name_from_reservation_set (T , Accum ++ UniqueHostnames ).
325331
326332get_hostname_names (Path ) ->
327333 case rabbitmq_aws :api_get_request (" ec2" , Path ) of
@@ -347,31 +353,69 @@ get_hostname_by_tags(Tags) ->
347353 Names
348354 end .
349355
350- -spec get_hostname_path () -> path ().
351- get_hostname_path () ->
352- UsePrivateIP = get_config_key (aws_use_private_ip , ? CONFIG_MODULE :config_map (? BACKEND_CONFIG_KEY )),
353- HostnamePath = get_config_key (aws_hostname_path , ? CONFIG_MODULE :config_map (? BACKEND_CONFIG_KEY )),
354- FinalPath = case HostnamePath of
355- [" privateDnsName" ] when UsePrivateIP -> [" privateIpAddress" ];
356- P -> P
356+ -spec get_hostname_paths () -> [path ()].
357+ get_hostname_paths () ->
358+ M = ? CONFIG_MODULE :config_map (? BACKEND_CONFIG_KEY ),
359+ UsePrivateIP = get_config_key (aws_use_private_ip , M ),
360+ RawPaths = case get_config_key (aws_hostname_paths , M ) of
361+ Paths when is_list (Paths ), Paths =/= [] ->
362+ ? LOG_DEBUG (" AWS peer discovery using multiple hostname paths" ),
363+ Paths ;
364+ _ ->
365+ % % Use single path configuration (including when Paths is [])
366+ SinglePath = get_single_hostname_path_raw (M ),
367+ ? LOG_DEBUG (" AWS peer discovery using single hostname path" ),
368+ [SinglePath ]
357369 end ,
358- ? LOG_DEBUG (" AWS peer discovery using hostname path: ~tp " , [FinalPath ]),
359- FinalPath .
370+ % % Apply use_private_ip override to all paths consistently
371+ FinalPaths = apply_private_ip_override (RawPaths , UsePrivateIP ),
372+ ? LOG_DEBUG (" AWS peer discovery final hostname paths: ~tp " , [FinalPaths ]),
373+ FinalPaths .
374+
375+ -spec get_single_hostname_path_raw (map ()) -> path ().
376+ get_single_hostname_path_raw (ConfigMap ) ->
377+ case get_config_key (aws_hostname_path , ConfigMap ) of
378+ undefined ->
379+ [" privateDnsName" ];
380+ P ->
381+ P
382+ end .
383+
384+ -spec apply_private_ip_override ([path ()], boolean ()) -> [path ()].
385+ apply_private_ip_override (Paths , UsePrivateIP ) ->
386+ apply_private_ip_override (Paths , UsePrivateIP , []).
387+ apply_private_ip_override ([], _ , Acc ) ->
388+ lists :reverse (Acc );
389+ apply_private_ip_override ([[" privateDnsName" ] | Paths ], true , Acc0 ) ->
390+ Acc1 = [[" privateIpAddress" ] | Acc0 ],
391+ apply_private_ip_override (Paths , true , Acc1 );
392+ apply_private_ip_override ([Path | Paths ], UsePrivateIP , Acc0 ) ->
393+ Acc1 = [Path | Acc0 ],
394+ apply_private_ip_override (Paths , UsePrivateIP , Acc1 ).
360395
361396-spec get_hostname (path (), props ()) -> string ().
397+ get_hostname ([], _Props ) ->
398+ ? LOG_DEBUG (" AWS peer discovery: empty hostname path provided" ),
399+ " " ; % % Handle empty paths gracefully
362400get_hostname (Path , Props ) ->
363401 List = lists :foldl (fun get_value /2 , Props , Path ),
364402 case io_lib :latin1_char_list (List ) of
365- true -> List ;
366- _ -> " "
403+ true ->
404+ ? LOG_DEBUG (" AWS peer discovery: extracted hostname '~ts ' from path ~tp " , [List , Path ]),
405+ List ;
406+ _ ->
407+ ? LOG_DEBUG (" AWS peer discovery: invalid hostname format from path ~tp , result: ~tp " , [Path , List ]),
408+ " "
367409 end .
368410
369411-spec get_value (string ()|integer (), props ()) -> props ().
370- get_value (_ , []) ->
371- [];
372- get_value (Key , Props ) when is_integer (Key ) ->
373- {" item" , Props2 } = lists :nth (Key , Props ),
374- Props2 ;
412+ get_value (Key , Props ) when is_integer (Key ), is_list (Props ), length (Props ) >= Key , Key > 0 ->
413+ case lists :nth (Key , Props ) of
414+ {" item" , Props2 } -> Props2 ;
415+ _ -> [] % Malformed data
416+ end ;
417+ get_value (Key , _Props ) when is_integer (Key ) ->
418+ []; % Out of bounds or empty list
375419get_value (Key , Props ) ->
376420 Value = proplists :get_value (Key , Props ),
377421 sort_ec2_hostname_path_set_members (Key , Value ).
@@ -413,3 +457,18 @@ get_tags() ->
413457 maps :from_list (Value );
414458 _ -> Tags
415459 end .
460+
461+ % % Helper functions for multiple hostname paths support
462+
463+ -spec extract_unique_hostnames ([path ()], [props ()]) -> [string ()].
464+ extract_unique_hostnames (Paths , Items ) ->
465+ ? LOG_DEBUG (" AWS peer discovery: extracting hostnames using ~p paths for ~p items" ,
466+ [length (Paths ), length (Items )]),
467+ % % Extract all hostnames from all paths for all items
468+ AllHostnames = [get_hostname (Path , Item ) || Path <- Paths , Item <- Items ],
469+ % % Filter out empty hostnames and remove duplicates
470+ ValidHostnames = [Name || Name <- AllHostnames , Name =/= " " ],
471+ UniqueHostnames = lists :uniq (ValidHostnames ),
472+ ? LOG_DEBUG (" AWS peer discovery: extracted ~p total hostnames, ~p valid, ~p unique: ~tp " ,
473+ [length (AllHostnames ), length (ValidHostnames ), length (UniqueHostnames ), UniqueHostnames ]),
474+ UniqueHostnames .
0 commit comments