Compare commits

...

106 Commits

Author SHA1 Message Date
x1001100011 23d72b334e feat: fix runtime issues after merge master 2021-10-28 20:04:41 -07:00
x1001100011 0f57fb9599 feat: fix runtime issues after merge master 2021-10-27 22:38:49 -07:00
x1001100011 5d31c7eb6b Merge branch 'master' into EMQX-782 2021-10-27 21:49:24 -07:00
Zaiming (Stone) Shi 44446bb762 refactor(dashboard): rename 'password' field to 'pwdhash' (#5990)
* refactor(dashboard): rename 'password' field to 'pwdhash'

rename as it is not plaintext password stored in db

* refactor(emqx_dashboard): rename records

* test(emqx_dashboard_token): add test case to cover match specs
2021-10-27 21:48:00 -07:00
JimMoen c5241670e0 refactor(paginate): use exported fun call `{M,F}` 2021-10-27 21:47:59 -07:00
JimMoen f936aba6b7 fix(authn): users pagination on spec listener_id and authn_id 2021-10-27 21:47:59 -07:00
JimMoen 295b1312be feat(authn_scram): authn_scram users page query 2021-10-27 21:47:59 -07:00
JimMoen c6ea575d35 feat(authn): authn users page query 2021-10-27 21:47:59 -07:00
JimMoen 36fd7369e0 fix(authn): api description using binary string 2021-10-27 21:47:59 -07:00
JimMoen 2b46e16d74 fix(authz): add license headers 2021-10-27 21:47:59 -07:00
JimMoen 7a4edc0104 chore(authz): fix test suite page params 2021-10-27 21:47:59 -07:00
JimMoen c1b737a9b2 fix(authz): authz rules page query 2021-10-27 21:47:59 -07:00
JianBo He 2ded7fbe8c fix(api): escape the searching string 2021-10-27 21:47:59 -07:00
Zaiming (Stone) Shi 4eb966549e fix: typo in apps/emqx_authz/src/emqx_authz.erl
Co-authored-by: Rory Z <Rory-Z@outlook.com>
2021-10-27 21:47:59 -07:00
Zaiming Shi 70491aee07 fix(authn): save certificates to certs dir 2021-10-27 21:47:59 -07:00
Zaiming Shi bc99d5c1a6 refactor(authz): call emqx_tls_lib to save & read SSL files 2021-10-27 21:47:59 -07:00
Zaiming Shi fdf439bc7b refactor(tls): move ssl files handling to emqx_tls_lib
This is an attempt ot make it more generic for other APPs to use.
Aslo added test cases to cover most of the code paths.
2021-10-27 21:47:59 -07:00
zhanghongtong d796f815d7 chore(authz): add more test case 2021-10-27 21:47:59 -07:00
zhanghongtong b8de05891e chore(authz): implement create_dry_run in other function clause
Signed-off-by: zhanghongtong <rory-z@outlook.com>
2021-10-27 21:47:59 -07:00
zhanghongtong 74b63f7d68 fix(emqx_resource): fix InstId type error 2021-10-27 21:47:59 -07:00
zhanghongtong 2def7e4ac2 fix(authz): fix configuration could be updated with incorrect values
when updating the configuration, first check with emqx_resouce:create_dry_run/2

Signed-off-by: zhanghongtong <rory-z@outlook.com>
2021-10-27 21:47:59 -07:00
zhouzb ddcf73f465 fix(authn): fix handling of pgsql response 2021-10-27 21:47:59 -07:00
zhouzb cc5b995cf2 fix(authn): no longer use single quotes to wrap placeholders 2021-10-27 21:47:59 -07:00
zhouzb ab201625c3 fix(authn): fix sql parse for mysql 2021-10-27 21:47:59 -07:00
firest 1c144d7d67 fix(emqx_telemetry): add default value to get_value 2021-10-27 21:47:59 -07:00
Zaiming Shi 92d5f4b3b2 test: fix emqx_config_SUITE 2021-10-27 21:47:59 -07:00
Zaiming Shi 54223e4fe6 fix(schema): add roots for emqx_zone_schema
emqx_zone_schema is never used at root level, but for config doc
generation, it needs the roots.
2021-10-27 21:47:59 -07:00
Zaiming Shi 0531a1925c docs: authenticator_config ref link to the struct 2021-10-27 21:47:59 -07:00
Zaiming Shi 1b56fba471 chore: pin hocon 0.20.5
for two changes:
default string values are filled with binary() instead of [integer()]
better reference links in config document
2021-10-27 21:47:59 -07:00
JimMoen 147e2e911f chore(dashboard): update version for dashboard 2021-10-27 21:47:59 -07:00
zhongwencool 1d24e46ece Rewrite http api with hocon schema (#5980)
* feat: rewrite http api with hocon

* fix: crash when default_username is empty

* chore: udpate rewrite api with emqx_conf's cluster_rpc

* fix: spec wrong
2021-10-27 21:47:59 -07:00
zhanghongtong d78fbc5a8a chore(CI): rename image 2021-10-27 21:47:59 -07:00
zhanghongtong 595598916f chore(CI): fix build docker error 2021-10-27 21:47:59 -07:00
zhanghongtong cde614aad8 build(docker): use ghcr image for build docker 2021-10-27 21:47:59 -07:00
zhanghongtong 7364e821b8 chore(CI): change otp version for docker compose file
Signed-off-by: zhanghongtong <rory-z@outlook.com>
2021-10-27 21:47:59 -07:00
zhanghongtong 2b7e93f55f chore(CI): use concurrency to cancel in-progress workflows 2021-10-27 21:47:59 -07:00
zhanghongtong b0e579fcd8 chore(CI): change otp version for workflows 2021-10-27 21:47:59 -07:00
k32 15205942e0 chore(xref): Extend the list of forbidden Mnesia APIs 2021-10-27 21:47:59 -07:00
Ilya Averyanov c9a0c37dbb style(behaviour attrs): unify behaviour declarations 2021-10-27 21:47:59 -07:00
zhongwencool d2fc66f436 emqx_conf (#5939)
* feat(emqx_conf): move conf manager for emqx_machine to emqx_conf

* chore(emqx_conf): change emqx:get_config/2 to emqx_conf:get/2

* fix: common test failed

* fix: badmatch by typo wrong key

* fix(emqx_conf): get the wrong core nodes

* fix(emqx_conf): get core node's tnx_id not latest tnx_id

* fix: add ro_transation when copy conf file

* fix: delete debug info

* fix: change ekka_rlog to mria_rlog

* fix: remove cluster_rpc from emqx_machine.

* fix: don't call ekka:start/0 explicitly

* fix: ekka should be start in emqx_machine
2021-10-27 21:47:59 -07:00
k32 6697b9fa42 fix(emqx_machine): Fix start/stop callbacks (#5969)
* fix(emqx_machine): Fix start/stop callbacks

* chore(ekka): Bump version to 0.11.1

* fix(router): Wait for the tables

* fix(emqx_cluster_rpc): Stop cluster RPC when joining a cluster

* fix(emqx_app): Fix a deadlock when joining the cluster

* fix(emqx_telemetry): Wait for mnesia tables

* test(ct_helper): Start ekka before emqx
2021-10-27 21:47:59 -07:00
Zaiming Shi 2f2a093150 refactor(authn): make schema doc generation work 2021-10-27 21:47:59 -07:00
Zaiming Shi efca545d3d fix(authn): allow single authenticator instance from config 2021-10-27 21:47:59 -07:00
Zaiming Shi 1c22c0d596 fix(authn): rename config key http-server to http 2021-10-27 21:47:59 -07:00
Zaiming Shi c0364ad5a2 refactor(emqx_config_handler): async remove 2021-10-27 21:47:59 -07:00
Zaiming Shi 6d9b3ed341 feat: support check_config callback for authenticator provider 2021-10-27 21:47:59 -07:00
Zaiming Shi 494bac419d fix: fill string fields' default value with binary 2021-10-27 21:47:59 -07:00
Zaiming Shi 835539364e refactor(authn): check authenticator config with provider module
mainly two changes:

1. the schema is simplified at root level, per-authenticator checks
   are done after the type can be identified
2. the config handling part is split out from emqx_authentication
   module to emqx_authentication_config module
2021-10-27 21:47:59 -07:00
zhouzb 4b8bd8e562 chore(deps): unify version of hocon 2021-10-27 21:47:59 -07:00
zhouzb fc1e4893a8 chore(deps): update version of hocon 2021-10-27 21:47:59 -07:00
zhouzb 257bc353a4 fix(authn): fix placeholders are not replaced correctly 2021-10-27 21:47:59 -07:00
William Yang 0d38b75bb2 feat(olp): bump to 0.1.2
remove noop logging
2021-10-27 21:47:59 -07:00
k32 6ef68f8e2c fix(mria): Replace mnesia calls with mria 2021-10-27 21:47:59 -07:00
k32 fca7fd755d fix(emqx_alarm): Wait for tables 2021-10-27 21:47:59 -07:00
k32 760d896d9d fix(dialyzer): Fix problems found by dialyzer 2021-10-27 21:47:59 -07:00
k32 69126fede6 fix(mria): Fix startup sequence 2021-10-27 21:47:59 -07:00
k32 887544c3c1 chore(ct): ekka_mnesia -> mria_mnesia 2021-10-27 21:47:59 -07:00
k32 d224687de2 fix(mria): Hook up mria to emqx_machine 2021-10-27 21:47:58 -07:00
k32 e182a5f38c chore(mria): Remove the obsolete annotiation 2021-10-27 21:47:58 -07:00
k32 1a473bb73b chore(mria): ekka_rlog -> mria_rlog 2021-10-27 21:47:58 -07:00
k32 3e8b9ff76a chore(mria): Get rid of copy_mnesia callback 2021-10-27 21:47:58 -07:00
k32 22858eb845 chore(mria): ekka_mnesia:start/stop -> mria:start/stop 2021-10-27 21:47:58 -07:00
k32 814623edae chore(mria): ekka_mnesia:create_table -> mria:create_table 2021-10-27 21:47:58 -07:00
k32 75c9267473 chore(mria): Fix clear_table and ro_transaction calls 2021-10-27 21:47:58 -07:00
k32 ae71bdc0fe chore(mria): ekka_mnesia:running_nodes -> mria:running_nodes 2021-10-27 21:47:58 -07:00
k32 fd482e2ec0 chore(mria): Rename module: ekka_mnesia -> mria 2021-10-27 21:47:58 -07:00
zhanghongtong 591b704f65 chore(CI): better build docker image 2021-10-27 21:47:58 -07:00
x1001100011 dbe45d9d6f Merge branch 'master' into EMQX-782 2021-10-20 00:01:07 -07:00
x1001100011 783a10c5a1 refactor: reuse overlay dsl in application 2021-10-19 23:56:27 -07:00
x1001100011 6a4b437446
feat: remove debug changes 2021-10-18 00:06:25 -07:00
x1001100011 d0b54ac365
feat: emqx_gateway version
Co-authored-by: JianBo He <heeejianbo@163.com>
2021-10-18 00:05:26 -07:00
x1001100011 b76334ea01 feat: patch after merge master branch 2021-10-17 21:04:46 -07:00
x1001100011 0312f07b11 Merge branch 'master' into EMQX-782 2021-10-17 20:57:01 -07:00
x1001100011 93532615c1 feat: add protos compiler 2021-10-13 21:41:19 -07:00
x1001100011 2d25e895a8 feat: fix applications start order issue 2021-10-12 00:00:57 -07:00
x1001100011 f20d5b5395 Merge branch 'master' into EMQX-782 2021-10-11 23:44:44 -07:00
x1001100011 ddb79f51ae feat: lock deps version 2021-09-23 21:21:17 -07:00
x1001100011 7e2c035562 style: auto format 2021-09-23 00:16:32 -07:00
x1001100011 df1cbb0bab Merge branch 'master' into EMQX-871-872 2021-09-23 00:12:57 -07:00
x1001100011 e3437d5b9e feat: refactor script 2021-09-22 23:50:02 -07:00
x1001100011 c14319e5bd feat: remove emqx_release_helper 2021-09-22 21:52:20 -07:00
x1001100011 188f44ad50 feat: refactor call_hocon to use escript 2021-09-19 19:15:05 -07:00
x1001100011 13e146d1ee feat: bin/emqx start_iex works 2021-09-14 00:06:16 -07:00
x1001100011 5e812a1add feat: sync with master 2021-09-12 15:32:03 -07:00
x1001100011 7a7cccb337 Merge branch 'master' into EMQX-871-872 2021-09-12 15:21:10 -07:00
x1001100011 69673613d6 Merge branch 'master' into EMQX-871-872 2021-09-09 23:38:38 -07:00
x1001100011 22b2a3902e feat: add mix bin/emqx 2021-09-09 22:35:34 -07:00
x1001100011 1ef7f4e2a0 feat: add emqx_machine application 2021-08-31 19:32:39 -07:00
x1001100011 5dd7f53662 Merge branch 'master' into EMQX-871-872 2021-08-11 21:54:59 -07:00
x1001100011 19e92d7936 feat: make mix release works 2021-08-11 00:49:15 -07:00
x1001100011 3c4430c252 feat: update depends 2021-08-09 22:22:50 -07:00
x1001100011 2c6e8204b8 Merge branch 'master' into EMQX-871-872 2021-08-09 22:02:43 -07:00
x1001100011 e4eeb585cb Merge branch 'master' into EMQX-871-872 2021-08-03 23:40:46 -07:00
x1001100011 25f03ed87a Merge branch 'master' into EMQX-871-872 2021-07-31 08:26:06 -07:00
x1001100011 d33465052f feat: rename plugin to application 2021-07-23 22:51:27 -07:00
x1001100011 bd3760d5c7 feat: run the package released by mix 2021-07-21 23:01:07 -07:00
x1001100011 4c1e03bbcd feat: add emqx_config_helper 2021-07-18 22:00:34 -07:00
x1001100011 ef4c30b2fd feat: set emqx in umbrella depend runtime false 2021-07-18 18:48:10 -07:00
x1001100011 9fc635826c feat: remove unused file 2021-07-11 15:38:21 -07:00
x1001100011 e83217fb09 feat: remove unused file 2021-07-11 15:37:15 -07:00
x1001100011 6905eb4ac1 feat: emqx_release_helper 2021-07-11 15:31:01 -07:00
x1001100011 c940ab9e0a
Merge pull request #5114 from x1001100011/EMQX-788
[EMQX-788] remove emqx_lua_hook and rename Emqx -> EMQX
2021-06-27 23:38:07 -07:00
x1001100011 e40148a6dd feat: Emqx -> EMQX 2021-06-27 23:35:52 -07:00
x1001100011 ba002bb1b5 fix: remove mix files for emqx_lua_hook 2021-06-27 23:25:51 -07:00
x1001100011 ed34783dd7 Merge branch 'master' into EMQX-788 2021-06-27 23:20:47 -07:00
x1001100011 8ec83705ad feat: add mix.exs for all applications 2021-06-26 19:53:18 -07:00
89 changed files with 2155 additions and 36 deletions

5
.formatter.exs Normal file
View File

@ -0,0 +1,5 @@
# Used by "mix format"
[
inputs: ["mix.exs", "config/*.exs"],
subdirectories: ["apps/*"]
]

4
apps/emqx/.formatter.exs Normal file
View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

42
apps/emqx/mix.exs Normal file
View File

@ -0,0 +1,42 @@
defmodule EMQX.MixProject do
use Mix.Project
def project do
[
app: :emqx,
version: "5.0.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X"
]
end
def application do
[
mod: {:emqx_app, []},
extra_applications: [:logger, :os_mon, :syntax_tools]
]
end
defp deps do
[
{:gproc, "0.9.0"},
{:recon, "2.5.2"},
{:cowboy, github: "emqx/cowboy", tag: "2.8.2"},
{:esockd, github: "emqx/esockd", tag: "5.8.0"},
{:ekka, github: "emqx/ekka", tag: "0.11.1"},
{:gen_rpc, github: "emqx/gen_rpc", tag: "2.5.1"},
{:cuttlefish, github: "emqx/cuttlefish", tag: "v4.0.1"},
{:hocon, github: "emqx/hocon"},
{:pbkdf2, github: "emqx/erlang-pbkdf2", tag: "2.0.4"},
{:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "0.14.0"},
{:jiffy, github: "emqx/jiffy", tag: "1.0.5"},
{:lc, github: "qzhuyan/lc", tag: "0.1.1"}
]
end
end

View File

@ -22,7 +22,6 @@
-include("logger.hrl").
-include_lib("lc/include/lc.hrl").
%% gen_event callbacks
-export([ init/1
, handle_event/2

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

38
apps/emqx_authn/mix.exs Normal file
View File

@ -0,0 +1,38 @@
defmodule EMQXAuthn.MixProject do
use Mix.Project
def project do
[
app: :emqx_authn,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Authentication"
]
end
def application do
[
registered: [:emqx_authn_sup, :emqx_authn_registry],
mod: {:emqx_authn_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false},
{:emqx_resource, in_umbrella: true},
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.2.1"},
{:esasl, github: "emqx/esasl", tag: "0.1.0"},
{:epgsql, github: "epgsql/epgsql", tag: "4.4.0"},
{:mysql, github: "emqx/mysql-otp", tag: "1.7.1"},
{:jose, "1.11.2"}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

29
apps/emqx_authz/mix.exs Normal file
View File

@ -0,0 +1,29 @@
defmodule EMQXAuthz.MixProject do
use Mix.Project
def project do
[
app: :emqx_authz,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx_connector, in_umbrella: true}
]
end
end

View File

@ -0,0 +1,32 @@
defmodule EMQXAutoSubscribe.MixProject do
use Mix.Project
def project do
[
app: :emqx_auto_subscribe,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Auto Subscribe"
]
end
def application do
[
registered: [],
mod: {:emqx_auto_subscribe_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false}
]
end
end

33
apps/emqx_bridge/mix.exs Normal file
View File

@ -0,0 +1,33 @@
defmodule EMQXBridge.MixProject do
use Mix.Project
def project do
[
app: :emqx_bridge,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Bridge"
]
end
def application do
[
registered: [],
mod: {:emqx_bridge_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false},
{:emqx_connector, in_umbrella: true}
]
end
end

32
apps/emqx_conf/mix.exs Normal file
View File

@ -0,0 +1,32 @@
defmodule EMQXConf.MixProject do
use Mix.Project
def project do
[
app: :emqx_conf,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Configuration Management"
]
end
def application do
[
mod: {:emqx_conf_app, []},
extra_applications: [:logger, :os_mon, :syntax_tools]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false},
{:hocon, github: "emqx/hocon"}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,33 @@
defmodule EMQXConnector.MixProject do
use Mix.Project
def project do
[
app: :emqx_connector,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
mod: {:emqx_connector_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx_resource, in_umbrella: true},
{:mysql, github: "emqx/mysql-otp", tag: "1.7.1"},
{:ecpool, github: "emqx/ecpool", tag: "0.5.1"},
{:emqtt, github: "emqx/emqtt", tag: "1.4.3"}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,33 @@
defmodule EMQXDashboard.MixProject do
use Mix.Project
def project do
[
app: :emqx_dashboard,
version: "4.4.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Web Dashboard"
]
end
def application do
[
registered: [:emqx_dashboard_sup],
mod: {:emqx_dashboard_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false},
{:minirest, github: "emqx/minirest", tag: "1.2.4"}
]
end
end

59
apps/emqx_exhook/mix.exs Normal file
View File

@ -0,0 +1,59 @@
defmodule EMQXExhook.MixProject do
use Mix.Project
def project do
[
app: :emqx_exhook,
version: "5.0.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
compilers: [:protos | Mix.compilers()],
aliases: ["compile.protos": &protos/1],
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Extension for Hook"
]
end
def application do
[
registered: [],
mod: {:emqx_exhook_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false},
{:grpc, github: "emqx/grpc-erl", tag: "0.6.2"}
]
end
defp protos(_args) do
app_path = Path.expand("..", __ENV__.file)
config = [
:use_packages,
:maps,
:strings_as_binaries,
rename: {:msg_name, :snake_case},
rename: {:msg_fqname, :base_name},
i: '.',
report_errors: false,
o: app_path |> Path.join("src") |> to_charlist(),
module_name_prefix: 'emqx_',
module_name_suffix: '_pb'
]
app_path
|> Path.join("priv/protos/*.proto")
|> Path.wildcard()
|> Enum.map(&to_charlist/1)
|> Enum.each(&:gpb_compile.file(&1, config))
:ok
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

62
apps/emqx_gateway/mix.exs Normal file
View File

@ -0,0 +1,62 @@
defmodule EMQXGateway.MixProject do
use Mix.Project
def project do
[
app: :emqx_gateway,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
compilers: [:protos | Mix.compilers()],
aliases: ["compile.protos": &protos/1],
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "The Gateway Management Application"
]
end
def application do
[
registered: [],
mod: {:emqx_gateway_app, []},
extra_applications: [:logger]
]
end
defp protos(_args) do
app_path = Path.expand("..", __ENV__.file)
config = [
:use_packages,
:maps,
:strings_as_binaries,
rename: {:msg_name, :snake_case},
rename: {:msg_fqname, :base_name},
i: '.',
report_errors: false,
o: app_path |> Path.join("src/exproto") |> to_charlist(),
module_name_prefix: 'emqx_',
module_name_suffix: '_pb'
]
app_path
|> Path.join("src/exproto/protos/*.proto")
|> Path.wildcard()
|> Enum.map(&to_charlist/1)
|> Enum.each(&:gpb_compile.file(&1, config))
:ok
end
defp deps do
[
{:gpb, "4.19.1", runtime: false},
{:emqx, in_umbrella: true},
{:lwm2m_coap, github: "emqx/lwm2m-coap", tag: "v2.0.0"},
{:grpc, github: "emqx/grpc-erl", tag: "0.6.2"},
{:esockd, github: "emqx/esockd", tag: "5.7.4"}
]
end
end

View File

@ -18,7 +18,7 @@
-behaviour(minirest_api).
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
%% API
-export([api_spec/0]).

View File

@ -19,7 +19,7 @@
-behaviour(emqx_gateway_channel).
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
%% API
-export([ info/1

View File

@ -30,8 +30,8 @@
%% API
-export([]).
-include("include/emqx_coap.hrl").
-include("apps/emqx/include/types.hrl").
-include_lib("emqx/include/types.hrl").
-include("emqx_coap.hrl").
-define(VERSION, 1).

View File

@ -20,7 +20,7 @@
-module(emqx_coap_medium).
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
%% API
-export([ empty/0, reset/1, reset/2

View File

@ -34,7 +34,7 @@
-export([ set/3, set_payload/2, get_option/2
, get_option/3, set_payload_block/3, set_payload_block/4]).
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
request(Type, Method) ->
request(Type, Method, <<>>, []).

View File

@ -18,7 +18,7 @@
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/emqx_mqtt.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
%% API
-export([ new/0

View File

@ -28,7 +28,7 @@
-export_type([manager/0, event_result/1]).
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
-type direction() :: in | out.

View File

@ -1,7 +1,7 @@
-module(emqx_coap_transport).
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
-define(ACK_TIMEOUT, 2000).
-define(ACK_RANDOM_FACTOR, 1000).

View File

@ -16,7 +16,7 @@
-module(emqx_coap_mqtt_handler).
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
-export([handle_request/4]).
-import(emqx_coap_message, [response/2, response/3]).

View File

@ -18,7 +18,7 @@
-module(emqx_coap_pubsub_handler).
-include_lib("emqx/include/emqx_mqtt.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include("emqx_coap.hrl").
-export([handle_request/4]).

View File

@ -15,7 +15,7 @@
%%--------------------------------------------------------------------
-module(emqx_exproto_channel).
-include("src/exproto/include/emqx_exproto.hrl").
-include("emqx_exproto.hrl").
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/emqx_mqtt.hrl").
-include_lib("emqx/include/types.hrl").

View File

@ -19,7 +19,7 @@
% -behaviour(emqx_exproto_v_1_connection_adapter_bhvr).
-include("src/exproto/include/emqx_exproto.hrl").
-include("emqx_exproto.hrl").
-include_lib("emqx/include/logger.hrl").
-define(IS_QOS(X), (X =:= 0 orelse X =:= 1 orelse X =:= 2)).

View File

@ -17,8 +17,8 @@
-module(emqx_lwm2m_channel).
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include_lib("emqx_gateway/src/lwm2m/include/emqx_lwm2m.hrl").
-include("emqx_coap.hrl").
-include("emqx_lwm2m.hrl").
%% API
-export([ info/1

View File

@ -17,8 +17,8 @@
-module(emqx_lwm2m_cmd).
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include_lib("emqx_gateway/src/lwm2m/include/emqx_lwm2m.hrl").
-include("emqx_coap.hrl").
-include("emqx_lwm2m.hrl").
-export([ mqtt_to_coap/2
, coap_to_mqtt/4

View File

@ -23,7 +23,7 @@
, translate_json/1
]).
-include("src/lwm2m/include/emqx_lwm2m.hrl").
-include("emqx_lwm2m.hrl").
tlv_to_json(BaseName, TlvData) ->
DecodedTlv = emqx_lwm2m_tlv:parse(TlvData),

View File

@ -18,8 +18,8 @@
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/emqx_mqtt.hrl").
-include_lib("emqx_gateway/src/coap/include/emqx_coap.hrl").
-include_lib("emqx_gateway/src/lwm2m/include/emqx_lwm2m.hrl").
-include("emqx_coap.hrl").
-include("emqx_lwm2m.hrl").
%% API
-export([ new/0, init/4, update/3, parse_object_list/1

View File

@ -25,7 +25,7 @@
-export([binary_to_hex_string/1]).
-endif.
-include("src/lwm2m/include/emqx_lwm2m.hrl").
-include("emqx_lwm2m.hrl").
-define(TLV_TYPE_OBJECT_INSTANCE, 0).
-define(TLV_TYPE_RESOURCE_INSTANCE, 1).
@ -158,4 +158,3 @@ encode_value(Value) ->
binary_to_hex_string(Data) ->
lists:flatten([io_lib:format("~2.16.0B ",[X]) || <<X:8>> <= Data ]).
-endif.

View File

@ -16,8 +16,8 @@
-module(emqx_lwm2m_xml_object).
-include_lib("emqx_gateway/src/lwm2m/include/emqx_lwm2m.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include("emqx_lwm2m.hrl").
-export([ get_obj_def/2
, get_object_id/1

View File

@ -16,9 +16,9 @@
-module(emqx_lwm2m_xml_object_db).
-include_lib("emqx_gateway/src/lwm2m/include/emqx_lwm2m.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("emqx/include/logger.hrl").
-include("emqx_lwm2m.hrl").
% This module is for future use. Disabled now.

View File

@ -18,7 +18,7 @@
-behaviour(gen_server).
-include("src/mqttsn/include/emqx_sn.hrl").
-include("emqx_sn.hrl").
-include_lib("emqx/include/logger.hrl").
-export([ start_link/2
@ -105,4 +105,3 @@ send_advertise(#state{gwid = GwId, sock = Sock, port = Port,
boradcast_addrs() ->
lists:usort([Addr || {ok, IfList} <- [inet:getiflist()], If <- IfList,
{ok, [{broadaddr, Addr}]} <- [inet:ifget(If, [broadaddr])]]).

View File

@ -18,7 +18,7 @@
-behaviour(emqx_gateway_channel).
-include("src/mqttsn/include/emqx_sn.hrl").
-include("emqx_sn.hrl").
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/emqx_mqtt.hrl").
-include_lib("emqx/include/logger.hrl").

View File

@ -20,7 +20,7 @@
-behaviour(emqx_gateway_frame).
-include("src/mqttsn/include/emqx_sn.hrl").
-include("emqx_sn.hrl").
-export([ initial_parse_state/1
, serialize_opts/0

View File

@ -21,7 +21,7 @@
-behaviour(gen_server).
-include("src/mqttsn/include/emqx_sn.hrl").
-include("emqx_sn.hrl").
-include_lib("emqx/include/logger.hrl").
-export([ start_link/2

View File

@ -18,7 +18,7 @@
-behaviour(emqx_gateway_channel).
-include("src/stomp/include/emqx_stomp.hrl").
-include("emqx_stomp.hrl").
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl").

View File

@ -70,7 +70,7 @@
-behaviour(emqx_gateway_frame).
-include("src/stomp/include/emqx_stomp.hrl").
-include("emqx_stomp.hrl").
-export([ initial_parse_state/1
, parse/2

View File

@ -17,7 +17,7 @@
%% @doc Stomp heartbeat.
-module(emqx_stomp_heartbeat).
-include("src/stomp/include/emqx_stomp.hrl").
-include("emqx_stomp.hrl").
-export([ init/1
, check/3

32
apps/emqx_limiter/mix.exs Normal file
View File

@ -0,0 +1,32 @@
defmodule EMQXLimiter.MixProject do
use Mix.Project
def project do
[
app: :emqx_limiter,
version: "1.0.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Hierachical Limiter"
]
end
def application do
[
registered: [:emqx_limiter_sup],
mod: {:emqx_limiter_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false}
]
end
end

30
apps/emqx_machine/mix.exs Normal file
View File

@ -0,0 +1,30 @@
defmodule EMQXMachine.MixProject do
use Mix.Project
def project do
[
app: :emqx_machine,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "The EMQ X Machine"
]
end
def application do
[
registered: [],
mod: {:emqx_machine_app, []},
extra_applications: [:logger]
]
end
defp deps do
[]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,35 @@
defmodule EMQXManagement.MixProject do
use Mix.Project
def project do
[
app: :emqx_management,
version: "4.4.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Management API and CLI"
]
end
def application do
[
registered: [:emqx_management_sup],
mod: {:emqx_mgmt_app, []},
extra_applications: [:logger, :syntax_tools]
]
end
defp deps do
[
{:emqx_rule_engine, in_umbrella: true},
{:ekka, github: "emqx/ekka", tag: "0.11.1", runtime: false},
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.2.1"},
{:minirest, github: "emqx/minirest", tag: "1.2.4"}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

29
apps/emqx_modules/mix.exs Normal file
View File

@ -0,0 +1,29 @@
defmodule EMQXModules.MixProject do
use Mix.Project
def project do
[
app: :emqx_modules,
version: "4.3.2",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
registered: [:emqx_mod_sup],
mod: {:emqx_modules_app, []},
extra_applications: [:logger]
]
end
defp deps do
[]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,28 @@
defmodule EMQXPluginLibs.MixProject do
use Mix.Project
def project do
[
app: :emqx_plugin_libs,
version: "4.3.1",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Plugin utility libs"
]
end
def application do
[
extra_applications: [:logger]
]
end
defp deps do
[]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,32 @@
defmodule EMQXPrometheus.MixProject do
use Mix.Project
def project do
[
app: :emqx_prometheus,
version: "4.3.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "Prometheus for EMQ X"
]
end
def application do
[
registered: [:emqx_prometheus_sup],
mod: {:emqx_prometheus_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:prometheus, github: "emqx/prometheus.erl", tag: "v3.1.1"}
]
end
end

32
apps/emqx_psk/mix.exs Normal file
View File

@ -0,0 +1,32 @@
defmodule EmqxPSK.MixProject do
use Mix.Project
def project do
[
app: :emqx_psk,
version: "5.0.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X PSK"
]
end
def application do
[
registered: [:emqx_psk_sup],
mod: {:emqx_psk_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false}
]
end
end

View File

@ -0,0 +1,11 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
locals_without_parens: [
start_type: 1,
overlay: 1,
mkdir: 1,
copy: 2,
template: 2
]
]

26
apps/emqx_release_helper/.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
emqx_release_helper-*.tar
# Temporary files, for example, from tests.
/tmp/

View File

@ -0,0 +1,21 @@
# EmqxReleaseHelper
**TODO: Add description**
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `emqx_release_helper` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:emqx_release_helper, "~> 0.1.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/emqx_release_helper](https://hexdocs.pm/emqx_release_helper).

View File

@ -0,0 +1,132 @@
defmodule EmqxReleaseHelper do
def applications do
config = profile_vars()
EmqxReleaseHelper.Applications.__all__()
|> Enum.filter(fn
%{enable?: fun} -> fun.(config)
_ -> true
end)
|> Enum.map(fn %{name: name, start_type: start_type} -> {name, start_type} end)
end
def run(release) do
config = Map.merge(profile_vars(), release_vars(release))
release
|> EmqxReleaseHelper.Script.run(config)
|> EmqxReleaseHelper.Overlay.run(config)
|> EmqxReleaseHelper.Applications.run(config)
end
def profile_vars() do
"RELEASE_PROFILE"
|> System.get_env("emqx")
|> String.to_existing_atom()
|> case do
:emqx ->
%{
release_type: :cloud,
package_type: :bin
}
end
|> Map.merge(%{
erts_vsn: :version |> :erlang.system_info() |> to_string(),
project_path: EMQXUmbrella.MixProject.project_path(),
enable_bcrypt: EMQXUmbrella.MixProject.enable_bcrypt(),
enable_plugin_emqx_modules: false,
enable_plugin_emqx_retainer: true,
apps_paths: Mix.Project.apps_paths(),
built_on_arch: get_arch()
})
|> then(fn %{release_type: release_type} = config ->
Map.merge(config, profile_vars(:release_type, release_type))
end)
|> then(fn %{package_type: package_type} = config ->
Map.merge(config, profile_vars(:package_type, package_type))
end)
end
defp profile_vars(:release_type, :cloud) do
%{
emqx_description: "EMQ X Broker",
enable_plugin_emqx_rule_engine: true,
enable_plugin_emqx_bridge_mqtt: false
}
end
defp profile_vars(:release_type, :edge) do
%{
emqx_description: "EMQ X Edge",
enable_plugin_emqx_rule_engine: false,
enable_plugin_emqx_bridge_mqtt: true
}
end
defp profile_vars(:package_type, :bin) do
%{
platform_bin_dir: "bin",
platform_data_dir: "data",
platform_etc_dir: "etc",
platform_lib_dir: "lib",
platform_log_dir: "log",
platform_plugins_dir: "etc/plugins",
runner_root_dir: "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)",
runner_bin_dir: "$RUNNER_ROOT_DIR/bin",
runner_etc_dir: "$RUNNER_ROOT_DIR/etc",
runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
runner_log_dir: "$RUNNER_ROOT_DIR/log",
runner_data_dir: "$RUNNER_ROOT_DIR/data",
runner_user: ""
}
end
defp profile_vars(:package_type, :pkg) do
%{
platform_bin_dir: "",
platform_data_dir: "/var/lib/emqx",
platform_etc_dir: "/etc/emqx",
platform_lib_dir: "",
platform_log_dir: "/var/log/emqx",
platform_plugins_dir: "/var/lib/emqx/plugins",
runner_root_dir: "/usr/lib/emqx",
runner_bin_dir: "/usr/bin",
runner_etc_dir: "/etc/emqx",
runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
runner_log_dir: "/var/log/emqx",
runner_data_dir: "/var/lib/emqx",
runner_user: "emqx"
}
end
defp release_vars(release) do
%{
release_version: release.version,
release_path: release.path,
release_version_path: release.version_path
}
end
defp get_arch do
major_version = System.otp_release()
otp_release =
[:code.root_dir(), "releases", major_version, "OTP_VERSION"]
|> Path.join()
|> File.read()
|> case do
{:ok, version} -> String.trim(version)
{:error, _} -> major_version
end
wordsize =
try do
:erlang.system_info({:wordsize, :external}) * 8
rescue
_ ->
:erlang.system_info(:wordsize) * 8
end
Enum.join([otp_release, :erlang.system_info(:system_architecture), wordsize], "-")
end
end

View File

@ -0,0 +1,138 @@
defmodule EmqxReleaseHelper.Applications do
use EmqxReleaseHelper.DSL.Application
application :emqx do
start_type :load
overlay %{release_type: release_type} do
copy "etc/certs", "etc/certs"
template "etc/ssl_dist.conf", "etc/ssl_dist.conf"
template "etc/emqx_#{release_type}/vm.args", "etc/vm.args"
end
end
application :emqx_conf do
start_type :load
overlay do
template "etc/emqx.conf.all", "etc/emqx.conf"
end
end
application :lc do
start_type :load
end
application :esasl do
start_type :load
end
application :mria do
start_type :load
end
application :mnesia do
start_type :load
end
application :ekka do
start_type :load
end
application :emqx_plugin_libs do
start_type :load
end
application :emqx_gateway do
start_type :load
overlay do
copy "src/lwm2m/lwm2m_xml", "etc/lwm2m_xml"
end
end
application :emqx_resource do
start_type :load
end
application :emqx_connector do
start_type :load
end
application :emqx_bridge do
start_type :load
end
application :emqx_authn do
start_type :load
end
application :emqx_authz do
start_type :load
overlay do
template "etc/acl.conf", "etc/acl.conf"
end
end
application :emqx_machine do
start_type :permanent
end
application :emqx_auto_subscribe do
start_type :permanent
end
application :emqx_exhook do
start_type :permanent
end
application :emqx_modules do
start_type :permanent
end
application :emqx_dashboard do
start_type :permanent
end
application :emqx_management do
start_type :permanent
end
application :emqx_statsd do
start_type :permanent
end
application :emqx_retainer do
start_type :permanent
end
application :emqx_rule_engine do
start_type :permanent
end
application :emqx_psk do
start_type :permanent
end
application :emqx_limiter do
start_type :permanent
end
application :emqx_prometheus do
start_type :permanent
end
application :bcrypt, %{enable_bcrypt: true, release_type: :cloud} do
start_type :permanent
end
application :xmerl, %{release_type: :cloud} do
start_type :permanent
end
application :observer, %{release_type: :cloud} do
start_type :load
end
end

View File

@ -0,0 +1,83 @@
defmodule EmqxReleaseHelper.DSL.Application do
defmacro __using__(_) do
quote do
import unquote(__MODULE__)
import EmqxReleaseHelper.DSL.Overlay, only: [
overlay: 1,
overlay: 2,
copy: 2,
template: 2
]
Module.register_attribute(__MODULE__, :applications, accumulate: true)
@before_compile unquote(__MODULE__)
@overlay_source_path :app_source_path
end
end
defmacro application(app, condition, do: block) do
func =
Macro.escape(
quote do
fn config -> match?(unquote(condition), config) end
end
)
quote do
@current_application %{name: unquote(app), enable?: unquote(func)}
@overlays []
unquote(block)
overlays = Enum.reverse(@overlays)
@applications Map.put(@current_application, :overlays, overlays)
@current_application nil
@overlays []
end
end
defmacro application(app, do: block) do
quote do
@current_application %{name: unquote(app)}
@overlays []
unquote(block)
overlays = Enum.reverse(@overlays)
@applications Map.put(@current_application, :overlays, overlays)
@current_application nil
@overlays []
end
end
defmacro start_type(type) do
quote do
@current_application Map.put(@current_application, :start_type, unquote(type))
end
end
defmacro __before_compile__(%Macro.Env{module: module}) do
block =
module
|> Module.get_attribute(:applications)
|> Enum.reverse()
|> Enum.map(fn app -> {:%{}, [], Map.to_list(app)} end)
quote do
def __all__, do: unquote(block)
def run(release, config) do
%{project_path: project_path, apps_paths: apps_paths} = config
__all__()
|> Enum.filter(fn %{name: name} -> Map.has_key?(apps_paths, name) end)
|> Enum.filter(fn
%{enable?: fun} -> fun.(config)
_ -> true
end)
|> Enum.each(fn %{name: name, overlays: overlays} ->
app_path = Map.get(apps_paths, name)
config = Map.put(config, :app_source_path, Path.join(project_path, app_path))
Enum.each(overlays, fn overlay -> overlay.(config) end)
end)
release
end
end
end
end

View File

@ -0,0 +1,132 @@
defmodule EmqxReleaseHelper.DSL.Overlay do
defmacro __using__(_) do
quote do
import unquote(__MODULE__)
@before_compile unquote(__MODULE__)
@overlays []
@overlay_source_path :project_path
end
end
defmacro overlay(do: block) do
block =
Macro.escape(
quote do
fn unquote(Macro.var(:config, nil)) ->
unquote(block)
end
end
)
quote do
@overlays [unquote(block) | @overlays]
end
end
defmacro overlay(literal_config, do: block) do
block =
Macro.escape(
quote do
fn unquote(literal_config) = unquote(Macro.var(:config, nil)) ->
unquote(block)
end
end
)
quote do
@overlays [unquote(block) | @overlays]
end
end
defmacro mkdir(path) do
path =
quote do
unquote(Macro.var(:config, nil))
|> Map.get(:release_path)
|> Path.join(unquote(path))
end
quote do
run_mkdir(unquote(path))
end
end
defmacro copy(from_path, to_path) do
from_path =
quote do
unquote(Macro.var(:config, nil))
|> Map.get(@overlay_source_path)
|> Path.join(unquote(from_path))
end
to_path =
quote do
unquote(Macro.var(:config, nil))
|> Map.get(:release_path)
|> Path.join(unquote(to_path))
end
quote do
unquote(__MODULE__).run_copy(unquote(from_path), unquote(to_path))
end
end
defmacro template(from_path, to_path) do
from_path =
quote do
unquote(Macro.var(:config, nil))
|> Map.get(@overlay_source_path)
|> Path.join(unquote(from_path))
end
to_path =
quote do
unquote(Macro.var(:config, nil))
|> Map.get(:release_path)
|> Path.join(unquote(to_path))
end
quote do
unquote(__MODULE__).run_template(
unquote(from_path),
unquote(to_path),
unquote(Macro.var(:config, nil))
)
end
end
def run_mkdir(path) do
File.mkdir_p!(path)
end
def run_copy(from_path, to_path) do
to_path |> Path.dirname() |> File.mkdir_p!()
File.cp_r!(from_path, to_path)
end
def run_template(from_path, to_path, config) do
config = Enum.map(config, fn {key, value} -> {to_charlist(key), value} end)
to_path |> Path.dirname() |> File.mkdir_p!()
content =
from_path
|> File.read!()
|> :bbmustache.render(config)
File.write!(to_path, content)
end
defmacro __before_compile__(%Macro.Env{module: module}) do
block =
module
|> Module.get_attribute(:overlays)
|> Enum.reverse()
quote do
def run(release, config) do
Enum.each(unquote(block), fn overlay -> overlay.(config) end)
release
end
end
end
end

View File

@ -0,0 +1,21 @@
defmodule EmqxReleaseHelper.Overlay do
use EmqxReleaseHelper.DSL.Overlay
overlay %{release_version: release_version} do
mkdir "log"
mkdir "etc"
mkdir "data"
mkdir "data/mnesia"
mkdir "data/configs"
mkdir "data/patches"
mkdir "data/scripts"
copy "bin/install_upgrade.escript", "bin/install_upgrade.escript"
copy "bin/node_dump", "bin/node_dump"
copy "bin/emqx_ctl", "bin/emqx_ctl"
template "data/emqx_vars", "releases/emqx_vars"
template "data/BUILT_ON", "releases/#{release_version}/BUILT_ON"
end
end

View File

@ -0,0 +1,17 @@
defmodule EmqxReleaseHelper.Script do
def run(release, config) do
script_path = Path.join(config.project_path, "scripts")
{_, 0} =
script_path
|> Path.join("merge-config.escript")
|> System.cmd([])
{_, 0} =
script_path
|> Path.join("get-dashboard.sh")
|> System.cmd([], env: [{"EMQX_DASHBOARD_VERSION", "v5.0.0-beta.13"}])
release
end
end

View File

@ -0,0 +1,29 @@
defmodule EMQXReleaseHelper.MixProject do
use Mix.Project
def project do
[
app: :emqx_release_helper,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
extra_applications: [:logger]
]
end
defp deps do
[
{:bbmustache, "1.12.1"}
]
end
end

View File

@ -0,0 +1,8 @@
defmodule EmqxReleaseHelperTest do
use ExUnit.Case
doctest EmqxReleaseHelper
test "greets the world" do
assert EmqxReleaseHelper.hello() == :world
end
end

View File

@ -0,0 +1 @@
ExUnit.start()

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,33 @@
defmodule EMQXResource.MixProject do
use Mix.Project
def project do
[
app: :emqx_resource,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
mod: {:emqx_resource_app, []},
extra_applications: [:logger, :syntax_tools]
]
end
defp deps do
[
{:jsx, "3.1.0"},
{:gproc, "0.9.0"},
{:hocon, github: "emqx/hocon"},
{:emqx_conf, in_umbrella: true}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,32 @@
defmodule EMQXRetainer.MixProject do
use Mix.Project
def project do
[
app: :emqx_retainer,
version: "4.3.1",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Retainer"
]
end
def application do
[
registered: [:emqx_retainer_sup],
mod: {:emqx_retainer_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -0,0 +1,34 @@
defmodule EMQXRuleEngine.MixProject do
use Mix.Project
def project do
[
app: :emqx_rule_engine,
version: "4.3.2",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Rule Engine"
]
end
def application do
[
registered: [:emqx_rule_engine_sup, :emqx_rule_registry],
mod: {:emqx_rule_engine_app, []},
extra_applications: [:logger, :syntax_tools]
]
end
defp deps do
[
{:emqx, in_umbrella: true, runtime: false},
{:ekka, github: "emqx/ekka", tag: "0.11.1", runtime: false},
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.2.1"}
]
end
end

View File

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

31
apps/emqx_statsd/mix.exs Normal file
View File

@ -0,0 +1,31 @@
defmodule EMQXStatsd.MixProject do
use Mix.Project
def project do
[
app: :emqx_statsd,
version: "0.1.0",
build_path: "../../_build",
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
description: "EMQ X Statsd"
]
end
def application do
[
mod: {:emqx_statsd_app, []},
extra_applications: [:logger]
]
end
defp deps do
[
{:estatsd, github: "emqx/estatsd", tag: "0.1.0"}
]
end
end

1
config/config.exs Normal file
View File

@ -0,0 +1 @@
import Config

View File

@ -58,7 +58,7 @@ do_stop()
# waiting stop done sleep 5
sleep 5
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
@ -146,5 +146,3 @@ case "$1" in
exit 3
;;
esac

0
log/emqx.log.1 Normal file
View File

BIN
log/emqx.log.idx Normal file

Binary file not shown.

BIN
log/emqx.log.siz Normal file

Binary file not shown.

75
mix.exs Normal file
View File

@ -0,0 +1,75 @@
defmodule EMQXUmbrella.MixProject do
use Mix.Project
def project do
[
apps_path: "apps",
version: pkg_vsn(),
start_permanent: Mix.env() == :prod,
deps: deps(),
releases: releases()
]
end
defp deps do
[
{:jiffy, github: "emqx/jiffy", tag: "1.0.5", override: true},
{:jsx, "~> 3.1", override: true},
{:gun, github: "emqx/gun", tag: "1.3.4", override: true},
{:hocon, github: "emqx/hocon", tag: "0.20.5", override: true},
{:cuttlefish,
github: "emqx/cuttlefish",
manager: :rebar3,
system_env: [{"CUTTLEFISH_ESCRIPT", "true"}],
override: true},
{:getopt, github: "emqx/getopt", tag: "v1.0.2", override: true},
{:cowboy, github: "emqx/cowboy", tag: "2.8.2", override: true},
{:cowlib, "~> 2.8", override: true},
{:ranch, "~> 2.0", override: true},
{:poolboy, github: "emqx/poolboy", tag: "1.5.2", override: true},
{:esockd, github: "emqx/esockd", tag: "5.8.0", override: true},
{:gproc, "~> 0.9", override: true},
{:eetcd, "~> 0.3", override: true},
{:grpc, github: "emqx/grpc-erl", tag: "0.6.2", override: true},
{:pbkdf2, github: "emqx/erlang-pbkdf2", tag: "2.0.4", override: true},
{:typerefl, github: "k32/typerefl", tag: "0.8.4", manager: :rebar3, override: true},
{:gen_rpc, github: "emqx/gen_rpc", tag: "2.5.1", override: true},
{:gen_coap, github: "emqx/gen_coap", tag: "v0.3.2", override: true},
{:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "0.14.0", override: true},
{:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.4.0", override: true}
| (enable_bcrypt() && [{:bcrypt, github: "emqx/erlang-bcrypt", tag: "0.6.0"}]) || []
]
end
defp releases do
[
emqx: fn ->
[
applications: EmqxReleaseHelper.applications(),
steps: [:assemble, &EmqxReleaseHelper.run/1]
]
end
]
end
def enable_bcrypt do
not match?({:win_32, _}, :os.type())
end
def project_path do
Path.expand("..", __ENV__.file)
end
def pkg_vsn do
project_path()
|> Path.join("pkg-vsn.sh")
|> System.cmd([])
|> elem(0)
|> String.trim()
|> String.split("-")
|> Enum.reverse()
|> tl()
|> Enum.reverse()
|> Enum.join("-")
end
end

44
mix.lock Normal file
View File

@ -0,0 +1,44 @@
%{
"bbmustache": {:hex, :bbmustache, "1.12.1", "857fbdf86bda46d07201b0e7a969820cb763a7c174c485fd0780d7e033efe9f0", [:rebar3], [], "hexpm", "f4320778c31a821a2a664db8894618abb79c1af7bbf7c03c703c8868d9bb09fe"},
"bcrypt": {:git, "https://github.com/emqx/erlang-bcrypt.git", "dc2ba66acf2332c111362d01137746eefecc5e90", [tag: "0.6.0"]},
"cowboy": {:git, "https://github.com/emqx/cowboy.git", "b89d4689a04149b1a4a3641280aa5c5643f921b2", [tag: "2.8.2"]},
"cowboy_swagger": {:git, "https://github.com/inaka/cowboy_swagger", "f4b49a4f289a9ee9ae1ff35772c4e191b5fafbd5", [tag: "2.4.0"]},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
"cuttlefish": {:git, "https://github.com/emqx/cuttlefish.git", "6c346563e89ebbd95dbc1c29017adaf9abf85ca1", []},
"ecpool": {:git, "https://github.com/emqx/ecpool.git", "0516d2cebd14654ef8c583c347e4a0b01363b86d", [tag: "0.5.1"]},
"eetcd": {:hex, :eetcd, "0.3.4", "27e8b4775230c53a9ef602f62a1603591302b40b2eb195d567edffb35b6cf1a2", [:rebar3], [{:gun, "1.3.3", [hex: :gun, repo: "hexpm", optional: false]}], "hexpm", "b763c0e1a9741d39a62f5a19186a342863eacbc769151c4e81db5790efecefca"},
"ekka": {:git, "https://github.com/emqx/ekka.git", "005fd6bb94199dc2ecb4ba03284f253b408e02d9", [tag: "0.11.1"]},
"emqtt": {:git, "https://github.com/emqx/emqtt.git", "25892ef48a979a9dfbd74d86133cb28cf11f3cf4", [tag: "1.4.3"]},
"emqx_http_lib": {:git, "https://github.com/emqx/emqx_http_lib.git", "9a1aafcbad1bb35392ebabc0cf102c7bce660432", [tag: "0.4.0"]},
"epgsql": {:git, "https://github.com/epgsql/epgsql.git", "895c8f9d53f08d09ec6a0301c56d3d6f270929f2", [tag: "4.4.0"]},
"esasl": {:git, "https://github.com/emqx/esasl.git", "1d4ab8d3ff7fd52018d3dddfec499933f9bb62b6", [tag: "0.1.0"]},
"esockd": {:git, "https://github.com/emqx/esockd.git", "9b959fc11a1c398a589892f335235be6c5b4a454", [tag: "5.8.0"]},
"estatsd": {:git, "https://github.com/emqx/estatsd.git", "5184d846b7ecb83509bd4d32695c60428c0198cd", [tag: "0.1.0"]},
"gen_coap": {:git, "https://github.com/emqx/gen_coap.git", "9bf5e7f795badf68e2fb4eb226f576308f5b1bb4", [tag: "v0.3.2"]},
"gen_rpc": {:git, "https://github.com/emqx/gen_rpc.git", "fb7418dc8cf7e97d153fba073bee0fac07dce753", [tag: "2.5.1"]},
"getopt": {:git, "https://github.com/emqx/getopt.git", "215f2083408e1fe562d441aea6062bf5d9e1fb67", [tag: "v1.0.2"]},
"gpb": {:hex, :gpb, "4.19.1", "665f59680577038508a11cf6c932fce26a4e35a19d586b912d763f292bc8e33b", [:make, :rebar3], [], "hexpm", "f6f4a7dcabd1723fdd3a3fd7c7efeea8146da02b6f575e75bfc49f15ff4db359"},
"gproc": {:hex, :gproc, "0.9.0", "853ccb7805e9ada25d227a157ba966f7b34508f386a3e7e21992b1b484230699", [:rebar3], [], "hexpm", "587e8af698ccd3504cf4ba8d90f893ede2b0f58cabb8a916e2bf9321de3cf10b"},
"grpc": {:git, "https://github.com/emqx/grpc-erl.git", "f8ba39eb075fb2a7f370563045d5e5d0914f2703", [tag: "0.6.2"]},
"gun": {:git, "https://github.com/emqx/gun.git", "e1b5e14139e2a936ad6561bf960f70f1e80b81e2", [tag: "1.3.4"]},
"hocon": {:git, "https://github.com/emqx/hocon.git", "2021a1b82c1f654c98181ba2dbfec5457c5c6eb7", [tag: "0.20.5"]},
"jiffy": {:git, "https://github.com/emqx/jiffy.git", "baa1f4e750ae3c5c9e54f9c2e52280b7fc24a8d9", [tag: "1.0.5"]},
"jose": {:hex, :jose, "1.11.2", "f4c018ccf4fdce22c71e44d471f15f723cb3efab5d909ab2ba202b5bf35557b3", [:mix, :rebar3], [], "hexpm", "98143fbc48d55f3a18daba82d34fe48959d44538e9697c08f34200fa5f0947d2"},
"jsx": {:hex, :jsx, "3.1.0", "d12516baa0bb23a59bb35dccaf02a1bd08243fcbb9efe24f2d9d056ccff71268", [:rebar3], [], "hexpm", "0c5cc8fdc11b53cc25cf65ac6705ad39e54ecc56d1c22e4adb8f5a53fb9427f3"},
"lc": {:git, "https://github.com/qzhuyan/lc.git", "6f38a748af0993bb4e440a0f9223d6aa7b90b86b", [tag: "0.1.1"]},
"lwm2m_coap": {:git, "https://github.com/emqx/lwm2m-coap.git", "495f3c62fae153040c89f9a0ba5344789ff5acc8", [tag: "v2.0.0"]},
"minirest": {:git, "https://github.com/emqx/minirest.git", "60c1a5a1f5df00a662cb34cf4101c7a21ffe08f9", [tag: "1.2.4"]},
"mria": {:git, "https://github.com/emqx/mria", "f0efc591339f960b5126ec4e1a0fed85d1578eb5", [tag: "0.1.2"]},
"mysql": {:git, "https://github.com/emqx/mysql-otp.git", "bdabac44cc8836a9e23897b7e1b77c7df7e04f70", [tag: "1.7.1"]},
"pbkdf2": {:git, "https://github.com/emqx/erlang-pbkdf2.git", "45d9981209ea07a83a58cf85aaf8236457da4342", [tag: "2.0.4"]},
"poolboy": {:git, "https://github.com/emqx/poolboy.git", "29be47db8c2be38b18c908e43a80ebb7b9b6116b", [tag: "1.5.2"]},
"prometheus": {:git, "https://github.com/emqx/prometheus.erl.git", "a41488df09472448057d264ef520cf2f71d925f8", [tag: "v3.1.1"]},
"quicer": {:git, "https://github.com/emqx/quic.git", "348c08a3f5a3b90861906fb436ff0ced453adfa2", [tag: "0.0.8"]},
"ranch": {:hex, :ranch, "2.1.0", "2261f9ed9574dcfcc444106b9f6da155e6e540b2f82ba3d42b339b93673b72a3", [:make, :rebar3], [], "hexpm", "244ee3fa2a6175270d8e1fc59024fd9dbc76294a321057de8f803b1479e76916"},
"recon": {:hex, :recon, "2.5.2", "cba53fa8db83ad968c9a652e09c3ed7ddcc4da434f27c3eaa9ca47ffb2b1ff03", [:mix, :rebar3], [], "hexpm", "2c7523c8dee91dff41f6b3d63cba2bd49eb6d2fe5bf1eec0df7f87eb5e230e1c"},
"replayq": {:git, "https://github.com/emqx/replayq", "9e5ba14d65ff1885ad85b6d33a859c01c322f273", [tag: "0.3.1"]},
"snabbkaffe": {:git, "https://github.com/kafka4beam/snabbkaffe.git", "ea1fbffddf8a3b5939bff61cc72ba45c3dceb058", [tag: "0.14.0"]},
"ssl_verify_fun": {:git, "https://github.com/deadtrickster/ssl_verify_fun.erl.git", "c5718226b0b9f3d1a38ef6ca3c3b4c75f53dda92", [tag: "1.1.4"]},
"trails": {:hex, :trails, "2.3.0", "b09703f056705f4943e14fff077b98c711a6f48fad40f4ff0b350794074ad69c", [:rebar3], [{:cowboy, "2.8.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:ranch, "2.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "40804001eb80417aa9d02400f39b7216956c3f251539a8a6096a69b3fac0ea07"},
"typerefl": {:git, "https://github.com/k32/typerefl.git", "a751e0664752b1824206ca34377ac2d2c3ed53bc", [tag: "0.8.4"]},
}

274
rel/overlays/bin/emqx Executable file
View File

@ -0,0 +1,274 @@
#!/bin/sh
set -e
SELF=$(readlink "$0" || true)
if [ -z "$SELF" ]; then SELF="$0"; fi
RELEASE_ROOT="$(CDPATH='' cd "$(dirname "$SELF")/.." && pwd -P)"
export RELEASE_ROOT
export RELEASE_NAME="${RELEASE_NAME:-"emqx"}"
export RELEASE_VSN="${RELEASE_VSN:-"$(cut -d' ' -f2 "$RELEASE_ROOT/releases/start_erl.data")"}"
export RELEASE_COMMAND="$1"
export RELEASE_MODE="${RELEASE_MODE:-"embedded"}"
export RELEASE_PROG="${RELEASE_PROG:-"$(echo "$0" | sed 's/.*\///')"}"
REL_VSN_DIR="$RELEASE_ROOT/releases/$RELEASE_VSN"
. "$REL_VSN_DIR/env.sh"
. "$RELEASE_ROOT/releases/emqx_vars"
export RELEASE_COOKIE="${RELEASE_COOKIE:-"$(cat "$RELEASE_ROOT/releases/COOKIE")"}"
export RELEASE_NODE="${RELEASE_NODE:-"$RELEASE_NAME"}"
export RELEASE_TMP="${RELEASE_TMP:-"$RELEASE_ROOT/tmp"}"
export RELEASE_VM_ARGS="${RELEASE_VM_ARGS:-"$REL_VSN_DIR/vm.args"}"
export RELEASE_REMOTE_VM_ARGS="${RELEASE_REMOTE_VM_ARGS:-"$REL_VSN_DIR/remote.vm.args"}"
export RELEASE_BOOT_SCRIPT="${RELEASE_BOOT_SCRIPT:-"start"}"
export RELEASE_BOOT_SCRIPT_CLEAN="${RELEASE_BOOT_SCRIPT_CLEAN:-"start_clean"}"
export RELEASE_SYS_CONFIG="${RELEASE_SYS_CONFIG:-"$REL_VSN_DIR/sys"}"
# defined in emqx_vars
export RUNNER_ROOT_DIR
export RUNNER_ETC_DIR
export ERTS_VSN
export SCHEMA_MOD=emqx_conf_schema
export CONFIGS_DIR="$RUNNER_DATA_DIR/configs"
export MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia"
set_name () {
IS_BOOT_COMMAND='no'
case "$1" in
start|start_iex|daemon|daemon_iex)
IS_BOOT_COMMAND='yes'
;;
esac
## Possible ways to configure emqx node name:
## 1. configure node.name in emqx.conf
## 2. override with environment variable EMQX_NODE_NAME
## Node name is either short-name (without '@'), e.g. 'emqx'
## or long name (with '@') e.g. 'emqx@example.net' or 'emqx@127.0.0.1'
NAME="${EMQX_NODE_NAME:-}"
if [ -z "$NAME" ]; then
if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
# for boot commands, inspect emqx.conf for node name
NAME="$(call_hocon -s $SCHEMA_MOD -c $RUNNER_ETC_DIR/emqx.conf get node.name | tr -d \")"
else
# for non-boot commands, inspect vm.<time>.args for node name
# shellcheck disable=SC2012,SC2086
LATEST_VM_ARGS="$(ls -t $CONFIGS_DIR/vm.*.args | head -1)"
NAME="$(grep -E '^-s?name' "$LATEST_VM_ARGS" | awk '{print $2}')"
fi
fi
[ -z "$NAME" ] && NAME='emqx'
case "$NAME" in
*@*)
NAME_TYPE='-name'
;;
*)
NAME_TYPE='-sname'
esac
SHORT_NAME="$(echo "$NAME" | awk -F'@' '{print $1}')"
export ESCRIPT_NAME="$SHORT_NAME"
export NAME_TYPE
export NAME
}
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
rand () {
dd count=1 bs=2 if=/dev/urandom 2> /dev/null | od -x | awk 'NR==1{print $2}'
}
generate_config () {
local name_type="$NAME_TYPE"
local node_name="$NAME"
## Delete the *.siz files first or it cann't start after
## changing the config 'log.rotation.size'
rm -rf "${RUNNER_LOG_DIR}"/*.siz
EMQX_LICENSE_CONF_OPTION=""
if [ "${EMQX_LICENSE_CONF:-}" != "" ]; then
EMQX_LICENSE_CONF_OPTION="-c ${EMQX_LICENSE_CONF}"
fi
## timestamp for each generation
local NOW_TIME
NOW_TIME="$(call_hocon now_time)"
## ths command populates two files: app.<time>.config and vm.<time>.args
## disable SC2086 to allow EMQX_LICENSE_CONF_OPTION to split
# shellcheck disable=SC2086
call_hocon -v -t $NOW_TIME -s $SCHEMA_MOD -c $RUNNER_ETC_DIR/emqx.conf $EMQX_LICENSE_CONF_OPTION -d $RUNNER_DATA_DIR/configs generate
## filenames are per-hocon convention
RELEASE_SYS_CONFIG="$CONFIGS_DIR/app.$NOW_TIME.config"
RELEASE_VM_ARGS="$CONFIGS_DIR/vm.$NOW_TIME.args"
## Merge hocon generated *.args into the vm.args
TMP_ARG_FILE="$CONFIGS_DIR/vm.args.tmp"
cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
echo "" >> "$TMP_ARG_FILE"
echo "-pa ${REL_VSN_DIR}/consolidated" >> "$TMP_ARG_FILE"
## read lines from generated vm.<time>.args file
## drop comment lines, and empty lines using sed
## pipe the lines to a while loop
sed '/^#/d' "$RELEASE_VM_ARGS" | sed '/^$/d' | while IFS='' read -r ARG_LINE || [ -n "$ARG_LINE" ]; do
## in the loop, split the 'key[:space:]value' pair
ARG_KEY=$(echo "$ARG_LINE" | awk '{$NF="";print}')
ARG_VALUE=$(echo "$ARG_LINE" | awk '{print $NF}')
## use the key to look up in vm.args file for the value
TMP_ARG_VALUE=$(grep "^$ARG_KEY" "$TMP_ARG_FILE" || true | awk '{print $NF}')
## compare generated (to override) value to original (to be overriden) value
if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
## if they are different
if [ -n "$TMP_ARG_VALUE" ]; then
## if the old value is present, replace it with generated value
sh -c "$SED_REPLACE 's|^$ARG_KEY.*$|$ARG_LINE|' $TMP_ARG_FILE"
else
## otherwise append generated value to the end
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
fi
fi
done
echo "$name_type $node_name" >> "$TMP_ARG_FILE"
## rename the generated vm.<time>.args file
mv -f "$TMP_ARG_FILE" "$RELEASE_VM_ARGS"
# # # shellcheck disable=SC2086
# if ! relx_nodetool chkconfig $CONFIG_ARGS; then
# die "failed_to_check_config $CONFIG_ARGS"
# fi
}
rpc () {
# TODO: remote vm args
exec "$REL_VSN_DIR/elixir" \
--hidden --cookie "$RELEASE_COOKIE" \
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
--vm-args "$RELEASE_REMOTE_VM_ARGS" \
--rpc-eval "$RELEASE_NODE" "$1"
}
start () {
generate_config
REL_EXEC="$1"
shift
exec "$REL_VSN_DIR/$REL_EXEC" \
--cookie "$RELEASE_COOKIE" \
--erl "-mode $RELEASE_MODE -mnesia dir \"${MNESIA_DATA_DIR}\"" \
--erl-config "$RELEASE_SYS_CONFIG" \
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
--vm-args "$RELEASE_VM_ARGS" "$@"
}
call_hocon() {
nodetool hocon "$@"
}
nodetool () {
command="$1"; shift
"$RUNNER_ROOT_DIR/erts-$ERTS_VSN/bin/erl" \
+B -noshell \
-boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
-boot_var RELEASE_LIB "$RELEASE_ROOT/lib" \
-run escript start \
-extra "$RUNNER_ROOT_DIR/bin/nodetool" \
"$command" "$@"
}
set_name "$1"
case $1 in
start)
start "elixir" --no-halt
;;
start_iex)
start "iex" --werl
;;
daemon)
start "elixir" --no-halt --pipe-to "${RELEASE_TMP}/pipe" "${RELEASE_TMP}/log"
;;
daemon_iex)
start "iex" --pipe-to "${RELEASE_TMP}/pipe" "${RELEASE_TMP}/log"
;;
eval)
if [ -z "$2" ]; then
echo "ERROR: EVAL expects an expression as argument" >&2
exit 1
fi
exec "$REL_VSN_DIR/elixir" \
--cookie "$RELEASE_COOKIE" \
--erl-config "$RELEASE_SYS_CONFIG" \
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
--vm-args "$RELEASE_VM_ARGS" --eval "$2"
;;
remote)
generate_config
exec "$REL_VSN_DIR/iex" \
--werl --hidden --cookie "$RELEASE_COOKIE" \
--boot "$REL_VSN_DIR/$RELEASE_BOOT_SCRIPT_CLEAN" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
--vm-args "$RELEASE_REMOTE_VM_ARGS" \
--remsh "$RELEASE_NODE"
;;
rpc)
if [ -z "$2" ]; then
echo "ERROR: RPC expects an expression as argument" >&2
exit 1
fi
rpc "$2"
;;
restart|stop)
rpc "System.$1()"
;;
pid)
rpc "IO.puts System.pid()"
;;
version)
echo "$RELEASE_NAME $RELEASE_VSN"
;;
*)
echo "Usage: $(basename "$0") COMMAND [ARGS]
The known commands are:
start Starts the system
start_iex Starts the system with IEx attached
daemon Starts the system as a daemon
daemon_iex Starts the system as a daemon with IEx attached
eval \"EXPR\" Executes the given expression on a new, non-booted system
rpc \"EXPR\" Executes the given expression remotely on the running system
remote Connects to the running system via a remote shell
restart Restarts the running system via a remote command
stop Stops the running system via a remote command
pid Prints the operating system PID of the running system via a remote command
version Prints the release name and version to be booted
" >&2
if [ -n "$1" ]; then
echo "ERROR: Unknown command $1" >&2
exit 1
fi
;;
esac

309
rel/overlays/bin/nodetool Executable file
View File

@ -0,0 +1,309 @@
#!/usr/bin/env escript
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
%% -------------------------------------------------------------------
%%
%% nodetool: Helper Script for interacting with live nodes
%%
%% -------------------------------------------------------------------
-mode(compile).
main(Args) ->
case os:type() of
{win32, nt} -> ok;
_nix ->
case init:get_argument(start_epmd) of
{ok, [["true"]]} ->
ok = start_epmd();
_ ->
ok
end
end,
case Args of
["hocon" | Rest] ->
%% forward the call to hocon_cli
hocon_cli:main(Rest);
_ ->
do(Args)
end.
do(Args) ->
ok = do_with_halt(Args, "mnesia_dir", fun create_mnesia_dir/2),
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",
fun(TargetName) ->
ThisNode = this_node_name(longnames, TargetName),
{ok, _} = net_kernel:start([ThisNode, longnames]),
put(target_node, nodename(TargetName))
end),
Args2 = do_with_ret(Args1, "-sname",
fun(TargetName) ->
ThisNode = this_node_name(shortnames, TargetName),
{ok, _} = net_kernel:start([ThisNode, shortnames]),
put(target_node, nodename(TargetName))
end),
RestArgs = do_with_ret(Args2, "-setcookie",
fun(Cookie) ->
erlang:set_cookie(node(), list_to_atom(Cookie))
end),
[application:start(App) || App <- [crypto, public_key, ssl]],
TargetNode = get(target_node),
%% See if the node is currently running -- if it's not, we'll bail
case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
{true, pong} ->
ok;
{false, pong} ->
io:format(standard_error, "Failed to connect to node ~p\n", [TargetNode]),
halt(1);
{_, pang} ->
io:format(standard_error, "Node ~p not responding to pings.\n", [TargetNode]),
halt(1)
end,
case RestArgs of
["getpid"] ->
io:format("~p\n", [list_to_integer(rpc:call(TargetNode, os, getpid, []))]);
["ping"] ->
%% If we got this far, the node already responsed to a ping, so just dump
%% a "pong"
io:format("pong\n");
["stop"] ->
case rpc:call(TargetNode, emqx_machine, graceful_shutdown, [], 60000) of
ok ->
ok;
{badrpc, nodedown} ->
%% nodetool commands are always executed after a ping
%% which if the code gets here, it's because the target node
%% has shutdown before RPC returns.
ok
end;
["rpc", Module, Function | RpcArgs] ->
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
[RpcArgs], 60000) of
ok ->
ok;
{error, cmd_not_found} ->
halt(1);
{error, Reason} ->
io:format("RPC to ~s error: ~p\n", [TargetNode, Reason]),
halt(1);
{badrpc, Reason} ->
io:format("RPC to ~s failed: ~p\n", [TargetNode, Reason]),
halt(1);
_ ->
halt(1)
end;
["rpc_infinity", Module, Function | RpcArgs] ->
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function), [RpcArgs], infinity) of
ok ->
ok;
{badrpc, Reason} ->
io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
halt(1);
_ ->
halt(1)
end;
["rpcterms", Module, Function | ArgsAsString] ->
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
consult(lists:flatten(ArgsAsString)), 60000) of
{badrpc, Reason} ->
io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
halt(1);
Other ->
io:format("~p\n", [Other])
end;
["eval" | ListOfArgs] ->
Parsed = parse_eval_args(ListOfArgs),
% and evaluate it on the remote node
case rpc:call(TargetNode, erl_eval, exprs, [Parsed, [] ]) of
{value, Value, _} ->
io:format ("~p~n",[Value]);
{badrpc, Reason} ->
io:format("RPC to ~p failed: ~p~n", [TargetNode, Reason]),
halt(1)
end;
Other ->
io:format("Other: ~p~n", [Other]),
io:format("Usage: nodetool chkconfig|getpid|ping|stop|rpc|rpc_infinity|rpcterms|eval|cold_eval [Terms] [RPC]\n")
end,
net_kernel:stop().
parse_eval_args(Args) ->
% shells may process args into more than one, and end up stripping
% spaces, so this converts all of that to a single string to parse
String = binary_to_list(
list_to_binary(
join(Args," ")
)
),
% then just as a convenience to users, if they forgot a trailing
% '.' add it for them.
Normalized =
case lists:reverse(String) of
[$. | _] -> String;
R -> lists:reverse([$. | R])
end,
% then scan and parse the string
{ok, Scanned, _} = erl_scan:string(Normalized),
{ok, Parsed } = erl_parse:parse_exprs(Scanned),
Parsed.
do_with_ret(Args, Name, Handler) ->
{arity, Arity} = erlang:fun_info(Handler, arity),
case take_args(Args, Name, Arity) of
false ->
Args;
{Args1, Rest} ->
_ = erlang:apply(Handler, Args1),
Rest
end.
do_with_halt(Args, Name, Handler) ->
{arity, Arity} = erlang:fun_info(Handler, arity),
case take_args(Args, Name, Arity) of
false ->
ok;
{Args1, _Rest} ->
erlang:apply(Handler, Args1), %% should halt
io:format(standard_error, "~s handler did not halt", [Name]),
halt(?LINE)
end.
%% Return option args list if found, otherwise 'false'.
take_args(Args, OptName, 0) ->
lists:member(OptName, Args) andalso [];
take_args(Args, OptName, OptArity) ->
take_args(Args, OptName, OptArity, _Scanned = []).
take_args([], _, _, _) -> false; %% no such option
take_args([Name | Rest], Name, Arity, Scanned) ->
length(Rest) >= Arity orelse error({not_enough_args_for, Name}),
{Result, Tail} = lists:split(Arity, Rest),
{Result, lists:reverse(Scanned) ++ Tail};
take_args([Other | Rest], Name, Arity, Scanned) ->
take_args(Rest, Name, Arity, [Other | Scanned]).
start_epmd() ->
[] = os:cmd("\"" ++ epmd_path() ++ "\" -daemon"),
ok.
epmd_path() ->
ErtsBinDir = filename:dirname(escript:script_name()),
Name = "epmd",
case os:find_executable(Name, ErtsBinDir) of
false ->
case os:find_executable(Name) of
false ->
io:format("Could not find epmd.~n"),
halt(1);
GlobalEpmd ->
GlobalEpmd
end;
Epmd ->
Epmd
end.
nodename(Name) ->
case re:split(Name, "@", [{return, list}, unicode]) of
[_Node, _Host] ->
list_to_atom(Name);
[Node] ->
[_, Host] = re:split(atom_to_list(node()), "@", [{return, list}, unicode]),
list_to_atom(lists:concat([Node, "@", Host]))
end.
this_node_name(longnames, Name) ->
[Node, Host] = re:split(Name, "@", [{return, list}, unicode]),
list_to_atom(lists:concat(["remsh_maint_", Node, os:getpid(), "@", Host]));
this_node_name(shortnames, Name) ->
list_to_atom(lists:concat(["remsh_maint_", Name, os:getpid()])).
%% For windows???
create_mnesia_dir(DataDir, NodeName) ->
MnesiaDir = filename:join(DataDir, NodeName),
file:make_dir(MnesiaDir),
io:format("~s", [MnesiaDir]),
halt(0).
chkconfig(File) ->
case file:consult(File) of
{ok, Terms} ->
case validate(Terms) of
ok ->
halt(0);
{error, Problems} ->
lists:foreach(fun print_issue/1, Problems),
%% halt(1) if any problems were errors
halt(case [x || {error, _} <- Problems] of
[] -> 0;
_ -> 1
end)
end;
{error, {Line, Mod, Term}} ->
io:format(standard_error, ["Error on line ", file:format_error({Line, Mod, Term}), "\n"], []),
halt(1);
{error, Error} ->
io:format(standard_error, ["Error reading config file: ", File, " ", file:format_error(Error), "\n"], []),
halt(1)
end.
%%
%% Given a string or binary, parse it into a list of terms, ala file:consult/0
%%
consult(Str) when is_list(Str) ->
consult([], Str, []);
consult(Bin) when is_binary(Bin)->
consult([], binary_to_list(Bin), []).
consult(Cont, Str, Acc) ->
case erl_scan:tokens(Cont, Str, 0) of
{done, Result, Remaining} ->
case Result of
{ok, Tokens, _} ->
{ok, Term} = erl_parse:parse_term(Tokens),
consult([], Remaining, [Term | Acc]);
{eof, _Other} ->
lists:reverse(Acc);
{error, Info, _} ->
{error, Info}
end;
{more, Cont1} ->
consult(Cont1, eof, Acc)
end.
%%
%% Validation functions for checking the app.config
%%
validate([Terms]) ->
Results = [ValidateFun(Terms) || ValidateFun <- get_validation_funs()],
Failures = [Res || Res <- Results, Res /= true],
case Failures of
[] ->
ok;
_ ->
{error, Failures}
end.
%% Some initial and basic checks for the app.config file
get_validation_funs() ->
[ ].
print_issue({warning, Warning}) ->
io:format(standard_error, "Warning in app.config: ~s~n", [Warning]);
print_issue({error, Error}) ->
io:format(standard_error, "Error in app.config: ~s~n", [Error]).
%% string:join/2 copy; string:join/2 is getting obsoleted
%% and replaced by lists:join/2, but lists:join/2 is too new
%% for version support (only appeared in 19.0) so it cannot be
%% used. Instead we just adopt join/2 locally and hope it works
%% for most unicode use cases anyway.
join([], Sep) when is_list(Sep) ->
[];
join([H|T], Sep) ->
H ++ lists:append([Sep ++ X || X <- T]).