Merge branch 'stable'
This commit is contained in:
		
						commit
						dffde95b82
					
				| 
						 | 
				
			
			@ -18,7 +18,7 @@
 | 
			
		|||
    </p>
 | 
			
		||||
 | 
			
		||||
    <p>
 | 
			
		||||
      To use it, <a href="/cli/rabbitmqadmin">download it</a> from this node (right click,
 | 
			
		||||
      To use it, <a href="rabbitmqadmin">download it</a> from this node (right click,
 | 
			
		||||
      Save As), make sure it is executable, and drop it in your <code>PATH</code>. Note that
 | 
			
		||||
      many browsers will rename the
 | 
			
		||||
      file <code>rabbitmqadmin.txt</code>. <code>rabbitmqadmin</code> requires Python
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,18 +22,43 @@
 | 
			
		|||
-export([dispatcher/0, web_ui/0]).
 | 
			
		||||
 | 
			
		||||
build_dispatcher(Ignore) ->
 | 
			
		||||
    Routes = build_routes(Ignore),
 | 
			
		||||
    cowboy_router:compile(Routes).
 | 
			
		||||
 | 
			
		||||
build_routes(Ignore) ->
 | 
			
		||||
    ManagementApp = module_app(?MODULE),
 | 
			
		||||
    Prefix = rabbit_mgmt_util:get_path_prefix(),
 | 
			
		||||
    RootIdxRtes = build_root_index_routes(Prefix, ManagementApp),
 | 
			
		||||
    ApiIdxRte = {"/api", cowboy_static, {priv_file, ManagementApp, "www/api/index.html"}},
 | 
			
		||||
    CliIdxRte = {"/cli", cowboy_static, {priv_file, ManagementApp, "www/cli/index.html"}},
 | 
			
		||||
    MgmtRdrRte = {"/mgmt", rabbit_mgmt_wm_redirect, "/"},
 | 
			
		||||
    LocalPaths = [{module_app(M), "www"} || M <- modules(Ignore)],
 | 
			
		||||
    cowboy_router:compile([{'_',
 | 
			
		||||
        [{"/api" ++ Path, Mod, Args}
 | 
			
		||||
            || {Path, Mod, Args} <- lists:append([Module:dispatcher()
 | 
			
		||||
                                                  || Module <- modules(Ignore)])]
 | 
			
		||||
     ++ [{"/", cowboy_static, {priv_file, ManagementApp, "www/index.html"}},
 | 
			
		||||
         {"/api", cowboy_static, {priv_file, ManagementApp, "www/api/index.html"}},
 | 
			
		||||
         {"/cli", cowboy_static, {priv_file, ManagementApp, "www/cli/index.html"}},
 | 
			
		||||
         {"/mgmt", rabbit_mgmt_wm_redirect, "/"}]
 | 
			
		||||
     ++ [{"/[...]", rabbit_mgmt_wm_static, LocalPaths}]
 | 
			
		||||
    }]).
 | 
			
		||||
    LocalStaticRte = {"/[...]", rabbit_mgmt_wm_static, LocalPaths},
 | 
			
		||||
    % NB: order is significant in the routing list
 | 
			
		||||
    Routes0 = build_module_routes(Ignore) ++
 | 
			
		||||
        [ApiIdxRte, CliIdxRte, MgmtRdrRte, LocalStaticRte],
 | 
			
		||||
    Routes1 = maybe_add_path_prefix(Routes0, Prefix),
 | 
			
		||||
    % NB: ensure the root routes are first
 | 
			
		||||
    Routes2 = RootIdxRtes ++ Routes1,
 | 
			
		||||
    [{'_', Routes2}].
 | 
			
		||||
 | 
			
		||||
build_root_index_routes("", ManagementApp) ->
 | 
			
		||||
    [{"/", cowboy_static, root_idx_file(ManagementApp)}];
 | 
			
		||||
build_root_index_routes(Prefix, ManagementApp) ->
 | 
			
		||||
    [{"/", rabbit_mgmt_wm_redirect, Prefix ++ "/"},
 | 
			
		||||
     {Prefix, cowboy_static, root_idx_file(ManagementApp)}].
 | 
			
		||||
 | 
			
		||||
root_idx_file(ManagementApp) ->
 | 
			
		||||
    {priv_file, ManagementApp, "www/index.html"}.
 | 
			
		||||
 | 
			
		||||
maybe_add_path_prefix(Routes, "") ->
 | 
			
		||||
    Routes;
 | 
			
		||||
maybe_add_path_prefix(Routes, Prefix) ->
 | 
			
		||||
    [{Prefix ++ Path, Mod, Args} || {Path, Mod, Args} <- Routes].
 | 
			
		||||
 | 
			
		||||
build_module_routes(Ignore) ->
 | 
			
		||||
    Routes = [Module:dispatcher() || Module <- modules(Ignore)],
 | 
			
		||||
    [{"/api" ++ Path, Mod, Args} || {Path, Mod, Args} <- lists:append(Routes)].
 | 
			
		||||
 | 
			
		||||
modules(IgnoreApps) ->
 | 
			
		||||
    [Module || {App, Module, Behaviours} <-
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@
 | 
			
		|||
        ]).
 | 
			
		||||
-export([direct_request/6]).
 | 
			
		||||
-export([qs_val/2]).
 | 
			
		||||
-export([get_path_prefix/0]).
 | 
			
		||||
 | 
			
		||||
-import(rabbit_misc, [pget/2]).
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -427,6 +428,19 @@ get_data({paged, Data}) ->
 | 
			
		|||
get_data({_, Data}) ->
 | 
			
		||||
    Data.
 | 
			
		||||
 | 
			
		||||
get_path_prefix() ->
 | 
			
		||||
    EnvPrefix = rabbit_misc:get_env(rabbitmq_management, path_prefix, ""),
 | 
			
		||||
    fixup_prefix(EnvPrefix).
 | 
			
		||||
 | 
			
		||||
fixup_prefix("") ->
 | 
			
		||||
    "";
 | 
			
		||||
fixup_prefix([Char|_Rest]=EnvPrefix) when is_list(EnvPrefix), Char =:= $/ ->
 | 
			
		||||
    EnvPrefix;
 | 
			
		||||
fixup_prefix(EnvPrefix) when is_list(EnvPrefix) ->
 | 
			
		||||
    "/" ++ EnvPrefix;
 | 
			
		||||
fixup_prefix(EnvPrefix) when is_binary(EnvPrefix) ->
 | 
			
		||||
    fixup_prefix(rabbit_data_coercion:to_list(EnvPrefix)).
 | 
			
		||||
 | 
			
		||||
%% XXX sort_list_and_paginate/2 is a more proper name for this function, keeping it
 | 
			
		||||
%% with this name for backwards compatibility
 | 
			
		||||
-spec sort_list([Fact], [string()]) -> [Fact] when
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,13 +93,14 @@ accept_content(ReqData0, {_Mode, Context}) ->
 | 
			
		|||
        {stop, _, _} = Res ->
 | 
			
		||||
            Res;
 | 
			
		||||
        {true, ReqData, Context2} ->
 | 
			
		||||
            Loc = rabbit_web_dispatch_util:relativise(
 | 
			
		||||
                    binary_to_list(cowboy_req:path(ReqData)),
 | 
			
		||||
                    binary_to_list(
 | 
			
		||||
                      rabbit_mgmt_format:url(
 | 
			
		||||
                        "/api/bindings/~s/e/~s/~s/~s/~s",
 | 
			
		||||
                        [VHost, Source, DestType, Dest,
 | 
			
		||||
                         rabbit_mgmt_format:pack_binding_props(Key, Args)]))),
 | 
			
		||||
            From = binary_to_list(cowboy_req:path(ReqData)),
 | 
			
		||||
            Prefix = rabbit_mgmt_util:get_path_prefix(),
 | 
			
		||||
            BindingProps = rabbit_mgmt_format:pack_binding_props(Key, Args),
 | 
			
		||||
            UrlWithBindings = rabbit_mgmt_format:url("/api/bindings/~s/e/~s/~s/~s/~s",
 | 
			
		||||
                                                     [VHost, Source, DestType,
 | 
			
		||||
                                                      Dest, BindingProps]),
 | 
			
		||||
            To = Prefix ++ binary_to_list(UrlWithBindings),
 | 
			
		||||
            Loc = rabbit_web_dispatch_util:relativise(From, To),
 | 
			
		||||
            {{true, Loc}, ReqData, Context2}
 | 
			
		||||
    end.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,17 +38,23 @@
 | 
			
		|||
-import(rabbit_misc, [pget/2]).
 | 
			
		||||
 | 
			
		||||
-define(COLLECT_INTERVAL, 1000).
 | 
			
		||||
-define(PATH_PREFIX, "/custom-prefix").
 | 
			
		||||
 | 
			
		||||
-compile(export_all).
 | 
			
		||||
 | 
			
		||||
all() ->
 | 
			
		||||
    [
 | 
			
		||||
     {group, non_parallel_tests}
 | 
			
		||||
     {group, all_tests_with_prefix},
 | 
			
		||||
     {group, all_tests_without_prefix}
 | 
			
		||||
    ].
 | 
			
		||||
 | 
			
		||||
groups() ->
 | 
			
		||||
    [
 | 
			
		||||
     {non_parallel_tests, [], [
 | 
			
		||||
     {all_tests_with_prefix, [], all_tests()},
 | 
			
		||||
     {all_tests_without_prefix, [], all_tests()}
 | 
			
		||||
    ].
 | 
			
		||||
 | 
			
		||||
all_tests() -> [
 | 
			
		||||
    overview_test,
 | 
			
		||||
    auth_test,
 | 
			
		||||
    cluster_name_test,
 | 
			
		||||
| 
						 | 
				
			
			@ -58,8 +64,6 @@ groups() ->
 | 
			
		|||
    vhosts_test,
 | 
			
		||||
    vhosts_trace_test,
 | 
			
		||||
    users_test,
 | 
			
		||||
                               without_permissions_users_test,
 | 
			
		||||
                               users_bulk_delete_test,
 | 
			
		||||
    users_legacy_administrator_test,
 | 
			
		||||
    adding_a_user_with_password_test,
 | 
			
		||||
    adding_a_user_with_password_hash_test,
 | 
			
		||||
| 
						 | 
				
			
			@ -74,8 +78,6 @@ groups() ->
 | 
			
		|||
    permissions_validation_test,
 | 
			
		||||
    permissions_list_test,
 | 
			
		||||
    permissions_test,
 | 
			
		||||
                               topic_permissions_list_test,
 | 
			
		||||
                               topic_permissions_test,
 | 
			
		||||
    connections_test,
 | 
			
		||||
    multiple_invalid_connections_test,
 | 
			
		||||
    exchanges_test,
 | 
			
		||||
| 
						 | 
				
			
			@ -129,9 +131,7 @@ groups() ->
 | 
			
		|||
    cors_test,
 | 
			
		||||
    vhost_limits_list_test,
 | 
			
		||||
    vhost_limit_set_test,
 | 
			
		||||
                               rates_test
 | 
			
		||||
                              ]}
 | 
			
		||||
    ].
 | 
			
		||||
    rates_test].
 | 
			
		||||
 | 
			
		||||
%% -------------------------------------------------------------------
 | 
			
		||||
%% Testsuite setup/teardown.
 | 
			
		||||
| 
						 | 
				
			
			@ -146,28 +146,37 @@ merge_app_env(Config) ->
 | 
			
		|||
                                     {sample_retention_policies,
 | 
			
		||||
                                          [{global,   [{605, 1}]},
 | 
			
		||||
                                           {basic,    [{605, 1}]},
 | 
			
		||||
                                           {detailed, [{10, 1}]}] }]}).
 | 
			
		||||
                                           {detailed, [{10, 1}]}]
 | 
			
		||||
                                     }]}).
 | 
			
		||||
 | 
			
		||||
init_per_suite(Config) ->
 | 
			
		||||
start_broker(Config) ->
 | 
			
		||||
    Setup0 = rabbit_ct_broker_helpers:setup_steps(),
 | 
			
		||||
    Setup1 = rabbit_ct_client_helpers:setup_steps(),
 | 
			
		||||
    Steps = Setup0 ++ Setup1,
 | 
			
		||||
    rabbit_ct_helpers:run_setup_steps(Config, Steps).
 | 
			
		||||
 | 
			
		||||
finish_init(Group, Config) ->
 | 
			
		||||
    rabbit_ct_helpers:log_environment(),
 | 
			
		||||
    inets:start(),
 | 
			
		||||
    Config1 = rabbit_ct_helpers:set_config(Config, [
 | 
			
		||||
                                                    {rmq_nodename_suffix, ?MODULE}
 | 
			
		||||
                                                   ]),
 | 
			
		||||
    Config2 = merge_app_env(Config1),
 | 
			
		||||
    rabbit_ct_helpers:run_setup_steps(Config2,
 | 
			
		||||
                      rabbit_ct_broker_helpers:setup_steps() ++
 | 
			
		||||
                      rabbit_ct_client_helpers:setup_steps()).
 | 
			
		||||
end_per_suite(Config) ->
 | 
			
		||||
    rabbit_ct_helpers:run_teardown_steps(Config,
 | 
			
		||||
                                         rabbit_ct_client_helpers:teardown_steps() ++
 | 
			
		||||
                                             rabbit_ct_broker_helpers:teardown_steps()).
 | 
			
		||||
    NodeConf = [{rmq_nodename_suffix, Group}],
 | 
			
		||||
    Config1 = rabbit_ct_helpers:set_config(Config, NodeConf),
 | 
			
		||||
    merge_app_env(Config1).
 | 
			
		||||
 | 
			
		||||
init_per_group(_, Config) ->
 | 
			
		||||
    Config.
 | 
			
		||||
init_per_group(all_tests_with_prefix=Group, Config0) ->
 | 
			
		||||
    PathConfig = {rabbitmq_management, [{path_prefix, ?PATH_PREFIX}]},
 | 
			
		||||
    Config1 = rabbit_ct_helpers:merge_app_env(Config0, PathConfig),
 | 
			
		||||
    Config2 = finish_init(Group, Config1),
 | 
			
		||||
    start_broker(Config2);
 | 
			
		||||
init_per_group(Group, Config0) ->
 | 
			
		||||
    Config1 = finish_init(Group, Config0),
 | 
			
		||||
    start_broker(Config1).
 | 
			
		||||
 | 
			
		||||
end_per_group(_, Config) ->
 | 
			
		||||
    Config.
 | 
			
		||||
    inets:stop(),
 | 
			
		||||
    Teardown0 = rabbit_ct_client_helpers:teardown_steps(),
 | 
			
		||||
    Teardown1 = rabbit_ct_broker_helpers:teardown_steps(),
 | 
			
		||||
    Steps = Teardown0 ++ Teardown1,
 | 
			
		||||
    rabbit_ct_helpers:run_teardown_steps(Config, Steps).
 | 
			
		||||
 | 
			
		||||
init_per_testcase(Testcase, Config) ->
 | 
			
		||||
    rabbit_ct_helpers:testcase_started(Config, Testcase).
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +209,6 @@ end_per_testcase0(_, Config) -> Config.
 | 
			
		|||
%% Testcases.
 | 
			
		||||
%% -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
overview_test(Config) ->
 | 
			
		||||
    %% Rather crude, but this req doesn't say much and at least this means it
 | 
			
		||||
    %% didn't blow up.
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +217,6 @@ overview_test(Config) ->
 | 
			
		|||
                                       {tags,     <<"management">>}], {group, '2xx'}),
 | 
			
		||||
    http_get(Config, "/overview", "myuser", "myuser", ?OK),
 | 
			
		||||
    http_delete(Config, "/users/myuser", {group, '2xx'}),
 | 
			
		||||
 | 
			
		||||
    passed.
 | 
			
		||||
 | 
			
		||||
cluster_name_test(Config) ->
 | 
			
		||||
| 
						 | 
				
			
			@ -956,23 +963,26 @@ bindings_post_test(Config) ->
 | 
			
		|||
    http_put(Config, "/queues/%2f/myqueue", QArgs, {group, '2xx'}),
 | 
			
		||||
    http_post(Config, "/bindings/%2f/e/myexchange/q/badqueue", BArgs, ?NOT_FOUND),
 | 
			
		||||
    http_post(Config, "/bindings/%2f/e/badexchange/q/myqueue", BArgs, ?NOT_FOUND),
 | 
			
		||||
 | 
			
		||||
    Headers1 = http_post(Config, "/bindings/%2f/e/myexchange/q/myqueue", #{}, {group, '2xx'}),
 | 
			
		||||
    "../../../../%2F/e/myexchange/q/myqueue/~" = pget("location", Headers1),
 | 
			
		||||
    Want0 = "../../../../%2F/e/myexchange/q/myqueue/~",
 | 
			
		||||
    ?assertEqual(Want0, pget("location", Headers1)),
 | 
			
		||||
 | 
			
		||||
    Headers2 = http_post(Config, "/bindings/%2f/e/myexchange/q/myqueue", BArgs, {group, '2xx'}),
 | 
			
		||||
    %% Args hash is calculated from a table, generated from args.
 | 
			
		||||
    Hash = table_hash([{<<"foo">>,longstr,<<"bar">>}]),
 | 
			
		||||
    PropertiesKey = "routing~" ++ Hash,
 | 
			
		||||
 | 
			
		||||
    Want1 = "../../../../%2F/e/myexchange/q/myqueue/" ++ PropertiesKey,
 | 
			
		||||
    ?assertEqual(Want1, pget("location", Headers2)),
 | 
			
		||||
 | 
			
		||||
    PropertiesKeyBin = list_to_binary(PropertiesKey),
 | 
			
		||||
    "../../../../%2F/e/myexchange/q/myqueue/" ++ PropertiesKey =
 | 
			
		||||
        pget("location", Headers2),
 | 
			
		||||
    Want2 = #{arguments => #{foo => <<"bar">>}, destination => <<"myqueue">>,
 | 
			
		||||
              destination_type => <<"queue">>, properties_key => PropertiesKeyBin,
 | 
			
		||||
              routing_key => <<"routing">>, source => <<"myexchange">>,vhost => <<"/">>},
 | 
			
		||||
    URI = "/bindings/%2F/e/myexchange/q/myqueue/" ++ PropertiesKey,
 | 
			
		||||
    #{source := <<"myexchange">>,
 | 
			
		||||
      vhost := <<"/">>,
 | 
			
		||||
      destination := <<"myqueue">>,
 | 
			
		||||
      destination_type := <<"queue">>,
 | 
			
		||||
      routing_key := <<"routing">>,
 | 
			
		||||
      arguments := #{foo := <<"bar">>},
 | 
			
		||||
      properties_key := PropertiesKeyBin} = http_get(Config, URI, ?OK),
 | 
			
		||||
    ?assertEqual(Want2, http_get(Config, URI, ?OK)),
 | 
			
		||||
 | 
			
		||||
    http_get(Config, URI ++ "x", ?NOT_FOUND),
 | 
			
		||||
    http_delete(Config, URI, {group, '2xx'}),
 | 
			
		||||
    http_delete(Config, "/exchanges/%2f/myexchange", {group, '2xx'}),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,8 @@ groups() ->
 | 
			
		|||
     {parallel_tests, [parallel], [
 | 
			
		||||
                                   tokenise_test,
 | 
			
		||||
                                   pack_binding_test,
 | 
			
		||||
                                   amqp_table_test
 | 
			
		||||
                                   amqp_table_test,
 | 
			
		||||
                                   path_prefix_test
 | 
			
		||||
                                  ]}
 | 
			
		||||
    ].
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +82,25 @@ assert_table(JSON, AMQP) ->
 | 
			
		|||
    ?assertEqual(JSON, rabbit_mgmt_format:amqp_table(AMQP)),
 | 
			
		||||
    ?assertEqual(AMQP, rabbit_mgmt_format:to_amqp_table(JSON)).
 | 
			
		||||
 | 
			
		||||
path_prefix_test(_Config) ->
 | 
			
		||||
    Got0 = rabbit_mgmt_util:get_path_prefix(),
 | 
			
		||||
    ?assertEqual("", Got0),
 | 
			
		||||
 | 
			
		||||
    Pfx0 = "/custom-prefix",
 | 
			
		||||
    application:set_env(rabbitmq_management, path_prefix, Pfx0),
 | 
			
		||||
    Got1 = rabbit_mgmt_util:get_path_prefix(),
 | 
			
		||||
    ?assertEqual(Pfx0, Got1),
 | 
			
		||||
 | 
			
		||||
    Pfx1 = "custom-prefix",
 | 
			
		||||
    application:set_env(rabbitmq_management, path_prefix, Pfx1),
 | 
			
		||||
    Got2 = rabbit_mgmt_util:get_path_prefix(),
 | 
			
		||||
    ?assertEqual(Pfx0, Got2),
 | 
			
		||||
 | 
			
		||||
    Pfx2 = <<"custom-prefix">>,
 | 
			
		||||
    application:set_env(rabbitmq_management, path_prefix, Pfx2),
 | 
			
		||||
    Got3 = rabbit_mgmt_util:get_path_prefix(),
 | 
			
		||||
    ?assertEqual(Pfx0, Got3).
 | 
			
		||||
 | 
			
		||||
%%--------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
assert_binding(Packed, Routing, Args) ->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue