From 4f2d453729b581bc1274dfd0cba68c97b59b5a15 Mon Sep 17 00:00:00 2001 From: viktor Date: Tue, 26 May 2020 14:53:56 +0300 Subject: [PATCH 01/13] Added TB_SERVICE_TYPE property --- k8s/thingsboard.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/k8s/thingsboard.yml b/k8s/thingsboard.yml index d1f598b6d3..11c2525129 100644 --- a/k8s/thingsboard.yml +++ b/k8s/thingsboard.yml @@ -90,6 +90,8 @@ spec: fieldPath: metadata.name - name: TB_SERVICE_TYPE value: "monolith" + - name: TB_QUEUE_TYPE + value: "kafka" - name: ZOOKEEPER_ENABLED value: "true" - name: ZOOKEEPER_URL From 8cb83a1904ce735fa02f1ec590d497f440401cc9 Mon Sep 17 00:00:00 2001 From: viktor Date: Tue, 26 May 2020 16:04:30 +0300 Subject: [PATCH 02/13] Fixed REMOTE_JS_EVAL_REQUEST_TOPIC env var --- k8s/thingsboard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/thingsboard.yml b/k8s/thingsboard.yml index 11c2525129..227d2d5952 100644 --- a/k8s/thingsboard.yml +++ b/k8s/thingsboard.yml @@ -35,7 +35,7 @@ spec: image: thingsboard/tb-js-executor:latest env: - name: REMOTE_JS_EVAL_REQUEST_TOPIC - value: "js.eval.requests" + value: "js_eval.requests" - name: TB_KAFKA_SERVERS value: "tb-kafka:9092" - name: LOGGER_LEVEL From 13a08a94cd85b95b97ac6d0eb40ab982865ff030 Mon Sep 17 00:00:00 2001 From: viktor Date: Tue, 26 May 2020 16:05:32 +0300 Subject: [PATCH 03/13] Replaces TB_SERVICE_TYPE with TB_QUEUE_TYPE for transport services --- k8s/thingsboard.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/k8s/thingsboard.yml b/k8s/thingsboard.yml index 227d2d5952..67a4cdd52e 100644 --- a/k8s/thingsboard.yml +++ b/k8s/thingsboard.yml @@ -175,8 +175,8 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - - name: TB_SERVICE_TYPE - value: "monolith" + - name: TB_QUEUE_TYPE + value: "kafka" - name: MQTT_BIND_ADDRESS value: "0.0.0.0" - name: MQTT_BIND_PORT @@ -248,8 +248,8 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - - name: TB_SERVICE_TYPE - value: "monolith" + - name: TB_QUEUE_TYPE + value: "kafka" - name: HTTP_BIND_ADDRESS value: "0.0.0.0" - name: HTTP_BIND_PORT @@ -321,8 +321,8 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - - name: TB_SERVICE_TYPE - value: "monolith" + - name: TB_QUEUE_TYPE + value: "kafka" - name: COAP_BIND_ADDRESS value: "0.0.0.0" - name: COAP_BIND_PORT From 9bf243dc0440af33a4505311c241e4005c280c44 Mon Sep 17 00:00:00 2001 From: viktor Date: Tue, 26 May 2020 16:25:04 +0300 Subject: [PATCH 04/13] Changed postgres image version to 12 --- k8s/postgres.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/postgres.yml b/k8s/postgres.yml index 08c7fe8d66..1ec7466408 100644 --- a/k8s/postgres.yml +++ b/k8s/postgres.yml @@ -51,7 +51,7 @@ spec: containers: - name: postgres imagePullPolicy: Always - image: postgres:10 + image: postgres:12 ports: - containerPort: 5432 name: postgres From 18193a697ed684bde46efa4d6b890a9914e26b33 Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 15:20:30 +0300 Subject: [PATCH 05/13] Refactored k8s configs (made 'basic' and 'high-availability' deployment modes) --- k8s/.env | 5 +- k8s/README.md | 11 +- k8s/basic/tb-node-cache-configmap.yml | 26 +++ k8s/basic/thirdparty.yml | 181 ++++++++++++++++++ k8s/{ => common}/cassandra.yml | 0 k8s/{ => common}/database-setup.yml | 0 k8s/{ => common}/postgres.yml | 0 .../tb-coap-transport-configmap.yml | 0 .../tb-http-transport-configmap.yml | 0 .../tb-mqtt-transport-configmap.yml | 0 k8s/{ => common}/tb-namespace.yml | 0 .../tb-node-cassandra-configmap.yml | 0 k8s/{ => common}/tb-node-configmap.yml | 0 .../tb-node-postgres-configmap.yml | 0 k8s/common/tb-node.yml | 98 ++++++++++ k8s/{ => common}/thingsboard.yml | 93 +-------- .../tb-node-cache-configmap.yml | 27 +++ k8s/{ => high-availability}/thirdparty.yml | 2 +- k8s/k8s-delete-resources.sh | 7 +- k8s/k8s-delete-thirdparty.sh | 4 +- k8s/k8s-deploy-resources.sh | 16 +- k8s/k8s-deploy-thirdparty.sh | 7 +- k8s/k8s-install-tb.sh | 25 ++- 23 files changed, 390 insertions(+), 112 deletions(-) create mode 100644 k8s/basic/tb-node-cache-configmap.yml create mode 100644 k8s/basic/thirdparty.yml rename k8s/{ => common}/cassandra.yml (100%) rename k8s/{ => common}/database-setup.yml (100%) rename k8s/{ => common}/postgres.yml (100%) rename k8s/{ => common}/tb-coap-transport-configmap.yml (100%) rename k8s/{ => common}/tb-http-transport-configmap.yml (100%) rename k8s/{ => common}/tb-mqtt-transport-configmap.yml (100%) rename k8s/{ => common}/tb-namespace.yml (100%) rename k8s/{ => common}/tb-node-cassandra-configmap.yml (100%) rename k8s/{ => common}/tb-node-configmap.yml (100%) rename k8s/{ => common}/tb-node-postgres-configmap.yml (100%) create mode 100644 k8s/common/tb-node.yml rename k8s/{ => common}/thingsboard.yml (80%) create mode 100644 k8s/high-availability/tb-node-cache-configmap.yml rename k8s/{ => high-availability}/thirdparty.yml (98%) diff --git a/k8s/.env b/k8s/.env index e50e57d9b8..5490250d8d 100644 --- a/k8s/.env +++ b/k8s/.env @@ -1,5 +1,8 @@ +# Can be either basic (with single instance of Zookeeper, Kafka and Redis) or high-availability (with Zookeeper, Kafka and Redis in cluster modes). +# According to the deployment type corresponding kubernetes resources will be deployed (see content of the directories ./basic and ./high-availability for details). +DEPLOYMENT_TYPE=basic # Database used by ThingsBoard, can be either postgres (PostgreSQL) or cassandra (Cassandra). # According to the database type corresponding kubernetes resources will be deployed (see postgres.yml, cassandra.yml for details). +DATABASE=cassandra -DATABASE=postgres diff --git a/k8s/README.md b/k8s/README.md index 6e888352dc..90fdea6afb 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -20,7 +20,7 @@ $ minikube addons enable ingress ## Installation -Before performing initial installation you can configure the type of database to be used with ThingsBoard. +Before performing initial installation you can configure the type of database to be used with ThingsBoard and the type of deployment. In order to set database type change the value of `DATABASE` variable in `.env` file to one of the following: - `postgres` - use PostgreSQL database; @@ -28,6 +28,13 @@ In order to set database type change the value of `DATABASE` variable in `.env` **NOTE**: According to the database type corresponding kubernetes resources will be deployed (see `postgres.yml`, `cassandra.yml` for details). +In order to set deployment type change the value of `DEPLOYMENT_TYPE` variable in `.env` file to one of the following: + +- `basic` - start up with single instance of Zookeeper, Kafka and Redis; +- `cassandra` - start up with Zookeeper, Kafka and Redis in cluster modes; + +**NOTE**: According to the deployment type corresponding kubernetes resources will be deployed (see content of the directories `./basic` and `./high-availability` for details). + Execute the following command to run installation: ` @@ -52,7 +59,7 @@ Get list of the running tb-redis pods and verify that all of them are in running $ kubectl get pods -l app=tb-redis ` -Execute the following command to create redis cluster: +If you are running ThingsBoard in `high-availability` `DEPLOYMENT_TYPE` execute the following command to create redis cluster: ` $ kubectl exec -it tb-redis-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=tb-redis -o jsonpath='{range.items[*]}{.status.podIP}:6379 ') diff --git a/k8s/basic/tb-node-cache-configmap.yml b/k8s/basic/tb-node-cache-configmap.yml new file mode 100644 index 0000000000..707247cd66 --- /dev/null +++ b/k8s/basic/tb-node-cache-configmap.yml @@ -0,0 +1,26 @@ +# +# Copyright © 2016-2020 The Thingsboard Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apiVersion: v1 +kind: ConfigMap +metadata: + name: tb-node-cache-config + namespace: thingsboard + labels: + name: tb-node-cache-config +data: + CACHE_TYPE: redis + REDIS_HOST: tb-redis \ No newline at end of file diff --git a/k8s/basic/thirdparty.yml b/k8s/basic/thirdparty.yml new file mode 100644 index 0000000000..62818a1fb1 --- /dev/null +++ b/k8s/basic/thirdparty.yml @@ -0,0 +1,181 @@ +# +# Copyright © 2016-2020 The Thingsboard Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: zookeeper + namespace: thingsboard +spec: + selector: + matchLabels: + app: zookeeper + template: + metadata: + labels: + app: zookeeper + spec: + containers: + - name: server + imagePullPolicy: Always + image: zookeeper:3.5 + ports: + - containerPort: 2181 + readinessProbe: + periodSeconds: 5 + tcpSocket: + port: 2181 + livenessProbe: + initialDelaySeconds: 15 + periodSeconds: 5 + tcpSocket: + port: 2181 + env: + - name: ZOO_MY_ID + value: "1" + - name: ZOO_SERVERS + value: "server.1=0.0.0.0:2888:3888;0.0.0.0:2181" + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + name: zookeeper + namespace: thingsboard +spec: + type: ClusterIP + selector: + app: zookeeper + ports: + - name: zk-port + port: 2181 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tb-kafka + namespace: thingsboard +spec: + selector: + matchLabels: + app: tb-kafka + template: + metadata: + labels: + app: tb-kafka + spec: + containers: + - name: server + imagePullPolicy: Always + image: wurstmeister/kafka:2.12-2.2.1 + ports: + - containerPort: 9092 + readinessProbe: + periodSeconds: 20 + tcpSocket: + port: 9092 + livenessProbe: + initialDelaySeconds: 25 + periodSeconds: 5 + tcpSocket: + port: 9092 + env: + - name: KAFKA_ZOOKEEPER_CONNECT + value: "zookeeper:2181" + - name: KAFKA_LISTENERS + value: "INSIDE://:9093,OUTSIDE://:9092" + - name: KAFKA_ADVERTISED_LISTENERS + value: "INSIDE://:9093,OUTSIDE://tb-kafka:9092" + - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP + value: "INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT" + - name: KAFKA_INTER_BROKER_LISTENER_NAME + value: "INSIDE" + - name: KAFKA_CREATE_TOPICS + value: "js_eval.requests:100:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb_transport.api.requests:30:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb_rule_engine:30:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600" + - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE + value: "false" + - name: KAFKA_LOG_RETENTION_BYTES + value: "1073741824" + - name: KAFKA_LOG_SEGMENT_BYTES + value: "268435456" + - name: KAFKA_LOG_RETENTION_MS + value: "300000" + - name: KAFKA_LOG_CLEANUP_POLICY + value: "delete" + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + name: tb-kafka + namespace: thingsboard +spec: + type: ClusterIP + selector: + app: tb-kafka + ports: + - name: tb-kafka-port + port: 9092 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tb-redis + namespace: thingsboard +spec: + selector: + matchLabels: + app: tb-redis + template: + metadata: + labels: + app: tb-redis + spec: + containers: + - name: server + imagePullPolicy: Always + image: redis:4.0 + ports: + - containerPort: 6379 + readinessProbe: + periodSeconds: 5 + tcpSocket: + port: 6379 + livenessProbe: + periodSeconds: 5 + tcpSocket: + port: 6379 + volumeMounts: + - mountPath: /data + name: redis-data + volumes: + - name: redis-data + emptyDir: {} + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + name: tb-redis + namespace: thingsboard +spec: + type: ClusterIP + selector: + app: tb-redis + ports: + - name: tb-redis-port + port: 6379 +--- \ No newline at end of file diff --git a/k8s/cassandra.yml b/k8s/common/cassandra.yml similarity index 100% rename from k8s/cassandra.yml rename to k8s/common/cassandra.yml diff --git a/k8s/database-setup.yml b/k8s/common/database-setup.yml similarity index 100% rename from k8s/database-setup.yml rename to k8s/common/database-setup.yml diff --git a/k8s/postgres.yml b/k8s/common/postgres.yml similarity index 100% rename from k8s/postgres.yml rename to k8s/common/postgres.yml diff --git a/k8s/tb-coap-transport-configmap.yml b/k8s/common/tb-coap-transport-configmap.yml similarity index 100% rename from k8s/tb-coap-transport-configmap.yml rename to k8s/common/tb-coap-transport-configmap.yml diff --git a/k8s/tb-http-transport-configmap.yml b/k8s/common/tb-http-transport-configmap.yml similarity index 100% rename from k8s/tb-http-transport-configmap.yml rename to k8s/common/tb-http-transport-configmap.yml diff --git a/k8s/tb-mqtt-transport-configmap.yml b/k8s/common/tb-mqtt-transport-configmap.yml similarity index 100% rename from k8s/tb-mqtt-transport-configmap.yml rename to k8s/common/tb-mqtt-transport-configmap.yml diff --git a/k8s/tb-namespace.yml b/k8s/common/tb-namespace.yml similarity index 100% rename from k8s/tb-namespace.yml rename to k8s/common/tb-namespace.yml diff --git a/k8s/tb-node-cassandra-configmap.yml b/k8s/common/tb-node-cassandra-configmap.yml similarity index 100% rename from k8s/tb-node-cassandra-configmap.yml rename to k8s/common/tb-node-cassandra-configmap.yml diff --git a/k8s/tb-node-configmap.yml b/k8s/common/tb-node-configmap.yml similarity index 100% rename from k8s/tb-node-configmap.yml rename to k8s/common/tb-node-configmap.yml diff --git a/k8s/tb-node-postgres-configmap.yml b/k8s/common/tb-node-postgres-configmap.yml similarity index 100% rename from k8s/tb-node-postgres-configmap.yml rename to k8s/common/tb-node-postgres-configmap.yml diff --git a/k8s/common/tb-node.yml b/k8s/common/tb-node.yml new file mode 100644 index 0000000000..7d90153eb7 --- /dev/null +++ b/k8s/common/tb-node.yml @@ -0,0 +1,98 @@ +# +# Copyright © 2016-2020 The Thingsboard Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tb-node + namespace: thingsboard +spec: + replicas: 2 + selector: + matchLabels: + app: tb-node + template: + metadata: + labels: + app: tb-node + spec: + volumes: + - name: tb-node-config + configMap: + name: tb-node-config + items: + - key: conf + path: thingsboard.conf + - key: logback + path: logback.xml + containers: + - name: server + imagePullPolicy: Always + image: thingsboard/tb-node:latest + ports: + - containerPort: 8080 + name: http + - containerPort: 9001 + name: rpc + env: + - name: TB_SERVICE_ID + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: TB_SERVICE_TYPE + value: "monolith" + - name: TB_QUEUE_TYPE + value: "kafka" + - name: ZOOKEEPER_ENABLED + value: "true" + - name: ZOOKEEPER_URL + value: "zookeeper:2181" + - name: TB_KAFKA_SERVERS + value: "tb-kafka:9092" + - name: JS_EVALUATOR + value: "remote" + - name: TRANSPORT_TYPE + value: "remote" + - name: HTTP_LOG_CONTROLLER_ERROR_STACK_TRACE + value: "false" + envFrom: + - configMapRef: + name: tb-node-db-config + - configMapRef: + name: tb-node-cache-config + volumeMounts: + - mountPath: /config + name: tb-node-config + livenessProbe: + httpGet: + path: /login + port: http + initialDelaySeconds: 300 + timeoutSeconds: 10 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + name: tb-node + namespace: thingsboard +spec: + type: ClusterIP + selector: + app: tb-node + ports: + - port: 8080 + name: http \ No newline at end of file diff --git a/k8s/thingsboard.yml b/k8s/common/thingsboard.yml similarity index 80% rename from k8s/thingsboard.yml rename to k8s/common/thingsboard.yml index 67a4cdd52e..5e17142527 100644 --- a/k8s/thingsboard.yml +++ b/k8s/common/thingsboard.yml @@ -20,7 +20,7 @@ metadata: name: tb-js-executor namespace: thingsboard spec: - replicas: 20 + replicas: 2 selector: matchLabels: app: tb-js-executor @@ -52,95 +52,6 @@ spec: --- apiVersion: apps/v1 kind: Deployment -metadata: - name: tb-node - namespace: thingsboard -spec: - replicas: 2 - selector: - matchLabels: - app: tb-node - template: - metadata: - labels: - app: tb-node - spec: - volumes: - - name: tb-node-config - configMap: - name: tb-node-config - items: - - key: conf - path: thingsboard.conf - - key: logback - path: logback.xml - containers: - - name: server - imagePullPolicy: Always - image: thingsboard/tb-node:latest - ports: - - containerPort: 8080 - name: http - - containerPort: 9001 - name: rpc - env: - - name: TB_SERVICE_ID - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: TB_SERVICE_TYPE - value: "monolith" - - name: TB_QUEUE_TYPE - value: "kafka" - - name: ZOOKEEPER_ENABLED - value: "true" - - name: ZOOKEEPER_URL - value: "zookeeper:2181" - - name: TB_KAFKA_SERVERS - value: "tb-kafka:9092" - - name: JS_EVALUATOR - value: "remote" - - name: TRANSPORT_TYPE - value: "remote" - - name: CACHE_TYPE - value: "redis" - - name: REDIS_HOST - value: "tb-redis" - - name: REDIS_CONNECTION_TYPE - value: "cluster" - - name: REDIS_NODES - value: "tb-redis:6379" - - name: HTTP_LOG_CONTROLLER_ERROR_STACK_TRACE - value: "false" - envFrom: - - configMapRef: - name: tb-node-db-config - volumeMounts: - - mountPath: /config - name: tb-node-config - livenessProbe: - httpGet: - path: /login - port: http - initialDelaySeconds: 120 - timeoutSeconds: 10 - restartPolicy: Always ---- -apiVersion: v1 -kind: Service -metadata: - name: tb-node - namespace: thingsboard -spec: - type: ClusterIP - selector: - app: tb-node - ports: - - port: 8080 - name: http ---- -apiVersion: apps/v1 -kind: Deployment metadata: name: tb-mqtt-transport namespace: thingsboard @@ -193,6 +104,7 @@ spec: tcpSocket: port: 1883 livenessProbe: + initialDelaySeconds: 120 periodSeconds: 20 tcpSocket: port: 1883 @@ -266,6 +178,7 @@ spec: tcpSocket: port: 8080 livenessProbe: + initialDelaySeconds: 120 periodSeconds: 20 tcpSocket: port: 8080 diff --git a/k8s/high-availability/tb-node-cache-configmap.yml b/k8s/high-availability/tb-node-cache-configmap.yml new file mode 100644 index 0000000000..d58d7688ae --- /dev/null +++ b/k8s/high-availability/tb-node-cache-configmap.yml @@ -0,0 +1,27 @@ +# +# Copyright © 2016-2020 The Thingsboard Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +apiVersion: v1 +kind: ConfigMap +metadata: + name: tb-node-cache-config + namespace: thingsboard + labels: + name: tb-node-cache-config +data: + CACHE_TYPE: redis + REDIS_CONNECTION_TYPE: cluster + REDIS_NODES: tb-redis:6379 \ No newline at end of file diff --git a/k8s/thirdparty.yml b/k8s/high-availability/thirdparty.yml similarity index 98% rename from k8s/thirdparty.yml rename to k8s/high-availability/thirdparty.yml index 2638bf0af5..06ff285cf1 100644 --- a/k8s/thirdparty.yml +++ b/k8s/high-availability/thirdparty.yml @@ -169,7 +169,7 @@ spec: - name: KAFKA_CONTROLLER_SHUTDOWN_ENABLE value: "true" - name: KAFKA_CREATE_TOPICS - value: "js_eval.requests:100:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb_transport.api.requests:30:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600" + value: "js_eval.requests:100:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb_transport.api.requests:30:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600,tb_rule_engine:30:1:delete --config=retention.ms=60000 --config=segment.bytes=26214400 --config=retention.bytes=104857600" - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE value: "false" - name: KAFKA_LOG_RETENTION_BYTES diff --git a/k8s/k8s-delete-resources.sh b/k8s/k8s-delete-resources.sh index 21efc56bc7..a815f8025c 100755 --- a/k8s/k8s-delete-resources.sh +++ b/k8s/k8s-delete-resources.sh @@ -17,6 +17,9 @@ set -e +source .env + kubectl config set-context $(kubectl config current-context) --namespace=thingsboard -kubectl delete -f thingsboard.yml -kubectl delete -f thirdparty.yml + +kubectl delete -f common/thingsboard.yml +kubectl delete -f common/tb-node.yml diff --git a/k8s/k8s-delete-thirdparty.sh b/k8s/k8s-delete-thirdparty.sh index a93b2b809e..e46e4973d5 100755 --- a/k8s/k8s-delete-thirdparty.sh +++ b/k8s/k8s-delete-thirdparty.sh @@ -17,5 +17,7 @@ set -e +source .env + kubectl config set-context $(kubectl config current-context) --namespace=thingsboard -kubectl delete -f thirdparty.yml +kubectl delete -f $DEPLOYMENT_TYPE/thirdparty.yml diff --git a/k8s/k8s-deploy-resources.sh b/k8s/k8s-deploy-resources.sh index 6a2deb31b4..14d12a6760 100755 --- a/k8s/k8s-deploy-resources.sh +++ b/k8s/k8s-deploy-resources.sh @@ -17,10 +17,14 @@ set -e -kubectl apply -f tb-namespace.yml +source .env + +kubectl apply -f common/tb-namespace.yml kubectl config set-context $(kubectl config current-context) --namespace=thingsboard -kubectl apply -f tb-node-configmap.yml -kubectl apply -f tb-mqtt-transport-configmap.yml -kubectl apply -f tb-http-transport-configmap.yml -kubectl apply -f tb-coap-transport-configmap.yml -kubectl apply -f thingsboard.yml +kubectl apply -f common/tb-node-configmap.yml +kubectl apply -f common/tb-mqtt-transport-configmap.yml +kubectl apply -f common/tb-http-transport-configmap.yml +kubectl apply -f common/tb-coap-transport-configmap.yml +kubectl apply -f common/thingsboard.yml +kubectl apply -f $DEPLOYMENT_TYPE/tb-node-cache-configmap.yml +kubectl apply -f common/tb-node.yml diff --git a/k8s/k8s-deploy-thirdparty.sh b/k8s/k8s-deploy-thirdparty.sh index adc526506a..17e9d3740f 100755 --- a/k8s/k8s-deploy-thirdparty.sh +++ b/k8s/k8s-deploy-thirdparty.sh @@ -17,6 +17,9 @@ set -e -kubectl apply -f tb-namespace.yml +source .env + +kubectl apply -f common/tb-namespace.yml kubectl config set-context $(kubectl config current-context) --namespace=thingsboard -kubectl apply -f thirdparty.yml + +kubectl apply -f $DEPLOYMENT_TYPE/thirdparty.yml diff --git a/k8s/k8s-install-tb.sh b/k8s/k8s-install-tb.sh index 1702a5b3b5..50ea6db443 100755 --- a/k8s/k8s-install-tb.sh +++ b/k8s/k8s-install-tb.sh @@ -19,8 +19,8 @@ function installTb() { loadDemo=$1 - kubectl apply -f tb-node-configmap.yml - kubectl apply -f database-setup.yml && + kubectl apply -f common/tb-node-configmap.yml + kubectl apply -f common/database-setup.yml && kubectl wait --for=condition=Ready pod/tb-db-setup --timeout=120s && kubectl exec tb-db-setup -- sh -c 'export INSTALL_TB=true; export LOAD_DEMO='"$loadDemo"'; start-tb-node.sh; touch /tmp/install-finished;' @@ -30,16 +30,16 @@ function installTb() { function installPostgres() { - kubectl apply -f postgres.yml - kubectl apply -f tb-node-postgres-configmap.yml + kubectl apply -f common/postgres.yml + kubectl apply -f common/tb-node-postgres-configmap.yml kubectl rollout status deployment/postgres } function installCassandra() { - kubectl apply -f cassandra.yml - kubectl apply -f tb-node-cassandra-configmap.yml + kubectl apply -f common/cassandra.yml + kubectl apply -f common/tb-node-cassandra-configmap.yml kubectl rollout status statefulset/cassandra @@ -75,9 +75,19 @@ fi source .env -kubectl apply -f tb-namespace.yml +kubectl apply -f common/tb-namespace.yml kubectl config set-context $(kubectl config current-context) --namespace=thingsboard +case $DEPLOYMENT_TYPE in + basic) + ;; + high-availability) + ;; + *) + echo "Unknown DEPLOYMENT_TYPE value specified: '${DEPLOYMENT_TYPE}'. Should be either basic or high-availability." >&2 + exit 1 +esac + case $DATABASE in postgres) installPostgres @@ -91,3 +101,4 @@ case $DATABASE in echo "Unknown DATABASE value specified: '${DATABASE}'. Should be either postgres or cassandra." >&2 exit 1 esac + From 53b240a72bd7f2e6c851662e4f33ecbb85fcbea0 Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 15:22:48 +0300 Subject: [PATCH 06/13] Fixed k8s-upgrade-tb.sh --- k8s/k8s-upgrade-tb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/k8s-upgrade-tb.sh b/k8s/k8s-upgrade-tb.sh index a97db5ea97..d814a15f90 100755 --- a/k8s/k8s-upgrade-tb.sh +++ b/k8s/k8s-upgrade-tb.sh @@ -36,7 +36,7 @@ else fromVersion="${FROM_VERSION// }" fi -kubectl apply -f database-setup.yml && +kubectl apply -f common/database-setup.yml && kubectl wait --for=condition=Ready pod/tb-db-setup --timeout=120s && kubectl exec tb-db-setup -- sh -c 'export UPGRADE_TB=true; export FROM_VERSION='"$fromVersion"'; start-tb-node.sh; touch /tmp/install-finished;' From 7c72233387a3ad52f461a743d9a3926e3e153e9e Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 15:40:57 +0300 Subject: [PATCH 07/13] Added commands for creating Redis cluster in k8s-deploy-thirdparty.sh --- k8s/.env | 2 +- k8s/README.md | 14 +------------- k8s/k8s-deploy-thirdparty.sh | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/k8s/.env b/k8s/.env index 5490250d8d..5f6b634b45 100644 --- a/k8s/.env +++ b/k8s/.env @@ -1,6 +1,6 @@ # Can be either basic (with single instance of Zookeeper, Kafka and Redis) or high-availability (with Zookeeper, Kafka and Redis in cluster modes). # According to the deployment type corresponding kubernetes resources will be deployed (see content of the directories ./basic and ./high-availability for details). -DEPLOYMENT_TYPE=basic +DEPLOYMENT_TYPE=high-availability # Database used by ThingsBoard, can be either postgres (PostgreSQL) or cassandra (Cassandra). # According to the database type corresponding kubernetes resources will be deployed (see postgres.yml, cassandra.yml for details). diff --git a/k8s/README.md b/k8s/README.md index 90fdea6afb..6017df1bd2 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -53,19 +53,7 @@ Execute the following command to deploy thirdparty resources: $ ./k8s-deploy-thirdparty.sh ` -Get list of the running tb-redis pods and verify that all of them are in running state: - -` -$ kubectl get pods -l app=tb-redis -` - -If you are running ThingsBoard in `high-availability` `DEPLOYMENT_TYPE` execute the following command to create redis cluster: - -` -$ kubectl exec -it tb-redis-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=tb-redis -o jsonpath='{range.items[*]}{.status.podIP}:6379 ') -` - -Type **'yes'** when prompted. +Type **'yes'** when prompted, if you are running ThingsBoard in `high-availability` `DEPLOYMENT_TYPE` for the first time and don't configured Redis cluster. Execute the following command to deploy resources: diff --git a/k8s/k8s-deploy-thirdparty.sh b/k8s/k8s-deploy-thirdparty.sh index 17e9d3740f..f530fb2903 100755 --- a/k8s/k8s-deploy-thirdparty.sh +++ b/k8s/k8s-deploy-thirdparty.sh @@ -23,3 +23,23 @@ kubectl apply -f common/tb-namespace.yml kubectl config set-context $(kubectl config current-context) --namespace=thingsboard kubectl apply -f $DEPLOYMENT_TYPE/thirdparty.yml + + +if [ "$DEPLOYMENT_TYPE" == "high-availability" ]; then + echo -n "waiting for all redis pods to be ready"; + while [[ $(kubectl get pods tb-redis-5 -o 'jsonpath={..status.conditions[?(@.type=="Ready")].status}' 2>/dev/null) != "True" ]]; + do + echo -n "." && sleep 5; + done + + if [[ $(kubectl exec -it tb-redis-0 -- redis-cli cluster info 2>&1 | head -n 1) =~ "cluster_state:ok" ]] + then + echo "redis cluster is already configured" + else + echo "starting redis cluster" + redisNodes=$(kubectl get pods -l app=tb-redis -o jsonpath='{range.items[*]}{.status.podIP}:6379 ') + kubectl exec -it tb-redis-0 -- redis-cli --cluster create --cluster-replicas 1 $redisNodes + fi + +fi + From 6c72912a36dbf31b3b7d47972bb2ca7718ff6e8c Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 15:44:39 +0300 Subject: [PATCH 08/13] Returned 20 js-executors as default --- k8s/common/thingsboard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/common/thingsboard.yml b/k8s/common/thingsboard.yml index 5e17142527..bb58ded9dd 100644 --- a/k8s/common/thingsboard.yml +++ b/k8s/common/thingsboard.yml @@ -20,7 +20,7 @@ metadata: name: tb-js-executor namespace: thingsboard spec: - replicas: 2 + replicas: 20 selector: matchLabels: app: tb-js-executor From c2648a64d46b3c08a84b75159e65242f9e40c175 Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 16:59:31 +0300 Subject: [PATCH 09/13] Fixed README.md --- k8s/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/README.md b/k8s/README.md index 6017df1bd2..05dd6a30cc 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -31,7 +31,7 @@ In order to set database type change the value of `DATABASE` variable in `.env` In order to set deployment type change the value of `DEPLOYMENT_TYPE` variable in `.env` file to one of the following: - `basic` - start up with single instance of Zookeeper, Kafka and Redis; -- `cassandra` - start up with Zookeeper, Kafka and Redis in cluster modes; +- `high-availability` - start up with Zookeeper, Kafka and Redis in cluster modes; **NOTE**: According to the deployment type corresponding kubernetes resources will be deployed (see content of the directories `./basic` and `./high-availability` for details). From 8ab77d2fd85250a7e38c9dc4916a0607683cae66 Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 17:08:11 +0300 Subject: [PATCH 10/13] Fixed README.md --- k8s/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8s/README.md b/k8s/README.md index 05dd6a30cc..5bd06c5f85 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -53,7 +53,7 @@ Execute the following command to deploy thirdparty resources: $ ./k8s-deploy-thirdparty.sh ` -Type **'yes'** when prompted, if you are running ThingsBoard in `high-availability` `DEPLOYMENT_TYPE` for the first time and don't configured Redis cluster. +Type **'yes'** when prompted, if you are running ThingsBoard in `high-availability` `DEPLOYMENT_TYPE` for the first time and don't have configured Redis cluster. Execute the following command to deploy resources: From 49b3df7de3ffb069de491898afbee7d1eace3c37 Mon Sep 17 00:00:00 2001 From: viktor Date: Wed, 27 May 2020 17:17:45 +0300 Subject: [PATCH 11/13] Added to README command to delete thirdparty-resources --- k8s/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/k8s/README.md b/k8s/README.md index 5bd06c5f85..24520dd68c 100644 --- a/k8s/README.md +++ b/k8s/README.md @@ -97,12 +97,18 @@ Or use `kubectl get services` to see the state of all the services. Or use `kubectl get deployments` to see the state of all the deployments. See [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) command reference for details. -Execute the following command to delete all deployed microservices: +Execute the following command to delete all ThingsBoard microservices: ` $ ./k8s-delete-resources.sh ` +Execute the following command to delete all thirdparty microservices: + +` +$ ./k8s-delete-thirdparty.sh +` + Execute the following command to delete all resources (including database): ` From 6c19857c99217d3051e41dbb684ad865108dc93f Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 29 May 2020 11:18:50 +0300 Subject: [PATCH 12/13] Update package versions --- msa/js-executor/package.json | 2 +- msa/web-ui/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index 60a107061a..8e9c01d800 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "2.5.0", + "version": "2.5.1", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.js", "bin": "server.js", diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 176791d65a..28f66fea46 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "2.5.0", + "version": "2.5.1", "description": "ThingsBoard Web UI Microservice", "main": "server.js", "bin": "server.js", diff --git a/ui/package.json b/ui/package.json index 6181e70de0..02a2f21219 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard", "private": true, - "version": "2.5.0", + "version": "2.5.1", "description": "ThingsBoard UI", "licenses": [ { From 3a303ccdb39b404cca697c439886cfb90b86c04a Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 29 May 2020 11:22:35 +0300 Subject: [PATCH 13/13] Update package-lock --- msa/js-executor/package-lock.json | 43 +++++++++++++++++++------------ msa/web-ui/package-lock.json | 2 +- ui/package-lock.json | 30 +++++++++++++++------ 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/msa/js-executor/package-lock.json b/msa/js-executor/package-lock.json index f2afdf1688..818b77550e 100644 --- a/msa/js-executor/package-lock.json +++ b/msa/js-executor/package-lock.json @@ -1,6 +1,6 @@ { "name": "thingsboard-js-executor", - "version": "2.5.0", + "version": "2.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1461,7 +1461,7 @@ }, "enabled": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", "requires": { "env-variable": "0.0.x" @@ -1740,7 +1740,7 @@ }, "fecha": { "version": "2.3.3", - "resolved": "http://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" }, "file-stream-rotator": { @@ -1872,12 +1872,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1892,17 +1894,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2019,7 +2024,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2031,6 +2037,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2045,6 +2052,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2156,7 +2164,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2168,6 +2177,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2289,6 +2299,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2390,7 +2401,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -2547,7 +2558,7 @@ }, "got": { "version": "6.7.1", - "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { @@ -2879,7 +2890,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, @@ -3241,7 +3252,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mixin-deep": { @@ -3540,7 +3551,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -3979,7 +3990,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -4289,7 +4300,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, diff --git a/msa/web-ui/package-lock.json b/msa/web-ui/package-lock.json index 59235f6911..695ef56342 100644 --- a/msa/web-ui/package-lock.json +++ b/msa/web-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "thingsboard-web-ui", - "version": "2.5.0", + "version": "2.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/ui/package-lock.json b/ui/package-lock.json index f2abd409c1..4de10ff7d8 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "2.5.0", + "version": "2.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -5259,12 +5259,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5279,17 +5281,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5406,7 +5411,8 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5418,6 +5424,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5432,6 +5439,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5439,12 +5447,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5463,6 +5473,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5552,7 +5563,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5564,6 +5576,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5685,6 +5698,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",