From 9b3ab169cea898ccc038665988f24cee5eee2ae5 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Thu, 4 Mar 2021 16:33:57 +0100 Subject: [PATCH 01/37] chore(versioning): detach package version from emqx app version --- include/emqx_release.hrl | 36 ++++++++++++++++++++++++++++++++++++ pkg-vsn.sh | 13 ++++--------- rebar.config.erl | 3 +-- src/emqx.app.src | 2 +- src/emqx_app.erl | 18 ++++++++++++++++-- 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 include/emqx_release.hrl diff --git a/include/emqx_release.hrl b/include/emqx_release.hrl new file mode 100644 index 000000000..0adfd2e48 --- /dev/null +++ b/include/emqx_release.hrl @@ -0,0 +1,36 @@ +%%-------------------------------------------------------------------- +%% 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. +%%-------------------------------------------------------------------- + +-ifndef(EMQX_RELEASE_HRL). +-define(EMQX_RELEASE_HRL, true). + +%% NOTE: this is the release version which is not always the same +%% as the emqx app version defined in emqx.app.src +%% App (plugin) versions are bumped independently. +%% e.g. EMQX_RELEASE being 4.3.1 does no always imply emqx app +%% should be 4.3.1, as it might be the case that only one of the +%% plugins had a bug to fix. So for a hot beam upgrade, only the app +%% with beam files changed needs an upgrade. + +%% NOTE: The version string prefix should be: +%% 'v' for opensource edition +%% 'e' for enterprise edition + +%% NOTE: This version number should be manually bumped for each release + +-define(EMQX_RELEASE, "v4.3-beta.1"). + +-endif. diff --git a/pkg-vsn.sh b/pkg-vsn.sh index 0c1c0cb33..02096e8ff 100755 --- a/pkg-vsn.sh +++ b/pkg-vsn.sh @@ -1,20 +1,15 @@ #!/usr/bin/env bash -set -e -u +set -euo pipefail # This script prints the release version for emqx # ensure dir cd -P -- "$(dirname -- "$0")" -case $(uname) in - *Darwin*) SED="sed -E";; - *) SED="sed -r";; -esac +RELEASE="$(grep -E 'define.+EMQX_RELEASE,' include/emqx_release.hrl | cut -d '"' -f2)" -# comment SUFFIX out when finalising RELEASE -RELEASE="$(grep -oE '\{vsn, (.*)\}' src/emqx.app.src | $SED 's/\{vsn, (.*)\}/\1/g' | $SED 's/\"//g')" -if [ -d .git ] && ! git describe --tags --match "v${RELEASE}" --exact >/dev/null 2>&1; then - SUFFIX="-$(git rev-parse HEAD | cut -b1-8)" +if [ -d .git ] && ! git describe --tags --match "${RELEASE}" --exact >/dev/null 2>&1; then + SUFFIX="-$(git rev-parse HEAD | cut -b1-8)" fi echo "${RELEASE}${SUFFIX:-}" diff --git a/rebar.config.erl b/rebar.config.erl index 6f839f16c..affe1d5b9 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -294,8 +294,7 @@ get_vsn() -> false -> os:cmd("./pkg-vsn.sh"); Vsn -> Vsn end, - Vsn2 = re:replace(PkgVsn, "v", "", [{return ,list}]), - re:replace(Vsn2, "\n", "", [{return ,list}]). + re:replace(PkgVsn, "\n", "", [{return ,list}]). maybe_dump(Config) -> is_debug() andalso file:write_file("rebar.config.rendered", [io_lib:format("~p.\n", [I]) || I <- Config]), diff --git a/src/emqx.app.src b/src/emqx.app.src index 70d64fff8..40c0ff955 100644 --- a/src/emqx.app.src +++ b/src/emqx.app.src @@ -1,7 +1,7 @@ {application, emqx, [{description, "EMQ X Broker"}, {id, "emqx"}, - {vsn, "4.3-beta.1"}, % strict semver, bump manually! + {vsn, "4.3.0"}, % strict semver, bump manually! {modules, []}, {registered, []}, {applications, [kernel,stdlib,gproc,gen_rpc,esockd,cowboy,sasl,os_mon]}, diff --git a/src/emqx_app.erl b/src/emqx_app.erl index cf4f8753d..8e0e51d25 100644 --- a/src/emqx_app.erl +++ b/src/emqx_app.erl @@ -20,10 +20,13 @@ -export([ start/2 , stop/1 + , get_release/0 ]). -define(APP, emqx). +-include("emqx_release.hrl"). + %%-------------------------------------------------------------------- %% Application callbacks %%-------------------------------------------------------------------- @@ -57,8 +60,19 @@ print_banner() -> print_vsn() -> {ok, Descr} = application:get_key(description), - {ok, Vsn} = application:get_key(vsn), - io:format("~s ~s is running now!~n", [Descr, Vsn]). + io:format("~s ~s is running now!~n", [Descr, get_release()]). + +-ifdef(TEST). +%% When testing, the 'cover' compiler stripps aways compile info +get_release() -> ?EMQX_RELEASE. +-else. +%% Otherwise print the build number, +%% which may have a git commit in its suffix. +get_release() -> + {_, Vsn} = lists:keyfind(emqx_vsn, 1, ?MODULE:module_info(compile)), + ?EMQX_RELEASE ++ _ = Vsn, %% assert + Vsn. +-endif. %%-------------------------------------------------------------------- %% Autocluster From 609b015f937b7ff596c15a7eea5f78b99df61aa0 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Fri, 5 Mar 2021 10:51:50 +0100 Subject: [PATCH 02/37] chore(build): Use different env variable for dashboard version --- Makefile | 4 ++-- scripts/get-dashboard.sh | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index dadc9dd3b..f74296361 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ REBAR_VERSION = 3.14.3-emqx-4 -DASHBOARD_VERSION = v4.3.0-beta.1 REBAR = $(CURDIR)/rebar3 BUILD = $(CURDIR)/build SCRIPTS = $(CURDIR)/scripts export PKG_VSN ?= $(shell $(CURDIR)/pkg-vsn.sh) +export EMQX_CE_DASHBOARD_VERSION ?= v4.3.0-beta.1 PROFILE ?= emqx REL_PROFILES := emqx emqx-edge @@ -27,7 +27,7 @@ $(REBAR): ensure-rebar3 .PHONY: get-dashboard get-dashboard: - @$(SCRIPTS)/get-dashboard.sh $(DASHBOARD_VERSION) + @$(SCRIPTS)/get-dashboard.sh .PHONY: eunit eunit: $(REBAR) diff --git a/scripts/get-dashboard.sh b/scripts/get-dashboard.sh index a0f484d12..b53741048 100755 --- a/scripts/get-dashboard.sh +++ b/scripts/get-dashboard.sh @@ -5,14 +5,15 @@ set -euo pipefail # ensure dir cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." -VERSION="$1" RELEASE_ASSET_FILE="emqx-dashboard.zip" if [ -f 'EMQX_ENTERPRISE' ]; then + VERSION="${EMQX_EE_DASHBOARD_VERSION}" DASHBOARD_PATH='lib-ee/emqx_dashboard/priv' DASHBOARD_REPO='emqx-enterprise-dashboard-frontend-src' AUTH="Authorization: token $(cat scripts/git-token)" else + VERSION="${EMQX_CE_DASHBOARD_VERSION}" DASHBOARD_PATH='lib-ce/emqx_dashboard/priv' DASHBOARD_REPO='emqx-dashboard-frontend' AUTH="" From cd4614876a099686e7012ffdbafdbce768cad155 Mon Sep 17 00:00:00 2001 From: zhanghongtong Date: Fri, 5 Mar 2021 16:24:07 +0800 Subject: [PATCH 03/37] chore(CI): add git syne workflow --- .github/workflows/build_packages.yaml | 4 ++-- .github/workflows/git_sync.yaml | 29 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/git_sync.yaml diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml index 057435e4e..2562a725f 100644 --- a/.github/workflows/build_packages.yaml +++ b/.github/workflows/build_packages.yaml @@ -356,7 +356,7 @@ jobs: if: github.event_name == 'release' run: | curl --silent --show-error \ - -H "Authorization: token ${{ secrets.AccessToken }}" \ + -H "Authorization: token ${{ secrets.CI_GIT_TOKEN }}" \ -H "Accept: application/vnd.github.v3+json" \ -X POST \ -d "{\"ref\":\"v1.0.1\",\"inputs\":{\"version\": \"${{ env.version }}\", \"emqx_ce\": \"true\"}}" \ @@ -366,7 +366,7 @@ jobs: run: | if [ -z $(echo $version | grep -oE "(alpha|beta|rc)\.[0-9]") ]; then curl --silent --show-error \ - -H "Authorization: token ${{ secrets.AccessToken }}" \ + -H "Authorization: token ${{ secrets.CI_GIT_TOKEN }}" \ -H "Accept: application/vnd.github.v3+json" \ -X POST \ -d "{\"ref\":\"v1.0.1\",\"inputs\":{\"version\": \"${{ env.version }}\"}}" \ diff --git a/.github/workflows/git_sync.yaml b/.github/workflows/git_sync.yaml new file mode 100644 index 000000000..a57a68ceb --- /dev/null +++ b/.github/workflows/git_sync.yaml @@ -0,0 +1,29 @@ +name: Sync to enterprise + +on: + push: + branches: + - master + +jobs: + sync_to_enterprise: + runs-on: ubuntu-20.04 + if: github.repository == 'emqx/emqx' + steps: + - name: git-sync + uses: Rory-Z/git-sync@v3.0.1 + with: + source_repo: ${{ github.repository }} + source_branch: ${{ github.ref }} + destination_repo: "${{ github.repository_owner }}/emqx-enterprise" + destination_branch: ${{ github.ref }} + destination_ssh_private_key: "${{ secrets.CI_SSH_PRIVATE_KEY }}" + - name: create pull request + run: | + set -euo pipefail + curl --silent --show-error \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: token ${{ secrets.CI_GIT_TOEKN }}" \ + -X POST \ + -d '{"title": "Sync code into enterprise from opensource", "head": "master", "base":"enterprise"}' \ + https://api.github.com/repos/${{ github.repository_owner }}/emqx-enterprise/pulls From bd66e93b6d372a2ae2d9ac738f975cab8966fb84 Mon Sep 17 00:00:00 2001 From: zhanghongtong Date: Fri, 5 Mar 2021 19:07:24 +0800 Subject: [PATCH 04/37] chore(CI): fix spell error --- .github/workflows/git_sync.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/git_sync.yaml b/.github/workflows/git_sync.yaml index a57a68ceb..6fe19eae6 100644 --- a/.github/workflows/git_sync.yaml +++ b/.github/workflows/git_sync.yaml @@ -23,7 +23,7 @@ jobs: set -euo pipefail curl --silent --show-error \ -H "Accept: application/vnd.github.v3+json" \ - -H "Authorization: token ${{ secrets.CI_GIT_TOEKN }}" \ + -H "Authorization: token ${{ secrets.CI_GIT_TOKEN }}" \ -X POST \ -d '{"title": "Sync code into enterprise from opensource", "head": "master", "base":"enterprise"}' \ https://api.github.com/repos/${{ github.repository_owner }}/emqx-enterprise/pulls From 4eb98fdf5e64b9c3c80e3bad6e0008c86c952867 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Fri, 5 Mar 2021 12:55:20 +0100 Subject: [PATCH 05/37] chore(compile): do not pass down EMQX_ENTERPRISE macro to deps --- rebar.config.erl | 1 - 1 file changed, 1 deletion(-) diff --git a/rebar.config.erl b/rebar.config.erl index affe1d5b9..2e73106c4 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -22,7 +22,6 @@ overrides() -> [ {add, [ {extra_src_dirs, [{"etc", [{recursive,true}]}]} , {erl_opts, [ deterministic , {compile_info, [{emqx_vsn, get_vsn()}]} - | [{d, 'EMQX_ENTERPRISE'} || is_enterprise()] ]} ]} ]. From 80125a9606e13b845be4fa86983e8cb41667f2f4 Mon Sep 17 00:00:00 2001 From: z8674558 Date: Thu, 4 Mar 2021 22:36:55 +0900 Subject: [PATCH 06/37] feat(rebar.config.erl): allow community plugins --- .github/workflows/run_test_cases.yaml | 4 ++- lib-extra/emqx_plugin_template | 1 + lib-extra/plugins | 5 +++ rebar.config.erl | 52 +++++++++++++++++++++------ 4 files changed, 51 insertions(+), 11 deletions(-) create mode 120000 lib-extra/emqx_plugin_template create mode 100644 lib-extra/plugins diff --git a/.github/workflows/run_test_cases.yaml b/.github/workflows/run_test_cases.yaml index 6adf099cb..0680ef10a 100644 --- a/.github/workflows/run_test_cases.yaml +++ b/.github/workflows/run_test_cases.yaml @@ -38,7 +38,9 @@ jobs: docker-compose -f .ci/apps_tests/docker-compose.yaml build --no-cache docker-compose -f .ci/apps_tests/docker-compose.yaml up -d - name: run eunit - run: docker exec -i erlang bash -c "make eunit" + run: | + docker exec -i erlang bash -c "make eunit" + docker exec --env EMQX_EXTRA_PLUGINS=all -i erlang bash -c "./rebar3 eunit --dir lib-extra/*" - name: run common test run: docker exec -i erlang bash -c "make ct" - name: run cover diff --git a/lib-extra/emqx_plugin_template b/lib-extra/emqx_plugin_template new file mode 120000 index 000000000..6cf8106d2 --- /dev/null +++ b/lib-extra/emqx_plugin_template @@ -0,0 +1 @@ +../_build/default/lib/emqx_plugin_template \ No newline at end of file diff --git a/lib-extra/plugins b/lib-extra/plugins new file mode 100644 index 000000000..03a360fd9 --- /dev/null +++ b/lib-extra/plugins @@ -0,0 +1,5 @@ +{erlang_plugins, + [ + {emqx_plugin_template, {git, "https://github.com/emqx/emqx-plugin-template", {branch, "master"}}} + ] +}. diff --git a/rebar.config.erl b/rebar.config.erl index 2e73106c4..a05083970 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -11,12 +11,32 @@ bcrypt() -> {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {branch, "0.6.0"}}}. deps(Config) -> - {deps, OldDpes} = lists:keyfind(deps, 1, Config), + {deps, OldDeps} = lists:keyfind(deps, 1, Config), MoreDeps = case provide_bcrypt_dep() of true -> [bcrypt()]; false -> [] end, - lists:keystore(deps, 1, Config, {deps, OldDpes ++ MoreDeps}). + lists:keystore(deps, 1, Config, {deps, OldDeps ++ MoreDeps ++ extra_deps()}). + +extra_deps() -> + {ok, Proplist} = file:consult("lib-extra/plugins"), + AllPlugins = proplists:get_value(erlang_plugins, Proplist), + Filter = string:split(os:getenv("EMQX_EXTRA_PLUGINS", ""), ",", all), + filter_extra_deps(AllPlugins, Filter). + +filter_extra_deps(AllPlugins, ["all"]) -> + AllPlugins; +filter_extra_deps(AllPlugins, Filter) -> + filter_extra_deps(AllPlugins, Filter, []). +filter_extra_deps([], _, Acc) -> + lists:reverse(Acc); +filter_extra_deps([{Plugin, _}=P|More], Filter, Acc) -> + case lists:member(atom_to_list(Plugin), Filter) of + true -> + filter_extra_deps(More, Filter, [P|Acc]); + false -> + filter_extra_deps(More, Filter, Acc) + end. overrides() -> [ {add, [ {extra_src_dirs, [{"etc", [{recursive,true}]}]} @@ -24,7 +44,10 @@ overrides() -> , {compile_info, [{emqx_vsn, get_vsn()}]} ]} ]} - ]. + ] ++ community_plugin_overrides(). + +community_plugin_overrides() -> + [{add, App, [ {erl_opts, [{i, "include"}]}]} || App <- relx_plugin_apps_extra()]. config() -> [ {plugins, plugins()} @@ -35,14 +58,14 @@ config() -> is_enterprise() -> filelib:is_regular("EMQX_ENTERPRISE"). -extra_lib_dir() -> +alternative_lib_dir() -> case is_enterprise() of true -> "lib-ee"; false -> "lib-ce" end. project_app_dirs() -> - ["apps/*", extra_lib_dir() ++ "/*", "."]. + ["apps/*", alternative_lib_dir() ++ "/*", "."]. plugins() -> [ {relup_helper,{git,"https://github.com/emqx/relup_helper", {branch,"master"}}}, @@ -185,7 +208,8 @@ relx_plugin_apps(ReleaseType) -> , emqx_modules ] ++ relx_plugin_apps_per_rel(ReleaseType) - ++ relx_plugin_apps_enterprise(is_enterprise()). + ++ relx_plugin_apps_enterprise(is_enterprise()) + ++ relx_plugin_apps_extra(). relx_plugin_apps_per_rel(cloud) -> [ emqx_lwm2m @@ -207,6 +231,9 @@ relx_plugin_apps_enterprise(true) -> filelib:is_dir(filename:join(["lib-ee", A]))]; relx_plugin_apps_enterprise(false) -> []. +relx_plugin_apps_extra() -> + [Plugin || {Plugin, _} <- extra_deps()]. + relx_overlay(ReleaseType) -> [ {mkdir,"log/"} , {mkdir,"data/"} @@ -234,7 +261,8 @@ relx_overlay(ReleaseType) -> etc_overlay(ReleaseType) -> PluginApps = relx_plugin_apps(ReleaseType), Templates = emqx_etc_overlay(ReleaseType) ++ - lists:append([plugin_etc_overlays(App) || App <- PluginApps]), + lists:append([plugin_etc_overlays(App) || App <- PluginApps]) ++ + [community_plugin_etc_overlays(App) || App <- relx_plugin_apps_extra()], [ {mkdir, "etc/"} , {mkdir, "etc/plugins"} , {template, "etc/BUILT_ON", "releases/{{release_version}}/BUILT_ON"} @@ -274,11 +302,15 @@ plugin_etc_overlays(App0) -> [{"{{base_dir}}/lib/"++ App ++"/etc/" ++ F, "etc/plugins/" ++ F} || F <- ConfFiles]. +community_plugin_etc_overlays(App0) -> + App = atom_to_list(App0), + {"{{base_dir}}/lib/"++ App ++"/etc/" ++ App ++ ".conf", "etc/plugins/" ++ App ++ ".conf"}. + %% NOTE: for apps fetched as rebar dependency (there is so far no such an app) %% the overlay should be hand-coded but not to rely on build-time wildcards. find_conf_files(App) -> Dir1 = filename:join(["apps", App, "etc"]), - Dir2 = filename:join([extra_lib_dir(), App, "etc"]), + Dir2 = filename:join([alternative_lib_dir(), App, "etc"]), filelib:wildcard("*.conf", Dir1) ++ filelib:wildcard("*.conf", Dir2). env(Name, Default) -> @@ -320,7 +352,7 @@ provide_bcrypt_release(ReleaseType) -> erl_opts_i() -> [{i, "apps"}] ++ [{i, Dir} || Dir <- filelib:wildcard(filename:join(["apps", "*", "include"]))] ++ - [{i, Dir} || Dir <- filelib:wildcard(filename:join([extra_lib_dir(), "*", "include"]))]. + [{i, Dir} || Dir <- filelib:wildcard(filename:join([alternative_lib_dir(), "*", "include"]))]. dialyzer(Config) -> {dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config), @@ -332,7 +364,7 @@ dialyzer(Config) -> [ list_to_atom(App) || App <- string:tokens(Value, ",")] end, - AppNames = [emqx | list_dir("apps")] ++ list_dir(extra_lib_dir()), + AppNames = [emqx | list_dir("apps")] ++ list_dir(alternative_lib_dir()), KnownApps = [Name || Name <- AppsToAnalyse, lists:member(Name, AppNames)], From b12d4f481f136e236fce319eb828d6b81b6c1023 Mon Sep 17 00:00:00 2001 From: zhanghongtong Date: Sat, 6 Mar 2021 09:44:47 +0800 Subject: [PATCH 07/37] chore(script): remove the prefix of pkg-vsn.sh --- .ci/build_packages/tests.sh | 5 +++-- .github/workflows/build_slim_packages.yaml | 26 ++++++++++++++++++++++ include/emqx_release.hrl | 6 +---- 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/build_slim_packages.yaml diff --git a/.ci/build_packages/tests.sh b/.ci/build_packages/tests.sh index 48e7c27a3..8ae3cc838 100755 --- a/.ci/build_packages/tests.sh +++ b/.ci/build_packages/tests.sh @@ -1,8 +1,9 @@ #!/bin/sh set -x -e -u +export CODE_PATH=${CODE_PATH:-"/emqx"} export EMQX_NAME=${EMQX_NAME:-"emqx"} -export PACKAGE_PATH="/emqx/_packages/${EMQX_NAME}" -export RELUP_PACKAGE_PATH="/emqx/relup_packages/${EMQX_NAME}" +export PACKAGE_PATH="${CODE_PATH}/_packages/${EMQX_NAME}" +export RELUP_PACKAGE_PATH="${CODE_PATH}/relup_packages/${EMQX_NAME}" # export EMQX_NODE_NAME="emqx-on-$(uname -m)@127.0.0.1" # export EMQX_NODE_COOKIE=$(date +%s%N) diff --git a/.github/workflows/build_slim_packages.yaml b/.github/workflows/build_slim_packages.yaml new file mode 100644 index 000000000..217e06917 --- /dev/null +++ b/.github/workflows/build_slim_packages.yaml @@ -0,0 +1,26 @@ +name: Build slim packages + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + + strategy: + matrix: + erl_otp: + - erl23.2.2 + os: + - ubuntu20.04 + - centos8 + + container: emqx/build-env:${{ matrix.erl_otp }}-${{ matrix.os }} + + steps: + - uses: actions/checkout@v1 + - name: build packages + run: make emqx-pkg + - name: pakcages test + run: | + export CODE_PATH=$GITHUB_WORKSPACE + .ci/build_packages/tests.sh diff --git a/include/emqx_release.hrl b/include/emqx_release.hrl index 0adfd2e48..42949070f 100644 --- a/include/emqx_release.hrl +++ b/include/emqx_release.hrl @@ -25,12 +25,8 @@ %% plugins had a bug to fix. So for a hot beam upgrade, only the app %% with beam files changed needs an upgrade. -%% NOTE: The version string prefix should be: -%% 'v' for opensource edition -%% 'e' for enterprise edition - %% NOTE: This version number should be manually bumped for each release --define(EMQX_RELEASE, "v4.3-beta.1"). +-define(EMQX_RELEASE, "4.3-beta.1"). -endif. From c752f3bec524a6801e49a19a7e40f0b736803ccb Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 06:35:02 +0100 Subject: [PATCH 08/37] Refactor http lib add uri parse (#4292) * feat(http_lib): Add uri parse to emqx_http_lib * fix(webhook): call emqx_http_lib to parse uri * fix(auth-http): Call emqx_http_lib to parse uri * fix(rule-engine): call emqx_http_lib to parse uri --- .../emqx_auth_http/src/emqx_auth_http_app.erl | 24 ++------ apps/emqx_rule_engine/src/emqx_rule_utils.erl | 19 ++---- .../src/emqx_web_hook_actions.erl | 34 +++-------- apps/emqx_web_hook/src/emqx_web_hook_app.erl | 24 ++------ src/emqx_http_lib.erl | 60 ++++++++++++++++++- test/emqx_http_lib_tests.erl | 28 +++++++++ 6 files changed, 112 insertions(+), 77 deletions(-) diff --git a/apps/emqx_auth_http/src/emqx_auth_http_app.erl b/apps/emqx_auth_http/src/emqx_auth_http_app.erl index 89f42a2cd..acbb67bf4 100644 --- a/apps/emqx_auth_http/src/emqx_auth_http_app.erl +++ b/apps/emqx_auth_http/src/emqx_auth_http_app.erl @@ -53,19 +53,16 @@ translate_env(EnvName) -> {ok, PoolSize} = application:get_env(?APP, pool_size), {ok, ConnectTimeout} = application:get_env(?APP, connect_timeout), URL = proplists:get_value(url, Req), - #{host := Host0, - path := Path0, - scheme := Scheme} = URIMap = uri_string:parse(add_default_scheme(uri_string:normalize(URL))), - Port = maps:get(port, URIMap, case Scheme of - "https" -> 443; - "http" -> 80 - end), + {ok, #{host := Host0, + path := Path0, + port := Port, + scheme := Scheme}} = emqx_http_lib:uri_parse(URL), Path = path(Path0), {Inet, Host} = parse_host(Host0), MoreOpts = case Scheme of - "http" -> + http -> [{transport_opts, [Inet]}]; - "https" -> + https -> CACertFile = application:get_env(?APP, cacertfile, undefined), CertFile = application:get_env(?APP, certfile, undefined), KeyFile = application:get_env(?APP, keyfile, undefined), @@ -158,15 +155,6 @@ ensure_content_type_header(Method, Headers) ensure_content_type_header(_Method, Headers) -> lists:keydelete("content-type", 1, Headers). -add_default_scheme(URL) when is_list(URL) -> - binary_to_list(add_default_scheme(list_to_binary(URL))); -add_default_scheme(<<"http://", _/binary>> = URL) -> - URL; -add_default_scheme(<<"https://", _/binary>> = URL) -> - URL; -add_default_scheme(URL) -> - <<"http://", URL/binary>>. - path("") -> "/"; path(Path) -> diff --git a/apps/emqx_rule_engine/src/emqx_rule_utils.erl b/apps/emqx_rule_engine/src/emqx_rule_utils.erl index 409095e02..e178fc9d2 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_utils.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_utils.erl @@ -202,15 +202,11 @@ http_connectivity(Url) -> -spec(http_connectivity(uri_string(), integer()) -> ok | {error, Reason :: term()}). http_connectivity(Url, Timeout) -> - case uri_string:parse(uri_string:normalize(Url)) of - {error, Reason, _} -> - {error, Reason}; - #{host := Host, port := Port} -> + case emqx_http_lib:uri_parse(Url) of + {ok, #{host := Host, port := Port}} -> tcp_connectivity(str(Host), Port, Timeout); - #{host := Host, scheme := Scheme} -> - tcp_connectivity(str(Host), default_port(Scheme), Timeout); - _ -> - {error, {invalid_url, Url}} + {error, Reason} -> + {error, Reason} end. -spec tcp_connectivity(Host :: inet:socket_address() | inet:hostname(), @@ -229,13 +225,6 @@ tcp_connectivity(Host, Port, Timeout) -> {error, Reason} -> {error, Reason} end. -default_port("http") -> 80; -default_port("https") -> 443; -default_port(<<"http">>) -> 80; -default_port(<<"https">>) -> 443; -default_port(Scheme) -> throw({bad_scheme, Scheme}). - - unwrap(<<"${", Val/binary>>) -> binary:part(Val, {0, byte_size(Val)-1}). diff --git a/apps/emqx_web_hook/src/emqx_web_hook_actions.erl b/apps/emqx_web_hook/src/emqx_web_hook_actions.erl index e5aa25c3a..4e63b54df 100644 --- a/apps/emqx_web_hook/src/emqx_web_hook_actions.erl +++ b/apps/emqx_web_hook/src/emqx_web_hook_actions.erl @@ -281,7 +281,7 @@ create_req(_, Path, Headers, Body) -> parse_action_params(Params = #{<<"url">> := URL}) -> try - #{path := CommonPath} = uri_string:parse(URL), + {ok, #{path := CommonPath}} = emqx_http_lib:uri_parse(URL), Method = method(maps:get(<<"method">>, Params, <<"POST">>)), Headers = headers(maps:get(<<"headers">>, Params, undefined)), NHeaders = ensure_content_type_header(Headers, Method), @@ -318,31 +318,19 @@ str(Str) when is_list(Str) -> Str; str(Atom) when is_atom(Atom) -> atom_to_list(Atom); str(Bin) when is_binary(Bin) -> binary_to_list(Bin). -add_default_scheme(<<"http://", _/binary>> = URL) -> - URL; -add_default_scheme(<<"https://", _/binary>> = URL) -> - URL; -add_default_scheme(URL) -> - <<"http://", URL/binary>>. - pool_opts(Params = #{<<"url">> := URL}, ResId) -> - #{host := Host0, scheme := Scheme} = URIMap = - uri_string:parse(binary_to_list(add_default_scheme(URL))), - DefaultPort = case is_https(Scheme) of - true -> 443; - false -> 80 - end, - Port = maps:get(port, URIMap, DefaultPort), + {ok, #{host := Host0, + port := Port, + scheme := Scheme}} = emqx_http_lib:uri_parse(URL), PoolSize = maps:get(<<"pool_size">>, Params, 32), ConnectTimeout = cuttlefish_duration:parse(str(maps:get(<<"connect_timeout">>, Params, <<"5s">>))), {Inet, Host} = parse_host(Host0), - TransportOpts = - case is_https(Scheme) of - true -> [Inet | get_ssl_opts(Params, ResId)]; - false -> [Inet] - end, - Opts = case is_https(Scheme) of + TransportOpts = case Scheme =:= https of + true -> [Inet | get_ssl_opts(Params, ResId)]; + false -> [Inet] + end, + Opts = case Scheme =:= https of true -> [{transport_opts, TransportOpts}, {transport, ssl}]; false -> [{transport_opts, TransportOpts}] end, @@ -357,10 +345,6 @@ pool_opts(Params = #{<<"url">> := URL}, ResId) -> pool_name(ResId) -> list_to_atom("webhook:" ++ str(ResId)). -is_https(Scheme) when is_list(Scheme) -> is_https(list_to_binary(Scheme)); -is_https(<<"https", _/binary>>) -> true; -is_https(_) -> false. - get_ssl_opts(Opts, ResId) -> Dir = filename:join([emqx:get_env(data_dir), "rule", ResId]), [{ssl, true}, {ssl_opts, emqx_plugin_libs_ssl:save_files_return_opts(Opts, Dir)}]. diff --git a/apps/emqx_web_hook/src/emqx_web_hook_app.erl b/apps/emqx_web_hook/src/emqx_web_hook_app.erl index 54ac9c317..67775e00f 100644 --- a/apps/emqx_web_hook/src/emqx_web_hook_app.erl +++ b/apps/emqx_web_hook/src/emqx_web_hook_app.erl @@ -39,31 +39,19 @@ stop(_State) -> emqx_web_hook:unload(), ehttpc_sup:stop_pool(?APP). -add_default_scheme(URL) when is_list(URL) -> - binary_to_list(add_default_scheme(list_to_binary(URL))); -add_default_scheme(<<"http://", _/binary>> = URL) -> - URL; -add_default_scheme(<<"https://", _/binary>> = URL) -> - URL; -add_default_scheme(URL) -> - <<"http://", URL/binary>>. - translate_env() -> {ok, URL} = application:get_env(?APP, url), - #{host := Host0, - path := Path0, - scheme := Scheme} = URIMap = uri_string:parse(add_default_scheme(uri_string:normalize(URL))), - Port = maps:get(port, URIMap, case Scheme of - "https" -> 443; - "http" -> 80 - end), + {ok, #{host := Host0, + path := Path0, + port := Port, + scheme := Scheme}} = emqx_http_lib:uri_parse(URL), Path = path(Path0), {Inet, Host} = parse_host(Host0), PoolSize = application:get_env(?APP, pool_size, 32), MoreOpts = case Scheme of - "http" -> + http -> [{transport_opts, [Inet]}]; - "https" -> + https -> CACertFile = application:get_env(?APP, cacertfile, undefined), CertFile = application:get_env(?APP, certfile, undefined), KeyFile = application:get_env(?APP, keyfile, undefined), diff --git a/src/emqx_http_lib.erl b/src/emqx_http_lib.erl index 695879236..195656622 100644 --- a/src/emqx_http_lib.erl +++ b/src/emqx_http_lib.erl @@ -16,7 +16,20 @@ -module(emqx_http_lib). --export([uri_encode/1, uri_decode/1]). +-export([ uri_encode/1 + , uri_decode/1 + , uri_parse/1 + ]). + +-export_type([uri_map/0]). + +-type uri_map() :: #{scheme := http | https, + host := unicode:chardata(), + port := non_neg_integer(), + path => unicode:chardata(), + query => unicode:chardata(), + fragment => unicode:chardata(), + userinfo => unicode:chardata()}. %% @doc Decode percent-encoded URI. %% This is copied from http_uri.erl which has been deprecated since OTP-23 @@ -35,6 +48,51 @@ uri_decode(<<>>) -> uri_encode(URI) when is_binary(URI) -> << <<(uri_encode_binary(Char))/binary>> || <> <= URI >>. +%% @doc Parse URI into a map as uri_string:uri_map(), but with two fields +%% normalised: (1): port number is never 'undefined', default ports are used +%% if missing. (2): scheme is always atom. +-spec uri_parse(string() | binary()) -> {ok, uri_map()} | {error, any()}. +uri_parse(URI) -> + try + {ok, do_parse(uri_string:normalize(URI))} + catch + throw : Reason -> + {error, Reason} + end. + +do_parse({error, Reason, Which}) -> throw({Reason, Which}); +do_parse(URI) -> + %% ensure we return string() instead of binary() in uri_map() values. + Map = uri_string:parse(unicode:characters_to_list(URI)), + case maps:is_key(scheme, Map) of + true -> + normalise_parse_result(Map); + false -> + %% missing scheme, add "http://" and try again + Map2 = uri_string:parse(unicode:characters_to_list(["http://", URI])), + normalise_parse_result(Map2) + end. + +normalise_parse_result(#{host := _, scheme := Scheme0} = Map) -> + Scheme = atom_scheme(Scheme0), + DefaultPort = case https =:= Scheme of + true -> 443; + false -> 80 + end, + Port = case maps:get(port, Map, undefined) of + N when is_number(N) -> N; + _ -> DefaultPort + end, + Map#{ scheme => Scheme + , port => Port + }. + +%% NOTE: so far we only support http schemes. +atom_scheme(Scheme) when is_list(Scheme) -> atom_scheme(list_to_binary(Scheme)); +atom_scheme(<<"https">>) -> https; +atom_scheme(<<"http">>) -> http; +atom_scheme(Other) -> throw({unsupported_scheme, Other}). + uri_encode_binary(Char) -> case reserved(Char) of true -> diff --git a/test/emqx_http_lib_tests.erl b/test/emqx_http_lib_tests.erl index 78a647417..b5c50e7c9 100644 --- a/test/emqx_http_lib_tests.erl +++ b/test/emqx_http_lib_tests.erl @@ -44,3 +44,31 @@ test_prop_uri(URI) -> Decoded2 = uri_string:percent_decode(Encoded), ?assertEqual(URI, Decoded2), true. + +uri_parse_test_() -> + [ {"default port http", + fun() -> ?assertMatch({ok, #{port := 80, scheme := http, host := "localhost"}}, + emqx_http_lib:uri_parse("localhost")) + end + } + , {"default port https", + fun() -> ?assertMatch({ok, #{port := 443, scheme := https}}, + emqx_http_lib:uri_parse("https://localhost")) + end + } + , {"bad url", + fun() -> ?assertMatch({error, {invalid_uri, _}}, + emqx_http_lib:uri_parse("https://localhost:notnumber")) + end + } + , {"normalise", + fun() -> ?assertMatch({ok, #{scheme := https}}, + emqx_http_lib:uri_parse("HTTPS://127.0.0.1")) + end + } + , {"unsupported_scheme", + fun() -> ?assertEqual({error, {unsupported_scheme, <<"wss">>}}, + emqx_http_lib:uri_parse("wss://127.0.0.1")) + end + } + ]. From 3e3c06118c9ddd8941f9b88dd6bd544a9df490e2 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 07:39:48 +0100 Subject: [PATCH 09/37] chore(build): Ensure git hooks from Makefile --- Makefile | 1 + scripts/git-hook-pre-push.sh | 12 ++++++++++++ scripts/git-hooks-init.sh | 13 +++++++++++++ 3 files changed, 26 insertions(+) create mode 100755 scripts/git-hook-pre-push.sh create mode 100755 scripts/git-hooks-init.sh diff --git a/Makefile b/Makefile index f74296361..f4cc5dc89 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +$(shell scripts/git-hooks-init.sh) REBAR_VERSION = 3.14.3-emqx-4 REBAR = $(CURDIR)/rebar3 BUILD = $(CURDIR)/build diff --git a/scripts/git-hook-pre-push.sh b/scripts/git-hook-pre-push.sh new file mode 100755 index 000000000..2f5a9abcd --- /dev/null +++ b/scripts/git-hook-pre-push.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -euo pipefail + +url="$2" + +if [ -f 'EMQX_ENTERPRISE' ]; then + if [[ "$url" != *emqx-enterprise* ]]; then + echo "$(tput setaf 1)error: enterprise_code_to_non_enterprise_repo" + exit 1 + fi +fi diff --git a/scripts/git-hooks-init.sh b/scripts/git-hooks-init.sh new file mode 100755 index 000000000..a9f02ab3a --- /dev/null +++ b/scripts/git-hooks-init.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -euo pipefail + +if [ ! -d .git ]; then + exit 0 +fi + +mkdir -p ".git/hooks" + +if [ ! -L '.git/hooks/pre-push' ]; then + ln -sf '../../scripts/git-hook-pre-push.sh' '.git/hooks/pre-push' +fi From 73500a098304a74ee07e84dd9c3a2cddef67a55e Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 07:59:43 +0100 Subject: [PATCH 10/37] chore(build): inject product description from makefile --- Makefile | 9 +++++---- build | 13 ------------- src/emqx.app.src | 3 +-- src/emqx.app.src.script | 7 +++++++ 4 files changed, 13 insertions(+), 19 deletions(-) create mode 100644 src/emqx.app.src.script diff --git a/Makefile b/Makefile index f4cc5dc89..ce92d5bbf 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ REBAR = $(CURDIR)/rebar3 BUILD = $(CURDIR)/build SCRIPTS = $(CURDIR)/scripts export PKG_VSN ?= $(shell $(CURDIR)/pkg-vsn.sh) +export EMQX_DESC ?= EMQ X export EMQX_CE_DASHBOARD_VERSION ?= v4.3.0-beta.1 PROFILE ?= emqx @@ -53,9 +54,9 @@ coveralls: $(REBAR) .PHONY: $(REL_PROFILES) $(REL_PROFILES:%=%): $(REBAR) get-dashboard ifneq ($(shell echo $(@) |grep edge),) - @export EMQX_DESC="EMQ X Edge" + @export EMQX_DESC="$${EMQX_DESC} Edge" else - @export EMQX_DESC="EMQ X Broker" + @export EMQX_DESC="$${EMQX_DESC} Broker" endif @$(REBAR) as $(@) release @@ -72,9 +73,9 @@ deps-all: $(REBAR) $(PROFILES:%=deps-%) .PHONY: $(PROFILES:%=deps-%) $(PROFILES:%=deps-%): $(REBAR) get-dashboard ifneq ($(shell echo $(@) |grep edge),) - @export EMQX_DESC="EMQ X Edge" + @export EMQX_DESC="$${EMQX_DESC} Edge" else - @export EMQX_DESC="EMQ X Broker" + @export EMQX_DESC="$${EMQX_DESC} Broker" endif @$(REBAR) as $(@:deps-%=%) get-deps diff --git a/build b/build index 03b734fc8..d7cd01183 100755 --- a/build +++ b/build @@ -12,19 +12,6 @@ ARTIFACT="$2" # ensure dir cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" -case "$PROFILE" in - emqx-edge*) - export EMQX_DESC="EMQ X Edge" - ;; - emqx*) - export EMQX_DESC="EMQ X Broker" - ;; - *) - echo "Unknown profile $PROFILE" - exit 1 - ;; -esac - PKG_VSN="${PKG_VSN:-$(./pkg-vsn.sh)}" export PKG_VSN diff --git a/src/emqx.app.src b/src/emqx.app.src index 40c0ff955..ce90feb1f 100644 --- a/src/emqx.app.src +++ b/src/emqx.app.src @@ -1,6 +1,5 @@ {application, emqx, - [{description, "EMQ X Broker"}, - {id, "emqx"}, + [{id, "emqx"}, {vsn, "4.3.0"}, % strict semver, bump manually! {modules, []}, {registered, []}, diff --git a/src/emqx.app.src.script b/src/emqx.app.src.script new file mode 100644 index 000000000..78a5e23ce --- /dev/null +++ b/src/emqx.app.src.script @@ -0,0 +1,7 @@ +[{application, Name, Opts}] = CONFIG, +case os:getenv("EMQX_DESC") of + [_ | _] = Desc -> + [{application, Name, [{description, Desc} | Opts]}]; + _ -> + error(env_var_EMQX_DESC_not_set) +end. From 1af1dd17b5c363f97c7518c075ac8bd9c57c411b Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 08:10:05 +0100 Subject: [PATCH 11/37] chore(build): use 'EMQ X test' as app description for test runs --- src/emqx.app.src.script | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/emqx.app.src.script b/src/emqx.app.src.script index 78a5e23ce..8495ca9bd 100644 --- a/src/emqx.app.src.script +++ b/src/emqx.app.src.script @@ -1,7 +1,6 @@ [{application, Name, Opts}] = CONFIG, -case os:getenv("EMQX_DESC") of - [_ | _] = Desc -> - [{application, Name, [{description, Desc} | Opts]}]; - _ -> - error(env_var_EMQX_DESC_not_set) -end. +Desc = case os:getenv("EMQX_DESC") of + [_ | _] = D -> D; + _ -> "EMQ X test" + end, +[{application, Name, [{description, Desc} | Opts]}]. From 00a2daba190e5ee846adffc44ef92547aabbc36f Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 10:53:47 +0100 Subject: [PATCH 12/37] chore(build): add more enterprise build support --- include/emqx_release.hrl | 9 ++++++++- pkg-vsn.sh | 8 +++++++- rebar.config.erl | 2 +- src/emqx_app.erl | 8 ++++++-- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/emqx_release.hrl b/include/emqx_release.hrl index 42949070f..b2c93a2bb 100644 --- a/include/emqx_release.hrl +++ b/include/emqx_release.hrl @@ -27,6 +27,13 @@ %% NOTE: This version number should be manually bumped for each release --define(EMQX_RELEASE, "4.3-beta.1"). +-ifndef(EMQX_ENTERPRISE). + +-define(EMQX_RELEASE, {opensource, "4.3-beta.1"}). + +-else. + + +-endif. -endif. diff --git a/pkg-vsn.sh b/pkg-vsn.sh index 02096e8ff..9e8c26320 100755 --- a/pkg-vsn.sh +++ b/pkg-vsn.sh @@ -6,7 +6,13 @@ set -euo pipefail # ensure dir cd -P -- "$(dirname -- "$0")" -RELEASE="$(grep -E 'define.+EMQX_RELEASE,' include/emqx_release.hrl | cut -d '"' -f2)" +if [ -f EMQX_ENTERPRISE ]; then + EDITION='enterprise' +else + EDITION='opensource' +fi + +RELEASE="$(grep -E "define.+EMQX_RELEASE.+${EDITION}" include/emqx_release.hrl | cut -d '"' -f2)" if [ -d .git ] && ! git describe --tags --match "${RELEASE}" --exact >/dev/null 2>&1; then SUFFIX="-$(git rev-parse HEAD | cut -b1-8)" diff --git a/rebar.config.erl b/rebar.config.erl index a05083970..c2af2c024 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -204,9 +204,9 @@ relx_plugin_apps(ReleaseType) -> , emqx_recon , emqx_rule_engine , emqx_sasl - , emqx_telemetry , emqx_modules ] + ++ [emqx_telemetry || not is_enterprise()] ++ relx_plugin_apps_per_rel(ReleaseType) ++ relx_plugin_apps_enterprise(is_enterprise()) ++ relx_plugin_apps_extra(). diff --git a/src/emqx_app.erl b/src/emqx_app.erl index 8e0e51d25..3d08cf668 100644 --- a/src/emqx_app.erl +++ b/src/emqx_app.erl @@ -64,16 +64,20 @@ print_vsn() -> -ifdef(TEST). %% When testing, the 'cover' compiler stripps aways compile info -get_release() -> ?EMQX_RELEASE. +get_release() -> release_in_macro(). -else. %% Otherwise print the build number, %% which may have a git commit in its suffix. get_release() -> {_, Vsn} = lists:keyfind(emqx_vsn, 1, ?MODULE:module_info(compile)), - ?EMQX_RELEASE ++ _ = Vsn, %% assert + VsnStr = release_in_macro(), + 1 = string:str(Vsn, VsnStr), %% assert Vsn. -endif. +release_in_macro() -> + element(2, ?EMQX_RELEASE). + %%-------------------------------------------------------------------- %% Autocluster %%-------------------------------------------------------------------- From 08aa022029911f1d671857b3778b7c74d57545ad Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 13:21:03 +0100 Subject: [PATCH 13/37] chore(rebar.config.erl): better release matrix support --- rebar.config.erl | 54 +++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/rebar.config.erl b/rebar.config.erl index c2af2c024..aa59567e7 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -102,17 +102,18 @@ test_compile_opts() -> ]. profiles() -> + Vsn = get_vsn(), [ {'emqx', [ {erl_opts, prod_compile_opts()} - , {relx, relx('emqx')} + , {relx, relx(Vsn, cloud, bin)} ]} , {'emqx-pkg', [ {erl_opts, prod_compile_opts()} - , {relx, relx('emqx-pkg')} + , {relx, relx(Vsn, cloud, pkg)} ]} , {'emqx-edge', [ {erl_opts, prod_compile_opts()} - , {relx, relx('emqx-edge')} + , {relx, relx(Vsn, edge, bin)} ]} , {'emqx-edge-pkg', [ {erl_opts, prod_compile_opts()} - , {relx, relx('emqx-edge-pkg')} + , {relx, relx(Vsn, edge, pkg)} ]} , {check, [ {erl_opts, test_compile_opts()} ]} @@ -121,41 +122,30 @@ profiles() -> , {erl_opts, test_compile_opts() ++ erl_opts_i()} , {extra_src_dirs, [{"test", [{recursive,true}]}]} ]} - ]. + ] ++ ee_profiles(Vsn). -relx(Profile) -> - Vsn = get_vsn(), +%% RelType: cloud (full size) | edge (slim size) +%% PkgType: bin | pkg +relx(Vsn, RelType, PkgType) -> [ {include_src,false} , {include_erts, true} , {extended_start_script,false} , {generate_start_script,false} , {sys_config,false} , {vm_args,false} - ] ++ do_relx(Profile, Vsn). - -do_relx('emqx', Vsn) -> - [ {release, {emqx, Vsn}, relx_apps(cloud)} - , {overlay, relx_overlay(cloud)} - , {overlay_vars, overlay_vars(["vars/vars-cloud.config","vars/vars-bin.config"])} - ]; -do_relx('emqx-pkg', Vsn) -> - [ {release, {emqx, Vsn}, relx_apps(cloud)} - , {overlay, relx_overlay(cloud)} - , {overlay_vars, overlay_vars(["vars/vars-cloud.config","vars/vars-pkg.config"])} - ]; -do_relx('emqx-edge', Vsn) -> - [ {release, {emqx, Vsn}, relx_apps(edge)} - , {overlay, relx_overlay(edge)} - , {overlay_vars, overlay_vars(["vars/vars-edge.config","vars/vars-bin.config"])} - ]; -do_relx('emqx-edge-pkg', Vsn) -> - [ {release, {emqx, Vsn}, relx_apps(edge)} - , {overlay, relx_overlay(edge)} - , {overlay_vars, overlay_vars(["vars/vars-edge.config","vars/vars-pkg.config"])} + , {release, {emqx, Vsn}, relx_apps(RelType)} + , {overlay, relx_overlay(RelType)} + , {overlay_vars, [ {built_on_arch, rebar_utils:get_arch()} + , overlay_vars_rel(RelType) + , overlay_vars_pkg(PkgType) + ]} ]. -overlay_vars(Files) -> - [{built_on_arch, rebar_utils:get_arch()} | Files]. +overlay_vars_rel(cloud) -> "vars/vars-cloud.config"; +overlay_vars_rel(edge) -> "vars/vars-edge.config". + +overlay_vars_pkg(bin) -> "vars/vars-bin.config"; +overlay_vars_pkg(pkg) -> "vars/vars-pkg.config". relx_apps(ReleaseType) -> [ kernel @@ -400,3 +390,7 @@ coveralls() -> list_dir(Dir) -> {ok, Names} = file:list_dir(Dir), [list_to_atom(Name) || Name <- Names, filelib:is_dir(filename:join([Dir, Name]))]. + +%% ==== Enterprise supports below ================================================================== + +ee_profiles(_Vsn) -> []. From 625755ea339fe71dc9636f4da6d579e441496aec Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 22:28:14 +0100 Subject: [PATCH 14/37] chore(Makefile): refine 'make clean' --- Makefile | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ce92d5bbf..6470e124c 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ export EMQX_CE_DASHBOARD_VERSION ?= v4.3.0-beta.1 PROFILE ?= emqx REL_PROFILES := emqx emqx-edge PKG_PROFILES := emqx-pkg emqx-edge-pkg -PROFILES := $(REL_PROFILES) $(PKG_PROFILES) +PROFILES := $(REL_PROFILES) $(PKG_PROFILES) default export REBAR_GIT_CLONE_OPTIONS += --depth=1 @@ -60,12 +60,22 @@ else endif @$(REBAR) as $(@) release -# rebar clean +## Not calling rebar3 clean because +## 1. rebar3 clean relies on rebar3, meaning it reads config, fetches dependencies etc. +## 2. it's slow +## NOTE: this does not force rebar3 to fetch new version dependencies +## make clean-all to delete all fetched dependencies for a fresh start-over .PHONY: clean $(PROFILES:%=clean-%) clean: $(PROFILES:%=clean-%) -$(PROFILES:%=clean-%): $(REBAR) - @$(REBAR) as $(@:clean-%=%) clean - @rm -rf apps/emqx_dashboard/priv/www +$(PROFILES:%=clean-%): + @if [ -d _build/$(@:clean-%=%) ]; then \ + rm -rf _build/$(@:clean-%=%)/rel; \ + find _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -type f | xargs rm -f; \ + fi + +.PHONY: clean-all +clean-all: + @rm -rf _build .PHONY: deps-all deps-all: $(REBAR) $(PROFILES:%=deps-%) From e495213618ec727a72d02b514b3b66f873f51cee Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sat, 6 Mar 2021 23:12:37 +0100 Subject: [PATCH 15/37] chore(build): Add README for lib-extra --- lib-extra/README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++ lib-extra/plugins | 3 +-- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 lib-extra/README.md diff --git a/lib-extra/README.md b/lib-extra/README.md new file mode 100644 index 000000000..3196f4b8c --- /dev/null +++ b/lib-extra/README.md @@ -0,0 +1,50 @@ +# EMQ X Extra plugin apps + +This directory keeps a `plugins` file which defines all the approved +external plugins from open-source community. + +The (maybe broken) symlinks are keept to help testing plugins +in this umbrella project. + +## How to build `plugin_foo` + +Add `plugin_foo` as a rebar3 dependency in `plugins` file. + +e.g. + +``` +{erlang_plugins, + [ {plugin_foo, {git, "https://github.com/bar/plugin-foo.git", {tag, "0.1.0"}}} + ] +}. +``` + +Exeucte command + +``` +export EMQX_EXTRA_PLUGINS='plugin_foo' +make +``` + +The plugin source code should downloaded to `_build/default/lib/plugin_foo` + +NOTE: Shallow clone with depth=1 is used for git dependencies. + +## How to test `plugin_foo` + +If the source code in `_build` is already symlinked from `lib-extra/`, +you may directlly run tests with commands below. + +```bash +./rebar3 eunit --dir lib-extra/plugin_foo +./rebar3 ct --dir lib-extra/plugin_foo +``` + +In case the plugin is being actively developed +it can be cloned to `lib-extra`, e.g. `lib-extra/plugin-bar-dev` +then it can be tested with commands below: + +```bash +./rebar3 eunit --dir lib-extra/plugin-bar-dev +./rebar3 ct --dir lib-extra/plugin-bar-dev +``` diff --git a/lib-extra/plugins b/lib-extra/plugins index 03a360fd9..0f3177b9e 100644 --- a/lib-extra/plugins +++ b/lib-extra/plugins @@ -1,5 +1,4 @@ {erlang_plugins, - [ - {emqx_plugin_template, {git, "https://github.com/emqx/emqx-plugin-template", {branch, "master"}}} + [ {emqx_plugin_template, {git, "https://github.com/emqx/emqx-plugin-template", {branch, "master"}}} ] }. From de6359b5fd57e433d885e1aa947fff6cfd5b18b9 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Sun, 7 Mar 2021 09:48:01 +0100 Subject: [PATCH 16/37] chore(ci): find and run plugin tests --- .github/workflows/run_test_cases.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_test_cases.yaml b/.github/workflows/run_test_cases.yaml index 0680ef10a..0a2f13eca 100644 --- a/.github/workflows/run_test_cases.yaml +++ b/.github/workflows/run_test_cases.yaml @@ -40,9 +40,11 @@ jobs: - name: run eunit run: | docker exec -i erlang bash -c "make eunit" - docker exec --env EMQX_EXTRA_PLUGINS=all -i erlang bash -c "./rebar3 eunit --dir lib-extra/*" + docker exec --env EMQX_EXTRA_PLUGINS=all -i erlang bash -c "./rebar3 eunit --dir $(find lib-extra/ -mindepth 1 -maxdepth 2 -type l | tr '\n' ',')" - name: run common test - run: docker exec -i erlang bash -c "make ct" + run: | + docker exec -i erlang bash -c "make ct" + docker exec --env EMQX_EXTRA_PLUGINS=all -i erlang bash -c "./rebar3 ct --dir $(find lib-extra/ -mindepth 1 -maxdepth 2 -type l | tr '\n' ',')" - name: run cover run: | docker exec -i erlang bash -c "make cover" From b7bde35b512d7481f0813f3a1897d4ea2b103e37 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Mon, 8 Mar 2021 11:35:15 +0100 Subject: [PATCH 17/37] chore(Makefile): delete .o .d files when make clean --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6470e124c..6ccc2fe8f 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ clean: $(PROFILES:%=clean-%) $(PROFILES:%=clean-%): @if [ -d _build/$(@:clean-%=%) ]; then \ rm -rf _build/$(@:clean-%=%)/rel; \ - find _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -type f | xargs rm -f; \ + find _build/$(@:clean-%=%) -name '*.beam' -o -name '*.so' -o -name '*.app' -o -name '*.appup' -o -name '*.o' -o -name '*.d' -type f | xargs rm -f; \ fi .PHONY: clean-all From 115397523d1b21542e5b368ba2d775484171f503 Mon Sep 17 00:00:00 2001 From: turtleDeng Date: Mon, 8 Mar 2021 20:47:31 +0800 Subject: [PATCH 18/37] chore(build): add more enterprise build support (#4302) --- bin/emqx | 7 ++- data/emqx_vars | 1 + data/loaded_plugins.tmpl | 7 +-- lib-ce/emqx_dashboard/src/emqx_dashboard.erl | 4 +- rebar.config.erl | 45 ++++++++++---------- vars/vars-cloud.config | 4 ++ vars/vars-edge.config | 4 ++ 7 files changed, 45 insertions(+), 27 deletions(-) diff --git a/bin/emqx b/bin/emqx index 3d5900ef7..43cc89b44 100755 --- a/bin/emqx +++ b/bin/emqx @@ -209,7 +209,12 @@ generate_config() { # the vm, we need to pass it in twice. CONFIG_ARGS=" -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -vm_args $RUNNER_ETC_DIR/vm.args " else - CONFIG_ARGS=$("$ERTS_PATH"/escript "$RUNNER_ROOT_DIR"/bin/cuttlefish -i "$REL_DIR"/emqx.schema -c "$RUNNER_ETC_DIR"/emqx.conf -d "$RUNNER_DATA_DIR"/configs generate) + EMQX_LICENSE_CONF_OPTION="" + if [ "${EMQX_LICENSE_CONF:-}" != "" ]; then + EMQX_LICENSE_CONF_OPTION="-i ${EMQX_LICENSE_CONF}" + fi + # shellcheck disable=SC2086 + CONFIG_ARGS=$("$ERTS_PATH"/escript "$RUNNER_ROOT_DIR"/bin/cuttlefish -i "$REL_DIR"/emqx.schema $EMQX_LICENSE_CONF_OPTION -c "$RUNNER_ETC_DIR"/emqx.conf -d "$RUNNER_DATA_DIR"/configs generate) ## Merge cuttlefish generated *.args into the vm.args CUTTLE_GEN_ARG_FILE=$(echo "$CONFIG_ARGS" | sed -n 's/^.*\(vm_args[[:space:]]\)//p' | awk '{print $1}') diff --git a/data/emqx_vars b/data/emqx_vars index 5159fa246..55fcec04d 100644 --- a/data/emqx_vars +++ b/data/emqx_vars @@ -16,6 +16,7 @@ RUNNER_USER="{{ runner_user }}" EMQX_DISCR="{{ emqx_description }}" LIB_EKKA_DIR="${RUNNER_LIB_DIR}/ekka-$(grep ekka "${RUNNER_ROOT_DIR}/releases/RELEASES" | awk -F '\"' '{print $2}')" +EMQX_LICENSE_CONF='' ## computed vars REL_NAME="emqx" ERTS_PATH="$RUNNER_ROOT_DIR/erts-$ERTS_VSN/bin" diff --git a/data/loaded_plugins.tmpl b/data/loaded_plugins.tmpl index 6fde9cace..d0dac7fe1 100644 --- a/data/loaded_plugins.tmpl +++ b/data/loaded_plugins.tmpl @@ -1,7 +1,8 @@ {emqx_management, true}. -{emqx_recon, true}. -{emqx_retainer, true}. {emqx_dashboard, true}. -{emqx_telemetry, true}. +{emqx_modules, {{enable_plugin_emqx_modules}}}. +{emqx_recon, {{enable_plugin_emqx_recon}}}. +{emqx_retainer, {{enable_plugin_emqx_retainer}}}. +{emqx_telemetry, {{enable_plugin_emqx_telemetry}}}. {emqx_rule_engine, {{enable_plugin_emqx_rule_engine}}}. {emqx_bridge_mqtt, {{enable_plugin_emqx_bridge_mqtt}}}. diff --git a/lib-ce/emqx_dashboard/src/emqx_dashboard.erl b/lib-ce/emqx_dashboard/src/emqx_dashboard.erl index cbf0d81d5..a2ba1f125 100644 --- a/lib-ce/emqx_dashboard/src/emqx_dashboard.erl +++ b/lib-ce/emqx_dashboard/src/emqx_dashboard.erl @@ -87,7 +87,8 @@ listener_name(Proto) -> http_handlers() -> Plugins = lists:map(fun(Plugin) -> Plugin#plugin.name end, emqx_plugins:list()), [{"/api/v4/", - minirest:handler(#{apps => Plugins, filter => fun ?MODULE:filter/1}), + minirest:handler(#{apps => Plugins ++ [emqx_modules], + filter => fun ?MODULE:filter/1}), [{authorization, fun ?MODULE:is_authorized/1}]}]. %%-------------------------------------------------------------------- @@ -113,6 +114,7 @@ is_authorized(_Path, Req) -> _ -> false end. +filter(#{app := emqx_modules}) -> true; filter(#{app := App}) -> case emqx_plugins:find_plugin(App) of false -> false; diff --git a/rebar.config.erl b/rebar.config.erl index aa59567e7..56949a409 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -164,8 +164,9 @@ relx_apps(ReleaseType) -> , {mnesia, load} , {ekka, load} , {emqx_plugin_libs, load} - , emqx_modules ] + ++ [emqx_modules || not is_enterprise()] + ++ [emqx_license || is_enterprise()] ++ [bcrypt || provide_bcrypt_release(ReleaseType)] ++ relx_apps_per_rel(ReleaseType) ++ [{N, load} || N <- relx_plugin_apps(ReleaseType)]. @@ -194,7 +195,6 @@ relx_plugin_apps(ReleaseType) -> , emqx_recon , emqx_rule_engine , emqx_sasl - , emqx_modules ] ++ [emqx_telemetry || not is_enterprise()] ++ relx_plugin_apps_per_rel(ReleaseType) @@ -225,28 +225,28 @@ relx_plugin_apps_extra() -> [Plugin || {Plugin, _} <- extra_deps()]. relx_overlay(ReleaseType) -> - [ {mkdir,"log/"} - , {mkdir,"data/"} - , {mkdir,"data/mnesia"} - , {mkdir,"data/configs"} - , {mkdir,"data/scripts"} + [ {mkdir, "log/"} + , {mkdir, "data/"} + , {mkdir, "data/mnesia"} + , {mkdir, "data/configs"} + , {mkdir, "data/scripts"} , {template, "data/loaded_plugins.tmpl", "data/loaded_plugins"} , {template, "data/loaded_modules.tmpl", "data/loaded_modules"} - , {template,"data/emqx_vars","releases/emqx_vars"} - , {copy,"bin/emqx","bin/emqx"} - , {copy,"bin/emqx_ctl","bin/emqx_ctl"} - , {copy,"bin/install_upgrade.escript", "bin/install_upgrade.escript"} - , {copy,"bin/emqx","bin/emqx-{{release_version}}"} %% for relup - , {copy,"bin/emqx_ctl","bin/emqx_ctl-{{release_version}}"} %% for relup - , {copy,"bin/install_upgrade.escript", "bin/install_upgrade.escript-{{release_version}}"} %% for relup - , {template,"bin/emqx.cmd","bin/emqx.cmd"} - , {template,"bin/emqx_ctl.cmd","bin/emqx_ctl.cmd"} - , {copy,"bin/nodetool","bin/nodetool"} - , {copy,"bin/nodetool","bin/nodetool-{{release_version}}"} - , {copy,"_build/default/lib/cuttlefish/cuttlefish","bin/cuttlefish"} - , {copy,"_build/default/lib/cuttlefish/cuttlefish","bin/cuttlefish-{{release_version}}"} - , {copy,"priv/emqx.schema","releases/{{release_version}}/"} - ] ++ etc_overlay(ReleaseType). + , {template, "data/emqx_vars", "releases/emqx_vars"} + , {copy, "bin/emqx", "bin/emqx"} + , {copy, "bin/emqx_ctl", "bin/emqx_ctl"} + , {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript"} + , {copy, "bin/emqx", "bin/emqx-{{release_version}}"} %% for relup + , {copy, "bin/emqx_ctl", "bin/emqx_ctl-{{release_version}}"} %% for relup + , {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript-{{release_version}}"} %% for relup + , {template, "bin/emqx.cmd", "bin/emqx.cmd"} + , {template, "bin/emqx_ctl.cmd", "bin/emqx_ctl.cmd"} + , {copy, "bin/nodetool", "bin/nodetool"} + , {copy, "bin/nodetool", "bin/nodetool-{{release_version}}"} + , {copy, "_build/default/lib/cuttlefish/cuttlefish", "bin/cuttlefish"} + , {copy, "_build/default/lib/cuttlefish/cuttlefish", "bin/cuttlefish-{{release_version}}"} + , {copy, "priv/emqx.schema", "releases/{{release_version}}/"} + ] ++ ee_etc_overlay() ++ etc_overlay(ReleaseType). etc_overlay(ReleaseType) -> PluginApps = relx_plugin_apps(ReleaseType), @@ -394,3 +394,4 @@ list_dir(Dir) -> %% ==== Enterprise supports below ================================================================== ee_profiles(_Vsn) -> []. +ee_etc_overlay() -> []. diff --git a/vars/vars-cloud.config b/vars/vars-cloud.config index 266ef717c..8362bcf56 100644 --- a/vars/vars-cloud.config +++ b/vars/vars-cloud.config @@ -1,4 +1,8 @@ {enable_plugin_emqx_rule_engine, true}. {enable_plugin_emqx_bridge_mqtt, false}. +{enable_plugin_emqx_modules, false}. +{enable_plugin_emqx_recon, true}. +{enable_plugin_emqx_retainer, true}. +{enable_plugin_emqx_telemetry, true}. {vm_args_file, "vm.args"}. {emqx_description, "EMQ X Broker"}. \ No newline at end of file diff --git a/vars/vars-edge.config b/vars/vars-edge.config index 9b1d76401..bc36db504 100644 --- a/vars/vars-edge.config +++ b/vars/vars-edge.config @@ -1,4 +1,8 @@ {enable_plugin_emqx_rule_engine, false}. {enable_plugin_emqx_bridge_mqtt, true}. +{enable_plugin_emqx_modules, false}. +{enable_plugin_emqx_recon, true}. +{enable_plugin_emqx_retainer, true}. +{enable_plugin_emqx_telemetry, true}. {vm_args_file, "vm.args.edge"}. {emqx_description, "EMQ X Edge"}. From 7eb6588cc984875503a4757177d5fe3ad5b932cc Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 01:50:24 +0100 Subject: [PATCH 19/37] Chore build update rebar3 version (#4303) * chore(Makefile): Delete unnecessary exports for deps-get * chore(rebar3): upgrade to rebar3 version 3.14.3-emqx-5 This rebar3 version does not copy .git directory. Before this, if a plugin repo clone is placed in lib-extra, rebar2 ct or eunit commnad may fail at source code copy step. --- Makefile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 6ccc2fe8f..ab0bbeac0 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ $(shell scripts/git-hooks-init.sh) -REBAR_VERSION = 3.14.3-emqx-4 +REBAR_VERSION = 3.14.3-emqx-5 REBAR = $(CURDIR)/rebar3 BUILD = $(CURDIR)/build SCRIPTS = $(CURDIR)/scripts @@ -80,13 +80,11 @@ clean-all: .PHONY: deps-all deps-all: $(REBAR) $(PROFILES:%=deps-%) +## deps- is used in CI scripts to download deps and the +## share downloads between CI steps and/or copied into containers +## which may not have the right credentials .PHONY: $(PROFILES:%=deps-%) $(PROFILES:%=deps-%): $(REBAR) get-dashboard -ifneq ($(shell echo $(@) |grep edge),) - @export EMQX_DESC="$${EMQX_DESC} Edge" -else - @export EMQX_DESC="$${EMQX_DESC} Broker" -endif @$(REBAR) as $(@:deps-%=%) get-deps .PHONY: xref From 4585306774cef3e61b321aec657c5fb8342a6e9a Mon Sep 17 00:00:00 2001 From: JianBo He Date: Wed, 24 Feb 2021 11:27:44 +0800 Subject: [PATCH 20/37] chore(exhook): upgrade to 0.6.2 --- .../docs/{design.md => design-cn.md} | 6 +-- apps/emqx_exhook/rebar.config | 8 +-- apps/emqx_exhook/src/emqx_exhook_handler.erl | 52 +++++++++++++++++++ apps/emqx_exproto/rebar.config | 10 ++-- 4 files changed, 66 insertions(+), 10 deletions(-) rename apps/emqx_exhook/docs/{design.md => design-cn.md} (93%) diff --git a/apps/emqx_exhook/docs/design.md b/apps/emqx_exhook/docs/design-cn.md similarity index 93% rename from apps/emqx_exhook/docs/design.md rename to apps/emqx_exhook/docs/design-cn.md index 671e240cc..6686e96e3 100644 --- a/apps/emqx_exhook/docs/design.md +++ b/apps/emqx_exhook/docs/design-cn.md @@ -19,7 +19,7 @@ 2. 将 `emqx-extension-hook` 重命名为 `emqx-exhook` -旧版本的设计参考:[emqx-extension-hook design in v4.2.0](https://github.com/emqx/emqx-exhook/blob/v4.2.0/docs/design.md) +旧版本的设计:[emqx-extension-hook design in v4.2.0](https://github.com/emqx/emqx-exhook/blob/v4.2.0/docs/design.md) ## 设计 @@ -39,13 +39,13 @@ `emqx-exhook` 通过 gRPC 的方式向用户部署的 gRPC 服务发送钩子的请求,并处理其返回的值。 -和 emqx 原生的钩子一致,emqx-exhook 也支持链式的方式计算和返回: +和 emqx 原生的钩子一致,emqx-exhook 也按照链式的方式执行: ### gRPC 服务示例 -用户需要实现的方法,和数据类型的定义在 `priv/protos/exhook.proto` 文件中。例如,其支持的接口有: +用户需要实现的方法,和数据类型的定义在 `priv/protos/exhook.proto` 文件中: ```protobuff syntax = "proto3"; diff --git a/apps/emqx_exhook/rebar.config b/apps/emqx_exhook/rebar.config index d2e437b8b..883aad9bd 100644 --- a/apps/emqx_exhook/rebar.config +++ b/apps/emqx_exhook/rebar.config @@ -1,11 +1,11 @@ %%-*- mode: erlang -*- {plugins, [rebar3_proper, - {grpc_plugin, {git, "https://github.com/HJianBo/grpcbox_plugin", {tag, "v0.10.0"}}} + {grpc_plugin, {git, "https://github.com/HJianBo/grpc_plugin", {tag, "v0.10.2"}}} ]}. {deps, - [{grpc, {git, "https://github.com/emqx/grpc", {tag, "0.6.0"}}} + [{grpc, {git, "https://github.com/emqx/grpc-erl", {tag, "0.6.2"}}} ]}. {grpc, @@ -15,7 +15,9 @@ ]}. {provider_hooks, - [{pre, [{compile, {grpc, gen}}]}]}. + [{pre, [{compile, {grpc, gen}}, + {clean, {grpc, clean}}]} +]}. {edoc_opts, [{preprocess, true}]}. diff --git a/apps/emqx_exhook/src/emqx_exhook_handler.erl b/apps/emqx_exhook/src/emqx_exhook_handler.erl index 3a35073ca..c565d5dee 100644 --- a/apps/emqx_exhook/src/emqx_exhook_handler.erl +++ b/apps/emqx_exhook/src/emqx_exhook_handler.erl @@ -42,6 +42,12 @@ , on_session_terminated/3 ]). +-export([ on_message_publish/1 + , on_message_dropped/3 + , on_message_delivered/2 + , on_message_acked/2 + ]). + %% Utils -export([ message/1 , stringfy/1 @@ -71,8 +77,15 @@ , {'session.discarded', {?MODULE, on_session_discarded, []}} , {'session.takeovered', {?MODULE, on_session_takeovered, []}} , {'session.terminated', {?MODULE, on_session_terminated, []}} + %]). + , {'message.publish', {?MODULE, on_message_publish, []}} + , {'message.delivered', {?MODULE, on_message_delivered, []}} + , {'message.acked', {?MODULE, on_message_acked, []}} + , {'message.dropped', {?MODULE, on_message_dropped, []}} ]). + + %%-------------------------------------------------------------------- %% Clients %%-------------------------------------------------------------------- @@ -185,6 +198,45 @@ on_session_terminated(ClientInfo, Reason, _SessInfo) -> reason => stringfy(Reason)}, cast('session.terminated', Req). +%%-------------------------------------------------------------------- +%% Message +%%-------------------------------------------------------------------- + +on_message_publish(#message{topic = <<"$SYS/", _/binary>>}) -> + ok; +on_message_publish(Message) -> + Req = #{message => message(Message)}, + case call_fold('message.publish', Req, + fun emqx_exhook_handler:merge_responsed_message/2) of + {StopOrOk, #{message := NMessage}} -> + {StopOrOk, assign_to_message(NMessage, Message)}; + _ -> {ok, Message} + end. + +on_message_dropped(#message{topic = <<"$SYS/", _/binary>>}, _By, _Reason) -> + ok; +on_message_dropped(Message, _By, Reason) -> + Req = #{message => message(Message), + reason => stringfy(Reason) + }, + cast('message.dropped', Req). + +on_message_delivered(_ClientInfo, #message{topic = <<"$SYS/", _/binary>>}) -> + ok; +on_message_delivered(ClientInfo, Message) -> + Req = #{clientinfo => clientinfo(ClientInfo), + message => message(Message) + }, + cast('message.delivered', Req). + +on_message_acked(_ClientInfo, #message{topic = <<"$SYS/", _/binary>>}) -> + ok; +on_message_acked(ClientInfo, Message) -> + Req = #{clientinfo => clientinfo(ClientInfo), + message => message(Message) + }, + cast('message.acked', Req). + %%-------------------------------------------------------------------- %% Types diff --git a/apps/emqx_exproto/rebar.config b/apps/emqx_exproto/rebar.config index 88831ce15..61677f0e3 100644 --- a/apps/emqx_exproto/rebar.config +++ b/apps/emqx_exproto/rebar.config @@ -9,11 +9,11 @@ {parse_transform}]}. {plugins, [rebar3_proper, - {grpc_plugin, {git, "https://github.com/HJianBo/grpcbox_plugin", {tag, "v0.10.0"}}} + {grpc_plugin, {git, "https://github.com/HJianBo/grpc_plugin", {tag, "v0.10.2"}}} ]}. {deps, - [{grpc, {git, "https://github.com/emqx/grpc", {tag, "0.6.0"}}} + [{grpc, {git, "https://github.com/emqx/grpc-erl", {tag, "0.6.2"}}} ]}. {grpc, @@ -21,10 +21,12 @@ {protos, ["priv/protos"]}, {gpb_opts, [{module_name_prefix, "emqx_"}, {module_name_suffix, "_pb"}]} - ]}. +]}. {provider_hooks, - [{pre, [{compile, {grpc, gen}}]}]}. + [{pre, [{compile, {grpc, gen}}, + {clean, {grpc, clean}}]} +]}. {xref_checks, [undefined_function_calls, undefined_functions, locals_not_used, deprecated_function_calls, From 0d8c137cb558d088c69fa2aceb0a5e01b5578ddd Mon Sep 17 00:00:00 2001 From: JianBo He Date: Thu, 25 Feb 2021 19:55:54 +0800 Subject: [PATCH 21/37] refactor(exhook): load only the necessary hooks --- apps/emqx_exhook/src/emqx_exhook_app.erl | 19 ++++++---- apps/emqx_exhook/src/emqx_exhook_handler.erl | 22 ++++++++++- apps/emqx_exhook/src/emqx_exhook_server.erl | 39 ++++++++++++++++++-- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/apps/emqx_exhook/src/emqx_exhook_app.erl b/apps/emqx_exhook/src/emqx_exhook_app.erl index b008c251a..45474d925 100644 --- a/apps/emqx_exhook/src/emqx_exhook_app.erl +++ b/apps/emqx_exhook/src/emqx_exhook_app.erl @@ -22,6 +22,8 @@ -emqx_plugin(extension). +-define(REGISTRAY, emqx_exhook_registray). + -export([ start/2 , stop/1 , prep_stop/1 @@ -30,8 +32,8 @@ %% Internal export -export([ load_server/2 , unload_server/1 - , load_exhooks/0 , unload_exhooks/0 + , init_hook_registray/0 ]). %%-------------------------------------------------------------------- @@ -41,12 +43,12 @@ start(_StartType, _StartArgs) -> {ok, Sup} = emqx_exhook_sup:start_link(), + %% Collect all available hooks + _ = init_hook_registray(), + %% Load all dirvers load_all_servers(), - %% Register all hooks - _ = load_exhooks(), - %% Register CLI emqx_ctl:register_command(exhook, {emqx_exhook_cli, cli}, []), {ok, Sup}. @@ -81,11 +83,14 @@ unload_server(Name) -> %%-------------------------------------------------------------------- %% Exhooks -load_exhooks() -> - [emqx:hook(Name, {M, F, A}) || {Name, {M, F, A}} <- search_exhooks()]. +init_hook_registray() -> + _ = ets:new(?REGISTRAY, [public, named_table]), + [ets:insert(?REGISTRAY, {Name, {M, F, A}, 0}) + || {Name, {M, F, A}} <- search_exhooks()]. unload_exhooks() -> - [emqx:unhook(Name, {M, F}) || {Name, {M, F, _A}} <- search_exhooks()]. + [emqx:unhook(Name, {M, F}) || + {Name, {M, F, _A}, _} <- ets:tab2list(?REGISTRAY)]. search_exhooks() -> search_exhooks(ignore_lib_apps(application:loaded_applications())). diff --git a/apps/emqx_exhook/src/emqx_exhook_handler.erl b/apps/emqx_exhook/src/emqx_exhook_handler.erl index c565d5dee..980fb7786 100644 --- a/apps/emqx_exhook/src/emqx_exhook_handler.erl +++ b/apps/emqx_exhook/src/emqx_exhook_handler.erl @@ -307,8 +307,26 @@ stringfy(Term) when is_atom(Term) -> stringfy(Term) -> unicode:characters_to_binary((io_lib:format("~0p", [Term]))). -hexstr(B) -> - iolist_to_binary([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(B)]). +hexstr(<<>>) -> []; +hexstr(<>) -> + iolist_to_binary([hexchar(H), hexchar(L)] ++ hexstr(B)). + +hexchar(0) -> $0; +hexchar(1) -> $1; +hexchar(2) -> $2; +hexchar(3) -> $3; +hexchar(4) -> $4; +hexchar(5) -> $5; +hexchar(6) -> $6; +hexchar(7) -> $7; +hexchar(8) -> $8; +hexchar(9) -> $9; +hexchar(10) -> $A; +hexchar(11) -> $B; +hexchar(12) -> $C; +hexchar(13) -> $D; +hexchar(14) -> $E; +hexchar(15) -> $F. %%-------------------------------------------------------------------- %% Acc funcs diff --git a/apps/emqx_exhook/src/emqx_exhook_server.erl b/apps/emqx_exhook/src/emqx_exhook_server.erl index 451983437..76a2e491d 100644 --- a/apps/emqx_exhook/src/emqx_exhook_server.erl +++ b/apps/emqx_exhook/src/emqx_exhook_server.erl @@ -20,6 +20,7 @@ -logger_header("[ExHook Svr]"). +-define(REGISTRAY, emqx_exhook_registray). -define(PB_CLIENT_MOD, emqx_exhook_v_1_hook_provider_client). %% Load/Unload @@ -83,13 +84,19 @@ load(Name0, Opts0) -> Name = prefix(Name0), {SvrAddr, ClientOpts} = channel_opts(Opts0), - case emqx_exhook_sup:start_grpc_client_channel(Name, SvrAddr, ClientOpts) of + case emqx_exhook_sup:start_grpc_client_channel( + Name, + SvrAddr, + ClientOpts) of {ok, _ChannPoolPid} -> case do_init(Name) of {ok, HookSpecs} -> %% Reigster metrics - Prefix = lists:flatten(io_lib:format("exhook.~s.", [Name])), + Prefix = lists:flatten( + io_lib:format("exhook.~s.", [Name])), ensure_metrics(Prefix, HookSpecs), + %% Ensure hooks + ensure_hooks(HookSpecs), {ok, #server{name = Name, options = Opts0, channel = _ChannPoolPid, @@ -126,8 +133,9 @@ channel_opts(Opts) -> {SvrAddr, ClientOpts}. -spec unload(server()) -> ok. -unload(#server{name = Name}) -> +unload(#server{name = Name, hookspec = HookSpecs}) -> _ = do_deinit(Name), + _ = may_unload_hooks(HookSpecs), _ = emqx_exhook_sup:stop_grpc_client_channel(Name), ok. @@ -177,6 +185,31 @@ ensure_metrics(Prefix, HookSpecs) -> || Hookpoint <- maps:keys(HookSpecs)], lists:foreach(fun emqx_metrics:ensure/1, Keys). +ensure_hooks(HookSpecs) -> + lists:foreach(fun(Hookpoint) -> + case ets:lookup(?REGISTRAY, Hookpoint) of + [] -> + ?LOG(warning, "Hoook ~s not found in registray", [Hookpoint]); + [{Hookpoint, {M, F, A}, _}] -> + emqx_hooks:put(Hookpoint, {M, F, A}), + ets:update_counter(?REGISTRAY, Hookpoint, {3, 1}) + end + end, maps:keys(HookSpecs)). + +may_unload_hooks(HookSpecs) -> + lists:foreach(fun(Hookpoint) -> + case ets:update_counter(?REGISTRAY, Hookpoint, {3, -1}) of + Cnt when Cnt =< 0 -> + case ets:lookup(?REGISTRAY, Hookpoint) of + [{Hookpoint, {M, F, _A}, _}] -> + emqx_hooks:del(Hookpoint, {M, F}); + _ -> ok + end, + ets:delete(?REGISTRAY, Hookpoint); + _ -> ok + end + end, maps:keys(HookSpecs)). + format(#server{name = Name, hookspec = Hooks}) -> io_lib:format("name=~p, hooks=~0p", [Name, Hooks]). From f9d5d3523d93958e96d051804afb848a86f40cc4 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Sun, 28 Feb 2021 15:36:34 +0800 Subject: [PATCH 22/37] chore(exhook): add more option for protobuff --- apps/emqx_exhook/priv/protos/exhook.proto | 6 +++++ apps/emqx_exhook/src/emqx_exhook_handler.erl | 23 ++++---------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/apps/emqx_exhook/priv/protos/exhook.proto b/apps/emqx_exhook/priv/protos/exhook.proto index 8dc9641b9..41f471d14 100644 --- a/apps/emqx_exhook/priv/protos/exhook.proto +++ b/apps/emqx_exhook/priv/protos/exhook.proto @@ -16,6 +16,12 @@ syntax = "proto3"; +option csharp_namespace = "Emqx.Exhook.V1"; +option go_package = "emqx.io/grpc/exhook"; +option java_multiple_files = true; +option java_package = "io.emqx.exhook"; +option java_outer_classname = "EmqxExHookProto"; + package emqx.exhook.v1; service HookProvider { diff --git a/apps/emqx_exhook/src/emqx_exhook_handler.erl b/apps/emqx_exhook/src/emqx_exhook_handler.erl index 980fb7786..b93f23cdd 100644 --- a/apps/emqx_exhook/src/emqx_exhook_handler.erl +++ b/apps/emqx_exhook/src/emqx_exhook_handler.erl @@ -307,26 +307,11 @@ stringfy(Term) when is_atom(Term) -> stringfy(Term) -> unicode:characters_to_binary((io_lib:format("~0p", [Term]))). -hexstr(<<>>) -> []; -hexstr(<>) -> - iolist_to_binary([hexchar(H), hexchar(L)] ++ hexstr(B)). +hexstr(B) -> + << <<(hexchar(H)), (hexchar(L))>> || <> <= B>>. -hexchar(0) -> $0; -hexchar(1) -> $1; -hexchar(2) -> $2; -hexchar(3) -> $3; -hexchar(4) -> $4; -hexchar(5) -> $5; -hexchar(6) -> $6; -hexchar(7) -> $7; -hexchar(8) -> $8; -hexchar(9) -> $9; -hexchar(10) -> $A; -hexchar(11) -> $B; -hexchar(12) -> $C; -hexchar(13) -> $D; -hexchar(14) -> $E; -hexchar(15) -> $F. +hexchar(I) when I >= 0 andalso I < 10 -> I + $0; +hexchar(I) -> I - 10 + $A. %%-------------------------------------------------------------------- %% Acc funcs From ebffdafe8699538b4d5857641a060b09d82ba43e Mon Sep 17 00:00:00 2001 From: JianBo He Date: Sat, 6 Mar 2021 15:28:18 +0800 Subject: [PATCH 23/37] fix(exproto): ignore undefined clientid --- apps/emqx_exproto/src/emqx_exproto_conn.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/emqx_exproto/src/emqx_exproto_conn.erl b/apps/emqx_exproto/src/emqx_exproto_conn.erl index b29e0b7f5..efe4b7f22 100644 --- a/apps/emqx_exproto/src/emqx_exproto_conn.erl +++ b/apps/emqx_exproto/src/emqx_exproto_conn.erl @@ -515,8 +515,12 @@ handle_timeout(TRef, keepalive, State = #state{socket = Socket, end; handle_timeout(_TRef, emit_stats, State = #state{channel = Channel}) -> - ClientId = emqx_exproto_channel:info(clientid, Channel), - emqx_cm:set_chan_stats(ClientId, stats(State)), + case emqx_exproto_channel:info(clientid, Channel) of + undefined -> + ignore; + ClientId -> + emqx_cm:set_chan_stats(ClientId, stats(State)) + end, {ok, State#state{stats_timer = undefined}}; handle_timeout(TRef, Msg, State) -> From 6bf15c6a2f7cac9ecceee2a7a71030ef93df8d90 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Mon, 8 Mar 2021 11:49:18 +0800 Subject: [PATCH 24/37] chore(exhook): deinit registray after application stopped --- apps/emqx_exhook/src/emqx_exhook_app.erl | 4 ++++ apps/emqx_exhook/src/emqx_exhook_handler.erl | 11 ++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/emqx_exhook/src/emqx_exhook_app.erl b/apps/emqx_exhook/src/emqx_exhook_app.erl index 45474d925..3b829e7cd 100644 --- a/apps/emqx_exhook/src/emqx_exhook_app.erl +++ b/apps/emqx_exhook/src/emqx_exhook_app.erl @@ -57,6 +57,7 @@ prep_stop(State) -> emqx_ctl:unregister_command(exhook), _ = unload_exhooks(), ok = unload_all_servers(), + _ = deinit_hook_registray(), State. stop(_State) -> @@ -92,6 +93,9 @@ unload_exhooks() -> [emqx:unhook(Name, {M, F}) || {Name, {M, F, _A}, _} <- ets:tab2list(?REGISTRAY)]. +deinit_hook_registray() -> + ets:delete(?REGISTRAY). + search_exhooks() -> search_exhooks(ignore_lib_apps(application:loaded_applications())). search_exhooks(Apps) -> diff --git a/apps/emqx_exhook/src/emqx_exhook_handler.erl b/apps/emqx_exhook/src/emqx_exhook_handler.erl index b93f23cdd..e60eadaa7 100644 --- a/apps/emqx_exhook/src/emqx_exhook_handler.erl +++ b/apps/emqx_exhook/src/emqx_exhook_handler.erl @@ -77,15 +77,12 @@ , {'session.discarded', {?MODULE, on_session_discarded, []}} , {'session.takeovered', {?MODULE, on_session_takeovered, []}} , {'session.terminated', {?MODULE, on_session_terminated, []}} - %]). - , {'message.publish', {?MODULE, on_message_publish, []}} - , {'message.delivered', {?MODULE, on_message_delivered, []}} - , {'message.acked', {?MODULE, on_message_acked, []}} - , {'message.dropped', {?MODULE, on_message_dropped, []}} + , {'message.publish', {?MODULE, on_message_publish, []}} + , {'message.delivered', {?MODULE, on_message_delivered, []}} + , {'message.acked', {?MODULE, on_message_acked, []}} + , {'message.dropped', {?MODULE, on_message_dropped, []}} ]). - - %%-------------------------------------------------------------------- %% Clients %%-------------------------------------------------------------------- From b629a6c58cc416f7a49aab79aaecdf72a849e314 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 12:33:58 +0100 Subject: [PATCH 25/37] chore(scripts): fix typo for var names --- bin/emqx | 6 +++--- data/emqx_vars | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/emqx b/bin/emqx index 43cc89b44..89a1d796a 100755 --- a/bin/emqx +++ b/bin/emqx @@ -393,10 +393,10 @@ case "$1" in fi sleep 1 if relx_nodetool "ping" >/dev/null 2>&1; then - echo "$EMQX_DISCR $REL_VSN is started successfully!" + echo "$EMQX_DESCRIPTION $REL_VSN is started successfully!" exit 0 fi - done && echo "$EMQX_DISCR $REL_VSN failed to start within ${WAIT_FOR_ERLANG:-15} seconds," + done && echo "$EMQX_DESCRIPTION $REL_VSN failed to start within ${WAIT_FOR_ERLANG:-15} seconds," echo "see the output of '$0 console' for more information." echo "If you want to wait longer, set the environment variable" echo "WAIT_FOR_ERLANG to the number of seconds to wait." @@ -415,7 +415,7 @@ case "$1" in ;; restart|reboot) - echo "$EMQX_DISCR $REL_VSN is stopped: $("$RUNNER_BIN_DIR"/emqx stop)" + echo "$EMQX_DESCRIPTION $REL_VSN is stopped: $("$RUNNER_BIN_DIR"/emqx stop)" "$RUNNER_BIN_DIR"/emqx start ;; diff --git a/data/emqx_vars b/data/emqx_vars index 55fcec04d..ea566d3ee 100644 --- a/data/emqx_vars +++ b/data/emqx_vars @@ -13,10 +13,11 @@ RUNNER_LIB_DIR="{{ runner_lib_dir }}" RUNNER_ETC_DIR="{{ runner_etc_dir }}" RUNNER_DATA_DIR="{{ runner_data_dir }}" RUNNER_USER="{{ runner_user }}" -EMQX_DISCR="{{ emqx_description }}" LIB_EKKA_DIR="${RUNNER_LIB_DIR}/ekka-$(grep ekka "${RUNNER_ROOT_DIR}/releases/RELEASES" | awk -F '\"' '{print $2}')" EMQX_LICENSE_CONF='' +EMQX_DESCRIPTION="{{ emqx_description }}" + ## computed vars REL_NAME="emqx" ERTS_PATH="$RUNNER_ROOT_DIR/erts-$ERTS_VSN/bin" From d14b90ef2efaee901a80ad0c0f425bb195fad4c9 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 15:32:26 +0100 Subject: [PATCH 26/37] chore(build): Feed relx overlay var from rebar.config.erl --- rebar.config.erl | 9 +++++++++ vars/vars-cloud.config | 1 - vars/vars-edge.config | 1 - 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/rebar.config.erl b/rebar.config.erl index 56949a409..b73e9522d 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -136,11 +136,20 @@ relx(Vsn, RelType, PkgType) -> , {release, {emqx, Vsn}, relx_apps(RelType)} , {overlay, relx_overlay(RelType)} , {overlay_vars, [ {built_on_arch, rebar_utils:get_arch()} + , {emqx_description, emqx_description(RelType)} , overlay_vars_rel(RelType) , overlay_vars_pkg(PkgType) ]} ]. +emqx_description(cloud) -> + case is_enterprise() of + true -> "EMQ X Enterprise"; + false -> "EMQ X Broker" + end; +emqx_description(edge) -> + "EMQ X Edge". + overlay_vars_rel(cloud) -> "vars/vars-cloud.config"; overlay_vars_rel(edge) -> "vars/vars-edge.config". diff --git a/vars/vars-cloud.config b/vars/vars-cloud.config index 8362bcf56..a898927d7 100644 --- a/vars/vars-cloud.config +++ b/vars/vars-cloud.config @@ -5,4 +5,3 @@ {enable_plugin_emqx_retainer, true}. {enable_plugin_emqx_telemetry, true}. {vm_args_file, "vm.args"}. -{emqx_description, "EMQ X Broker"}. \ No newline at end of file diff --git a/vars/vars-edge.config b/vars/vars-edge.config index bc36db504..2df294838 100644 --- a/vars/vars-edge.config +++ b/vars/vars-edge.config @@ -5,4 +5,3 @@ {enable_plugin_emqx_retainer, true}. {enable_plugin_emqx_telemetry, true}. {vm_args_file, "vm.args.edge"}. -{emqx_description, "EMQ X Edge"}. From e1979bf488d0d0c6b802f854b63c80d03c537f3c Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 15:43:44 +0100 Subject: [PATCH 27/37] chore(build): Single source of EMQX_DESCRIPTION --- Makefile | 5 ----- data/emqx_vars | 2 +- src/emqx.app.src | 1 + src/emqx.app.src.script | 6 ------ src/emqx_app.erl | 12 ++++++++++-- src/emqx_sys.erl | 6 ++---- 6 files changed, 14 insertions(+), 18 deletions(-) delete mode 100644 src/emqx.app.src.script diff --git a/Makefile b/Makefile index ab0bbeac0..69682f29c 100644 --- a/Makefile +++ b/Makefile @@ -53,11 +53,6 @@ coveralls: $(REBAR) .PHONY: $(REL_PROFILES) $(REL_PROFILES:%=%): $(REBAR) get-dashboard -ifneq ($(shell echo $(@) |grep edge),) - @export EMQX_DESC="$${EMQX_DESC} Edge" -else - @export EMQX_DESC="$${EMQX_DESC} Broker" -endif @$(REBAR) as $(@) release ## Not calling rebar3 clean because diff --git a/data/emqx_vars b/data/emqx_vars index ea566d3ee..8081badbe 100644 --- a/data/emqx_vars +++ b/data/emqx_vars @@ -16,7 +16,7 @@ RUNNER_USER="{{ runner_user }}" LIB_EKKA_DIR="${RUNNER_LIB_DIR}/ekka-$(grep ekka "${RUNNER_ROOT_DIR}/releases/RELEASES" | awk -F '\"' '{print $2}')" EMQX_LICENSE_CONF='' -EMQX_DESCRIPTION="{{ emqx_description }}" +export EMQX_DESCRIPTION='{{ emqx_description }}' ## computed vars REL_NAME="emqx" diff --git a/src/emqx.app.src b/src/emqx.app.src index ce90feb1f..a9ae81cac 100644 --- a/src/emqx.app.src +++ b/src/emqx.app.src @@ -1,5 +1,6 @@ {application, emqx, [{id, "emqx"}, + {description, "EMQ X"}, {vsn, "4.3.0"}, % strict semver, bump manually! {modules, []}, {registered, []}, diff --git a/src/emqx.app.src.script b/src/emqx.app.src.script deleted file mode 100644 index 8495ca9bd..000000000 --- a/src/emqx.app.src.script +++ /dev/null @@ -1,6 +0,0 @@ -[{application, Name, Opts}] = CONFIG, -Desc = case os:getenv("EMQX_DESC") of - [_ | _] = D -> D; - _ -> "EMQ X test" - end, -[{application, Name, [{description, Desc} | Opts]}]. diff --git a/src/emqx_app.erl b/src/emqx_app.erl index 3d08cf668..4f8d47390 100644 --- a/src/emqx_app.erl +++ b/src/emqx_app.erl @@ -20,6 +20,7 @@ -export([ start/2 , stop/1 + , get_description/0 , get_release/0 ]). @@ -59,8 +60,15 @@ print_banner() -> io:format("Starting ~s on node ~s~n", [?APP, node()]). print_vsn() -> - {ok, Descr} = application:get_key(description), - io:format("~s ~s is running now!~n", [Descr, get_release()]). + io:format("~s ~s is running now!~n", [get_description(), get_release()]). + +get_description() -> + {ok, Descr0} = application:get_key(?APP, description), + case os:getenv("EMQX_DESCRIPTION") of + false -> Descr0; + "" -> Descr0; + Str -> string:strip(Str, both, $\n) + end. -ifdef(TEST). %% When testing, the 'cover' compiler stripps aways compile info diff --git a/src/emqx_sys.erl b/src/emqx_sys.erl index 9b256df0b..5542566a5 100644 --- a/src/emqx_sys.erl +++ b/src/emqx_sys.erl @@ -85,13 +85,11 @@ stop() -> %% @doc Get sys version -spec(version() -> string()). -version() -> - {ok, Version} = application:get_key(?APP, vsn), Version. +version() -> emqx_app:get_release(). %% @doc Get sys description -spec(sysdescr() -> string()). -sysdescr() -> - {ok, Descr} = application:get_key(?APP, description), Descr. +sysdescr() -> emqx_app:get_description(). %% @doc Get sys uptime -spec(uptime() -> string()). From 582dea10f57161f756e00a5eb525c96f599c64d2 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 16:26:35 +0100 Subject: [PATCH 28/37] style(emqx_sys): make elvis happy --- src/emqx_sys.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/emqx_sys.erl b/src/emqx_sys.erl index 5542566a5..11f9f5635 100644 --- a/src/emqx_sys.erl +++ b/src/emqx_sys.erl @@ -153,7 +153,8 @@ handle_info({timeout, TRef, heartbeat}, State = #state{heartbeat = TRef}) -> publish_any(datetime, iolist_to_binary(datetime())), {noreply, heartbeat(State)}; -handle_info({timeout, TRef, tick}, State = #state{ticker = TRef, version = Version, sysdescr = Descr}) -> +handle_info({timeout, TRef, tick}, + State = #state{ticker = TRef, version = Version, sysdescr = Descr}) -> publish_any(version, Version), publish_any(sysdescr, Descr), publish_any(brokers, ekka_mnesia:running_nodes()), From 95847ea10b20042aabdf873732a5d4e61f4e7be9 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 16:35:31 +0100 Subject: [PATCH 29/37] chore(build): Support vars file for enterprise --- rebar.config.erl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/rebar.config.erl b/rebar.config.erl index b73e9522d..3e3173c99 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -127,6 +127,7 @@ profiles() -> %% RelType: cloud (full size) | edge (slim size) %% PkgType: bin | pkg relx(Vsn, RelType, PkgType) -> + IsEnterprise = is_enterprise(), [ {include_src,false} , {include_erts, true} , {extended_start_script,false} @@ -136,22 +137,19 @@ relx(Vsn, RelType, PkgType) -> , {release, {emqx, Vsn}, relx_apps(RelType)} , {overlay, relx_overlay(RelType)} , {overlay_vars, [ {built_on_arch, rebar_utils:get_arch()} - , {emqx_description, emqx_description(RelType)} - , overlay_vars_rel(RelType) + , {emqx_description, emqx_description(RelType, IsEnterprise)} + , overlay_vars_rel(RelType, IsEnterprise) , overlay_vars_pkg(PkgType) ]} ]. -emqx_description(cloud) -> - case is_enterprise() of - true -> "EMQ X Enterprise"; - false -> "EMQ X Broker" - end; -emqx_description(edge) -> - "EMQ X Edge". +emqx_description(cloud, true) -> "EMQ X Enterprise"; +emqx_description(cloud, false) -> "EMQ X Broker"; +emqx_description(edge, _) -> "EMQ X Edge". -overlay_vars_rel(cloud) -> "vars/vars-cloud.config"; -overlay_vars_rel(edge) -> "vars/vars-edge.config". +overlay_vars_rel(cloud, true) -> "vars/vars-enterprise.config"; +overlay_vars_rel(cloud, false) -> "vars/vars-cloud.config"; +overlay_vars_rel(edge, _) -> "vars/vars-edge.config". overlay_vars_pkg(bin) -> "vars/vars-bin.config"; overlay_vars_pkg(pkg) -> "vars/vars-pkg.config". From 984b4364d679d9480178447fc0594ab282965e8a Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 17:08:54 +0100 Subject: [PATCH 30/37] chore(build): drop vars files --- rebar.config.erl | 63 ++++++++++++++++++++++++++++++++++++------ vars/vars-bin.config | 23 --------------- vars/vars-cloud.config | 7 ----- vars/vars-edge.config | 7 ----- vars/vars-pkg.config | 22 --------------- 5 files changed, 55 insertions(+), 67 deletions(-) delete mode 100644 vars/vars-bin.config delete mode 100644 vars/vars-cloud.config delete mode 100644 vars/vars-edge.config delete mode 100644 vars/vars-pkg.config diff --git a/rebar.config.erl b/rebar.config.erl index 3e3173c99..9965273c3 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -138,21 +138,67 @@ relx(Vsn, RelType, PkgType) -> , {overlay, relx_overlay(RelType)} , {overlay_vars, [ {built_on_arch, rebar_utils:get_arch()} , {emqx_description, emqx_description(RelType, IsEnterprise)} - , overlay_vars_rel(RelType, IsEnterprise) - , overlay_vars_pkg(PkgType) - ]} + | overlay_vars(RelType, PkgType, IsEnterprise)]} ]. emqx_description(cloud, true) -> "EMQ X Enterprise"; emqx_description(cloud, false) -> "EMQ X Broker"; emqx_description(edge, _) -> "EMQ X Edge". -overlay_vars_rel(cloud, true) -> "vars/vars-enterprise.config"; -overlay_vars_rel(cloud, false) -> "vars/vars-cloud.config"; -overlay_vars_rel(edge, _) -> "vars/vars-edge.config". -overlay_vars_pkg(bin) -> "vars/vars-bin.config"; -overlay_vars_pkg(pkg) -> "vars/vars-pkg.config". +overlay_vars(_RelType, PkgType, true) -> + ee_overlay_vars(PkgType); +overlay_vars(RelType, PkgType, false) -> + overlay_vars_rel(RelType) ++ overlay_vars_pkg(PkgType). + +%% vars per release type, cloud or edge +overlay_vars_rel(RelType) -> + VmArgs = case RelType of + cloud -> "vm.args"; + edge -> "vm.args.edge" + end, + [ {enable_plugin_emqx_rule_engine, RelType =:= cloud} + , {enable_plugin_emqx_bridge_mqtt, RelType =:= edge} + , {enable_plugin_emqx_modules, false} %% modules is not a plugin in ce + , {enable_plugin_emqx_recon, true} + , {enable_plugin_emqx_retainer, true} + , {enable_plugin_emqx_telemetry, true} + , {vm_args_file, VmArgs} + ]. + +%% vars per packaging type, bin(zip/tar.gz/docker) or pkg(rpm/deb) +overlay_vars_pkg(bin) -> + [ {platform_bin_dir, "bin"} + , {platform_data_dir, "data"} + , {platform_etc_dir, "etc"} + , {platform_lib_dir, "lib"} + , {platform_log_dir, "log"} + , {platform_plugins_dir, "plugins"} + , {runner_root_dir, "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"} + , {runner_bin_dir, "$RUNNER_ROOT_DIR/bin"} + , {runner_etc_dir, "$RUNNER_ROOT_DIR/etc"} + , {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"} + , {runner_log_dir, "$RUNNER_ROOT_DIR/log"} + , {runner_data_dir, "$RUNNER_ROOT_DIR/data"} + , {pipe_dir, "/tmp/$RUNNER_SCRIPT/"} + , {runner_user, ""} + ]; +overlay_vars_pkg(pkg) -> + [ {platform_bin_dir, ""} + , {platform_data_dir, "/var/lib/emqx"} + , {platform_etc_dir, "/etc/emqx"} + , {platform_lib_dir, ""} + , {platform_log_dir, "/var/log/emqx"} + , {platform_plugins_dir, "/var/lib/emqx/plugins"} + , {runner_root_dir, "/usr/lib/emqx"} + , {runner_bin_dir, "/usr/bin"} + , {runner_etc_dir, "/etc/emqx"} + , {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"} + , {runner_log_dir, "/var/log/emqx"} + , {runner_data_dir, "/var/lib/emqx"} + , {pipe_dir, "/tmp/$RUNNER_SCRIPT/"} + , {runner_user, "emqx"} + ]. relx_apps(ReleaseType) -> [ kernel @@ -402,3 +448,4 @@ list_dir(Dir) -> ee_profiles(_Vsn) -> []. ee_etc_overlay() -> []. +ee_overlay_vars(_PkgType) -> []. diff --git a/vars/vars-bin.config b/vars/vars-bin.config deleted file mode 100644 index 3d56fb4f4..000000000 --- a/vars/vars-bin.config +++ /dev/null @@ -1,23 +0,0 @@ -%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- -%% ex: ft=erlang ts=4 sw=4 et - -%% Platform-specific installation paths -{platform_bin_dir, "bin"}. -{platform_data_dir, "data"}. -{platform_etc_dir, "etc"}. -{platform_lib_dir, "lib"}. -{platform_log_dir, "log"}. -{platform_plugins_dir, "plugins"}. - -%% -%% bin/emqx -%% -{runner_root_dir, "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"}. -{runner_bin_dir, "$RUNNER_ROOT_DIR/bin"}. -{runner_etc_dir, "$RUNNER_ROOT_DIR/etc"}. -{runner_lib_dir, "$RUNNER_ROOT_DIR/lib"}. -{runner_log_dir, "$RUNNER_ROOT_DIR/log"}. -{runner_data_dir, "$RUNNER_ROOT_DIR/data"}. -{pipe_dir, "/tmp/$RUNNER_SCRIPT/"}. -{runner_user, ""}. - diff --git a/vars/vars-cloud.config b/vars/vars-cloud.config deleted file mode 100644 index a898927d7..000000000 --- a/vars/vars-cloud.config +++ /dev/null @@ -1,7 +0,0 @@ -{enable_plugin_emqx_rule_engine, true}. -{enable_plugin_emqx_bridge_mqtt, false}. -{enable_plugin_emqx_modules, false}. -{enable_plugin_emqx_recon, true}. -{enable_plugin_emqx_retainer, true}. -{enable_plugin_emqx_telemetry, true}. -{vm_args_file, "vm.args"}. diff --git a/vars/vars-edge.config b/vars/vars-edge.config deleted file mode 100644 index 2df294838..000000000 --- a/vars/vars-edge.config +++ /dev/null @@ -1,7 +0,0 @@ -{enable_plugin_emqx_rule_engine, false}. -{enable_plugin_emqx_bridge_mqtt, true}. -{enable_plugin_emqx_modules, false}. -{enable_plugin_emqx_recon, true}. -{enable_plugin_emqx_retainer, true}. -{enable_plugin_emqx_telemetry, true}. -{vm_args_file, "vm.args.edge"}. diff --git a/vars/vars-pkg.config b/vars/vars-pkg.config deleted file mode 100644 index a48227a75..000000000 --- a/vars/vars-pkg.config +++ /dev/null @@ -1,22 +0,0 @@ -%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- -%% ex: ft=erlang ts=4 sw=4 et - -%% Platform-specific installation paths -{platform_bin_dir, ""}. -{platform_data_dir, "/var/lib/emqx"}. -{platform_etc_dir, "/etc/emqx"}. -{platform_lib_dir, ""}. -{platform_log_dir, "/var/log/emqx"}. -{platform_plugins_dir, "/var/lib/emqx/plugins"}. - -%% -%% bin/emqx -%% -{runner_root_dir, "/usr/lib/emqx"}. -{runner_bin_dir, "/usr/bin"}. -{runner_etc_dir, "/etc/emqx"}. -{runner_lib_dir, "$RUNNER_ROOT_DIR/lib"}. -{runner_log_dir, "/var/log/emqx"}. -{runner_data_dir, "/var/lib/emqx"}. -{pipe_dir, "/tmp/$RUNNER_SCRIPT/"}. -{runner_user, "emqx"}. From 3d06bc30fb16b72bfb09c2782c3ff887badd5c0f Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 17:14:09 +0100 Subject: [PATCH 31/37] chore(build): pipe_dir is no longer parmaterised --- rebar.config.erl | 2 -- 1 file changed, 2 deletions(-) diff --git a/rebar.config.erl b/rebar.config.erl index 9965273c3..43c4d271d 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -180,7 +180,6 @@ overlay_vars_pkg(bin) -> , {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"} , {runner_log_dir, "$RUNNER_ROOT_DIR/log"} , {runner_data_dir, "$RUNNER_ROOT_DIR/data"} - , {pipe_dir, "/tmp/$RUNNER_SCRIPT/"} , {runner_user, ""} ]; overlay_vars_pkg(pkg) -> @@ -196,7 +195,6 @@ overlay_vars_pkg(pkg) -> , {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"} , {runner_log_dir, "/var/log/emqx"} , {runner_data_dir, "/var/lib/emqx"} - , {pipe_dir, "/tmp/$RUNNER_SCRIPT/"} , {runner_user, "emqx"} ]. From b8d2e3357dc338c344845c6d9db3b25d268054c4 Mon Sep 17 00:00:00 2001 From: zhouzb Date: Wed, 10 Mar 2021 15:17:05 +0800 Subject: [PATCH 32/37] chore(configuration): fix the configuration example in the comment --- etc/emqx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/emqx.conf b/etc/emqx.conf index 672ce8556..86cf50122 100644 --- a/etc/emqx.conf +++ b/etc/emqx.conf @@ -1576,7 +1576,7 @@ listener.ws.external.access.1 = allow all ## Set to false for WeChat MiniApp. ## ## Value: true | false -## listener.ws.external.fail_if_no_subprotocol = on +## listener.ws.external.fail_if_no_subprotocol = true ## Supported subprotocols ## From b400571dbbdeb281250912797b07e54900458c3f Mon Sep 17 00:00:00 2001 From: Shawn <506895667@qq.com> Date: Wed, 10 Mar 2021 11:37:57 +0800 Subject: [PATCH 33/37] fix(emqx): validate mqtt malformed varible byte integer --- src/emqx_frame.erl | 3 +++ test/emqx_frame_SUITE.erl | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/emqx_frame.erl b/src/emqx_frame.erl index d09b8416e..8dd3fa602 100644 --- a/src/emqx_frame.erl +++ b/src/emqx_frame.erl @@ -141,6 +141,9 @@ parse_remaining_len(<<0:8, Rest/binary>>, Header, 1, 0, Options) -> %% Match PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK... parse_remaining_len(<<0:1, 2:7, Rest/binary>>, Header, 1, 0, Options) -> parse_frame(Rest, Header, 2, Options); +parse_remaining_len(<<1:1, _Len:7, _Rest/binary>>, _Header, Multiplier, _Value, _Options) + when Multiplier > 2097152 -> + error(malformed_variable_byte_integer); parse_remaining_len(<<1:1, Len:7, Rest/binary>>, Header, Multiplier, Value, Options) -> parse_remaining_len(Rest, Header, Multiplier * ?HIGHBIT, Value + Len * Multiplier, Options); parse_remaining_len(<<0:1, Len:7, Rest/binary>>, Header, Multiplier, Value, diff --git a/test/emqx_frame_SUITE.erl b/test/emqx_frame_SUITE.erl index fa24dc910..c1fb1b580 100644 --- a/test/emqx_frame_SUITE.erl +++ b/test/emqx_frame_SUITE.erl @@ -42,7 +42,8 @@ all() -> groups() -> [{parse, [parallel], [t_parse_cont, - t_parse_frame_too_large + t_parse_frame_too_large, + t_parse_frame_malformed_variable_byte_integer ]}, {connect, [parallel], [t_serialize_parse_v3_connect, @@ -129,6 +130,12 @@ t_parse_frame_too_large(_) -> ?catch_error(frame_too_large, parse_serialize(Packet, #{max_size => 512})), ?assertEqual(Packet, parse_serialize(Packet, #{max_size => 2048, version => ?MQTT_PROTO_V4})). +t_parse_frame_malformed_variable_byte_integer(_) -> + MalformedPayload = << <<16#80>> || _ <- lists:seq(1, 4) >>, + ParseState = emqx_frame:initial_parse_state(#{}), + ?catch_error(malformed_variable_byte_integer, + emqx_frame:parse(MalformedPayload, ParseState)). + t_serialize_parse_v3_connect(_) -> Bin = <<16,37,0,6,77,81,73,115,100,112,3,2,0,60,0,23,109,111,115, 113,112,117, 98,47,49,48,52,53,49,45,105,77,97,99,46,108, From 1ddb300a5674e4aa777166d05478110a4764476e Mon Sep 17 00:00:00 2001 From: wwhai <751957846@qq.com> Date: Thu, 11 Mar 2021 00:29:37 +0800 Subject: [PATCH 34/37] feat(mgmt): add http listener restart support (#4301) --- .../src/emqx_mgmt_api_listeners.erl | 2 ++ apps/emqx_management/src/emqx_mgmt_cli.erl | 26 +++++++++++++++++++ apps/emqx_management/src/emqx_mgmt_http.erl | 2 ++ lib-ce/emqx_dashboard/src/emqx_dashboard.erl | 2 ++ 4 files changed, 32 insertions(+) diff --git a/apps/emqx_management/src/emqx_mgmt_api_listeners.erl b/apps/emqx_management/src/emqx_mgmt_api_listeners.erl index b2e75d7ff..382c1051b 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_listeners.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_listeners.erl @@ -61,6 +61,8 @@ restart(#{node := Node, identifier := Identifier}, _Params) -> end; %% Restart listeners in the cluster. +restart(#{identifier := <<"http", _/binary>>}, _Params) -> + {403, <<"http_listener_restart_unsupported">>}; restart(#{identifier := Identifier}, _Params) -> Results = [{Node, emqx_mgmt:restart_listener(Node, Identifier)} || {Node, _Info} <- emqx_mgmt:list_nodes()], case lists:filter(fun({_, Result}) -> Result =/= ok end, Results) of diff --git a/apps/emqx_management/src/emqx_mgmt_cli.erl b/apps/emqx_management/src/emqx_mgmt_cli.erl index fc18bc1bf..20b4f1b01 100644 --- a/apps/emqx_management/src/emqx_mgmt_cli.erl +++ b/apps/emqx_management/src/emqx_mgmt_cli.erl @@ -509,6 +509,18 @@ listeners(["stop", _Proto, ListenOn]) -> end, stop_listener(emqx_listeners:find_by_listen_on(ListenOn1), ListenOn1); +listeners(["restart", "http:management"]) -> + restart_http_listener(http, emqx_management); + +listeners(["restart", "https:management"]) -> + restart_http_listener(https, emqx_management); + +listeners(["restart", "http:dashboard"]) -> + restart_http_listener(http, emqx_dashboard); + +listeners(["restart", "https:dashboard"]) -> + restart_http_listener(https, emqx_dashboard); + listeners(["restart", Identifier]) -> case emqx_listeners:restart_listener(Identifier) of ok -> @@ -661,3 +673,17 @@ listener_identifier(Protocol, ListenOn) -> ID -> ID end. + +restart_http_listener(Scheme, AppName) -> + Listeners = application:get_env(AppName, listeners, []), + case lists:keyfind(Scheme, 1, Listeners) of + false -> + emqx_ctl:print("Listener ~s not exists!~n", [AppName]); + {Scheme, Port, Options} -> + ModName = http_mod_name(AppName), + ModName:stop_listener({Scheme, Port, Options}), + ModName:start_listener({Scheme, Port, Options}) + end. + +http_mod_name(emqx_management) -> emqx_mgmt_http; +http_mod_name(Name) -> Name. diff --git a/apps/emqx_management/src/emqx_mgmt_http.erl b/apps/emqx_management/src/emqx_mgmt_http.erl index 2bf6ef38a..aee057d39 100644 --- a/apps/emqx_management/src/emqx_mgmt_http.erl +++ b/apps/emqx_management/src/emqx_mgmt_http.erl @@ -21,6 +21,8 @@ -export([ start_listeners/0 , handle_request/2 , stop_listeners/0 + , start_listener/1 + , stop_listener/1 ]). -export([init/2]). diff --git a/lib-ce/emqx_dashboard/src/emqx_dashboard.erl b/lib-ce/emqx_dashboard/src/emqx_dashboard.erl index a2ba1f125..b7b6ca42e 100644 --- a/lib-ce/emqx_dashboard/src/emqx_dashboard.erl +++ b/lib-ce/emqx_dashboard/src/emqx_dashboard.erl @@ -23,6 +23,8 @@ -export([ start_listeners/0 , stop_listeners/0 + , start_listener/1 + , stop_listener/1 ]). %% for minirest From 0eda65d06fa6a5c42ce49b8575be42f05797869d Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 21:01:10 +0100 Subject: [PATCH 35/37] chore(config): emqx.conf segmentation This is to facilitate enterprise edition release script to slice up the files into smaller config files --- etc/emqx.conf | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/etc/emqx.conf b/etc/emqx.conf index 86cf50122..684a1d0f8 100644 --- a/etc/emqx.conf +++ b/etc/emqx.conf @@ -1,10 +1,8 @@ -##==================================================================== -## EMQ X Configuration R4.0 -##==================================================================== +## EMQ X Configuration 4.3 -##-------------------------------------------------------------------- -## Cluster -##-------------------------------------------------------------------- +## NOTE: Do not change format of CONFIG_SECTION_{BGN,END} comments! + +## CONFIG_SECTION_BGN=cluster ================================================== ## Cluster name. ## @@ -173,6 +171,8 @@ cluster.autoclean = 5m ## Value: String ## cluster.k8s.namespace = default +## CONFIG_SECTION_END=cluster ================================================== + ##-------------------------------------------------------------------- ## Node ##-------------------------------------------------------------------- @@ -301,9 +301,8 @@ node.crash_dump = {{ platform_log_dir }}/crash.dump node.dist_listen_min = 6369 node.dist_listen_max = 6369 -##-------------------------------------------------------------------- -## RPC -##-------------------------------------------------------------------- +## CONFIG_SECTION_BGN=rpc ====================================================== + ## RPC Mode. ## ## Value: sync | async @@ -400,9 +399,9 @@ rpc.socket_recbuf = 1MB ## Value: Seconds rpc.socket_buffer = 1MB -##-------------------------------------------------------------------- -## Log -##-------------------------------------------------------------------- +## CONFIG_SECTION_END=rpc ====================================================== + +## CONFIG_SECTION_BGN=logger =================================================== ## Where to emit the logs. ## Enable the console (standard output) logs. @@ -571,6 +570,8 @@ log.rotation.count = 5 ## #log.burst_limit = 20000, 1s +## CONFIG_SECTION_END=logger =================================================== + ##-------------------------------------------------------------------- ## Authentication/Access Control ##-------------------------------------------------------------------- @@ -685,9 +686,7 @@ mqtt.strict_mode = false ## Value: String ## mqtt.response_information = example -##-------------------------------------------------------------------- -## Zones -##-------------------------------------------------------------------- +## CONFIG_SECTION_BGN=zones =================================================== ##-------------------------------------------------------------------- ## External Zone @@ -1021,9 +1020,9 @@ zone.internal.strict_mode = false ## Value: true | false zone.internal.bypass_auth_plugins = true -##-------------------------------------------------------------------- -## Listeners -##-------------------------------------------------------------------- +## CONFIG_SECTION_END=zones ==================================================== + +## CONFIG_SECTION_BGN=listeners ================================================ ##-------------------------------------------------------------------- ## MQTT/TCP - External TCP Listener for MQTT Protocol @@ -2048,9 +2047,10 @@ listener.wss.external.allow_origin_absence = true ## Value: http://url eg. https://localhost:8084, https://127.0.0.1:8084 listener.wss.external.check_origins = https://localhost:8084, https://127.0.0.1:8084 -##-------------------------------------------------------------------- -## Modules -##-------------------------------------------------------------------- +## CONFIG_SECTION_END=listeners ================================================ + +## CONFIG_SECTION_BGN=modules ================================================== + ## The file to store loaded module names. ## ## Value: File @@ -2177,9 +2177,9 @@ broker.shared_dispatch_ack_enabled = false ## Value: Flag broker.route_batch_clean = off -##-------------------------------------------------------------------- -## System Monitor -##-------------------------------------------------------------------- +## CONFIG_SECTION_END=modules ================================================== + +## CONFIG_SECTION_BGN=sys_mon ================================================== ## Enable Long GC monitoring. Disable if the value is 0. ## Notice: don't enable the monitor in production for: @@ -2326,4 +2326,6 @@ alarm.size_limit = 1000 ## Default: 24h alarm.validity_period = 24h +## CONFIG_SECTION_END=sys_mon ================================================== + {{ additional_configs }} From b4ee2f8d2491dd64783a7d0b227417081f1ee8ef Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 9 Mar 2021 21:14:58 +0100 Subject: [PATCH 36/37] chore(build): refactor rebar.config.erl overlay function --- rebar.config.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rebar.config.erl b/rebar.config.erl index 43c4d271d..ddfaa7133 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -297,7 +297,10 @@ relx_overlay(ReleaseType) -> , {copy, "_build/default/lib/cuttlefish/cuttlefish", "bin/cuttlefish"} , {copy, "_build/default/lib/cuttlefish/cuttlefish", "bin/cuttlefish-{{release_version}}"} , {copy, "priv/emqx.schema", "releases/{{release_version}}/"} - ] ++ ee_etc_overlay() ++ etc_overlay(ReleaseType). + ] ++ case is_enterprise() of + true -> ee_etc_overlay(ReleaseType); + false -> etc_overlay(ReleaseType) + end. etc_overlay(ReleaseType) -> PluginApps = relx_plugin_apps(ReleaseType), @@ -445,5 +448,5 @@ list_dir(Dir) -> %% ==== Enterprise supports below ================================================================== ee_profiles(_Vsn) -> []. -ee_etc_overlay() -> []. +ee_etc_overlay(_) -> []. ee_overlay_vars(_PkgType) -> []. From 4373367c15a6d2a154b6686a66018472fc7c55a3 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 10 Mar 2021 14:00:19 +0100 Subject: [PATCH 37/37] chore(script): Add a script to split emqx.conf --- .gitignore | 1 + scripts/split-config.escript | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100755 scripts/split-config.escript diff --git a/.gitignore b/.gitignore index 59ebdd433..c702d3955 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ emqx_dialyzer_*_plt */emqx_dashboard/priv/www dist.zip scripts/git-token +etc/*.seg diff --git a/scripts/split-config.escript b/scripts/split-config.escript new file mode 100755 index 000000000..07caf6503 --- /dev/null +++ b/scripts/split-config.escript @@ -0,0 +1,62 @@ +#!/usr/bin/env escript + +%% This script reads up emqx.conf and split the sections +%% and dump sections to separate files. +%% Sections are grouped between CONFIG_SECTION_BGN and +%% CONFIG_SECTION_END pairs +%% +%% NOTE: this feature is so far not used in opensource +%% edition due to backward-compatibility reasons. + +-mode(compile). + +-define(BASE, <<"emqx">>). + +main(_) -> + {ok, Bin} = file:read_file("etc/emqx.conf"), + Lines = binary:split(Bin, <<"\n">>, [global]), + Sections0 = parse_sections(Lines), + Sections = lists:filter(fun({<<"modules">>, _}) -> false; + (_) -> true + end, Sections0), + ok = dump_sections(Sections). + +parse_sections(Lines) -> + {ok, P} = re:compile("#+\s*CONFIG_SECTION_(BGN|END)\s*=\s*([^\s-]+)\s*="), + Parser = + fun(Line) -> + case re:run(Line, P, [{capture, all_but_first, binary}]) of + {match, [<<"BGN">>, Name]} -> {section_bgn, Name}; + {match, [<<"END">>, Name]} -> {section_end, Name}; + nomatch -> continue + end + end, + parse_sections(Lines, Parser, ?BASE, #{?BASE => []}). + +parse_sections([], _Parse, _Section, Sections) -> + lists:map(fun({N, Lines}) -> {N, lists:reverse(Lines)} end, + maps:to_list(Sections)); +parse_sections([Line | Lines], Parse, Section, Sections) -> + case Parse(Line) of + {section_bgn, Name} -> + ?BASE = Section, %% assert + true = (Name =/= ?BASE), %% assert + false = maps:is_key(Name, Sections), %% assert + Include = iolist_to_binary(["include {{ platform_etc_dir }}/", Name, ".conf"]), + Base = maps:get(?BASE, Sections), + NewSections = Sections#{?BASE := [Include | Base], Name => []}, + parse_sections(Lines, Parse, Name, NewSections); + {section_end, Name} -> + true = (Name =:= Section), %% assert + parse_sections(Lines, Parse, ?BASE, Sections); + continue -> + Acc = maps:get(Section, Sections), + parse_sections(Lines, Parse, Section, Sections#{Section => [Line | Acc]}) + end. + +dump_sections([]) -> ok; +dump_sections([{Name, Lines0} | Rest]) -> + Filename = filename:join(["etc", iolist_to_binary([Name, ".conf.seg"])]), + Lines = [[L, "\n"] || L <- Lines0], + ok = file:write_file(Filename, Lines), + dump_sections(Rest).