• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

emqx / emqx / 12276826942

11 Dec 2024 12:56PM UTC coverage: 82.085%. First build
12276826942

Pull #14261

github

web-flow
Merge 463e84b8e into 38a83ed9b
Pull Request #14261: Multi-tenancy GA M1 `tns` to `clientid` index

177 of 208 new or added lines in 11 files covered. (85.1%)

56805 of 69203 relevant lines covered (82.08%)

15159.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.67
/apps/emqx_mt/src/emqx_mt_api.erl
1
%%--------------------------------------------------------------------
2
%% Copyright (c) 2024 EMQ Technologies Co., Ltd. All Rights Reserved.
3
%%--------------------------------------------------------------------
4
-module(emqx_mt_api).
5

6
-behaviour(minirest_api).
7

8
-include_lib("typerefl/include/types.hrl").
9
-include_lib("hocon/include/hoconsc.hrl").
10
-include_lib("emqx_utils/include/emqx_utils_api.hrl").
11
-include("emqx_mt.hrl").
12
%% -include_lib("emqx/include/logger.hrl").
13

14
%% `minirest' and `minirest_trails' API
15
-export([
16
    namespace/0,
17
    api_spec/0,
18
    fields/1,
19
    paths/0,
20
    schema/1
21
]).
22

23
%% `minirest' handlers
24
-export([
25
    ns_list/2,
26
    client_list/2,
27
    client_count/2
28
]).
29

30
%%-------------------------------------------------------------------------------------------------
31
%% Type definitions
32
%%-------------------------------------------------------------------------------------------------
33

34
-define(TAGS, [<<"Multi-tenancy">>]).
35

36
%%-------------------------------------------------------------------------------------------------
37
%% `minirest' and `minirest_trails' API
38
%%-------------------------------------------------------------------------------------------------
39

NEW
40
namespace() -> "mt".
×
41

42
api_spec() ->
43
    emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
27✔
44

45
paths() ->
46
    [
27✔
47
        "/mt/ns_list",
48
        "/mt/:ns/client_list",
49
        "/mt/:ns/client_count"
50
    ].
51

52
schema("/mt/ns_list") ->
53
    #{
29✔
54
        'operationId' => ns_list,
55
        get => #{
56
            tags => ?TAGS,
57
            summary => <<"List Namespaces">>,
58
            description => ?DESC("ns_list"),
59
            parameters => [
60
                last_ns_in_query(),
61
                limit_in_query()
62
            ],
63
            responses =>
64
                #{
65
                    200 =>
66
                        emqx_dashboard_swagger:schema_with_examples(
67
                            array(binary()),
68
                            example_ns_list()
69
                        )
70
                }
71
        }
72
    };
73
schema("/mt/:ns/client_list") ->
74
    #{
30✔
75
        'operationId' => client_list,
76
        get => #{
77
            tags => ?TAGS,
78
            summary => <<"List Clients in a Namespace">>,
79
            description => ?DESC("client_list"),
80
            parameters => [
81
                param_path_ns(),
82
                last_clientid_in_query(),
83
                limit_in_query()
84
            ],
85
            responses =>
86
                #{
87
                    200 =>
88
                        emqx_dashboard_swagger:schema_with_examples(
89
                            array(binary()),
90
                            example_client_list()
91
                        ),
92
                    404 => error_schema('NOT_FOUND', "Namespace not found")
93
                }
94
        }
95
    };
96
schema("/mt/:ns/client_count") ->
97
    #{
29✔
98
        'operationId' => client_count,
99
        get => #{
100
            tags => ?TAGS,
101
            summary => <<"Count Clients in a Namespace">>,
102
            description => ?DESC("client_count"),
103
            parameters => [param_path_ns()],
104
            responses =>
105
                #{
106
                    200 => [{count, mk(non_neg_integer(), #{desc => <<"Client count">>})}],
107
                    404 => error_schema('NOT_FOUND', "Namespace not found")
108
                }
109
        }
110
    }.
111

112
param_path_ns() ->
113
    {ns,
59✔
114
        mk(
115
            binary(),
116
            #{
117
                in => path,
118
                required => true,
119
                example => <<"ns1">>,
120
                desc => ?DESC("param_path_ns")
121
            }
122
        )}.
123

124
last_ns_in_query() ->
125
    {last_ns,
29✔
126
        mk(
127
            binary(),
128
            #{
129
                in => query,
130
                required => false,
131
                example => <<"ns1">>,
132
                desc => ?DESC("last_ns_in_query")
133
            }
134
        )}.
135

136
limit_in_query() ->
137
    {limit,
59✔
138
        mk(
139
            non_neg_integer(),
140
            #{
141
                in => query,
142
                required => false,
143
                example => 100,
144
                desc => ?DESC("limit_in_query")
145
            }
146
        )}.
147

148
last_clientid_in_query() ->
149
    {last_clientid,
30✔
150
        mk(
151
            binary(),
152
            #{
153
                in => query,
154
                required => false,
155
                example => <<"clientid1">>,
156
                desc => ?DESC("last_clientid_in_query")
157
            }
158
        )}.
159

160
%% no structs in this schema
NEW
161
fields(_) -> [].
×
162

163
mk(Type, Props) -> hoconsc:mk(Type, Props).
206✔
164

165
array(Type) -> hoconsc:array(Type).
59✔
166

167
error_schema(Code, Message) ->
168
    BinMsg = unicode:characters_to_binary(Message),
59✔
169
    emqx_dashboard_swagger:error_codes([Code], BinMsg).
59✔
170

171
%%-------------------------------------------------------------------------------------------------
172
%% `minirest' handlers
173
%%-------------------------------------------------------------------------------------------------
174

175
ns_list(get, Params) ->
176
    QS = maps:get(query_string, Params, #{}),
2✔
177
    LastNs = maps:get(<<"last_ns">>, QS, ?MIN_NS),
2✔
178
    Limit = maps:get(<<"limit">>, QS, ?DEFAULT_PAGE_SIZE),
2✔
179
    ?OK(emqx_mt:list_ns(LastNs, Limit)).
2✔
180

181
client_list(get, #{bindings := #{ns := Ns}} = Params) ->
182
    QS = maps:get(query_string, Params, #{}),
3✔
183
    LastClientId = maps:get(<<"last_clientid">>, QS, ?MIN_CLIENTID),
3✔
184
    Limit = maps:get(<<"limit">>, QS, ?DEFAULT_PAGE_SIZE),
3✔
185
    case emqx_mt:list_clients(Ns, LastClientId, Limit) of
3✔
186
        {ok, Clients} -> ?OK(Clients);
3✔
NEW
187
        {error, not_found} -> ?NOT_FOUND("Namespace not found")
×
188
    end.
189

190
client_count(get, #{bindings := #{ns := Ns}}) ->
191
    case emqx_mt:count_clients(Ns) of
2✔
192
        {ok, Count} -> ?OK(#{count => Count});
2✔
NEW
193
        {error, not_found} -> ?NOT_FOUND("Namespace not found")
×
194
    end.
195

196
%%-------------------------------------------------------------------------------------------------
197
%% helper functions
198
%%-------------------------------------------------------------------------------------------------
199
example_ns_list() ->
200
    #{
29✔
201
        <<"list">> =>
202
            #{
203
                summary => <<"List">>,
204
                value => [<<"ns1">>, <<"ns2">>]
205
            }
206
    }.
207

208
example_client_list() ->
209
    #{
30✔
210
        <<"list">> =>
211
            #{
212
                summary => <<"List">>,
213
                value => [<<"client1">>, <<"client2">>]
214
            }
215
    }.
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc