Merge pull request #2650 from rabbitmq/rabbitmq-stream-management
Introduce stream management plugin
This commit is contained in:
commit
54554b88d0
|
|
@ -40,6 +40,7 @@
|
|||
!/deps/rabbitmq_shovel_management/
|
||||
!/deps/rabbitmq_stomp/
|
||||
!/deps/rabbitmq_stream/
|
||||
!/deps/rabbitmq_stream_management/
|
||||
!/deps/rabbitmq_top/
|
||||
!/deps/rabbitmq_tracing/
|
||||
!/deps/rabbitmq_trust_store/
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -463,6 +463,7 @@ tracked_connection_from_connection_created(EventDetails) ->
|
|||
username = pget(user, EventDetails),
|
||||
connected_at = pget(connected_at, EventDetails),
|
||||
pid = pget(pid, EventDetails),
|
||||
protocol = pget(protocol, EventDetails),
|
||||
type = pget(type, EventDetails),
|
||||
peer_host = pget(peer_host, EventDetails),
|
||||
peer_port = pget(peer_port, EventDetails)}.
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
-include("rabbit_core_metrics.hrl").
|
||||
|
||||
-export([create_table/1]).
|
||||
-export([init/0]).
|
||||
-export([terminate/0]).
|
||||
|
||||
|
|
@ -104,9 +105,13 @@
|
|||
%%----------------------------------------------------------------------------
|
||||
%% API
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
create_table({Table, Type}) ->
|
||||
ets:new(Table, [Type, public, named_table, {write_concurrency, true},
|
||||
{read_concurrency, true}]).
|
||||
|
||||
init() ->
|
||||
_ = [ets:new(Table, [Type, public, named_table, {write_concurrency, true},
|
||||
{read_concurrency, true}])
|
||||
_ = [create_table({Table, Type})
|
||||
|| {Table, Type} <- ?CORE_TABLES ++ ?CORE_EXTRA_TABLES],
|
||||
ok.
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -866,15 +866,18 @@ function filter_ui(items) {
|
|||
|
||||
}
|
||||
|
||||
function paginate_header_ui(pages, context){
|
||||
function paginate_header_ui(pages, context, label){
|
||||
if (label == undefined) {
|
||||
label = context;
|
||||
}
|
||||
var res = '<h2 class="updatable">';
|
||||
res += ' All ' + context +' (' + pages.total_count + ((pages.filtered_count != pages.total_count) ? ', filtered down to ' + pages.filtered_count : '') + ')';
|
||||
res += ' All ' + label +' (' + pages.total_count + ((pages.filtered_count != pages.total_count) ? ', filtered down to ' + pages.filtered_count : '') + ')';
|
||||
res += '</h2>';
|
||||
return res;
|
||||
}
|
||||
|
||||
function paginate_ui(pages, context){
|
||||
var res = paginate_header_ui(pages, context);
|
||||
function paginate_ui(pages, context, label){
|
||||
var res = paginate_header_ui(pages, context, label);
|
||||
res += '<div class="hider">';
|
||||
res += '<h3>Pagination</h3>';
|
||||
res += '<div class="filter">';
|
||||
|
|
|
|||
|
|
@ -166,6 +166,8 @@ var DISABLED_STATS_COLUMNS =
|
|||
|
||||
var COLUMNS;
|
||||
|
||||
var RENDER_CALLBACKS = {};
|
||||
|
||||
// All help ? popups
|
||||
var HELP = {
|
||||
'delivery-limit':
|
||||
|
|
|
|||
|
|
@ -739,11 +739,11 @@ function postprocess() {
|
|||
update_multifields();
|
||||
}
|
||||
|
||||
function url_pagination_template(template, defaultPage, defaultPageSize){
|
||||
var page_number_request = fmt_page_number_request(template, defaultPage);
|
||||
var page_size = fmt_page_size_request(template, defaultPageSize);
|
||||
var name_request = fmt_filter_name_request(template, "");
|
||||
var use_regex = fmt_regex_request(template, "") == "checked";
|
||||
function url_pagination_template_context(template, context, defaultPage, defaultPageSize){
|
||||
var page_number_request = fmt_page_number_request(context, defaultPage);
|
||||
var page_size = fmt_page_size_request(context, defaultPageSize);
|
||||
var name_request = fmt_filter_name_request(context, "");
|
||||
var use_regex = fmt_regex_request(context, "") == "checked";
|
||||
if (use_regex) {
|
||||
name_request = esc(name_request);
|
||||
}
|
||||
|
|
@ -754,6 +754,10 @@ function url_pagination_template(template, defaultPage, defaultPageSize){
|
|||
'&use_regex=' + use_regex;
|
||||
}
|
||||
|
||||
function url_pagination_template(template, defaultPage, defaultPageSize){
|
||||
return url_pagination_template_context(template, template, defaultPage, defaultPageSize);
|
||||
}
|
||||
|
||||
function stored_page_info(template, page_start){
|
||||
var pageSize = fmt_strip_tags($('#' + template+'-pagesize').val());
|
||||
var filterName = fmt_strip_tags($('#' + template+'-name').val());
|
||||
|
|
@ -780,6 +784,12 @@ function update_pages(template, page_start){
|
|||
case 'exchanges' : renderExchanges(); break;
|
||||
case 'connections' : renderConnections(); break;
|
||||
case 'channels' : renderChannels(); break;
|
||||
default:
|
||||
renderCallback = RENDER_CALLBACKS[template];
|
||||
if (renderCallback != undefined) {
|
||||
renderCallback();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<h1>Connection <%= fmt_string(connection.name) %> <%= fmt_maybe_vhost(connection.vhost) %></h1>
|
||||
<h2>Connection <%= fmt_string(connection.name) %> <%= fmt_maybe_vhost(connection.vhost) %></h1>
|
||||
|
||||
<% if (!disable_stats) { %>
|
||||
<div class="section">
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
code_change/3, handle_pre_hibernate/1,
|
||||
format_message_queue/2]).
|
||||
|
||||
-export([submit/1, get_data_from_nodes/1]).
|
||||
|
||||
-import(rabbit_misc, [pget/3]).
|
||||
|
||||
-type maybe_slide() :: exometer_slide:slide() | not_found.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
is_authorized_user/4,
|
||||
is_authorized_monitor/2, is_authorized_policies/2,
|
||||
is_authorized_vhost_visible/2,
|
||||
is_authorized_vhost_visible_for_monitoring/2,
|
||||
is_authorized_global_parameters/2]).
|
||||
|
||||
-export([bad_request/3, bad_request_exception/4, internal_server_error/4,
|
||||
|
|
@ -117,6 +118,15 @@ is_authorized_vhost_visible(ReqData, Context) ->
|
|||
is_admin(Tags) orelse user_matches_vhost_visible(ReqData, User)
|
||||
end).
|
||||
|
||||
is_authorized_vhost_visible_for_monitoring(ReqData, Context) ->
|
||||
is_authorized(ReqData, Context,
|
||||
<<"User not authorised to access virtual host">>,
|
||||
fun(#user{tags = Tags} = User) ->
|
||||
is_admin(Tags)
|
||||
orelse is_monitor(Tags)
|
||||
orelse user_matches_vhost_visible(ReqData, User)
|
||||
end).
|
||||
|
||||
disable_stats(ReqData) ->
|
||||
MgmtOnly = case qs_val(<<"disable_stats">>, ReqData) of
|
||||
<<"true">> -> true;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -177,7 +177,9 @@ protocol(unknown) ->
|
|||
protocol(Version = {_Major, _Minor, _Revision}) ->
|
||||
protocol({'AMQP', Version});
|
||||
protocol({Family, Version}) ->
|
||||
print("~s ~s", [Family, protocol_version(Version)]).
|
||||
print("~s ~s", [Family, protocol_version(Version)]);
|
||||
protocol(Protocol) when is_binary(Protocol) ->
|
||||
print("~s", [Protocol]).
|
||||
|
||||
protocol_version(Arbitrary)
|
||||
when is_list(Arbitrary) -> Arbitrary;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
-define(TABLE_CONSUMER, rabbit_stream_consumer_created).
|
||||
-define(TABLE_PUBLISHER, rabbit_stream_publisher_created).
|
||||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
start(_Type, _Args) ->
|
||||
rabbit_stream_metrics:init(),
|
||||
rabbit_stream_sup:start_link().
|
||||
|
||||
host() ->
|
||||
|
|
@ -43,7 +44,8 @@ hostname_from_node() ->
|
|||
[_, Hostname] ->
|
||||
Hostname;
|
||||
[_] ->
|
||||
rabbit_data_coercion:to_binary(inet:gethostname())
|
||||
{ok, H} = inet:gethostname(),
|
||||
rabbit_data_coercion:to_binary(H)
|
||||
end.
|
||||
|
||||
port() ->
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ init([Conf]) ->
|
|||
{ok, #state{configuration = Conf}}.
|
||||
|
||||
-spec create(binary(), binary(), #{binary() => binary()}, binary()) ->
|
||||
{ok, map()} | {error, reference_already_exists} | {error, internal_error}.
|
||||
{ok, map()} | {error, reference_already_exists} | {error, internal_error}
|
||||
| {error, validation_failed}.
|
||||
create(VirtualHost, Reference, Arguments, Username) ->
|
||||
gen_server:call(?MODULE, {create, VirtualHost, Reference, Arguments, Username}).
|
||||
|
||||
|
|
@ -47,12 +48,14 @@ delete(VirtualHost, Reference, Username) ->
|
|||
lookup_leader(VirtualHost, Stream) ->
|
||||
gen_server:call(?MODULE, {lookup_leader, VirtualHost, Stream}).
|
||||
|
||||
-spec lookup_local_member(binary(), binary()) -> {ok, pid()} | {error, not_found}.
|
||||
-spec lookup_local_member(binary(), binary()) -> {ok, pid()}
|
||||
| {error, not_found} | {error, not_available}.
|
||||
lookup_local_member(VirtualHost, Stream) ->
|
||||
gen_server:call(?MODULE, {lookup_local_member, VirtualHost, Stream}).
|
||||
|
||||
-spec topology(binary(), binary()) ->
|
||||
{ok, #{leader_node => pid(), replica_nodes => [pid()]}} | {error, stream_not_found}.
|
||||
{ok, #{leader_node => undefined | pid(), replica_nodes => [pid()]}}
|
||||
| {error, stream_not_found} | {error, stream_not_available}.
|
||||
topology(VirtualHost, Stream) ->
|
||||
gen_server:call(?MODULE, {topology, VirtualHost, Stream}).
|
||||
|
||||
|
|
@ -116,19 +119,31 @@ handle_call({create, VirtualHost, Reference, Arguments, Username}, _From, State)
|
|||
none, true, false, none, StreamQueueArguments,
|
||||
VirtualHost, #{user => Username}, rabbit_stream_queue
|
||||
),
|
||||
try
|
||||
case rabbit_stream_queue:declare(Q0, node()) of
|
||||
{new, Q} ->
|
||||
{reply, {ok, amqqueue:get_type_state(Q)}, State};
|
||||
{existing, _} ->
|
||||
{reply, {error, reference_already_exists}, State};
|
||||
{error, Err} ->
|
||||
rabbit_log:warning("Error while creating ~p stream, ~p~n", [Reference, Err]),
|
||||
{reply, {error, internal_error}, State}
|
||||
end
|
||||
catch
|
||||
exit:Error ->
|
||||
rabbit_log:info("Error while creating ~p stream, ~p~n", [Reference, Error]),
|
||||
case rabbit_amqqueue:with(
|
||||
Name,
|
||||
fun(Q) ->
|
||||
ok = rabbit_amqqueue:assert_equivalence(Q, true, false, StreamQueueArguments, none)
|
||||
end) of
|
||||
ok ->
|
||||
{reply, {error, reference_already_exists}, State};
|
||||
{error, not_found} ->
|
||||
try
|
||||
case rabbit_stream_queue:declare(Q0, node()) of
|
||||
{new, Q} ->
|
||||
{reply, {ok, amqqueue:get_type_state(Q)}, State};
|
||||
{existing, _} ->
|
||||
{reply, {error, reference_already_exists}, State};
|
||||
{error, Err} ->
|
||||
rabbit_log:warning("Error while creating ~p stream, ~p~n", [Reference, Err]),
|
||||
{reply, {error, internal_error}, State}
|
||||
end
|
||||
catch
|
||||
exit:Error ->
|
||||
rabbit_log:info("Error while creating ~p stream, ~p~n", [Reference, Error]),
|
||||
{reply, {error, internal_error}, State}
|
||||
end;
|
||||
{error, {absent, _, Reason}} ->
|
||||
rabbit_log:warning("Error while creating ~p stream, ~p~n", [Reference, Reason]),
|
||||
{reply, {error, internal_error}, State}
|
||||
end;
|
||||
error ->
|
||||
|
|
@ -201,9 +216,7 @@ handle_call({lookup_local_member, VirtualHost, Stream}, _From, State) ->
|
|||
{error, not_found};
|
||||
_ ->
|
||||
{error, not_available}
|
||||
end;
|
||||
_ ->
|
||||
{error, not_found}
|
||||
end
|
||||
end,
|
||||
{reply, Res, State};
|
||||
handle_call({topology, VirtualHost, Stream}, _From, State) ->
|
||||
|
|
@ -240,9 +253,7 @@ handle_call({topology, VirtualHost, Stream}, _From, State) ->
|
|||
{error, stream_not_found};
|
||||
_ ->
|
||||
{error, stream_not_available}
|
||||
end;
|
||||
_ ->
|
||||
{error, stream_not_found}
|
||||
end
|
||||
end,
|
||||
{reply, Res, State};
|
||||
handle_call(which_children, _From, State) ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
%% The contents of this file are subject to the Mozilla Public License
|
||||
%% Version 2.0 (the "License"); you may not use this file except in
|
||||
%% compliance with the License. You may obtain a copy of the License
|
||||
%% at https://www.mozilla.org/en-US/MPL/2.0/
|
||||
%%
|
||||
%% Software distributed under the License is distributed on an "AS IS"
|
||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%% the License for the specific language governing rights and
|
||||
%% limitations under the License.
|
||||
%%
|
||||
%% The Original Code is RabbitMQ.
|
||||
%%
|
||||
%% The Initial Developer of the Original Code is Pivotal Software, Inc.
|
||||
%% Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_metrics).
|
||||
|
||||
-include("rabbit_stream_metrics.hrl").
|
||||
|
||||
%% API
|
||||
-export([init/0]).
|
||||
-export([consumer_created/6, consumer_updated/6, consumer_cancelled/3]).
|
||||
-export([publisher_created/4, publisher_updated/7, publisher_deleted/3]).
|
||||
|
||||
init() ->
|
||||
rabbit_core_metrics:create_table({?TABLE_CONSUMER, set}),
|
||||
rabbit_core_metrics:create_table({?TABLE_PUBLISHER, set}),
|
||||
ok.
|
||||
|
||||
consumer_created(Connection, StreamResource, SubscriptionId, Credits, MessageCount, Offset) ->
|
||||
Values = [{credits, Credits}, {consumed, MessageCount}, {offset, Offset}],
|
||||
ets:insert(?TABLE_CONSUMER, {{StreamResource, Connection, SubscriptionId}, Values}),
|
||||
ok.
|
||||
|
||||
consumer_updated(Connection, StreamResource, SubscriptionId, Credits, MessageCount, Offset) ->
|
||||
Values = [{credits, Credits}, {consumed, MessageCount}, {offset, Offset}],
|
||||
ets:insert(?TABLE_CONSUMER, {{StreamResource, Connection, SubscriptionId}, Values}),
|
||||
ok.
|
||||
|
||||
consumer_cancelled(Connection, StreamResource, SubscriptionId) ->
|
||||
ets:delete(?TABLE_CONSUMER, {StreamResource, Connection, SubscriptionId}),
|
||||
ok.
|
||||
|
||||
publisher_created(Connection, StreamResource, PublisherId, Reference) ->
|
||||
Values = [
|
||||
{reference, format_publisher_reference(Reference)},
|
||||
{published, 0}, {confirmed, 0}, {errored, 0}],
|
||||
ets:insert(?TABLE_PUBLISHER, {{StreamResource, Connection, PublisherId}, Values}),
|
||||
ok.
|
||||
|
||||
publisher_updated(Connection, StreamResource, PublisherId, Reference, Published, Confirmed, Errored) ->
|
||||
Values = [
|
||||
{reference, format_publisher_reference(Reference)},
|
||||
{published, Published}, {confirmed, Confirmed}, {errored, Errored}],
|
||||
ets:insert(?TABLE_PUBLISHER, {{StreamResource, Connection, PublisherId}, Values}),
|
||||
ok.
|
||||
|
||||
publisher_deleted(Connection, StreamResource, PublisherId) ->
|
||||
ets:delete(?TABLE_PUBLISHER, {StreamResource, Connection, PublisherId}),
|
||||
ok.
|
||||
|
||||
format_publisher_reference(undefined) ->
|
||||
<<"">>;
|
||||
format_publisher_reference(Ref) when is_binary(Ref) ->
|
||||
Ref.
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
%% The contents of this file are subject to the Mozilla Public License
|
||||
%% Version 2.0 (the "License"); you may not use this file except in
|
||||
%% compliance with the License. You may obtain a copy of the License
|
||||
%% at https://www.mozilla.org/en-US/MPL/2.0/
|
||||
%%
|
||||
%% Software distributed under the License is distributed on an "AS IS"
|
||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%% the License for the specific language governing rights and
|
||||
%% limitations under the License.
|
||||
%%
|
||||
%% The Original Code is RabbitMQ.
|
||||
%%
|
||||
%% The Initial Developer of the Original Code is Pivotal Software, Inc.
|
||||
%% Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_metrics_gc).
|
||||
|
||||
-include_lib("rabbitmq_stream/include/rabbit_stream_metrics.hrl").
|
||||
|
||||
-record(state, {timer,
|
||||
interval
|
||||
}).
|
||||
|
||||
-export([start_link/0]).
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
|
||||
code_change/3]).
|
||||
|
||||
-spec start_link() -> rabbit_types:ok_pid_or_error().
|
||||
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
|
||||
init(_) ->
|
||||
Interval = rabbit_misc:get_env(rabbit, core_metrics_gc_interval, 120000),
|
||||
{ok, start_timer(#state{interval = Interval})}.
|
||||
|
||||
handle_call(which_children, _From, State) ->
|
||||
{reply, [], State}.
|
||||
|
||||
handle_cast(_Request, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_info(start_gc, State) ->
|
||||
GbSet = gb_sets:from_list(rabbit_amqqueue:list_names()),
|
||||
gc_process_and_entity(?TABLE_CONSUMER, GbSet),
|
||||
gc_process_and_entity(?TABLE_PUBLISHER, GbSet),
|
||||
{noreply, start_timer(State)}.
|
||||
|
||||
terminate(_Reason, #state{timer = TRef}) ->
|
||||
erlang:cancel_timer(TRef),
|
||||
ok.
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
start_timer(#state{interval = Interval} = St) ->
|
||||
TRef = erlang:send_after(Interval, self(), start_gc),
|
||||
St#state{timer = TRef}.
|
||||
|
||||
gc_process_and_entity(Table, GbSet) ->
|
||||
ets:foldl(fun({{Id, Pid, _} = Key, _}, none) ->
|
||||
gc_process_and_entity(Id, Pid, Table, Key, GbSet)
|
||||
end, none, Table).
|
||||
|
||||
gc_process_and_entity(Id, Pid, Table, Key, GbSet) ->
|
||||
case rabbit_misc:is_process_alive(Pid) andalso gb_sets:is_member(Id, GbSet) of
|
||||
true ->
|
||||
none;
|
||||
false ->
|
||||
ets:delete(Table, Key),
|
||||
none
|
||||
end.
|
||||
|
||||
|
|
@ -28,7 +28,8 @@
|
|||
publisher_id :: publisher_id(),
|
||||
stream :: stream(),
|
||||
reference :: 'undefined' | publisher_reference(),
|
||||
leader :: pid()
|
||||
leader :: pid(),
|
||||
message_counters :: atomics:atomics_ref()
|
||||
}).
|
||||
|
||||
-record(consumer, {
|
||||
|
|
@ -38,7 +39,8 @@
|
|||
subscription_id :: subscription_id(),
|
||||
segment :: osiris_log:state(),
|
||||
credit :: integer(),
|
||||
stream :: stream()
|
||||
stream :: stream(),
|
||||
counters :: atomics:atomics_ref()
|
||||
}).
|
||||
|
||||
-record(stream_connection_state, {
|
||||
|
|
@ -48,7 +50,7 @@
|
|||
}).
|
||||
|
||||
-record(stream_connection, {
|
||||
name :: string(),
|
||||
name :: binary(),
|
||||
%% server host
|
||||
host,
|
||||
%% client host
|
||||
|
|
@ -71,12 +73,12 @@
|
|||
virtual_host :: 'undefined' | binary(),
|
||||
connection_step :: atom(), % tcp_connected, peer_properties_exchanged, authenticating, authenticated, tuning, tuned, opened, failure, closing, closing_done
|
||||
frame_max :: integer(),
|
||||
heartbeat :: integer(),
|
||||
heartbeat :: undefined | integer(),
|
||||
heartbeater :: any(),
|
||||
client_properties = #{} :: #{binary() => binary()},
|
||||
monitors = #{} :: #{reference() => stream()},
|
||||
stats_timer :: reference(),
|
||||
send_file_oct :: atomics:atomics_ref()
|
||||
stats_timer :: undefined | reference(),
|
||||
send_file_oct :: atomics:atomics_ref() % number of bytes sent with send_file (for metrics)
|
||||
}).
|
||||
|
||||
-record(configuration, {
|
||||
|
|
@ -92,6 +94,7 @@
|
|||
peer_host, ssl, peer_cert_subject, peer_cert_issuer,
|
||||
peer_cert_validity, auth_mechanism, ssl_protocol,
|
||||
ssl_key_exchange, ssl_cipher, ssl_hash, protocol, user, vhost,
|
||||
protocol,
|
||||
timeout, frame_max, channel_max, client_properties, connected_at,
|
||||
node, user_who_performed_action]).
|
||||
-define(SIMPLE_METRICS, [pid, recv_oct, send_oct, reductions]).
|
||||
|
|
@ -187,6 +190,36 @@ has_credits(CreditReference) ->
|
|||
has_enough_credits_to_unblock(CreditReference, CreditsRequiredForUnblocking) ->
|
||||
atomics:get(CreditReference, 1) > CreditsRequiredForUnblocking.
|
||||
|
||||
increase_messages_consumed(Counters, Count) ->
|
||||
atomics:add(Counters, 1, Count).
|
||||
|
||||
set_consumer_offset(Counters, Offset) ->
|
||||
atomics:put(Counters, 2, Offset).
|
||||
|
||||
increase_messages_published(Counters, Count) ->
|
||||
atomics:add(Counters, 1, Count).
|
||||
|
||||
increase_messages_confirmed(Counters, Count) ->
|
||||
atomics:add(Counters, 2, Count).
|
||||
|
||||
increase_messages_errored(Counters, Count) ->
|
||||
atomics:add(Counters, 3, Count).
|
||||
|
||||
messages_consumed(Counters) ->
|
||||
atomics:get(Counters, 1).
|
||||
|
||||
consumer_offset(Counters) ->
|
||||
atomics:get(Counters, 2).
|
||||
|
||||
messages_published(Counters) ->
|
||||
atomics:get(Counters, 1).
|
||||
|
||||
messages_confirmed(Counters) ->
|
||||
atomics:get(Counters, 2).
|
||||
|
||||
messages_errored(Counters) ->
|
||||
atomics:get(Counters, 3).
|
||||
|
||||
listen_loop_pre_auth(Transport, #stream_connection{socket = S} = Connection, State,
|
||||
#configuration{frame_max = FrameMax, heartbeat = Heartbeat} = Configuration) ->
|
||||
{OK, Closed, Error} = Transport:messages(),
|
||||
|
|
@ -248,7 +281,7 @@ close(Transport, S) ->
|
|||
listen_loop_post_auth(Transport, #stream_connection{socket = S,
|
||||
stream_subscriptions = StreamSubscriptions, credits = Credits,
|
||||
heartbeater = Heartbeater, monitors = Monitors, client_properties = ClientProperties,
|
||||
publisher_to_ids = PublisherRefToIds,
|
||||
publishers = Publishers, publisher_to_ids = PublisherRefToIds,
|
||||
send_file_oct = SendFileOct} = Connection0,
|
||||
#stream_connection_state{consumers = Consumers, blocked = Blocked} = State,
|
||||
#configuration{credits_required_for_unblocking = CreditsRequiredForUnblocking} = Configuration) ->
|
||||
|
|
@ -322,6 +355,8 @@ listen_loop_post_auth(Transport, #stream_connection{socket = S,
|
|||
Transport:send(S, [<<FrameSize:32, ?COMMAND_PUBLISH_CONFIRM:16, ?VERSION_0:16>>,
|
||||
<<CurrentPublisherId:8>>,
|
||||
<<Count:32>>, PublishingIds]),
|
||||
#{CurrentPublisherId := #publisher{message_counters = Counters}} = Publishers,
|
||||
increase_messages_confirmed(Counters, Count),
|
||||
{OtherPublisherId, <<PublishingId:64>>, 1}
|
||||
end
|
||||
end, {FirstPublisherId, <<>>, 0}, CorrelationList),
|
||||
|
|
@ -329,6 +364,8 @@ listen_loop_post_auth(Transport, #stream_connection{socket = S,
|
|||
Transport:send(S, [<<FrameSize:32, ?COMMAND_PUBLISH_CONFIRM:16, ?VERSION_0:16>>,
|
||||
<<LastPublisherId:8>>,
|
||||
<<LastCount:32>>, LastPublishingIds]),
|
||||
#{LastPublisherId := #publisher{message_counters = Counters}} = Publishers,
|
||||
increase_messages_confirmed(Counters, LastCount),
|
||||
CorrelationIdCount = length(CorrelationList),
|
||||
add_credits(Credits, CorrelationIdCount),
|
||||
State1 = case Blocked of
|
||||
|
|
@ -356,6 +393,8 @@ listen_loop_post_auth(Transport, #stream_connection{socket = S,
|
|||
Transport:send(S, [<<FrameSize:32, ?COMMAND_PUBLISH_CONFIRM:16, ?VERSION_0:16>>,
|
||||
<<PublisherId:8>>,
|
||||
<<PublishingIdCount:32>>, PubIds]),
|
||||
#{PublisherId := #publisher{message_counters = Counters}} = Publishers,
|
||||
increase_messages_confirmed(Counters, PublishingIdCount),
|
||||
add_credits(Credits, PublishingIdCount),
|
||||
State1 = case Blocked of
|
||||
true ->
|
||||
|
|
@ -726,14 +765,13 @@ notify_auth_result(Username, AuthResult, ExtraProps, Connection, ConnectionState
|
|||
rabbit_event:notify(AuthResult, [P || {_, V} = P <- EventProps, V =/= '']).
|
||||
|
||||
handle_frame_post_auth(Transport, #stream_connection{
|
||||
virtual_host = VirtualHost, user = User,
|
||||
user = User,
|
||||
publishers = Publishers0, publisher_to_ids = RefIds0} = Connection0, State,
|
||||
<<?COMMAND_DECLARE_PUBLISHER:16, ?VERSION_0:16, CorrelationId:32,
|
||||
PublisherId:8,
|
||||
ReferenceSize:16, Reference:ReferenceSize/binary,
|
||||
StreamSize:16, Stream:StreamSize/binary>>, Rest) ->
|
||||
case rabbit_stream_utils:check_write_permitted(
|
||||
#resource{name = Stream, kind = queue, virtual_host = VirtualHost},
|
||||
case rabbit_stream_utils:check_write_permitted(stream_r(Stream, Connection0),
|
||||
User,
|
||||
#{}) of
|
||||
ok ->
|
||||
|
|
@ -751,8 +789,11 @@ handle_frame_post_auth(Transport, #stream_connection{
|
|||
Publisher = #publisher{publisher_id = PublisherId,
|
||||
stream = Stream,
|
||||
reference = PublisherReference,
|
||||
leader = ClusterLeader},
|
||||
leader = ClusterLeader,
|
||||
message_counters = atomics:new(3, [{signed, false}])},
|
||||
response(Transport, Connection0, ?COMMAND_DECLARE_PUBLISHER, CorrelationId, ?RESPONSE_CODE_OK),
|
||||
rabbit_stream_metrics:publisher_created(
|
||||
self(), stream_r(Stream, Connection1), PublisherId, PublisherReference),
|
||||
{Connection1#stream_connection{publishers = Publishers0#{PublisherId => Publisher},
|
||||
publisher_to_ids = RefIds1}, State, Rest}
|
||||
end;
|
||||
|
|
@ -775,6 +816,7 @@ handle_frame_post_auth(Transport, #stream_connection{publishers = Publishers,
|
|||
publisher_to_ids = maps:remove({Stream, Ref}, PubToIds)},
|
||||
Connection2 = maybe_clean_connection_from_stream(Stream, Connection1),
|
||||
response(Transport, Connection1, ?COMMAND_DELETE_PUBLISHER, CorrelationId, ?RESPONSE_CODE_OK),
|
||||
rabbit_stream_metrics:publisher_deleted(self(), stream_r(Stream, Connection2), PublisherId),
|
||||
{Connection2, State, Rest};
|
||||
_ ->
|
||||
response(Transport, Connection0, ?COMMAND_DELETE_PUBLISHER, CorrelationId, ?RESPONSE_CODE_PUBLISHER_DOES_NOT_EXIST),
|
||||
|
|
@ -788,7 +830,9 @@ handle_frame_post_auth(Transport, #stream_connection{
|
|||
MessageCount:32, Messages/binary>>, Rest) ->
|
||||
case Publishers of
|
||||
#{PublisherId := Publisher} ->
|
||||
#publisher{stream = Stream, reference = Reference, leader = Leader} = Publisher,
|
||||
#publisher{stream = Stream, reference = Reference, leader = Leader,
|
||||
message_counters = Counters} = Publisher,
|
||||
increase_messages_published(Counters, MessageCount),
|
||||
case rabbit_stream_utils:check_write_permitted(
|
||||
#resource{name = Stream, kind = queue, virtual_host = VirtualHost},
|
||||
User,
|
||||
|
|
@ -803,6 +847,7 @@ handle_frame_post_auth(Transport, #stream_connection{
|
|||
Transport:send(S, [<<FrameSize:32, ?COMMAND_PUBLISH_ERROR:16, ?VERSION_0:16,
|
||||
PublisherId:8,
|
||||
MessageCount:32, Details/binary>>]),
|
||||
increase_messages_errored(Counters, MessageCount),
|
||||
{Connection, State, Rest}
|
||||
end;
|
||||
_ ->
|
||||
|
|
@ -856,11 +901,13 @@ handle_frame_post_auth(Transport, #stream_connection{socket = Socket,
|
|||
{{timestamp, Timestamp}, Crdt}
|
||||
end,
|
||||
{ok, Segment} = osiris:init_reader(LocalMemberPid, OffsetSpec),
|
||||
ConsumerCounters = atomics:new(2, [{signed, false}]),
|
||||
ConsumerState = #consumer{
|
||||
member_pid = LocalMemberPid, offset = OffsetSpec, subscription_id = SubscriptionId, socket = Socket,
|
||||
segment = Segment,
|
||||
credit = Credit,
|
||||
stream = Stream
|
||||
stream = Stream,
|
||||
counters = ConsumerCounters
|
||||
},
|
||||
|
||||
Connection1 = maybe_monitor_stream(LocalMemberPid, Stream, Connection),
|
||||
|
|
@ -881,6 +928,10 @@ handle_frame_post_auth(Transport, #stream_connection{socket = Socket,
|
|||
_ ->
|
||||
StreamSubscriptions#{Stream => [SubscriptionId]}
|
||||
end,
|
||||
rabbit_stream_metrics:consumer_created(
|
||||
self(), stream_r(Stream, Connection1), SubscriptionId, Credit1,
|
||||
messages_consumed(ConsumerCounters),
|
||||
consumer_offset(ConsumerCounters)),
|
||||
{Connection1#stream_connection{stream_subscriptions = StreamSubscriptions1}, State#stream_connection_state{consumers = Consumers1}, Rest}
|
||||
end
|
||||
end;
|
||||
|
|
@ -911,6 +962,7 @@ handle_frame_post_auth(Transport, #stream_connection{stream_subscriptions = Stre
|
|||
Connection1 = Connection#stream_connection{stream_subscriptions = StreamSubscriptions1},
|
||||
Consumers1 = maps:remove(SubscriptionId, Consumers),
|
||||
Connection2 = maybe_clean_connection_from_stream(Stream, Connection1),
|
||||
rabbit_stream_metrics:consumer_cancelled(self(), stream_r(Stream, Connection2), SubscriptionId),
|
||||
response_ok(Transport, Connection, ?COMMAND_SUBSCRIBE, CorrelationId),
|
||||
{Connection2, State#stream_connection_state{consumers = Consumers1}, Rest}
|
||||
end;
|
||||
|
|
@ -1177,8 +1229,17 @@ handle_frame_post_auth(Transport, Connection, State, Frame, Rest) ->
|
|||
frame(Transport, Connection, CloseFrame),
|
||||
{Connection#stream_connection{connection_step = close_sent}, State, Rest}.
|
||||
|
||||
notify_connection_closed(#stream_connection{name = Name} = Connection, ConnectionState) ->
|
||||
notify_connection_closed(#stream_connection{
|
||||
name = Name,
|
||||
publishers = Publishers} = Connection,
|
||||
#stream_connection_state{consumers = Consumers} = ConnectionState) ->
|
||||
rabbit_core_metrics:connection_closed(self()),
|
||||
[rabbit_stream_metrics:consumer_cancelled(
|
||||
self(), stream_r(S, Connection), SubId) || #consumer{stream = S, subscription_id = SubId}
|
||||
<- maps:values(Consumers)],
|
||||
[rabbit_stream_metrics:publisher_deleted(self(), stream_r(S, Connection), PubId)
|
||||
|| #publisher{stream = S, publisher_id = PubId} <- maps:values(Publishers)
|
||||
],
|
||||
ClientProperties = i(client_properties, Connection, ConnectionState),
|
||||
EventProperties = [{name, Name},
|
||||
{pid, self()},
|
||||
|
|
@ -1198,6 +1259,9 @@ handle_frame_post_close(_Transport, Connection, State, Frame, Rest) ->
|
|||
rabbit_log:warning("ignored frame on close ~p ~p.~n", [Frame, Rest]),
|
||||
{Connection, State, Rest}.
|
||||
|
||||
stream_r(Stream, #stream_connection{virtual_host = VHost}) ->
|
||||
#resource{name = Stream, kind = queue, virtual_host = VHost}.
|
||||
|
||||
clean_state_after_stream_deletion_or_failure(Stream,
|
||||
#stream_connection{stream_subscriptions = StreamSubscriptions,
|
||||
publishers = Publishers,
|
||||
|
|
@ -1207,6 +1271,9 @@ clean_state_after_stream_deletion_or_failure(Stream,
|
|||
{SubscriptionsCleaned, C1, S1} = case stream_has_subscriptions(Stream, C0) of
|
||||
true ->
|
||||
#{Stream := SubscriptionIds} = StreamSubscriptions,
|
||||
[rabbit_stream_metrics:consumer_cancelled(
|
||||
self(), stream_r(Stream, C0), SubId)
|
||||
|| SubId <- SubscriptionIds],
|
||||
{true, C0#stream_connection{
|
||||
stream_subscriptions = maps:remove(Stream, StreamSubscriptions)
|
||||
}, S0#stream_connection_state{consumers = maps:without(SubscriptionIds, Consumers)}};
|
||||
|
|
@ -1219,6 +1286,7 @@ clean_state_after_stream_deletion_or_failure(Stream,
|
|||
fun(PubId, #publisher{stream = S, reference = Ref}, {Pubs, PubToIds}) ->
|
||||
case S of
|
||||
Stream ->
|
||||
rabbit_stream_metrics:publisher_deleted(self(), stream_r(S, C1), PubId),
|
||||
{maps:remove(PubId, Pubs), maps:remove({Stream, Ref}, PubToIds)};
|
||||
_ ->
|
||||
{Pubs, PubToIds}
|
||||
|
|
@ -1325,12 +1393,15 @@ subscription_exists(StreamSubscriptions, SubscriptionId) ->
|
|||
SubscriptionIds = lists:flatten(maps:values(StreamSubscriptions)),
|
||||
lists:any(fun(Id) -> Id =:= SubscriptionId end, SubscriptionIds).
|
||||
|
||||
send_file_callback(Transport, #consumer{socket = S, subscription_id = SubscriptionId}, Counter) ->
|
||||
fun(_Header, Size) ->
|
||||
send_file_callback(Transport, #consumer{socket = S, subscription_id = SubscriptionId, counters = Counters}, Counter) ->
|
||||
fun(#{chunk_id := FirstOffsetInChunk,
|
||||
num_entries := NumEntries}, Size) ->
|
||||
FrameSize = 2 + 2 + 1 + Size,
|
||||
FrameBeginning = <<FrameSize:32, ?COMMAND_DELIVER:16, ?VERSION_0:16, SubscriptionId:8/unsigned>>,
|
||||
Transport:send(S, FrameBeginning),
|
||||
atomics:add(Counter, 1, Size)
|
||||
atomics:add(Counter, 1, Size),
|
||||
increase_messages_consumed(Counters, NumEntries),
|
||||
set_consumer_offset(Counters, FirstOffsetInChunk)
|
||||
end.
|
||||
|
||||
send_chunks(Transport, #consumer{credit = Credit} = State, Counter) ->
|
||||
|
|
@ -1366,13 +1437,24 @@ send_chunks(Transport, #consumer{socket = S} = State, Segment, Credit, Retry, Co
|
|||
end
|
||||
end.
|
||||
|
||||
emit_stats(Connection, ConnectionState) ->
|
||||
emit_stats(#stream_connection{publishers = Publishers} = Connection,
|
||||
#stream_connection_state{consumers = Consumers} = ConnectionState) ->
|
||||
[{_, Pid}, {_, Recv_oct}, {_, Send_oct}, {_, Reductions}] = I
|
||||
= infos(?SIMPLE_METRICS, Connection, ConnectionState),
|
||||
Infos = infos(?OTHER_METRICS, Connection, ConnectionState),
|
||||
rabbit_core_metrics:connection_stats(Pid, Infos),
|
||||
rabbit_core_metrics:connection_stats(Pid, Recv_oct, Send_oct, Reductions),
|
||||
rabbit_event:notify(connection_stats, Infos ++ I),
|
||||
[rabbit_stream_metrics:consumer_updated(
|
||||
self(), stream_r(S, Connection), Id, Credit,
|
||||
messages_consumed(Counters), consumer_offset(Counters))
|
||||
|| #consumer{stream = S, subscription_id = Id,
|
||||
credit = Credit, counters = Counters} <- maps:values(Consumers)],
|
||||
[rabbit_stream_metrics:publisher_updated(
|
||||
self(), stream_r(S, Connection), Id, PubReference,
|
||||
messages_published(Counters), messages_confirmed(Counters), messages_errored(Counters))
|
||||
|| #publisher{stream = S, publisher_id = Id, reference = PubReference,
|
||||
message_counters = Counters} <- maps:values(Publishers)],
|
||||
Connection1 = rabbit_event:reset_stats_timer(Connection, #stream_connection.stats_timer),
|
||||
ensure_stats_timer(Connection1).
|
||||
|
||||
|
|
@ -1427,7 +1509,7 @@ i(ssl_key_exchange, _, _) -> '';
|
|||
i(ssl_cipher, _, _) -> '';
|
||||
i(ssl_hash, _, _) -> '';
|
||||
i(channels, _, _) -> 0;
|
||||
i(protocol, _, _) -> {<<"stream">>, ""};
|
||||
i(protocol, _, _) -> <<"stream">>;
|
||||
i(user_who_performed_action, Connection, ConnectionState) -> i(user, Connection, ConnectionState);
|
||||
i(user, #stream_connection{user = U}, _) -> U#user.username;
|
||||
i(vhost, #stream_connection{virtual_host = VirtualHost}, _) -> VirtualHost;
|
||||
|
|
|
|||
|
|
@ -43,8 +43,14 @@ init([]) ->
|
|||
type => worker,
|
||||
start => {rabbit_stream_manager, start_link, [OsirisConf]}},
|
||||
|
||||
MetricsGc = #{
|
||||
id => rabbit_stream_metrics_gc_sup,
|
||||
type => worker,
|
||||
start => {rabbit_stream_metrics_gc, start_link, []}
|
||||
},
|
||||
|
||||
{ok, {{one_for_all, 10, 10},
|
||||
[StreamManager] ++
|
||||
[StreamManager, MetricsGc] ++
|
||||
listener_specs(fun tcp_listener_spec/1,
|
||||
[SocketOpts, ServerConfiguration, NumTcpAcceptors], Listeners)}}.
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
-module(rabbit_stream_SUITE).
|
||||
|
||||
-include_lib("common_test/include/ct.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
-include("rabbit_stream.hrl").
|
||||
-include("rabbit_stream_metrics.hrl").
|
||||
|
||||
-compile(export_all).
|
||||
|
||||
|
|
@ -29,7 +31,7 @@ all() ->
|
|||
|
||||
groups() ->
|
||||
[
|
||||
{single_node, [], [test_stream]},
|
||||
{single_node, [], [test_stream, test_gc_consumers, test_gc_publishers]},
|
||||
{cluster, [], [test_stream, java]}
|
||||
].
|
||||
|
||||
|
|
@ -43,6 +45,10 @@ end_per_suite(Config) ->
|
|||
init_per_group(single_node, Config) ->
|
||||
Config1 = rabbit_ct_helpers:set_config(Config, [{rmq_nodes_clustered, false}]),
|
||||
rabbit_ct_helpers:run_setup_steps(Config1,
|
||||
[fun(StepConfig) ->
|
||||
rabbit_ct_helpers:merge_app_env(StepConfig,
|
||||
{rabbit, [{core_metrics_gc_interval, 1000}]})
|
||||
end] ++
|
||||
rabbit_ct_broker_helpers:setup_steps());
|
||||
init_per_group(cluster = Group, Config) ->
|
||||
Config1 = rabbit_ct_helpers:set_config(Config, [{rmq_nodes_clustered, true}]),
|
||||
|
|
@ -76,6 +82,55 @@ test_stream(Config) ->
|
|||
test_server(Port),
|
||||
ok.
|
||||
|
||||
test_gc_consumers(Config) ->
|
||||
Pid = spawn(fun() -> ok end),
|
||||
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_stream_metrics, consumer_created,
|
||||
[Pid, #resource{name = <<"test">>, kind = queue, virtual_host = <<"/">>}, 0, 10, 0, 0]
|
||||
),
|
||||
ok = wait_until(fun() -> consumer_count(Config) == 0 end),
|
||||
ok.
|
||||
|
||||
test_gc_publishers(Config) ->
|
||||
Pid = spawn(fun() -> ok end),
|
||||
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_stream_metrics, publisher_created,
|
||||
[Pid, #resource{name = <<"test">>, kind = queue, virtual_host = <<"/">>}, 0, <<"ref">>]
|
||||
),
|
||||
ok = wait_until(fun() -> publisher_count(Config) == 0 end),
|
||||
ok.
|
||||
|
||||
wait_until(Predicate) ->
|
||||
Fun = fun(Pid, Fun) ->
|
||||
case Predicate() of
|
||||
true ->
|
||||
Pid ! done,
|
||||
ok;
|
||||
_ ->
|
||||
timer:sleep(100),
|
||||
Fun(Pid, Fun)
|
||||
end
|
||||
end,
|
||||
CurrentPid = self(),
|
||||
Pid = spawn(fun() -> Fun(CurrentPid, Fun) end),
|
||||
Result = receive
|
||||
done ->
|
||||
ok
|
||||
after
|
||||
5000 ->
|
||||
failed
|
||||
end,
|
||||
exit(Pid, kill),
|
||||
Result.
|
||||
|
||||
consumer_count(Config) ->
|
||||
ets_count(Config, ?TABLE_CONSUMER).
|
||||
|
||||
publisher_count(Config) ->
|
||||
ets_count(Config, ?TABLE_PUBLISHER).
|
||||
|
||||
ets_count(Config, Table) ->
|
||||
Info = rabbit_ct_broker_helpers:rpc(Config, 0, ets, info, [Table]),
|
||||
rabbit_misc:pget(size, Info).
|
||||
|
||||
java(Config) ->
|
||||
StreamPortNode1 = get_stream_port(Config, 0),
|
||||
StreamPortNode2 = get_stream_port(Config, 1),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
.eunit
|
||||
*.o
|
||||
*.beam
|
||||
*.plt
|
||||
erl_crash.dump
|
||||
.concrete/DEV_MODE
|
||||
|
||||
# rebar 2.x
|
||||
.rebar
|
||||
rel/example_project
|
||||
ebin/*.beam
|
||||
deps
|
||||
|
||||
# rebar 3
|
||||
.rebar3
|
||||
_build/
|
||||
_checkouts/
|
||||
|
||||
erl_crash.dump
|
||||
.sw?
|
||||
.*.sw?
|
||||
*.beam
|
||||
/.erlang.mk/
|
||||
/cover/
|
||||
/deps/
|
||||
/ebin/
|
||||
/logs/
|
||||
/plugins/
|
||||
/xrefr
|
||||
elvis
|
||||
callgrind*
|
||||
ct.coverdata
|
||||
test/ct.cover.spec
|
||||
_build
|
||||
|
||||
rabbitmq_stream.d
|
||||
*.plt
|
||||
*.d
|
||||
|
||||
*.jar
|
||||
|
||||
|
||||
*~
|
||||
.sw?
|
||||
.*.sw?
|
||||
*.beam
|
||||
*.class
|
||||
*.dat
|
||||
*.dump
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.DS_Store
|
||||
\#~
|
||||
/.idea/
|
||||
/deps/
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open
|
||||
and welcoming community, we pledge to respect all people who contribute through reporting
|
||||
issues, posting feature requests, updating documentation, submitting pull requests or
|
||||
patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for
|
||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
||||
religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments,
|
||||
commits, code, wiki edits, issues, and other contributions that are not aligned to this
|
||||
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
|
||||
that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
|
||||
consistently applying these principles to every aspect of managing this project. Project
|
||||
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
|
||||
from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an
|
||||
individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
||||
contacting a project maintainer at [info@rabbitmq.com](mailto:info@rabbitmq.com). All complaints will
|
||||
be reviewed and investigated and will result in a response that is deemed necessary and
|
||||
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
|
||||
with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
[Contributor Covenant](http://contributor-covenant.org), version 1.3.0, available at
|
||||
[contributor-covenant.org/version/1/3/0/](http://contributor-covenant.org/version/1/3/0/)
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
## Overview
|
||||
|
||||
RabbitMQ projects use pull requests to discuss, collaborate on and accept code contributions.
|
||||
Pull requests is the primary place of discussing code changes.
|
||||
|
||||
## How to Contribute
|
||||
|
||||
The process is fairly standard:
|
||||
|
||||
* Fork the repository or repositories you plan on contributing to
|
||||
* Clone [RabbitMQ umbrella repository](https://github.com/rabbitmq/rabbitmq-public-umbrella)
|
||||
* `cd umbrella`, `make co`
|
||||
* Create a branch with a descriptive name in the relevant repositories
|
||||
* Make your changes, run tests, commit with a [descriptive message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), push to your fork
|
||||
* Submit pull requests with an explanation what has been changed and **why**
|
||||
* Submit a filled out and signed [Contributor Agreement](https://github.com/rabbitmq/ca#how-to-submit) if needed (see below)
|
||||
* Be patient. We will get to your pull request eventually
|
||||
|
||||
If what you are going to work on is a substantial change, please first ask the core team
|
||||
of their opinion on [RabbitMQ mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users).
|
||||
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
|
||||
|
||||
|
||||
## Contributor Agreement
|
||||
|
||||
If you want to contribute a non-trivial change, please submit a signed copy of our
|
||||
[Contributor Agreement](https://github.com/rabbitmq/ca#how-to-submit) around the time
|
||||
you submit your pull request. This will make it much easier (in some cases, possible)
|
||||
for the RabbitMQ team at Pivotal to merge your contribution.
|
||||
|
||||
|
||||
## Where to Ask Questions
|
||||
|
||||
If something isn't clear, feel free to ask on our [mailing list](https://groups.google.com/forum/#!forum/rabbitmq-users).
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
This package, the RabbitMQ server is licensed under the MPL 2.0. For the
|
||||
MPL 2.0, please see LICENSE-MPL-RabbitMQ.
|
||||
|
||||
If you have any questions regarding licensing, please contact us at
|
||||
info@rabbitmq.com.
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
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 http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
The Original Code is RabbitMQ.
|
||||
|
||||
The Initial Developer of the Original Code is Pivotal Software, Inc.
|
||||
Copyright (c) 2020 VMware, Inc or its affiliates. All rights reserved.
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
PROJECT = rabbitmq_stream_management
|
||||
PROJECT_DESCRIPTION = RabbitMQ Stream Management
|
||||
PROJECT_MOD = rabbit_stream_management
|
||||
|
||||
define PROJECT_ENV
|
||||
[
|
||||
]
|
||||
endef
|
||||
|
||||
|
||||
DEPS = rabbit rabbitmq_management rabbitmq_stream
|
||||
TEST_DEPS = rabbitmq_ct_helpers rabbitmq_ct_client_helpers
|
||||
|
||||
DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk
|
||||
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk
|
||||
|
||||
# FIXME: Use erlang.mk patched for RabbitMQ, while waiting for PRs to be
|
||||
# reviewed and merged.
|
||||
|
||||
ERLANG_MK_REPO = https://github.com/rabbitmq/erlang.mk.git
|
||||
ERLANG_MK_COMMIT = rabbitmq-tmp
|
||||
|
||||
include rabbitmq-components.mk
|
||||
include erlang.mk
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
= RabbitMQ Stream Plugin Management
|
||||
|
||||
== Project Maturity
|
||||
|
||||
The project is in early stages of development and is considered experimental.
|
||||
It is not ready for production use.
|
||||
|
||||
== Support
|
||||
|
||||
* For questions: https://groups.google.com/forum/#!forum/rabbitmq-users[RabbitMQ Users]
|
||||
* For bugs and feature requests: https://github.com/rabbitmq/rabbitmq-stream/issues[GitHub Issues]
|
||||
|
||||
The project is currently under development, there is no guarantee yet that it will be maintained and supported
|
||||
in the future (read: you are welcome to experiment with it and give feedback, but please do not base
|
||||
your whole business on it).
|
||||
|
||||
== Licensing
|
||||
|
||||
Released under the link:LICENSE-MPL-RabbitMQ[MPL 2.0].
|
||||
|
||||
== Copyright
|
||||
|
||||
(c) 2020 VMware, Inc. or its affiliates.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,59 @@
|
|||
dispatcher_add(function(sammy) {
|
||||
sammy.get('#/stream/connections', function() {
|
||||
renderStreamConnections();
|
||||
});
|
||||
sammy.get('#/stream/connections/:vhost/:name', function() {
|
||||
var vhost = esc(this.params['vhost']);
|
||||
var name = esc(this.params['name']);
|
||||
render({'connection': {path: '/stream/connections/'+ vhost + '/' + name,
|
||||
options: {ranges: ['data-rates-conn']}},
|
||||
'consumers': '/stream/connections/' + vhost + '/' + name + '/consumers',
|
||||
'publishers': '/stream/connections/' + vhost + '/' + name + '/publishers'},
|
||||
'streamConnection', '#/stream/connections');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
NAVIGATION['Stream'] = ['#/stream/connections', "monitoring"];
|
||||
|
||||
var ALL_STREAM_CONNECTION_COLUMNS =
|
||||
{'Overview': [['user', 'User name', true],
|
||||
['state', 'State', true]],
|
||||
'Details': [['protocol', 'Protocol', true],
|
||||
['frame_max', 'Frame max', false],
|
||||
['auth_mechanism', 'Auth mechanism', false],
|
||||
['client', 'Client', false]],
|
||||
'Network': [['from_client', 'From client', true],
|
||||
['to_client', 'To client', true],
|
||||
['heartbeat', 'Heartbeat', false],
|
||||
['connected_at', 'Connected at', false]]};
|
||||
|
||||
var DISABLED_STATS_STREAM_CONNECTION_COLUMNS =
|
||||
{'Overview': [['user', 'User name', true],
|
||||
['state', 'State', true]]};
|
||||
|
||||
COLUMNS['streamConnections'] = disable_stats?DISABLED_STATS_STREAM_CONNECTION_COLUMNS:ALL_STREAM_CONNECTION_COLUMNS;
|
||||
|
||||
var ALL_STREAM_CONNECTION_COLUMNS =
|
||||
{'Overview': [['user', 'User name', true],
|
||||
['state', 'State', true]],
|
||||
'Details': [['protocol', 'Protocol', true],
|
||||
['frame_max', 'Frame max', false],
|
||||
['auth_mechanism', 'Auth mechanism', false],
|
||||
['client', 'Client', false]],
|
||||
'Network': [['from_client', 'From client', true],
|
||||
['to_client', 'To client', true],
|
||||
['heartbeat', 'Heartbeat', false],
|
||||
['connected_at', 'Connected at', false]]};
|
||||
|
||||
function renderStreamConnections() {
|
||||
render({'connections': {path: url_pagination_template_context('stream/connections', 'streamConnections', 1, 100),
|
||||
options: {sort:true}}},
|
||||
'streamConnections', '#/stream/connections');
|
||||
}
|
||||
|
||||
function link_stream_conn(vhost, name, desc) {
|
||||
return _link_to(short_conn(name), '#/stream/connections/' + esc(vhost) + '/' + esc(name));
|
||||
}
|
||||
|
||||
RENDER_CALLBACKS['streamConnections'] = function() { renderStreamConnections() };
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
<h2>Connection <%= fmt_string(connection.name) %> <%= fmt_maybe_vhost(connection.vhost) %></h1>
|
||||
|
||||
<% if (!disable_stats) { %>
|
||||
<div class="section">
|
||||
<h2>Overview</h2>
|
||||
<div class="hider updatable">
|
||||
<%= data_rates('data-rates-conn', connection, 'Data rates') %>
|
||||
|
||||
<h3>Details</h3>
|
||||
<table class="facts facts-l">
|
||||
<% if (nodes_interesting) { %>
|
||||
<tr>
|
||||
<th>Node</th>
|
||||
<td><%= fmt_node(connection.node) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
<% if (connection.client_properties.connection_name) { %>
|
||||
<tr>
|
||||
<th>Client-provided name</th>
|
||||
<td><%= fmt_string(connection.client_properties.connection_name) %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<td><%= fmt_string(connection.user) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Protocol</th>
|
||||
<td><%= connection.protocol %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Connected at</th>
|
||||
<td><%= fmt_timestamp(connection.connected_at) %></td>
|
||||
</tr>
|
||||
|
||||
<% if (connection.auth_mechanism) { %>
|
||||
<tr>
|
||||
<th>Authentication</th>
|
||||
<td><%= connection.auth_mechanism %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</table>
|
||||
|
||||
<% if (connection.state) { %>
|
||||
<table class="facts">
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<td><%= fmt_object_state(connection) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Heartbeat</th>
|
||||
<td><%= fmt_time(connection.timeout, 's') %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Frame max</th>
|
||||
<td><%= connection.frame_max %> bytes</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<% } %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Publishers</h2>
|
||||
<div class="hider updatable">
|
||||
<%= format('streamPublishersList', {'publishers': publishers}) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Consumers</h2>
|
||||
<div class="hider updatable">
|
||||
<%= format('streamConsumersList', {'consumers': consumers}) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if (properties_size(connection.client_properties) > 0) { %>
|
||||
<div class="section-hidden">
|
||||
<h2>Client properties</h2>
|
||||
<div class="hider">
|
||||
<%= fmt_table_long(connection.client_properties) %>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if(connection.reductions || connection.garbage_collection) { %>
|
||||
<div class="section-hidden">
|
||||
<h2>Runtime Metrics (Advanced)</h2>
|
||||
<div class="hider updatable">
|
||||
<%= data_reductions('reductions-rates-conn', connection) %>
|
||||
<table class="facts">
|
||||
<% if (connection.garbage_collection.min_bin_vheap_size) { %>
|
||||
<tr>
|
||||
<th>Minimum binary virtual heap size in words (min_bin_vheap_size)</th>
|
||||
<td><%= connection.garbage_collection.min_bin_vheap_size %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
<% if (connection.garbage_collection.min_heap_size) { %>
|
||||
<tr>
|
||||
<th>Minimum heap size in words (min_heap_size)</th>
|
||||
<td><%= connection.garbage_collection.min_heap_size %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
<% if (connection.garbage_collection.fullsweep_after) { %>
|
||||
<tr>
|
||||
<th>Maximum generational collections before fullsweep (fullsweep_after)</th>
|
||||
<td><%= connection.garbage_collection.fullsweep_after %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
|
||||
<% if (connection.garbage_collection.minor_gcs) { %>
|
||||
<tr>
|
||||
<th>Number of minor GCs (minor_gcs)</th>
|
||||
<td><%= connection.garbage_collection.minor_gcs %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
<div class="section-hidden">
|
||||
<h2>Close this connection</h2>
|
||||
<div class="hider">
|
||||
<form action="#/connections" method="delete" class="confirm">
|
||||
<input type="hidden" name="name" value="<%= fmt_string(connection.name) %>"/>
|
||||
<table class="form">
|
||||
<tr>
|
||||
<th><label>Reason:</label></th>
|
||||
<td>
|
||||
<input type="text" name="reason" value="Closed via management plugin" class="wide"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="submit" value="Force Close"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
<div class="section">
|
||||
<%= paginate_ui(connections, 'streamConnections', 'stream connections') %>
|
||||
</div>
|
||||
<div class="updatable">
|
||||
<% if (connections.items.length > 0) { %>
|
||||
<table class="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<%= group_heading('streamConnections', 'Overview', [vhosts_interesting, nodes_interesting, true]) %>
|
||||
<% if (!disable_stats) { %>
|
||||
<%= group_heading('streamConnections', 'Details', []) %>
|
||||
<%= group_heading('streamConnections', 'Network', []) %>
|
||||
<% } %>
|
||||
<th class="plus-minus"><span class="popup-options-link" title="Click to change columns" type="columns" for="streamConnections">+/-</span></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<% if (vhosts_interesting) { %>
|
||||
<th><%= fmt_sort('Virtual host', 'vhost') %></th>
|
||||
<% } %>
|
||||
<% if(disable_stats) { %>
|
||||
<th><%= fmt_sort('Name', 'name') %></th>
|
||||
<% } else { %>
|
||||
<th><%= fmt_sort('Name', 'client_properties.connection_name') %></th>
|
||||
<% } %>
|
||||
<% if (nodes_interesting) { %>
|
||||
<th><%= fmt_sort('Node', 'node') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'user')) { %>
|
||||
<th><%= fmt_sort('User name', 'user') %></th>
|
||||
<% } %>
|
||||
<% if (!disable_stats) { %>
|
||||
<% if (show_column('streamConnections', 'state')) { %>
|
||||
<th><%= fmt_sort('State', 'state') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'protocol')) { %>
|
||||
<th><%= fmt_sort('Protocol', 'protocol') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'frame_max')) { %>
|
||||
<th><%= fmt_sort('Frame max', 'frame_max') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'auth_mechanism')) { %>
|
||||
<th><%= fmt_sort('Auth mechanism', 'auth_mechanism') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'client')) { %>
|
||||
<th><%= fmt_sort('Client', 'properties') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'from_client')) { %>
|
||||
<th><%= fmt_sort('From client', 'recv_oct_details.rate') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'to_client')) { %>
|
||||
<th><%= fmt_sort('To client', 'send_oct_details.rate') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'heartbeat')) { %>
|
||||
<th><%= fmt_sort('Heartbeat', 'timeout') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'connected_at')) { %>
|
||||
<th><%= fmt_sort('Connected at', 'connected_at') %></th>
|
||||
<% } %>
|
||||
<% } %>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%
|
||||
for (var i = 0; i < connections.items.length; i++) {
|
||||
var connection = connections.items[i];
|
||||
%>
|
||||
<tr<%= alt_rows(i)%>>
|
||||
<% if (vhosts_interesting) { %>
|
||||
<td><%= fmt_string(connection.vhost) %></td>
|
||||
<% } %>
|
||||
<% if(connection.client_properties) { %>
|
||||
<td>
|
||||
<%= link_stream_conn(connection.vhost, connection.name) %>
|
||||
<sub><%= fmt_string(short_conn(connection.client_properties.connection_name)) %></sub>
|
||||
</td>
|
||||
<% } else { %>
|
||||
<td><%= link_stream_conn(connection.vhost, connection.name) %></td>
|
||||
<% } %>
|
||||
<% if (nodes_interesting) { %>
|
||||
<td><%= fmt_node(connection.node) %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'user')) { %>
|
||||
<td class="c"><%= fmt_string(connection.user) %></td>
|
||||
<% } %>
|
||||
<% if (!disable_stats) { %>
|
||||
<% if (show_column('streamConnections', 'state')) { %>
|
||||
<td><%= fmt_object_state(connection) %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'protocol')) { %>
|
||||
<td class="c"><%= connection.protocol %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'frame_max')) { %>
|
||||
<td class="r"><%= fmt_string(connection.frame_max, '') %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'auth_mechanism')) { %>
|
||||
<td class="c"><%= fmt_string(connection.auth_mechanism, '') %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'client')) { %>
|
||||
<td><%= fmt_client_name(connection.client_properties) %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'from_client')) { %>
|
||||
<td><%= fmt_detail_rate_bytes(connection, 'recv_oct') %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'to_client')) { %>
|
||||
<td><%= fmt_detail_rate_bytes(connection, 'send_oct') %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'heartbeat')) { %>
|
||||
<td class="r"><%= fmt_time(connection.timeout, 's') %></td>
|
||||
<% } %>
|
||||
<% if (show_column('streamConnections', 'connected_at')) { %>
|
||||
<td><%= fmt_timestamp_mini(connection.connected_at) %></td>
|
||||
<% } %>
|
||||
<% } %>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } else { %>
|
||||
<p>... no connections ...</p>
|
||||
<% } %>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<% if (consumers.length > 0) { %>
|
||||
<table class="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Subscription ID</th>
|
||||
<th>Queue</th>
|
||||
<th>Credits</th>
|
||||
<th>Offset</th>
|
||||
<th>Messages Consumed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<%
|
||||
for (var i = 0; i < consumers.length; i++) {
|
||||
var consumer = consumers[i];
|
||||
%>
|
||||
<tr<%= alt_rows(i) %>>
|
||||
<td><%= consumer.subscription_id %></td>
|
||||
<td><%= link_queue(consumer.queue.vhost, consumer.queue.name) %></td>
|
||||
<td class="c"><%= consumer.credits %></td>
|
||||
<td class="c"><%= consumer.offset %></td>
|
||||
<td class="c"><%= consumer.consumed %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</table>
|
||||
<% } else { %>
|
||||
<p>... no consumers ...</p>
|
||||
<% } %>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<% if (publishers.length > 0) { %>
|
||||
<table class="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Reference</th>
|
||||
<th>Queue</th>
|
||||
<th>Messages Published</th>
|
||||
<th>Messages Confirmed</th>
|
||||
<th>Messages Errored</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<%
|
||||
for (var i = 0; i < publishers.length; i++) {
|
||||
var publisher = publishers[i];
|
||||
%>
|
||||
<tr<%= alt_rows(i) %>>
|
||||
<td><%= publisher.publisher_id %></td>
|
||||
<td class="c"><%= fmt_string(publisher.reference) %></td>
|
||||
<td><%= link_queue(publisher.queue.vhost, publisher.queue.name) %></td>
|
||||
<td class="c"><%= publisher.published %></td>
|
||||
<td class="c"><%= publisher.confirmed %></td>
|
||||
<td class="c"><%= publisher.errored %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</table>
|
||||
<% } else { %>
|
||||
<p>... no publishers ...</p>
|
||||
<% } %>
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
ifeq ($(.DEFAULT_GOAL),)
|
||||
# Define default goal to `all` because this file defines some targets
|
||||
# before the inclusion of erlang.mk leading to the wrong target becoming
|
||||
# the default.
|
||||
.DEFAULT_GOAL = all
|
||||
endif
|
||||
|
||||
# PROJECT_VERSION defaults to:
|
||||
# 1. the version exported by rabbitmq-server-release;
|
||||
# 2. the version stored in `git-revisions.txt`, if it exists;
|
||||
# 3. a version based on git-describe(1), if it is a Git clone;
|
||||
# 4. 0.0.0
|
||||
|
||||
PROJECT_VERSION := $(RABBITMQ_VERSION)
|
||||
|
||||
ifeq ($(PROJECT_VERSION),)
|
||||
PROJECT_VERSION := $(shell \
|
||||
if test -f git-revisions.txt; then \
|
||||
head -n1 git-revisions.txt | \
|
||||
awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \
|
||||
else \
|
||||
(git describe --dirty --abbrev=7 --tags --always --first-parent \
|
||||
2>/dev/null || echo rabbitmq_v0_0_0) | \
|
||||
sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \
|
||||
-e 's/-/./g'; \
|
||||
fi)
|
||||
endif
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# RabbitMQ components.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# For RabbitMQ repositories, we want to checkout branches which match
|
||||
# the parent project. For instance, if the parent project is on a
|
||||
# release tag, dependencies must be on the same release tag. If the
|
||||
# parent project is on a topic branch, dependencies must be on the same
|
||||
# topic branch or fallback to `stable` or `master` whichever was the
|
||||
# base of the topic branch.
|
||||
|
||||
dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_amqp10_client = git_rmq rabbitmq-amqp1.0-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_amqp10_common = git_rmq rabbitmq-amqp1.0-common $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_oauth2 = git_rmq rabbitmq-auth-backend-oauth2 $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_aws = git_rmq rabbitmq-aws $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_lvc_exchange = git_rmq rabbitmq-lvc-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_etcd = git_rmq rabbitmq-peer-discovery-etcd $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_k8s = git_rmq rabbitmq-peer-discovery-k8s $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_prometheus = git_rmq rabbitmq-prometheus $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_random_exchange = git_rmq rabbitmq-random-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master
|
||||
dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
||||
dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
||||
# Third-party dependencies version pinning.
|
||||
#
|
||||
# We do that in this file, which is copied in all projects, to ensure
|
||||
# all projects use the same versions. It avoids conflicts and makes it
|
||||
# possible to work with rabbitmq-public-umbrella.
|
||||
|
||||
dep_accept = hex 0.3.5
|
||||
dep_cowboy = hex 2.8.0
|
||||
dep_cowlib = hex 2.9.1
|
||||
dep_jsx = hex 2.11.0
|
||||
dep_lager = hex 3.8.0
|
||||
dep_prometheus = git https://github.com/deadtrickster/prometheus.erl.git master
|
||||
dep_ra = git https://github.com/rabbitmq/ra.git master
|
||||
dep_ranch = hex 1.7.1
|
||||
dep_recon = hex 2.5.1
|
||||
dep_observer_cli = hex 1.5.4
|
||||
dep_stdout_formatter = hex 0.2.4
|
||||
dep_sysmon_handler = hex 1.3.0
|
||||
|
||||
RABBITMQ_COMPONENTS = amqp_client \
|
||||
amqp10_common \
|
||||
amqp10_client \
|
||||
rabbit \
|
||||
rabbit_common \
|
||||
rabbitmq_amqp1_0 \
|
||||
rabbitmq_auth_backend_amqp \
|
||||
rabbitmq_auth_backend_cache \
|
||||
rabbitmq_auth_backend_http \
|
||||
rabbitmq_auth_backend_ldap \
|
||||
rabbitmq_auth_backend_oauth2 \
|
||||
rabbitmq_auth_mechanism_ssl \
|
||||
rabbitmq_aws \
|
||||
rabbitmq_boot_steps_visualiser \
|
||||
rabbitmq_cli \
|
||||
rabbitmq_codegen \
|
||||
rabbitmq_consistent_hash_exchange \
|
||||
rabbitmq_ct_client_helpers \
|
||||
rabbitmq_ct_helpers \
|
||||
rabbitmq_delayed_message_exchange \
|
||||
rabbitmq_dotnet_client \
|
||||
rabbitmq_event_exchange \
|
||||
rabbitmq_federation \
|
||||
rabbitmq_federation_management \
|
||||
rabbitmq_java_client \
|
||||
rabbitmq_jms_client \
|
||||
rabbitmq_jms_cts \
|
||||
rabbitmq_jms_topic_exchange \
|
||||
rabbitmq_lvc_exchange \
|
||||
rabbitmq_management \
|
||||
rabbitmq_management_agent \
|
||||
rabbitmq_management_exchange \
|
||||
rabbitmq_management_themes \
|
||||
rabbitmq_message_timestamp \
|
||||
rabbitmq_metronome \
|
||||
rabbitmq_mqtt \
|
||||
rabbitmq_objc_client \
|
||||
rabbitmq_peer_discovery_aws \
|
||||
rabbitmq_peer_discovery_common \
|
||||
rabbitmq_peer_discovery_consul \
|
||||
rabbitmq_peer_discovery_etcd \
|
||||
rabbitmq_peer_discovery_k8s \
|
||||
rabbitmq_prometheus \
|
||||
rabbitmq_random_exchange \
|
||||
rabbitmq_recent_history_exchange \
|
||||
rabbitmq_routing_node_stamp \
|
||||
rabbitmq_rtopic_exchange \
|
||||
rabbitmq_server_release \
|
||||
rabbitmq_sharding \
|
||||
rabbitmq_shovel \
|
||||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
rabbitmq_trust_store \
|
||||
rabbitmq_web_dispatch \
|
||||
rabbitmq_web_mqtt \
|
||||
rabbitmq_web_mqtt_examples \
|
||||
rabbitmq_web_stomp \
|
||||
rabbitmq_web_stomp_examples \
|
||||
rabbitmq_website
|
||||
|
||||
# Erlang.mk does not rebuild dependencies by default, once they were
|
||||
# compiled once, except for those listed in the `$(FORCE_REBUILD)`
|
||||
# variable.
|
||||
#
|
||||
# We want all RabbitMQ components to always be rebuilt: this eases
|
||||
# the work on several components at the same time.
|
||||
|
||||
FORCE_REBUILD = $(RABBITMQ_COMPONENTS)
|
||||
|
||||
# Several components have a custom erlang.mk/build.config, mainly
|
||||
# to disable eunit. Therefore, we can't use the top-level project's
|
||||
# erlang.mk copy.
|
||||
NO_AUTOPATCH += $(RABBITMQ_COMPONENTS)
|
||||
|
||||
ifeq ($(origin current_rmq_ref),undefined)
|
||||
ifneq ($(wildcard .git),)
|
||||
current_rmq_ref := $(shell (\
|
||||
ref=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\
|
||||
if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi))
|
||||
else
|
||||
current_rmq_ref := master
|
||||
endif
|
||||
endif
|
||||
export current_rmq_ref
|
||||
|
||||
ifeq ($(origin base_rmq_ref),undefined)
|
||||
ifneq ($(wildcard .git),)
|
||||
possible_base_rmq_ref := master
|
||||
ifeq ($(possible_base_rmq_ref),$(current_rmq_ref))
|
||||
base_rmq_ref := $(current_rmq_ref)
|
||||
else
|
||||
base_rmq_ref := $(shell \
|
||||
(git rev-parse --verify -q master >/dev/null && \
|
||||
git rev-parse --verify -q $(possible_base_rmq_ref) >/dev/null && \
|
||||
git merge-base --is-ancestor $$(git merge-base master HEAD) $(possible_base_rmq_ref) && \
|
||||
echo $(possible_base_rmq_ref)) || \
|
||||
echo master)
|
||||
endif
|
||||
else
|
||||
base_rmq_ref := master
|
||||
endif
|
||||
endif
|
||||
export base_rmq_ref
|
||||
|
||||
# Repository URL selection.
|
||||
#
|
||||
# First, we infer other components' location from the current project
|
||||
# repository URL, if it's a Git repository:
|
||||
# - We take the "origin" remote URL as the base
|
||||
# - The current project name and repository name is replaced by the
|
||||
# target's properties:
|
||||
# eg. rabbitmq-common is replaced by rabbitmq-codegen
|
||||
# eg. rabbit_common is replaced by rabbitmq_codegen
|
||||
#
|
||||
# If cloning from this computed location fails, we fallback to RabbitMQ
|
||||
# upstream which is GitHub.
|
||||
|
||||
# Macro to transform eg. "rabbit_common" to "rabbitmq-common".
|
||||
rmq_cmp_repo_name = $(word 2,$(dep_$(1)))
|
||||
|
||||
# Upstream URL for the current project.
|
||||
RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT))
|
||||
RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
|
||||
RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
|
||||
|
||||
# Current URL for the current project. If this is not a Git clone,
|
||||
# default to the upstream Git repository.
|
||||
ifneq ($(wildcard .git),)
|
||||
git_origin_fetch_url := $(shell git config remote.origin.url)
|
||||
git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url)
|
||||
RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url)
|
||||
RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url)
|
||||
else
|
||||
RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL)
|
||||
RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL)
|
||||
endif
|
||||
|
||||
# Macro to replace the following pattern:
|
||||
# 1. /foo.git -> /bar.git
|
||||
# 2. /foo -> /bar
|
||||
# 3. /foo/ -> /bar/
|
||||
subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3))))
|
||||
|
||||
# Macro to replace both the project's name (eg. "rabbit_common") and
|
||||
# repository name (eg. "rabbitmq-common") by the target's equivalent.
|
||||
#
|
||||
# This macro is kept on one line because we don't want whitespaces in
|
||||
# the returned value, as it's used in $(dep_fetch_git_rmq) in a shell
|
||||
# single-quoted string.
|
||||
dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo))
|
||||
|
||||
dep_rmq_commits = $(if $(dep_$(1)), \
|
||||
$(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \
|
||||
$(pkg_$(1)_commit))
|
||||
|
||||
define dep_fetch_git_rmq
|
||||
fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \
|
||||
fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \
|
||||
if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \
|
||||
git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \
|
||||
fetch_url="$$$$fetch_url1"; \
|
||||
push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \
|
||||
elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \
|
||||
fetch_url="$$$$fetch_url2"; \
|
||||
push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \
|
||||
fi; \
|
||||
cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \
|
||||
$(foreach ref,$(call dep_rmq_commits,$(1)), \
|
||||
git checkout -q $(ref) >/dev/null 2>&1 || \
|
||||
) \
|
||||
(echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \
|
||||
1>&2 && false) ) && \
|
||||
(test "$$$$fetch_url" = "$$$$push_url" || \
|
||||
git remote set-url --push origin "$$$$push_url")
|
||||
endef
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Component distribution.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
list-dist-deps::
|
||||
@:
|
||||
|
||||
prepare-dist::
|
||||
@:
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Umbrella-specific settings.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# If the top-level project is a RabbitMQ component, we override
|
||||
# $(DEPS_DIR) for this project to point to the top-level's one.
|
||||
#
|
||||
# We also verify that the guessed DEPS_DIR is actually named `deps`,
|
||||
# to rule out any situation where it is a coincidence that we found a
|
||||
# `rabbitmq-components.mk` up upper directories.
|
||||
|
||||
possible_deps_dir_1 = $(abspath ..)
|
||||
possible_deps_dir_2 = $(abspath ../../..)
|
||||
|
||||
ifeq ($(notdir $(possible_deps_dir_1)),deps)
|
||||
ifneq ($(wildcard $(possible_deps_dir_1)/../rabbitmq-components.mk),)
|
||||
deps_dir_overriden = 1
|
||||
DEPS_DIR ?= $(possible_deps_dir_1)
|
||||
DISABLE_DISTCLEAN = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(deps_dir_overriden),)
|
||||
ifeq ($(notdir $(possible_deps_dir_2)),deps)
|
||||
ifneq ($(wildcard $(possible_deps_dir_2)/../rabbitmq-components.mk),)
|
||||
deps_dir_overriden = 1
|
||||
DEPS_DIR ?= $(possible_deps_dir_2)
|
||||
DISABLE_DISTCLEAN = 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(wildcard UMBRELLA.md),)
|
||||
DISABLE_DISTCLEAN = 1
|
||||
endif
|
||||
|
||||
# We disable `make distclean` so $(DEPS_DIR) is not accidentally removed.
|
||||
|
||||
ifeq ($(DISABLE_DISTCLEAN),1)
|
||||
ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),)
|
||||
SKIP_DEPS = 1
|
||||
endif
|
||||
endif
|
||||
56
deps/rabbitmq_stream_management/src/rabbit_stream_connection_consumers_mgmt.erl
vendored
Normal file
56
deps/rabbitmq_stream_management/src/rabbit_stream_connection_consumers_mgmt.erl
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_connection_consumers_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, to_json/2, content_types_provided/2, is_authorized/2]).
|
||||
-export([resource_exists/2]).
|
||||
-export([variances/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
dispatcher() -> [{"/stream/connections/:vhost/:connection/consumers", ?MODULE, []}].
|
||||
|
||||
web_ui() -> [].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
init(Req, _State) ->
|
||||
{cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
variances(Req, Context) ->
|
||||
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
|
||||
|
||||
resource_exists(ReqData, Context) ->
|
||||
case rabbit_mgmt_wm_connection:conn(ReqData) of
|
||||
error -> {false, ReqData, Context};
|
||||
not_found -> {false, ReqData, Context};
|
||||
_Conn -> {true, ReqData, Context}
|
||||
end.
|
||||
|
||||
to_json(ReqData, Context) ->
|
||||
Pid = proplists:get_value(pid, rabbit_mgmt_wm_connection:conn(ReqData)),
|
||||
Consumers = rabbit_mgmt_format:strip_pids(rabbit_stream_mgmt_db:get_connection_consumers(Pid)),
|
||||
rabbit_mgmt_util:reply_list(
|
||||
Consumers,
|
||||
ReqData, Context).
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
try
|
||||
rabbit_mgmt_util:is_authorized_user(
|
||||
ReqData, Context, rabbit_mgmt_wm_connection:conn(ReqData))
|
||||
catch
|
||||
{error, invalid_range_parameters, Reason} ->
|
||||
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
|
||||
end.
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_connection_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, resource_exists/2, to_json/2, content_types_provided/2,
|
||||
is_authorized/2, allowed_methods/2, delete_resource/2]).
|
||||
-export([variances/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
dispatcher() -> [{"/stream/connections/:vhost/:connection", ?MODULE, []}].
|
||||
|
||||
web_ui() -> [].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init(Req, _State) ->
|
||||
{cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
variances(Req, Context) ->
|
||||
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
|
||||
|
||||
allowed_methods(ReqData, Context) ->
|
||||
{[<<"HEAD">>, <<"GET">>, <<"DELETE">>, <<"OPTIONS">>], ReqData, Context}.
|
||||
|
||||
resource_exists(ReqData, Context) ->
|
||||
case conn(ReqData) of
|
||||
not_found -> {false, ReqData, Context};
|
||||
_Conn -> {true, ReqData, Context}
|
||||
end.
|
||||
|
||||
to_json(ReqData, Context) ->
|
||||
case rabbit_mgmt_util:disable_stats(ReqData) of
|
||||
false ->
|
||||
rabbit_mgmt_util:reply(
|
||||
maps:from_list(rabbit_mgmt_format:strip_pids(conn_stats(ReqData))), ReqData, Context);
|
||||
true ->
|
||||
rabbit_mgmt_util:reply([{name, rabbit_mgmt_util:id(connection, ReqData)}],
|
||||
ReqData, Context)
|
||||
end.
|
||||
|
||||
delete_resource(ReqData, Context) ->
|
||||
case conn(ReqData) of
|
||||
not_found -> ok;
|
||||
Conn ->
|
||||
case proplists:get_value(pid, Conn) of
|
||||
undefined -> ok;
|
||||
Pid when is_pid(Pid) ->
|
||||
force_close_connection(ReqData, Pid)
|
||||
end
|
||||
end,
|
||||
{true, ReqData, Context}.
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
try
|
||||
rabbit_mgmt_util:is_authorized_user(ReqData, Context, conn(ReqData))
|
||||
catch
|
||||
{error, invalid_range_parameters, Reason} ->
|
||||
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
conn(ReqData) ->
|
||||
case rabbit_mgmt_util:disable_stats(ReqData) of
|
||||
false ->
|
||||
conn_stats(ReqData);
|
||||
true ->
|
||||
VHost = rabbit_mgmt_util:id(vhost, ReqData),
|
||||
case rabbit_connection_tracking:lookup(rabbit_mgmt_util:id(connection, ReqData)) of
|
||||
#tracked_connection{name = Name, pid = Pid,
|
||||
username = Username, type = Type,
|
||||
protocol = <<"stream">>, vhost = VHost} ->
|
||||
[{name, Name}, {pid, Pid}, {user, Username}, {type, Type}];
|
||||
#tracked_connection{} ->
|
||||
not_found;
|
||||
not_found ->
|
||||
not_found
|
||||
end
|
||||
end.
|
||||
|
||||
conn_stats(ReqData) ->
|
||||
case rabbit_mgmt_db:get_connection(rabbit_mgmt_util:id(connection, ReqData),
|
||||
rabbit_mgmt_util:range_ceil(ReqData)) of
|
||||
not_found ->
|
||||
not_found;
|
||||
Connection ->
|
||||
VHost = rabbit_mgmt_util:id(vhost, ReqData),
|
||||
case {rabbit_stream_management_utils:is_stream_connection(Connection),
|
||||
same_vhost(VHost, Connection)} of
|
||||
{true, true} ->
|
||||
Connection;
|
||||
_ ->
|
||||
not_found
|
||||
end
|
||||
end.
|
||||
|
||||
same_vhost(Vhost, Connection) ->
|
||||
case lists:keyfind(vhost, 1, Connection) of
|
||||
{vhost, Vhost} ->
|
||||
true;
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
force_close_connection(ReqData, Pid) ->
|
||||
Reason = case cowboy_req:header(<<"x-reason">>, ReqData) of
|
||||
undefined -> "Closed via management plugin";
|
||||
V -> binary_to_list(V)
|
||||
end,
|
||||
gen_server:call(Pid, {shutdown, Reason}, infinity),
|
||||
ok.
|
||||
56
deps/rabbitmq_stream_management/src/rabbit_stream_connection_publishers_mgmt.erl
vendored
Normal file
56
deps/rabbitmq_stream_management/src/rabbit_stream_connection_publishers_mgmt.erl
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_connection_publishers_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, to_json/2, content_types_provided/2, is_authorized/2]).
|
||||
-export([resource_exists/2]).
|
||||
-export([variances/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
dispatcher() -> [{"/stream/connections/:vhost/:connection/publishers", ?MODULE, []}].
|
||||
|
||||
web_ui() -> [].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
init(Req, _State) ->
|
||||
{cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
variances(Req, Context) ->
|
||||
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
|
||||
|
||||
resource_exists(ReqData, Context) ->
|
||||
case rabbit_mgmt_wm_connection:conn(ReqData) of
|
||||
error -> {false, ReqData, Context};
|
||||
not_found -> {false, ReqData, Context};
|
||||
_Conn -> {true, ReqData, Context}
|
||||
end.
|
||||
|
||||
to_json(ReqData, Context) ->
|
||||
Pid = proplists:get_value(pid, rabbit_mgmt_wm_connection:conn(ReqData)),
|
||||
Publishers = rabbit_mgmt_format:strip_pids(rabbit_stream_mgmt_db:get_connection_publishers(Pid)),
|
||||
rabbit_mgmt_util:reply_list(
|
||||
Publishers,
|
||||
ReqData, Context).
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
try
|
||||
rabbit_mgmt_util:is_authorized_user(
|
||||
ReqData, Context, rabbit_mgmt_wm_connection:conn(ReqData))
|
||||
catch
|
||||
{error, invalid_range_parameters, Reason} ->
|
||||
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
|
||||
end.
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_connections_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, to_json/2, content_types_provided/2, is_authorized/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
|
||||
dispatcher() -> [{"/stream/connections", ?MODULE, []}].
|
||||
|
||||
web_ui() -> [{javascript, <<"stream.js">>}].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init(Req, _Opts) ->
|
||||
{cowboy_rest, rabbit_mgmt_cors:set_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{[{<<"application/json">>, to_json}], ReqData, Context}.
|
||||
|
||||
to_json(ReqData, Context) ->
|
||||
try
|
||||
Connections = do_connections_query(ReqData, Context),
|
||||
rabbit_mgmt_util:reply_list_or_paginate(Connections, ReqData, Context)
|
||||
catch
|
||||
{error, invalid_range_parameters, Reason} ->
|
||||
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
|
||||
end.
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
rabbit_mgmt_util:is_authorized(ReqData, Context).
|
||||
|
||||
augmented(ReqData, Context) ->
|
||||
rabbit_mgmt_util:filter_conn_ch_list(
|
||||
rabbit_mgmt_db:get_all_connections(
|
||||
rabbit_mgmt_util:range_ceil(ReqData)), ReqData, Context).
|
||||
|
||||
do_connections_query(ReqData, Context) ->
|
||||
case rabbit_mgmt_util:disable_stats(ReqData) of
|
||||
false ->
|
||||
rabbit_stream_management_utils:keep_stream_connections(augmented(ReqData, Context));
|
||||
true ->
|
||||
TrackedStreamConnections = rabbit_stream_management_utils:keep_tracked_stream_connections(
|
||||
rabbit_connection_tracking:list()),
|
||||
rabbit_mgmt_util:filter_tracked_conn_list(TrackedStreamConnections,
|
||||
ReqData, Context)
|
||||
end.
|
||||
49
deps/rabbitmq_stream_management/src/rabbit_stream_connections_vhost_mgmt.erl
vendored
Normal file
49
deps/rabbitmq_stream_management/src/rabbit_stream_connections_vhost_mgmt.erl
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_connections_vhost_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, to_json/2, content_types_provided/2, resource_exists/2, is_authorized/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
-include_lib("amqp_client/include/amqp_client.hrl").
|
||||
|
||||
dispatcher() -> [{"/stream/connections/:vhost", ?MODULE, []}].
|
||||
|
||||
web_ui() -> [].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init(Req, _Opts) ->
|
||||
{cowboy_rest, rabbit_mgmt_cors:set_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{[{<<"application/json">>, to_json}], ReqData, Context}.
|
||||
|
||||
resource_exists(ReqData, Context) ->
|
||||
{rabbit_vhost:exists(rabbit_mgmt_util:id(vhost, ReqData)), ReqData, Context}.
|
||||
|
||||
to_json(ReqData, Context) ->
|
||||
try
|
||||
rabbit_mgmt_util:reply_list(rabbit_stream_management_utils:keep_stream_connections(
|
||||
augmented(ReqData, Context)), ReqData, Context
|
||||
)
|
||||
catch
|
||||
{error, invalid_range_parameters, Reason} ->
|
||||
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
|
||||
end.
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
rabbit_mgmt_util:is_authorized_vhost_visible_for_monitoring(ReqData, Context).
|
||||
|
||||
augmented(ReqData, Context) ->
|
||||
rabbit_mgmt_util:filter_conn_ch_list(
|
||||
rabbit_mgmt_db:get_all_connections(
|
||||
rabbit_mgmt_util:range_ceil(ReqData)), ReqData, Context).
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_consumers_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, resource_exists/2, to_json/2, content_types_provided/2, is_authorized/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
dispatcher() -> [
|
||||
{"/stream/consumers", ?MODULE, []},
|
||||
{"/stream/consumers/:vhost", ?MODULE, []}
|
||||
].
|
||||
|
||||
web_ui() -> [].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init(Req, _Opts) ->
|
||||
{cowboy_rest, rabbit_mgmt_cors:set_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{[{<<"application/json">>, to_json}], ReqData, Context}.
|
||||
|
||||
resource_exists(ReqData, Context) ->
|
||||
{case rabbit_mgmt_util:vhost(ReqData) of
|
||||
not_found -> false;
|
||||
none -> true; % none means `all`
|
||||
_ -> true
|
||||
end, ReqData, Context}.
|
||||
|
||||
to_json(ReqData, Context = #context{user = User}) ->
|
||||
case rabbit_mgmt_util:disable_stats(ReqData) of
|
||||
false ->
|
||||
Arg = case rabbit_mgmt_util:vhost(ReqData) of
|
||||
none -> all;
|
||||
VHost -> VHost
|
||||
end,
|
||||
Consumers = rabbit_mgmt_format:strip_pids(rabbit_stream_mgmt_db:get_all_consumers(Arg)),
|
||||
rabbit_mgmt_util:reply_list(
|
||||
filter_user(Consumers, User), [], ReqData, Context);
|
||||
true ->
|
||||
rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context)
|
||||
end.
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
rabbit_mgmt_util:is_authorized(ReqData, Context).
|
||||
|
||||
filter_user(List, #user{username = Username, tags = Tags}) ->
|
||||
case rabbit_mgmt_util:is_monitor(Tags) of
|
||||
true -> List;
|
||||
false -> [I || I <- List,
|
||||
rabbit_misc:pget(user, rabbit_misc:pget(connection_details, I)) == Username]
|
||||
end.
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_management_utils).
|
||||
|
||||
|
||||
-export([keep_stream_connections/1, keep_tracked_stream_connections/1, is_stream_connection/1]).
|
||||
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
|
||||
keep_stream_connections(Connections) ->
|
||||
lists:filter(fun is_stream_connection/1, Connections).
|
||||
|
||||
is_stream_connection(Connection) ->
|
||||
case lists:keyfind(protocol, 1, Connection) of
|
||||
{protocol, <<"stream">>} ->
|
||||
true;
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
keep_tracked_stream_connections(Connections) ->
|
||||
lists:filter(fun(#tracked_connection{protocol = <<"stream">>}) ->
|
||||
true;
|
||||
(_) ->
|
||||
false
|
||||
end, Connections).
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_mgmt_db).
|
||||
|
||||
-define(ENTITY_CONSUMER, consumer).
|
||||
-define(ENTITY_PUBLISHER, publisher).
|
||||
|
||||
-include_lib("rabbitmq_stream/include/rabbit_stream_metrics.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
-export([get_all_consumers/1, get_all_publishers/1]).
|
||||
-export([entity_data/4]).
|
||||
-export([get_connection_consumers/1, get_connection_publishers/1]).
|
||||
|
||||
get_all_consumers(VHosts) ->
|
||||
rabbit_mgmt_db:submit(fun(_Interval) -> consumers_stats(VHosts) end).
|
||||
|
||||
get_all_publishers(VHosts) ->
|
||||
rabbit_mgmt_db:submit(fun(_Interval) -> publishers_stats(VHosts) end).
|
||||
|
||||
get_connection_consumers(ConnectionPid) when is_pid(ConnectionPid) ->
|
||||
rabbit_mgmt_db:submit(fun(_Interval) -> connection_consumers_stats(ConnectionPid) end).
|
||||
|
||||
get_connection_publishers(ConnectionPid) when is_pid(ConnectionPid) ->
|
||||
rabbit_mgmt_db:submit(fun(_Interval) -> connection_publishers_stats(ConnectionPid) end).
|
||||
|
||||
consumers_stats(VHost) ->
|
||||
Data = rabbit_mgmt_db:get_data_from_nodes({rabbit_stream_mgmt_db, entity_data,
|
||||
[VHost, ?ENTITY_CONSUMER, fun consumers_by_vhost/1]}),
|
||||
[V || {_, V} <- maps:to_list(Data)].
|
||||
|
||||
publishers_stats(VHost) ->
|
||||
Data = rabbit_mgmt_db:get_data_from_nodes({rabbit_stream_mgmt_db, entity_data,
|
||||
[VHost, ?ENTITY_PUBLISHER, fun publishers_by_vhost/1]}),
|
||||
[V || {_, V} <- maps:to_list(Data)].
|
||||
|
||||
connection_consumers_stats(ConnectionPid) ->
|
||||
Data = rabbit_mgmt_db:get_data_from_nodes({rabbit_stream_mgmt_db, entity_data,
|
||||
[ConnectionPid, ?ENTITY_CONSUMER, fun consumers_by_connection/1]}),
|
||||
[V || {_, V} <- maps:to_list(Data)].
|
||||
|
||||
connection_publishers_stats(ConnectionPid) ->
|
||||
Data = rabbit_mgmt_db:get_data_from_nodes({rabbit_stream_mgmt_db, entity_data,
|
||||
[ConnectionPid, ?ENTITY_PUBLISHER, fun publishers_by_connection/1]}),
|
||||
[V || {_, V} <- maps:to_list(Data)].
|
||||
|
||||
entity_data(_Pid, Param, EntityType, QueryFun) ->
|
||||
maps:from_list(
|
||||
[begin
|
||||
AugmentedPublisher = augment_entity(EntityType, P),
|
||||
{P, augment_connection_pid(AugmentedPublisher) ++ AugmentedPublisher}
|
||||
end
|
||||
|| P <- QueryFun(Param)]
|
||||
).
|
||||
|
||||
augment_entity(?ENTITY_CONSUMER, {{Q, ConnPid, SubId}, Props}) ->
|
||||
[{queue, format_resource(Q)},
|
||||
{connection, ConnPid},
|
||||
{subscription_id, SubId} | Props];
|
||||
augment_entity(?ENTITY_PUBLISHER, {{Q, ConnPid, PubId}, Props}) ->
|
||||
[{queue, format_resource(Q)},
|
||||
{connection, ConnPid},
|
||||
{publisher_id, PubId} | Props].
|
||||
|
||||
consumers_by_vhost(VHost) ->
|
||||
ets:select(?TABLE_CONSUMER,
|
||||
[{{{#resource{virtual_host = '$1', _ = '_'}, '_', '_'}, '_'},
|
||||
[{'orelse', {'==', 'all', VHost}, {'==', VHost, '$1'}}],
|
||||
['$_']}]).
|
||||
|
||||
publishers_by_vhost(VHost) ->
|
||||
ets:select(?TABLE_PUBLISHER,
|
||||
[{{{#resource{virtual_host = '$1', _ = '_'}, '_', '_'}, '_'},
|
||||
[{'orelse', {'==', 'all', VHost}, {'==', VHost, '$1'}}],
|
||||
['$_']}]).
|
||||
|
||||
consumers_by_connection(ConnectionPid) ->
|
||||
get_entity_stats(?TABLE_CONSUMER, ConnectionPid).
|
||||
|
||||
publishers_by_connection(ConnectionPid) ->
|
||||
get_entity_stats(?TABLE_PUBLISHER, ConnectionPid).
|
||||
|
||||
get_entity_stats(Table, Id) ->
|
||||
ets:select(Table, match_entity_spec(Id)).
|
||||
|
||||
match_entity_spec(ConnectionId) ->
|
||||
[{{{'_', '$1', '_'}, '_'}, [{'==', ConnectionId, '$1'}], ['$_']}].
|
||||
|
||||
augment_connection_pid(Consumer) ->
|
||||
Pid = rabbit_misc:pget(connection, Consumer),
|
||||
Conn = rabbit_mgmt_data:lookup_element(connection_created_stats, Pid, 3),
|
||||
ConnDetails = case Conn of
|
||||
[] -> %% If the connection has just been opened, we might not yet have the data
|
||||
[];
|
||||
_ ->
|
||||
[{name, rabbit_misc:pget(name, Conn)},
|
||||
{user, rabbit_misc:pget(user, Conn)},
|
||||
{node, rabbit_misc:pget(node, Conn)},
|
||||
{peer_port, rabbit_misc:pget(peer_port, Conn)},
|
||||
{peer_host, rabbit_misc:pget(peer_host, Conn)}]
|
||||
end,
|
||||
[{connection_details, ConnDetails}].
|
||||
|
||||
format_resource(unknown) -> unknown;
|
||||
format_resource(Res) -> format_resource(name, Res).
|
||||
|
||||
format_resource(_, unknown) ->
|
||||
unknown;
|
||||
format_resource(NameAs, #resource{name = Name, virtual_host = VHost}) ->
|
||||
[{NameAs, Name}, {vhost, VHost}].
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
%% 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) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_stream_publishers_mgmt).
|
||||
|
||||
-behaviour(rabbit_mgmt_extension).
|
||||
|
||||
-export([dispatcher/0, web_ui/0]).
|
||||
-export([init/2, resource_exists/2, to_json/2, content_types_provided/2, is_authorized/2]).
|
||||
|
||||
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
dispatcher() -> [
|
||||
{"/stream/publishers", ?MODULE, []},
|
||||
{"/stream/publishers/:vhost", ?MODULE, []}
|
||||
].
|
||||
|
||||
web_ui() -> [].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init(Req, _Opts) ->
|
||||
{cowboy_rest, rabbit_mgmt_cors:set_headers(Req, ?MODULE), #context{}}.
|
||||
|
||||
content_types_provided(ReqData, Context) ->
|
||||
{[{<<"application/json">>, to_json}], ReqData, Context}.
|
||||
|
||||
resource_exists(ReqData, Context) ->
|
||||
{case rabbit_mgmt_util:vhost(ReqData) of
|
||||
not_found -> false;
|
||||
none -> true; % none means `all`
|
||||
_ -> true
|
||||
end, ReqData, Context}.
|
||||
|
||||
to_json(ReqData, Context = #context{user = User}) ->
|
||||
case rabbit_mgmt_util:disable_stats(ReqData) of
|
||||
false ->
|
||||
Arg = case rabbit_mgmt_util:vhost(ReqData) of
|
||||
none -> all;
|
||||
VHost -> VHost
|
||||
end,
|
||||
Publishers = rabbit_mgmt_format:strip_pids(rabbit_stream_mgmt_db:get_all_publishers(Arg)),
|
||||
rabbit_mgmt_util:reply_list(
|
||||
filter_user(Publishers, User), [], ReqData, Context);
|
||||
true ->
|
||||
rabbit_mgmt_util:bad_request(<<"Stats in management UI are disabled on this node">>, ReqData, Context)
|
||||
end.
|
||||
|
||||
is_authorized(ReqData, Context) ->
|
||||
rabbit_mgmt_util:is_authorized(ReqData, Context).
|
||||
|
||||
filter_user(List, #user{username = Username, tags = Tags}) ->
|
||||
case rabbit_mgmt_util:is_monitor(Tags) of
|
||||
true -> List;
|
||||
false -> [I || I <- List,
|
||||
rabbit_misc:pget(user, rabbit_misc:pget(connection_details, I)) == Username]
|
||||
end.
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
%% 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-2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(http_SUITE).
|
||||
|
||||
-include_lib("common_test/include/ct.hrl").
|
||||
-include_lib("rabbit_common/include/rabbit_framing.hrl").
|
||||
-include_lib("rabbitmq_ct_helpers/include/rabbit_mgmt_test.hrl").
|
||||
|
||||
-compile(export_all).
|
||||
|
||||
all() ->
|
||||
[
|
||||
{group, non_parallel_tests}
|
||||
].
|
||||
|
||||
groups() ->
|
||||
[
|
||||
{non_parallel_tests, [], [
|
||||
stream_management
|
||||
]}
|
||||
].
|
||||
|
||||
%% -------------------------------------------------------------------
|
||||
%% Testsuite setup/teardown.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
init_per_suite(Config) ->
|
||||
rabbit_ct_helpers:log_environment(),
|
||||
Config1 = rabbit_ct_helpers:set_config(Config, [
|
||||
{rmq_nodename_suffix, ?MODULE}
|
||||
]),
|
||||
rabbit_ct_helpers:run_setup_steps(Config1,
|
||||
[fun(StepConfig) ->
|
||||
rabbit_ct_helpers:merge_app_env(StepConfig,
|
||||
{rabbit, [{collect_statistics_interval, 500}]})
|
||||
end] ++
|
||||
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()).
|
||||
|
||||
init_per_group(_, Config) ->
|
||||
Config.
|
||||
|
||||
end_per_group(_, Config) ->
|
||||
Config.
|
||||
|
||||
init_per_testcase(Testcase, Config) ->
|
||||
rabbit_ct_helpers:testcase_started(Config, Testcase).
|
||||
|
||||
end_per_testcase(Testcase, Config) ->
|
||||
rabbit_ct_helpers:testcase_finished(Config, Testcase).
|
||||
|
||||
%% -------------------------------------------------------------------
|
||||
%% Testcases.
|
||||
%% -------------------------------------------------------------------
|
||||
|
||||
stream_management(Config) ->
|
||||
UserManagement = <<"user-management">>,
|
||||
UserMonitoring = <<"user-monitoring">>,
|
||||
Vhost1 = <<"vh1">>,
|
||||
Vhost2 = <<"vh2">>,
|
||||
rabbit_ct_broker_helpers:add_user(Config, UserManagement),
|
||||
rabbit_ct_broker_helpers:set_user_tags(Config, 0, UserManagement, [management]),
|
||||
rabbit_ct_broker_helpers:add_user(Config, UserMonitoring),
|
||||
rabbit_ct_broker_helpers:set_user_tags(Config, 0, UserMonitoring, [monitoring]),
|
||||
rabbit_ct_broker_helpers:add_vhost(Config, Vhost1),
|
||||
rabbit_ct_broker_helpers:add_vhost(Config, Vhost2),
|
||||
|
||||
rabbit_ct_broker_helpers:set_full_permissions(Config, UserManagement, Vhost1),
|
||||
rabbit_ct_broker_helpers:set_full_permissions(Config, UserMonitoring, Vhost1),
|
||||
rabbit_ct_broker_helpers:set_full_permissions(Config, <<"guest">>, Vhost1),
|
||||
rabbit_ct_broker_helpers:set_full_permissions(Config, <<"guest">>, Vhost2),
|
||||
|
||||
StreamPortNode = get_stream_port(Config),
|
||||
ManagementPortNode = get_management_port(Config),
|
||||
DataDir = rabbit_ct_helpers:get_config(Config, data_dir),
|
||||
MakeResult = rabbit_ct_helpers:make(Config, DataDir, ["tests",
|
||||
{"STREAM_PORT=~b", [StreamPortNode]},
|
||||
{"MANAGEMENT_PORT=~b", [ManagementPortNode]}
|
||||
]),
|
||||
{ok, _} = MakeResult.
|
||||
|
||||
get_stream_port(Config) ->
|
||||
rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_stream).
|
||||
|
||||
get_management_port(Config) ->
|
||||
rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_mgmt).
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
/build/
|
||||
/lib/
|
||||
/target/
|
||||
117
deps/rabbitmq_stream_management/test/http_SUITE_data/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
117
deps/rabbitmq_stream_management/test/http_SUITE_data/.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright 2007-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||
* use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||
".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||
".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if(mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if(mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if(!outputFile.getParentFile().exists()) {
|
||||
if(!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
||||
BIN
deps/rabbitmq_stream_management/test/http_SUITE_data/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
deps/rabbitmq_stream_management/test/http_SUITE_data/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
deps/rabbitmq_stream_management/test/http_SUITE_data/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
deps/rabbitmq_stream_management/test/http_SUITE_data/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
export PATH :=$(CURDIR):$(PATH)
|
||||
HOSTNAME := $(shell hostname)
|
||||
MVN_FLAGS += -Dstream.port=$(STREAM_PORT) \
|
||||
-Dmanagement.port=$(MANAGEMENT_PORT)
|
||||
|
||||
.PHONY: tests clean
|
||||
|
||||
tests:
|
||||
# Note: to run a single test
|
||||
# @mvnw -q $(MVN_FLAGS) -Dtest=StreamTest#metadataOnClusterShouldReturnLeaderAndReplicas test
|
||||
@mvnw -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B $(MVN_FLAGS) test
|
||||
|
||||
clean:
|
||||
@mvnw clean
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.rabbitmq.stream</groupId>
|
||||
<artifactId>rabbitmq-stream-management-tests</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MPL 2.0</name>
|
||||
<url>https://www.mozilla.org/en-US/MPL/2.0/</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<email>info@rabbitmq.com</email>
|
||||
<name>Team RabbitMQ</name>
|
||||
<organization>VMware, Inc. or its affiliates.</organization>
|
||||
<organizationUrl>https://rabbitmq.com</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<stream-client.version>0.1.0-SNAPSHOT</stream-client.version>
|
||||
<proton-j.version>0.33.7</proton-j.version>
|
||||
<junit.jupiter.version>5.7.0</junit.jupiter.version>
|
||||
<assertj.version>3.18.1</assertj.version>
|
||||
<okhttp.version>4.9.0</okhttp.version>
|
||||
<gson.version>2.8.6</gson.version>
|
||||
<logback.version>1.2.3</logback.version>
|
||||
<maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
|
||||
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
|
||||
<spotless.version>2.2.0</spotless.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.rabbitmq</groupId>
|
||||
<artifactId>stream-client</artifactId>
|
||||
<version>${stream-client.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.qpid</groupId>
|
||||
<artifactId>proton-j</artifactId>
|
||||
<version>${proton-j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven.compiler.plugin.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<compilerArgs>
|
||||
<arg>-Xlint:deprecation</arg>
|
||||
<arg>-Xlint:unchecked</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<version>${spotless.version}</version>
|
||||
<configuration>
|
||||
<java>
|
||||
<googleJavaFormat>
|
||||
<version>1.9</version>
|
||||
<style>GOOGLE</style>
|
||||
</googleJavaFormat>
|
||||
</java>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<snapshots><enabled>true</enabled></snapshots>
|
||||
<releases><enabled>false</enabled></releases>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
</project>
|
||||
685
deps/rabbitmq_stream_management/test/http_SUITE_data/src/test/java/com/rabbitmq/stream/HttpTest.java
vendored
Normal file
685
deps/rabbitmq_stream_management/test/http_SUITE_data/src/test/java/com/rabbitmq/stream/HttpTest.java
vendored
Normal file
|
|
@ -0,0 +1,685 @@
|
|||
// The contents of this file are subject to the Mozilla Public License
|
||||
// Version 2.0 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License
|
||||
// at https://www.mozilla.org/en-US/MPL/2.0/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS"
|
||||
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
// the License for the specific language governing rights and
|
||||
// limitations under the License.
|
||||
//
|
||||
// The Original Code is RabbitMQ.
|
||||
//
|
||||
// The Initial Developer of the Original Code is Pivotal Software, Inc.
|
||||
// Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
//
|
||||
|
||||
package com.rabbitmq.stream;
|
||||
|
||||
import static com.rabbitmq.stream.TestUtils.waitUntil;
|
||||
import static java.lang.String.format;
|
||||
import static org.assertj.core.api.Assertions.as;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.MAP;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.rabbitmq.stream.TestUtils.ClientFactory;
|
||||
import com.rabbitmq.stream.impl.Client;
|
||||
import com.rabbitmq.stream.impl.Client.ClientParameters;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
@ExtendWith(TestUtils.StreamTestInfrastructureExtension.class)
|
||||
public class HttpTest {
|
||||
|
||||
static OkHttpClient httpClient = httpClient("guest");
|
||||
static Gson gson = new GsonBuilder().create();
|
||||
ClientFactory cf;
|
||||
String stream;
|
||||
|
||||
static OkHttpClient httpClient(String usernamePassword) {
|
||||
return new OkHttpClient.Builder()
|
||||
.authenticator(TestUtils.authenticator(usernamePassword))
|
||||
.build();
|
||||
}
|
||||
|
||||
static String get(String endpoint) throws IOException {
|
||||
return get(httpClient, endpoint);
|
||||
}
|
||||
|
||||
static String get(OkHttpClient client, String endpoint) throws IOException {
|
||||
Request request = new Request.Builder().url(url(endpoint)).build();
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
||||
|
||||
ResponseBody body = response.body();
|
||||
return body == null ? "" : body.string();
|
||||
}
|
||||
}
|
||||
|
||||
static String url(String endpoint) {
|
||||
return "http://localhost:" + TestUtils.managementPort() + "/api" + endpoint;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, String> connectionDetails(Map<String, Object> parent) {
|
||||
return (Map<String, String>) parent.get("connection_details");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, String> queue(Map<String, Object> parent) {
|
||||
return (Map<String, String>) parent.get("queue");
|
||||
}
|
||||
|
||||
static void delete(String endpoint) throws IOException {
|
||||
Request request = new Request.Builder().delete().url(url(endpoint)).build();
|
||||
try (Response response = httpClient.newCall(request).execute()) {
|
||||
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Map<String, Object>> toMaps(String json) {
|
||||
return Arrays.asList(gson.fromJson(json, Map[].class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> toMap(String json) {
|
||||
return gson.fromJson(json, Map.class);
|
||||
}
|
||||
|
||||
static String connectionName(Client client) {
|
||||
InetSocketAddress localAddress = (InetSocketAddress) client.localAddress();
|
||||
InetSocketAddress remoteAddress = (InetSocketAddress) client.remoteAddress();
|
||||
return format("127.0.0.1:%d -> 127.0.0.1:%d", localAddress.getPort(), remoteAddress.getPort());
|
||||
}
|
||||
|
||||
static List<Map<String, Object>> entities(List<Map<String, Object>> entities, Client client) {
|
||||
String connectionName = connectionName(client);
|
||||
return entities.stream()
|
||||
.filter(
|
||||
c ->
|
||||
c.get("connection_details") instanceof Map
|
||||
&& connectionName.equals(connectionDetails(c).get("name")))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static TestRequest[] requests(TestRequest... requests) {
|
||||
return requests;
|
||||
}
|
||||
|
||||
static TestRequest r(String endpoint, int expectedCount) {
|
||||
return new TestRequest(endpoint, expectedCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void connections() throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/connections"));
|
||||
int initialCount = request.call().size();
|
||||
String connectionProvidedName = UUID.randomUUID().toString();
|
||||
AtomicBoolean closed = new AtomicBoolean(false);
|
||||
Client client =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.clientProperty("connection_name", connectionProvidedName)
|
||||
.shutdownListener(shutdownContext -> closed.set(true)));
|
||||
|
||||
waitUntil(() -> request.call().size() == initialCount + 1);
|
||||
|
||||
Map<String, Object> c =
|
||||
request.call().stream()
|
||||
.filter(conn -> connectionProvidedName.equals(conn.get("user_provided_name")))
|
||||
.findFirst()
|
||||
.get();
|
||||
|
||||
String connectionName = connectionName(client);
|
||||
assertThat(c).containsEntry("name", connectionName);
|
||||
|
||||
Callable<Map<String, Object>> cRequest =
|
||||
() -> toMap(get("/stream/connections/%2F/" + connectionName));
|
||||
// wait until some stats are in the response
|
||||
waitUntil(() -> cRequest.call().containsKey("recv_oct_details"));
|
||||
c = cRequest.call();
|
||||
|
||||
Condition<Object> mapCondition = new Condition<>(e -> e instanceof Map, "Must be a map");
|
||||
assertThat(c)
|
||||
.hasEntrySatisfying("recv_oct_details", mapCondition)
|
||||
.hasEntrySatisfying("send_oct_details", mapCondition)
|
||||
.hasEntrySatisfying("garbage_collection", mapCondition)
|
||||
.hasEntrySatisfying("reductions_details", mapCondition);
|
||||
|
||||
assertThat(closed.get()).isFalse();
|
||||
delete("/stream/connections/%2F/" + connectionName);
|
||||
waitUntil(closed::get);
|
||||
|
||||
assertThatThrownBy(cRequest::call).isInstanceOf(IOException.class);
|
||||
waitUntil(() -> request.call().size() == initialCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void connectionConsumers() throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/connections"));
|
||||
int initialCount = request.call().size();
|
||||
String s = UUID.randomUUID().toString();
|
||||
Client c1 = cf.get(new ClientParameters().virtualHost("vh1"));
|
||||
try {
|
||||
c1.create(s);
|
||||
assertThat(c1.subscribe((byte) 0, s, OffsetSpecification.first(), 10).isOk()).isTrue();
|
||||
assertThat(c1.subscribe((byte) 1, s, OffsetSpecification.first(), 5).isOk()).isTrue();
|
||||
Client c2 =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.virtualHost("vh1")
|
||||
.username("user-management")
|
||||
.password("user-management"));
|
||||
assertThat(c2.subscribe((byte) 0, s, OffsetSpecification.first(), 10).isOk()).isTrue();
|
||||
waitUntil(() -> request.call().size() == initialCount + 2);
|
||||
|
||||
Callable<Map<String, Object>> cRequest =
|
||||
() -> toMap(get("/stream/connections/vh1/" + connectionName(c1)));
|
||||
// wait until some stats are in the response
|
||||
waitUntil(() -> cRequest.call().containsKey("recv_oct_details"));
|
||||
|
||||
Callable<List<Map<String, Object>>> consumersRequest =
|
||||
() -> toMaps(get("/stream/connections/vh1/" + connectionName(c1) + "/consumers"));
|
||||
List<Map<String, Object>> consumers = consumersRequest.call();
|
||||
|
||||
assertThat(consumers).hasSize(2);
|
||||
consumers.forEach(
|
||||
c -> {
|
||||
assertThat(c).containsKeys("subscription_id", "credits", "connection_details", "queue");
|
||||
assertThat(c)
|
||||
.extractingByKey("connection_details", as(MAP))
|
||||
.containsValue(connectionName(c1));
|
||||
});
|
||||
|
||||
consumersRequest =
|
||||
() -> toMaps(get("/stream/connections/vh1/" + connectionName(c2) + "/consumers"));
|
||||
consumers = consumersRequest.call();
|
||||
assertThat(consumers).hasSize(1);
|
||||
assertThat(consumers.get(0))
|
||||
.extractingByKey("connection_details", as(MAP))
|
||||
.containsValue(connectionName(c2));
|
||||
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
get(
|
||||
httpClient("user-management"),
|
||||
"/stream/connections/vh1/" + connectionName(c1) + "/consumers"))
|
||||
.hasMessageContaining("401");
|
||||
} finally {
|
||||
c1.delete(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void connectionPublishers() throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/connections"));
|
||||
int initialCount = request.call().size();
|
||||
String s = UUID.randomUUID().toString();
|
||||
Client c1 = cf.get(new ClientParameters().virtualHost("vh1"));
|
||||
try {
|
||||
c1.create(s);
|
||||
assertThat(c1.declarePublisher((byte) 0, null, s).isOk()).isTrue();
|
||||
assertThat(c1.declarePublisher((byte) 1, null, s).isOk()).isTrue();
|
||||
Client c2 =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.virtualHost("vh1")
|
||||
.username("user-management")
|
||||
.password("user-management"));
|
||||
assertThat(c2.declarePublisher((byte) 0, null, s).isOk()).isTrue();
|
||||
waitUntil(() -> request.call().size() == initialCount + 2);
|
||||
|
||||
Callable<Map<String, Object>> cRequest =
|
||||
() -> toMap(get("/stream/connections/vh1/" + connectionName(c1)));
|
||||
// wait until some stats are in the response
|
||||
waitUntil(() -> cRequest.call().containsKey("recv_oct_details"));
|
||||
|
||||
Callable<List<Map<String, Object>>> publishersRequest =
|
||||
() -> toMaps(get("/stream/connections/vh1/" + connectionName(c1) + "/publishers"));
|
||||
List<Map<String, Object>> publishers = publishersRequest.call();
|
||||
|
||||
assertThat(publishers).hasSize(2);
|
||||
publishers.forEach(
|
||||
c -> {
|
||||
assertThat(c)
|
||||
.containsKeys(
|
||||
"publisher_id",
|
||||
"reference",
|
||||
"published",
|
||||
"confirmed",
|
||||
"errored",
|
||||
"connection_details",
|
||||
"queue");
|
||||
assertThat(c)
|
||||
.extractingByKey("connection_details", as(MAP))
|
||||
.containsValue(connectionName(c1));
|
||||
});
|
||||
|
||||
publishersRequest =
|
||||
() -> toMaps(get("/stream/connections/vh1/" + connectionName(c2) + "/publishers"));
|
||||
publishers = publishersRequest.call();
|
||||
assertThat(publishers).hasSize(1);
|
||||
assertThat(publishers.get(0))
|
||||
.extractingByKey("connection_details", as(MAP))
|
||||
.containsValue(connectionName(c2));
|
||||
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
get(
|
||||
httpClient("user-management"),
|
||||
"/stream/connections/vh1/" + connectionName(c1) + "/publishers"))
|
||||
.hasMessageContaining("401");
|
||||
} finally {
|
||||
c1.delete(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void publishers() throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/publishers"));
|
||||
int initialCount = request.call().size();
|
||||
String connectionProvidedName = UUID.randomUUID().toString();
|
||||
AtomicBoolean closed = new AtomicBoolean(false);
|
||||
Client client =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.clientProperty("connection_name", connectionProvidedName)
|
||||
.shutdownListener(shutdownContext -> closed.set(true)));
|
||||
|
||||
client.declarePublisher((byte) 0, null, stream);
|
||||
waitUntil(() -> request.call().size() == initialCount + 1);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
|
||||
Map<String, Object> publisher = entities(request.call(), client).get(0);
|
||||
assertThat(publisher.get("reference").toString()).isEmpty();
|
||||
assertThat(((Number) publisher.get("published")).intValue()).isEqualTo(0);
|
||||
assertThat(((Number) publisher.get("confirmed")).intValue()).isEqualTo(0);
|
||||
assertThat(((Number) publisher.get("errored")).intValue()).isEqualTo(0);
|
||||
assertThat(((Number) publisher.get("publisher_id")).intValue()).isEqualTo(0);
|
||||
assertThat(connectionDetails(publisher))
|
||||
.containsEntry("name", connectionName(client))
|
||||
.containsEntry("user", "guest")
|
||||
.containsKey("node");
|
||||
assertThat(queue(publisher)).containsEntry("name", stream).containsEntry("vhost", "/");
|
||||
|
||||
client.publish(
|
||||
(byte) 0,
|
||||
Collections.singletonList(
|
||||
client.messageBuilder().addData("".getBytes(StandardCharsets.UTF_8)).build()));
|
||||
|
||||
waitUntil(
|
||||
() -> ((Number) entities(request.call(), client).get(0).get("confirmed")).intValue() == 1);
|
||||
publisher = entities(request.call(), client).get(0);
|
||||
assertThat(((Number) publisher.get("published")).intValue()).isEqualTo(1);
|
||||
assertThat(((Number) publisher.get("confirmed")).intValue()).isEqualTo(1);
|
||||
|
||||
client.declarePublisher((byte) 1, null, stream);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 2);
|
||||
|
||||
client.deletePublisher((byte) 0);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
client.deletePublisher((byte) 1);
|
||||
waitUntil(() -> entities(request.call(), client).isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"foo"})
|
||||
@NullSource
|
||||
void publisherReference(String reference) throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/publishers"));
|
||||
int initialCount = request.call().size();
|
||||
String connectionProvidedName = UUID.randomUUID().toString();
|
||||
AtomicBoolean closed = new AtomicBoolean(false);
|
||||
Client client =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.clientProperty("connection_name", connectionProvidedName)
|
||||
.shutdownListener(shutdownContext -> closed.set(true)));
|
||||
|
||||
client.declarePublisher((byte) 0, reference, stream);
|
||||
waitUntil(() -> request.call().size() == initialCount + 1);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
|
||||
Map<String, Object> publisher = entities(request.call(), client).get(0);
|
||||
String publisherReference = (String) publisher.get("reference");
|
||||
if (reference == null || reference.isEmpty()) {
|
||||
assertThat(publisherReference).isEmpty();
|
||||
} else {
|
||||
assertThat(publisher.get("reference").toString()).isEqualTo(reference);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"foo"})
|
||||
@NullSource
|
||||
void publisherShouldBeDeletedAfterStreamDeletion(String reference) throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/publishers"));
|
||||
int initialCount = request.call().size();
|
||||
String connectionProvidedName = UUID.randomUUID().toString();
|
||||
String s = UUID.randomUUID().toString();
|
||||
AtomicBoolean closed = new AtomicBoolean(false);
|
||||
Client client =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.clientProperty("connection_name", connectionProvidedName)
|
||||
.shutdownListener(shutdownContext -> closed.set(true)));
|
||||
|
||||
client.create(s);
|
||||
client.declarePublisher((byte) 0, reference, s);
|
||||
waitUntil(() -> request.call().size() == initialCount + 1);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
|
||||
client.delete(s);
|
||||
waitUntil(() -> request.call().size() == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void consumerShouldBeDeletedAfterStreamDeletion() throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/consumers"));
|
||||
int initialCount = request.call().size();
|
||||
String connectionProvidedName = UUID.randomUUID().toString();
|
||||
String s = UUID.randomUUID().toString();
|
||||
AtomicBoolean closed = new AtomicBoolean(false);
|
||||
Client client =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.clientProperty("connection_name", connectionProvidedName)
|
||||
.shutdownListener(shutdownContext -> closed.set(true)));
|
||||
|
||||
client.create(s);
|
||||
client.subscribe((byte) 0, s, OffsetSpecification.first(), 10);
|
||||
waitUntil(() -> request.call().size() == initialCount + 1);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
|
||||
client.delete(s);
|
||||
waitUntil(() -> request.call().size() == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void consumers() throws Exception {
|
||||
Callable<List<Map<String, Object>>> request = () -> toMaps(get("/stream/consumers"));
|
||||
int initialCount = request.call().size();
|
||||
String connectionProvidedName = UUID.randomUUID().toString();
|
||||
AtomicBoolean closed = new AtomicBoolean(false);
|
||||
Client client =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.clientProperty("connection_name", connectionProvidedName)
|
||||
.chunkListener(
|
||||
(client1, subscriptionId, offset, messageCount, dataSize) ->
|
||||
client1.credit(subscriptionId, 1))
|
||||
.shutdownListener(shutdownContext -> closed.set(true)));
|
||||
|
||||
client.subscribe((byte) 0, stream, OffsetSpecification.first(), 10);
|
||||
waitUntil(() -> request.call().size() == initialCount + 1);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
|
||||
Map<String, Object> consumer = entities(request.call(), client).get(0);
|
||||
assertThat(((Number) consumer.get("credits")).intValue()).isEqualTo(10);
|
||||
assertThat(((Number) consumer.get("consumed")).intValue()).isEqualTo(0);
|
||||
assertThat(((Number) consumer.get("offset")).intValue()).isEqualTo(0);
|
||||
assertThat(((Number) consumer.get("subscription_id")).intValue()).isEqualTo(0);
|
||||
assertThat(connectionDetails(consumer))
|
||||
.containsEntry("name", connectionName(client))
|
||||
.containsEntry("user", "guest")
|
||||
.containsKey("node");
|
||||
assertThat(queue(consumer)).containsEntry("name", stream).containsEntry("vhost", "/");
|
||||
|
||||
client.subscribe((byte) 1, stream, OffsetSpecification.first(), 10);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 2);
|
||||
|
||||
client.unsubscribe((byte) 0);
|
||||
waitUntil(() -> entities(request.call(), client).size() == 1);
|
||||
|
||||
int messageCount = 10_000;
|
||||
assertThat(client.declarePublisher((byte) 0, null, stream).isOk()).isTrue();
|
||||
IntStream.range(0, messageCount)
|
||||
.forEach(
|
||||
i ->
|
||||
client.publish(
|
||||
(byte) 0,
|
||||
Collections.singletonList(
|
||||
client
|
||||
.messageBuilder()
|
||||
.addData("".getBytes(StandardCharsets.UTF_8))
|
||||
.build())));
|
||||
|
||||
waitUntil(
|
||||
() -> {
|
||||
Map<String, Object> c = entities(request.call(), client).get(0);
|
||||
return ((Number) c.get("consumed")).intValue() == messageCount;
|
||||
});
|
||||
|
||||
consumer = entities(request.call(), client).get(0);
|
||||
assertThat(((Number) consumer.get("consumed")).intValue()).isEqualTo(messageCount);
|
||||
assertThat(((Number) consumer.get("offset")).intValue()).isPositive();
|
||||
|
||||
client.unsubscribe((byte) 1);
|
||||
waitUntil(() -> entities(request.call(), client).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissions() throws Exception {
|
||||
String[][] vhostsUsers =
|
||||
new String[][] {
|
||||
{"/", "guest"},
|
||||
{"vh1", "user-management"},
|
||||
{"vh1", "user-management"},
|
||||
{"vh2", "guest"},
|
||||
{"vh2", "guest"},
|
||||
};
|
||||
Map<String, Client> vhostClients = new HashMap<>();
|
||||
List<Client> clients =
|
||||
Arrays.stream(vhostsUsers)
|
||||
.map(
|
||||
vhostUser -> {
|
||||
Client c =
|
||||
cf.get(
|
||||
new ClientParameters()
|
||||
.virtualHost(vhostUser[0])
|
||||
.username(vhostUser[1])
|
||||
.password(vhostUser[1]));
|
||||
vhostClients.put(vhostUser[0], c);
|
||||
return c;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> nonDefaultVhosts =
|
||||
Arrays.stream(vhostsUsers)
|
||||
.map(vhostUser -> vhostUser[0])
|
||||
.filter(vhost -> !vhost.equals("/"))
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
nonDefaultVhosts.forEach(
|
||||
vhost -> {
|
||||
Client c = vhostClients.get(vhost);
|
||||
c.create(stream);
|
||||
});
|
||||
|
||||
try {
|
||||
int entitiesPerConnection = 2;
|
||||
|
||||
IntStream.range(0, entitiesPerConnection)
|
||||
.forEach(
|
||||
i ->
|
||||
clients.forEach(
|
||||
c -> {
|
||||
c.subscribe((byte) i, stream, OffsetSpecification.first(), 10);
|
||||
c.declarePublisher((byte) i, null, stream);
|
||||
}));
|
||||
Callable<List<Map<String, Object>>> allConnectionsRequest =
|
||||
() -> toMaps(get("/stream/connections"));
|
||||
int initialCount = allConnectionsRequest.call().size();
|
||||
waitUntil(() -> allConnectionsRequest.call().size() == initialCount + 5);
|
||||
|
||||
String vhost1ConnectionName =
|
||||
toMaps(get("/stream/connections/vh1")).stream()
|
||||
.filter(c -> "vh1".equals(c.get("vhost")))
|
||||
.map(c -> c.get("name").toString())
|
||||
.findFirst()
|
||||
.get();
|
||||
|
||||
String vhost2ConnectionName =
|
||||
toMaps(get("/stream/connections/vh2")).stream()
|
||||
.filter(c -> "vh2".equals(c.get("vhost")))
|
||||
.map(c -> c.get("name").toString())
|
||||
.findFirst()
|
||||
.get();
|
||||
|
||||
PermissionsTestConfiguration[] testConfigurations =
|
||||
new PermissionsTestConfiguration[] {
|
||||
new PermissionsTestConfiguration(
|
||||
"guest",
|
||||
"/connections",
|
||||
requests(r("", 5), r("/%2f", 1), r("/vh1", 2), r("/vh2", 2)),
|
||||
"vh1/" + vhost1ConnectionName,
|
||||
true,
|
||||
"vh2/" + vhost2ConnectionName,
|
||||
true),
|
||||
new PermissionsTestConfiguration(
|
||||
"user-monitoring",
|
||||
"/connections",
|
||||
requests(r("", 5), r("/%2f", 1), r("/vh1", 2), r("/vh2", 2)),
|
||||
"vh1/" + vhost1ConnectionName,
|
||||
true,
|
||||
"vh2/" + vhost2ConnectionName,
|
||||
true),
|
||||
new PermissionsTestConfiguration(
|
||||
"user-management",
|
||||
"/connections",
|
||||
requests(r("", 2), r("/%2f", -1), r("/vh1", 2), r("/vh2", -1)),
|
||||
"vh1/" + vhost1ConnectionName,
|
||||
true,
|
||||
"vh2/" + vhost2ConnectionName,
|
||||
false),
|
||||
new PermissionsTestConfiguration(
|
||||
"guest",
|
||||
"",
|
||||
requests(
|
||||
r("/consumers", vhostsUsers.length * entitiesPerConnection),
|
||||
r("/publishers", vhostsUsers.length * entitiesPerConnection),
|
||||
r("/consumers/%2f", entitiesPerConnection),
|
||||
r("/publishers/%2f", entitiesPerConnection),
|
||||
r("/consumers/vh1", entitiesPerConnection * 2),
|
||||
r("/publishers/vh1", entitiesPerConnection * 2))),
|
||||
new PermissionsTestConfiguration(
|
||||
"user-management",
|
||||
"",
|
||||
requests(
|
||||
r("/consumers", entitiesPerConnection * 2), // only their connections
|
||||
r("/publishers", entitiesPerConnection * 2), // only their connections
|
||||
r("/consumers/vh1", entitiesPerConnection * 2),
|
||||
r("/publishers/vh1", entitiesPerConnection * 2),
|
||||
r("/consumers/vh2", 0),
|
||||
r("/consumers/vh2", 0)))
|
||||
};
|
||||
|
||||
for (PermissionsTestConfiguration configuration : testConfigurations) {
|
||||
OkHttpClient client = httpClient(configuration.user);
|
||||
for (TestRequest request : configuration.requests) {
|
||||
if (request.expectedCount >= 0) {
|
||||
assertThat(toMaps(get(client, "/stream" + configuration.endpoint + request.endpoint)))
|
||||
.hasSize(request.expectedCount);
|
||||
} else {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
toMaps(get(client, "/stream" + configuration.endpoint + request.endpoint)))
|
||||
.hasMessageContaining("401");
|
||||
}
|
||||
}
|
||||
for (Entry<String, Boolean> request : configuration.vhostConnections.entrySet()) {
|
||||
if (request.getValue()) {
|
||||
Condition<Object> connNameCondition =
|
||||
new Condition<>(
|
||||
e -> request.getKey().endsWith(e.toString()), "connection name must match");
|
||||
assertThat(toMap(get(client, "/stream/connections/" + request.getKey())))
|
||||
.hasEntrySatisfying("name", connNameCondition);
|
||||
} else {
|
||||
assertThatThrownBy(() -> toMap(get(client, "/stream/connections/" + request.getKey())))
|
||||
.hasMessageContaining("401");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clients.forEach(Client::close);
|
||||
waitUntil(() -> allConnectionsRequest.call().size() == initialCount);
|
||||
} finally {
|
||||
nonDefaultVhosts.forEach(
|
||||
vhost -> {
|
||||
Client c = cf.get(new ClientParameters().virtualHost(vhost));
|
||||
c.delete(stream);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(
|
||||
strings = {
|
||||
"/stream/connections/%2F/foo-connection-name",
|
||||
"/stream/connections/foo-virtual-host",
|
||||
"/stream/connections/foo-virtual-host/foo-connection-name",
|
||||
"/stream/connections/%2F/foo-connection-name/consumers",
|
||||
"/stream/connections/%2F/foo-connection-name/publishers",
|
||||
"/stream/consumers/foo-virtual-host",
|
||||
"/stream/publishers/foo-virtual-host"
|
||||
})
|
||||
void shouldReturnNotFound(String endpoint) {
|
||||
assertThatThrownBy(() -> get(endpoint)).hasMessageContaining("404");
|
||||
}
|
||||
|
||||
static class PermissionsTestConfiguration {
|
||||
final String user;
|
||||
final String endpoint;
|
||||
final TestRequest[] requests;
|
||||
final Map<String, Boolean> vhostConnections;
|
||||
|
||||
PermissionsTestConfiguration(
|
||||
String user, String endpoint, TestRequest[] requests, Object... vhostConnections) {
|
||||
this.user = user;
|
||||
this.endpoint = endpoint;
|
||||
this.requests = requests;
|
||||
this.vhostConnections = new LinkedHashMap<>();
|
||||
for (int i = 0; i < vhostConnections.length; i = i + 2) {
|
||||
this.vhostConnections.put(
|
||||
vhostConnections[i].toString(), (Boolean) vhostConnections[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TestRequest {
|
||||
final String endpoint;
|
||||
final int expectedCount;
|
||||
|
||||
TestRequest(String endpoint, int expectedCount) {
|
||||
this.endpoint = endpoint;
|
||||
this.expectedCount = expectedCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
// The contents of this file are subject to the Mozilla Public License
|
||||
// Version 2.0 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License
|
||||
// at https://www.mozilla.org/en-US/MPL/2.0/
|
||||
//
|
||||
// Software distributed under the License is distributed on an "AS IS"
|
||||
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
// the License for the specific language governing rights and
|
||||
// limitations under the License.
|
||||
//
|
||||
// The Original Code is RabbitMQ.
|
||||
//
|
||||
// The Initial Developer of the Original Code is Pivotal Software, Inc.
|
||||
// Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved.
|
||||
//
|
||||
|
||||
package com.rabbitmq.stream;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import com.rabbitmq.stream.impl.Client;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.Duration;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import okhttp3.Authenticator;
|
||||
import okhttp3.Credentials;
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
public class TestUtils {
|
||||
|
||||
static int streamPort() {
|
||||
String port = System.getProperty("stream.port", "5555");
|
||||
return Integer.valueOf(port);
|
||||
}
|
||||
|
||||
static int managementPort() {
|
||||
String port = System.getProperty("management.port", "15672");
|
||||
return Integer.valueOf(port);
|
||||
}
|
||||
|
||||
static void waitUntil(CallableBooleanSupplier condition) throws Exception {
|
||||
waitAtMost(Duration.ofSeconds(10), condition);
|
||||
}
|
||||
|
||||
static void waitAtMost(Duration duration, CallableBooleanSupplier condition) throws Exception {
|
||||
if (condition.getAsBoolean()) {
|
||||
return;
|
||||
}
|
||||
int waitTime = 100;
|
||||
int waitedTime = 0;
|
||||
long timeoutInMs = duration.toMillis();
|
||||
while (waitedTime <= timeoutInMs) {
|
||||
Thread.sleep(waitTime);
|
||||
if (condition.getAsBoolean()) {
|
||||
return;
|
||||
}
|
||||
waitedTime += waitTime;
|
||||
}
|
||||
fail("Waited " + duration.getSeconds() + " second(s), condition never got true");
|
||||
}
|
||||
|
||||
static Authenticator authenticator(String usernamePassword) {
|
||||
return (route, response) -> {
|
||||
if (response.request().header("Authorization") != null) {
|
||||
return null; // Give up, we've already attempted to authenticate.
|
||||
}
|
||||
return response
|
||||
.request()
|
||||
.newBuilder()
|
||||
.header("Authorization", Credentials.basic(usernamePassword, usernamePassword))
|
||||
.build();
|
||||
};
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface CallableBooleanSupplier {
|
||||
boolean getAsBoolean() throws Exception;
|
||||
}
|
||||
|
||||
static class StreamTestInfrastructureExtension
|
||||
implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback {
|
||||
|
||||
private static final ExtensionContext.Namespace NAMESPACE =
|
||||
ExtensionContext.Namespace.create(StreamTestInfrastructureExtension.class);
|
||||
|
||||
private static ExtensionContext.Store store(ExtensionContext extensionContext) {
|
||||
return extensionContext.getRoot().getStore(NAMESPACE);
|
||||
}
|
||||
|
||||
private static EventLoopGroup eventLoopGroup(ExtensionContext context) {
|
||||
return (EventLoopGroup) store(context).get("nettyEventLoopGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) {
|
||||
store(context).put("nettyEventLoopGroup", new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) throws Exception {
|
||||
try {
|
||||
Field streamField =
|
||||
context.getTestInstance().get().getClass().getDeclaredField("eventLoopGroup");
|
||||
streamField.setAccessible(true);
|
||||
streamField.set(context.getTestInstance().get(), eventLoopGroup(context));
|
||||
} catch (NoSuchFieldException e) {
|
||||
|
||||
}
|
||||
try {
|
||||
Field streamField = context.getTestInstance().get().getClass().getDeclaredField("stream");
|
||||
streamField.setAccessible(true);
|
||||
String stream = UUID.randomUUID().toString();
|
||||
streamField.set(context.getTestInstance().get(), stream);
|
||||
Client client =
|
||||
new Client(
|
||||
new Client.ClientParameters()
|
||||
.eventLoopGroup(eventLoopGroup(context))
|
||||
.port(streamPort()));
|
||||
Client.Response response = client.create(stream);
|
||||
assertThat(response.isOk()).isTrue();
|
||||
client.close();
|
||||
store(context).put("testMethodStream", stream);
|
||||
} catch (NoSuchFieldException e) {
|
||||
|
||||
}
|
||||
|
||||
for (Field declaredField : context.getTestInstance().get().getClass().getDeclaredFields()) {
|
||||
if (declaredField.getType().equals(ClientFactory.class)) {
|
||||
declaredField.setAccessible(true);
|
||||
ClientFactory clientFactory = new ClientFactory(eventLoopGroup(context));
|
||||
declaredField.set(context.getTestInstance().get(), clientFactory);
|
||||
store(context).put("testClientFactory", clientFactory);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) throws Exception {
|
||||
try {
|
||||
Field streamField = context.getTestInstance().get().getClass().getDeclaredField("stream");
|
||||
streamField.setAccessible(true);
|
||||
String stream = (String) streamField.get(context.getTestInstance().get());
|
||||
Client client =
|
||||
new Client(
|
||||
new Client.ClientParameters()
|
||||
.eventLoopGroup(eventLoopGroup(context))
|
||||
.port(streamPort()));
|
||||
Client.Response response = client.delete(stream);
|
||||
assertThat(response.isOk()).isTrue();
|
||||
client.close();
|
||||
store(context).remove("testMethodStream");
|
||||
} catch (NoSuchFieldException e) {
|
||||
|
||||
}
|
||||
|
||||
ClientFactory clientFactory = (ClientFactory) store(context).get("testClientFactory");
|
||||
if (clientFactory != null) {
|
||||
clientFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) throws Exception {
|
||||
EventLoopGroup eventLoopGroup = eventLoopGroup(context);
|
||||
eventLoopGroup.shutdownGracefully(1, 10, SECONDS).get(10, SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
static class ClientFactory {
|
||||
|
||||
private final EventLoopGroup eventLoopGroup;
|
||||
private final Set<Client> clients = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public ClientFactory(EventLoopGroup eventLoopGroup) {
|
||||
this.eventLoopGroup = eventLoopGroup;
|
||||
}
|
||||
|
||||
public Client get() {
|
||||
return get(new Client.ClientParameters());
|
||||
}
|
||||
|
||||
public Client get(Client.ClientParameters parameters) {
|
||||
Client client = new Client(parameters.eventLoopGroup(eventLoopGroup).port(streamPort()));
|
||||
clients.add(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
private void close() {
|
||||
for (Client c : clients) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
deps/rabbitmq_stream_management/test/http_SUITE_data/src/test/resources/logback-test.xml
vendored
Normal file
13
deps/rabbitmq_stream_management/test/http_SUITE_data/src/test/resources/logback-test.xml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="com.rabbitmq.stream" level="info" />
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ PLUGINS := rabbitmq_amqp1_0 \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
rabbitmq_trust_store \
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_re
|
|||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stream_management = git_rmq rabbitmq-stream-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
|
@ -177,6 +178,7 @@ RABBITMQ_COMPONENTS = amqp_client \
|
|||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_stream \
|
||||
rabbitmq_stream_management \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
|
|
|
|||
Loading…
Reference in New Issue