Переглянути джерело

feat(plugins): add emqx_plugins skeleton

* added emqx_plugins app.
* emqx_plugins.erl is moved from emqx app to emqx_plugins app
  same for the test SUITE
Zaiming (Stone) Shi 4 роки тому
батько
коміт
38ac10d3e2
23 змінених файлів з 185 додано та 16 видалено
  1. 0 10
      apps/emqx/src/emqx_schema.erl
  2. 1 0
      apps/emqx_conf/src/emqx_conf_schema.erl
  3. 7 0
      apps/emqx_plugins/etc/emqx_plugins.conf
  4. 9 0
      apps/emqx_plugins/src/emqx_plugins.app.src
  5. 8 0
      apps/emqx_plugins/src/emqx_plugins.appup.src
  6. 3 4
      apps/emqx/src/emqx_plugins.erl
  7. 30 0
      apps/emqx_plugins/src/emqx_plugins_app.erl
  8. 94 0
      apps/emqx_plugins/src/emqx_plugins_schema.erl
  9. 30 0
      apps/emqx_plugins/src/emqx_plugins_sup.erl
  10. 2 2
      apps/emqx/test/emqx_plugins_SUITE.erl
  11. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile
  12. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf
  13. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config
  14. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src
  15. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl
  16. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl
  17. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile
  18. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf
  19. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema
  20. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config
  21. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src
  22. 0 0
      apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl
  23. 1 0
      rebar.config.erl

+ 0 - 10
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()]),

+ 1 - 0
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

+ 7 - 0
apps/emqx_plugins/etc/emqx_plugins.conf

@@ -0,0 +1,7 @@
+plugins {
+    prebuilt {
+    }
+    external {
+    }
+    install_dir = "plugins"
+}

+ 9 - 0
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, []}
+ ]}.

+ 8 - 0
apps/emqx_plugins/src/emqx_plugins.appup.src

@@ -0,0 +1,8 @@
+%% -*- mode: erlang -*-
+{"0.1.0",
+ [ {<<".*">>, []}
+ ],
+ [
+   {<<".*">>, []}
+ ]
+}.

+ 3 - 4
apps/emqx/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()}).

+ 30 - 0
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.

+ 94 - 0
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.
+<br>
+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.
+<br>
+Most of the prebuilt plugins from 4.x are converted into features since 5.0.
+""" ++ prebuilt_plugins() ++
+"""
+<br>
+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.
+<br>
+Example config: <code>{emqx_foo_bar: true, emqx_bazz: false}</code>
+""".
+
+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'.
+<br>
+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.
+<br>
+Example config: <code>{emqx_extplug1: \"0.1.0\", emqx_extplug2: false}</code>
+""".
+
+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 <code>emqx_foo_bar-0.1.0</code>.
+""".
+
+%% 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".

+ 30 - 0
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}}.

+ 2 - 2
apps/emqx/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, _},

apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/Makefile


apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/etc/emqx_hocon_plugin.conf


apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config


apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin.app.src


apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_app.erl


apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/src/emqx_hocon_plugin_schema.erl


apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/Makefile


apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/etc/emqx_mini_plugin.conf


apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/priv/emqx_mini_plugin.schema


apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config


apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin.app.src


apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl → apps/emqx_plugins/test/emqx_plugins_SUITE_data/emqx_mini_plugin/src/emqx_mini_plugin_app.erl


+ 1 - 0
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)]