Commit 4bf57ebf20d83aa922f95aae80b5dba3e36aadfa

Authored by Igor Kulikov
1 parent 52f04308

ThingsBoard Web UI Microservice.

... ... @@ -29,7 +29,7 @@ services:
29 29 environment:
30 30 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
31 31 KAFKA_LISTENERS: INSIDE://:9093,OUTSIDE://:9092
32   - KAFKA_ADVERTISED_LISTENERS: INSIDE://:9093,OUTSIDE://${KAFKA_HOSTNAME}:9092
  32 + KAFKA_ADVERTISED_LISTENERS: INSIDE://:9093,OUTSIDE://${EXTERNAL_HOSTNAME}:9092
33 33 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
34 34 KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
35 35 KAFKA_CREATE_TOPICS: "${KAFKA_TOPICS}"
... ... @@ -44,3 +44,14 @@ services:
44 44 - tb-js-executor.env
45 45 depends_on:
46 46 - kafka
  47 + tb-web-ui:
  48 + image: "local-maven-build/tb-web-ui:latest"
  49 + ports:
  50 + - "8090:8090"
  51 + environment:
  52 + HTTP_BIND_ADDRESS: 0.0.0.0
  53 + HTTP_BIND_PORT: 8090
  54 + TB_HOST: ${EXTERNAL_HOSTNAME}
  55 + TB_PORT: 8080
  56 + env_file:
  57 + - tb-web-ui.env
... ...
  1 +
  2 +HTTP_BIND_ADDRESS=0.0.0.0
  3 +HTTP_BIND_PORT=8090
  4 +TB_HOST=localhost
  5 +TB_PORT=8080
  6 +LOGGER_LEVEL=debug
  7 +LOG_FOLDER=logs
  8 +LOGGER_FILENAME=tb-web-ui-%DATE%.log
  9 +DOCKER_MODE=true
\ No newline at end of file
... ...
... ... @@ -36,6 +36,7 @@
36 36
37 37 <modules>
38 38 <module>js-executor</module>
  39 + <module>web-ui</module>
39 40 </modules>
40 41
41 42 </project>
... ...
  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 +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 + // Copy web files
  69 + from("target/package/linux/web") {
  70 + into "web"
  71 + }
  72 +
  73 +}
  74 +
  75 +// Configure our RPM build task
  76 +buildRpm {
  77 +
  78 + arch = X86_64
  79 +
  80 + version = projectVersion.replace('-', '')
  81 + archiveName = "${pkgName}.rpm"
  82 +
  83 + preInstall file("${buildDir}/control/rpm/preinst")
  84 + postInstall file("${buildDir}/control/rpm/postinst")
  85 + preUninstall file("${buildDir}/control/rpm/prerm")
  86 + postUninstall file("${buildDir}/control/rpm/postrm")
  87 +
  88 + user pkgUser
  89 + permissionGroup pkgUser
  90 +
  91 + // Copy the system unit files
  92 + from("${buildDir}/control/${pkgName}.service") {
  93 + addParentDirs = false
  94 + fileMode 0644
  95 + into "/usr/lib/systemd/system"
  96 + }
  97 +
  98 + directory(pkgLogFolder, 0755)
  99 + link("/etc/${pkgName}/conf", "${pkgInstallFolder}/conf")
  100 +}
  101 +
  102 +// Same as the buildRpm task
  103 +buildDeb {
  104 +
  105 + arch = "amd64"
  106 +
  107 + archiveName = "${pkgName}.deb"
  108 +
  109 + configurationFile("${pkgInstallFolder}/conf/${pkgName}.conf")
  110 + configurationFile("${pkgInstallFolder}/conf/custom-environment-variables.yml")
  111 + configurationFile("${pkgInstallFolder}/conf/default.yml")
  112 + configurationFile("${pkgInstallFolder}/conf/logger.js")
  113 +
  114 + preInstall file("${buildDir}/control/deb/preinst")
  115 + postInstall file("${buildDir}/control/deb/postinst")
  116 + preUninstall file("${buildDir}/control/deb/prerm")
  117 + postUninstall file("${buildDir}/control/deb/postrm")
  118 +
  119 + user pkgUser
  120 + permissionGroup pkgUser
  121 +
  122 + directory(pkgLogFolder, 0755)
  123 + link("/etc/init.d/${pkgName}", "${pkgInstallFolder}/init/${pkgName}")
  124 + link("/etc/${pkgName}/conf", "${pkgInstallFolder}/conf")
  125 +}
... ...
  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 +server:
  18 + # Server bind address
  19 + address: "HTTP_BIND_ADDRESS"
  20 + # Server bind port
  21 + port: "HTTP_BIND_PORT"
  22 +thingsboard:
  23 + # ThingsBoard node host
  24 + host: "TB_HOST"
  25 + # ThingsBoard node port
  26 + port: "TB_PORT"
  27 +logger:
  28 + level: "LOGGER_LEVEL"
  29 + path: "LOG_FOLDER"
  30 + 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 +server:
  18 + # Server bind address
  19 + address: "0.0.0.0"
  20 + # Server bind port
  21 + port: "8090"
  22 +thingsboard:
  23 + # ThingsBoard node host
  24 + host: "localhost"
  25 + # ThingsBoard node port
  26 + port: "8080"
  27 +logger:
  28 + level: "info"
  29 + path: "logs"
  30 + filename: "tb-web-ui-%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' || process.env.DOCKER_MODE === 'true') {
  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
  20 +export WEB_FOLDER=${pkg.installFolder}/web
\ 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 +FROM debian:stretch
  18 +
  19 +COPY start-web-ui.sh ${pkg.name}.deb /tmp/
  20 +
  21 +RUN chmod a+x /tmp/*.sh \
  22 + && mv /tmp/start-web-ui.sh /usr/bin
  23 +
  24 +RUN dpkg -i /tmp/${pkg.name}.deb
  25 +
  26 +CMD ["start-web-ui.sh"]
... ...
  1 +#!/bin/bash
  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 +
  19 +echo "Starting '${project.name}' ..."
  20 +
  21 +CONF_FOLDER="${pkg.installFolder}/conf"
  22 +
  23 +mainfile=${pkg.installFolder}/bin/${pkg.name}
  24 +configfile=${pkg.name}.conf
  25 +identity=${pkg.name}
  26 +
  27 +source "${CONF_FOLDER}/${configfile}"
  28 +
  29 +su -s /bin/sh -c "$mainfile"
... ...
  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-web-ui-linux'),
  25 + path.join(targetPackageDir('linux'), 'bin', 'tb-web-ui'),
  26 + {overwrite: true});
  27 + await fse.move(path.join(projectRoot(), 'target', 'thingsboard-web-ui-win.exe'),
  28 + path.join(targetPackageDir('windows'), 'bin', 'tb-web-ui.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-web-ui",
  3 + "private": true,
  4 + "version": "2.2.0",
  5 + "description": "ThingsBoard Web UI 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": "WEB_FOLDER=./target/web nodemon server.js",
  12 + "start-prod": "NODE_ENV=production nodemon server.js"
  13 + },
  14 + "dependencies": {
  15 + "config": "^1.30.0",
  16 + "connect-history-api-fallback": "^1.5.0",
  17 + "express": "^4.16.3",
  18 + "http": "0.0.0",
  19 + "http-proxy": "^1.17.0",
  20 + "js-yaml": "^3.12.0",
  21 + "winston": "^3.0.0",
  22 + "winston-daily-rotate-file": "^3.2.1"
  23 + },
  24 + "engine": "node >= 5.9.0",
  25 + "nyc": {
  26 + "exclude": [
  27 + "test",
  28 + "__tests__",
  29 + "node_modules",
  30 + "target"
  31 + ]
  32 + },
  33 + "devDependencies": {
  34 + "fs-extra": "^6.0.1",
  35 + "nodemon": "^1.17.5",
  36 + "pkg": "^4.3.3"
  37 + }
  38 +}
... ...
  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>web-ui</artifactId>
  28 + <packaging>pom</packaging>
  29 +
  30 + <name>ThingsBoard Web UI Microservice</name>
  31 + <url>https://thingsboard.io</url>
  32 + <description>Service for hosting ThingsBoard Web UI</description>
  33 +
  34 + <properties>
  35 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  36 + <main.dir>${basedir}/../..</main.dir>
  37 + <pkg.name>tb-web-ui</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 + <dockerfile.skip>true</dockerfile.skip>
  44 + </properties>
  45 +
  46 + <dependencies>
  47 + <dependency>
  48 + <groupId>org.thingsboard</groupId>
  49 + <artifactId>ui</artifactId>
  50 + <version>${project.version}</version>
  51 + <type>jar</type>
  52 + <scope>provided</scope>
  53 + </dependency>
  54 + <dependency>
  55 + <groupId>com.sun.winsw</groupId>
  56 + <artifactId>winsw</artifactId>
  57 + <classifier>bin</classifier>
  58 + <type>exe</type>
  59 + <scope>provided</scope>
  60 + </dependency>
  61 + </dependencies>
  62 +
  63 + <build>
  64 + <plugins>
  65 + <plugin>
  66 + <groupId>com.github.eirslett</groupId>
  67 + <artifactId>frontend-maven-plugin</artifactId>
  68 + <version>1.0</version>
  69 + <configuration>
  70 + <installDirectory>target</installDirectory>
  71 + <workingDirectory>${basedir}</workingDirectory>
  72 + </configuration>
  73 + <executions>
  74 + <execution>
  75 + <id>install node and npm</id>
  76 + <goals>
  77 + <goal>install-node-and-npm</goal>
  78 + </goals>
  79 + <configuration>
  80 + <nodeVersion>v8.11.3</nodeVersion>
  81 + <npmVersion>5.6.0</npmVersion>
  82 + </configuration>
  83 + </execution>
  84 + <execution>
  85 + <id>npm install</id>
  86 + <goals>
  87 + <goal>npm</goal>
  88 + </goals>
  89 + <configuration>
  90 + <arguments>install</arguments>
  91 + </configuration>
  92 + </execution>
  93 + </executions>
  94 + </plugin>
  95 + <plugin>
  96 + <groupId>org.apache.maven.plugins</groupId>
  97 + <artifactId>maven-dependency-plugin</artifactId>
  98 + <executions>
  99 + <execution>
  100 + <id>extract-web-ui</id>
  101 + <goals>
  102 + <goal>unpack</goal>
  103 + </goals>
  104 + <configuration>
  105 + <artifactItems>
  106 + <artifactItem>
  107 + <groupId>org.thingsboard</groupId>
  108 + <artifactId>ui</artifactId>
  109 + <type>jar</type>
  110 + <overWrite>false</overWrite>
  111 + <outputDirectory>${project.build.directory}/web</outputDirectory>
  112 + </artifactItem>
  113 + </artifactItems>
  114 + </configuration>
  115 + </execution>
  116 + <execution>
  117 + <id>copy-winsw-service</id>
  118 + <phase>package</phase>
  119 + <goals>
  120 + <goal>copy</goal>
  121 + </goals>
  122 + <configuration>
  123 + <artifactItems>
  124 + <artifactItem>
  125 + <groupId>com.sun.winsw</groupId>
  126 + <artifactId>winsw</artifactId>
  127 + <classifier>bin</classifier>
  128 + <type>exe</type>
  129 + <destFileName>service.exe</destFileName>
  130 + </artifactItem>
  131 + </artifactItems>
  132 + <outputDirectory>${pkg.win.dist}</outputDirectory>
  133 + </configuration>
  134 + </execution>
  135 + </executions>
  136 + </plugin>
  137 + <plugin>
  138 + <groupId>org.apache.maven.plugins</groupId>
  139 + <artifactId>maven-resources-plugin</artifactId>
  140 + <executions>
  141 + <execution>
  142 + <id>copy-linux-conf</id>
  143 + <phase>process-resources</phase>
  144 + <goals>
  145 + <goal>copy-resources</goal>
  146 + </goals>
  147 + <configuration>
  148 + <outputDirectory>${pkg.linux.dist}/conf</outputDirectory>
  149 + <resources>
  150 + <resource>
  151 + <directory>config</directory>
  152 + <filtering>true</filtering>
  153 + </resource>
  154 + </resources>
  155 + <filters>
  156 + <filter>src/main/filters/unix.properties</filter>
  157 + </filters>
  158 + </configuration>
  159 + </execution>
  160 + <execution>
  161 + <id>copy-linux-init</id>
  162 + <phase>process-resources</phase>
  163 + <goals>
  164 + <goal>copy-resources</goal>
  165 + </goals>
  166 + <configuration>
  167 + <outputDirectory>${pkg.linux.dist}/init</outputDirectory>
  168 + <resources>
  169 + <resource>
  170 + <directory>src/main/scripts/init</directory>
  171 + <filtering>true</filtering>
  172 + </resource>
  173 + </resources>
  174 + <filters>
  175 + <filter>src/main/filters/unix.properties</filter>
  176 + </filters>
  177 + </configuration>
  178 + </execution>
  179 + <execution>
  180 + <id>copy-win-conf</id>
  181 + <phase>process-resources</phase>
  182 + <goals>
  183 + <goal>copy-resources</goal>
  184 + </goals>
  185 + <configuration>
  186 + <outputDirectory>${pkg.win.dist}/conf</outputDirectory>
  187 + <resources>
  188 + <resource>
  189 + <directory>config</directory>
  190 + <excludes>
  191 + <exclude>tb-web-ui.conf</exclude>
  192 + </excludes>
  193 + <filtering>true</filtering>
  194 + </resource>
  195 + </resources>
  196 + <filters>
  197 + <filter>src/main/filters/windows.properties</filter>
  198 + </filters>
  199 + </configuration>
  200 + </execution>
  201 + <execution>
  202 + <id>copy-control</id>
  203 + <phase>process-resources</phase>
  204 + <goals>
  205 + <goal>copy-resources</goal>
  206 + </goals>
  207 + <configuration>
  208 + <outputDirectory>${project.build.directory}/control</outputDirectory>
  209 + <resources>
  210 + <resource>
  211 + <directory>src/main/scripts/control</directory>
  212 + <filtering>true</filtering>
  213 + </resource>
  214 + </resources>
  215 + <filters>
  216 + <filter>src/main/filters/unix.properties</filter>
  217 + </filters>
  218 + </configuration>
  219 + </execution>
  220 + <execution>
  221 + <id>copy-windows-control</id>
  222 + <phase>process-resources</phase>
  223 + <goals>
  224 + <goal>copy-resources</goal>
  225 + </goals>
  226 + <configuration>
  227 + <outputDirectory>${pkg.win.dist}</outputDirectory>
  228 + <resources>
  229 + <resource>
  230 + <directory>src/main/scripts/windows</directory>
  231 + <filtering>true</filtering>
  232 + </resource>
  233 + </resources>
  234 + <filters>
  235 + <filter>src/main/filters/windows.properties</filter>
  236 + </filters>
  237 + </configuration>
  238 + </execution>
  239 + <execution>
  240 + <id>copy-docker-config</id>
  241 + <phase>process-resources</phase>
  242 + <goals>
  243 + <goal>copy-resources</goal>
  244 + </goals>
  245 + <configuration>
  246 + <outputDirectory>${project.build.directory}</outputDirectory>
  247 + <resources>
  248 + <resource>
  249 + <directory>docker</directory>
  250 + <filtering>true</filtering>
  251 + </resource>
  252 + </resources>
  253 + </configuration>
  254 + </execution>
  255 + </executions>
  256 + </plugin>
  257 + <plugin>
  258 + <groupId>org.fortasoft</groupId>
  259 + <artifactId>gradle-maven-plugin</artifactId>
  260 + <configuration>
  261 + <tasks>
  262 + <task>build</task>
  263 + <task>buildDeb</task>
  264 + <task>buildRpm</task>
  265 + </tasks>
  266 + <args>
  267 + <arg>-PprojectBuildDir=${project.build.directory}</arg>
  268 + <arg>-PprojectVersion=${project.version}</arg>
  269 + <arg>-PpkgName=${pkg.name}</arg>
  270 + <arg>-PpkgUser=${pkg.user}</arg>
  271 + <arg>-PpkgInstallFolder=${pkg.installFolder}</arg>
  272 + <arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg>
  273 + </args>
  274 + </configuration>
  275 + <executions>
  276 + <execution>
  277 + <phase>package</phase>
  278 + <goals>
  279 + <goal>invoke</goal>
  280 + </goals>
  281 + </execution>
  282 + </executions>
  283 + </plugin>
  284 + <plugin>
  285 + <groupId>org.apache.maven.plugins</groupId>
  286 + <artifactId>maven-assembly-plugin</artifactId>
  287 + <version>3.0.0</version>
  288 + <configuration>
  289 + <finalName>${pkg.name}</finalName>
  290 + <descriptors>
  291 + <descriptor>src/main/assembly/windows.xml</descriptor>
  292 + </descriptors>
  293 + </configuration>
  294 + <executions>
  295 + <execution>
  296 + <id>assembly</id>
  297 + <phase>package</phase>
  298 + <goals>
  299 + <goal>single</goal>
  300 + </goals>
  301 + </execution>
  302 + </executions>
  303 + </plugin>
  304 + <plugin>
  305 + <groupId>com.spotify</groupId>
  306 + <artifactId>dockerfile-maven-plugin</artifactId>
  307 + <version>1.4.4</version>
  308 + <executions>
  309 + <execution>
  310 + <id>build-docker-image</id>
  311 + <phase>pre-integration-test</phase>
  312 + <goals>
  313 + <goal>build</goal>
  314 + </goals>
  315 + </execution>
  316 + </executions>
  317 + <configuration>
  318 + <skip>${dockerfile.skip}</skip>
  319 + <repository>local-maven-build/${pkg.name}</repository>
  320 + <verbose>true</verbose>
  321 + <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled>
  322 + <contextDirectory>${project.build.directory}</contextDirectory>
  323 + </configuration>
  324 + </plugin>
  325 + </plugins>
  326 + </build>
  327 + <profiles>
  328 + <profile>
  329 + <id>npm-start</id>
  330 + <activation>
  331 + <property>
  332 + <name>npm-start</name>
  333 + </property>
  334 + </activation>
  335 + <build>
  336 + <plugins>
  337 + <plugin>
  338 + <groupId>com.github.eirslett</groupId>
  339 + <artifactId>frontend-maven-plugin</artifactId>
  340 + <version>1.0</version>
  341 + <configuration>
  342 + <installDirectory>target</installDirectory>
  343 + <workingDirectory>${basedir}</workingDirectory>
  344 + </configuration>
  345 + <executions>
  346 + <execution>
  347 + <id>npm start</id>
  348 + <goals>
  349 + <goal>npm</goal>
  350 + </goals>
  351 +
  352 + <configuration>
  353 + <arguments>start</arguments>
  354 + </configuration>
  355 + </execution>
  356 + </executions>
  357 + </plugin>
  358 + </plugins>
  359 + </build>
  360 + </profile>
  361 + </profiles>
  362 + <repositories>
  363 + <repository>
  364 + <id>jenkins</id>
  365 + <name>Jenkins Repository</name>
  366 + <url>http://repo.jenkins-ci.org/releases</url>
  367 + <snapshots>
  368 + <enabled>false</enabled>
  369 + </snapshots>
  370 + </repository>
  371 + </repositories>
  372 +</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 +
  17 +const config = require('config'),
  18 + logger = require('./config/logger')('main'),
  19 + express = require('express'),
  20 + http = require('http'),
  21 + httpProxy = require('http-proxy'),
  22 + path = require('path'),
  23 + historyApiFallback = require("connect-history-api-fallback");
  24 +
  25 +var server;
  26 +
  27 +(async() => {
  28 + try {
  29 + logger.info('Starting ThingsBoard Web UI Microservice...');
  30 +
  31 + const bindAddress = config.get('server.address');
  32 + const bindPort = config.get('server.port');
  33 +
  34 + const thingsboardHost = config.get('thingsboard.host');
  35 + const thingsboardPort = config.get('thingsboard.port');
  36 +
  37 + logger.info('Bind address: %s', bindAddress);
  38 + logger.info('Bind port: %s', bindPort);
  39 + logger.info('ThingsBoard host: %s', thingsboardHost);
  40 + logger.info('ThingsBoard port: %s', thingsboardPort);
  41 +
  42 + var webDir = path.join(__dirname, 'web');
  43 +
  44 + if (typeof process.env.WEB_FOLDER === 'string') {
  45 + webDir = path.resolve(process.env.WEB_FOLDER);
  46 + }
  47 + logger.info('Web folder: %s', webDir);
  48 +
  49 + const app = express();
  50 + server = http.createServer(app);
  51 +
  52 + const apiProxy = httpProxy.createProxyServer({
  53 + target: {
  54 + host: thingsboardHost,
  55 + port: thingsboardPort
  56 + }
  57 + });
  58 +
  59 + apiProxy.on('error', function (err, req, res) {
  60 + logger.warn('API proxy error: %s', err.message);
  61 + res.writeHead(500);
  62 + if (err.code && err.code === 'ECONNREFUSED') {
  63 + res.end('Unable to connect to ThingsBoard server.');
  64 + } else {
  65 + res.end('Thingsboard server connection error: ' + err.code ? err.code : '');
  66 + }
  67 + });
  68 +
  69 + const root = path.join(webDir, 'public');
  70 +
  71 + const staticDir = path.join(root, 'static');
  72 +
  73 + app.all('/api/*', (req, res) => {
  74 + logger.info(req.method + ' ' + req.originalUrl);
  75 + apiProxy.web(req, res);
  76 + });
  77 +
  78 + app.all('/static/rulenode/*', (req, res) => {
  79 + apiProxy.web(req, res);
  80 + });
  81 +
  82 + app.use(historyApiFallback());
  83 +
  84 + app.use('/static', express.static(staticDir));
  85 +
  86 + app.get('*', (req, res) => {
  87 + apiProxy.web(req, res);
  88 + });
  89 +
  90 + server.on('upgrade', (req, socket, head) => {
  91 + apiProxy.ws(req, socket, head);
  92 + });
  93 +
  94 + server.listen(bindPort, bindAddress, (error) => {
  95 + if (error) {
  96 + logger.error('Failed to start ThingsBoard Web UI Microservice: %s', e.message);
  97 + logger.error(error.stack);
  98 + exit(-1);
  99 + } else {
  100 + logger.info('==> 🌎 Listening on port %s.', bindPort);
  101 + logger.info('Started ThingsBoard Web UI Microservice.');
  102 + }
  103 + });
  104 +
  105 + } catch (e) {
  106 + logger.error('Failed to start ThingsBoard Web UI Microservice: %s', e.message);
  107 + logger.error(e.stack);
  108 + exit(-1);
  109 + }
  110 +})();
  111 +
  112 +process.on('exit', function () {
  113 + exit(0);
  114 +});
  115 +
  116 +function exit(status) {
  117 + logger.info('Exiting with status: %d ...', status);
  118 + if (server) {
  119 + logger.info('Stopping HTTP Server...');
  120 + var _server = server;
  121 + server = null;
  122 + _server.close(() => {
  123 + logger.info('HTTP Server stopped.');
  124 + process.exit(status);
  125 + });
  126 + } else {
  127 + process.exit(status);
  128 + }
  129 +}
... ...
  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 + <fileSet>
  42 + <directory>${project.build.directory}/web</directory>
  43 + <outputDirectory>web</outputDirectory>
  44 + </fileSet>
  45 + </fileSets>
  46 +
  47 + <files>
  48 + <file>
  49 + <source>${pkg.win.dist}/bin/${pkg.name}.exe</source>
  50 + <outputDirectory>bin</outputDirectory>
  51 + <destName>${pkg.name}.exe</destName>
  52 + </file>
  53 + <file>
  54 + <source>${pkg.win.dist}/service.exe</source>
  55 + <outputDirectory/>
  56 + <destName>${pkg.name}.exe</destName>
  57 + </file>
  58 + <file>
  59 + <source>${pkg.win.dist}/service.xml</source>
  60 + <outputDirectory/>
  61 + <destName>${pkg.name}.xml</destName>
  62 + <lineEnding>windows</lineEnding>
  63 + </file>
  64 + <file>
  65 + <source>${pkg.win.dist}/install.bat</source>
  66 + <outputDirectory/>
  67 + <lineEnding>windows</lineEnding>
  68 + </file>
  69 + <file>
  70 + <source>${pkg.win.dist}/uninstall.bat</source>
  71 + <outputDirectory/>
  72 + <lineEnding>windows</lineEnding>
  73 + </file>
  74 + </files>
  75 +</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-web-ui
  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 + <env name="WEB_FOLDER" value="%BASE%\web" />
  29 + <executable>%BASE%\bin\${pkg.name}.exe</executable>
  30 +</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
... ...
... ... @@ -2,7 +2,7 @@
2 2 "name": "thingsboard",
3 3 "private": true,
4 4 "version": "2.2.0",
5   - "description": "Thingsboard UI",
  5 + "description": "ThingsBoard UI",
6 6 "licenses": [
7 7 {
8 8 "type": "Apache-2.0",
... ...