Commit b8c13535e45acb906216f58fbbe89c5fa17f81f3

Authored by Igor Kulikov
1 parent c0668dcb

Add Microservices module. Add ThingsBoard JS Executor Microservice.

  1 +*.toDelete
  2 +output/**
  3 +*.class
  4 +*~
  5 +*.iml
  6 +*/.idea/**
  7 +.idea/**
  8 +.idea
  9 +*.log
  10 +*.log.[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
  11 +*/.classpath
  12 +.classpath
  13 +*/.project
  14 +.project
  15 +.cache/**
  16 +target/
  17 +logs/
  18 +build/
  19 +.settings/
  20 +/bin
  21 +bin/
  22 +**/dependency-reduced-pom.xml
  23 +pom.xml.versionsBackup
  24 +.DS_Store
  25 +**/.gradle
  26 +**/local.properties
  27 +**/build
  28 +**/target
  29 +**/.env
  30 +node_modules
  31 +package-lock.json
... ...
  1 +/*
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +'use strict';
  18 +
  19 +var logger = require('../config/logger')('JsMessageConsumer');
  20 +
  21 +exports.onJsInvokeMessage = function(message, producer) {
  22 +
  23 + logger.info('Received message: %s', message);
  24 +
  25 +}
... ...
  1 +/**
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +import org.apache.tools.ant.filters.ReplaceTokens
  17 +
  18 +buildscript {
  19 + ext {
  20 + osPackageVersion = "3.8.0"
  21 + }
  22 + repositories {
  23 + jcenter()
  24 + }
  25 + dependencies {
  26 + classpath("com.netflix.nebula:gradle-ospackage-plugin:${osPackageVersion}")
  27 + }
  28 +}
  29 +
  30 +apply plugin: "nebula.ospackage"
  31 +
  32 +buildDir = projectBuildDir
  33 +version = projectVersion
  34 +distsDirName = "./"
  35 +
  36 +// OS Package plugin configuration
  37 +ospackage {
  38 + packageName = pkgName
  39 + version = "${project.version}"
  40 + release = 1
  41 + os = LINUX
  42 + type = BINARY
  43 +
  44 + into pkgInstallFolder
  45 +
  46 + user pkgUser
  47 + permissionGroup pkgUser
  48 +
  49 + // Copy the executable file
  50 + from("target/package/linux/bin/${pkgName}") {
  51 + fileMode 0500
  52 + into "bin"
  53 + }
  54 +
  55 + // Copy the init file
  56 + from("target/package/linux/init/${pkgName}") {
  57 + fileMode 0500
  58 + into "init"
  59 + }
  60 +
  61 + // Copy the config files
  62 + from("target/package/linux/conf") {
  63 + fileType CONFIG | NOREPLACE
  64 + fileMode 0754
  65 + into "conf"
  66 + }
  67 +
  68 +}
  69 +
  70 +// Configure our RPM build task
  71 +buildRpm {
  72 +
  73 + arch = X86_64
  74 +
  75 + version = projectVersion.replace('-', '')
  76 + archiveName = "${pkgName}.rpm"
  77 +
  78 + preInstall file("${buildDir}/control/rpm/preinst")
  79 + postInstall file("${buildDir}/control/rpm/postinst")
  80 + preUninstall file("${buildDir}/control/rpm/prerm")
  81 + postUninstall file("${buildDir}/control/rpm/postrm")
  82 +
  83 + user pkgUser
  84 + permissionGroup pkgUser
  85 +
  86 + // Copy the system unit files
  87 + from("${buildDir}/control/${pkgName}.service") {
  88 + addParentDirs = false
  89 + fileMode 0644
  90 + into "/usr/lib/systemd/system"
  91 + }
  92 +
  93 + directory(pkgLogFolder, 0755)
  94 + link("/etc/${pkgName}/conf", "${pkgInstallFolder}/conf")
  95 +}
  96 +
  97 +// Same as the buildRpm task
  98 +buildDeb {
  99 +
  100 + arch = "amd64"
  101 +
  102 + archiveName = "${pkgName}.deb"
  103 +
  104 + configurationFile("${pkgInstallFolder}/conf/${pkgName}.conf")
  105 + configurationFile("${pkgInstallFolder}/conf/custom-environment-variables.yml")
  106 + configurationFile("${pkgInstallFolder}/conf/default.yml")
  107 + configurationFile("${pkgInstallFolder}/conf/logger.js")
  108 +
  109 + preInstall file("${buildDir}/control/deb/preinst")
  110 + postInstall file("${buildDir}/control/deb/postinst")
  111 + preUninstall file("${buildDir}/control/deb/prerm")
  112 + postUninstall file("${buildDir}/control/deb/postrm")
  113 +
  114 + user pkgUser
  115 + permissionGroup pkgUser
  116 +
  117 + directory(pkgLogFolder, 0755)
  118 + link("/etc/init.d/${pkgName}", "${pkgInstallFolder}/init/${pkgName}")
  119 + link("/etc/${pkgName}/conf", "${pkgInstallFolder}/conf")
  120 +}
... ...
  1 +#
  2 +# Copyright © 2016-2018 The Thingsboard Authors
  3 +#
  4 +# Licensed under the Apache License, Version 2.0 (the "License");
  5 +# you may not use this file except in compliance with the License.
  6 +# You may obtain a copy of the License at
  7 +#
  8 +# http://www.apache.org/licenses/LICENSE-2.0
  9 +#
  10 +# Unless required by applicable law or agreed to in writing, software
  11 +# distributed under the License is distributed on an "AS IS" BASIS,
  12 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +# See the License for the specific language governing permissions and
  14 +# limitations under the License.
  15 +#
  16 +
  17 +kafka:
  18 + request_topic: "REMOTE_JS_EVAL_REQUEST_TOPIC"
  19 + bootstrap:
  20 + # Kafka Bootstrap Servers
  21 + servers: "TB_KAFKA_SERVERS"
  22 +logger:
  23 + level: "LOGGER_LEVEL"
  24 + path: "LOG_FOLDER"
  25 + filename: "LOGGER_FILENAME"
... ...
  1 +#
  2 +# Copyright © 2016-2018 The Thingsboard Authors
  3 +#
  4 +# Licensed under the Apache License, Version 2.0 (the "License");
  5 +# you may not use this file except in compliance with the License.
  6 +# You may obtain a copy of the License at
  7 +#
  8 +# http://www.apache.org/licenses/LICENSE-2.0
  9 +#
  10 +# Unless required by applicable law or agreed to in writing, software
  11 +# distributed under the License is distributed on an "AS IS" BASIS,
  12 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +# See the License for the specific language governing permissions and
  14 +# limitations under the License.
  15 +#
  16 +
  17 +kafka:
  18 + request_topic: "js.eval.requests"
  19 + bootstrap:
  20 + # Kafka Bootstrap Servers
  21 + servers: "localhost:9092"
  22 +
  23 +logger:
  24 + level: "info"
  25 + path: "logs"
  26 + filename: "tb-js-executor-%DATE%.log"
... ...
  1 +/*
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +var config = require('config'),
  17 + path = require('path'),
  18 + DailyRotateFile = require('winston-daily-rotate-file');
  19 +
  20 +const { createLogger, format, transports } = require('winston');
  21 +const { combine, timestamp, label, printf, splat } = format;
  22 +
  23 +var loggerTransports = [];
  24 +
  25 +if (process.env.NODE_ENV !== 'production') {
  26 + loggerTransports.push(new transports.Console({
  27 + handleExceptions: true
  28 + }));
  29 +} else {
  30 + var filename = path.join(config.get('logger.path'), config.get('logger.filename'));
  31 + var transport = new (DailyRotateFile)({
  32 + filename: filename,
  33 + datePattern: 'YYYY-MM-DD-HH',
  34 + zippedArchive: true,
  35 + maxSize: '20m',
  36 + maxFiles: '14d',
  37 + handleExceptions: true
  38 + });
  39 + loggerTransports.push(transport);
  40 +}
  41 +
  42 +const tbFormat = printf(info => {
  43 + return `${info.timestamp} [${info.label}] ${info.level.toUpperCase()}: ${info.message}`;
  44 +});
  45 +
  46 +function _logger(moduleLabel) {
  47 + return createLogger({
  48 + level: config.get('logger.level'),
  49 + format:combine(
  50 + splat(),
  51 + label({ label: moduleLabel }),
  52 + timestamp({format: 'YYYY-MM-DD HH:mm:ss,SSS'}),
  53 + tbFormat
  54 + ),
  55 + transports: loggerTransports
  56 + });
  57 +}
  58 +
  59 +module.exports = _logger;
\ No newline at end of file
... ...
  1 +#
  2 +# Copyright © 2016-2018 The Thingsboard Authors
  3 +#
  4 +# Licensed under the Apache License, Version 2.0 (the "License");
  5 +# you may not use this file except in compliance with the License.
  6 +# You may obtain a copy of the License at
  7 +#
  8 +# http://www.apache.org/licenses/LICENSE-2.0
  9 +#
  10 +# Unless required by applicable law or agreed to in writing, software
  11 +# distributed under the License is distributed on an "AS IS" BASIS,
  12 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +# See the License for the specific language governing permissions and
  14 +# limitations under the License.
  15 +#
  16 +
  17 +export NODE_CONFIG_DIR=${pkg.installFolder}/conf
  18 +export LOG_FOLDER=${pkg.logFolder}
  19 +export NODE_ENV=production
... ...
  1 +/*
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +const fs = require('fs');
  17 +const fse = require('fs-extra');
  18 +const path = require('path');
  19 +
  20 +let _projectRoot = null;
  21 +
  22 +
  23 +(async() => {
  24 + await fse.move(path.join(projectRoot(), 'target', 'thingsboard-js-executor-linux'),
  25 + path.join(targetPackageDir('linux'), 'bin', 'tb-js-executor'),
  26 + {overwrite: true});
  27 + await fse.move(path.join(projectRoot(), 'target', 'thingsboard-js-executor-win.exe'),
  28 + path.join(targetPackageDir('windows'), 'bin', 'tb-js-executor.exe'),
  29 + {overwrite: true});
  30 +})();
  31 +
  32 +
  33 +function projectRoot() {
  34 + if (!_projectRoot) {
  35 + _projectRoot = __dirname;
  36 + }
  37 + return _projectRoot;
  38 +}
  39 +
  40 +function targetPackageDir(platform) {
  41 + return path.join(projectRoot(), 'target', 'package', platform);
  42 +}
... ...
  1 +{
  2 + "name": "thingsboard-js-executor",
  3 + "private": true,
  4 + "version": "2.2.0",
  5 + "description": "ThingsBoard JavaScript Executor Microservice",
  6 + "main": "server.js",
  7 + "bin": "server.js",
  8 + "scripts": {
  9 + "install": "pkg -t node8-linux-x64,node8-win-x64 --out-path ./target . && node install.js",
  10 + "test": "echo \"Error: no test specified\" && exit 1",
  11 + "start": "nodemon server.js",
  12 + "start-prod": "NODE_ENV=production nodemon server.js"
  13 + },
  14 + "dependencies": {
  15 + "config": "^1.30.0",
  16 + "js-yaml": "^3.12.0",
  17 + "kafka-node": "^3.0.1",
  18 + "winston": "^3.0.0",
  19 + "winston-daily-rotate-file": "^3.2.1"
  20 + },
  21 + "engine": "node >= 5.9.0",
  22 + "nyc": {
  23 + "exclude": [
  24 + "test",
  25 + "__tests__",
  26 + "node_modules",
  27 + "target"
  28 + ]
  29 + },
  30 + "devDependencies": {
  31 + "fs-extra": "^6.0.1",
  32 + "nodemon": "^1.17.5",
  33 + "pkg": "^4.3.3"
  34 + }
  35 +}
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2018 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  20 + <modelVersion>4.0.0</modelVersion>
  21 + <parent>
  22 + <groupId>org.thingsboard</groupId>
  23 + <version>2.2.0-SNAPSHOT</version>
  24 + <artifactId>msa</artifactId>
  25 + </parent>
  26 + <groupId>org.thingsboard.msa</groupId>
  27 + <artifactId>js-executor</artifactId>
  28 + <packaging>pom</packaging>
  29 +
  30 + <name>ThingsBoard JavaScript Executor Microservice</name>
  31 + <url>https://thingsboard.io</url>
  32 + <description>Service executing JavaScript functions in sandboxed environment</description>
  33 +
  34 + <properties>
  35 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  36 + <main.dir>${basedir}/../..</main.dir>
  37 + <pkg.name>tb-js-executor</pkg.name>
  38 + <pkg.user>thingsboard</pkg.user>
  39 + <pkg.unixLogFolder>/var/log/${pkg.name}</pkg.unixLogFolder>
  40 + <pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
  41 + <pkg.linux.dist>${project.build.directory}/package/linux</pkg.linux.dist>
  42 + <pkg.win.dist>${project.build.directory}/package/windows</pkg.win.dist>
  43 + </properties>
  44 +
  45 + <dependencies>
  46 + <dependency>
  47 + <groupId>com.sun.winsw</groupId>
  48 + <artifactId>winsw</artifactId>
  49 + <classifier>bin</classifier>
  50 + <type>exe</type>
  51 + <scope>provided</scope>
  52 + </dependency>
  53 + </dependencies>
  54 +
  55 + <build>
  56 + <plugins>
  57 + <plugin>
  58 + <groupId>com.github.eirslett</groupId>
  59 + <artifactId>frontend-maven-plugin</artifactId>
  60 + <version>1.0</version>
  61 + <configuration>
  62 + <installDirectory>target</installDirectory>
  63 + <workingDirectory>${basedir}</workingDirectory>
  64 + </configuration>
  65 + <executions>
  66 + <execution>
  67 + <id>install node and npm</id>
  68 + <goals>
  69 + <goal>install-node-and-npm</goal>
  70 + </goals>
  71 + <configuration>
  72 + <nodeVersion>v8.11.3</nodeVersion>
  73 + <npmVersion>5.6.0</npmVersion>
  74 + </configuration>
  75 + </execution>
  76 + <execution>
  77 + <id>npm install</id>
  78 + <goals>
  79 + <goal>npm</goal>
  80 + </goals>
  81 + <configuration>
  82 + <arguments>install</arguments>
  83 + </configuration>
  84 + </execution>
  85 + </executions>
  86 + </plugin>
  87 + <plugin>
  88 + <groupId>org.apache.maven.plugins</groupId>
  89 + <artifactId>maven-dependency-plugin</artifactId>
  90 + <executions>
  91 + <execution>
  92 + <id>copy-winsw-service</id>
  93 + <phase>package</phase>
  94 + <goals>
  95 + <goal>copy</goal>
  96 + </goals>
  97 + <configuration>
  98 + <artifactItems>
  99 + <artifactItem>
  100 + <groupId>com.sun.winsw</groupId>
  101 + <artifactId>winsw</artifactId>
  102 + <classifier>bin</classifier>
  103 + <type>exe</type>
  104 + <destFileName>service.exe</destFileName>
  105 + </artifactItem>
  106 + </artifactItems>
  107 + <outputDirectory>${pkg.win.dist}</outputDirectory>
  108 + </configuration>
  109 + </execution>
  110 + </executions>
  111 + </plugin>
  112 + <plugin>
  113 + <groupId>org.apache.maven.plugins</groupId>
  114 + <artifactId>maven-resources-plugin</artifactId>
  115 + <executions>
  116 + <execution>
  117 + <id>copy-linux-conf</id>
  118 + <phase>process-resources</phase>
  119 + <goals>
  120 + <goal>copy-resources</goal>
  121 + </goals>
  122 + <configuration>
  123 + <outputDirectory>${pkg.linux.dist}/conf</outputDirectory>
  124 + <resources>
  125 + <resource>
  126 + <directory>config</directory>
  127 + <filtering>true</filtering>
  128 + </resource>
  129 + </resources>
  130 + <filters>
  131 + <filter>src/main/filters/unix.properties</filter>
  132 + </filters>
  133 + </configuration>
  134 + </execution>
  135 + <execution>
  136 + <id>copy-linux-init</id>
  137 + <phase>process-resources</phase>
  138 + <goals>
  139 + <goal>copy-resources</goal>
  140 + </goals>
  141 + <configuration>
  142 + <outputDirectory>${pkg.linux.dist}/init</outputDirectory>
  143 + <resources>
  144 + <resource>
  145 + <directory>src/main/scripts/init</directory>
  146 + <filtering>true</filtering>
  147 + </resource>
  148 + </resources>
  149 + <filters>
  150 + <filter>src/main/filters/unix.properties</filter>
  151 + </filters>
  152 + </configuration>
  153 + </execution>
  154 + <execution>
  155 + <id>copy-win-conf</id>
  156 + <phase>process-resources</phase>
  157 + <goals>
  158 + <goal>copy-resources</goal>
  159 + </goals>
  160 + <configuration>
  161 + <outputDirectory>${pkg.win.dist}/conf</outputDirectory>
  162 + <resources>
  163 + <resource>
  164 + <directory>config</directory>
  165 + <excludes>
  166 + <exclude>tb-js-executor.conf</exclude>
  167 + </excludes>
  168 + <filtering>true</filtering>
  169 + </resource>
  170 + </resources>
  171 + <filters>
  172 + <filter>src/main/filters/windows.properties</filter>
  173 + </filters>
  174 + </configuration>
  175 + </execution>
  176 + <execution>
  177 + <id>copy-control</id>
  178 + <phase>process-resources</phase>
  179 + <goals>
  180 + <goal>copy-resources</goal>
  181 + </goals>
  182 + <configuration>
  183 + <outputDirectory>${project.build.directory}/control</outputDirectory>
  184 + <resources>
  185 + <resource>
  186 + <directory>src/main/scripts/control</directory>
  187 + <filtering>true</filtering>
  188 + </resource>
  189 + </resources>
  190 + <filters>
  191 + <filter>src/main/filters/unix.properties</filter>
  192 + </filters>
  193 + </configuration>
  194 + </execution>
  195 + <execution>
  196 + <id>copy-windows-control</id>
  197 + <phase>process-resources</phase>
  198 + <goals>
  199 + <goal>copy-resources</goal>
  200 + </goals>
  201 + <configuration>
  202 + <outputDirectory>${pkg.win.dist}</outputDirectory>
  203 + <resources>
  204 + <resource>
  205 + <directory>src/main/scripts/windows</directory>
  206 + <filtering>true</filtering>
  207 + </resource>
  208 + </resources>
  209 + <filters>
  210 + <filter>src/main/filters/windows.properties</filter>
  211 + </filters>
  212 + </configuration>
  213 + </execution>
  214 + </executions>
  215 + </plugin>
  216 + <plugin>
  217 + <groupId>org.fortasoft</groupId>
  218 + <artifactId>gradle-maven-plugin</artifactId>
  219 + <configuration>
  220 + <tasks>
  221 + <task>build</task>
  222 + <task>buildDeb</task>
  223 + <task>buildRpm</task>
  224 + </tasks>
  225 + <args>
  226 + <arg>-PprojectBuildDir=${project.build.directory}</arg>
  227 + <arg>-PprojectVersion=${project.version}</arg>
  228 + <arg>-PpkgName=${pkg.name}</arg>
  229 + <arg>-PpkgUser=${pkg.user}</arg>
  230 + <arg>-PpkgInstallFolder=${pkg.installFolder}</arg>
  231 + <arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg>
  232 + </args>
  233 + </configuration>
  234 + <executions>
  235 + <execution>
  236 + <phase>package</phase>
  237 + <goals>
  238 + <goal>invoke</goal>
  239 + </goals>
  240 + </execution>
  241 + </executions>
  242 + </plugin>
  243 + <plugin>
  244 + <groupId>org.apache.maven.plugins</groupId>
  245 + <artifactId>maven-assembly-plugin</artifactId>
  246 + <version>3.0.0</version>
  247 + <configuration>
  248 + <finalName>${pkg.name}</finalName>
  249 + <descriptors>
  250 + <descriptor>src/main/assembly/windows.xml</descriptor>
  251 + </descriptors>
  252 + </configuration>
  253 + <executions>
  254 + <execution>
  255 + <id>assembly</id>
  256 + <phase>package</phase>
  257 + <goals>
  258 + <goal>single</goal>
  259 + </goals>
  260 + </execution>
  261 + </executions>
  262 + </plugin>
  263 + </plugins>
  264 + </build>
  265 + <profiles>
  266 + <profile>
  267 + <id>npm-start</id>
  268 + <activation>
  269 + <property>
  270 + <name>npm-start</name>
  271 + </property>
  272 + </activation>
  273 + <build>
  274 + <plugins>
  275 + <plugin>
  276 + <groupId>com.github.eirslett</groupId>
  277 + <artifactId>frontend-maven-plugin</artifactId>
  278 + <version>1.0</version>
  279 + <configuration>
  280 + <installDirectory>target</installDirectory>
  281 + <workingDirectory>${basedir}</workingDirectory>
  282 + </configuration>
  283 + <executions>
  284 + <execution>
  285 + <id>npm start</id>
  286 + <goals>
  287 + <goal>npm</goal>
  288 + </goals>
  289 +
  290 + <configuration>
  291 + <arguments>start</arguments>
  292 + </configuration>
  293 + </execution>
  294 + </executions>
  295 + </plugin>
  296 + </plugins>
  297 + </build>
  298 + </profile>
  299 + </profiles>
  300 + <repositories>
  301 + <repository>
  302 + <id>jenkins</id>
  303 + <name>Jenkins Repository</name>
  304 + <url>http://repo.jenkins-ci.org/releases</url>
  305 + <snapshots>
  306 + <enabled>false</enabled>
  307 + </snapshots>
  308 + </repository>
  309 + </repositories>
  310 +</project>
... ...
  1 +/*
  2 + * Copyright © 2016-2018 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +var config = require('config'),
  17 + kafka = require('kafka-node'),
  18 + Consumer = kafka.Consumer,
  19 + Producer = kafka.Producer,
  20 + JsMessageConsumer = require('./api/jsMessageConsumer');
  21 +
  22 +var logger = require('./config/logger')('main');
  23 +
  24 +var kafkaBootstrapServers = config.get('kafka.bootstrap.servers');
  25 +var kafkaRequestTopic = config.get('kafka.request_topic');
  26 +
  27 +logger.info('Kafka Bootstrap Servers: %s', kafkaBootstrapServers);
  28 +logger.info('Kafka Requests Topic: %s', kafkaRequestTopic);
  29 +
  30 +var kafkaClient;
  31 +
  32 +(async() => {
  33 + try {
  34 + logger.info('Starting ThingsBoard JavaScript Executor Microservice...');
  35 +
  36 + kafkaClient = new kafka.KafkaClient({kafkaHost: kafkaBootstrapServers});
  37 +
  38 + var consumer = new Consumer(
  39 + kafkaClient,
  40 + [
  41 + { topic: kafkaRequestTopic, partition: 0 }
  42 + ],
  43 + {
  44 + autoCommit: true
  45 + }
  46 + );
  47 +
  48 + var producer = new Producer(kafkaClient);
  49 + producer.on('error', (err) => {
  50 + logger.error('Unexpected kafka producer error');
  51 + logger.error(err);
  52 + });
  53 +
  54 + producer.on('ready', () => {
  55 + consumer.on('message', (message) => {
  56 + JsMessageConsumer.onJsInvokeMessage(message, producer);
  57 + });
  58 + });
  59 +
  60 + logger.info('Started ThingsBoard JavaScript Executor Microservice.');
  61 + } catch (e) {
  62 + logger.error('Failed to start ThingsBoard JavaScript Executor Microservice: %s', e.message);
  63 + logger.error(e);
  64 + exit(-1);
  65 + }
  66 +})();
  67 +
  68 +process.on('exit', function () {
  69 + exit(0);
  70 +});
  71 +
  72 +function exit(status) {
  73 + logger.info('Exiting with status: %d ...', status);
  74 + if (kafkaClient) {
  75 + logger.info('Stopping Kafka Client...');
  76 + kafkaClient.close(() => {
  77 + logger.info('Kafka Client stopped.');
  78 + process.exit(status);
  79 + });
  80 + } else {
  81 + process.exit(status);
  82 + }
  83 +}
\ No newline at end of file
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2018 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
  19 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  20 + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
  21 + <id>windows</id>
  22 +
  23 + <formats>
  24 + <format>zip</format>
  25 + </formats>
  26 +
  27 + <!-- Workaround to create logs directory -->
  28 + <fileSets>
  29 + <fileSet>
  30 + <directory>${pkg.win.dist}</directory>
  31 + <outputDirectory>logs</outputDirectory>
  32 + <excludes>
  33 + <exclude>*/**</exclude>
  34 + </excludes>
  35 + </fileSet>
  36 + <fileSet>
  37 + <directory>${pkg.win.dist}/conf</directory>
  38 + <outputDirectory>conf</outputDirectory>
  39 + <lineEnding>windows</lineEnding>
  40 + </fileSet>
  41 + </fileSets>
  42 +
  43 + <files>
  44 + <file>
  45 + <source>${pkg.win.dist}/bin/${pkg.name}.exe</source>
  46 + <outputDirectory>bin</outputDirectory>
  47 + <destName>${pkg.name}.exe</destName>
  48 + </file>
  49 + <file>
  50 + <source>${pkg.win.dist}/service.exe</source>
  51 + <outputDirectory/>
  52 + <destName>${pkg.name}.exe</destName>
  53 + </file>
  54 + <file>
  55 + <source>${pkg.win.dist}/service.xml</source>
  56 + <outputDirectory/>
  57 + <destName>${pkg.name}.xml</destName>
  58 + <lineEnding>windows</lineEnding>
  59 + </file>
  60 + <file>
  61 + <source>${pkg.win.dist}/install.bat</source>
  62 + <outputDirectory/>
  63 + <lineEnding>windows</lineEnding>
  64 + </file>
  65 + <file>
  66 + <source>${pkg.win.dist}/uninstall.bat</source>
  67 + <outputDirectory/>
  68 + <lineEnding>windows</lineEnding>
  69 + </file>
  70 + </files>
  71 +</assembly>
... ...
  1 +pkg.logFolder=${pkg.unixLogFolder}
\ No newline at end of file
... ...
  1 +pkg.logFolder=${BASE}\\logs
  2 +pkg.winWrapperLogFolder=%BASE%\\logs
... ...
  1 +#!/bin/sh
  2 +
  3 +chown -R ${pkg.user}: ${pkg.logFolder}
  4 +chown -R ${pkg.user}: ${pkg.installFolder}
  5 +update-rc.d ${pkg.name} defaults
  6 +
... ...
  1 +#!/bin/sh
  2 +
  3 +update-rc.d -f ${pkg.name} remove
... ...
  1 +#!/bin/sh
  2 +
  3 +if ! getent group ${pkg.user} >/dev/null; then
  4 + addgroup --system ${pkg.user}
  5 +fi
  6 +
  7 +if ! getent passwd ${pkg.user} >/dev/null; then
  8 + adduser --quiet \
  9 + --system \
  10 + --ingroup ${pkg.user} \
  11 + --quiet \
  12 + --disabled-login \
  13 + --disabled-password \
  14 + --home ${pkg.installFolder} \
  15 + --no-create-home \
  16 + -gecos "Thingsboard application" \
  17 + ${pkg.user}
  18 +fi
... ...
  1 +#!/bin/sh
  2 +
  3 +if [ -e /var/run/${pkg.name}/${pkg.name}.pid ]; then
  4 + service ${pkg.name} stop
  5 +fi
... ...
  1 +#!/bin/sh
  2 +
  3 +chown -R ${pkg.user}: ${pkg.logFolder}
  4 +chown -R ${pkg.user}: ${pkg.installFolder}
  5 +
  6 +if [ $1 -eq 1 ] ; then
  7 + # Initial installation
  8 + systemctl --no-reload enable ${pkg.name}.service >/dev/null 2>&1 || :
  9 +fi
... ...
  1 +#!/bin/sh
  2 +
  3 +if [ $1 -ge 1 ] ; then
  4 + # Package upgrade, not uninstall
  5 + systemctl try-restart ${pkg.name}.service >/dev/null 2>&1 || :
  6 +fi
... ...
  1 +#!/bin/sh
  2 +
  3 +getent group ${pkg.user} >/dev/null || groupadd -r ${pkg.user}
  4 +getent passwd ${pkg.user} >/dev/null || \
  5 +useradd -d ${pkg.installFolder} -g ${pkg.user} -M -r ${pkg.user} -s /sbin/nologin \
  6 +-c "Thingsboard application"
... ...
  1 +#!/bin/sh
  2 +
  3 +if [ $1 -eq 0 ] ; then
  4 + # Package removal, not upgrade
  5 + systemctl --no-reload disable --now ${pkg.name}.service > /dev/null 2>&1 || :
  6 +fi
... ...
  1 +[Unit]
  2 +Description=${pkg.name}
  3 +After=syslog.target
  4 +
  5 +[Service]
  6 +User=${pkg.user}
  7 +ExecStart=${pkg.installFolder}/init/${pkg.name}
  8 +SuccessExitStatus=143
  9 +
  10 +[Install]
  11 +WantedBy=multi-user.target
... ...
  1 +#!/bin/bash
  2 +#
  3 +
  4 +
  5 +### BEGIN INIT INFO
  6 +# Provides: tb-js-executor
  7 +# Required-Start: $remote_fs $syslog $network
  8 +# Required-Stop: $remote_fs $syslog $network
  9 +# Default-Start: 2 3 4 5
  10 +# Default-Stop: 0 1 6
  11 +# Short-Description: ${project.name}
  12 +# Description: ${project.description}
  13 +# chkconfig: 2345 99 01
  14 +### END INIT INFO
  15 +
  16 +[[ -n "$DEBUG" ]] && set -x
  17 +
  18 +# Initialize variables that cannot be provided by a .conf file
  19 +WORKING_DIR="$(pwd)"
  20 +# shellcheck disable=SC2153
  21 +
  22 +mainfile=${pkg.installFolder}/bin/${pkg.name}
  23 +configfile=${pkg.name}.conf
  24 +
  25 +# Follow symlinks to find the real script and detect init.d script
  26 +cd "$(dirname "$0")" || exit 1
  27 +[[ -z "$initfile" ]] && initfile=$(pwd)/$(basename "$0")
  28 +while [[ -L "$initfile" ]]; do
  29 + [[ "$initfile" =~ init\.d ]] && init_script=$(basename "$initfile")
  30 + initfile=$(readlink "$initfile")
  31 + cd "$(dirname "$initfile")" || exit 1
  32 + initfile=$(pwd)/$(basename "$initfile")
  33 +done
  34 +initfolder="$( (cd "$(dirname "initfile")" && pwd -P) )"
  35 +cd "$WORKING_DIR" || exit 1
  36 +
  37 +# Initialize CONF_FOLDER location
  38 +[[ -z "$CONF_FOLDER" ]] && CONF_FOLDER="${pkg.installFolder}/conf"
  39 +
  40 +# shellcheck source=/dev/null
  41 +[[ -r "${CONF_FOLDER}/${configfile}" ]] && source "${CONF_FOLDER}/${configfile}"
  42 +
  43 +# Initialize PID/LOG locations if they weren't provided by the config file
  44 +[[ -z "$PID_FOLDER" ]] && PID_FOLDER="/var/run"
  45 +[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="${pkg.unixLogFolder}"
  46 +! [[ "$PID_FOLDER" == /* ]] && PID_FOLDER="$(dirname "$mainfile")"/"$PID_FOLDER"
  47 +! [[ "$LOG_FOLDER" == /* ]] && LOG_FOLDER="$(dirname "$mainfile")"/"$LOG_FOLDER"
  48 +! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp"
  49 +! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp"
  50 +
  51 +# Set up defaults
  52 +[[ -z "$MODE" ]] && MODE="auto" # modes are "auto", "service" or "run"
  53 +[[ -z "$USE_START_STOP_DAEMON" ]] && USE_START_STOP_DAEMON="true"
  54 +
  55 +# Create an identity for log/pid files
  56 +if [[ -z "$identity" ]]; then
  57 + if [[ -n "$init_script" ]]; then
  58 + identity="${init_script}"
  59 + else
  60 + identity=$(basename "${initfile%.*}")_${initfolder//\//}
  61 + fi
  62 +fi
  63 +
  64 +# Initialize log file name if not provided by the config file
  65 +[[ -z "$LOG_FILENAME" ]] && LOG_FILENAME="${identity}.log"
  66 +
  67 +# ANSI Colors
  68 +echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
  69 +echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
  70 +echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
  71 +
  72 +# Utility functions
  73 +checkPermissions() {
  74 + touch "$pid_file" &> /dev/null || { echoRed "Operation not permitted (cannot access pid file)"; return 4; }
  75 + touch "$log_file" &> /dev/null || { echoRed "Operation not permitted (cannot access log file)"; return 4; }
  76 +}
  77 +
  78 +isRunning() {
  79 + ps -p "$1" &> /dev/null
  80 +}
  81 +
  82 +await_file() {
  83 + end=$(date +%s)
  84 + let "end+=10"
  85 + while [[ ! -s "$1" ]]
  86 + do
  87 + now=$(date +%s)
  88 + if [[ $now -ge $end ]]; then
  89 + break
  90 + fi
  91 + sleep 1
  92 + done
  93 +}
  94 +
  95 +# Determine the script mode
  96 +action="run"
  97 +if [[ "$MODE" == "auto" && -n "$init_script" ]] || [[ "$MODE" == "service" ]]; then
  98 + action="$1"
  99 + shift
  100 +fi
  101 +
  102 +# Build the pid and log filenames
  103 +if [[ "$identity" == "$init_script" ]] || [[ "$identity" == "$APP_NAME" ]]; then
  104 + PID_FOLDER="$PID_FOLDER/${identity}"
  105 + pid_subfolder=$PID_FOLDER
  106 +fi
  107 +pid_file="$PID_FOLDER/${identity}.pid"
  108 +log_file="$LOG_FOLDER/$LOG_FILENAME"
  109 +
  110 +# Determine the user to run as if we are root
  111 +# shellcheck disable=SC2012
  112 +[[ $(id -u) == "0" ]] && run_user=$(ls -ld "$mainfile" | awk '{print $3}')
  113 +
  114 +arguments=($RUN_ARGS "$@")
  115 +
  116 +# Action functions
  117 +start() {
  118 + if [[ -f "$pid_file" ]]; then
  119 + pid=$(cat "$pid_file")
  120 + isRunning "$pid" && { echoYellow "Already running [$pid]"; return 0; }
  121 + fi
  122 + do_start "$@"
  123 +}
  124 +
  125 +do_start() {
  126 + working_dir=$(dirname "$mainfile")
  127 + pushd "$working_dir" > /dev/null
  128 + mkdir -p "$PID_FOLDER" &> /dev/null
  129 + if [[ -n "$run_user" ]]; then
  130 + checkPermissions || return $?
  131 + if [[ -z "$pid_subfolder" ]]; then
  132 + chown "$run_user" "$pid_subfolder"
  133 + fi
  134 + chown "$run_user" "$pid_file"
  135 + chown "$run_user" "$log_file"
  136 + if [ $USE_START_STOP_DAEMON = true ] && type start-stop-daemon > /dev/null 2>&1; then
  137 + start-stop-daemon --start --quiet \
  138 + --chuid "$run_user" \
  139 + --name "$identity" \
  140 + --make-pidfile --pidfile "$pid_file" \
  141 + --background --no-close \
  142 + --startas "$mainfile" \
  143 + --chdir "$working_dir" \
  144 + -- "${arguments[@]}" \
  145 + >> "$log_file" 2>&1
  146 + await_file "$pid_file"
  147 + else
  148 + su -s /bin/sh -c "$mainfile $(printf "\"%s\" " "${arguments[@]}") >> \"$log_file\" 2>&1 & echo \$!" "$run_user" > "$pid_file"
  149 + fi
  150 + pid=$(cat "$pid_file")
  151 + else
  152 + checkPermissions || return $?
  153 + "$mainfile" "${arguments[@]}" >> "$log_file" 2>&1 &
  154 + pid=$!
  155 + disown $pid
  156 + echo "$pid" > "$pid_file"
  157 + fi
  158 + [[ -z $pid ]] && { echoRed "Failed to start"; return 1; }
  159 + echoGreen "Started [$pid]"
  160 +}
  161 +
  162 +stop() {
  163 + working_dir=$(dirname "$mainfile")
  164 + pushd "$working_dir" > /dev/null
  165 + [[ -f $pid_file ]] || { echoYellow "Not running (pidfile not found)"; return 0; }
  166 + pid=$(cat "$pid_file")
  167 + isRunning "$pid" || { echoYellow "Not running (process ${pid}). Removing stale pid file."; rm -f "$pid_file"; return 0; }
  168 + do_stop "$pid" "$pid_file"
  169 +}
  170 +
  171 +do_stop() {
  172 + kill -2 "$1" &> /dev/null || { echoRed "Unable to kill process $1"; return 1; }
  173 + for i in $(seq 1 60); do
  174 + isRunning "$1" || { echoGreen "Stopped [$1]"; rm -f "$2"; return 0; }
  175 + [[ $i -eq 30 ]] && kill -9 "$1" &> /dev/null
  176 + sleep 1
  177 + done
  178 + echoRed "Unable to kill process $1";
  179 + return 1;
  180 +}
  181 +
  182 +restart() {
  183 + stop && start
  184 +}
  185 +
  186 +orce_reload() {
  187 + working_dir=$(dirname "$mainfile")
  188 + pushd "$working_dir" > /dev/null
  189 + [[ -f $pid_file ]] || { echoRed "Not running (pidfile not found)"; return 7; }
  190 + pid=$(cat "$pid_file")
  191 + rm -f "$pid_file"
  192 + isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 7; }
  193 + do_stop "$pid" "$pid_file"
  194 + do_start
  195 +}
  196 +
  197 +status() {
  198 + working_dir=$(dirname "$mainfile")
  199 + pushd "$working_dir" > /dev/null
  200 + [[ -f "$pid_file" ]] || { echoRed "Not running"; return 3; }
  201 + pid=$(cat "$pid_file")
  202 + isRunning "$pid" || { echoRed "Not running (process ${pid} not found)"; return 1; }
  203 + echoGreen "Running [$pid]"
  204 + return 0
  205 +}
  206 +
  207 +run() {
  208 + pushd "$(dirname "$mainfile")" > /dev/null
  209 + "$mainfile" "${arguments[@]}"
  210 + result=$?
  211 + popd > /dev/null
  212 + return "$result"
  213 +}
  214 +
  215 +# Call the appropriate action function
  216 +case "$action" in
  217 +start)
  218 + start "$@"; exit $?;;
  219 +stop)
  220 + stop "$@"; exit $?;;
  221 +restart)
  222 + restart "$@"; exit $?;;
  223 +force-reload)
  224 + force_reload "$@"; exit $?;;
  225 +status)
  226 + status "$@"; exit $?;;
  227 +run)
  228 + run "$@"; exit $?;;
  229 +*)
  230 + echo "Usage: $0 {start|stop|restart|force-reload|status|run}"; exit 1;
  231 +esac
  232 +
  233 +exit 0
... ...
  1 +@REM
  2 +@REM Copyright © 2016-2018 The Thingsboard Authors
  3 +@REM
  4 +@REM Licensed under the Apache License, Version 2.0 (the "License");
  5 +@REM you may not use this file except in compliance with the License.
  6 +@REM You may obtain a copy of the License at
  7 +@REM
  8 +@REM http://www.apache.org/licenses/LICENSE-2.0
  9 +@REM
  10 +@REM Unless required by applicable law or agreed to in writing, software
  11 +@REM distributed under the License is distributed on an "AS IS" BASIS,
  12 +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +@REM See the License for the specific language governing permissions and
  14 +@REM limitations under the License.
  15 +@REM
  16 +
  17 +@ECHO OFF
  18 +
  19 +setlocal ENABLEEXTENSIONS
  20 +
  21 +@ECHO Installing ${pkg.name} ...
  22 +
  23 +SET BASE=%~dp0
  24 +
  25 +%BASE%${pkg.name}.exe install
  26 +
  27 +@ECHO ${pkg.name} installed successfully!
  28 +
  29 +GOTO END
  30 +
  31 +:END
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2018 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<service>
  19 + <id>${pkg.name}</id>
  20 + <name>${project.name}</name>
  21 + <description>${project.description}</description>
  22 + <workingdirectory>%BASE%\bin</workingdirectory>
  23 + <logpath>${pkg.winWrapperLogFolder}</logpath>
  24 + <logmode>rotate</logmode>
  25 + <env name="NODE_CONFIG_DIR" value="%BASE%\conf" />
  26 + <env name="LOG_FOLDER" value="${pkg.winWrapperLogFolder}" />
  27 + <env name="NODE_ENV" value="production" />
  28 + <executable>%BASE%\bin\${pkg.name}.exe</executable>
  29 +</service>
... ...
  1 +@REM
  2 +@REM Copyright © 2016-2018 The Thingsboard Authors
  3 +@REM
  4 +@REM Licensed under the Apache License, Version 2.0 (the "License");
  5 +@REM you may not use this file except in compliance with the License.
  6 +@REM You may obtain a copy of the License at
  7 +@REM
  8 +@REM http://www.apache.org/licenses/LICENSE-2.0
  9 +@REM
  10 +@REM Unless required by applicable law or agreed to in writing, software
  11 +@REM distributed under the License is distributed on an "AS IS" BASIS,
  12 +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +@REM See the License for the specific language governing permissions and
  14 +@REM limitations under the License.
  15 +@REM
  16 +
  17 +@ECHO OFF
  18 +
  19 +@ECHO Stopping ${pkg.name} ...
  20 +net stop ${pkg.name}
  21 +
  22 +@ECHO Uninstalling ${pkg.name} ...
  23 +%~dp0${pkg.name}.exe uninstall
  24 +
  25 +@ECHO DONE.
\ No newline at end of file
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2018 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  20 + <modelVersion>4.0.0</modelVersion>
  21 + <parent>
  22 + <groupId>org.thingsboard</groupId>
  23 + <version>2.2.0-SNAPSHOT</version>
  24 + <artifactId>thingsboard</artifactId>
  25 + </parent>
  26 + <groupId>org.thingsboard</groupId>
  27 + <artifactId>msa</artifactId>
  28 + <packaging>pom</packaging>
  29 +
  30 + <name>ThingsBoard Microservices</name>
  31 + <url>https://thingsboard.io</url>
  32 +
  33 + <properties>
  34 + <main.dir>${basedir}/..</main.dir>
  35 + </properties>
  36 +
  37 + <modules>
  38 + <module>js-executor</module>
  39 + </modules>
  40 +
  41 +</project>
... ...
... ... @@ -93,6 +93,7 @@
93 93 <module>ui</module>
94 94 <module>tools</module>
95 95 <module>application</module>
  96 + <module>msa</module>
96 97 </modules>
97 98
98 99 <profiles>
... ...