Skip to content

Commit 1cae417

Browse files
Merge pull request #12821 from rabbitmq/rabbitmq-server-12776
Definition export: inject default queue type into virtual host metadata
2 parents d95b2ca + f377e8f commit 1cae417

File tree

11 files changed

+357
-64
lines changed

11 files changed

+357
-64
lines changed

deps/rabbit/src/rabbit_definitions.erl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,10 +1071,13 @@ list_vhosts() ->
10711071
[vhost_definition(V) || V <- rabbit_vhost:all()].
10721072

10731073
vhost_definition(VHost) ->
1074+
Name = vhost:get_name(VHost),
1075+
DQT = rabbit_queue_type:short_alias_of(rabbit_vhost:default_queue_type(Name)),
10741076
#{
1075-
<<"name">> => vhost:get_name(VHost),
1077+
<<"name">> => Name,
10761078
<<"limits">> => vhost:get_limits(VHost),
1077-
<<"metadata">> => vhost:get_metadata(VHost)
1079+
<<"metadata">> => vhost:get_metadata(VHost),
1080+
<<"default_queue_type">> => DQT
10781081
}.
10791082

10801083
list_users() ->

deps/rabbit/src/rabbit_queue_type.erl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
-behaviour(rabbit_registry_class).
1212

1313
-include("amqqueue.hrl").
14+
-include("vhost.hrl").
1415
-include_lib("rabbit_common/include/rabbit.hrl").
1516
-include_lib("amqp10_common/include/amqp10_types.hrl").
1617

@@ -22,7 +23,10 @@
2223
feature_flag_name/1,
2324
to_binary/1,
2425
default/0,
26+
default_alias/0,
2527
fallback/0,
28+
inject_dqt/1,
29+
vhosts_with_dqt/1,
2630
is_enabled/1,
2731
is_compatible/4,
2832
declare/2,
@@ -319,6 +323,15 @@ short_alias_of(rabbit_stream_queue) ->
319323
%% AMQP 1.0 management client
320324
short_alias_of({utf8, <<"stream">>}) ->
321325
<<"stream">>;
326+
%% for cases where this function is used for
327+
%% formatting of values that already might use these
328+
%% short aliases
329+
short_alias_of(<<"quorum">>) ->
330+
<<"quorum">>;
331+
short_alias_of(<<"classic">>) ->
332+
<<"classic">>;
333+
short_alias_of(<<"stream">>) ->
334+
<<"stream">>;
322335
short_alias_of(_Other) ->
323336
undefined.
324337

@@ -345,6 +358,10 @@ default() ->
345358
fallback()),
346359
rabbit_data_coercion:to_atom(V).
347360

361+
-spec default_alias() -> binary().
362+
default_alias() ->
363+
short_alias_of(default()).
364+
348365
-spec to_binary(module()) -> binary().
349366
to_binary(rabbit_classic_queue) ->
350367
<<"classic">>;
@@ -841,6 +858,29 @@ known_queue_type_names() ->
841858
QTypeBins = lists:map(fun(X) -> atom_to_binary(X) end, QueueTypes),
842859
?KNOWN_QUEUE_TYPES ++ QTypeBins.
843860

861+
inject_dqt(VHost) when ?is_vhost(VHost) ->
862+
inject_dqt(vhost:to_map(VHost));
863+
inject_dqt(VHost) when is_list(VHost) ->
864+
inject_dqt(rabbit_data_coercion:to_map(VHost));
865+
inject_dqt(M = #{default_queue_type := undefined}) ->
866+
NQT = short_alias_of(default()),
867+
Meta0 = maps:get(metadata, M, #{}),
868+
Meta = Meta0#{default_queue_type => NQT},
869+
870+
M#{default_queue_type => NQT, metadata => Meta};
871+
inject_dqt(M = #{default_queue_type := DQT}) ->
872+
NQT = short_alias_of(DQT),
873+
Meta0 = maps:get(metadata, M, #{}),
874+
Meta = Meta0#{default_queue_type => NQT},
875+
876+
M#{default_queue_type => NQT, metadata => Meta}.
877+
878+
-spec vhosts_with_dqt([any()]) -> [map()].
879+
vhosts_with_dqt(List) when is_list(List) ->
880+
%% inject DQT (default queue type) at the top level and
881+
%% its metadata
882+
lists:map(fun inject_dqt/1, List).
883+
844884
-spec check_queue_limits(amqqueue:amqqueue()) ->
845885
ok |
846886
{error, queue_limit_exceeded, Reason :: string(), Args :: term()}.

deps/rabbit/src/rabbit_vhost.erl

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -511,13 +511,14 @@ default_queue_type(VirtualHost) ->
511511
default_queue_type(VirtualHost, rabbit_queue_type:fallback()).
512512
-spec default_queue_type(VirtualHost :: vhost:name(), Fallback :: rabbit_queue_type:queue_type()) -> rabbit_queue_type:queue_type().
513513
default_queue_type(VirtualHost, FallbackQueueType) ->
514+
NodeDefault = application:get_env(rabbit, default_queue_type, FallbackQueueType),
514515
case exists(VirtualHost) of
515-
false -> FallbackQueueType;
516+
false -> NodeDefault;
516517
true ->
517518
Record = lookup(VirtualHost),
518519
case vhost:get_default_queue_type(Record) of
519-
undefined -> FallbackQueueType;
520-
<<"undefined">> -> FallbackQueueType;
520+
undefined -> NodeDefault;
521+
<<"undefined">> -> NodeDefault;
521522
Type -> Type
522523
end
523524
end.
@@ -622,8 +623,19 @@ i(tracing, VHost) -> rabbit_trace:enabled(vhost:get_name(VHost));
622623
i(cluster_state, VHost) -> vhost_cluster_state(vhost:get_name(VHost));
623624
i(description, VHost) -> vhost:get_description(VHost);
624625
i(tags, VHost) -> vhost:get_tags(VHost);
625-
i(default_queue_type, VHost) -> vhost:get_default_queue_type(VHost);
626-
i(metadata, VHost) -> vhost:get_metadata(VHost);
626+
i(default_queue_type, VHost) -> rabbit_queue_type:short_alias_of(default_queue_type(vhost:get_name(VHost)));
627+
i(metadata, VHost) ->
628+
DQT = rabbit_queue_type:short_alias_of(default_queue_type(vhost:get_name(VHost))),
629+
case vhost:get_metadata(VHost) of
630+
undefined ->
631+
#{default_queue_type => DQT};
632+
M = #{default_queue_type := undefined} ->
633+
M#{default_queue_type => DQT};
634+
M = #{default_queue_type := QT} ->
635+
M#{default_queue_type => rabbit_queue_type:short_alias_of(QT)};
636+
M when is_map(M) ->
637+
M#{default_queue_type => DQT}
638+
end;
627639
i(Item, VHost) ->
628640
rabbit_log:error("Don't know how to compute a virtual host info item '~ts' for virtual host '~tp'", [Item, VHost]),
629641
throw({bad_argument, Item}).

deps/rabbit/src/vhost.erl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@
2626
get_description/1,
2727
get_tags/1,
2828
get_default_queue_type/1,
29+
2930
set_limits/2,
3031
set_metadata/2,
3132
merge_metadata/2,
3233
new_metadata/3,
33-
is_tagged_with/2
34+
is_tagged_with/2,
35+
36+
to_map/1
3437
]).
3538

3639
-define(record_version, vhost_v2).
@@ -196,3 +199,13 @@ new_metadata(Description, Tags, DefaultQueueType) ->
196199
-spec is_tagged_with(vhost(), tag()) -> boolean().
197200
is_tagged_with(VHost, Tag) ->
198201
lists:member(Tag, get_tags(VHost)).
202+
203+
-spec to_map(vhost()) -> map().
204+
to_map(VHost) ->
205+
#{
206+
name => get_name(VHost),
207+
description => get_description(VHost),
208+
tags => get_tags(VHost),
209+
default_queue_type => get_default_queue_type(VHost),
210+
metadata => get_metadata(VHost)
211+
}.

deps/rabbitmq_cli/lib/rabbitmq/cli/ctl/commands/export_definitions_command.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## License, v. 2.0. If a copy of the MPL was not distributed with this
33
## file, You can obtain one at https://mozilla.org/MPL/2.0/.
44
##
5-
## Copyright (c) 2007-2023 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
5+
## Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
66

77
defmodule RabbitMQ.CLI.Ctl.Commands.ExportDefinitionsCommand do
88
alias RabbitMQ.CLI.Core.{DocGuide, ExitCodes, Helpers}

deps/rabbitmq_cli/lib/rabbitmq/cli/ctl/commands/list_vhosts_command.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostsCommand do
1919
use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout
2020

2121
def merge_defaults([], opts) do
22+
# this default historically benefits those who script using 'rabbitmqctl list_vhosts',
23+
# adding more fields here would break scripts but be more useful to a human reader. MK.
2224
merge_defaults(["name"], opts)
2325
end
2426

deps/rabbitmq_ct_helpers/src/rabbit_ct_broker_helpers.erl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
add_vhost/2,
112112
add_vhost/3,
113113
add_vhost/4,
114+
update_vhost_metadata/3,
114115
delete_vhost/2,
115116
delete_vhost/3,
116117
delete_vhost/4,
@@ -1602,6 +1603,9 @@ add_vhost(Config, Node, VHost) ->
16021603
add_vhost(Config, Node, VHost, Username) ->
16031604
catch rpc(Config, Node, rabbit_vhost, add, [VHost, Username]).
16041605

1606+
update_vhost_metadata(Config, VHost, Meta) ->
1607+
catch rpc(Config, 0, rabbit_vhost, update_metadata, [VHost, Meta, <<"acting-user">>]).
1608+
16051609
delete_vhost(Config, VHost) ->
16061610
delete_vhost(Config, 0, VHost).
16071611

deps/rabbitmq_management/src/rabbit_mgmt_wm_definitions.erl

Lines changed: 83 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -58,30 +58,39 @@ all_definitions(ReqData, Context) ->
5858
Vsn = rabbit:base_product_version(),
5959
ProductName = rabbit:product_name(),
6060
ProductVersion = rabbit:product_version(),
61-
rabbit_mgmt_util:reply(
62-
[{rabbit_version, rabbit_data_coercion:to_binary(Vsn)},
63-
{rabbitmq_version, rabbit_data_coercion:to_binary(Vsn)},
64-
{product_name, rabbit_data_coercion:to_binary(ProductName)},
65-
{product_version, rabbit_data_coercion:to_binary(ProductVersion)}] ++
66-
retain_whitelisted(
67-
[{users, rabbit_mgmt_wm_users:users(all)},
68-
{vhosts, rabbit_mgmt_wm_vhosts:basic()},
69-
{permissions, rabbit_mgmt_wm_permissions:permissions()},
70-
{topic_permissions, rabbit_mgmt_wm_topic_permissions:topic_permissions()},
71-
{parameters, rabbit_mgmt_wm_parameters:basic(ReqData)},
72-
{global_parameters, rabbit_mgmt_wm_global_parameters:basic()},
73-
{policies, rabbit_mgmt_wm_policies:basic(ReqData)},
74-
{queues, Qs},
75-
{exchanges, Xs},
76-
{bindings, Bs}]),
77-
case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
78-
undefined -> ReqData;
79-
Filename -> rabbit_mgmt_util:set_resp_header(
80-
<<"Content-Disposition">>,
81-
"attachment; filename=" ++
82-
binary_to_list(Filename), ReqData)
83-
end,
84-
Context).
61+
62+
Contents = [
63+
{users, rabbit_mgmt_wm_users:users(all)},
64+
{vhosts, rabbit_mgmt_wm_vhosts:basic()},
65+
{permissions, rabbit_mgmt_wm_permissions:permissions()},
66+
{topic_permissions, rabbit_mgmt_wm_topic_permissions:topic_permissions()},
67+
{parameters, rabbit_mgmt_wm_parameters:basic(ReqData)},
68+
{global_parameters, rabbit_mgmt_wm_global_parameters:basic()},
69+
{policies, rabbit_mgmt_wm_policies:basic(ReqData)},
70+
{queues, Qs},
71+
{exchanges, Xs},
72+
{bindings, Bs}
73+
],
74+
75+
TopLevelDefsAndMetadata = [
76+
{rabbit_version, rabbit_data_coercion:to_binary(Vsn)},
77+
{rabbitmq_version, rabbit_data_coercion:to_binary(Vsn)},
78+
{product_name, rabbit_data_coercion:to_binary(ProductName)},
79+
{product_version, rabbit_data_coercion:to_binary(ProductVersion)},
80+
{rabbitmq_definition_format, <<"cluster">>},
81+
{original_cluster_name, rabbit_nodes:cluster_name()},
82+
{explanation, rabbit_data_coercion:to_binary(io_lib:format("Definitions of cluster '~ts'", [rabbit_nodes:cluster_name()]))}
83+
],
84+
Result = TopLevelDefsAndMetadata ++ retain_whitelisted(Contents),
85+
ReqData1 = case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
86+
undefined -> ReqData;
87+
Filename -> rabbit_mgmt_util:set_resp_header(
88+
<<"Content-Disposition">>,
89+
"attachment; filename=" ++
90+
binary_to_list(Filename), ReqData)
91+
end,
92+
93+
rabbit_mgmt_util:reply(Result, ReqData1, Context).
8594

8695
accept_json(ReqData0, Context) ->
8796
BodySizeLimit = application:get_env(rabbitmq_management, max_http_body_size, ?MANAGEMENT_DEFAULT_HTTP_MAX_BODY_SIZE),
@@ -94,7 +103,10 @@ accept_json(ReqData0, Context) ->
94103
accept(Body, ReqData, Context)
95104
end.
96105

97-
vhost_definitions(ReqData, VHost, Context) ->
106+
vhost_definitions(ReqData, VHostName, Context) ->
107+
%% the existence of this virtual host is verified in the called, 'to_json/2'
108+
VHost = rabbit_vhost:lookup(VHostName),
109+
98110
%% rabbit_mgmt_wm_<>:basic/1 filters by VHost if it is available.
99111
%% TODO: should we stop stripping virtual host? Such files cannot be imported on boot, for example.
100112
Xs = [strip_vhost(X) || X <- rabbit_mgmt_wm_exchanges:basic(ReqData),
@@ -105,25 +117,48 @@ vhost_definitions(ReqData, VHost, Context) ->
105117
%% TODO: should we stop stripping virtual host? Such files cannot be imported on boot, for example.
106118
Bs = [strip_vhost(B) || B <- rabbit_mgmt_wm_bindings:basic(ReqData),
107119
export_binding(B, QNames)],
108-
{ok, Vsn} = application:get_key(rabbit, vsn),
109120
Parameters = [strip_vhost(
110121
rabbit_mgmt_format:parameter(P))
111-
|| P <- rabbit_runtime_parameters:list(VHost)],
112-
rabbit_mgmt_util:reply(
113-
[{rabbit_version, rabbit_data_coercion:to_binary(Vsn)}] ++
114-
retain_whitelisted(
115-
[{parameters, Parameters},
116-
{policies, [strip_vhost(P) || P <- rabbit_mgmt_wm_policies:basic(ReqData)]},
117-
{queues, Qs},
118-
{exchanges, Xs},
119-
{bindings, Bs}]),
120-
case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
121-
undefined -> ReqData;
122-
Filename ->
123-
HeaderVal = "attachment; filename=" ++ binary_to_list(Filename),
124-
rabbit_mgmt_util:set_resp_header(<<"Content-Disposition">>, HeaderVal, ReqData)
125-
end,
126-
Context).
122+
|| P <- rabbit_runtime_parameters:list(VHostName)],
123+
Contents = [
124+
{parameters, Parameters},
125+
{policies, [strip_vhost(P) || P <- rabbit_mgmt_wm_policies:basic(ReqData)]},
126+
{queues, Qs},
127+
{exchanges, Xs},
128+
{bindings, Bs}
129+
],
130+
131+
Vsn = rabbit:base_product_version(),
132+
ProductName = rabbit:product_name(),
133+
ProductVersion = rabbit:product_version(),
134+
135+
DQT = rabbit_queue_type:short_alias_of(rabbit_vhost:default_queue_type(VHostName)),
136+
%% note: the type changes to a map
137+
VHost1 = rabbit_queue_type:inject_dqt(VHost),
138+
Metadata = maps:get(metadata, VHost1),
139+
140+
TopLevelDefsAndMetadata = [
141+
{rabbit_version, rabbit_data_coercion:to_binary(Vsn)},
142+
{rabbitmq_version, rabbit_data_coercion:to_binary(Vsn)},
143+
{product_name, rabbit_data_coercion:to_binary(ProductName)},
144+
{product_version, rabbit_data_coercion:to_binary(ProductVersion)},
145+
{rabbitmq_definition_format, <<"single_virtual_host">>},
146+
{original_vhost_name, VHostName},
147+
{explanation, rabbit_data_coercion:to_binary(io_lib:format("Definitions of virtual host '~ts'", [VHostName]))},
148+
{metadata, Metadata},
149+
{description, vhost:get_description(VHost)},
150+
{default_queue_type, DQT},
151+
{limits, vhost:get_limits(VHost)}
152+
],
153+
Result = TopLevelDefsAndMetadata ++ retain_whitelisted(Contents),
154+
155+
ReqData1 = case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
156+
undefined -> ReqData;
157+
Filename ->
158+
HeaderVal = "attachment; filename=" ++ binary_to_list(Filename),
159+
rabbit_mgmt_util:set_resp_header(<<"Content-Disposition">>, HeaderVal, ReqData)
160+
end,
161+
rabbit_mgmt_util:reply(Result, ReqData1, Context).
127162

128163
accept_multipart(ReqData0, Context) ->
129164
{Parts, ReqData} = get_all_parts(ReqData0),
@@ -271,7 +306,12 @@ retain_whitelisted(Items) ->
271306
retain_whitelisted_items(Name, List, Allowed) ->
272307
{Name, [only_whitelisted_for_item(I, Allowed) || I <- List]}.
273308

274-
only_whitelisted_for_item(Item, Allowed) ->
309+
only_whitelisted_for_item(Item, Allowed) when is_map(Item) ->
310+
Map1 = maps:with(Allowed, Item),
311+
maps:filter(fun(_Key, Val) ->
312+
Val =/= undefined
313+
end, Map1);
314+
only_whitelisted_for_item(Item, Allowed) when is_list(Item) ->
275315
[{K, Fact} || {K, Fact} <- Item, lists:member(K, Allowed), Fact =/= undefined].
276316

277317
strip_vhost(Item) ->

deps/rabbitmq_management/src/rabbit_mgmt_wm_overview.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ to_json(ReqData, Context = #context{user = User = #user{tags = Tags}}) ->
5252
{erlang_version, erlang_version()},
5353
{erlang_full_version, erlang_full_version()},
5454
{disable_stats, rabbit_mgmt_util:disable_stats(ReqData)},
55+
{default_queue_type, rabbit_queue_type:default_alias()},
5556
{is_op_policy_updating_enabled, not rabbit_mgmt_features:is_op_policy_updating_disabled()},
5657
{enable_queue_totals, rabbit_mgmt_util:enable_queue_totals(ReqData)}],
5758
try

deps/rabbitmq_management/src/rabbit_mgmt_wm_vhosts.erl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ to_json(ReqData, Context = #context{user = User}) ->
3131
try
3232
Basic = [rabbit_vhost:info(V)
3333
|| V <- rabbit_mgmt_util:list_visible_vhosts(User)],
34-
Data = rabbit_mgmt_util:augment_resources(Basic, ?DEFAULT_SORT,
35-
?BASIC_COLUMNS, ReqData,
36-
Context, fun augment/2),
34+
Augmented = rabbit_mgmt_util:augment_resources(Basic, ?DEFAULT_SORT,
35+
?BASIC_COLUMNS, ReqData,
36+
Context, fun augment/2),
37+
%% inject default DQT into virtual host metadata,
38+
%% where necessary
39+
Data = rabbit_queue_type:vhosts_with_dqt(Augmented),
3740
rabbit_mgmt_util:reply(Data, ReqData, Context)
3841
catch
3942
{error, invalid_range_parameters, Reason} ->
@@ -64,4 +67,7 @@ augmented(ReqData, #context{user = User}) ->
6467
end.
6568

6669
basic() ->
67-
rabbit_vhost:info_all([name, description, tags, default_queue_type, metadata]).
70+
Maps = lists:map(
71+
fun maps:from_list/1,
72+
rabbit_vhost:info_all([name, description, tags, default_queue_type, metadata])),
73+
rabbit_queue_type:vhosts_with_dqt(Maps).

0 commit comments

Comments
 (0)