diff --git a/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl b/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl index d85830828..9fe2d2e76 100644 --- a/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl +++ b/apps/emqx_bridge/test/emqx_bridge_v2_tests.erl @@ -25,8 +25,8 @@ non_deprecated_fields(Fields) -> [K || {K, Schema} <- Fields, not hocon_schema:is_deprecated(Schema)]. -find_resource_opts_fields(SchemaMod, FieldName) -> - Fields = hocon_schema:fields(SchemaMod, FieldName), +find_resource_opts_fields(SchemaMod, StructName) -> + Fields = hocon_schema:fields(SchemaMod, StructName), case lists:keyfind(resource_opts, 1, Fields) of false -> undefined; @@ -35,8 +35,8 @@ find_resource_opts_fields(SchemaMod, FieldName) -> end. get_resource_opts_subfields(Sc) -> - ?R_REF(SchemaModRO, FieldNameRO) = hocon_schema:field_schema(Sc, type), - ROFields = non_deprecated_fields(hocon_schema:fields(SchemaModRO, FieldNameRO)), + ?R_REF(SchemaModRO, StructNameRO) = hocon_schema:field_schema(Sc, type), + ROFields = non_deprecated_fields(hocon_schema:fields(SchemaModRO, StructNameRO)), proplists:get_keys(ROFields). %%------------------------------------------------------------------------------ @@ -107,3 +107,33 @@ connector_resource_opts_test() -> } ), 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. diff --git a/apps/emqx_bridge_matrix/src/emqx_bridge_matrix.erl b/apps/emqx_bridge_matrix/src/emqx_bridge_matrix.erl index 4f7a1a370..205edef56 100644 --- a/apps/emqx_bridge_matrix/src/emqx_bridge_matrix.erl +++ b/apps/emqx_bridge_matrix/src/emqx_bridge_matrix.erl @@ -23,6 +23,7 @@ ]). -define(CONNECTOR_TYPE, matrix). +-define(ACTION_TYPE, matrix). %% ------------------------------------------------------------------------------------------------- %% api @@ -44,7 +45,7 @@ namespace() -> "bridge_matrix". roots() -> []. fields("post") -> - emqx_bridge_pgsql:fields("post", matrix); + emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, "config"); fields("config_connector") -> emqx_bridge_pgsql:fields("config_connector"); fields(action) -> @@ -61,7 +62,7 @@ fields("put_bridge_v2") -> fields("get_bridge_v2") -> emqx_bridge_pgsql:fields(pgsql_action); fields("post_bridge_v2") -> - emqx_bridge_pgsql:fields(pgsql_action); + emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, pgsql_action); fields(Field) when Field == "get_connector"; Field == "put_connector"; diff --git a/apps/emqx_bridge_pgsql/src/emqx_bridge_pgsql.erl b/apps/emqx_bridge_pgsql/src/emqx_bridge_pgsql.erl index 4c0efe269..50c322941 100644 --- a/apps/emqx_bridge_pgsql/src/emqx_bridge_pgsql.erl +++ b/apps/emqx_bridge_pgsql/src/emqx_bridge_pgsql.erl @@ -13,13 +13,15 @@ -include_lib("snabbkaffe/include/snabbkaffe.hrl"). -include_lib("emqx_resource/include/emqx_resource.hrl"). +%% `hocon_schema' API -export([ namespace/0, roots/0, fields/1, - desc/1, - fields/2 + desc/1 ]). +%% for sharing with other actions +-export([fields/3]). %% Examples -export([ @@ -33,9 +35,7 @@ values_conn_bridge_examples/2 ]). --define(PGSQL_HOST_OPTIONS, #{ - default_port => ?PGSQL_DEFAULT_PORT -}). +-define(ACTION_TYPE, pgsql). %% Hocon Schema Definitions namespace() -> "bridge_pgsql". @@ -81,7 +81,7 @@ fields("put_bridge_v2") -> fields("get_bridge_v2") -> fields(pgsql_action); fields("post_bridge_v2") -> - fields(pgsql_action); + fields("post", pgsql, pgsql_action); fields("config") -> [ {enable, hoconsc:mk(boolean(), #{desc => ?DESC("config_enable"), default => true})}, @@ -99,14 +99,14 @@ fields("config") -> (emqx_postgresql:fields(config) -- emqx_connector_schema_lib:prepare_statement_fields()); fields("post") -> - fields("post", pgsql); + fields("post", ?ACTION_TYPE, "config"); fields("put") -> fields("config"); fields("get") -> emqx_bridge_schema:status_fields() ++ fields("post"). -fields("post", Type) -> - [type_field(Type), name_field() | fields("config")]. +fields("post", Type, StructName) -> + [type_field(Type), name_field() | fields(StructName)]. type_field(Type) -> {type, hoconsc:mk(hoconsc:enum([Type]), #{required => true, desc => ?DESC("desc_type")})}. diff --git a/apps/emqx_bridge_timescale/src/emqx_bridge_timescale.erl b/apps/emqx_bridge_timescale/src/emqx_bridge_timescale.erl index 5d6c5498d..0d1d80879 100644 --- a/apps/emqx_bridge_timescale/src/emqx_bridge_timescale.erl +++ b/apps/emqx_bridge_timescale/src/emqx_bridge_timescale.erl @@ -23,6 +23,7 @@ ]). -define(CONNECTOR_TYPE, timescale). +-define(ACTION_TYPE, timescale). %% ------------------------------------------------------------------------------------------------- %% api @@ -44,7 +45,7 @@ namespace() -> "bridge_timescale". roots() -> []. fields("post") -> - emqx_bridge_pgsql:fields("post", timescale); + emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, "config"); fields("config_connector") -> emqx_postgresql_connector_schema:fields("config_connector"); fields(action) -> @@ -61,7 +62,7 @@ fields("put_bridge_v2") -> fields("get_bridge_v2") -> emqx_bridge_pgsql:fields(pgsql_action); fields("post_bridge_v2") -> - emqx_bridge_pgsql:fields(pgsql_action); + emqx_bridge_pgsql:fields("post", ?ACTION_TYPE, pgsql_action); fields(Field) when Field == "get_connector"; Field == "put_connector";