feat(ft-api): provide configuration API
To configure `emqx_ft` during the runtime.
This commit is contained in:
parent
34793c5ed0
commit
a2b03716be
|
@ -118,7 +118,7 @@
|
||||||
-type route_path() :: string() | binary().
|
-type route_path() :: string() | binary().
|
||||||
-type route_methods() :: map().
|
-type route_methods() :: map().
|
||||||
-type route_handler() :: atom().
|
-type route_handler() :: atom().
|
||||||
-type route_options() :: #{filter => filter() | undefined}.
|
-type route_options() :: #{filter => filter()}.
|
||||||
|
|
||||||
-type api_spec_entry() :: {route_path(), route_methods(), route_handler(), route_options()}.
|
-type api_spec_entry() :: {route_path(), route_methods(), route_handler(), route_options()}.
|
||||||
-type api_spec_component() :: map().
|
-type api_spec_component() :: map().
|
||||||
|
@ -137,10 +137,9 @@ spec(Module, Options) ->
|
||||||
{ApiSpec, AllRefs} =
|
{ApiSpec, AllRefs} =
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(Path, {AllAcc, AllRefsAcc}) ->
|
fun(Path, {AllAcc, AllRefsAcc}) ->
|
||||||
{OperationId, Specs, Refs} = parse_spec_ref(Module, Path, Options),
|
{OperationId, Specs, Refs, RouteOpts} = parse_spec_ref(Module, Path, Options),
|
||||||
Opts = #{filter => filter(Options)},
|
|
||||||
{
|
{
|
||||||
[{filename:join("/", Path), Specs, OperationId, Opts} | AllAcc],
|
[{filename:join("/", Path), Specs, OperationId, RouteOpts} | AllAcc],
|
||||||
Refs ++ AllRefsAcc
|
Refs ++ AllRefsAcc
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
|
@ -350,6 +349,7 @@ parse_spec_ref(Module, Path, Options) ->
|
||||||
),
|
),
|
||||||
error({failed_to_generate_swagger_spec, Module, Path})
|
error({failed_to_generate_swagger_spec, Module, Path})
|
||||||
end,
|
end,
|
||||||
|
OperationId = maps:get('operationId', Schema),
|
||||||
{Specs, Refs} = maps:fold(
|
{Specs, Refs} = maps:fold(
|
||||||
fun(Method, Meta, {Acc, RefsAcc}) ->
|
fun(Method, Meta, {Acc, RefsAcc}) ->
|
||||||
(not lists:member(Method, ?METHODS)) andalso
|
(not lists:member(Method, ?METHODS)) andalso
|
||||||
|
@ -358,9 +358,13 @@ parse_spec_ref(Module, Path, Options) ->
|
||||||
{Acc#{Method => Spec}, SubRefs ++ RefsAcc}
|
{Acc#{Method => Spec}, SubRefs ++ RefsAcc}
|
||||||
end,
|
end,
|
||||||
{#{}, []},
|
{#{}, []},
|
||||||
maps:without(['operationId'], Schema)
|
maps:without(['operationId', 'filter'], Schema)
|
||||||
),
|
),
|
||||||
{maps:get('operationId', Schema), Specs, Refs}.
|
RouteOpts = generate_route_opts(Schema, Options),
|
||||||
|
{OperationId, Specs, Refs, RouteOpts}.
|
||||||
|
|
||||||
|
generate_route_opts(Schema, Options) ->
|
||||||
|
#{filter => compose_filters(filter(Options), custom_filter(Schema))}.
|
||||||
|
|
||||||
check_parameters(Request, Spec, Module) ->
|
check_parameters(Request, Spec, Module) ->
|
||||||
#{bindings := Bindings, query_string := QueryStr} = Request,
|
#{bindings := Bindings, query_string := QueryStr} = Request,
|
||||||
|
|
|
@ -108,8 +108,12 @@ t_ref(_Config) ->
|
||||||
LocalPath = "/test/in/ref/local",
|
LocalPath = "/test/in/ref/local",
|
||||||
Path = "/test/in/ref",
|
Path = "/test/in/ref",
|
||||||
Expect = [#{<<"$ref">> => <<"#/components/parameters/emqx_swagger_parameter_SUITE.page">>}],
|
Expect = [#{<<"$ref">> => <<"#/components/parameters/emqx_swagger_parameter_SUITE.page">>}],
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, RouteOpts} = emqx_dashboard_swagger:parse_spec_ref(
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, LocalPath, #{}),
|
?MODULE, Path, #{}
|
||||||
|
),
|
||||||
|
{OperationId, Spec, Refs, RouteOpts} = emqx_dashboard_swagger:parse_spec_ref(
|
||||||
|
?MODULE, LocalPath, #{}
|
||||||
|
),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
Params = maps:get(parameters, maps:get(post, Spec)),
|
Params = maps:get(parameters, maps:get(post, Spec)),
|
||||||
?assertEqual(Expect, Params),
|
?assertEqual(Expect, Params),
|
||||||
|
@ -122,7 +126,7 @@ t_public_ref(_Config) ->
|
||||||
#{<<"$ref">> => <<"#/components/parameters/public.page">>},
|
#{<<"$ref">> => <<"#/components/parameters/public.page">>},
|
||||||
#{<<"$ref">> => <<"#/components/parameters/public.limit">>}
|
#{<<"$ref">> => <<"#/components/parameters/public.limit">>}
|
||||||
],
|
],
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
Params = maps:get(parameters, maps:get(post, Spec)),
|
Params = maps:get(parameters, maps:get(post, Spec)),
|
||||||
?assertEqual(Expect, Params),
|
?assertEqual(Expect, Params),
|
||||||
|
@ -264,7 +268,7 @@ t_nullable(_Config) ->
|
||||||
t_method(_Config) ->
|
t_method(_Config) ->
|
||||||
PathOk = "/method/ok",
|
PathOk = "/method/ok",
|
||||||
PathError = "/method/error",
|
PathError = "/method/error",
|
||||||
{test, Spec, []} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, PathOk, #{}),
|
{test, Spec, [], #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, PathOk, #{}),
|
||||||
?assertEqual(lists:sort(?METHODS), lists:sort(maps:keys(Spec))),
|
?assertEqual(lists:sort(?METHODS), lists:sort(maps:keys(Spec))),
|
||||||
?assertThrow(
|
?assertThrow(
|
||||||
{error, #{module := ?MODULE, path := PathError, method := bar}},
|
{error, #{module := ?MODULE, path := PathError, method := bar}},
|
||||||
|
@ -393,7 +397,7 @@ assert_all_filters_equal(Spec, Filter) ->
|
||||||
).
|
).
|
||||||
|
|
||||||
validate(Path, ExpectParams) ->
|
validate(Path, ExpectParams) ->
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
Params = maps:get(parameters, maps:get(post, Spec)),
|
Params = maps:get(parameters, maps:get(post, Spec)),
|
||||||
?assertEqual(ExpectParams, Params),
|
?assertEqual(ExpectParams, Params),
|
||||||
|
|
|
@ -719,7 +719,7 @@ t_object_trans_error(_Config) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
validate(Path, ExpectSpec, ExpectRefs) ->
|
validate(Path, ExpectSpec, ExpectRefs) ->
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
?assertEqual(ExpectSpec, Spec),
|
?assertEqual(ExpectSpec, Spec),
|
||||||
?assertEqual(ExpectRefs, Refs),
|
?assertEqual(ExpectRefs, Refs),
|
||||||
|
|
|
@ -129,7 +129,7 @@ t_error(_Config) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
Response = maps:get(responses, maps:get(get, Spec)),
|
Response = maps:get(responses, maps:get(get, Spec)),
|
||||||
?assertEqual(Error400, maps:get(<<"400">>, Response)),
|
?assertEqual(Error400, maps:get(<<"400">>, Response)),
|
||||||
|
@ -375,7 +375,7 @@ t_complicated_type(_Config) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
Response = maps:get(responses, maps:get(post, Spec)),
|
Response = maps:get(responses, maps:get(post, Spec)),
|
||||||
?assertEqual(Object, maps:get(<<"200">>, Response)),
|
?assertEqual(Object, maps:get(<<"200">>, Response)),
|
||||||
|
@ -665,7 +665,7 @@ schema("/fields/sub") ->
|
||||||
to_schema(hoconsc:ref(sub_fields)).
|
to_schema(hoconsc:ref(sub_fields)).
|
||||||
|
|
||||||
validate(Path, ExpectObject, ExpectRefs) ->
|
validate(Path, ExpectObject, ExpectRefs) ->
|
||||||
{OperationId, Spec, Refs} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
{OperationId, Spec, Refs, #{}} = emqx_dashboard_swagger:parse_spec_ref(?MODULE, Path, #{}),
|
||||||
?assertEqual(test, OperationId),
|
?assertEqual(test, OperationId),
|
||||||
Response = maps:get(responses, maps:get(post, Spec)),
|
Response = maps:get(responses, maps:get(post, Spec)),
|
||||||
?assertEqual(ExpectObject, maps:get(<<"200">>, Response)),
|
?assertEqual(ExpectObject, maps:get(<<"200">>, Response)),
|
||||||
|
|
|
@ -40,27 +40,30 @@
|
||||||
%% API callbacks
|
%% API callbacks
|
||||||
-export([
|
-export([
|
||||||
'/file_transfer/files'/2,
|
'/file_transfer/files'/2,
|
||||||
'/file_transfer/files/:clientid/:fileid'/2
|
'/file_transfer/files/:clientid/:fileid'/2,
|
||||||
|
'/file_transfer'/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-import(hoconsc, [mk/2, ref/1, ref/2]).
|
-import(hoconsc, [mk/2, ref/1, ref/2]).
|
||||||
|
|
||||||
|
-define(SCHEMA_CONFIG, ref(emqx_ft_schema, file_transfer)).
|
||||||
|
|
||||||
namespace() -> "file_transfer".
|
namespace() -> "file_transfer".
|
||||||
|
|
||||||
api_spec() ->
|
api_spec() ->
|
||||||
emqx_dashboard_swagger:spec(?MODULE, #{
|
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
|
||||||
check_schema => true, filter => fun ?MODULE:check_ft_enabled/2
|
|
||||||
}).
|
|
||||||
|
|
||||||
paths() ->
|
paths() ->
|
||||||
[
|
[
|
||||||
"/file_transfer/files",
|
"/file_transfer/files",
|
||||||
"/file_transfer/files/:clientid/:fileid"
|
"/file_transfer/files/:clientid/:fileid",
|
||||||
|
"/file_transfer"
|
||||||
].
|
].
|
||||||
|
|
||||||
schema("/file_transfer/files") ->
|
schema("/file_transfer/files") ->
|
||||||
#{
|
#{
|
||||||
'operationId' => '/file_transfer/files',
|
'operationId' => '/file_transfer/files',
|
||||||
|
filter => fun ?MODULE:check_ft_enabled/2,
|
||||||
get => #{
|
get => #{
|
||||||
tags => ?TAGS,
|
tags => ?TAGS,
|
||||||
summary => <<"List all uploaded files">>,
|
summary => <<"List all uploaded files">>,
|
||||||
|
@ -83,6 +86,7 @@ schema("/file_transfer/files") ->
|
||||||
schema("/file_transfer/files/:clientid/:fileid") ->
|
schema("/file_transfer/files/:clientid/:fileid") ->
|
||||||
#{
|
#{
|
||||||
'operationId' => '/file_transfer/files/:clientid/:fileid',
|
'operationId' => '/file_transfer/files/:clientid/:fileid',
|
||||||
|
filter => fun ?MODULE:check_ft_enabled/2,
|
||||||
get => #{
|
get => #{
|
||||||
tags => ?TAGS,
|
tags => ?TAGS,
|
||||||
summary => <<"List files uploaded in a specific transfer">>,
|
summary => <<"List files uploaded in a specific transfer">>,
|
||||||
|
@ -101,6 +105,36 @@ schema("/file_transfer/files/:clientid/:fileid") ->
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
schema("/file_transfer") ->
|
||||||
|
#{
|
||||||
|
'operationId' => '/file_transfer',
|
||||||
|
get => #{
|
||||||
|
tags => [<<"file_transfer">>],
|
||||||
|
summary => <<"Get current File Transfer configuration">>,
|
||||||
|
description => ?DESC("file_transfer_get_config"),
|
||||||
|
responses => #{
|
||||||
|
200 => ?SCHEMA_CONFIG,
|
||||||
|
503 => emqx_dashboard_swagger:error_codes(
|
||||||
|
['SERVICE_UNAVAILABLE'], error_desc('SERVICE_UNAVAILABLE')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
put => #{
|
||||||
|
tags => [<<"file_transfer">>],
|
||||||
|
summary => <<"Update File Transfer configuration">>,
|
||||||
|
description => ?DESC("file_transfer_update_config"),
|
||||||
|
'requestBody' => ?SCHEMA_CONFIG,
|
||||||
|
responses => #{
|
||||||
|
200 => ?SCHEMA_CONFIG,
|
||||||
|
400 => emqx_dashboard_swagger:error_codes(
|
||||||
|
['INVALID_CONFIG'], error_desc('INVALID_CONFIG')
|
||||||
|
),
|
||||||
|
503 => emqx_dashboard_swagger:error_codes(
|
||||||
|
['SERVICE_UNAVAILABLE'], error_desc('SERVICE_UNAVAILABLE')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}.
|
}.
|
||||||
|
|
||||||
check_ft_enabled(Params, _Meta) ->
|
check_ft_enabled(Params, _Meta) ->
|
||||||
|
@ -108,7 +142,7 @@ check_ft_enabled(Params, _Meta) ->
|
||||||
true ->
|
true ->
|
||||||
{ok, Params};
|
{ok, Params};
|
||||||
false ->
|
false ->
|
||||||
{503, error_msg('SERVICE_UNAVAILABLE', <<"Service unavailable">>)}
|
{503, error_msg('SERVICE_UNAVAILABLE')}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
'/file_transfer/files'(get, #{
|
'/file_transfer/files'(get, #{
|
||||||
|
@ -147,6 +181,18 @@ check_ft_enabled(Params, _Meta) ->
|
||||||
{503, error_msg('SERVICE_UNAVAILABLE')}
|
{503, error_msg('SERVICE_UNAVAILABLE')}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
'/file_transfer'(get, _Meta) ->
|
||||||
|
{200, format_config(emqx_ft_conf:get())};
|
||||||
|
'/file_transfer'(put, #{body := ConfigIn}) ->
|
||||||
|
case emqx_ft_conf:update(ConfigIn) of
|
||||||
|
{ok, #{config := Config}} ->
|
||||||
|
{200, format_config(Config)};
|
||||||
|
{error, Error = #{kind := validation_error}} ->
|
||||||
|
{400, error_msg('INVALID_CONFIG', format_validation_error(Error))};
|
||||||
|
{error, Error} ->
|
||||||
|
{400, error_msg('INVALID_CONFIG', emqx_utils:format(Error))}
|
||||||
|
end.
|
||||||
|
|
||||||
format_page(#{items := Files, cursor := Cursor}) ->
|
format_page(#{items := Files, cursor := Cursor}) ->
|
||||||
#{
|
#{
|
||||||
<<"files">> => lists:map(fun format_file_info/1, Files),
|
<<"files">> => lists:map(fun format_file_info/1, Files),
|
||||||
|
@ -157,14 +203,23 @@ format_page(#{items := Files}) ->
|
||||||
<<"files">> => lists:map(fun format_file_info/1, Files)
|
<<"files">> => lists:map(fun format_file_info/1, Files)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
|
format_config(Config) ->
|
||||||
|
Schema = emqx_hocon:make_schema(emqx_ft_schema:fields(file_transfer)),
|
||||||
|
hocon_tconf:make_serializable(Schema, emqx_utils_maps:binary_key_map(Config), #{}).
|
||||||
|
|
||||||
|
format_validation_error(Error) ->
|
||||||
|
emqx_logger_jsonfmt:best_effort_json(Error).
|
||||||
|
|
||||||
error_msg(Code) ->
|
error_msg(Code) ->
|
||||||
#{code => Code, message => error_desc(Code)}.
|
#{code => Code, message => error_desc(Code)}.
|
||||||
|
|
||||||
error_msg(Code, Msg) ->
|
error_msg(Code, Msg) ->
|
||||||
#{code => Code, message => emqx_utils:readable_error_msg(Msg)}.
|
#{code => Code, message => Msg}.
|
||||||
|
|
||||||
error_desc('FILES_NOT_FOUND') ->
|
error_desc('FILES_NOT_FOUND') ->
|
||||||
<<"Files requested for this transfer could not be found">>;
|
<<"Files requested for this transfer could not be found">>;
|
||||||
|
error_desc('INVALID_CONFIG') ->
|
||||||
|
<<"Provided configuration is invalid">>;
|
||||||
error_desc('SERVICE_UNAVAILABLE') ->
|
error_desc('SERVICE_UNAVAILABLE') ->
|
||||||
<<"Service unavailable">>.
|
<<"Service unavailable">>.
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,11 @@ init_per_testcase(Case, Config) ->
|
||||||
[{tc, Case} | Config].
|
[{tc, Case} | Config].
|
||||||
end_per_testcase(t_ft_disabled, _Config) ->
|
end_per_testcase(t_ft_disabled, _Config) ->
|
||||||
emqx_config:put([file_transfer, enable], true);
|
emqx_config:put([file_transfer, enable], true);
|
||||||
|
end_per_testcase(t_configure, Config) ->
|
||||||
|
{ok, 200, _} = request(put, uri(["file_transfer"]), #{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => emqx_ft_test_helpers:local_storage(Config)
|
||||||
|
});
|
||||||
end_per_testcase(_Case, _Config) ->
|
end_per_testcase(_Case, _Config) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
@ -310,6 +315,155 @@ t_ft_disabled(Config) ->
|
||||||
)
|
)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
t_configure(Config) ->
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 200, #{<<"enable">> := true, <<"storage">> := #{}}},
|
||||||
|
request_json(get, uri(["file_transfer"]), Config)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 200, #{<<"enable">> := false}},
|
||||||
|
request_json(put, uri(["file_transfer"]), #{<<"enable">> => false}, Config)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 200, #{<<"enable">> := false}},
|
||||||
|
request_json(get, uri(["file_transfer"]), Config)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 200, #{}},
|
||||||
|
request_json(
|
||||||
|
put,
|
||||||
|
uri(["file_transfer"]),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => emqx_ft_test_helpers:local_storage(Config)
|
||||||
|
},
|
||||||
|
Config
|
||||||
|
)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 400, _},
|
||||||
|
request(
|
||||||
|
put,
|
||||||
|
uri(["file_transfer"]),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => #{
|
||||||
|
<<"local">> => #{},
|
||||||
|
<<"remote">> => #{}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Config
|
||||||
|
)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 400, _},
|
||||||
|
request(
|
||||||
|
put,
|
||||||
|
uri(["file_transfer"]),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => #{
|
||||||
|
<<"local">> => #{
|
||||||
|
<<"gc">> => #{<<"interval">> => -42}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Config
|
||||||
|
)
|
||||||
|
),
|
||||||
|
S3Exporter = #{
|
||||||
|
<<"host">> => <<"localhost">>,
|
||||||
|
<<"port">> => 9000,
|
||||||
|
<<"bucket">> => <<"emqx">>,
|
||||||
|
<<"transport_options">> => #{
|
||||||
|
<<"ssl">> => #{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"certfile">> => emqx_ft_test_helpers:pem_privkey(),
|
||||||
|
<<"keyfile">> => emqx_ft_test_helpers:pem_privkey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 200, #{
|
||||||
|
<<"enable">> := true,
|
||||||
|
<<"storage">> := #{
|
||||||
|
<<"local">> := #{
|
||||||
|
<<"exporter">> := #{
|
||||||
|
<<"s3">> := #{
|
||||||
|
<<"transport_options">> := #{
|
||||||
|
<<"ssl">> := #{
|
||||||
|
<<"enable">> := true,
|
||||||
|
<<"certfile">> := <<"/", _CertFilepath/bytes>>,
|
||||||
|
<<"keyfile">> := <<"/", _KeyFilepath/bytes>>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
request_json(
|
||||||
|
put,
|
||||||
|
uri(["file_transfer"]),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => #{
|
||||||
|
<<"local">> => #{
|
||||||
|
<<"exporter">> => #{
|
||||||
|
<<"s3">> => S3Exporter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Config
|
||||||
|
)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 400, _},
|
||||||
|
request_json(
|
||||||
|
put,
|
||||||
|
uri(["file_transfer"]),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => #{
|
||||||
|
<<"local">> => #{
|
||||||
|
<<"exporter">> => #{
|
||||||
|
<<"s3">> => emqx_utils_maps:deep_put(
|
||||||
|
[<<"transport_options">>, <<"ssl">>, <<"keyfile">>],
|
||||||
|
S3Exporter,
|
||||||
|
<<>>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Config
|
||||||
|
)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, 200, #{}},
|
||||||
|
request_json(
|
||||||
|
put,
|
||||||
|
uri(["file_transfer"]),
|
||||||
|
#{
|
||||||
|
<<"enable">> => true,
|
||||||
|
<<"storage">> => #{
|
||||||
|
<<"local">> => #{
|
||||||
|
<<"exporter">> => #{
|
||||||
|
<<"s3">> => emqx_utils_maps:deep_put(
|
||||||
|
[<<"transport_options">>, <<"ssl">>, <<"enable">>],
|
||||||
|
S3Exporter,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Config
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ok.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Helpers
|
%% Helpers
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -332,17 +486,26 @@ mk_file_name(N) ->
|
||||||
"file." ++ integer_to_list(N).
|
"file." ++ integer_to_list(N).
|
||||||
|
|
||||||
request(Method, Url, Config) ->
|
request(Method, Url, Config) ->
|
||||||
Opts = #{compatible_mode => true, httpc_req_opts => [{body_format, binary}]},
|
request(Method, Url, [], Config).
|
||||||
emqx_mgmt_api_test_util:request_api(Method, Url, [], auth_header(Config), [], Opts).
|
|
||||||
|
|
||||||
request_json(Method, Url, Config) ->
|
request(Method, Url, Body, Config) ->
|
||||||
case request(Method, Url, Config) of
|
Opts = #{compatible_mode => true, httpc_req_opts => [{body_format, binary}]},
|
||||||
|
request(Method, Url, Body, Opts, Config).
|
||||||
|
|
||||||
|
request(Method, Url, Body, Opts, Config) ->
|
||||||
|
emqx_mgmt_api_test_util:request_api(Method, Url, Body, auth_header(Config), [], Opts).
|
||||||
|
|
||||||
|
request_json(Method, Url, Body, Config) ->
|
||||||
|
case request(Method, Url, Body, [], Config) of
|
||||||
{ok, Code, Body} ->
|
{ok, Code, Body} ->
|
||||||
{ok, Code, json(Body)};
|
{ok, Code, json(Body)};
|
||||||
Otherwise ->
|
Otherwise ->
|
||||||
Otherwise
|
Otherwise
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
request_json(Method, Url, Config) ->
|
||||||
|
request_json(Method, Url, [], Config).
|
||||||
|
|
||||||
json(Body) when is_binary(Body) ->
|
json(Body) when is_binary(Body) ->
|
||||||
emqx_utils_json:decode(Body, [return_maps]).
|
emqx_utils_json:decode(Body, [return_maps]).
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,8 @@
|
||||||
safe_filename/1,
|
safe_filename/1,
|
||||||
diff_lists/3,
|
diff_lists/3,
|
||||||
merge_lists/3,
|
merge_lists/3,
|
||||||
tcp_keepalive_opts/4
|
tcp_keepalive_opts/4,
|
||||||
|
format/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
|
@ -525,6 +526,9 @@ tcp_keepalive_opts({unix, darwin}, Idle, Interval, Probes) ->
|
||||||
tcp_keepalive_opts(OS, _Idle, _Interval, _Probes) ->
|
tcp_keepalive_opts(OS, _Idle, _Interval, _Probes) ->
|
||||||
{error, {unsupported_os, OS}}.
|
{error, {unsupported_os, OS}}.
|
||||||
|
|
||||||
|
format(Term) ->
|
||||||
|
iolist_to_binary(io_lib:format("~0p", [Term])).
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% Internal Functions
|
%% Internal Functions
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
@ -606,7 +610,7 @@ to_hr_error({not_authorized, _}) ->
|
||||||
to_hr_error({malformed_username_or_password, _}) ->
|
to_hr_error({malformed_username_or_password, _}) ->
|
||||||
<<"Bad username or password">>;
|
<<"Bad username or password">>;
|
||||||
to_hr_error(Error) ->
|
to_hr_error(Error) ->
|
||||||
iolist_to_binary(io_lib:format("~0p", [Error])).
|
format(Error).
|
||||||
|
|
||||||
try_to_existing_atom(Convert, Data, Encoding) ->
|
try_to_existing_atom(Convert, Data, Encoding) ->
|
||||||
try Convert(Data, Encoding) of
|
try Convert(Data, Encoding) of
|
||||||
|
|
|
@ -6,6 +6,12 @@ file_list.desc:
|
||||||
file_list_transfer.desc:
|
file_list_transfer.desc:
|
||||||
"""List a file uploaded during specified transfer, identified by client id and file id."""
|
"""List a file uploaded during specified transfer, identified by client id and file id."""
|
||||||
|
|
||||||
|
file_transfer_get_config.desc:
|
||||||
|
"""Show current File Transfer configuration."""
|
||||||
|
|
||||||
|
file_transfer_update_config.desc:
|
||||||
|
"""Replace File Transfer configuration."""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emqx_ft_storage_exporter_fs_api {
|
emqx_ft_storage_exporter_fs_api {
|
||||||
|
|
Loading…
Reference in New Issue