feat(connectors api): add dependent actions and sources to response
Fixes https://emqx.atlassian.net/browse/EMQX-12654
This commit is contained in:
parent
3a893626b8
commit
ae828e8cfb
|
@ -252,23 +252,26 @@ init_per_testcase(TestCase, Config) when
|
||||||
BridgeConfig
|
BridgeConfig
|
||||||
| Config
|
| Config
|
||||||
];
|
];
|
||||||
init_per_testcase(_TestCase, Config) ->
|
init_per_testcase(TestCase, Config) ->
|
||||||
case ?config(cluster_nodes, Config) of
|
case ?config(cluster_nodes, Config) of
|
||||||
undefined ->
|
undefined ->
|
||||||
init_mocks();
|
init_mocks();
|
||||||
Nodes ->
|
Nodes ->
|
||||||
[erpc:call(Node, ?MODULE, init_mocks, []) || Node <- Nodes]
|
[erpc:call(Node, ?MODULE, init_mocks, []) || Node <- Nodes]
|
||||||
end,
|
end,
|
||||||
|
ShouldCreateConnector = not lists:member(TestCase, skip_connector_creation_test_cases()),
|
||||||
case ?config(bridge_kind, Config) of
|
case ?config(bridge_kind, Config) of
|
||||||
action ->
|
action when ShouldCreateConnector ->
|
||||||
{ok, 201, _} = request(post, uri(["connectors"]), ?ACTIONS_CONNECTOR, Config);
|
{ok, 201, _} = request(post, uri(["connectors"]), ?ACTIONS_CONNECTOR, Config);
|
||||||
source ->
|
source when ShouldCreateConnector ->
|
||||||
{ok, 201, _} = request(
|
{ok, 201, _} = request(
|
||||||
post,
|
post,
|
||||||
uri(["connectors"]),
|
uri(["connectors"]),
|
||||||
source_connector_create_config(#{}),
|
source_connector_create_config(#{}),
|
||||||
Config
|
Config
|
||||||
)
|
);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
end,
|
end,
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
|
@ -284,6 +287,11 @@ end_per_testcase(_TestCase, Config) ->
|
||||||
ok = emqx_common_test_helpers:call_janitor(),
|
ok = emqx_common_test_helpers:call_janitor(),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
skip_connector_creation_test_cases() ->
|
||||||
|
[
|
||||||
|
t_connector_dependencies
|
||||||
|
].
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% Helper fns
|
%% Helper fns
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
@ -500,6 +508,23 @@ source_config_base() ->
|
||||||
}
|
}
|
||||||
}.
|
}.
|
||||||
|
|
||||||
|
mqtt_action_config_base() ->
|
||||||
|
source_config_base().
|
||||||
|
|
||||||
|
mqtt_action_create_config(Overrides0) ->
|
||||||
|
Overrides = emqx_utils_maps:binary_key_map(Overrides0),
|
||||||
|
Conf0 = maps:merge(
|
||||||
|
mqtt_action_config_base(),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"type">> => ?SOURCE_TYPE
|
||||||
|
}
|
||||||
|
),
|
||||||
|
emqx_utils_maps:deep_merge(
|
||||||
|
Conf0,
|
||||||
|
Overrides
|
||||||
|
).
|
||||||
|
|
||||||
source_create_config(Overrides0) ->
|
source_create_config(Overrides0) ->
|
||||||
Overrides = emqx_utils_maps:binary_key_map(Overrides0),
|
Overrides = emqx_utils_maps:binary_key_map(Overrides0),
|
||||||
Conf0 = maps:merge(
|
Conf0 = maps:merge(
|
||||||
|
@ -575,6 +600,32 @@ maybe_get_other_node(Config) ->
|
||||||
OtherNode
|
OtherNode
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
list_connectors_api() ->
|
||||||
|
Res = emqx_bridge_v2_testlib:list_connectors_http_api(),
|
||||||
|
emqx_mgmt_api_test_util:simplify_result(Res).
|
||||||
|
|
||||||
|
get_connector_api(Type, Name) ->
|
||||||
|
Res = emqx_bridge_v2_testlib:get_connector_api(Type, Name),
|
||||||
|
emqx_mgmt_api_test_util:simplify_result(Res).
|
||||||
|
|
||||||
|
create_source_api(Name, Type, Params) ->
|
||||||
|
Res = emqx_bridge_v2_testlib:create_kind_api([
|
||||||
|
{bridge_kind, source},
|
||||||
|
{source_type, Type},
|
||||||
|
{source_name, Name},
|
||||||
|
{source_config, Params}
|
||||||
|
]),
|
||||||
|
emqx_mgmt_api_test_util:simplify_result(Res).
|
||||||
|
|
||||||
|
create_action_api(Name, Type, Params) ->
|
||||||
|
Res = emqx_bridge_v2_testlib:create_kind_api([
|
||||||
|
{bridge_kind, action},
|
||||||
|
{action_type, Type},
|
||||||
|
{action_name, Name},
|
||||||
|
{action_config, Params}
|
||||||
|
]),
|
||||||
|
emqx_mgmt_api_test_util:simplify_result(Res).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% Testcases
|
%% Testcases
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
@ -1598,3 +1649,97 @@ t_start_action_or_source_with_disabled_connector(matrix) ->
|
||||||
t_start_action_or_source_with_disabled_connector(Config) ->
|
t_start_action_or_source_with_disabled_connector(Config) ->
|
||||||
ok = emqx_bridge_v2_testlib:t_start_action_or_source_with_disabled_connector(Config),
|
ok = emqx_bridge_v2_testlib:t_start_action_or_source_with_disabled_connector(Config),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
%% Verifies that listing connectors return the actions and sources that depend on the
|
||||||
|
%% connector
|
||||||
|
t_connector_dependencies(matrix) ->
|
||||||
|
[
|
||||||
|
[single, actions],
|
||||||
|
[single, sources]
|
||||||
|
];
|
||||||
|
t_connector_dependencies(Config) when is_list(Config) ->
|
||||||
|
?check_trace(
|
||||||
|
begin
|
||||||
|
%% This particular source type happens to serve both actions and sources, a
|
||||||
|
%% nice edge case for this test.
|
||||||
|
ActionType = ?SOURCE_TYPE,
|
||||||
|
ConnectorType = ?SOURCE_CONNECTOR_TYPE,
|
||||||
|
ConnectorName = <<"c">>,
|
||||||
|
{ok, {{_, 201, _}, _, _}} =
|
||||||
|
emqx_bridge_v2_testlib:create_connector_api([
|
||||||
|
{connector_config, source_connector_create_config(#{})},
|
||||||
|
{connector_name, ConnectorName},
|
||||||
|
{connector_type, ConnectorType}
|
||||||
|
]),
|
||||||
|
?assertMatch(
|
||||||
|
{200, [
|
||||||
|
#{
|
||||||
|
<<"actions">> := [],
|
||||||
|
<<"sources">> := []
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
list_connectors_api()
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{200, #{
|
||||||
|
<<"actions">> := [],
|
||||||
|
<<"sources">> := []
|
||||||
|
}},
|
||||||
|
get_connector_api(ConnectorType, ConnectorName)
|
||||||
|
),
|
||||||
|
|
||||||
|
SourceName1 = <<"s1">>,
|
||||||
|
{201, _} = create_source_api(
|
||||||
|
SourceName1,
|
||||||
|
?SOURCE_TYPE,
|
||||||
|
source_create_config(#{
|
||||||
|
<<"connector">> => ConnectorName
|
||||||
|
})
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{200, [
|
||||||
|
#{
|
||||||
|
<<"actions">> := [],
|
||||||
|
<<"sources">> := [SourceName1]
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
list_connectors_api()
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{200, #{
|
||||||
|
<<"actions">> := [],
|
||||||
|
<<"sources">> := [SourceName1]
|
||||||
|
}},
|
||||||
|
get_connector_api(ConnectorType, ConnectorName)
|
||||||
|
),
|
||||||
|
|
||||||
|
ActionName1 = <<"a1">>,
|
||||||
|
{201, _} = create_action_api(
|
||||||
|
ActionName1,
|
||||||
|
ActionType,
|
||||||
|
mqtt_action_create_config(#{
|
||||||
|
<<"connector">> => ConnectorName
|
||||||
|
})
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{200, [
|
||||||
|
#{
|
||||||
|
<<"actions">> := [ActionName1],
|
||||||
|
<<"sources">> := [SourceName1]
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
list_connectors_api()
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{200, #{
|
||||||
|
<<"actions">> := [ActionName1],
|
||||||
|
<<"sources">> := [SourceName1]
|
||||||
|
}},
|
||||||
|
get_connector_api(ConnectorType, ConnectorName)
|
||||||
|
),
|
||||||
|
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
[]
|
||||||
|
),
|
||||||
|
ok.
|
||||||
|
|
|
@ -655,7 +655,22 @@ format_resource_data(error, undefined, Result) ->
|
||||||
format_resource_data(error, Error, Result) ->
|
format_resource_data(error, Error, Result) ->
|
||||||
Result#{status_reason => emqx_utils:readable_error_msg(Error)};
|
Result#{status_reason => emqx_utils:readable_error_msg(Error)};
|
||||||
format_resource_data(channels, Channels, Result) ->
|
format_resource_data(channels, Channels, Result) ->
|
||||||
Result#{actions => lists:map(fun format_action/1, maps:keys(Channels))};
|
#{
|
||||||
|
actions := Actions,
|
||||||
|
sources := Sources
|
||||||
|
} = lists:foldl(
|
||||||
|
fun(Id, Acc) ->
|
||||||
|
case emqx_bridge_v2:parse_id(Id) of
|
||||||
|
#{kind := source, name := Name} ->
|
||||||
|
maps:update_with(sources, fun(Ss) -> [Name | Ss] end, Acc);
|
||||||
|
#{name := Name} ->
|
||||||
|
maps:update_with(actions, fun(As) -> [Name | As] end, Acc)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
#{actions => [], sources => []},
|
||||||
|
maps:keys(Channels)
|
||||||
|
),
|
||||||
|
Result#{actions => lists:sort(Actions), sources => lists:sort(Sources)};
|
||||||
format_resource_data(K, V, Result) ->
|
format_resource_data(K, V, Result) ->
|
||||||
Result#{K => V}.
|
Result#{K => V}.
|
||||||
|
|
||||||
|
@ -673,12 +688,6 @@ unpack_connector_conf(Type, PackedConf) ->
|
||||||
#{<<"foo">> := RawConf} = maps:get(TypeBin, Bridges),
|
#{<<"foo">> := RawConf} = maps:get(TypeBin, Bridges),
|
||||||
RawConf.
|
RawConf.
|
||||||
|
|
||||||
format_action(ActionId) ->
|
|
||||||
case emqx_bridge_v2:parse_id(ActionId) of
|
|
||||||
#{name := Name} ->
|
|
||||||
Name
|
|
||||||
end.
|
|
||||||
|
|
||||||
is_ok(ok) ->
|
is_ok(ok) ->
|
||||||
ok;
|
ok;
|
||||||
is_ok(OkResult = {ok, _}) ->
|
is_ok(OkResult = {ok, _}) ->
|
||||||
|
|
|
@ -109,9 +109,10 @@
|
||||||
emqx_conf,
|
emqx_conf,
|
||||||
emqx,
|
emqx,
|
||||||
emqx_auth,
|
emqx_auth,
|
||||||
emqx_management,
|
emqx_connector,
|
||||||
{emqx_connector, "connectors {}"},
|
emqx_bridge,
|
||||||
{emqx_bridge, "actions {}"}
|
emqx_rule_engine,
|
||||||
|
emqx_management
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(APPSPEC_DASHBOARD,
|
-define(APPSPEC_DASHBOARD,
|
||||||
|
|
Loading…
Reference in New Issue