Merge pull request #671 from rabbitmq/rabbitmq-management-665

Allow loading definitions from file or directory
This commit is contained in:
Michael Klishin 2019-03-12 04:40:36 +03:00 committed by GitHub
commit b2bf952704
6 changed files with 72 additions and 30 deletions

View File

@ -4,11 +4,11 @@
%% See http://www.rabbitmq.com/management.html for details
%% ----------------------------------------------------------------------------
% {rabbitmq_management,
% [%% Pre-Load schema definitions from the following JSON file. See
%% Load definitions from a JSON file or directory of files. See
%% http://www.rabbitmq.com/management.html#load-definitions
%%
%% {load_definitions, "/path/to/schema.json"},
%% {load_definitions, "/path/to/schemas"},
{mapping, "management.load_definitions", "rabbitmq_management.load_definitions",
[{datatype, string},
{validators, ["file_accessible"]}]}.

View File

@ -11,14 +11,14 @@
%% The Original Code is RabbitMQ Management Plugin.
%%
%% The Initial Developer of the Original Code is GoPivotal, Inc.
%% Copyright (c) 2007-2018 Pivotal Software, Inc. All rights reserved.
%% Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
%%
-module(rabbit_mgmt_load_definitions).
-include_lib("rabbit_common/include/rabbit.hrl").
-export([maybe_load_definitions/0]).
-export([maybe_load_definitions/0, maybe_load_definitions_from/2]).
%% We want to A) make sure we apply definitions before being open for
%% business (hence why we don't do this in the mgmt app startup) and
@ -34,15 +34,42 @@
{enables, empty_db_check}]}).
maybe_load_definitions() ->
{ok, File} = application:get_env(rabbitmq_management, load_definitions),
case File of
none -> ok;
_ -> case file:read_file(File) of
{ok, Body} -> rabbit_log:info(
"Applying definitions from: ~s", [File]),
load_definitions(Body);
{error, E} -> {error, {could_not_read_defs, {File, E}}}
end
case application:get_env(rabbitmq_management, load_definitions) of
{ok, none} ->
ok;
{ok, FileOrDir} ->
IsDir = filelib:is_dir(FileOrDir),
maybe_load_definitions_from(IsDir, FileOrDir)
end.
maybe_load_definitions_from(true, Dir) ->
rabbit_log:info("Applying definitions from directory ~s", [Dir]),
load_definitions_from_files(file:list_dir(Dir), Dir);
maybe_load_definitions_from(false, File) ->
load_definitions_from_file(File).
load_definitions_from_files({ok, Filenames0}, Dir) ->
Filenames1 = lists:sort(Filenames0),
Filenames2 = [filename:join(Dir, F) || F <- Filenames1],
load_definitions_from_filenames(Filenames2);
load_definitions_from_files({error, E}, Dir) ->
rabbit_log:error("Could not read definitions from directory ~s, Error: ~p", [Dir, E]),
{error, {could_not_read_defs, E}}.
load_definitions_from_filenames([]) ->
ok;
load_definitions_from_filenames([File|Rest]) ->
load_definitions_from_file(File),
load_definitions_from_filenames(Rest).
load_definitions_from_file(File) ->
case file:read_file(File) of
{ok, Body} ->
rabbit_log:info("Applying definitions from ~s", [File]),
load_definitions(Body);
{error, E} ->
rabbit_log:error("Could not read definitions from ~s, Error: ~p", [File, E]),
{error, {could_not_read_defs, {File, E}}}
end.
load_definitions(Body) ->

View File

@ -166,7 +166,7 @@ accept(Body, ReqData, Context = #context{user = #user{username = Username}}) ->
end.
apply_defs(Body, ActingUser, SuccessFun, ErrorFun) ->
rabbit_log:info("Asked to import definitions. Acting user: ~p", [ActingUser]),
rabbit_log:info("Asked to import definitions. Acting user: ~s", [rabbit_data_coercion:to_binary(ActingUser)]),
case rabbit_mgmt_util:decode([], Body) of
{error, E} ->
ErrorFun(E);

View File

@ -42,7 +42,8 @@ groups() ->
import_case5,
import_case6,
import_case7,
import_case8
import_case8,
import_case9
]}
].
@ -80,16 +81,18 @@ end_per_testcase(Testcase, Config) ->
%% Tests
%%
import_case1(Config) -> import_case(Config, "case1").
import_case2(Config) -> import_case(Config, "case2").
import_case3(Config) -> import_case(Config, "case3").
import_case4(Config) -> import_case(Config, "case4").
import_case6(Config) -> import_case(Config, "case6").
import_case7(Config) -> import_case(Config, "case7").
import_case8(Config) -> import_case(Config, "case8").
import_case1(Config) -> import_file_case(Config, "case1").
import_case2(Config) -> import_file_case(Config, "case2").
import_case3(Config) -> import_file_case(Config, "case3").
import_case4(Config) -> import_file_case(Config, "case4").
import_case6(Config) -> import_file_case(Config, "case6").
import_case7(Config) -> import_file_case(Config, "case7").
import_case8(Config) -> import_file_case(Config, "case8").
import_case9(Config) -> import_from_directory_case(Config, "case9").
import_case5(Config) ->
import_case(Config, "case5"),
import_file_case(Config, "case5"),
?assertEqual(rabbit_ct_broker_helpers:rpc(Config, 0,
rabbit_runtime_parameters, value_global,
[mqtt_port_to_vhost_mapping]),
@ -97,15 +100,25 @@ import_case5(Config) ->
[{<<"1883">>,<<"/">>},
{<<"1884">>,<<"vhost2">>}]).
import_case(Config, CaseName) ->
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_from_directory_case(Config, CaseName) ->
CasePath = filename:join(?config(data_dir, Config), CaseName),
?assert(filelib:is_dir(CasePath)),
rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, run_directory_import_case, [CasePath]),
ok.
run_directory_import_case(Path) ->
ct:pal("Will load definitions from files under ~p~n", [Path]),
rabbit_mgmt_load_definitions:maybe_load_definitions_from(true, Path).
run_import_case(Path) ->
{ok, Body} = file:read_file(Path),
ct:pal("Successfully loaded a definition to import from ~p~n", [Path]),
rabbit_mgmt_wm_definitions:apply_defs(Body, ?INTERNAL_USER,
fun () -> ct:pal("Import case ~p succeeded~n", [Path]) end,
fun (E) -> ct:pal("Import case ~p failed: ~p~n", [Path, E]),
ct:fail({failure, Path, E}) end).
{ok, Body} = file:read_file(Path),
ct:pal("Successfully loaded a definition to import from ~p~n", [Path]),
rabbit_mgmt_wm_definitions:apply_defs(Body, ?INTERNAL_USER,
fun () -> ct:pal("Import case ~p succeeded~n", [Path]) end,
fun (E) -> ct:pal("Import case ~p failed: ~p~n", [Path, E]),
ct:fail({failure, Path, E}) end).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long