diff --git a/.github/workflows/apps_version_check.yaml b/.github/workflows/apps_version_check.yaml index 86fe60204..257eba4f7 100644 --- a/.github/workflows/apps_version_check.yaml +++ b/.github/workflows/apps_version_check.yaml @@ -28,7 +28,9 @@ jobs: if: endsWith(github.repository, 'enterprise') run: ./scripts/update-appup.sh emqx-ee --check - name: Check apps version - run: ./scripts/apps-version-check.sh + run: ./scripts/check-apps-vsn.sh + - name: Check chart versions + run: ./scripts/check-chart-vsn.sh - uses: actions/upload-artifact@v3.1.0 if: failure() with: diff --git a/.github/workflows/build_slim_packages.yaml b/.github/workflows/build_slim_packages.yaml index 356ba491b..daa525989 100644 --- a/.github/workflows/build_slim_packages.yaml +++ b/.github/workflows/build_slim_packages.yaml @@ -49,12 +49,7 @@ jobs: - name: make xref run: make xref - name: make dialyzer - run: | - # TODO: once dialyzer warnings are fixed in 4.4+, we may - # enforce this. - if [[ "$(./pkg-vsn.sh)" =~ 4.3.* ]]; then - make dialyzer - fi + run: make dialyzer - name: build zip packages run: make ${EMQX_NAME}-zip - name: build deb/rpm packages @@ -64,7 +59,7 @@ jobs: with: name: rebar3.crashdump path: ./rebar3.crashdump - - name: pakcages test + - name: packages test run: | export CODE_PATH=$GITHUB_WORKSPACE .ci/build_packages/tests.sh @@ -102,18 +97,27 @@ jobs: id: cache with: path: ~/.kerl/${{ matrix.erl_otp }} - key: otp-install-${{ matrix.erl_otp }}-${{ matrix.macos }} + key: otp-install-${{ matrix.erl_otp }}-${{ matrix.macos }}-static-ssl-disable-hipe-disable-jit - name: build erlang if: steps.cache.outputs.cache-hit != 'true' timeout-minutes: 60 env: KERL_BUILD_BACKEND: git OTP_GITHUB_URL: https://github.com/emqx/otp + KERL_CONFIGURE_OPTIONS: --disable-dynamic-ssl-lib --with-ssl=/usr/local/opt/openssl@1.1 --disable-hipe --disable-jit run: | kerl update releases kerl build ${{ matrix.erl_otp }} kerl install ${{ matrix.erl_otp }} $HOME/.kerl/${{ matrix.erl_otp }} - name: build + env: + APPLE_SIGN_BINARIES: 1 + APPLE_ID: developers@emqx.io + APPLE_TEAM_ID: 26N6HYJLZA + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_DEVELOPER_IDENTITY: ${{ secrets.APPLE_DEVELOPER_IDENTITY }} + APPLE_DEVELOPER_ID_BUNDLE: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE }} + APPLE_DEVELOPER_ID_BUNDLE_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_BUNDLE_PASSWORD }} run: | . $HOME/.kerl/${{ matrix.erl_otp }}/activate make ensure-rebar3 @@ -129,7 +133,10 @@ jobs: pkg_name=$(basename _packages/${EMQX_NAME}/emqx-*.zip) unzip -q _packages/${EMQX_NAME}/$pkg_name gsed -i '/emqx_telemetry/d' ./emqx/data/loaded_plugins - ./emqx/bin/emqx start || cat emqx/log/erlang.log.1 + # test with a spaces in path + mv ./emqx "./emqx home/" + cd "./emqx home/" + ./bin/emqx start || cat log/erlang.log.1 ready='no' for i in {1..10}; do if curl -fs 127.0.0.1:18083 > /dev/null; then @@ -140,12 +147,13 @@ jobs: done if [ "$ready" != "yes" ]; then echo "Timed out waiting for emqx to be ready" - cat emqx/log/erlang.log.1 + cat log/erlang.log.1 exit 1 fi - ./emqx/bin/emqx_ctl status - ./emqx/bin/emqx stop - rm -rf emqx + ./bin/emqx_ctl status + ./bin/emqx stop + cd .. + rm -rf "emqx home" - uses: actions/upload-artifact@v2 with: name: macos diff --git a/.github/workflows/run_test_cases.yaml b/.github/workflows/run_test_cases.yaml index 96cce885a..def12cb16 100644 --- a/.github/workflows/run_test_cases.yaml +++ b/.github/workflows/run_test_cases.yaml @@ -5,6 +5,8 @@ on: tags: - v* - e* + branches: + - 'main-v4.[0-9]?' pull_request: jobs: @@ -26,6 +28,7 @@ jobs: run_common_test: runs-on: ${{ matrix.runs-on }} strategy: + fail-fast: false matrix: runs-on: - aws-amd64 @@ -110,6 +113,7 @@ jobs: - name: run cover run: | printenv > .env + docker exec -i erlang bash -c "git config --global --add safe.directory /emqx" docker exec -i erlang bash -c "make cover" docker exec --env-file .env -i erlang bash -c "make coveralls" - name: cat rebar.crashdump diff --git a/CHANGES-4.3.md b/CHANGES-4.3.md index 0e320dbb4..713f89f37 100644 --- a/CHANGES-4.3.md +++ b/CHANGES-4.3.md @@ -10,6 +10,44 @@ File format: - One list item per change topic Change log ends with a list of GitHub PRs +## v4.3.22 + +### Minor changes + +## v4.3.21 + +### Enhancements + +- TLS listener memory usage optimization [#9005](https://github.com/emqx/emqx/pull/9005). + New config `listener.ssl.$NAME.hibernate_after` to hibernate TLS connection process after idling. + Hibernation can reduce RAM usage significantly, but may cost more CPU. + This configuration is by default disabled. + Our preliminary test shows a 50% of RAM usage decline when configured to '5s'. + +- TLS listener default buffer size to 4KB [#9007](https://github.com/emqx/emqx/pull/9007) + Eliminate uncertainty that the buffer size is set by OS default. + +- Disable authorization for `api/v4/emqx_prometheus` endpoint. [8955](https://github.com/emqx/emqx/pull/8955) + +- Added a test to prevent a last will testament message to be + published when a client is denied connection. [#8894](https://github.com/emqx/emqx/pull/8894) + +### Bug fixes + +- Fix delayed publish inaccurate caused by os time change. [#8908](https://github.com/emqx/emqx/pull/8908) + +- Hide redis password in error logs [#9071](https://github.com/emqx/emqx/pull/9071) + In this change, it also included more changes in redis client: + - Improve redis connection error logging [eredis:19](https://github.com/emqx/eredis/pull/19). + Also added support for eredis to accept an anonymous function as password instead of + passing around plaintext args which may get dumpped to crash logs (hard to predict where). + This change also added `format_status` callback for `gen_server` states which hold plaintext + password so the process termination log and `sys:get_status` will print '******' instead of + the password to console. + - Avoid pool name clashing [eredis_cluster#22](https://github.com/emqx/eredis_cluster/pull/22) + Same `format_status` callback is added here too for `gen_server`s which hold password in + their state. + ## v4.3.20 ### Bug fixes diff --git a/Makefile b/Makefile index f7f46c48f..aaa0b683a 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ $(REL_PROFILES:%=%): $(REBAR) get-dashboard clean: $(PROFILES:%=clean-%) $(PROFILES:%=clean-%): @if [ -d _build/$(@:clean-%=%) ]; then \ - rm rebar.lock \ + rm -f rebar.lock; \ rm -rf _build/$(@:clean-%=%)/rel; \ $(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; \ $(FIND) _build/$(@:clean-%=%) -type l -delete; \ @@ -114,8 +114,9 @@ $(PROFILES:%=deps-%): $(REBAR) get-dashboard @rm -f rebar.lock .PHONY: xref -xref: $(REBAR) +xref: $(REBAR) $(REL_PROFILES:%=%-rel) @$(REBAR) as check xref + @scripts/xref-check.escript .PHONY: dialyzer dialyzer: $(REBAR) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src index 44882dc1b..05d4d3754 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.app.src @@ -1,6 +1,6 @@ {application, emqx_auth_jwt, [{description, "EMQ X Authentication with JWT"}, - {vsn, "4.3.6"}, % strict semver, bump manually! + {vsn, "4.3.7"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_auth_jwt_sup]}, {applications, [kernel,stdlib,jose]}, diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src index 5868efc9e..6f07c4449 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src @@ -1,7 +1,8 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"4.3.5", + [{"4.3.6",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, + {"4.3.5", [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {"4.3.4", @@ -12,7 +13,8 @@ {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]}, {<<".*">>,[]}], - [{"4.3.5", + [{"4.3.6",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, + {"4.3.5", [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {"4.3.4", diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl index 3a5c619aa..049f07533 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl @@ -200,7 +200,7 @@ do_verify(JwsCompacted, [Jwk|More]) -> end. check_claims(Claims) -> - Now = os:system_time(seconds), + Now = erlang:system_time(seconds), Checker = [{<<"exp">>, with_num_value( fun(ExpireTime) -> Now < ExpireTime end)}, {<<"iat">>, with_num_value( diff --git a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl index eb6d3c195..a0be3768f 100644 --- a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl +++ b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl @@ -75,7 +75,7 @@ t_check_auth(_Config) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, - {exp, os:system_time(seconds) + 2}], <<"HS256">>, <<"emqxsecret">>), + {exp, erlang:system_time(seconds) + 2}], <<"HS256">>, <<"emqxsecret">>), ct:pal("Jwt: ~p~n", [Jwt]), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), @@ -101,7 +101,7 @@ t_check_nbf(_Config) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, - {nbf, os:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), + {nbf, erlang:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), ct:pal("Jwt: ~p~n", [Jwt]), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), @@ -114,7 +114,7 @@ t_check_iat(_Config) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, - {iat, os:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), + {iat, erlang:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), ct:pal("Jwt: ~p~n", [Jwt]), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), @@ -147,7 +147,7 @@ t_check_auth_str_exp(init, _Config) -> application:unset_env(emqx_auth_jwt, verify_claims). t_check_auth_str_exp(_Config) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, - Exp = integer_to_binary(os:system_time(seconds) + 3), + Exp = integer_to_binary(erlang:system_time(seconds) + 3), Jwt0 = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, @@ -167,7 +167,7 @@ t_check_auth_str_exp(_Config) -> ct:pal("Auth result: ~p~n", [Result1]), ?assertMatch({error, _}, Result1), - Exp2 = float_to_binary(os:system_time(seconds) + 3.5), + Exp2 = float_to_binary(erlang:system_time(seconds) + 3.5), Jwt2 = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, @@ -182,7 +182,7 @@ t_check_auth_float_exp(init, _Config) -> application:unset_env(emqx_auth_jwt, verify_claims). t_check_auth_float_exp(_Config) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, - Exp = os:system_time(seconds) + 3.5, + Exp = erlang:system_time(seconds) + 3.5, Jwt0 = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, @@ -209,7 +209,7 @@ t_check_claims(_Config) -> Jwt = sign([{client_id, <<"client1">>}, {username, <<"plain">>}, {sub, value}, - {exp, os:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), + {exp, erlang:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), ct:pal("Auth result: ~p~n", [Result0]), ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0), @@ -225,7 +225,7 @@ t_check_claims_clientid(_Config) -> Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client23">>}, {username, <<"plain">>}, - {exp, os:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), + {exp, erlang:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), ct:pal("Auth result: ~p~n", [Result0]), ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0), @@ -241,7 +241,7 @@ t_check_claims_username(_Config) -> Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, Jwt = sign([{client_id, <<"client23">>}, {username, <<"plain">>}, - {exp, os:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), + {exp, erlang:system_time(seconds) + 3}], <<"HS256">>, <<"emqxsecret">>), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), ct:pal("Auth result: ~p~n", [Result0]), ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0), @@ -257,7 +257,7 @@ t_check_claims_kid_in_header(_Config) -> Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client23">>}, {username, <<"plain">>}, - {exp, os:system_time(seconds) + 3}], + {exp, erlang:system_time(seconds) + 3}], #{<<"alg">> => <<"HS256">>, <<"kid">> => <<"a_kid_str">>}, <<"emqxsecret">>), Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), @@ -298,7 +298,7 @@ t_check_jwt_acl(_Config) -> {sub, value}, {acl, [{sub, [<<"a/b">>]}, {pub, [<<"c/d">>]}]}, - {exp, os:system_time(seconds) + 10}], + {exp, erlang:system_time(seconds) + 10}], <<"HS256">>, <<"emqxsecret">>), @@ -338,7 +338,7 @@ t_check_jwt_acl_no_recs(_Config) -> {username, <<"plain">>}, {sub, value}, {acl, []}, - {exp, os:system_time(seconds) + 10}], + {exp, erlang:system_time(seconds) + 10}], <<"HS256">>, <<"emqxsecret">>), @@ -361,7 +361,7 @@ t_check_jwt_acl_no_acl_claim(_Config) -> Jwt = sign([{client_id, <<"client1">>}, {username, <<"plain">>}, {sub, value}, - {exp, os:system_time(seconds) + 10}], + {exp, erlang:system_time(seconds) + 10}], <<"HS256">>, <<"emqxsecret">>), @@ -423,7 +423,7 @@ t_check_jwt_acl_expire(_Config) -> {username, <<"plain">>}, {sub, value}, {acl, [{sub, [<<"a/b">>]}]}, - {exp, os:system_time(seconds) + 1}], + {exp, erlang:system_time(seconds) + 1}], <<"HS256">>, <<"emqxsecret">>), diff --git a/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl index 941ebedb9..213f9c278 100644 --- a/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl @@ -20,6 +20,7 @@ -compile(export_all). -include("emqx_auth_mnesia.hrl"). +-include_lib("emqx/include/emqx.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl"). @@ -77,15 +78,37 @@ init_per_testcase_migration(_, Config) -> emqx_acl_mnesia_migrator:migrate_records(), Config. +init_per_testcase_other(t_last_will_testament_message_check_acl, Config) -> + OriginalACLNoMatch = application:get_env(emqx, acl_nomatch), + application:set_env(emqx, acl_nomatch, deny), + emqx_mod_acl_internal:unload([]), + %% deny all for this client + ClientID = <<"lwt_client">>, + ok = emqx_acl_mnesia_db:add_acl({clientid, ClientID}, <<"#">>, pubsub, deny), + [ {original_acl_nomatch, OriginalACLNoMatch} + , {clientid, ClientID} + | Config]; +init_per_testcase_other(_TestCase, Config) -> + Config. + init_per_testcase(Case, Config) -> PerTestInitializers = [ fun init_per_testcase_clean/2, fun init_per_testcase_migration/2, - fun init_per_testcase_emqx_hook/2 + fun init_per_testcase_emqx_hook/2, + fun init_per_testcase_other/2 ], lists:foldl(fun(Init, Conf) -> Init(Case, Conf) end, Config, PerTestInitializers). -end_per_testcase(_, Config) -> +end_per_testcase(t_last_will_testament_message_check_acl, Config) -> + emqx:unhook('client.check_acl', fun emqx_acl_mnesia:check_acl/5), + case ?config(original_acl_nomatch, Config) of + {ok, Original} -> application:set_env(emqx, acl_nomatch, Original); + _ -> ok + end, + emqx_mod_acl_internal:load([]), + ok; +end_per_testcase(_TestCase, Config) -> emqx:unhook('client.check_acl', fun emqx_acl_mnesia:check_acl/5), Config. @@ -464,6 +487,35 @@ t_rest_api(_Config) -> {ok, Res3} = request_http_rest_list(["$all"]), ?assertMatch([], get_http_data(Res3)). +%% asserts that we check ACL for the LWT topic before publishing the +%% LWT. +t_last_will_testament_message_check_acl(Config) -> + ClientID = ?config(clientid, Config), + {ok, C} = emqtt:start_link([ + {clientid, ClientID}, + {will_topic, <<"$SYS/lwt">>}, + {will_payload, <<"should not be published">>} + ]), + {ok, _} = emqtt:connect(C), + ok = emqx:subscribe(<<"$SYS/lwt">>), + unlink(C), + ok = snabbkaffe:start_trace(), + {true, {ok, _}} = + ?wait_async_action( + exit(C, kill), + #{?snk_kind := last_will_testament_publish_denied}, + 1_000 + ), + ok = snabbkaffe:stop(), + + receive + {deliver, <<"$SYS/lwt">>, #message{payload = <<"should not be published">>}} -> + error(lwt_should_not_be_published_to_forbidden_topic) + after 1_000 -> + ok + end, + + ok. create_conflicting_records() -> Records = [ diff --git a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl index 0253110aa..f7071bc17 100644 --- a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -21,6 +21,9 @@ -include("emqx_auth_mnesia.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). +-include_lib("snabbkaffe/include/snabbkaffe.hrl"). + +-include_lib("emqx/include/emqx_mqtt.hrl"). -import(emqx_ct_http, [ request_api/3 , request_api/5 @@ -74,6 +77,20 @@ set_default(ClientId, UserName, Pwd, HashType) -> application:set_env(emqx_auth_mnesia, username_list, [{UserName, Pwd}]), application:set_env(emqx_auth_mnesia, password_hash, HashType), ok. + +init_per_testcase(t_will_message_connection_denied, Config) -> + emqx_zone:set_env(external, allow_anonymous, false), + Config; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(t_will_message_connection_denied, _Config) -> + emqx_zone:unset_env(external, allow_anonymous), + application:stop(emqx_auth_mnesia), + ok; +end_per_testcase(_TestCase, _Config) -> + ok. + %%------------------------------------------------------------------------------ %% Testcases %%------------------------------------------------------------------------------ @@ -390,6 +407,48 @@ t_password_hash(_) -> application:stop(emqx_auth_mnesia), ok = application:start(emqx_auth_mnesia). +t_will_message_connection_denied(Config) when is_list(Config) -> + ClientId = Username = <<"subscriber">>, + Password = <<"p">>, + application:stop(emqx_auth_mnesia), + ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia]), + ok = emqx_auth_mnesia_cli:add_user({clientid, ClientId}, Password), + + {ok, Subscriber} = emqtt:start_link([ + {clientid, ClientId}, + {password, Password} + ]), + {ok, _} = emqtt:connect(Subscriber), + {ok, _, [?RC_SUCCESS]} = emqtt:subscribe(Subscriber, <<"lwt">>), + + process_flag(trap_exit, true), + + {ok, Publisher} = emqtt:start_link([ + {clientid, <<"publisher">>}, + {will_topic, <<"lwt">>}, + {will_payload, <<"should not be published">>} + ]), + snabbkaffe:start_trace(), + ?wait_async_action( + {error, _} = emqtt:connect(Publisher), + #{?snk_kind := channel_terminated} + ), + snabbkaffe:stop(), + + timer:sleep(1000), + + receive + {publish, #{ + topic := <<"lwt">>, + payload := <<"should not be published">> + }} -> + ct:fail("should not publish will message") + after 0 -> + ok + end, + + ok. + %%------------------------------------------------------------------------------ %% Helpers %%------------------------------------------------------------------------------ diff --git a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl index 9d1fadd34..66f5253d0 100644 --- a/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl +++ b/apps/emqx_auth_mongo/test/emqx_auth_mongo_SUITE.erl @@ -52,10 +52,14 @@ all() -> init_per_suite(Cfg) -> emqx_ct_helpers:start_apps([emqx_auth_mongo], fun set_special_confs/1), init_mongo_data(), + %% avoid inter-suite flakiness + ok = emqx_mod_acl_internal:unload([]), Cfg. end_per_suite(_Cfg) -> deinit_mongo_data(), + %% avoid inter-suite flakiness + ok = emqx_mod_acl_internal:load([]), emqx_ct_helpers:stop_apps([emqx_auth_mongo]). set_special_confs(emqx) -> diff --git a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl index f7170e92b..4905b32bf 100644 --- a/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl +++ b/apps/emqx_auth_pgsql/src/emqx_auth_pgsql_cli.erl @@ -147,4 +147,3 @@ safe_get(K, ClientInfo) -> bin(A) when is_atom(A) -> atom_to_binary(A, utf8); bin(B) when is_binary(B) -> B; bin(X) -> X. - diff --git a/apps/emqx_exhook/src/emqx_exhook.app.src b/apps/emqx_exhook/src/emqx_exhook.app.src index d0067742a..1d05b43f4 100644 --- a/apps/emqx_exhook/src/emqx_exhook.app.src +++ b/apps/emqx_exhook/src/emqx_exhook.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_exhook, [{description, "EMQ X Extension for Hook"}, - {vsn, "4.3.7"}, + {vsn, "4.3.8"}, {modules, []}, {registered, []}, {mod, {emqx_exhook_app, []}}, diff --git a/apps/emqx_exhook/src/emqx_exhook.appup.src b/apps/emqx_exhook/src/emqx_exhook.appup.src index 8aec1b9d4..7919e3e67 100644 --- a/apps/emqx_exhook/src/emqx_exhook.appup.src +++ b/apps/emqx_exhook/src/emqx_exhook.appup.src @@ -1,7 +1,8 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{<<"4\\.3\\.[5-6]">>, + [{"4.3.7",[{load_module,emqx_exhook_server,brutal_purge,soft_purge,[]}]}, + {<<"4\\.3\\.[5-6]">>, [{load_module,emqx_exhook_handler,brutal_purge,soft_purge,[]}, {load_module,emqx_exhook,brutal_purge,soft_purge,[]}, {load_module,emqx_exhook_server,brutal_purge,soft_purge,[]}, @@ -15,7 +16,8 @@ {update,emqx_exhook_mngr,{advanced,["4.3.4"]}}]}, {<<"4\\.3\\.[0-3]">>,[{restart_application,emqx_exhook}]}, {<<".*">>,[]}], - [{<<"4\\.3\\.[5-6]">>, + [{"4.3.7",[{load_module,emqx_exhook_server,brutal_purge,soft_purge,[]}]}, + {<<"4\\.3\\.[5-6]">>, [{load_module,emqx_exhook_handler,brutal_purge,soft_purge,[]}, {load_module,emqx_exhook,brutal_purge,soft_purge,[]}, {load_module,emqx_exhook_mngr,brutal_purge,soft_purge,[]}, diff --git a/apps/emqx_exhook/src/emqx_exhook_server.erl b/apps/emqx_exhook/src/emqx_exhook_server.erl index 9a8468700..b77aaa445 100644 --- a/apps/emqx_exhook/src/emqx_exhook_server.erl +++ b/apps/emqx_exhook/src/emqx_exhook_server.erl @@ -46,7 +46,7 @@ channel :: pid(), %% Registered hook names and options hookspec :: #{hookpoint() => map()}, - %% Metrcis name prefix + %% Metrics name prefix prefix :: list() }). @@ -75,8 +75,6 @@ -export_type([server/0]). --dialyzer({nowarn_function, [inc_metrics/2]}). - %%-------------------------------------------------------------------- %% Load/Unload APIs %%-------------------------------------------------------------------- @@ -249,10 +247,6 @@ call(Hookpoint, Req, #server{name = ChannName, options = ReqOpts, end. %% @private -inc_metrics(IncFun, Name) when is_function(IncFun) -> - %% BACKW: e4.2.0-e4.2.2 - {env, [Prefix|_]} = erlang:fun_info(IncFun, env), - inc_metrics(Prefix, Name); inc_metrics(Prefix, Name) when is_list(Prefix) -> emqx_metrics:inc(list_to_atom(Prefix ++ atom_to_list(Name))). diff --git a/apps/emqx_exproto/src/emqx_exproto.app.src b/apps/emqx_exproto/src/emqx_exproto.app.src index 98610a40c..40be93b33 100644 --- a/apps/emqx_exproto/src/emqx_exproto.app.src +++ b/apps/emqx_exproto/src/emqx_exproto.app.src @@ -1,6 +1,6 @@ {application, emqx_exproto, [{description, "EMQ X Extension for Protocol"}, - {vsn, "4.3.11"}, %% 4.3.3 is used by ee + {vsn, "4.3.12"}, %% 4.3.3 is used by ee {modules, []}, {registered, []}, {mod, {emqx_exproto_app, []}}, diff --git a/apps/emqx_exproto/src/emqx_exproto.appup.src b/apps/emqx_exproto/src/emqx_exproto.appup.src index fcf2fe6db..f31e4a969 100644 --- a/apps/emqx_exproto/src/emqx_exproto.appup.src +++ b/apps/emqx_exproto/src/emqx_exproto.appup.src @@ -1,9 +1,13 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"4.3.10",[{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, + [{"4.3.11",[{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}]}, + {"4.3.10", + [{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, + {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, {"4.3.9", - [{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}, + [{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, + {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_exproto_gcli,brutal_purge,soft_purge,[]}]}, {<<"4\\.3\\.[2-8]">>, [{load_module,emqx_exproto_gcli,brutal_purge,soft_purge,[]}, @@ -15,9 +19,13 @@ {load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, {<<".*">>,[]}], - [{"4.3.10",[{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, + [{"4.3.11",[{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}]}, + {"4.3.10", + [{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, + {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}]}, {"4.3.9", - [{load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}, + [{load_module,emqx_exproto_conn,brutal_purge,soft_purge,[]}, + {load_module,emqx_exproto_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_exproto_gcli,brutal_purge,soft_purge,[]}]}, {<<"4\\.3\\.[2-8]">>, [{load_module,emqx_exproto_gcli,brutal_purge,soft_purge,[]}, diff --git a/apps/emqx_exproto/src/emqx_exproto_conn.erl b/apps/emqx_exproto/src/emqx_exproto_conn.erl index 152c0edf1..7c6eb6cb3 100644 --- a/apps/emqx_exproto/src/emqx_exproto_conn.erl +++ b/apps/emqx_exproto/src/emqx_exproto_conn.erl @@ -91,14 +91,6 @@ -define(ENABLED(X), (X =/= undefined)). --dialyzer({nowarn_function, - [ system_terminate/4 - , handle_call/3 - , handle_msg/2 - , shutdown/3 - , stop/3 - ]}). - %% udp start_link(Socket = {udp, _SockPid, _Sock}, Peername, Options) -> Args = [self(), Socket, Peername, Options], @@ -501,6 +493,7 @@ terminate(Reason, State = #state{channel = Channel}) -> system_continue(Parent, _Debug, State) -> recvloop(Parent, State). +-spec system_terminate(atom(), term(), term(), state()) -> no_return(). system_terminate(Reason, _Parent, _Debug, State) -> terminate(Reason, State). diff --git a/apps/emqx_management/src/emqx_management.app.src b/apps/emqx_management/src/emqx_management.app.src index fbec68057..1003a1140 100644 --- a/apps/emqx_management/src/emqx_management.app.src +++ b/apps/emqx_management/src/emqx_management.app.src @@ -1,6 +1,6 @@ {application, emqx_management, [{description, "EMQ X Management API and CLI"}, - {vsn, "4.3.17"}, % strict semver, bump manually! + {vsn, "4.3.18"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_management_sup]}, {applications, [kernel,stdlib,minirest]}, diff --git a/apps/emqx_management/src/emqx_mgmt_data_backup.erl b/apps/emqx_management/src/emqx_mgmt_data_backup.erl index b0d346489..e66a8834e 100644 --- a/apps/emqx_management/src/emqx_mgmt_data_backup.erl +++ b/apps/emqx_management/src/emqx_mgmt_data_backup.erl @@ -185,7 +185,6 @@ confs_to_binary(Confs) -> -endif. --dialyzer([{nowarn_function, [import_rules/1, import_rule/1]}]). import_rule(#{<<"id">> := RuleId, <<"rawsql">> := RawSQL, <<"actions">> := Actions, @@ -537,7 +536,6 @@ do_import_acl_mnesia(Acls) -> end, Acls). -ifdef(EMQX_ENTERPRISE). --dialyzer({nowarn_function, [import_modules/1]}). import_modules(Modules) -> case ets:info(emqx_modules) of undefined -> diff --git a/apps/emqx_psk_file/include/emqx_psk_file.hrl b/apps/emqx_psk_file/include/emqx_psk_file.hrl new file mode 100644 index 000000000..fe8ed1f94 --- /dev/null +++ b/apps/emqx_psk_file/include/emqx_psk_file.hrl @@ -0,0 +1,25 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2022 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_PSK_FILE). +-define(EMQX_PSK_FILE, true). + +-define(PSK_FILE_TAB, emqx_psk_file). + +-record(psk_entry, {psk_id :: binary(), + psk_str :: binary()}). + +-endif. diff --git a/apps/emqx_psk_file/src/emqx_psk_file.app.src b/apps/emqx_psk_file/src/emqx_psk_file.app.src index b8a6f08a0..ef18c8b69 100644 --- a/apps/emqx_psk_file/src/emqx_psk_file.app.src +++ b/apps/emqx_psk_file/src/emqx_psk_file.app.src @@ -1,6 +1,6 @@ {application, emqx_psk_file, [{description,"EMQX PSK Plugin from File"}, - {vsn, "4.3.0"}, % strict semver, bump manually! + {vsn, "4.3.1"}, % strict semver, bump manually! {modules,[]}, {registered,[emqx_psk_file_sup]}, {applications,[kernel,stdlib]}, diff --git a/apps/emqx_psk_file/src/emqx_psk_file.appup.src b/apps/emqx_psk_file/src/emqx_psk_file.appup.src new file mode 100644 index 000000000..c782000b5 --- /dev/null +++ b/apps/emqx_psk_file/src/emqx_psk_file.appup.src @@ -0,0 +1,10 @@ +%% -*- mode: erlang -*- +{VSN, + [{"4.3.0", + [{load_module,emqx_psk_file,brutal_purge,soft_purge,[]}, + {load_module,emqx_psk_file_sup,brutal_purge,soft_purge,[]}]} + ], + [{"4.3.0", + [{load_module,emqx_psk_file,brutal_purge,soft_purge,[]}, + {load_module,emqx_psk_file_sup,brutal_purge,soft_purge,[]}]} + ]}. diff --git a/apps/emqx_psk_file/src/emqx_psk_file.erl b/apps/emqx_psk_file/src/emqx_psk_file.erl index b4daee370..e252393c4 100644 --- a/apps/emqx_psk_file/src/emqx_psk_file.erl +++ b/apps/emqx_psk_file/src/emqx_psk_file.erl @@ -16,6 +16,7 @@ -module(emqx_psk_file). +-include("emqx_psk_file.hrl"). -include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/logger.hrl"). @@ -26,15 +27,10 @@ %% Hooks functions -export([on_psk_lookup/2]). --define(TAB, ?MODULE). -define(LF, 10). --record(psk_entry, {psk_id :: binary(), - psk_str :: binary()}). - %% Called when the plugin application start load(Env) -> - _ = ets:new(?TAB, [set, named_table, {keypos, #psk_entry.psk_id}]), {ok, PskFile} = file:open(get_value(path, Env), [read, raw, binary, read_ahead]), preload_psks(PskFile, bin(get_value(delimiter, Env))), _ = file:close(PskFile), @@ -45,7 +41,7 @@ unload() -> emqx:unhook('tls_handshake.psk_lookup', fun ?MODULE:on_psk_lookup/2). on_psk_lookup(ClientPSKID, UserState) -> - case ets:lookup(?TAB, ClientPSKID) of + case ets:lookup(?PSK_FILE_TAB, ClientPSKID) of [#psk_entry{psk_str = PskStr}] -> {stop, PskStr}; [] -> @@ -57,7 +53,9 @@ preload_psks(FileHandler, Delimiter) -> {ok, Line} -> case binary:split(Line, Delimiter) of [Key, Rem] -> - ets:insert(?TAB, #psk_entry{psk_id = Key, psk_str = trim_lf(Rem)}), + ets:insert( + ?PSK_FILE_TAB, + #psk_entry{psk_id = Key, psk_str = trim_lf(Rem)}), preload_psks(FileHandler, Delimiter); [Line] -> ?LOG(warning, "[~p] - Invalid line: ~p, delimiter: ~p", [?MODULE, Line, Delimiter]) diff --git a/apps/emqx_psk_file/src/emqx_psk_file_sup.erl b/apps/emqx_psk_file/src/emqx_psk_file_sup.erl index 2e739519c..e643c000a 100644 --- a/apps/emqx_psk_file/src/emqx_psk_file_sup.erl +++ b/apps/emqx_psk_file/src/emqx_psk_file_sup.erl @@ -16,6 +16,8 @@ -module(emqx_psk_file_sup). +-include("emqx_psk_file.hrl"). + -behaviour(supervisor). %% API @@ -25,8 +27,11 @@ -export([init/1]). start_link() -> + _ = ets:new( + ?PSK_FILE_TAB, + [set, named_table, public, {keypos, #psk_entry.psk_id}] + ), supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> {ok, { {one_for_one, 0, 1}, []} }. - diff --git a/apps/emqx_retainer/src/emqx_retainer.app.src b/apps/emqx_retainer/src/emqx_retainer.app.src index 80ec02c73..dcc48fbae 100644 --- a/apps/emqx_retainer/src/emqx_retainer.app.src +++ b/apps/emqx_retainer/src/emqx_retainer.app.src @@ -1,6 +1,6 @@ {application, emqx_retainer, [{description, "EMQ X Retainer"}, - {vsn, "4.3.4"}, % strict semver, bump manually! + {vsn, "4.3.5"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_retainer_sup]}, {applications, [kernel,stdlib]}, diff --git a/apps/emqx_retainer/src/emqx_retainer_sup.erl b/apps/emqx_retainer/src/emqx_retainer_sup.erl index 2028affb6..ca16a98bb 100644 --- a/apps/emqx_retainer/src/emqx_retainer_sup.erl +++ b/apps/emqx_retainer/src/emqx_retainer_sup.erl @@ -34,6 +34,23 @@ init([Env]) -> type => worker, modules => [emqx_retainer]} || not is_managed_by_modules()]}}. +-ifdef(EMQX_ENTERPRISE). + +is_managed_by_modules() -> + try + case supervisor:get_childspec(emqx_modules_sup, emqx_retainer) of + {ok, _} -> true; + _ -> false + end + catch + exit : {noproc, _} -> + false + end. + +-else. + is_managed_by_modules() -> %% always false for opensource edition false. + +-endif. diff --git a/apps/emqx_retainer/test/emqx_retainer_ct_helper.erl b/apps/emqx_retainer/test/emqx_retainer_ct_helper.erl index fd12a4e01..67f58ec26 100644 --- a/apps/emqx_retainer/test/emqx_retainer_ct_helper.erl +++ b/apps/emqx_retainer/test/emqx_retainer_ct_helper.erl @@ -20,7 +20,9 @@ -export([ensure_start/0, ensure_stop/0]). -ifdef(EMQX_ENTERPRISE). ensure_start() -> + %% for enterprise edition, retainer is started by modules application:stop(emqx_modules), + ensure_stop(), init_conf(), emqx_ct_helpers:start_apps([emqx_retainer]), ok. @@ -29,6 +31,7 @@ ensure_start() -> ensure_start() -> init_conf(), + ensure_stop(), emqx_ct_helpers:start_apps([emqx_retainer]), ok. diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src index cbdb2e7f7..dffcc7024 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src @@ -1,6 +1,6 @@ {application, emqx_rule_engine, [{description, "EMQ X Rule Engine"}, - {vsn, "4.3.15"}, % strict semver, bump manually! + {vsn, "4.3.16"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_rule_engine_sup, emqx_rule_registry]}, {applications, [kernel,stdlib,rulesql,getopt]}, diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src index c24bead6e..6aa35d2d6 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src @@ -1,24 +1,36 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"4.3.14", - [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, + [{"4.3.15", + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}]}, + {"4.3.14", + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}]}, {"4.3.13", - [{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, {"4.3.12", - [{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, {"4.3.11", - [{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, @@ -26,7 +38,8 @@ {load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {"4.3.10", - [{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, @@ -34,7 +47,8 @@ {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {"4.3.9", - [{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, @@ -184,24 +198,36 @@ {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {<<".*">>,[]}], - [{"4.3.14", - [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, + [{"4.3.15", + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}]}, + {"4.3.14", + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}]}, {"4.3.13", - [{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, {"4.3.12", - [{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, {"4.3.11", - [{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, @@ -209,7 +235,8 @@ {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {"4.3.10", - [{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, @@ -217,7 +244,8 @@ {load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {"4.3.9", - [{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, + [{load_module,emqx_rule_sqltester,brutal_purge,soft_purge,[]}, + {load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_actions,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_utils,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}, diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.erl b/apps/emqx_rule_engine/src/emqx_rule_engine.erl index f48b8a02b..ac0ccaf4f 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.erl @@ -207,7 +207,7 @@ create_rule(Params = #{rawsql := Sql, actions := ActArgs}) -> Reason -> {error, Reason} end. --spec(update_rule(#{id := binary(), _=>_}) -> {ok, rule()} | {error, {not_found, rule_id()}}). +-spec(update_rule(#{id := binary(), _=>_}) -> {ok, rule()} | {error, {not_found, rule_id()} | term()}). update_rule(Params = #{id := RuleId}) -> case emqx_rule_registry:get_rule(RuleId) of {ok, Rule0} -> @@ -336,7 +336,6 @@ start_resource(ResId) -> {error, {resource_not_found, ResId}} end. --dialyzer([{nowarn_function, test_resource/1}]). -spec(test_resource(#{type := _, config := _, _ => _}) -> ok | {error, Reason :: term()}). test_resource(#{type := Type} = Params) -> case emqx_rule_registry:find_resource_type(Type) of diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl index 223c672e6..50fdcfe22 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl @@ -207,12 +207,6 @@ <<"Bad Arguments: ", R0/binary>> end). --dialyzer({nowarn_function, [create_rule/2, - test_rule_sql/1, - do_create_rule/1, - update_rule/2 - ]}). - %%------------------------------------------------------------------------------ %% Rules API %%------------------------------------------------------------------------------ diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_cli.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_cli.erl index 45a847ada..101fa54f6 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_cli.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_cli.erl @@ -96,7 +96,6 @@ unload() -> %%----------------------------------------------------------------------------- %% 'rules' command %%----------------------------------------------------------------------------- --dialyzer([{nowarn_function, [rules/1]}]). rules(["list"]) -> print_all(emqx_rule_registry:get_rules_ordered_by_ts()); diff --git a/apps/emqx_rule_engine/src/emqx_rule_runtime.erl b/apps/emqx_rule_engine/src/emqx_rule_runtime.erl index 71775f6ee..c6c3da533 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_runtime.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_runtime.erl @@ -180,7 +180,6 @@ select_and_collect([Field|More], Input, {Output, LastKV}) -> {nested_put(Key, Val, Output), LastKV}). %% Filter each item got from FOREACH --dialyzer({nowarn_function, filter_collection/4}). filter_collection(Input, InCase, DoEach, {CollKey, CollVal}) -> lists:filtermap( fun(Item) -> diff --git a/apps/emqx_rule_engine/src/emqx_rule_sqltester.erl b/apps/emqx_rule_engine/src/emqx_rule_sqltester.erl index 79ac0f328..b1df2f01d 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_sqltester.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_sqltester.erl @@ -20,16 +20,6 @@ -export([ test/1 ]). -%% Dialyzer gives up on the generated code. -%% probably due to stack depth, or inlines. --dialyzer({nowarn_function, [test/1, - test_rule/4, - flatten/1, - sql_test_action/0, - fill_default_values/2, - envs_examp/1 - ]}). - -spec(test(#{}) -> {ok, map() | list()} | {error, term()}). test(#{<<"rawsql">> := Sql, <<"ctx">> := Context}) -> {ok, Select} = emqx_rule_sqlparser:parse_select(Sql), diff --git a/apps/emqx_stomp/src/emqx_stomp.app.src b/apps/emqx_stomp/src/emqx_stomp.app.src index 5883cbca5..e35e570d3 100644 --- a/apps/emqx_stomp/src/emqx_stomp.app.src +++ b/apps/emqx_stomp/src/emqx_stomp.app.src @@ -1,6 +1,6 @@ {application, emqx_stomp, [{description, "EMQ X Stomp Protocol Plugin"}, - {vsn, "4.3.5"}, % strict semver, bump manually! + {vsn, "4.3.6"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_stomp_sup]}, {applications, [kernel,stdlib]}, diff --git a/apps/emqx_stomp/src/emqx_stomp.appup.src b/apps/emqx_stomp/src/emqx_stomp.appup.src index 3493ade03..69e571934 100644 --- a/apps/emqx_stomp/src/emqx_stomp.appup.src +++ b/apps/emqx_stomp/src/emqx_stomp.appup.src @@ -1,6 +1,10 @@ %% -*- mode: erlang -*- +%% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"4.3.4", + [{"4.3.5", + [{load_module,emqx_stomp_protocol,brutal_purge,soft_purge,[]}, + {load_module,emqx_stomp_connection,brutal_purge,soft_purge,[]}]}, + {"4.3.4", [{load_module,emqx_stomp_protocol,brutal_purge,soft_purge,[]}, {load_module,emqx_stomp_connection,brutal_purge,soft_purge,[]}]}, {"4.3.3", @@ -19,7 +23,10 @@ [{restart_application,emqx_stomp}, {apply,{emqx_stomp,force_clear_after_app_stoped,[]}}]}, {<<".*">>,[]}], - [{"4.3.4", + [{"4.3.5", + [{load_module,emqx_stomp_protocol,brutal_purge,soft_purge,[]}, + {load_module,emqx_stomp_connection,brutal_purge,soft_purge,[]}]}, + {"4.3.4", [{load_module,emqx_stomp_protocol,brutal_purge,soft_purge,[]}, {load_module,emqx_stomp_connection,brutal_purge,soft_purge,[]}]}, {"4.3.3", diff --git a/apps/emqx_stomp/src/emqx_stomp_connection.erl b/apps/emqx_stomp/src/emqx_stomp_connection.erl index 767ea3814..e58b242e5 100644 --- a/apps/emqx_stomp/src/emqx_stomp_connection.erl +++ b/apps/emqx_stomp/src/emqx_stomp_connection.erl @@ -91,13 +91,6 @@ -define(ENABLED(X), (X =/= undefined)). --dialyzer({nowarn_function, [ ensure_stats_timer/2 - ]}). - --dialyzer({no_return, [ init/1 - , init_state/3 - ]}). - start_link(Transport, Sock, ProtoEnv) -> {ok, proc_lib:spawn_link(?MODULE, init, [[Transport, Sock, ProtoEnv]])}. @@ -143,6 +136,7 @@ call(Pid, Req) -> call(Pid, Req, Timeout) -> gen_server:call(Pid, Req, Timeout). +-spec init([term()]) -> no_return(). init([Transport, RawSocket, ProtoEnv]) -> case Transport:wait(RawSocket) of {ok, Socket} -> @@ -152,6 +146,7 @@ init([Transport, RawSocket, ProtoEnv]) -> exit_on_sock_error(Reason) end. +-spec init_state(module(), port(), [proplists:property()]) -> no_return(). init_state(Transport, Socket, ProtoEnv) -> {ok, Peername} = Transport:ensure_ok_or_exit(peername, [Socket]), {ok, Sockname} = Transport:ensure_ok_or_exit(sockname, [Socket]), diff --git a/apps/emqx_stomp/src/emqx_stomp_protocol.erl b/apps/emqx_stomp/src/emqx_stomp_protocol.erl index 0a8a7be75..e2cc2888b 100644 --- a/apps/emqx_stomp/src/emqx_stomp_protocol.erl +++ b/apps/emqx_stomp/src/emqx_stomp_protocol.erl @@ -50,9 +50,29 @@ , handle_recv_nack_frame/2 ]). +-type stomp_conninfo() :: #{socktype := emqx_types:socktype(), + sockname := emqx_types:peername(), + peername := emqx_types:peername(), + peercert := nossl | undefined | esockd_peercert:peercert(), + conn_mod := module(), + proto_name => binary(), + proto_ver => emqx_types:ver(), + clean_start => boolean(), + clientid => emqx_types:clientid(), + username => emqx_types:username(), + conn_props => emqx_types:properties(), + connected => boolean(), + connected_at => undefined | non_neg_integer(), + disconnected_at => non_neg_integer(), + keepalive => undefined | 0..16#FFFF, + receive_maximum => non_neg_integer(), + expiry_interval => non_neg_integer(), + atom() => term() + }. + -record(pstate, { %% Stomp ConnInfo - conninfo :: emqx_types:conninfo(), + conninfo :: stomp_conninfo(), %% Stomp ClientInfo clientinfo :: emqx_types:clientinfo(), %% Stomp Heartbeats @@ -104,10 +124,6 @@ awaiting_rel_max ]). --dialyzer({nowarn_function, [ check_acl/3 - , init/2 - ]}). - -type(pstate() :: #pstate{}). %% @doc Init protocol @@ -687,12 +703,8 @@ backoff({Cx, Cy}) -> parse_topic_filters(TopicFilters) -> lists:map(fun emqx_topic:parse/1, TopicFilters). -check_acl(PubSub, Topic, State = #pstate{clientinfo = ClientInfo}) -> - case is_acl_enabled(State) andalso - emqx_access_control:check_acl(ClientInfo, PubSub, Topic) of - false -> allow; - Res -> Res - end. +check_acl(PubSub, Topic, #pstate{clientinfo = ClientInfo}) -> + emqx_access_control:check_acl(ClientInfo, PubSub, Topic). do_subscribe(TopicFilter, SubOpts, State = #pstate{clientinfo = ClientInfo, subscriptions = Subs}) -> @@ -728,10 +740,6 @@ find_sub_by_id(Id, Subs) -> [Sub | _] -> Sub end. -is_acl_enabled(_) -> - %% TODO: configs from somewhere - true. - %% automaticly fill the next sub-id and ack if sub-id is absent enrich_sub_opts(SubOpts0, Subs) -> SubOpts = maps:merge(?DEFAULT_SUBOPTS, SubOpts0), diff --git a/bin/emqx b/bin/emqx index 306efe527..82eb90e16 100755 --- a/bin/emqx +++ b/bin/emqx @@ -481,6 +481,16 @@ case "$1" in ;; esac +if [ "$IS_BOOT_COMMAND" = 'no' ]; then + # for non-boot commands, inspect vm.