feat: upgrade hocon to 0.25.0 to replace nullable with required.
This commit is contained in:
parent
334d315838
commit
db584f79d6
|
@ -19,7 +19,7 @@
|
||||||
, {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}}
|
, {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}}
|
||||||
, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.12.1"}}}
|
, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.12.1"}}}
|
||||||
, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.8.0"}}}
|
, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.8.0"}}}
|
||||||
, {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.24.0"}}}
|
, {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.25.0"}}}
|
||||||
, {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}}
|
, {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}}
|
||||||
, {recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}}
|
, {recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}}
|
||||||
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.18.0"}}}
|
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.18.0"}}}
|
||||||
|
|
|
@ -295,7 +295,7 @@ include_dirs() ->
|
||||||
[filename:join(emqx:data_dir(), "configs")].
|
[filename:join(emqx:data_dir(), "configs")].
|
||||||
|
|
||||||
merge_envs(SchemaMod, RawConf) ->
|
merge_envs(SchemaMod, RawConf) ->
|
||||||
Opts = #{nullable => true, %% TODO: evil, remove, nullable should be declared in schema
|
Opts = #{required => false, %% TODO: evil, remove, required should be declared in schema
|
||||||
format => map,
|
format => map,
|
||||||
apply_override_envs => true
|
apply_override_envs => true
|
||||||
},
|
},
|
||||||
|
@ -308,7 +308,7 @@ check_config(SchemaMod, RawConf) ->
|
||||||
|
|
||||||
check_config(SchemaMod, RawConf, Opts0) ->
|
check_config(SchemaMod, RawConf, Opts0) ->
|
||||||
Opts1 = #{return_plain => true,
|
Opts1 = #{return_plain => true,
|
||||||
nullable => true, %% TODO: evil, remove, nullable should be declared in schema
|
required => false, %% TODO: evil, remove, required should be declared in schema
|
||||||
format => map
|
format => map
|
||||||
},
|
},
|
||||||
Opts = maps:merge(Opts0, Opts1),
|
Opts = maps:merge(Opts0, Opts1),
|
||||||
|
@ -331,7 +331,7 @@ fill_defaults(RawConf) ->
|
||||||
-spec fill_defaults(module(), raw_config()) -> map().
|
-spec fill_defaults(module(), raw_config()) -> map().
|
||||||
fill_defaults(SchemaMod, RawConf) ->
|
fill_defaults(SchemaMod, RawConf) ->
|
||||||
hocon_tconf:check_plain(SchemaMod, RawConf,
|
hocon_tconf:check_plain(SchemaMod, RawConf,
|
||||||
#{nullable => true, only_fill_defaults => true},
|
#{required => false, only_fill_defaults => true},
|
||||||
root_names_from_conf(RawConf)).
|
root_names_from_conf(RawConf)).
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,9 @@ format_path([Name | Rest]) ->
|
||||||
-spec check(module(), hocon:config() | iodata()) ->
|
-spec check(module(), hocon:config() | iodata()) ->
|
||||||
{ok, hocon:config()} | {error, any()}.
|
{ok, hocon:config()} | {error, any()}.
|
||||||
check(SchemaModule, Conf) when is_map(Conf) ->
|
check(SchemaModule, Conf) when is_map(Conf) ->
|
||||||
%% TODO: remove nullable
|
%% TODO: remove required
|
||||||
%% fields should state nullable or not in their schema
|
%% fields should state required or not in their schema
|
||||||
Opts = #{atom_key => true, nullable => true},
|
Opts = #{atom_key => true, required => false},
|
||||||
try
|
try
|
||||||
{ok, hocon_tconf:check_plain(SchemaModule, Conf, Opts)}
|
{ok, hocon_tconf:check_plain(SchemaModule, Conf, Opts)}
|
||||||
catch
|
catch
|
||||||
|
|
|
@ -602,31 +602,31 @@ fields("listeners") ->
|
||||||
[ {"tcp",
|
[ {"tcp",
|
||||||
sc(map(name, ref("mqtt_tcp_listener")),
|
sc(map(name, ref("mqtt_tcp_listener")),
|
||||||
#{ desc => "TCP listeners"
|
#{ desc => "TCP listeners"
|
||||||
, nullable => {true, recursively}
|
, required => {false, recursively}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
, {"ssl",
|
, {"ssl",
|
||||||
sc(map(name, ref("mqtt_ssl_listener")),
|
sc(map(name, ref("mqtt_ssl_listener")),
|
||||||
#{ desc => "SSL listeners"
|
#{ desc => "SSL listeners"
|
||||||
, nullable => {true, recursively}
|
, required => {false, recursively}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
, {"ws",
|
, {"ws",
|
||||||
sc(map(name, ref("mqtt_ws_listener")),
|
sc(map(name, ref("mqtt_ws_listener")),
|
||||||
#{ desc => "HTTP websocket listeners"
|
#{ desc => "HTTP websocket listeners"
|
||||||
, nullable => {true, recursively}
|
, required => {false, recursively}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
, {"wss",
|
, {"wss",
|
||||||
sc(map(name, ref("mqtt_wss_listener")),
|
sc(map(name, ref("mqtt_wss_listener")),
|
||||||
#{ desc => "HTTPS websocket listeners"
|
#{ desc => "HTTPS websocket listeners"
|
||||||
, nullable => {true, recursively}
|
, required => {false, recursively}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
, {"quic",
|
, {"quic",
|
||||||
sc(map(name, ref("mqtt_quic_listener")),
|
sc(map(name, ref("mqtt_quic_listener")),
|
||||||
#{ desc => "QUIC listeners"
|
#{ desc => "QUIC listeners"
|
||||||
, nullable => {true, recursively}
|
, required => {false, recursively}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -1145,7 +1145,7 @@ mqtt_listener() ->
|
||||||
base_listener() ->
|
base_listener() ->
|
||||||
[ {"bind",
|
[ {"bind",
|
||||||
sc(hoconsc:union([ip_port(), integer()]),
|
sc(hoconsc:union([ip_port(), integer()]),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
})}
|
})}
|
||||||
, {"acceptors",
|
, {"acceptors",
|
||||||
sc(integer(),
|
sc(integer(),
|
||||||
|
@ -1204,7 +1204,7 @@ common_ssl_opts_schema(Defaults) ->
|
||||||
, {"cacertfile",
|
, {"cacertfile",
|
||||||
sc(string(),
|
sc(string(),
|
||||||
#{ default => D("cacertfile")
|
#{ default => D("cacertfile")
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
"""Trusted PEM format CA certificates bundle file.<br>
|
"""Trusted PEM format CA certificates bundle file.<br>
|
||||||
The certificates in this file are used to verify the TLS peer's certificates.
|
The certificates in this file are used to verify the TLS peer's certificates.
|
||||||
|
@ -1219,7 +1219,7 @@ already established connections.
|
||||||
, {"certfile",
|
, {"certfile",
|
||||||
sc(string(),
|
sc(string(),
|
||||||
#{ default => D("certfile")
|
#{ default => D("certfile")
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
"""PEM format certificates chain file.<br>
|
"""PEM format certificates chain file.<br>
|
||||||
The certificates in this file should be in reversed order of the certificate
|
The certificates in this file should be in reversed order of the certificate
|
||||||
|
@ -1233,7 +1233,7 @@ the file if it is to be added.
|
||||||
, {"keyfile",
|
, {"keyfile",
|
||||||
sc(string(),
|
sc(string(),
|
||||||
#{ default => D("keyfile")
|
#{ default => D("keyfile")
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
"""PEM format private key file.<br>
|
"""PEM format private key file.<br>
|
||||||
"""
|
"""
|
||||||
|
@ -1257,7 +1257,7 @@ the file if it is to be added.
|
||||||
, {"password",
|
, {"password",
|
||||||
sc(string(),
|
sc(string(),
|
||||||
#{ sensitive => true
|
#{ sensitive => true
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
"""String containing the user's password. Only used if the private
|
"""String containing the user's password. Only used if the private
|
||||||
key file is password-protected."""
|
key file is password-protected."""
|
||||||
|
@ -1305,7 +1305,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
|
||||||
[ {"dhfile",
|
[ {"dhfile",
|
||||||
sc(string(),
|
sc(string(),
|
||||||
#{ default => D("dhfile")
|
#{ default => D("dhfile")
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
"""Path to a file containing PEM-encoded Diffie Hellman parameters
|
"""Path to a file containing PEM-encoded Diffie Hellman parameters
|
||||||
to be used by the server if a cipher suite using Diffie Hellman
|
to be used by the server if a cipher suite using Diffie Hellman
|
||||||
|
@ -1361,7 +1361,7 @@ client_ssl_opts_schema(Defaults) ->
|
||||||
common_ssl_opts_schema(Defaults) ++
|
common_ssl_opts_schema(Defaults) ++
|
||||||
[ { "server_name_indication",
|
[ { "server_name_indication",
|
||||||
sc(hoconsc:union([disable, string()]),
|
sc(hoconsc:union([disable, string()]),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
"""Specify the host name to be used in TLS Server Name Indication extension.<br>
|
"""Specify the host name to be used in TLS Server Name Indication extension.<br>
|
||||||
For instance, when connecting to \"server.example.net\", the genuine server
|
For instance, when connecting to \"server.example.net\", the genuine server
|
||||||
|
|
|
@ -116,7 +116,7 @@ fields(request_user_create) ->
|
||||||
fields(request_user_update) ->
|
fields(request_user_update) ->
|
||||||
[
|
[
|
||||||
{password, binary()},
|
{password, binary()},
|
||||||
{is_superuser, mk(boolean(), #{default => false, nullable => true})}
|
{is_superuser, mk(boolean(), #{default => false, required => false})}
|
||||||
];
|
];
|
||||||
|
|
||||||
fields(request_move) ->
|
fields(request_move) ->
|
||||||
|
@ -128,7 +128,7 @@ fields(request_import_users) ->
|
||||||
fields(response_user) ->
|
fields(response_user) ->
|
||||||
[
|
[
|
||||||
{user_id, binary()},
|
{user_id, binary()},
|
||||||
{is_superuser, mk(boolean(), #{default => false, nullable => true})}
|
{is_superuser, mk(boolean(), #{default => false, required => false})}
|
||||||
];
|
];
|
||||||
|
|
||||||
fields(response_users) ->
|
fields(response_users) ->
|
||||||
|
@ -379,8 +379,8 @@ schema("/authentication/:id/users") ->
|
||||||
description => <<"List users in authenticator in global authentication chain">>,
|
description => <<"List users in authenticator in global authentication chain">>,
|
||||||
parameters => [
|
parameters => [
|
||||||
param_auth_id(),
|
param_auth_id(),
|
||||||
{page, mk(integer(), #{in => query, desc => <<"Page Index">>, nullable => true})},
|
{page, mk(integer(), #{in => query, desc => <<"Page Index">>, required => false})},
|
||||||
{limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})}
|
{limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, required => false})}
|
||||||
],
|
],
|
||||||
responses => #{
|
responses => #{
|
||||||
200 => emqx_dashboard_swagger:schema_with_example(
|
200 => emqx_dashboard_swagger:schema_with_example(
|
||||||
|
@ -415,8 +415,8 @@ schema("/listeners/:listener_id/authentication/:id/users") ->
|
||||||
description => <<"List users in authenticator in listener authentication chain">>,
|
description => <<"List users in authenticator in listener authentication chain">>,
|
||||||
parameters => [
|
parameters => [
|
||||||
param_listener_id(), param_auth_id(),
|
param_listener_id(), param_auth_id(),
|
||||||
{page, mk(integer(), #{in => query, desc => <<"Page Index">>, nullable => true})},
|
{page, mk(integer(), #{in => query, desc => <<"Page Index">>, required => false})},
|
||||||
{limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, nullable => true})}
|
{limit, mk(integer(), #{in => query, desc => <<"Page Limit">>, required => false})}
|
||||||
],
|
],
|
||||||
responses => #{
|
responses => #{
|
||||||
200 => emqx_dashboard_swagger:schema_with_example(
|
200 => emqx_dashboard_swagger:schema_with_example(
|
||||||
|
|
|
@ -81,8 +81,7 @@ salt_rounds(default) -> 10;
|
||||||
salt_rounds(_) -> undefined.
|
salt_rounds(_) -> undefined.
|
||||||
|
|
||||||
dk_length(type) -> integer();
|
dk_length(type) -> integer();
|
||||||
dk_length(nullable) -> true;
|
dk_length(required) -> false;
|
||||||
dk_length(default) -> undefined;
|
|
||||||
dk_length(_) -> undefined.
|
dk_length(_) -> undefined.
|
||||||
|
|
||||||
type_rw(type) ->
|
type_rw(type) ->
|
||||||
|
|
|
@ -54,8 +54,8 @@ root_type() ->
|
||||||
|
|
||||||
mechanism(Name) ->
|
mechanism(Name) ->
|
||||||
hoconsc:mk(hoconsc:enum([Name]),
|
hoconsc:mk(hoconsc:enum([Name]),
|
||||||
#{nullable => false}).
|
#{required => true}).
|
||||||
|
|
||||||
backend(Name) ->
|
backend(Name) ->
|
||||||
hoconsc:mk(hoconsc:enum([Name]),
|
hoconsc:mk(hoconsc:enum([Name]),
|
||||||
#{nullable => false}).
|
#{required => true}).
|
||||||
|
|
|
@ -77,7 +77,7 @@ validations() ->
|
||||||
|
|
||||||
url(type) -> binary();
|
url(type) -> binary();
|
||||||
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
||||||
url(nullable) -> false;
|
url(required) -> true;
|
||||||
url(_) -> undefined.
|
url(_) -> undefined.
|
||||||
|
|
||||||
headers(type) -> map();
|
headers(type) -> map();
|
||||||
|
|
|
@ -76,11 +76,11 @@ password_hash_field(type) -> binary();
|
||||||
password_hash_field(_) -> undefined.
|
password_hash_field(_) -> undefined.
|
||||||
|
|
||||||
salt_field(type) -> binary();
|
salt_field(type) -> binary();
|
||||||
salt_field(nullable) -> true;
|
salt_field(required) -> false;
|
||||||
salt_field(_) -> undefined.
|
salt_field(_) -> undefined.
|
||||||
|
|
||||||
is_superuser_field(type) -> binary();
|
is_superuser_field(type) -> binary();
|
||||||
is_superuser_field(nullable) -> true;
|
is_superuser_field(required) -> false;
|
||||||
is_superuser_field(_) -> undefined.
|
is_superuser_field(_) -> undefined.
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
|
@ -85,7 +85,7 @@ fields(position) ->
|
||||||
|
|
||||||
url(type) -> binary();
|
url(type) -> binary();
|
||||||
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
||||||
url(nullable) -> false;
|
url(required) -> true;
|
||||||
url(_) -> undefined.
|
url(_) -> undefined.
|
||||||
|
|
||||||
headers(type) -> map();
|
headers(type) -> map();
|
||||||
|
|
|
@ -145,7 +145,7 @@ fields(redis_cluster) ->
|
||||||
http_common_fields() ->
|
http_common_fields() ->
|
||||||
[ {url, fun url/1}
|
[ {url, fun url/1}
|
||||||
, {request_timeout, mk_duration("Request timeout", #{default => "30s"})}
|
, {request_timeout, mk_duration("Request timeout", #{default => "30s"})}
|
||||||
, {body, #{type => map(), nullable => true}}
|
, {body, #{type => map(), required => false}}
|
||||||
] ++ maps:to_list(maps:without([ base_url
|
] ++ maps:to_list(maps:without([ base_url
|
||||||
, pool_type],
|
, pool_type],
|
||||||
maps:from_list(connector_fields(http)))).
|
maps:from_list(connector_fields(http)))).
|
||||||
|
@ -181,7 +181,7 @@ headers_no_content_type(_) -> undefined.
|
||||||
|
|
||||||
url(type) -> binary();
|
url(type) -> binary();
|
||||||
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
||||||
url(nullable) -> false;
|
url(required) -> true;
|
||||||
url(_) -> undefined.
|
url(_) -> undefined.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
|
@ -13,7 +13,7 @@ roots() -> [].
|
||||||
fields("bridge") ->
|
fields("bridge") ->
|
||||||
basic_config() ++
|
basic_config() ++
|
||||||
[ {url, mk(binary(),
|
[ {url, mk(binary(),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, desc =>"""
|
, desc =>"""
|
||||||
The URL of the HTTP Bridge.<br>
|
The URL of the HTTP Bridge.<br>
|
||||||
Template with variables is allowed in the path, but variables cannot be used in the scheme, host,
|
Template with variables is allowed in the path, but variables cannot be used in the scheme, host,
|
||||||
|
|
|
@ -52,7 +52,7 @@ common_bridge_fields() ->
|
||||||
})}
|
})}
|
||||||
, {connector,
|
, {connector,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, example => <<"mqtt:my_mqtt_connector">>
|
, example => <<"mqtt:my_mqtt_connector">>
|
||||||
, desc =>"""
|
, desc =>"""
|
||||||
The connector ID to be used for this bridge. Connector IDs must be of format:
|
The connector ID to be used for this bridge. Connector IDs must be of format:
|
||||||
|
@ -75,7 +75,7 @@ metrics_status_fields() ->
|
||||||
|
|
||||||
direction_field(Dir, Desc) ->
|
direction_field(Dir, Desc) ->
|
||||||
{direction, mk(Dir,
|
{direction, mk(Dir,
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, default => egress
|
, default => egress
|
||||||
, desc => "The direction of the bridge. Can be one of 'ingress' or 'egress'.<br>"
|
, desc => "The direction of the bridge. Can be one of 'ingress' or 'egress'.<br>"
|
||||||
++ Desc
|
++ Desc
|
||||||
|
|
|
@ -162,7 +162,7 @@ check_cluster_rpc_result(Result) ->
|
||||||
%% Only gen hot_conf schema, not all configuration fields.
|
%% Only gen hot_conf schema, not all configuration fields.
|
||||||
gen_hot_conf_schema(File) ->
|
gen_hot_conf_schema(File) ->
|
||||||
{ApiSpec0, Components0} = emqx_dashboard_swagger:spec(emqx_mgmt_api_configs,
|
{ApiSpec0, Components0} = emqx_dashboard_swagger:spec(emqx_mgmt_api_configs,
|
||||||
#{schema_to_spec_func => fun hocon_schema_to_spec/2}),
|
#{schema_converter => fun hocon_schema_to_spec/2}),
|
||||||
ApiSpec = lists:foldl(fun({Path, Spec, _, _}, Acc) ->
|
ApiSpec = lists:foldl(fun({Path, Spec, _, _}, Acc) ->
|
||||||
NewSpec = maps:fold(fun(Method, #{responses := Responses}, SubAcc) ->
|
NewSpec = maps:fold(fun(Method, #{responses := Responses}, SubAcc) ->
|
||||||
case Responses of
|
case Responses of
|
||||||
|
@ -187,8 +187,6 @@ gen_hot_conf_schema(File) ->
|
||||||
-define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])).
|
-define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])).
|
||||||
-define(TO_COMPONENTS_SCHEMA(_M_, _F_), iolist_to_binary([<<"#/components/schemas/">>,
|
-define(TO_COMPONENTS_SCHEMA(_M_, _F_), iolist_to_binary([<<"#/components/schemas/">>,
|
||||||
?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_)])).
|
?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_)])).
|
||||||
-define(TO_COMPONENTS_PARAM(_M_, _F_), iolist_to_binary([<<"#/components/parameters/">>,
|
|
||||||
?TO_REF(emqx_dashboard_swagger:namespace(_M_), _F_)])).
|
|
||||||
|
|
||||||
hocon_schema_to_spec(?R_REF(Module, StructName), _LocalModule) ->
|
hocon_schema_to_spec(?R_REF(Module, StructName), _LocalModule) ->
|
||||||
{#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(Module, StructName)},
|
{#{<<"$ref">> => ?TO_COMPONENTS_SCHEMA(Module, StructName)},
|
||||||
|
@ -224,8 +222,8 @@ typename_to_spec("term()", _Mod) -> #{type => string};
|
||||||
typename_to_spec("boolean()", _Mod) -> #{type => boolean};
|
typename_to_spec("boolean()", _Mod) -> #{type => boolean};
|
||||||
typename_to_spec("binary()", _Mod) -> #{type => string};
|
typename_to_spec("binary()", _Mod) -> #{type => string};
|
||||||
typename_to_spec("float()", _Mod) -> #{type => number};
|
typename_to_spec("float()", _Mod) -> #{type => number};
|
||||||
typename_to_spec("integer()", _Mod) -> #{type => integer};
|
typename_to_spec("integer()", _Mod) -> #{type => number};
|
||||||
typename_to_spec("non_neg_integer()", _Mod) -> #{type => integer, minimum => 1};
|
typename_to_spec("non_neg_integer()", _Mod) -> #{type => number, minimum => 1};
|
||||||
typename_to_spec("number()", _Mod) -> #{type => number};
|
typename_to_spec("number()", _Mod) -> #{type => number};
|
||||||
typename_to_spec("string()", _Mod) -> #{type => string};
|
typename_to_spec("string()", _Mod) -> #{type => string};
|
||||||
typename_to_spec("atom()", _Mod) -> #{type => string};
|
typename_to_spec("atom()", _Mod) -> #{type => string};
|
||||||
|
@ -234,7 +232,7 @@ typename_to_spec("duration()", _Mod) -> #{type => duration};
|
||||||
typename_to_spec("duration_s()", _Mod) -> #{type => duration};
|
typename_to_spec("duration_s()", _Mod) -> #{type => duration};
|
||||||
typename_to_spec("duration_ms()", _Mod) -> #{type => duration};
|
typename_to_spec("duration_ms()", _Mod) -> #{type => duration};
|
||||||
typename_to_spec("percent()", _Mod) -> #{type => percent};
|
typename_to_spec("percent()", _Mod) -> #{type => percent};
|
||||||
typename_to_spec("file()", _Mod) -> #{type => file};
|
typename_to_spec("file()", _Mod) -> #{type => string};
|
||||||
typename_to_spec("ip_port()", _Mod) -> #{type => ip_port};
|
typename_to_spec("ip_port()", _Mod) -> #{type => ip_port};
|
||||||
typename_to_spec("url()", _Mod) -> #{type => url};
|
typename_to_spec("url()", _Mod) -> #{type => url};
|
||||||
typename_to_spec("bytesize()", _Mod) -> #{type => byteSize};
|
typename_to_spec("bytesize()", _Mod) -> #{type => byteSize};
|
||||||
|
@ -263,7 +261,7 @@ default_type(Type) -> Type.
|
||||||
range(Name) ->
|
range(Name) ->
|
||||||
case string:split(Name, "..") of
|
case string:split(Name, "..") of
|
||||||
[MinStr, MaxStr] -> %% 1..10 1..inf -inf..10
|
[MinStr, MaxStr] -> %% 1..10 1..inf -inf..10
|
||||||
Schema = #{type => integer},
|
Schema = #{type => number},
|
||||||
Schema1 = add_integer_prop(Schema, minimum, MinStr),
|
Schema1 = add_integer_prop(Schema, minimum, MinStr),
|
||||||
add_integer_prop(Schema1, maximum, MaxStr);
|
add_integer_prop(Schema1, maximum, MaxStr);
|
||||||
_ -> nomatch
|
_ -> nomatch
|
||||||
|
|
|
@ -262,7 +262,7 @@ fields("node") ->
|
||||||
})}
|
})}
|
||||||
, {"data_dir",
|
, {"data_dir",
|
||||||
sc(string(),
|
sc(string(),
|
||||||
#{ nullable => false,
|
#{ required => true,
|
||||||
mapping => "emqx.data_dir",
|
mapping => "emqx.data_dir",
|
||||||
desc => "Path to the persistent data directory. It must be unique per broker instance."
|
desc => "Path to the persistent data directory. It must be unique per broker instance."
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -61,7 +61,7 @@ roots() ->
|
||||||
fields(config) ->
|
fields(config) ->
|
||||||
[ {base_url,
|
[ {base_url,
|
||||||
sc(url(),
|
sc(url(),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, validator => fun(#{query := _Query}) ->
|
, validator => fun(#{query := _Query}) ->
|
||||||
{error, "There must be no query in the base_url"};
|
{error, "There must be no query in the base_url"};
|
||||||
(_) -> ok
|
(_) -> ok
|
||||||
|
@ -106,7 +106,7 @@ For example: http://localhost:9901/
|
||||||
, {request, hoconsc:mk(
|
, {request, hoconsc:mk(
|
||||||
ref("request"),
|
ref("request"),
|
||||||
#{ default => undefined
|
#{ default => undefined
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => """
|
, desc => """
|
||||||
If the request is provided, the caller can send HTTP requests via
|
If the request is provided, the caller can send HTTP requests via
|
||||||
<code>emqx_resource:query(ResourceId, {send_message, BridgeId, Message})</code>
|
<code>emqx_resource:query(ResourceId, {send_message, BridgeId, Message})</code>
|
||||||
|
@ -115,13 +115,13 @@ If the request is provided, the caller can send HTTP requests via
|
||||||
] ++ emqx_connector_schema_lib:ssl_fields();
|
] ++ emqx_connector_schema_lib:ssl_fields();
|
||||||
|
|
||||||
fields("request") ->
|
fields("request") ->
|
||||||
[ {method, hoconsc:mk(hoconsc:enum([post, put, get, delete]), #{nullable => true})}
|
[ {method, hoconsc:mk(hoconsc:enum([post, put, get, delete]), #{required => false})}
|
||||||
, {path, hoconsc:mk(binary(), #{nullable => true})}
|
, {path, hoconsc:mk(binary(), #{required => false})}
|
||||||
, {body, hoconsc:mk(binary(), #{nullable => true})}
|
, {body, hoconsc:mk(binary(), #{required => false})}
|
||||||
, {headers, hoconsc:mk(map(), #{nullable => true})}
|
, {headers, hoconsc:mk(map(), #{required => false})}
|
||||||
, {request_timeout,
|
, {request_timeout,
|
||||||
sc(emqx_schema:duration_ms(),
|
sc(emqx_schema:duration_ms(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => "The timeout when sending request to the HTTP server"
|
, desc => "The timeout when sending request to the HTTP server"
|
||||||
})}
|
})}
|
||||||
].
|
].
|
||||||
|
|
|
@ -91,11 +91,9 @@ mongo_fields() ->
|
||||||
, {pool_size, fun emqx_connector_schema_lib:pool_size/1}
|
, {pool_size, fun emqx_connector_schema_lib:pool_size/1}
|
||||||
, {username, fun emqx_connector_schema_lib:username/1}
|
, {username, fun emqx_connector_schema_lib:username/1}
|
||||||
, {password, fun emqx_connector_schema_lib:password/1}
|
, {password, fun emqx_connector_schema_lib:password/1}
|
||||||
, {auth_source, #{type => binary(),
|
, {auth_source, #{type => binary(), required => false}}
|
||||||
nullable => true}}
|
|
||||||
, {database, fun emqx_connector_schema_lib:database/1}
|
, {database, fun emqx_connector_schema_lib:database/1}
|
||||||
, {topology, #{type => hoconsc:ref(?MODULE, topology),
|
, {topology, #{type => hoconsc:ref(?MODULE, topology), required => false}}
|
||||||
nullable => true}}
|
|
||||||
] ++
|
] ++
|
||||||
emqx_connector_schema_lib:ssl_fields().
|
emqx_connector_schema_lib:ssl_fields().
|
||||||
|
|
||||||
|
@ -289,14 +287,14 @@ init_worker_options([], Acc) -> Acc.
|
||||||
%% Schema funcs
|
%% Schema funcs
|
||||||
|
|
||||||
server(type) -> emqx_schema:ip_port();
|
server(type) -> emqx_schema:ip_port();
|
||||||
server(nullable) -> false;
|
server(required) -> true;
|
||||||
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
||||||
server(converter) -> fun to_server_raw/1;
|
server(converter) -> fun to_server_raw/1;
|
||||||
server(desc) -> ?SERVER_DESC("MongoDB", integer_to_list(?MONGO_DEFAULT_PORT));
|
server(desc) -> ?SERVER_DESC("MongoDB", integer_to_list(?MONGO_DEFAULT_PORT));
|
||||||
server(_) -> undefined.
|
server(_) -> undefined.
|
||||||
|
|
||||||
servers(type) -> binary();
|
servers(type) -> binary();
|
||||||
servers(nullable) -> false;
|
servers(required) -> true;
|
||||||
servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")];
|
servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")];
|
||||||
servers(converter) -> fun to_servers_raw/1;
|
servers(converter) -> fun to_servers_raw/1;
|
||||||
servers(desc) -> ?SERVERS_DESC ++ server(desc);
|
servers(desc) -> ?SERVERS_DESC ++ server(desc);
|
||||||
|
@ -311,11 +309,11 @@ r_mode(default) -> master;
|
||||||
r_mode(_) -> undefined.
|
r_mode(_) -> undefined.
|
||||||
|
|
||||||
duration(type) -> emqx_schema:duration_ms();
|
duration(type) -> emqx_schema:duration_ms();
|
||||||
duration(nullable) -> true;
|
duration(required) -> false;
|
||||||
duration(_) -> undefined.
|
duration(_) -> undefined.
|
||||||
|
|
||||||
replica_set_name(type) -> binary();
|
replica_set_name(type) -> binary();
|
||||||
replica_set_name(nullable) -> true;
|
replica_set_name(required) -> false;
|
||||||
replica_set_name(_) -> undefined.
|
replica_set_name(_) -> undefined.
|
||||||
|
|
||||||
srv_record(type) -> boolean();
|
srv_record(type) -> boolean();
|
||||||
|
|
|
@ -50,7 +50,7 @@ fields(config) ->
|
||||||
emqx_connector_schema_lib:ssl_fields().
|
emqx_connector_schema_lib:ssl_fields().
|
||||||
|
|
||||||
server(type) -> emqx_schema:ip_port();
|
server(type) -> emqx_schema:ip_port();
|
||||||
server(nullable) -> false;
|
server(required) -> true;
|
||||||
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
||||||
server(converter) -> fun to_server/1;
|
server(converter) -> fun to_server/1;
|
||||||
server(desc) -> ?SERVER_DESC("MySQL", integer_to_list(?MYSQL_DEFAULT_PORT));
|
server(desc) -> ?SERVER_DESC("MySQL", integer_to_list(?MYSQL_DEFAULT_PORT));
|
||||||
|
|
|
@ -56,11 +56,11 @@ fields(config) ->
|
||||||
emqx_connector_schema_lib:ssl_fields().
|
emqx_connector_schema_lib:ssl_fields().
|
||||||
|
|
||||||
named_queries(type) -> map();
|
named_queries(type) -> map();
|
||||||
named_queries(nullable) -> true;
|
named_queries(required) -> false;
|
||||||
named_queries(_) -> undefined.
|
named_queries(_) -> undefined.
|
||||||
|
|
||||||
server(type) -> emqx_schema:ip_port();
|
server(type) -> emqx_schema:ip_port();
|
||||||
server(nullable) -> false;
|
server(required) -> true;
|
||||||
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
||||||
server(converter) -> fun to_server/1;
|
server(converter) -> fun to_server/1;
|
||||||
server(desc) -> ?SERVER_DESC("PostgreSQL", integer_to_list(?PGSQL_DEFAULT_PORT));
|
server(desc) -> ?SERVER_DESC("PostgreSQL", integer_to_list(?PGSQL_DEFAULT_PORT));
|
||||||
|
|
|
@ -76,14 +76,14 @@ fields(sentinel) ->
|
||||||
emqx_connector_schema_lib:ssl_fields().
|
emqx_connector_schema_lib:ssl_fields().
|
||||||
|
|
||||||
server(type) -> emqx_schema:ip_port();
|
server(type) -> emqx_schema:ip_port();
|
||||||
server(nullable) -> false;
|
server(required) -> true;
|
||||||
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
server(validator) -> [?NOT_EMPTY("the value of the field 'server' cannot be empty")];
|
||||||
server(converter) -> fun to_server_raw/1;
|
server(converter) -> fun to_server_raw/1;
|
||||||
server(desc) -> ?SERVER_DESC("Redis", integer_to_list(?REDIS_DEFAULT_PORT));
|
server(desc) -> ?SERVER_DESC("Redis", integer_to_list(?REDIS_DEFAULT_PORT));
|
||||||
server(_) -> undefined.
|
server(_) -> undefined.
|
||||||
|
|
||||||
servers(type) -> list();
|
servers(type) -> list();
|
||||||
servers(nullable) -> false;
|
servers(required) -> true;
|
||||||
servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")];
|
servers(validator) -> [?NOT_EMPTY("the value of the field 'servers' cannot be empty")];
|
||||||
servers(converter) -> fun to_servers_raw/1;
|
servers(converter) -> fun to_servers_raw/1;
|
||||||
servers(desc) -> ?SERVERS_DESC ++ server(desc);
|
servers(desc) -> ?SERVERS_DESC ++ server(desc);
|
||||||
|
|
|
@ -66,7 +66,7 @@ relational_db_fields() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
database(type) -> binary();
|
database(type) -> binary();
|
||||||
database(nullable) -> false;
|
database(required) -> true;
|
||||||
database(validator) -> [?NOT_EMPTY("the value of the field 'database' cannot be empty")];
|
database(validator) -> [?NOT_EMPTY("the value of the field 'database' cannot be empty")];
|
||||||
database(_) -> undefined.
|
database(_) -> undefined.
|
||||||
|
|
||||||
|
@ -76,11 +76,11 @@ pool_size(validator) -> [?MIN(1)];
|
||||||
pool_size(_) -> undefined.
|
pool_size(_) -> undefined.
|
||||||
|
|
||||||
username(type) -> binary();
|
username(type) -> binary();
|
||||||
username(nullable) -> true;
|
username(required) -> false;
|
||||||
username(_) -> undefined.
|
username(_) -> undefined.
|
||||||
|
|
||||||
password(type) -> binary();
|
password(type) -> binary();
|
||||||
password(nullable) -> true;
|
password(required) -> false;
|
||||||
password(_) -> undefined.
|
password(_) -> undefined.
|
||||||
|
|
||||||
auto_reconnect(type) -> boolean();
|
auto_reconnect(type) -> boolean();
|
||||||
|
|
|
@ -57,7 +57,7 @@ topic filters for 'remote_topic' of ingress connections.
|
||||||
})}
|
})}
|
||||||
, {name,
|
, {name,
|
||||||
sc(binary(),
|
sc(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => "Connector name, used as a human-readable description of the connector."
|
, desc => "Connector name, used as a human-readable description of the connector."
|
||||||
})}
|
})}
|
||||||
, {server,
|
, {server,
|
||||||
|
@ -105,7 +105,7 @@ fields("ingress") ->
|
||||||
%% the message maybe subscribed by rules, in this case 'local_topic' is not necessary
|
%% the message maybe subscribed by rules, in this case 'local_topic' is not necessary
|
||||||
[ {remote_topic,
|
[ {remote_topic,
|
||||||
sc(binary(),
|
sc(binary(),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, desc => "Receive messages from which topic of the remote broker"
|
, desc => "Receive messages from which topic of the remote broker"
|
||||||
})}
|
})}
|
||||||
, {remote_qos,
|
, {remote_qos,
|
||||||
|
|
|
@ -29,8 +29,8 @@ check_fields({FieldName, FieldValue}) ->
|
||||||
if
|
if
|
||||||
is_map(FieldValue) ->
|
is_map(FieldValue) ->
|
||||||
?assert(
|
?assert(
|
||||||
maps:is_key(type, FieldValue) and maps:is_key(default, FieldValue) or
|
(maps:is_key(type, FieldValue) andalso maps:is_key(default, FieldValue)) orelse
|
||||||
(maps:is_key(nullable, FieldValue) and maps:get(nullable, FieldValue, false) =:= true)
|
((maps:is_key(required, FieldValue) andalso maps:get(required, FieldValue)))
|
||||||
);
|
);
|
||||||
true ->
|
true ->
|
||||||
?assert(is_function(FieldValue))
|
?assert(is_function(FieldValue))
|
||||||
|
|
|
@ -48,7 +48,7 @@ fields("http") ->
|
||||||
[ {"protocol", sc(
|
[ {"protocol", sc(
|
||||||
hoconsc:enum([http, https]),
|
hoconsc:enum([http, https]),
|
||||||
#{ desc => "HTTP/HTTPS protocol."
|
#{ desc => "HTTP/HTTPS protocol."
|
||||||
, nullable => false
|
, required => true
|
||||||
, default => http})}
|
, default => http})}
|
||||||
, {"bind", fun bind/1}
|
, {"bind", fun bind/1}
|
||||||
, {"num_acceptors", sc(
|
, {"num_acceptors", sc(
|
||||||
|
@ -74,18 +74,18 @@ fields("https") ->
|
||||||
|
|
||||||
bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]);
|
bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]);
|
||||||
bind(default) -> 18083;
|
bind(default) -> 18083;
|
||||||
bind(nullable) -> false;
|
bind(required) -> true;
|
||||||
bind(desc) -> "Port without IP(18083) or port with specified IP(127.0.0.1:18083).";
|
bind(desc) -> "Port without IP(18083) or port with specified IP(127.0.0.1:18083).";
|
||||||
bind(_) -> undefined.
|
bind(_) -> undefined.
|
||||||
|
|
||||||
default_username(type) -> string();
|
default_username(type) -> string();
|
||||||
default_username(default) -> "admin";
|
default_username(default) -> "admin";
|
||||||
default_username(nullable) -> false;
|
default_username(required) -> true;
|
||||||
default_username(_) -> undefined.
|
default_username(_) -> undefined.
|
||||||
|
|
||||||
default_password(type) -> string();
|
default_password(type) -> string();
|
||||||
default_password(default) -> "public";
|
default_password(default) -> "public";
|
||||||
default_password(nullable) -> false;
|
default_password(required) -> true;
|
||||||
default_password(sensitive) -> true;
|
default_password(sensitive) -> true;
|
||||||
default_password(desc) -> """
|
default_password(desc) -> """
|
||||||
The initial default password for dashboard 'admin' user.
|
The initial default password for dashboard 'admin' user.
|
||||||
|
@ -94,7 +94,7 @@ default_password(_) -> undefined.
|
||||||
|
|
||||||
cors(type) -> boolean();
|
cors(type) -> boolean();
|
||||||
cors(default) -> false;
|
cors(default) -> false;
|
||||||
cors(nullable) -> true;
|
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
|
||||||
|
|
|
@ -56,7 +56,10 @@
|
||||||
-type(filter_result() :: {ok, request()} | {400, 'BAD_REQUEST', binary()}).
|
-type(filter_result() :: {ok, request()} | {400, 'BAD_REQUEST', binary()}).
|
||||||
-type(filter() :: fun((request(), request_meta()) -> filter_result())).
|
-type(filter() :: fun((request(), request_meta()) -> filter_result())).
|
||||||
|
|
||||||
-type(spec_opts() :: #{check_schema => boolean() | filter(), translate_body => boolean()}).
|
-type(spec_opts() :: #{check_schema => boolean() | filter(),
|
||||||
|
translate_body => boolean(),
|
||||||
|
schema_converter => fun((hocon_schema:schema(), Module::atom()) -> map())
|
||||||
|
}).
|
||||||
|
|
||||||
-type(route_path() :: string() | binary()).
|
-type(route_path() :: string() | binary()).
|
||||||
-type(route_methods() :: map()).
|
-type(route_methods() :: map()).
|
||||||
|
@ -217,7 +220,7 @@ check_request_body(#{body := Body}, Schema, Module, CheckFun, true) ->
|
||||||
_ -> Type0
|
_ -> Type0
|
||||||
end,
|
end,
|
||||||
NewSchema = ?INIT_SCHEMA#{roots => [{root, Type}]},
|
NewSchema = ?INIT_SCHEMA#{roots => [{root, Type}]},
|
||||||
Option = #{nullable => true},
|
Option = #{required => false},
|
||||||
#{<<"root">> := NewBody} = CheckFun(NewSchema, #{<<"root">> => Body}, Option),
|
#{<<"root">> := NewBody} = CheckFun(NewSchema, #{<<"root">> => Body}, Option),
|
||||||
NewBody;
|
NewBody;
|
||||||
%% TODO not support nest object check yet, please use ref!
|
%% TODO not support nest object check yet, please use ref!
|
||||||
|
@ -265,30 +268,22 @@ parameters(Params, Module) ->
|
||||||
In = hocon_schema:field_schema(Type, in),
|
In = hocon_schema:field_schema(Type, in),
|
||||||
In =:= undefined andalso
|
In =:= undefined andalso
|
||||||
throw({error, <<"missing in:path/query field in parameters">>}),
|
throw({error, <<"missing in:path/query field in parameters">>}),
|
||||||
Nullable = hocon_schema:field_schema(Type, nullable),
|
Required = hocon_schema:field_schema(Type, required),
|
||||||
Default = hocon_schema:field_schema(Type, default),
|
Default = hocon_schema:field_schema(Type, default),
|
||||||
HoconType = hocon_schema:field_schema(Type, type),
|
HoconType = hocon_schema:field_schema(Type, type),
|
||||||
Meta = init_meta(Nullable, Default),
|
Meta = init_meta(Default),
|
||||||
{ParamType, Refs} = hocon_schema_to_spec(HoconType, Module),
|
{ParamType, Refs} = hocon_schema_to_spec(HoconType, Module),
|
||||||
Spec0 = init_prop([required | ?DEFAULT_FIELDS],
|
Spec0 = init_prop([required | ?DEFAULT_FIELDS],
|
||||||
#{schema => maps:merge(ParamType, Meta), name => Name, in => In}, Type),
|
#{schema => maps:merge(ParamType, Meta), name => Name, in => In}, Type),
|
||||||
Spec1 = trans_required(Spec0, Nullable, In),
|
Spec1 = trans_required(Spec0, Required, In),
|
||||||
Spec2 = trans_desc(Spec1, Type),
|
Spec2 = trans_desc(Spec1, Type),
|
||||||
{[Spec2 | Acc], Refs ++ RefsAcc}
|
{[Spec2 | Acc], Refs ++ RefsAcc}
|
||||||
end
|
end
|
||||||
end, {[], []}, Params),
|
end, {[], []}, Params),
|
||||||
{lists:reverse(SpecList), AllRefs}.
|
{lists:reverse(SpecList), AllRefs}.
|
||||||
|
|
||||||
init_meta(Nullable, Default) ->
|
init_meta(undefined) -> #{};
|
||||||
Init =
|
init_meta(Default) -> #{default => Default}.
|
||||||
case Nullable of
|
|
||||||
true -> #{nullable => true};
|
|
||||||
_ -> #{}
|
|
||||||
end,
|
|
||||||
case Default =:= undefined of
|
|
||||||
true -> Init;
|
|
||||||
false -> Init#{default => Default}
|
|
||||||
end.
|
|
||||||
|
|
||||||
init_prop(Keys, Init, Type) ->
|
init_prop(Keys, Init, Type) ->
|
||||||
lists:foldl(fun(Key, Acc) ->
|
lists:foldl(fun(Key, Acc) ->
|
||||||
|
@ -298,7 +293,7 @@ init_prop(Keys, Init, Type) ->
|
||||||
end
|
end
|
||||||
end, Init, Keys).
|
end, Init, Keys).
|
||||||
|
|
||||||
trans_required(Spec, false, _) -> Spec#{required => true};
|
trans_required(Spec, true, _) -> Spec#{required => true};
|
||||||
trans_required(Spec, _, path) -> Spec#{required => true};
|
trans_required(Spec, _, path) -> Spec#{required => true};
|
||||||
trans_required(Spec, _, _) -> Spec.
|
trans_required(Spec, _, _) -> Spec.
|
||||||
|
|
||||||
|
@ -335,7 +330,7 @@ response(Status, #{content := _} = Content, {Acc, RefsAcc, Module, Options}) ->
|
||||||
response(Status, ?REF(StructName), {Acc, RefsAcc, Module, Options}) ->
|
response(Status, ?REF(StructName), {Acc, RefsAcc, Module, Options}) ->
|
||||||
response(Status, ?R_REF(Module, StructName), {Acc, RefsAcc, Module, Options});
|
response(Status, ?R_REF(Module, StructName), {Acc, RefsAcc, Module, Options});
|
||||||
response(Status, ?R_REF(_Mod, _Name) = RRef, {Acc, RefsAcc, Module, Options}) ->
|
response(Status, ?R_REF(_Mod, _Name) = RRef, {Acc, RefsAcc, Module, Options}) ->
|
||||||
SchemaToSpec = schema_to_spec_func(Options),
|
SchemaToSpec = schema_converter(Options),
|
||||||
{Spec, Refs} = SchemaToSpec(RRef, Module),
|
{Spec, Refs} = SchemaToSpec(RRef, Module),
|
||||||
Content = content(Spec),
|
Content = content(Spec),
|
||||||
{Acc#{integer_to_binary(Status) => #{<<"content">> => Content}}, Refs ++ RefsAcc, Module, Options};
|
{Acc#{integer_to_binary(Status) => #{<<"content">> => Content}}, Refs ++ RefsAcc, Module, Options};
|
||||||
|
@ -557,7 +552,7 @@ parse_object(PropList = [_ | _], Module, Options) when is_list(PropList) ->
|
||||||
HoconType = hocon_schema:field_schema(Hocon, type),
|
HoconType = hocon_schema:field_schema(Hocon, type),
|
||||||
Init0 = init_prop([default | ?DEFAULT_FIELDS], #{}, Hocon),
|
Init0 = init_prop([default | ?DEFAULT_FIELDS], #{}, Hocon),
|
||||||
Init = trans_desc(Init0, Hocon),
|
Init = trans_desc(Init0, Hocon),
|
||||||
SchemaToSpec = schema_to_spec_func(Options),
|
SchemaToSpec = schema_converter(Options),
|
||||||
{Prop, Refs1} = SchemaToSpec(HoconType, Module),
|
{Prop, Refs1} = SchemaToSpec(HoconType, Module),
|
||||||
NewRequiredAcc =
|
NewRequiredAcc =
|
||||||
case is_required(Hocon) of
|
case is_required(Hocon) of
|
||||||
|
@ -581,8 +576,7 @@ parse_object(Other, Module, Options) ->
|
||||||
args => Other, module => Module, options => Options}}).
|
args => Other, module => Module, options => Options}}).
|
||||||
|
|
||||||
is_required(Hocon) ->
|
is_required(Hocon) ->
|
||||||
hocon_schema:field_schema(Hocon, required) =:= true orelse
|
hocon_schema:field_schema(Hocon, required) =:= true.
|
||||||
hocon_schema:field_schema(Hocon, nullable) =:= false.
|
|
||||||
|
|
||||||
content(ApiSpec) ->
|
content(ApiSpec) ->
|
||||||
content(ApiSpec, undefined).
|
content(ApiSpec, undefined).
|
||||||
|
@ -596,5 +590,5 @@ to_ref(Mod, StructName, Acc, RefsAcc) ->
|
||||||
Ref = #{<<"$ref">> => ?TO_COMPONENTS_PARAM(Mod, StructName)},
|
Ref = #{<<"$ref">> => ?TO_COMPONENTS_PARAM(Mod, StructName)},
|
||||||
{[Ref | Acc], [{Mod, StructName, parameter} | RefsAcc]}.
|
{[Ref | Acc], [{Mod, StructName, parameter} | RefsAcc]}.
|
||||||
|
|
||||||
schema_to_spec_func(Options) ->
|
schema_converter(Options) ->
|
||||||
maps:get(schema_to_spec_func, Options, fun hocon_schema_to_spec/2).
|
maps:get(schema_converter, Options, fun hocon_schema_to_spec/2).
|
||||||
|
|
|
@ -124,8 +124,7 @@ t_nullable(_Config) ->
|
||||||
NullableFalse = [#{in => query,name => userid, required => true,
|
NullableFalse = [#{in => query,name => userid, required => true,
|
||||||
schema => #{example => <<"binary-example">>, type => string}}],
|
schema => #{example => <<"binary-example">>, type => string}}],
|
||||||
NullableTrue = [#{in => query,name => userid,
|
NullableTrue = [#{in => query,name => userid,
|
||||||
schema => #{example => <<"binary-example">>, type => string,
|
schema => #{example => <<"binary-example">>, type => string}, required => false}],
|
||||||
nullable => true}}],
|
|
||||||
validate("/nullable/false", NullableFalse),
|
validate("/nullable/false", NullableFalse),
|
||||||
validate("/nullable/true", NullableTrue),
|
validate("/nullable/true", NullableTrue),
|
||||||
ok.
|
ok.
|
||||||
|
@ -358,9 +357,9 @@ schema("/test/without/in") ->
|
||||||
schema("/required/false") ->
|
schema("/required/false") ->
|
||||||
to_schema([{'userid', mk(binary(), #{in => query, required => false})}]);
|
to_schema([{'userid', mk(binary(), #{in => query, required => false})}]);
|
||||||
schema("/nullable/false") ->
|
schema("/nullable/false") ->
|
||||||
to_schema([{'userid', mk(binary(), #{in => query, nullable => false})}]);
|
to_schema([{'userid', mk(binary(), #{in => query, required => true})}]);
|
||||||
schema("/nullable/true") ->
|
schema("/nullable/true") ->
|
||||||
to_schema([{'userid', mk(binary(), #{in => query, nullable => true})}]);
|
to_schema([{'userid', mk(binary(), #{in => query, required => false})}]);
|
||||||
schema("/method/ok") ->
|
schema("/method/ok") ->
|
||||||
Response = #{responses => #{200 => <<"ok">>}},
|
Response = #{responses => #{200 => <<"ok">>}},
|
||||||
lists:foldl(fun(Method, Acc) -> Acc#{Method => Response} end,
|
lists:foldl(fun(Method, Acc) -> Acc#{Method => Response} end,
|
||||||
|
|
|
@ -50,10 +50,10 @@ fields("ref3") ->
|
||||||
|
|
||||||
default_username(type) -> string();
|
default_username(type) -> string();
|
||||||
default_username(default) -> "admin";
|
default_username(default) -> "admin";
|
||||||
default_username(nullable) -> false;
|
default_username(required) -> true;
|
||||||
default_username(_) -> undefined.
|
default_username(_) -> undefined.
|
||||||
|
|
||||||
default_password(type) -> string();
|
default_password(type) -> string();
|
||||||
default_password(default) -> "public";
|
default_password(default) -> "public";
|
||||||
default_password(nullable) -> false;
|
default_password(required) -> true;
|
||||||
default_password(_) -> undefined.
|
default_password(_) -> undefined.
|
||||||
|
|
|
@ -499,16 +499,16 @@ paths() ->
|
||||||
|
|
||||||
schema("/object") ->
|
schema("/object") ->
|
||||||
to_schema([
|
to_schema([
|
||||||
{per_page, mk(range(1, 100), #{nullable => false, desc => <<"good per page desc">>})},
|
{per_page, mk(range(1, 100), #{required => true, desc => <<"good per page desc">>})},
|
||||||
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
||||||
#{default => 5, nullable => false})},
|
#{default => 5, required => true})},
|
||||||
{inner_ref, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
{inner_ref, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
||||||
]);
|
]);
|
||||||
schema("/nest/object") ->
|
schema("/nest/object") ->
|
||||||
to_schema([
|
to_schema([
|
||||||
{per_page, mk(range(1, 100), #{desc => <<"good per page desc">>})},
|
{per_page, mk(range(1, 100), #{desc => <<"good per page desc">>})},
|
||||||
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
||||||
#{default => 5, nullable => false})},
|
#{default => 5, required => true})},
|
||||||
{nest_object, [
|
{nest_object, [
|
||||||
{good_nest_1, mk(integer(), #{})},
|
{good_nest_1, mk(integer(), #{})},
|
||||||
{good_nest_2, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
{good_nest_2, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
||||||
|
@ -572,5 +572,5 @@ enable(_) -> undefined.
|
||||||
|
|
||||||
init_file(type) -> binary();
|
init_file(type) -> binary();
|
||||||
init_file(desc) -> <<"test test desc">>;
|
init_file(desc) -> <<"test test desc">>;
|
||||||
init_file(nullable) -> true;
|
init_file(required) -> false;
|
||||||
init_file(_) -> undefined.
|
init_file(_) -> undefined.
|
||||||
|
|
|
@ -299,9 +299,9 @@ schema("/simple/bin") ->
|
||||||
to_schema(<<"binary ok">>);
|
to_schema(<<"binary ok">>);
|
||||||
schema("/object") ->
|
schema("/object") ->
|
||||||
Object = [
|
Object = [
|
||||||
{per_page, mk(range(1, 100), #{nullable => false, desc => <<"good per page desc">>})},
|
{per_page, mk(range(1, 100), #{required => true, desc => <<"good per page desc">>})},
|
||||||
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
||||||
#{default => 5, nullable => false})},
|
#{default => 5, required => true})},
|
||||||
{inner_ref, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
{inner_ref, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
||||||
],
|
],
|
||||||
to_schema(Object);
|
to_schema(Object);
|
||||||
|
@ -309,7 +309,7 @@ schema("/nest/object") ->
|
||||||
Response = [
|
Response = [
|
||||||
{per_page, mk(range(1, 100), #{desc => <<"good per page desc">>})},
|
{per_page, mk(range(1, 100), #{desc => <<"good per page desc">>})},
|
||||||
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
{timeout, mk(hoconsc:union([infinity, emqx_schema:duration_s()]),
|
||||||
#{default => 5, nullable => false})},
|
#{default => 5, required => true})},
|
||||||
{nest_object, [
|
{nest_object, [
|
||||||
{good_nest_1, mk(integer(), #{})},
|
{good_nest_1, mk(integer(), #{})},
|
||||||
{good_nest_2, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
{good_nest_2, mk(hoconsc:ref(?MODULE, good_ref), #{})}
|
||||||
|
@ -425,5 +425,5 @@ enable(_) -> undefined.
|
||||||
|
|
||||||
init_file(type) -> binary();
|
init_file(type) -> binary();
|
||||||
init_file(desc) -> <<"test test desc">>;
|
init_file(desc) -> <<"test test desc">>;
|
||||||
init_file(nullable) -> true;
|
init_file(required) -> false;
|
||||||
init_file(_) -> undefined.
|
init_file(_) -> undefined.
|
||||||
|
|
|
@ -219,7 +219,7 @@ params_gateway_status_in_qs() ->
|
||||||
[{status,
|
[{status,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Gateway Status">>
|
, desc => <<"Gateway Status">>
|
||||||
, example => <<"">>
|
, example => <<"">>
|
||||||
})}
|
})}
|
||||||
|
@ -245,11 +245,11 @@ fields(gateway_overview) ->
|
||||||
#{desc => <<"The Gateway created datetime">>})}
|
#{desc => <<"The Gateway created datetime">>})}
|
||||||
, {started_at,
|
, {started_at,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"The Gateway started datetime">>})}
|
, desc => <<"The Gateway started datetime">>})}
|
||||||
, {stopped_at,
|
, {stopped_at,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"The Gateway stopped datetime">>})}
|
, desc => <<"The Gateway stopped datetime">>})}
|
||||||
, {max_connections,
|
, {max_connections,
|
||||||
mk(integer(),
|
mk(integer(),
|
||||||
|
@ -260,7 +260,7 @@ fields(gateway_overview) ->
|
||||||
})}
|
})}
|
||||||
, {listeners,
|
, {listeners,
|
||||||
mk(hoconsc:array(ref(gateway_listener_overview)),
|
mk(hoconsc:array(ref(gateway_listener_overview)),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The Gateway listeners overview">>})}
|
, desc => <<"The Gateway listeners overview">>})}
|
||||||
];
|
];
|
||||||
fields(gateway_listener_overview) ->
|
fields(gateway_listener_overview) ->
|
||||||
|
@ -295,7 +295,7 @@ fields(Listener) when Listener == tcp_listener;
|
||||||
Listener == dtls_listener ->
|
Listener == dtls_listener ->
|
||||||
[ {id,
|
[ {id,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener ID">>})}
|
, desc => <<"Listener ID">>})}
|
||||||
, {type,
|
, {type,
|
||||||
mk(hoconsc:union([tcp, ssl, udp, dtls]),
|
mk(hoconsc:union([tcp, ssl, udp, dtls]),
|
||||||
|
@ -305,7 +305,7 @@ fields(Listener) when Listener == tcp_listener;
|
||||||
#{ desc => <<"Listener Name">>})}
|
#{ desc => <<"Listener Name">>})}
|
||||||
, {running,
|
, {running,
|
||||||
mk(boolean(),
|
mk(boolean(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener running status">>})}
|
, desc => <<"Listener running status">>})}
|
||||||
] ++ emqx_gateway_schema:fields(Listener);
|
] ++ emqx_gateway_schema:fields(Listener);
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ convert_listener_struct(Schema) ->
|
||||||
{value, {listeners,
|
{value, {listeners,
|
||||||
#{type := Type}}, Schema1} = lists:keytake(listeners, 1, Schema),
|
#{type := Type}}, Schema1} = lists:keytake(listeners, 1, Schema),
|
||||||
ListenerSchema = hoconsc:mk(listeners_schema(Type),
|
ListenerSchema = hoconsc:mk(listeners_schema(Type),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The gateway listeners">>
|
, desc => <<"The gateway listeners">>
|
||||||
}),
|
}),
|
||||||
lists:keystore(listeners, 1, Schema1, {listeners, ListenerSchema}).
|
lists:keystore(listeners, 1, Schema1, {listeners, ListenerSchema}).
|
||||||
|
|
|
@ -287,13 +287,13 @@ params_userid_in_path() ->
|
||||||
params_paging_in_qs() ->
|
params_paging_in_qs() ->
|
||||||
[{page, mk(integer(),
|
[{page, mk(integer(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Page Index">>
|
, desc => <<"Page Index">>
|
||||||
, example => 1
|
, example => 1
|
||||||
})},
|
})},
|
||||||
{limit, mk(integer(),
|
{limit, mk(integer(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Page Limit">>
|
, desc => <<"Page Limit">>
|
||||||
, example => 100
|
, example => 100
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -468,7 +468,7 @@ params_client_insta() ->
|
||||||
++ params_gateway_name_in_path().
|
++ params_gateway_name_in_path().
|
||||||
|
|
||||||
params_client_searching_in_qs() ->
|
params_client_searching_in_qs() ->
|
||||||
M = #{in => query, nullable => true, example => <<"">>},
|
M = #{in => query, required => false, example => <<"">>},
|
||||||
[ {node,
|
[ {node,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
M#{desc => <<"Match the client's node name">>})}
|
M#{desc => <<"Match the client's node name">>})}
|
||||||
|
@ -532,7 +532,7 @@ params_paging() ->
|
||||||
[ {page,
|
[ {page,
|
||||||
mk(integer(),
|
mk(integer(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Page Index">>
|
, desc => <<"Page Index">>
|
||||||
, example => 1
|
, example => 1
|
||||||
})}
|
})}
|
||||||
|
@ -540,7 +540,7 @@ params_paging() ->
|
||||||
mk(integer(),
|
mk(integer(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, desc => <<"Page Limit">>
|
, desc => <<"Page Limit">>
|
||||||
, nullable => true
|
, required => false
|
||||||
, example => 100
|
, example => 100
|
||||||
})}
|
})}
|
||||||
].
|
].
|
||||||
|
|
|
@ -434,13 +434,13 @@ params_userid_in_path() ->
|
||||||
params_paging_in_qs() ->
|
params_paging_in_qs() ->
|
||||||
[{page, mk(integer(),
|
[{page, mk(integer(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Page Index">>
|
, desc => <<"Page Index">>
|
||||||
, example => 1
|
, example => 1
|
||||||
})},
|
})},
|
||||||
{limit, mk(integer(),
|
{limit, mk(integer(),
|
||||||
#{ in => query
|
#{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Page Limit">>
|
, desc => <<"Page Limit">>
|
||||||
, example => 100
|
, example => 100
|
||||||
})}
|
})}
|
||||||
|
@ -457,22 +457,22 @@ fields(listener) ->
|
||||||
common_listener_opts() ++
|
common_listener_opts() ++
|
||||||
[ {tcp,
|
[ {tcp,
|
||||||
mk(ref(tcp_listener_opts),
|
mk(ref(tcp_listener_opts),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The tcp socket options for tcp or ssl listener">>
|
, desc => <<"The tcp socket options for tcp or ssl listener">>
|
||||||
})}
|
})}
|
||||||
, {ssl,
|
, {ssl,
|
||||||
mk(ref(ssl_listener_opts),
|
mk(ref(ssl_listener_opts),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The ssl socket options for ssl listener">>
|
, desc => <<"The ssl socket options for ssl listener">>
|
||||||
})}
|
})}
|
||||||
, {udp,
|
, {udp,
|
||||||
mk(ref(udp_listener_opts),
|
mk(ref(udp_listener_opts),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The udp socket options for udp or dtls listener">>
|
, desc => <<"The udp socket options for udp or dtls listener">>
|
||||||
})}
|
})}
|
||||||
, {dtls,
|
, {dtls,
|
||||||
mk(ref(dtls_listener_opts),
|
mk(ref(dtls_listener_opts),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The dtls socket options for dtls listener">>
|
, desc => <<"The dtls socket options for dtls listener">>
|
||||||
})}
|
})}
|
||||||
];
|
];
|
||||||
|
@ -529,47 +529,47 @@ lists_key_without([K | Ks], N, L) ->
|
||||||
common_listener_opts() ->
|
common_listener_opts() ->
|
||||||
[ {enable,
|
[ {enable,
|
||||||
mk(boolean(),
|
mk(boolean(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Whether to enable this listener">>})}
|
, desc => <<"Whether to enable this listener">>})}
|
||||||
, {id,
|
, {id,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener Id">>})}
|
, desc => <<"Listener Id">>})}
|
||||||
, {name,
|
, {name,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener name">>})}
|
, desc => <<"Listener name">>})}
|
||||||
, {type,
|
, {type,
|
||||||
mk(hoconsc:enum([tcp, ssl, udp, dtls]),
|
mk(hoconsc:enum([tcp, ssl, udp, dtls]),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener type. Enum: tcp, udp, ssl, dtls">>})}
|
, desc => <<"Listener type. Enum: tcp, udp, ssl, dtls">>})}
|
||||||
, {running,
|
, {running,
|
||||||
mk(boolean(),
|
mk(boolean(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener running status">>})}
|
, desc => <<"Listener running status">>})}
|
||||||
, {bind,
|
, {bind,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener bind address or port">>})}
|
, desc => <<"Listener bind address or port">>})}
|
||||||
, {acceptors,
|
, {acceptors,
|
||||||
mk(integer(),
|
mk(integer(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener acceptors number">>})}
|
, desc => <<"Listener acceptors number">>})}
|
||||||
, {access_rules,
|
, {access_rules,
|
||||||
mk(hoconsc:array(binary()),
|
mk(hoconsc:array(binary()),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Listener Access rules for client">>})}
|
, desc => <<"Listener Access rules for client">>})}
|
||||||
, {max_conn_rate,
|
, {max_conn_rate,
|
||||||
mk(integer(),
|
mk(integer(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Max connection rate for the listener">>})}
|
, desc => <<"Max connection rate for the listener">>})}
|
||||||
, {max_connections,
|
, {max_connections,
|
||||||
mk(integer(),
|
mk(integer(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc => <<"Max connections for the listener">>})}
|
, desc => <<"Max connections for the listener">>})}
|
||||||
, {mountpoint,
|
, {mountpoint,
|
||||||
mk(binary(),
|
mk(binary(),
|
||||||
#{ nullable => true
|
#{ required => false
|
||||||
, desc =>
|
, desc =>
|
||||||
<<"The Mounpoint for clients of the listener. "
|
<<"The Mounpoint for clients of the listener. "
|
||||||
"The gateway-level mountpoint configuration can be overloaded "
|
"The gateway-level mountpoint configuration can be overloaded "
|
||||||
|
@ -577,7 +577,7 @@ common_listener_opts() ->
|
||||||
%% FIXME:
|
%% FIXME:
|
||||||
, {authentication,
|
, {authentication,
|
||||||
mk(emqx_authn_schema:authenticator_type(),
|
mk(emqx_authn_schema:authenticator_type(),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => <<"The authenticatior for this listener">>
|
, desc => <<"The authenticatior for this listener">>
|
||||||
})}
|
})}
|
||||||
] ++ emqx_gateway_schema:proxy_protocol_opts().
|
] ++ emqx_gateway_schema:proxy_protocol_opts().
|
||||||
|
|
|
@ -59,21 +59,21 @@ roots() -> [gateway].
|
||||||
fields(gateway) ->
|
fields(gateway) ->
|
||||||
[{stomp,
|
[{stomp,
|
||||||
sc(ref(stomp),
|
sc(ref(stomp),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc =>
|
, desc =>
|
||||||
"The Stomp Gateway configuration.<br>
|
"The Stomp Gateway configuration.<br>
|
||||||
This gateway supports v1.2/1.1/1.0"
|
This gateway supports v1.2/1.1/1.0"
|
||||||
})},
|
})},
|
||||||
{mqttsn,
|
{mqttsn,
|
||||||
sc(ref(mqttsn),
|
sc(ref(mqttsn),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc =>
|
, desc =>
|
||||||
"The MQTT-SN Gateway configuration.<br>
|
"The MQTT-SN Gateway configuration.<br>
|
||||||
This gateway only supports the v1.2 protocol"
|
This gateway only supports the v1.2 protocol"
|
||||||
})},
|
})},
|
||||||
{coap,
|
{coap,
|
||||||
sc(ref(coap),
|
sc(ref(coap),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc =>
|
, desc =>
|
||||||
"The CoAP Gateway configuration.<br>
|
"The CoAP Gateway configuration.<br>
|
||||||
This gateway is implemented based on RFC-7252 and
|
This gateway is implemented based on RFC-7252 and
|
||||||
|
@ -81,14 +81,14 @@ https://core-wg.github.io/coap-pubsub/draft-ietf-core-pubsub.html"
|
||||||
})},
|
})},
|
||||||
{lwm2m,
|
{lwm2m,
|
||||||
sc(ref(lwm2m),
|
sc(ref(lwm2m),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc =>
|
, desc =>
|
||||||
"The LwM2M Gateway configuration.<br>
|
"The LwM2M Gateway configuration.<br>
|
||||||
This gateway only supports the v1.0.1 protocol"
|
This gateway only supports the v1.0.1 protocol"
|
||||||
})},
|
})},
|
||||||
{exproto,
|
{exproto,
|
||||||
sc(ref(exproto),
|
sc(ref(exproto),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
, desc => "The Extension Protocol configuration"
|
, desc => "The Extension Protocol configuration"
|
||||||
})}
|
})}
|
||||||
];
|
];
|
||||||
|
@ -120,7 +120,7 @@ fields(mqttsn) ->
|
||||||
[ {gateway_id,
|
[ {gateway_id,
|
||||||
sc(integer(),
|
sc(integer(),
|
||||||
#{ default => 1
|
#{ default => 1
|
||||||
, nullable => false
|
, required => true
|
||||||
, desc =>
|
, desc =>
|
||||||
"MQTT-SN Gateway ID.<br>
|
"MQTT-SN Gateway ID.<br>
|
||||||
When the <code>broadcast</code> option is enabled,
|
When the <code>broadcast</code> option is enabled,
|
||||||
|
@ -145,7 +145,7 @@ The client just sends its 'PUBLISH' messages to a GW"
|
||||||
, {predefined,
|
, {predefined,
|
||||||
sc(hoconsc:array(ref(mqttsn_predefined)),
|
sc(hoconsc:array(ref(mqttsn_predefined)),
|
||||||
#{ default => []
|
#{ default => []
|
||||||
, nullable => {true, recursively}
|
, required => {false, recursively}
|
||||||
, desc =>
|
, desc =>
|
||||||
<<"The pre-defined topic IDs and topic names.<br>
|
<<"The pre-defined topic IDs and topic names.<br>
|
||||||
A 'pre-defined' topic ID is a topic ID whose mapping to a topic name
|
A 'pre-defined' topic ID is a topic ID whose mapping to a topic name
|
||||||
|
@ -221,7 +221,7 @@ fields(lwm2m) ->
|
||||||
[ {xml_dir,
|
[ {xml_dir,
|
||||||
sc(binary(),
|
sc(binary(),
|
||||||
#{ default =>"etc/lwm2m_xml"
|
#{ default =>"etc/lwm2m_xml"
|
||||||
, nullable => false
|
, required => true
|
||||||
, desc => "The Directory for LwM2M Resource definition"
|
, desc => "The Directory for LwM2M Resource definition"
|
||||||
})}
|
})}
|
||||||
, {lifetime_min,
|
, {lifetime_min,
|
||||||
|
@ -261,7 +261,7 @@ beyond this time window are temporarily stored in memory."
|
||||||
})}
|
})}
|
||||||
, {translators,
|
, {translators,
|
||||||
sc(ref(lwm2m_translators),
|
sc(ref(lwm2m_translators),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, desc => "Topic configuration for LwM2M's gateway publishing and subscription"
|
, desc => "Topic configuration for LwM2M's gateway publishing and subscription"
|
||||||
})}
|
})}
|
||||||
, {listeners, sc(ref(udp_listeners))}
|
, {listeners, sc(ref(udp_listeners))}
|
||||||
|
@ -270,12 +270,12 @@ beyond this time window are temporarily stored in memory."
|
||||||
fields(exproto) ->
|
fields(exproto) ->
|
||||||
[ {server,
|
[ {server,
|
||||||
sc(ref(exproto_grpc_server),
|
sc(ref(exproto_grpc_server),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, desc => "Configurations for starting the <code>ConnectionAdapter</code> service"
|
, desc => "Configurations for starting the <code>ConnectionAdapter</code> service"
|
||||||
})}
|
})}
|
||||||
, {handler,
|
, {handler,
|
||||||
sc(ref(exproto_grpc_handler),
|
sc(ref(exproto_grpc_handler),
|
||||||
#{ nullable => false
|
#{ required => true
|
||||||
, desc => "Configurations for request to <code>ConnectionHandler</code> service"
|
, desc => "Configurations for request to <code>ConnectionHandler</code> service"
|
||||||
})}
|
})}
|
||||||
, {listeners, sc(ref(udp_tcp_listeners))}
|
, {listeners, sc(ref(udp_tcp_listeners))}
|
||||||
|
@ -284,18 +284,18 @@ fields(exproto) ->
|
||||||
fields(exproto_grpc_server) ->
|
fields(exproto_grpc_server) ->
|
||||||
[ {bind,
|
[ {bind,
|
||||||
sc(hoconsc:union([ip_port(), integer()]),
|
sc(hoconsc:union([ip_port(), integer()]),
|
||||||
#{nullable => false})}
|
#{required => true})}
|
||||||
, {ssl,
|
, {ssl,
|
||||||
sc(ref(ssl_server_opts),
|
sc(ref(ssl_server_opts),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
})}
|
})}
|
||||||
];
|
];
|
||||||
|
|
||||||
fields(exproto_grpc_handler) ->
|
fields(exproto_grpc_handler) ->
|
||||||
[ {address, sc(binary(), #{nullable => false})}
|
[ {address, sc(binary(), #{required => true})}
|
||||||
, {ssl,
|
, {ssl,
|
||||||
sc(ref(ssl_client_opts),
|
sc(ref(ssl_client_opts),
|
||||||
#{ nullable => {true, recursively}
|
#{ required => {false, recursively}
|
||||||
})}
|
})}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -324,13 +324,13 @@ fields(lwm2m_translators) ->
|
||||||
For each new LwM2M client that succeeds in going online, the gateway creates
|
For each new LwM2M client that succeeds in going online, the gateway creates
|
||||||
a subscription relationship to receive downstream commands and send it to
|
a subscription relationship to receive downstream commands and send it to
|
||||||
the LwM2M client"
|
the LwM2M client"
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
, {response,
|
, {response,
|
||||||
sc(ref(translator),
|
sc(ref(translator),
|
||||||
#{ desc =>
|
#{ desc =>
|
||||||
"The topic for gateway to publish the acknowledge events from LwM2M client"
|
"The topic for gateway to publish the acknowledge events from LwM2M client"
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
, {notify,
|
, {notify,
|
||||||
sc(ref(translator),
|
sc(ref(translator),
|
||||||
|
@ -338,24 +338,24 @@ the LwM2M client"
|
||||||
"The topic for gateway to publish the notify events from LwM2M client.<br>
|
"The topic for gateway to publish the notify events from LwM2M client.<br>
|
||||||
After succeed observe a resource of LwM2M client, Gateway will send the
|
After succeed observe a resource of LwM2M client, Gateway will send the
|
||||||
notify events via this topic, if the client reports any resource changes"
|
notify events via this topic, if the client reports any resource changes"
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
, {register,
|
, {register,
|
||||||
sc(ref(translator),
|
sc(ref(translator),
|
||||||
#{ desc =>
|
#{ desc =>
|
||||||
"The topic for gateway to publish the register events from LwM2M client.<br>"
|
"The topic for gateway to publish the register events from LwM2M client.<br>"
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
, {update,
|
, {update,
|
||||||
sc(ref(translator),
|
sc(ref(translator),
|
||||||
#{ desc =>
|
#{ desc =>
|
||||||
"The topic for gateway to publish the update events from LwM2M client.<br>"
|
"The topic for gateway to publish the update events from LwM2M client.<br>"
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
];
|
];
|
||||||
|
|
||||||
fields(translator) ->
|
fields(translator) ->
|
||||||
[ {topic, sc(binary(), #{nullable => false})}
|
[ {topic, sc(binary(), #{required => true})}
|
||||||
, {qos, sc(emqx_schema:qos(), #{default => 0})}
|
, {qos, sc(emqx_schema:qos(), #{default => 0})}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ fields(dtls_opts) ->
|
||||||
|
|
||||||
authentication_schema() ->
|
authentication_schema() ->
|
||||||
sc(emqx_authn_schema:authenticator_type(),
|
sc(emqx_authn_schema:authenticator_type(),
|
||||||
#{ nullable => {true, 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>
|
||||||
|
|
|
@ -44,7 +44,7 @@ schema("/alarms") ->
|
||||||
hoconsc:ref(emqx_dashboard_swagger, limit),
|
hoconsc:ref(emqx_dashboard_swagger, limit),
|
||||||
{activated, hoconsc:mk(boolean(), #{in => query,
|
{activated, hoconsc:mk(boolean(), #{in => query,
|
||||||
desc => <<"All alarms, if not specified">>,
|
desc => <<"All alarms, if not specified">>,
|
||||||
nullable => true})}
|
required => false})}
|
||||||
],
|
],
|
||||||
responses => #{
|
responses => #{
|
||||||
200 => [
|
200 => [
|
||||||
|
|
|
@ -94,7 +94,7 @@ fields(app) ->
|
||||||
{expired_at, hoconsc:mk(hoconsc:union([undefined, emqx_datetime:epoch_second()]),
|
{expired_at, hoconsc:mk(hoconsc:union([undefined, emqx_datetime:epoch_second()]),
|
||||||
#{desc => "No longer valid datetime",
|
#{desc => "No longer valid datetime",
|
||||||
example => <<"2021-12-05T02:01:34.186Z">>,
|
example => <<"2021-12-05T02:01:34.186Z">>,
|
||||||
nullable => true,
|
required => false,
|
||||||
default => undefined
|
default => undefined
|
||||||
})},
|
})},
|
||||||
{created_at, hoconsc:mk(emqx_datetime:epoch_second(),
|
{created_at, hoconsc:mk(emqx_datetime:epoch_second(),
|
||||||
|
@ -102,8 +102,8 @@ fields(app) ->
|
||||||
example => <<"2021-12-01T00:00:00.000Z">>
|
example => <<"2021-12-01T00:00:00.000Z">>
|
||||||
})},
|
})},
|
||||||
{desc, hoconsc:mk(binary(),
|
{desc, hoconsc:mk(binary(),
|
||||||
#{example => <<"Note">>, nullable => true})},
|
#{example => <<"Note">>, required => false})},
|
||||||
{enable, hoconsc:mk(boolean(), #{desc => "Enable/Disable", nullable => true})}
|
{enable, hoconsc:mk(boolean(), #{desc => "Enable/Disable", required => false})}
|
||||||
];
|
];
|
||||||
fields(name) ->
|
fields(name) ->
|
||||||
[{name, hoconsc:mk(binary(),
|
[{name, hoconsc:mk(binary(),
|
||||||
|
|
|
@ -101,27 +101,27 @@ fields(ban) ->
|
||||||
[
|
[
|
||||||
{as, hoconsc:mk(hoconsc:enum(?BANNED_TYPES), #{
|
{as, hoconsc:mk(hoconsc:enum(?BANNED_TYPES), #{
|
||||||
desc => <<"Banned type clientid, username, peerhost">>,
|
desc => <<"Banned type clientid, username, peerhost">>,
|
||||||
nullable => false,
|
required => true,
|
||||||
example => username})},
|
example => username})},
|
||||||
{who, hoconsc:mk(binary(), #{
|
{who, hoconsc:mk(binary(), #{
|
||||||
desc => <<"Client info as banned type">>,
|
desc => <<"Client info as banned type">>,
|
||||||
nullable => false,
|
required => true,
|
||||||
example => <<"Banned name"/utf8>>})},
|
example => <<"Banned name"/utf8>>})},
|
||||||
{by, hoconsc:mk(binary(), #{
|
{by, hoconsc:mk(binary(), #{
|
||||||
desc => <<"Commander">>,
|
desc => <<"Commander">>,
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"mgmt_api">>})},
|
example => <<"mgmt_api">>})},
|
||||||
{reason, hoconsc:mk(binary(), #{
|
{reason, hoconsc:mk(binary(), #{
|
||||||
desc => <<"Banned reason">>,
|
desc => <<"Banned reason">>,
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"Too many requests">>})},
|
example => <<"Too many requests">>})},
|
||||||
{at, hoconsc:mk(emqx_datetime:epoch_second(), #{
|
{at, hoconsc:mk(emqx_datetime:epoch_second(), #{
|
||||||
desc => <<"Create banned time, rfc3339, now if not specified">>,
|
desc => <<"Create banned time, rfc3339, now if not specified">>,
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"2021-10-25T21:48:47+08:00">>})},
|
example => <<"2021-10-25T21:48:47+08:00">>})},
|
||||||
{until, hoconsc:mk(emqx_datetime:epoch_second(), #{
|
{until, hoconsc:mk(emqx_datetime:epoch_second(), #{
|
||||||
desc => <<"Cancel banned time, rfc3339, now + 5 minute if not specified">>,
|
desc => <<"Cancel banned time, rfc3339, now + 5 minute if not specified">>,
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"2021-10-25T21:53:47+08:00">>})
|
example => <<"2021-10-25T21:53:47+08:00">>})
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -93,65 +93,65 @@ schema("/clients") ->
|
||||||
hoconsc:ref(emqx_dashboard_swagger, limit),
|
hoconsc:ref(emqx_dashboard_swagger, limit),
|
||||||
{node, hoconsc:mk(binary(), #{
|
{node, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Node name">>,
|
desc => <<"Node name">>,
|
||||||
example => atom_to_list(node())})},
|
example => atom_to_list(node())})},
|
||||||
{username, hoconsc:mk(binary(), #{
|
{username, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"User name">>})},
|
desc => <<"User name">>})},
|
||||||
{zone, hoconsc:mk(binary(), #{
|
{zone, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true})},
|
required => false})},
|
||||||
{ip_address, hoconsc:mk(binary(), #{
|
{ip_address, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Client's IP address">>,
|
desc => <<"Client's IP address">>,
|
||||||
example => <<"127.0.0.1">>})},
|
example => <<"127.0.0.1">>})},
|
||||||
{conn_state, hoconsc:mk(hoconsc:enum([connected, idle, disconnected]), #{
|
{conn_state, hoconsc:mk(hoconsc:enum([connected, idle, disconnected]), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"The current connection status of the client, ",
|
desc => <<"The current connection status of the client, ",
|
||||||
"the possible values are connected,idle,disconnected">>})},
|
"the possible values are connected,idle,disconnected">>})},
|
||||||
{clean_start, hoconsc:mk(boolean(), #{
|
{clean_start, hoconsc:mk(boolean(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
description => <<"Whether the client uses a new session">>})},
|
description => <<"Whether the client uses a new session">>})},
|
||||||
{proto_name, hoconsc:mk(hoconsc:enum(['MQTT', 'CoAP', 'LwM2M', 'MQTT-SN']), #{
|
{proto_name, hoconsc:mk(hoconsc:enum(['MQTT', 'CoAP', 'LwM2M', 'MQTT-SN']), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
description => <<"Client protocol name, ",
|
description => <<"Client protocol name, ",
|
||||||
"the possible values are MQTT,CoAP,LwM2M,MQTT-SN">>})},
|
"the possible values are MQTT,CoAP,LwM2M,MQTT-SN">>})},
|
||||||
{proto_ver, hoconsc:mk(binary(), #{
|
{proto_ver, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Client protocol version">>})},
|
desc => <<"Client protocol version">>})},
|
||||||
{like_clientid, hoconsc:mk(binary(), #{
|
{like_clientid, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Fuzzy search of client identifier by substring method">>})},
|
desc => <<"Fuzzy search of client identifier by substring method">>})},
|
||||||
{like_username, hoconsc:mk(binary(), #{
|
{like_username, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Client user name, fuzzy search by substring">>})},
|
desc => <<"Client user name, fuzzy search by substring">>})},
|
||||||
{gte_created_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
{gte_created_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Search client session creation time by greater",
|
desc => <<"Search client session creation time by greater",
|
||||||
" than or equal method, rfc3339 or timestamp(millisecond)">>})},
|
" than or equal method, rfc3339 or timestamp(millisecond)">>})},
|
||||||
{lte_created_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
{lte_created_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Search client session creation time by less",
|
desc => <<"Search client session creation time by less",
|
||||||
" than or equal method, rfc3339 or timestamp(millisecond)">>})},
|
" than or equal method, rfc3339 or timestamp(millisecond)">>})},
|
||||||
{gte_connected_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
{gte_connected_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Search client connection creation time by greater"
|
desc => <<"Search client connection creation time by greater"
|
||||||
" than or equal method, rfc3339 or timestamp(epoch millisecond)">>})},
|
" than or equal method, rfc3339 or timestamp(epoch millisecond)">>})},
|
||||||
{lte_connected_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
{lte_connected_at, hoconsc:mk(emqx_datetime:epoch_millisecond(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Search client connection creation time by less"
|
desc => <<"Search client connection creation time by less"
|
||||||
" than or equal method, rfc3339 or timestamp(millisecond)">>})}
|
" than or equal method, rfc3339 or timestamp(millisecond)">>})}
|
||||||
],
|
],
|
||||||
|
|
|
@ -67,7 +67,7 @@ schema("/configs") ->
|
||||||
desc =>
|
desc =>
|
||||||
<<"Node's name: If you do not fill in the fields, this node will be used by default.">>})}],
|
<<"Node's name: If you do not fill in the fields, this node will be used by default.">>})}],
|
||||||
responses => #{
|
responses => #{
|
||||||
200 => config_list([])
|
200 => config_list(?EXCLUDES)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,7 +71,7 @@ schema("/metrics") ->
|
||||||
[{ aggregate
|
[{ aggregate
|
||||||
, mk( boolean()
|
, mk( boolean()
|
||||||
, #{ in => query
|
, #{ in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, desc => <<"Whether to aggregate all nodes Metrics">>})
|
, desc => <<"Whether to aggregate all nodes Metrics">>})
|
||||||
}]
|
}]
|
||||||
, responses =>
|
, responses =>
|
||||||
|
|
|
@ -140,7 +140,7 @@ fields(node_info) ->
|
||||||
, mk( emqx_schema:bytesize()
|
, mk( emqx_schema:bytesize()
|
||||||
, #{desc => <<"Used memory">>, example => "256.00M"})}
|
, #{desc => <<"Used memory">>, example => "256.00M"})}
|
||||||
, { node_status
|
, { node_status
|
||||||
, mk( enum(["Running", "Stopped"])
|
, mk( enum(['Running', 'Stopped'])
|
||||||
, #{desc => <<"Node status">>, example => "Running"})}
|
, #{desc => <<"Node status">>, example => "Running"})}
|
||||||
, { otp_release
|
, { otp_release
|
||||||
, mk( string()
|
, mk( string()
|
||||||
|
@ -164,7 +164,7 @@ fields(node_info) ->
|
||||||
, mk( string()
|
, mk( string()
|
||||||
, #{desc => <<"Path to log files">>, example => "path/to/log | not found"})}
|
, #{desc => <<"Path to log files">>, example => "path/to/log | not found"})}
|
||||||
, { role
|
, { role
|
||||||
, mk( enum(["core", "replicant"])
|
, mk( enum([core, replicant])
|
||||||
, #{desc => <<"Node role">>, example => "core"})}
|
, #{desc => <<"Node role">>, example => "core"})}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ fields(aggregate) ->
|
||||||
, mk( boolean()
|
, mk( boolean()
|
||||||
, #{ desc => <<"Calculation aggregate for all nodes">>
|
, #{ desc => <<"Calculation aggregate for all nodes">>
|
||||||
, in => query
|
, in => query
|
||||||
, nullable => true
|
, required => false
|
||||||
, example => false})}
|
, example => false})}
|
||||||
];
|
];
|
||||||
fields(node_stats_data) ->
|
fields(node_stats_data) ->
|
||||||
|
|
|
@ -75,38 +75,38 @@ parameters() ->
|
||||||
{
|
{
|
||||||
node, hoconsc:mk(binary(), #{
|
node, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Node name">>,
|
desc => <<"Node name">>,
|
||||||
example => atom_to_list(node())})
|
example => atom_to_list(node())})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
clientid, hoconsc:mk(binary(), #{
|
clientid, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Client ID">>})
|
desc => <<"Client ID">>})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
qos, hoconsc:mk(emqx_schema:qos(), #{
|
qos, hoconsc:mk(emqx_schema:qos(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"QoS">>})
|
desc => <<"QoS">>})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
topic, hoconsc:mk(binary(), #{
|
topic, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Topic, url encoding">>})
|
desc => <<"Topic, url encoding">>})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match_topic, hoconsc:mk(binary(), #{
|
match_topic, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Match topic string, url encoding">>})
|
desc => <<"Match topic string, url encoding">>})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
share_group, hoconsc:mk(binary(), #{
|
share_group, hoconsc:mk(binary(), #{
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
desc => <<"Shared subscription group name">>})
|
desc => <<"Shared subscription group name">>})
|
||||||
}
|
}
|
||||||
].
|
].
|
||||||
|
|
|
@ -144,45 +144,45 @@ fields(trace) ->
|
||||||
{name, hoconsc:mk(binary(),
|
{name, hoconsc:mk(binary(),
|
||||||
#{desc => "Unique and format by [a-zA-Z0-9-_]",
|
#{desc => "Unique and format by [a-zA-Z0-9-_]",
|
||||||
validator => fun ?MODULE:validate_name/1,
|
validator => fun ?MODULE:validate_name/1,
|
||||||
nullable => false,
|
required => true,
|
||||||
example => <<"EMQX-TRACE-1">>})},
|
example => <<"EMQX-TRACE-1">>})},
|
||||||
{type, hoconsc:mk(hoconsc:enum([clientid, topic, ip_address]),
|
{type, hoconsc:mk(hoconsc:enum([clientid, topic, ip_address]),
|
||||||
#{desc => """Filter type""",
|
#{desc => """Filter type""",
|
||||||
nullable => false,
|
required => true,
|
||||||
example => <<"clientid">>})},
|
example => <<"clientid">>})},
|
||||||
{topic, hoconsc:mk(binary(),
|
{topic, hoconsc:mk(binary(),
|
||||||
#{desc => """support mqtt wildcard topic.""",
|
#{desc => """support mqtt wildcard topic.""",
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"/dev/#">>})},
|
example => <<"/dev/#">>})},
|
||||||
{clientid, hoconsc:mk(binary(),
|
{clientid, hoconsc:mk(binary(),
|
||||||
#{desc => """mqtt clientid.""",
|
#{desc => """mqtt clientid.""",
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"dev-001">>})},
|
example => <<"dev-001">>})},
|
||||||
%% TODO add ip_address type in emqx_schema.erl
|
%% TODO add ip_address type in emqx_schema.erl
|
||||||
{ip_address, hoconsc:mk(binary(),
|
{ip_address, hoconsc:mk(binary(),
|
||||||
#{desc => "client ip address",
|
#{desc => "client ip address",
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"127.0.0.1">>
|
example => <<"127.0.0.1">>
|
||||||
})},
|
})},
|
||||||
{status, hoconsc:mk(hoconsc:enum([running, stopped, waiting]),
|
{status, hoconsc:mk(hoconsc:enum([running, stopped, waiting]),
|
||||||
#{desc => "trace status",
|
#{desc => "trace status",
|
||||||
nullable => true,
|
required => false,
|
||||||
example => running
|
example => running
|
||||||
})},
|
})},
|
||||||
{start_at, hoconsc:mk(emqx_datetime:epoch_second(),
|
{start_at, hoconsc:mk(emqx_datetime:epoch_second(),
|
||||||
#{desc => "rfc3339 timestamp or epoch second",
|
#{desc => "rfc3339 timestamp or epoch second",
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"2021-11-04T18:17:38+08:00">>
|
example => <<"2021-11-04T18:17:38+08:00">>
|
||||||
})},
|
})},
|
||||||
{end_at, hoconsc:mk(emqx_datetime:epoch_second(),
|
{end_at, hoconsc:mk(emqx_datetime:epoch_second(),
|
||||||
#{desc => "rfc3339 timestamp or epoch second",
|
#{desc => "rfc3339 timestamp or epoch second",
|
||||||
nullable => true,
|
required => false,
|
||||||
example => <<"2021-11-05T18:17:38+08:00">>
|
example => <<"2021-11-05T18:17:38+08:00">>
|
||||||
})},
|
})},
|
||||||
{log_size, hoconsc:mk(hoconsc:array(map()),
|
{log_size, hoconsc:mk(hoconsc:array(map()),
|
||||||
#{desc => "trace log size",
|
#{desc => "trace log size",
|
||||||
example => [#{<<"node">> => <<"emqx@127.0.0.1">>, <<"size">> => 1024}],
|
example => [#{<<"node">> => <<"emqx@127.0.0.1">>, <<"size">> => 1024}],
|
||||||
nullable => true})}
|
required => false})}
|
||||||
];
|
];
|
||||||
fields(name) ->
|
fields(name) ->
|
||||||
[{name, hoconsc:mk(binary(),
|
[{name, hoconsc:mk(binary(),
|
||||||
|
@ -198,14 +198,14 @@ fields(node) ->
|
||||||
#{
|
#{
|
||||||
desc => "Node name",
|
desc => "Node name",
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true
|
required => false
|
||||||
})}];
|
})}];
|
||||||
fields(bytes) ->
|
fields(bytes) ->
|
||||||
[{bytes, hoconsc:mk(integer(),
|
[{bytes, hoconsc:mk(integer(),
|
||||||
#{
|
#{
|
||||||
desc => "Maximum number of bytes to store in request",
|
desc => "Maximum number of bytes to store in request",
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
default => 1000
|
default => 1000
|
||||||
})}];
|
})}];
|
||||||
fields(position) ->
|
fields(position) ->
|
||||||
|
@ -213,7 +213,7 @@ fields(position) ->
|
||||||
#{
|
#{
|
||||||
desc => "Offset from the current trace position.",
|
desc => "Offset from the current trace position.",
|
||||||
in => query,
|
in => query,
|
||||||
nullable => true,
|
required => false,
|
||||||
default => 0
|
default => 0
|
||||||
})}].
|
})}].
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ t_http_test(_Config) ->
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
#{
|
#{
|
||||||
<<"code">> => <<"BAD_REQUEST">>,
|
<<"code">> => <<"BAD_REQUEST">>,
|
||||||
<<"message">> => <<"name : not_nullable">>
|
<<"message">> => <<"name : mandatory_required_field">>
|
||||||
}, json(Body)),
|
}, json(Body)),
|
||||||
|
|
||||||
Name = <<"test-name">>,
|
Name = <<"test-name">>,
|
||||||
|
|
|
@ -121,12 +121,12 @@ fields(reset) ->
|
||||||
<<"Topic Name. If this parameter is not present,"
|
<<"Topic Name. If this parameter is not present,"
|
||||||
" all created topic metrics will be reset">>
|
" all created topic metrics will be reset">>
|
||||||
, example => <<"testtopic/1">>
|
, example => <<"testtopic/1">>
|
||||||
, nullable => true})}
|
, required => false})}
|
||||||
, {action
|
, {action
|
||||||
, mk( string()
|
, mk( string()
|
||||||
, #{ desc => <<"Action Name. Only as a \"reset\"">>
|
, #{ desc => <<"Action Name. Only as a \"reset\"">>
|
||||||
, enum => [reset]
|
, enum => [reset]
|
||||||
, nullable => false
|
, required => true
|
||||||
, example => <<"reset">>})}
|
, example => <<"reset">>})}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -135,21 +135,21 @@ fields(topic_metrics) ->
|
||||||
, mk( binary()
|
, mk( binary()
|
||||||
, #{ desc => <<"Topic Name">>
|
, #{ desc => <<"Topic Name">>
|
||||||
, example => <<"testtopic/1">>
|
, example => <<"testtopic/1">>
|
||||||
, nullable => false})},
|
, required => true})},
|
||||||
{ create_time
|
{ create_time
|
||||||
, mk( emqx_datetime:epoch_second()
|
, mk( emqx_datetime:epoch_second()
|
||||||
, #{ desc => <<"Topic Metrics created date time, in rfc3339">>
|
, #{ desc => <<"Topic Metrics created date time, in rfc3339">>
|
||||||
, nullable => false
|
, required => true
|
||||||
, example => <<"2022-01-14T21:48:47+08:00">>})},
|
, example => <<"2022-01-14T21:48:47+08:00">>})},
|
||||||
{ reset_time
|
{ reset_time
|
||||||
, mk( emqx_datetime:epoch_second()
|
, mk( emqx_datetime:epoch_second()
|
||||||
, #{ desc => <<"Topic Metrics reset date time, in rfc3339. Nullable if never reset">>
|
, #{ desc => <<"Topic Metrics reset date time, in rfc3339. Nullable if never reset">>
|
||||||
, nullable => true
|
, required => false
|
||||||
, example => <<"2022-01-14T21:48:47+08:00">>})},
|
, example => <<"2022-01-14T21:48:47+08:00">>})},
|
||||||
{ metrics
|
{ metrics
|
||||||
, mk( ref(metrics)
|
, mk( ref(metrics)
|
||||||
, #{ desc => <<"Topic Metrics fields">>
|
, #{ desc => <<"Topic Metrics fields">>
|
||||||
, nullable => false})
|
, required => true})
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,12 @@ state_fields() ->
|
||||||
"It should match the plugin application name-version as the "
|
"It should match the plugin application name-version as the "
|
||||||
"for the plugin release package name<br>"
|
"for the plugin release package name<br>"
|
||||||
"For example: my_plugin-0.1.0."
|
"For example: my_plugin-0.1.0."
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
, {enable,
|
, {enable,
|
||||||
hoconsc:mk(boolean(),
|
hoconsc:mk(boolean(),
|
||||||
#{ desc => "Set to 'true' to enable this plugin"
|
#{ desc => "Set to 'true' to enable this plugin"
|
||||||
, nullable => false
|
, required => true
|
||||||
})}
|
})}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
@ -69,14 +69,14 @@ root_fields() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
states(type) -> hoconsc:array(hoconsc:ref(state));
|
states(type) -> hoconsc:array(hoconsc:ref(state));
|
||||||
states(nullable) -> true;
|
states(required) -> false;
|
||||||
states(default) -> [];
|
states(default) -> [];
|
||||||
states(desc) -> "An array of plugins in the desired states.<br>"
|
states(desc) -> "An array of plugins in the desired states.<br>"
|
||||||
"The plugins are started in the defined order";
|
"The plugins are started in the defined order";
|
||||||
states(_) -> undefined.
|
states(_) -> undefined.
|
||||||
|
|
||||||
install_dir(type) -> string();
|
install_dir(type) -> string();
|
||||||
install_dir(nullable) -> true;
|
install_dir(required) -> false;
|
||||||
install_dir(default) -> "plugins"; %% runner's root dir
|
install_dir(default) -> "plugins"; %% runner's root dir
|
||||||
install_dir(T) when T =/= desc -> undefined;
|
install_dir(T) when T =/= desc -> undefined;
|
||||||
install_dir(desc) -> """
|
install_dir(desc) -> """
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
[ {emqx, {path, "../emqx"}},
|
[ {emqx, {path, "../emqx"}},
|
||||||
%% FIXME: tag this as v3.1.3
|
%% FIXME: tag this as v3.1.3
|
||||||
{prometheus, {git, "https://github.com/deadtrickster/prometheus.erl", {tag, "v4.8.1"}}},
|
{prometheus, {git, "https://github.com/deadtrickster/prometheus.erl", {tag, "v4.8.1"}}},
|
||||||
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.24.0"}}}
|
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.25.0"}}}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
{edoc_opts, [{preprocess, true}]}.
|
{edoc_opts, [{preprocess, true}]}.
|
||||||
|
|
|
@ -60,7 +60,7 @@ init_file(desc) ->
|
||||||
"The file has to be structured line-by-line, each line must be in ",
|
"The file has to be structured line-by-line, each line must be in ",
|
||||||
"the format of <code>PSKIdentity:SharedSecret</code>. For example: ",
|
"the format of <code>PSKIdentity:SharedSecret</code>. For example: ",
|
||||||
"<code>mydevice1:c2VjcmV0</code>">>;
|
"<code>mydevice1:c2VjcmV0</code>">>;
|
||||||
init_file(nullable) -> true;
|
init_file(required) -> false;
|
||||||
init_file(_) -> undefined.
|
init_file(_) -> undefined.
|
||||||
|
|
||||||
separator(type) -> binary();
|
separator(type) -> binary();
|
||||||
|
|
|
@ -35,11 +35,11 @@ roots() -> [{name, fun name/1},
|
||||||
{register, fun register/1}].
|
{register, fun register/1}].
|
||||||
|
|
||||||
name(type) -> atom();
|
name(type) -> atom();
|
||||||
name(nullable) -> false;
|
name(required) -> true;
|
||||||
name(_) -> undefined.
|
name(_) -> undefined.
|
||||||
|
|
||||||
register(type) -> boolean();
|
register(type) -> boolean();
|
||||||
register(nullable) -> false;
|
register(required) -> true;
|
||||||
register(default) -> false;
|
register(default) -> false;
|
||||||
register(_) -> undefined.
|
register(_) -> undefined.
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ fields("rule_info") ->
|
||||||
%% TODO: we can delete this API if the Dashboard not denpends on it
|
%% TODO: we can delete this API if the Dashboard not denpends on it
|
||||||
fields("rule_events") ->
|
fields("rule_events") ->
|
||||||
ETopics = [binary_to_atom(emqx_rule_events:event_topic(E)) || E <- emqx_rule_events:event_names()],
|
ETopics = [binary_to_atom(emqx_rule_events:event_topic(E)) || E <- emqx_rule_events:event_names()],
|
||||||
[ {"event", sc(hoconsc:enum(ETopics), #{desc => "The event topics", nullable => false})}
|
[ {"event", sc(hoconsc:enum(ETopics), #{desc => "The event topics", required => true})}
|
||||||
, {"title", sc(binary(), #{desc => "The title", example => "some title"})}
|
, {"title", sc(binary(), #{desc => "The title", example => "some title"})}
|
||||||
, {"description", sc(binary(), #{desc => "The description", example => "some desc"})}
|
, {"description", sc(binary(), #{desc => "The description", example => "some desc"})}
|
||||||
, {"columns", sc(map(), #{desc => "The columns"})}
|
, {"columns", sc(map(), #{desc => "The columns"})}
|
||||||
|
@ -75,7 +75,7 @@ fields("rule_test") ->
|
||||||
]),
|
]),
|
||||||
#{desc => "The context of the event for testing",
|
#{desc => "The context of the event for testing",
|
||||||
default => #{}})}
|
default => #{}})}
|
||||||
, {"sql", sc(binary(), #{desc => "The SQL of the rule for testing", nullable => false})}
|
, {"sql", sc(binary(), #{desc => "The SQL of the rule for testing", required => true})}
|
||||||
];
|
];
|
||||||
|
|
||||||
fields("metrics") ->
|
fields("metrics") ->
|
||||||
|
@ -121,7 +121,7 @@ fields("node_metrics") ->
|
||||||
] ++ fields("metrics");
|
] ++ fields("metrics");
|
||||||
|
|
||||||
fields("ctx_pub") ->
|
fields("ctx_pub") ->
|
||||||
[ {"event_type", sc(message_publish, #{desc => "Event Type", nullable => false})}
|
[ {"event_type", sc(message_publish, #{desc => "Event Type", required => true})}
|
||||||
, {"id", sc(binary(), #{desc => "Message ID"})}
|
, {"id", sc(binary(), #{desc => "Message ID"})}
|
||||||
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
||||||
, {"username", sc(binary(), #{desc => "The User Name"})}
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
||||||
|
@ -133,7 +133,7 @@ fields("ctx_pub") ->
|
||||||
] ++ [qos()];
|
] ++ [qos()];
|
||||||
|
|
||||||
fields("ctx_sub") ->
|
fields("ctx_sub") ->
|
||||||
[ {"event_type", sc(session_subscribed, #{desc => "Event Type", nullable => false})}
|
[ {"event_type", sc(session_subscribed, #{desc => "Event Type", required => true})}
|
||||||
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
||||||
, {"username", sc(binary(), #{desc => "The User Name"})}
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
||||||
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
|
, {"payload", sc(binary(), #{desc => "The Message Payload"})}
|
||||||
|
@ -144,11 +144,11 @@ fields("ctx_sub") ->
|
||||||
] ++ [qos()];
|
] ++ [qos()];
|
||||||
|
|
||||||
fields("ctx_unsub") ->
|
fields("ctx_unsub") ->
|
||||||
[{"event_type", sc(session_unsubscribed, #{desc => "Event Type", nullable => false})}] ++
|
[{"event_type", sc(session_unsubscribed, #{desc => "Event Type", required => true})}] ++
|
||||||
proplists:delete("event_type", fields("ctx_sub"));
|
proplists:delete("event_type", fields("ctx_sub"));
|
||||||
|
|
||||||
fields("ctx_delivered") ->
|
fields("ctx_delivered") ->
|
||||||
[ {"event_type", sc(message_delivered, #{desc => "Event Type", nullable => false})}
|
[ {"event_type", sc(message_delivered, #{desc => "Event Type", required => true})}
|
||||||
, {"id", sc(binary(), #{desc => "Message ID"})}
|
, {"id", sc(binary(), #{desc => "Message ID"})}
|
||||||
, {"from_clientid", sc(binary(), #{desc => "The Client ID"})}
|
, {"from_clientid", sc(binary(), #{desc => "The Client ID"})}
|
||||||
, {"from_username", sc(binary(), #{desc => "The User Name"})}
|
, {"from_username", sc(binary(), #{desc => "The User Name"})}
|
||||||
|
@ -162,11 +162,11 @@ fields("ctx_delivered") ->
|
||||||
] ++ [qos()];
|
] ++ [qos()];
|
||||||
|
|
||||||
fields("ctx_acked") ->
|
fields("ctx_acked") ->
|
||||||
[{"event_type", sc(message_acked, #{desc => "Event Type", nullable => false})}] ++
|
[{"event_type", sc(message_acked, #{desc => "Event Type", required => true})}] ++
|
||||||
proplists:delete("event_type", fields("ctx_delivered"));
|
proplists:delete("event_type", fields("ctx_delivered"));
|
||||||
|
|
||||||
fields("ctx_dropped") ->
|
fields("ctx_dropped") ->
|
||||||
[ {"event_type", sc(message_dropped, #{desc => "Event Type", nullable => false})}
|
[ {"event_type", sc(message_dropped, #{desc => "Event Type", required => true})}
|
||||||
, {"id", sc(binary(), #{desc => "Message ID"})}
|
, {"id", sc(binary(), #{desc => "Message ID"})}
|
||||||
, {"reason", sc(binary(), #{desc => "The Reason for Dropping"})}
|
, {"reason", sc(binary(), #{desc => "The Reason for Dropping"})}
|
||||||
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
||||||
|
@ -179,7 +179,7 @@ fields("ctx_dropped") ->
|
||||||
] ++ [qos()];
|
] ++ [qos()];
|
||||||
|
|
||||||
fields("ctx_connected") ->
|
fields("ctx_connected") ->
|
||||||
[ {"event_type", sc(client_connected, #{desc => "Event Type", nullable => false})}
|
[ {"event_type", sc(client_connected, #{desc => "Event Type", required => true})}
|
||||||
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
||||||
, {"username", sc(binary(), #{desc => "The User Name"})}
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
||||||
, {"mountpoint", sc(binary(), #{desc => "The Mountpoint"})}
|
, {"mountpoint", sc(binary(), #{desc => "The Mountpoint"})}
|
||||||
|
@ -196,7 +196,7 @@ fields("ctx_connected") ->
|
||||||
];
|
];
|
||||||
|
|
||||||
fields("ctx_disconnected") ->
|
fields("ctx_disconnected") ->
|
||||||
[ {"event_type", sc(client_disconnected, #{desc => "Event Type", nullable => false})}
|
[ {"event_type", sc(client_disconnected, #{desc => "Event Type", required => true})}
|
||||||
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
, {"clientid", sc(binary(), #{desc => "The Client ID"})}
|
||||||
, {"username", sc(binary(), #{desc => "The User Name"})}
|
, {"username", sc(binary(), #{desc => "The User Name"})}
|
||||||
, {"reason", sc(binary(), #{desc => "The Reason for Disconnect"})}
|
, {"reason", sc(binary(), #{desc => "The Reason for Disconnect"})}
|
||||||
|
@ -211,7 +211,7 @@ qos() ->
|
||||||
|
|
||||||
rule_id() ->
|
rule_id() ->
|
||||||
{"id", sc(binary(),
|
{"id", sc(binary(),
|
||||||
#{ desc => "The ID of the rule", nullable => false
|
#{ desc => "The ID of the rule", required => true
|
||||||
, example => "293fb66f"
|
, example => "293fb66f"
|
||||||
})}.
|
})}.
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ SQL query to transform the messages.<br>
|
||||||
Example: <code>SELECT * FROM \"test/topic\" WHERE payload.x = 1</code><br>
|
Example: <code>SELECT * FROM \"test/topic\" WHERE payload.x = 1</code><br>
|
||||||
"""
|
"""
|
||||||
, example => "SELECT * FROM \"test/topic\" WHERE payload.x = 1"
|
, example => "SELECT * FROM \"test/topic\" WHERE payload.x = 1"
|
||||||
, nullable => false
|
, required => true
|
||||||
, validator => fun ?MODULE:validate_sql/1
|
, validator => fun ?MODULE:validate_sql/1
|
||||||
})}
|
})}
|
||||||
, {"outputs", sc(hoconsc:array(hoconsc:union(outputs())),
|
, {"outputs", sc(hoconsc:array(hoconsc:union(outputs())),
|
||||||
|
@ -143,7 +143,7 @@ fields("republish_args") ->
|
||||||
The target topic of message to be re-published.<br>
|
The target topic of message to be re-published.<br>
|
||||||
Template with variables is allowed, see description of the 'republish_args'.
|
Template with variables is allowed, see description of the 'republish_args'.
|
||||||
"""
|
"""
|
||||||
, nullable => false
|
, required => true
|
||||||
, example => <<"a/1">>
|
, example => <<"a/1">>
|
||||||
})}
|
})}
|
||||||
, {qos, sc(qos(),
|
, {qos, sc(qos(),
|
||||||
|
@ -182,7 +182,7 @@ rule_name() ->
|
||||||
{"name", sc(binary(),
|
{"name", sc(binary(),
|
||||||
#{ desc => "The name of the rule"
|
#{ desc => "The name of the rule"
|
||||||
, default => ""
|
, default => ""
|
||||||
, nullable => false
|
, required => true
|
||||||
, example => "foo"
|
, example => "foo"
|
||||||
})}.
|
})}.
|
||||||
|
|
||||||
|
|
|
@ -33,19 +33,19 @@ namespace() -> "statsd".
|
||||||
roots() -> ["statsd"].
|
roots() -> ["statsd"].
|
||||||
|
|
||||||
fields("statsd") ->
|
fields("statsd") ->
|
||||||
[ {enable, hoconsc:mk(boolean(), #{default => false, nullable => false})}
|
[ {enable, hoconsc:mk(boolean(), #{default => false, required => true})}
|
||||||
, {server, fun server/1}
|
, {server, fun server/1}
|
||||||
, {sample_time_interval, fun duration_ms/1}
|
, {sample_time_interval, fun duration_ms/1}
|
||||||
, {flush_time_interval, fun duration_ms/1}
|
, {flush_time_interval, fun duration_ms/1}
|
||||||
].
|
].
|
||||||
|
|
||||||
server(type) -> emqx_schema:ip_port();
|
server(type) -> emqx_schema:ip_port();
|
||||||
server(nullable) -> false;
|
server(required) -> true;
|
||||||
server(default) -> "127.0.0.1:8125";
|
server(default) -> "127.0.0.1:8125";
|
||||||
server(_) -> undefined.
|
server(_) -> undefined.
|
||||||
|
|
||||||
duration_ms(type) -> emqx_schema:duration_ms();
|
duration_ms(type) -> emqx_schema:duration_ms();
|
||||||
duration_ms(nullable) -> false;
|
duration_ms(required) -> true;
|
||||||
duration_ms(default) -> "10s";
|
duration_ms(default) -> "10s";
|
||||||
duration_ms(_) -> undefined.
|
duration_ms(_) -> undefined.
|
||||||
|
|
||||||
|
|
2
mix.exs
2
mix.exs
|
@ -68,7 +68,7 @@ defmodule EMQXUmbrella.MixProject do
|
||||||
# in conflict by emqtt and hocon
|
# in conflict by emqtt and hocon
|
||||||
{:getopt, "1.0.2", override: true},
|
{:getopt, "1.0.2", override: true},
|
||||||
{:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "0.18.0", override: true},
|
{:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "0.18.0", override: true},
|
||||||
{:hocon, github: "emqx/hocon", tag: "0.24.0", override: true},
|
{:hocon, github: "emqx/hocon", tag: "0.25.0", override: true},
|
||||||
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.4.1", override: true},
|
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.4.1", override: true},
|
||||||
{:esasl, github: "emqx/esasl", tag: "0.2.0"},
|
{:esasl, github: "emqx/esasl", tag: "0.2.0"},
|
||||||
{:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"},
|
{:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"},
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
, {system_monitor, {git, "https://github.com/ieQu1/system_monitor", {tag, "3.0.2"}}}
|
, {system_monitor, {git, "https://github.com/ieQu1/system_monitor", {tag, "3.0.2"}}}
|
||||||
, {getopt, "1.0.2"}
|
, {getopt, "1.0.2"}
|
||||||
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.18.0"}}}
|
, {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.18.0"}}}
|
||||||
, {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.24.0"}}}
|
, {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.25.0"}}}
|
||||||
, {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.4.1"}}}
|
, {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.4.1"}}}
|
||||||
, {esasl, {git, "https://github.com/emqx/esasl", {tag, "0.2.0"}}}
|
, {esasl, {git, "https://github.com/emqx/esasl", {tag, "0.2.0"}}}
|
||||||
, {jose, {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.2"}}}
|
, {jose, {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.2"}}}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue