Skip to content

Commit

Permalink
Merge branch 'v3.12.x-backport-11619' into v3.12.x
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelklishin committed Jul 8, 2024
2 parents 0dae3e3 + ceed076 commit bcc46a3
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 12 deletions.
15 changes: 14 additions & 1 deletion deps/rabbit/src/rabbit_definitions.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1077,9 +1077,22 @@ runtime_parameter_definition(Param) ->
<<"vhost">> => pget(vhost, Param),
<<"component">> => pget(component, Param),
<<"name">> => pget(name, Param),
<<"value">> => maps:from_list(pget(value, Param))
<<"value">> => maybe_map(pget(value, Param))
}.

maybe_map(Value) when is_list(Value) ->
%% Not all definitions are maps. `federation-upstream-set` is
%% a list of maps, and it should be exported as it has been
%% imported
try
maps:from_list(Value)
catch
_:_ ->
Value
end;
maybe_map(Value) ->
Value.

list_global_runtime_parameters() ->
[global_runtime_parameter_definition(P) || P <- rabbit_runtime_parameters:list_global(), not is_internal_parameter(P)].

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,9 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ExportDefinitionsCommand do
#

defp serialise(raw_map, "json") do
# make sure all runtime parameter values are maps, otherwise
# they will end up being a list of pairs (a keyword list/proplist)
# in the resulting JSON document
map =
Map.update!(raw_map, :parameters, fn params ->
Enum.map(params, fn param ->
Map.update!(param, "value", &:rabbit_data_coercion.to_map/1)
end)
end)

{:ok, json} = JSON.encode(map)
# rabbit_definitions already takes care of transforming all
# proplists into maps
{:ok, json} = JSON.encode(raw_map)
json
end

Expand Down
5 changes: 5 additions & 0 deletions deps/rabbitmq_federation/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ eunit(

broker_for_integration_suites()

rabbitmq_integration_suite(
name = "definition_import_SUITE",
size = "small",
)

rabbitmq_integration_suite(
name = "exchange_SUITE",
size = "large",
Expand Down
9 changes: 9 additions & 0 deletions deps/rabbitmq_federation/app.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ def all_srcs(name = "all_srcs"):
)

def test_suite_beam_files(name = "test_suite_beam_files"):
erlang_bytecode(
name = "definition_import_SUITE_beam_files",
testonly = True,
srcs = ["test/definition_import_SUITE.erl"],
outs = ["test/definition_import_SUITE.beam"],
app_name = "rabbitmq_federation",
erlc_opts = "//:test_erlc_opts",
deps = ["//deps/rabbitmq_ct_helpers:erlang_app"],
)
erlang_bytecode(
name = "exchange_SUITE_beam_files",
testonly = True,
Expand Down
146 changes: 146 additions & 0 deletions deps/rabbitmq_federation/test/definition_import_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
%%

-module(definition_import_SUITE).

-include_lib("rabbitmq_ct_helpers/include/rabbit_assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").

-compile(export_all).

all() ->
[
{group, roundtrip}
].

groups() ->
[
{roundtrip, [], [
export_import_round_trip
]}
].

%% -------------------------------------------------------------------
%% Test suite setup/teardown.
%% -------------------------------------------------------------------

init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
inets:start(),
Config.
end_per_suite(Config) ->
Config.

init_per_group(Group, Config) ->
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, Group}
]),
rabbit_ct_helpers:run_setup_steps(Config1, rabbit_ct_broker_helpers:setup_steps()).

end_per_group(_, Config) ->
rabbit_ct_helpers:run_teardown_steps(Config, rabbit_ct_broker_helpers:teardown_steps()).

init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase).

end_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_finished(Config, Testcase).

%%
%% Tests
%%

export_import_round_trip(Config) ->
case rabbit_ct_helpers:is_mixed_versions() of
false ->
import_file_case(Config, "case1"),
Defs = export(Config),
import_raw(Config, rabbit_json:encode(Defs));
_ ->
%% skip the test in mixed version mode
{skip, "Should not run in mixed version environments"}
end.

%%
%% Implementation
%%

import_file_case(Config, CaseName) ->
CasePath = filename:join([
?config(data_dir, Config),
CaseName ++ ".json"
]),
rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, run_import_case, [CasePath]),
ok.


import_raw(Config, Body) ->
case rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_definitions, import_raw, [Body]) of
ok -> ok;
{error, E} ->
ct:pal("Import of JSON definitions ~tp failed: ~tp~n", [Body, E]),
ct:fail({expected_failure, Body, E})
end.

export(Config) ->
rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, run_export, []).

run_export() ->
rabbit_definitions:all_definitions().

run_directory_import_case(Path, Expected) ->
ct:pal("Will load definitions from files under ~tp~n", [Path]),
Result = rabbit_definitions:maybe_load_definitions_from(true, Path),
case Expected of
ok ->
ok = Result;
error ->
?assertMatch({error, {failed_to_import_definitions, _, _}}, Result)
end.

run_import_case(Path) ->
{ok, Body} = file:read_file(Path),
ct:pal("Successfully loaded a definition to import from ~tp~n", [Path]),
case rabbit_definitions:import_raw(Body) of
ok -> ok;
{error, E} ->
ct:pal("Import case ~tp failed: ~tp~n", [Path, E]),
ct:fail({expected_failure, Path, E})
end.

run_invalid_import_case(Path) ->
{ok, Body} = file:read_file(Path),
ct:pal("Successfully loaded a definition file at ~tp~n", [Path]),
case rabbit_definitions:import_raw(Body) of
ok ->
ct:pal("Expected import case ~tp to fail~n", [Path]),
ct:fail({expected_failure, Path});
{error, _E} -> ok
end.

run_invalid_import_case_if_unchanged(Path) ->
Mod = rabbit_definitions_import_local_filesystem,
ct:pal("Successfully loaded a definition to import from ~tp~n", [Path]),
case rabbit_definitions:maybe_load_definitions_from_local_filesystem_if_unchanged(Mod, false, Path) of
ok ->
ct:pal("Expected import case ~tp to fail~n", [Path]),
ct:fail({expected_failure, Path});
{error, _E} -> ok
end.

queue_lookup(Config, VHost, Name) ->
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_amqqueue, lookup, [rabbit_misc:r(VHost, queue, Name)]).

vhost_lookup(Config, VHost) ->
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_vhost, lookup, [VHost]).

user_lookup(Config, User) ->
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_auth_backend_internal, lookup_user, [User]).

delete_vhost(Config, VHost) ->
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_vhost, delete, [VHost, <<"CT tests">>]).
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"permissions": [
{
"configure": ".*",
"read": ".*",
"user": "guest",
"vhost": "/",
"write": ".*"
}
],
"bindings": [],
"queues": [],
"parameters": [
{
"component": "federation-upstream-set",
"name": "location-1",
"value": [
{
"upstream":"up-1"
},
{
"upstream":"up-2"
}
],
"vhost":"/"}],
"policies": [],
"rabbitmq_version": "3.13.0+376.g1bc0d89.dirty",
"users": [
{
"hashing_algorithm": "rabbit_password_hashing_sha256",
"limits": {},
"name": "guest",
"password_hash": "jTcCKuOmGJeeRQ/K1LG5sdZLcdnEnqv8wcrP2n68R7nMuqy2",
"tags": ["administrator"]
}
],
"rabbit_version": "3.13.0+376.g1bc0d89.dirty",
"exchanges": [],
"topic_permissions": [],
"vhosts": [
{
"limits": [],
"metadata":
{
"description": "Default virtual host",
"tags": []
},
"name":"/"
}
],
"global_parameters": []
}

0 comments on commit bcc46a3

Please sign in to comment.