Showing
32 changed files
with
1421 additions
and
2 deletions
... | ... | @@ -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 | ... | ... |
msa/docker/tb-web-ui.env
0 → 100644
msa/web-ui/.gitignore
0 → 100644
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 | ... | ... |
msa/web-ui/build.gradle
0 → 100644
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" | ... | ... |
msa/web-ui/config/default.yml
0 → 100644
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" | ... | ... |
msa/web-ui/config/logger.js
0 → 100644
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 | ... | ... |
msa/web-ui/config/tb-web-ui.conf
0 → 100644
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 | ... | ... |
msa/web-ui/docker/Dockerfile
0 → 100644
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"] | ... | ... |
msa/web-ui/docker/start-web-ui.sh
0 → 100755
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" | ... | ... |
msa/web-ui/install.js
0 → 100644
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 | +} | ... | ... |
msa/web-ui/package.json
0 → 100644
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 | +} | ... | ... |
msa/web-ui/pom.xml
0 → 100644
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> | ... | ... |
msa/web-ui/server.js
0 → 100644
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 | +} | ... | ... |
msa/web-ui/src/main/assembly/windows.xml
0 → 100644
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> | ... | ... |
msa/web-ui/src/main/filters/unix.properties
0 → 100644
1 | +pkg.logFolder=${pkg.unixLogFolder} | |
\ No newline at end of file | ... | ... |
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 | ... | ... |
msa/web-ui/src/main/scripts/init/tb-web-ui
0 → 100644
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 | ... | ... |