feat(emqx_bridge): add separate endpoint for enable/disable of bridge
In order to improve the consistency with other API endpoints, we move the enable/disable operations to a separate endpoint /bridges/{id}/enable/[true,false].
This commit is contained in:
parent
860e21d40f
commit
42f42de4d9
|
@ -2,8 +2,8 @@ emqx_bridge_api {
|
||||||
|
|
||||||
desc_param_path_operation_cluster {
|
desc_param_path_operation_cluster {
|
||||||
desc {
|
desc {
|
||||||
en: """Operations can be one of: enable, disable, start, stop, restart"""
|
en: """Operations can be one of: start, stop, restart"""
|
||||||
zh: """集群可用操作:启用、禁用、启动、停止、重新启动"""
|
zh: """"""
|
||||||
}
|
}
|
||||||
label: {
|
label: {
|
||||||
en: "Cluster Operation"
|
en: "Cluster Operation"
|
||||||
|
@ -44,6 +44,16 @@ emqx_bridge_api {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
desc_param_path_enable {
|
||||||
|
desc {
|
||||||
|
en: """Whether or not the bridge is enabled"""
|
||||||
|
zh: """"""
|
||||||
|
}
|
||||||
|
label: {
|
||||||
|
en: "Enable bridge"
|
||||||
|
zh: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
desc_api1 {
|
desc_api1 {
|
||||||
desc {
|
desc {
|
||||||
en: """List all created bridges"""
|
en: """List all created bridges"""
|
||||||
|
@ -112,8 +122,8 @@ emqx_bridge_api {
|
||||||
|
|
||||||
desc_api7 {
|
desc_api7 {
|
||||||
desc {
|
desc {
|
||||||
en: """Enable/Disable/Stop/Restart bridges on all nodes in the cluster."""
|
en: """Stop/Restart bridges on all nodes in the cluster."""
|
||||||
zh: """在集群中的所有节点上启用/禁用/停止/重新启动 Bridge。"""
|
zh: """"""
|
||||||
}
|
}
|
||||||
label: {
|
label: {
|
||||||
en: "Cluster Bridge Operate"
|
en: "Cluster Bridge Operate"
|
||||||
|
@ -123,10 +133,8 @@ emqx_bridge_api {
|
||||||
|
|
||||||
desc_api8 {
|
desc_api8 {
|
||||||
desc {
|
desc {
|
||||||
en: """Stop/Restart bridges on a specific node.
|
en: """Stop/Restart bridges on a specific node."""
|
||||||
NOTE: It's not allowed to disable/enable bridges on a single node."""
|
zh: """在某个节点上停止/重新启动 Bridge。"""
|
||||||
zh: """在某个节点上停止/重新启动 Bridge。
|
|
||||||
NOTE:不允许在单节点上启用/禁用 Bridge"""
|
|
||||||
}
|
}
|
||||||
label: {
|
label: {
|
||||||
en: "Node Bridge Operate"
|
en: "Node Bridge Operate"
|
||||||
|
@ -144,4 +152,15 @@ NOTE:不允许在单节点上启用/禁用 Bridge"""
|
||||||
zh: ""
|
zh: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
desc_enable_bridge {
|
||||||
|
desc {
|
||||||
|
en: """Enable or Disable bridges on all nodes in the cluster."""
|
||||||
|
zh: """"""
|
||||||
|
}
|
||||||
|
label: {
|
||||||
|
en: "Cluster Bridge Enable"
|
||||||
|
zh: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
-export([
|
-export([
|
||||||
'/bridges'/2,
|
'/bridges'/2,
|
||||||
'/bridges/:id'/2,
|
'/bridges/:id'/2,
|
||||||
|
'/bridges/:id/enable/:enable'/2,
|
||||||
'/bridges/:id/:operation'/2,
|
'/bridges/:id/:operation'/2,
|
||||||
'/nodes/:node/bridges/:id/:operation'/2,
|
'/nodes/:node/bridges/:id/:operation'/2,
|
||||||
'/bridges/:id/metrics'/2,
|
'/bridges/:id/metrics'/2,
|
||||||
|
@ -67,6 +68,7 @@ paths() ->
|
||||||
[
|
[
|
||||||
"/bridges",
|
"/bridges",
|
||||||
"/bridges/:id",
|
"/bridges/:id",
|
||||||
|
"/bridges/:id/enable/:enable",
|
||||||
"/bridges/:id/:operation",
|
"/bridges/:id/:operation",
|
||||||
"/nodes/:node/bridges/:id/:operation",
|
"/nodes/:node/bridges/:id/:operation",
|
||||||
"/bridges/:id/metrics",
|
"/bridges/:id/metrics",
|
||||||
|
@ -89,7 +91,7 @@ get_response_body_schema() ->
|
||||||
param_path_operation_cluster() ->
|
param_path_operation_cluster() ->
|
||||||
{operation,
|
{operation,
|
||||||
mk(
|
mk(
|
||||||
enum([enable, disable, stop, restart]),
|
enum([stop, restart]),
|
||||||
#{
|
#{
|
||||||
in => path,
|
in => path,
|
||||||
required => true,
|
required => true,
|
||||||
|
@ -134,6 +136,17 @@ param_path_id() ->
|
||||||
}
|
}
|
||||||
)}.
|
)}.
|
||||||
|
|
||||||
|
param_path_enable() ->
|
||||||
|
{enable,
|
||||||
|
mk(
|
||||||
|
boolean(),
|
||||||
|
#{
|
||||||
|
in => path,
|
||||||
|
desc => ?DESC("desc_param_path_enable"),
|
||||||
|
example => true
|
||||||
|
}
|
||||||
|
)}.
|
||||||
|
|
||||||
bridge_info_array_example(Method, WithMetrics) ->
|
bridge_info_array_example(Method, WithMetrics) ->
|
||||||
[Config || #{value := Config} <- maps:values(bridge_info_examples(Method, WithMetrics))].
|
[Config || #{value := Config} <- maps:values(bridge_info_examples(Method, WithMetrics))].
|
||||||
|
|
||||||
|
@ -367,12 +380,29 @@ schema("/bridges/:id/metrics/reset") ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
schema("/bridges/:id/enable/:enable") ->
|
||||||
|
#{
|
||||||
|
'operationId' => '/bridges/:id/enable/:enable',
|
||||||
|
put =>
|
||||||
|
#{
|
||||||
|
tags => [<<"bridges">>],
|
||||||
|
summary => <<"Enable or Disable Bridge">>,
|
||||||
|
desc => ?DESC("desc_enable_bridge"),
|
||||||
|
parameters => [param_path_id(), param_path_enable()],
|
||||||
|
responses =>
|
||||||
|
#{
|
||||||
|
204 => <<"Success">>,
|
||||||
|
400 => error_schema('INVALID_ID', "Bad bridge ID"),
|
||||||
|
503 => error_schema('SERVICE_UNAVAILABLE', "Service unavailable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
schema("/bridges/:id/:operation") ->
|
schema("/bridges/:id/:operation") ->
|
||||||
#{
|
#{
|
||||||
'operationId' => '/bridges/:id/:operation',
|
'operationId' => '/bridges/:id/:operation',
|
||||||
post => #{
|
post => #{
|
||||||
tags => [<<"bridges">>],
|
tags => [<<"bridges">>],
|
||||||
summary => <<"Enable/Disable/Stop/Restart Bridge">>,
|
summary => <<"Stop or Restart Bridge">>,
|
||||||
description => ?DESC("desc_api7"),
|
description => ?DESC("desc_api7"),
|
||||||
parameters => [
|
parameters => [
|
||||||
param_path_id(),
|
param_path_id(),
|
||||||
|
@ -515,6 +545,28 @@ lookup_from_local_node(BridgeType, BridgeName) ->
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
'/bridges/:id/enable/:enable'(put, #{bindings := #{id := Id, enable := Enable}}) ->
|
||||||
|
?TRY_PARSE_ID(
|
||||||
|
Id,
|
||||||
|
case enable_func(Enable) of
|
||||||
|
invalid ->
|
||||||
|
{400, error_msg('BAD_REQUEST', <<"invalid operation">>)};
|
||||||
|
OperFunc ->
|
||||||
|
case emqx_bridge:disable_enable(OperFunc, BridgeType, BridgeName) of
|
||||||
|
{ok, _} ->
|
||||||
|
{204};
|
||||||
|
{error, {pre_config_update, _, bridge_not_found}} ->
|
||||||
|
{404, error_msg('NOT_FOUND', <<"bridge not found">>)};
|
||||||
|
{error, {_, _, timeout}} ->
|
||||||
|
{503, error_msg('SERVICE_UNAVAILABLE', <<"request timeout">>)};
|
||||||
|
{error, timeout} ->
|
||||||
|
{503, error_msg('SERVICE_UNAVAILABLE', <<"request timeout">>)};
|
||||||
|
{error, Reason} ->
|
||||||
|
{500, error_msg('INTERNAL_ERROR', Reason)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
).
|
||||||
|
|
||||||
'/bridges/:id/:operation'(post, #{
|
'/bridges/:id/:operation'(post, #{
|
||||||
bindings :=
|
bindings :=
|
||||||
#{id := Id, operation := Op}
|
#{id := Id, operation := Op}
|
||||||
|
@ -524,19 +576,6 @@ lookup_from_local_node(BridgeType, BridgeName) ->
|
||||||
case operation_func(Op) of
|
case operation_func(Op) of
|
||||||
invalid ->
|
invalid ->
|
||||||
{400, error_msg('BAD_REQUEST', <<"invalid operation">>)};
|
{400, error_msg('BAD_REQUEST', <<"invalid operation">>)};
|
||||||
OperFunc when OperFunc == enable; OperFunc == disable ->
|
|
||||||
case emqx_bridge:disable_enable(OperFunc, BridgeType, BridgeName) of
|
|
||||||
{ok, _} ->
|
|
||||||
{200};
|
|
||||||
{error, {pre_config_update, _, bridge_not_found}} ->
|
|
||||||
{404, error_msg('NOT_FOUND', <<"bridge not found">>)};
|
|
||||||
{error, {_, _, timeout}} ->
|
|
||||||
{503, error_msg('SERVICE_UNAVAILABLE', <<"request timeout">>)};
|
|
||||||
{error, timeout} ->
|
|
||||||
{503, error_msg('SERVICE_UNAVAILABLE', <<"request timeout">>)};
|
|
||||||
{error, Reason} ->
|
|
||||||
{500, error_msg('INTERNAL_ERROR', Reason)}
|
|
||||||
end;
|
|
||||||
OperFunc ->
|
OperFunc ->
|
||||||
Nodes = mria_mnesia:running_nodes(),
|
Nodes = mria_mnesia:running_nodes(),
|
||||||
operation_to_all_nodes(Nodes, OperFunc, BridgeType, BridgeName)
|
operation_to_all_nodes(Nodes, OperFunc, BridgeType, BridgeName)
|
||||||
|
@ -573,10 +612,12 @@ node_operation_func(_) -> invalid.
|
||||||
|
|
||||||
operation_func(<<"stop">>) -> stop;
|
operation_func(<<"stop">>) -> stop;
|
||||||
operation_func(<<"restart">>) -> restart;
|
operation_func(<<"restart">>) -> restart;
|
||||||
operation_func(<<"enable">>) -> enable;
|
|
||||||
operation_func(<<"disable">>) -> disable;
|
|
||||||
operation_func(_) -> invalid.
|
operation_func(_) -> invalid.
|
||||||
|
|
||||||
|
enable_func(<<"true">>) -> enable;
|
||||||
|
enable_func(<<"false">>) -> disable;
|
||||||
|
enable_func(_) -> invalid.
|
||||||
|
|
||||||
operation_to_all_nodes(Nodes, OperFunc, BridgeType, BridgeName) ->
|
operation_to_all_nodes(Nodes, OperFunc, BridgeType, BridgeName) ->
|
||||||
RpcFunc =
|
RpcFunc =
|
||||||
case OperFunc of
|
case OperFunc of
|
||||||
|
|
|
@ -498,19 +498,19 @@ t_enable_disable_bridges(Config) ->
|
||||||
} = jsx:decode(Bridge),
|
} = jsx:decode(Bridge),
|
||||||
BridgeID = emqx_bridge_resource:bridge_id(?BRIDGE_TYPE, Name),
|
BridgeID = emqx_bridge_resource:bridge_id(?BRIDGE_TYPE, Name),
|
||||||
%% disable it
|
%% disable it
|
||||||
{ok, 200, <<>>} = request(post, operation_path(cluster, disable, BridgeID), <<"">>),
|
{ok, 204, <<>>} = request(put, enable_path(false, BridgeID), <<"">>),
|
||||||
{ok, 200, Bridge2} = request(get, uri(["bridges", BridgeID]), []),
|
{ok, 200, Bridge2} = request(get, uri(["bridges", BridgeID]), []),
|
||||||
?assertMatch(#{<<"status">> := <<"stopped">>}, jsx:decode(Bridge2)),
|
?assertMatch(#{<<"status">> := <<"stopped">>}, jsx:decode(Bridge2)),
|
||||||
%% enable again
|
%% enable again
|
||||||
{ok, 200, <<>>} = request(post, operation_path(cluster, enable, BridgeID), <<"">>),
|
{ok, 204, <<>>} = request(put, enable_path(true, BridgeID), <<"">>),
|
||||||
{ok, 200, Bridge3} = request(get, uri(["bridges", BridgeID]), []),
|
{ok, 200, Bridge3} = request(get, uri(["bridges", BridgeID]), []),
|
||||||
?assertMatch(#{<<"status">> := <<"connected">>}, jsx:decode(Bridge3)),
|
?assertMatch(#{<<"status">> := <<"connected">>}, jsx:decode(Bridge3)),
|
||||||
%% enable an already started bridge
|
%% enable an already started bridge
|
||||||
{ok, 200, <<>>} = request(post, operation_path(cluster, enable, BridgeID), <<"">>),
|
{ok, 204, <<>>} = request(put, enable_path(true, BridgeID), <<"">>),
|
||||||
{ok, 200, Bridge3} = request(get, uri(["bridges", BridgeID]), []),
|
{ok, 200, Bridge3} = request(get, uri(["bridges", BridgeID]), []),
|
||||||
?assertMatch(#{<<"status">> := <<"connected">>}, jsx:decode(Bridge3)),
|
?assertMatch(#{<<"status">> := <<"connected">>}, jsx:decode(Bridge3)),
|
||||||
%% disable it again
|
%% disable it again
|
||||||
{ok, 200, <<>>} = request(post, operation_path(cluster, disable, BridgeID), <<"">>),
|
{ok, 204, <<>>} = request(put, enable_path(false, BridgeID), <<"">>),
|
||||||
|
|
||||||
{ok, 403, Res} = request(post, operation_path(node, restart, BridgeID), <<"">>),
|
{ok, 403, Res} = request(post, operation_path(node, restart, BridgeID), <<"">>),
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
|
@ -519,7 +519,7 @@ t_enable_disable_bridges(Config) ->
|
||||||
),
|
),
|
||||||
|
|
||||||
%% enable a stopped bridge
|
%% enable a stopped bridge
|
||||||
{ok, 200, <<>>} = request(post, operation_path(cluster, enable, BridgeID), <<"">>),
|
{ok, 204, <<>>} = request(put, enable_path(true, BridgeID), <<"">>),
|
||||||
{ok, 200, Bridge4} = request(get, uri(["bridges", BridgeID]), []),
|
{ok, 200, Bridge4} = request(get, uri(["bridges", BridgeID]), []),
|
||||||
?assertMatch(#{<<"status">> := <<"connected">>}, jsx:decode(Bridge4)),
|
?assertMatch(#{<<"status">> := <<"connected">>}, jsx:decode(Bridge4)),
|
||||||
%% delete the bridge
|
%% delete the bridge
|
||||||
|
@ -674,5 +674,8 @@ operation_path(node, Oper, BridgeID) ->
|
||||||
operation_path(cluster, Oper, BridgeID) ->
|
operation_path(cluster, Oper, BridgeID) ->
|
||||||
uri(["bridges", BridgeID, Oper]).
|
uri(["bridges", BridgeID, Oper]).
|
||||||
|
|
||||||
|
enable_path(Enable, BridgeID) ->
|
||||||
|
uri(["bridges", BridgeID, "enable", Enable]).
|
||||||
|
|
||||||
str(S) when is_list(S) -> S;
|
str(S) when is_list(S) -> S;
|
||||||
str(S) when is_binary(S) -> binary_to_list(S).
|
str(S) when is_binary(S) -> binary_to_list(S).
|
||||||
|
|
Loading…
Reference in New Issue