refactor: only PUT, no POST for '/gateways'
This commit is contained in:
parent
2914523117
commit
9cc5920b0d
|
@ -57,6 +57,14 @@ It's enum with `stomp`, `mqttsn`, `coap`, `lwm2m`, `exproto`
|
|||
}
|
||||
}
|
||||
|
||||
gateway_enable_in_path {
|
||||
desc {
|
||||
en: """Whether or not gateway is enabled"""
|
||||
|
||||
zh: """是否开启此网关"""
|
||||
}
|
||||
}
|
||||
|
||||
gateway_status {
|
||||
desc {
|
||||
en: """Gateway status"""
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%% -*- mode: erlang -*-
|
||||
{application, emqx_gateway, [
|
||||
{description, "The Gateway management application"},
|
||||
{vsn, "0.1.7"},
|
||||
{vsn, "0.1.8"},
|
||||
{registered, []},
|
||||
{mod, {emqx_gateway_app, []}},
|
||||
{applications, [kernel, stdlib, grpc, emqx, emqx_authn]},
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
-include("emqx_gateway_http.hrl").
|
||||
-include_lib("typerefl/include/types.hrl").
|
||||
-include_lib("hocon/include/hoconsc.hrl").
|
||||
-include_lib("emqx/include/emqx_placeholder.hrl").
|
||||
-include_lib("emqx/include/emqx_authentication.hrl").
|
||||
|
||||
-behaviour(minirest_api).
|
||||
|
||||
|
@ -49,8 +47,9 @@
|
|||
|
||||
%% http handlers
|
||||
-export([
|
||||
gateways/2,
|
||||
gateway/2,
|
||||
gateway_insta/2
|
||||
gateway_enable/2
|
||||
]).
|
||||
|
||||
-define(KNOWN_GATEWAY_STATUSES, [<<"running">>, <<"stopped">>, <<"unloaded">>]).
|
||||
|
@ -66,13 +65,14 @@ api_spec() ->
|
|||
paths() ->
|
||||
emqx_gateway_utils:make_deprecated_paths([
|
||||
"/gateways",
|
||||
"/gateways/:name"
|
||||
"/gateways/:name",
|
||||
"/gateways/:name/enable/:enable"
|
||||
]).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% http handlers
|
||||
|
||||
gateway(get, Request) ->
|
||||
gateways(get, Request) ->
|
||||
Params = maps:get(query_string, Request, #{}),
|
||||
Status = maps:get(<<"status">>, Params, <<"all">>),
|
||||
case lists:member(Status, [<<"all">> | ?KNOWN_GATEWAY_STATUSES]) of
|
||||
|
@ -89,84 +89,85 @@ gateway(get, Request) ->
|
|||
lists:join(", ", ?KNOWN_GATEWAY_STATUSES)
|
||||
]
|
||||
)
|
||||
end;
|
||||
gateway(post, Request) ->
|
||||
Body = maps:get(body, Request, #{}),
|
||||
try
|
||||
Name0 = maps:get(<<"name">>, Body),
|
||||
GwName = binary_to_existing_atom(Name0),
|
||||
case emqx_gateway_registry:lookup(GwName) of
|
||||
undefined ->
|
||||
error(badarg);
|
||||
_ ->
|
||||
GwConf = maps:without([<<"name">>], Body),
|
||||
case emqx_gateway_conf:load_gateway(GwName, GwConf) of
|
||||
{ok, NGwConf} ->
|
||||
{201, NGwConf};
|
||||
{error, Reason} ->
|
||||
emqx_gateway_http:reason2resp(Reason)
|
||||
end
|
||||
end
|
||||
catch
|
||||
error:{badkey, K} ->
|
||||
return_http_error(400, [K, " is required"]);
|
||||
error:{badconf, _} = Reason1 ->
|
||||
emqx_gateway_http:reason2resp(Reason1);
|
||||
error:badarg ->
|
||||
return_http_error(404, "Bad gateway name")
|
||||
end.
|
||||
|
||||
gateway_insta(delete, #{bindings := #{name := Name0}}) ->
|
||||
with_gateway(Name0, fun(GwName, _) ->
|
||||
case emqx_gateway_conf:unload_gateway(GwName) of
|
||||
ok ->
|
||||
gateway(get, #{bindings := #{name := Name}}) ->
|
||||
try
|
||||
GwName = gw_name(Name),
|
||||
case emqx_gateway:lookup(GwName) of
|
||||
undefined ->
|
||||
{200, #{name => GwName, status => unloaded}};
|
||||
Gateway ->
|
||||
GwConf = emqx_gateway_conf:gateway(Name),
|
||||
GwInfo0 = emqx_gateway_utils:unix_ts_to_rfc3339(
|
||||
[created_at, started_at, stopped_at],
|
||||
Gateway
|
||||
),
|
||||
GwInfo1 = maps:with(
|
||||
[
|
||||
name,
|
||||
status,
|
||||
created_at,
|
||||
started_at,
|
||||
stopped_at
|
||||
],
|
||||
GwInfo0
|
||||
),
|
||||
{200, maps:merge(GwConf, GwInfo1)}
|
||||
end
|
||||
catch
|
||||
throw:not_found ->
|
||||
return_http_error(404, <<"NOT FOUND">>)
|
||||
end;
|
||||
gateway(put, #{
|
||||
body := GwConf0,
|
||||
bindings := #{name := Name}
|
||||
}) ->
|
||||
GwConf = maps:without([<<"name">>], GwConf0),
|
||||
try
|
||||
GwName = gw_name(Name),
|
||||
LoadOrUpdateF =
|
||||
case emqx_gateway:lookup(GwName) of
|
||||
undefined ->
|
||||
fun emqx_gateway_conf:load_gateway/2;
|
||||
_ ->
|
||||
fun emqx_gateway_conf:update_gateway/2
|
||||
end,
|
||||
case LoadOrUpdateF(GwName, GwConf) of
|
||||
{ok, _} ->
|
||||
{204};
|
||||
{error, Reason} ->
|
||||
emqx_gateway_http:reason2resp(Reason)
|
||||
end
|
||||
end);
|
||||
gateway_insta(get, #{bindings := #{name := Name0}}) ->
|
||||
try binary_to_existing_atom(Name0) of
|
||||
GwName ->
|
||||
case emqx_gateway:lookup(GwName) of
|
||||
undefined ->
|
||||
{200, #{name => GwName, status => unloaded}};
|
||||
Gateway ->
|
||||
GwConf = emqx_gateway_conf:gateway(Name0),
|
||||
GwInfo0 = emqx_gateway_utils:unix_ts_to_rfc3339(
|
||||
[created_at, started_at, stopped_at],
|
||||
Gateway
|
||||
),
|
||||
GwInfo1 = maps:with(
|
||||
[
|
||||
name,
|
||||
status,
|
||||
created_at,
|
||||
started_at,
|
||||
stopped_at
|
||||
],
|
||||
GwInfo0
|
||||
),
|
||||
{200, maps:merge(GwConf, GwInfo1)}
|
||||
end
|
||||
catch
|
||||
error:badarg ->
|
||||
return_http_error(404, "Bad gateway name")
|
||||
end;
|
||||
gateway_insta(put, #{
|
||||
body := GwConf0,
|
||||
bindings := #{name := Name0}
|
||||
}) ->
|
||||
with_gateway(Name0, fun(GwName, _) ->
|
||||
%% XXX: Clear the unused fields
|
||||
GwConf = maps:without([<<"name">>], GwConf0),
|
||||
case emqx_gateway_conf:update_gateway(GwName, GwConf) of
|
||||
{ok, Gateway} ->
|
||||
{200, Gateway};
|
||||
{error, Reason} ->
|
||||
emqx_gateway_http:reason2resp(Reason)
|
||||
error:{badconf, _} = Reason1 ->
|
||||
emqx_gateway_http:reason2resp(Reason1);
|
||||
throw:not_found ->
|
||||
return_http_error(404, <<"NOT FOUND">>)
|
||||
end.
|
||||
|
||||
gateway_enable(put, #{bindings := #{name := Name, enable := Enable}}) ->
|
||||
try
|
||||
GwName = gw_name(Name),
|
||||
case emqx_gateway:lookup(GwName) of
|
||||
undefined ->
|
||||
return_http_error(404, <<"NOT FOUND">>);
|
||||
_Gateway ->
|
||||
{ok, _} = emqx_gateway_conf:update_gateway(GwName, #{<<"enable">> => Enable}),
|
||||
{204}
|
||||
end
|
||||
end).
|
||||
catch
|
||||
throw:not_found ->
|
||||
return_http_error(404, <<"NOT FOUND">>)
|
||||
end.
|
||||
|
||||
-spec gw_name(binary()) -> stomp | coap | lwm2m | mqttsn | exproto | no_return().
|
||||
gw_name(<<"stomp">>) -> stomp;
|
||||
gw_name(<<"coap">>) -> coap;
|
||||
gw_name(<<"lwm2m">>) -> lwm2m;
|
||||
gw_name(<<"mqttsn">>) -> mqttsn;
|
||||
gw_name(<<"exproto">>) -> exproto;
|
||||
gw_name(_Else) -> throw(not_found).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Swagger defines
|
||||
|
@ -174,7 +175,7 @@ gateway_insta(put, #{
|
|||
|
||||
schema("/gateways") ->
|
||||
#{
|
||||
'operationId' => gateway,
|
||||
'operationId' => gateways,
|
||||
get =>
|
||||
#{
|
||||
tags => ?TAGS,
|
||||
|
@ -182,29 +183,20 @@ schema("/gateways") ->
|
|||
summary => <<"List All Gateways">>,
|
||||
parameters => params_gateway_status_in_qs(),
|
||||
responses =>
|
||||
?STANDARD_RESP(
|
||||
#{
|
||||
200 => emqx_dashboard_swagger:schema_with_example(
|
||||
hoconsc:array(ref(gateway_overview)),
|
||||
examples_gateway_overview()
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
post =>
|
||||
#{
|
||||
tags => ?TAGS,
|
||||
desc => ?DESC(enable_gateway),
|
||||
summary => <<"Enable a Gateway">>,
|
||||
%% TODO: distinguish create & response swagger schema
|
||||
'requestBody' => schema_gateways_conf(),
|
||||
responses =>
|
||||
?STANDARD_RESP(#{201 => schema_gateways_conf()})
|
||||
#{
|
||||
200 => emqx_dashboard_swagger:schema_with_example(
|
||||
hoconsc:array(ref(gateway_overview)),
|
||||
examples_gateway_overview()
|
||||
),
|
||||
400 => emqx_dashboard_swagger:error_codes(
|
||||
[?BAD_REQUEST], <<"Bad request">>
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
schema("/gateways/:name") ->
|
||||
#{
|
||||
'operationId' => gateway_insta,
|
||||
'operationId' => gateway,
|
||||
get =>
|
||||
#{
|
||||
tags => ?TAGS,
|
||||
|
@ -212,26 +204,41 @@ schema("/gateways/:name") ->
|
|||
summary => <<"Get the Gateway">>,
|
||||
parameters => params_gateway_name_in_path(),
|
||||
responses =>
|
||||
?STANDARD_RESP(#{200 => schema_gateways_conf()})
|
||||
},
|
||||
delete =>
|
||||
#{
|
||||
tags => ?TAGS,
|
||||
desc => ?DESC(delete_gateway),
|
||||
summary => <<"Unload the gateway">>,
|
||||
parameters => params_gateway_name_in_path(),
|
||||
responses =>
|
||||
?STANDARD_RESP(#{204 => <<"Deleted">>})
|
||||
#{
|
||||
200 => schema_gateways_conf(),
|
||||
404 => emqx_dashboard_swagger:error_codes(
|
||||
[?NOT_FOUND, ?RESOURCE_NOT_FOUND], <<"Not Found">>
|
||||
)
|
||||
}
|
||||
},
|
||||
put =>
|
||||
#{
|
||||
tags => ?TAGS,
|
||||
desc => ?DESC(update_gateway),
|
||||
summary => <<"Update the gateway confs">>,
|
||||
% [FIXME] add proper desc
|
||||
summary => <<"Load or update the gateway confs">>,
|
||||
parameters => params_gateway_name_in_path(),
|
||||
'requestBody' => schema_update_gateways_conf(),
|
||||
'requestBody' => schema_load_or_update_gateways_conf(),
|
||||
responses =>
|
||||
?STANDARD_RESP(#{200 => schema_gateways_conf()})
|
||||
?STANDARD_RESP(#{204 => <<"Gateway configuration updated">>})
|
||||
}
|
||||
};
|
||||
schema("/gateways/:name/enable/:enable") ->
|
||||
#{
|
||||
'operationId' => gateway_enable,
|
||||
put =>
|
||||
#{
|
||||
tags => ?TAGS,
|
||||
desc => ?DESC(update_gateway),
|
||||
summary => <<"Enable or disable gateway">>,
|
||||
parameters => params_gateway_name_in_path() ++ params_gateway_enable_in_path(),
|
||||
responses =>
|
||||
#{
|
||||
204 => <<"Gateway configuration updated">>,
|
||||
404 => emqx_dashboard_swagger:error_codes(
|
||||
[?NOT_FOUND, ?RESOURCE_NOT_FOUND], <<"Not Found">>
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
schema(Path) ->
|
||||
|
@ -268,6 +275,18 @@ params_gateway_status_in_qs() ->
|
|||
)}
|
||||
].
|
||||
|
||||
params_gateway_enable_in_path() ->
|
||||
[
|
||||
{enable,
|
||||
mk(
|
||||
boolean(),
|
||||
#{
|
||||
in => path,
|
||||
desc => ?DESC(gateway_enable_in_path),
|
||||
example => true
|
||||
}
|
||||
)}
|
||||
].
|
||||
%%--------------------------------------------------------------------
|
||||
%% schemas
|
||||
|
||||
|
@ -377,8 +396,6 @@ fields(Gw) when
|
|||
->
|
||||
[{name, mk(Gw, #{desc => ?DESC(gateway_name)})}] ++
|
||||
convert_listener_struct(emqx_gateway_schema:fields(Gw));
|
||||
fields(update_disable_enable_only) ->
|
||||
[{enable, mk(boolean(), #{desc => <<"Enable/Disable the gateway">>})}];
|
||||
fields(Gw) when
|
||||
Gw == update_stomp;
|
||||
Gw == update_mqttsn;
|
||||
|
@ -431,15 +448,19 @@ fields(Listener) when
|
|||
fields(gateway_stats) ->
|
||||
[{key, mk(binary(), #{})}].
|
||||
|
||||
schema_update_gateways_conf() ->
|
||||
schema_load_or_update_gateways_conf() ->
|
||||
emqx_dashboard_swagger:schema_with_examples(
|
||||
hoconsc:union([
|
||||
ref(?MODULE, stomp),
|
||||
ref(?MODULE, mqttsn),
|
||||
ref(?MODULE, coap),
|
||||
ref(?MODULE, lwm2m),
|
||||
ref(?MODULE, exproto),
|
||||
ref(?MODULE, update_stomp),
|
||||
ref(?MODULE, update_mqttsn),
|
||||
ref(?MODULE, update_coap),
|
||||
ref(?MODULE, update_lwm2m),
|
||||
ref(?MODULE, update_exproto),
|
||||
ref(?MODULE, update_disable_enable_only)
|
||||
ref(?MODULE, update_exproto)
|
||||
]),
|
||||
examples_update_gateway_confs()
|
||||
).
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
emqx_gateway_test_utils,
|
||||
[
|
||||
assert_confs/2,
|
||||
assert_feilds_apperence/2,
|
||||
assert_fields_exist/2,
|
||||
request/2,
|
||||
request/3,
|
||||
ssl_server_opts/0,
|
||||
|
@ -32,6 +32,7 @@
|
|||
).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
|
||||
|
||||
%% this parses to #{}, will not cause config cleanup
|
||||
%% so we will need call emqx_config:erase
|
||||
|
@ -55,32 +56,68 @@ end_per_suite(Conf) ->
|
|||
emqx_mgmt_api_test_util:end_suite([emqx_gateway, emqx_authn, emqx_conf]),
|
||||
Conf.
|
||||
|
||||
init_per_testcase(t_gateway_fail, Config) ->
|
||||
meck:expect(
|
||||
emqx_gateway_conf,
|
||||
update_gateway,
|
||||
fun
|
||||
(stomp, V) -> {error, {badconf, #{key => gw, value => V, reason => test_error}}};
|
||||
(coap, V) -> error({badconf, #{key => gw, value => V, reason => test_crash}})
|
||||
end
|
||||
),
|
||||
Config;
|
||||
init_per_testcase(_, Config) ->
|
||||
Config.
|
||||
|
||||
end_per_testcase(TestCase, Config) ->
|
||||
case TestCase of
|
||||
t_gateway_fail -> meck:unload(emqx_gateway_conf);
|
||||
_ -> ok
|
||||
end,
|
||||
[emqx_gateway_conf:unload_gateway(GwName) || GwName <- [stomp, mqttsn, coap, lwm2m, exproto]],
|
||||
Config.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Cases
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
t_gateway(_) ->
|
||||
t_gateways(_) ->
|
||||
{200, Gateways} = request(get, "/gateways"),
|
||||
lists:foreach(fun assert_gw_unloaded/1, Gateways),
|
||||
{200, UnloadedGateways} = request(get, "/gateways?status=unloaded"),
|
||||
lists:foreach(fun assert_gw_unloaded/1, UnloadedGateways),
|
||||
{200, NoRunningGateways} = request(get, "/gateways?status=running"),
|
||||
?assertEqual([], NoRunningGateways),
|
||||
{404, GwNotFoundReq} = request(get, "/gateways/unknown_gateway"),
|
||||
assert_not_found(GwNotFoundReq),
|
||||
{400, BadReqInvalidStatus} = request(get, "/gateways?status=invalid_status"),
|
||||
assert_bad_request(BadReqInvalidStatus),
|
||||
{400, BadReqUCStatus} = request(get, "/gateways?status=UNLOADED"),
|
||||
assert_bad_request(BadReqUCStatus),
|
||||
{201, _} = request(post, "/gateways", #{name => <<"stomp">>}),
|
||||
{200, StompGw1} = request(get, "/gateways/stomp"),
|
||||
assert_feilds_apperence(
|
||||
ok.
|
||||
|
||||
t_gateway(_) ->
|
||||
{404, GwNotFoundReq1} = request(get, "/gateways/not_a_known_atom"),
|
||||
assert_not_found(GwNotFoundReq1),
|
||||
{404, GwNotFoundReq2} = request(get, "/gateways/undefined"),
|
||||
assert_not_found(GwNotFoundReq2),
|
||||
{204, _} = request(put, "/gateways/stomp", #{}),
|
||||
{200, StompGw} = request(get, "/gateways/stomp"),
|
||||
assert_fields_exist(
|
||||
[name, status, enable, created_at, started_at],
|
||||
StompGw1
|
||||
StompGw
|
||||
),
|
||||
{204, _} = request(delete, "/gateways/stomp"),
|
||||
{200, StompGw2} = request(get, "/gateways/stomp"),
|
||||
assert_gw_unloaded(StompGw2),
|
||||
{204, _} = request(put, "/gateways/stomp", #{enable => true}),
|
||||
{200, #{enable := true}} = request(get, "/gateway/stomp"),
|
||||
{204, _} = request(put, "/gateways/stomp", #{enable => false}),
|
||||
{200, #{enable := false}} = request(get, "/gateway/stomp"),
|
||||
{404, _} = request(put, "/gateways/undefined", #{}),
|
||||
{400, _} = request(put, "/gateways/stomp", #{bad_key => "foo"}),
|
||||
ok.
|
||||
|
||||
t_gateway_fail(_) ->
|
||||
{204, _} = request(put, "/gateways/stomp", #{}),
|
||||
{400, _} = request(put, "/gateways/stomp", #{}),
|
||||
{204, _} = request(put, "/gateways/coap", #{}),
|
||||
{400, _} = request(put, "/gateways/coap", #{}),
|
||||
ok.
|
||||
|
||||
t_deprecated_gateway(_) ->
|
||||
|
@ -88,21 +125,30 @@ t_deprecated_gateway(_) ->
|
|||
lists:foreach(fun assert_gw_unloaded/1, Gateways),
|
||||
{404, NotFoundReq} = request(get, "/gateway/uname_gateway"),
|
||||
assert_not_found(NotFoundReq),
|
||||
{201, _} = request(post, "/gateway", #{name => <<"stomp">>}),
|
||||
{200, StompGw1} = request(get, "/gateway/stomp"),
|
||||
assert_feilds_apperence(
|
||||
{204, _} = request(put, "/gateway/stomp", #{}),
|
||||
{200, StompGw} = request(get, "/gateway/stomp"),
|
||||
assert_fields_exist(
|
||||
[name, status, enable, created_at, started_at],
|
||||
StompGw1
|
||||
StompGw
|
||||
),
|
||||
{204, _} = request(delete, "/gateway/stomp"),
|
||||
{200, StompGw2} = request(get, "/gateway/stomp"),
|
||||
assert_gw_unloaded(StompGw2),
|
||||
ok.
|
||||
|
||||
t_gateway_enable(_) ->
|
||||
{204, _} = request(put, "/gateways/stomp", #{}),
|
||||
{200, #{enable := Enable}} = request(get, "/gateway/stomp"),
|
||||
NotEnable = not Enable,
|
||||
{204, _} = request(put, "/gateways/stomp/enable/" ++ atom_to_list(NotEnable), undefined),
|
||||
{200, #{enable := NotEnable}} = request(get, "/gateway/stomp"),
|
||||
{204, _} = request(put, "/gateways/stomp/enable/" ++ atom_to_list(Enable), undefined),
|
||||
{200, #{enable := Enable}} = request(get, "/gateway/stomp"),
|
||||
{404, _} = request(put, "/gateways/undefined/enable/true", undefined),
|
||||
{404, _} = request(put, "/gateways/not_a_known_atom/enable/true", undefined),
|
||||
{404, _} = request(put, "/gateways/coap/enable/true", undefined),
|
||||
ok.
|
||||
|
||||
t_gateway_stomp(_) ->
|
||||
{200, Gw} = request(get, "/gateways/stomp"),
|
||||
assert_gw_unloaded(Gw),
|
||||
%% post
|
||||
GwConf = #{
|
||||
name => <<"stomp">>,
|
||||
frame => #{
|
||||
|
@ -114,20 +160,18 @@ t_gateway_stomp(_) ->
|
|||
#{name => <<"def">>, type => <<"tcp">>, bind => <<"61613">>}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/stomp", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/stomp"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
%% put
|
||||
GwConf2 = emqx_map_lib:deep_merge(GwConf, #{frame => #{max_headers => 10}}),
|
||||
{200, _} = request(put, "/gateways/stomp", maps:without([name, listeners], GwConf2)),
|
||||
{204, _} = request(put, "/gateways/stomp", maps:without([name, listeners], GwConf2)),
|
||||
{200, ConfResp2} = request(get, "/gateways/stomp"),
|
||||
assert_confs(GwConf2, ConfResp2),
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
t_gateway_mqttsn(_) ->
|
||||
{200, Gw} = request(get, "/gateways/mqttsn"),
|
||||
assert_gw_unloaded(Gw),
|
||||
%% post
|
||||
GwConf = #{
|
||||
name => <<"mqttsn">>,
|
||||
gateway_id => 1,
|
||||
|
@ -138,20 +182,18 @@ t_gateway_mqttsn(_) ->
|
|||
#{name => <<"def">>, type => <<"udp">>, bind => <<"1884">>}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/mqttsn", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/mqttsn"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
%% put
|
||||
GwConf2 = emqx_map_lib:deep_merge(GwConf, #{predefined => []}),
|
||||
{200, _} = request(put, "/gateways/mqttsn", maps:without([name, listeners], GwConf2)),
|
||||
{204, _} = request(put, "/gateways/mqttsn", maps:without([name, listeners], GwConf2)),
|
||||
{200, ConfResp2} = request(get, "/gateways/mqttsn"),
|
||||
assert_confs(GwConf2, ConfResp2),
|
||||
{204, _} = request(delete, "/gateways/mqttsn").
|
||||
ok.
|
||||
|
||||
t_gateway_coap(_) ->
|
||||
{200, Gw} = request(get, "/gateways/coap"),
|
||||
assert_gw_unloaded(Gw),
|
||||
%% post
|
||||
GwConf = #{
|
||||
name => <<"coap">>,
|
||||
heartbeat => <<"60s">>,
|
||||
|
@ -160,20 +202,18 @@ t_gateway_coap(_) ->
|
|||
#{name => <<"def">>, type => <<"udp">>, bind => <<"5683">>}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/coap", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/coap"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
%% put
|
||||
GwConf2 = emqx_map_lib:deep_merge(GwConf, #{heartbeat => <<"10s">>}),
|
||||
{200, _} = request(put, "/gateways/coap", maps:without([name, listeners], GwConf2)),
|
||||
{204, _} = request(put, "/gateways/coap", maps:without([name, listeners], GwConf2)),
|
||||
{200, ConfResp2} = request(get, "/gateways/coap"),
|
||||
assert_confs(GwConf2, ConfResp2),
|
||||
{204, _} = request(delete, "/gateways/coap").
|
||||
ok.
|
||||
|
||||
t_gateway_lwm2m(_) ->
|
||||
{200, Gw} = request(get, "/gateways/lwm2m"),
|
||||
assert_gw_unloaded(Gw),
|
||||
%% post
|
||||
GwConf = #{
|
||||
name => <<"lwm2m">>,
|
||||
xml_dir => <<"../../lib/emqx_gateway/src/lwm2m/lwm2m_xml">>,
|
||||
|
@ -192,20 +232,18 @@ t_gateway_lwm2m(_) ->
|
|||
#{name => <<"def">>, type => <<"udp">>, bind => <<"5783">>}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/lwm2m", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/lwm2m"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
%% put
|
||||
GwConf2 = emqx_map_lib:deep_merge(GwConf, #{qmode_time_window => <<"10s">>}),
|
||||
{200, _} = request(put, "/gateways/lwm2m", maps:without([name, listeners], GwConf2)),
|
||||
{204, _} = request(put, "/gateways/lwm2m", maps:without([name, listeners], GwConf2)),
|
||||
{200, ConfResp2} = request(get, "/gateways/lwm2m"),
|
||||
assert_confs(GwConf2, ConfResp2),
|
||||
{204, _} = request(delete, "/gateways/lwm2m").
|
||||
ok.
|
||||
|
||||
t_gateway_exproto(_) ->
|
||||
{200, Gw} = request(get, "/gateways/exproto"),
|
||||
assert_gw_unloaded(Gw),
|
||||
%% post
|
||||
GwConf = #{
|
||||
name => <<"exproto">>,
|
||||
server => #{bind => <<"9100">>},
|
||||
|
@ -214,15 +252,14 @@ t_gateway_exproto(_) ->
|
|||
#{name => <<"def">>, type => <<"tcp">>, bind => <<"7993">>}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/exproto", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/exproto"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
%% put
|
||||
GwConf2 = emqx_map_lib:deep_merge(GwConf, #{server => #{bind => <<"9200">>}}),
|
||||
{200, _} = request(put, "/gateways/exproto", maps:without([name, listeners], GwConf2)),
|
||||
{204, _} = request(put, "/gateways/exproto", maps:without([name, listeners], GwConf2)),
|
||||
{200, ConfResp2} = request(get, "/gateways/exproto"),
|
||||
assert_confs(GwConf2, ConfResp2),
|
||||
{204, _} = request(delete, "/gateways/exproto").
|
||||
ok.
|
||||
|
||||
t_gateway_exproto_with_ssl(_) ->
|
||||
{200, Gw} = request(get, "/gateways/exproto"),
|
||||
|
@ -230,7 +267,6 @@ t_gateway_exproto_with_ssl(_) ->
|
|||
|
||||
SslSvrOpts = ssl_server_opts(),
|
||||
SslCliOpts = ssl_client_opts(),
|
||||
%% post
|
||||
GwConf = #{
|
||||
name => <<"exproto">>,
|
||||
server => #{
|
||||
|
@ -245,27 +281,22 @@ t_gateway_exproto_with_ssl(_) ->
|
|||
#{name => <<"def">>, type => <<"tcp">>, bind => <<"7993">>}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/exproto", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/exproto"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
%% put
|
||||
GwConf2 = emqx_map_lib:deep_merge(GwConf, #{
|
||||
server => #{
|
||||
bind => <<"9200">>,
|
||||
ssl_options => SslCliOpts
|
||||
}
|
||||
}),
|
||||
{200, _} = request(put, "/gateways/exproto", maps:without([name, listeners], GwConf2)),
|
||||
{204, _} = request(put, "/gateways/exproto", maps:without([name, listeners], GwConf2)),
|
||||
{200, ConfResp2} = request(get, "/gateways/exproto"),
|
||||
assert_confs(GwConf2, ConfResp2),
|
||||
{204, _} = request(delete, "/gateways/exproto").
|
||||
ok.
|
||||
|
||||
t_authn(_) ->
|
||||
GwConf = #{name => <<"stomp">>},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
ct:sleep(500),
|
||||
{204, _} = request(get, "/gateways/stomp/authentication"),
|
||||
|
||||
init_gw("stomp"),
|
||||
AuthConf = #{
|
||||
mechanism => <<"password_based">>,
|
||||
backend => <<"built_in_database">>,
|
||||
|
@ -283,22 +314,18 @@ t_authn(_) ->
|
|||
|
||||
{204, _} = request(delete, "/gateways/stomp/authentication"),
|
||||
{204, _} = request(get, "/gateways/stomp/authentication"),
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
t_authn_data_mgmt(_) ->
|
||||
GwConf = #{name => <<"stomp">>},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
ct:sleep(500),
|
||||
{204, _} = request(get, "/gateways/stomp/authentication"),
|
||||
|
||||
init_gw("stomp"),
|
||||
AuthConf = #{
|
||||
mechanism => <<"password_based">>,
|
||||
backend => <<"built_in_database">>,
|
||||
user_id_type => <<"clientid">>
|
||||
},
|
||||
{201, _} = request(post, "/gateways/stomp/authentication", AuthConf),
|
||||
ct:sleep(500),
|
||||
{200, ConfResp} = request(get, "/gateways/stomp/authentication"),
|
||||
{200, ConfResp} =
|
||||
?retry(10, 10, {200, _} = request(get, "/gateways/stomp/authentication")),
|
||||
assert_confs(AuthConf, ConfResp),
|
||||
|
||||
User1 = #{
|
||||
|
@ -358,11 +385,10 @@ t_authn_data_mgmt(_) ->
|
|||
|
||||
{204, _} = request(delete, "/gateways/stomp/authentication"),
|
||||
{204, _} = request(get, "/gateways/stomp/authentication"),
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
t_listeners_tcp(_) ->
|
||||
GwConf = #{name => <<"stomp">>},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/stomp", #{}),
|
||||
{404, _} = request(get, "/gateways/stomp/listeners"),
|
||||
LisConf = #{
|
||||
name => <<"def">>,
|
||||
|
@ -387,7 +413,7 @@ t_listeners_tcp(_) ->
|
|||
|
||||
{204, _} = request(delete, "/gateways/stomp/listeners/stomp:tcp:def"),
|
||||
{404, _} = request(get, "/gateways/stomp/listeners/stomp:tcp:def"),
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
t_listeners_authn(_) ->
|
||||
GwConf = #{
|
||||
|
@ -400,9 +426,7 @@ t_listeners_authn(_) ->
|
|||
}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
ct:sleep(500),
|
||||
{200, ConfResp} = request(get, "/gateways/stomp"),
|
||||
ConfResp = init_gw("stomp", GwConf),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
|
||||
AuthConf = #{
|
||||
|
@ -424,7 +448,7 @@ t_listeners_authn(_) ->
|
|||
{204, _} = request(delete, Path),
|
||||
%% FIXME: 204?
|
||||
{204, _} = request(get, Path),
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
t_listeners_authn_data_mgmt(_) ->
|
||||
GwConf = #{
|
||||
|
@ -437,7 +461,7 @@ t_listeners_authn_data_mgmt(_) ->
|
|||
}
|
||||
]
|
||||
},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(put, "/gateways/stomp", GwConf),
|
||||
{200, ConfResp} = request(get, "/gateways/stomp"),
|
||||
assert_confs(GwConf, ConfResp),
|
||||
|
||||
|
@ -514,13 +538,10 @@ t_listeners_authn_data_mgmt(_) ->
|
|||
{filename, "user-credentials.csv", CSVData}
|
||||
]),
|
||||
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
t_authn_fuzzy_search(_) ->
|
||||
GwConf = #{name => <<"stomp">>},
|
||||
{201, _} = request(post, "/gateways", GwConf),
|
||||
{204, _} = request(get, "/gateways/stomp/authentication"),
|
||||
|
||||
init_gw("stomp"),
|
||||
AuthConf = #{
|
||||
mechanism => <<"password_based">>,
|
||||
backend => <<"built_in_database">>,
|
||||
|
@ -561,7 +582,25 @@ t_authn_fuzzy_search(_) ->
|
|||
|
||||
{204, _} = request(delete, "/gateways/stomp/authentication"),
|
||||
{204, _} = request(get, "/gateways/stomp/authentication"),
|
||||
{204, _} = request(delete, "/gateways/stomp").
|
||||
ok.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Helpers
|
||||
|
||||
init_gw(GwName) ->
|
||||
init_gw(GwName, #{}).
|
||||
|
||||
init_gw(GwName, GwConf) ->
|
||||
{204, _} = request(put, "/gateways/" ++ GwName, GwConf),
|
||||
?retry(
|
||||
10,
|
||||
10,
|
||||
begin
|
||||
{200, #{status := Status} = RespConf} = request(get, "/gateways/" ++ GwName),
|
||||
false = (Status == <<"unloaded">>),
|
||||
RespConf
|
||||
end
|
||||
).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Asserts
|
||||
|
|
|
@ -94,7 +94,7 @@ maybe_unconvert_listeners(Conf) when is_map(Conf) ->
|
|||
maybe_unconvert_listeners(Conf) ->
|
||||
Conf.
|
||||
|
||||
assert_feilds_apperence(Ks, Map) ->
|
||||
assert_fields_exist(Ks, Map) ->
|
||||
lists:foreach(
|
||||
fun(K) ->
|
||||
_ = maps:get(K, Map)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
-import(
|
||||
emqx_gateway_test_utils,
|
||||
[
|
||||
assert_feilds_apperence/2,
|
||||
assert_fields_exist/2,
|
||||
request/2,
|
||||
request/3
|
||||
]
|
||||
|
@ -730,7 +730,7 @@ t_rest_clienit_info(_) ->
|
|||
binary_to_list(ClientId),
|
||||
{200, StompClient1} = request(get, ClientPath),
|
||||
?assertEqual(StompClient, StompClient1),
|
||||
assert_feilds_apperence(
|
||||
assert_fields_exist(
|
||||
[
|
||||
proto_name,
|
||||
awaiting_rel_max,
|
||||
|
@ -787,7 +787,7 @@ t_rest_clienit_info(_) ->
|
|||
|
||||
{200, Subs} = request(get, ClientPath ++ "/subscriptions"),
|
||||
?assertEqual(1, length(Subs)),
|
||||
assert_feilds_apperence([topic, qos], lists:nth(1, Subs)),
|
||||
assert_fields_exist([topic, qos], lists:nth(1, Subs)),
|
||||
|
||||
{201, _} = request(
|
||||
post,
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
- Enhance the `banned` feature [#9367](https://github.com/emqx/emqx/pull/9367).
|
||||
Now the corresponding session will be kicked when client is banned by `clientid`.
|
||||
|
||||
- Redesign `/gateways` API [9364](https://github.com/emqx/emqx/pull/9364).
|
||||
Use `PUT /gateways/{name}` instead of `POST /gateways`, gateway gets 'loaded'
|
||||
automatically if needed. Use `PUT /gateways/{name}/enable/{true|false}` to
|
||||
enable or disable gateway. No more `DELETE /gateways/{name}`.
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Return 404 for status of unknown authenticator in `/authenticator/{id}/status` [#9328](https://github.com/emqx/emqx/pull/9328).
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
- 增加 `封禁` 功能 [#9367](https://github.com/emqx/emqx/pull/9367)。
|
||||
现在客户端通过 `clientid` 被封禁时将会踢掉对应的会话。
|
||||
|
||||
- 重新设计了 /gateways API [9364](https://github.com/emqx/emqx/pull/9364)。
|
||||
使用 PUT /gateways/{name} 代替了 POST /gateways,现在网关将在需要时自动加载,然后删除了 DELETE /gateways/{name},之后可以使用 PUT /gateways/{name}/enable/{true|false} 来开启或禁用网关。
|
||||
|
||||
## 修复
|
||||
|
||||
- 通过 `/authenticator/{id}/status` 请求未知认证器的状态时,将会返回 404。
|
||||
|
|
Loading…
Reference in New Issue