Merge pull request #4149 from emqx/dev/v4.3.0
Auto-pull-request-on-2021-02-04
This commit is contained in:
commit
55253f914c
|
@ -12,6 +12,14 @@ services:
|
||||||
- ldap_server
|
- ldap_server
|
||||||
networks:
|
networks:
|
||||||
- emqx_bridge
|
- emqx_bridge
|
||||||
|
environment:
|
||||||
|
GITHUB_ACTIONS: ${GITHUB_ACTIONS}
|
||||||
|
GITHUB_TOKEN: ${GITHUB_TOKEN}
|
||||||
|
GITHUB_RUN_ID: ${GITHUB_RUN_ID}
|
||||||
|
GITHUB_SHA: ${GITHUB_SHA}
|
||||||
|
GITHUB_RUN_NUMBER: ${GITHUB_RUN_NUMBER}
|
||||||
|
GITHUB_EVENT_NAME: ${GITHUB_EVENT_NAME}
|
||||||
|
GITHUB_REF: ${GITHUB_REF}
|
||||||
volumes:
|
volumes:
|
||||||
- ../../.:/emqx
|
- ../../.:/emqx
|
||||||
working_dir: /emqx
|
working_dir: /emqx
|
||||||
|
|
|
@ -7,7 +7,7 @@ export RELUP_PACKAGE_PATH="/emqx/relup_packages/${EMQX_NAME}"
|
||||||
# export EMQX_NODE_COOKIE=$(date +%s%N)
|
# export EMQX_NODE_COOKIE=$(date +%s%N)
|
||||||
|
|
||||||
emqx_prepare(){
|
emqx_prepare(){
|
||||||
mkdir -p ${PACKAGE_PATH}
|
mkdir -p "${PACKAGE_PATH}"
|
||||||
|
|
||||||
if [ ! -d "/paho-mqtt-testing" ]; then
|
if [ ! -d "/paho-mqtt-testing" ]; then
|
||||||
git clone -b develop-4.0 https://github.com/emqx/paho.mqtt.testing.git /paho-mqtt-testing
|
git clone -b develop-4.0 https://github.com/emqx/paho.mqtt.testing.git /paho-mqtt-testing
|
||||||
|
@ -16,28 +16,28 @@ emqx_prepare(){
|
||||||
}
|
}
|
||||||
|
|
||||||
emqx_test(){
|
emqx_test(){
|
||||||
cd ${PACKAGE_PATH}
|
cd "${PACKAGE_PATH}"
|
||||||
|
|
||||||
for var in $(ls $PACKAGE_PATH/${EMQX_NAME}-*);do
|
for var in "$PACKAGE_PATH"/"${EMQX_NAME}"-*;do
|
||||||
case ${var##*.} in
|
case ${var##*.} in
|
||||||
"zip")
|
"zip")
|
||||||
packagename=`basename ${PACKAGE_PATH}/${EMQX_NAME}-*.zip`
|
packagename=$(basename "${PACKAGE_PATH}/${EMQX_NAME}"-*.zip)
|
||||||
unzip -q ${PACKAGE_PATH}/$packagename
|
unzip -q "${PACKAGE_PATH}/${packagename}"
|
||||||
sed -i "/zone.external.server_keepalive/c zone.external.server_keepalive = 60" ${PACKAGE_PATH}/emqx/etc/emqx.conf
|
sed -i "/zone.external.server_keepalive/c zone.external.server_keepalive = 60" "${PACKAGE_PATH}"/emqx/etc/emqx.conf
|
||||||
sed -i "/mqtt.max_topic_alias/c mqtt.max_topic_alias = 10" ${PACKAGE_PATH}/emqx/etc/emqx.conf
|
sed -i "/mqtt.max_topic_alias/c mqtt.max_topic_alias = 10" "${PACKAGE_PATH}"/emqx/etc/emqx.conf
|
||||||
sed -i '/emqx_telemetry/d' ${PACKAGE_PATH}/emqx/data/loaded_plugins
|
sed -i '/emqx_telemetry/d' "${PACKAGE_PATH}"/emqx/data/loaded_plugins
|
||||||
|
|
||||||
if [ ! -z $(echo ${EMQX_DEPS_DEFAULT_VSN#v} | grep -oE "[0-9]+\.[0-9]+(\.[0-9]+)?-(alpha|beta|rc)\.[0-9]") ]; then
|
if echo "${EMQX_DEPS_DEFAULT_VSN#v}" | grep -qE "[0-9]+\.[0-9]+(\.[0-9]+)?-(alpha|beta|rc)\.[0-9]"; then
|
||||||
if [ ! -d ${PACKAGE_PATH}/emqx/lib/emqx-${EMQX_DEPS_DEFAULT_VSN#v} ] || [ ! -d ${PACKAGE_PATH}/emqx/releases/${EMQX_DEPS_DEFAULT_VSN#v} ] ;then
|
if [ ! -d "${PACKAGE_PATH}/emqx/lib/emqx-${EMQX_DEPS_DEFAULT_VSN#v}" ] || [ ! -d "${PACKAGE_PATH}/emqx/releases/${EMQX_DEPS_DEFAULT_VSN#v}" ] ;then
|
||||||
echo "emqx zip version error"
|
echo "emqx zip version error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "running ${packagename} start"
|
echo "running ${packagename} start"
|
||||||
${PACKAGE_PATH}/emqx/bin/emqx start || tail ${PACKAGE_PATH}/emqx/log/erlang.log.1
|
"${PACKAGE_PATH}"/emqx/bin/emqx start || tail "${PACKAGE_PATH}"/emqx/log/erlang.log.1
|
||||||
IDLE_TIME=0
|
IDLE_TIME=0
|
||||||
while [ -z "$(${PACKAGE_PATH}/emqx/bin/emqx_ctl status |grep 'is running'|awk '{print $1}')" ]
|
while [ -z "$("${PACKAGE_PATH}"/emqx/bin/emqx_ctl status |grep 'is running'|awk '{print $1}')" ]
|
||||||
do
|
do
|
||||||
if [ $IDLE_TIME -gt 10 ]
|
if [ $IDLE_TIME -gt 10 ]
|
||||||
then
|
then
|
||||||
|
@ -48,54 +48,54 @@ emqx_test(){
|
||||||
IDLE_TIME=$((IDLE_TIME+1))
|
IDLE_TIME=$((IDLE_TIME+1))
|
||||||
done
|
done
|
||||||
pytest -v /paho-mqtt-testing/interoperability/test_client/V5/test_connect.py::test_basic
|
pytest -v /paho-mqtt-testing/interoperability/test_client/V5/test_connect.py::test_basic
|
||||||
${PACKAGE_PATH}/emqx/bin/emqx stop
|
"${PACKAGE_PATH}"/emqx/bin/emqx stop
|
||||||
echo "running ${packagename} stop"
|
echo "running ${packagename} stop"
|
||||||
rm -rf ${PACKAGE_PATH}/emqx
|
rm -rf "${PACKAGE_PATH}"/emqx
|
||||||
;;
|
;;
|
||||||
"deb")
|
"deb")
|
||||||
packagename=`basename ${PACKAGE_PATH}/${EMQX_NAME}-*.deb`
|
packagename=$(basename "${PACKAGE_PATH}/${EMQX_NAME}"-*.deb)
|
||||||
dpkg -i ${PACKAGE_PATH}/$packagename
|
dpkg -i "${PACKAGE_PATH}/${packagename}"
|
||||||
if [ $(dpkg -l |grep emqx |awk '{print $1}') != "ii" ]
|
if [ "$(dpkg -l |grep emqx |awk '{print $1}')" != "ii" ]
|
||||||
then
|
then
|
||||||
echo "package install error"
|
echo "package install error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "running ${packagename} start"
|
echo "running ${packagename} start"
|
||||||
running_test
|
running_test
|
||||||
echo "running ${packagename} stop"
|
echo "running ${packagename} stop"
|
||||||
|
|
||||||
dpkg -r ${EMQX_NAME}
|
dpkg -r "${EMQX_NAME}"
|
||||||
if [ $(dpkg -l |grep emqx |awk '{print $1}') != "rc" ]
|
if [ "$(dpkg -l |grep emqx |awk '{print $1}')" != "rc" ]
|
||||||
then
|
then
|
||||||
echo "package remove error"
|
echo "package remove error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dpkg -P ${EMQX_NAME}
|
dpkg -P "${EMQX_NAME}"
|
||||||
if [ ! -z "$(dpkg -l |grep emqx)" ]
|
if dpkg -l |grep -q emqx
|
||||||
then
|
then
|
||||||
echo "package uninstall error"
|
echo "package uninstall error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
"rpm")
|
"rpm")
|
||||||
packagename=`basename ${PACKAGE_PATH}/${EMQX_NAME}-*.rpm`
|
packagename=$(basename "${PACKAGE_PATH}/${EMQX_NAME}"-*.rpm)
|
||||||
rpm -ivh ${PACKAGE_PATH}/$packagename
|
rpm -ivh "${PACKAGE_PATH}/${packagename}"
|
||||||
if [ -z $(rpm -q emqx | grep -o emqx) ];then
|
if ! rpm -q emqx | grep -q emqx; then
|
||||||
echo "package install error"
|
echo "package install error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "running ${packagename} start"
|
echo "running ${packagename} start"
|
||||||
running_test
|
running_test
|
||||||
echo "running ${packagename} stop"
|
echo "running ${packagename} stop"
|
||||||
|
|
||||||
rpm -e ${EMQX_NAME}
|
rpm -e "${EMQX_NAME}"
|
||||||
if [ "$(rpm -q emqx)" != "package emqx is not installed" ];then
|
if [ "$(rpm -q emqx)" != "package emqx is not installed" ];then
|
||||||
echo "package uninstall error"
|
echo "package uninstall error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
|
@ -103,8 +103,8 @@ emqx_test(){
|
||||||
}
|
}
|
||||||
|
|
||||||
running_test(){
|
running_test(){
|
||||||
if [ ! -z $(echo ${EMQX_DEPS_DEFAULT_VSN#v} | grep -oE "[0-9]+\.[0-9]+(\.[0-9]+)?-(alpha|beta|rc)\.[0-9]") ]; then
|
if echo "${EMQX_DEPS_DEFAULT_VSN#v}" | grep -qE "[0-9]+\.[0-9]+(\.[0-9]+)?-(alpha|beta|rc)\.[0-9]"; then
|
||||||
if [ ! -d /usr/lib/emqx/lib/emqx-${EMQX_DEPS_DEFAULT_VSN#v} ] || [ ! -d /usr/lib/emqx/releases/${EMQX_DEPS_DEFAULT_VSN#v} ];then
|
if [ ! -d /usr/lib/emqx/lib/emqx-"${EMQX_DEPS_DEFAULT_VSN#v}" ] || [ ! -d /usr/lib/emqx/releases/"${EMQX_DEPS_DEFAULT_VSN#v}" ];then
|
||||||
echo "emqx package version error"
|
echo "emqx package version error"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -127,11 +127,12 @@ running_test(){
|
||||||
IDLE_TIME=$((IDLE_TIME+1))
|
IDLE_TIME=$((IDLE_TIME+1))
|
||||||
done
|
done
|
||||||
pytest -v /paho-mqtt-testing/interoperability/test_client/V5/test_connect.py::test_basic
|
pytest -v /paho-mqtt-testing/interoperability/test_client/V5/test_connect.py::test_basic
|
||||||
emqx stop || kill $(ps -ef | grep -E '\-progname\s.+emqx\s' |awk '{print $2}')
|
# shellcheck disable=SC2009 # pgrep does not support Extended Regular Expressions
|
||||||
|
emqx stop || kill "$(ps -ef | grep -E '\-progname\s.+emqx\s' |awk '{print $2}')"
|
||||||
|
|
||||||
if [ $(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g') = ubuntu ] \
|
if [ "$(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g')" = ubuntu ] \
|
||||||
|| [ $(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g') = debian ] \
|
|| [ "$(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g')" = debian ] \
|
||||||
|| [ $(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g') = raspbian ];then
|
|| [ "$(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g')" = raspbian ];then
|
||||||
service emqx start || tail /var/log/emqx/erlang.log.1
|
service emqx start || tail /var/log/emqx/erlang.log.1
|
||||||
IDLE_TIME=0
|
IDLE_TIME=0
|
||||||
while [ -z "$(emqx_ctl status |grep 'is running'|awk '{print $1}')" ]
|
while [ -z "$(emqx_ctl status |grep 'is running'|awk '{print $1}')" ]
|
||||||
|
@ -149,18 +150,18 @@ running_test(){
|
||||||
}
|
}
|
||||||
|
|
||||||
relup_test(){
|
relup_test(){
|
||||||
if [ -d ${RELUP_PACKAGE_PATH} ];then
|
if [ -d "${RELUP_PACKAGE_PATH}" ];then
|
||||||
cd ${RELUP_PACKAGE_PATH }
|
cd "${RELUP_PACKAGE_PATH }"
|
||||||
|
|
||||||
for var in $(ls ${EMQX_NAME}-*-$(uname -m).zip);do
|
for var in "${EMQX_NAME}"-*-"$(uname -m)".zip;do
|
||||||
packagename=`basename ${var}`
|
packagename=$(basename "${var}")
|
||||||
unzip $packagename
|
unzip "$packagename"
|
||||||
./emqx/bin/emqx start
|
./emqx/bin/emqx start
|
||||||
./emqx/bin/emqx_ctl status
|
./emqx/bin/emqx_ctl status
|
||||||
./emqx/bin/emqx versions
|
./emqx/bin/emqx versions
|
||||||
cp ${PACKAGE_PATH}/${EMQX_NAME}-*-${EMQX_DEPS_DEFAULT_VSN#v}-$(uname -m).zip ./emqx/releases
|
cp "${PACKAGE_PATH}/${EMQX_NAME}"-*-"${EMQX_DEPS_DEFAULT_VSN#v}-$(uname -m)".zip ./emqx/releases
|
||||||
./emqx/bin/emqx install ${EMQX_DEPS_DEFAULT_VSN#v}
|
./emqx/bin/emqx install "${EMQX_DEPS_DEFAULT_VSN#v}"
|
||||||
[ $(./emqx/bin/emqx versions |grep permanent | grep -oE "[0-9].[0-9].[0-9]") = ${EMQX_DEPS_DEFAULT_VSN#v} ] || exit 1
|
[ "$(./emqx/bin/emqx versions |grep permanent | grep -oE "[0-9].[0-9].[0-9]")" = "${EMQX_DEPS_DEFAULT_VSN#v}" ] || exit 1
|
||||||
./emqx/bin/emqx_ctl status
|
./emqx/bin/emqx_ctl status
|
||||||
./emqx/bin/emqx stop
|
./emqx/bin/emqx stop
|
||||||
rm -rf emqx
|
rm -rf emqx
|
||||||
|
|
|
@ -31,7 +31,7 @@ rm -f \
|
||||||
/data/conf/nodes.7001.conf \
|
/data/conf/nodes.7001.conf \
|
||||||
/data/conf/nodes.7002.conf ;
|
/data/conf/nodes.7002.conf ;
|
||||||
|
|
||||||
if [ ${node} = "cluster" ] ; then
|
if [ "${node}" = "cluster" ] ; then
|
||||||
if $tls ; then
|
if $tls ; then
|
||||||
redis-server /data/conf/redis-tls.conf --port 7000 --cluster-config-file /data/conf/nodes.7000.conf \
|
redis-server /data/conf/redis-tls.conf --port 7000 --cluster-config-file /data/conf/nodes.7000.conf \
|
||||||
--tls-port 8000 --cluster-enabled yes ;
|
--tls-port 8000 --cluster-enabled yes ;
|
||||||
|
@ -44,7 +44,7 @@ if [ ${node} = "cluster" ] ; then
|
||||||
redis-server /data/conf/redis.conf --port 7001 --cluster-config-file /data/conf/nodes.7001.conf --cluster-enabled yes;
|
redis-server /data/conf/redis.conf --port 7001 --cluster-config-file /data/conf/nodes.7001.conf --cluster-enabled yes;
|
||||||
redis-server /data/conf/redis.conf --port 7002 --cluster-config-file /data/conf/nodes.7002.conf --cluster-enabled yes;
|
redis-server /data/conf/redis.conf --port 7002 --cluster-config-file /data/conf/nodes.7002.conf --cluster-enabled yes;
|
||||||
fi
|
fi
|
||||||
elif [ ${node} = "sentinel" ] ; then
|
elif [ "${node}" = "sentinel" ] ; then
|
||||||
redis-server /data/conf/redis.conf --port 7000 --cluster-config-file /data/conf/nodes.7000.conf \
|
redis-server /data/conf/redis.conf --port 7000 --cluster-config-file /data/conf/nodes.7000.conf \
|
||||||
--cluster-enabled no;
|
--cluster-enabled no;
|
||||||
redis-server /data/conf/redis.conf --port 7001 --cluster-config-file /data/conf/nodes.7001.conf \
|
redis-server /data/conf/redis.conf --port 7001 --cluster-config-file /data/conf/nodes.7001.conf \
|
||||||
|
@ -75,9 +75,9 @@ do
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
fi
|
fi
|
||||||
if [ ${node} = "cluster" ] ; then
|
if [ "${node}" = "cluster" ] ; then
|
||||||
yes "yes" | redis-cli --cluster create 172.16.239.10:7000 172.16.239.10:7001 172.16.239.10:7002;
|
yes "yes" | redis-cli --cluster create 172.16.239.10:7000 172.16.239.10:7001 172.16.239.10:7002;
|
||||||
elif [ ${node} = "sentinel" ] ; then
|
elif [ "${node}" = "sentinel" ] ; then
|
||||||
cp /data/conf/sentinel.conf /_sentinel.conf
|
cp /data/conf/sentinel.conf /_sentinel.conf
|
||||||
redis-server /_sentinel.conf --sentinel;
|
redis-server /_sentinel.conf --sentinel;
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -25,6 +25,7 @@ jobs:
|
||||||
MONGO_TAG: 4
|
MONGO_TAG: 4
|
||||||
PGSQL_TAG: 13
|
PGSQL_TAG: 13
|
||||||
LDAP_TAG: 2.4.50
|
LDAP_TAG: 2.4.50
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
docker-compose -f .ci/apps_tests/docker-compose.yaml build --no-cache
|
docker-compose -f .ci/apps_tests/docker-compose.yaml build --no-cache
|
||||||
docker-compose -f .ci/apps_tests/docker-compose.yaml up -d
|
docker-compose -f .ci/apps_tests/docker-compose.yaml up -d
|
||||||
|
@ -48,6 +49,7 @@ jobs:
|
||||||
docker exec -i erlang bash -c "make xref"
|
docker exec -i erlang bash -c "make xref"
|
||||||
docker exec -i erlang bash -c "make ct"
|
docker exec -i erlang bash -c "make ct"
|
||||||
docker exec -i erlang bash -c "make cover"
|
docker exec -i erlang bash -c "make cover"
|
||||||
|
docker exec -i erlang bash -c "make coveralls"
|
||||||
- uses: actions/upload-artifact@v1
|
- uses: actions/upload-artifact@v1
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
name: Shellcheck
|
||||||
|
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
shellcheck:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- name: Install shellcheck
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt install shellcheck
|
||||||
|
- name: Run shellcheck
|
||||||
|
run: |
|
||||||
|
./scripts/shellcheck.sh
|
||||||
|
echo "success"
|
8
Makefile
8
Makefile
|
@ -31,6 +31,10 @@ get-dashboard:
|
||||||
eunit: $(REBAR)
|
eunit: $(REBAR)
|
||||||
$(REBAR) eunit
|
$(REBAR) eunit
|
||||||
|
|
||||||
|
.PHONY: proper
|
||||||
|
proper: $(REBAR)
|
||||||
|
$(REBAR) as test proper -d test/props -c
|
||||||
|
|
||||||
.PHONY: ct
|
.PHONY: ct
|
||||||
ct: $(REBAR)
|
ct: $(REBAR)
|
||||||
$(REBAR) ct --name 'test@127.0.0.1' -c -v
|
$(REBAR) ct --name 'test@127.0.0.1' -c -v
|
||||||
|
@ -39,6 +43,10 @@ ct: $(REBAR)
|
||||||
cover: $(REBAR)
|
cover: $(REBAR)
|
||||||
$(REBAR) cover
|
$(REBAR) cover
|
||||||
|
|
||||||
|
.PHONY: coveralls
|
||||||
|
coveralls: $(REBAR)
|
||||||
|
$(REBAR) as test coveralls send
|
||||||
|
|
||||||
.PHONY: $(REL_PROFILES)
|
.PHONY: $(REL_PROFILES)
|
||||||
$(REL_PROFILES:%=%): $(REBAR) get-dashboard
|
$(REL_PROFILES:%=%): $(REBAR) get-dashboard
|
||||||
ifneq ($(shell echo $(@) |grep edge),)
|
ifneq ($(shell echo $(@) |grep edge),)
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
.eunit
|
|
||||||
deps
|
|
||||||
*.o
|
|
||||||
*.beam
|
|
||||||
*.plt
|
|
||||||
erl_crash.dump
|
|
||||||
ebin
|
|
||||||
rel/example_project
|
|
||||||
.concrete/DEV_MODE
|
|
||||||
.rebar
|
|
||||||
.erlang.mk/
|
|
||||||
data/
|
|
||||||
emqx_plugin_template.d
|
|
||||||
.DS_Store
|
|
||||||
erlang.mk
|
|
||||||
_build/
|
|
||||||
rebar.lock
|
|
||||||
test/ct.cover.spec
|
|
||||||
.rebar3
|
|
|
@ -1,34 +0,0 @@
|
||||||
emqx-plugin-template
|
|
||||||
====================
|
|
||||||
|
|
||||||
This is a template plugin for the EMQ X broker. And you can see [Plugin Development Guide](https://docs.emqx.io/broker/v3/en/plugins.html#plugin-development-template) to learning how to use it.
|
|
||||||
|
|
||||||
Plugin Config
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Each plugin should have a 'etc/{plugin_name}.conf|config' file to store application config.
|
|
||||||
|
|
||||||
Authentication and ACL
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
```
|
|
||||||
emqx:hook('client.authenticate', fun ?MODULE:on_client_authenticate/3, [Env]).
|
|
||||||
emqx:hook('client.check_acl', fun ?MODULE:on_client_check_acl/5, [Env]).
|
|
||||||
```
|
|
||||||
|
|
||||||
Plugin and Hooks
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
[Plugin Design](https://docs.emqx.io/broker/v3/en/design.html#plugin-design)
|
|
||||||
|
|
||||||
[Hooks Design](https://docs.emqx.io/broker/v3/en/design.html#hooks-design)
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
Apache License Version 2.0
|
|
||||||
|
|
||||||
Author
|
|
||||||
------
|
|
||||||
|
|
||||||
EMQ X Team.
|
|
|
@ -1,3 +0,0 @@
|
||||||
1. Add a script to generate plugin project
|
|
||||||
2. Upgrade the README.md
|
|
||||||
3. Add the plugin development guide
|
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
[
|
|
||||||
{emqx_plugin_template, []}
|
|
||||||
].
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{deps, []}.
|
|
||||||
|
|
||||||
{erl_opts, [debug_info]}.
|
|
|
@ -1,26 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
%% you may not use this file except in compliance with the License.
|
|
||||||
%% You may obtain a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_cli_demo).
|
|
||||||
|
|
||||||
-export([cmd/1]).
|
|
||||||
|
|
||||||
cmd(["arg1", "arg2"]) ->
|
|
||||||
emqx_ctl:print("ok");
|
|
||||||
|
|
||||||
cmd(_) ->
|
|
||||||
emqx_ctl:usage([{"cmd arg1 arg2", "cmd demo"}]).
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
{application, emqx_plugin_template,
|
|
||||||
[{description, "EMQ X Plugin Template"},
|
|
||||||
{vsn, "4.3.0"}, % strict semver, bump manually!
|
|
||||||
{modules, []},
|
|
||||||
{registered, [emqx_plugin_template_sup]},
|
|
||||||
{applications, [kernel,stdlib]},
|
|
||||||
{mod, {emqx_plugin_template_app,[]}},
|
|
||||||
{env, []},
|
|
||||||
{licenses, ["Apache-2.0"]},
|
|
||||||
{maintainers, ["EMQ X Team <contact@emqx.io>"]},
|
|
||||||
{links, [{"Homepage", "https://emqx.io/"},
|
|
||||||
{"Github", "https://github.com/emqx/emqx-plugin-template"}
|
|
||||||
]}
|
|
||||||
]}.
|
|
|
@ -1,193 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
%% you may not use this file except in compliance with the License.
|
|
||||||
%% You may obtain a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_plugin_template).
|
|
||||||
|
|
||||||
-include_lib("emqx/include/emqx.hrl").
|
|
||||||
|
|
||||||
-export([ load/1
|
|
||||||
, unload/0
|
|
||||||
]).
|
|
||||||
|
|
||||||
%% Client Lifecircle Hooks
|
|
||||||
-export([ on_client_connect/3
|
|
||||||
, on_client_connack/4
|
|
||||||
, on_client_connected/3
|
|
||||||
, on_client_disconnected/4
|
|
||||||
, on_client_authenticate/3
|
|
||||||
, on_client_check_acl/5
|
|
||||||
, on_client_subscribe/4
|
|
||||||
, on_client_unsubscribe/4
|
|
||||||
]).
|
|
||||||
|
|
||||||
%% Session Lifecircle Hooks
|
|
||||||
-export([ on_session_created/3
|
|
||||||
, on_session_subscribed/4
|
|
||||||
, on_session_unsubscribed/4
|
|
||||||
, on_session_resumed/3
|
|
||||||
, on_session_discarded/3
|
|
||||||
, on_session_takeovered/3
|
|
||||||
, on_session_terminated/4
|
|
||||||
]).
|
|
||||||
|
|
||||||
%% Message Pubsub Hooks
|
|
||||||
-export([ on_message_publish/2
|
|
||||||
, on_message_delivered/3
|
|
||||||
, on_message_acked/3
|
|
||||||
, on_message_dropped/4
|
|
||||||
]).
|
|
||||||
|
|
||||||
%% Called when the plugin application start
|
|
||||||
load(Env) ->
|
|
||||||
hook('client.connect', {?MODULE, on_client_connect, [Env]}),
|
|
||||||
hook('client.connack', {?MODULE, on_client_connack, [Env]}),
|
|
||||||
hook('client.connected', {?MODULE, on_client_connected, [Env]}),
|
|
||||||
hook('client.disconnected', {?MODULE, on_client_disconnected, [Env]}),
|
|
||||||
hook('client.authenticate', {?MODULE, on_client_authenticate, [Env]}),
|
|
||||||
hook('client.check_acl', {?MODULE, on_client_check_acl, [Env]}),
|
|
||||||
hook('client.subscribe', {?MODULE, on_client_subscribe, [Env]}),
|
|
||||||
hook('client.unsubscribe', {?MODULE, on_client_unsubscribe, [Env]}),
|
|
||||||
hook('session.created', {?MODULE, on_session_created, [Env]}),
|
|
||||||
hook('session.subscribed', {?MODULE, on_session_subscribed, [Env]}),
|
|
||||||
hook('session.unsubscribed',{?MODULE, on_session_unsubscribed, [Env]}),
|
|
||||||
hook('session.resumed', {?MODULE, on_session_resumed, [Env]}),
|
|
||||||
hook('session.discarded', {?MODULE, on_session_discarded, [Env]}),
|
|
||||||
hook('session.takeovered', {?MODULE, on_session_takeovered, [Env]}),
|
|
||||||
hook('session.terminated', {?MODULE, on_session_terminated, [Env]}),
|
|
||||||
hook('message.publish', {?MODULE, on_message_publish, [Env]}),
|
|
||||||
hook('message.delivered', {?MODULE, on_message_delivered, [Env]}),
|
|
||||||
hook('message.acked', {?MODULE, on_message_acked, [Env]}),
|
|
||||||
hook('message.dropped', {?MODULE, on_message_dropped, [Env]}).
|
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Client Lifecircle Hooks
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
on_client_connect(ConnInfo = #{clientid := ClientId}, Props, _Env) ->
|
|
||||||
io:format("Client(~s) connect, ConnInfo: ~p, Props: ~p~n",
|
|
||||||
[ClientId, ConnInfo, Props]),
|
|
||||||
{ok, Props}.
|
|
||||||
|
|
||||||
on_client_connack(ConnInfo = #{clientid := ClientId}, Rc, Props, _Env) ->
|
|
||||||
io:format("Client(~s) connack, ConnInfo: ~p, Rc: ~p, Props: ~p~n",
|
|
||||||
[ClientId, ConnInfo, Rc, Props]),
|
|
||||||
{ok, Props}.
|
|
||||||
|
|
||||||
on_client_connected(ClientInfo = #{clientid := ClientId}, ConnInfo, _Env) ->
|
|
||||||
io:format("Client(~s) connected, ClientInfo:~n~p~n, ConnInfo:~n~p~n",
|
|
||||||
[ClientId, ClientInfo, ConnInfo]).
|
|
||||||
|
|
||||||
on_client_disconnected(ClientInfo = #{clientid := ClientId}, ReasonCode, ConnInfo, _Env) ->
|
|
||||||
io:format("Client(~s) disconnected due to ~p, ClientInfo:~n~p~n, ConnInfo:~n~p~n",
|
|
||||||
[ClientId, ReasonCode, ClientInfo, ConnInfo]).
|
|
||||||
|
|
||||||
on_client_authenticate(_ClientInfo = #{clientid := ClientId}, Result, _Env) ->
|
|
||||||
io:format("Client(~s) authenticate, Result:~n~p~n", [ClientId, Result]),
|
|
||||||
{ok, Result}.
|
|
||||||
|
|
||||||
on_client_check_acl(_ClientInfo = #{clientid := ClientId}, Topic, PubSub, Result, _Env) ->
|
|
||||||
io:format("Client(~s) check_acl, PubSub:~p, Topic:~p, Result:~p~n",
|
|
||||||
[ClientId, PubSub, Topic, Result]),
|
|
||||||
{ok, Result}.
|
|
||||||
|
|
||||||
on_client_subscribe(#{clientid := ClientId}, _Properties, TopicFilters, _Env) ->
|
|
||||||
io:format("Client(~s) will subscribe: ~p~n", [ClientId, TopicFilters]),
|
|
||||||
{ok, TopicFilters}.
|
|
||||||
|
|
||||||
on_client_unsubscribe(#{clientid := ClientId}, _Properties, TopicFilters, _Env) ->
|
|
||||||
io:format("Client(~s) will unsubscribe ~p~n", [ClientId, TopicFilters]),
|
|
||||||
{ok, TopicFilters}.
|
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Session Lifecircle Hooks
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
on_session_created(#{clientid := ClientId}, SessInfo, _Env) ->
|
|
||||||
io:format("Session(~s) created, Session Info:~n~p~n", [ClientId, SessInfo]).
|
|
||||||
|
|
||||||
on_session_subscribed(#{clientid := ClientId}, Topic, SubOpts, _Env) ->
|
|
||||||
io:format("Session(~s) subscribed ~s with subopts: ~p~n", [ClientId, Topic, SubOpts]).
|
|
||||||
|
|
||||||
on_session_unsubscribed(#{clientid := ClientId}, Topic, Opts, _Env) ->
|
|
||||||
io:format("Session(~s) unsubscribed ~s with opts: ~p~n", [ClientId, Topic, Opts]).
|
|
||||||
|
|
||||||
on_session_resumed(#{clientid := ClientId}, SessInfo, _Env) ->
|
|
||||||
io:format("Session(~s) resumed, Session Info:~n~p~n", [ClientId, SessInfo]).
|
|
||||||
|
|
||||||
on_session_discarded(_ClientInfo = #{clientid := ClientId}, SessInfo, _Env) ->
|
|
||||||
io:format("Session(~s) is discarded. Session Info: ~p~n", [ClientId, SessInfo]).
|
|
||||||
|
|
||||||
on_session_takeovered(_ClientInfo = #{clientid := ClientId}, SessInfo, _Env) ->
|
|
||||||
io:format("Session(~s) is takeovered. Session Info: ~p~n", [ClientId, SessInfo]).
|
|
||||||
|
|
||||||
on_session_terminated(_ClientInfo = #{clientid := ClientId}, Reason, SessInfo, _Env) ->
|
|
||||||
io:format("Session(~s) is terminated due to ~p~nSession Info: ~p~n",
|
|
||||||
[ClientId, Reason, SessInfo]).
|
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Message PubSub Hooks
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
%% Transform message and return
|
|
||||||
on_message_publish(Message = #message{topic = <<"$SYS/", _/binary>>}, _Env) ->
|
|
||||||
{ok, Message};
|
|
||||||
|
|
||||||
on_message_publish(Message, _Env) ->
|
|
||||||
io:format("Publish ~s~n", [emqx_message:format(Message)]),
|
|
||||||
{ok, Message}.
|
|
||||||
|
|
||||||
on_message_dropped(#message{topic = <<"$SYS/", _/binary>>}, _By, _Reason, _Env) ->
|
|
||||||
ok;
|
|
||||||
on_message_dropped(Message, _By = #{node := Node}, Reason, _Env) ->
|
|
||||||
io:format("Message dropped by node ~s due to ~s: ~s~n",
|
|
||||||
[Node, Reason, emqx_message:format(Message)]).
|
|
||||||
|
|
||||||
on_message_delivered(_ClientInfo = #{clientid := ClientId}, Message, _Env) ->
|
|
||||||
io:format("Message delivered to client(~s): ~s~n",
|
|
||||||
[ClientId, emqx_message:format(Message)]),
|
|
||||||
{ok, Message}.
|
|
||||||
|
|
||||||
on_message_acked(_ClientInfo = #{clientid := ClientId}, Message, _Env) ->
|
|
||||||
io:format("Message acked by client(~s): ~s~n",
|
|
||||||
[ClientId, emqx_message:format(Message)]).
|
|
||||||
|
|
||||||
%% Called when the plugin application stop
|
|
||||||
unload() ->
|
|
||||||
emqx:unhook('client.connect', {?MODULE, on_client_connect}),
|
|
||||||
emqx:unhook('client.connack', {?MODULE, on_client_connack}),
|
|
||||||
emqx:unhook('client.connected', {?MODULE, on_client_connected}),
|
|
||||||
emqx:unhook('client.disconnected', {?MODULE, on_client_disconnected}),
|
|
||||||
emqx:unhook('client.authenticate', {?MODULE, on_client_authenticate}),
|
|
||||||
emqx:unhook('client.check_acl', {?MODULE, on_client_check_acl}),
|
|
||||||
emqx:unhook('client.subscribe', {?MODULE, on_client_subscribe}),
|
|
||||||
emqx:unhook('client.unsubscribe', {?MODULE, on_client_unsubscribe}),
|
|
||||||
emqx:unhook('session.created', {?MODULE, on_session_created}),
|
|
||||||
emqx:unhook('session.subscribed', {?MODULE, on_session_subscribed}),
|
|
||||||
emqx:unhook('session.unsubscribed',{?MODULE, on_session_unsubscribed}),
|
|
||||||
emqx:unhook('session.resumed', {?MODULE, on_session_resumed}),
|
|
||||||
emqx:unhook('session.discarded', {?MODULE, on_session_discarded}),
|
|
||||||
emqx:unhook('session.takeovered', {?MODULE, on_session_takeovered}),
|
|
||||||
emqx:unhook('session.terminated', {?MODULE, on_session_terminated}),
|
|
||||||
emqx:unhook('message.publish', {?MODULE, on_message_publish}),
|
|
||||||
emqx:unhook('message.delivered', {?MODULE, on_message_delivered}),
|
|
||||||
emqx:unhook('message.acked', {?MODULE, on_message_acked}),
|
|
||||||
emqx:unhook('message.dropped', {?MODULE, on_message_dropped}).
|
|
||||||
|
|
||||||
hook(Name, MFA) ->
|
|
||||||
case emqx:hook(Name, MFA) of
|
|
||||||
ok -> ok;
|
|
||||||
{error, already_exists} -> ok
|
|
||||||
end.
|
|
|
@ -1,34 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
%% you may not use this file except in compliance with the License.
|
|
||||||
%% You may obtain a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_plugin_template_app).
|
|
||||||
|
|
||||||
-behaviour(application).
|
|
||||||
|
|
||||||
-emqx_plugin(?MODULE).
|
|
||||||
|
|
||||||
-export([ start/2
|
|
||||||
, stop/1
|
|
||||||
]).
|
|
||||||
|
|
||||||
start(_StartType, _StartArgs) ->
|
|
||||||
{ok, Sup} = emqx_plugin_template_sup:start_link(),
|
|
||||||
emqx_plugin_template:load(application:get_all_env()),
|
|
||||||
{ok, Sup}.
|
|
||||||
|
|
||||||
stop(_State) ->
|
|
||||||
emqx_plugin_template:unload().
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
%% you may not use this file except in compliance with the License.
|
|
||||||
%% You may obtain a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_plugin_template_sup).
|
|
||||||
|
|
||||||
-behaviour(supervisor).
|
|
||||||
|
|
||||||
-export([start_link/0]).
|
|
||||||
|
|
||||||
-export([init/1]).
|
|
||||||
|
|
||||||
start_link() ->
|
|
||||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
||||||
|
|
||||||
init([]) ->
|
|
||||||
{ok, { {one_for_all, 0, 1}, []} }.
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
%% you may not use this file except in compliance with the License.
|
|
||||||
%% You may obtain a copy of the License at
|
|
||||||
%%
|
|
||||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_plugin_template_SUITE).
|
|
||||||
|
|
||||||
-compile(nowarn_export_all).
|
|
||||||
-compile(export_all).
|
|
||||||
|
|
||||||
all() -> [].
|
|
||||||
|
|
||||||
groups() -> [].
|
|
|
@ -290,58 +290,22 @@ prop_message_acked() ->
|
||||||
true
|
true
|
||||||
end).
|
end).
|
||||||
|
|
||||||
prop_try_again() ->
|
|
||||||
Setup = fun() ->
|
|
||||||
logger:set_module_level(emqx_web_hook, emergency),
|
|
||||||
meck:new(httpc, [passthrough, no_history]),
|
|
||||||
meck:expect(httpc, request,
|
|
||||||
fun(Method, {Url, [], ContentType, Body}, _HttpOpts, _Opt) ->
|
|
||||||
self() ! {Method, Url, ContentType, Body}, {error, get(code)}
|
|
||||||
end),
|
|
||||||
meck:new(emqx_metrics, [passthrough, no_history]),
|
|
||||||
meck:expect(emqx_metrics, inc, fun(_) -> ok end)
|
|
||||||
end,
|
|
||||||
Teardown = fun() ->
|
|
||||||
meck:unload(httpc),
|
|
||||||
meck:unload(emqx_metrics),
|
|
||||||
logger:set_module_level(emqx_web_hook, debug)
|
|
||||||
end,
|
|
||||||
?SETUP(fun() -> Setup(), Teardown end,
|
|
||||||
?FORALL({ConnInfo, ConnProps, Env, Code},
|
|
||||||
{conninfo(), conn_properties(), empty_env(), http_code()},
|
|
||||||
begin
|
|
||||||
%% pre-set error code
|
|
||||||
put(code, Code),
|
|
||||||
%% run hook
|
|
||||||
ok = emqx_web_hook:on_client_connect(ConnInfo, ConnProps, Env),
|
|
||||||
|
|
||||||
Bodys = receive_http_request_bodys(),
|
|
||||||
Body = emqx_json:encode(
|
|
||||||
#{action => client_connect,
|
|
||||||
node => stringfy(node()),
|
|
||||||
clientid => maps:get(clientid, ConnInfo),
|
|
||||||
username => maybe(maps:get(username, ConnInfo)),
|
|
||||||
ipaddress => peer2addr(maps:get(peername, ConnInfo)),
|
|
||||||
keepalive => maps:get(keepalive, ConnInfo),
|
|
||||||
proto_ver => maps:get(proto_ver, ConnInfo)
|
|
||||||
}),
|
|
||||||
[ B = Body || B <- Bodys],
|
|
||||||
if Code == socket_closed_remotely ->
|
|
||||||
4 = length(Bodys);
|
|
||||||
true -> ok
|
|
||||||
end,
|
|
||||||
true
|
|
||||||
end)).
|
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Helper
|
%% Helper
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
do_setup() ->
|
do_setup() ->
|
||||||
|
%% Pre-defined envs
|
||||||
|
application:set_env(emqx_web_hook, path, "path"),
|
||||||
|
application:set_env(emqx_web_hook, headers, []),
|
||||||
|
|
||||||
|
meck:new(ehttpc_pool, [passthrough, no_history]),
|
||||||
|
meck:expect(ehttpc_pool, pick_worker, fun(_, _) -> ok end),
|
||||||
|
|
||||||
Self = self(),
|
Self = self(),
|
||||||
meck:new(httpc, [passthrough, no_history]),
|
meck:new(ehttpc, [passthrough, no_history]),
|
||||||
meck:expect(httpc, request,
|
meck:expect(ehttpc, request,
|
||||||
fun(Method, {Url, [], ContentType, Body}, _HttpOpts, _Opt) ->
|
fun(_ClientId, Method, {Path, Headers, Body}) ->
|
||||||
Self ! {Method, Url, ContentType, Body}, {ok, ok}
|
Self ! {Method, Path, Headers, Body}, {ok, ok, ok}
|
||||||
end),
|
end),
|
||||||
|
|
||||||
meck:new(emqx_metrics, [passthrough, no_history]),
|
meck:new(emqx_metrics, [passthrough, no_history]),
|
||||||
|
@ -349,7 +313,8 @@ do_setup() ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
do_teardown(_) ->
|
do_teardown(_) ->
|
||||||
meck:unload(httpc),
|
meck:unload(ehttpc_pool),
|
||||||
|
meck:unload(ehttpc),
|
||||||
meck:unload(emqx_metrics).
|
meck:unload(emqx_metrics).
|
||||||
|
|
||||||
maybe(undefined) -> null;
|
maybe(undefined) -> null;
|
||||||
|
@ -372,7 +337,7 @@ stringfy(Term) ->
|
||||||
|
|
||||||
receive_http_request_body() ->
|
receive_http_request_body() ->
|
||||||
receive
|
receive
|
||||||
{post, "http://127.0.0.1", "application/json", Body} ->
|
{post, _, _, Body} ->
|
||||||
Body
|
Body
|
||||||
after 100 ->
|
after 100 ->
|
||||||
exit(waiting_message_timeout)
|
exit(waiting_message_timeout)
|
||||||
|
@ -383,7 +348,7 @@ receive_http_request_bodys() ->
|
||||||
|
|
||||||
receive_http_request_bodys_(Acc) ->
|
receive_http_request_bodys_(Acc) ->
|
||||||
receive
|
receive
|
||||||
{post, "http://127.0.0.1", "application/json", Body} ->
|
{post, _, _, Body} ->
|
||||||
receive_http_request_bodys_([Body|Acc])
|
receive_http_request_bodys_([Body|Acc])
|
||||||
after 1000 ->
|
after 1000 ->
|
||||||
lists:reverse(Acc)
|
lists:reverse(Acc)
|
||||||
|
|
100
bin/emqx
100
bin/emqx
|
@ -1,11 +1,12 @@
|
||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
# -*- tab-width:4;indent-tabs-mode:nil -*-
|
# -*- tab-width:4;indent-tabs-mode:nil -*-
|
||||||
# ex: ts=4 sw=4 et
|
# ex: ts=4 sw=4 et
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
ROOT_DIR="$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"
|
ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)"
|
||||||
. $ROOT_DIR/releases/emqx_vars
|
# shellcheck disable=SC1090
|
||||||
|
. "$ROOT_DIR"/releases/emqx_vars
|
||||||
|
|
||||||
RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
|
RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
|
||||||
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
|
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
|
||||||
|
@ -79,7 +80,7 @@ relx_usage() {
|
||||||
check_user() {
|
check_user() {
|
||||||
# Validate that the user running the script is the owner of the
|
# Validate that the user running the script is the owner of the
|
||||||
# RUN_DIR.
|
# RUN_DIR.
|
||||||
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
|
if [ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]; then
|
||||||
if [ "x$WHOAMI" != "xroot" ]; then
|
if [ "x$WHOAMI" != "xroot" ]; then
|
||||||
echo "You need to be root or use sudo to run this command"
|
echo "You need to be root or use sudo to run this command"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -90,13 +91,13 @@ check_user() {
|
||||||
done
|
done
|
||||||
# This will drop priviledges into the runner user
|
# This will drop priviledges into the runner user
|
||||||
# It exec's in a new shell and the current shell will exit
|
# It exec's in a new shell and the current shell will exit
|
||||||
exec su - $RUNNER_USER -c "$CMD"
|
exec su - "$RUNNER_USER" -c "$CMD"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Make sure the user running this script is the owner and/or su to that user
|
# Make sure the user running this script is the owner and/or su to that user
|
||||||
check_user $@
|
check_user "$@"
|
||||||
ES=$?
|
ES=$?
|
||||||
if [ "$ES" -ne 0 ]; then
|
if [ "$ES" -ne 0 ]; then
|
||||||
exit $ES
|
exit $ES
|
||||||
|
@ -109,7 +110,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Warn the user if ulimit -n is less than 1024
|
# Warn the user if ulimit -n is less than 1024
|
||||||
ULIMIT_F=`ulimit -n`
|
ULIMIT_F=$(ulimit -n)
|
||||||
if [ "$ULIMIT_F" -lt 1024 ]; then
|
if [ "$ULIMIT_F" -lt 1024 ]; then
|
||||||
echo "!!!!"
|
echo "!!!!"
|
||||||
echo "!!!! WARNING: ulimit -n is ${ULIMIT_F}; 1024 is the recommended minimum."
|
echo "!!!! WARNING: ulimit -n is ${ULIMIT_F}; 1024 is the recommended minimum."
|
||||||
|
@ -133,6 +134,7 @@ esac
|
||||||
relx_get_pid() {
|
relx_get_pid() {
|
||||||
if output="$(relx_nodetool rpcterms os getpid)"
|
if output="$(relx_nodetool rpcterms os getpid)"
|
||||||
then
|
then
|
||||||
|
# shellcheck disable=SC2001 # Escaped quote taken as closing quote in editor
|
||||||
echo "$output" | sed -e 's/"//g'
|
echo "$output" | sed -e 's/"//g'
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
|
@ -143,7 +145,7 @@ relx_get_pid() {
|
||||||
|
|
||||||
relx_get_nodename() {
|
relx_get_nodename() {
|
||||||
id="longname$(relx_gen_id)-${NAME}"
|
id="longname$(relx_gen_id)-${NAME}"
|
||||||
"$BINDIR/erl" -boot "$REL_DIR/start_clean" -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
|
"$BINDIR/erl" -boot "$REL_DIR/start_clean" -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell "${NAME_TYPE}" "$id"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Connect to a remote node
|
# Connect to a remote node
|
||||||
|
@ -154,10 +156,11 @@ relx_rem_sh() {
|
||||||
# Get the node's ticktime so that we use the same thing.
|
# Get the node's ticktime so that we use the same thing.
|
||||||
TICKTIME="$(relx_nodetool rpcterms net_kernel get_net_ticktime)"
|
TICKTIME="$(relx_nodetool rpcterms net_kernel get_net_ticktime)"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086 # $EPMD_ARG is supposed to be split by whitespace
|
||||||
# Setup remote shell command to control node
|
# Setup remote shell command to control node
|
||||||
exec "$BINDIR/erl" "$NAME_TYPE" "$id" -remsh "$NAME" -boot "$REL_DIR/start_clean" \
|
exec "$BINDIR/erl" "$NAME_TYPE" "$id" -remsh "$NAME" -boot "$REL_DIR/start_clean" \
|
||||||
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
|
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
|
||||||
-setcookie "$COOKIE" -hidden -kernel net_ticktime $TICKTIME $EPMD_ARG
|
-setcookie "$COOKIE" -hidden -kernel net_ticktime "$TICKTIME" $EPMD_ARG
|
||||||
}
|
}
|
||||||
|
|
||||||
# Generate a random id
|
# Generate a random id
|
||||||
|
@ -171,7 +174,7 @@ relx_nodetool() {
|
||||||
|
|
||||||
ERL_FLAGS="$ERL_FLAGS $EPMD_ARG" \
|
ERL_FLAGS="$ERL_FLAGS $EPMD_ARG" \
|
||||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
||||||
-setcookie "$COOKIE" "$command" $@
|
-setcookie "$COOKIE" "$command" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run an escript in the node's environment
|
# Run an escript in the node's environment
|
||||||
|
@ -179,7 +182,7 @@ relx_escript() {
|
||||||
shift; scriptpath="$1"; shift
|
shift; scriptpath="$1"; shift
|
||||||
export RUNNER_ROOT_DIR
|
export RUNNER_ROOT_DIR
|
||||||
|
|
||||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
|
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Output a start command for the last argument of run_erl
|
# Output a start command for the last argument of run_erl
|
||||||
|
@ -202,19 +205,19 @@ generate_config() {
|
||||||
# the vm, we need to pass it in twice.
|
# 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 "
|
CONFIG_ARGS=" -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -vm_args $RUNNER_ETC_DIR/vm.args "
|
||||||
else
|
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`
|
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)
|
||||||
|
|
||||||
## Merge cuttlefish generated *.args into the vm.args
|
## 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}'`
|
CUTTLE_GEN_ARG_FILE=$(echo "$CONFIG_ARGS" | sed -n 's/^.*\(vm_args[[:space:]]\)//p' | awk '{print $1}')
|
||||||
TMP_ARG_FILE="$RUNNER_DATA_DIR/configs/vm.args.tmp"
|
TMP_ARG_FILE="$RUNNER_DATA_DIR/configs/vm.args.tmp"
|
||||||
cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
|
cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
|
||||||
echo "" >> "$TMP_ARG_FILE"
|
echo "" >> "$TMP_ARG_FILE"
|
||||||
sed '/^#/d' $CUTTLE_GEN_ARG_FILE | sed '/^$/d' | while IFS='' read -r ARG_LINE || [ -n "$ARG_LINE" ]; do
|
sed '/^#/d' "$CUTTLE_GEN_ARG_FILE" | sed '/^$/d' | while IFS='' read -r ARG_LINE || [ -n "$ARG_LINE" ]; do
|
||||||
ARG_KEY=`echo "$ARG_LINE" | awk '{$NF="";print}'`
|
ARG_KEY=$(echo "$ARG_LINE" | awk '{$NF="";print}')
|
||||||
ARG_VALUE=`echo "$ARG_LINE" | awk '{print $NF}'`
|
ARG_VALUE=$(echo "$ARG_LINE" | awk '{print $NF}')
|
||||||
TMP_ARG_VALUE=`grep "^$ARG_KEY" "$TMP_ARG_FILE" | awk '{print $NF}'`
|
TMP_ARG_VALUE=$(grep "^$ARG_KEY" "$TMP_ARG_FILE" | awk '{print $NF}')
|
||||||
if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
|
if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
|
||||||
if [ ! -z $TMP_ARG_VALUE ]; then
|
if [ -n "$TMP_ARG_VALUE" ]; then
|
||||||
sh -c "$SED_REPLACE 's/^$ARG_KEY.*$/$ARG_LINE/' $TMP_ARG_FILE"
|
sh -c "$SED_REPLACE 's/^$ARG_KEY.*$/$ARG_LINE/' $TMP_ARG_FILE"
|
||||||
else
|
else
|
||||||
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
|
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
|
||||||
|
@ -224,6 +227,7 @@ generate_config() {
|
||||||
mv -f "$TMP_ARG_FILE" "$CUTTLE_GEN_ARG_FILE"
|
mv -f "$TMP_ARG_FILE" "$CUTTLE_GEN_ARG_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086
|
||||||
if ! relx_nodetool chkconfig $CONFIG_ARGS; then
|
if ! relx_nodetool chkconfig $CONFIG_ARGS; then
|
||||||
echoerr "Error reading $CONFIG_ARGS"
|
echoerr "Error reading $CONFIG_ARGS"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -233,7 +237,7 @@ generate_config() {
|
||||||
# Call bootstrapd for daemon commands like start/stop/console
|
# Call bootstrapd for daemon commands like start/stop/console
|
||||||
bootstrapd() {
|
bootstrapd() {
|
||||||
if [ -e "$RUNNER_DATA_DIR/.erlang.cookie" ]; then
|
if [ -e "$RUNNER_DATA_DIR/.erlang.cookie" ]; then
|
||||||
chown $RUNNER_USER $RUNNER_DATA_DIR/.erlang.cookie
|
chown "$RUNNER_USER" "$RUNNER_DATA_DIR"/.erlang.cookie
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,8 +253,9 @@ fi
|
||||||
if [ -z "$NAME_ARG" ]; then
|
if [ -z "$NAME_ARG" ]; then
|
||||||
NODENAME="${EMQX_NODE_NAME:-}"
|
NODENAME="${EMQX_NODE_NAME:-}"
|
||||||
# check if there is a node running, inspect its name
|
# check if there is a node running, inspect its name
|
||||||
[ -z "$NODENAME" ] && NODENAME=`ps -ef | grep -E '\-progname\s.*emqx\s' | grep -o -E '\-name (\S*)' | awk '{print $2}'`
|
# shellcheck disable=SC2009 # pgrep does not support Extended Regular Expressions
|
||||||
[ -z "$NODENAME" ] && NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
|
[ -z "$NODENAME" ] && NODENAME=$(ps -ef | grep -E '\-progname\s.*emqx\s' | grep -o -E '\-name (\S*)' | awk '{print $2}')
|
||||||
|
[ -z "$NODENAME" ] && NODENAME=$(grep -E '^[ \t]*node.name[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-)
|
||||||
if [ -z "$NODENAME" ]; then
|
if [ -z "$NODENAME" ]; then
|
||||||
echoerr "vm.args needs to have a -name parameter."
|
echoerr "vm.args needs to have a -name parameter."
|
||||||
echoerr " -sname is not supported."
|
echoerr " -sname is not supported."
|
||||||
|
@ -273,8 +278,9 @@ PIPE_DIR="${PIPE_DIR:-/$RUNNER_DATA_DIR/${WHOAMI}_erl_pipes/$NAME/}"
|
||||||
if [ -z "$COOKIE_ARG" ]; then
|
if [ -z "$COOKIE_ARG" ]; then
|
||||||
COOKIE="${EMQX_NODE_COOKIE:-}"
|
COOKIE="${EMQX_NODE_COOKIE:-}"
|
||||||
# check if there is a node running, steal its cookie
|
# check if there is a node running, steal its cookie
|
||||||
[ -z "$COOKIE" ] && COOKIE=`ps -ef | grep -E '\-progname\s.*emqx\s' | grep -o -E '\-setcookie (\S*)' | awk '{print $2}'`
|
# shellcheck disable=SC2009 # pgrep does not support Extended Regular Expressions
|
||||||
[ -z "$COOKIE" ] && COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
|
[ -z "$COOKIE" ] && COOKIE=$(ps -ef | grep -E '\-progname\s.*emqx\s' | grep -o -E '\-setcookie (\S*)' | awk '{print $2}')
|
||||||
|
[ -z "$COOKIE" ] && COOKIE=$(grep -E '^[ \t]*node.cookie[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-)
|
||||||
if [ -z "$COOKIE" ]; then
|
if [ -z "$COOKIE" ]; then
|
||||||
echoerr "vm.args needs to have a -setcookie parameter."
|
echoerr "vm.args needs to have a -setcookie parameter."
|
||||||
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
|
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
|
||||||
|
@ -288,7 +294,7 @@ fi
|
||||||
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
|
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
|
||||||
|
|
||||||
# Support for IPv6 Dist. See: https://github.com/emqtt/emqttd/issues/1460
|
# Support for IPv6 Dist. See: https://github.com/emqtt/emqttd/issues/1460
|
||||||
PROTO_DIST=`egrep '^[ \t]*cluster.proto_dist[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
|
PROTO_DIST=$(grep -E '^[ \t]*cluster.proto_dist[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-)
|
||||||
if [ -z "$PROTO_DIST" ]; then
|
if [ -z "$PROTO_DIST" ]; then
|
||||||
PROTO_DIST_ARG=""
|
PROTO_DIST_ARG=""
|
||||||
else
|
else
|
||||||
|
@ -327,7 +333,7 @@ case "$1" in
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
||||||
bootstrapd $@
|
bootstrapd
|
||||||
|
|
||||||
# Save this for later.
|
# Save this for later.
|
||||||
CMD=$1
|
CMD=$1
|
||||||
|
@ -343,7 +349,7 @@ case "$1" in
|
||||||
HEART_OPTION="start_boot"
|
HEART_OPTION="start_boot"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
RUN_PARAM="$@"
|
RUN_PARAM="$*"
|
||||||
|
|
||||||
# Set arguments for the heart command
|
# Set arguments for the heart command
|
||||||
set -- "$RUNNER_SCRIPT" "$HEART_OPTION"
|
set -- "$RUNNER_SCRIPT" "$HEART_OPTION"
|
||||||
|
@ -366,9 +372,9 @@ case "$1" in
|
||||||
"$(relx_start_command)"
|
"$(relx_start_command)"
|
||||||
|
|
||||||
WAIT_TIME=${WAIT_FOR_ERLANG:-15}
|
WAIT_TIME=${WAIT_FOR_ERLANG:-15}
|
||||||
while [ $WAIT_TIME -gt 0 ]; do
|
while [ "$WAIT_TIME" -gt 0 ]; do
|
||||||
if ! relx_nodetool "ping" >/dev/null 2>&1; then
|
if ! relx_nodetool "ping" >/dev/null 2>&1; then
|
||||||
WAIT_TIME=`expr $WAIT_TIME - 1`
|
WAIT_TIME=$((WAIT_TIME - 1))
|
||||||
sleep 1
|
sleep 1
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
@ -390,14 +396,14 @@ case "$1" in
|
||||||
if ! relx_nodetool "stop"; then
|
if ! relx_nodetool "stop"; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
while $(kill -s 0 "$PID" 2>/dev/null); do
|
while kill -s 0 "$PID" 2>/dev/null; do
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
|
|
||||||
restart|reboot)
|
restart|reboot)
|
||||||
echo "$EMQX_DISCR $REL_VSN is stopped: $($RUNNER_BIN_DIR/emqx stop)"
|
echo "$EMQX_DISCR $REL_VSN is stopped: $("$RUNNER_BIN_DIR"/emqx stop)"
|
||||||
$RUNNER_BIN_DIR/emqx start
|
"$RUNNER_BIN_DIR"/emqx start
|
||||||
;;
|
;;
|
||||||
|
|
||||||
pid)
|
pid)
|
||||||
|
@ -416,7 +422,7 @@ case "$1" in
|
||||||
|
|
||||||
escript)
|
escript)
|
||||||
## Run an escript under the node's environment
|
## Run an escript under the node's environment
|
||||||
if ! relx_escript $@; then
|
if ! relx_escript "$@"; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
@ -429,7 +435,7 @@ case "$1" in
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
||||||
bootstrapd $@
|
bootstrapd
|
||||||
|
|
||||||
shift
|
shift
|
||||||
exec "$BINDIR/to_erl" "$PIPE_DIR"
|
exec "$BINDIR/to_erl" "$PIPE_DIR"
|
||||||
|
@ -443,7 +449,7 @@ case "$1" in
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
||||||
bootstrapd $@
|
bootstrapd
|
||||||
|
|
||||||
shift
|
shift
|
||||||
relx_rem_sh
|
relx_rem_sh
|
||||||
|
@ -485,7 +491,7 @@ case "$1" in
|
||||||
|
|
||||||
console|console_clean|console_boot)
|
console|console_clean|console_boot)
|
||||||
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
||||||
bootstrapd $@
|
bootstrapd
|
||||||
|
|
||||||
# .boot file typically just $REL_NAME (ie, the app name)
|
# .boot file typically just $REL_NAME (ie, the app name)
|
||||||
# however, for debugging, sometimes start_clean.boot is useful.
|
# however, for debugging, sometimes start_clean.boot is useful.
|
||||||
|
@ -519,8 +525,9 @@ case "$1" in
|
||||||
export PROGNAME
|
export PROGNAME
|
||||||
|
|
||||||
# Store passed arguments since they will be erased by `set`
|
# Store passed arguments since they will be erased by `set`
|
||||||
ARGS="$@"
|
ARGS="$*"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086 # $RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG are supposed to be split by whitespace
|
||||||
# Build an array of arguments to pass to exec later on
|
# Build an array of arguments to pass to exec later on
|
||||||
# Build it here because this command will be used for logging.
|
# Build it here because this command will be used for logging.
|
||||||
set -- "$BINDIR/erlexec" -boot "$BOOTFILE" -mode "$CODE_LOADING_MODE" \
|
set -- "$BINDIR/erlexec" -boot "$BOOTFILE" -mode "$CODE_LOADING_MODE" \
|
||||||
|
@ -529,12 +536,12 @@ case "$1" in
|
||||||
$RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG
|
$RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG
|
||||||
|
|
||||||
# Dump environment info for logging purposes
|
# Dump environment info for logging purposes
|
||||||
echo "Exec: $@" -- ${1+$ARGS}
|
echo "Exec: $*" -- ${1+$ARGS}
|
||||||
echo "Root: $ROOTDIR"
|
echo "Root: $ROOTDIR"
|
||||||
|
|
||||||
# Log the startup
|
# Log the startup
|
||||||
echo "$RUNNER_ROOT_DIR"
|
echo "$RUNNER_ROOT_DIR"
|
||||||
logger -t "$REL_NAME[$$]" "Starting up"
|
logger -t "${REL_NAME[$$]}" "Starting up"
|
||||||
|
|
||||||
# Start the VM
|
# Start the VM
|
||||||
exec "$@" -- ${1+$ARGS}
|
exec "$@" -- ${1+$ARGS}
|
||||||
|
@ -542,7 +549,7 @@ case "$1" in
|
||||||
|
|
||||||
foreground)
|
foreground)
|
||||||
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
|
||||||
bootstrapd $@
|
bootstrapd
|
||||||
# start up the release in the foreground for use by runit
|
# start up the release in the foreground for use by runit
|
||||||
# or other supervision services
|
# or other supervision services
|
||||||
|
|
||||||
|
@ -560,8 +567,9 @@ case "$1" in
|
||||||
export PROGNAME
|
export PROGNAME
|
||||||
|
|
||||||
# Store passed arguments since they will be erased by `set`
|
# Store passed arguments since they will be erased by `set`
|
||||||
ARGS="$@"
|
ARGS="$*"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086 # $RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG are supposed to be split by whitespace
|
||||||
# Build an array of arguments to pass to exec later on
|
# Build an array of arguments to pass to exec later on
|
||||||
# Build it here because this command will be used for logging.
|
# Build it here because this command will be used for logging.
|
||||||
set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
|
set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
|
||||||
|
@ -571,14 +579,14 @@ case "$1" in
|
||||||
$RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG
|
$RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG
|
||||||
|
|
||||||
# Dump environment info for logging purposes
|
# Dump environment info for logging purposes
|
||||||
echo "Exec: $@" -- ${1+$ARGS}
|
echo "Exec: $*" -- ${1+$ARGS}
|
||||||
echo "Root: $ROOTDIR"
|
echo "Root: $ROOTDIR"
|
||||||
|
|
||||||
# Start the VM
|
# Start the VM
|
||||||
exec "$@" -- ${1+$ARGS}
|
exec "$@" -- ${1+$ARGS}
|
||||||
;;
|
;;
|
||||||
ertspath)
|
ertspath)
|
||||||
echo $ERTS_PATH
|
echo "$ERTS_PATH"
|
||||||
;;
|
;;
|
||||||
rpc)
|
rpc)
|
||||||
# Make sure a node IS running
|
# Make sure a node IS running
|
||||||
|
@ -589,7 +597,7 @@ case "$1" in
|
||||||
|
|
||||||
shift
|
shift
|
||||||
|
|
||||||
relx_nodetool rpc $@
|
relx_nodetool rpc "$@"
|
||||||
;;
|
;;
|
||||||
rpcterms)
|
rpcterms)
|
||||||
# Make sure a node IS running
|
# Make sure a node IS running
|
||||||
|
@ -600,7 +608,7 @@ case "$1" in
|
||||||
|
|
||||||
shift
|
shift
|
||||||
|
|
||||||
relx_nodetool rpcterms $@
|
relx_nodetool rpcterms "$@"
|
||||||
;;
|
;;
|
||||||
root_dir)
|
root_dir)
|
||||||
# Make sure a node IS running
|
# Make sure a node IS running
|
||||||
|
@ -620,10 +628,10 @@ case "$1" in
|
||||||
fi
|
fi
|
||||||
|
|
||||||
shift
|
shift
|
||||||
relx_nodetool "eval" $@
|
relx_nodetool "eval" "$@"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
relx_usage $1
|
relx_usage "$1"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
19
bin/emqx_ctl
19
bin/emqx_ctl
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
ROOT_DIR="$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"
|
ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)"
|
||||||
. $ROOT_DIR/releases/emqx_vars
|
# shellcheck disable=SC1090
|
||||||
|
. "$ROOT_DIR"/releases/emqx_vars
|
||||||
|
|
||||||
# Echo to stderr on errors
|
# Echo to stderr on errors
|
||||||
echoerr() { echo "$@" 1>&2; }
|
echoerr() { echo "$@" 1>&2; }
|
||||||
|
@ -18,7 +19,7 @@ fi
|
||||||
|
|
||||||
relx_get_nodename() {
|
relx_get_nodename() {
|
||||||
id="longname$(relx_gen_id)-${NAME}"
|
id="longname$(relx_gen_id)-${NAME}"
|
||||||
"$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
|
"$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell "${NAME_TYPE}" "$id"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Control a node
|
# Control a node
|
||||||
|
@ -34,8 +35,9 @@ relx_nodetool() {
|
||||||
if [ -z "$NAME_ARG" ]; then
|
if [ -z "$NAME_ARG" ]; then
|
||||||
NODENAME="${EMQX_NODE_NAME:-}"
|
NODENAME="${EMQX_NODE_NAME:-}"
|
||||||
# check if there is a node running, inspect its name
|
# check if there is a node running, inspect its name
|
||||||
[ -z "$NODENAME" ] && NODENAME=`ps -ef | grep -E '\progname\s.*emqx\s' | grep -o -E '\-name (\S*)' | awk '{print $2}'`
|
# shellcheck disable=SC2009 # pgrep does not support Extended Regular Expressions
|
||||||
[ -z "$NODENAME" ] && NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
|
[ -z "$NODENAME" ] && NODENAME=$(ps -ef | grep -E '\progname\s.*emqx\s' | grep -o -E '\-name (\S*)' | awk '{print $2}')
|
||||||
|
[ -z "$NODENAME" ] && NODENAME=$(grep -E '^[ \t]*node.name[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-)
|
||||||
if [ -z "$NODENAME" ]; then
|
if [ -z "$NODENAME" ]; then
|
||||||
echoerr "vm.args needs to have a -name parameter."
|
echoerr "vm.args needs to have a -name parameter."
|
||||||
echoerr " -sname is not supported."
|
echoerr " -sname is not supported."
|
||||||
|
@ -54,8 +56,9 @@ NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
|
||||||
if [ -z "$COOKIE_ARG" ]; then
|
if [ -z "$COOKIE_ARG" ]; then
|
||||||
COOKIE="${EMQX_NODE_COOKIE:-}"
|
COOKIE="${EMQX_NODE_COOKIE:-}"
|
||||||
# check if there is a node running, steal its cookie
|
# check if there is a node running, steal its cookie
|
||||||
[ -z "$COOKIE" ] && COOKIE=`ps -ef | grep -E '\-progname\s.*emqx\s' | grep -o -E '\-setcookie (\S*)' | awk '{print $2}'`
|
# shellcheck disable=SC2009 # pgrep does not support Extended Regular Expressions
|
||||||
[ -z "$COOKIE" ] && COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
|
[ -z "$COOKIE" ] && COOKIE=$(ps -ef | grep -E '\-progname\s.*emqx\s' | grep -o -E '\-setcookie (\S*)' | awk '{print $2}')
|
||||||
|
[ -z "$COOKIE" ] && COOKIE=$(grep -E '^[ \t]*node.cookie[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-)
|
||||||
if [ -z "$COOKIE" ]; then
|
if [ -z "$COOKIE" ]; then
|
||||||
echoerr "vm.args needs to have a -setcookie parameter."
|
echoerr "vm.args needs to have a -setcookie parameter."
|
||||||
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
|
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
|
||||||
|
@ -69,7 +72,7 @@ fi
|
||||||
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
|
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
|
||||||
|
|
||||||
# Support for IPv6 Dist. See: https://github.com/emqtt/emqttd/issues/1460
|
# Support for IPv6 Dist. See: https://github.com/emqtt/emqttd/issues/1460
|
||||||
PROTO_DIST=`egrep '^[ \t]*cluster.proto_dist[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
|
PROTO_DIST=$(grep -E '^[ \t]*cluster.proto_dist[ \t]*=[ \t]*' "$RUNNER_ETC_DIR"/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-)
|
||||||
if [ -z "$PROTO_DIST" ]; then
|
if [ -z "$PROTO_DIST" ]; then
|
||||||
PROTO_DIST_ARG=""
|
PROTO_DIST_ARG=""
|
||||||
else
|
else
|
||||||
|
|
3
build
3
build
|
@ -71,7 +71,8 @@ make_relup() {
|
||||||
local releases=()
|
local releases=()
|
||||||
if [ -d "$releases_dir" ]; then
|
if [ -d "$releases_dir" ]; then
|
||||||
while read -r dir; do
|
while read -r dir; do
|
||||||
local version="$(basename "$dir")"
|
local version
|
||||||
|
version="$(basename "$dir")"
|
||||||
# skip current version
|
# skip current version
|
||||||
if [ "$version" != "$PKG_VSN" ]; then
|
if [ "$version" != "$PKG_VSN" ]; then
|
||||||
releases+=( "$version" )
|
releases+=( "$version" )
|
||||||
|
|
|
@ -128,9 +128,9 @@ try_fill_config() {
|
||||||
if grep -qE "^[#[:space:]]*$escaped_key\s*=" "$file"; then
|
if grep -qE "^[#[:space:]]*$escaped_key\s*=" "$file"; then
|
||||||
echo_value "$key" "$value"
|
echo_value "$key" "$value"
|
||||||
if [[ -z "$value" ]]; then
|
if [[ -z "$value" ]]; then
|
||||||
echo "$(sed -r "s/^[#[:space:]]*($escaped_key)\s*=\s*(.*)/# \1 = \2/" "$file")" > "$file"
|
sed -r "s/^[#[:space:]]*($escaped_key)\s*=\s*(.*)/# \1 = \2/" "$file" > tmpfile && cat tmpfile > "$file"
|
||||||
else
|
else
|
||||||
echo "$(sed -r "s/^[#[:space:]]*($escaped_key)\s*=\s*(.*)/\1 = $escaped_value/" "$file")" > "$file"
|
sed -r "s/^[#[:space:]]*($escaped_key)\s*=\s*(.*)/\1 = $escaped_value/" "$file" > tmpfile && cat tmpfile > "$file"
|
||||||
fi
|
fi
|
||||||
# Check if config has a numbering system, but no existing configuration line in file
|
# Check if config has a numbering system, but no existing configuration line in file
|
||||||
elif echo "$key" | grep -qE '\.\d+|\d+\.'; then
|
elif echo "$key" | grep -qE '\.\d+|\d+\.'; then
|
||||||
|
@ -139,7 +139,7 @@ try_fill_config() {
|
||||||
template="$(echo "$escaped_key" | sed -r -e 's/\\\.[0-9]+/\\.[0-9]+/g' -e 's/[0-9]+\\\./[0-9]+\\./g')"
|
template="$(echo "$escaped_key" | sed -r -e 's/\\\.[0-9]+/\\.[0-9]+/g' -e 's/[0-9]+\\\./[0-9]+\\./g')"
|
||||||
if grep -qE "^[#[:space:]]*$template\s*=" "$file"; then
|
if grep -qE "^[#[:space:]]*$template\s*=" "$file"; then
|
||||||
echo_value "$key" "$value"
|
echo_value "$key" "$value"
|
||||||
echo "$(sed '$a'\\ "$file")" > "$file"
|
sed '$a'\\ "$file" > tmpfile && cat tmpfile > "$file"
|
||||||
echo "$key = $value" >> "$file"
|
echo "$key = $value" >> "$file"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -171,12 +171,12 @@ fill_tuples() {
|
||||||
local elements=${*:2}
|
local elements=${*:2}
|
||||||
for var in $elements; do
|
for var in $elements; do
|
||||||
if grep -qE "\{\s*$var\s*,\s*(true|false)\s*\}\s*\." "$file"; then
|
if grep -qE "\{\s*$var\s*,\s*(true|false)\s*\}\s*\." "$file"; then
|
||||||
echo "$(sed -r "s/\{\s*($var)\s*,\s*(true|false)\s*\}\s*\./{\1, true}./1" "$file")" > "$file"
|
sed -r "s/\{\s*($var)\s*,\s*(true|false)\s*\}\s*\./{\1, true}./1" "$file" > tmpfile && mv tmpfile "$file"
|
||||||
elif grep -q "$var\s*\." "$file"; then
|
elif grep -q "$var\s*\." "$file"; then
|
||||||
# backward compatible.
|
# backward compatible.
|
||||||
echo "$(sed -r "s/($var)\s*\./{\1, true}./1" "$file")" > "$file"
|
sed -r "s/($var)\s*\./{\1, true}./1" "$file" > tmpfile && cat tmpfile > "$file"
|
||||||
else
|
else
|
||||||
echo "$(sed '$a'\\ "$file")" > "$file"
|
sed '$a'\\ "$file" > tmpfile && cat tmpfile > "$file"
|
||||||
echo "{$var, true}." >> "$file"
|
echo "{$var, true}." >> "$file"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# emqx
|
# emqx
|
||||||
#
|
#
|
||||||
|
@ -8,11 +8,11 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# Source function library.
|
# Source function library.
|
||||||
|
# shellcheck disable=SC1091
|
||||||
. /etc/rc.d/init.d/functions
|
. /etc/rc.d/init.d/functions
|
||||||
|
|
||||||
RETVAL=0
|
RETVAL=0
|
||||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||||
DESC="EMQX, a distributed, massively scalable, highly extensible MQTT message broker written in Erlang/OTP"
|
|
||||||
NAME=emqx
|
NAME=emqx
|
||||||
DAEMON=/usr/bin/$NAME
|
DAEMON=/usr/bin/$NAME
|
||||||
lockfile=/var/lock/subsys/$NAME
|
lockfile=/var/lock/subsys/$NAME
|
||||||
|
@ -25,6 +25,7 @@ pidfile=/var/run/$NAME/$NAME.pid
|
||||||
[ -d /var/lib/$NAME ] || exit 0
|
[ -d /var/lib/$NAME ] || exit 0
|
||||||
|
|
||||||
# Read configuration variable file if it is present and readable
|
# Read configuration variable file if it is present and readable
|
||||||
|
# shellcheck disable=SC1090
|
||||||
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
|
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
|
||||||
|
|
||||||
# `service` strips all environmental VARS so
|
# `service` strips all environmental VARS so
|
||||||
|
@ -34,15 +35,17 @@ if [ -z "$HOME" ]; then
|
||||||
export HOME=
|
export HOME=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
status -p $pidfile -l $(basename $lockfile) $NAME >/dev/null 2>&1
|
status -p $pidfile -l "$(basename $lockfile)" $NAME >/dev/null 2>&1
|
||||||
running=$?
|
running=$?
|
||||||
|
|
||||||
find_pid() {
|
find_pid() {
|
||||||
|
# shellcheck disable=SC2009 # pgrep does not support Extended Regular Expressions
|
||||||
ps ax | grep -E "\-progname\s+$NAME\s" | awk '{print $1}'
|
ps ax | grep -E "\-progname\s+$NAME\s" | awk '{print $1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
check_pid_status() {
|
check_pid_status() {
|
||||||
local pid="$(find_pid)"
|
local pid
|
||||||
|
pid="$(find_pid)"
|
||||||
if [ "$pid" = "" ]; then
|
if [ "$pid" = "" ]; then
|
||||||
# prog not running?
|
# prog not running?
|
||||||
return 1
|
return 1
|
||||||
|
@ -72,7 +75,7 @@ stop() {
|
||||||
# Stop daemon.
|
# Stop daemon.
|
||||||
echo -n $"Shutting down emqx: "
|
echo -n $"Shutting down emqx: "
|
||||||
$DAEMON stop 2>/dev/null
|
$DAEMON stop 2>/dev/null
|
||||||
for n in $(seq 1 10); do
|
for _ in $(seq 1 10); do
|
||||||
sleep 1
|
sleep 1
|
||||||
check_pid_status
|
check_pid_status
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
|
@ -93,7 +96,7 @@ stop() {
|
||||||
hardstop() {
|
hardstop() {
|
||||||
echo -n $"Shutting down $NAME: "
|
echo -n $"Shutting down $NAME: "
|
||||||
su - emqx -c "ps -ef | grep -E '\-progname\s+$NAME\s' | awk '{print \$2}' | xargs kill -9"
|
su - emqx -c "ps -ef | grep -E '\-progname\s+$NAME\s' | awk '{print \$2}' | xargs kill -9"
|
||||||
for n in $(seq 1 10); do
|
for _ in $(seq 1 10); do
|
||||||
sleep 1
|
sleep 1
|
||||||
check_pid_status
|
check_pid_status
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
|
@ -133,7 +136,7 @@ case "$1" in
|
||||||
restart
|
restart
|
||||||
;;
|
;;
|
||||||
status)
|
status)
|
||||||
status -p $pidfile -l $(basename $lockfile) $NAME
|
status -p $pidfile -l "$(basename $lockfile)" $NAME
|
||||||
;;
|
;;
|
||||||
ping)
|
ping)
|
||||||
$DAEMON ping || exit $?
|
$DAEMON ping || exit $?
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
{erl_opts, [warn_unused_vars,warn_shadow_vars,warn_unused_import,
|
{erl_opts, [warn_unused_vars,warn_shadow_vars,warn_unused_import,
|
||||||
warn_obsolete_guard,compressed]}.
|
warn_obsolete_guard,compressed]}.
|
||||||
|
|
||||||
{overrides,[{add,[{erl_opts,[compressed,deterministic]}]}
|
{overrides,[{add,[{extra_src_dirs, [{"etc", [{recursive,true}]}]}]}
|
||||||
,{add,[{extra_src_dirs, [{"etc", [{recursive,true}]}]}]}
|
|
||||||
]}.
|
]}.
|
||||||
{extra_src_dirs, [{"etc", [{recursive,true}]}]}.
|
{extra_src_dirs, [{"etc", [{recursive,true}]}]}.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
do(Dir, CONFIG) ->
|
do(Dir, CONFIG) ->
|
||||||
ok = compile_and_load_pase_transforms(Dir),
|
ok = compile_and_load_pase_transforms(Dir),
|
||||||
dump(deps(CONFIG) ++ dialyzer(CONFIG) ++ config()).
|
dump(deps(CONFIG) ++ dialyzer(CONFIG) ++ coveralls() ++ config()).
|
||||||
|
|
||||||
bcrypt() ->
|
bcrypt() ->
|
||||||
{bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {branch, "0.6.0"}}}.
|
{bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {branch, "0.6.0"}}}.
|
||||||
|
@ -27,28 +27,37 @@ plugins() ->
|
||||||
{er_coap_client, {git, "https://github.com/emqx/er_coap_client", {tag, "v1.0"}}}
|
{er_coap_client, {git, "https://github.com/emqx/er_coap_client", {tag, "v1.0"}}}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
test_plugins() ->
|
||||||
|
[ rebar3_proper,
|
||||||
|
{coveralls, {git, "https://github.com/emqx/coveralls-erl", {branch, "github"}}}
|
||||||
|
].
|
||||||
|
|
||||||
test_deps() ->
|
test_deps() ->
|
||||||
[ {bbmustache, "1.10.0"}
|
[ {bbmustache, "1.10.0"}
|
||||||
, {emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {branch, "hocon"}}}
|
, {emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {branch, "hocon"}}}
|
||||||
, meck
|
, meck
|
||||||
].
|
].
|
||||||
|
|
||||||
|
default_compile_opts() ->
|
||||||
|
[compressed, deterministic, no_debug_info, warnings_as_errors, {parse_transform, mod_vsn}].
|
||||||
|
|
||||||
profiles() ->
|
profiles() ->
|
||||||
[ {'emqx', [ {erl_opts, [no_debug_info, warnings_as_errors, {parse_transform, mod_vsn}]}
|
[ {'emqx', [ {erl_opts, default_compile_opts()}
|
||||||
, {relx, relx('emqx')}
|
, {relx, relx('emqx')}
|
||||||
]}
|
]}
|
||||||
, {'emqx-pkg', [ {erl_opts, [no_debug_info, warnings_as_errors, {parse_transform, mod_vsn}]}
|
, {'emqx-pkg', [ {erl_opts, default_compile_opts()}
|
||||||
, {relx, relx('emqx-pkg')}
|
, {relx, relx('emqx-pkg')}
|
||||||
]}
|
]}
|
||||||
, {'emqx-edge', [ {erl_opts, [no_debug_info, warnings_as_errors, {parse_transform, mod_vsn}]}
|
, {'emqx-edge', [ {erl_opts, default_compile_opts()}
|
||||||
, {relx, relx('emqx-edge')}
|
, {relx, relx('emqx-edge')}
|
||||||
]}
|
]}
|
||||||
, {'emqx-edge-pkg', [ {erl_opts, [no_debug_info, warnings_as_errors, {parse_transform, mod_vsn}]}
|
, {'emqx-edge-pkg', [ {erl_opts, default_compile_opts()}
|
||||||
, {relx, relx('emqx-edge-pkg')}
|
, {relx, relx('emqx-edge-pkg')}
|
||||||
]}
|
]}
|
||||||
, {check, [ {erl_opts, [debug_info, warnings_as_errors, {parse_transform, mod_vsn}]}
|
, {check, [ {erl_opts, [debug_info, warnings_as_errors, {parse_transform, mod_vsn}]}
|
||||||
]}
|
]}
|
||||||
, {test, [ {deps, test_deps()}
|
, {test, [ {deps, test_deps()}
|
||||||
|
, {plugins, test_plugins()}
|
||||||
, {erl_opts, [debug_info, {parse_transform, mod_vsn}] ++ erl_opts_i()}
|
, {erl_opts, [debug_info, {parse_transform, mod_vsn}] ++ erl_opts_i()}
|
||||||
]}
|
]}
|
||||||
].
|
].
|
||||||
|
@ -146,7 +155,6 @@ relx_plugin_apps_per_rel(cloud) ->
|
||||||
, emqx_exproto
|
, emqx_exproto
|
||||||
, emqx_prometheus
|
, emqx_prometheus
|
||||||
, emqx_psk_file
|
, emqx_psk_file
|
||||||
, emqx_plugin_template
|
|
||||||
];
|
];
|
||||||
relx_plugin_apps_per_rel(edge) ->
|
relx_plugin_apps_per_rel(edge) ->
|
||||||
[].
|
[].
|
||||||
|
@ -295,6 +303,26 @@ dialyzer(Config) ->
|
||||||
Config
|
Config
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
coveralls() ->
|
||||||
|
case {os:getenv("GITHUB_ACTIONS"), os:getenv("GITHUB_TOKEN")} of
|
||||||
|
{"true", Token} when is_list(Token) ->
|
||||||
|
Cfgs = [{coveralls_repo_token, Token},
|
||||||
|
{coveralls_service_job_id, os:getenv("GITHUB_RUN_ID")},
|
||||||
|
{coveralls_commit_sha, os:getenv("GITHUB_SHA")},
|
||||||
|
{coveralls_service_number, os:getenv("GITHUB_RUN_NUMBER")},
|
||||||
|
{coveralls_coverdata, "_build/test/cover/*.coverdata"},
|
||||||
|
{coveralls_service_name, "github"}],
|
||||||
|
case os:getenv("GITHUB_EVENT_NAME") =:= "pull_request"
|
||||||
|
andalso string:tokens(os:getenv("GITHUB_REF"), "/") of
|
||||||
|
[_, "pull", PRNO, _] ->
|
||||||
|
[{coveralls_service_pull_request, PRNO} | Cfgs];
|
||||||
|
_ ->
|
||||||
|
Cfgs
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
end.
|
||||||
|
|
||||||
list_dir(Dir) ->
|
list_dir(Dir) ->
|
||||||
{ok, Names} = file:list_dir(Dir),
|
{ok, Names} = file:list_dir(Dir),
|
||||||
[list_to_atom(Name) || Name <- Names, filelib:is_dir(filename:join([Dir, Name]))].
|
[list_to_atom(Name) || Name <- Names, filelib:is_dir(filename:join([Dir, Name]))].
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
target_files=()
|
||||||
|
while IFS='' read -r line; do target_files+=("$line"); done < <(grep -r -l --exclude-dir=.git --exclude-dir=_build "#!/bin/" .)
|
||||||
|
return_code=0
|
||||||
|
for i in "${target_files[@]}"; do
|
||||||
|
echo checking "$i" ...
|
||||||
|
if ! shellcheck "$i"; then
|
||||||
|
return_code=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $return_code
|
|
@ -39,8 +39,8 @@ docker run -d -t --restart=always --name "$NODE1" \
|
||||||
-e EMQX_NODE_COOKIE="$COOKIE" \
|
-e EMQX_NODE_COOKIE="$COOKIE" \
|
||||||
-e WAIT_FOR_ERLANG=60 \
|
-e WAIT_FOR_ERLANG=60 \
|
||||||
-p 18083:18083 \
|
-p 18083:18083 \
|
||||||
-v $PROJ_DIR/_build/emqx/rel/emqx:/built \
|
-v "$PROJ_DIR"/_build/emqx/rel/emqx:/built \
|
||||||
$IMAGE sh -c 'cp -r /built /emqx && /emqx/bin/emqx console'
|
"$IMAGE" sh -c 'cp -r /built /emqx && /emqx/bin/emqx console'
|
||||||
|
|
||||||
docker run -d -t --restart=always --name "$NODE2" \
|
docker run -d -t --restart=always --name "$NODE2" \
|
||||||
--net "$NET" \
|
--net "$NET" \
|
||||||
|
@ -48,8 +48,8 @@ docker run -d -t --restart=always --name "$NODE2" \
|
||||||
-e EMQX_NODE_COOKIE="$COOKIE" \
|
-e EMQX_NODE_COOKIE="$COOKIE" \
|
||||||
-e WAIT_FOR_ERLANG=60 \
|
-e WAIT_FOR_ERLANG=60 \
|
||||||
-p 18084:18083 \
|
-p 18084:18083 \
|
||||||
-v $PROJ_DIR/_build/emqx/rel/emqx:/built \
|
-v "$PROJ_DIR"/_build/emqx/rel/emqx:/built \
|
||||||
$IMAGE sh -c 'cp -r /built /emqx && /emqx/bin/emqx console'
|
"$IMAGE" sh -c 'cp -r /built /emqx && /emqx/bin/emqx console'
|
||||||
|
|
||||||
wait (){
|
wait (){
|
||||||
container="$1"
|
container="$1"
|
||||||
|
|
21
sync-apps.sh
21
sync-apps.sh
|
@ -21,7 +21,6 @@ apps=(
|
||||||
"emqx_lua_hook"
|
"emqx_lua_hook"
|
||||||
"emqx_lwm2m"
|
"emqx_lwm2m"
|
||||||
"emqx_management"
|
"emqx_management"
|
||||||
"emqx_plugin_template"
|
|
||||||
"emqx_prometheus"
|
"emqx_prometheus"
|
||||||
"emqx_psk_file"
|
"emqx_psk_file"
|
||||||
"emqx_recon"
|
"emqx_recon"
|
||||||
|
@ -43,12 +42,14 @@ mkdir -p tmp/
|
||||||
download_zip() {
|
download_zip() {
|
||||||
local app="$1"
|
local app="$1"
|
||||||
local ref="$2"
|
local ref="$2"
|
||||||
local vsn="$(echo "$ref" | tr '/' '-')"
|
local vsn
|
||||||
|
vsn="$(echo "$ref" | tr '/' '-')"
|
||||||
local file="tmp/${app}-${vsn}.zip"
|
local file="tmp/${app}-${vsn}.zip"
|
||||||
if [ -f "$file" ] && [ "$force" != "force" ]; then
|
if [ -f "$file" ] && [ "$force" != "force" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
local repo="$(echo "$app" | sed 's#_#-#g')"
|
local repo
|
||||||
|
repo=${app//_/-}
|
||||||
local url="https://github.com/emqx/$repo/archive/$ref.zip"
|
local url="https://github.com/emqx/$repo/archive/$ref.zip"
|
||||||
echo "downloading ${url}"
|
echo "downloading ${url}"
|
||||||
curl -fLsS -o "$file" "$url"
|
curl -fLsS -o "$file" "$url"
|
||||||
|
@ -56,7 +57,7 @@ download_zip() {
|
||||||
|
|
||||||
default_vsn="dev/v4.3.0"
|
default_vsn="dev/v4.3.0"
|
||||||
download_zip "emqx_auth_mnesia" "e4.2.3"
|
download_zip "emqx_auth_mnesia" "e4.2.3"
|
||||||
for app in ${apps[@]}; do
|
for app in "${apps[@]}"; do
|
||||||
download_zip "$app" "$default_vsn"
|
download_zip "$app" "$default_vsn"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -64,7 +65,8 @@ extract_zip(){
|
||||||
local app="$1"
|
local app="$1"
|
||||||
local ref="$2"
|
local ref="$2"
|
||||||
local vsn_arg="${3:-}"
|
local vsn_arg="${3:-}"
|
||||||
local vsn_dft="$(echo "$ref" | tr '/' '-')"
|
local vsn_dft
|
||||||
|
vsn_dft="$(echo "$ref" | tr '/' '-')"
|
||||||
local vsn
|
local vsn
|
||||||
if [ -n "$vsn_arg" ]; then
|
if [ -n "$vsn_arg" ]; then
|
||||||
vsn="$vsn_arg"
|
vsn="$vsn_arg"
|
||||||
|
@ -72,14 +74,15 @@ extract_zip(){
|
||||||
vsn="$vsn_dft"
|
vsn="$vsn_dft"
|
||||||
fi
|
fi
|
||||||
local file="tmp/${app}-${vsn_dft}.zip"
|
local file="tmp/${app}-${vsn_dft}.zip"
|
||||||
local repo="$(echo "$app" | sed 's#_#-#g')"
|
local repo
|
||||||
|
repo=${app//_/-}
|
||||||
rm -rf "apps/${app}/"
|
rm -rf "apps/${app}/"
|
||||||
unzip "$file" -d apps/
|
unzip "$file" -d apps/
|
||||||
mv "apps/${repo}-${vsn}/" "apps/$app/"
|
mv "apps/${repo}-${vsn}/" "apps/$app/"
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_zip "emqx_auth_mnesia" "e4.2.3" "e4.2.3"
|
extract_zip "emqx_auth_mnesia" "e4.2.3" "e4.2.3"
|
||||||
for app in ${apps[@]}; do
|
for app in "${apps[@]}"; do
|
||||||
extract_zip "$app" "$default_vsn"
|
extract_zip "$app" "$default_vsn"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -95,6 +98,6 @@ cleanup_app(){
|
||||||
}
|
}
|
||||||
|
|
||||||
apps+=( "emqx_auth_mnesia" )
|
apps+=( "emqx_auth_mnesia" )
|
||||||
for app in ${apps[@]}; do
|
for app in "${apps[@]}"; do
|
||||||
cleanup_app $app
|
cleanup_app "$app"
|
||||||
done
|
done
|
||||||
|
|
Loading…
Reference in New Issue