Merge pull request #12118 from thalesmg/fix-missing-type-name-api-actions-r54-20231206

fix(actions_api): add missing fields to API spec and returned data
This commit is contained in:
Thales Macedo Garitezi 2023-12-07 09:34:29 -03:00 committed by GitHub
commit c274450c5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 21 deletions

View File

@ -799,11 +799,12 @@ format_resource(
name := Name, name := Name,
status := Status, status := Status,
error := Error, error := Error,
raw_config := RawConf, raw_config := RawConf0,
resource_data := _ResourceData resource_data := _ResourceData
}, },
Node Node
) -> ) ->
RawConf = fill_defaults(Type, RawConf0),
redact( redact(
maps:merge( maps:merge(
RawConf#{ RawConf#{
@ -934,6 +935,20 @@ aggregate_metrics(
M17 + N17 M17 + N17
). ).
fill_defaults(Type, RawConf) ->
PackedConf = pack_bridge_conf(Type, RawConf),
FullConf = emqx_config:fill_defaults(emqx_bridge_v2_schema, PackedConf, #{}),
unpack_bridge_conf(Type, FullConf).
pack_bridge_conf(Type, RawConf) ->
#{<<"actions">> => #{bin(Type) => #{<<"foo">> => RawConf}}}.
unpack_bridge_conf(Type, PackedConf) ->
TypeBin = bin(Type),
#{<<"actions">> := Bridges} = PackedConf,
#{<<"foo">> := RawConf} = maps:get(TypeBin, Bridges),
RawConf.
format_bridge_status_and_error(Data) -> format_bridge_status_and_error(Data) ->
maps:fold(fun format_resource_data/3, #{}, maps:with([status, error], Data)). maps:fold(fun format_resource_data/3, #{}, maps:with([status, error], Data)).

View File

@ -304,7 +304,7 @@ t_bridges_lifecycle(Config) ->
<<"status">> := <<"connected">>, <<"status">> := <<"connected">>,
<<"node_status">> := [_ | _], <<"node_status">> := [_ | _],
<<"connector">> := ?CONNECTOR_NAME, <<"connector">> := ?CONNECTOR_NAME,
<<"kafka">> := #{}, <<"parameters">> := #{},
<<"local_topic">> := _, <<"local_topic">> := _,
<<"resource_opts">> := _ <<"resource_opts">> := _
}}, }},
@ -1138,6 +1138,19 @@ t_cluster_later_join_metrics(Config) ->
), ),
ok. ok.
t_raw_config_response_defaults(Config) ->
Params = maps:remove(<<"enable">>, ?KAFKA_BRIDGE(?BRIDGE_NAME)),
?assertMatch(
{ok, 201, #{<<"enable">> := true}},
request_json(
post,
uri([?ROOT]),
Params,
Config
)
),
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

@ -25,8 +25,8 @@
non_deprecated_fields(Fields) -> non_deprecated_fields(Fields) ->
[K || {K, Schema} <- Fields, not hocon_schema:is_deprecated(Schema)]. [K || {K, Schema} <- Fields, not hocon_schema:is_deprecated(Schema)].
find_resource_opts_fields(SchemaMod, FieldName) -> find_resource_opts_fields(SchemaMod, StructName) ->
Fields = hocon_schema:fields(SchemaMod, FieldName), Fields = hocon_schema:fields(SchemaMod, StructName),
case lists:keyfind(resource_opts, 1, Fields) of case lists:keyfind(resource_opts, 1, Fields) of
false -> false ->
undefined; undefined;
@ -35,8 +35,8 @@ find_resource_opts_fields(SchemaMod, FieldName) ->
end. end.
get_resource_opts_subfields(Sc) -> get_resource_opts_subfields(Sc) ->
?R_REF(SchemaModRO, FieldNameRO) = hocon_schema:field_schema(Sc, type), ?R_REF(SchemaModRO, StructNameRO) = hocon_schema:field_schema(Sc, type),
ROFields = non_deprecated_fields(hocon_schema:fields(SchemaModRO, FieldNameRO)), ROFields = non_deprecated_fields(hocon_schema:fields(SchemaModRO, StructNameRO)),
proplists:get_keys(ROFields). proplists:get_keys(ROFields).
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
@ -107,3 +107,33 @@ connector_resource_opts_test() ->
} }
), ),
ok. ok.
actions_api_spec_post_fields_test() ->
?UNION(Union) = emqx_bridge_v2_schema:post_request(),
Schemas =
lists:map(
fun(?R_REF(SchemaMod, StructName)) ->
{SchemaMod, hocon_schema:fields(SchemaMod, StructName)}
end,
hoconsc:union_members(Union)
),
MinimalFields0 =
[
binary_to_atom(F)
|| F <- emqx_bridge_v2_schema:top_level_common_action_keys(),
F =/= <<"local_topic">>
],
MinimalFields = [type, name | MinimalFields0],
MissingFields =
lists:filtermap(
fun({SchemaMod, FieldSchemas}) ->
Missing = MinimalFields -- proplists:get_keys(FieldSchemas),
case Missing of
[] -> false;
_ -> {true, {SchemaMod, Missing}}
end
end,
Schemas
),
?assertEqual(#{}, maps:from_list(MissingFields)),
ok.

View File

@ -23,6 +23,7 @@
]). ]).
-define(CONNECTOR_TYPE, matrix). -define(CONNECTOR_TYPE, matrix).
-define(ACTION_TYPE, matrix).
%% ------------------------------------------------------------------------------------------------- %% -------------------------------------------------------------------------------------------------
%% api %% api
@ -44,7 +45,7 @@ namespace() -> "bridge_matrix".
roots() -> []. roots() -> [].
fields("post") -> fields("post") ->
emqx_bridge_pgsql:fields("post", matrix); emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, "config");
fields("config_connector") -> fields("config_connector") ->
emqx_bridge_pgsql:fields("config_connector"); emqx_bridge_pgsql:fields("config_connector");
fields(action) -> fields(action) ->
@ -61,7 +62,7 @@ fields("put_bridge_v2") ->
fields("get_bridge_v2") -> fields("get_bridge_v2") ->
emqx_bridge_pgsql:fields(pgsql_action); emqx_bridge_pgsql:fields(pgsql_action);
fields("post_bridge_v2") -> fields("post_bridge_v2") ->
emqx_bridge_pgsql:fields(pgsql_action); emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, pgsql_action);
fields(Field) when fields(Field) when
Field == "get_connector"; Field == "get_connector";
Field == "put_connector"; Field == "put_connector";

View File

@ -13,13 +13,15 @@
-include_lib("snabbkaffe/include/snabbkaffe.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl").
-include_lib("emqx_resource/include/emqx_resource.hrl"). -include_lib("emqx_resource/include/emqx_resource.hrl").
%% `hocon_schema' API
-export([ -export([
namespace/0, namespace/0,
roots/0, roots/0,
fields/1, fields/1,
desc/1, desc/1
fields/2
]). ]).
%% for sharing with other actions
-export([fields/3]).
%% Examples %% Examples
-export([ -export([
@ -33,9 +35,7 @@
values_conn_bridge_examples/2 values_conn_bridge_examples/2
]). ]).
-define(PGSQL_HOST_OPTIONS, #{ -define(ACTION_TYPE, pgsql).
default_port => ?PGSQL_DEFAULT_PORT
}).
%% Hocon Schema Definitions %% Hocon Schema Definitions
namespace() -> "bridge_pgsql". namespace() -> "bridge_pgsql".
@ -81,7 +81,7 @@ fields("put_bridge_v2") ->
fields("get_bridge_v2") -> fields("get_bridge_v2") ->
fields(pgsql_action); fields(pgsql_action);
fields("post_bridge_v2") -> fields("post_bridge_v2") ->
fields(pgsql_action); fields("post", pgsql, pgsql_action);
fields("config") -> fields("config") ->
[ [
{enable, hoconsc:mk(boolean(), #{desc => ?DESC("config_enable"), default => true})}, {enable, hoconsc:mk(boolean(), #{desc => ?DESC("config_enable"), default => true})},
@ -99,14 +99,14 @@ fields("config") ->
(emqx_postgresql:fields(config) -- (emqx_postgresql:fields(config) --
emqx_connector_schema_lib:prepare_statement_fields()); emqx_connector_schema_lib:prepare_statement_fields());
fields("post") -> fields("post") ->
fields("post", pgsql); fields("post", ?ACTION_TYPE, "config");
fields("put") -> fields("put") ->
fields("config"); fields("config");
fields("get") -> fields("get") ->
emqx_bridge_schema:status_fields() ++ fields("post"). emqx_bridge_schema:status_fields() ++ fields("post").
fields("post", Type) -> fields("post", Type, StructName) ->
[type_field(Type), name_field() | fields("config")]. [type_field(Type), name_field() | fields(StructName)].
type_field(Type) -> type_field(Type) ->
{type, hoconsc:mk(hoconsc:enum([Type]), #{required => true, desc => ?DESC("desc_type")})}. {type, hoconsc:mk(hoconsc:enum([Type]), #{required => true, desc => ?DESC("desc_type")})}.

View File

@ -23,6 +23,7 @@
]). ]).
-define(CONNECTOR_TYPE, timescale). -define(CONNECTOR_TYPE, timescale).
-define(ACTION_TYPE, timescale).
%% ------------------------------------------------------------------------------------------------- %% -------------------------------------------------------------------------------------------------
%% api %% api
@ -44,7 +45,7 @@ namespace() -> "bridge_timescale".
roots() -> []. roots() -> [].
fields("post") -> fields("post") ->
emqx_bridge_pgsql:fields("post", timescale); emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, "config");
fields("config_connector") -> fields("config_connector") ->
emqx_postgresql_connector_schema:fields("config_connector"); emqx_postgresql_connector_schema:fields("config_connector");
fields(action) -> fields(action) ->
@ -61,7 +62,7 @@ fields("put_bridge_v2") ->
fields("get_bridge_v2") -> fields("get_bridge_v2") ->
emqx_bridge_pgsql:fields(pgsql_action); emqx_bridge_pgsql:fields(pgsql_action);
fields("post_bridge_v2") -> fields("post_bridge_v2") ->
emqx_bridge_pgsql:fields(pgsql_action); emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, pgsql_action);
fields(Field) when fields(Field) when
Field == "get_connector"; Field == "get_connector";
Field == "put_connector"; Field == "put_connector";

View File

@ -766,7 +766,7 @@ t_actions_field(Config) ->
<<"status">> := <<"connected">>, <<"status">> := <<"connected">>,
<<"node_status">> := [_ | _], <<"node_status">> := [_ | _],
<<"connector">> := Name, <<"connector">> := Name,
<<"kafka">> := #{}, <<"parameters">> := #{},
<<"local_topic">> := _, <<"local_topic">> := _,
<<"resource_opts">> := _ <<"resource_opts">> := _
}}, }},
@ -821,7 +821,7 @@ t_fail_delete_with_action(Config) ->
<<"status">> := <<"connected">>, <<"status">> := <<"connected">>,
<<"node_status">> := [_ | _], <<"node_status">> := [_ | _],
<<"connector">> := Name, <<"connector">> := Name,
<<"kafka">> := #{}, <<"parameters">> := #{},
<<"local_topic">> := _, <<"local_topic">> := _,
<<"resource_opts">> := _ <<"resource_opts">> := _
}}, }},