feat(actions_api): add `/action_types` API

This commit is contained in:
Thales Macedo Garitezi 2023-11-09 13:54:57 -03:00
parent a828eea613
commit eabd09051a
4 changed files with 78 additions and 5 deletions

View File

@ -40,7 +40,8 @@
'/actions/:id/enable/:enable'/2, '/actions/:id/enable/:enable'/2,
'/actions/:id/:operation'/2, '/actions/:id/:operation'/2,
'/nodes/:node/actions/:id/:operation'/2, '/nodes/:node/actions/:id/:operation'/2,
'/actions_probe'/2 '/actions_probe'/2,
'/action_types'/2
]). ]).
%% BpAPI %% BpAPI
@ -79,7 +80,8 @@ paths() ->
"/actions/:id/enable/:enable", "/actions/:id/enable/:enable",
"/actions/:id/:operation", "/actions/:id/:operation",
"/nodes/:node/actions/:id/:operation", "/nodes/:node/actions/:id/:operation",
"/actions_probe" "/actions_probe",
"/action_types"
]. ].
error_schema(Code, Message) when is_atom(Code) -> error_schema(Code, Message) when is_atom(Code) ->
@ -338,6 +340,27 @@ schema("/actions_probe") ->
400 => error_schema(['TEST_FAILED'], "bridge test failed") 400 => error_schema(['TEST_FAILED'], "bridge test failed")
} }
} }
};
schema("/action_types") ->
#{
'operationId' => '/action_types',
get => #{
tags => [<<"actions">>],
desc => ?DESC("desc_api10"),
summary => <<"List available action types">>,
responses => #{
200 => emqx_dashboard_swagger:schema_with_examples(
array(emqx_bridge_v2_schema:types_sc()),
#{
<<"types">> =>
#{
summary => <<"Action types">>,
value => emqx_bridge_v2_schema:types()
}
}
)
}
}
}. }.
'/actions'(post, #{body := #{<<"type">> := BridgeType, <<"name">> := BridgeName} = Conf0}) -> '/actions'(post, #{body := #{<<"type">> := BridgeType, <<"name">> := BridgeName} = Conf0}) ->
@ -486,6 +509,9 @@ schema("/actions_probe") ->
redact(BadRequest) redact(BadRequest)
end. end.
'/action_types'(get, _Request) ->
?OK(emqx_bridge_v2_schema:types()).
maybe_deobfuscate_bridge_probe(#{<<"type">> := BridgeType, <<"name">> := BridgeName} = Params) -> maybe_deobfuscate_bridge_probe(#{<<"type">> := BridgeType, <<"name">> := BridgeName} = Params) ->
case emqx_bridge:lookup(BridgeType, BridgeName) of case emqx_bridge:lookup(BridgeType, BridgeName) of
{ok, #{raw_config := RawConf}} -> {ok, #{raw_config := RawConf}} ->

View File

@ -30,9 +30,18 @@
post_request/0 post_request/0
]). ]).
-export([types/0, types_sc/0]).
-export([enterprise_api_schemas/1]). -export([enterprise_api_schemas/1]).
-export_type([action_type/0]).
%% Should we explicitly list them here so dialyzer may be more helpful?
-type action_type() :: atom().
-if(?EMQX_RELEASE_EDITION == ee). -if(?EMQX_RELEASE_EDITION == ee).
-spec enterprise_api_schemas(Method) -> [{_Type :: binary(), ?R_REF(module(), Method)}] when
Method :: string().
enterprise_api_schemas(Method) -> enterprise_api_schemas(Method) ->
%% We *must* do this to ensure the module is really loaded, especially when we use %% We *must* do this to ensure the module is really loaded, especially when we use
%% `call_hocon' from `nodetool' to generate initial configurations. %% `call_hocon' from `nodetool' to generate initial configurations.
@ -55,6 +64,8 @@ enterprise_fields_actions() ->
-else. -else.
-spec enterprise_api_schemas(Method) -> [{_Type :: binary(), ?R_REF(module(), Method)}] when
Method :: string().
enterprise_api_schemas(_Method) -> []. enterprise_api_schemas(_Method) -> [].
enterprise_fields_actions() -> []. enterprise_fields_actions() -> [].
@ -129,6 +140,14 @@ desc(actions) ->
desc(_) -> desc(_) ->
undefined. undefined.
-spec types() -> [action_type()].
types() ->
proplists:get_keys(?MODULE:fields(actions)).
-spec types_sc() -> ?ENUM([action_type()]).
types_sc() ->
hoconsc:enum(types()).
-ifdef(TEST). -ifdef(TEST).
-include_lib("hocon/include/hocon_types.hrl"). -include_lib("hocon/include/hocon_types.hrl").
schema_homogeneous_test() -> schema_homogeneous_test() ->

View File

@ -236,6 +236,14 @@ end_per_group(_, Config) ->
emqx_cth_suite:stop(?config(group_apps, Config)), emqx_cth_suite:stop(?config(group_apps, Config)),
ok. ok.
init_per_testcase(t_action_types, Config) ->
case ?config(cluster_nodes, Config) of
undefined ->
init_mocks();
Nodes ->
[erpc:call(Node, ?MODULE, init_mocks, []) || Node <- Nodes]
end,
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 ->
@ -260,8 +268,14 @@ end_per_testcase(_TestCase, Config) ->
-define(CONNECTOR_IMPL, emqx_bridge_v2_dummy_connector). -define(CONNECTOR_IMPL, emqx_bridge_v2_dummy_connector).
init_mocks() -> init_mocks() ->
case emqx_release:edition() of
ee ->
meck:new(emqx_connector_ee_schema, [passthrough, no_link]), meck:new(emqx_connector_ee_schema, [passthrough, no_link]),
meck:expect(emqx_connector_ee_schema, resource_type, 1, ?CONNECTOR_IMPL), meck:expect(emqx_connector_ee_schema, resource_type, 1, ?CONNECTOR_IMPL),
ok;
ce ->
ok
end,
meck:new(?CONNECTOR_IMPL, [non_strict, no_link]), meck:new(?CONNECTOR_IMPL, [non_strict, no_link]),
meck:expect(?CONNECTOR_IMPL, callback_mode, 0, async_if_possible), meck:expect(?CONNECTOR_IMPL, callback_mode, 0, async_if_possible),
meck:expect( meck:expect(
@ -289,7 +303,7 @@ init_mocks() ->
ok = meck:expect(?CONNECTOR_IMPL, on_get_channels, fun(ResId) -> ok = meck:expect(?CONNECTOR_IMPL, on_get_channels, fun(ResId) ->
emqx_bridge_v2:get_channels_for_connector(ResId) emqx_bridge_v2:get_channels_for_connector(ResId)
end), end),
[?CONNECTOR_IMPL, emqx_connector_ee_schema]. ok.
clear_resources() -> clear_resources() ->
lists:foreach( lists:foreach(
@ -886,6 +900,14 @@ t_cascade_delete_actions(Config) ->
), ),
{ok, 200, []} = request_json(get, uri([?ROOT]), Config). {ok, 200, []} = request_json(get, uri([?ROOT]), Config).
t_action_types(Config) ->
Res = request_json(get, uri(["action_types"]), Config),
?assertMatch({ok, 200, _}, Res),
{ok, 200, Types} = Res,
?assert(is_list(Types), #{types => Types}),
?assert(lists:all(fun is_binary/1, Types), #{types => Types}),
ok.
%%% helpers %%% helpers
listen_on_random_port() -> listen_on_random_port() ->
SockOpts = [binary, {active, false}, {packet, raw}, {reuseaddr, true}, {backlog, 1000}], SockOpts = [binary, {active, false}, {packet, raw}, {reuseaddr, true}, {backlog, 1000}],

View File

@ -54,6 +54,12 @@ desc_api9.desc:
desc_api9.label: desc_api9.label:
"""Test Bridge Creation""" """Test Bridge Creation"""
desc_api10.desc:
"""Lists the available action types."""
desc_api10.label:
"""List action types"""
desc_bridge_metrics.desc: desc_bridge_metrics.desc:
"""Get bridge metrics by id.""" """Get bridge metrics by id."""