فهرست منبع

Merge pull request #11907 from zmstone/1108-add-type-aliases

1108 add type aliases
Zaiming (Stone) Shi 2 سال پیش
والد
کامیت
64b4db1104
60فایلهای تغییر یافته به همراه297 افزوده شده و 187 حذف شده
  1. 1 1
      apps/emqx/rebar.config
  2. 17 7
      apps/emqx/src/emqx_limiter/src/emqx_limiter_schema.erl
  3. 1 1
      apps/emqx/src/emqx_schema.erl
  4. 5 1
      apps/emqx_auth/src/emqx_authn/emqx_authn_schema.erl
  5. 2 2
      apps/emqx_auth/src/emqx_authz/emqx_authz_schema.erl
  6. 0 1
      apps/emqx_auth/test/emqx_authn/emqx_authn_chains_SUITE.erl
  7. 2 2
      apps/emqx_auth/test/emqx_authn/emqx_authn_schema_SUITE.erl
  8. 19 11
      apps/emqx_auth/test/emqx_authn/emqx_authn_schema_tests.erl
  9. 9 6
      apps/emqx_auth_http/src/emqx_authn_http_schema.erl
  10. 7 4
      apps/emqx_auth_http/src/emqx_authz_http_schema.erl
  11. 6 3
      apps/emqx_auth_jwt/src/emqx_authn_jwt_schema.erl
  12. 7 4
      apps/emqx_auth_ldap/src/emqx_authn_ldap_bind_schema.erl
  13. 6 3
      apps/emqx_auth_ldap/src/emqx_authn_ldap_schema.erl
  14. 4 1
      apps/emqx_auth_ldap/src/emqx_authz_ldap_schema.erl
  15. 4 1
      apps/emqx_auth_mnesia/src/emqx_authn_mnesia_schema.erl
  16. 3 0
      apps/emqx_auth_mnesia/src/emqx_authn_scram_mnesia_schema.erl
  17. 4 1
      apps/emqx_auth_mnesia/src/emqx_authz_mnesia_schema.erl
  18. 6 3
      apps/emqx_auth_mongodb/src/emqx_authn_mongodb_schema.erl
  19. 7 4
      apps/emqx_auth_mongodb/src/emqx_authz_mongodb_schema.erl
  20. 6 3
      apps/emqx_auth_mysql/src/emqx_authn_mysql_schema.erl
  21. 3 0
      apps/emqx_auth_mysql/src/emqx_authz_mysql_schema.erl
  22. 3 0
      apps/emqx_auth_postgresql/src/emqx_authn_postgresql_schema.erl
  23. 3 0
      apps/emqx_auth_postgresql/src/emqx_authz_postgresql_schema.erl
  24. 1 1
      apps/emqx_auth_postgresql/test/emqx_authn_postgresql_SUITE.erl
  25. 3 0
      apps/emqx_auth_redis/src/emqx_authn_redis_schema.erl
  26. 3 0
      apps/emqx_auth_redis/src/emqx_authz_redis_schema.erl
  27. 1 1
      apps/emqx_auth_redis/test/emqx_authn_redis_SUITE.erl
  28. 1 1
      apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub.erl
  29. 1 1
      apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.app.src
  30. 1 1
      apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.erl
  31. 1 9
      apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl
  32. 1 1
      apps/emqx_bridge_influxdb/src/emqx_bridge_influxdb.app.src
  33. 6 2
      apps/emqx_bridge_influxdb/src/emqx_bridge_influxdb.erl
  34. 1 1
      apps/emqx_bridge_pulsar/test/emqx_bridge_pulsar_tests.erl
  35. 1 1
      apps/emqx_bridge_rabbitmq/src/emqx_bridge_rabbitmq.app.src
  36. 3 1
      apps/emqx_bridge_rabbitmq/src/emqx_bridge_rabbitmq_connector.erl
  37. 1 1
      apps/emqx_conf/src/emqx_conf.erl
  38. 12 16
      apps/emqx_conf/src/emqx_conf_schema.erl
  39. 20 10
      apps/emqx_dashboard/src/emqx_dashboard_swagger.erl
  40. 64 61
      apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl
  41. 1 1
      apps/emqx_dashboard_sso/src/emqx_dashboard_sso.app.src
  42. 4 0
      apps/emqx_dashboard_sso/src/emqx_dashboard_sso_ldap.erl
  43. 3 1
      apps/emqx_dashboard_sso/src/emqx_dashboard_sso_schema.erl
  44. 1 1
      apps/emqx_enterprise/src/emqx_enterprise_schema.erl
  45. 6 3
      apps/emqx_gcp_device/src/emqx_gcp_device_authn_schema.erl
  46. 4 1
      apps/emqx_ldap/src/emqx_ldap.erl
  47. 3 1
      apps/emqx_license/src/emqx_license_schema.erl
  48. 1 1
      apps/emqx_management/src/emqx_mgmt_api_listeners.erl
  49. 1 1
      apps/emqx_mongodb/src/emqx_mongodb.app.src
  50. 6 1
      apps/emqx_mongodb/src/emqx_mongodb.erl
  51. 1 1
      apps/emqx_prometheus/src/emqx_prometheus_schema.erl
  52. 1 1
      apps/emqx_retainer/src/emqx_retainer_schema.erl
  53. 3 1
      apps/emqx_rule_engine/src/emqx_rule_api_schema.erl
  54. 1 1
      apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl
  55. 1 1
      apps/emqx_s3/src/emqx_s3_schema.erl
  56. 1 1
      apps/emqx_telemetry/src/emqx_telemetry.app.src
  57. 4 0
      apps/emqx_telemetry/src/emqx_telemetry_schema.erl
  58. 1 1
      mix.exs
  59. 1 1
      rebar.config
  60. 7 1
      scripts/apps-version-check.sh

+ 1 - 1
apps/emqx/rebar.config

@@ -30,7 +30,7 @@
     {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.7"}}},
     {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.15.16"}}},
     {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "3.2.1"}}},
-    {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.39.19"}}},
+    {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.40.0"}}},
     {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.5.3"}}},
     {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}},
     {recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}},

+ 17 - 7
apps/emqx/src/emqx_limiter/src/emqx_limiter_schema.erl

@@ -33,7 +33,8 @@
     desc/1,
     types/0,
     short_paths/0,
-    short_paths_fields/0
+    short_paths_fields/0,
+    rate_type/0
 ]).
 
 -define(KILOBYTE, 1024).
@@ -129,9 +130,9 @@ fields(limiter) ->
         ];
 fields(node_opts) ->
     [
-        {rate, ?HOCON(rate(), #{desc => deprecated_desc(rate), default => <<"infinity">>})},
+        {rate, ?HOCON(rate_type(), #{desc => deprecated_desc(rate), default => <<"infinity">>})},
         {burst,
-            ?HOCON(burst_rate(), #{
+            ?HOCON(burst_rate_type(), #{
                 desc => deprecated_desc(burst),
                 default => <<"0">>
             })}
@@ -142,7 +143,7 @@ fields(bucket_opts) ->
     fields_of_bucket(<<"infinity">>);
 fields(client_opts) ->
     [
-        {rate, ?HOCON(rate(), #{default => <<"infinity">>, desc => deprecated_desc(rate)})},
+        {rate, ?HOCON(rate_type(), #{default => <<"infinity">>, desc => deprecated_desc(rate)})},
         {initial,
             ?HOCON(initial(), #{
                 default => <<"0">>,
@@ -164,7 +165,7 @@ fields(client_opts) ->
                 }
             )},
         {burst,
-            ?HOCON(burst(), #{
+            ?HOCON(burst_type(), #{
                 desc => deprecated_desc(burst),
                 default => <<"0">>,
                 importance => ?IMPORTANCE_HIDDEN,
@@ -211,7 +212,7 @@ short_paths_fields() ->
 short_paths_fields(Importance) ->
     [
         {Name,
-            ?HOCON(rate(), #{
+            ?HOCON(rate_type(), #{
                 desc => ?DESC(Name),
                 required => false,
                 importance => Importance,
@@ -415,7 +416,7 @@ composite_bucket_fields(Types, ClientRef) ->
 
 fields_of_bucket(Default) ->
     [
-        {rate, ?HOCON(rate(), #{desc => deprecated_desc(rate), default => Default})},
+        {rate, ?HOCON(rate_type(), #{desc => deprecated_desc(rate), default => Default})},
         {burst,
             ?HOCON(burst(), #{
                 desc => deprecated_desc(burst),
@@ -461,3 +462,12 @@ alias_of_type(_) ->
 
 deprecated_desc(_Field) ->
     <<"Deprecated since v5.0.25">>.
+
+rate_type() ->
+    typerefl:alias("string", rate()).
+
+burst_type() ->
+    typerefl:alias("string", burst()).
+
+burst_rate_type() ->
+    typerefl:alias("string", burst_rate()).

+ 1 - 1
apps/emqx/src/emqx_schema.erl

@@ -3316,7 +3316,7 @@ get_tombstone_map_value_type(Schema) ->
     %% hoconsc:map_value_type(Schema)
     ?MAP(_Name, Union) = hocon_schema:field_schema(Schema, type),
     %% TODO: violation of abstraction, fix hoconsc:union_members/1
-    ?UNION(Members) = Union,
+    ?UNION(Members, _) = Union,
     Tombstone = tombstone(),
     [Type, Tombstone] = hoconsc:union_members(Members),
     Type.

+ 5 - 1
apps/emqx_auth/src/emqx_authn/emqx_authn_schema.erl

@@ -38,7 +38,8 @@
     authenticator_type_without/1,
     authenticator_type_without/2,
     mechanism/1,
-    backend/1
+    backend/1,
+    namespace/0
 ]).
 
 -export([
@@ -60,6 +61,7 @@
     api_write
     %% config: schema for config validation
     | config.
+-callback namespace() -> string().
 -callback refs() -> [schema_ref()].
 -callback refs(shema_kind()) -> [schema_ref()].
 -callback select_union_member(emqx_config:raw_config()) -> [schema_ref()] | undefined | no_return().
@@ -74,6 +76,8 @@
     refs/1
 ]).
 
+namespace() -> "authn".
+
 roots() -> [].
 
 injected_fields(AuthnSchemaMods) ->

+ 2 - 2
apps/emqx_auth/src/emqx_authz/emqx_authz_schema.erl

@@ -136,7 +136,7 @@ authz_fields() ->
     [
         {sources,
             ?HOCON(
-                ?ARRAY(?UNION(UnionMemberSelector)),
+                ?ARRAY(hoconsc:union(UnionMemberSelector)),
                 #{
                     default => [default_authz()],
                     desc => ?DESC(sources),
@@ -153,7 +153,7 @@ api_authz_fields() ->
     [{sources, ?HOCON(?ARRAY(api_source_type()), #{desc => ?DESC(sources)})}].
 
 api_source_type() ->
-    ?UNION(api_authz_refs()).
+    hoconsc:union(api_authz_refs()).
 
 api_authz_refs() ->
     lists:concat([api_source_refs(Mod) || Mod <- source_schema_mods()]).

+ 0 - 1
apps/emqx_auth/test/emqx_authn/emqx_authn_chains_SUITE.erl

@@ -16,7 +16,6 @@
 
 -module(emqx_authn_chains_SUITE).
 
--behaviour(hocon_schema).
 -behaviour(emqx_authn_provider).
 
 -compile(export_all).

+ 2 - 2
apps/emqx_auth/test/emqx_authn/emqx_authn_schema_SUITE.erl

@@ -54,7 +54,7 @@ t_check_schema(_Config) ->
     ?assertThrow(
         #{
             path := "authentication.1.password_hash_algorithm.name",
-            matched_type := "builtin_db/authn-hash:simple",
+            matched_type := "authn:builtin_db/authn-hash:simple",
             reason := unable_to_convert_to_enum_symbol
         },
         Check(ConfigNotOk)
@@ -73,7 +73,7 @@ t_check_schema(_Config) ->
         #{
             path := "authentication.1.password_hash_algorithm",
             reason := "algorithm_name_missing",
-            matched_type := "builtin_db"
+            matched_type := "authn:builtin_db"
         },
         Check(ConfigMissingAlgoName)
     ).

+ 19 - 11
apps/emqx_auth/test/emqx_authn/emqx_authn_schema_tests.erl

@@ -22,6 +22,7 @@
 -define(ERR(Reason), {error, Reason}).
 
 union_member_selector_mongo_test_() ->
+    ok = ensure_schema_load(),
     [
         {"unknown", fun() ->
             ?assertMatch(
@@ -31,25 +32,26 @@ union_member_selector_mongo_test_() ->
         end},
         {"single", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "mongo_single"}),
+                ?ERR(#{matched_type := "authn:mongo_single"}),
                 check("{mechanism = password_based, backend = mongodb, mongo_type = single}")
             )
         end},
         {"replica-set", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "mongo_rs"}),
+                ?ERR(#{matched_type := "authn:mongo_rs"}),
                 check("{mechanism = password_based, backend = mongodb, mongo_type = rs}")
             )
         end},
         {"sharded", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "mongo_sharded"}),
+                ?ERR(#{matched_type := "authn:mongo_sharded"}),
                 check("{mechanism = password_based, backend = mongodb, mongo_type = sharded}")
             )
         end}
     ].
 
 union_member_selector_jwt_test_() ->
+    ok = ensure_schema_load(),
     [
         {"unknown", fun() ->
             ?assertMatch(
@@ -59,25 +61,26 @@ union_member_selector_jwt_test_() ->
         end},
         {"jwks", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "jwt_jwks"}),
+                ?ERR(#{matched_type := "authn:jwt_jwks"}),
                 check("{mechanism = jwt, use_jwks = true}")
             )
         end},
         {"publick-key", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "jwt_public_key"}),
+                ?ERR(#{matched_type := "authn:jwt_public_key"}),
                 check("{mechanism = jwt, use_jwks = false, public_key = 1}")
             )
         end},
         {"hmac-based", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "jwt_hmac"}),
+                ?ERR(#{matched_type := "authn:jwt_hmac"}),
                 check("{mechanism = jwt, use_jwks = false}")
             )
         end}
     ].
 
 union_member_selector_redis_test_() ->
+    ok = ensure_schema_load(),
     [
         {"unknown", fun() ->
             ?assertMatch(
@@ -87,25 +90,26 @@ union_member_selector_redis_test_() ->
         end},
         {"single", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "redis_single"}),
+                ?ERR(#{matched_type := "authn:redis_single"}),
                 check("{mechanism = password_based, backend = redis, redis_type = single}")
             )
         end},
         {"cluster", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "redis_cluster"}),
+                ?ERR(#{matched_type := "authn:redis_cluster"}),
                 check("{mechanism = password_based, backend = redis, redis_type = cluster}")
             )
         end},
         {"sentinel", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "redis_sentinel"}),
+                ?ERR(#{matched_type := "authn:redis_sentinel"}),
                 check("{mechanism = password_based, backend = redis, redis_type = sentinel}")
             )
         end}
     ].
 
 union_member_selector_http_test_() ->
+    ok = ensure_schema_load(),
     [
         {"unknown", fun() ->
             ?assertMatch(
@@ -115,13 +119,13 @@ union_member_selector_http_test_() ->
         end},
         {"get", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "http_get"}),
+                ?ERR(#{matched_type := "authn:http_get"}),
                 check("{mechanism = password_based, backend = http, method = get}")
             )
         end},
         {"post", fun() ->
             ?assertMatch(
-                ?ERR(#{matched_type := "http_post"}),
+                ?ERR(#{matched_type := "authn:http_post"}),
                 check("{mechanism = password_based, backend = http, method = post}")
             )
         end}
@@ -132,3 +136,7 @@ check(HoconConf) ->
         #{roots => emqx_authn_schema:global_auth_fields()},
         ["authentication= ", HoconConf]
     ).
+
+ensure_schema_load() ->
+    _ = emqx_conf_schema:roots(),
+    ok.

+ 9 - 6
apps/emqx_auth_http/src/emqx_authn_http_schema.erl

@@ -16,10 +16,6 @@
 
 -module(emqx_authn_http_schema).
 
--include("emqx_auth_http.hrl").
--include_lib("emqx_auth/include/emqx_authn.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
@@ -27,9 +23,14 @@
     validations/0,
     desc/1,
     refs/0,
-    select_union_member/1
+    select_union_member/1,
+    namespace/0
 ]).
 
+-include("emqx_auth_http.hrl").
+-include_lib("emqx_auth/include/emqx_authn.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
 -define(NOT_EMPTY(MSG), emqx_resource_validator:not_empty(MSG)).
 -define(THROW_VALIDATION_ERROR(ERROR, MESSAGE),
     throw(#{
@@ -38,6 +39,8 @@
     })
 ).
 
+namespace() -> "authn".
+
 refs() ->
     [?R_REF(http_get), ?R_REF(http_post)].
 
@@ -97,7 +100,7 @@ common_fields() ->
         {backend, emqx_authn_schema:backend(?AUTHN_BACKEND)},
         {url, fun url/1},
         {body,
-            hoconsc:mk(map([{fuzzy, term(), binary()}]), #{
+            hoconsc:mk(typerefl:alias("map", map([{fuzzy, term(), binary()}])), #{
                 required => false, desc => ?DESC(body)
             })},
         {request_timeout, fun request_timeout/1}

+ 7 - 4
apps/emqx_auth_http/src/emqx_authz_http_schema.erl

@@ -26,7 +26,8 @@
     fields/1,
     desc/1,
     source_refs/0,
-    select_union_member/1
+    select_union_member/1,
+    namespace/0
 ]).
 
 -export([
@@ -38,6 +39,8 @@
 
 -import(emqx_schema, [mk_duration/2]).
 
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 source_refs() ->
@@ -96,7 +99,7 @@ http_common_fields() ->
             mk_duration("Request timeout", #{
                 required => false, default => <<"30s">>, desc => ?DESC(request_timeout)
             })},
-        {body, ?HOCON(map(), #{required => false, desc => ?DESC(body)})}
+        {body, ?HOCON(hoconsc:map(name, binary()), #{required => false, desc => ?DESC(body)})}
     ] ++
         lists:keydelete(
             pool_type,
@@ -105,7 +108,7 @@ http_common_fields() ->
         ).
 
 headers(type) ->
-    list({binary(), binary()});
+    typerefl:alias("map", list({binary(), binary()}));
 headers(desc) ->
     ?DESC(?FUNCTION_NAME);
 headers(converter) ->
@@ -118,7 +121,7 @@ headers(_) ->
     undefined.
 
 headers_no_content_type(type) ->
-    list({binary(), binary()});
+    typerefl:alias("map", list({binary(), binary()}));
 headers_no_content_type(desc) ->
     ?DESC(?FUNCTION_NAME);
 headers_no_content_type(converter) ->

+ 6 - 3
apps/emqx_auth_jwt/src/emqx_authn_jwt_schema.erl

@@ -16,18 +16,21 @@
 
 -module(emqx_authn_jwt_schema).
 
--include("emqx_auth_jwt.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+-include("emqx_auth_jwt.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authn".
+
 refs() ->
     [
         ?R_REF(jwt_hmac),

+ 7 - 4
apps/emqx_auth_ldap/src/emqx_authn_ldap_bind_schema.erl

@@ -16,18 +16,21 @@
 
 -module(emqx_authn_ldap_bind_schema).
 
--include("emqx_auth_ldap.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
     fields/1,
     desc/1,
     refs/0,
-    select_union_member/1
+    select_union_member/1,
+    namespace/0
 ]).
 
+-include("emqx_auth_ldap.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authn".
+
 refs() ->
     [?R_REF(ldap_bind)].
 

+ 6 - 3
apps/emqx_auth_ldap/src/emqx_authn_ldap_schema.erl

@@ -16,18 +16,21 @@
 
 -module(emqx_authn_ldap_schema).
 
--include("emqx_auth_ldap.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+-include("emqx_auth_ldap.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authn".
+
 refs() ->
     [?R_REF(ldap)].
 

+ 4 - 1
apps/emqx_auth_ldap/src/emqx_authz_ldap_schema.erl

@@ -26,9 +26,12 @@
     fields/1,
     desc/1,
     source_refs/0,
-    select_union_member/1
+    select_union_member/1,
+    namespace/0
 ]).
 
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 fields(ldap) ->

+ 4 - 1
apps/emqx_auth_mnesia/src/emqx_authn_mnesia_schema.erl

@@ -25,9 +25,12 @@
     fields/1,
     desc/1,
     refs/1,
-    select_union_member/2
+    select_union_member/2,
+    namespace/0
 ]).
 
+namespace() -> "authn".
+
 refs(api_write) ->
     [?R_REF(builtin_db_api)];
 refs(_) ->

+ 3 - 0
apps/emqx_auth_mnesia/src/emqx_authn_scram_mnesia_schema.erl

@@ -22,12 +22,15 @@
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+namespace() -> "authn".
+
 refs() ->
     [?R_REF(scram)].
 

+ 4 - 1
apps/emqx_auth_mnesia/src/emqx_authz_mnesia_schema.erl

@@ -26,9 +26,12 @@
     fields/1,
     desc/1,
     source_refs/0,
-    select_union_member/1
+    select_union_member/1,
+    namespace/0
 ]).
 
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 fields(builtin_db) ->

+ 6 - 3
apps/emqx_auth_mongodb/src/emqx_authn_mongodb_schema.erl

@@ -16,18 +16,21 @@
 
 -module(emqx_authn_mongodb_schema).
 
--include("emqx_auth_mongodb.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+-include("emqx_auth_mongodb.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authn".
+
 refs() ->
     [
         ?R_REF(mongo_single),

+ 7 - 4
apps/emqx_auth_mongodb/src/emqx_authz_mongodb_schema.erl

@@ -16,17 +16,20 @@
 
 -module(emqx_authz_mongodb_schema).
 
--include("emqx_auth_mongodb.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -export([
     type/0,
     fields/1,
     desc/1,
     source_refs/0,
-    select_union_member/1
+    select_union_member/1,
+    namespace/0
 ]).
 
+-include("emqx_auth_mongodb.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 source_refs() ->

+ 6 - 3
apps/emqx_auth_mysql/src/emqx_authn_mysql_schema.erl

@@ -16,18 +16,21 @@
 
 -module(emqx_authn_mysql_schema).
 
--include("emqx_auth_mysql.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+-include("emqx_auth_mysql.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authn".
+
 refs() ->
     [?R_REF(mysql)].
 

+ 3 - 0
apps/emqx_auth_mysql/src/emqx_authz_mysql_schema.erl

@@ -22,6 +22,7 @@
 -behaviour(emqx_authz_schema).
 
 -export([
+    namespace/0,
     type/0,
     fields/1,
     desc/1,
@@ -29,6 +30,8 @@
     select_union_member/1
 ]).
 
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 fields(mysql) ->

+ 3 - 0
apps/emqx_auth_postgresql/src/emqx_authn_postgresql_schema.erl

@@ -22,12 +22,15 @@
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+namespace() -> "authn".
+
 select_union_member(
     #{
         <<"mechanism">> := ?AUTHN_MECHANISM_BIN, <<"backend">> := ?AUTHN_BACKEND_BIN

+ 3 - 0
apps/emqx_auth_postgresql/src/emqx_authz_postgresql_schema.erl

@@ -22,6 +22,7 @@
 -behaviour(emqx_authz_schema).
 
 -export([
+    namespace/0,
     type/0,
     fields/1,
     desc/1,
@@ -29,6 +30,8 @@
     select_union_member/1
 ]).
 
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 fields(postgresql) ->

+ 1 - 1
apps/emqx_auth_postgresql/test/emqx_authn_postgresql_SUITE.erl

@@ -104,7 +104,7 @@ t_update_with_invalid_config(_Config) ->
     ?assertMatch(
         {error, #{
             kind := validation_error,
-            matched_type := "postgresql",
+            matched_type := "authn:postgresql",
             path := "authentication.1.server",
             reason := required_field
         }},

+ 3 - 0
apps/emqx_auth_redis/src/emqx_authn_redis_schema.erl

@@ -22,12 +22,15 @@
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+namespace() -> "authn".
+
 refs() ->
     [
         ?R_REF(redis_single),

+ 3 - 0
apps/emqx_auth_redis/src/emqx_authz_redis_schema.erl

@@ -22,6 +22,7 @@
 -behaviour(emqx_authz_schema).
 
 -export([
+    namespace/0,
     type/0,
     fields/1,
     desc/1,
@@ -29,6 +30,8 @@
     select_union_member/1
 ]).
 
+namespace() -> "authz".
+
 type() -> ?AUTHZ_TYPE.
 
 fields(redis_single) ->

+ 1 - 1
apps/emqx_auth_redis/test/emqx_authn_redis_SUITE.erl

@@ -170,7 +170,7 @@ test_create_invalid_config(InvalidAuthConfig, Path) ->
     ?assertMatch(
         {error, #{
             kind := validation_error,
-            matched_type := "redis_single",
+            matched_type := "authn:redis_single",
             path := Path
         }},
         emqx:update_config(?PATH, {create_authenticator, ?GLOBAL, InvalidAuthConfig})

+ 1 - 1
apps/emqx_bridge_gcp_pubsub/src/emqx_bridge_gcp_pubsub.erl

@@ -101,7 +101,7 @@ fields(connector_config) ->
             )},
         {service_account_json,
             sc(
-                service_account_json(),
+                typerefl:alias("map", ?MODULE:service_account_json()),
                 #{
                     required => true,
                     validator => fun ?MODULE:service_account_json_validator/1,

+ 1 - 1
apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.app.src

@@ -1,6 +1,6 @@
 {application, emqx_bridge_greptimedb, [
     {description, "EMQX GreptimeDB Bridge"},
-    {vsn, "0.1.3"},
+    {vsn, "0.1.4"},
     {registered, []},
     {applications, [
         kernel,

+ 1 - 1
apps/emqx_bridge_greptimedb/src/emqx_bridge_greptimedb.erl

@@ -126,7 +126,7 @@ desc(_) ->
     undefined.
 
 write_syntax(type) ->
-    emqx_bridge_influxdb:write_syntax();
+    emqx_bridge_influxdb:write_syntax_type();
 write_syntax(required) ->
     true;
 write_syntax(validator) ->

+ 1 - 9
apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl

@@ -46,14 +46,6 @@
 
 -export([validate_method/1, join_paths/2]).
 
--type connect_timeout() :: emqx_schema:duration() | infinity.
--type pool_type() :: random | hash.
-
--reflect_type([
-    connect_timeout/0,
-    pool_type/0
-]).
-
 -define(DEFAULT_PIPELINE_SIZE, 100).
 -define(DEFAULT_REQUEST_TIMEOUT_MS, 30_000).
 
@@ -89,7 +81,7 @@ fields(config) ->
             )},
         {pool_type,
             sc(
-                pool_type(),
+                hoconsc:enum([random, hash]),
                 #{
                     default => random,
                     desc => ?DESC("pool_type")

+ 1 - 1
apps/emqx_bridge_influxdb/src/emqx_bridge_influxdb.app.src

@@ -1,6 +1,6 @@
 {application, emqx_bridge_influxdb, [
     {description, "EMQX Enterprise InfluxDB Bridge"},
-    {vsn, "0.1.5"},
+    {vsn, "0.1.6"},
     {registered, []},
     {applications, [
         kernel,

+ 6 - 2
apps/emqx_bridge_influxdb/src/emqx_bridge_influxdb.erl

@@ -11,7 +11,8 @@
 -import(hoconsc, [mk/2, enum/1, ref/2]).
 
 -export([
-    conn_bridge_examples/1
+    conn_bridge_examples/1,
+    write_syntax_type/0
 ]).
 
 -export([
@@ -29,6 +30,9 @@
 %% -------------------------------------------------------------------------------------------------
 %% api
 
+write_syntax_type() ->
+    typerefl:alias("string", write_syntax()).
+
 conn_bridge_examples(Method) ->
     [
         #{
@@ -154,7 +158,7 @@ desc(_) ->
     undefined.
 
 write_syntax(type) ->
-    ?MODULE:write_syntax();
+    write_syntax_type();
 write_syntax(required) ->
     true;
 write_syntax(validator) ->

+ 1 - 1
apps/emqx_bridge_pulsar/test/emqx_bridge_pulsar_tests.erl

@@ -11,7 +11,7 @@
 %%===========================================================================
 
 pulsar_producer_validations_test() ->
-    Name = my_producer,
+    Name = list_to_atom("my_producer"),
     Conf0 = pulsar_producer_hocon(),
     Conf1 =
         Conf0 ++

+ 1 - 1
apps/emqx_bridge_rabbitmq/src/emqx_bridge_rabbitmq.app.src

@@ -1,6 +1,6 @@
 {application, emqx_bridge_rabbitmq, [
     {description, "EMQX Enterprise RabbitMQ Bridge"},
-    {vsn, "0.1.5"},
+    {vsn, "0.1.6"},
     {registered, []},
     {applications, [
         kernel,

+ 3 - 1
apps/emqx_bridge_rabbitmq/src/emqx_bridge_rabbitmq_connector.erl

@@ -20,7 +20,7 @@
 -behaviour(ecpool_worker).
 
 %% hocon_schema callbacks
--export([roots/0, fields/1]).
+-export([namespace/0, roots/0, fields/1]).
 
 %% HTTP API callbacks
 -export([values/1]).
@@ -43,6 +43,8 @@
 %% Internal callbacks
 -export([publish_messages/3]).
 
+namespace() -> "rabbitmq".
+
 roots() ->
     [{config, #{type => hoconsc:ref(?MODULE, config)}}].
 

+ 1 - 1
apps/emqx_conf/src/emqx_conf.erl

@@ -292,7 +292,7 @@ hocon_schema_to_spec(?MAP(Name, Type), LocalModule) ->
         },
         SubRefs
     };
-hocon_schema_to_spec(?UNION(Types), LocalModule) ->
+hocon_schema_to_spec(?UNION(Types, _DisplayName), LocalModule) ->
     {OneOf, Refs} = lists:foldl(
         fun(Type, {Acc, RefsAcc}) ->
             {Schema, SubRefs} = hocon_schema_to_spec(Type, LocalModule),

+ 12 - 16
apps/emqx_conf/src/emqx_conf_schema.erl

@@ -28,21 +28,14 @@
 
 -include("emqx_conf.hrl").
 
--type log_level() :: debug | info | notice | warning | error | critical | alert | emergency | all.
--type file() :: string().
--type cipher() :: map().
-
 -behaviour(hocon_schema).
 
--reflect_type([
-    log_level/0,
-    file/0,
-    cipher/0
-]).
-
 -export([
     namespace/0, roots/0, fields/1, translations/0, translation/1, validations/0, desc/1, tags/0
 ]).
+
+-export([log_level/0]).
+
 -export([conf_get/2, conf_get/3, keys/2, filter/1]).
 -export([upgrade_raw_conf/1]).
 
@@ -548,7 +541,7 @@ fields("node") ->
             )},
         {"crash_dump_file",
             sc(
-                file(),
+                string(),
                 #{
                     mapping => "vm_args.-env ERL_CRASH_DUMP",
                     desc => ?DESC(node_crash_dump_file),
@@ -839,7 +832,7 @@ fields("rpc") ->
             )},
         {"certfile",
             sc(
-                file(),
+                string(),
                 #{
                     mapping => "gen_rpc.certfile",
                     converter => fun ensure_unicode_path/2,
@@ -848,7 +841,7 @@ fields("rpc") ->
             )},
         {"keyfile",
             sc(
-                file(),
+                string(),
                 #{
                     mapping => "gen_rpc.keyfile",
                     converter => fun ensure_unicode_path/2,
@@ -857,7 +850,7 @@ fields("rpc") ->
             )},
         {"cacertfile",
             sc(
-                file(),
+                string(),
                 #{
                     mapping => "gen_rpc.cacertfile",
                     converter => fun ensure_unicode_path/2,
@@ -985,7 +978,7 @@ fields("log") ->
             })},
         {"file",
             sc(
-                ?UNION([
+                hoconsc:union([
                     ?R_REF("log_file_handler"),
                     ?MAP(handler_name, ?R_REF("log_file_handler"))
                 ]),
@@ -1004,7 +997,7 @@ fields("log_file_handler") ->
     [
         {"path",
             sc(
-                file(),
+                string(),
                 #{
                     desc => ?DESC("log_file_handler_file"),
                     default => <<"${EMQX_LOG_DIR}/emqx.log">>,
@@ -1538,3 +1531,6 @@ ensure_unicode_path(Path, _) when is_list(Path) ->
     Path;
 ensure_unicode_path(Path, _) ->
     throw({"not_string", Path}).
+
+log_level() ->
+    hoconsc:enum([debug, info, notice, warning, error, critical, alert, emergency, all]).

+ 20 - 10
apps/emqx_dashboard/src/emqx_dashboard_swagger.erl

@@ -345,15 +345,7 @@ parse_spec_ref(Module, Path, Options) ->
             erlang:apply(Module, schema, [Path])
         catch
             Error:Reason:Stacktrace ->
-                %% This error is intended to fail the build
-                %% hence print to standard_error
-                io:format(
-                    standard_error,
-                    "Failed to generate swagger for path ~p in module ~p~n"
-                    "error:~p~nreason:~p~n~p~n",
-                    [Module, Path, Error, Reason, Stacktrace]
-                ),
-                error({failed_to_generate_swagger_spec, Module, Path})
+                failed_to_generate_swagger_spec(Module, Path, Error, Reason, Stacktrace)
         end,
     OperationId = maps:get('operationId', Schema),
     {Specs, Refs} = maps:fold(
@@ -369,6 +361,24 @@ parse_spec_ref(Module, Path, Options) ->
     RouteOpts = generate_route_opts(Schema, Options),
     {OperationId, Specs, Refs, RouteOpts}.
 
+-ifdef(TEST).
+-spec failed_to_generate_swagger_spec(_, _, _, _, _) -> no_return().
+failed_to_generate_swagger_spec(Module, Path, _Error, _Reason, _Stacktrace) ->
+    error({failed_to_generate_swagger_spec, Module, Path}).
+-else.
+-spec failed_to_generate_swagger_spec(_, _, _, _, _) -> no_return().
+failed_to_generate_swagger_spec(Module, Path, Error, Reason, Stacktrace) ->
+    %% This error is intended to fail the build
+    %% hence print to standard_error
+    io:format(
+        standard_error,
+        "Failed to generate swagger for path ~p in module ~p~n"
+        "error:~p~nreason:~p~n~p~n",
+        [Module, Path, Error, Reason, Stacktrace]
+    ),
+    error({failed_to_generate_swagger_spec, Module, Path}).
+
+-endif.
 generate_route_opts(Schema, Options) ->
     #{filter => compose_filters(filter(Options), custom_filter(Schema))}.
 
@@ -776,7 +786,7 @@ hocon_schema_to_spec(?MAP(Name, Type), LocalModule) ->
         },
         SubRefs
     };
-hocon_schema_to_spec(?UNION(Types), LocalModule) ->
+hocon_schema_to_spec(?UNION(Types, _DisplayName), LocalModule) ->
     {OneOf, Refs} = lists:foldl(
         fun(Type, {Acc, RefsAcc}) ->
             {Schema, SubRefs} = hocon_schema_to_spec(Type, LocalModule),

+ 64 - 61
apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl

@@ -317,68 +317,72 @@ t_sub_fields(_Config) ->
     validate(Path, Object, ExpectRefs),
     ok.
 
-t_complicated_type(_Config) ->
+t_complex_type(_Config) ->
     Path = "/ref/complex_type",
-    Object = #{
-        <<"content">> => #{
-            <<"application/json">> =>
-                #{
-                    <<"schema">> => #{
-                        <<"properties">> =>
-                            [
-                                {<<"no_neg_integer">>, #{minimum => 0, type => integer}},
-                                {<<"url">>, #{example => <<"http://127.0.0.1">>, type => string}},
-                                {<<"server">>, #{example => <<"127.0.0.1:80">>, type => string}},
-                                {<<"connect_timeout">>, #{
-                                    example => infinity,
-                                    <<"oneOf">> => [
-                                        #{example => infinity, type => string},
-                                        #{type => integer}
-                                    ]
-                                }},
-                                {<<"pool_type">>, #{enum => [random, hash], type => string}},
-                                {<<"timeout">>, #{
-                                    example => infinity,
-                                    <<"oneOf">> => [
-                                        #{example => infinity, type => string}, #{type => integer}
-                                    ]
-                                }},
-                                {<<"bytesize">>, #{example => <<"32MB">>, type => string}},
-                                {<<"wordsize">>, #{example => <<"1024KB">>, type => string}},
-                                {<<"maps">>, #{example => #{}, type => object}},
-                                {<<"comma_separated_list">>, #{
-                                    example => <<"item1,item2">>, type => string
-                                }},
-                                {<<"comma_separated_atoms">>, #{
-                                    example => <<"item1,item2">>, type => string
-                                }},
-                                {<<"log_level">>, #{
-                                    enum => [
-                                        debug,
-                                        info,
-                                        notice,
-                                        warning,
-                                        error,
-                                        critical,
-                                        alert,
-                                        emergency,
-                                        all
-                                    ],
-                                    type => string
-                                }},
-                                {<<"fix_integer">>, #{
-                                    default => 100, enum => [100], type => integer
-                                }}
-                            ],
-                        <<"type">> => object
-                    }
-                }
-        }
-    },
     {OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
     ?assertEqual(test, OperationId),
     Response = maps:get(responses, maps:get(post, Spec)),
-    ?assertEqual(Object, maps:get(<<"200">>, Response)),
+    ResponseBody = maps:get(<<"200">>, Response),
+    Content = maps:get(<<"content">>, ResponseBody),
+    JsonContent = maps:get(<<"application/json">>, Content),
+    Schema = maps:get(<<"schema">>, JsonContent),
+    ?assertMatch(#{<<"type">> := object}, Schema),
+    Properties = maps:get(<<"properties">>, Schema),
+    ?assertMatch(
+        [
+            {<<"no_neg_integer">>, #{minimum := 0, type := integer}},
+            {<<"url">>, #{
+                example := <<"http://127.0.0.1">>, type := string
+            }},
+            {<<"server">>, #{
+                example := <<"127.0.0.1:80">>, type := string
+            }},
+            {<<"connect_timeout">>, #{
+                example := _, type := string
+            }},
+            {<<"pool_type">>, #{
+                enum := [random, hash], type := string
+            }},
+            {<<"timeout">>, #{
+                example := infinity,
+                <<"oneOf">> := [
+                    #{example := infinity, type := string},
+                    #{type := integer}
+                ]
+            }},
+            {<<"bytesize">>, #{
+                example := <<"32MB">>, type := string
+            }},
+            {<<"wordsize">>, #{
+                example := <<"1024KB">>, type := string
+            }},
+            {<<"maps">>, #{example := #{}, type := object}},
+            {<<"comma_separated_list">>, #{
+                example := <<"item1,item2">>, type := string
+            }},
+            {<<"comma_separated_atoms">>, #{
+                example := <<"item1,item2">>, type := string
+            }},
+            {<<"log_level">>, #{
+                enum := [
+                    debug,
+                    info,
+                    notice,
+                    warning,
+                    error,
+                    critical,
+                    alert,
+                    emergency,
+                    all
+                ],
+                type := string
+            }},
+            {<<"fix_integer">>, #{
+                default := 100, enum := [100], type := integer
+            }}
+        ],
+        Properties
+    ),
     ?assertEqual([], Refs),
     ok.
 
@@ -647,9 +651,8 @@ schema("/ref/complex_type") ->
                     {no_neg_integer, hoconsc:mk(non_neg_integer(), #{})},
                     {url, hoconsc:mk(url(), #{})},
                     {server, hoconsc:mk(emqx_schema:ip_port(), #{})},
-                    {connect_timeout,
-                        hoconsc:mk(emqx_bridge_http_connector:connect_timeout(), #{})},
-                    {pool_type, hoconsc:mk(emqx_bridge_http_connector:pool_type(), #{})},
+                    {connect_timeout, hoconsc:mk(emqx_schema:timeout_duration(), #{})},
+                    {pool_type, hoconsc:mk(hoconsc:enum([random, hash]), #{})},
                     {timeout, hoconsc:mk(timeout(), #{})},
                     {bytesize, hoconsc:mk(emqx_schema:bytesize(), #{})},
                     {wordsize, hoconsc:mk(emqx_schema:wordsize(), #{})},

+ 1 - 1
apps/emqx_dashboard_sso/src/emqx_dashboard_sso.app.src

@@ -1,6 +1,6 @@
 {application, emqx_dashboard_sso, [
     {description, "EMQX Dashboard Single Sign-On"},
-    {vsn, "0.1.1"},
+    {vsn, "0.1.2"},
     {registered, [emqx_dashboard_sso_sup]},
     {applications, [
         kernel,

+ 4 - 0
apps/emqx_dashboard_sso/src/emqx_dashboard_sso_ldap.erl

@@ -12,6 +12,7 @@
 -behaviour(emqx_dashboard_sso).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1
 ]).
@@ -30,6 +31,9 @@
 %% Hocon Schema
 %%------------------------------------------------------------------------------
 
+namespace() ->
+    "sso".
+
 hocon_ref() ->
     hoconsc:ref(?MODULE, ldap).
 

+ 3 - 1
apps/emqx_dashboard_sso/src/emqx_dashboard_sso_schema.erl

@@ -8,7 +8,7 @@
 -include_lib("typerefl/include/types.hrl").
 
 %% Hocon
--export([fields/1, desc/1]).
+-export([namespace/0, fields/1, desc/1]).
 
 -export([
     common_backend_schema/1,
@@ -21,6 +21,8 @@
 %%------------------------------------------------------------------------------
 %% Hocon Schema
 %%------------------------------------------------------------------------------
+namespace() -> "sso".
+
 fields(sso) ->
     lists:map(
         fun({Type, Module}) ->

+ 1 - 1
apps/emqx_enterprise/src/emqx_enterprise_schema.erl

@@ -53,7 +53,7 @@ fields("log_audit_handler") ->
 
         {"path",
             hoconsc:mk(
-                emqx_conf_schema:file(),
+                string(),
                 #{
                     desc => ?DESC(emqx_conf_schema, "audit_file_handler_path"),
                     default => <<"${EMQX_LOG_DIR}/audit.log">>,

+ 6 - 3
apps/emqx_gcp_device/src/emqx_gcp_device_authn_schema.erl

@@ -16,18 +16,21 @@
 
 -module(emqx_gcp_device_authn_schema).
 
--include("emqx_gcp_device.hrl").
--include_lib("hocon/include/hoconsc.hrl").
-
 -behaviour(emqx_authn_schema).
 
 -export([
+    namespace/0,
     fields/1,
     desc/1,
     refs/0,
     select_union_member/1
 ]).
 
+-include("emqx_gcp_device.hrl").
+-include_lib("hocon/include/hoconsc.hrl").
+
+namespace() -> "authn".
+
 refs() -> [?R_REF(gcp_device)].
 
 select_union_member(#{<<"mechanism">> := ?AUTHN_MECHANISM_BIN}) ->

+ 4 - 1
apps/emqx_ldap/src/emqx_ldap.erl

@@ -37,7 +37,7 @@
 %% ecpool connect & reconnect
 -export([connect/1]).
 
--export([roots/0, fields/1, desc/1]).
+-export([namespace/0, roots/0, fields/1, desc/1]).
 
 -export([do_get_status/1]).
 
@@ -57,6 +57,9 @@
 
 %%=====================================================================
 %% Hocon schema
+
+namespace() -> "ldap".
+
 roots() ->
     [{config, #{type => hoconsc:ref(?MODULE, config)}}].
 

+ 3 - 1
apps/emqx_license/src/emqx_license_schema.erl

@@ -13,12 +13,14 @@
 
 -behaviour(hocon_schema).
 
--export([roots/0, fields/1, validations/0, desc/1, tags/0]).
+-export([namespace/0, roots/0, fields/1, validations/0, desc/1, tags/0]).
 
 -export([
     default_license/0
 ]).
 
+namespace() -> "license".
+
 roots() ->
     [
         {license,

+ 1 - 1
apps/emqx_management/src/emqx_mgmt_api_listeners.erl

@@ -313,7 +313,7 @@ create_listener_schema(Opts) ->
     ],
     Example = maps:remove(id, tcp_schema_example()),
     emqx_dashboard_swagger:schema_with_example(
-        ?UNION(Schemas),
+        hoconsc:union(Schemas),
         Example#{name => <<"demo">>}
     ).
 

+ 1 - 1
apps/emqx_mongodb/src/emqx_mongodb.app.src

@@ -1,6 +1,6 @@
 {application, emqx_mongodb, [
     {description, "EMQX MongoDB Connector"},
-    {vsn, "0.1.2"},
+    {vsn, "0.1.3"},
     {registered, []},
     {applications, [
         kernel,

+ 6 - 1
apps/emqx_mongodb/src/emqx_mongodb.erl

@@ -22,6 +22,7 @@
 -include_lib("snabbkaffe/include/snabbkaffe.hrl").
 
 -behaviour(emqx_resource).
+-behaviour(hocon_schema).
 
 %% callbacks of behaviour emqx_resource
 -export([
@@ -29,7 +30,8 @@
     on_start/2,
     on_stop/2,
     on_query/3,
-    on_get_status/2
+    on_get_status/2,
+    namespace/0
 ]).
 
 %% ecpool callback
@@ -50,6 +52,9 @@
 }).
 
 %%=====================================================================
+
+namespace() -> "mongo".
+
 roots() ->
     [
         {config, #{

+ 1 - 1
apps/emqx_prometheus/src/emqx_prometheus_schema.erl

@@ -57,7 +57,7 @@ fields("prometheus") ->
             )},
         {headers,
             ?HOCON(
-                list({string(), string()}),
+                typerefl:alias("map", list({string(), string()})),
                 #{
                     default => #{},
                     required => false,

+ 1 - 1
apps/emqx_retainer/src/emqx_retainer_schema.erl

@@ -77,7 +77,7 @@ fields("retainer") ->
             )},
         {delivery_rate,
             ?HOCON(
-                emqx_limiter_schema:rate(),
+                emqx_limiter_schema:rate_type(),
                 #{
                     required => false,
                     desc => ?DESC(delivery_rate),

+ 3 - 1
apps/emqx_rule_engine/src/emqx_rule_api_schema.erl

@@ -24,7 +24,7 @@
 
 -export([check_params/2]).
 
--export([roots/0, fields/1]).
+-export([namespace/0, roots/0, fields/1]).
 
 -type tag() :: rule_creation | rule_test | rule_engine.
 
@@ -46,6 +46,8 @@ check_params(Params, Tag) ->
 %%======================================================================================
 %% Hocon Schema Definitions
 
+namespace() -> "rule_engine".
+
 roots() ->
     [
         {"rule_engine", sc(ref("rule_engine"), #{desc => ?DESC("root_rule_engine")})},

+ 1 - 1
apps/emqx_rule_engine/src/emqx_rule_engine_schema.erl

@@ -262,7 +262,7 @@ actions() ->
     end.
 
 qos() ->
-    ?UNION([emqx_schema:qos(), binary()]).
+    hoconsc:union([emqx_schema:qos(), binary()]).
 
 rule_engine_settings() ->
     [

+ 1 - 1
apps/emqx_s3/src/emqx_s3_schema.erl

@@ -37,7 +37,7 @@ fields(s3) ->
             )},
         {secret_access_key,
             mk(
-                secret_access_key(),
+                typerefl:alias("string", secret_access_key()),
                 #{
                     desc => ?DESC("secret_access_key"),
                     required => false,

+ 1 - 1
apps/emqx_telemetry/src/emqx_telemetry.app.src

@@ -1,6 +1,6 @@
 {application, emqx_telemetry, [
     {description, "Report telemetry data for EMQX Opensource edition"},
-    {vsn, "0.1.2"},
+    {vsn, "0.1.3"},
     {registered, [emqx_telemetry_sup, emqx_telemetry]},
     {mod, {emqx_telemetry_app, []}},
     {applications, [

+ 4 - 0
apps/emqx_telemetry/src/emqx_telemetry_schema.erl

@@ -22,11 +22,15 @@
 -behaviour(hocon_schema).
 
 -export([
+    namespace/0,
     roots/0,
     fields/1,
     desc/1
 ]).
 
+%% 'emqxtel' to distinguish open-telemetry
+namespace() -> "emqxtel".
+
 roots() -> ["telemetry"].
 
 fields("telemetry") ->

+ 1 - 1
mix.exs

@@ -72,7 +72,7 @@ defmodule EMQXUmbrella.MixProject do
       # in conflict by emqtt and hocon
       {:getopt, "1.0.2", override: true},
       {:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "1.0.8", override: true},
-      {:hocon, github: "emqx/hocon", tag: "0.39.19", override: true},
+      {:hocon, github: "emqx/hocon", tag: "0.40.0", override: true},
       {:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.5.3", override: true},
       {:esasl, github: "emqx/esasl", tag: "0.2.0"},
       {:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"},

+ 1 - 1
rebar.config

@@ -75,7 +75,7 @@
     , {system_monitor, {git, "https://github.com/ieQu1/system_monitor", {tag, "3.0.3"}}}
     , {getopt, "1.0.2"}
     , {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "1.0.8"}}}
-    , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.39.19"}}}
+    , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.40.0"}}}
     , {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.5.3"}}}
     , {esasl, {git, "https://github.com/emqx/esasl", {tag, "0.2.0"}}}
     , {jose, {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.2"}}}

+ 7 - 1
scripts/apps-version-check.sh

@@ -4,6 +4,12 @@ set -euo pipefail
 # ensure dir
 cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.."
 
+log_red() {
+  local RED='\033[0;31m' # Red
+  local NC='\033[0m' # No Color
+  echo -e "${RED}${1}${NC}"
+}
+
 # match any official release tag 'e*' and 'v*'
 latest_release="$(env PREV_TAG_MATCH_PATTERN='*' ./scripts/find-prev-rel-tag.sh)"
 echo "Version check compare base: $latest_release"
@@ -47,7 +53,7 @@ for app in ${APPS}; do
                              -- "$app_path/priv" \
                              -- "$app_path/c_src" | wc -l ) "
         if [ "$changed_lines" -gt 0 ]; then
-            echo "ERROR: $src_file needs a vsn bump"
+            log_red "ERROR: $src_file needs a vsn bump"
             bad_app_count=$(( bad_app_count + 1))
         fi
     else