diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl
index c4f77b9a0..4a15597f0 100644
--- a/apps/emqx/src/emqx_schema.erl
+++ b/apps/emqx/src/emqx_schema.erl
@@ -157,9 +157,6 @@ roots(low) ->
, {"quota",
sc(ref("quota"),
#{})}
- , {"plugins", %% TODO: move to emqx_conf_schema
- sc(ref("plugins"),
- #{})}
, {"stats",
sc(ref("stats"),
#{})}
@@ -797,13 +794,6 @@ fields("deflate_opts") ->
}
];
-fields("plugins") ->
- [ {"expand_plugins_dir",
- sc(string(),
- #{})
- }
- ];
-
fields("broker") ->
[ {"sys_msg_interval",
sc(hoconsc:union([disabled, duration()]),
diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl
index 9f03d1e7f..3136bf557 100644
--- a/apps/emqx_conf/src/emqx_conf_schema.erl
+++ b/apps/emqx_conf/src/emqx_conf_schema.erl
@@ -50,6 +50,7 @@
, emqx_authz_schema
, emqx_auto_subscribe_schema
, emqx_modules_schema
+ , emqx_plugins_schema
, emqx_dashboard_schema
, emqx_gateway_schema
, emqx_prometheus_schema
diff --git a/apps/emqx_plugins/etc/emqx_plugins.conf b/apps/emqx_plugins/etc/emqx_plugins.conf
new file mode 100644
index 000000000..35f02a9f8
--- /dev/null
+++ b/apps/emqx_plugins/etc/emqx_plugins.conf
@@ -0,0 +1,7 @@
+plugins {
+ prebuilt {
+ }
+ external {
+ }
+ install_dir = "plugins"
+}
diff --git a/apps/emqx_plugins/src/emqx_plugins.app.src b/apps/emqx_plugins/src/emqx_plugins.app.src
new file mode 100644
index 000000000..a772f219f
--- /dev/null
+++ b/apps/emqx_plugins/src/emqx_plugins.app.src
@@ -0,0 +1,9 @@
+%% -*- mode: erlang -*-
+{application, emqx_plugins,
+ [{description, "EMQ X Plugin Management"},
+ {vsn, "0.1.0"},
+ {modules, []},
+ {mod, {emqx_plugins_app,[]}},
+ {applications, [kernel,stdlib,emqx]},
+ {env, []}
+ ]}.
diff --git a/apps/emqx_plugins/src/emqx_plugins.appup.src b/apps/emqx_plugins/src/emqx_plugins.appup.src
new file mode 100644
index 000000000..f9474dd33
--- /dev/null
+++ b/apps/emqx_plugins/src/emqx_plugins.appup.src
@@ -0,0 +1,8 @@
+%% -*- mode: erlang -*-
+{"0.1.0",
+ [ {<<".*">>, []}
+ ],
+ [
+ {<<".*">>, []}
+ ]
+}.
diff --git a/apps/emqx/src/emqx_plugins.erl b/apps/emqx_plugins/src/emqx_plugins.erl
similarity index 98%
rename from apps/emqx/src/emqx_plugins.erl
rename to apps/emqx_plugins/src/emqx_plugins.erl
index c28ead717..003ca7ec3 100644
--- a/apps/emqx/src/emqx_plugins.erl
+++ b/apps/emqx_plugins/src/emqx_plugins.erl
@@ -16,9 +16,8 @@
-module(emqx_plugins).
--include("emqx.hrl").
--include("logger.hrl").
-
+-include_lib("emqx/include/emqx.hrl").
+-include_lib("emqx/include/logger.hrl").
-export([ load/0
, load/1
@@ -41,7 +40,7 @@
%% @doc Load all plugins when the broker started.
-spec(load() -> ok | ignore | {error, term()}).
load() ->
- ok = load_ext_plugins(emqx:get_config([plugins, expand_plugins_dir], undefined)).
+ ok = load_ext_plugins(emqx:get_config([plugins, install_dir], undefined)).
%% @doc Load a Plugin
-spec(load(atom()) -> ok | {error, term()}).
diff --git a/apps/emqx_plugins/src/emqx_plugins_app.erl b/apps/emqx_plugins/src/emqx_plugins_app.erl
new file mode 100644
index 000000000..c04fbb445
--- /dev/null
+++ b/apps/emqx_plugins/src/emqx_plugins_app.erl
@@ -0,0 +1,30 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_plugins_app).
+
+-behaviour(application).
+
+-export([ start/2
+ , stop/1
+ ]).
+
+start(_Type, _Args) ->
+ {ok, Sup} = emqx_plugins_sup:start_link(),
+ {ok, Sup}.
+
+stop(_State) ->
+ ok.
diff --git a/apps/emqx_plugins/src/emqx_plugins_schema.erl b/apps/emqx_plugins/src/emqx_plugins_schema.erl
new file mode 100644
index 000000000..7b7b3c15e
--- /dev/null
+++ b/apps/emqx_plugins/src/emqx_plugins_schema.erl
@@ -0,0 +1,94 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_plugins_schema).
+
+-behaviour(hocon_schema).
+
+-export([ roots/0
+ , fields/1
+ ]).
+
+-include_lib("typerefl/include/types.hrl").
+
+roots() -> ["plugins"].
+
+fields("plugins") ->
+ #{fields => fields(),
+ desc => """
+Manage EMQ X plugins.
+
+Plugins can be pre-built as a part of EMQ X package,
+or installed as a standalone package to the specific directory.
+The standalone-installed plugins are referred to as 'external' plugins.
+"""
+ }.
+
+fields() ->
+ [ {prebuilt, fun prebuilt/1}
+ , {external, fun external/1}
+ , {install_dir, fun install_dir/1}
+ ].
+
+prebuilt(type) -> hoconsc:map("name", boolean());
+prebuilt(nullable) -> true;
+prebuilt(T) when T=/= desc -> undefined;
+prebuilt(desc) -> """
+A map() from plugin name to a boolean (true | false) flag to indicate
+whether or not to enable the prebuilt plugin.
+
+Most of the prebuilt plugins from 4.x are converted into features since 5.0.
+""" ++ prebuilt_plugins() ++
+"""
+
+Enabled plugins are loaded (started) as a part of EMQ X node's boot sequence.
+Plugins can be loaded on the fly, and enabled from dashbaord UI and/or CLI.
+
+Example config: {emqx_foo_bar: true, emqx_bazz: false}
+""".
+
+external(type) -> hoconsc:map("name", string());
+external(nullable) -> true;
+external(T) when T =/= desc -> undefined;
+external(desc) ->
+"""
+A map from plugin name to a version number string for enabled ones.
+To disable an external plugin, set the value to 'false'.
+
+Enabled plugins are loaded (started) as a part of EMQ X node's boot sequence.
+Plugins can be loaded on the fly, and enabled from dashbaord UI and/or CLI.
+
+Example config: {emqx_extplug1: \"0.1.0\", emqx_extplug2: false}
+""".
+
+install_dir(type) -> string();
+install_dir(nullable) -> true;
+install_dir(default) -> "plugins"; %% runner's root dir
+install_dir(T) when T =/= desc -> undefined;
+install_dir(desc) -> """
+In which directory are the external plugins installed.
+The plugin beam files and configuration files should reside in
+the sub-directory named as emqx_foo_bar-0.1.0
.
+""".
+
+%% TODO: when we have some prebuilt plugins, change this function to:
+%% """
+%% The names should be one of
+%% - name1
+%% - name2
+%% """
+prebuilt_plugins() ->
+ "So far, we do not have any prebuilt plugins".
diff --git a/apps/emqx_plugins/src/emqx_plugins_sup.erl b/apps/emqx_plugins/src/emqx_plugins_sup.erl
new file mode 100644
index 000000000..c1e26752e
--- /dev/null
+++ b/apps/emqx_plugins/src/emqx_plugins_sup.erl
@@ -0,0 +1,30 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_plugins_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0]).
+
+-export([init/1]).
+
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ Children = [],
+ {ok, {{one_for_one, 10, 10}, Children}}.
diff --git a/apps/emqx/test/emqx_plugins_SUITE.erl b/apps/emqx_plugins/test/emqx_plugins_SUITE.erl
similarity index 97%
rename from apps/emqx/test/emqx_plugins_SUITE.erl
rename to apps/emqx_plugins/test/emqx_plugins_SUITE.erl
index 3aba5a997..2281f09dc 100644
--- a/apps/emqx/test/emqx_plugins_SUITE.erl
+++ b/apps/emqx_plugins/test/emqx_plugins_SUITE.erl
@@ -42,7 +42,7 @@ init_per_suite(Config) ->
emqx_common_test_helpers:boot_modules([]),
emqx_common_test_helpers:start_apps([]),
- emqx_config:put([plugins, expand_plugins_dir], DataPath),
+ emqx_config:put([plugins, install_dir], DataPath),
?assertEqual(ok, emqx_plugins:load()),
Config.
@@ -57,7 +57,7 @@ t_load(_) ->
?assertEqual({error, not_started}, emqx_plugins:unload(emqx_mini_plugin)),
?assertEqual({error, not_started}, emqx_plugins:unload(emqx_hocon_plugin)),
- emqx_config:put([plugins, expand_plugins_dir], undefined).
+ emqx_config:put([plugins, install_dir], undefined).
t_load_ext_plugin(_) ->
?assertError({plugin_app_file_not_found, _},
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src
diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl b/apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl
similarity index 100%
rename from apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl
rename to apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl
diff --git a/rebar.config.erl b/rebar.config.erl
index 2beabd147..f63fedd84 100644
--- a/rebar.config.erl
+++ b/rebar.config.erl
@@ -305,6 +305,7 @@ relx_apps(ReleaseType, Edition) ->
, emqx_statsd
, emqx_prometheus
, emqx_psk
+ , emqx_plugins
]
++ [quicer || is_quicer_supported()]
%++ [emqx_license || is_enterprise(Edition)]