Merge pull request #7386 from ieQu1/doc-schema-3

docs(schema): Add descriptions to the schema
This commit is contained in:
Dmitrii 2022-03-24 14:05:38 +01:00 committed by GitHub
commit f4125fbe0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 39 deletions

View File

@ -114,10 +114,10 @@ fields(limiter_opts) ->
]; ];
fields(bucket_opts) -> fields(bucket_opts) ->
[ {rate, sc(rate(), #{desc => "The rate for this bucket"})} [ {rate, sc(rate(), #{desc => "Rate for this bucket."})}
, {capacity, sc(capacity(), #{desc => "The maximum number of tokens for this bucket"})} , {capacity, sc(capacity(), #{desc => "The maximum number of tokens for this bucket."})}
, {initial, sc(initial(), #{default => "0", , {initial, sc(initial(), #{default => "0",
desc => "The initial number of tokens for this bucket"})} desc => "The initial number of tokens for this bucket."})}
, {per_client, sc(ref(client_bucket), , {per_client, sc(ref(client_bucket),
#{default => #{}, #{default => #{},
desc => "The rate limit for each user of the bucket," desc => "The rate limit for each user of the bucket,"
@ -126,8 +126,8 @@ fields(bucket_opts) ->
]; ];
fields(client_bucket) -> fields(client_bucket) ->
[ {rate, sc(rate(), #{default => "infinity"})} [ {rate, sc(rate(), #{default => "infinity", desc => "Rate for this bucket."})}
, {initial, sc(initial(), #{default => "0"})} , {initial, sc(initial(), #{default => "0", desc => "The initial number of tokens for this bucket."})}
%% low_water_mark add for emqx_channel and emqx_session %% low_water_mark 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

View File

@ -100,6 +100,11 @@
-elvis([{elvis_style, god_modules, disable}]). -elvis([{elvis_style, god_modules, disable}]).
-define(IDLE_TIMOUT_DESC,
"Close transport-layer connections from the clients that have not sent MQTT CONNECT\n"
"message within this interval."
).
namespace() -> undefined. namespace() -> undefined.
roots() -> roots() ->
@ -786,7 +791,7 @@ fields("force_gc") ->
{"enable", {"enable",
sc( sc(
boolean(), boolean(),
#{default => true} #{default => true, desc => "Enable forced garbage collection."}
)}, )},
{"count", {"count",
sc( sc(
@ -905,24 +910,24 @@ fields("mqtt_quic_listener") ->
{"enabled", {"enabled",
sc( sc(
boolean(), boolean(),
#{default => true} #{default => true, desc => "Enable QUIC listener."}
)}, )},
%% TODO: ensure cacertfile is configurable %% TODO: ensure cacertfile is configurable
{"certfile", {"certfile",
sc( sc(
string(), string(),
#{} #{desc => "Path to the certificate."}
)}, )},
{"keyfile", {"keyfile",
sc( sc(
string(), string(),
#{} #{desc => "Path to the secret key file."}
)}, )},
{"ciphers", ciphers_schema(quic)}, {"ciphers", ciphers_schema(quic)},
{"idle_timeout", {"idle_timeout",
sc( sc(
duration(), duration(),
#{default => "15s"} #{default => "15s", desc => ?IDLE_TIMOUT_DESC}
)} )}
] ++ base_listener(); ] ++ base_listener();
fields("ws_opts") -> fields("ws_opts") ->
@ -957,9 +962,7 @@ fields("ws_opts") ->
duration(), duration(),
#{ #{
default => "15s", default => "15s",
desc => desc => ?IDLE_TIMOUT_DESC
"The idle time after the TCP connection is established <br/>\n"
" If no packets are received within this time, the connection will be closed."
} }
)}, )},
{"max_frame_size", {"max_frame_size",
@ -1652,17 +1655,30 @@ mqtt_listener() ->
{"access_rules", {"access_rules",
sc( sc(
hoconsc:array(string()), hoconsc:array(string()),
#{} #{
desc =>
"The access control rules for this listener.<br/>"
"See: https://github.com/emqtt/esockd#allowdeny"
}
)}, )},
{"proxy_protocol", {"proxy_protocol",
sc( sc(
boolean(), boolean(),
#{default => false} #{
default => false,
desc =>
"Enable the Proxy Protocol V1/2 if the EMQX cluster is deployed\n"
" behind HAProxy or Nginx.<br/>"
"See: https://www.haproxy.com/blog/haproxy/proxy-protocol/"
}
)}, )},
{"proxy_protocol_timeout", {"proxy_protocol_timeout",
sc( sc(
duration(), duration(),
#{} #{
desc =>
"Timeout for proxy protocol. EMQX will close the TCP connection if proxy protocol packet is not received within the timeout."
}
)}, )},
{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME, {?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME,
authentication("Per-listener authentication override")} authentication("Per-listener authentication override")}
@ -1762,7 +1778,10 @@ common_ssl_opts_schema(Defaults) ->
{"enable", {"enable",
sc( sc(
boolean(), boolean(),
#{default => Df("enable", false)} #{
default => Df("enable", false),
desc => "Enable TLS."
}
)}, )},
{"cacertfile", {"cacertfile",
sc( sc(
@ -1808,12 +1827,20 @@ common_ssl_opts_schema(Defaults) ->
{"verify", {"verify",
sc( sc(
hoconsc:enum([verify_peer, verify_none]), hoconsc:enum([verify_peer, verify_none]),
#{default => Df("verify", verify_none)} #{
default => Df("verify", verify_none),
desc =>
"Enable or disable peer verification."
}
)}, )},
{"reuse_sessions", {"reuse_sessions",
sc( sc(
boolean(), boolean(),
#{default => Df("reuse_sessions", true)} #{
default => Df("reuse_sessions", true),
desc =>
"Enable TLS session reuse."
}
)}, )},
{"depth", {"depth",
sc( sc(
@ -1850,7 +1877,9 @@ common_ssl_opts_schema(Defaults) ->
typerefl:alias("string", any()), typerefl:alias("string", any()),
#{ #{
default => <<"emqx_tls_psk:lookup">>, default => <<"emqx_tls_psk:lookup">>,
converter => fun ?MODULE:parse_user_lookup_fun/1 converter => fun ?MODULE:parse_user_lookup_fun/1,
desc =>
"EMQX-internal callback that is used to lookup pre-shared key (PSK) identity."
} }
)}, )},
{"secure_renegotiate", {"secure_renegotiate",
@ -1905,7 +1934,14 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
{"honor_cipher_order", {"honor_cipher_order",
sc( sc(
boolean(), boolean(),
#{default => Df("honor_cipher_order", true)} #{
default => Df("honor_cipher_order", true),
desc =>
"An important security setting, it forces the cipher to be set based\n"
" on the server-specified order instead of the client-specified order,\n"
" hence enforcing the (usually more properly configured) security\n"
" ordering of the server administrator."
}
)}, )},
{"client_renegotiation", {"client_renegotiation",
sc( sc(

View File

@ -608,7 +608,7 @@ fields("log") ->
[ {"console_handler", ref("console_handler")} [ {"console_handler", ref("console_handler")}
, {"file_handlers", , {"file_handlers",
sc(map(name, ref("log_file_handler")), sc(map(name, ref("log_file_handler")),
#{})} #{desc => "Key-value list of file-based log handlers."})}
, {"error_logger", , {"error_logger",
sc(atom(), sc(atom(),
#{mapping => "kernel.error_logger", #{mapping => "kernel.error_logger",

View File

@ -5,10 +5,10 @@
dashboard { dashboard {
default_username = "admin" default_username = "admin"
default_password = "public" default_password = "public"
## notice: sample_interval should be divisible by 60. ## Note: sample_interval should be a divisor of 60.
## like 1s, 2s, 3s, 5s, 10s, 12s, 15s, 20s, 30s, 60s ## like 1s, 2s, 3s, 5s, 10s, 12s, 15s, 20s, 30s, 60s
sample_interval = 10s sample_interval = 10s
## api jwt timeout. default is 30 minute ## JWT token expiration time.
token_expired_time = 60m token_expired_time = 60m
listeners = [ listeners = [
{ {

View File

@ -38,8 +38,15 @@ Alternatively, the HTTP listener can specify a unique IP address for each listen
but use the same port."})} but use the same port."})}
, {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, sc(emqx_schema:duration_s(), #{default => "10s"})} , {sample_interval, sc(emqx_schema:duration_s(),
, {token_expired_time, sc(emqx_schema:duration(), #{default => "30m"})} #{ default => "10s"
, desc => "How often to update metrics displayed in the dashboard.<br/>"
"Note: `sample_interval` should be a divisor of 60."
})}
, {token_expired_time, sc(emqx_schema:duration(),
#{ default => "30m"
, desc => "JWT token expiration time."
})}
, {cors, fun cors/1} , {cors, fun cors/1}
]; ];
@ -113,9 +120,9 @@ cors(type) -> boolean();
cors(default) -> false; cors(default) -> false;
cors(required) -> false; cors(required) -> false;
cors(desc) -> cors(desc) ->
"""Support Cross-Origin Resource Sharing (CORS). "Support Cross-Origin Resource Sharing (CORS).
Allows a server to indicate any origins (domain, scheme, or port) other than Allows a server to indicate any origins (domain, scheme, or port) other than
its own from which a browser should permit loading resources."""; its own from which a browser should permit loading resources.";
cors(_) -> undefined. cors(_) -> undefined.
sc(Type, Meta) -> hoconsc:mk(Type, Meta). sc(Type, Meta) -> hoconsc:mk(Type, Meta).

View File

@ -89,7 +89,10 @@ ref(Field) ->
failed_action() -> failed_action() ->
sc(hoconsc:enum([deny, ignore]), sc(hoconsc:enum([deny, ignore]),
#{default => deny}). #{ default => deny
, desc => "The value that is returned when the request "
"to the gRPC server fails for any reason."
}).
server_config() -> server_config() ->
fields(server). fields(server).

View File

@ -382,7 +382,7 @@ fields(udp_tcp_listeners) ->
fields(tcp_listener) -> fields(tcp_listener) ->
[ %% some special configs for tcp listener [ %% some special configs for tcp listener
{acceptors, sc(integer(), #{default => 16})} {acceptors, sc(integer(), #{default => 16, desc => "Size of the acceptor pool."})}
] ++ ] ++
tcp_opts() ++ tcp_opts() ++
proxy_protocol_opts() ++ proxy_protocol_opts() ++
@ -404,17 +404,21 @@ fields(udp_listener) ->
common_listener_opts(); common_listener_opts();
fields(dtls_listener) -> fields(dtls_listener) ->
[ {acceptors, sc(integer(), #{default => 16})} [ {acceptors, sc(integer(), #{default => 16, desc => "Size of the acceptor pool."})}
] ++ ] ++
fields(udp_listener) ++ fields(udp_listener) ++
[{dtls, sc(ref(dtls_opts), #{desc => "DTLS listener options"})}]; [{dtls, sc(ref(dtls_opts), #{desc => "DTLS listener options"})}];
fields(udp_opts) -> fields(udp_opts) ->
[ {active_n, sc(integer(), #{default => 100})} [ {active_n, sc(integer(),
, {recbuf, sc(bytesize())} #{ default => 100
, {sndbuf, sc(bytesize())} , desc => "Specify the {active, N} option for the socket.<br/>"
, {buffer, sc(bytesize())} "See: https://erlang.org/doc/man/inet.html#setopts-2"
, {reuseaddr, sc(boolean(), #{default => true})} })}
, {recbuf, sc(bytesize(), #{desc => "Size of the kernel-space receive buffer for the socket."})}
, {sndbuf, sc(bytesize(), #{desc => "Size of the kernel-space send buffer for the socket."})}
, {buffer, sc(bytesize(), #{desc => "Size of the user-space buffer for the socket."})}
, {reuseaddr, sc(boolean(), #{default => true, desc => "Allow local reuse of port numbers."})}
]; ];
fields(dtls_opts) -> fields(dtls_opts) ->
@ -429,9 +433,9 @@ authentication_schema() ->
sc(emqx_authn_schema:authenticator_type(), sc(emqx_authn_schema:authenticator_type(),
#{ required => {false, recursively} #{ required => {false, recursively}
, desc => , desc =>
"""Default authentication configs for all the gateway listeners.<br> "Default authentication configs for all the gateway listeners.<br>
For per-listener overrides see <code>authentication</code> For per-listener overrides see <code>authentication</code>
in listener configs""" in listener configs"
}). }).
gateway_common_options() -> gateway_common_options() ->
@ -528,10 +532,16 @@ proxy_protocol_opts() ->
[ {proxy_protocol, [ {proxy_protocol,
sc(boolean(), sc(boolean(),
#{ default => false #{ default => false
, desc => "Enable the Proxy Protocol V1/2 if the EMQX cluster is deployed "
"behind HAProxy or Nginx.<br/>"
"See: https://www.haproxy.com/blog/haproxy/proxy-protocol/"
})} })}
, {proxy_protocol_timeout, , {proxy_protocol_timeout,
sc(duration(), sc(duration(),
#{ default => "15s" #{ default => "15s"
, desc => "Timeout for proxy protocol.<br/>"
"EMQX will close the TCP connection if proxy protocol packet is not "
"received within the timeout."
})} })}
]. ].

View File

@ -32,7 +32,7 @@ fields("retainer") ->
]; ];
fields(mnesia_config) -> fields(mnesia_config) ->
[ {type, ?TYPE(hoconsc:union([built_in_database]))} [ {type, hoconsc:mk(hoconsc:union([built_in_database]), #{desc => "Backend type."})}
, {storage_type, sc(hoconsc:union([ram, disc]), , {storage_type, sc(hoconsc:union([ram, disc]),
"Specifies whether the messages are stored in RAM or persisted on disc.", "Specifies whether the messages are stored in RAM or persisted on disc.",
ram)} ram)}