Merge branch 'master' into rabbitmq-server-995

This commit is contained in:
Luke Bakken 2017-11-01 16:58:40 -07:00
commit a394a76902
11 changed files with 231 additions and 136 deletions

View File

@ -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

View File

@ -391,6 +391,10 @@ var HELP = {
'memory-use' : '<p>Note that the memory details shown here are only updated on request - they could be too expensive to calculate every few seconds on a busy server.</p><p><a target="_blank" href="http://www.rabbitmq.com/memory-use.html">Read more</a> on memory use.</p>',
'memory-calculation-strategy-breakdown' : '<p>The setting <code>vm_memory_calculation_strategy</code> defines which of the below memory values is used to check if the memory usage reaches the watermark or paging to disk is required.</p><p><a target="_blank" href="http://www.rabbitmq.com/memory-use.html">Read more</a> on memory use.</p>',
'memory-calculation-strategy' : '<p>This value can be calculated using different strategies the <code>vm_memory_calculation_strategy</code> config setting.</p><p><a target="_blank" href="http://www.rabbitmq.com/memory-use.html">Read more</a> on memory use.</p>',
'binary-use' : '<p>Binary accounting is not exact; binaries are shared between processes (and thus the same binary might be counted in more than one section), and the VM does not allow us to track binaries that are not associated with processes (so some binary use might not appear at all).</p>',
'policy-ha-mode' : 'One of <code>all</code> (mirror to all nodes in the cluster), <code>exactly</code> (mirror to a set number of nodes) or <code>nodes</code> (mirror to an explicit list of nodes). If you choose one of the latter two, you must also set <code>ha-params</code>.',

View File

@ -65,8 +65,22 @@ var key = [[{name: 'Queues', colour: 'queue',
<div class="memory-info">
Last updated: <b><%= fmt_date(new Date()) %></b>.<br/>
Total memory used at last update: <b><%= fmt_bytes(memory.total) %></b>
<span class="help" id="memory-use"></span>
Memory calculation strategy: <b><%= memory.strategy %></b>. <span class="help" id="memory-calculation-strategy-breakdown"></span><br/><br/>
Amount of memory used vs. allocated during last update: <span class="help" id="memory-use"></span><br/>
<table class="facts">
<tr>
<th>Runtime Used</th>
<td><%= fmt_bytes(memory.total.erlang) %></td>
</tr>
<tr>
<th>Runtime Allocated</th>
<td><%= fmt_bytes(memory.total.allocated) %></td>
</tr>
<tr>
<th>Resident Set Size (RSS) reported by the OS</th>
<td><%= fmt_bytes(memory.total.rss) %></td>
</tr>
</table>
</div>
<% } %>

View File

@ -104,7 +104,7 @@
</tr>
<tr>
<th>
Memory
Memory <span class="help" id="memory-calculation-strategy"></span>
</th>
<td>
<% if (node.mem_limit != 'memory_monitoring_disabled') { %>

View File

@ -82,7 +82,7 @@
<th>Erlang processes</th>
<% } %>
<% if (show_column('overview', 'memory')) { %>
<th>Memory</th>
<th>Memory <span class="help" id="memory-calculation-strategy"></span></th>
<% } %>
<% if (show_column('overview', 'disk_space')) { %>
<th>Disk space</th>
@ -182,6 +182,7 @@
<abbr title="Broker definitions are held in RAM. Messages will still be written to disc if necessary.">RAM</abbr>
<% } %>
<%= fmt_plugins_small(node) %>
<abbr title="Memory calculation strategy"><%= fmt_string(node.mem_calculation_strategy) %></abbr>
</td>
<% } %>
<% if(user_administrator && show_column('overview', 'reset_stats')) { %>

View File

@ -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} <-

View File

@ -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

View File

@ -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.

View File

@ -70,7 +70,9 @@ augment(Mode, ReqData) ->
format(absolute, Result) ->
Result;
format(relative, Result) ->
{value, {total, Total}, Rest} = lists:keytake(total, 1, Result),
{value, {strategy, Strategy}, Rest0} = lists:keytake(strategy, 1, Result),
{value, {total, Totals}, Rest} = lists:keytake(total, 1, Rest0),
Total = proplists:get_value(Strategy, Totals),
[{total, 100} | [{K, percentage(V, Total)} || {K, V} <- Rest]].
percentage(Part, Total) ->

View File

@ -38,101 +38,101 @@
-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, [], [
overview_test,
auth_test,
cluster_name_test,
nodes_test,
memory_test,
ets_tables_memory_test,
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,
adding_a_user_with_permissions_in_single_operation_test,
adding_a_user_without_tags_fails_test,
adding_a_user_without_password_or_hash_test,
adding_a_user_with_both_password_and_hash_fails_test,
updating_a_user_without_password_or_hash_clears_password_test,
user_credential_validation_accept_everything_succeeds_test,
user_credential_validation_min_length_succeeds_test,
user_credential_validation_min_length_fails_test,
permissions_validation_test,
permissions_list_test,
permissions_test,
topic_permissions_list_test,
topic_permissions_test,
connections_test,
multiple_invalid_connections_test,
exchanges_test,
queues_test,
queues_well_formed_json_test,
bindings_test,
bindings_post_test,
bindings_e2e_test,
permissions_administrator_test,
permissions_vhost_test,
permissions_amqp_test,
permissions_connection_channel_consumer_test,
consumers_test,
definitions_test,
definitions_vhost_test,
definitions_password_test,
definitions_remove_things_test,
definitions_server_named_queue_test,
aliveness_test,
healthchecks_test,
arguments_test,
arguments_table_test,
queue_purge_test,
queue_actions_test,
exclusive_consumer_test,
exclusive_queue_test,
connections_channels_pagination_test,
exchanges_pagination_test,
exchanges_pagination_permissions_test,
queue_pagination_test,
queue_pagination_columns_test,
queues_pagination_permissions_test,
samples_range_test,
sorting_test,
format_output_test,
columns_test,
get_test,
get_fail_test,
publish_test,
publish_accept_json_test,
publish_fail_test,
publish_base64_test,
publish_unrouted_test,
if_empty_unused_test,
parameters_test,
global_parameters_test,
policy_test,
policy_permissions_test,
issue67_test,
extensions_test,
cors_test,
vhost_limits_list_test,
vhost_limit_set_test,
rates_test
]}
{all_tests_with_prefix, [], all_tests()},
{all_tests_without_prefix, [], all_tests()}
].
all_tests() -> [
overview_test,
auth_test,
cluster_name_test,
nodes_test,
memory_test,
ets_tables_memory_test,
vhosts_test,
vhosts_trace_test,
users_test,
users_legacy_administrator_test,
adding_a_user_with_password_test,
adding_a_user_with_password_hash_test,
adding_a_user_with_permissions_in_single_operation_test,
adding_a_user_without_tags_fails_test,
adding_a_user_without_password_or_hash_test,
adding_a_user_with_both_password_and_hash_fails_test,
updating_a_user_without_password_or_hash_clears_password_test,
user_credential_validation_accept_everything_succeeds_test,
user_credential_validation_min_length_succeeds_test,
user_credential_validation_min_length_fails_test,
permissions_validation_test,
permissions_list_test,
permissions_test,
connections_test,
multiple_invalid_connections_test,
exchanges_test,
queues_test,
queues_well_formed_json_test,
bindings_test,
bindings_post_test,
bindings_e2e_test,
permissions_administrator_test,
permissions_vhost_test,
permissions_amqp_test,
permissions_connection_channel_consumer_test,
consumers_test,
definitions_test,
definitions_vhost_test,
definitions_password_test,
definitions_remove_things_test,
definitions_server_named_queue_test,
aliveness_test,
healthchecks_test,
arguments_test,
arguments_table_test,
queue_purge_test,
queue_actions_test,
exclusive_consumer_test,
exclusive_queue_test,
connections_channels_pagination_test,
exchanges_pagination_test,
exchanges_pagination_permissions_test,
queue_pagination_test,
queue_pagination_columns_test,
queues_pagination_permissions_test,
samples_range_test,
sorting_test,
format_output_test,
columns_test,
get_test,
get_fail_test,
publish_test,
publish_accept_json_test,
publish_fail_test,
publish_base64_test,
publish_unrouted_test,
if_empty_unused_test,
parameters_test,
global_parameters_test,
policy_test,
policy_permissions_test,
issue67_test,
extensions_test,
cors_test,
vhost_limits_list_test,
vhost_limit_set_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,30 @@ 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 = #{source => <<"myexchange">>,
vhost => <<"/">>,
destination => <<"myqueue">>,
destination_type => <<"queue">>,
routing_key => <<"routing">>,
arguments => #{foo => <<"bar">>},
properties_key => PropertiesKeyBin},
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'}),

View File

@ -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) ->