Skip to content

Commit

Permalink
Rework virtual host-specific definition export
Browse files Browse the repository at this point in the history
1. Add more metadata, see #12835
2. Include DQT

Closes #12835

(cherry picked from commit 48a1660)
  • Loading branch information
michaelklishin authored and mergify[bot] committed Nov 27, 2024
1 parent 8c0e23b commit 204ac01
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 48 deletions.
112 changes: 70 additions & 42 deletions deps/rabbitmq_management/src/rabbit_mgmt_wm_definitions.erl
Original file line number Diff line number Diff line change
Expand Up @@ -58,30 +58,39 @@ all_definitions(ReqData, Context) ->
Vsn = rabbit:base_product_version(),
ProductName = rabbit:product_name(),
ProductVersion = rabbit:product_version(),
rabbit_mgmt_util:reply(
[{rabbit_version, rabbit_data_coercion:to_binary(Vsn)},
{rabbitmq_version, rabbit_data_coercion:to_binary(Vsn)},
{product_name, rabbit_data_coercion:to_binary(ProductName)},
{product_version, rabbit_data_coercion:to_binary(ProductVersion)}] ++
retain_whitelisted(
[{users, rabbit_mgmt_wm_users:users(all)},
{vhosts, rabbit_mgmt_wm_vhosts:basic()},
{permissions, rabbit_mgmt_wm_permissions:permissions()},
{topic_permissions, rabbit_mgmt_wm_topic_permissions:topic_permissions()},
{parameters, rabbit_mgmt_wm_parameters:basic(ReqData)},
{global_parameters, rabbit_mgmt_wm_global_parameters:basic()},
{policies, rabbit_mgmt_wm_policies:basic(ReqData)},
{queues, Qs},
{exchanges, Xs},
{bindings, Bs}]),
case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
undefined -> ReqData;
Filename -> rabbit_mgmt_util:set_resp_header(
<<"Content-Disposition">>,
"attachment; filename=" ++
binary_to_list(Filename), ReqData)
end,
Context).

Contents = [
{users, rabbit_mgmt_wm_users:users(all)},
{vhosts, rabbit_mgmt_wm_vhosts:basic()},
{permissions, rabbit_mgmt_wm_permissions:permissions()},
{topic_permissions, rabbit_mgmt_wm_topic_permissions:topic_permissions()},
{parameters, rabbit_mgmt_wm_parameters:basic(ReqData)},
{global_parameters, rabbit_mgmt_wm_global_parameters:basic()},
{policies, rabbit_mgmt_wm_policies:basic(ReqData)},
{queues, Qs},
{exchanges, Xs},
{bindings, Bs}
],

TopLevelDefsAndMetadata = [
{rabbit_version, rabbit_data_coercion:to_binary(Vsn)},
{rabbitmq_version, rabbit_data_coercion:to_binary(Vsn)},
{product_name, rabbit_data_coercion:to_binary(ProductName)},
{product_version, rabbit_data_coercion:to_binary(ProductVersion)},
{rabbitmq_definition_format, <<"cluster">>},
{original_cluster_name, rabbit_nodes:cluster_name()},
{explanation, rabbit_data_coercion:to_binary(io_lib:format("Definitions of cluster '~ts'", [rabbit_nodes:cluster_name()]))}
],
Result = TopLevelDefsAndMetadata ++ retain_whitelisted(Contents),
ReqData1 = case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
undefined -> ReqData;
Filename -> rabbit_mgmt_util:set_resp_header(
<<"Content-Disposition">>,
"attachment; filename=" ++
binary_to_list(Filename), ReqData)
end,

rabbit_mgmt_util:reply(Result, ReqData1, Context).

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

vhost_definitions(ReqData, VHost, Context) ->
vhost_definitions(ReqData, VHostName, Context) ->
%% the existence of this virtual host is verified in the called, 'to_json/2'
VHost = rabbit_vhost:lookup(VHostName),

%% rabbit_mgmt_wm_<>:basic/1 filters by VHost if it is available.
%% TODO: should we stop stripping virtual host? Such files cannot be imported on boot, for example.
Xs = [strip_vhost(X) || X <- rabbit_mgmt_wm_exchanges:basic(ReqData),
Expand All @@ -105,25 +117,41 @@ vhost_definitions(ReqData, VHost, Context) ->
%% TODO: should we stop stripping virtual host? Such files cannot be imported on boot, for example.
Bs = [strip_vhost(B) || B <- rabbit_mgmt_wm_bindings:basic(ReqData),
export_binding(B, QNames)],
{ok, Vsn} = application:get_key(rabbit, vsn),
Parameters = [strip_vhost(
rabbit_mgmt_format:parameter(P))
|| P <- rabbit_runtime_parameters:list(VHost)],
rabbit_mgmt_util:reply(
[{rabbit_version, rabbit_data_coercion:to_binary(Vsn)}] ++
retain_whitelisted(
[{parameters, Parameters},
{policies, [strip_vhost(P) || P <- rabbit_mgmt_wm_policies:basic(ReqData)]},
{queues, Qs},
{exchanges, Xs},
{bindings, Bs}]),
case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
undefined -> ReqData;
Filename ->
HeaderVal = "attachment; filename=" ++ binary_to_list(Filename),
rabbit_mgmt_util:set_resp_header(<<"Content-Disposition">>, HeaderVal, ReqData)
end,
Context).
|| P <- rabbit_runtime_parameters:list(VHostName)],
Contents = [
{parameters, Parameters},
{policies, [strip_vhost(P) || P <- rabbit_mgmt_wm_policies:basic(ReqData)]},
{queues, Qs},
{exchanges, Xs},
{bindings, Bs}
],

Vsn = rabbit:base_product_version(),
ProductName = rabbit:product_name(),
ProductVersion = rabbit:product_version(),

TopLevelDefsAndMetadata = [
{rabbit_version, rabbit_data_coercion:to_binary(Vsn)},
{rabbitmq_version, rabbit_data_coercion:to_binary(Vsn)},
{product_name, rabbit_data_coercion:to_binary(ProductName)},
{product_version, rabbit_data_coercion:to_binary(ProductVersion)},
{rabbitmq_definition_format, <<"single_virtual_host">>},
{original_vhost_name, VHostName},
{explanation, rabbit_data_coercion:to_binary(io_lib:format("Definitions of virtual host '~ts'", [VHostName]))},
{description, vhost:get_description(VHost)},
{default_queue_type, rabbit_queue_type:short_alias_of(rabbit_vhost:default_queue_type(VHostName))}
],
Result = TopLevelDefsAndMetadata ++ retain_whitelisted(Contents),

ReqData1 = case rabbit_mgmt_util:qs_val(<<"download">>, ReqData) of
undefined -> ReqData;
Filename ->
HeaderVal = "attachment; filename=" ++ binary_to_list(Filename),
rabbit_mgmt_util:set_resp_header(<<"Content-Disposition">>, HeaderVal, ReqData)
end,
rabbit_mgmt_util:reply(Result, ReqData1, Context).

accept_multipart(ReqData0, Context) ->
{Parts, ReqData} = get_all_parts(ReqData0),
Expand Down
47 changes: 41 additions & 6 deletions deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ definitions_group1_tests() ->
definitions_group2_tests() ->
[
definitions_default_queue_type_test,
definitions_vhost_metadata_test
definitions_vhost_metadata_test,
definitions_file_metadata_test
].

definitions_group3_tests() ->
Expand Down Expand Up @@ -1940,7 +1941,7 @@ long_definitions_vhosts(long_definitions_multipart_test) ->
definitions_vhost_metadata_test(Config) ->
register_parameters_and_policy_validator(Config),

VHostName = <<"definitions-vhost-metadata-test">>,
VHostName = rabbit_data_coercion:to_binary(?FUNCTION_NAME),
Desc = <<"Created by definitions_vhost_metadata_test">>,
DQT = <<"quorum">>,
Tags = [<<"one">>, <<"tag-two">>],
Expand All @@ -1951,19 +1952,19 @@ definitions_vhost_metadata_test(Config) ->
},

%% Create a test vhost
http_put(Config, "/vhosts/definitions-vhost-metadata-test", Metadata, {group, '2xx'}),
http_put(Config, io_lib:format("/vhosts/~ts", [VHostName]), Metadata, {group, '2xx'}),
PermArgs = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}],
http_put(Config, "/permissions/definitions-vhost-metadata-test/guest", PermArgs, {group, '2xx'}),
http_put(Config, io_lib:format("/permissions/~ts/guest", [VHostName]), PermArgs, {group, '2xx'}),

%% Get the definitions
Definitions = http_get(Config, "/definitions", ?OK),
ct:pal("Exported definitions:~n~tp~tn", [Definitions]),

%% Check if vhost definition is correct
VHosts = maps:get(vhosts, Definitions),
{value, VH} = lists:search(fun(VH) ->
maps:get(name, VH) =:= VHostName
end, VHosts),
ct:pal("VHost: ~p", [VH]),
?assertEqual(#{
name => VHostName,
description => Desc,
Expand All @@ -1976,7 +1977,41 @@ definitions_vhost_metadata_test(Config) ->
http_post(Config, "/definitions", Definitions, {group, '2xx'}),

%% Remove the test vhost
http_delete(Config, "/vhosts/definitions-vhost-metadata-test", {group, '2xx'}),
http_delete(Config, io_lib:format("/vhosts/~ts", [VHostName]), {group, '2xx'}),
ok.

definitions_file_metadata_test(Config) ->
register_parameters_and_policy_validator(Config),

VHostName = rabbit_data_coercion:to_binary(?FUNCTION_NAME),
Desc = <<"Created by definitions_vhost_metadata_test">>,
DQT = <<"quorum">>,
Tags = [<<"tag-one">>, <<"tag-two">>],
Metadata = #{
description => Desc,
default_queue_type => DQT,
tags => Tags
},

http_put(Config, io_lib:format("/vhosts/~ts", [VHostName]), Metadata, {group, '2xx'}),
PermArgs = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}],
http_put(Config, io_lib:format("/permissions/~ts/guest", [VHostName]), PermArgs, {group, '2xx'}),

AllDefinitions = http_get(Config, "/definitions", ?OK),
%% verify definitions file metadata
?assertEqual(<<"cluster">>, maps:get(rabbitmq_definition_format, AllDefinitions)),
?assert(is_binary(maps:get(original_cluster_name, AllDefinitions))),

%% Post the definitions back
http_post(Config, "/definitions", AllDefinitions, {group, '2xx'}),

VHDefinitions = http_get(Config, io_lib:format("/definitions/~ts", [VHostName]), ?OK),
%% verify definitions file metadata
?assertEqual(<<"single_virtual_host">>, maps:get(rabbitmq_definition_format, VHDefinitions)),
?assertEqual(VHostName, (maps:get(original_vhost_name, VHDefinitions))),

%% Remove the test vhost
http_delete(Config, io_lib:format("/vhosts/~ts", [VHostName]), {group, '2xx'}),
ok.

definitions_default_queue_type_test(Config) ->
Expand Down

0 comments on commit 204ac01

Please sign in to comment.