sysc release-4.2¡°

This commit is contained in:
U-JOHNLIU\jonhl 2021-05-14 07:28:48 +08:00
parent 564e820cb4
commit 0a39405e1b
67 changed files with 3543 additions and 1831 deletions

164
.ci/deps_tests/boot.py Normal file
View File

@ -0,0 +1,164 @@
#!/usr/bin/python
##
import os
import sys
import re
from bs4 import BeautifulSoup
## get all test catalog
def get_test_all_catalog(name):
CatalogList = []
PackageNameList = []
filepath = os.path.join(os.getcwd(), name)
packagenames = os.listdir(name)
for packagename in packagenames:
tmp_path = os.path.join(filepath, packagename)
if os.path.isdir(tmp_path):
CatalogList.append(tmp_path)
PackageNameList.append(packagename)
return CatalogList, PackageNameList
## Start Galaxy Engine
## Save index. d by extracting important information from index.html.
## extract index.html and deal with path information in index.html
def extract_core_content(path, filename, packagename):
filepath = os.path.join(path, filename)
if os.path.exists(filepath):
fopen = open(filepath)
filecontent = fopen.read()
original_core_content = re.findall(r"<\s*body[^>]*>(.+?)<div class=\"copyright\">Copyright", filecontent, re.S)
content = original_core_content[0]
core_content = content.replace('<a href=\"', '<a href=\"'+packagename+"\\")
## change title
core_content = core_content.replace('Test Results', packagename + ' Test Results')
return core_content
def replace_href(path, filename, packagename):
filepath = os.path.join(path, filename)
if os.path.exists(filepath):
fopen = open(filepath)
filecontent = fopen.read()
re_data = re.compile(r"<div class=\"copyright\">Copyright(.+?)<\s*/\s*html\s*>", re.S)
original_core_content = re_data.sub('', filecontent)
replacecontent = original_core_content.replace('<a href=\"', '<a href=\"'+packagename+"\\")
replacecontent = replacecontent.replace('<link rel=\"stylesheet\" href=\"', '<link rel=\"stylesheet\" href=\"'+packagename+"\\")
replacecontent = replacecontent.replace('<script type=\"text/javascript\" src=\"', '<script type=\"text/javascript\" src=\"'+packagename+"\\")
replacecontent = replacecontent.replace('Test Results', packagename + ' Test Results')
ra_title = re.compile("<title>(.+?)</title>", re.S)
replacecontent = ra_title.sub('<title> Test Result </title>', replacecontent)
return replacecontent
# Splicing content
def splicing_content(name, filename):
CoreContent = []
index = 0,
CatalogList, PackageNameList = get_test_all_catalog(name)
for catalog, packageName in zip(CatalogList, PackageNameList):
if(index == (0,)):
Content = replace_href(catalog, filename, packageName)
CoreContent.append(Content)
index = 1
else:
Content = extract_core_content(catalog, filename, packageName)
CoreContent.append(Content)
str = ""
con = str.join('%s' % id for id in CoreContent)
con = con + "</body></html>"
return con
## process data statistics
def data_statistics(filestream):
soup_string = BeautifulSoup(filestream, "html.parser")
body_datas = soup_string.find_all("tbody")
testpluginList = []
testmoudleList = []
testsuccessList = []
testfailList = []
testskipList = []
allsuccessValue = allfailValue = allSkipValue = 0
for body_data in body_datas:
## test moudle data
# testmoudledata = body_data.find_all("a")
testplugindata = body_data.find_all("tr")
for testplugin in testplugindata:
data = testplugin.find_all("td")
testpluginname = data[8]
con = testpluginname.find("a")['href']
re_data = re.compile(r"\\ct_run(.+?).html", re.S)
re_data = re_data.sub('', con)
testpluginList.append(str(re_data))
testmoudledata = testplugin.find_all("a")[0]
testmoudleList.append(testmoudledata)
successdata = data[3]
testsuccessList.append(successdata)
faildata = data[4]
testfailList.append(faildata)
skipdata = data[5]
testskipList.append(skipdata)
## get all value
testallvalues = soup_string.find_all("tfoot")
for testallvalue in testallvalues:
data = testallvalue.find_all("td")
allsuccessValue += int(data[3].string)
allfailValue += int(data[4].string)
datas = str(data[5].string)
re_skipdata = re.compile("(.+?)/", re.S)
datas = str(re_skipdata.sub('', datas)).replace(")", "")
allSkipValue += int(datas)
tbody = ""
table_head = "<center><h1>Data Outline</h1></center><br /><center><table id=\"SortableTable\"\><thead><tr><th>Test Name</th><th>Success</th><th>Failed</th><th>Skiped</th><th>Plugin Name</th></tr></thead>"
for testplugin, testmoudle, testsuccess, testfail, testskip in zip(testpluginList, testmoudleList, testsuccessList, testfailList, testskipList):
moudlebody = "<tbody><tr><td>{}</td>".format(testmoudle)
successbody = "{}".format(testsuccess)
failbody = "{}".format(testfail)
skipbody = "{}".format(testskip)
pluginbody = "<td>{}</td></tr></tbody>".format(testplugin)
tbody += str(moudlebody) + str(successbody) +str(failbody) + str(skipbody) + str(pluginbody)
totalbody = "<tfoot><tr><td><b>Total</b></td><td>{}</td><td><font color=\"red\">{}</font></td><td><font color=\"green\">{}</font></td><td>&nbsp;</td></tr></tfoot></table>".format(allsuccessValue, allfailValue, allSkipValue)
outline_head = "<center><h1>Executing Plugin Name</h1></center><br /><center><table id=\"SortableTable\"\><thead><tr><th>All Test Plugin Name</th><th>Success extract Log plugin name</th><th>Empty plugin name</th></tr></thead>"
catalogList, packageNameList = get_test_all_catalog("logs")
successPluginData = ""
failedPluginData = ""
for catalog, packagename in zip(catalogList, packageNameList):
successPlugin, failedPlugin = outline_value(catalog, packagename)
successPluginData += successPlugin + " "
failedPluginData += failedPlugin +" "
outline_body_value = "<tbody><tfoot><tr><td>{}</td><td>{}</td><td><font color=\"red\">{}<font></td></tr></tfoot></tbody></table>".format(packageNameList, successPluginData, failedPluginData)
data_outline_html = outline_head + outline_body_value + table_head + tbody + totalbody
return data_outline_html, allfailValue
def outline_value(path, pluginName):
filepath = os.path.join(path, "index.html")
successPlugin = ""
failedPlugin = ""
if os.path.exists(filepath):
successPlugin = pluginName
else:
failedPlugin = pluginName
return successPlugin, failedPlugin
def produceHtml():
htmldata = splicing_content("logs", "index.html")
data_outline_html, allfailValue = data_statistics(htmldata)
headdatamatch = re.match(r"<!DOCTYPE(.+?)<\s*body[^>]*>", htmldata, re.S)
headdata = ""
if headdatamatch:
headdata = headdatamatch.group()
# re_data = re.compile(r"<!DOCTYPE (.+?)<\s*body[^>]*>", re.S)
replacedata = headdata + data_outline_html
htmldata = htmldata.replace(headdata, replacedata)
savepath = os.path.join(os.getcwd(), "logs")
savepath = os.path.join(savepath, "index.html")
if os.path.exists(savepath):
os.remove(savepath)
f = open(savepath, 'w')
f.write(htmldata)
f.close
## send exit message when failed
if allfailValue >0 :
exit(1)
# htmldata = splicing_content("logs", "index.html")
# data_statistics(htmldata)
produceHtml()

View File

@ -0,0 +1,101 @@
version: '3'
services:
nginx:
build: ./emqx-nginx
image: emqx-nginx:1.15
restart: always
ports:
- "18080:80"
networks:
- emqx-bridge
volumes:
- ../../tests/logs:/usr/share/nginx/html
emqx:
build: ./emqx-erlang
image: emqx-erlang
depends_on:
- mysql_server
- redis_server
- mongo_server
- pgsql_server
- ldap_server
networks:
- emqx-bridge
volumes:
- ../../.:/emqx-rel
tty: true
python:
image: python:3.7.2
networks:
- emqx-bridge
volumes:
- ../../.:/emqx-rel
tty: true
mysql_server:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: public
MYSQL_DATABASE: mqtt
volumes:
- ../../_build/emqx/lib/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/ca.pem:/etc/certs/ca-cert.pem
- ../../_build/emqx/lib/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-cert.pem:/etc/certs/server-cert.pem
- ../../_build/emqx/lib/emqx_auth_mysql/test/emqx_auth_mysql_SUITE_data/server-key.pem:/etc/certs/server-key.pem
networks:
- emqx-bridge
command:
--bind-address 0.0.0.0
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
--skip-symbolic-links
--ssl-ca=/etc/certs/ca.pem
--ssl-cert=/etc/certs/server-cert.pem
--ssl-key=/etc/certs/server-key.pem
redis_server:
build: ./emqx-redis
image: emqx-redis:5
restart: always
networks:
- emqx-bridge
mongo_server:
image: mongo:4.1
restart: always
environment:
MONGO_INITDB_DATABASE: mqtt
networks:
- emqx-bridge
command: --bind_ip_all
pgsql_server:
image: postgres:11
restart: always
environment:
POSTGRES_PASSWORD: public
POSTGRES_USER: root
POSTGRES_DB: mqtt
networks:
- emqx-bridge
ldap_server:
build: ./emqx-ldap
image: emqx-ldap:1.0
restart: always
networks:
- emqx-bridge
networks:
emqx-bridge:
driver: bridge
volumes:
logs-volumes:

View File

@ -0,0 +1,15 @@
FROM erlang:22.3
# RUN curl -L -o /tmp/openjdk-14.0.1_linux-x64_bin.tar.gz https://download.java.net/java/GA/jdk14.0.1/664493ef4a6946b186ff29eb326336a2/7/GPL/openjdk-14.0.1_linux-x64_bin.tar.gz \
# && tar xvf /tmp/openjdk-14.0.1_linux-x64_bin.tar.gz -C /usr/local
# ENV PATH=/usr/local/jdk-14.0.1/bin:$PATH
RUN wget --no-cookies \
--no-check-certificate \
--header "Cookie: oraclelicense=accept-securebackup-cookie" \
https://download.oracle.com/otn-pub/java/jdk/8u251-b08/3d5a2bb8f8d4428bbe94aed7ec7ae784/jdk-8u251-linux-x64.tar.gz \
-O /tmp/jdk-8u251-linux-x64.tar.gz \
&& tar xvf /tmp/jdk-8u251-linux-x64.tar.gz -C /usr/local
ENV PATH=/usr/local/jdk1.8.0_251/bin:$PATH

View File

@ -0,0 +1,22 @@
FROM buildpack-deps:stretch
ENV VERSION=2.4.47
RUN apt-get update && apt-get install -y groff groff-base
RUN wget ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-${VERSION}.tgz \
&& gunzip -c openldap-${VERSION}.tgz | tar xvfB - \
&& cd openldap-${VERSION} \
&& ./configure && make depend && make && make install \
&& cd .. && rm -rf openldap-${VERSION}
COPY slapd.conf /usr/local/etc/openldap/slapd.conf
COPY schema/emqx.io.ldif /usr/local/etc/openldap/schema/emqx.io.ldif
COPY schema/emqx.schema /usr/local/etc/openldap/schema/emqx.schema
RUN mkdir -p /usr/local/etc/openldap/data \
&& slapadd -l /usr/local/etc/openldap/schema/emqx.io.ldif -f /usr/local/etc/openldap/slapd.conf
WORKDIR /usr/local/etc/
EXPOSE 389
CMD [ "/usr/local/libexec/slapd", "-d", "3" ]

View File

@ -0,0 +1,132 @@
## create emqx.io
dn:dc=emqx,dc=io
objectclass: top
objectclass: dcobject
objectclass: organization
dc:emqx
o:emqx,Inc.
# create testdevice.emqx.io
dn:ou=testdevice,dc=emqx,dc=io
objectClass: top
objectclass:organizationalUnit
ou:testdevice
# create user admin
dn:uid=admin,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: simpleSecurityObject
objectClass: account
userPassword:: e1NIQX1XNnBoNU1tNVB6OEdnaVVMYlBnekczN21qOWc9
uid: admin
## create user=mqttuser0001,
# password=mqttuser0001,
# passhash={SHA}mlb3fat40MKBTXUVZwCKmL73R/0=
# base64passhash=e1NIQX1tbGIzZmF0NDBNS0JUWFVWWndDS21MNzNSLzA9
dn:uid=mqttuser0001,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
objectClass: mqttDevice
objectClass: mqttSecurity
uid: mqttuser0001
isEnabled: TRUE
mqttPublishTopic: mqttuser0001/pub/1
mqttPublishTopic: mqttuser0001/pub/+
mqttPublishTopic: mqttuser0001/pub/#
mqttSubscriptionTopic: mqttuser0001/sub/1
mqttSubscriptionTopic: mqttuser0001/sub/+
mqttSubscriptionTopic: mqttuser0001/sub/#
mqttPubSubTopic: mqttuser0001/pubsub/1
mqttPubSubTopic: mqttuser0001/pubsub/+
mqttPubSubTopic: mqttuser0001/pubsub/#
userPassword:: e1NIQX1tbGIzZmF0NDBNS0JUWFVWWndDS21MNzNSLzA9
## create user=mqttuser0002
# password=mqttuser0002,
# passhash={SSHA}n9XdtoG4Q/TQ3TQF4Y+khJbMBH4qXj4M
# base64passhash=e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0=
dn:uid=mqttuser0002,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
objectClass: mqttDevice
objectClass: mqttSecurity
uid: mqttuser0002
isEnabled: TRUE
mqttPublishTopic: mqttuser0002/pub/1
mqttPublishTopic: mqttuser0002/pub/+
mqttPublishTopic: mqttuser0002/pub/#
mqttSubscriptionTopic: mqttuser0002/sub/1
mqttSubscriptionTopic: mqttuser0002/sub/+
mqttSubscriptionTopic: mqttuser0002/sub/#
mqttPubSubTopic: mqttuser0002/pubsub/1
mqttPubSubTopic: mqttuser0002/pubsub/+
mqttPubSubTopic: mqttuser0002/pubsub/#
userPassword:: e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0=
## create user mqttuser0003
# password=mqttuser0003,
# passhash={MD5}ybsPGoaK3nDyiQvveiCOIw==
# base64passhash=e01ENX15YnNQR29hSzNuRHlpUXZ2ZWlDT0l3PT0=
dn:uid=mqttuser0003,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
objectClass: mqttDevice
objectClass: mqttSecurity
uid: mqttuser0003
isEnabled: TRUE
mqttPublishTopic: mqttuser0003/pub/1
mqttPublishTopic: mqttuser0003/pub/+
mqttPublishTopic: mqttuser0003/pub/#
mqttSubscriptionTopic: mqttuser0003/sub/1
mqttSubscriptionTopic: mqttuser0003/sub/+
mqttSubscriptionTopic: mqttuser0003/sub/#
mqttPubSubTopic: mqttuser0003/pubsub/1
mqttPubSubTopic: mqttuser0003/pubsub/+
mqttPubSubTopic: mqttuser0003/pubsub/#
userPassword:: e01ENX15YnNQR29hSzNuRHlpUXZ2ZWlDT0l3PT0=
## create user mqttuser0004
# password=mqttuser0004,
# passhash={MD5}2Br6pPDSEDIEvUlu9+s+MA==
# base64passhash=e01ENX0yQnI2cFBEU0VESUV2VWx1OStzK01BPT0=
dn:uid=mqttuser0004,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
objectClass: mqttDevice
objectClass: mqttSecurity
uid: mqttuser0004
isEnabled: TRUE
mqttPublishTopic: mqttuser0004/pub/1
mqttPublishTopic: mqttuser0004/pub/+
mqttPublishTopic: mqttuser0004/pub/#
mqttSubscriptionTopic: mqttuser0004/sub/1
mqttSubscriptionTopic: mqttuser0004/sub/+
mqttSubscriptionTopic: mqttuser0004/sub/#
mqttPubSubTopic: mqttuser0004/pubsub/1
mqttPubSubTopic: mqttuser0004/pubsub/+
mqttPubSubTopic: mqttuser0004/pubsub/#
userPassword: {MD5}2Br6pPDSEDIEvUlu9+s+MA==
## create user mqttuser0005
# password=mqttuser0005,
# passhash={SHA}jKnxeEDGR14kE8AR7yuVFOelhz4=
# base64passhash=e1NIQX1qS254ZUVER1IxNGtFOEFSN3l1VkZPZWxoejQ9
objectClass: top
dn:uid=mqttuser0005,ou=testdevice,dc=emqx,dc=io
objectClass: mqttUser
objectClass: mqttDevice
objectClass: mqttSecurity
uid: mqttuser0005
isEnabled: TRUE
mqttPublishTopic: mqttuser0005/pub/1
mqttPublishTopic: mqttuser0005/pub/+
mqttPublishTopic: mqttuser0005/pub/#
mqttSubscriptionTopic: mqttuser0005/sub/1
mqttSubscriptionTopic: mqttuser0005/sub/+
mqttSubscriptionTopic: mqttuser0005/sub/#
mqttPubSubTopic: mqttuser0005/pubsub/1
mqttPubSubTopic: mqttuser0005/pubsub/+
mqttPubSubTopic: mqttuser0005/pubsub/#
userPassword: {SHA}jKnxeEDGR14kE8AR7yuVFOelhz4=

View File

@ -0,0 +1,40 @@
#
# Preliminary Apple OS X Native LDAP Schema
# This file is subject to change.
#
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.1.3 NAME 'isEnabled'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.1 NAME ( 'mqttPublishTopic' 'mpt' )
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.2 NAME ( 'mqttSubscriptionTopic' 'mst' )
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.3 NAME ( 'mqttPubSubTopic' 'mpst' )
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
USAGE userApplications )
objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4 NAME 'mqttUser'
AUXILIARY
MAY ( mqttPublishTopic $ mqttSubscriptionTopic $ mqttPubSubTopic) )
objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.2 NAME 'mqttDevice'
SUP top
STRUCTURAL
MUST ( uid )
MAY ( isEnabled ) )
objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.3 NAME 'mqttSecurity'
SUP top
AUXILIARY
MAY ( userPassword $ userPKCS12 $ pwdAttribute $ pwdLockout ) )

View File

@ -0,0 +1,12 @@
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
include /usr/local/etc/openldap/schema/ppolicy.schema
include /usr/local/etc/openldap/schema/emqx.schema
database bdb
suffix "dc=emqx,dc=io"
rootdn "cn=root,dc=emqx,dc=io"
rootpw {SSHA}eoF7NhNrejVYYyGHqnt+MdKNBh4r1w3W
directory /usr/local/etc/openldap/data

View File

@ -0,0 +1,2 @@
FROM nginx:1.15
COPY default.conf /etc/nginx/conf.d/default.conf

View File

@ -0,0 +1,46 @@
server {
listen 80;
server_name localhost;
autoindex on;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}

View File

@ -0,0 +1,3 @@
FROM redis:5
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

File diff suppressed because it is too large Load Diff

1
.ci/paho_tests/.env Normal file
View File

@ -0,0 +1 @@
IMAGE=emqx/emqx:latest

54
.ci/paho_tests/Makefile Normal file
View File

@ -0,0 +1,54 @@
## default globals
TARGET ?= emqx/emqx
EMQX_NAME = $(subst emqx/,,$(TARGET))
## versioning
EMQX_DEPS_DEFAULT_VSN ?= develop
PAHO_BRANCH ?= develop-4.0
.PHONY: all
all: test
define wait_emqx
@while [ "$$(docker inspect -f '{{ .State.Health.Status}}' $$(docker ps -a -q -f name=paho_test_emqx1))" != "healthy" ] || [ "$$(docker inspect -f '{{ .State.Health.Status}}' $$(docker ps -a -q -f name=paho_test_emqx2))" != "healthy" ]; do \
if [ $$(docker ps -a -f name=paho_test_emqx -f status=exited -q | wc -l) -ne 0 ]; then \
echo "['$$(date -u +"%Y-%m-%dT%H:%M:%SZ")']:emqx stop"; \
exit; \
else \
echo "['$$(date -u +"%Y-%m-%dT%H:%M:%SZ")']:waiting emqx"; \
sleep 5; \
fi; \
done
endef
.PHONY: create_container
create_container: clean
@sed -i "/IMAGE=/c\IMAGE=$(TARGET):$(EMQX_DEPS_DEFAULT_VSN:v%=%)" .env
@docker-compose -p paho_test up -d
$(call wait_emqx)
.PHONY: test
test: create_container
@docker exec -i $$(docker ps -a -q -f name=paho_test_client) sh -c "apk update && apk add git curl \
&& git clone -b $(PAHO_BRANCH) https://hub.fastgit.org/emqx/paho.mqtt.testing.git /paho.mqtt.testing \
&& pip install pytest \
&& pytest -v /paho.mqtt.testing/interoperability/test_client/ --host node1.emqx.io"
@docker-compose -p paho_test down
.PHONY: cluster_test
cluster_test: create_container
@docker exec -i $$(docker ps -a -q -f name=paho_test_client) sh -c "apk update && apk add git curl \
&& git clone -b $(PAHO_BRANCH) https://hub.fastgit.org/emqx/paho.mqtt.testing.git /paho.mqtt.testing \
&& pip install pytest \
&& pytest -v /paho.mqtt.testing/interoperability/test_client/V5/test_connect.py -k test_basic --host node1.emqx.io \
&& pytest -v /paho.mqtt.testing/interoperability/test_cluster --host1 node1.emqx.io --host2 node2.emqx.io"
@docker-compose -p paho_test down
.PHONY: clean
clean:
@if [ ! -z "$$(docker ps -a -q -f name=paho_test)" ]; then docker-compose -p paho_test down; fi

View File

@ -0,0 +1,65 @@
version: '3'
services:
emqx1:
image: ${IMAGE}
environment:
- "EMQX_NAME=emqx"
- "EMQX_HOST=node1.emqx.io"
- "EMQX_CLUSTER__DISCOVERY=static"
- "EMQX_CLUSTER__STATIC__SEEDS=emqx@node1.emqx.io, emqx@node2.emqx.io"
- "EMQX_ZONE__EXTERNAL__RETRY_INTERVAL=2s"
- "EMQX_MQTT__MAX_TOPIC_ALIAS=10"
command:
- /bin/sh
- -c
- |
sed -i "s 127.0.0.1 $$(ip route show |grep "link" |awk '{print $$1}') g" /opt/emqx/etc/acl.conf
/usr/bin/start.sh
healthcheck:
test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"]
interval: 5s
timeout: 25s
retries: 5
networks:
emqx-bridge:
aliases:
- node1.emqx.io
emqx2:
image: ${IMAGE}
environment:
- "EMQX_NAME=emqx"
- "EMQX_HOST=node2.emqx.io"
- "EMQX_CLUSTER__DISCOVERY=static"
- "EMQX_CLUSTER__STATIC__SEEDS=emqx@node1.emqx.io, emqx@node2.emqx.io"
- "EMQX_ZONE__EXTERNAL__RETRY_INTERVAL=2s"
- "EMQX_MQTT__MAX_TOPIC_ALIAS=10"
command:
- /bin/sh
- -c
- |
sed -i "s 127.0.0.1 $$(ip route show |grep "link" |awk '{print $$1}') g" /opt/emqx/etc/acl.conf
/usr/bin/start.sh
healthcheck:
test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"]
interval: 5s
timeout: 25s
retries: 5
networks:
emqx-bridge:
aliases:
- node2.emqx.io
client:
image: python:3.7.2-alpine3.9
depends_on:
- emqx1
- emqx2
tty: true
networks:
emqx-bridge:
networks:
emqx-bridge:
driver: bridge

32
.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
.eunit
deps
*.o
*.beam
*.plt
erl_crash.dump
rebar3.crashdump
ebin
_rel/*
.concrete/DEV_MODE
.rebar
.erlang.mk/
etc/plugins/
data/configs/*.config
data/configs/*.conf
data/configs/*.args
rel/
log/
ct/logs/*
.DS_Store
.idea/
*.d
*.iml
vars.config
erlang.mk
_build
rebar.lock
test/
_checkouts
_packages
deploy/docker/tmp
.vscode/settings.json

2
.idea/.gitignore vendored
View File

@ -1,2 +0,0 @@
# Default ignored files
/workspace.xml

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/_build/default/plugins/rebar3_proper/priv/templates" />
</list>
</option>
</component>
</module>

View File

@ -1,9 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="Erlang 20" project-jdk-type="Erlang SDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="Erlang 21" project-jdk-type="Erlang SDK">
<output url="file://$PROJECT_DIR$/classes" />
</component>
</project>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/dgiot_server.iml" filepath="$PROJECT_DIR$/.idea/dgiot_server.iml" />
</modules>
</component>
</project>

View File

@ -2,51 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/default/plugins/pc" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/cowboy" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/cowlib" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/cuttlefish" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/cuttlefish/_build/default/lib/getopt" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/cuttlefish/_build/escript/lib/getopt" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/ekka" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_dashboard" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_delayed_publish" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_management" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_psk_file" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_recon" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_reloader" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_retainer" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/emqx_rule_engine" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/erlport" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/erlydtl" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/esockd" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/gen_rpc" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/goldrush" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/jesse" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/lager" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/minirest" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/poolboy" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/prometheus" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/ranch" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/rfc3339" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/rulesql" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_api" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_bridge" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_device_shadow" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_evidence" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_exproto" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_framework" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_group" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_license" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_mqtt" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_parse" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_public" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_statsd" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_task" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_td" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/shuwa_web_manager" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/ssl_verify_fun" vcs="Git" />
<mapping directory="$PROJECT_DIR$/_build/dgiot/lib/websocket_client" vcs="Git" />
</component>
</project>

View File

@ -178,7 +178,7 @@
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -3,22 +3,18 @@
REBAR_GIT_CLONE_OPTIONS += --depth 1
export REBAR_GIT_CLONE_OPTIONS
#TAG = $(shell git tag -l --points-at HEAD)
TAG = $(shell git tag -l --points-at HEAD)
TAG = v4.0.0
#CUR_BRANCH := $(shell git branch | grep -e "^*" | cut -d' ' -f 2)
#CUR_BRANCH := release-4.0
#ifeq ($(EMQX_DEPS_DEFAULT_VSN),)
# ifneq ($(TAG),)
EMQX_DEPS_DEFAULT_VSN ?= $(TAG)
# else
# EMQX_DEPS_DEFAULT_VSN ?= $(CUR_BRANCH)
# endif
#endif
CUR_BRANCH := $(shell git branch | grep -e "^*" | cut -d' ' -f 2)
EMQX_DEPS_DEFAULT_VSN = release-4.2
ifeq ($(EMQX_DEPS_DEFAULT_VSN),)
ifneq ($(TAG),)
EMQX_DEPS_DEFAULT_VSN ?= $(lastword 1, $(TAG))
else
EMQX_DEPS_DEFAULT_VSN ?= $(CUR_BRANCH)
endif
endif
REBAR = $(CURDIR)/rebar3
@ -26,11 +22,36 @@ REBAR_URL = https://s3.amazonaws.com/rebar3/rebar3
export EMQX_DEPS_DEFAULT_VSN
PROFILE ?= dgiot
PROFILES := dgiot dgiot-edge
PKG_PROFILES := dgiot-pkg dgiot-edge-pkg
PROFILE ?= emqx
PROFILES := emqx emqx-edge
PKG_PROFILES := emqx-pkg emqx-edge-pkg
CT_APPS := emqx_auth_jwt
CT_APPS := emqx \
emqx_auth_clientid \
emqx_auth_http \
emqx_auth_jwt \
emqx_auth_ldap \
emqx_auth_mongo \
emqx_auth_mysql \
emqx_auth_pgsql \
emqx_auth_redis \
emqx_auth_username \
emqx_auth_mnesia \
emqx_sasl \
emqx_coap \
emqx_recon \
emqx_dashboard \
emqx_delayed_publish \
emqx_lua_hook \
emqx_lwm2m \
emqx_management \
emqx_retainer \
emqx_sn \
emqx_stomp \
emqx_web_hook \
emqx_bridge_mqtt \
emqx_rule_engine \
emqx_extension_hook
.PHONY: default
default: $(REBAR) $(PROFILE)
@ -47,8 +68,9 @@ distclean:
.PHONY: $(PROFILES)
$(PROFILES:%=%): $(REBAR)
ifneq ($(OS),Windows_NT)
ln -snf _build/$(@)/lib ./_checkouts
@ln -snf _build/$(@)/lib ./_checkouts
endif
@if [ $$(echo $(@) |grep edge) ];then export EMQX_DESC="EMQ X Edge";else export EMQX_DESC="EMQ X Broker"; fi;\
$(REBAR) as $(@) release
.PHONY: $(PROFILES:%=build-%)
@ -93,7 +115,9 @@ checkout:
.PHONY: $(REBAR) $(CT_APPS:%=ct-%)
ct: $(CT_APPS:%=ct-%)
$(CT_APPS:%=ct-%): checkout-$(PROFILE)
$(REBAR) as $(PROFILE) ct --verbose --dir _checkouts/$(@:ct-%=%)/test --verbosity 50
-make -C _build/emqx/lib/$(@:ct-%=%) ct
@mkdir -p tests/logs/$(@:ct-%=%)
@if [ -d _build/emqx/lib/$(@:ct-%=%)/_build/test/logs ]; then cp -r _build/emqx/lib/$(@:ct-%=%)/_build/test/logs/* tests/logs/$(@:ct-%=%); fi
$(REBAR):
ifneq ($(wildcard rebar3),rebar3)
@ -105,6 +129,7 @@ endif
.PHONY: $(PKG_PROFILES)
$(PKG_PROFILES:%=%): $(REBAR)
ln -snf _build/$(@)/lib ./_checkouts
@if [ $$(echo $(@) |grep edge) ];then export EMQX_DESC="EMQ X Edge";else export EMQX_DESC="EMQ X Broker"; fi;\
$(REBAR) as $(@) release
EMQX_REL=$$(pwd) EMQX_BUILD=$(@) EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/packages
@ -112,36 +137,36 @@ $(PKG_PROFILES:%=%): $(REBAR)
.PHONY: $(PROFILES:%=%-docker-build)
$(PROFILES:%=%-docker-build):
@if [ ! -z `echo $(@) |grep -oE edge` ]; then \
TARGET=dgiot/dgiot-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker; \
TARGET=emqx/emqx-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker; \
else \
TARGET=dgiot/dgiot EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker; \
TARGET=emqx/emqx EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker; \
fi;
# Save docker images
.PHONY: $(PROFILES:%=%-docker-save)
$(PROFILES:%=%-docker-save):
@if [ ! -z `echo $(@) |grep -oE edge` ]; then \
TARGET=dgiot/dgiot-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker save; \
TARGET=emqx/emqx-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker save; \
else \
TARGET=dgiot/dgiot EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker save; \
TARGET=emqx/emqx EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker save; \
fi;
# Push docker image
.PHONY: $(PROFILES:%=%-docker-push)
$(PROFILES:%=%-docker-push):
@if [ ! -z `echo $(@) |grep -oE edge` ]; then \
TARGET=dgiot/dgiot-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker push; \
TARGET=dgiot/dgiot-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker manifest_list; \
TARGET=emqx/emqx-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker push; \
TARGET=emqx/emqx-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker manifest_list; \
else \
TARGET=dgiot/dgiot EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker push; \
TARGET=dgiot/dgiot EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker manifest_list; \
TARGET=emqx/emqx EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker push; \
TARGET=emqx/emqx EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker manifest_list; \
fi;
# Clean docker image
.PHONY: $(PROFILES:%=%-docker-clean)
$(PROFILES:%=%-docker-clean):
@if [ ! -z `echo $(@) |grep -oE edge` ]; then \
TARGET=dgiot/dgiot-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker clean; \
TARGET=emqx/emqx-edge EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker clean; \
else \
TARGET=dgiot/dgiot EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker clean; \
TARGET=emqx/emqx EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) make -C deploy/docker clean; \
fi;

180
README.md
View File

@ -1,132 +1,92 @@
# 数蛙工业物联网SaaS平台
## 前言
数蛙团队2016年之前在互联网和移动互联网爬坑多年2016年开始进入物联网爬坑希望通过这个开源平台把多年爬坑经验共享出来让多学科交叉的工业互联网项目变得更简单。
- 让丰富工程人员可以通过视窗交互可以完成需求较简单的工业互联网项目
- 让广大的初级前端工程师通过serverless的方式可以承接需求较复杂的工业互联网项目
- 让Python、Java、Go、C/C++初级后台工程师通过web编程开发通道来承接复杂的工业互联网项目
工业物联网落地过程是IT和OT持续融合的过程也是技术领域和业务领域持续融合的过程。会者不难难着不会要把工业互联网项目变得简单一些主要还是需要依赖于各个领域的专家围绕业务场景进行信息流的无缝路由构建一张多学科融合的知识路由表。
基于数蛙工业物联网持续集成平台可以让学者多学科交叉的知识路由表中发布学术论文,技者在实战中练就快速消化项目的本领和收入回报,商者围绕实际项目找到盈利商机。
# 愿景
数蛙团队希望通过数蛙工业互联网持续集成平台达成下面一些愿景:
+ 通过工程人员、前端工程师、初级后台工程师在不超过1个月的实际完成中小型的工业互联网项目
+ 通过代码开源、软件免费、文档共享、技术认证、产品认证、运维托管等多种方式保证高质量的交付
+ 技术领域专家不断持续集成业界优秀技术框架、业务领域专家不断持续优化业务模型和流程、构建多学科交叉的开放平台
+ 近朱者赤数蛙工业物联网持续集成平台将学习10个的工业互联网业界标杆对接100个优秀行业软件
# emqx-rel
# 开发
The Release Project for EMQ X Broker.
github国内下载速度太慢可以直接下载腾讯云上的开发工程包进行快速开发,更多详情请见[开发部署](https://github.com/dgiot/dgiot_deploy)
NOTICE: Requires Erlang/OTP 21.3 to build since EMQ X 3.2
## window开发环境
[dgiot_server.zip](http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/dgiot4.0/windows/dgiot_server_v4.0.0.tar.gz)
There are 4 target profiles for building emqx-rel: emqx, emqx-pkg, emqx-edge,and emqx-edge-pkg. The default target profile is emqx. User can build specified target release by execute command `make ${target-release}` in emqx_rel.
## Install Erlang/OTP-R21.3 and rebar3
Read the section below and install rebar3
```
wget http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/dgiot4.0/windows/dgiot_server_v4.0.0.tar.gz
tar xvf dgiot_server_v4.0.0.tar.gz
cd dgiot_server
https://www.rebar3.org/docs/getting-started#section-installing-from-source
```
## Build on Linux/Unix/Mac
```
git clone -b v4.0.0 https://hub.fastgit.org/emqx/emqx-rel.git emqx-rel
cd emqx-rel && make
./_build/emqx/rel/emqx/bin/emqx console
```
## Build rpm or deb package on Linux
```
git clone -b v4.0.0 https://hub.fastgit.org/emqx/emqx-rel.git emqx-rel
cd emqx-rel && make emqx-pkg
ls _packages/emqx
```
## Build docker image
```
git clone -b v4.0.0 https://hub.fastgit.org/emqx/emqx-rel.git emqx-rel
cd emqx-rel && make emqx-docker-build
```
## Build on Windows
```
git clone -b v4.0.0 https://hub.fastgit.org/emqx/emqx-rel.git emqx-rel
cd emqx-rel
make
_build/dgiot/rel/emqx/bin/emqx.cmd console
```
http://127.0.0.1:5080 用户名:dgiot_admin 密码:dgiot_admin
## centos 7.6 开发环境
[dgiot_server.zip](http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/dgiot4.0/linux/dgiot_server_v4.0.0.tar.gz)
```
wget http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/dgiot4.0/linux/dgiot_server_v4.0.0.tar.gz
tar xvf dgiot_server_v4.0.0.tar.gz
cd dgiot_server
make
_build/dgiot/rel/emqx/bin/emqx.cmd console
cd _build\emqx\rel\emqx
bin\emqx console
```
## Build with elixir plugins
Modify the rebar.config.
# 产品
```erlang
+ 边缘侧系列产品
{elixir_deps,
[ {plugin_name, {git, "url_of_plugin", {tag, "tag_of_plugin"}}}
, ....
....
]
}
+ 云端系统产品
......
......
# 业界标杆
| 业界标杆 | 平台插件 | 说明 |
| ------------ | ------------ | ------------ |
| 阿里云物模型 | dgiot_thing | 物模型 |
| 亚马逊AWS IoT | dgiot_server | DMP |
# 行业软件
| 行业软件 | 平台插件 | 说明 |
| ------------ | ------------ | ------------ |
| 微信 | dgiot_wechat | 微信 |
| 微信公众号 | dgiot_wx | 微信公众号 |
| 微信小程序 | dgiot_mini-_program | 微信小程序 |
| 百度地图 | dgiot_baidumap | 百度地图 |
| kafka | dgiot_kafka | kafka桥接 |
| mysql | dgiot_mysql | mysql集成 |
| postgres | dgiot_postgres | postgres集成 |
| TDengine | dgiot_td | TD集成 |
| Grafana | dgiot_grafana | Grafana |
| Prometheus | dgiot_prometheus | Prometheus集成 |
| gitlab | dgiot_gitlab | 代码提交 |
| jenkins | dgiot jenkins | 持续集成|
| MES | dgiot_mes | mes集成 |
| 金蝶ERP | dgiot_erp | erp集成 |
# 构建
+ Linux/Unix/Mac构建
```shell
git clone https://hub.fastgit.org/dgiot/dgiot_server.git
cd dgiot_server
make
```
+ windows构建
{elixir_relx_apps,
[ app_name1
, app_name2]}.
```
下载msys64
git clone https://hub.fastgit.org/dgiot/dgiot_server.git
cd dgiot_server
make
Due to the limit of the `rebar3_elixir_compile`, users have to specify all the
dependencies of the the elixir plugin in rebar.config in emqx-rel.
## Start with epmd
For now, emqx starts without epmd by default. If you want to run emqx with epmd,
you should set the environment variable $WITH_EPMD with any value you want, for example, execute `export $WITH_EPMD=true` in your shell, then run emqx, epmd will start soon afterwards.
# Test
```bash
make ct
```
## 预览地址
# License
[腾讯云预览地址](https://dgiotdashboard-8gb17b3673ff6cdd-1253666439.ap-shanghai.app.tcloudbase.com?ftom=git)
Apache License Version 2.0
## 扫码预览
# Author
![dgiot_dashboard.png](http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/wechat/dgiot_dashboard.png)
## 环境要求
- node > 14.5
### 关于我们
| 联系方式 | 地址 |
| -------------- | ----------------------------------------------------------------------------------------- |
| github | [https://github.com/dgiot](https://github.com/dgiot?from=git) |
| gitee | [https://gitee.com/dgiot](https://gitee.com/dgiiot?from=git) |
| 官网 | [https://www.iotn2n.com](https://www.iotn2n.com?from=git) |
| 博客 | [https://tech.iotn2n.com](https://tech.iotn2n.com?from=git) |
| 物联网接入平台 | [https://dgiot.iotn2n.com](https://dgiot.iotn2n.com?from=git) |
| 公众号 | ![qrcode.png](http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/wechat/qrcode.png) |
EMQ X Team.

601
bin/dgiot
View File

@ -1,601 +0,0 @@
#!/bin/sh
# -*- tab-width:4;indent-tabs-mode:nil -*-
# ex: ts=4 sw=4 et
set -e
REL_NAME="dgiot"
## constants from relx template
RUNNER_ROOT_DIR="{{ runner_root_dir }}"
RUNNER_BIN_DIR="{{ runner_bin_dir }}"
REL_VSN="{{ rel_vsn }}"
ERTS_VSN="{{ erts_vsn }}"
ERL_OPTS="{{ erl_opts }}"
RUNNER_LOG_DIR="{{ runner_log_dir }}"
RUNNER_LIB_DIR="{{ runner_lib_dir }}"
RUNNER_ETC_DIR="{{ runner_etc_dir }}"
RUNNER_DATA_DIR="{{ runner_data_dir }}"
RUNNER_USER="{{ runner_user }}"
RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
ERTS_PATH=$RUNNER_ROOT_DIR/erts-$ERTS_VSN/bin
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
WHOAMI=$(whoami)
if [ -z "$WITH_EPMD" ]; then
EPMD_ARG="-start_epmd false -epmd_module ekka_epmd -proto_dist ekka"
else
EPMD_ARG="-start_epmd true $PROTO_DIST_ARG"
fi
# Warn the user if ulimit -n is less than 1024
ULIMIT_F=`ulimit -n`
if [ "$ULIMIT_F" -lt 1024 ]; then
echo "!!!!"
echo "!!!! WARNING: ulimit -n is ${ULIMIT_F}; 1024 is the recommended minimum."
echo "!!!!"
fi
# Echo to stderr on errors
echoerr() { echo "$@" 1>&2; }
# By default, use cuttlefish to generate app.config and vm.args
CUTTLEFISH="${USE_CUTTLEFISH:-yes}"
CUTTLEFISH_COMMAND_PREFIX="$ERTS_PATH/escript $RUNNER_ROOT_DIR/bin/cuttlefish -s $REL_DIR/schema -d $RUNNER_DATA_DIR/configs"
SED_REPLACE="sed -i "
case $(sed --help 2>&1) in
*GNU*) SED_REPLACE="sed -i ";;
*BusyBox*) SED_REPLACE="sed -i ";;
*) SED_REPLACE="sed -i ''";;
esac
# Get node pid
relx_get_pid() {
if output="$(relx_nodetool rpcterms os getpid)"
then
echo "$output" | sed -e 's/"//g'
return 0
else
echo "$output"
return 1
fi
}
relx_get_nodename() {
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
}
# Connect to a remote node
relx_rem_sh() {
# Generate a unique id used to allow multiple remsh to the same node
# transparently
id="remsh$(relx_gen_id)-${NAME}"
# Get the node's ticktime so that we use the same thing.
TICKTIME="$(relx_nodetool rpcterms net_kernel get_net_ticktime)"
# Setup remote shell command to control node
exec "$BINDIR/erl" "$NAME_TYPE" "$id" -remsh "$NAME" -boot start_clean \
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
-setcookie "$COOKIE" -hidden -kernel net_ticktime $TICKTIME
}
# Generate a random id
relx_gen_id() {
od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}
# Control a node
relx_nodetool() {
command="$1"; shift
ERL_FLAGS="$ERL_FLAGS $EPMD_ARG" \
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
-setcookie "$COOKIE" "$command" $@
}
# Run an escript in the node's environment
relx_escript() {
shift; scriptpath="$1"; shift
export RUNNER_ROOT_DIR
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}
# Output a start command for the last argument of run_erl
relx_start_command() {
printf "exec \"%s\" \"%s\"" "$RUNNER_SCRIPT" \
"$START_OPTION"
}
# Function to generate app.config and vm.args
generate_config() {
## Delete the *.siz files first or it cann't start after
## changing the config 'log.rotation.size'
rm -rf "${RUNNER_LOG_DIR}"/*.siz
if [ "$CUTTLEFISH" != "yes" ]; then
# Note: we have added a parameter '-vm_args' to this. It
# appears redundant but it is not! the erlang vm allows us to
# access all arguments to the erl command EXCEPT '-args_file',
# so in order to get access to this file location from within
# the vm, we need to pass it in twice.
CONFIG_ARGS=" -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -vm_args $RUNNER_ETC_DIR/vm.args "
else
APPCONF=`relx_nodetool mergeconf $RUNNER_ETC_DIR/emqx.conf $RUNNER_ETC_DIR/plugins $RUNNER_DATA_DIR/configs`
replace_env_in_conf
CONFIG_ARGS=`$CUTTLEFISH_COMMAND_PREFIX -c $APPCONF generate`
## Merge cuttlefish generated *.args into the vm.args
CUTTLE_GEN_ARG_FILE=`echo "$CONFIG_ARGS" | sed -n 's/^.*\(vm_args[[:space:]]\)//p' | awk '{print $1}'`
TMP_ARG_FILE="$RUNNER_DATA_DIR/configs/vm.args.tmp"
cp "$RUNNER_ETC_DIR/vm.args" "$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
ARG_KEY=`echo "$ARG_LINE" | awk '{NF--; print}'`
## if not found in vm.args, append a new line
if ! grep -q "^$ARG_KEY" "$TMP_ARG_FILE"; then
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
fi
done
mv -f "$TMP_ARG_FILE" "$CUTTLE_GEN_ARG_FILE"
fi
if ! relx_nodetool chkconfig $CONFIG_ARGS; then
echoerr "Error reading $CONFIG_ARGS"
exit 1
fi
}
replace_env_in_conf() {
[ "x" = "x$EMQX_NODE_NAME" ] || $SED_REPLACE "s/^[ \t]*node.name[ \t]*=.*$/node.name= $EMQX_NODE_NAME/" $APPCONF
[ "x" = "x$EMQX_NODE_COOKIE" ] || $SED_REPLACE "s/^[ \t]*node.cookie[ \t]*=.*$/node.cookie= $EMQX_NODE_COOKIE/" $APPCONF
[ "x" = "x$EMQX_MAX_PORTS" ] || $SED_REPLACE "s/^[ \t]*node.max_ports[ \t]*=.*$/node.max_ports = $EMQX_MAX_PORTS/" $APPCONF
[ "x" = "x$EMQX_MAX_PACKET_SIZE" ] || $SED_REPLACE "s/^[ \t]*mqtt.max_packet_size[ \t]*=.*$/mqtt.max_packet_size = $EMQX_MAX_PACKET_SIZE/" $APPCONF
[ "x" = "x$EMQX_TCP_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.tcp.external[ \t]*=.*$/listener.tcp.external = $EMQX_TCP_PORT/" $APPCONF
[ "x" = "x$EMQX_SSL_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.ssl.external[ \t]*=.*$/listener.ssl.external = $EMQX_SSL_PORT/" $APPCONF
[ "x" = "x$EMQX_WS_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.ws.external[ \t]*=.*$/listener.ws.external = $EMQX_WS_PORT/" $APPCONF
[ "x" = "x$EMQX_WSS_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.wss.external[ \t]*=.*$/listener.wss.external = $EMQX_WSS_PORT/" $APPCONF
}
# Call bootstrapd for daemon commands like start/stop/console
bootstrapd() {
if [ -e "$RUNNER_DATA_DIR/.erlang.cookie" ]; then
chown $RUNNER_USER $RUNNER_DATA_DIR/.erlang.cookie
fi
# Fail fast if they have no rights to mess around with pids
check_user_internal
# Make sure the user running this script is the owner and/or su to that user
check_user $@
ES=$?
if [ "$ES" -ne 0 ]; then
exit $ES
fi
}
# Simple way to check the correct user and fail early
check_user_internal() {
# Validate that the user running the script is the owner of the
# RUN_DIR.
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
if [ "x$WHOAMI" != "xroot" ]; then
echo "You need to be root or use sudo to run this command"
exit 1
fi
fi
}
# Function to su into correct user that is poorly named for historical
check_user() {
check_user_internal
# do not su again if we are already the runner user
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
ESCAPED_ARGS=`echo "$@" | sed -e 's/\([{}"]\)/\\\\\1/g'`
# This will drop priviledges into the runner user
# It exec's in a new shell and the current shell will exit
exec su - $RUNNER_USER -c "$RUNNER_SCRIPT $ESCAPED_ARGS"
fi
}
# Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR"
# Use $CWD/etc/sys.config if exists
if [ -z "$RELX_CONFIG_PATH" ]; then
if [ -f "$RUNNER_ETC_DIR/sys.config" ]; then
RELX_CONFIG_PATH="-config $RUNNER_ETC_DIR/sys.config"
else
RELX_CONFIG_PATH=""
fi
fi
[ "x" = "x$EMQX_NODE_NAME" ] || NAME_ARG="-name $EMQX_NODE_NAME"
# Extract the target node name from node.args
if [ -z "$NAME_ARG" ]; then
NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
if [ -z "$NODENAME" ]; then
echoerr "vm.args needs to have a -name parameter."
echoerr " -sname is not supported."
exit 1
else
NAME_ARG="-name ${NODENAME# *}"
fi
fi
# Extract the name type and name from the NAME_ARG for REMSH
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
PIPE_DIR="${PIPE_DIR:-/$RUNNER_DATA_DIR/${WHOAMI}_erl_pipes/$NAME/}"
[ "x" = "x$EMQX_NODE_COOKIE" ] || COOKIE_ARG="-setcookie $EMQX_NODE_COOKIE"
# Extract the target cookie
if [ -z "$COOKIE_ARG" ]; then
COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
if [ -z "$COOKIE" ]; then
echoerr "vm.args needs to have a -setcookie parameter."
exit 1
else
COOKIE_ARG="-setcookie $COOKIE"
fi
fi
# Extract cookie name from COOKIE_ARG
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
# Support for IPv6 Dist. See: https://hub.fastgit.org/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-`
if [ -z "$PROTO_DIST" ]; then
PROTO_DIST_ARG=""
else
PROTO_DIST_ARG="-proto_dist $PROTO_DIST"
fi
export ROOTDIR="$RUNNER_ROOT_DIR"
export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
ERTS_LIB_DIR="$ERTS_DIR/../lib"
MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia/$NAME"
cd "$ROOTDIR"
# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
*@*)
# Nothing to do
;;
*)
NAME=$NAME@$(relx_get_nodename)
;;
esac
# Check the first argument for instructions
case "$1" in
start|start_boot)
# Make sure a node IS not running
if relx_nodetool "ping" >/dev/null 2>&1; then
echo "Node is already running!"
exit 1
fi
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
bootstrapd $@
# Save this for later.
CMD=$1
case "$1" in
start)
shift
START_OPTION="console"
HEART_OPTION="start"
;;
start_boot)
shift
START_OPTION="console_boot"
HEART_OPTION="start_boot"
;;
esac
RUN_PARAM="$@"
# Set arguments for the heart command
set -- "$RUNNER_SCRIPT" "$HEART_OPTION"
[ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"
# Export the HEART_COMMAND
HEART_COMMAND="$RUNNER_SCRIPT $CMD"
export HEART_COMMAND
## See: http://erlang.org/doc/man/run_erl.html
# Export the RUN_ERL_LOG_GENERATIONS
# RUN_ERL_LOG_GENERATIONS=5
# export RUN_ERL_LOG_GENERATIONS
# Export the RUN_ERL_LOG_MAXSIZE
RUN_ERL_LOG_MAXSIZE=1048576
export RUN_ERL_LOG_MAXSIZE
mkdir -p "$PIPE_DIR"
"$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
"$(relx_start_command)"
WAIT=${WAIT_FOR_ERLANG:-15}
while [ $WAIT -gt 0 ]; do
WAIT=`expr $WAIT - 1`
sleep 1
if ! relx_nodetool "ping" >/dev/null 2>&1; then
continue
fi
echo "dgiot $REL_VSN is started successfully!"
exit 0
done
echo "The broker failed to start within ${WAIT_FOR_ERLANG:-15} seconds,"
echo "see the output of './bin/dgiot console' for more information."
echo "If you want to wait longer, set the environment variable"
echo "WAIT_FOR_ERLANG to the number of seconds to wait."
exit 1
;;
stop)
# Wait for the node to completely stop...
PID="$(relx_get_pid)"
if ! relx_nodetool "stop"; then
exit 1
fi
while $(kill -s 0 "$PID" 2>/dev/null);
do
sleep 1
done
;;
restart)
#generate app.config and vm.args
generate_config
## Restart the VM without exiting the process
if ! relx_nodetool "restart" $CONFIG_ARGS; then
exit 1
fi
;;
reboot)
#generate app.config and vm.args
generate_config
## Restart the VM completely (uses heart to restart it)
if ! relx_nodetool "reboot" $CONFIG_ARGS; then
exit 1
fi
;;
pid)
## Get the VM's pid
if ! relx_get_pid; then
exit 1
fi
;;
ping)
## See if the VM is alive
if ! relx_nodetool "ping"; then
exit 1
fi
;;
escript)
## Run an escript under the node's environment
if ! relx_escript $@; then
exit 1
fi
;;
attach)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
bootstrapd $@
shift
exec "$BINDIR/to_erl" "$PIPE_DIR"
;;
remote_console)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
bootstrapd $@
shift
relx_rem_sh
;;
upgrade|downgrade|install)
if [ -z "$2" ]; then
echo "Missing package argument"
echo "Usage: $REL_NAME $1 {package base name}"
echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
exit 1
fi
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
"install" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
;;
unpack)
if [ -z "$2" ]; then
echo "Missing package argument"
echo "Usage: $REL_NAME $1 {package base name}"
echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
exit 1
fi
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
"unpack" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
;;
console|console_clean|console_boot)
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
bootstrapd $@
# .boot file typically just $REL_NAME (ie, the app name)
# however, for debugging, sometimes start_clean.boot is useful.
# For e.g. 'setup', one may even want to name another boot script.
case "$1" in
console)
if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
BOOTFILE="$REL_DIR/$REL_NAME"
else
BOOTFILE="$REL_DIR/start"
fi
;;
console_clean)
BOOTFILE="$ROOTDIR/bin/start_clean"
;;
console_boot)
shift
BOOTFILE="$1"
shift
;;
esac
#generate app.config and vm.args
generate_config
# Setup beam-required vars
EMU="beam"
PROGNAME="${0#*/}"
export EMU
export PROGNAME
# Store passed arguments since they will be erased by `set`
ARGS="$@"
# Build an array of arguments to pass to exec later on
# Build it here because this command will be used for logging.
set -- "$BINDIR/erlexec" -boot "$BOOTFILE" -mode "$CODE_LOADING_MODE" \
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
-mnesia dir "\"${MNESIA_DATA_DIR}\"" \
$RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG
# Dump environment info for logging purposes
echo "Exec: $@" -- ${1+$ARGS}
echo "Root: $ROOTDIR"
# Log the startup
echo "$RUNNER_ROOT_DIR"
logger -t "$REL_NAME[$$]" "Starting up"
# Start the VM
exec "$@" -- ${1+$ARGS}
;;
foreground)
# Bootstrap daemon command (check perms & drop to $RUNNER_USER)
bootstrapd $@
# start up the release in the foreground for use by runit
# or other supervision services
#generate app.config and vm.args
generate_config
[ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
FOREGROUNDOPTIONS="-noshell -noinput +Bd"
# Setup beam-required vars
EMU=beam
PROGNAME="${0#*/}"
export EMU
export PROGNAME
# Store passed arguments since they will be erased by `set`
ARGS="$@"
# Build an array of arguments to pass to exec later on
# Build it here because this command will be used for logging.
set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
-boot "$REL_DIR/$BOOTFILE" -mode "$CODE_LOADING_MODE" \
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
-mnesia dir "\"${MNESIA_DATA_DIR}\"" \
$RELX_CONFIG_PATH $CONFIG_ARGS $EPMD_ARG
# Dump environment info for logging purposes
echo "Exec: $@" -- ${1+$ARGS}
echo "Root: $ROOTDIR"
# Start the VM
exec "$@" -- ${1+$ARGS}
;;
ertspath)
echo $ERTS_PATH
;;
rpc)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
shift
relx_nodetool rpc $@
;;
rpcterms)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
shift
relx_nodetool rpcterms $@
;;
eval)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
shift
relx_nodetool "eval" $@
;;
*)
echo "Usage: $REL_NAME {start|start_boot <file>|ertspath|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|escript|rpc|rpcterms|eval}"
exit 1
;;
esac
exit 0

View File

@ -1,267 +0,0 @@
:: This batch file handles managing an Erlang node as a Windows service.
::
:: Commands provided:
::
:: * install - install the release as a Windows service
:: * start - start the service and Erlang node
:: * stop - stop the service and Erlang node
:: * restart - run the stop command and start command
:: * uninstall - uninstall the service and kill a running node
:: * ping - check if the node is running
:: * console - start the Erlang release in a `werl` Windows shell
:: * attach - connect to a running node and open an interactive console
:: * list - display a listing of installed Erlang services
:: * usage - display available commands
:: Set variables that describe the release
@set rel_name=dgiot
@set rel_vsn={{ rel_vsn }}
@set erts_vsn={{ erts_vsn }}
@set erl_opts={{ erl_opts }}
@set script=%~n0
:: Discover the release root directory from the directory
:: of this script
@set script_dir=%~dp0
@for %%A in ("%script_dir%\..") do @(
set rel_root_dir=%%~fA
)
@set rel_dir=%rel_root_dir%\releases\%rel_vsn%
@set etc_dir=%rel_root_dir%\etc
@set lib_dir=%rel_root_dir%\lib
@set data_dir=%rel_root_dir%\data
@set emqx_conf=%etc_dir%\emqx.conf
@call :find_erts_dir
@call :find_vm_args
@call :find_sys_config
@call :set_boot_script_var
@set service_name=%rel_name%_%rel_vsn%
@set bindir=%erts_dir%\bin
@set progname=erl.exe
@set clean_boot_script=%rel_root_dir%\bin\start_clean
@set erlsrv="%bindir%\erlsrv.exe"
@set epmd="%bindir%\epmd.exe"
@set escript="%bindir%\escript.exe"
@set werl="%bindir%\werl.exe"
@set erl_exe="%bindir%\erl.exe"
@set nodetool="%rel_root_dir%\bin\nodetool"
@set cuttlefish="%rel_root_dir%\bin\cuttlefish"
@set node_type="-name"
:: Extract node name from emqx.conf
@for /f "usebackq delims=\= tokens=2" %%I in (`findstr /b node\.name "%emqx_conf%"`) do @(
@call :set_trim node_name %%I
)
:: Extract node cookie from emqx.conf
@for /f "usebackq delims=\= tokens=2" %%I in (`findstr /b node\.cookie "%emqx_conf%"`) do @(
@call :set_trim node_cookie= %%I
)
:: Write the erl.ini file to set up paths relative to this script
@call :write_ini
:: If a start.boot file is not present, copy one from the named .boot file
@if not exist "%rel_dir%\start.boot" (
copy "%rel_dir%\%rel_name%.boot" "%rel_dir%\start.boot" >nul
)
@if "%1"=="install" @goto install
@if "%1"=="uninstall" @goto uninstall
@if "%1"=="start" @goto start
@if "%1"=="stop" @goto stop
@if "%1"=="restart" @call :stop && @goto start
::@if "%1"=="upgrade" @goto relup
::@if "%1"=="downgrade" @goto relup
@if "%1"=="console" @goto console
@if "%1"=="ping" @goto ping
@if "%1"=="list" @goto list
@if "%1"=="attach" @goto attach
@if "%1"=="" @goto usage
@echo Unknown command: "%1"
@goto :eof
:: Find the ERTS dir
:find_erts_dir
@set possible_erts_dir=%rel_root_dir%\erts-%erts_vsn%
@if exist "%possible_erts_dir%" (
call :set_erts_dir_from_default
) else (
call :set_erts_dir_from_erl
)
@goto :eof
:: Set the ERTS dir from the passed in erts_vsn
:set_erts_dir_from_default
@set erts_dir=%possible_erts_dir%
@set rootdir=%rel_root_dir%
@goto :eof
:: Set the ERTS dir from erl
:set_erts_dir_from_erl
@for /f "delims=" %%i in ('where erl') do @(
set erl=%%i
)
@set dir_cmd="%erl%" -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop
@for /f %%i in ('%%dir_cmd%%') do @(
set erl_root=%%i
)
@set erts_dir=%erl_root%\erts-%erts_vsn%
@set rootdir=%erl_root%
@goto :eof
:find_vm_args
@set possible_vm=%etc_dir%\vm.args
@if exist %possible_vm% (
set args_file=-args_file "%possible_vm%"
)
@goto :eof
:: Find the sys.config file
:find_sys_config
@set possible_sys=%etc_dir%\sys.config
@if exist %possible_sys% (
set sys_config=-config "%possible_sys%"
)
@goto :eof
:create_mnesia_dir
@set create_dir_cmd=%escript% %nodetool% mnesia_dir %data_dir%\mnesia %node_name%
@for /f "delims=" %%Z in ('%%create_dir_cmd%%') do @(
set mnesia_dir=%%Z
)
@goto :eof
:generate_app_config
@set mergeconf_cmd=%escript% %nodetool% mergeconf %etc_dir%\emqx.conf %etc_dir%\plugins %data_dir%\configs
@for /f %%Z in ('%%mergeconf_cmd%%') do @(
set merged_app_conf=%%Z
)
@set gen_config_cmd=%escript% %cuttlefish% -s %rel_dir%\schema -c %merged_app_conf% -d %data_dir%\configs generate
@for /f "delims=" %%A in ('%%gen_config_cmd%%') do @(
set generated_config_args=%%A
)
@goto :eof
:: set boot_script variable
:set_boot_script_var
@if exist "%rel_dir%\%rel_name%.boot" (
set boot_script=%rel_dir%\%rel_name%
) else (
set boot_script=%rel_dir%\start
)
@goto :eof
:: Write the erl.ini file
:write_ini
@set erl_ini=%erts_dir%\bin\erl.ini
@set converted_bindir=%bindir:\=\\%
@set converted_rootdir=%rootdir:\=\\%
@echo [erlang] > "%erl_ini%"
@echo Bindir=%converted_bindir% >> "%erl_ini%"
@echo Progname=%progname% >> "%erl_ini%"
@echo Rootdir=%converted_rootdir% >> "%erl_ini%"
@goto :eof
:: Display usage information
:usage
@echo usage: %~n0 ^(install^|uninstall^|start^|stop^|restart^|console^|ping^|list^|attach^)
@goto :eof
:: Install the release as a Windows service
:: or install the specified version passed as argument
:install
@call :create_mnesia_dir
@call :generate_app_config
:: Install the service
@set args="-boot %boot_script% %sys_config% %generated_config_args% -mnesia dir '%mnesia_dir%'"
@set description=EMQ node %node_name% in %rootdir%
@if "" == "%2" (
%erlsrv% add %service_name% %node_type% "%node_name%" -on restart -c "%description%" ^
-i "emqx" -w "%rootdir%" -m %erl_exe% -args %args% ^
-st "init:stop()."
sc config emqx start=delayed-auto
) else (
:: relup and reldown
goto relup
)
@goto :eof
:: Uninstall the Windows service
:uninstall
@%erlsrv% remove %service_name%
@%epmd% -kill
@goto :eof
:: Start the Windows service
:start
:: window service?
:: @%erlsrv% start %service_name%
@call :create_mnesia_dir
@call :generate_app_config
@set args=-detached %sys_config% %generated_config_args% -mnesia dir '%mnesia_dir%'
@echo off
cd /d %rel_root_dir%
@echo on
@start "%rel_name%" %werl% -boot "%boot_script%" %args%
@goto :eof
:: Stop the Windows service
:stop
:: window service?
:: @%erlsrv% stop %service_name%
@%escript% %nodetool% %node_type% %node_name% -setcookie %node_cookie% stop
@goto :eof
:: Relup and reldown
:relup
@if "" == "%2" (
echo Missing package argument
echo Usage: %rel_name% %1 {package base name}
echo NOTE {package base name} MUST NOT include the .tar.gz suffix
set ERRORLEVEL=1
exit /b %ERRORLEVEL%
)
@%escript% "%rootdir%/bin/install_upgrade.escript" "%rel_name%" "%node_name%" "%node_cookie%" "%2"
@goto :eof
:: Start a console
:console
@call :create_mnesia_dir
@call :generate_app_config
@set args=%sys_config% %generated_config_args% -mnesia dir '%mnesia_dir%'
@echo off
cd /d %rel_root_dir%
@echo on
@start "bin\%rel_name% console" %werl% -boot "%boot_script%" %args%
@echo dgiot is started!
@goto :eof
:: Ping the running node
:ping
@%escript% %nodetool% ping %node_type% "%node_name%" -setcookie "%node_cookie%"
@goto :eof
:: List installed Erlang services
:list
@%erlsrv% list %service_name%
@goto :eof
:: Attach to a running node
:attach
:: @start "%node_name% attach"
@start "%node_name% attach" %werl% -boot "%clean_boot_script%" ^
-remsh %node_name% %node_type% console_%node_name% -setcookie %node_cookie%
@goto :eof
:: Trim variable
:set_trim
@set %1=%2
@goto :eof

View File

@ -1,81 +0,0 @@
#!/bin/sh
# -*- tab-width:4;indent-tabs-mode:nil -*-
# ex: ts=4 sw=4 et
set -e
REL_NAME="dgiot"
## constants from relx template
RUNNER_ROOT_DIR="{{ runner_root_dir }}"
ERTS_VSN="{{ erts_vsn }}"
RUNNER_ETC_DIR="{{ runner_etc_dir }}"
if [ -z "$WITH_EPMD" ]; then
EPMD_ARG="-start_epmd false -epmd_module nodetool_epmd"
else
EPMD_ARG="-start_epmd true"
fi
relx_get_nodename() {
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
}
# Control a node
relx_nodetool() {
command="$1"; shift
ERL_FLAGS="$ERL_FLAGS $EPMD_ARG $PROTO_DIST_ARG" \
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
-setcookie "$COOKIE" "$command" "$@"
}
[ "x" = "x$EMQX_NODE_NAME" ] || NAME_ARG="-name $EMQX_NODE_NAME"
# Extract the target node name from node.args
if [ -z "$NAME_ARG" ]; then
NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
if [ -z "$NODENAME" ]; then
echoerr "vm.args needs to have a -name parameter."
echoerr " -sname is not supported."
exit 1
else
NAME_ARG="-name ${NODENAME# *}"
fi
fi
# Extract the name type and name from the NAME_ARG for REMSH
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
[ "x" = "x$EMQX_NODE_COOKIE" ] || COOKIE_ARG="-setcookie $EMQX_NODE_COOKIE"
# Extract the target cookie
if [ -z "$COOKIE_ARG" ]; then
COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
if [ -z "$COOKIE" ]; then
echoerr "vm.args needs to have a -setcookie parameter."
exit 1
else
COOKIE_ARG="-setcookie $COOKIE"
fi
fi
# Extract cookie name from COOKIE_ARG
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
# Support for IPv6 Dist. See: https://hub.fastgit.org/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-`
if [ -z "$PROTO_DIST" ]; then
PROTO_DIST_ARG=""
else
PROTO_DIST_ARG="-proto_dist $PROTO_DIST"
fi
export ROOTDIR="$RUNNER_ROOT_DIR"
export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
export BINDIR="$ERTS_DIR/bin"
cd "$ROOTDIR"
relx_nodetool rpc dgiot_ctl run_command "$@"

View File

@ -1,92 +0,0 @@
:: The batch file for emqx_ctl command
@set args=%*
:: Set variables that describe the release
@set rel_name=dgiot
@set rel_vsn={{ rel_vsn }}
@set erts_vsn={{ erts_vsn }}
@set erl_opts={{ erl_opts }}
:: Discover the release root directory from the directory
:: of this script
@set script_dir=%~dp0
@for %%A in ("%script_dir%\..") do @(
set rel_root_dir=%%~fA
)
@set rel_dir=%rel_root_dir%\releases\%rel_vsn%
@set emqx_conf=%rel_root_dir%\etc\emqx.conf
@call :find_erts_dir
@set bindir=%erts_dir%\bin
@set progname=erl.exe
@set escript="%bindir%\escript.exe"
@set nodetool="%rel_root_dir%\bin\nodetool"
@set node_type="-name"
:: Extract node name from emqx.conf
@for /f "usebackq delims=\= tokens=2" %%I in (`findstr /b node\.name "%emqx_conf%"`) do @(
@call :set_trim node_name %%I
)
:: Extract node cookie from emqx.conf
@for /f "usebackq delims=\= tokens=2" %%I in (`findstr /b node\.cookie "%emqx_conf%"`) do @(
@call :set_trim node_cookie= %%I
)
:: Write the erl.ini file to set up paths relative to this script
@call :write_ini
:: If a start.boot file is not present, copy one from the named .boot file
@if not exist "%rel_dir%\start.boot" (
copy "%rel_dir%\%rel_name%.boot" "%rel_dir%\start.boot" >nul
)
@%escript% %nodetool% %node_type% "%node_name%" -setcookie "%node_cookie%" rpc emqx_ctl run_command %args%
:: Find the ERTS dir
:find_erts_dir
@set possible_erts_dir=%rel_root_dir%\erts-%erts_vsn%
@if exist "%possible_erts_dir%" (
call :set_erts_dir_from_default
) else (
call :set_erts_dir_from_erl
)
@goto :eof
:: Set the ERTS dir from the passed in erts_vsn
:set_erts_dir_from_default
@set erts_dir=%possible_erts_dir%
@set rootdir=%rel_root_dir%
@goto :eof
:: Set the ERTS dir from erl
:set_erts_dir_from_erl
@for /f "delims=" %%i in ('where erl') do @(
set erl=%%i
)
@set dir_cmd="%erl%" -noshell -eval "io:format(\"~s\", [filename:nativename(code:root_dir())])." -s init stop
@for /f %%i in ('%%dir_cmd%%') do @(
set erl_root=%%i
)
@set erts_dir=%erl_root%\erts-%erts_vsn%
@set rootdir=%erl_root%
@goto :eof
:: Write the erl.ini file
:write_ini
@set erl_ini=%erts_dir%\bin\erl.ini
@set converted_bindir=%bindir:\=\\%
@set converted_rootdir=%rootdir:\=\\%
@echo [erlang] > "%erl_ini%"
@echo Bindir=%converted_bindir% >> "%erl_ini%"
@echo Progname=%progname% >> "%erl_ini%"
@echo Rootdir=%converted_rootdir% >> "%erl_ini%"
@goto :eof
:: Trim variable
:set_trim
@set %1=%2
@goto :eof

View File

@ -1,11 +0,0 @@
#!/bin/sh
[ "x" = "x$EMQX_NODE_NAME" ] && EMQX_NODE_NAME=dgiot@127.0.0.1
[ "x" = "x$EMQX_NODE_COOKIE" ] && EMQX_NODE_COOKIE=dgiotsecretcookie
[ "x" = "x$EMQX_MAX_PACKET_SIZE" ] && EMQX_MAX_PACKET_SIZE=64KB
[ "x" = "x$EMQX_MAX_PORTS" ] && EMQX_MAX_PORTS=65536
[ "x" = "x$EMQX_TCP_PORT" ] && EMQX_TCP_PORT=1883
[ "x" = "x$EMQX_SSL_PORT" ] && EMQX_SSL_PORT=8883
[ "x" = "x$EMQX_WS_PORT" ] && EMQX_WS_PORT=8083
[ "x" = "x$EMQX_WSS_PORT" ] && EMQX_WSS_PORT=8084

174
bin/emqx
View File

@ -7,16 +7,16 @@ set -e
REL_NAME="emqx"
## constants from relx template
RUNNER_ROOT_DIR="$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"
RUNNER_BIN_DIR="$RUNNER_ROOT_DIR/bin"
REL_VSN="v4.0.0"
ERTS_VSN="10.3"
ERL_OPTS=""
RUNNER_LOG_DIR="$RUNNER_ROOT_DIR/log"
RUNNER_LIB_DIR="$RUNNER_ROOT_DIR/lib"
RUNNER_ETC_DIR="$RUNNER_ROOT_DIR/etc"
RUNNER_DATA_DIR="$RUNNER_ROOT_DIR/data"
RUNNER_USER=""
RUNNER_ROOT_DIR="{{ runner_root_dir }}"
RUNNER_BIN_DIR="{{ runner_bin_dir }}"
REL_VSN="{{ rel_vsn }}"
ERTS_VSN="{{ erts_vsn }}"
ERL_OPTS="{{ erl_opts }}"
RUNNER_LOG_DIR="{{ runner_log_dir }}"
RUNNER_LIB_DIR="{{ runner_lib_dir }}"
RUNNER_ETC_DIR="{{ runner_etc_dir }}"
RUNNER_DATA_DIR="{{ runner_data_dir }}"
RUNNER_USER="{{ runner_user }}"
RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
ERTS_PATH=$RUNNER_ROOT_DIR/erts-$ERTS_VSN/bin
@ -25,6 +25,36 @@ REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
WHOAMI=$(whoami)
# Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR"
# Make sure data directory exists
mkdir -p "$RUNNER_DATA_DIR"
# Simple way to check the correct user and fail early
check_user() {
# Validate that the user running the script is the owner of the
# RUN_DIR.
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
if [ "x$WHOAMI" != "xroot" ]; then
echo "You need to be root or use sudo to run this command"
exit 1
fi
ESCAPED_ARGS=`echo "$@" | sed -e 's/\([{}"]\)/\\\\\1/g'`
# This will drop priviledges into the runner user
# It exec's in a new shell and the current shell will exit
exec su - $RUNNER_USER -c "$RUNNER_SCRIPT $ESCAPED_ARGS"
fi
}
# Make sure the user running this script is the owner and/or su to that user
check_user $@
ES=$?
if [ "$ES" -ne 0 ]; then
exit $ES
fi
if [ -z "$WITH_EPMD" ]; then
EPMD_ARG="-start_epmd false -epmd_module ekka_epmd -proto_dist ekka"
else
@ -44,7 +74,6 @@ echoerr() { echo "$@" 1>&2; }
# By default, use cuttlefish to generate app.config and vm.args
CUTTLEFISH="${USE_CUTTLEFISH:-yes}"
CUTTLEFISH_COMMAND_PREFIX="$ERTS_PATH/escript $RUNNER_ROOT_DIR/bin/cuttlefish -s $REL_DIR/schema -d $RUNNER_DATA_DIR/configs"
SED_REPLACE="sed -i "
case $(sed --help 2>&1) in
@ -127,9 +156,7 @@ generate_config() {
# the vm, we need to pass it in twice.
CONFIG_ARGS=" -config $RUNNER_ETC_DIR/app.config -args_file $RUNNER_ETC_DIR/vm.args -vm_args $RUNNER_ETC_DIR/vm.args "
else
APPCONF=`relx_nodetool mergeconf $RUNNER_ETC_DIR/emqx.conf $RUNNER_ETC_DIR/plugins $RUNNER_DATA_DIR/configs`
replace_env_in_conf
CONFIG_ARGS=`$CUTTLEFISH_COMMAND_PREFIX -c $APPCONF 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
CUTTLE_GEN_ARG_FILE=`echo "$CONFIG_ARGS" | sed -n 's/^.*\(vm_args[[:space:]]\)//p' | awk '{print $1}'`
@ -137,11 +164,16 @@ generate_config() {
cp "$RUNNER_ETC_DIR/vm.args" "$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
ARG_KEY=`echo "$ARG_LINE" | awk '{NF--; print}'`
## if not found in vm.args, append a new line
if ! grep -q "^$ARG_KEY" "$TMP_ARG_FILE"; then
ARG_KEY=`echo "$ARG_LINE" | awk '{$NF="";print}'`
ARG_VALUE=`echo "$ARG_LINE" | awk '{print $NF}'`
TMP_ARG_VALUE=`grep "^$ARG_KEY" "$TMP_ARG_FILE" | awk '{print $NF}'`
if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
if [ ! -z $TMP_ARG_VALUE ]; then
sh -c "$SED_REPLACE 's/^$ARG_KEY.*$/$ARG_LINE/' $TMP_ARG_FILE"
else
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
fi
fi
done
mv -f "$TMP_ARG_FILE" "$CUTTLE_GEN_ARG_FILE"
fi
@ -152,60 +184,13 @@ generate_config() {
fi
}
replace_env_in_conf() {
[ "x" = "x$EMQX_NODE_NAME" ] || $SED_REPLACE "s/^[ \t]*node.name[ \t]*=.*$/node.name= $EMQX_NODE_NAME/" $APPCONF
[ "x" = "x$EMQX_NODE_COOKIE" ] || $SED_REPLACE "s/^[ \t]*node.cookie[ \t]*=.*$/node.cookie= $EMQX_NODE_COOKIE/" $APPCONF
[ "x" = "x$EMQX_MAX_PORTS" ] || $SED_REPLACE "s/^[ \t]*node.max_ports[ \t]*=.*$/node.max_ports = $EMQX_MAX_PORTS/" $APPCONF
[ "x" = "x$EMQX_MAX_PACKET_SIZE" ] || $SED_REPLACE "s/^[ \t]*mqtt.max_packet_size[ \t]*=.*$/mqtt.max_packet_size = $EMQX_MAX_PACKET_SIZE/" $APPCONF
[ "x" = "x$EMQX_TCP_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.tcp.external[ \t]*=.*$/listener.tcp.external = $EMQX_TCP_PORT/" $APPCONF
[ "x" = "x$EMQX_SSL_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.ssl.external[ \t]*=.*$/listener.ssl.external = $EMQX_SSL_PORT/" $APPCONF
[ "x" = "x$EMQX_WS_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.ws.external[ \t]*=.*$/listener.ws.external = $EMQX_WS_PORT/" $APPCONF
[ "x" = "x$EMQX_WSS_PORT" ] || $SED_REPLACE "s/^[ \t]*listener.wss.external[ \t]*=.*$/listener.wss.external = $EMQX_WSS_PORT/" $APPCONF
}
# Call bootstrapd for daemon commands like start/stop/console
bootstrapd() {
if [ -e "$RUNNER_DATA_DIR/.erlang.cookie" ]; then
chown $RUNNER_USER $RUNNER_DATA_DIR/.erlang.cookie
fi
# Fail fast if they have no rights to mess around with pids
check_user_internal
# Make sure the user running this script is the owner and/or su to that user
check_user $@
ES=$?
if [ "$ES" -ne 0 ]; then
exit $ES
fi
}
# Simple way to check the correct user and fail early
check_user_internal() {
# Validate that the user running the script is the owner of the
# RUN_DIR.
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
if [ "x$WHOAMI" != "xroot" ]; then
echo "You need to be root or use sudo to run this command"
exit 1
fi
fi
}
# Function to su into correct user that is poorly named for historical
check_user() {
check_user_internal
# do not su again if we are already the runner user
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
ESCAPED_ARGS=`echo "$@" | sed -e 's/\([{}"]\)/\\\\\1/g'`
# This will drop priviledges into the runner user
# It exec's in a new shell and the current shell will exit
exec su - $RUNNER_USER -c "$RUNNER_SCRIPT $ESCAPED_ARGS"
fi
}
# Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR"
# Use $CWD/etc/sys.config if exists
if [ -z "$RELX_CONFIG_PATH" ]; then
if [ -f "$RUNNER_ETC_DIR/sys.config" ]; then
@ -215,13 +200,19 @@ if [ -z "$RELX_CONFIG_PATH" ]; then
fi
fi
[ "x" = "x$EMQX_NODE_NAME" ] || NAME_ARG="-name $EMQX_NODE_NAME"
# Extract the target node name from node.args
if [ -z "$NAME_ARG" ]; then
NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
if [ ! -z "$EMQX_NODE_NAME" ]; then
NODENAME="$EMQX_NODE_NAME"
elif [ ! -z `ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-name (\S*)' | awk '{print $2}'` ]; then
NODENAME=`ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-name (\S*)' | awk '{print $2}'`
else
NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
fi
if [ -z "$NODENAME" ]; then
echoerr "vm.args needs to have a -name parameter."
echoerr " -sname is not supported."
echoerr "perhaps you do not have read permissions on $RUNNER_ETC_DIR/emqx.conf"
exit 1
else
NAME_ARG="-name ${NODENAME# *}"
@ -234,12 +225,18 @@ NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
PIPE_DIR="${PIPE_DIR:-/$RUNNER_DATA_DIR/${WHOAMI}_erl_pipes/$NAME/}"
[ "x" = "x$EMQX_NODE_COOKIE" ] || COOKIE_ARG="-setcookie $EMQX_NODE_COOKIE"
# Extract the target cookie
if [ -z "$COOKIE_ARG" ]; then
COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
if [ ! -z "$EMQX_NODE_COOKIE" ]; then
COOKIE="$EMQX_NODE_COOKIE"
elif [ ! -z `ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-setcookie (\S*)' | awk '{print $2}'` ]; then
COOKIE=`ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-setcookie (\S*)' | awk '{print $2}'`
else
COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' "$RUNNER_ETC_DIR/emqx.conf" 2> /dev/null | tail -1 | cut -d = -f 2-`
fi
if [ -z "$COOKIE" ]; then
echoerr "vm.args needs to have a -setcookie parameter."
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
exit 1
else
COOKIE_ARG="-setcookie $COOKIE"
@ -250,7 +247,7 @@ fi
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
# Support for IPv6 Dist. See: https://hub.fastgit.org/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=`egrep '^[ \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
PROTO_DIST_ARG=""
else
@ -329,18 +326,20 @@ case "$1" in
"$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
"$(relx_start_command)"
WAIT=${WAIT_FOR_ERLANG:-15}
while [ $WAIT -gt 0 ]; do
WAIT=`expr $WAIT - 1`
sleep 1
WAIT_TIME=${WAIT_FOR_ERLANG:-15}
while [ $WAIT_TIME -gt 0 ]; do
if ! relx_nodetool "ping" >/dev/null 2>&1; then
WAIT_TIME=`expr $WAIT_TIME - 1`
sleep 1
continue
fi
echo "emqx $REL_VSN is started successfully!"
sleep 1
if relx_nodetool "ping" >/dev/null 2>&1; then
echo "{{ emqx_description }} $REL_VSN is started successfully!"
exit 0
done
echo "The broker failed to start within ${WAIT_FOR_ERLANG:-15} seconds,"
echo "see the output of './bin/emqx console' for more information."
fi
done && echo "{{ emqx_description }} $REL_VSN failed to start within ${WAIT_FOR_ERLANG:-15} seconds,"
echo "see the output of '$0 console' for more information."
echo "If you want to wait longer, set the environment variable"
echo "WAIT_FOR_ERLANG to the number of seconds to wait."
exit 1
@ -358,24 +357,9 @@ case "$1" in
done
;;
restart)
#generate app.config and vm.args
generate_config
## Restart the VM without exiting the process
if ! relx_nodetool "restart" $CONFIG_ARGS; then
exit 1
fi
;;
reboot)
#generate app.config and vm.args
generate_config
## Restart the VM completely (uses heart to restart it)
if ! relx_nodetool "reboot" $CONFIG_ARGS; then
exit 1
fi
restart|reboot)
echo "{{ emqx_description }} $REL_VSN is stopped: $($RUNNER_BIN_DIR/emqx stop)"
$RUNNER_BIN_DIR/emqx start
;;
pid)

View File

@ -15,9 +15,9 @@
:: Set variables that describe the release
@set rel_name=emqx
@set rel_vsn=v4.0.0
@set erts_vsn=10.3
@set erl_opts=
@set rel_vsn={{ rel_vsn }}
@set erts_vsn={{ erts_vsn }}
@set erl_opts={{ erl_opts }}
@set script=%~n0
@ -138,11 +138,7 @@
@goto :eof
:generate_app_config
@set mergeconf_cmd=%escript% %nodetool% mergeconf %etc_dir%\emqx.conf %etc_dir%\plugins %data_dir%\configs
@for /f %%Z in ('%%mergeconf_cmd%%') do @(
set merged_app_conf=%%Z
)
@set gen_config_cmd=%escript% %cuttlefish% -s %rel_dir%\schema -c %merged_app_conf% -d %data_dir%\configs generate
@set gen_config_cmd=%escript% %cuttlefish% -i %rel_dir%\emqx.schema -c %etc_dir%\emqx.conf -d %data_dir%\configs generate
@for /f "delims=" %%A in ('%%gen_config_cmd%%') do @(
set generated_config_args=%%A
)
@ -180,7 +176,7 @@
@call :generate_app_config
:: Install the service
@set args="-boot %boot_script% %sys_config% %generated_config_args% -mnesia dir '%mnesia_dir%'"
@set description=EMQ node %node_name% in %rootdir%
@set description=EMQX node %node_name% in %rootdir%
@if "" == "%2" (
%erlsrv% add %service_name% %node_type% "%node_name%" -on restart -c "%description%" ^
-i "emqx" -w "%rootdir%" -m %erl_exe% -args %args% ^

View File

@ -7,9 +7,12 @@ set -e
REL_NAME="emqx"
## constants from relx template
RUNNER_ROOT_DIR="$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"
ERTS_VSN="10.3"
RUNNER_ETC_DIR="$RUNNER_ROOT_DIR/etc"
RUNNER_ROOT_DIR="{{ runner_root_dir }}"
ERTS_VSN="{{ erts_vsn }}"
RUNNER_ETC_DIR="{{ runner_etc_dir }}"
# Echo to stderr on errors
echoerr() { echo "$@" 1>&2; }
if [ -z "$WITH_EPMD" ]; then
EPMD_ARG="-start_epmd false -epmd_module nodetool_epmd"
@ -32,13 +35,19 @@ relx_nodetool() {
}
[ "x" = "x$EMQX_NODE_NAME" ] || NAME_ARG="-name $EMQX_NODE_NAME"
# Extract the target node name from node.args
if [ -z "$NAME_ARG" ]; then
if [ ! -z "$EMQX_NODE_NAME" ]; then
NODENAME="$EMQX_NODE_NAME"
elif [ ! -z `ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-name (\S*)' | awk '{print $2}'` ]; then
NODENAME=`ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-name (\S*)' | awk '{print $2}'`
else
NODENAME=`egrep '^[ \t]*node.name[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
fi
if [ -z "$NODENAME" ]; then
echoerr "vm.args needs to have a -name parameter."
echoerr " -sname is not supported."
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
exit 1
else
NAME_ARG="-name ${NODENAME# *}"
@ -49,12 +58,18 @@ fi
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
[ "x" = "x$EMQX_NODE_COOKIE" ] || COOKIE_ARG="-setcookie $EMQX_NODE_COOKIE"
# Extract the target cookie
if [ -z "$COOKIE_ARG" ]; then
if [ ! -z "$EMQX_NODE_COOKIE" ]; then
COOKIE="$EMQX_NODE_COOKIE"
elif [ ! -z `ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-setcookie (\S*)' | awk '{print $2}'` ]; then
COOKIE=`ps -ef | grep "$ERTS_PATH/beam.smp" | grep -o -E '\-setcookie (\S*)' | awk '{print $2}'`
else
COOKIE=`egrep '^[ \t]*node.cookie[ \t]*=[ \t]*' $RUNNER_ETC_DIR/emqx.conf 2> /dev/null | tail -1 | cut -d = -f 2-`
fi
if [ -z "$COOKIE" ]; then
echoerr "vm.args needs to have a -setcookie parameter."
echoerr "please check $RUNNER_ETC_DIR/emqx.conf"
exit 1
else
COOKIE_ARG="-setcookie $COOKIE"

View File

@ -4,9 +4,9 @@
:: Set variables that describe the release
@set rel_name=emqx
@set rel_vsn=v4.0.0
@set erts_vsn=10.3
@set erl_opts=
@set rel_vsn={{ rel_vsn }}
@set erts_vsn={{ erts_vsn }}
@set erl_opts={{ erl_opts }}
:: Discover the release root directory from the directory
:: of this script

View File

@ -20,7 +20,6 @@ main(Args) ->
end
end,
ok = do_with_halt(Args, "mnesia_dir", fun create_mnesia_dir/2),
ok = do_with_halt(Args, "mergeconf", fun mergeconf/3),
ok = do_with_halt(Args, "chkconfig", fun("-config", X) -> chkconfig(X) end),
ok = do_with_halt(Args, "chkconfig", fun chkconfig/1),
Args1 = do_with_ret(Args, "-name",
@ -67,8 +66,6 @@ main(Args) ->
io:format("~p\n", [rpc:call(TargetNode, init, stop, [], 60000)]);
["restart", "-config", ConfigFile | _RestArgs1] ->
io:format("~p\n", [rpc:call(TargetNode, emqx, restart, [ConfigFile], 60000)]);
["reboot", "-config", ConfigFile | _RestArgs1] ->
io:format("~p\n", [rpc:call(TargetNode, emqx, restart, [ConfigFile], 60000)]);
["rpc", Module, Function | RpcArgs] ->
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
[RpcArgs], 60000) of
@ -221,14 +218,14 @@ compile_epmd_module() ->
"dist_port(Name) when is_atom(Name) ->
dist_port(atom_to_list(Name));
dist_port(Name) when is_list(Name) ->
NodeName = re:replace(Name, \"@.*$\", \"\"),
Offset =
case re:run(NodeName, \"[0-9]+$\", [{capture, first, list}]) of
4370 + offset(Name).",
"offset(NodeName) ->
ShortName = re:replace(NodeName, \"@.*$\", \"\"),
case re:run(ShortName, \"[0-9]+$\", [{capture, first, list}]) of
nomatch -> 0;
{match, [OffsetAsString]} ->
list_to_integer(OffsetAsString)
end,
4370 + Offset."
(list_to_integer(OffsetAsString) rem 60000)
end."
]).
compile(Exprs) ->
@ -265,34 +262,6 @@ create_mnesia_dir(DataDir, NodeName) ->
io:format("~s", [MnesiaDir]),
halt(0).
mergeconf(EmqCfg, PluginsEtc, DestDir) ->
filelib:ensure_dir(DestDir),%% support brew on macosx
AppConf = filename:join(DestDir, appconf()),
case file:open(AppConf, [write]) of
{ok, DestFd} ->
CfgFiles = [EmqCfg | cfgfiles(PluginsEtc)],
lists:foreach(fun(CfgFile) ->
{ok, CfgData} = file:read_file(CfgFile),
file:write(DestFd, CfgData),
file:write(DestFd, <<"\n">>)
end, CfgFiles),
file:close(DestFd),
io:format("~s", [AppConf]),
halt(0);
{error, Error} ->
io:format(standard_error, ["Error opening file: ", AppConf, " ", file:format_error(Error), "\n"], []),
halt(1)
end.
appconf() ->
{{Y, M, D}, {H, MM, S}} = calendar:local_time(),
lists:flatten(
io_lib:format(
"app.~4..0w.~2..0w.~2..0w.~2..0w.~2..0w.~2..0w.conf", [Y, M, D, H, MM, S])).
cfgfiles(Dir) ->
[filename:join(Dir, CfgFile) || CfgFile <- filelib:wildcard("*.conf", Dir)].
chkconfig(File) ->
case file:consult(File) of
{ok, Terms} ->

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo $DIR
cmd=`python $DIR/remote_console_cmd.py $DIR`
echo $cmd
$cmd

View File

@ -1,40 +0,0 @@
import os
import sys
workdir = sys.argv[1]
project_dir = os.path.dirname(workdir)
def get_dgiot_config(key):
with open(os.path.join(project_dir, 'etc', 'emqx.conf'), 'r') as f:
for line in f.readlines():
if line.startswith(key):
return line.strip('\n').split('=')[1].strip()
def remote_node(node):
name, ip = node.split('@')
return name + '2' + '@' + ip
def ekka():
for plugin in os.listdir(os.path.join(project_dir, 'lib')):
if plugin.startswith('ekka'):
return os.path.join(project_dir, 'lib', plugin, 'ebin')
cmd = "erl" \
" -name {remote_node} " \
" -setcookie {cookie}" \
" -start_epmd false" \
" -epmd_module ekka_epmd" \
" -proto_dist ekka" \
" -pa {ekka}" \
" -remsh {node}".format(
remote_node=remote_node(get_dgiot_config('node.name')),
node=get_dgiot_config('node.name'),
ekka=ekka(),
cookie=get_dgiot_config('node.cookie')
)
print(cmd)

View File

@ -1,80 +0,0 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from erlport import Atom
from erlport import erlang
OK = 0
ERROR = 1
##--------------------------------------------------------------------
## Connection level
def init(conn, conninfo):
print(f'[python] established a conn={conn}, conninfo={conninfo}')
## set an integer num to the connection state
## it just a example structure to record the callback total times
state = 0
## subscribe the topic `t/dn` with qos0
subscribe(conn, b"t/dn", 0)
## return the initial conn's state
return (OK, state)
def received(conn, data, state):
print(f'[python] received data conn={conn}, data={data}, state={state}')
## echo the conn's data
send(conn, data)
## return the new conn's state
return (OK, state+1)
def terminated(conn, reason, state):
print(f'[python] terminated conn={conn}, reason={reason}, state={state}')
return
##--------------------------------------------------------------------
## Protocol/Session level
def deliver(conn, msgs, state):
print(f'[python] received messages: conn={conn}, msgs={msgs}, state={state}')
## echo the protocol/session messages
for msg in msgs:
msg[3] = (Atom(b'topic'), b't/up')
publish(conn, msg)
## return the new conn's state
return (OK, state+1)
##--------------------------------------------------------------------
## APIs
##--------------------------------------------------------------------
def send(conn, data):
erlang.call(Atom(b'shuwa_exproto'), Atom(b'send'), [conn, data])
return
def close(conn):
erlang.call(Atom(b'shuwa_exproto'), Atom(b'close'), [conn])
return
def register(conn, clientinfo):
erlang.call(Atom(b'shuwa_exproto'), Atom(b'register'), [conn, clientinfo])
return
def publish(conn, message):
erlang.call(Atom(b'shuwa_exproto'), Atom(b'publish'), [conn, message])
return
def subscribe(conn, topic, qos):
erlang.call(Atom(b'shuwa_exproto'), Atom(b'subscribe'), [conn, topic, qos])
return
def unsubscribe(conn, topic):
erlang.call(Atom(b'shuwa_exproto'), Atom(b'subscribe'), [conn, topic])
return

2
data/loaded_modules.tmpl Normal file
View File

@ -0,0 +1,2 @@
{emqx_mod_acl_internal, true}.
{emqx_mod_presence, true}.

View File

@ -1,23 +1,6 @@
{emqx_management, true}.
{emqx_recon, true}.
{emqx_retainer, true}.
{emqx_dashboard, {{enable_plugin_emqx_dashboard}}}.
{emqx_dashboard, true}.
{emqx_rule_engine, {{enable_plugin_emqx_rule_engine}}}.
{emqx_cube, {{enable_plugin_emqx_cube}}}.
{shuwa_license, {{enable_plugin_shuwa_license}}}.
{shuwa_public, {{enable_plugin_shuwa_public}}}.
{shuwa_mqtt, {{enable_plugin_shuwa_mqtt}}}.
{shuwa_framework, {{enable_plugin_shuwa_framework}}}.
{shuwa_device_shadow, {{enable_plugin_shuwa_device_shadow}}}.
{shuwa_parse, {{enable_plugin_shuwa_parse}}}.
{shuwa_bridge,{{enable_plugin_shuwa_bridge}}}.
{shuwa_evidence, {{enable_plugin_shuwa_evidence}}}.
{shuwa_group, {{enable_plugin_shuwa_group}}}.
{shuwa_web_manager,{{enable_plugin_shuwa_web_manager}}}.
{shuwa_exproto,{{enable_plugin_shuwa_exproto}}}.
{shuwa_td, {{enable_plugin_shuwa_td}}}.
{shuwa_task,{{enable_plugin_shuwa_task}}}.
{shuwa_api,{{enable_plugin_shuwa_api}}}.
{shuwa_smartmeter,{{enable_plugin_shuwa_smartmeter}}}.
{dgiot_meter,{{enable_plugin_dgiot_meter}}}.
{dgiot_amazedtu,{{enable_plugin_dgiot_amazedtu}}}.
{emqx_bridge_mqtt, {{enable_plugin_emqx_bridge_mqtt}}}.

View File

@ -0,0 +1,20 @@
apiVersion: v2
name: emqx
description: A Helm chart for EMQ X
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: v4.1-rc.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: v4.1-rc.1

View File

@ -0,0 +1,65 @@
# Introduction
This chart bootstraps an emqx deployment on a Kubernetes cluster using the Helm package manager.
# Prerequisites
+ Kubernetes 1.6+
+ Helm
# Installing the Chart
To install the chart with the release name `my-emqx`:
+ From github
```
$ git clone https://github.com/emqx/emqx-rel.git
$ cd emqx-rel/deploy/charts/emqx
$ helm install my-emqx .
```
+ From chart repos
```
helm repo add emqx https://repos.emqx.io/charts
helm install my-emqx emqx/emqx
```
> If you want to install an unstable version, you need to add `--devel` when you execute the `helm install` command.
# Uninstalling the Chart
To uninstall/delete the `my-emqx` deployment:
```
$ helm del my-emqx
```
# Configuration
The following table lists the configurable parameters of the emqx chart and their default values.
| Parameter | Description | Default Value |
| --- | --- | --- |
| `replicaCount` | It is recommended to have odd number of nodes in a cluster, otherwise the emqx cluster cannot be automatically healed in case of net-split. |3|
| `image.repository` | EMQ X Image name |emqx/emqx|
| `image.pullPolicy` | Global Docker registry secret names as an array |IfNotPresent|
| `persistence.enabled` | Enable EMQX persistence using PVC |false|
| `persistence.storageClass` | Storage class of backing PVC |`nil` (uses alpha storage class annotation)|
| `persistence.existingClaim` | EMQ X data Persistent Volume existing claim name, evaluated as a template |""|
| `persistence.accessMode` | PVC Access Mode for EMQX volume |ReadWriteOnce|
| `persistence.size` | PVC Storage Request for EMQX volume |20Mi|
| `resources` | CPU/Memory resource requests/limits |{}|
| `nodeSelector` | Node labels for pod assignment |`{}`|
| `tolerations` | Toleration labels for pod assignment |`[]`|
| `affinity` | Map of node/pod affinities |`{}`|
| `service.type` | Kubernetes Service type. |ClusterIP|
| `service.mqtt` | Port for MQTT. |1883|
| `service.mqttssl` | Port for MQTT(SSL). |8883|
| `service.mgmt` | Port for mgmt API. |8081|
| `service.ws` | Port for WebSocket/HTTP. |8083|
| `service.wss` | Port for WSS/HTTPS. |8084|
| `service.dashboard` | Port for dashboard. |18083|
| `service.nodePorts.mqtt` | Kubernetes node port for MQTT. |nil|
| `service.nodePorts.mqttssl` | Kubernetes node port for MQTT(SSL). |nil|
| `service.nodePorts.mgmt` | Kubernetes node port for mgmt API. |nil|
| `service.nodePorts.ws` | Kubernetes node port for WebSocket/HTTP. |nil|
| `service.nodePorts.wss` | Kubernetes node port for WSS/HTTPS. |nil|
| `service.nodePorts.dashboard` | Kubernetes node port for dashboard. |nil|
| `service.loadBalancerIP` | loadBalancerIP for Service | nil |
| `service.loadBalancerSourceRanges` | Address(es) that are allowed when service is LoadBalancer | [] |
| `service.annotations` | Service annotations | {}(evaluated as a template)|
| `emqxConfig` | Emqx configuration item, see the [documentation](https://hub.docker.com/r/emqx/emqx) | |
| `emqxAclConfig` | Emqx acl configuration item, see the [documentation](https://docs.emqx.io/broker/latest/en/advanced/acl-file.html) | |

View File

@ -0,0 +1,136 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "emqx.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
helm.sh/chart: {{ include "emqx.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
serviceName: {{ include "emqx.fullname" . }}-headless
{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: emqx-data
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
helm.sh/chart: {{ include "emqx.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
annotations:
{{- if .Values.persistence.storageClass }}
volume.beta.kubernetes.io/storage-class: {{ .Values.persistence.storageClass | quote }}
{{- else }}
volume.alpha.kubernetes.io/storage-class: default
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- end }}
updateStrategy:
type: RollingUpdate
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
volumes:
- name: emqx-acl
configMap:
name: {{ include "emqx.fullname" . }}-acl
items:
- key: acl.conf
path: acl.conf
{{- if not .Values.persistence.enabled }}
- name: emqx-data
emptyDir: {}
{{- else if .Values.persistence.existingClaim }}
- name: emqx-data
persistentVolumeClaim:
{{- with .Values.persistence.existingClaim }}
claimName: {{ tpl . $ }}
{{- end }}
{{- end }}
{{- if .Values.emqxLicneseSecretName }}
- name: emqx-license
secret:
secretName: {{ .Values.emqxLicneseSecretName }}
{{- end }}
serviceAccountName: {{ include "emqx.fullname" . }}
securityContext:
fsGroup: 1000
containers:
- name: emqx
image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: mqtt
containerPort: {{ .Values.emqxConfig.EMQX_LISTENER__TCP__EXTERNAL | default 1883 }}
- name: mqttssl
containerPort: {{ .Values.emqxConfig.EMQX_LISTENER__SSL__EXTERNAL | default 8883 }}
- name: mgmt
containerPort: {{ .Values.emqxConfig.EMQX_MANAGEMENT__LISTENER__HTTP | default 8081 }}
- name: ws
containerPort: {{ .Values.emqxConfig.EMQX_LISTENER__WS__EXTERNAL | default 8083 }}
- name: wss
containerPort: {{ .Values.emqxConfig.EMQX_LISTENER__WSS__EXTERNAL | default 8084 }}
- name: dashboard
containerPort: {{ .Values.emqxConfig.EMQX_DASHBOARD__LISTENER__HTTP | default 18083 }}
envFrom:
- configMapRef:
name: {{ include "emqx.fullname" . }}-env
env:
- name: EMQX_NAME
value: {{ .Release.Name }}
- name: EMQX_CLUSTER__K8S__APP_NAME
value: {{ .Release.Name }}
- name: EMQX_CLUSTER__DISCOVERY
value: k8s
- name: EMQX_CLUSTER__K8S__SERVICE_NAME
value: {{ include "emqx.fullname" . }}-headless
- name: EMQX_CLUSTER__K8S__NAMESPACE
value: {{ .Release.Namespace }}
resources:
{{ toYaml .Values.resources | indent 12 }}
volumeMounts:
- name: emqx-data
mountPath: "/opt/emqx/data/mnesia"
- name: emqx-acl
mountPath: "/opt/emqx/etc/acl.conf"
subPath: "acl.conf"
{{ if .Values.emqxLicneseSecretName }}
- name: emqx-license
mountPath: "/opt/emqx/etc/emqx.lic"
subPath: "emqx.lic"
readOnly: true
{{ end }}
readinessProbe:
httpGet:
path: /status
port: {{ .Values.emqxConfig.EMQX_MANAGEMENT__LISTENER__HTTP | default 8081 }}
initialDelaySeconds: 5
periodSeconds: 5
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "emqx.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "emqx.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "emqx.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "emqx.fullname" . }}-env
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
helm.sh/chart: {{ include "emqx.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
data:
{{- range $index, $value := .Values.emqxConfig}}
{{$index}}: "{{ $value }}"
{{- end}}

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "emqx.fullname" . }}-acl
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
helm.sh/chart: {{ include "emqx.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
data:
"acl.conf": |
{{ .Values.emqxAclConfig }}

View File

@ -0,0 +1,34 @@
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: {{ .Release.Namespace }}
name: {{ include "emqx.fullname" . }}
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: {{ .Release.Namespace }}
name: {{ include "emqx.fullname" . }}
rules:
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
- watch
- list
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: {{ .Release.Namespace }}
name: {{ include "emqx.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ include "emqx.fullname" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "emqx.fullname" . }}
apiGroup: rbac.authorization.k8s.io

View File

@ -0,0 +1,122 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "emqx.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
helm.sh/chart: {{ include "emqx.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
{{- if eq .Values.service.type "LoadBalancer" }}
{{- if .Values.service.loadBalancerIP }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
{{- if .Values.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges: {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
{{- end }}
{{- end }}
ports:
- name: mqtt
port: {{ .Values.service.mqtt | default 1883 }}
protocol: TCP
targetPort: mqtt
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.mqtt)) }}
nodePort: {{ .Values.service.nodePorts.mqtt }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
- name: mqttssl
port: {{ .Values.service.mqttssl | default 8883 }}
protocol: TCP
targetPort: mqttssl
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.mqttssl)) }}
nodePort: {{ .Values.service.nodePorts.mqttssl }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
- name: mgmt
port: {{ .Values.service.mgmt | default 8081 }}
protocol: TCP
targetPort: mgmt
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.mgmt)) }}
nodePort: {{ .Values.service.nodePorts.mgmt }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
- name: ws
port: {{ .Values.service.ws | default 8083 }}
protocol: TCP
targetPort: ws
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.ws)) }}
nodePort: {{ .Values.service.nodePorts.ws }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
- name: wss
port: {{ .Values.service.wss | default 8084 }}
protocol: TCP
targetPort: wss
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.wss)) }}
nodePort: {{ .Values.service.nodePorts.wss }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
- name: dashboard
port: {{ .Values.service.dashboard | default 18083 }}
protocol: TCP
targetPort: dashboard
{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.dashboard)) }}
nodePort: {{ .Values.service.nodePorts.dashboard }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
selector:
app.kubernetes.io/name: {{ include "emqx.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "emqx.fullname" . }}-headless
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "emqx.name" . }}
helm.sh/chart: {{ include "emqx.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
type: ClusterIP
sessionAffinity: None
clusterIP: None
ports:
- name: mqtt
port: {{ .Values.service.mqtt | default 1883 }}
protocol: TCP
targetPort: mqtt
- name: mqttssl
port: {{ .Values.service.mqttssl | default 8883 }}
protocol: TCP
targetPort: mqttssl
- name: mgmt
port: {{ .Values.service.mgmt | default 8081 }}
protocol: TCP
targetPort: mgmt
- name: ws
port: {{ .Values.service.ws | default 8083 }}
protocol: TCP
targetPort: ws
- name: wss
port: {{ .Values.service.wss | default 8084 }}
protocol: TCP
targetPort: wss
- name: dashboard
port: {{ .Values.service.dashboard | default 18083 }}
protocol: TCP
targetPort: dashboard
selector:
app.kubernetes.io/name: {{ include "emqx.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}

View File

@ -0,0 +1,137 @@
## Default values for emqx.
## This is a YAML-formatted file.
## Declare variables to be passed into your templates.
## It is recommended to have odd number of nodes in a cluster, otherwise the emqx cluster cannot be automatically healed in case of net-split.
replicaCount: 3
image:
repository: emqx/emqx
pullPolicy: IfNotPresent
persistence:
enabled: false
size: 20Mi
## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
## Default: volume.alpha.kubernetes.io/storage-class: default
# storageClass: "-"
accessMode: ReadWriteOnce
## Existing PersistentVolumeClaims
## The value is evaluated as a template
## So, for example, the name can depend on .Release or .Chart
# existingClaim: ""
resources: {}
# limits:
# cpu: 500m
# memory: 512Mi
# requests:
# cpu: 500m
# memory: 512Mi
## EMQX configuration item, see the documentation (https://github.com/emqx/emqx-docker#emq-x-configuration)
emqxConfig:
EMQX_CLUSTER__K8S__APISERVER: "https://kubernetes.default.svc:443"
## The address type is used to extract host from k8s service.
## Value: ip | dns | hostname
## NoteHostname is only supported after v4.0-rc.2
EMQX_CLUSTER__K8S__ADDRESS_TYPE: "hostname"
EMQX_CLUSTER__K8S__SUFFIX: "svc.cluster.local"
## if EMQX_CLUSTER__K8S__ADDRESS_TYPE eq dns
# EMQX_CLUSTER__K8S__SUFFIX: "pod.cluster.local"
## --------------------------------------------------------------------
## [ACL](https://docs.emqx.io/broker/latest/en/advanced/acl-file.html)
## -type(who() :: all | binary() |
## {ipaddr, esockd_access:cidr()} |
## {client, binary()} |
## {user, binary()}).
## -type(access() :: subscribe | publish | pubsub).
## -type(topic() :: binary()).
## -type(rule() :: {allow, all} |
## {allow, who(), access(), list(topic())} |
## {deny, all} |
## {deny, who(), access(), list(topic())}).
## --------------------------------------------------------------------
emqxAclConfig: >
{allow, {user, "dashboard"}, subscribe, ["$SYS/#"]}.
{allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.
{deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.
{allow, all}.
## EMQX Enterprise Edition requires manual creation of a Secret containing the licensed content. Write the name of Secret to the value of "emqxLicneseSecretName"
## Example:
## kubectl create secret generic emqx-license-secret-name --from-file=/path/to/emqx.lic
emqxLicneseSecretName:
service:
## Service type
##
type: ClusterIP
## Port for MQTT
##
mqtt: 1883
## Port for MQTT(SSL)
##
mqttssl: 8883
## Port for mgmt API
##
mgmt: 8081
## Port for WebSocket/HTTP
##
ws: 8083
## Port for WSS/HTTPS
##
wss: 8084
## Port for dashboard
##
dashboard: 18083
## Specify the nodePort(s) value for the LoadBalancer and NodePort service types.
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
##
nodePorts:
mqtt:
mqttssl:
mgmt:
ws:
wss:
dashboard:
## Set the LoadBalancer service type to internal only.
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
##
# loadBalancerIP:
## Load Balancer sources
## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service
## Example:
## loadBalancerSourceRanges:
## - 10.10.10.0/24
##
loadBalancerSourceRanges: []
## Provide any additional annotations which may be required. Evaluated as a template
##
annotations: {}
nodeSelector: {}
tolerations: []
affinity: {}
## TODO:
ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
path: /
hosts:
- chart-example.local
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local

View File

@ -1,5 +1,5 @@
ARG BUILD_FROM=erlang:22.1-alpine
ARG RUN_FROM=alpine:3.10
ARG BUILD_FROM=emqx/build-env:erl22.3-alpine-amd64
ARG RUN_FROM=alpine:3.11
FROM ${BUILD_FROM} AS builder
ARG QEMU_ARCH=x86_64
@ -9,13 +9,15 @@ COPY . /emqx_rel
RUN apk add git \
curl \
gcc \
g++ \
make \
perl \
ncurses-dev \
openssl-dev \
coreutils \
bsd-compat-headers \
libc-dev
libc-dev \
libstdc++
ARG EMQX_DEPS_DEFAULT_VSN=develop
ARG EMQX_NAME=emqx
@ -40,7 +42,7 @@ COPY deploy/docker/docker-entrypoint.sh deploy/docker/start.sh deploy/docker/tmp
COPY --from=builder /emqx_rel/_build/emqx*/rel/emqx /opt/emqx
RUN ln -s /opt/emqx/bin/* /usr/local/bin/
RUN apk add --no-cache ncurses-libs openssl sudo
RUN apk add --no-cache curl ncurses-libs openssl sudo libstdc++
WORKDIR /opt/emqx
@ -56,7 +58,7 @@ VOLUME ["/opt/emqx/log", "/opt/emqx/data", "/opt/emqx/lib", "/opt/emqx/etc"]
# emqx will occupy these port:
# - 1883 port for MQTT
# - 8080 for mgmt API
# - 8081 for mgmt API
# - 8083 for WebSocket/HTTP
# - 8084 for WSS/HTTPS
# - 8883 port for MQTT(SSL)
@ -65,7 +67,7 @@ VOLUME ["/opt/emqx/log", "/opt/emqx/data", "/opt/emqx/lib", "/opt/emqx/etc"]
# - 4369 for port mapping
# - 5369 for gen_rpc port mapping
# - 6369 for distributed node
EXPOSE 1883 8080 8083 8084 8883 11883 18083 4369 5369 6369
EXPOSE 1883 8081 8083 8084 8883 11883 18083 4369 5369 6369
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]

View File

@ -3,11 +3,11 @@ TARGET ?= emqx/emqx
QEMU_ARCH ?= x86_64
ARCH ?= amd64
QEMU_VERSION ?= v4.0.0
OS ?= alpine3.10
OS ?= alpine
## versioning
EMQX_DEPS_DEFAULT_VSN ?= develop
BUILD_VERSION ?= $(EMQX_DEPS_DEFAULT_VSN)
BUILD_VERSION ?= $(EMQX_DEPS_DEFAULT_VSN:v%=%)
EMQX_NAME = $(subst emqx/,,$(TARGET))
ARCH_LIST = amd64 arm64v8 arm32v7 i386 s390x
@ -18,9 +18,9 @@ all: build tag
.PHONY: prepare
prepare:
## Prepare the machine before any code installation scripts
@echo "PREPARE: Setting up dependencies."
@apt update -y
@apt install --only-upgrade docker-ce -y
# @echo "PREPARE: Setting up dependencies."
# @apt update -y
# @apt install --only-upgrade docker-ce -y
## Update docker configuration to enable docker manifest command
@echo "PREPARE: Updating docker configuration"
@ -57,8 +57,8 @@ build:
@cd ../.. \
&& docker build --no-cache \
--build-arg EMQX_DEPS_DEFAULT_VSN=$(EMQX_DEPS_DEFAULT_VSN) \
--build-arg BUILD_FROM=$(ARCH)/erlang:22.1-alpine \
--build-arg RUN_FROM=$(ARCH)/alpine:3.10 \
--build-arg BUILD_FROM=emqx/build-env:erl22.3-alpine-$(ARCH) \
--build-arg RUN_FROM=$(ARCH)/alpine:3.11 \
--build-arg EMQX_NAME=$(EMQX_NAME) \
--build-arg QEMU_ARCH=$(QEMU_ARCH) \
--tag $(TARGET):build-$(OS)-$(ARCH) \

View File

@ -1,58 +1,35 @@
# EMQ X Docker
# Quick reference
TODO: ...
+ **Where to get help**:
*EMQ* (Erlang MQTT Broker) is a distributed, massively scalable, highly extensible MQTT messaging broker written in Erlang/OTP.
https://emqx.io, https://github.com/emqx/emqx-rel, or https://github.com/emqx/emqx
Current docker image size: 47 MB
+ **Where to file issues:**
### Build emqx from source
https://github.com/emqx/emqx-rel/issues
1. Update docker configuration to enable docker manifest command and prepare qemu to build images other then x86_64
```bash
make prepare
```
2. Build Docker image
```bash
make build
```
3. Test the docker image with paho
```bash
make test
```
4. Tag Docker image
```bash
make tag
```
5. Save the docker image as a zip file
```bash
make save
```
6. Push Docker image
```bash
docker login
make push
make manifest-list
docker logout
```
7. Clean up the compiled image
```bash
make clear
```
+ **Supported architectures**
### Get emqx from the docker hub
`amd64`, `arm64v8`, `arm32v7`, `i386`, `s390x`
You can pull the image on the [docker hub](https://hub.docker.com/r/emqx/emqx).
```bash
docker pull emqx/emqx:latest
```
+ **Supported Docker versions**:
[the latest release](https://github.com/docker/docker-ce/releases/latest)
# What is EMQ X
[EMQ X MQTT broker](https://emqx.io/products/broker) is a fully open source, highly scalable, highly available distributed MQTT messaging broker for IoT, M2M and Mobile applications that can handle tens of millions of concurrent clients.
Starting from 3.0 release, *EMQ X* broker fully supports MQTT V5.0 protocol specifications and backward compatible with MQTT V3.1 and V3.1.1, as well as other communication protocols such as MQTT-SN, CoAP, LwM2M, WebSocket and STOMP. The 3.0 release of the *EMQ X* broker can scaled to 10+ million concurrent MQTT connections on one cluster.
# How to use this image
### Run emqx
Execute some command under this docker image
``docker run -d -v `pwd`:$(somewhere) emqx/emqx:$(tag) $(somecommand)``
``docker run -d --name emqx emqx/emqx:$(tag)``
For example
@ -90,7 +67,7 @@ These environment variables will ignore for configuration file.
#### EMQ X Configuration
> NOTE: All EMQ X Configuration in [etc/emqx.conf](https://github.com/emqx/emqx/blob/emqx30/etc/emqx.conf) could config by environment. The following list is just an example, not a complete configuration.
> NOTE: All EMQ X Configuration in [etc/emqx.conf](https://github.com/emqx/emqx/blob/master/etc/emqx.conf) could config by environment. The following list is just an example, not a complete configuration.
| Options | Default | Mapped | Description |
| ---------------------------| ------------------ | ------------------------- | ------------------------------------- |
@ -110,7 +87,7 @@ These environment variables will ignore for configuration file.
| EMQX_LISTENER__API__MGMT | 8080 | listener.api.mgmt | MGMT API port |
| EMQX_MQTT__MAX_PACKET_SIZE | 64KB | mqtt.max_packet_size | Max Packet Size Allowed |
The list is incomplete and may changed with [etc/emqx.conf](https://github.com/emqx/emqx/blob/emqx30/etc/emqx.conf) and plugin configuration files. But the mapping rule is similar.
The list is incomplete and may changed with [etc/emqx.conf](https://github.com/emqx/emqx/blob/master/etc/emqx.conf) and plugin configuration files. But the mapping rule is similar.
If set ``EMQX_NAME`` and ``EMQX_HOST``, and unset ``EMQX_NODE__NAME``, ``EMQX_NODE__NAME=$EMQX_NAME@$EMQX_HOST``.
@ -182,26 +159,97 @@ docker run -d --name emqx -p 18083:18083 -p 1883:1883 -p 4369:4369 \
### Cluster
You can specify a initial cluster and join.
EMQ X supports a variety of clustering methods, see our [documentation](https://docs.emqx.io/broker/latest/en/advanced/cluster.html#emqx-service-discovery) for details.
> Note: You must publsh port 4369, 5369 and range of port 6000-6999 for EMQ X Cluster.
Let's create a static node list cluster from docker-compose.
For example, using 6000-6100 for cluster.
+ Create `docker-compose.yaml`:
```bash
```
version: '3'
docker run -d --name emqx -p 18083:18083 -p 1883:1883 -p 4369:4369 -p 6000-6100:6000-6100 \
-e EMQX_NAME="emqx" \
-e EMQX_HOST="t.emqx.io" \
-e EMQX_LISTENER__TCP__EXTERNAL=1883 \
-e EMQX_JOIN_CLUSTER="emqx@t.emqx.io" \
emqx/emqx:latest
services:
emqx1:
image: emqx/emqx:v4.0.0
environment:
- "EMQX_NAME=emqx"
- "EMQX_HOST=node1.emqx.io"
- "EMQX_CLUSTER__DISCOVERY=static"
- "EMQX_CLUSTER__STATIC__SEEDS=emqx@node1.emqx.io, emqx@node2.emqx.io"
networks:
emqx-bridge:
aliases:
- node1.emqx.io
emqx2:
image: emqx/emqx:v4.0.0
environment:
- "EMQX_NAME=emqx"
- "EMQX_HOST=node2.emqx.io"
- "EMQX_CLUSTER__DISCOVERY=static"
- "EMQX_CLUSTER__STATIC__SEEDS=emqx@node1.emqx.io, emqx@node2.emqx.io"
networks:
emqx-bridge:
aliases:
- node2.emqx.io
networks:
emqx-bridge:
driver: bridge
```
+ Start the docker-compose cluster
```
$ docker-compose -p my_emqx up -d
```
+ View cluster
```
$ docker exec -it my_emqx_emqx1_1 sh -c "emqx_ctl cluster status"
Cluster status: #{running_nodes => ['emqx@node1.emqx.io','emqx@node2.emqx.io'],
stopped_nodes => []}
```
### Persistence
If you want to persist the EMQ X docker container, you need to keep the following directories:
+ `/opt/emqx/data`
+ `/opt/emqx/etc`
+ `/opt/emqx/log`
Since data in these folders are partially stored under the `/opt/emqx/data/mnesia/${node_name}`, the user also needs to reuse the same node name to see the previous state. In detail, one needs to specify the two environment variables: `EMQX_NAME` and `EMQX_HOST`, `EMQX_HOST` set as `127.0.0.1` or network alias would be useful.
In if you use docker-compose, the configuration would look something like this:
```
volumes:
vol-emqx-data:
name: foo-emqx-data
vol-emqx-etc:
name: foo-emqx-etc
vol-emqx-log:
name: foo-emqx-log
services:
emqx:
image: emqx/emqx:v4.0.0
restart: always
environment:
EMQX_NAME: foo_emqx
EMQX_HOST: 127.0.0.1
volumes:
- vol-emqx-data:/opt/emqx/data
- vol-emqx-etc:/opt/emqx/etc
- vol-emqx-log:/opt/emqx/log
```
### Kernel Tuning
Under linux host machine, the easiest way is [tuning host machine's kernel](http://emqttd-docs.readthedocs.io/en/latest/tune.html).
Under linux host machine, the easiest way is [tuning host machine's kernel](https://docs.emqx.io/broker/latest/en/tutorial/turn.html#turning-guide).
If you want tune linux kernel by docker, you must ensure your docker is latest version (>=1.12).
@ -233,3 +281,4 @@ docker run -d --name emqx -p 18083:18083 -p 1883:1883 -p 4369:4369 \
+ [@je-al](https://github.com/emqx/emqx-docker/issues/2)
+ [@RaymondMouthaan](https://github.com/emqx/emqx-docker/pull/91)
+ [@zhongjiewu](https://github.com/emqx/emqx/issues/3427)

View File

@ -34,9 +34,13 @@ fi
if [[ -z "$EMQX_HOST" ]]; then
if [[ "$EMQX_CLUSTER__K8S__ADDRESS_TYPE" == "dns" ]] && [[ ! -z "$EMQX_CLUSTER__K8S__NAMESPACE" ]];then
# DNSAddress=$(sed -n "/^${LOCAL_IP}/"p /etc/hosts | grep -e "$(hostname).*.${EMQX_CLUSTER__K8S__NAMESPACE}.svc.cluster.local" -o)
DNSAddress="${LOCAL_IP//./-}.${EMQX_CLUSTER__K8S__NAMESPACE}.pod.cluster.local"
EMQX_CLUSTER__K8S__SUFFIX=${EMQX_CLUSTER__K8S__SUFFIX:-"pod.cluster.local"}
DNSAddress="${LOCAL_IP//./-}.${EMQX_CLUSTER__K8S__NAMESPACE}.${EMQX_CLUSTER__K8S__SUFFIX}"
export EMQX_HOST="$DNSAddress"
elif [[ "$EMQX_CLUSTER__K8S__ADDRESS_TYPE" == "hostname" ]] && [[ ! -z "$EMQX_CLUSTER__K8S__NAMESPACE" ]]; then
EMQX_CLUSTER__K8S__SUFFIX=${EMQX_CLUSTER__K8S__SUFFIX:-"svc.cluster.local"}
HostAddress=$(sed -n "/^${LOCAL_IP}/"p /etc/hosts | grep -e "$(hostname).*.${EMQX_CLUSTER__K8S__NAMESPACE}.${EMQX_CLUSTER__K8S__SUFFIX}" -o)
export EMQX_HOST="$HostAddress"
else
export EMQX_HOST="$LOCAL_IP"
fi
@ -46,10 +50,6 @@ if [[ -z "$EMQX_WAIT_TIME" ]]; then
export EMQX_WAIT_TIME=5
fi
if [[ -z "$EMQX_NODE__NAME" ]]; then
export EMQX_NODE__NAME="$EMQX_NAME@$EMQX_HOST"
fi
if [[ -z "$EMQX_NODE_NAME" ]]; then
export EMQX_NODE_NAME="$EMQX_NAME@$EMQX_HOST"
fi
@ -117,14 +117,22 @@ do
# Config in emq.conf
if [[ ! -z "$(cat $CONFIG |grep -E "^(^|^#*|^#*\s*)$VAR_NAME")" ]]; then
echo "$VAR_NAME=$(eval echo \$$VAR_FULL_NAME)"
if [[ -z "$(eval echo \$$VAR_FULL_NAME)" ]]; then
echo "$(sed -r "s/(^\s*)($VAR_NAME\s*=\s*.*)/#\2/g" $CONFIG)" > $CONFIG
else
echo "$(sed -r "s/(^#*\s*)($VAR_NAME)\s*=\s*(.*)/\2 = $(eval echo \$$VAR_FULL_NAME|sed -e 's/\//\\\//g')/g" $CONFIG)" > $CONFIG
fi
fi
# Config in plugins/*
for CONFIG_PLUGINS_FILE in $(ls $CONFIG_PLUGINS); do
if [[ ! -z "$(cat $CONFIG_PLUGINS/$CONFIG_PLUGINS_FILE |grep -E "^(^|^#*|^#*\s*)$VAR_NAME")" ]]; then
echo "$VAR_NAME=$(eval echo \$$VAR_FULL_NAME)"
if [[ -z "$(eval echo \$$VAR_FULL_NAME)" ]]; then
echo "$(sed -r "s/(^\s*)($VAR_NAME\s*=\s*.*)/#\2/g" $CONFIG_PLUGINS/$CONFIG_PLUGINS_FILE)" > $CONFIG_PLUGINS/$CONFIG_PLUGINS_FILE
else
echo "$(sed -r "s/(^#*\s*)($VAR_NAME)\s*=\s*(.*)/\2 = $(eval echo \$$VAR_FULL_NAME|sed -e 's/\//\\\//g')/g" $CONFIG_PLUGINS/$CONFIG_PLUGINS_FILE)" > $CONFIG_PLUGINS/$CONFIG_PLUGINS_FILE
fi
fi
done
fi
# Config template such like {{ platform_etc_dir }}

View File

@ -17,20 +17,7 @@ emqx_exit(){
/opt/emqx/bin/emqx start || emqx_exit
tail -f /opt/emqx/log/emqx.log.1 &
# Wait and ensure emqx status is running
WAIT_TIME=0
while [[ -z "$(/opt/emqx/bin/emqx_ctl status |grep 'is running'|awk '{print $1}')" ]]
do
sleep 1
echo "['$(date -u +"%Y-%m-%dT%H:%M:%SZ")']:waiting emqx"
WAIT_TIME=$((WAIT_TIME+1))
if [[ $WAIT_TIME -gt $EMQX_WAIT_TIME ]]; then
echo "['$(date -u +"%Y-%m-%dT%H:%M:%SZ")']:timeout error"
exit 1
fi
done
tail -f /opt/emqx/log/erlang.log.1 &
# Sleep 5 seconds to wait for the loaded plugins catch up.
sleep 5
@ -43,15 +30,16 @@ echo "['$(date -u +"%Y-%m-%dT%H:%M:%SZ")']:emqx start"
# and docker dispatching system can known and restart this container.
NEW_LOG_NUM=2
IDLE_TIME=0
while [[ $IDLE_TIME -lt 5 ]]
do
MGMT_CONF='/opt/emqx/etc/plugins/emqx_management.conf'
MGMT_PORT=$(sed -n -r '/^management.listener.http[ \t]=[ \t].*$/p' $MGMT_CONF | sed -r 's/^management.listener.http = (.*)$/\1/g')
while [[ $IDLE_TIME -lt 5 ]]; do
IDLE_TIME=$((IDLE_TIME+1))
if [[ ! -z "$(/opt/emqx/bin/emqx_ctl status |grep 'is running'|awk '{print $1}')" ]]; then
if curl http://localhost:${MGMT_PORT}/status >/dev/null 2>&1; then
IDLE_TIME=0
# Print the latest emqx.log
if [[ -f /opt/emqx/log/emqx.log.${NEW_LOG_NUM} ]];then
tail -f /opt/emqx/log/emqx.log.${NEW_LOG_NUM} &
[[ ! -z $(ps -ef |grep "tail -f /opt/emqx/log/emqx.log" | grep -vE "grep|emqx.log.${NEW_LOG_NUM}" | awk '{print $1}') ]] && kill $(ps -ef |grep "tail -f /opt/emqx/log/emqx.log" | grep -vE "grep|emqx.log.${NEW_LOG_NUM}" | awk '{print $1}')
# Print the latest erlang.log
if [[ -f /opt/emqx/log/erlang.log.${NEW_LOG_NUM} ]];then
tail -f /opt/emqx/log/erlang.log.${NEW_LOG_NUM} &
[[ ! -z $(ps -ef |grep "tail -f /opt/emqx/log/erlang.log" | grep -vE "grep|erlang.log.${NEW_LOG_NUM}" | awk '{print $1}') ]] && kill $(ps -ef |grep "tail -f /opt/emqx/log/erlang.log" | grep -vE "grep|erlang.log.${NEW_LOG_NUM}" | awk '{print $1}')
NEW_LOG_NUM=$((NEW_LOG_NUM+1))
fi
else

View File

@ -6,7 +6,7 @@ ifneq ($(shell uname -s),Linux)
endif
# The version-release used for package
ifneq ($(shell echo $(EMQX_DEPS_DEFAULT_VSN) | grep -oE "v[0-9]+\.[0-9]+(\.[0-9]+)?"),)
PKG_VSN := $(EMQX_DEPS_DEFAULT_VSN)
PKG_VSN := $(EMQX_DEPS_DEFAULT_VSN:v%=%)
else
PKG_VSN := 4.0
endif

View File

@ -2,17 +2,15 @@
TOPDIR := /tmp/emqx
SRCDIR := $(TOPDIR)/$(PKG_VSN)
BUILT := $(SRCDIR)/BUILT
DEB_VSN := $(PKG_VSN:v%=%)
ARCH := $(shell dpkg --print-architecture)
SOURCE_PKG := $(EMQX_NAME)_$(DEB_VSN)_$(ARCH)
TARGET_PKG := $(EMQX_NAME)-$(SYSTEM)-$(PKG_VSN)_$(ARCH)
SOURCE_PKG := $(EMQX_NAME)_$(PKG_VSN)_$(shell dpkg --print-architecture)
TARGET_PKG := $(EMQX_NAME)-$(SYSTEM)-$(PKG_VSN)_$(shell uname -m)
.PHONY: all
all: | $(BUILT)
cp -r debian $(SRCDIR)/
sed -i "s#<DATETIME>#$(shell date -u '+%a, %d %b %Y %T %z')#g" $(SRCDIR)/debian/changelog
sed -i "s#<VERSION>#$(DEB_VSN)#g" $(SRCDIR)/debian/changelog
sed -i "s#<VERSION>#$(PKG_VSN)#g" $(SRCDIR)/debian/changelog
if [ ! -z $(shell echo $(EMQX_NAME) |grep edge) ]; then \
sed -i "s/emqx-pkg/emqx-edge-pkg/g" $(SRCDIR)/debian/rules; \
sed -i "s debian/emqx debian/emqx-edge g" $(SRCDIR)/debian/rules; \

View File

@ -8,13 +8,19 @@ space := $(none) $(none)
RPM_VSN ?= $(shell echo $(PKG_VSN) | grep -oE "[0-9]+\.[0-9]+(\.[0-9]+)?")
RPM_REL ?= $(shell echo $(PKG_VSN) | grep -oE "(alpha|beta|rc)\.[0-9]")
TARGET_PKG := $(EMQX_NAME)-$(SYSTEM)-v$(RPM_VSN)-$(RPM_REL).x86_64
ARCH:=$(shell uname -m)
ifeq ($(ARCH),mips64)
ARCH:=mips64el
endif
TARGET_PKG := $(EMQX_NAME)-$(SYSTEM)-$(RPM_VSN)-$(RPM_REL).$(ARCH)
ifeq ($(RPM_REL),)
# no tail
RPM_REL := 1
TARGET_PKG := $(EMQX_NAME)-$(SYSTEM)-v$(RPM_VSN).x86_64
TARGET_PKG := $(EMQX_NAME)-$(SYSTEM)-$(RPM_VSN).$(ARCH)
endif
SOURCE_PKG := emqx-$(SYSTEM)-v$(RPM_VSN)-$(RPM_REL).x86_64
SOURCE_PKG := emqx-$(SYSTEM)-$(RPM_VSN)-$(RPM_REL).$(ARCH)
SYSTEMD := $(shell if command -v systemctl >/dev/null 2>&1; then echo yes; fi)
# Not $(PWD) as it does not work for make -C
@ -43,7 +49,7 @@ all: | $(BUILT)
--define "_sharedstatedir /var/lib" \
emqx.spec
mkdir -p $(EMQX_REL)/_packages/$(EMQX_NAME)
cp $(TOPDIR)/RPMS/x86_64/$(SOURCE_PKG).rpm $(EMQX_REL)/_packages/$(EMQX_NAME)/$(TARGET_PKG).rpm
cp $(TOPDIR)/RPMS/$(ARCH)/$(SOURCE_PKG).rpm $(EMQX_REL)/_packages/$(EMQX_NAME)/$(TARGET_PKG).rpm
$(BUILT):
mkdir -p $(TOPDIR) $(SRCDIR)

View File

@ -5,7 +5,8 @@
%define _log_dir %{_var}/log/%{_name}
%define _lib_home /usr/lib/%{_name}
%define _var_home %{_sharedstatedir}/%{_name}
%define _build_name_fmt %{_arch}/%{_name}%{?_ostype}-v%{_version}-%{_release}.%{_arch}.rpm
%define _build_name_fmt %{_arch}/%{_name}%{?_ostype}-%{_version}-%{_release}.%{_arch}.rpm
%define _build_id_links none
Name: %{_package_name}
Version: %{_version}
@ -16,6 +17,7 @@ License: Apache License Version 2.0
URL: https://www.emqx.io
BuildRoot: %{_tmppath}/%{_name}-%{_version}-root
Provides: %{_name}
AutoReq: 0
%description
EMQX, a distributed, massively scalable, highly extensible MQTT message broker written in Erlang/OTP.
@ -39,7 +41,7 @@ cp -R %{_reldir}/releases %{buildroot}%{_lib_home}/
cp -R %{_reldir}/bin %{buildroot}%{_lib_home}/
cp -R %{_reldir}/etc/* %{buildroot}%{_conf_dir}/
cp -R %{_reldir}/data/* %{buildroot}%{_var_home}/
install -m755 %{_service_src} %{buildroot}%{_service_dst}
install -m644 %{_service_src} %{buildroot}%{_service_dst}
%pre
if [ $1 = 1 ]; then

422
emqx.rebar.config Normal file
View File

@ -0,0 +1,422 @@
{plugins,[]}.
{edge_relx_overlay,[]}.
{edoc_opts,[{preprocess,true}]}.
{erl_opts,[warn_unused_vars,warn_shadow_vars,warn_unused_import,
warn_obsolete_guard,no_debug_info,compressed]}.
{overrides,[{add,[{erl_opts,[no_debug_info,compressed]}]}]}.
{xref_checks,[undefined_function_calls,undefined_functions,locals_not_used,
deprecated_function_calls,warnings_as_errors,
deprecated_functions]}.
{cover_enabled,true}.
{cover_opts,[verbose]}.
{cover_export_enabled,true}.
{post_hooks,[{"(linux|darwin|solaris|freebsd|netbsd|openbsd)",compile,
"./post-compile.sh"},
{"win32",compile,"post-compile.cmd"}]}.
{profiles,
[{emqx,
[{deps,
[{emqx,
{git,"https://hub.fastgit.org/emqx/emqx",
{tag,"release-4.2"}}},
{emqx_retainer,
{git,"https://hub.fastgit.org/emqx/emqx-retainer",
{tag,"release-4.2"}}},
{emqx_management,
{git,"https://hub.fastgit.org/emqx/emqx-management",
{tag,"release-4.2"}}},
{emqx_dashboard,
{git,"https://hub.fastgit.org/emqx/emqx-dashboard",
{tag,"release-4.2"}}},
{emqx_bridge_mqtt,
{git,"https://hub.fastgit.org/emqx/emqx-bridge-mqtt",
{tag,"release-4.2"}}},
{emqx_web_hook,
{git,"https://hub.fastgit.org/emqx/emqx-web-hook",
{tag,"release-4.2"}}},
{emqx_recon,
{git,"https://hub.fastgit.org/emqx/emqx-recon",
{tag,"release-4.2"}}},
{emqx_rule_engine,
{git,"https://hub.fastgit.org/emqx/emqx-rule-engine",
{tag,"release-4.2"}}},
{emqx_sasl,
{git,"https://hub.fastgit.org/emqx/emqx-sasl",
{tag,"release-4.2"}}},
{emqx_lua_hook,
{git,"https://hub.fastgit.org/emqx/emqx-lua-hook",
{tag,"release-4.2"}}},
{emqx_statsd,
{git,"https://hub.fastgit.org/emqx/emqx-statsd",
{tag,"release-4.2"}}},
{emqx_reloader,
{git,"https://hub.fastgit.org/emqx/emqx-reloader",
{tag,"release-4.2"}}},
{emqx_psk_file,
{git,"https://hub.fastgit.org/emqx/emqx-psk-file",
{tag,"release-4.2"}}},
{emqx_extension_hook,
{git,"https://hub.fastgit.org/emqx/emqx-extension-hook",
{tag,"release-4.2"}}}]},
{relx,
[{include_src,false},
{extended_start_script,false},
{generate_start_script,false},
{sys_config,false},
{vm_args,false},
{release,
{emqx,"release-4.2"},
[kernel,sasl,crypto,public_key,asn1,syntax_tools,ssl,jsx,
os_mon,inets,compiler,runtime_tools,cuttlefish,emqx,
{mnesia,load},
{ekka,load},
{emqx_retainer,load},
{emqx_management,load},
{emqx_dashboard,load},
{emqx_bridge_mqtt,load},
{emqx_web_hook,load},
{emqx_recon,load},
{emqx_rule_engine,load},
{emqx_sasl,load},
{emqx_lua_hook,load},
{emqx_extension_hook,load},
{emqx_statsd,load},
{emqx_reloader,load},
{emqx_psk_file,load},
{observer,load},
luerl,xmerl]},
{overlay,
[{mkdir,"etc/"},
{mkdir,"log/"},
{mkdir,"data/"},
{mkdir,"data/mnesia"},
{mkdir,"data/configs"},
{mkdir,"data/scripts"},
{template,"bin/emqx_env","bin/emqx_env"},
{template,"bin/emqx","bin/emqx"},
{template,"bin/emqx_ctl","bin/emqx_ctl"},
{template,"bin/emqx.cmd","bin/emqx.cmd"},
{template,"bin/emqx_ctl.cmd","bin/emqx_ctl.cmd"},
{copy,"{{output_dir}}/../../conf/plugins","etc/"},
{template,"{{output_dir}}/../../conf/emqx.conf",
"etc/emqx.conf"},
{template,"{{output_dir}}/../../conf/ssl_dist.conf",
"etc/ssl_dist.conf"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_bridge_mqtt.conf",
"etc/plugins/emqx_bridge_mqtt.conf"},
{template,"data/loaded_plugins.tmpl",
"data/loaded_plugins"},
{template,"data/loaded_modules.tmpl",
"data/loaded_modules"},
{copy,"{{output_dir}}/../../conf/acl.conf","etc/acl.conf"},
{copy,"bin/nodetool","bin/nodetool"},
{copy,"{{output_dir}}/../../conf/schema/emqx.schema",
"releases/{{rel_vsn}}/"},
{copy,"bin/install_upgrade_escript",
"bin/install_upgrade_escript"},
{template,
"{{output_dir}}/../../lib/emqx/etc/{{vm_args_file}}",
"etc/vm.args"},
{copy,"{{output_dir}}/../../lib/emqx/etc/certs","etc/"},
{copy,"{{output_dir}}/../../lib/cuttlefish/cuttlefish",
"bin/"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_psk_file.conf",
"etc/plugins/emqx_psk_file.conf"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_extension_hook.conf",
"etc/plugins/emqx_extension_hook.conf"},
{copy,
"{{output_dir}}/../../lib/emqx_psk_file/etc/psk.txt",
"etc/psk.txt"}]},
{overlay_vars,["vars-cloud.config","vars-bin.config"]}]}]},
{'emqx-pkg',
[{deps,
[{emqx,
{git,"https://hub.fastgit.org/emqx/emqx",
{tag,"release-4.2"}}},
{emqx_retainer,
{git,"https://hub.fastgit.org/emqx/emqx-retainer",
{tag,"release-4.2"}}},
{emqx_management,
{git,"https://hub.fastgit.org/emqx/emqx-management",
{tag,"release-4.2"}}},
{emqx_dashboard,
{git,"https://hub.fastgit.org/emqx/emqx-dashboard",
{tag,"release-4.2"}}},
{emqx_bridge_mqtt,
{git,"https://hub.fastgit.org/emqx/emqx-bridge-mqtt",
{tag,"release-4.2"}}},
{emqx_web_hook,
{git,"https://hub.fastgit.org/emqx/emqx-web-hook",
{tag,"release-4.2"}}},
{emqx_recon,
{git,"https://hub.fastgit.org/emqx/emqx-recon",
{tag,"release-4.2"}}},
{emqx_rule_engine,
{git,"https://hub.fastgit.org/emqx/emqx-rule-engine",
{tag,"release-4.2"}}},
{emqx_sasl,
{git,"https://hub.fastgit.org/emqx/emqx-sasl",
{tag,"release-4.2"}}},
{emqx_lua_hook,
{git,"https://hub.fastgit.org/emqx/emqx-lua-hook",
{tag,"release-4.2"}}},
{emqx_statsd,
{git,"https://hub.fastgit.org/emqx/emqx-statsd",
{tag,"release-4.2"}}},
{emqx_reloader,
{git,"https://hub.fastgit.org/emqx/emqx-reloader",
{tag,"release-4.2"}}},
{emqx_psk_file,
{git,"https://hub.fastgit.org/emqx/emqx-psk-file",
{tag,"release-4.2"}}},
{emqx_extension_hook,
{git,"https://hub.fastgit.org/emqx/emqx-extension-hook",
{tag,"release-4.2"}}}]},
{relx,
[{include_src,false},
{extended_start_script,false},
{generate_start_script,false},
{sys_config,false},
{vm_args,false},
{release,
{emqx,"release-4.2"},
[kernel,sasl,crypto,public_key,asn1,syntax_tools,ssl,jsx,
os_mon,inets,compiler,runtime_tools,cuttlefish,emqx,
{mnesia,load},
{ekka,load},
{emqx_retainer,load},
{emqx_management,load},
{emqx_dashboard,load},
{emqx_bridge_mqtt,load},
{emqx_web_hook,load},
{emqx_recon,load},
{emqx_rule_engine,load},
{emqx_sasl,load},
{emqx_lua_hook,load},
{emqx_extension_hook,load},
{emqx_statsd,load},
{emqx_reloader,load},
{emqx_psk_file,load},
{observer,load},
luerl,xmerl]},
{overlay,
[{mkdir,"etc/"},
{mkdir,"log/"},
{mkdir,"data/"},
{mkdir,"data/mnesia"},
{mkdir,"data/configs"},
{mkdir,"data/scripts"},
{template,"bin/emqx_env","bin/emqx_env"},
{template,"bin/emqx","bin/emqx"},
{template,"bin/emqx_ctl","bin/emqx_ctl"},
{template,"bin/emqx.cmd","bin/emqx.cmd"},
{template,"bin/emqx_ctl.cmd","bin/emqx_ctl.cmd"},
{copy,"{{output_dir}}/../../conf/plugins","etc/"},
{template,"{{output_dir}}/../../conf/emqx.conf",
"etc/emqx.conf"},
{template,"{{output_dir}}/../../conf/ssl_dist.conf",
"etc/ssl_dist.conf"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_bridge_mqtt.conf",
"etc/plugins/emqx_bridge_mqtt.conf"},
{template,"data/loaded_plugins.tmpl",
"data/loaded_plugins"},
{template,"data/loaded_modules.tmpl",
"data/loaded_modules"},
{copy,"{{output_dir}}/../../conf/acl.conf","etc/acl.conf"},
{copy,"bin/nodetool","bin/nodetool"},
{copy,"{{output_dir}}/../../conf/schema/emqx.schema",
"releases/{{rel_vsn}}/"},
{copy,"bin/install_upgrade_escript",
"bin/install_upgrade_escript"},
{template,
"{{output_dir}}/../../lib/emqx/etc/{{vm_args_file}}",
"etc/vm.args"},
{copy,"{{output_dir}}/../../lib/emqx/etc/certs","etc/"},
{copy,"{{output_dir}}/../../lib/cuttlefish/cuttlefish",
"bin/"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_psk_file.conf",
"etc/plugins/emqx_psk_file.conf"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_extension_hook.conf",
"etc/plugins/emqx_extension_hook.conf"},
{copy,
"{{output_dir}}/../../lib/emqx_psk_file/etc/psk.txt",
"etc/psk.txt"}]},
{overlay_vars,["vars-cloud.config","vars-pkg.config"]}]}]},
{'emqx-edge',
[{deps,
[{emqx,
{git,"https://hub.fastgit.org/emqx/emqx",
{tag,"release-4.2"}}},
{emqx_retainer,
{git,"https://hub.fastgit.org/emqx/emqx-retainer",
{tag,"release-4.2"}}},
{emqx_management,
{git,"https://hub.fastgit.org/emqx/emqx-management",
{tag,"release-4.2"}}},
{emqx_dashboard,
{git,"https://hub.fastgit.org/emqx/emqx-dashboard",
{tag,"release-4.2"}}},
{emqx_bridge_mqtt,
{git,"https://hub.fastgit.org/emqx/emqx-bridge-mqtt",
{tag,"release-4.2"}}},
{emqx_web_hook,
{git,"https://hub.fastgit.org/emqx/emqx-web-hook",
{tag,"release-4.2"}}},
{emqx_recon,
{git,"https://hub.fastgit.org/emqx/emqx-recon",
{tag,"release-4.2"}}},
{emqx_rule_engine,
{git,"https://hub.fastgit.org/emqx/emqx-rule-engine",
{tag,"release-4.2"}}},
{emqx_sasl,
{git,"https://hub.fastgit.org/emqx/emqx-sasl",
{tag,"release-4.2"}}}]},
{relx,
[{include_src,false},
{extended_start_script,false},
{generate_start_script,false},
{sys_config,false},
{vm_args,false},
{release,
{emqx,"release-4.2"},
[kernel,sasl,crypto,public_key,asn1,syntax_tools,ssl,jsx,
os_mon,inets,compiler,runtime_tools,cuttlefish,emqx,
{mnesia,load},
{ekka,load},
{emqx_retainer,load},
{emqx_management,load},
{emqx_dashboard,load},
{emqx_bridge_mqtt,load},
{emqx_web_hook,load},
{emqx_recon,load},
{emqx_rule_engine,load},
{emqx_sasl,load}]},
{overlay,
[{mkdir,"etc/"},
{mkdir,"log/"},
{mkdir,"data/"},
{mkdir,"data/mnesia"},
{mkdir,"data/configs"},
{mkdir,"data/scripts"},
{template,"bin/emqx_env","bin/emqx_env"},
{template,"bin/emqx","bin/emqx"},
{template,"bin/emqx_ctl","bin/emqx_ctl"},
{template,"bin/emqx.cmd","bin/emqx.cmd"},
{template,"bin/emqx_ctl.cmd","bin/emqx_ctl.cmd"},
{copy,"{{output_dir}}/../../conf/plugins","etc/"},
{template,"{{output_dir}}/../../conf/emqx.conf",
"etc/emqx.conf"},
{template,"{{output_dir}}/../../conf/ssl_dist.conf",
"etc/ssl_dist.conf"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_bridge_mqtt.conf",
"etc/plugins/emqx_bridge_mqtt.conf"},
{template,"data/loaded_plugins.tmpl",
"data/loaded_plugins"},
{template,"data/loaded_modules.tmpl",
"data/loaded_modules"},
{copy,"{{output_dir}}/../../conf/acl.conf","etc/acl.conf"},
{copy,"bin/nodetool","bin/nodetool"},
{copy,"{{output_dir}}/../../conf/schema/emqx.schema",
"releases/{{rel_vsn}}/"},
{copy,"bin/install_upgrade_escript",
"bin/install_upgrade_escript"},
{template,
"{{output_dir}}/../../lib/emqx/etc/{{vm_args_file}}",
"etc/vm.args"},
{copy,"{{output_dir}}/../../lib/emqx/etc/certs","etc/"},
{copy,"{{output_dir}}/../../lib/cuttlefish/cuttlefish",
"bin/"}]},
{overlay_vars,["vars-edge.config","vars-bin.config"]}]}]},
{'emqx-edge-pkg',
[{deps,
[{emqx,
{git,"https://hub.fastgit.org/emqx/emqx",
{tag,"release-4.2"}}},
{emqx_retainer,
{git,"https://hub.fastgit.org/emqx/emqx-retainer",
{tag,"release-4.2"}}},
{emqx_management,
{git,"https://hub.fastgit.org/emqx/emqx-management",
{tag,"release-4.2"}}},
{emqx_dashboard,
{git,"https://hub.fastgit.org/emqx/emqx-dashboard",
{tag,"release-4.2"}}},
{emqx_bridge_mqtt,
{git,"https://hub.fastgit.org/emqx/emqx-bridge-mqtt",
{tag,"release-4.2"}}},
{emqx_web_hook,
{git,"https://hub.fastgit.org/emqx/emqx-web-hook",
{tag,"release-4.2"}}},
{emqx_recon,
{git,"https://hub.fastgit.org/emqx/emqx-recon",
{tag,"release-4.2"}}},
{emqx_rule_engine,
{git,"https://hub.fastgit.org/emqx/emqx-rule-engine",
{tag,"release-4.2"}}},
{emqx_sasl,
{git,"https://hub.fastgit.org/emqx/emqx-sasl",
{tag,"release-4.2"}}}]},
{relx,
[{include_src,false},
{extended_start_script,false},
{generate_start_script,false},
{sys_config,false},
{vm_args,false},
{release,
{emqx,"release-4.2"},
[kernel,sasl,crypto,public_key,asn1,syntax_tools,ssl,jsx,
os_mon,inets,compiler,runtime_tools,cuttlefish,emqx,
{mnesia,load},
{ekka,load},
{emqx_retainer,load},
{emqx_management,load},
{emqx_dashboard,load},
{emqx_bridge_mqtt,load},
{emqx_web_hook,load},
{emqx_recon,load},
{emqx_rule_engine,load},
{emqx_sasl,load}]},
{overlay,
[{mkdir,"etc/"},
{mkdir,"log/"},
{mkdir,"data/"},
{mkdir,"data/mnesia"},
{mkdir,"data/configs"},
{mkdir,"data/scripts"},
{template,"bin/emqx_env","bin/emqx_env"},
{template,"bin/emqx","bin/emqx"},
{template,"bin/emqx_ctl","bin/emqx_ctl"},
{template,"bin/emqx.cmd","bin/emqx.cmd"},
{template,"bin/emqx_ctl.cmd","bin/emqx_ctl.cmd"},
{copy,"{{output_dir}}/../../conf/plugins","etc/"},
{template,"{{output_dir}}/../../conf/emqx.conf",
"etc/emqx.conf"},
{template,"{{output_dir}}/../../conf/ssl_dist.conf",
"etc/ssl_dist.conf"},
{template,
"{{output_dir}}/../../conf/plugins/emqx_bridge_mqtt.conf",
"etc/plugins/emqx_bridge_mqtt.conf"},
{template,"data/loaded_plugins.tmpl",
"data/loaded_plugins"},
{template,"data/loaded_modules.tmpl",
"data/loaded_modules"},
{copy,"{{output_dir}}/../../conf/acl.conf","etc/acl.conf"},
{copy,"bin/nodetool","bin/nodetool"},
{copy,"{{output_dir}}/../../conf/schema/emqx.schema",
"releases/{{rel_vsn}}/"},
{copy,"bin/install_upgrade_escript",
"bin/install_upgrade_escript"},
{template,
"{{output_dir}}/../../lib/emqx/etc/{{vm_args_file}}",
"etc/vm.args"},
{copy,"{{output_dir}}/../../lib/emqx/etc/certs","etc/"},
{copy,"{{output_dir}}/../../lib/cuttlefish/cuttlefish",
"bin/"}]},
{overlay_vars,["vars-edge.config","vars-pkg.config"]}]}]}]}.

View File

@ -14,10 +14,6 @@ for /d %%i in ("lib\emqx*") do call :conf %%i
for /d %%i in ("lib\emqx*") do call :schema %%i
for /d %%i in ("lib\shuwa*") do call :conf %%i
for /d %%i in ("lib\shuwa*") do call :schema %%i
exit 0
:conf
@ -41,10 +37,7 @@ popd
:schema
pushd %1
for %%f in ("priv\*.schema") do (
::echo %%f
copy %%f "%REBAR_BUILD_DIR%\conf\schema\"
)
copy priv\emqx.schema "%REBAR_BUILD_DIR%\conf\schema\"
popd
:end

View File

@ -27,7 +27,5 @@ done
## Collect all schema files
mkdir -p conf/schema
for schema in lib/*/priv/*.schema; do
cp ${schema} conf/schema/
done
cp lib/emqx/priv/emqx.schema conf/schema/

View File

@ -5,37 +5,24 @@
[emqx,
emqx_retainer,
emqx_management,
emqx_reloader,
emqx_delayed_publish,
emqx_dashboard,
emqx_bridge_mqtt,
emqx_web_hook,
emqx_recon,
emqx_psk_file,
emqx_rule_engine
emqx_rule_engine,
emqx_sasl
]}.
%% Added to deps list for 'cloud' profile
{cloud_deps,
[
emqx_dashboard,
shuwa_statsd,
shuwa_public,
shuwa_license,
shuwa_framework,
shuwa_parse,
shuwa_mqtt,
shuwa_device_shadow,
shuwa_bridge,
shuwa_evidence,
shuwa_group,
shuwa_web_manager,
shuwa_task,
shuwa_exproto,
shuwa_td,
shuwa_api,
shuwa_smartmeter,
dgiot_meter
[emqx_lua_hook,
emqx_statsd,
emqx_reloader,
emqx_psk_file,
emqx_extension_hook
]}.
{edge_deps, [emqx_cube]}.
{edge_deps, []}.
{relx,
[{include_src, false},
@ -43,7 +30,7 @@
{generate_start_script, false},
{sys_config, false},
{vm_args, false},
{release, {dgiot, git_describe},
{release, {emqx, git_describe},
[kernel,
sasl,
crypto,
@ -51,45 +38,23 @@
asn1,
syntax_tools,
ssl,
jsx,
os_mon,
inets,
compiler,
runtime_tools,
gproc,
esockd,
getopt,
cuttlefish,
jsx,
cowboy,
lager,
poolboy,
emqx,
{mnesia, load},
{ekka, load},
{emqx_recon, load},
{emqx_management, load},
{emqx_rule_engine, load},
{emqx_retainer, load},
{emqx_reloader, load},
{emqx_delayed_publish, load},
{emqx_psk_file, load},
{shuwa_statsd, load},
{shuwa_public, load},
{shuwa_parse, load},
{shuwa_mqtt, load},
{shuwa_license, load},
{shuwa_framework, load},
{shuwa_device_shadow,load},
{shuwa_web_manager, load},
{shuwa_group,load},
{shuwa_bridge, load},
{shuwa_task, load},
{shuwa_evidence, load},
{shuwa_exproto,load},
{shuwa_td, load},
{shuwa_api,load},
{shuwa_smartmeter,load},
{dgiot_meter,load}
{emqx_management, load},
{emqx_dashboard, load},
{emqx_bridge_mqtt, load},
{emqx_web_hook, load},
{emqx_recon, load},
{emqx_rule_engine, load},
{emqx_sasl, load}
]},
{overlay,
[{mkdir,"etc/"},
@ -99,52 +64,56 @@
{mkdir,"data/configs"},
{mkdir,"data/scripts"},
{template,"bin/emqx_env","bin/emqx_env"},
{template,"bin/dgiot_env","bin/dgiot_env"},
{template,"bin/emqx","bin/emqx"},
{template,"bin/dgiot","bin/dgiot"},
{template,"bin/emqx_ctl","bin/emqx_ctl"},
{template,"bin/dgiot_ctl","bin/dgiot_ctl"},
{template,"bin/emqx.cmd","bin/emqx.cmd"},
{template,"bin/dgiot.cmd","bin/dgiot.cmd"},
{template,"bin/emqx_ctl.cmd","bin/emqx_ctl.cmd"},
{template,"bin/dgiot_ctl.cmd","bin/dgiot_ctl.cmd"},
{copy,"{{output_dir}}/../../conf/plugins","etc/"},
{template,"{{output_dir}}/../../conf/emqx.conf","etc/emqx.conf"},
{template,"{{output_dir}}/../../conf/ssl_dist.conf","etc/ssl_dist.conf"},
{template,"{{output_dir}}/../../conf/plugins/emqx_psk_file.conf", "etc/plugins/emqx_psk_file.conf"},
{template,"{{output_dir}}/../../conf/plugins/emqx_bridge_mqtt.conf", "etc/plugins/emqx_bridge_mqtt.conf"},
{template, "data/loaded_plugins.tmpl", "data/loaded_plugins"},
{template, "data/loaded_modules.tmpl", "data/loaded_modules"},
{copy,"{{output_dir}}/../../conf/acl.conf","etc/acl.conf"},
{copy,"bin/nodetool","bin/nodetool"},
{copy, "data/dvmeter_info.dets","data/"},
{copy,"{{output_dir}}/../../conf/schema","releases/{{rel_vsn}}/"},
{copy,"{{output_dir}}/../../conf/schema/emqx.schema","releases/{{rel_vsn}}/"},
{copy,"bin/install_upgrade_escript", "bin/install_upgrade_escript"},
{template,"{{output_dir}}/../../lib/emqx/etc/{{vm_args_file}}","etc/vm.args"},
{copy, "{{output_dir}}/../../lib/emqx/etc/certs","etc/"},
{copy, "{{output_dir}}/../../lib/cuttlefish/cuttlefish","bin/"},
{copy, "{{output_dir}}/../../lib/emqx_psk_file/etc/psk.txt", "etc/psk.txt"}
{copy, "{{output_dir}}/../../lib/cuttlefish/cuttlefish","bin/"}
]}
]}.
{elixir_relx_apps, []}.
{edge_relx_apps, [{emqx_cube, load}]}.
{edge_relx_apps, []}.
{cloud_relx_apps,
[
{emqx_dashboard, load},
{emqx_lua_hook, load},
{emqx_extension_hook, load},
{emqx_statsd, load},
{emqx_reloader, load},
{emqx_psk_file, load},
{observer, load},
luerl,
xmerl
]}.
{cloud_relx_overlay,
[
[{template,"{{output_dir}}/../../conf/plugins/emqx_psk_file.conf", "etc/plugins/emqx_psk_file.conf"},
{template,"{{output_dir}}/../../conf/plugins/emqx_extension_hook.conf", "etc/plugins/emqx_extension_hook.conf"},
{copy, "{{output_dir}}/../../lib/emqx_psk_file/etc/psk.txt", "etc/psk.txt"}
]}.
{edge_relx_overlay, []}.
{edoc_opts, [{preprocess,true}]}.
{erl_opts, [warn_unused_vars,warn_shadow_vars,warn_unused_import,
warn_obsolete_guard,debug_info]}.
warn_obsolete_guard,no_debug_info,compressed]}.
{overrides, [{add, [{erl_opts, [no_debug_info, compressed]}]}]}.
{xref_checks, [undefined_function_calls,undefined_functions,locals_not_used,
deprecated_function_calls,warnings_as_errors,

View File

@ -65,28 +65,9 @@ MakeDep =
{Name, Tag} when is_list(Tag) -> {Name, {tag, Tag}};
Name when is_atom(Name) -> {Name, DefaultDepRef}
end,
{URL, NewGitRef} =
case atom_to_list(AppName) of
"emqx" ->
RepoName = string:join(string:tokens(atom_to_list(AppName), "_"), "-"),
{"https://gitee.com/fastdgiot/" ++ RepoName ++ ".git", GitRef};
_ ->
case string:split(atom_to_list(AppName),"_") of
["emqx", _] ->
RepoName = string:join(string:tokens(atom_to_list(AppName), "_"), "-"),
{"https://gitee.com/fastdgiot/" ++ RepoName ++ ".git",GitRef};
["dgiot", Mod] ->
RepoName = string:join(string:tokens(atom_to_list(AppName), "_"), "_"),
{"https://gitee.com/dgiiot/" ++ RepoName ++ ".git", {branch,"master"}};
["shuwa", Mod] ->
RepoName = string:join(string:tokens(atom_to_list(AppName), "_"), "_"),
{"https://gitee.com/fastdgiot/" ++ RepoName ++ ".git", {branch,"master"}};
_ ->
RepoName = string:join(string:tokens(atom_to_list(AppName), "_"), "-"),
{"https://gitee.com/fastdgiot/" ++ RepoName ++ ".git", GitRef}
end
end,
{AppName, {git, URL, NewGitRef}}
URL = "https://hub.fastgit.org/emqx/" ++ RepoName,
{AppName, {git, URL, GitRef}}
end,
MakeDeps = fun(Deps, DefaultDepRef, TestDeps) -> [MakeDep(App, DefaultDepRef) || App <- Deps] ++ TestDeps end,
@ -117,7 +98,7 @@ DefaultDepRef =
false -> {branch, BRANCH}; %% not set
"" -> {branch, BRANCH}; %% set empty
MaybeTag ->
case re:run(MaybeTag, "v\[0-9\]+\.\[0-9\]+\.*") of
case re:run(MaybeTag, "[0-9\]+\.\[0-9\]+\.*") of
nomatch -> {branch, MaybeTag};
_ -> {tag, MaybeTag}
end
@ -126,13 +107,10 @@ DefaultDepRef =
%% ==============================================================================
%% Relx configs
%% ==============================================================================
GitDescribe = case DefaultDepRef of
{tag, EnvTag} -> EnvTag;
_Else ->
case catch lists:last(string:tokens(os:cmd("git tag -l \"v*\""), "\n")) of
{'EXIT', Reason} -> "";
Version -> Version
end
{tag, EnvTag} -> re:replace(EnvTag, "v", "", [global, {return ,list}]);
_Else -> lists:last(string:tokens(os:cmd("git tag -l \"v*\""), "\n"))
end,
Relx0 = Kf(relx, CONFIG2),
{release, {_, Vsn0}, RelxBaseApps0} = lists:keyfind(release, 1, Relx0),
@ -171,16 +149,16 @@ TestDeps = [ {meck, "0.8.13"} % hex
%% Profiles
%% ==============================================================================
Profiles =
[ {dgiot, [ {deps, MakeDeps(CloudDeps, DefaultDepRef, [])}
, {relx, RelxCloud([cloud, dev])}
[ {emqx, [ {deps, MakeDeps(CloudDeps, DefaultDepRef, [])}
, {relx, RelxCloud([cloud, bin])}
]}
, {'dgiot-pkg', [ {deps, MakeDeps(CloudDeps, DefaultDepRef, [])}
, {'emqx-pkg', [ {deps, MakeDeps(CloudDeps, DefaultDepRef, [])}
, {relx, RelxCloud([cloud, pkg])}
]}
, {'dgiot-edge', [ {deps, MakeDeps(EdgeDeps, DefaultDepRef, [])}
, {relx, RelxEdge([edge, dev])}
, {'emqx-edge', [ {deps, MakeDeps(EdgeDeps, DefaultDepRef, [])}
, {relx, RelxEdge([edge, bin])}
]}
, {'dgiot-edge-pkg', [ {deps, MakeDeps(EdgeDeps, DefaultDepRef, [])}
, {'emqx-edge-pkg', [ {deps, MakeDeps(EdgeDeps, DefaultDepRef, [])}
, {relx, RelxEdge([edge, pkg])}
]}
],
@ -204,9 +182,9 @@ CONFIG4 = lists:foldl(fun({K, V}, Acc) -> lists:keystore(K, 1, Acc, {K, V}) end,
FilePath = case os:type() of
{win32, nt} ->
"dgiot.rebar.config";
"emqx.rebar.config";
_ ->
"/tmp/dgiot.rebar.config"
"/tmp/emqx.rebar.config"
end,
file:write_file(FilePath, [io_lib:format("~p.\n", [I]) || I <- CONFIG4]),

BIN
rebar3

Binary file not shown.

BIN
relx Normal file

Binary file not shown.

View File

@ -1,23 +1,4 @@
{enable_plugin_emqx_dashboard, true}.
{enable_plugin_emqx_rule_engine, true}.
{enable_plugin_emqx_bridge_mqtt, true}.
{enable_plugin_emqx_cube, false}.
{enable_plugin_shuwa_statsd, true}.
{enable_plugin_shuwa_license, true}.
{enable_plugin_shuwa_public, true}.
{enable_plugin_shuwa_mqtt, true}.
{enable_plugin_shuwa_framework, true}.
{enable_plugin_shuwa_device_shadow, true}.
{enable_plugin_shuwa_parse, true}.
{enable_plugin_shuwa_bridge, true}.
{enable_plugin_shuwa_evidence, true}.
{enable_plugin_shuwa_group, true}.
{enable_plugin_shuwa_web_manager, true}.
{enable_plugin_shuwa_exproto,true}.
{enable_plugin_shuwa_task, true}.
{enable_plugin_shuwa_td, true}.
{enable_plugin_shuwa_api,true}.
{enable_plugin_shuwa_smartmeter,true}.
{enable_plugin_dgiot_meter,true}.
{enable_plugin_dgiot_amazedtu,true}.
{enable_plugin_emqx_bridge_mqtt, false}.
{vm_args_file, "vm.args"}.
{emqx_description, "EMQ X Broker"}.

View File

@ -1,5 +1,4 @@
{enable_plugin_emqx_dashboard, false}.
{enable_plugin_emqx_rule_engine, false}.
{enable_plugin_emqx_bridge_mqtt, true}.
{enable_plugin_emqx_cube, true}.
{vm_args_file, "vm.args.edge"}.
{emqx_description, "EMQ X Edge"}.

View File

@ -19,4 +19,4 @@
{runner_log_dir, "/var/log/emqx"}.
{runner_data_dir, "/var/lib/emqx"}.
{pipe_dir, "/tmp/$RUNNER_SCRIPT/"}.
{runner_user, "dgiot"}.
{runner_user, "emqx"}.