feat: add `/rule_engine` API endpoint

This commit is contained in:
Stefan Strigler 2023-04-05 14:40:18 +02:00
parent a39312e892
commit aea870f319
6 changed files with 125 additions and 21 deletions

View File

@ -48,12 +48,15 @@ check_params(Params, Tag) ->
roots() ->
[
{"rule_engine", sc(ref("rule_engine"), #{desc => ?DESC("root_rule_engine")})},
{"rule_creation", sc(ref("rule_creation"), #{desc => ?DESC("root_rule_creation")})},
{"rule_info", sc(ref("rule_info"), #{desc => ?DESC("root_rule_info")})},
{"rule_events", sc(ref("rule_events"), #{desc => ?DESC("root_rule_events")})},
{"rule_test", sc(ref("rule_test"), #{desc => ?DESC("root_rule_test")})}
].
fields("rule_engine") ->
emqx_rule_engine_schema:fields("rule_engine");
fields("rule_creation") ->
emqx_rule_engine_schema:fields("rules");
fields("rule_info") ->

View File

@ -32,6 +32,7 @@
%% API callbacks
-export([
'/rule_engine'/2,
'/rule_events'/2,
'/rule_test'/2,
'/rules'/2,
@ -41,7 +42,7 @@
]).
%% query callback
-export([qs2ms/2, run_fuzzy_match/2, format_rule_resp/1]).
-export([qs2ms/2, run_fuzzy_match/2, format_rule_info_resp/1]).
-define(ERR_BADARGS(REASON), begin
R0 = err_msg(REASON),
@ -134,6 +135,7 @@ api_spec() ->
paths() ->
[
"/rule_engine",
"/rule_events",
"/rule_test",
"/rules",
@ -145,6 +147,9 @@ paths() ->
error_schema(Code, Message) when is_atom(Code) ->
emqx_dashboard_swagger:error_codes([Code], list_to_binary(Message)).
rule_engine_schema() ->
ref(emqx_rule_api_schema, "rule_engine").
rule_creation_schema() ->
ref(emqx_rule_api_schema, "rule_creation").
@ -184,7 +189,7 @@ schema("/rules") ->
responses => #{
200 =>
[
{data, mk(array(rule_info_schema()), #{desc => ?DESC("desc9")})},
{data, mk(array(rule_info_schema()), #{desc => ?DESC("api1_resp")})},
{meta, mk(ref(emqx_dashboard_swagger, meta), #{})}
],
400 => error_schema('BAD_REQUEST', "Invalid Parameters")
@ -289,6 +294,26 @@ schema("/rule_test") ->
200 => <<"Rule Test Pass">>
}
}
};
schema("/rule_engine") ->
#{
'operationId' => '/rule_engine',
get => #{
tags => [<<"rules">>],
description => ?DESC("api9"),
responses => #{
200 => rule_engine_schema()
}
},
put => #{
tags => [<<"rules">>],
description => ?DESC("api10"),
'requestBody' => rule_engine_schema(),
responses => #{
200 => rule_engine_schema(),
400 => error_schema('BAD_REQUEST', "Invalid request")
}
}
}.
param_path_id() ->
@ -309,7 +334,7 @@ param_path_id() ->
QueryString,
?RULE_QS_SCHEMA,
fun ?MODULE:qs2ms/2,
fun ?MODULE:format_rule_resp/1
fun ?MODULE:format_rule_info_resp/1
)
of
{error, page_limit_invalid} ->
@ -331,7 +356,7 @@ param_path_id() ->
case emqx_conf:update(ConfPath, Params, #{override_to => cluster}) of
{ok, #{post_config_update := #{emqx_rule_engine := AllRules}}} ->
[Rule] = get_one_rule(AllRules, Id),
{201, format_rule_resp(Rule)};
{201, format_rule_info_resp(Rule)};
{error, Reason} ->
?SLOG(error, #{
msg => "create_rule_failed",
@ -362,7 +387,7 @@ param_path_id() ->
'/rules/:id'(get, #{bindings := #{id := Id}}) ->
case emqx_rule_engine:get_rule(Id) of
{ok, Rule} ->
{200, format_rule_resp(Rule)};
{200, format_rule_info_resp(Rule)};
not_found ->
{404, #{code => 'NOT_FOUND', message => <<"Rule Id Not Found">>}}
end;
@ -372,7 +397,7 @@ param_path_id() ->
case emqx_conf:update(ConfPath, Params, #{override_to => cluster}) of
{ok, #{post_config_update := #{emqx_rule_engine := AllRules}}} ->
[Rule] = get_one_rule(AllRules, Id),
{200, format_rule_resp(Rule)};
{200, format_rule_info_resp(Rule)};
{error, Reason} ->
?SLOG(error, #{
msg => "update_rule_failed",
@ -419,6 +444,20 @@ param_path_id() ->
{404, #{code => 'NOT_FOUND', message => <<"Rule Id Not Found">>}}
end.
'/rule_engine'(get, _Params) ->
{200, format_rule_engine_resp(emqx_conf:get([rule_engine]))};
'/rule_engine'(put, #{body := Params}) ->
case emqx_conf:update([rule_engine], Params, #{override_to => cluster}) of
{ok, #{config := Config}} ->
{200, format_rule_engine_resp(Config)};
{error, Reason} ->
?SLOG(error, #{
msg => "update_rule_engine_failed",
reason => Reason
}),
{400, #{code => 'BAD_REQUEST', message => ?ERR_BADARGS(Reason)}}
end.
%%------------------------------------------------------------------------------
%% Internal functions
%%------------------------------------------------------------------------------
@ -440,11 +479,11 @@ encode_nested_error(RuleError, Reason) ->
{RuleError, Reason}
end.
format_rule_resp(Rules) when is_list(Rules) ->
[format_rule_resp(R) || R <- Rules];
format_rule_resp({Id, Rule}) ->
format_rule_resp(Rule#{id => Id});
format_rule_resp(#{
format_rule_info_resp(Rules) when is_list(Rules) ->
[format_rule_info_resp(R) || R <- Rules];
format_rule_info_resp({Id, Rule}) ->
format_rule_info_resp(Rule#{id => Id});
format_rule_info_resp(#{
id := Id,
name := Name,
created_at := CreatedAt,
@ -465,6 +504,26 @@ format_rule_resp(#{
description => Descr
}.
format_rule_engine_resp(#{rules := Rules} = Config) ->
Config#{rules => maps:map(fun format_rule_resp/2, Rules)}.
format_rule_resp(_Id, #{
name := Name,
metadata := MetaData = #{created_at := CreatedAt},
actions := Action,
sql := SQL,
enable := Enable,
description := Descr
}) ->
#{
name => Name,
actions => format_action(Action),
sql => SQL,
enable => Enable,
metadata => MetaData#{created_at => format_datetime(CreatedAt, millisecond)},
description => Descr
}.
format_datetime(Timestamp, Unit) ->
list_to_binary(calendar:system_time_to_rfc3339(Timestamp, [{unit, Unit}])).

View File

@ -281,3 +281,16 @@ test_rule_params(Sql, Payload) ->
<<"sql">> => Sql
}
}.
t_rule_engine(_) ->
{200, _} = emqx_rule_engine_api:'/rule_engine'(get, foo),
{200, #{
jq_function_default_timeout := 12000,
jq_implementation_module := jq_port
}} = emqx_rule_engine_api:'/rule_engine'(put, #{
body => #{
<<"jq_function_default_timeout">> => <<"12s">>,
<<"jq_implementation_module">> => <<"jq_port">>
}
}),
{400, _} = emqx_rule_engine_api:'/rule_engine'(put, #{body => #{<<"something">> => <<"weird">>}}).

View File

@ -0,0 +1 @@
Add `/rule_engine` API endpoint to manage configuration of rule engine.

View File

@ -638,6 +638,17 @@ emqx_rule_api_schema {
}
}
root_rule_engine {
desc {
en: "Rule engine configuration schema"
zh: "规则引擎配置模式"
}
label: {
en: "Configuration Schema"
zh: "配置模式"
}
}
root_rule_creation {
desc {
en: "Schema for creating rules"

View File

@ -50,7 +50,16 @@ emqx_rule_engine_api {
zh: "根据规则来源 Topic 过滤, 使用 MQTT Topic 匹配"
}
}
api1_resp {
desc {
en: "List of rules"
zh: "列出所有规则"
}
label: {
en: "List Rules"
zh: "列出所有规则"
}
}
api2 {
desc {
en: "Create a new rule using given Id"
@ -116,7 +125,6 @@ emqx_rule_engine_api {
zh: "删除集群规则"
}
}
api7 {
desc {
en: "Reset a rule metrics"
@ -127,7 +135,6 @@ emqx_rule_engine_api {
zh: "重置规则计数"
}
}
api8 {
desc {
en: "Test a rule"
@ -138,14 +145,24 @@ emqx_rule_engine_api {
zh: "测试规则"
}
}
desc9 {
api9 {
desc {
en: "List of rules"
zh: "列出所有规则"
en: "Get rule engine configuration"
zh: "获取规则引擎配置"
}
label: {
en: "List Rules"
zh: "列出所有规则"
label {
en: "Get configuration"
zh: "获取配置"
}
}
api10 {
desc {
en: "Update rule engine configuration"
zh: "更新规则引擎配置"
}
label {
en: "Update configuration"
zh: "更新配置"
}
}
}
}