Commit e4afcfc4 by root

rearrange branch

parent c31221c3
node_modules
.DS_Store .DS_Store
node_nodules .vscode
*.rdb
xtest*
.env
.make-function .make-function
temp
# a helper shell script # a helper shell script
MAKE_VERSION=1.1.2 MAKE_VERSION=1.2.5
define MAKEFUNCTIONCODE define MAKEFUNCTIONCODE
function hasChanges() { function hasChanges() {
...@@ -10,7 +10,18 @@ define MAKEFUNCTIONCODE ...@@ -10,7 +10,18 @@ define MAKEFUNCTIONCODE
} }
function getRelease() { function getRelease() {
awk -F= '/^RELEASE=/{print $$2}' release.conf # old : use tag in release.conf
# awk -F= '/^RELEASE=/{print $$2}' release.conf
# new use tag from git of the form -> 1.0.1-2-3b10c420
TAGN=$$(git describe | sed -e "s/-g.*//")
TV=$$(echo $$TAGN | sed -e "s/-.*//")
TM=$$(echo $$TAGN | sed -e "s/^[^\-]*//")
if [ -z "$$TM" ]
then
TM="-0"
fi
echo $$TV$$TM
} }
function getBaseTag() { function getBaseTag() {
...@@ -62,8 +73,21 @@ define MAKEFUNCTIONCODE ...@@ -62,8 +73,21 @@ define MAKEFUNCTIONCODE
function getVersion() { function getVersion() {
result=$$(getRelease) result=$$(getRelease)
if hasChanges ; then
result="$$result-dirty"
fi
echo $$result
}
function getVersionWithHash() {
result=$$(getRelease)
if differsFromRelease; then if differsFromRelease; then
result="$$result-$$(git log -n 1 --format=%h .)" # output only first 7 characters
# result="$$result-$$(git log -n 1 --format=%h .)"
# output first 8 characters
result="$$result-$$(git log -n 1 --format=%H . | head -c 8)"
fi fi
if hasChanges ; then if hasChanges ; then
...@@ -101,19 +125,66 @@ SHELL=/bin/bash ...@@ -101,19 +125,66 @@ SHELL=/bin/bash
include release.conf include release.conf
IMAGE=$(REGISTRY_HOST)/$(GROUPNAME)/$(PROJECTNAME) IMAGE=$(REGISTRY_HOST)/$(GROUPNAME)/$(PROJECTNAME)
VERSION=$(shell . $(RELEASE_SUPPORT) ; getVersion) VERSION=$(shell . $(RELEASE_SUPPORT) ; getVersion)
VERSIONHASH=$(shell . $(RELEASE_SUPPORT) ; getVersionWithHash)
TAG=$(shell . $(RELEASE_SUPPORT); getTag) TAG=$(shell . $(RELEASE_SUPPORT); getTag)
PROJECTPATH?=.
BUILDARG?=
RELEASE_SUPPORT := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))/.make-function RELEASE_SUPPORT := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))/.make-function
export MAKEFUNCTIONCODE export MAKEFUNCTIONCODE
.PHONY: pre-build docker-build post-build build release patch-release minor-release major-release tag check-status check-release showtag show-tag \
push do-push post-push post-init update-make # If the first argument is "run"...
doit=
ifeq (rmi,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (images,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (deploy,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (show-deploy,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (annotate,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifeq (rollback,$(firstword $(MAKECMDGOALS)))
doit=true
endif
ifdef doit
# use the rest as arguments for "make xxx"
#CMD_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
# ...and turn them into do-nothing targets
#$(eval $(CMD_ARGS):;@:)
ifdef n
DEPLOYARG= -n $(n) --context=$(c)
else
DEPLOYARG= -n nexpieio --context=$(c)
endif
endif
# ifeq ($(CMD_ARGS),)
# else
# EMPTY=
# SPACE=$(EMPTY) $(EMPTY)
# TDARG = $(subst $(SPACE), --context=,$(CMD_ARGS))
# DARG = -n $(TDARG)
# endif
.PHONY: pre-build docker-build post-build build cleanbuild release patch-release minor-release major-release tag check-status check-release showtag show-tag \
push do-push post-push post-init update-make rmi images deploy show-deploy annotate rollback
init: init:
@echo "$$MAKEFUNCTIONCODE" > ./.make-function @echo "$$MAKEFUNCTIONCODE" > ./.make-function
build: init pre-build docker-build post-build build: init pre-build docker-build post-build
cleanbuild: init pre-build docker-cleanbuild post-build
pre-build: pre-build:
post-build: post-build:
...@@ -126,65 +197,60 @@ post-init: ...@@ -126,65 +197,60 @@ post-init:
@rm .make-function @rm .make-function
docker-build: docker-build:
docker build -t $(IMAGE):$(VERSION) . docker build $(BUILDARG) -t $(IMAGE):$(VERSIONHASH) $(PROJECTPATH)
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \ @DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \ DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \ if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\ echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\ docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
else \ else \
echo docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ;\ echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ; \ docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ; \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
fi
docker-cleanbuild:
docker build --no-cache -t $(IMAGE):$(VERSIONHASH) $(PROJECTPATH)
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
echo docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag -f $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
else \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):latest ; \
echo docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
docker tag $(IMAGE):$(VERSIONHASH) $(IMAGE):$(VERSION) ;\
fi fi
release: check-status check-release build push release: check-status check-release build push
push: init do-push post-push push: init do-push post-push
rmi: delete-docker-image
images: list-docker-image
do-push: do-push:
docker push $(IMAGE):$(VERSIONHASH)
docker push $(IMAGE):$(VERSION) docker push $(IMAGE):$(VERSION)
docker push $(IMAGE):latest docker push $(IMAGE):latest
snapshot: build push build-push: build push
show-tag: init release.conf show-tag: init release.conf
@. $(RELEASE_SUPPORT); getVersion @. $(RELEASE_SUPPORT); getVersionWithHash
@rm .make-function @rm .make-function
showtag: init release.conf showtag: init release.conf
@. $(RELEASE_SUPPORT); getVersion @. $(RELEASE_SUPPORT); getVersionWithHash
@rm .make-function @rm .make-function
tag-patch-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextPatchLevel)
tag-patch-release: release.conf tag
tag-minor-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMinorLevel)
tag-minor-release: release.conf tag
tag-major-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMajorLevel)
tag-major-release: release.conf tag
patch-release: tag-patch-release release
@echo $(VERSION)
minor-release: tag-minor-release release
@echo $(VERSION)
major-release: tag-major-release release
@echo $(VERSION)
tag: TAG=$(shell . $(RELEASE_SUPPORT); getTag $(VERSION))
tag: check-status
@. $(RELEASE_SUPPORT) ; ! tagExists $(TAG) || (echo "ERROR: tag $(TAG) for version $(VERSION) already tagged in git" >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; setRelease $(VERSION)
git add .
git commit -m "bumped to version $(VERSION)" ;
git tag $(TAG) ;
@ if [ -n "$(shell git remote -v)" ] ; then git push --tags ; else echo 'no remote to push tags to' ; fi
check-status: init check-status: init
@. $(RELEASE_SUPPORT) ; ! hasChanges || (echo "ERROR: there are still outstanding changes" >&2) ; @. $(RELEASE_SUPPORT) ; ! hasChanges || (echo "ERROR: there are still outstanding changes" >&2) ;
@rm .make-function @rm .make-function
...@@ -200,3 +266,60 @@ update-make: init ...@@ -200,3 +266,60 @@ update-make: init
make-version: make-version:
@echo $(MAKE_VERSION) @echo $(MAKE_VERSION)
# awk to cut the column 3, xargs to run command passing arg from pipe
delete-docker-image:
@docker images | grep $(CMD_ARGS) | awk '{print $$3}' | xargs docker rmi || true
# || true to force exoit code to 0 otherwise if no line matched, make will show some error
list-docker-image:
@docker images | grep $(CMD_ARGS) || true
env-snippet:
@jq -r '..|select(type=="string") + "="' config/custom-environment-variables.json > _temp_file_.env
@keg -s nexpieconfig _temp_file_.env > /dev/null
@cat env-snippet-nexpieconfig.yaml
@rm _temp_file_.env
@rm nexpieconfig.yaml
@rm env-snippet-nexpieconfig.yaml
show-deploy: init release.conf
ifndef c
@echo Please run make show-deploy c={context}
else
kubectl rollout history deployment/$(DEPLOYMENT) $(DEPLOYARG)
endif
@rm .make-function
annotate: init release.conf
ifndef c
@echo Please run make show-deploy c={context} a="{annotation text}"
else ifndef a
@echo Please run make show-deploy c={context} a="{annotation text}"
else
kubectl annotate deployment/$(DEPLOYMENT) kubernetes.io/change-cause="$(a)" $(DEPLOYARG)
endif
@rm .make-function
rollback: init release.conf
ifndef r
@echo Please run make rollback r={revision} c={context}
else
kubectl rollout undo deployment/$(DEPLOYMENT) --to-revision=$(r) $(DEPLOYARG)
endif
@rm .make-function
deploy: init release.conf
ifndef c
@echo Deploy failed : Please make deploy with c={context}
else
@cat k8s/deployment.yaml | sed "s/{{IMAGE_TAG}}/$(VERSIONHASH)/g" | kubectl apply -f - $(DEPLOYARG)
@rm .make-function
ifdef a
@kubectl annotate deployment/$(DEPLOYMENT) kubernetes.io/change-cause="$(a)" $(DEPLOYARG)
endif
endif
.DS_Store
node_modules/
config/*.json
*.rdb
FROM node:8.10.0-alpine
WORKDIR /usr/src/app
ENV TERM=xterm
RUN apk add --update --no-cache python \
python-dev \
py-pip \
yarn \
openssh-client \
git \
&& rm -rf /var/cache/apk/*
COPY . .
RUN npm install
RUN apk del git \
&& rm -rf /var/cache/apk/*
EXPOSE 40000
CMD npm start
# a helper shell script
MAKE_VERSION=1.1.2
define MAKEFUNCTIONCODE
function hasChanges() {
# old version, just track uncommited + untracked files
# test -n "$$(git status -s .)"
# expect 1 to be normal so the untracked file .make-funcition will be ignored
test 0 -ne "$$(git status -s . | sed -e '/.make-function/d' | wc -l)"
}
function getRelease() {
awk -F= '/^RELEASE=/{print $$2}' release.conf
}
function getBaseTag() {
sed -n -e "s/^tag=\(.*\)$$(getRelease)\$$/\1/p" release.conf
}
function getTag() {
if [ -z "$$1" ] ; then
awk -F= '/^tag/{print $$2}' release.conf
else
echo "$$(getBaseTag)$$1"
fi
}
function setRelease() {
if [ -n "$$1" ] ; then
sed -i.x -e "s/^tag=.*/tag=$$(getTag $$1)/" release.conf
sed -i.x -e "s/^RELEASE=.*/RELEASE=$$1/g" release.conf
rm -f release.conf.x
runPreTagCommand "$$1"
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function runPreTagCommand() {
if [ -n "$$1" ] ; then
COMMAND=$$(sed -n -e "s/@@RELEASE@@/$$1/g" -e 's/^pre_tag_command=\(.*\)/\1/p' release.conf)
if [ -n "$$COMMAND" ] ; then
if ! OUTPUT=$$(bash -c "$$COMMAND" 2>&1) ; then echo $$OUTPUT >&2 && exit 1 ; fi
fi
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function tagExists() {
tag=$${1:-$$(getTag)}
test -n "$$tag" && test -n "$$(git tag | grep "^$$tag\$$")"
}
function differsFromRelease() {
tag=$$(getTag)
! tagExists $$tag || test -n "$$(git diff --shortstat -r $$tag .)"
}
function getVersion() {
result=$$(getRelease)
if differsFromRelease; then
result="$$result-$$(git log -n 1 --format=%h .)"
fi
if hasChanges ; then
result="$$result-dirty"
fi
echo $$result
}
function nextPatchLevel() {
version=$${1:-$$(getRelease)}
major_and_minor=$$(echo $$version | cut -d. -f1,2)
patch=$$(echo $$version | cut -d. -f3)
version=$$(printf "%s.%d" $$major_and_minor $$(($$patch + 1)))
echo $$version
}
function nextMinorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
minor=$$(echo $$version | cut -d. -f2);
version=$$(printf "%d.%d.0" $$major $$(($$minor + 1))) ;
echo $$version
}
function nextMajorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
version=$$(printf "%d.0.0" $$(($$major + 1)))
echo $$version
}
endef
SHELL=/bin/bash
include release.conf
IMAGE=$(REGISTRY_HOST)/$(GROUPNAME)/$(PROJECTNAME)
VERSION=$(shell . $(RELEASE_SUPPORT) ; getVersion)
TAG=$(shell . $(RELEASE_SUPPORT); getTag)
RELEASE_SUPPORT := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))/.make-function
export MAKEFUNCTIONCODE
.PHONY: pre-build docker-build post-build build release patch-release minor-release major-release tag check-status check-release showtag show-tag \
push do-push post-push post-init update-make
init:
@echo "$$MAKEFUNCTIONCODE" > ./.make-function
build: init pre-build docker-build post-build
pre-build:
post-build:
@rm .make-function
post-push:
@rm .make-function
post-init:
@rm .make-function
docker-build:
docker build -t $(IMAGE):$(VERSION) .
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\
else \
echo docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ; \
fi
release: check-status check-release build push
push: init do-push post-push
do-push:
docker push $(IMAGE):$(VERSION)
docker push $(IMAGE):latest
snapshot: build push
show-tag: init release.conf
@. $(RELEASE_SUPPORT); getVersion
@rm .make-function
showtag: init release.conf
@. $(RELEASE_SUPPORT); getVersion
@rm .make-function
tag-patch-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextPatchLevel)
tag-patch-release: release.conf tag
tag-minor-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMinorLevel)
tag-minor-release: release.conf tag
tag-major-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMajorLevel)
tag-major-release: release.conf tag
patch-release: tag-patch-release release
@echo $(VERSION)
minor-release: tag-minor-release release
@echo $(VERSION)
major-release: tag-major-release release
@echo $(VERSION)
tag: TAG=$(shell . $(RELEASE_SUPPORT); getTag $(VERSION))
tag: check-status
@. $(RELEASE_SUPPORT) ; ! tagExists $(TAG) || (echo "ERROR: tag $(TAG) for version $(VERSION) already tagged in git" >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; setRelease $(VERSION)
git add .
git commit -m "bumped to version $(VERSION)" ;
git tag $(TAG) ;
@ if [ -n "$(shell git remote -v)" ] ; then git push --tags ; else echo 'no remote to push tags to' ; fi
check-status: init
@. $(RELEASE_SUPPORT) ; ! hasChanges || (echo "ERROR: there are still outstanding changes" >&2) ;
@rm .make-function
check-release: init release.conf post-init
@. $(RELEASE_SUPPORT) ; tagExists $(TAG) || (echo "ERROR: version not yet tagged in git. make [minor,major,patch]-release." >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; ! differsFromRelease $(TAG) || (echo "ERROR: current directory differs from tagged $(TAG). make [minor,major,patch]-release." ; exit 1)
update-make: init
@rm Makefile
wget https://dev.nexpie.com/sample/docker-makefile-sample/raw/master/Makefile
@rm .make-function
make-version:
@echo $(MAKE_VERSION)
var config = require('config');
// https://github.com/isaacs/node-lru-cache
var on_message_redis = require('./redis/on_message').on_message_redis
var LRU = require("lru-cache"),
cache = LRU({
max: 500,
maxAge: 1000 * 60 * 5
});
module.exports = function (options = {}) {
return function (req, res, next) {
if (req.header('vernemq-hook') == 'auth_on_publish' && req && req.body) {
if (options.debug) {
console.log('auth_on_publish-------------');
console.log(req.body);
}
var topic = req.body.topic;
var authstatus;
var cachekey = 'pub:' + req.body.client_id + ':' + req.body.username + ':' + topic;
var authstatus = cache.get(cachekey);
if (typeof (authstatus) === 'undefined') {
cache.set(cachekey, true); // cache missed
}
var response
var decoded = require('jwt-verify').verify(req.body.username).res
if (decoded) {
if (decoded.role === 'realtimedb') response = { 'result': 'ok' }
else response = { result: { error: 'not allowed' } }
res.send(response);
next();
}
else {
var GGID = require('./utils/getGroupID');
var output = {};
GGID.getGroupID(req.body.username, req.body.client_id, function (group) {
if (group) {
var _ftopic = require('./utils/router').rewriteTopic(topic, 'pub', group, req.body.client_id, output); // get topic where concat with groupID
response = {
'result': 'ok',
'modifiers': {
'topic': _ftopic,
'qos': 0,
'retain': false
}
}
if (options.debug) {
console.log(response);
}
if (output.verb == 'get' || output.verb == 'read') {
response.modifiers.payload = Buffer.from(req.body.client_id).toString('base64');
}
// save on redis before send response
try {
on_message_redis(req.body.client_id, req.body.payload, topic)
res.send(response);
}
catch (e) {
res.send({ result: { error: 'not allowed' } });
}
next();
}
else {
res.send({ result: { error: 'not allowed' } });
next();
}
});
}
}
else {
res.send({ result: { error: 'not allowed' } });
next();
}
}
}
var validator = require('./validator');
var config = require('config');
// var seneca = require('seneca')({log: 'silent'}).client({ port: config.get('device_registry_port'), host: config.get('device_registry_host') });
var seneca = require('seneca')({ log: 'silent' }).client({ port: config.get('token_registry_port'), host: config.get('token_registry_host') });
var on_register_redis = require('./redis/on_register').on_register_redis
// https://github.com/isaacs/node-lru-cache
var LRU = require("lru-cache"),
cache = LRU({
max: 500,
maxAge: 1000 * 60 * 5
});
var debug = false;
// var authclient = require('seneca')({ log: 'silent' })
// .client({ port: config.get('authserv_port'), host: config.get('authserv_host') });
function authCheck(client_id, token, password, callback) {
const util = require('util')
// console.log(util.inspect(myObject, false, null, true));
// console.log('jwt-result:' + util.inspect(require('jwt-verify').verify(token), false, null, true))
if (require('jwt-verify').verify(token).res) { // auth realtimedb by token
callback(true);
}
else {
console.log('token :' + token)
seneca.act('ms:tokenregistry, cmd:getAttributes, type:device, tokencode:' + token, function (err, res) {
console.log('result : ' + util.inspect(res.result, false, null, true))
if (res.result) {
var token_profile = (res && res.result) ? res.result : {};
var mqttauth = {
clientid: client_id,
token: token,
password: password
};
console.log('validator:', util.inspect(validator.auth_connect(mqttauth, token_profile), false, null, true))
callback(validator.auth_connect(mqttauth, token_profile).status);
}
else {
callback(false);
}
});
}
}
module.exports = function (options = {}) {
debug = options.debug || false;
return function (req, res, next) {
if (req.header('vernemq-hook') == 'auth_on_register' && req && req.body) {
if (debug) {
console.log('auth_on_register-------------');
console.log(req.body);
}
var cachekey = 'auth:' + req.body.client_id + ':' + req.body.username + ':' + req.body.password;
var authstatus = cache.get(cachekey);
if (typeof (authstatus) == 'undefined') {
authCheck(req.body.client_id, req.body.username, req.body.password, function (result) {
cache.set(cachekey, result);
if (result) {
try {
on_register_redis(req.body.client_id)
res.send({ result: 'ok' });
}
catch (e) {
res.send({ result: { error: 'not allowed' } });
}
} else {
res.send({ result: { error: 'not allowed' } });
}
});
}
else {
if (authstatus) {
on_register_redis(req.body.client_id)
res.send({ result: 'ok' });
} else {
res.send({ result: { error: 'not allowed' } });
}
}
next();
}
else {
res.send({ result: { error: 'not allowed' } });
next();
}
}
}
var config = require('config');
// https://github.com/isaacs/node-lru-cache
var LRU = require("lru-cache"),
cache = LRU({
max: 500,
maxAge: 1000 * 60 * 5
});
module.exports = function (options = {}) {
return function (req, res, next) {
if (options.debug) {
console.log('auth_on_subscribe-------------');
console.log(req.body);
}
if (req.header('vernemq-hook') == 'auth_on_subscribe' && req && req.body) {
var authstatus;
var topic = req.body.topics[0].topic;
var cachekey = 'sub:' + req.body.client_id + ':' + req.body.username + ':' + topic;
var authstatus = cache.get(cachekey);
if (typeof (authstatus) == 'undefined') {
cache.set(cachekey, true); // cache missed
}
var response
var decoded = require('jwt-verify').verify(req.body.username).res
if (decoded) {
if (decoded.role === 'realtimedb') response = { 'result': 'ok' }
else response = { result: {error: 'not allowed'} }
if (options.debug) {
console.log('response:');
console.log(req.body);
}
res.send(response);
next();
}
else {
var GGID = require('./utils/getGroupID');
GGID.getGroupID(req.body.username, req.body.client_id, function (group) {
if (group) {
var _ftopic = require('./utils/router').rewriteTopic(topic, 'sub', group, req.body.client_id) // get topic where concat with groupID
var _topic = [{ // setTopic for response
'topic': _ftopic,
'qos': 0
}]
response = {
'result': 'ok',
'topics': _topic
}
if (options.debug) {
console.log(response);
}
res.send(response);
next();
}
else {
res.send({ result: {error: 'not allowed'} });
next();
}
});
}
}
else {
res.send({ result: {error: 'not allowed'} });
next();
}
}
}
{
"device_registry_host" : "DEVICEREGISTRY_HOST",
"device_registry_port" : "DEVICEREGISTRY_PORT",
"token_registry_host" : "TOKENREGISTRY_HOST",
"token_registry_port" : "TOKENREGISTRY_PORT",
"auth_on_register_debug" : "AUTH_ON_REGISTER_DEBUG",
"auth_on_publish_debug" : "AUTH_ON_PUBLISH_DEBUG",
"auth_on_subscribe_debug" : "AUTH_ON_SUBSCRIBE_DEBUG",
"on_publish_debug" : "ON_PUBLISH_DEBUG",
"on_deliver_debug" : "ON_DELIVER_DEBUG",
"on_unsubscribe_debug" : "ON_UNSUBSCRIBE_DEBUG",
"on_offline_debug" : "ON_OFFLINE_DEBUG"
}
{
"device_registry_host" : "127.0.0.1",
"device_registry_port" : 8990,
"auth_on_register_debug" : false,
"auth_on_publish_debug" : false,
"auth_on_subscribe_debug" : false,
"on_publish_debug" : false,
"on_deliver_debug" : false,
"on_unsubscribe_debug" : false,
"on_offline_debug" : false
}
{
"device_registry_host" : "alpha.nexpie.io",
"device_registry_port" : 8990,
"token_registry_host" : "localhost",
"token_registry_port" : 8790,
"auth_on_register_debug" : true,
"auth_on_publish_debug" : true,
"auth_on_subscribe_debug" : true,
"on_publish_debug" : true,
"on_deliver_debug" : true,
"on_unsubscribe_debug" : true,
"on_offline_debug" : true
}
{
"device_registry_host" : "alpha.nexpie.io",
"device_registry_port" : 8990,
"token_registry_host" : "alpha.nexpie.io",
"token_registry_port" : 8790,
"auth_on_register_debug" : true,
"auth_on_publish_debug" : true,
"auth_on_subscribe_debug" : true,
"on_publish_debug" : true,
"on_deliver_debug" : true,
"on_unsubscribe_debug" : true,
"on_offline_debug" : true
}
process.env["NODE_CONFIG_DIR"] = __dirname + "/config/";
var config = require('config');
var auth_on_register_debug = config.get('auth_on_register_debug');
var auth_on_publish_debug = config.get('auth_on_publish_debug');
var auth_on_subscribe_debug = config.get('auth_on_subscribe_debug');
var on_publish_debug = config.get('on_publish_debug');
var on_deliver_debug = config.get('on_deliver_debug');
var on_unsubscribe_debug = config.get('on_unsubscribe_debug');
var on_offline_debug = config.get('on_offline_debug');
var restify = require('restify');
var auth_on_register = require('./auth_on_register')({ debug: auth_on_register_debug });
var auth_on_publish = require('./auth_on_publish')({ debug: auth_on_publish_debug });
var auth_on_subscribe = require('./auth_on_subscribe')({ debug: auth_on_subscribe_debug });
var on_publish = require('./on_publish')({ debug: on_publish_debug });
var on_deliver = require('./on_deliver')({ debug: on_deliver_debug });
var on_unsubscribe = require('./on_unsubscribe')({ debug: on_unsubscribe_debug });
var on_offline = require('./on_offline')({ debug: on_offline_debug });
const server = restify.createServer({
name: 'authhook',
version: '1.0.1',
});
const port = 40000;
server.use(restify.plugins.bodyParser());
// for testing
function authByUserPasswd(client_id, username, password) {
if (!client_id || !username || !password) return false;
else return true;
}
server.get('/about', function (req, res, next) {
res.send(server.name);
});
server.post('/authreg', auth_on_register);
server.post('/authpub', auth_on_publish);
server.post('/authsub', auth_on_subscribe);
server.post('/onsub', (req, res, next) => {
console.log(req.body)
res.send('')
})
server.post('/onunsub', on_unsubscribe)
server.post('/ondeliver', on_deliver)
server.post('/onpub', on_publish)
server.post('/onoff', on_offline)
server.post('/ongone', on_offline)
server.listen(port, function () {
console.log('%s listening at %s', server.name, server.url);
});
var modify = require('./utils/modify');
module.exports = function(options = {}) {
return function (req, res, next) {
console.log('----on_deliver-----')
var topics = modify.removeTempWordInTopic(req.body.topic)
console.log(req.body)
// console.log(topics)
var response = {
'result': 'ok',
'modifiers': {
"topic": topics
}
}
console.log(response);
res.send(response)
}
// module.exports.on_deliver = on_deliver
// function joinTopic(topics) {
// var topic = topics.split('/!')[1]
// return topics.split('/!')[0] + topic.substring(topic.indexOf('/'), topic.length)
// }
}
var on_offline_redis = require('./redis/on_offline').on_offline_redis
module.exports = function (options = {}) {
debug = options.debug || false;
return function (req, res, next) {
console.log('auth_on_offline')
on_offline_redis(req.body.client_id)
res.status(200);
res.send('');
}
}
var config = require('config');
// https://github.com/isaacs/node-lru-cache
var LRU = require("lru-cache") ,
cache = LRU({
max: 500,
maxAge: 1000 * 60 * 5
});
module.exports = function(options={}) {
return function(req, res, next) {
if (req.header('vernemq-hook') == 'on_publish' && req && req.body) {
if (options.debug) {
console.log('on_publish-------------');
console.log(req.body);
}
console.log(req.body)
var topic = req.body.topic;
var cachekey = 'pub:'+req.body.client_id +':'+ req.body.username+':'+topic;
var authstatus = cache.get(cachekey);
res.status(200);
res.send('');
next();
}
else {
res.status(200);
res.send('');
next();
}
}
}
module.exports = function(options = {}) {
return function (req, res, next) {
console.log('------on unsubscribe-------')
console.log(req.body)
var topic = req.body.topics[0];
var token = req.body.username
var client_id = req.body.client_id
var response
var decoded = require('jwt-verify').verify(token).res
if (decoded) {
if (decoded.role === 'realtimedb') {
response = { result: 'ok' }
}
else response = { result: {error: 'not allowed'} }
res.send(response);
next()
}
else {
var GGID = require('./utils/getGroupID');
GGID.getGroupID(token, client_id, function(group) {
if (group) {
var _ftopic = require('./utils/router').rewriteTopic(topic, 'unsub', group, client_id)
response = {
"result": "ok",
"topics": [_ftopic]
}
}
else response = { result: {error: 'not allowed'} }
if (options.debug) {
console.log('on_unsubscribe-------------');
console.log(response);
}
res.send(response);
next()
});
}
}
}
{
"name": "authhook",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
"integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"backoff": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
"integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=",
"requires": {
"precond": "0.2"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"optional": true,
"requires": {
"tweetnacl": "^0.14.3"
}
},
"boom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
"integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=",
"requires": {
"hoek": "4.x.x"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=",
"dev": true
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"bunyan": {
"version": "1.8.12",
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
"requires": {
"dtrace-provider": "~0.8",
"moment": "^2.10.6",
"mv": "~2",
"safe-json-stringify": "~1"
}
},
"cluster-key-slot": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.12.tgz",
"integrity": "sha512-21O0kGmvED5OJ7ZTdqQ5lQQ+sjuez33R+d35jZKLwqUb5mqcPHUsxOSzj61+LHVtxGZd1kShbQM3MjB/gBJkVg=="
},
"commander": {
"version": "2.15.1",
"resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"config": {
"version": "1.31.0",
"resolved": "https://registry.npmjs.org/config/-/config-1.31.0.tgz",
"integrity": "sha1-qwiuumU2AV0iDNCv4Us+BQEIJUI=",
"requires": {
"json5": "^1.0.1"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"csv": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/csv/-/csv-1.2.1.tgz",
"integrity": "sha1-UjHt/BxxUlEuxFeBB2p6l/9SXAw=",
"requires": {
"csv-generate": "^1.1.2",
"csv-parse": "^1.3.3",
"csv-stringify": "^1.1.2",
"stream-transform": "^0.2.2"
}
},
"csv-generate": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-1.1.2.tgz",
"integrity": "sha1-7GsA7a7W5ZrZwgWC9MNk4osUYkA="
},
"csv-parse": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.3.3.tgz",
"integrity": "sha1-0c/YdDwvhJoKuy/VRNtWaV0ZpJA="
},
"csv-stringify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-1.1.2.tgz",
"integrity": "sha1-d6QVJlgbzjOA8SsA18W7rHDIK1g=",
"requires": {
"lodash.get": "~4.4.2"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"requires": {
"ms": "2.0.0"
}
},
"denque": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.3.0.tgz",
"integrity": "sha512-4SRaSj+PqmrS1soW5/Avd7eJIM2JJIqLLmwhRqIGleZM/8KwZq80njbSS2Iqas+6oARkSkLDHEk4mm78q3JlIg=="
},
"detect-node": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
"integrity": "sha1-AU7o+PZpxcWAI9pkuBecCDooxGw="
},
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=",
"dev": true
},
"dtrace-provider": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz",
"integrity": "sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=",
"optional": true,
"requires": {
"nan": "^2.10.0"
}
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"optional": true,
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"ecdsa-sig-formatter": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
"integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"eraro": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eraro/-/eraro-1.0.0.tgz",
"integrity": "sha1-iiFn8LxvlkIAovzeejhtLV27+RI=",
"requires": {
"lodash": "4.17"
}
},
"escape-regexp-component": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz",
"integrity": "sha1-nGO20LJf8qiMOtvRjFthrMO5+qI="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
"ewma": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ewma/-/ewma-2.0.1.tgz",
"integrity": "sha1-mHbBxJGsVzPIZmABo5YaBMl88eg=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-decode-uri-component": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.0.tgz",
"integrity": "sha1-fOEDNqpLJihv7pPXHmeF/w9ZajM="
},
"find-my-way": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-1.15.2.tgz",
"integrity": "sha1-fpoGJ94DrXpBlZ83yQhs65pfUJA=",
"requires": {
"fast-decode-uri-component": "^1.0.0",
"safe-regex": "^1.1.0",
"semver-store": "^0.3.0"
}
},
"flexbuffer": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/flexbuffer/-/flexbuffer-0.0.6.tgz",
"integrity": "sha1-A5/fI/iCPkQMOPMnfm/vEXQhWzA="
},
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha1-cPt8oCkO5v+WEJBBX0s989IIJlk="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"gate-executor": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/gate-executor/-/gate-executor-1.1.1.tgz",
"integrity": "sha1-Zn9ncoSg2+hrbEigtK/oxISBLK8="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"gex": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/gex/-/gex-0.3.0.tgz",
"integrity": "sha1-IXMkzNblxh0khckT63YUshNYuX8=",
"requires": {
"lodash": "4.17"
}
},
"glob": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
"integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
"optional": true,
"requires": {
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "2 || 3",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4=",
"dev": true
},
"handle-thing": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
"integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"he": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
"dev": true
},
"hoek": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
"integrity": "sha1-ljRQKqEsRF3Vp8VzS1cruHOKrLs="
},
"hpack.js": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
"integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
"requires": {
"inherits": "^2.0.1",
"obuf": "^1.0.0",
"readable-stream": "^2.0.1",
"wbuf": "^1.1.0"
}
},
"http-deceiver": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
"integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ioredis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.2.0.tgz",
"integrity": "sha512-PdxZGNJBfPiR2RI6DkqmiacL1+ML3gaqEiaC5QXWQt9eSTlGj+BwDCct0s8irn1ed8GyzAHTzcjvU9fmnl6D7A==",
"requires": {
"cluster-key-slot": "^1.0.6",
"debug": "^3.1.0",
"denque": "^1.1.0",
"flexbuffer": "0.0.6",
"lodash.defaults": "^4.2.0",
"lodash.flatten": "^4.4.0",
"redis-commands": "1.4.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
"standard-as-callback": "^1.0.0"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=",
"requires": {
"minimist": "^1.2.0"
}
},
"jsonic": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/jsonic/-/jsonic-0.3.0.tgz",
"integrity": "sha1-tUXalfVDkuWLPdoF9fLjd6bJ0b8="
},
"jsonwebtoken": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
"integrity": "sha1-BWyQ7ummXtbmxy3bCh0yUQmq9kM=",
"requires": {
"jws": "^3.1.5",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1"
},
"dependencies": {
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"jwa": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz",
"integrity": "sha1-hyQOdsmAjb3hh4PPImTvSSnuUOY=",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.10",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz",
"integrity": "sha1-gNEtBbKT0ehB58uLTmnlYa3Pg08=",
"requires": {
"jwa": "^1.1.5",
"safe-buffer": "^5.0.1"
}
},
"jwt-verify": {
"version": "git+https://nexpienpm:CCqLQjg4ytvzN7QbssUV@dev.nexpie.com/npm/jwt-verify.git#c9692da3fd11464e9270acd0c47f289648119ec9",
"from": "git+https://nexpienpm:CCqLQjg4ytvzN7QbssUV@dev.nexpie.com/npm/jwt-verify.git",
"requires": {
"config": "^2.0.1",
"jsonwebtoken": "^8.3.0"
},
"dependencies": {
"config": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/config/-/config-2.0.1.tgz",
"integrity": "sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ==",
"requires": {
"json5": "^1.0.1"
}
}
}
},
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
},
"lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
},
"lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
},
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"lru-cache": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
"integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=",
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE="
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
},
"dependencies": {
"minimist": {
"version": "0.0.8",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
},
"mocha": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
"integrity": "sha1-bYrlCPWRZ/lA8rWzxKYSrlDJCuY=",
"dev": true,
"requires": {
"browser-stdout": "1.3.1",
"commander": "2.15.1",
"debug": "3.1.0",
"diff": "3.5.0",
"escape-string-regexp": "1.0.5",
"glob": "7.1.2",
"growl": "1.10.5",
"he": "1.1.1",
"minimatch": "3.0.4",
"mkdirp": "0.5.1",
"supports-color": "5.4.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
}
}
},
"moment": {
"version": "2.22.2",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=",
"optional": true
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"mv": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
"integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=",
"optional": true,
"requires": {
"mkdirp": "~0.5.1",
"ncp": "~2.0.0",
"rimraf": "~2.4.0"
}
},
"nan": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz",
"integrity": "sha1-V042Dk2VSrFpZuwQLAwEn9lhoJk=",
"optional": true
},
"ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"optional": true
},
"ndjson": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz",
"integrity": "sha1-rmA7NrE0vOw0e0UkIrC/mNWDLsg=",
"requires": {
"json-stringify-safe": "^5.0.1",
"minimist": "^1.2.0",
"split2": "^2.1.0",
"through2": "^2.0.3"
}
},
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"nid": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/nid/-/nid-0.3.2.tgz",
"integrity": "sha1-l3qTGO1cKjjt1mJj8+r9gUPyJRo="
},
"norma": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/norma/-/norma-0.4.1.tgz",
"integrity": "sha1-C+LwW7pMA0xs5brJhE4SQWmdZYU=",
"requires": {
"eraro": "1.0",
"lodash": "4.17"
}
},
"obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
"integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"ordu": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ordu/-/ordu-0.1.1.tgz",
"integrity": "sha1-nIEJSTaTyvCCmfyoTFlq64YLrqo="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"patrun": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/patrun/-/patrun-1.0.0.tgz",
"integrity": "sha1-xQohdOPgKv5/vDXRbmWNIcZqHmY=",
"requires": {
"gex": "0.3",
"lodash": "4.17"
}
},
"pidusage": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-1.2.0.tgz",
"integrity": "sha1-Ze6WrOTgikzT+SQJlshbNnFx7pI="
},
"precond": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
"integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw="
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY="
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"reconnect-core": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/reconnect-core/-/reconnect-core-1.3.0.tgz",
"integrity": "sha1-+65SkZp4d9hE4yRtAaLyZwHIM8g=",
"requires": {
"backoff": "~2.5.0"
}
},
"redis-commands": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz",
"integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw=="
},
"redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
"integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
},
"redis-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
"integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
"requires": {
"redis-errors": "^1.0.0"
}
},
"restify": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/restify/-/restify-7.2.1.tgz",
"integrity": "sha1-+sTRSSJMvPs+0GWF3whDNWkCXas=",
"requires": {
"assert-plus": "^1.0.0",
"bunyan": "^1.8.12",
"csv": "^1.1.1",
"dtrace-provider": "^0.8.1",
"escape-regexp-component": "^1.0.2",
"ewma": "^2.0.1",
"find-my-way": "^1.13.0",
"formidable": "^1.2.1",
"http-signature": "^1.2.0",
"lodash": "^4.17.10",
"lru-cache": "^4.1.3",
"mime": "^1.5.0",
"negotiator": "^0.6.1",
"once": "^1.4.0",
"pidusage": "^1.2.0",
"qs": "^6.5.2",
"restify-errors": "^5.0.0",
"semver": "^5.4.1",
"spdy": "^3.4.7",
"uuid": "^3.1.0",
"vasync": "^1.6.4",
"verror": "^1.10.0"
}
},
"restify-errors": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/restify-errors/-/restify-errors-5.0.0.tgz",
"integrity": "sha1-ZocX4QBoPuxs4NUV+J/x2+wlSo0=",
"requires": {
"assert-plus": "^1.0.0",
"lodash": "^4.2.1",
"safe-json-stringify": "^1.0.3",
"verror": "^1.8.1"
}
},
"ret": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
"integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w="
},
"rimraf": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"optional": true,
"requires": {
"glob": "^6.0.1"
}
},
"rolling-stats": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/rolling-stats/-/rolling-stats-0.1.1.tgz",
"integrity": "sha1-zVr3dKiJOzCmdIMvovSrqkeM/IA="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
},
"safe-json-stringify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
"integrity": "sha1-NW5EvJjx+TzkXfFLzXwBzahuCv0=",
"optional": true
},
"safe-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"requires": {
"ret": "~0.1.10"
}
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
},
"semver": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
"integrity": "sha1-ff3YgUvbfKvHvg+x1zTPtmyUBHc="
},
"semver-store": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz",
"integrity": "sha1-zmAv8H3zcIDsn0+0CylXZUe+++k="
},
"seneca": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/seneca/-/seneca-3.7.0.tgz",
"integrity": "sha1-HaY79FINyBjdh5SgChYfi3GWm9M=",
"requires": {
"archy": "1.0",
"eraro": "1.0",
"gate-executor": "1.1",
"gex": "0.3",
"json-stringify-safe": "5.0",
"jsonic": "0.3",
"lodash": "4.17",
"minimist": "1.2",
"nid": "0.3",
"norma": "0.4",
"ordu": "0.1",
"patrun": "1.0",
"qs": "6.5",
"rolling-stats": "0.1",
"semver": "5.5",
"seneca-transport": "2.3",
"use-plugin": "1.0",
"wreck": "12.5"
}
},
"seneca-transport": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/seneca-transport/-/seneca-transport-2.3.0.tgz",
"integrity": "sha1-85KtZrknyzLmld8WEzKrsRtNdBA=",
"requires": {
"eraro": "1.0",
"gex": "0.3",
"jsonic": "0.3",
"lodash": "4.17",
"lru-cache": "4.1",
"ndjson": "1.5",
"nid": "0.3",
"patrun": "1.0",
"qs": "6.5",
"reconnect-core": "1.3",
"wreck": "12.5"
}
},
"spdy": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
"integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
"requires": {
"debug": "^2.6.8",
"handle-thing": "^1.2.5",
"http-deceiver": "^1.2.7",
"safe-buffer": "^5.0.1",
"select-hose": "^2.0.0",
"spdy-transport": "^2.0.18"
}
},
"spdy-transport": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz",
"integrity": "sha1-S7sVqv/tC+791WrWHb3Iuj4st6E=",
"requires": {
"debug": "^2.6.8",
"detect-node": "^2.0.3",
"hpack.js": "^2.1.6",
"obuf": "^1.1.1",
"readable-stream": "^2.2.9",
"safe-buffer": "^5.0.1",
"wbuf": "^1.7.2"
}
},
"split2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
"integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=",
"requires": {
"through2": "^2.0.2"
}
},
"sshpk": {
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"standard-as-callback": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-1.0.1.tgz",
"integrity": "sha512-izxEITSyc7S+5oOiF/URiYaNkemPUxIndCNv66jJ548Y1TVxhBvioNMSPrZIQdaZDlhnguOdUzHA/7hJ3xFhuQ=="
},
"stream-transform": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-0.2.2.tgz",
"integrity": "sha1-dYZ0h/SVKPi/HYJJllh1PQLfeDg="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
"integrity": "sha1-HGszdALCE3YF7+GfEP7DkPb6q1Q=",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"through2": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
"integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
"requires": {
"readable-stream": "^2.1.5",
"xtend": "~4.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
},
"use-plugin": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/use-plugin/-/use-plugin-1.0.2.tgz",
"integrity": "sha1-kuTm2asDtpAxCTpnhkWdwIeR1DY=",
"requires": {
"eraro": "1.0",
"nid": "0.3",
"norma": "0.4"
}
},
"util": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/util/-/util-0.11.0.tgz",
"integrity": "sha512-5n12uMzKCjvB2HPFHnbQSjaqAa98L5iIXmHrZCLavuZVe0qe/SJGbDGWlpaHk5lnBkWRDO+dRu1/PgmUYKPPTw==",
"requires": {
"inherits": "2.0.3"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE="
},
"vasync": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz",
"integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=",
"requires": {
"verror": "1.6.0"
},
"dependencies": {
"extsprintf": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz",
"integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk="
},
"verror": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz",
"integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=",
"requires": {
"extsprintf": "1.2.0"
}
}
}
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"wbuf": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
"integrity": "sha1-wdjRSTFtPqhShIiVy2oL/oh7h98=",
"requires": {
"minimalistic-assert": "^1.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"wreck": {
"version": "12.5.1",
"resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz",
"integrity": "sha1-zS/84WdEnh8CQu2c+AVS4g+2kCo=",
"requires": {
"boom": "5.x.x",
"hoek": "4.x.x"
}
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
}
}
}
{
"name": "authhook",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "mocha"
},
"author": "",
"license": "ISC",
"dependencies": {
"config": "^1.30.0",
"ioredis": "^4.2.0",
"jsonwebtoken": "^8.3.0",
"jwt-verify": "git+https://nexpienpm:CCqLQjg4ytvzN7QbssUV@dev.nexpie.com/npm/jwt-verify.git",
"lru-cache": "^4.1.3",
"restify": "^7.1.1",
"seneca": "^3.6.0",
"util": "^0.11.0"
},
"devDependencies": {
"mocha": "^5.2.0"
}
}
var Redis = require('ioredis')
var redis = new Redis()
function on_message_redis(deviceid, payload, topic) { // first time to access on authhook auth_on_register
if (deviceid.indexOf('mqtt') === 0) {
console.log(deviceid)
}
else {
var information = setValue(deviceid, payload, topic)
console.log(information.total_message_size)
redis.hincrby(information.keys, 'actual_message_count', 1)
redis.hincrby(information.keys, 'charged_message_count', information.charged_message_count)
redis.hincrby(information.keys, 'total_message_size', Math.floor(information.total_message_size))
redis.hincrby(setBrokerValue().keys, 'actual_message_count', 1)
redis.hincrby(setBrokerValue().keys, 'charged_message_count', information.charged_message_count)
redis.hincrby(setBrokerValue().keys, 'total_message_size', Math.floor(information.total_message_size))
redis.hset(information.keys, 'last_publish', information.last_publish)
}
}
module.exports.on_message_redis = on_message_redis
redis.on("error", (error) => {
console.log("Redis connection error", error);
});
redis.on('reconnecting', function reconnecting() {
console.log('Connection reestablished');
});
redis.on('connect', function connect() {
console.log('connecting');
});
function setValue(deviceid, payload, topic) {
var dateNow = Math.floor(Date.now() / 1000)
var keys = 'deviceid:' + deviceid
var last_publish = dateNow
var total_message_size = (payload.length + topic.length) * (3 / 4)
console.log('total_message_size: ' + total_message_size)
var msg_count_size = total_message_size
var charged_message_count = 1
while (msg_count_size > 5000) {
charged_message_count += 1
msg_count_size = msg_count_size - 5000
}
return {
keys: keys,
last_publish: last_publish,
charged_message_count: charged_message_count,
total_message_size: total_message_size
}
}
function setBrokerValue() {
var keys = '_broker:1'
return {
keys: keys
}
}
\ No newline at end of file
var Redis = require('ioredis')
var redis = new Redis()
function on_offline_redis(deviceid) { // first time to access on authhook auth_on_register
if (deviceid.indexOf('mqtt') === 0) {
}
else {
var information = setValue(deviceid)
var status = redis.hget(information.keys, 'status')
if (status !== false) {
redis.hset(information.keys, 'status', information.status, 'offline_on', information.offline_on)
deviceUsageCount()
}
}
}
module.exports.on_offline_redis = on_offline_redis
redis.on("error", (error) => {
console.log("Redis connection error", error);
});
redis.on('reconnecting', function reconnecting() {
console.log('Connection reestablished');
});
redis.on('connect', function connect() {
console.log('connecting');
});
function setValue(deviceid) {
var dateNow = Math.floor(Date.now() / 1000)
var keys = 'deviceid:' + deviceid
var status = false
var offline_on = dateNow
return {
keys: keys,
status: status,
offline_on: offline_on
}
}
function deviceUsageCount() {
console.log('device_usage_offline')
redis.hincrby('_broker:1', 'device_online', -1)
}
\ No newline at end of file
var Redis = require('ioredis')
var redis = new Redis()
function on_register_redis(deviceid) { // first time to access on authhook auth_on_register
if (deviceid.indexOf('mqtt') === 0) {
}
else {
var information = setValue(deviceid)
redis.hdel(information.keys, 'offline_on')
var status = redis.hget(information.keys, 'status')
if (status !== true) {
redis.hset(information.keys, 'status', information.status, 'register_on', information.register_on, 'last_check', information.last_check)
deviceUsageCount()
}
}
}
module.exports.on_register_redis = on_register_redis
redis.on("error", (error) => {
console.log("Redis connection error", error);
});
redis.on('reconnecting', function reconnecting() {
console.log('Connection reestablished');
});
redis.on('connect', function connect() {
console.log('connecting');
});
function setValue(deviceid) {
var dateNow = Math.floor(Date.now() / 1000)
var keys = 'deviceid:' + deviceid
var status = true
var register_on = dateNow
var last_check = dateNow
return {
keys: keys,
status: status,
register_on: register_on,
last_check: last_check
}
}
function deviceUsageCount() {
console.log('device_usage_online')
redis.hincrby('_broker:1', 'device_online', 1)
}
\ No newline at end of file
REGISTRY_HOST=dock.nexpie.com
GROUPNAME=stack
PROJECTNAME=vernemq/authhook
RELEASE=1.0.0
var assert = require('assert')
var getTopic = require('../utils/router').rewriteTopic
describe('GetTopic', () => {
describe('realtime msg', () => {
it('should return topic that id_group have insert between @msg and topic', () => {
var topic = '@msg/any/light'
var id_group = 'bulb'
var tgConcat = '@msg/!bulb/any/light'
var _topic = getTopic(topic, id_group)
assert.equal(_topic, tgConcat)
})
})
describe('shadow', () => {
describe('update pub', () => {
it('should return topic that id have insert between @shadow/update and topic', () => {
var topic = '@shadow/update/any/light'
var id = 'd4484cdb-a47a-4936-bcfd-33c1af39b857'
var tgConcat = '@shadow/update/!d4484cdb-a47a-4936-bcfd-33c1af39b857/any/light'
var _topic = getTopic(topic, id)
assert.equal(_topic, tgConcat)
})
})
describe('update sub', () => {
it('should return topic that id have insert behind @shadow/updated', () => {
var topic = '@shadow/updated'
var id = 'd4484cdb-a47a-4936-bcfd-33c1af39b857'
var tgConcat = '@shadow/updated/!d4484cdb-a47a-4936-bcfd-33c1af39b857'
var _topic = getTopic(topic, id)
assert.equal(_topic, tgConcat)
})
})
describe('get pub', () => {
it('should return topic that id have insert between @shadow/get and topic', () => {
var topic = '@shadow/get/any/light'
var id = 'd4484cdb-a47a-4936-bcfd-33c1af39b857'
var tgConcat = '@shadow/get/!d4484cdb-a47a-4936-bcfd-33c1af39b857/any/light'
var _topic = getTopic(topic, id)
assert.equal(_topic, tgConcat)
})
})
describe('get sub', () => {
it('should return topic that id have insert between @client and #', () => {
var topic = '@client/#'
var id = 'd4484cdb-a47a-4936-bcfd-33c1af39b857'
var tgConcat = '@client/!d4484cdb-a47a-4936-bcfd-33c1af39b857/#'
var _topic = getTopic(topic, id)
assert.equal(_topic, tgConcat)
})
})
})
})
module.exports.getGroupID = getGroupID
var config = require('config');
var seneca = require('seneca')({log: 'silent'}).client({ port: config.get('device_registry_port'), host: config.get('device_registry_host') });
// var getRole = require('../checkClientRole').getRole
function getGroupID(token, client_id, callback) {
var role = require('jwt-verify').verify(token).res
if (role && role.hasOwnProperty('groupId')) {
callback(role.groupId);
}
else {
doDB(client_id, function(groupid) {
if (groupid) callback(groupid);
else callback(client_id); // fake group to isolate device
});
}
}
function doDB(client_id, callback) {
seneca.act('cmd:getGroupByClientid, clientid:'+client_id, function(err, res) {
if (err) callback(null);
else callback((res && res.result &&res.result[0])?res.result[0]:null);
});
}
module.exports.insertWordIntoTopic = insertWordIntoTopic
module.exports.removeTempWordInTopic = removeTempWordInTopic
module.exports.replaceWords = replaceWords
module.exports.cleanUpTopic = cleanUpTopic
/*
Ex: insertWordIntoTopic('@shadow/home/temp', '!GROUP', 1)
expected return : "@shadow/!GROUP/home/temp"
*/
function insertWordIntoTopic(topic, word, pos) {
var a = topic.split('/');
a.splice(pos, 0, word);
// console.log('>>> insertWordIntoTopic('+topic +','+ word +','+ pos +');');
// console.log(a.join('/'));
return a.join('/');
}
/*
Ex : removeTempWordInTopic('@shadow/!GROUP/home/temp')
expected return : "@shadowhome/temp"
*/
function removeTempWordInTopic(topic) {
var a = topic.split('/');
var k=0, l=a.length;
while (k<l) {
if (a[k].substr(0,1)=='!') {
a.splice(k,1);
l--;
}
else k++;
}
return a.join('/');
}
function replaceWords(topic, word, from, to) {
var a = topic.split('/');
a.splice(from,to-from+1);
if (word != null) a.splice(from, 0, word);
return a.join('/');
}
// Sample
// var str = insertWordIntoTopic('@shadow/home/temp', '!GROUP', 0);
// console.log(str);
// console.log(removeTempWordInTopic(str));
//console.log(replaceWords('@shadow/set/home/bob/bedroom/temp', 'CLIENTID-XXXXX', 2, 3));
function cleanUpTopic(topic) {
topic = topic.trim();
if (topic.substr(-1)=='/') return topic.slice(-1);
}
var modify = require('./modify');
function rewriteTopic(topic, op, groupid, clientid, output) {
var chunk = topic.split('/');
switch (chunk[0]) {
case '@msg' :
return modify.insertWordIntoTopic(topic, '!'+groupid, 1);
case '@feed' :
if (chunk[1] == 'senml') {
if (chunk[2]=='update' || chunk[2].startsWith('update:')) {
return modify.insertWordIntoTopic(topic, clientid, 3);
}
else return topic;
}
else return topic;
case '@shadow' :
if (chunk[1] == 'data') {
if (chunk[2]=='get' || chunk[2]=='update' || chunk[2].startsWith('get:') || chunk[2].startsWith('update:')) {
return modify.insertWordIntoTopic(topic, clientid, 3);
}
else if (chunk[2]=='updated' ) {
return modify.insertWordIntoTopic(topic, '!'+clientid, 3);
}
else if ( chunk[2].startsWith('updated:')) {
return modify.insertWordIntoTopic(topic, '!'+groupid, 3);
}
else {
return topic;
}
}
else if (chunk[1] == 'state') {
if (chunk[2]=='get' || chunk[2]=='update' || chunk[2].startsWith('get:') || chunk[2].startsWith('update:')) {
return modify.insertWordIntoTopic(topic, clientid, 3);
}
else if (chunk[2]=='updated' || chunk[2]=='mismatched' ) {
return modify.insertWordIntoTopic(topic, '!'+clientid, 3);
}
else if ( chunk[2].startsWith('updated:') || chunk[2].startsWith('mismatched:')) {
return modify.insertWordIntoTopic(topic, '!'+groupid, 3);
}
else {
return topic;
}
}
break;
case '@private' :
//console.log(modify.insertWordIntoTopic(topic, '!'+clientid, 1));
return modify.insertWordIntoTopic(topic, '!'+clientid, 1);
}
}
module.exports.rewriteTopic = rewriteTopic
module.exports.auth_connect = auth_connect
/*
{ _key: '1196651',
_id: 'access_token/1196651',
_rev: '_XdtTzQK--_',
"type": "v1",
"code": "f2a05d9a420e141d2d268b0c41f2af8e",
"device": "bd2w9fkc-bobclient",
"scope": [
"w:@shadow/read",
"w:@shadow/write"
],
"iat": 1537502874269,
"nbf": 1537502874269,
"exp": 1537609874269,
"for": [
{
"clientid": "bd2w9fkc-bobclient",
"verify": false
}
],
"user": "nexpie"
}
*/
function auth_connect(mqttauth, token_profile) {
console.log('auth_connect')
var dateNow = Math.floor(Date.now() / 1000)
var res = {
status : true
}
if (token_profile) {
if (token_profile.for) {
var found = false;
for (var i=0; i<token_profile.for.length; i++) {
if (token_profile.for[i].clientid == mqttauth.clientid) {
found = true;
break;
}
}
if (!found) return {status: false, reason: 'uneligible'};
}
if (dateNow > token_profile.exp) return {status: false, reason: 'expired'};
if (token_profile.nbf && (dateNow < token_profile.nbf)) return {status: false, reason: 'uneligible'};
return {status: true};
}
else return false;
}
\ No newline at end of file
%% -*- erlang -*-
main([ThisNode]) ->
code:add_paths(filelib:wildcard("/usr/lib/vernemq/lib/*/ebin")),
FileName = "/var/lib/vernemq/meta/peer_service/cluster_state",
case filelib:is_regular(FileName) of
true ->
{ok, Bin} = file:read_file(FileName),
{ok, State} = riak_dt_orswot:from_binary(Bin),
AThisNode = list_to_atom(ThisNode),
TargetNodes = riak_dt_orswot:value(State) -- [AThisNode],
L = lists:foldl(
fun(N, Acc) ->
Acc ++ atom_to_list(N) ++ "\n"
end, "", TargetNodes),
io:format(L);
false ->
io:format("")
end.
#!/usr/bin/env bash
IP_ADDRESS=$(ip -4 addr show eth0 | grep -oP "(?<=inet).*(?=/)"| sed -e "s/^[[:space:]]*//" | tail -n 1)
# Ensure correct ownership and permissions on volumes
chown vernemq:vernemq /var/lib/vernemq /var/log/vernemq
chmod 755 /var/lib/vernemq /var/log/vernemq
# Ensure the Erlang node name is set correctly
if env | grep -q "DOCKER_VERNEMQ_NODENAME"; then
sed -i.bak -r "s/VerneMQ@.+/VerneMQ@${DOCKER_VERNEMQ_NODENAME}/" /etc/vernemq/vm.args
else
sed -i.bak -r "s/VerneMQ@.+/VerneMQ@${IP_ADDRESS}/" /etc/vernemq/vm.args
fi
if env | grep -q "DOCKER_VERNEMQ_DISCOVERY_NODE"; then
echo "-eval \"vmq_server_cmd:node_join('VerneMQ@${DOCKER_VERNEMQ_DISCOVERY_NODE}')\"" >> /etc/vernemq/vm.args
fi
# Cluster discovery implementation based on https://github.com/thesandlord/kubernetes-pod-ip-finder
if env | grep -q "KUBE_VERNEMQ_DISCOVERY_URL"; then
response=$(curl ${KUBE_VERNEMQ_DISCOVERY_URL})
IFS=','
nodes=($(echo "$response" | tr -d '[]"'))
length=$(echo ${#nodes[@]})
for i in "${nodes[@]}"
do
if [ "$i" != "null" ] && [ "$i" != "$IP_ADDRESS" ] && (($length > 1)); then
echo "Start Joining to VerneMQ@${i}."
echo "-eval \"vmq_server_cmd:node_join('VerneMQ@${i}')\"" >> /etc/vernemq/vm.args
fi
done
IFS=''
fi
if env | grep -q "DOCKER_VERNEMQ_ALLOW_ANONYMOUS=on"; then
echo "allow_anonymous = on" >> /etc/vernemq/vernemq.conf
fi
if env | grep -q "DOCKER_VERNEMQ_TRADE_CONSISTENCY=on"; then
echo "trade_consistency = on" >> /etc/vernemq/vernemq.conf
fi
if env | grep -q "DOCKER_VERNEMQ_ALLOW_MULTIPLE_SESSIONS=on"; then
echo "allow_multiple_sessions = on" >> /etc/vernemq/vernemq.conf
fi
if env | grep -q "DOCKER_VERNEMQ_MAX_CLIENT_ID_SIZE"; then
echo "max_client_id_size = ${DOCKER_VERNEMQ_MAX_CLIENT_ID_SIZE}" >> /etc/vernemq/vernemq.conf
fi
if [ -f /etc/vernemq/vernemq.conf.local ]; then
cp /etc/vernemq/vernemq.conf.local /etc/vernemq/vernemq.conf
else
sed -i '/########## Start ##########/,/########## End ##########/d' /etc/vernemq/vernemq.conf
echo "########## Start ##########" >> /etc/vernemq/vernemq.conf
env | grep DOCKER_VERNEMQ | grep -v 'DISCOVERY_NODE\|KUBERNETES\|DOCKER_VERNEMQ_USER' | cut -c 16- | awk '{match($0,/^[A-Z0-9_]*/)}{print tolower(substr($0,RSTART,RLENGTH)) substr($0,RLENGTH+1)}' | sed 's/__/./g' >> /etc/vernemq/vernemq.conf
users_are_set=$(env | grep DOCKER_VERNEMQ_USER)
if [ ! -z "$users_are_set" ]; then
echo "vmq_passwd.password_file = /etc/vernemq/vmq.passwd" >> /etc/vernemq/vernemq.conf
touch /etc/vernemq/vmq.passwd
fi
for vernemq_user in $(env | grep DOCKER_VERNEMQ_USER); do
username=$(echo $vernemq_user | awk -F '=' '{ print $1 }' | sed 's/DOCKER_VERNEMQ_USER_//g' | tr '[:upper:]' '[:lower:]')
password=$(echo $vernemq_user | awk -F '=' '{ print $2 }')
vmq-passwd /etc/vernemq/vmq.passwd $username <<EOF
$password
$password
EOF
done
echo "erlang.distribution.port_range.minimum = 9100" >> /etc/vernemq/vernemq.conf
echo "erlang.distribution.port_range.maximum = 9109" >> /etc/vernemq/vernemq.conf
echo "listener.tcp.default = ${IP_ADDRESS}:1883" >> /etc/vernemq/vernemq.conf
echo "listener.ws.default = ${IP_ADDRESS}:8083" >> /etc/vernemq/vernemq.conf
echo "listener.vmq.clustering = ${IP_ADDRESS}:44053" >> /etc/vernemq/vernemq.conf
echo "listener.http.metrics = ${IP_ADDRESS}:8888" >> /etc/vernemq/vernemq.conf
echo "########## End ##########" >> /etc/vernemq/vernemq.conf
fi
# Check configuration file
su - vernemq -c "/usr/sbin/vernemq config generate 2>&1 > /dev/null" | tee /tmp/config.out | grep error
if [ $? -ne 1 ]; then
echo "configuration error, exit"
echo "$(cat /tmp/config.out)"
exit $?
fi
pid=0
# SIGUSR1-handler
siguser1_handler() {
echo "stopped"
}
# SIGTERM-handler
sigterm_handler() {
if [ $pid -ne 0 ]; then
# this will stop the VerneMQ process
vmq-admin cluster leave node=VerneMQ@$IP_ADDRESS -k > /dev/null
wait "$pid"
fi
exit 143; # 128 + 15 -- SIGTERM
}
# setup handlers
# on callback, kill the last background process, which is `tail -f /dev/null`
# and execute the specified handler
trap 'kill ${!}; siguser1_handler' SIGUSR1
trap 'kill ${!}; sigterm_handler' SIGTERM
/usr/sbin/vernemq start
pid=$(ps aux | grep '[b]eam.smp' | awk '{print $2}')
while true
do
tail -f /var/log/vernemq/console.log & wait ${!}
done
## Allow anonymous users to connect, default is 'off'
##
## Default: offf
##
## Acceptable values:
## - on or off
allow_anonymous = off
## Allow new client connections even when a VerneMQ cluster is inconsistent.
##
## Default: off
##
## Acceptable values:
## - on or off
allow_register_during_netsplit = off
## Allow message publishs even when a VerneMQ cluster is inconsistent.
##
## Default: off
##
## Acceptable values:
## - on or off
allow_publish_during_netsplit = off
## Allow new subscriptions even when a VerneMQ cluster is inconsistent.
##
## Default: off
##
## Acceptable values:
## - on or off
allow_subscribe_during_netsplit = off
## Allow clients to unsubscribe when a VerneMQ cluster is inconsistent.
##
## Default: off
##
## Acceptable values:
## - on or off
allow_unsubscribe_during_netsplit = off
## Allows a client to logon multiple times using the same client id
## (non-standard behaviour!).
##
## Default: off
##
## Acceptable values:
## - on or off
allow_multiple_sessions = off
## Set the time in seconds VerneMQ waits before a retry, in case a (QoS=1 or QoS=2) message
## delivery gets no answer.
##
## Default: 20
##
## Acceptable values:
## - an integer
## retry_interval = 20
## Set the maximum size for client IDs. MQTT v3.1 specifies a
## limit of 23 characters
##
## Default: 100
##
## Acceptable values:
## - an integer
## max_client_id_size = 100
## This option allows persistent clients ( = clean session set to
## false) to be removed if they do not reconnect within 'persistent_client_expiration'.
## This is a non-standard option. As far as the MQTT specification is concerned,
## persistent clients persist forever.
## The expiration period should be an integer followed by one of 'd', 'w', 'm', 'y' for
## day, week, month, and year.
##
## Default: never
##
## Acceptable values:
## - text
## persistent_client_expiration = 1w
## The maximum number of QoS 1 or 2 messages that can be in the process of being
## transmitted simultaneously. This includes messages currently going through handshakes
## and messages that are being retried. Defaults to 20. Set to 0 for no maximum. If set
## to 1, this will guarantee in-order delivery of messages.
##
## Default: 20
##
## Acceptable values:
## - an integer
max_inflight_messages = 20
## The maximum number of messages to hold in the queue above
## those messages that are currently in flight. Defaults to 1000. This affects
## messages of any QoS. Set to -1 for no maximum (not recommended).
## This option allows to control how a specific client session can deal
## with message bursts. As a general rule of thumb set
## this number a bit higher than the expected message rate a single consumer is
## required to process. Note that setting this value to 0 will totally block
## delivery from any queue.
##
## Default: 1000
##
## Acceptable values:
## - an integer
max_online_messages = 1000
## The maximum number of QoS 1 or 2 messages to hold in the offline queue.
## Defaults to 1000. Set to -1 for no maximum (not recommended). Set to 0
## if no messages should be stored offline.
##
## Default: 1000
##
## Acceptable values:
## - an integer
max_offline_messages = 1000
## This option sets the maximum MQTT size that VerneMQ will
## allow. Messages that exceed this size will not be accepted by
## VerneMQ. The default value is 0, which means that all valid MQTT
## messages are accepted. MQTT imposes a maximum payload size of
## 268435455 bytes.
##
## Default: 0
##
## Acceptable values:
## - an integer
max_message_size = 0
## If a message is published with a QoS lower than the QoS of the subscription it is
## delivered to, VerneMQ can upgrade the outgoing QoS. This is a non-standard option.
##
## Default: off
##
## Acceptable values:
## - on or off
upgrade_outgoing_qos = off
## listener.max_connections is an integer or 'infinity' defining
## the maximum number of concurrent connections. This option can be overridden
## on the protocol level by:
## - listener.tcp.max_connections
## - listener.ssl.max_connections
## - listener.ws.max_connections
## - listener.wss.max_connections
## or on the listener level by:
## - listener.tcp.my_tcp_listener.max_connections
## - listener.ssl.my_ssl_listener.max_connections
## - listener.ws.my_ws_listener.max_connections
## - listener.wss.my_wss_listener.max_connections
##
## Default: 10000
##
## Acceptable values:
## - an integer
## - the text "infinity"
listener.max_connections = 10000
## Set the nr of acceptors waiting to concurrently accept new connections.
## This can be specified either on the protocol level:
## - listener.tcp.nr_of_acceptors
## - listener.ssl.nr_of_acceptors
## - listener.ws.nr_of_acceptors
## - listener.wss.nr_of_acceptors
## or on the listener level:
## - listener.tcp.my_tcp_listener.nr_of_acceptors
## - listener.ssl.my_ssl_listener.nr_of_acceptors
## - listener.ws.my_ws_listener.nr_of_acceptors
## - listener.wss.my_wss_listener.nr_of_acceptors
##
## Default: 10
##
## Acceptable values:
## - an integer
listener.nr_of_acceptors = 10
## listener.tcp.<name> is an IP address and TCP port that
## the broker will bind to. You can define multiple listeners e.g:
## - listener.tcp.default = 127.0.0.1:1883
## - listener.tcp.internal = 127.0.0.1:10883
## - listener.tcp.my_other_listener = 127.0.0.1:10884
## This also works for SSL listeners and WebSocket handlers:
## - listener.ssl.default = 127.0.0.1:8883
## - listener.ws.default = 127.0.0.1:800
## - listener.wss.default = 127.0.0.1:880
##
## Default: 127.0.0.1:1883
##
## Acceptable values:
## - an IP/port pair, e.g. 127.0.0.1:10011
#listener.tcp.default = 127.0.0.1:1883
listener.tcp.default = 0.0.0.0:1883
listener.ws.default = 0.0.0.0:8083
## listener.vmq.clustering is the IP address and TCP port that
## the broker will bind to accept connections from other cluster
## nodes e.g:
## - listener.vmq.clustering = 0.0.0.0:18883
## This also works for SSL listeners:
## - listener.vmqs.clustering = 0.0.0.0:18884
##
## Default: 0.0.0.0:44053
##
## Acceptable values:
## - an IP/port pair, e.g. 127.0.0.1:10011
listener.vmq.clustering = 0.0.0.0:44053
## listener.http.default is the IP address and TCP port that
## the broker will bind to accept HTTP connections
## - listener.http.default = 0.0.0.0:8888
## This also works for SSL listeners:
## - listener.https.default= 0.0.0.0:8889
##
## Default: 127.0.0.1:8888
##
## Acceptable values:
## - an IP/port pair, e.g. 127.0.0.1:10011
listener.http.default = 127.0.0.1:8888
## Set the mountpoint on the protocol level or on the listener level
## - listener.tcp.mountpoint
## - listener.ssl.mountpoint
## - listener.ws.mountpoint
## - listener.wss.mountpoint
## listener level:
## - listener.tcp.my_tcp_listener.mountpoint
## - listener.ssl.my_ssl_listener.mountpoint
## - listener.ws.my_ws_listener.mountpoint
## - listener.wss.my_wss_listener.mountpoint
##
## Default: off
##
## Acceptable values:
## - text
listener.mountpoint = off
## The cafile is used to define the path to a file containing
## the PEM encoded CA certificates that are trusted. Set the cafile
## on the protocol level or on the listener level:
## - listener.ssl.cafile
## - listener.wss.cafile
## or on the listener level:
## - listener.ssl.my_ssl_listener.cafile
## - listener.wss.my_wss_listener.cafile
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.ssl.cafile = /etc/vernemq/cacerts.pem
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.https.cafile = /etc/vernemq/cacerts.pem
## Set the path to the PEM encoded server certificate
## on the protocol level or on the listener level:
## - listener.ssl.certfile
## - listener.wss.certfile
## or on the listener level:
## - listener.ssl.my_ssl_listener.certfile
## - listener.wss.my_wss_listener.certfile
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.ssl.certfile = /etc/vernemq/cert.pem
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.https.certfile = /etc/vernemq/cert.pem
## Set the path to the PEM encoded key file on the protocol
## level or on the listener level:
## - listener.ssl.keyfile
## - listener.wss.keyfile
## or on the listener level:
## - listener.ssl.my_ssl_listener.keyfile
## - listener.wss.my_wss_listener.keyfile
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.ssl.keyfile = /etc/vernemq/key.pem
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.vmqs.keyfile = /etc/vernemq/key.pem
##
## Default:
##
## Acceptable values:
## - the path to a file
## listener.https.keyfile = /etc/vernemq/key.pem
## Set the list of allowed ciphers (each separated with a colon),
## on the protocol level or on the listener level. Reasonable defaults
## are used if nothing is specified:
## - listener.ssl.ciphers
## - listener.wss.ciphers
## or on the listener level:
## - listener.ssl.my_ssl_listener.ciphers
## - listener.wss.my_wss_listener.ciphers
##
## Default:
##
## Acceptable values:
## - text
## listener.ssl.ciphers =
##
## Default:
##
## Acceptable values:
## - text
## listener.vmqs.ciphers =
##
## Default:
##
## Acceptable values:
## - text
## listener.https.ciphers =
## If you have 'listener.ssl.require_certificate' set to true,
## you can create a certificate revocation list file to revoke access
## to particular client certificates. If you have done this, use crlfile
## to point to the PEM encoded revocation file. This can be done on the
## protocol level or on the listener level.
## - listener.ssl.crlfile
## - listener.wss.crlfile
## or on the listener level:
## - listener.ssl.my_ssl_listener.crlfile
## - listener.wss.my_wss_listener.crlfile
##
## Default:
##
## Acceptable values:
## - text
## listener.ssl.crlfile =
## Enable this option if you want to use SSL client certificates
## to authenticate your clients. This can be done on the protocol level
## or on the listener level.
## - listener.ssl.require_certificate
## - listener.wss.require_certificate
## or on the listener level:
## - listener.ssl.my_ssl_listener.require_certificate
## - listener.wss.my_wss_listener.require_certificate
##
## Default: off
##
## Acceptable values:
## - on or off
## listener.ssl.require_certificate = off
##
## Default: off
##
## Acceptable values:
## - on or off
## listener.vmqs.require_certificate = off
##
## Default: off
##
## Acceptable values:
## - on or off
## listener.https.require_certificate = off
## Configure the TLS protocol version (tlsv1, tlsv1.1, or tlsv1.2) to be
##
## Default: tlsv1.2
##
## Acceptable values:
## - text
## listener.ssl.tls_version = tlsv1.2
##
## Default: tlsv1.2
##
## Acceptable values:
## - text
## listener.vmqs.tls_version = tlsv1.2
##
## Default: tlsv1.2
##
## Acceptable values:
## - text
## listener.https.tls_version = tlsv1.2
## If 'listener.ssl.require_certificate' is enabled, you may enable
## 'listener.ssl.use_identity_as_username' to use the CN value from the client
## certificate as a username. If enabled other authentication plugins are not
## considered. The option can be specified either for all SSL listeners or for
## a specific listener:
## - listener.ssl.use_identity_as_username
## - listener.wss.use_identity_as_username
## or on the listener level:
## - listener.ssl.my_ssl_listener.use_identity_as_username
## - listener.wss.my_wss_listener.use_identity_as_username
##
## Default: off
##
## Acceptable values:
## - on or off
## listener.ssl.use_identity_as_username = off
## Enable the $SYSTree Reporter.
##
## Default: on
##
## Acceptable values:
## - on or off
systree_enabled = on
## The integer number of milliseconds between updates of the $SYS subscription hierarchy,
## which provides status information about the broker. If unset, defaults to 20 seconds.
## Set to 0 to disable publishing the $SYS hierarchy completely.
##
## Default: 20000
##
## Acceptable values:
## - an integer
systree_interval = 20000
## Enable the Graphite Reporter. Ensure to also configure a
## proper graphite.host
##
## Default: off
##
## Acceptable values:
## - on or off
graphite_enabled = off
## the graphite server host name
##
## Default: localhost
##
## Acceptable values:
## - text
graphite_host = localhost
## the tcp port of the graphite server
##
## Default: 2003
##
## Acceptable values:
## - an integer
graphite_port = 2003
## the interval we push metrics to the graphite server in ms
##
## Default: 20000
##
## Acceptable values:
## - an integer
graphite_interval = 20000
## set the prefix that is applied to all metrics reported to graphite
##
## Default:
##
## Acceptable values:
## - text
## graphite_prefix = my-prefix
## the graphite server api key, e.g. used by hostedgraphite.com
##
## Default:
##
## Acceptable values:
## - text
## graphite_api_key = My-Api-Key
## Distribution policy for shared subscriptions. Default is
## 'prefer_local' which will ensure that local subscribers will be
## used if any are available. 'local_only' will select a random local
## subscriber if any are available. 'random' will randomly choose
## between all available subscribers.
##
## Default: prefer_local
##
## Acceptable values:
## - text
shared_subscription_policy = prefer_local
## plugins.<plugin> enables/disables a plugin.
## Plugin specific settings are set via the plugin itself, i.e., to
## set the 'file' setting for the myplugin plugin, add a line like:
## myplugin.file = /path/to/file
##
## Acceptable values:
## - on or off
## plugins.name = on
## plugins.<name>.path defines the location of the plugin
## associated with <name>. This is needed for plugins that are not
## shipped with VerneMQ.
##
## Acceptable values:
## - the path to a directory
## plugins.mypluginname.path = /path/to/myplugin
## plugins.<name>.priority defines the load order of the
## plugins. Plugins are loaded by priority. If no priority is given
## the load order is undefined. Prioritized plugins will always be
## loaded before plugins with no defined priority.
##
## Acceptable values:
## - an integer
## plugins.mypluginname.priority = 5
## File based authentication plugin.
##
## Default: on
##
## Acceptable values:
## - on or off
plugins.vmq_passwd = on
## File based authorization plugin.
##
## Default: on
##
## Acceptable values:
## - on or off
plugins.vmq_acl = off
## Lua based plugins.
##
## Default: off
##
## Acceptable values:
## - on or off
plugins.vmq_diversity = off
## Webhook based plugins.
##
## Default: off
##
## Acceptable values:
## - on or off
plugins.vmq_webhooks = on
## The VerneMQ bridge plugin.
##
## Default: off
##
## Acceptable values:
## - on or off
plugins.vmq_bridge = off
## Set the path to an access control list file.
##
## Default: /etc/vernemq/vmq.acl
##
## Acceptable values:
## - the path to a file
vmq_acl.acl_file = /etc/vernemq/vmq.acl
## set the acl reload interval in seconds, the value 0 disables
## the automatic reloading of the acl file.
##
## Default: 10
##
## Acceptable values:
## - an integer
vmq_acl.acl_reload_interval = 10
## Set the path to a password file.
##
## Default: /etc/vernemq/vmq.passwd
##
## Acceptable values:
## - the path to a file
vmq_passwd.password_file = /etc/vernemq/vmq.passwd
## set the password reload interval in seconds, the value 0
## disables the automatic reloading of the password file.
##
## Default: 10
##
## Acceptable values:
## - an integer
vmq_passwd.password_reload_interval = 10
## Configure the vmq_diversity plugin script dir. The script dir
## is searched for Lua scripts which are automatically loaded when the
## plugin is enabled.
##
## Default: /usr/share/vernemq/lua
##
## Acceptable values:
## - the path to a directory
vmq_diversity.script_dir = /usr/share/vernemq/lua
##
## Default: off
##
## Acceptable values:
## - on or off
vmq_diversity.auth_postgres.enabled = off
##
## Default: localhost
##
## Acceptable values:
## - text
## vmq_diversity.postgres.host = localhost
##
## Default: 5432
##
## Acceptable values:
## - an integer
## vmq_diversity.postgres.port = 5432
##
## Default: root
##
## Acceptable values:
## - text
## vmq_diversity.postgres.user = root
##
## Default: password
##
## Acceptable values:
## - text
## vmq_diversity.postgres.password = password
##
## Default: vernemq_db
##
## Acceptable values:
## - text
## vmq_diversity.postgres.database = vernemq_db
##
## Default: off
##
## Acceptable values:
## - on or off
vmq_diversity.auth_mysql.enabled = off
##
## Default: localhost
##
## Acceptable values:
## - text
## vmq_diversity.mysql.host = localhost
##
## Default: 3306
##
## Acceptable values:
## - an integer
## vmq_diversity.mysql.port = 3306
##
## Default: root
##
## Acceptable values:
## - text
## vmq_diversity.mysql.user = root
##
## Default: password
##
## Acceptable values:
## - text
## vmq_diversity.mysql.password = password
##
## Default: vernemq_db
##
## Acceptable values:
## - text
## vmq_diversity.mysql.database = vernemq_db
##
## Default: off
##
## Acceptable values:
## - on or off
vmq_diversity.auth_mongodb.enabled = off
##
## Default: localhost
##
## Acceptable values:
## - text
## vmq_diversity.mongodb.host = localhost
##
## Default: 27017
##
## Acceptable values:
## - an integer
## vmq_diversity.mongodb.port = 27017
##
## Acceptable values:
## - text
## vmq_diversity.mongodb.login =
##
## Acceptable values:
## - text
## vmq_diversity.mongodb.password =
##
## Acceptable values:
## - text
## vmq_diversity.mongodb.database =
##
## Default: off
##
## Acceptable values:
## - on or off
vmq_diversity.auth_redis.enabled = off
##
## Default: localhost
##
## Acceptable values:
## - text
## vmq_diversity.redis.host = localhost
##
## Default: 6379
##
## Acceptable values:
## - an integer
## vmq_diversity.redis.port = 6379
##
## Default:
##
## Acceptable values:
## - text
## vmq_diversity.redis.password =
##
## Default: 0
##
## Acceptable values:
## - an integer
## vmq_diversity.redis.database = 0
##
## Default: localhost
##
## Acceptable values:
## - text
## vmq_diversity.memcache.host = localhost
##
## Default: 11211
##
## Acceptable values:
## - an integer
## vmq_diversity.memcache.port = 11211
## vmq_diversity.<name>.plugin = <file> loads a specific lua
## script when `vmq_diversity` starts. The scripts are loaded in the
## order defined by the names given, i.e., the script with <name>
## 'script1' is started before the plugin with <name> 'script2'.
##
## Acceptable values:
## - the path to a file
## vmq_diversity.script1.file = path/to/my/script.lua
## To configure and register a webhook a hook and an endpoint
## need to be configured and this is achieved by associating both with
## a name. vmq_webhooks.<name>.hook = <hook> associates the hook
## <hook> with the name <name>. Webhooks are registered in the order
## of the name given to it. Therefore a webhook with name 'webhook1'
## is regisered before a webhook with the name 'webhook2'.
##
## Acceptable values:
## - one of: auth_on_register, auth_on_publish, auth_on_subscribe, on_register, on_publish, on_subscribe, on_unsubscribe, on_deliver, on_offline_message, on_client_wakeup, on_client_offline, on_client_gone
## vmq_webhooks.webhook1.hook = auth_on_register
## Associate an endpoint with a name.
##
## Acceptable values:
## - text
## vmq_webhooks.webhook1.endpoint = http://localhost/myendpoints
vmq_webhooks.webhook1.hook = auth_on_register
vmq_webhooks.webhook1.endpoint = http://localhost:40000/authreg
vmq_webhooks.webhook2.hook = auth_on_subscribe
vmq_webhooks.webhook2.endpoint = http://localhost:40000/authsub
vmq_webhooks.webhook3.hook = auth_on_publish
vmq_webhooks.webhook3.endpoint = http://localhost:40000/authpub
#vmq_webhooks.webhook4.hook = on_publish
#vmq_webhooks.webhook4.endpoint = http://localhost:41000/onpub
vmq_webhooks.webhook5.hook = on_deliver
vmq_webhooks.webhook5.endpoint = http://localhost:40000/ondeliver
#vmq_webhooks.webhook6.hook = on_unsubscribe
#vmq_webhooks.webhook6.endpoint = http://localhost:40000/onunsub
vmq_webhooks.webhook7.hook = on_client_offline
vmq_webhooks.webhook7.endpoint = http://localhost:40000/onoff
vmq_webhooks.webhook8.hook = on_client_gone
vmq_webhooks.webhook8.endpoint = http://localhost:40000/ongone
## Specify the address and port of the bridge to connect to. Several
## bridges can configured by using different bridge names (e.g. br0). If the
## connection supports SSL encryption bridge.ssl.<name> can be used.
##
## Acceptable values:
## - text
## vmq_bridge.tcp.br0 = 127.0.0.1:1889
## Set the clean session option for the bridge. By default this is disabled,
## which means that all subscriptions on the remote broker are kept in case of
## the network connection dropping. If enabled, all subscriptions and messages
## on the remote broker will be cleaned up if the connection drops.
##
## Default: off
##
## Acceptable values:
## - on or off
## vmq_bridge.tcp.br0.cleansession = off
## Set the client id for this bridge connection. If not defined, this
## defaults to 'name.hostname', where name is the connection name and hostname
## is the hostname of this computer.
##
## Default: auto
##
## Acceptable values:
## - text
## vmq_bridge.tcp.br0.client_id = auto
## Set the number of seconds after which the bridge should send a ping if
## no other traffic has occurred.
##
## Default: 60
##
## Acceptable values:
## - an integer
## vmq_bridge.tcp.br0.keepalive_interval = 60
## Configure a username for the bridge. This is used for authentication
## purposes when connecting to a broker that support MQTT v3.1 and requires a
## username and/or password to connect. See also the password option.
##
## Acceptable values:
## - text
## vmq_bridge.tcp.br0.username = my_remote_user
## Configure a password for the bridge. This is used for authentication
## purposes when connecting to a broker that support MQTT v3.1 and requires a
## username and/or password to connect. This option is only valid if a username
## is also supplied.
##
## Acceptable values:
## - text
## vmq_bridge.tcp.br0.password = my_remote_password
## Define one or more topic pattern to be shared between the two brokers.
## Any topics matching the pattern (including wildcards) are shared.
## The following format is used:
## pattern [[[ out | in | both ] qos-level] local-prefix remote-prefix]
## [ out | in | both ]: specifies that this bridge exports messages (out), imports
## messages (in) or shared in both directions (both). If undefined we default to
## export (out).
## qos-level: specifies the publish/subscribe QoS level used for this
## toppic. If undefined we default to QoS 0.
## local-prefix and remote-prefix: For incoming topics, the bridge
## will prepend the pattern with the remote prefix and subscribe to
## the resulting topic on the remote broker. When a matching
## incoming message is received, the remote prefix will be removed
## from the topic and then the local prefix added.
## For outgoing topics, the bridge will prepend the pattern with the
## local prefix and subscribe to the resulting topic on the local
## broker. When an outgoing message is processed, the local prefix
## will be removed from the topic then the remote prefix added.
##
## Acceptable values:
## - text
## vmq_bridge.tcp.br0.topic.1 = topic
## Set the amount of time a bridge using the automatic start type will wait
## until attempting to reconnect. Defaults to 30 seconds.
##
## Default: 10
##
## Acceptable values:
## - an integer
## vmq_bridge.tcp.br0.restart_timeout = 10
## If try_private is enabled, the bridge will attempt to indicate to the
## remote broker that it is a bridge not an ordinary client.
## Note that loop detection for bridges is not yet implemented.
##
## Default: on
##
## Acceptable values:
## - on or off
## vmq_bridge.tcp.br0.try_private = on
## The cafile is used to define the path to a file containing
## the PEM encoded CA certificates that are trusted.
##
## Default:
##
## Acceptable values:
## - the path to a file
## vmq_bridge.ssl.sbr0.cafile = /etc/vernemq/cacerts.pem
## Define the path to a folder containing
## the PEM encoded CA certificates that are trusted.
##
## Default:
##
## Acceptable values:
## - the path to a file
## vmq_bridge.ssl.sbr0.capath = /etc/vernemq/cacerts
## Set the path to the PEM encoded server certificate.
##
## Default:
##
## Acceptable values:
## - the path to a file
## vmq_bridge.ssl.sbr0.certfile = /etc/vernemq/cert.pem
## Set the path to the PEM encoded key file.
##
## Default:
##
## Acceptable values:
## - the path to a file
## vmq_bridge.ssl.sbr0.keyfile = /etc/vernemq/key.pem
## When using certificate based TLS, the bridge will attempt to verify the
## hostname provided in the remote certificate matches the host/address being
## connected to. This may cause problems in testing scenarios, so this option
## may be enabled to disable the hostname verification.
## Setting this option to true means that a malicious third party could
## potentially inpersonate your server, so it should always be disabled in
## production environments.
##
## Default: off
##
## Acceptable values:
## - on or off
## vmq_bridge.ssl.sbr0.insecure = off
## Configure the TLS protocol version (tlsv1, tlsv1.1, or tlsv1.2) to be
## used for this bridge.
##
## Default: tlsv1.2
##
## Acceptable values:
## - text
## vmq_bridge.ssl.sbr0.tls_version = tlsv1.2
## Pre-shared-key encryption provides an alternative to certificate based
## encryption. This option specifies the identity used.
##
## Default:
##
## Acceptable values:
## - text
## vmq_bridge.ssl.sbr0.identity =
## Pre-shared-key encryption provides an alternative to certificate based
## encryption. This option specifies the shared secret used in hexadecimal
## format without leading '0x'.
##
## Default:
##
## Acceptable values:
## - text
## vmq_bridge.ssl.sbr0.psk =
## Where to emit the default log messages (typically at 'info'
## severity):
## off: disabled
## file: the file specified by log.console.file
## console: to standard output (seen when using `vmq attach-direct`)
## both: log.console.file and standard out.
##
## Default: file
##
## Acceptable values:
## - one of: off, file, console, both
log.console = file
## The severity level of the console log, default is 'info'.
##
## Default: info
##
## Acceptable values:
## - one of: debug, info, warning, error
log.console.level = info
## When 'log.console' is set to 'file' or 'both', the file where
## console messages will be logged.
##
## Default: /var/log/vernemq/console.log
##
## Acceptable values:
## - the path to a file
log.console.file = /var/log/vernemq/console.log
## The file where error messages will be logged.
##
## Default: /var/log/vernemq/error.log
##
## Acceptable values:
## - the path to a file
log.error.file = /var/log/vernemq/error.log
## When set to 'on', enables log output to syslog.
##
## Default: off
##
## Acceptable values:
## - on or off
log.syslog = off
## Whether to enable the crash log.
##
## Default: on
##
## Acceptable values:
## - on or off
log.crash = on
## If the crash log is enabled, the file where its messages will
## be written.
##
## Default: /var/log/vernemq/crash.log
##
## Acceptable values:
## - the path to a file
log.crash.file = /var/log/vernemq/crash.log
## Maximum size in bytes of individual messages in the crash log
##
## Default: 64KB
##
## Acceptable values:
## - a byte size with units, e.g. 10GB
log.crash.maximum_message_size = 64KB
## Maximum size of the crash log in bytes, before it is rotated
##
## Default: 10MB
##
## Acceptable values:
## - a byte size with units, e.g. 10GB
log.crash.size = 10MB
## The schedule on which to rotate the crash log. For more
## information see:
## https://github.com/basho/lager/blob/master/README.md#internal-log-rotation
##
## Default: $D0
##
## Acceptable values:
## - text
log.crash.rotation = $D0
## The number of rotated crash logs to keep. When set to
## 'current', only the current open log file is kept.
##
## Default: 5
##
## Acceptable values:
## - an integer
## - the text "current"
log.crash.rotation.keep = 5
## Name of the Erlang node
##
## Default: VerneMQ@127.0.0.1
##
## Acceptable values:
## - text
nodename = VerneMQ@127.0.0.1
## Cookie for distributed node communication. All nodes in the
## same cluster should use the same cookie or they will not be able to
## communicate.
## IMPORTANT!!! SET the cookie to a private value! DO NOT LEAVE AT DEFAULT!
##
## Default: vmq
##
## Acceptable values:
## - text
distributed_cookie = vmq
## Sets the number of threads in async thread pool, valid range
## is 0-1024. If thread support is available, the default is 64.
## More information at: http://erlang.org/doc/man/erl.html
##
## Default: 64
##
## Acceptable values:
## - an integer
erlang.async_threads = 64
## The number of concurrent ports/sockets
## Valid range is 1024-134217727
##
## Default: 262144
##
## Acceptable values:
## - an integer
erlang.max_ports = 262144
## Set scheduler forced wakeup interval. All run queues will be
## scanned each Interval milliseconds. While there are sleeping
## schedulers in the system, one scheduler will be woken for each
## non-empty run queue found. An Interval of zero disables this
## feature, which also is the default.
## This feature is a workaround for lengthy executing native code, and
## native code that do not bump reductions properly.
## More information: http://www.erlang.org/doc/man/erl.html#+sfwi
##
## Acceptable values:
## - an integer
## erlang.schedulers.force_wakeup_interval = 500
## Enable or disable scheduler compaction of load. By default
## scheduler compaction of load is enabled. When enabled, load
## balancing will strive for a load distribution which causes as many
## scheduler threads as possible to be fully loaded (i.e., not run out
## of work). This is accomplished by migrating load (e.g. runnable
## processes) into a smaller set of schedulers when schedulers
## frequently run out of work. When disabled, the frequency with which
## schedulers run out of work will not be taken into account by the
## load balancing logic.
## More information: http://www.erlang.org/doc/man/erl.html#+scl
##
## Acceptable values:
## - one of: true, false
## erlang.schedulers.compaction_of_load = false
## Enable or disable scheduler utilization balancing of load. By
## default scheduler utilization balancing is disabled and instead
## scheduler compaction of load is enabled which will strive for a
## load distribution which causes as many scheduler threads as
## possible to be fully loaded (i.e., not run out of work). When
## scheduler utilization balancing is enabled the system will instead
## try to balance scheduler utilization between schedulers. That is,
## strive for equal scheduler utilization on all schedulers.
## More information: http://www.erlang.org/doc/man/erl.html#+sub
##
## Acceptable values:
## - one of: true, false
## erlang.schedulers.utilization_balancing = true
## This parameter defines the percentage of total server memory
## to assign to LevelDB. LevelDB will dynamically adjust its internal
## cache sizes to stay within this size. The memory size can
## alternately be assigned as a byte count via leveldb.maximum_memory
## instead.
##
## Default: 70
##
## Acceptable values:
## - an integer
leveldb.maximum_memory.percent = 70
\ No newline at end of file
+P 256000
-env ERL_MAX_ETS_TABLES 256000
-env ERL_CRASH_DUMP /erl_crash.dump
-env ERL_FULLSWEEP_AFTER 0
-env ERL_MAX_PORTS 65536
+A 64
-setcookie vmq
-name VerneMQ@127.0.0.1
+K true
+W w
-smp enable
+zdbbl 32768
# VerneMQube
## VerneMQ on Kubernetes - Auto Discovery Cluster
### Prerquisties
- First you need a [Kubernetes Cluster](http://kubernetes.io/gettingstarted/)
- Then you need to run [Kubernetes Pod IP finder](https://github.com/thesandlord/kubernetes-pod-ip-finder) for nodes discovery
NOTE: I didn't managed to make the node discovery work with services because of Erlang Port Mapper daemon logic and Service ClusterIP limitation. If you make it work let me know what did you do.
### How to Use
1. Launch Service
- ```kubectl create -f vernemq-service.yaml```
1. Launch Deployment
- ```kubectl create -f vernemq-deployment.yaml```
### Checking cluster status
```kubectl get pods```
```
vernemq-3099899313-7gkrr 2/2 Running 0 17s
vernemq-3099899313-qbi91 2/2 Running 0 17s
vernemq-3099899313-u5rrq 2/2 Running 0 17s
kubernetes-pod-ip-finder-6le9j 1/1 Running 0 4h
```
```kubectl exec vernemq-3099899313-7gkrr vmq-admin cluster status```
```
+------------------+-------+
| Node |Running|
+------------------+-------+
|VerneMQ@172.17.0.6| true |
|VerneMQ@172.17.0.7| true |
|VerneMQ@172.17.0.8| true |
+------------------+-------+
```
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
ports:
- port: 6379
targetPort: 6379
selector:
"app": "nexpieio-vernemq-broker"
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: vernemq
namespace: default
labels:
app: broker
tier: backend
spec:
# this replicas value is default
# modify it according to your case
replicas: 1
# selector can be applied automatically
# from the labels in the pod template if not set
selector:
matchLabels:
app: broker
tier: backend
template:
metadata:
labels:
app: broker
tier: backend
spec:
containers:
- name: vernemq-authhook
image: dock.nexpie.com/stack/broker/authhook
ports:
- containerPort: 40000
name: authhook
- name: vernemq
image: dock.nexpie.com/stack/broker
env:
- name: KUBE_VERNEMQ_DISCOVERY_URL
#Considering namespace = default. Change according your namespace Eg: kubernetes-pod-ip-finder.dev.svc.cluster.local/?app=broker
value: http://kubernetes-pod-ip-finder.default.svc.cluster.local/?app=broker
ports:
- containerPort: 1883
name: mqtt
- containerPort: 8080
name: websock
- containerPort: 44053
name: epmd
- containerPort: 4369
name: data
- containerPort: 9100
- containerPort: 9101
- containerPort: 9102
- containerPort: 9103
- containerPort: 9104
- containerPort: 9105
- containerPort: 9106
- containerPort: 9107
- containerPort: 9108
- containerPort: 9109
apiVersion: v1
kind: Service
metadata:
name: vernemq
labels:
app: broker
tier: backend
spec:
selector:
app: broker
tier: backend
ports:
- port: 8080
targetPort: 80
name: websock
- port: 1883
targetPort: 1883
name: mqtt
{
"lockfileVersion": 1
}
node_modules
.DS_Store
FROM node:8.10.0-alpine
WORKDIR /usr/src/app
ENV TERM=xterm
RUN apk add --update --no-cache python \
python-dev \
py-pip \
yarn \
openssh-client \
&& rm -rf /var/cache/apk/*
COPY . .
RUN npm install
EXPOSE 40000
CMD npm start
# a helper shell script
MAKE_VERSION=1.1.2
define MAKEFUNCTIONCODE
function hasChanges() {
# old version, just track uncommited + untracked files
# test -n "$$(git status -s .)"
# expect 1 to be normal so the untracked file .make-funcition will be ignored
test 1 -ne "$$(git status -s . | wc -l )"
}
function getRelease() {
awk -F= '/^RELEASE=/{print $$2}' release.conf
}
function getBaseTag() {
sed -n -e "s/^tag=\(.*\)$$(getRelease)\$$/\1/p" release.conf
}
function getTag() {
if [ -z "$$1" ] ; then
awk -F= '/^tag/{print $$2}' release.conf
else
echo "$$(getBaseTag)$$1"
fi
}
function setRelease() {
if [ -n "$$1" ] ; then
sed -i.x -e "s/^tag=.*/tag=$$(getTag $$1)/" release.conf
sed -i.x -e "s/^RELEASE=.*/RELEASE=$$1/g" release.conf
rm -f release.conf.x
runPreTagCommand "$$1"
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function runPreTagCommand() {
if [ -n "$$1" ] ; then
COMMAND=$$(sed -n -e "s/@@RELEASE@@/$$1/g" -e 's/^pre_tag_command=\(.*\)/\1/p' release.conf)
if [ -n "$$COMMAND" ] ; then
if ! OUTPUT=$$(bash -c "$$COMMAND" 2>&1) ; then echo $$OUTPUT >&2 && exit 1 ; fi
fi
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function tagExists() {
tag=$${1:-$$(getTag)}
test -n "$$tag" && test -n "$$(git tag | grep "^$$tag\$$")"
}
function differsFromRelease() {
tag=$$(getTag)
! tagExists $$tag || test -n "$$(git diff --shortstat -r $$tag .)"
}
function getVersion() {
result=$$(getRelease)
if differsFromRelease; then
result="$$result-$$(git log -n 1 --format=%h .)"
fi
if hasChanges ; then
result="$$result-dirty"
fi
echo $$result
}
function nextPatchLevel() {
version=$${1:-$$(getRelease)}
major_and_minor=$$(echo $$version | cut -d. -f1,2)
patch=$$(echo $$version | cut -d. -f3)
version=$$(printf "%s.%d" $$major_and_minor $$(($$patch + 1)))
echo $$version
}
function nextMinorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
minor=$$(echo $$version | cut -d. -f2);
version=$$(printf "%d.%d.0" $$major $$(($$minor + 1))) ;
echo $$version
}
function nextMajorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
version=$$(printf "%d.0.0" $$(($$major + 1)))
echo $$version
}
endef
SHELL=/bin/bash
include release.conf
IMAGE=$(REGISTRY_HOST)/$(GROUPNAME)/$(PROJECTNAME)
VERSION=$(shell . $(RELEASE_SUPPORT) ; getVersion)
TAG=$(shell . $(RELEASE_SUPPORT); getTag)
RELEASE_SUPPORT := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))/.make-function
export MAKEFUNCTIONCODE
.PHONY: pre-build docker-build post-build build release patch-release minor-release major-release tag check-status check-release showtag show-tag \
push do-push post-push post-init update-make
init:
@echo "$$MAKEFUNCTIONCODE" > ./.make-function
build: init pre-build docker-build post-build
pre-build:
post-build:
@rm .make-function
post-push:
@rm .make-function
post-init:
@rm .make-function
docker-build:
docker build -t $(IMAGE):$(VERSION) .
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\
else \
echo docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ; \
fi
release: check-status check-release build push
push: init do-push post-push
do-push:
docker push $(IMAGE):$(VERSION)
docker push $(IMAGE):latest
snapshot: build push
show-tag: init release.conf
@. $(RELEASE_SUPPORT); getVersion
@rm .make-function
showtag: init release.conf
@. $(RELEASE_SUPPORT); getVersion
@rm .make-function
tag-patch-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextPatchLevel)
tag-patch-release: release.conf tag
tag-minor-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMinorLevel)
tag-minor-release: release.conf tag
tag-major-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMajorLevel)
tag-major-release: release.conf tag
patch-release: tag-patch-release release
@echo $(VERSION)
minor-release: tag-minor-release release
@echo $(VERSION)
major-release: tag-major-release release
@echo $(VERSION)
tag: TAG=$(shell . $(RELEASE_SUPPORT); getTag $(VERSION))
tag: check-status
@. $(RELEASE_SUPPORT) ; ! tagExists $(TAG) || (echo "ERROR: tag $(TAG) for version $(VERSION) already tagged in git" >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; setRelease $(VERSION)
git add .
git commit -m "bumped to version $(VERSION)" ;
git tag $(TAG) ;
@ if [ -n "$(shell git remote -v)" ] ; then git push --tags ; else echo 'no remote to push tags to' ; fi
check-status: init
@. $(RELEASE_SUPPORT) ; ! hasChanges || (echo "ERROR: there are still outstanding changes" >&2) ;
@rm .make-function
check-release: init release.conf post-init
@. $(RELEASE_SUPPORT) ; tagExists $(TAG) || (echo "ERROR: version not yet tagged in git. make [minor,major,patch]-release." >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; ! differsFromRelease $(TAG) || (echo "ERROR: current directory differs from tagged $(TAG). make [minor,major,patch]-release." ; exit 1)
update-make: init
@rm Makefile
wget https://dev.nexpie.com/sample/docker-makefile-sample/raw/master/Makefile
@rm .make-function
make-version:
@echo $(MAKE_VERSION)
{
"rabbitmq_host" : "npn1.kube.nexpie.com",
"rabbitmq_port" : "32672",
"rabbitmq_username" : "b1ffb9e39865f3cb70cc2ef14920e023",
"rabbitmq_password" : "c3efbc0c4bdb1747a31cebac20d9b9b8"
}
{
"rabbitmq_host" : "RABBITMQ_HOST",
"rabbitmq_port" : "RABBITMQ_PORT",
"rabbitmq_username" : "RABBITMQ_USERNAME",
"rabbitmq_password" : "RABBITMQ_PASSWORD"
}
{
"authserv_host" : "203.154.135.231",
"authserv_port" : 31088
}
// process.env["NODE_ENV"] = "development";
// process.env["NODE_CONFIG_DIR"] = __dirname + "/config/";
var restify = require('restify');
var on_publish = require('./on_publish')({debug:true});
const server = restify.createServer({
name: 'pubhook',
version: '1.0.0',
});
const port = 41000;
server.use(restify.plugins.bodyParser());
server.get('/about', function (req, res, next) {
res.send(server.name);
});
server.post('/onpub', on_publish);
server.listen(port, function () {
console.log('%s listening at %s', server.name, server.url);
});
var config = require('config');
// https://github.com/isaacs/node-lru-cache
var LRU = require("lru-cache") ,
cache = LRU({
max: 500,
maxAge: 1000 * 60 * 5
});
var client_wf = require('seneca')()
.use('seneca-amqp-transport')
.client({
type: 'amqp',
pin: 'cmd:wf',
url: 'amqp://'+config.get('rabbitmq_username')+':'+config.get('rabbitmq_password')+'@'+config.get('rabbitmq_host')+':'+config.get('rabbitmq_port')
});
var client_push = require('seneca')()
.use('seneca-amqp-transport')
.client({
type: 'amqp',
pin: 'cmd:push',
url: 'amqp://'+config.get('rabbitmq_username')+':'+config.get('rabbitmq_password')+'@'+config.get('rabbitmq_host')+':'+config.get('rabbitmq_port')
});
module.exports = function(options={}) {
return function(req, res, next) {
if (req.header('vernemq-hook') == 'on_publish' && req && req.body) {
if (options.debug) {
console.log('on_publish-------------');
console.log(req.body);
}
var data = req.body;
if (data.topic.substring(0,5) == '$exec') {
var stopic = data.topic.substr(6);
var a = data.topic.split('/');
var ptext = Buffer.from(data.payload, 'base64').toString();
if (stopic && ptext) {
switch (a[0]) {
case 'wf' :
case 'writefeed' :
let wfmsg = [{
"topic": stopic,
"payload":ptext,
"ts": Date.now(),
"cid": data.client_id,
}];
client_wf.act('cmd:wf', {
message: JSON.stringify(wfmsg)
}, (err, res) => {
if (err) {
throw err;
}
});
break;
case 'push' :
let pushmsg = [{
"topic": stopic,
"payload":ptext,
"ts": Date.now(),
"cid": data.client_id,
}];
client_push.act('cmd:push', {
message: JSON.stringify(pushmsg)
}, (err, res) => {
if (err) {
throw err;
}
});
break;
}
}
}
var topic = req.body.topic;
var cachekey = 'pub:'+req.body.client_id +':'+ req.body.username+':'+topic;
var authstatus = cache.get(cachekey);
res.status(200);
res.send('');
next();
}
else {
res.status(200);
res.send('');
next();
}
}
}
{
"name": "authhook",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"amqplib": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz",
"integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==",
"requires": {
"bitsyntax": "0.0.4",
"bluebird": "3.5.1",
"buffer-more-ints": "0.0.2",
"readable-stream": "1.1.14",
"safe-buffer": "5.1.2"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"amqpuri": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/amqpuri/-/amqpuri-1.1.0.tgz",
"integrity": "sha1-v4Qt8OUJXDA+tPJVU5snY7G0Bis=",
"requires": {
"lodash.curry": "4.1.1",
"lodash.flowright": "3.5.0",
"lodash.pick": "4.4.0"
}
},
"archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
"integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA="
},
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"backoff": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
"integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=",
"requires": {
"precond": "0.2.3"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"optional": true
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"bitsyntax": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz",
"integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=",
"requires": {
"buffer-more-ints": "0.0.2"
}
},
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
},
"boom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
"requires": {
"hoek": "4.2.1"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"optional": true,
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"buffer-more-ints": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz",
"integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw="
},
"bunyan": {
"version": "1.8.12",
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
"requires": {
"dtrace-provider": "0.8.7",
"moment": "2.22.2",
"mv": "2.1.1",
"safe-json-stringify": "1.2.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"optional": true
},
"config": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/config/-/config-1.30.0.tgz",
"integrity": "sha1-HWCp81NIoTwXV5jThOgaWhbDum4=",
"requires": {
"json5": "0.4.0",
"os-homedir": "1.0.2"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"csv": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/csv/-/csv-1.2.1.tgz",
"integrity": "sha1-UjHt/BxxUlEuxFeBB2p6l/9SXAw=",
"requires": {
"csv-generate": "1.1.2",
"csv-parse": "1.3.3",
"csv-stringify": "1.1.2",
"stream-transform": "0.2.2"
}
},
"csv-generate": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-1.1.2.tgz",
"integrity": "sha1-7GsA7a7W5ZrZwgWC9MNk4osUYkA="
},
"csv-parse": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.3.3.tgz",
"integrity": "sha1-0c/YdDwvhJoKuy/VRNtWaV0ZpJA="
},
"csv-stringify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-1.1.2.tgz",
"integrity": "sha1-d6QVJlgbzjOA8SsA18W7rHDIK1g=",
"requires": {
"lodash.get": "4.4.2"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "1.0.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"detect-node": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
"integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc="
},
"dtrace-provider": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz",
"integrity": "sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=",
"optional": true,
"requires": {
"nan": "2.10.0"
}
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"eraro": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eraro/-/eraro-1.0.0.tgz",
"integrity": "sha512-JeEqKyNgOxZNji2otWWDCDu1sWqGkrIBBhoGQH0LrPZObccQW8CoD94xkOtpmmlHeY/frG8IwR+jeCS8SQA/Xw==",
"requires": {
"lodash": "4.17.10"
}
},
"escape-regexp-component": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz",
"integrity": "sha1-nGO20LJf8qiMOtvRjFthrMO5+qI="
},
"ewma": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ewma/-/ewma-2.0.1.tgz",
"integrity": "sha512-MYYK17A76cuuyvkR7MnqLW4iFYPEi5Isl2qb8rXiWpLiwFS9dxW/rncuNnjjgSENuVqZQkIuR4+DChVL4g1lnw==",
"requires": {
"assert-plus": "1.0.0"
}
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-decode-uri-component": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.0.tgz",
"integrity": "sha512-WQSYVKn6tDW/3htASeUkrx5LcnuTENQIZQPCVlwdnvIJ7bYtSpoJYq38MgUJnx1CQIR1gjZ8HJxAEcN4gqugBg=="
},
"find-my-way": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-1.15.1.tgz",
"integrity": "sha512-cwR1IxkB1JIIGxWpX3TQC1U/51htT4dps536rno7fkszeSSevvZGkl1dpIANRNq+X6/VDSF/S4JAuDPSTepHBA==",
"requires": {
"fast-decode-uri-component": "1.0.0",
"safe-regex": "1.1.0",
"semver-store": "0.3.0"
}
},
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
},
"gate-executor": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/gate-executor/-/gate-executor-1.1.1.tgz",
"integrity": "sha1-Zn9ncoSg2+hrbEigtK/oxISBLK8="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "1.0.0"
}
},
"gex": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/gex/-/gex-0.3.0.tgz",
"integrity": "sha512-A1F2DMZUAnieFmVowt1QHcH7AJQZApRThR+z4C0GlzMGi6VYUAf9UvQdxODiCajGPGSRso86YJQ48E8+b5CBAQ==",
"requires": {
"lodash": "4.17.10"
}
},
"glob": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
"integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
"optional": true,
"requires": {
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"handle-thing": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
"integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ="
},
"hoek": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
},
"hpack.js": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
"integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
"requires": {
"inherits": "2.0.3",
"obuf": "1.1.2",
"readable-stream": "2.3.6",
"wbuf": "1.7.3"
}
},
"http-deceiver": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
"integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "1.0.0",
"jsprim": "1.4.1",
"sshpk": "1.14.2"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"optional": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"json5": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz",
"integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0="
},
"jsonic": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/jsonic/-/jsonic-0.3.0.tgz",
"integrity": "sha1-tUXalfVDkuWLPdoF9fLjd6bJ0b8="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
},
"lodash.curry": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
"integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
},
"lodash.flowright": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/lodash.flowright/-/lodash.flowright-3.5.0.tgz",
"integrity": "sha1-K1//OZcW1+fcVyT+k0n2cGUYTWc="
},
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
"lodash.pick": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
"integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
},
"lru-cache": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
"integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
"requires": {
"pseudomap": "1.0.2",
"yallist": "2.1.2"
}
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"optional": true,
"requires": {
"brace-expansion": "1.1.11"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"optional": true
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"optional": true,
"requires": {
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.22.2",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=",
"optional": true
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"mv": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
"integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=",
"optional": true,
"requires": {
"mkdirp": "0.5.1",
"ncp": "2.0.0",
"rimraf": "2.4.5"
}
},
"nan": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
"optional": true
},
"ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"optional": true
},
"ndjson": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz",
"integrity": "sha1-rmA7NrE0vOw0e0UkIrC/mNWDLsg=",
"requires": {
"json-stringify-safe": "5.0.1",
"minimist": "1.2.0",
"split2": "2.2.0",
"through2": "2.0.3"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"nid": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/nid/-/nid-0.3.2.tgz",
"integrity": "sha1-l3qTGO1cKjjt1mJj8+r9gUPyJRo="
},
"norma": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/norma/-/norma-0.4.1.tgz",
"integrity": "sha512-BSnU+B35GzJgkEcNqiMIm79507Qg68O5L7gRVKATRSx17BHyDn0gVJsi3YzoANC1NbBoKRExwd3KsEZSUox63Q==",
"requires": {
"eraro": "1.0.0",
"lodash": "4.17.10"
}
},
"obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
}
},
"ordu": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ordu/-/ordu-0.1.1.tgz",
"integrity": "sha1-nIEJSTaTyvCCmfyoTFlq64YLrqo="
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"optional": true
},
"patrun": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/patrun/-/patrun-1.0.0.tgz",
"integrity": "sha512-oemWSuxjb27nPkREl88BxZ2EFDFUKSPace+zYZjFKj2xFn6w/LgDFGptgQvme384As2gpEFIv4WMVE1cb9lDXQ==",
"requires": {
"gex": "0.3.0",
"lodash": "4.17.10"
}
},
"pidusage": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-1.2.0.tgz",
"integrity": "sha512-OGo+iSOk44HRJ8q15AyG570UYxcm5u+R99DI8Khu8P3tKGkVu5EZX4ywHglWSTMNNXQ274oeGpYrvFEhDIFGPg=="
},
"precond": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
"integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw="
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "2.0.0",
"safe-buffer": "5.1.2",
"string_decoder": "1.1.1",
"util-deprecate": "1.0.2"
}
},
"reconnect-core": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/reconnect-core/-/reconnect-core-1.3.0.tgz",
"integrity": "sha1-+65SkZp4d9hE4yRtAaLyZwHIM8g=",
"requires": {
"backoff": "2.5.0"
}
},
"restify": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/restify/-/restify-7.2.1.tgz",
"integrity": "sha512-xygVfQn/FiyzSPNIiOlzos6+RVcmTTK/bN0/m4z6vQwUY1yXntAsXM8ckq6hMxYfkhZfbPMM5hvBf75B8zLE1g==",
"requires": {
"assert-plus": "1.0.0",
"bunyan": "1.8.12",
"csv": "1.2.1",
"dtrace-provider": "0.8.7",
"escape-regexp-component": "1.0.2",
"ewma": "2.0.1",
"find-my-way": "1.15.1",
"formidable": "1.2.1",
"http-signature": "1.2.0",
"lodash": "4.17.10",
"lru-cache": "4.1.3",
"mime": "1.6.0",
"negotiator": "0.6.1",
"once": "1.4.0",
"pidusage": "1.2.0",
"qs": "6.5.2",
"restify-errors": "5.0.0",
"semver": "5.5.0",
"spdy": "3.4.7",
"uuid": "3.3.2",
"vasync": "1.6.4",
"verror": "1.10.0"
}
},
"restify-errors": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/restify-errors/-/restify-errors-5.0.0.tgz",
"integrity": "sha512-+vby9Kxf7qlzvbZSTIEGkIixkeHG+pVCl34dk6eKnL+ua4pCezpdLT/1/eabzPZb65ADrgoc04jeWrrF1E1pvQ==",
"requires": {
"assert-plus": "1.0.0",
"lodash": "4.17.10",
"safe-json-stringify": "1.2.0",
"verror": "1.10.0"
}
},
"ret": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
},
"rimraf": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"optional": true,
"requires": {
"glob": "6.0.4"
}
},
"rolling-stats": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/rolling-stats/-/rolling-stats-0.1.1.tgz",
"integrity": "sha1-zVr3dKiJOzCmdIMvovSrqkeM/IA="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safe-json-stringify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
"integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==",
"optional": true
},
"safe-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"requires": {
"ret": "0.1.15"
}
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
},
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
},
"semver-store": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz",
"integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg=="
},
"seneca": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/seneca/-/seneca-3.6.0.tgz",
"integrity": "sha512-vZO/rU0n1CQE/2bHuUtJU1NevF0NTlr+fZuHDrVuk+sSqoy+u+rtcG/8P1nqNEpPLRWfgJB8c/BrJyieg4uEgg==",
"requires": {
"archy": "1.0.0",
"eraro": "1.0.0",
"gate-executor": "1.1.1",
"gex": "0.3.0",
"json-stringify-safe": "5.0.1",
"jsonic": "0.3.0",
"lodash": "4.17.10",
"minimist": "1.2.0",
"nid": "0.3.2",
"norma": "0.4.1",
"ordu": "0.1.1",
"patrun": "1.0.0",
"qs": "6.5.2",
"rolling-stats": "0.1.1",
"semver": "5.5.0",
"seneca-transport": "2.3.0",
"use-plugin": "1.0.2",
"wreck": "12.5.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"seneca-amqp-transport": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/seneca-amqp-transport/-/seneca-amqp-transport-2.2.0.tgz",
"integrity": "sha512-3hNQEc/pCZj9d5Qhjev90OIOHdncX1GKCdx7Cf8uKirA6R97Nizf/V2CcXLDsLQqvzvtc2G9sG3mnERasewpxA==",
"requires": {
"amqplib": "0.5.2",
"amqpuri": "1.1.0",
"bluebird": "3.5.1",
"jsonic": "0.3.0",
"lodash": "4.17.10",
"uuid": "3.3.2"
}
},
"seneca-transport": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/seneca-transport/-/seneca-transport-2.3.0.tgz",
"integrity": "sha512-kocolZ+54fNbwVFloBnOyjeH4SFXFGyefeuqh2sNoQCycAGxBQpzFC8CIJkjL1YUQS8KczPxEs5sIFrKYIQdnA==",
"requires": {
"eraro": "1.0.0",
"gex": "0.3.0",
"jsonic": "0.3.0",
"lodash": "4.17.10",
"lru-cache": "4.1.3",
"ndjson": "1.5.0",
"nid": "0.3.2",
"patrun": "1.0.0",
"qs": "6.5.2",
"reconnect-core": "1.3.0",
"wreck": "12.5.1"
}
},
"spdy": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
"integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
"requires": {
"debug": "2.6.9",
"handle-thing": "1.2.5",
"http-deceiver": "1.2.7",
"safe-buffer": "5.1.2",
"select-hose": "2.0.0",
"spdy-transport": "2.1.0"
}
},
"spdy-transport": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz",
"integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==",
"requires": {
"debug": "2.6.9",
"detect-node": "2.0.3",
"hpack.js": "2.1.6",
"obuf": "1.1.2",
"readable-stream": "2.3.6",
"safe-buffer": "5.1.2",
"wbuf": "1.7.3"
}
},
"split2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
"integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==",
"requires": {
"through2": "2.0.3"
}
},
"sshpk": {
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.2",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jsbn": "0.1.1",
"safer-buffer": "2.1.2",
"tweetnacl": "0.14.5"
}
},
"stream-transform": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-0.2.2.tgz",
"integrity": "sha1-dYZ0h/SVKPi/HYJJllh1PQLfeDg="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"through2": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
"integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
"requires": {
"readable-stream": "2.3.6",
"xtend": "4.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
},
"use-plugin": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/use-plugin/-/use-plugin-1.0.2.tgz",
"integrity": "sha512-46ZNYmSDMgyCBsUIPwLFWzY45jIu4sHFKKq3/M63XCd/RxvliC4qRVWtUAWEexP7q8X1MHJ2Br1U5KLkVFcQCw==",
"requires": {
"eraro": "1.0.0",
"nid": "0.3.2",
"norma": "0.4.1"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"vasync": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz",
"integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=",
"requires": {
"verror": "1.6.0"
},
"dependencies": {
"extsprintf": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz",
"integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk="
},
"verror": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz",
"integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=",
"requires": {
"extsprintf": "1.2.0"
}
}
}
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "1.3.0"
}
},
"wbuf": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
"integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
"requires": {
"minimalistic-assert": "1.0.1"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"wreck": {
"version": "12.5.1",
"resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz",
"integrity": "sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A==",
"requires": {
"boom": "5.2.0",
"hoek": "4.2.1"
}
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
}
}
}
{
"name": "authhook",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"config": "^1.30.0",
"lru-cache": "^4.1.3",
"restify": "^7.1.1",
"seneca": "^3.6.0",
"seneca-amqp-transport": "^2.2.0"
}
}
REGISTRY_HOST=dock.nexpie.com
GROUPNAME=stack
PROJECTNAME=vernemq/pubhook
RELEASE=1.0.0
FROM alpine:3.8
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN addgroup -S redis && adduser -S -G redis redis
RUN apk add --no-cache \
# grab su-exec for easy step-down from root
'su-exec>=0.2' \
# add tzdata for https://github.com/docker-library/redis/issues/138
tzdata
ENV REDIS_VERSION 5.0.0
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.0.tar.gz
ENV REDIS_DOWNLOAD_SHA 70c98b2d0640b2b73c9d8adb4df63bcb62bad34b788fe46d1634b6cf87dc99a4
# for redis-sentinel see: http://redis.io/topics/sentinel
RUN set -ex; \
\
apk add --no-cache --virtual .build-deps \
coreutils \
gcc \
jemalloc-dev \
linux-headers \
make \
musl-dev \
; \
\
wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \
echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \
mkdir -p /usr/src/redis; \
tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \
rm redis.tar.gz; \
\
# disable Redis protected mode [1] as it is unnecessary in context of Docker
# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P)
# [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da
grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h; \
sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h; \
grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h; \
# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything"
# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840
# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default)
\
make -C /usr/src/redis -j "$(nproc)"; \
make -C /usr/src/redis install; \
\
rm -r /usr/src/redis; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --virtual .redis-rundeps $runDeps; \
apk del .build-deps; \
\
redis-server --version
RUN mkdir /data && chown redis:redis /data
VOLUME /data
WORKDIR /data
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD ["redis-server"]
\ No newline at end of file
# a helper shell script
MAKE_VERSION=1.1.2
define MAKEFUNCTIONCODE
function hasChanges() {
# old version, just track uncommited + untracked files
# test -n "$$(git status -s .)"
# expect 1 to be normal so the untracked file .make-funcition will be ignored
test 1 -ne "$$(git status -s . | wc -l )"
}
function getRelease() {
awk -F= '/^RELEASE=/{print $$2}' release.conf
}
function getBaseTag() {
sed -n -e "s/^tag=\(.*\)$$(getRelease)\$$/\1/p" release.conf
}
function getTag() {
if [ -z "$$1" ] ; then
awk -F= '/^tag/{print $$2}' release.conf
else
echo "$$(getBaseTag)$$1"
fi
}
function setRelease() {
if [ -n "$$1" ] ; then
sed -i.x -e "s/^tag=.*/tag=$$(getTag $$1)/" release.conf
sed -i.x -e "s/^RELEASE=.*/RELEASE=$$1/g" release.conf
rm -f release.conf.x
runPreTagCommand "$$1"
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function runPreTagCommand() {
if [ -n "$$1" ] ; then
COMMAND=$$(sed -n -e "s/@@RELEASE@@/$$1/g" -e 's/^pre_tag_command=\(.*\)/\1/p' release.conf)
if [ -n "$$COMMAND" ] ; then
if ! OUTPUT=$$(bash -c "$$COMMAND" 2>&1) ; then echo $$OUTPUT >&2 && exit 1 ; fi
fi
else
echo "ERROR: missing release version parameter " >&2
return 1
fi
}
function tagExists() {
tag=$${1:-$$(getTag)}
test -n "$$tag" && test -n "$$(git tag | grep "^$$tag\$$")"
}
function differsFromRelease() {
tag=$$(getTag)
! tagExists $$tag || test -n "$$(git diff --shortstat -r $$tag .)"
}
function getVersion() {
result=$$(getRelease)
if differsFromRelease; then
result="$$result-$$(git log -n 1 --format=%h .)"
fi
if hasChanges ; then
result="$$result-dirty"
fi
echo $$result
}
function nextPatchLevel() {
version=$${1:-$$(getRelease)}
major_and_minor=$$(echo $$version | cut -d. -f1,2)
patch=$$(echo $$version | cut -d. -f3)
version=$$(printf "%s.%d" $$major_and_minor $$(($$patch + 1)))
echo $$version
}
function nextMinorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
minor=$$(echo $$version | cut -d. -f2);
version=$$(printf "%d.%d.0" $$major $$(($$minor + 1))) ;
echo $$version
}
function nextMajorLevel() {
version=$${1:-$$(getRelease)}
major=$$(echo $$version | cut -d. -f1);
version=$$(printf "%d.0.0" $$(($$major + 1)))
echo $$version
}
endef
SHELL=/bin/bash
include release.conf
IMAGE=$(REGISTRY_HOST)/$(GROUPNAME)/$(PROJECTNAME)
VERSION=$(shell . $(RELEASE_SUPPORT) ; getVersion)
TAG=$(shell . $(RELEASE_SUPPORT); getTag)
RELEASE_SUPPORT := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))/.make-function
export MAKEFUNCTIONCODE
.PHONY: pre-build docker-build post-build build release patch-release minor-release major-release tag check-status check-release showtag show-tag \
push do-push post-push post-init update-make
init:
@echo "$$MAKEFUNCTIONCODE" > ./.make-function
build: init pre-build docker-build post-build
pre-build:
post-build:
@rm .make-function
post-push:
@rm .make-function
post-init:
@rm .make-function
docker-build:
docker build -t $(IMAGE):$(VERSION) .
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
echo docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\
docker tag -f $(IMAGE):$(VERSION) $(IMAGE):latest ;\
else \
echo docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ;\
docker tag $(IMAGE):$(VERSION) $(IMAGE):latest ; \
fi
release: check-status check-release build push
push: init do-push post-push
do-push:
docker push $(IMAGE):$(VERSION)
docker push $(IMAGE):latest
snapshot: build push
show-tag: init release.conf
@. $(RELEASE_SUPPORT); getVersion
@rm .make-function
showtag: init release.conf
@. $(RELEASE_SUPPORT); getVersion
@rm .make-function
tag-patch-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextPatchLevel)
tag-patch-release: release.conf tag
tag-minor-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMinorLevel)
tag-minor-release: release.conf tag
tag-major-release: init
VERSION := $(shell . $(RELEASE_SUPPORT); nextMajorLevel)
tag-major-release: release.conf tag
patch-release: tag-patch-release release
@echo $(VERSION)
minor-release: tag-minor-release release
@echo $(VERSION)
major-release: tag-major-release release
@echo $(VERSION)
tag: TAG=$(shell . $(RELEASE_SUPPORT); getTag $(VERSION))
tag: check-status
@. $(RELEASE_SUPPORT) ; ! tagExists $(TAG) || (echo "ERROR: tag $(TAG) for version $(VERSION) already tagged in git" >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; setRelease $(VERSION)
git add .
git commit -m "bumped to version $(VERSION)" ;
git tag $(TAG) ;
@ if [ -n "$(shell git remote -v)" ] ; then git push --tags ; else echo 'no remote to push tags to' ; fi
check-status: init
@. $(RELEASE_SUPPORT) ; ! hasChanges || (echo "ERROR: there are still outstanding changes" >&2) ;
@rm .make-function
check-release: init release.conf post-init
@. $(RELEASE_SUPPORT) ; tagExists $(TAG) || (echo "ERROR: version not yet tagged in git. make [minor,major,patch]-release." >&2 && exit 1) ;
@. $(RELEASE_SUPPORT) ; ! differsFromRelease $(TAG) || (echo "ERROR: current directory differs from tagged $(TAG). make [minor,major,patch]-release." ; exit 1)
update-make: init
@rm Makefile
wget https://dev.nexpie.com/sample/docker-makefile-sample/raw/master/Makefile
@rm .make-function
make-version:
@echo $(MAKE_VERSION)
#!/bin/sh
set -e
# first arg is `-f` or `--some-option`
# or first arg is `something.conf`
if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then
set -- redis-server "$@"
fi
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
find . \! -user redis -exec chown redis '{}' +
exec su-exec redis "$0" "$@"
fi
exec "$@"
\ No newline at end of file
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis
namespace: nexpieio
labels:
app: redis
tier: backend
spec:
# this replicas value is default
# modify it according to your case
replicas: 1
# selector can be applied automatically
# from the labels in the pod template if not set
selector:
matchLabels:
app: redis
tier: backend
template:
metadata:
labels:
app: redis
tier: backend
spec:
imagePullSecrets:
- name: docknexpie
containers:
- name: redis
image: dock.nexpie.com/stack/vernemq/redis:1.0.0-d640c8a
ports:
- containerPort: 6379
name: redis
REGISTRY_HOST=dock.nexpie.com
GROUPNAME=stack
PROJECTNAME=vernemq/redis
RELEASE=1.0.0
REGISTRY_HOST=dock.nexpie.com REGISTRY_HOST=dock.nexpie.com
GROUPNAME=stack GROUPNAME=stack
PROJECTNAME=vernemq PROJECTNAME=vernemq
RELEASE=1.0.0 RELEASE=1.12.5
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment