Jelajahi Sumber

feat(gw): return the created/updated resource info

JianBo He 4 tahun lalu
induk
melakukan
169848c027

+ 6 - 8
apps/emqx_gateway/src/emqx_gateway_api_authn.erl

@@ -82,17 +82,15 @@ authn(get, #{bindings := #{name := Name0}}) ->
 authn(put, #{bindings := #{name := Name0},
              body := Body}) ->
     with_gateway(Name0, fun(GwName, _) ->
-        %% TODO: return the authn instances?
-        ok = emqx_gateway_http:update_authn(GwName, Body),
-        {204}
+        {ok, Authn} = emqx_gateway_http:update_authn(GwName, Body),
+        {200, Authn}
     end);
 
 authn(post, #{bindings := #{name := Name0},
               body := Body}) ->
     with_gateway(Name0, fun(GwName, _) ->
-        %% TODO: return the authn instances?
-        ok = emqx_gateway_http:add_authn(GwName, Body),
-        {204}
+        {ok, Authn} = emqx_gateway_http:add_authn(GwName, Body),
+        {201, Authn}
     end);
 
 authn(delete, #{bindings := #{name := Name0}}) ->
@@ -181,7 +179,7 @@ schema("/gateway/:name/authentication") ->
                , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
                , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-               , 204 => <<"Updated">> %% XXX: ??? return the updated object
+               , 200 => schema_authn()
                }
           },
        post =>
@@ -193,7 +191,7 @@ schema("/gateway/:name/authentication") ->
                , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
                , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-               , 204 => <<"Added">>
+               , 201 => schema_authn()
                }
           },
        delete =>

+ 21 - 18
apps/emqx_gateway/src/emqx_gateway_api_listeners.erl

@@ -93,8 +93,9 @@ listeners(post, #{bindings := #{name := Name0}, body := LConf}) ->
             undefined ->
                 ListenerId = emqx_gateway_utils:listener_id(
                                GwName, Type, LName),
-                ok = emqx_gateway_http:add_listener(ListenerId, LConf),
-                {204};
+                {ok, RespConf} = emqx_gateway_http:add_listener(
+                                   ListenerId, LConf),
+                {201, RespConf};
             _ ->
                 return_http_error(400, "Listener name has occupied")
         end
@@ -123,8 +124,8 @@ listeners_insta(put, #{body := LConf,
                       }) ->
     ListenerId = emqx_mgmt_util:urldecode(ListenerId0),
     with_gateway(Name0, fun(_GwName, _) ->
-        ok = emqx_gateway_http:update_listener(ListenerId, LConf),
-        {204}
+        {ok, RespConf} = emqx_gateway_http:update_listener(ListenerId, LConf),
+        {200, RespConf}
     end).
 
 listeners_insta_authn(get, #{bindings := #{name := Name0,
@@ -145,16 +146,17 @@ listeners_insta_authn(post, #{body := Conf,
                                             id := ListenerId0}}) ->
     ListenerId = emqx_mgmt_util:urldecode(ListenerId0),
     with_gateway(Name0, fun(GwName, _) ->
-        ok = emqx_gateway_http:add_authn(GwName, ListenerId, Conf),
-        {204}
+        {ok, Authn} = emqx_gateway_http:add_authn(GwName, ListenerId, Conf),
+        {201, Authn}
     end);
 listeners_insta_authn(put, #{body := Conf,
                              bindings := #{name := Name0,
                                            id := ListenerId0}}) ->
     ListenerId = emqx_mgmt_util:urldecode(ListenerId0),
     with_gateway(Name0, fun(GwName, _) ->
-        ok = emqx_gateway_http:update_authn(GwName, ListenerId, Conf),
-        {204}
+        {ok, Authn} = emqx_gateway_http:update_authn(
+                        GwName, ListenerId, Conf),
+        {200, Authn}
     end);
 listeners_insta_authn(delete, #{bindings := #{name := Name0,
                                               id := ListenerId0}}) ->
@@ -246,7 +248,9 @@ schema("/gateway/:name/listeners") ->
               , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
               , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-              , 204 => <<"Created">>
+              , 201 => emqx_dashboard_swagger:schema_with_examples(
+                         ref(listener),
+                         examples_listener_list())
               }
           }
      };
@@ -290,7 +294,9 @@ schema("/gateway/:name/listeners/:id") ->
               , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
               , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-              , 200 => <<"Updated">>
+              , 200 => emqx_dashboard_swagger:schema_with_examples(
+                         ref(listener),
+                         examples_listener())
               }
           }
      };
@@ -319,7 +325,7 @@ schema("/gateway/:name/listeners/:id/authentication") ->
               , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
               , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-              , 204 => <<"Added">>
+              , 201 => schema_authn()
               }
           },
        put =>
@@ -332,7 +338,7 @@ schema("/gateway/:name/listeners/:id/authentication") ->
               , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
               , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-              , 204 => <<"Updated">>
+              , 200 => schema_authn()
               }
           },
        delete =>
@@ -344,7 +350,7 @@ schema("/gateway/:name/listeners/:id/authentication") ->
               , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
               , 500 => error_codes([?INTERNAL_ERROR],
                                    <<"Ineternal Server Error">>)
-              , 204 => <<"Deleted">>
+              , 200 => <<"Deleted">>
               }
           }
      };
@@ -431,9 +437,7 @@ schema("/gateway/:name/listeners/:id/authentication/users/:uid") ->
                 , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
                 , 500 => error_codes([?INTERNAL_ERROR],
                                      <<"Ineternal Server Error">>)
-                , 200 => emqx_dashboard_swagger:schema_with_example(
-                           ref(emqx_authn_api, response_user),
-                           emqx_authn_api:response_user_examples())
+                , 204 =>  <<"Deleted">>
                 }
            }
      };
@@ -451,8 +455,7 @@ schema("/gateway/:name/listeners/:id/authentication/import_users") ->
               #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>)
                , 404 => error_codes([?NOT_FOUND], <<"Not Found">>)
                , 500 => error_codes([?INTERNAL_ERROR],
-                                     <<"Ineternal Server Error">>)
-               %% XXX: Put a hint message into 204 return ?
+                                    <<"Ineternal Server Error">>)
                , 204 => <<"Imported">>
               }
           }

+ 72 - 33
apps/emqx_gateway/src/emqx_gateway_conf.erl

@@ -59,7 +59,8 @@
 -define(AUTHN_BIN, ?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_BINARY).
 
 -type atom_or_bin() :: atom() | binary().
--type ok_or_err() :: ok_or_err().
+-type ok_or_err() :: ok | {error, term()}.
+-type map_or_err() :: map() | {error, term()}.
 -type listener_ref() :: {ListenerType :: atom_or_bin(),
                          ListenerName :: atom_or_bin()}.
 
@@ -85,7 +86,8 @@ load_gateway(GwName, Conf) ->
                 {Ls, Conf1} ->
                     Conf1#{<<"listeners">> => unconvert_listeners(Ls)}
             end,
-    update({?FUNCTION_NAME, bin(GwName), NConf}).
+    %% TODO:
+    ret_ok_err(update({?FUNCTION_NAME, bin(GwName), NConf})).
 
 %% @doc convert listener array to map
 unconvert_listeners(Ls) when is_list(Ls) ->
@@ -111,13 +113,14 @@ update_gateway(GwName, Conf0) ->
     Exclude0 = [listeners, ?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_ATOM],
     Exclude1 = [atom_to_binary(K, utf8) || K <- Exclude0],
     Conf = maps:without(Exclude0 ++ Exclude1, Conf0),
-    update({?FUNCTION_NAME, bin(GwName), Conf}).
+
+    ret_ok_err(update({?FUNCTION_NAME, bin(GwName), Conf})).
 
 %% FIXME: delete cert files ??
 
 -spec unload_gateway(atom_or_bin()) -> ok_or_err().
 unload_gateway(GwName) ->
-    update({?FUNCTION_NAME, bin(GwName)}).
+    ret_ok_err(update({?FUNCTION_NAME, bin(GwName)})).
 
 %% @doc Get the gateway configurations.
 %% Missing fields are filled with default values. This function is typically
@@ -139,18 +142,20 @@ convert_listeners(GwName, Ls) when is_map(Ls) ->
     lists:append([do_convert_listener(GwName, Type, maps:to_list(Conf))
                   || {Type, Conf} <- maps:to_list(Ls)]).
 
-do_convert_listener(GwName, Type, Conf) ->
-    [begin
-         ListenerId = emqx_gateway_utils:listener_id(GwName, Type, LName),
-         Running = emqx_gateway_utils:is_running(ListenerId, LConf),
-         bind2str(
-           LConf#{
-             id => ListenerId,
-             type => Type,
-             name => LName,
-             running => Running
-            })
-     end || {LName, LConf} <- Conf, is_map(LConf)].
+do_convert_listener(GwName, LType, Conf) ->
+    [ do_convert_listener2(GwName, LType, LName, LConf)
+      || {LName, LConf} <- Conf, is_map(LConf)].
+
+do_convert_listener2(GwName, LType, LName, LConf) ->
+     ListenerId = emqx_gateway_utils:listener_id(GwName, LType, LName),
+     Running = emqx_gateway_utils:is_running(ListenerId, LConf),
+     bind2str(
+       LConf#{
+         id => ListenerId,
+         type => LType,
+         name => LName,
+         running => Running
+        }).
 
 bind2str(LConf = #{bind := Bind}) when is_integer(Bind) ->
     maps:put(bind, integer_to_binary(Bind), LConf);
@@ -194,48 +199,56 @@ listener(ListenerId) ->
             {error, Reason}
     end.
 
--spec add_listener(atom_or_bin(), listener_ref(), map()) -> ok_or_err().
+-spec add_listener(atom_or_bin(), listener_ref(), map()) -> map_or_err().
 add_listener(GwName, ListenerRef, Conf) ->
-    update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}).
+    ret_listener_or_err(
+      GwName, ListenerRef,
+      update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})).
 
--spec update_listener(atom_or_bin(), listener_ref(), map()) -> ok_or_err().
+-spec update_listener(atom_or_bin(), listener_ref(), map()) -> map_or_err().
 update_listener(GwName, ListenerRef, Conf) ->
-    update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}).
+    ret_listener_or_err(
+      GwName, ListenerRef,
+      update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})).
 
 -spec remove_listener(atom_or_bin(), listener_ref()) -> ok_or_err().
 remove_listener(GwName, ListenerRef) ->
-    update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)}).
+    ret_ok_err(update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)})).
 
--spec add_authn(atom_or_bin(), map()) -> ok_or_err().
+-spec add_authn(atom_or_bin(), map()) -> map_or_err().
 add_authn(GwName, Conf) ->
-    update({?FUNCTION_NAME, bin(GwName), Conf}).
+    ret_authn(GwName, update({?FUNCTION_NAME, bin(GwName), Conf})).
 
--spec add_authn(atom_or_bin(), listener_ref(), map()) -> ok_or_err().
+-spec add_authn(atom_or_bin(), listener_ref(), map()) -> map_or_err().
 add_authn(GwName, ListenerRef, Conf) ->
-    update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}).
+    ret_authn(
+      GwName, ListenerRef,
+      update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})).
 
--spec update_authn(atom_or_bin(), map()) -> ok_or_err().
+-spec update_authn(atom_or_bin(), map()) -> map_or_err().
 update_authn(GwName, Conf) ->
-    update({?FUNCTION_NAME, bin(GwName), Conf}).
+    ret_authn(GwName, update({?FUNCTION_NAME, bin(GwName), Conf})).
 
--spec update_authn(atom_or_bin(), listener_ref(), map()) -> ok_or_err().
+-spec update_authn(atom_or_bin(), listener_ref(), map()) -> map_or_err().
 update_authn(GwName, ListenerRef, Conf) ->
-    update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}).
+    ret_authn(
+      GwName, ListenerRef,
+      update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})).
 
 -spec remove_authn(atom_or_bin()) -> ok_or_err().
 remove_authn(GwName) ->
-    update({?FUNCTION_NAME, bin(GwName)}).
+    ret_ok_err(update({?FUNCTION_NAME, bin(GwName)})).
 
 -spec remove_authn(atom_or_bin(), listener_ref()) -> ok_or_err().
 remove_authn(GwName, ListenerRef) ->
-    update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)}).
+    ret_ok_err(update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)})).
 
 %% @private
 update(Req) ->
     res(emqx_conf:update([gateway], Req, #{override_to => cluster})).
 
-res({ok, _Result}) -> ok;
-res({error, {pre_config_update, emqx_gateway_conf, Reason}}) -> {error, Reason};
+res({ok, Result}) -> {ok, Result};
+res({error, {error, {pre_config_update,emqx_gateway_conf,Reason}}}) -> {error, Reason};
 res({error, Reason}) -> {error, Reason}.
 
 bin({LType, LName}) ->
@@ -245,6 +258,32 @@ bin(A) when is_atom(A) ->
 bin(B) when is_binary(B) ->
     B.
 
+ret_ok_err({ok, _}) -> ok;
+ret_ok_err(Err) -> Err.
+
+ret_authn(GwName, {ok, #{raw_config := GwConf}}) ->
+    Authn = emqx_map_lib:deep_get(
+              [bin(GwName), <<"authentication">>],
+              GwConf),
+    {ok, Authn};
+ret_authn(_GwName, Err) -> Err.
+
+ret_authn(GwName, {LType, LName}, {ok, #{raw_config := GwConf}}) ->
+    Authn = emqx_map_lib:deep_get(
+              [bin(GwName), <<"listeners">>, bin(LType),
+               bin(LName), <<"authentication">>],
+              GwConf),
+    {ok, Authn};
+ret_authn(_, _, Err) -> Err.
+
+ret_listener_or_err(GwName, {LType, LName}, {ok, #{raw_config := GwConf}}) ->
+    LConf = emqx_map_lib:deep_get(
+              [bin(GwName), <<"listeners">>, bin(LType), bin(LName)],
+              GwConf),
+    {ok, do_convert_listener2(GwName, LType, LName, LConf)};
+ret_listener_or_err(_, _, Err) ->
+    Err.
+
 %%--------------------------------------------------------------------
 %% Config Handler
 %%--------------------------------------------------------------------

+ 13 - 12
apps/emqx_gateway/src/emqx_gateway_http.erl

@@ -146,14 +146,14 @@ get_listeners_status(GwName, Config) ->
 %% Mgmt APIs - listeners
 %%--------------------------------------------------------------------
 
--spec add_listener(atom() | binary(), map()) -> ok.
+-spec add_listener(atom() | binary(), map()) -> {ok, map()}.
 add_listener(ListenerId, NewConf0) ->
     {GwName, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
     NewConf = maps:without([<<"id">>, <<"name">>,
                             <<"type">>, <<"running">>], NewConf0),
     confexp(emqx_gateway_conf:add_listener(GwName, {Type, Name}, NewConf)).
 
--spec update_listener(atom() | binary(), map()) -> ok.
+-spec update_listener(atom() | binary(), map()) -> {ok, map()}.
 update_listener(ListenerId, NewConf0) ->
     {GwName, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
 
@@ -194,23 +194,23 @@ wrap_chain_name(ChainName, Conf) ->
             Conf
     end.
 
--spec add_authn(gateway_name(), map()) -> ok.
+-spec add_authn(gateway_name(), map()) -> {ok, map()}.
 add_authn(GwName, AuthConf) ->
     confexp(emqx_gateway_conf:add_authn(GwName, AuthConf)).
 
--spec add_authn(gateway_name(), binary(), map()) -> ok.
+-spec add_authn(gateway_name(), binary(), map()) -> {ok, map()}.
 add_authn(GwName, ListenerId, AuthConf) ->
-    {_, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
-    confexp(emqx_gateway_conf:add_authn(GwName, {Type, Name}, AuthConf)).
+    {_, LType, LName} = emqx_gateway_utils:parse_listener_id(ListenerId),
+    confexp(emqx_gateway_conf:add_authn(GwName, {LType, LName}, AuthConf)).
 
--spec update_authn(gateway_name(), map()) -> ok.
+-spec update_authn(gateway_name(), map()) -> {ok, map()}.
 update_authn(GwName, AuthConf) ->
     confexp(emqx_gateway_conf:update_authn(GwName, AuthConf)).
 
--spec update_authn(gateway_name(), binary(), map()) -> ok.
+-spec update_authn(gateway_name(), binary(), map()) -> {ok, map()}.
 update_authn(GwName, ListenerId, AuthConf) ->
-    {_, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
-    confexp(emqx_gateway_conf:update_authn(GwName, {Type, Name}, AuthConf)).
+    {_, LType, LName} = emqx_gateway_utils:parse_listener_id(ListenerId),
+    confexp(emqx_gateway_conf:update_authn(GwName, {LType, LName}, AuthConf)).
 
 -spec remove_authn(gateway_name()) -> ok.
 remove_authn(GwName) ->
@@ -218,10 +218,11 @@ remove_authn(GwName) ->
 
 -spec remove_authn(gateway_name(), binary()) -> ok.
 remove_authn(GwName, ListenerId) ->
-    {_, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
-    confexp(emqx_gateway_conf:remove_authn(GwName, {Type, Name})).
+    {_, LType, LName} = emqx_gateway_utils:parse_listener_id(ListenerId),
+    confexp(emqx_gateway_conf:remove_authn(GwName, {LType, LName})).
 
 confexp(ok) -> ok;
+confexp({ok, Res}) -> {ok, Res};
 confexp({error, not_found}) ->
     error({update_conf_error, not_found});
 confexp({error, already_exist}) ->

+ 8 - 8
apps/emqx_gateway/test/emqx_gateway_api_SUITE.erl

@@ -196,12 +196,12 @@ t_authn(_) ->
                  backend => <<"built-in-database">>,
                  user_id_type => <<"clientid">>
                 },
-    {204, _} = request(post, "/gateway/stomp/authentication", AuthConf),
+    {201, _} = request(post, "/gateway/stomp/authentication", AuthConf),
     {200, ConfResp} = request(get, "/gateway/stomp/authentication"),
     assert_confs(AuthConf, ConfResp),
 
     AuthConf2 = maps:merge(AuthConf, #{user_id_type => <<"username">>}),
-    {204, _} = request(put, "/gateway/stomp/authentication", AuthConf2),
+    {200, _} = request(put, "/gateway/stomp/authentication", AuthConf2),
 
     {200, ConfResp2} = request(get, "/gateway/stomp/authentication"),
     assert_confs(AuthConf2, ConfResp2),
@@ -219,7 +219,7 @@ t_authn_data_mgmt(_) ->
                  backend => <<"built-in-database">>,
                  user_id_type => <<"clientid">>
                 },
-    {204, _} = request(post, "/gateway/stomp/authentication", AuthConf),
+    {201, _} = request(post, "/gateway/stomp/authentication", AuthConf),
     {200, ConfResp} = request(get, "/gateway/stomp/authentication"),
     assert_confs(AuthConf, ConfResp),
 
@@ -262,14 +262,14 @@ t_listeners(_) ->
                 type => <<"tcp">>,
                 bind => <<"61613">>
                },
-    {204, _} = request(post, "/gateway/stomp/listeners", LisConf),
+    {201, _} = request(post, "/gateway/stomp/listeners", LisConf),
     {200, ConfResp} = request(get, "/gateway/stomp/listeners"),
     assert_confs([LisConf], ConfResp),
     {200, ConfResp1} = request(get, "/gateway/stomp/listeners/stomp:tcp:def"),
     assert_confs(LisConf, ConfResp1),
 
     LisConf2 = maps:merge(LisConf, #{bind => <<"61614">>}),
-    {204, _} = request(
+    {200, _} = request(
                  put,
                  "/gateway/stomp/listeners/stomp:tcp:def",
                  LisConf2
@@ -298,12 +298,12 @@ t_listeners_authn(_) ->
                  user_id_type => <<"clientid">>
                 },
     Path = "/gateway/stomp/listeners/stomp:tcp:def/authentication",
-    {204, _} = request(post, Path, AuthConf),
+    {201, _} = request(post, Path, AuthConf),
     {200, ConfResp2} = request(get, Path),
     assert_confs(AuthConf, ConfResp2),
 
     AuthConf2 = maps:merge(AuthConf, #{user_id_type => <<"username">>}),
-    {204, _} = request(put, Path, AuthConf2),
+    {200, _} = request(put, Path, AuthConf2),
 
     {200, ConfResp3} = request(get, Path),
     assert_confs(AuthConf2, ConfResp3),
@@ -325,7 +325,7 @@ t_listeners_authn_data_mgmt(_) ->
                  user_id_type => <<"clientid">>
                 },
     Path = "/gateway/stomp/listeners/stomp:tcp:def/authentication",
-    {204, _} = request(post, Path, AuthConf),
+    {201, _} = request(post, Path, AuthConf),
     {200, ConfResp2} = request(get, Path),
     assert_confs(AuthConf, ConfResp2),