Merge pull request #8135 from zhongwencool/schema-default-value

fix: add default&example for schema
This commit is contained in:
zhongwencool 2022-06-06 15:15:55 +08:00 committed by GitHub
commit beed3aa24e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 348 additions and 405 deletions

View File

@ -78,7 +78,6 @@
-export_type([limiter_type/0, bucket_path/0]). -export_type([limiter_type/0, bucket_path/0]).
-import(emqx_schema, [sc/2, map/2]).
-define(UNIT_TIME_IN_MS, 1000). -define(UNIT_TIME_IN_MS, 1000).
namespace() -> limiter. namespace() -> limiter.
@ -87,28 +86,29 @@ roots() -> [limiter].
fields(limiter) -> fields(limiter) ->
[ [
{Type, sc(ref(limiter_opts), #{desc => ?DESC(Type), default => #{<<"enable">> => false}})} {Type,
?HOCON(?R_REF(limiter_opts), #{
desc => ?DESC(Type),
default => #{<<"enable">> => false}
})}
|| Type <- types() || Type <- types()
]; ];
fields(limiter_opts) -> fields(limiter_opts) ->
[ [
{enable, sc(boolean(), #{desc => ?DESC(enable), default => true})}, {enable, ?HOCON(boolean(), #{desc => ?DESC(enable), default => true})},
{rate, sc(rate(), #{desc => ?DESC(rate), default => "infinity"})}, {rate, ?HOCON(rate(), #{desc => ?DESC(rate), default => "infinity"})},
{burst, {burst,
sc( ?HOCON(burst_rate(), #{
burst_rate(), desc => ?DESC(burst),
#{ default => 0
desc => ?DESC(burst), })},
default => 0
}
)},
{bucket, {bucket,
sc( ?HOCON(
map("bucket_name", ref(bucket_opts)), ?MAP("bucket_name", ?R_REF(bucket_opts)),
#{ #{
desc => ?DESC(bucket_cfg), desc => ?DESC(bucket_cfg),
default => #{<<"default">> => #{}}, default => #{<<"default">> => #{}},
examples => #{ example => #{
<<"mybucket-name">> => #{ <<"mybucket-name">> => #{
<<"rate">> => <<"infinity">>, <<"rate">> => <<"infinity">>,
<<"capcity">> => <<"infinity">>, <<"capcity">> => <<"infinity">>,
@ -121,12 +121,12 @@ fields(limiter_opts) ->
]; ];
fields(bucket_opts) -> fields(bucket_opts) ->
[ [
{rate, sc(rate(), #{desc => ?DESC(rate), default => "infinity"})}, {rate, ?HOCON(rate(), #{desc => ?DESC(rate), default => "infinity"})},
{capacity, sc(capacity(), #{desc => ?DESC(capacity), default => "infinity"})}, {capacity, ?HOCON(capacity(), #{desc => ?DESC(capacity), default => "infinity"})},
{initial, sc(initial(), #{default => "0", desc => ?DESC(initial)})}, {initial, ?HOCON(initial(), #{default => "0", desc => ?DESC(initial)})},
{per_client, {per_client,
sc( ?HOCON(
ref(client_bucket), ?R_REF(client_bucket),
#{ #{
default => #{}, default => #{},
desc => ?DESC(per_client) desc => ?DESC(per_client)
@ -135,14 +135,14 @@ fields(bucket_opts) ->
]; ];
fields(client_bucket) -> fields(client_bucket) ->
[ [
{rate, sc(rate(), #{default => "infinity", desc => ?DESC(rate)})}, {rate, ?HOCON(rate(), #{default => "infinity", desc => ?DESC(rate)})},
{initial, sc(initial(), #{default => "0", desc => ?DESC(initial)})}, {initial, ?HOCON(initial(), #{default => "0", desc => ?DESC(initial)})},
%% low_watermark add for emqx_channel and emqx_session %% low_watermark add for emqx_channel and emqx_session
%% both modules consume first and then check %% both modules consume first and then check
%% so we need to use this value to prevent excessive consumption %% so we need to use this value to prevent excessive consumption
%% (e.g, consumption from an empty bucket) %% (e.g, consumption from an empty bucket)
{low_watermark, {low_watermark,
sc( ?HOCON(
initial(), initial(),
#{ #{
desc => ?DESC(low_watermark), desc => ?DESC(low_watermark),
@ -150,12 +150,12 @@ fields(client_bucket) ->
} }
)}, )},
{capacity, {capacity,
sc(capacity(), #{ ?HOCON(capacity(), #{
desc => ?DESC(client_bucket_capacity), desc => ?DESC(client_bucket_capacity),
default => "infinity" default => "infinity"
})}, })},
{divisible, {divisible,
sc( ?HOCON(
boolean(), boolean(),
#{ #{
desc => ?DESC(divisible), desc => ?DESC(divisible),
@ -163,7 +163,7 @@ fields(client_bucket) ->
} }
)}, )},
{max_retry_time, {max_retry_time,
sc( ?HOCON(
emqx_schema:duration(), emqx_schema:duration(),
#{ #{
desc => ?DESC(max_retry_time), desc => ?DESC(max_retry_time),
@ -171,7 +171,7 @@ fields(client_bucket) ->
} }
)}, )},
{failure_strategy, {failure_strategy,
sc( ?HOCON(
failure_strategy(), failure_strategy(),
#{ #{
desc => ?DESC(failure_strategy), desc => ?DESC(failure_strategy),
@ -212,7 +212,6 @@ types() ->
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
ref(Field) -> hoconsc:ref(?MODULE, Field).
to_burst_rate(Str) -> to_burst_rate(Str) ->
to_rate(Str, false, true). to_rate(Str, false, true).

View File

@ -36,6 +36,7 @@
-type percent() :: float(). -type percent() :: float().
-type file() :: string(). -type file() :: string().
-type comma_separated_list() :: list(). -type comma_separated_list() :: list().
-type comma_separated_binary() :: [binary()].
-type comma_separated_atoms() :: [atom()]. -type comma_separated_atoms() :: [atom()].
-type bar_separated_list() :: list(). -type bar_separated_list() :: list().
-type ip_port() :: tuple(). -type ip_port() :: tuple().
@ -48,6 +49,7 @@
-typerefl_from_string({wordsize/0, emqx_schema, to_wordsize}). -typerefl_from_string({wordsize/0, emqx_schema, to_wordsize}).
-typerefl_from_string({percent/0, emqx_schema, to_percent}). -typerefl_from_string({percent/0, emqx_schema, to_percent}).
-typerefl_from_string({comma_separated_list/0, emqx_schema, to_comma_separated_list}). -typerefl_from_string({comma_separated_list/0, emqx_schema, to_comma_separated_list}).
-typerefl_from_string({comma_separated_binary/0, emqx_schema, to_comma_separated_binary}).
-typerefl_from_string({bar_separated_list/0, emqx_schema, to_bar_separated_list}). -typerefl_from_string({bar_separated_list/0, emqx_schema, to_bar_separated_list}).
-typerefl_from_string({ip_port/0, emqx_schema, to_ip_port}). -typerefl_from_string({ip_port/0, emqx_schema, to_ip_port}).
-typerefl_from_string({cipher/0, emqx_schema, to_erl_cipher_suite}). -typerefl_from_string({cipher/0, emqx_schema, to_erl_cipher_suite}).
@ -73,6 +75,7 @@
to_wordsize/1, to_wordsize/1,
to_percent/1, to_percent/1,
to_comma_separated_list/1, to_comma_separated_list/1,
to_comma_separated_binary/1,
to_bar_separated_list/1, to_bar_separated_list/1,
to_ip_port/1, to_ip_port/1,
to_erl_cipher_suite/1, to_erl_cipher_suite/1,
@ -90,6 +93,7 @@
percent/0, percent/0,
file/0, file/0,
comma_separated_list/0, comma_separated_list/0,
comma_separated_binary/0,
bar_separated_list/0, bar_separated_list/0,
ip_port/0, ip_port/0,
cipher/0, cipher/0,
@ -315,7 +319,6 @@ fields("authorization") ->
#{ #{
default => allow, default => allow,
required => true, required => true,
%% TODO: make sources a reference link
desc => ?DESC(fields_authorization_no_match) desc => ?DESC(fields_authorization_no_match)
} }
)}, )},
@ -455,7 +458,7 @@ fields("mqtt") ->
sc( sc(
string(), string(),
#{ #{
default => "", default => <<"">>,
desc => ?DESC(mqtt_response_information) desc => ?DESC(mqtt_response_information)
} }
)}, )},
@ -790,7 +793,7 @@ fields("mqtt_tcp_listener") ->
ref("tcp_opts"), ref("tcp_opts"),
#{} #{}
)} )}
] ++ mqtt_listener(); ] ++ mqtt_listener(1883);
fields("mqtt_ssl_listener") -> fields("mqtt_ssl_listener") ->
[ [
{"tcp", {"tcp",
@ -803,7 +806,7 @@ fields("mqtt_ssl_listener") ->
ref("listener_ssl_opts"), ref("listener_ssl_opts"),
#{} #{}
)} )}
] ++ mqtt_listener(); ] ++ mqtt_listener(8883);
fields("mqtt_ws_listener") -> fields("mqtt_ws_listener") ->
[ [
{"tcp", {"tcp",
@ -816,7 +819,7 @@ fields("mqtt_ws_listener") ->
ref("ws_opts"), ref("ws_opts"),
#{} #{}
)} )}
] ++ mqtt_listener(); ] ++ mqtt_listener(8083);
fields("mqtt_wss_listener") -> fields("mqtt_wss_listener") ->
[ [
{"tcp", {"tcp",
@ -834,7 +837,7 @@ fields("mqtt_wss_listener") ->
ref("ws_opts"), ref("ws_opts"),
#{} #{}
)} )}
] ++ mqtt_listener(); ] ++ mqtt_listener(8084);
fields("mqtt_quic_listener") -> fields("mqtt_quic_listener") ->
[ [
{"enabled", {"enabled",
@ -865,7 +868,7 @@ fields("mqtt_quic_listener") ->
desc => ?DESC(fields_mqtt_quic_listener_idle_timeout) desc => ?DESC(fields_mqtt_quic_listener_idle_timeout)
} }
)} )}
] ++ base_listener(); ] ++ base_listener(14567);
fields("ws_opts") -> fields("ws_opts") ->
[ [
{"mqtt_path", {"mqtt_path",
@ -942,9 +945,10 @@ fields("ws_opts") ->
)}, )},
{"check_origins", {"check_origins",
sc( sc(
hoconsc:array(binary()), comma_separated_binary(),
#{ #{
default => [], default => "",
example => <<"http://localhost:18083, http://127.0.0.1:18083">>,
desc => ?DESC(fields_ws_opts_check_origins) desc => ?DESC(fields_ws_opts_check_origins)
} }
)}, )},
@ -1007,19 +1011,25 @@ fields("tcp_opts") ->
{"recbuf", {"recbuf",
sc( sc(
bytesize(), bytesize(),
#{desc => ?DESC(fields_tcp_opts_recbuf)} #{
example => <<"2KB">>,
desc => ?DESC(fields_tcp_opts_recbuf)
}
)}, )},
{"sndbuf", {"sndbuf",
sc( sc(
bytesize(), bytesize(),
#{desc => ?DESC(fields_tcp_opts_sndbuf)} #{
example => <<"4KB">>,
desc => ?DESC(fields_tcp_opts_sndbuf)
}
)}, )},
{"buffer", {"buffer",
sc( sc(
bytesize(), bytesize(),
#{ #{
desc => ?DESC(fields_tcp_opts_buffer), example => <<"4KB">>,
default => "4KB" desc => ?DESC(fields_tcp_opts_buffer)
} }
)}, )},
{"high_watermark", {"high_watermark",
@ -1087,12 +1097,16 @@ fields("deflate_opts") ->
{"strategy", {"strategy",
sc( sc(
hoconsc:enum([default, filtered, huffman_only, rle]), hoconsc:enum([default, filtered, huffman_only, rle]),
#{desc => ?DESC(fields_deflate_opts_strategy)} #{
default => default,
desc => ?DESC(fields_deflate_opts_strategy)
}
)}, )},
{"server_context_takeover", {"server_context_takeover",
sc( sc(
hoconsc:enum([takeover, no_takeover]), hoconsc:enum([takeover, no_takeover]),
#{ #{
default => takeover,
desc => ?DESC(fields_deflate_opts_server_context_takeover) desc => ?DESC(fields_deflate_opts_server_context_takeover)
} }
)}, )},
@ -1100,6 +1114,7 @@ fields("deflate_opts") ->
sc( sc(
hoconsc:enum([takeover, no_takeover]), hoconsc:enum([takeover, no_takeover]),
#{ #{
default => takeover,
desc => ?DESC(fields_deflate_opts_client_context_takeover) desc => ?DESC(fields_deflate_opts_client_context_takeover)
} }
)}, )},
@ -1107,16 +1122,16 @@ fields("deflate_opts") ->
sc( sc(
range(8, 15), range(8, 15),
#{ #{
desc => ?DESC(fields_deflate_opts_server_max_window_bits), default => 15,
default => 15 desc => ?DESC(fields_deflate_opts_server_max_window_bits)
} }
)}, )},
{"client_max_window_bits", {"client_max_window_bits",
sc( sc(
range(8, 15), range(8, 15),
#{ #{
desc => ?DESC(fields_deflate_opts_client_max_window_bits), default => 15,
default => 15 desc => ?DESC(fields_deflate_opts_client_max_window_bits)
} }
)} )}
]; ];
@ -1170,7 +1185,10 @@ fields("broker") ->
{"shared_subscription_group", {"shared_subscription_group",
sc( sc(
map(name, ref("shared_subscription_group")), map(name, ref("shared_subscription_group")),
#{desc => ?DESC(shared_subscription_group_strategy)} #{
example => #{<<"example_group">> => #{<<"strategy">> => <<"random">>}},
desc => ?DESC(shared_subscription_group_strategy)
}
)} )}
]; ];
fields("shared_subscription_group") -> fields("shared_subscription_group") ->
@ -1179,6 +1197,7 @@ fields("shared_subscription_group") ->
sc( sc(
hoconsc:enum([random, round_robin, sticky, local, hash_topic, hash_clientid]), hoconsc:enum([random, round_robin, sticky, local, hash_topic, hash_clientid]),
#{ #{
default => random,
desc => ?DESC(shared_subscription_strategy_enum) desc => ?DESC(shared_subscription_strategy_enum)
} }
)} )}
@ -1309,6 +1328,7 @@ fields("sysmon_vm") ->
sc( sc(
hoconsc:union([disabled, duration()]), hoconsc:union([disabled, duration()]),
#{ #{
default => disabled,
desc => ?DESC(sysmon_vm_long_gc) desc => ?DESC(sysmon_vm_long_gc)
} }
)}, )},
@ -1511,8 +1531,8 @@ fields("trace") ->
})} })}
]. ].
mqtt_listener() -> mqtt_listener(Bind) ->
base_listener() ++ base_listener(Bind) ++
[ [
{"access_rules", {"access_rules",
sc( sc(
@ -1541,14 +1561,15 @@ mqtt_listener() ->
{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME, authentication(listener)} {?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME, authentication(listener)}
]. ].
base_listener() -> base_listener(Bind) ->
[ [
{"bind", {"bind",
sc( sc(
hoconsc:union([ip_port(), integer()]), hoconsc:union([ip_port(), integer()]),
#{ #{
desc => ?DESC(base_listener_bind), default => Bind,
required => true required => true,
desc => ?DESC(base_listener_bind)
} }
)}, )},
{"acceptors", {"acceptors",
@ -1822,6 +1843,7 @@ common_ssl_opts_schema(Defaults) ->
#{ #{
sensitive => true, sensitive => true,
required => false, required => false,
example => <<"">>,
desc => ?DESC(common_ssl_opts_schema_password) desc => ?DESC(common_ssl_opts_schema_password)
} }
)}, )},
@ -1926,6 +1948,7 @@ client_ssl_opts_schema(Defaults) ->
hoconsc:union([disable, string()]), hoconsc:union([disable, string()]),
#{ #{
required => false, required => false,
example => disable,
validator => fun emqx_schema:non_empty_string/1, validator => fun emqx_schema:non_empty_string/1,
desc => ?DESC(client_ssl_opts_schema_server_name_indication) desc => ?DESC(client_ssl_opts_schema_server_name_indication)
} }
@ -2060,6 +2083,9 @@ to_percent(Str) ->
to_comma_separated_list(Str) -> to_comma_separated_list(Str) ->
{ok, string:tokens(Str, ", ")}. {ok, string:tokens(Str, ", ")}.
to_comma_separated_binary(Str) ->
{ok, lists:map(fun erlang:list_to_binary/1, string:tokens(Str, ", "))}.
to_comma_separated_atoms(Str) -> to_comma_separated_atoms(Str) ->
{ok, lists:map(fun to_atom/1, string:tokens(Str, ", "))}. {ok, lists:map(fun to_atom/1, string:tokens(Str, ", "))}.

View File

@ -18,7 +18,6 @@
-elvis([{elvis_style, invalid_dynamic_call, disable}]). -elvis([{elvis_style, invalid_dynamic_call, disable}]).
-include_lib("hocon/include/hoconsc.hrl"). -include_lib("hocon/include/hoconsc.hrl").
-import(hoconsc, [mk/2, ref/2]).
-export([ -export([
common_fields/0, common_fields/0,
@ -45,20 +44,18 @@ authenticator_type() ->
hoconsc:union(config_refs([Module || {_AuthnType, Module} <- emqx_authn:providers()])). hoconsc:union(config_refs([Module || {_AuthnType, Module} <- emqx_authn:providers()])).
authenticator_type_without_scram() -> authenticator_type_without_scram() ->
Providers = lists:filter( Providers = lists:filtermap(
fun fun
({{password_based, _Backend}, _Mod}) -> ({{password_based, _Backend}, Mod}) ->
true; {true, Mod};
({jwt, _Mod}) -> ({jwt, Mod}) ->
true; {true, Mod};
({{scram, _Backend}, _Mod}) -> ({{scram, _Backend}, _Mod}) ->
false false
end, end,
emqx_authn:providers() emqx_authn:providers()
), ),
hoconsc:union( hoconsc:union(config_refs(Providers)).
config_refs([Module || {_AuthnType, Module} <- Providers])
).
config_refs(Modules) -> config_refs(Modules) ->
lists:append([Module:refs() || Module <- Modules]). lists:append([Module:refs() || Module <- Modules]).
@ -70,8 +67,8 @@ root_type() ->
hoconsc:array(authenticator_type()). hoconsc:array(authenticator_type()).
mechanism(Name) -> mechanism(Name) ->
hoconsc:mk( ?HOCON(
hoconsc:enum([Name]), Name,
#{ #{
required => true, required => true,
desc => ?DESC("mechanism") desc => ?DESC("mechanism")
@ -79,81 +76,62 @@ mechanism(Name) ->
). ).
backend(Name) -> backend(Name) ->
hoconsc:mk( ?HOCON(Name, #{
hoconsc:enum([Name]), required => true,
#{ desc => ?DESC("backend")
required => true, }).
desc => ?DESC("backend")
}
).
fields("metrics_status_fields") -> fields("metrics_status_fields") ->
[ [
{"resource_metrics", mk(ref(?MODULE, "resource_metrics"), #{desc => ?DESC("metrics")})}, {"resource_metrics", ?HOCON(?R_REF("resource_metrics"), #{desc => ?DESC("metrics")})},
{"node_resource_metrics", array("node_resource_metrics", "node_metrics"),
mk( {"metrics", ?HOCON(?R_REF("metrics"), #{desc => ?DESC("metrics")})},
hoconsc:array(ref(?MODULE, "node_resource_metrics")), array("node_metrics"),
#{desc => ?DESC("node_metrics")} {"status", ?HOCON(cluster_status(), #{desc => ?DESC("status")})},
)}, array("node_status"),
{"metrics", mk(ref(?MODULE, "metrics"), #{desc => ?DESC("metrics")})}, array("node_error")
{"node_metrics",
mk(
hoconsc:array(ref(?MODULE, "node_metrics")),
#{desc => ?DESC("node_metrics")}
)},
{"status", mk(cluster_status(), #{desc => ?DESC("status")})},
{"node_status",
mk(
hoconsc:array(ref(?MODULE, "node_status")),
#{desc => ?DESC("node_status")}
)},
{"node_error",
mk(
hoconsc:array(ref(?MODULE, "node_error")),
#{desc => ?DESC("node_error")}
)}
]; ];
fields("metrics") -> fields("metrics") ->
[ [
{"nomatch", mk(integer(), #{desc => ?DESC("metrics_nomatch")})}, {"nomatch", ?HOCON(integer(), #{desc => ?DESC("metrics_nomatch")})},
{"total", mk(integer(), #{desc => ?DESC("metrics_total")})}, {"total", ?HOCON(integer(), #{desc => ?DESC("metrics_total")})},
{"success", mk(integer(), #{desc => ?DESC("metrics_success")})}, {"success", ?HOCON(integer(), #{desc => ?DESC("metrics_success")})},
{"failed", mk(integer(), #{desc => ?DESC("metrics_failed")})}, {"failed", ?HOCON(integer(), #{desc => ?DESC("metrics_failed")})},
{"rate", mk(float(), #{desc => ?DESC("metrics_rate")})}, {"rate", ?HOCON(float(), #{desc => ?DESC("metrics_rate")})},
{"rate_max", mk(float(), #{desc => ?DESC("metrics_rate_max")})}, {"rate_max", ?HOCON(float(), #{desc => ?DESC("metrics_rate_max")})},
{"rate_last5m", mk(float(), #{desc => ?DESC("metrics_rate_last5m")})} {"rate_last5m", ?HOCON(float(), #{desc => ?DESC("metrics_rate_last5m")})}
]; ];
fields("resource_metrics") -> fields("resource_metrics") ->
common_field(); common_field();
fields("node_metrics") -> fields("node_metrics") ->
[ [
node_name(), node_name(),
{"metrics", mk(ref(?MODULE, "metrics"), #{desc => ?DESC("metrics")})} {"metrics", ?HOCON(?R_REF("metrics"), #{desc => ?DESC("metrics")})}
]; ];
fields("node_resource_metrics") -> fields("node_resource_metrics") ->
[ [
node_name(), node_name(),
{"metrics", mk(ref(?MODULE, "resource_metrics"), #{desc => ?DESC("metrics")})} {"metrics", ?HOCON(?R_REF("resource_metrics"), #{desc => ?DESC("metrics")})}
]; ];
fields("node_status") -> fields("node_status") ->
[ [
node_name(), node_name(),
{"status", mk(status(), #{desc => ?DESC("node_status")})} {"status", ?HOCON(status(), #{desc => ?DESC("node_status")})}
]; ];
fields("node_error") -> fields("node_error") ->
[ [
node_name(), node_name(),
{"error", mk(string(), #{desc => ?DESC("node_error")})} {"error", ?HOCON(string(), #{desc => ?DESC("node_error")})}
]. ].
common_field() -> common_field() ->
[ [
{"matched", mk(integer(), #{desc => ?DESC("matched")})}, {"matched", ?HOCON(integer(), #{desc => ?DESC("matched")})},
{"success", mk(integer(), #{desc => ?DESC("success")})}, {"success", ?HOCON(integer(), #{desc => ?DESC("success")})},
{"failed", mk(integer(), #{desc => ?DESC("failed")})}, {"failed", ?HOCON(integer(), #{desc => ?DESC("failed")})},
{"rate", mk(float(), #{desc => ?DESC("rate")})}, {"rate", ?HOCON(float(), #{desc => ?DESC("rate")})},
{"rate_max", mk(float(), #{desc => ?DESC("rate_max")})}, {"rate_max", ?HOCON(float(), #{desc => ?DESC("rate_max")})},
{"rate_last5m", mk(float(), #{desc => ?DESC("rate_last5m")})} {"rate_last5m", ?HOCON(float(), #{desc => ?DESC("rate_last5m")})}
]. ].
status() -> status() ->
@ -163,4 +141,10 @@ cluster_status() ->
hoconsc:enum([connected, disconnected, connecting, inconsistent]). hoconsc:enum([connected, disconnected, connecting, inconsistent]).
node_name() -> node_name() ->
{"node", mk(binary(), #{desc => ?DESC("node"), example => "emqx@127.0.0.1"})}. {"node", ?HOCON(binary(), #{desc => ?DESC("node"), example => "emqx@127.0.0.1"})}.
array(Name) ->
array(Name, Name).
array(Name, DescId) ->
{Name, ?HOCON(?R_REF(Name), #{desc => ?DESC(DescId)})}.

View File

@ -62,7 +62,7 @@ roots() ->
fields(get) -> fields(get) ->
[ [
{method, #{type => get, required => true, default => post, desc => ?DESC(method)}}, {method, #{type => get, required => true, default => get, desc => ?DESC(method)}},
{headers, fun headers_no_content_type/1} {headers, fun headers_no_content_type/1}
] ++ common_fields(); ] ++ common_fields();
fields(post) -> fields(post) ->

View File

@ -19,7 +19,6 @@
-include("emqx_authz.hrl"). -include("emqx_authz.hrl").
-include_lib("hocon/include/hoconsc.hrl"). -include_lib("hocon/include/hoconsc.hrl").
-include_lib("emqx_connector/include/emqx_connector.hrl"). -include_lib("emqx_connector/include/emqx_connector.hrl").
-import(hoconsc, [mk/2, ref/2]).
-reflect_type([ -reflect_type([
permission/0, permission/0,
@ -55,43 +54,46 @@ namespace() -> authz.
roots() -> []. roots() -> [].
fields("authorization") -> fields("authorization") ->
Types = [
file,
http_get,
http_post,
mnesia,
mongo_single,
mongo_rs,
mongo_sharded,
mysql,
postgresql,
redis_single,
redis_sentinel,
redis_cluster
],
Unions = [?R_REF(Type) || Type <- Types],
[ [
{sources, #{ {sources,
type => union_array( ?HOCON(
[ ?ARRAY(?UNION(Unions)),
hoconsc:ref(?MODULE, file), #{
hoconsc:ref(?MODULE, http_get), default => [],
hoconsc:ref(?MODULE, http_post), desc => ?DESC(sources)
hoconsc:ref(?MODULE, mnesia), }
hoconsc:ref(?MODULE, mongo_single), )}
hoconsc:ref(?MODULE, mongo_rs),
hoconsc:ref(?MODULE, mongo_sharded),
hoconsc:ref(?MODULE, mysql),
hoconsc:ref(?MODULE, postgresql),
hoconsc:ref(?MODULE, redis_single),
hoconsc:ref(?MODULE, redis_sentinel),
hoconsc:ref(?MODULE, redis_cluster)
]
),
default => [],
desc => ?DESC(sources)
}}
]; ];
fields(file) -> fields(file) ->
authz_common_fields(file) ++ authz_common_fields(file) ++
[{path, #{type => string(), required => true, desc => ?DESC(path)}}]; [{path, ?HOCON(string(), #{required => true, desc => ?DESC(path)})}];
fields(http_get) -> fields(http_get) ->
authz_common_fields(http) ++ authz_common_fields(http) ++
http_common_fields() ++ http_common_fields() ++
[ [
{method, #{type => get, default => get, required => true, desc => ?DESC(method)}}, {method, method(get)},
{headers, fun headers_no_content_type/1} {headers, fun headers_no_content_type/1}
]; ];
fields(http_post) -> fields(http_post) ->
authz_common_fields(http) ++ authz_common_fields(http) ++
http_common_fields() ++ http_common_fields() ++
[ [
{method, #{type => post, default => post, required => true, desc => ?DESC(method)}}, {method, method(post)},
{headers, fun headers/1} {headers, fun headers/1}
]; ];
fields(mnesia) -> fields(mnesia) ->
@ -130,65 +132,49 @@ fields(redis_cluster) ->
[{cmd, cmd()}]; [{cmd, cmd()}];
fields("metrics_status_fields") -> fields("metrics_status_fields") ->
[ [
{"resource_metrics", mk(ref(?MODULE, "resource_metrics"), #{desc => ?DESC("metrics")})}, {"resource_metrics", ?HOCON(?R_REF("resource_metrics"), #{desc => ?DESC("metrics")})},
{"node_resource_metrics", {"node_resource_metrics", array("node_resource_metrics", "node_metrics")},
mk( {"metrics", ?HOCON(?R_REF("metrics"), #{desc => ?DESC("metrics")})},
hoconsc:array(ref(?MODULE, "node_resource_metrics")), {"node_metrics", array("node_metrics")},
#{desc => ?DESC("node_metrics")} {"status", ?HOCON(cluster_status(), #{desc => ?DESC("status")})},
)}, {"node_status", array("node_status")},
{"metrics", mk(ref(?MODULE, "metrics"), #{desc => ?DESC("metrics")})}, {"node_error", array("node_error")}
{"node_metrics",
mk(
hoconsc:array(ref(?MODULE, "node_metrics")),
#{desc => ?DESC("node_metrics")}
)},
{"status", mk(cluster_status(), #{desc => ?DESC("status")})},
{"node_status",
mk(
hoconsc:array(ref(?MODULE, "node_status")),
#{desc => ?DESC("node_status")}
)},
{"node_error",
mk(
hoconsc:array(ref(?MODULE, "node_error")),
#{desc => ?DESC("node_error")}
)}
]; ];
fields("metrics") -> fields("metrics") ->
[ [
{"total", mk(integer(), #{desc => ?DESC("metrics_total")})}, {"total", ?HOCON(integer(), #{desc => ?DESC("metrics_total")})},
{"allow", mk(integer(), #{desc => ?DESC("allow")})}, {"allow", ?HOCON(integer(), #{desc => ?DESC("allow")})},
{"deny", mk(integer(), #{desc => ?DESC("deny")})}, {"deny", ?HOCON(integer(), #{desc => ?DESC("deny")})},
{"nomatch", mk(float(), #{desc => ?DESC("nomatch")})} {"nomatch", ?HOCON(float(), #{desc => ?DESC("nomatch")})}
] ++ common_rate_field(); ] ++ common_rate_field();
fields("node_metrics") -> fields("node_metrics") ->
[ [
node_name(), node_name(),
{"metrics", mk(ref(?MODULE, "metrics"), #{desc => ?DESC("metrics")})} {"metrics", ?HOCON(?R_REF("metrics"), #{desc => ?DESC("metrics")})}
]; ];
fields("resource_metrics") -> fields("resource_metrics") ->
common_field(); common_field();
fields("node_resource_metrics") -> fields("node_resource_metrics") ->
[ [
node_name(), node_name(),
{"metrics", mk(ref(?MODULE, "resource_metrics"), #{desc => ?DESC("metrics")})} {"metrics", ?HOCON(?R_REF("resource_metrics"), #{desc => ?DESC("metrics")})}
]; ];
fields("node_status") -> fields("node_status") ->
[ [
node_name(), node_name(),
{"status", mk(status(), #{desc => ?DESC("node_status")})} {"status", ?HOCON(status(), #{desc => ?DESC("node_status")})}
]; ];
fields("node_error") -> fields("node_error") ->
[ [
node_name(), node_name(),
{"error", mk(string(), #{desc => ?DESC("node_error")})} {"error", ?HOCON(string(), #{desc => ?DESC("node_error")})}
]. ].
common_field() -> common_field() ->
[ [
{"matched", mk(integer(), #{desc => ?DESC("matched")})}, {"matched", ?HOCON(integer(), #{desc => ?DESC("matched")})},
{"success", mk(integer(), #{desc => ?DESC("success")})}, {"success", ?HOCON(integer(), #{desc => ?DESC("success")})},
{"failed", mk(integer(), #{desc => ?DESC("failed")})} {"failed", ?HOCON(integer(), #{desc => ?DESC("failed")})}
] ++ common_rate_field(). ] ++ common_rate_field().
status() -> status() ->
@ -198,7 +184,7 @@ cluster_status() ->
hoconsc:enum([connected, disconnected, connecting, inconsistent]). hoconsc:enum([connected, disconnected, connecting, inconsistent]).
node_name() -> node_name() ->
{"node", mk(binary(), #{desc => ?DESC("node"), example => "emqx@127.0.0.1"})}. {"node", ?HOCON(binary(), #{desc => ?DESC("node"), example => "emqx@127.0.0.1"})}.
desc(?CONF_NS) -> desc(?CONF_NS) ->
?DESC(?CONF_NS); ?DESC(?CONF_NS);
@ -231,8 +217,8 @@ desc(_) ->
authz_common_fields(Type) -> authz_common_fields(Type) ->
[ [
{type, #{type => Type, required => true, desc => ?DESC(type)}}, {type, ?HOCON(Type, #{required => true, desc => ?DESC(type)})},
{enable, #{type => boolean(), default => true, desc => ?DESC(enable)}} {enable, ?HOCON(boolean(), #{default => true, desc => ?DESC(enable)})}
]. ].
http_common_fields() -> http_common_fields() ->
@ -242,7 +228,7 @@ http_common_fields() ->
mk_duration("Request timeout", #{ mk_duration("Request timeout", #{
required => false, default => "30s", desc => ?DESC(request_timeout) required => false, default => "30s", desc => ?DESC(request_timeout)
})}, })},
{body, #{type => map(), required => false, desc => ?DESC(body)}} {body, ?HOCON(map(), #{required => false, desc => ?DESC(body)})}
] ++ ] ++
maps:to_list( maps:to_list(
maps:without( maps:without(
@ -256,17 +242,17 @@ http_common_fields() ->
mongo_common_fields() -> mongo_common_fields() ->
[ [
{collection, #{ {collection,
type => atom(), ?HOCON(atom(), #{
required => true, required => true,
desc => ?DESC(collection) desc => ?DESC(collection)
}}, })},
{filter, #{ {filter,
type => map(), ?HOCON(map(), #{
required => false, required => false,
default => #{}, default => #{},
desc => ?DESC(filter) desc => ?DESC(filter)
}} })}
]. ].
validations() -> validations() ->
@ -347,31 +333,31 @@ transform_header_name(Headers) ->
Headers Headers
). ).
%% TODO: fix me, not work
check_ssl_opts(Conf) -> check_ssl_opts(Conf) ->
case hocon_maps:get("config.url", Conf) of Sources = hocon_maps:get("authorization.sources", Conf, []),
undefined -> lists:foreach(
true; fun
Url -> (#{<<"url">> := Url} = Source) ->
case emqx_authz_http:parse_url(Url) of case emqx_authz_http:parse_url(Url) of
{<<"https", _>>, _, _} -> {<<"https", _/binary>>, _, _} ->
case hocon_maps:get("config.ssl.enable", Conf) of case emqx_map_lib:deep_find([<<"ssl">>, <<"enable">>], Source) of
true -> true; {ok, true} -> true;
_ -> {error, ssl_not_enable} {ok, false} -> throw({ssl_not_enable, Url});
end; _ -> throw({ssl_enable_not_found, Url})
{<<"http", _>>, _, _} -> end;
true; {<<"http", _/binary>>, _, _} ->
Bad -> ok;
{bad_scheme, Url, Bad} Bad ->
end throw({bad_scheme, Url, Bad})
end. end;
(_Source) ->
union_array(Item) when is_list(Item) -> ok
hoconsc:array(hoconsc:union(Item)). end,
Sources
).
query() -> query() ->
#{ ?HOCON(binary(), #{
type => binary(),
desc => ?DESC(query), desc => ?DESC(query),
required => true, required => true,
validator => fun(S) -> validator => fun(S) ->
@ -380,11 +366,10 @@ query() ->
_ -> {error, "Request query"} _ -> {error, "Request query"}
end end
end end
}. }).
cmd() -> cmd() ->
#{ ?HOCON(binary(), #{
type => binary(),
desc => ?DESC(cmd), desc => ?DESC(cmd),
required => true, required => true,
validator => fun(S) -> validator => fun(S) ->
@ -393,7 +378,7 @@ cmd() ->
_ -> {error, "Request query"} _ -> {error, "Request query"}
end end
end end
}. }).
connector_fields(DB) -> connector_fields(DB) ->
connector_fields(DB, config). connector_fields(DB, config).
@ -417,7 +402,15 @@ to_list(B) when is_binary(B) ->
common_rate_field() -> common_rate_field() ->
[ [
{"rate", mk(float(), #{desc => ?DESC("rate")})}, {"rate", ?HOCON(float(), #{desc => ?DESC("rate")})},
{"rate_max", mk(float(), #{desc => ?DESC("rate_max")})}, {"rate_max", ?HOCON(float(), #{desc => ?DESC("rate_max")})},
{"rate_last5m", mk(float(), #{desc => ?DESC("rate_last5m")})} {"rate_last5m", ?HOCON(float(), #{desc => ?DESC("rate_last5m")})}
]. ].
method(Method) ->
?HOCON(Method, #{default => Method, required => true, desc => ?DESC(method)}).
array(Ref) -> array(Ref, Ref).
array(Ref, DescId) ->
?HOCON(?ARRAY(?R_REF(Ref)), #{desc => ?DESC(DescId)}).

View File

@ -78,6 +78,7 @@ set_special_configs(_App) ->
<<"enable">> => true, <<"enable">> => true,
<<"url">> => <<"https://example.com:443/a/b?c=d">>, <<"url">> => <<"https://example.com:443/a/b?c=d">>,
<<"headers">> => #{}, <<"headers">> => #{},
<<"ssl">> => #{<<"enable">> => true},
<<"method">> => <<"get">>, <<"method">> => <<"get">>,
<<"request_timeout">> => 5000 <<"request_timeout">> => 5000
}). }).

View File

@ -33,6 +33,7 @@
<<"type">> => <<"http">>, <<"type">> => <<"http">>,
<<"enable">> => true, <<"enable">> => true,
<<"url">> => <<"https://fake.com:443/acl?username=", ?PH_USERNAME/binary>>, <<"url">> => <<"https://fake.com:443/acl?username=", ?PH_USERNAME/binary>>,
<<"ssl">> => #{<<"enable">> => true},
<<"headers">> => #{}, <<"headers">> => #{},
<<"method">> => <<"get">>, <<"method">> => <<"get">>,
<<"request_timeout">> => <<"5s">> <<"request_timeout">> => <<"5s">>

View File

@ -36,36 +36,36 @@ roots() ->
fields("auto_subscribe") -> fields("auto_subscribe") ->
[ [
{topics, {topics,
hoconsc:mk( ?HOCON(
hoconsc:array(hoconsc:ref(?MODULE, "topic")), ?ARRAY(?R_REF("topic")),
#{desc => ?DESC(auto_subscribe), default => []} #{desc => ?DESC(auto_subscribe), default => []}
)} )}
]; ];
fields("topic") -> fields("topic") ->
[ [
{topic, {topic,
sc(binary(), #{ ?HOCON(binary(), #{
required => true, required => true,
example => topic_example(), example => topic_example(),
desc => ?DESC("topic") desc => ?DESC("topic")
})}, })},
{qos, {qos,
sc(emqx_schema:qos(), #{ ?HOCON(emqx_schema:qos(), #{
default => 0, default => 0,
desc => ?DESC("qos") desc => ?DESC("qos")
})}, })},
{rh, {rh,
sc(range(0, 2), #{ ?HOCON(range(0, 2), #{
default => 0, default => 0,
desc => ?DESC("rh") desc => ?DESC("rh")
})}, })},
{rap, {rap,
sc(range(0, 1), #{ ?HOCON(range(0, 1), #{
default => 0, default => 0,
desc => ?DESC("rap") desc => ?DESC("rap")
})}, })},
{nl, {nl,
sc(range(0, 1), #{ ?HOCON(range(0, 1), #{
default => 0, default => 0,
desc => ?DESC(nl) desc => ?DESC(nl)
})} })}
@ -78,10 +78,3 @@ desc(_) -> undefined.
topic_example() -> topic_example() ->
<<"/clientid/", ?PH_S_CLIENTID, "/username/", ?PH_S_USERNAME, "/host/", ?PH_S_HOST, "/port/", <<"/clientid/", ?PH_S_CLIENTID, "/username/", ?PH_S_USERNAME, "/host/", ?PH_S_HOST, "/port/",
?PH_S_PORT>>. ?PH_S_PORT>>.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
sc(Type, Meta) ->
hoconsc:mk(Type, Meta).

View File

@ -341,6 +341,7 @@ fields(cluster_k8s) ->
sc( sc(
string(), string(),
#{ #{
default => "http://10.110.111.204:8080",
desc => ?DESC(cluster_k8s_apiserver), desc => ?DESC(cluster_k8s_apiserver),
'readOnly' => true 'readOnly' => true
} }
@ -358,6 +359,7 @@ fields(cluster_k8s) ->
sc( sc(
hoconsc:enum([ip, dns, hostname]), hoconsc:enum([ip, dns, hostname]),
#{ #{
default => ip,
desc => ?DESC(cluster_k8s_address_type), desc => ?DESC(cluster_k8s_address_type),
'readOnly' => true 'readOnly' => true
} }
@ -731,7 +733,7 @@ fields("rpc") ->
emqx_schema:duration_s(), emqx_schema:duration_s(),
#{ #{
mapping => "gen_rpc.socket_keepalive_idle", mapping => "gen_rpc.socket_keepalive_idle",
default => "7200s", default => "15m",
desc => ?DESC(rpc_socket_keepalive_idle) desc => ?DESC(rpc_socket_keepalive_idle)
} }
)}, )},

View File

@ -20,8 +20,6 @@
-include_lib("typerefl/include/types.hrl"). -include_lib("typerefl/include/types.hrl").
-include_lib("hocon/include/hoconsc.hrl"). -include_lib("hocon/include/hoconsc.hrl").
-import(hoconsc, [mk/2, ref/2]).
-export([namespace/0, roots/0, fields/1, desc/1]). -export([namespace/0, roots/0, fields/1, desc/1]).
-export([ -export([
@ -46,8 +44,8 @@ post_request() ->
http_schema("post"). http_schema("post").
http_schema(Method) -> http_schema(Method) ->
Schemas = [ref(schema_mod(Type), Method) || Type <- ?CONN_TYPES], Schemas = [?R_REF(schema_mod(Type), Method) || Type <- ?CONN_TYPES],
hoconsc:union(Schemas). ?UNION(Schemas).
%%====================================================================================== %%======================================================================================
%% Hocon Schema Definitions %% Hocon Schema Definitions
@ -61,11 +59,8 @@ fields(connectors) ->
fields("connectors") -> fields("connectors") ->
[ [
{mqtt, {mqtt,
mk( ?HOCON(
hoconsc:map( ?MAP(name, ?R_REF(emqx_connector_mqtt_schema, "connector")),
name,
ref(emqx_connector_mqtt_schema, "connector")
),
#{desc => ?DESC("mqtt")} #{desc => ?DESC("mqtt")}
)} )}
]. ].

View File

@ -30,14 +30,14 @@ roots() -> ["dashboard"].
fields("dashboard") -> fields("dashboard") ->
[ [
{listeners, {listeners,
sc( ?HOCON(
ref("listeners"), ?R_REF("listeners"),
#{desc => ?DESC(listeners)} #{desc => ?DESC(listeners)}
)}, )},
{default_username, fun default_username/1}, {default_username, fun default_username/1},
{default_password, fun default_password/1}, {default_password, fun default_password/1},
{sample_interval, {sample_interval,
sc( ?HOCON(
emqx_schema:duration_s(), emqx_schema:duration_s(),
#{ #{
default => "10s", default => "10s",
@ -46,7 +46,7 @@ fields("dashboard") ->
} }
)}, )},
{token_expired_time, {token_expired_time,
sc( ?HOCON(
emqx_schema:duration(), emqx_schema:duration(),
#{ #{
default => "60m", default => "60m",
@ -59,16 +59,16 @@ fields("dashboard") ->
fields("listeners") -> fields("listeners") ->
[ [
{"http", {"http",
sc( ?HOCON(
ref("http"), ?R_REF("http"),
#{ #{
desc => "TCP listeners", desc => "TCP listeners",
required => {false, recursively} required => {false, recursively}
} }
)}, )},
{"https", {"https",
sc( ?HOCON(
ref("https"), ?R_REF("https"),
#{ #{
desc => "SSL listeners", desc => "SSL listeners",
required => {false, recursively} required => {false, recursively}
@ -78,13 +78,13 @@ fields("listeners") ->
fields("http") -> fields("http") ->
[ [
enable(true), enable(true),
bind(18803) bind(18083)
| common_listener_fields() | common_listener_fields()
]; ];
fields("https") -> fields("https") ->
[ [
enable(false), enable(false),
bind(18804) bind(18084)
| common_listener_fields() ++ | common_listener_fields() ++
exclude_fields( exclude_fields(
["fail_if_no_peer_cert"], ["fail_if_no_peer_cert"],
@ -104,7 +104,7 @@ exclude_fields([FieldName | Rest], Fields) ->
common_listener_fields() -> common_listener_fields() ->
[ [
{"num_acceptors", {"num_acceptors",
sc( ?HOCON(
integer(), integer(),
#{ #{
default => 4, default => 4,
@ -112,7 +112,7 @@ common_listener_fields() ->
} }
)}, )},
{"max_connections", {"max_connections",
sc( ?HOCON(
integer(), integer(),
#{ #{
default => 512, default => 512,
@ -120,7 +120,7 @@ common_listener_fields() ->
} }
)}, )},
{"backlog", {"backlog",
sc( ?HOCON(
integer(), integer(),
#{ #{
default => 1024, default => 1024,
@ -128,7 +128,7 @@ common_listener_fields() ->
} }
)}, )},
{"send_timeout", {"send_timeout",
sc( ?HOCON(
emqx_schema:duration(), emqx_schema:duration(),
#{ #{
default => "5s", default => "5s",
@ -136,7 +136,7 @@ common_listener_fields() ->
} }
)}, )},
{"inet6", {"inet6",
sc( ?HOCON(
boolean(), boolean(),
#{ #{
default => false, default => false,
@ -144,7 +144,7 @@ common_listener_fields() ->
} }
)}, )},
{"ipv6_v6only", {"ipv6_v6only",
sc( ?HOCON(
boolean(), boolean(),
#{ #{
default => false, default => false,
@ -155,7 +155,7 @@ common_listener_fields() ->
enable(Bool) -> enable(Bool) ->
{"enable", {"enable",
sc( ?HOCON(
boolean(), boolean(),
#{ #{
default => Bool, default => Bool,
@ -166,12 +166,12 @@ enable(Bool) ->
bind(Port) -> bind(Port) ->
{"bind", {"bind",
sc( ?HOCON(
hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]), ?UNION([non_neg_integer(), emqx_schema:ip_port()]),
#{ #{
default => Port, default => Port,
required => true, required => true,
extra => #{example => [Port, "0.0.0.0:" ++ integer_to_list(Port)]}, example => "0.0.0.0:" ++ integer_to_list(Port),
desc => ?DESC(bind) desc => ?DESC(bind)
} }
)}. )}.
@ -222,7 +222,3 @@ validate_sample_interval(Second) ->
Msg = "must be between 1 and 60 and be a divisor of 60.", Msg = "must be between 1 and 60 and be a divisor of 60.",
{error, Msg} {error, Msg}
end. end.
sc(Type, Meta) -> hoconsc:mk(Type, Meta).
ref(Field) -> hoconsc:ref(?MODULE, Field).

View File

@ -667,6 +667,8 @@ typename_to_spec("{binary(), binary()}", _Mod) ->
#{type => object, example => #{}}; #{type => object, example => #{}};
typename_to_spec("comma_separated_list()", _Mod) -> typename_to_spec("comma_separated_list()", _Mod) ->
#{type => string, example => <<"item1,item2">>}; #{type => string, example => <<"item1,item2">>};
typename_to_spec("comma_separated_binary()", _Mod) ->
#{type => string, example => <<"item1,item2">>};
typename_to_spec("comma_separated_atoms()", _Mod) -> typename_to_spec("comma_separated_atoms()", _Mod) ->
#{type => string, example => <<"item1,item2">>}; #{type => string, example => <<"item1,item2">>};
typename_to_spec("pool_type()", _Mod) -> typename_to_spec("pool_type()", _Mod) ->

View File

@ -27,12 +27,6 @@
-behaviour(hocon_schema). -behaviour(hocon_schema).
-type duration() :: integer().
-typerefl_from_string({duration/0, emqx_schema, to_duration}).
-reflect_type([duration/0]).
-export([namespace/0, roots/0, fields/1, desc/1, server_config/0]). -export([namespace/0, roots/0, fields/1, desc/1, server_config/0]).
namespace() -> exhook. namespace() -> exhook.
@ -42,65 +36,48 @@ roots() -> [exhook].
fields(exhook) -> fields(exhook) ->
[ [
{servers, {servers,
sc( ?HOCON(?ARRAY(?R_REF(server)), #{
hoconsc:array(ref(server)), default => [],
#{ desc => ?DESC(servers)
default => [], })}
desc => ?DESC(servers)
}
)}
]; ];
fields(server) -> fields(server) ->
[ [
{name, {name,
sc( ?HOCON(binary(), #{
binary(), example => <<"default">>,
#{ required => true,
required => true, validator => fun validate_name/1,
validator => fun validate_name/1, desc => ?DESC(name)
desc => ?DESC(name) })},
}
)},
{enable, {enable,
sc( ?HOCON(boolean(), #{
boolean(), default => true,
#{ desc => ?DESC(enable)
default => true, })},
desc => ?DESC(enable)
}
)},
{url, {url,
sc( ?HOCON(binary(), #{
binary(), required => true,
#{required => true, desc => ?DESC(url)} desc => ?DESC(url),
)}, example => <<"http://127.0.0.1:9000">>
})},
{request_timeout, {request_timeout,
sc( ?HOCON(emqx_schema:duration(), #{
duration(), default => "5s",
#{ desc => ?DESC(request_timeout)
default => "5s", })},
desc => ?DESC(request_timeout)
}
)},
{failed_action, failed_action()}, {failed_action, failed_action()},
{ssl, sc(ref(ssl_conf), #{})}, {ssl, ?HOCON(?R_REF(ssl_conf), #{})},
{auto_reconnect, {auto_reconnect,
sc( ?HOCON(hoconsc:union([false, emqx_schema:duration()]), #{
hoconsc:union([false, duration()]), default => "60s",
#{ desc => ?DESC(auto_reconnect)
default => "60s", })},
desc => ?DESC(auto_reconnect)
}
)},
{pool_size, {pool_size,
sc( ?HOCON(pos_integer(), #{
pos_integer(), default => 8,
#{ desc => ?DESC(pool_size)
default => 8, })}
example => 8,
desc => ?DESC(pool_size)
}
)}
]; ];
fields(ssl_conf) -> fields(ssl_conf) ->
Schema = emqx_schema:client_ssl_opts_schema(#{}), Schema = emqx_schema:client_ssl_opts_schema(#{}),
@ -115,20 +92,11 @@ desc(ssl_conf) ->
desc(_) -> desc(_) ->
undefined. undefined.
%% types
sc(Type, Meta) -> Meta#{type => Type}.
ref(Field) ->
hoconsc:ref(?MODULE, Field).
failed_action() -> failed_action() ->
sc( ?HOCON(?ENUM([deny, ignore]), #{
hoconsc:enum([deny, ignore]), default => deny,
#{ desc => ?DESC(failed_action)
default => deny, }).
desc => ?DESC(failed_action)
}
).
validate_name(Name) -> validate_name(Name) ->
NameRE = "^[A-Za-z0-9]+[A-Za-z0-9-_]*$", NameRE = "^[A-Za-z0-9]+[A-Za-z0-9-_]*$",
@ -138,7 +106,7 @@ validate_name(Name) ->
case re:run(Name, NameRE) of case re:run(Name, NameRE) of
{match, _} -> {match, _} ->
ok; ok;
_Nomatch -> _NoMatch ->
Reason = list_to_binary( Reason = list_to_binary(
io_lib:format("Bad ExHook Name ~p, expect ~p", [Name, NameRE]) io_lib:format("Bad ExHook Name ~p, expect ~p", [Name, NameRE])
), ),

View File

@ -215,7 +215,7 @@ fields(coap) ->
)}, )},
{notify_type, {notify_type,
sc( sc(
hoconsc:union([non, con, qos]), hoconsc:enum([non, con, qos]),
#{ #{
default => qos, default => qos,
desc => ?DESC(coap_notify_type) desc => ?DESC(coap_notify_type)
@ -291,9 +291,9 @@ fields(lwm2m) ->
%% FIXME: not working now %% FIXME: not working now
{update_msg_publish_condition, {update_msg_publish_condition,
sc( sc(
hoconsc:union([always, contains_object_list]), hoconsc:enum([always, contains_object_list]),
#{ #{
default => "contains_object_list", default => contains_object_list,
desc => ?DESC(lwm2m_update_msg_publish_condition) desc => ?DESC(lwm2m_update_msg_publish_condition)
} }
)}, )},

View File

@ -39,33 +39,34 @@ roots() ->
]. ].
fields("telemetry") -> fields("telemetry") ->
[{enable, hoconsc:mk(boolean(), #{default => true, desc => "Enable telemetry."})}]; [{enable, ?HOCON(boolean(), #{default => true, desc => "Enable telemetry."})}];
fields("delayed") -> fields("delayed") ->
[ [
{enable, hoconsc:mk(boolean(), #{default => true, desc => ?DESC(enable)})}, {enable, ?HOCON(boolean(), #{default => true, desc => ?DESC(enable)})},
{max_delayed_messages, sc(integer(), #{desc => ?DESC(max_delayed_messages), default => 0})} {max_delayed_messages,
?HOCON(integer(), #{desc => ?DESC(max_delayed_messages), default => 0})}
]; ];
fields("rewrite") -> fields("rewrite") ->
[ [
{action, {action,
sc( ?HOCON(
hoconsc:enum([subscribe, publish, all]), hoconsc:enum([subscribe, publish, all]),
#{required => true, desc => ?DESC(tr_action), example => publish} #{required => true, desc => ?DESC(tr_action), example => publish}
)}, )},
{source_topic, {source_topic,
sc( ?HOCON(
binary(), binary(),
#{required => true, desc => ?DESC(tr_source_topic), example => "x/#"} #{required => true, desc => ?DESC(tr_source_topic), example => "x/#"}
)}, )},
{dest_topic, {dest_topic,
sc( ?HOCON(
binary(), binary(),
#{required => true, desc => ?DESC(tr_dest_topic), example => "z/y/$1"} #{required => true, desc => ?DESC(tr_dest_topic), example => "z/y/$1"}
)}, )},
{re, fun regular_expression/1} {re, fun regular_expression/1}
]; ];
fields("topic_metrics") -> fields("topic_metrics") ->
[{topic, sc(binary(), #{desc => "Collect metrics for the topic."})}]. [{topic, ?HOCON(binary(), #{desc => "Collect metrics for the topic."})}].
desc("telemetry") -> desc("telemetry") ->
"Settings for the telemetry module."; "Settings for the telemetry module.";
@ -91,6 +92,4 @@ is_re(Bin) ->
{error, Reason} -> {error, {Bin, Reason}} {error, Reason} -> {error, {Bin, Reason}}
end. end.
array(Name, Meta) -> {Name, hoconsc:mk(hoconsc:array(hoconsc:ref(?MODULE, Name)), Meta)}. array(Name, Meta) -> {Name, ?HOCON(?ARRAY(?R_REF(Name)), Meta)}.
sc(Type, Meta) -> hoconsc:mk(Type, Meta).

View File

@ -45,7 +45,7 @@ fields(state) ->
state_fields() -> state_fields() ->
[ [
{name_vsn, {name_vsn,
hoconsc:mk( ?HOCON(
string(), string(),
#{ #{
desc => ?DESC(name_vsn), desc => ?DESC(name_vsn),
@ -53,7 +53,7 @@ state_fields() ->
} }
)}, )},
{enable, {enable,
hoconsc:mk( ?HOCON(
boolean(), boolean(),
#{ #{
desc => ?DESC(enable), desc => ?DESC(enable),
@ -69,7 +69,7 @@ root_fields() ->
{check_interval, fun check_interval/1} {check_interval, fun check_interval/1}
]. ].
states(type) -> hoconsc:array(hoconsc:ref(?MODULE, state)); states(type) -> ?ARRAY(?R_REF(state));
states(required) -> false; states(required) -> false;
states(default) -> []; states(default) -> [];
states(desc) -> ?DESC(states); states(desc) -> ?DESC(states);

View File

@ -34,7 +34,7 @@ roots() -> ["prometheus"].
fields("prometheus") -> fields("prometheus") ->
[ [
{push_gateway_server, {push_gateway_server,
sc( ?HOCON(
string(), string(),
#{ #{
default => "http://127.0.0.1:9091", default => "http://127.0.0.1:9091",
@ -43,7 +43,7 @@ fields("prometheus") ->
} }
)}, )},
{interval, {interval,
sc( ?HOCON(
emqx_schema:duration_ms(), emqx_schema:duration_ms(),
#{ #{
default => "15s", default => "15s",
@ -52,7 +52,7 @@ fields("prometheus") ->
} }
)}, )},
{enable, {enable,
sc( ?HOCON(
boolean(), boolean(),
#{ #{
default => false, default => false,
@ -64,5 +64,3 @@ fields("prometheus") ->
desc("prometheus") -> ?DESC(prometheus); desc("prometheus") -> ?DESC(prometheus);
desc(_) -> undefined. desc(_) -> undefined.
sc(Type, Meta) -> hoconsc:mk(Type, Meta).

View File

@ -27,8 +27,6 @@
fields/1 fields/1
]). ]).
-import(emqx_schema, [sc/2]).
namespace() -> "authn-psk". namespace() -> "authn-psk".
roots() -> ["psk_authentication"]. roots() -> ["psk_authentication"].
@ -42,33 +40,24 @@ fields("psk_authentication") ->
fields() -> fields() ->
[ [
{enable, {enable,
sc(boolean(), #{ ?HOCON(boolean(), #{
default => false, default => false,
require => true, require => true,
desc => ?DESC(enable) desc => ?DESC(enable)
})}, })},
{init_file, {init_file,
sc( ?HOCON(binary(), #{
binary(), required => false,
#{ desc => ?DESC(init_file)
required => false, })},
desc => ?DESC(init_file)
}
)},
{separator, {separator,
sc( ?HOCON(binary(), #{
binary(), default => <<":">>,
#{ desc => ?DESC(separator)
default => <<":">>, })},
desc => ?DESC(separator)
}
)},
{chunk_size, {chunk_size,
sc( ?HOCON(integer(), #{
integer(), default => 50,
#{ desc => ?DESC(chunk_size)
default => 50, })}
desc => ?DESC(chunk_size)
}
)}
]. ].

View File

@ -52,10 +52,10 @@ fields("retainer") ->
]; ];
fields(mnesia_config) -> fields(mnesia_config) ->
[ [
{type, sc(hoconsc:enum([built_in_database]), mnesia_config_type, built_in_database)}, {type, sc(built_in_database, mnesia_config_type, built_in_database)},
{storage_type, {storage_type,
sc( sc(
hoconsc:union([ram, disc]), hoconsc:enum([ram, disc]),
mnesia_config_storage_type, mnesia_config_storage_type,
ram ram
)}, )},

View File

@ -37,13 +37,13 @@ roots() -> ["rule_engine"].
fields("rule_engine") -> fields("rule_engine") ->
[ [
{ignore_sys_message, {ignore_sys_message,
sc(boolean(), #{default => true, desc => ?DESC("rule_engine_ignore_sys_message")})}, ?HOCON(boolean(), #{default => true, desc => ?DESC("rule_engine_ignore_sys_message")})},
{rules, {rules,
sc(hoconsc:map("id", ref("rules")), #{ ?HOCON(hoconsc:map("id", ?R_REF("rules")), #{
desc => ?DESC("rule_engine_rules"), default => #{} desc => ?DESC("rule_engine_rules"), default => #{}
})}, })},
{jq_function_default_timeout, {jq_function_default_timeout,
sc( ?HOCON(
emqx_schema:duration_ms(), emqx_schema:duration_ms(),
#{ #{
default => "10s", default => "10s",
@ -55,7 +55,7 @@ fields("rules") ->
[ [
rule_name(), rule_name(),
{"sql", {"sql",
sc( ?HOCON(
binary(), binary(),
#{ #{
desc => ?DESC("rules_sql"), desc => ?DESC("rules_sql"),
@ -65,8 +65,8 @@ fields("rules") ->
} }
)}, )},
{"actions", {"actions",
sc( ?HOCON(
hoconsc:array(hoconsc:union(actions())), ?ARRAY(?UNION(actions())),
#{ #{
desc => ?DESC("rules_actions"), desc => ?DESC("rules_actions"),
default => [], default => [],
@ -82,9 +82,9 @@ fields("rules") ->
] ]
} }
)}, )},
{"enable", sc(boolean(), #{desc => ?DESC("rules_enable"), default => true})}, {"enable", ?HOCON(boolean(), #{desc => ?DESC("rules_enable"), default => true})},
{"description", {"description",
sc( ?HOCON(
binary(), binary(),
#{ #{
desc => ?DESC("rules_description"), desc => ?DESC("rules_description"),
@ -95,12 +95,12 @@ fields("rules") ->
]; ];
fields("builtin_action_republish") -> fields("builtin_action_republish") ->
[ [
{function, sc(republish, #{desc => ?DESC("republish_function")})}, {function, ?HOCON(republish, #{desc => ?DESC("republish_function")})},
{args, sc(ref("republish_args"), #{default => #{}})} {args, ?HOCON(?R_REF("republish_args"), #{default => #{}})}
]; ];
fields("builtin_action_console") -> fields("builtin_action_console") ->
[ [
{function, sc(console, #{desc => ?DESC("console_function")})} {function, ?HOCON(console, #{desc => ?DESC("console_function")})}
%% we may support some args for the console action in the future %% we may support some args for the console action in the future
%, {args, sc(map(), #{desc => "The arguments of the built-in 'console' action", %, {args, sc(map(), #{desc => "The arguments of the built-in 'console' action",
% default => #{}})} % default => #{}})}
@ -108,7 +108,7 @@ fields("builtin_action_console") ->
fields("user_provided_function") -> fields("user_provided_function") ->
[ [
{function, {function,
sc( ?HOCON(
binary(), binary(),
#{ #{
desc => ?DESC("user_provided_function_function"), desc => ?DESC("user_provided_function_function"),
@ -117,7 +117,7 @@ fields("user_provided_function") ->
} }
)}, )},
{args, {args,
sc( ?HOCON(
map(), map(),
#{ #{
desc => ?DESC("user_provided_function_args"), desc => ?DESC("user_provided_function_args"),
@ -128,7 +128,7 @@ fields("user_provided_function") ->
fields("republish_args") -> fields("republish_args") ->
[ [
{topic, {topic,
sc( ?HOCON(
binary(), binary(),
#{ #{
desc => ?DESC("republish_args_topic"), desc => ?DESC("republish_args_topic"),
@ -137,7 +137,7 @@ fields("republish_args") ->
} }
)}, )},
{qos, {qos,
sc( ?HOCON(
qos(), qos(),
#{ #{
desc => ?DESC("republish_args_qos"), desc => ?DESC("republish_args_qos"),
@ -146,8 +146,8 @@ fields("republish_args") ->
} }
)}, )},
{retain, {retain,
sc( ?HOCON(
hoconsc:union([binary(), boolean()]), hoconsc:union([boolean(), binary()]),
#{ #{
desc => ?DESC("republish_args_retain"), desc => ?DESC("republish_args_retain"),
default => <<"${retain}">>, default => <<"${retain}">>,
@ -155,7 +155,7 @@ fields("republish_args") ->
} }
)}, )},
{payload, {payload,
sc( ?HOCON(
binary(), binary(),
#{ #{
desc => ?DESC("republish_args_payload"), desc => ?DESC("republish_args_payload"),
@ -182,7 +182,7 @@ desc(_) ->
rule_name() -> rule_name() ->
{"name", {"name",
sc( ?HOCON(
binary(), binary(),
#{ #{
desc => ?DESC("rules_name"), desc => ?DESC("rules_name"),
@ -195,19 +195,16 @@ rule_name() ->
actions() -> actions() ->
[ [
binary(), binary(),
ref("builtin_action_republish"), ?R_REF("builtin_action_republish"),
ref("builtin_action_console"), ?R_REF("builtin_action_console"),
ref("user_provided_function") ?R_REF("user_provided_function")
]. ].
qos() -> qos() ->
hoconsc:union([emqx_schema:qos(), binary()]). ?UNION([emqx_schema:qos(), binary()]).
validate_sql(Sql) -> validate_sql(Sql) ->
case emqx_rule_sqlparser:parse(Sql) of case emqx_rule_sqlparser:parse(Sql) of
{ok, _Result} -> ok; {ok, _Result} -> ok;
{error, Reason} -> {error, Reason} {error, Reason} -> {error, Reason}
end. end.
sc(Type, Meta) -> hoconsc:mk(Type, Meta).
ref(Field) -> hoconsc:ref(?MODULE, Field).

View File

@ -32,7 +32,7 @@ fields("slow_subs") ->
)}, )},
{stats_type, {stats_type,
sc( sc(
hoconsc:enum([whole, internal, response]), ?ENUM([whole, internal, response]),
whole, whole,
stats_type stats_type
)} )}
@ -47,4 +47,4 @@ desc(_) ->
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
sc(Type, Default, Desc) -> sc(Type, Default, Desc) ->
hoconsc:mk(Type, #{default => Default, desc => ?DESC(Desc)}). ?HOCON(Type, #{default => Default, desc => ?DESC(Desc)}).