@yarkivaev/scada 2.3.90 → 2.3.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +6 -1
  2. package/charts/scada/Chart.yaml +6 -0
  3. package/charts/scada/templates/_helpers.tpl +63 -0
  4. package/charts/scada/templates/clickhouse.yaml +57 -0
  5. package/charts/scada/templates/collector.yaml +115 -0
  6. package/charts/scada/templates/postgres.yaml +70 -0
  7. package/charts/scada/templates/rabbitmq.yaml +150 -0
  8. package/charts/scada/templates/site-server.yaml +110 -0
  9. package/charts/scada/templates/supervisor-sink.yaml +64 -0
  10. package/charts/scada/values.yaml +30 -0
  11. package/index.js +10 -0
  12. package/package.json +3 -1
  13. package/src/application/deploy/appReleases.js +50 -0
  14. package/src/application/deploy/applyIncludes.js +31 -0
  15. package/src/application/deploy/expand.js +49 -0
  16. package/src/application/deploy/expandDevices.js +135 -0
  17. package/src/application/deploy/expandFlows.js +281 -0
  18. package/src/application/deploy/expandNamespace.js +193 -0
  19. package/src/application/deploy/expandPattern.js +207 -0
  20. package/src/application/deploy/expandProfiles.js +70 -0
  21. package/src/application/deploy/frozen.js +23 -0
  22. package/src/application/deploy/mergeDocuments.js +98 -0
  23. package/src/application/deploy/paths.js +86 -0
  24. package/src/application/deploy/pointPaths.js +20 -0
  25. package/src/application/deploy/readDocument.js +169 -0
  26. package/src/application/deploy/releaseEdges.js +185 -0
  27. package/src/application/deploy/releaseNodes.js +118 -0
  28. package/src/application/deploy/releaseValues.js +200 -0
  29. package/src/application/deploy/releases.js +115 -0
  30. package/src/application/deploy/withCollectors.js +28 -0
  31. package/src/bin/modbus-to-mqtt.js +57 -0
  32. package/src/infrastructure/ingest/mqtt/addressWindow.js +79 -0
  33. package/src/infrastructure/ingest/mqtt/modbusPublish.js +277 -0
  34. package/src/infrastructure/ingest/mqtt/registerPoint.js +90 -0
  35. package/src/infrastructure/ingest/mqtt/registerPublish.js +84 -0
package/README.md CHANGED
@@ -134,7 +134,7 @@ Main entry (`import { … } from '@yarkivaev/scada'`):
134
134
  | `pgTimeline`, `pgAlerts`, `stateDataFromPool`, `stateDataFromMemory` | State ports |
135
135
  | `stompTimeline`, `stompAlerts`, `userDecisions` | STOMP messaging |
136
136
  | `machineOwners`, `ownerTimeline`, `httpTimeline`, `httpOperations` | Owner-routed timeline and operations write (local or edge HTTP) |
137
- | `mqttMetrics`, `modbusMqtt`, `activityTracking`, `amqpMetricsIngest` | Ingest pipelines |
137
+ | `mqttMetrics`, `modbusMqtt`, `modbusPublish`, `activityTracking`, `amqpMetricsIngest` | Ingest pipelines |
138
138
  | `analyticsMcp`, `namespaceTree`, `coverageSpans`, `coverageOverlay`, `coverageCursor`, `sqlGuard` | Analytics MCP, path index, coverage spans, timeline-name overlay, checkpoint-or-sample cursor, read-only SQL guard |
139
139
 
140
140
  Subpath exports:
@@ -184,6 +184,7 @@ Alert and HMI copy are inject-only: pass `translations` into `siteServer` / `pla
184
184
  | Binary | Role |
185
185
  |--------|------|
186
186
  | `supervisor-sink` | STOMP → PostgreSQL ingest + edge HTTP API (`STATE_HTTP_PORT`, default 8081) |
187
+ | `modbus-to-mqtt` | Poll Modbus and publish `STREAM` + `MAPPING` document paths (`src/bin/modbus-to-mqtt.js`) |
187
188
 
188
189
  Full plant API with site-specific routes: plant packages call `siteServer` from this package.
189
190
 
@@ -223,6 +224,10 @@ Set `SINK_DB_PROFILE=central|edge`. Migrations run at supervisor-sink startup vi
223
224
  | `CLICKHOUSE_URL` | Central metrics sink |
224
225
  | `PORT` | Plant API port (siteServer, default 3000) |
225
226
 
227
+ ## Deploy
228
+
229
+ The deployment DSL is specified in [docs/deploy.md](docs/deploy.md). A flow is `from` and `name`. An object listed on a node is state that node is responsible for. Profile, cluster, and modules are implementation. One Helm release of `charts/scada` is one cluster, cut from that document.
230
+
226
231
  ## Testing
227
232
 
228
233
  ```bash
@@ -0,0 +1,6 @@
1
+ apiVersion: v2
2
+ name: scada
3
+ description: Generic SCADA site — site-server, supervisor-sink, collectors, Postgres, RabbitMQ, optional ClickHouse
4
+ type: application
5
+ version: 0.2.1
6
+ appVersion: "2.3.112"
@@ -0,0 +1,63 @@
1
+ {{- define "scada.labels" -}}
2
+ app.kubernetes.io/name: scada
3
+ app.kubernetes.io/instance: {{ .Release.Name }}
4
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
5
+ {{- end }}
6
+
7
+ {{- define "scada.device" -}}
8
+ {{- $serial := regexFind "/dev/tty[A-Za-z0-9]+" . -}}
9
+ {{- if $serial -}}
10
+ {{- $serial -}}
11
+ {{- else -}}
12
+ {{- . -}}
13
+ {{- end -}}
14
+ {{- end }}
15
+
16
+ {{- define "scada.slug" -}}
17
+ {{- regexReplaceAll "[^A-Za-z0-9]+" . "-" | trimAll "-" | lower -}}
18
+ {{- end }}
19
+
20
+ {{- define "scada.routingKey" -}}
21
+ {{- if eq . "*" -}}
22
+ #
23
+ {{- else if hasSuffix "/*" . -}}
24
+ {{- printf "%s.#" (replace "/" "." (trimSuffix "/*" .)) -}}
25
+ {{- else -}}
26
+ {{- replace "/" "." . -}}
27
+ {{- end -}}
28
+ {{- end }}
29
+
30
+ {{- define "scada.linkEnv" -}}
31
+ - name: SINK_DB_PROFILE
32
+ value: {{ .Values.role | quote }}
33
+ {{- if .Values.postgres.enabled }}
34
+ - name: POSTGRES_URL
35
+ valueFrom:
36
+ secretKeyRef:
37
+ name: {{ .Values.postgres.secret }}
38
+ key: url
39
+ - name: POSTGRES_ADMIN_URL
40
+ valueFrom:
41
+ secretKeyRef:
42
+ name: {{ .Values.postgres.secret }}
43
+ key: adminUrl
44
+ {{- end }}
45
+ {{- if .Values.rabbitmq.enabled }}
46
+ - name: STOMP_URL
47
+ value: {{ printf "stomp://%s-rabbitmq:61613" .Release.Name | quote }}
48
+ - name: STOMP_LOGIN
49
+ value: guest
50
+ - name: STOMP_PASSCODE
51
+ value: guest
52
+ - name: STOMP_HOST
53
+ value: /
54
+ - name: AMQP_URL
55
+ value: {{ printf "amqp://guest:guest@%s-rabbitmq:5672" .Release.Name | quote }}
56
+ {{- end }}
57
+ {{- if .Values.clickhouse.enabled }}
58
+ - name: CLICKHOUSE_HOST
59
+ value: {{ printf "%s-clickhouse" .Release.Name | quote }}
60
+ - name: CLICKHOUSE_URL
61
+ value: {{ printf "http://%s-clickhouse:8123" .Release.Name | quote }}
62
+ {{- end }}
63
+ {{- end }}
@@ -0,0 +1,57 @@
1
+ {{- if .Values.clickhouse.enabled }}
2
+ apiVersion: v1
3
+ kind: Service
4
+ metadata:
5
+ name: {{ .Release.Name }}-clickhouse
6
+ namespace: {{ .Release.Namespace }}
7
+ labels:
8
+ {{- include "scada.labels" . | nindent 4 }}
9
+ app: clickhouse
10
+ spec:
11
+ ports:
12
+ - name: http
13
+ port: 8123
14
+ targetPort: http
15
+ selector:
16
+ app: clickhouse
17
+ app.kubernetes.io/instance: {{ .Release.Name }}
18
+ ---
19
+ apiVersion: apps/v1
20
+ kind: StatefulSet
21
+ metadata:
22
+ name: {{ .Release.Name }}-clickhouse
23
+ namespace: {{ .Release.Namespace }}
24
+ labels:
25
+ {{- include "scada.labels" . | nindent 4 }}
26
+ app: clickhouse
27
+ spec:
28
+ serviceName: {{ .Release.Name }}-clickhouse
29
+ replicas: 1
30
+ selector:
31
+ matchLabels:
32
+ app: clickhouse
33
+ app.kubernetes.io/instance: {{ .Release.Name }}
34
+ template:
35
+ metadata:
36
+ labels:
37
+ {{- include "scada.labels" . | nindent 8 }}
38
+ app: clickhouse
39
+ spec:
40
+ containers:
41
+ - name: clickhouse
42
+ image: {{ .Values.clickhouse.image | quote }}
43
+ ports:
44
+ - name: http
45
+ containerPort: 8123
46
+ volumeMounts:
47
+ - name: data
48
+ mountPath: /var/lib/clickhouse
49
+ volumeClaimTemplates:
50
+ - metadata:
51
+ name: data
52
+ spec:
53
+ accessModes: ["ReadWriteOnce"]
54
+ resources:
55
+ requests:
56
+ storage: 20Gi
57
+ {{- end }}
@@ -0,0 +1,115 @@
1
+ {{- if .Values.collectors }}
2
+ {{- $groups := dict -}}
3
+ {{- range $item := .Values.collectors }}
4
+ {{- $device := include "scada.device" $item.address | trim -}}
5
+ {{- if not $device }}
6
+ {{- fail "collector has no address" }}
7
+ {{- end }}
8
+ {{- if not $item.path }}
9
+ {{- fail (printf "collector %s has no path" $device) }}
10
+ {{- end }}
11
+ {{- if not $item.command }}
12
+ {{- fail (printf "collector %s has no command" $device) }}
13
+ {{- end }}
14
+ {{- $token := $item.command | toJson -}}
15
+ {{- $prior := list -}}
16
+ {{- if hasKey $groups $token }}
17
+ {{- $prior = index $groups $token -}}
18
+ {{- end }}
19
+ {{- $groups = set $groups $token (append $prior $item) -}}
20
+ {{- end }}
21
+ {{- $claimed := dict -}}
22
+ {{- range $token, $items := $groups }}
23
+ {{- range $item := $items }}
24
+ {{- $device := include "scada.device" $item.address | trim -}}
25
+ {{- if hasPrefix "/dev/" $device }}
26
+ {{- if and (hasKey $claimed $device) (ne (index $claimed $device) $token) }}
27
+ {{- fail (printf "collectors on %s use different commands" $device) }}
28
+ {{- end }}
29
+ {{- $claimed = set $claimed $device $token -}}
30
+ {{- end }}
31
+ {{- end }}
32
+ {{- end }}
33
+ {{- range $token, $items := $groups }}
34
+ {{- $argv := (index $items 0).command -}}
35
+ {{- $slug := include "scada.slug" (index $argv (sub (len $argv) 1)) | trim -}}
36
+ {{- if not $slug }}
37
+ {{- fail (printf "collector %s has no name" $token) }}
38
+ {{- end }}
39
+ {{- $paths := list -}}
40
+ {{- $maps := list -}}
41
+ {{- $addresses := list -}}
42
+ {{- $serials := list -}}
43
+ {{- range $item := $items }}
44
+ {{- $paths = append $paths $item.path -}}
45
+ {{- $maps = append $maps ($item.mapping | default (dict)) -}}
46
+ {{- $addresses = append $addresses $item.address -}}
47
+ {{- $device := include "scada.device" $item.address | trim -}}
48
+ {{- if and (hasPrefix "/dev/" $device) (not (has $device $serials)) }}
49
+ {{- $serials = append $serials $device -}}
50
+ {{- end }}
51
+ {{- end }}
52
+ ---
53
+ apiVersion: apps/v1
54
+ kind: Deployment
55
+ metadata:
56
+ name: {{ $.Release.Name }}-collector-{{ $slug }}
57
+ namespace: {{ $.Release.Namespace }}
58
+ labels:
59
+ {{- include "scada.labels" $ | nindent 4 }}
60
+ app: collector
61
+ spec:
62
+ replicas: 1
63
+ selector:
64
+ matchLabels:
65
+ app: collector
66
+ app.kubernetes.io/instance: {{ $.Release.Name }}
67
+ scada/command: {{ $slug }}
68
+ template:
69
+ metadata:
70
+ labels:
71
+ {{- include "scada.labels" $ | nindent 8 }}
72
+ app: collector
73
+ scada/command: {{ $slug }}
74
+ spec:
75
+ {{- with $.Values.pullSecret }}
76
+ imagePullSecrets:
77
+ - name: {{ . }}
78
+ {{- end }}
79
+ containers:
80
+ - name: collector
81
+ image: {{ required "image is required" $.Values.image | quote }}
82
+ command: {{ $argv | toJson }}
83
+ {{- if $serials }}
84
+ securityContext:
85
+ privileged: true
86
+ volumeMounts:
87
+ {{- range $serials }}
88
+ - name: {{ include "scada.slug" . | trim }}
89
+ mountPath: {{ . }}
90
+ {{- end }}
91
+ {{- end }}
92
+ env:
93
+ - name: ADDRESS
94
+ value: {{ $addresses | toJson | quote }}
95
+ - name: STREAM
96
+ value: {{ $paths | toJson | quote }}
97
+ - name: MAPPING
98
+ value: {{ $maps | toJson | quote }}
99
+ {{- if $.Values.rabbitmq.enabled }}
100
+ - name: MQTT_URL
101
+ value: {{ printf "mqtt://%s-rabbitmq:1883" $.Release.Name | quote }}
102
+ {{- end }}
103
+ resources:
104
+ {{- toYaml $.Values.resources | nindent 12 }}
105
+ {{- if $serials }}
106
+ volumes:
107
+ {{- range $serials }}
108
+ - name: {{ include "scada.slug" . | trim }}
109
+ hostPath:
110
+ path: {{ . }}
111
+ type: CharDevice
112
+ {{- end }}
113
+ {{- end }}
114
+ {{- end }}
115
+ {{- end }}
@@ -0,0 +1,70 @@
1
+ {{- if .Values.postgres.enabled }}
2
+ apiVersion: v1
3
+ kind: Service
4
+ metadata:
5
+ name: {{ .Release.Name }}-postgres
6
+ namespace: {{ .Release.Namespace }}
7
+ labels:
8
+ {{- include "scada.labels" . | nindent 4 }}
9
+ app: postgres
10
+ spec:
11
+ ports:
12
+ - name: postgres
13
+ port: 5432
14
+ targetPort: postgres
15
+ selector:
16
+ app: postgres
17
+ app.kubernetes.io/instance: {{ .Release.Name }}
18
+ ---
19
+ apiVersion: apps/v1
20
+ kind: StatefulSet
21
+ metadata:
22
+ name: {{ .Release.Name }}-postgres
23
+ namespace: {{ .Release.Namespace }}
24
+ labels:
25
+ {{- include "scada.labels" . | nindent 4 }}
26
+ app: postgres
27
+ spec:
28
+ serviceName: {{ .Release.Name }}-postgres
29
+ replicas: 1
30
+ selector:
31
+ matchLabels:
32
+ app: postgres
33
+ app.kubernetes.io/instance: {{ .Release.Name }}
34
+ template:
35
+ metadata:
36
+ labels:
37
+ {{- include "scada.labels" . | nindent 8 }}
38
+ app: postgres
39
+ spec:
40
+ containers:
41
+ - name: postgres
42
+ image: {{ .Values.postgres.image | quote }}
43
+ ports:
44
+ - name: postgres
45
+ containerPort: 5432
46
+ env:
47
+ - name: POSTGRES_DB
48
+ value: {{ .Values.postgres.database | quote }}
49
+ - name: POSTGRES_USER
50
+ valueFrom:
51
+ secretKeyRef:
52
+ name: {{ .Values.postgres.secret }}
53
+ key: user
54
+ - name: POSTGRES_PASSWORD
55
+ valueFrom:
56
+ secretKeyRef:
57
+ name: {{ .Values.postgres.secret }}
58
+ key: password
59
+ volumeMounts:
60
+ - name: data
61
+ mountPath: /var/lib/postgresql/data
62
+ volumeClaimTemplates:
63
+ - metadata:
64
+ name: data
65
+ spec:
66
+ accessModes: ["ReadWriteOnce"]
67
+ resources:
68
+ requests:
69
+ storage: 10Gi
70
+ {{- end }}
@@ -0,0 +1,150 @@
1
+ {{- if .Values.rabbitmq.enabled }}
2
+ {{- $ingest := list -}}
3
+ {{- $outgoing := list -}}
4
+ {{- range .Values.collectors }}
5
+ {{- if .path }}
6
+ {{- $ingest = append $ingest (include "scada.routingKey" .path | trim) -}}
7
+ {{- end }}
8
+ {{- end }}
9
+ {{- range $item := concat (.Values.buses | default (list)) (.Values.bus | default (list)) }}
10
+ {{- range $name := ($item.names | default (list)) }}
11
+ {{- $routed := include "scada.routingKey" $name | trim -}}
12
+ {{- $ingest = append $ingest $routed -}}
13
+ {{- $outgoing = append $outgoing $routed -}}
14
+ {{- end }}
15
+ {{- end }}
16
+ {{- $outgoing = $outgoing | uniq -}}
17
+ {{- if $ingest }}
18
+ {{- $ingest = $ingest | uniq -}}
19
+ {{- else }}
20
+ {{- $ingest = list "#" -}}
21
+ {{- end }}
22
+ {{- $exchange := list
23
+ (dict "name" "scada.alerts" "vhost" "/" "type" "topic" "durable" true "auto_delete" false)
24
+ (dict "name" "scada.segments" "vhost" "/" "type" "topic" "durable" true "auto_delete" false)
25
+ (dict "name" "scada.telemetry" "vhost" "/" "type" "topic" "durable" true "auto_delete" false)
26
+ (dict "name" "scada.operations" "vhost" "/" "type" "topic" "durable" true "auto_delete" false)
27
+ (dict "name" "scada.user_decisions" "vhost" "/" "type" "topic" "durable" true "auto_delete" false)
28
+ -}}
29
+ {{- $queue := list
30
+ (dict "name" "scada.segments.ingest" "vhost" "/" "durable" true "auto_delete" false)
31
+ (dict "name" "scada.telemetry.ingest" "vhost" "/" "durable" true "auto_delete" false)
32
+ (dict "name" "scada.operations.ingest" "vhost" "/" "durable" true "auto_delete" false)
33
+ (dict "name" "scada.user_decisions" "vhost" "/" "durable" true "auto_delete" false)
34
+ -}}
35
+ {{- if $outgoing }}
36
+ {{- $queue = append $queue (dict "name" "scada.telemetry.outbox" "vhost" "/" "durable" true "auto_delete" false) -}}
37
+ {{- end }}
38
+ {{- $binding := list -}}
39
+ {{- range $key := $ingest }}
40
+ {{- $binding = append $binding (dict "source" "scada.telemetry" "vhost" "/" "destination" "scada.telemetry.ingest" "destination_type" "queue" "routing_key" $key) -}}
41
+ {{- end }}
42
+ {{- range $pair := (list
43
+ (dict "source" "scada.operations" "destination" "scada.operations.ingest")
44
+ (dict "source" "scada.segments" "destination" "scada.segments.ingest")
45
+ (dict "source" "scada.user_decisions" "destination" "scada.user_decisions")) }}
46
+ {{- $binding = append $binding (dict "source" $pair.source "vhost" "/" "destination" $pair.destination "destination_type" "queue" "routing_key" "#") -}}
47
+ {{- end }}
48
+ {{- range $key := $outgoing }}
49
+ {{- $binding = append $binding (dict "source" "scada.telemetry" "vhost" "/" "destination" "scada.telemetry.outbox" "destination_type" "queue" "routing_key" $key) -}}
50
+ {{- end }}
51
+ {{- $definitions := dict
52
+ "vhosts" (list (dict "name" "/"))
53
+ "users" (list (dict "name" "guest" "password" "guest" "tags" (list "administrator")))
54
+ "permissions" (list (dict "user" "guest" "vhost" "/" "configure" ".*" "write" ".*" "read" ".*"))
55
+ "exchanges" $exchange
56
+ "queues" $queue
57
+ "bindings" $binding
58
+ -}}
59
+ apiVersion: v1
60
+ kind: ConfigMap
61
+ metadata:
62
+ name: {{ .Release.Name }}-rabbitmq
63
+ namespace: {{ .Release.Namespace }}
64
+ labels:
65
+ {{- include "scada.labels" . | nindent 4 }}
66
+ app: rabbitmq
67
+ data:
68
+ enabled_plugins: |
69
+ [rabbitmq_stomp, rabbitmq_mqtt, rabbitmq_management].
70
+ rabbitmq.conf: |
71
+ load_definitions = /etc/rabbitmq/definitions.json
72
+ mqtt.listeners.tcp.default = 1883
73
+ mqtt.allow_anonymous = true
74
+ mqtt.vhost = /
75
+ mqtt.exchange = scada.telemetry
76
+ definitions.json: |
77
+ {{ $definitions | toPrettyJson | nindent 4 }}
78
+ ---
79
+ apiVersion: v1
80
+ kind: Service
81
+ metadata:
82
+ name: {{ .Release.Name }}-rabbitmq
83
+ namespace: {{ .Release.Namespace }}
84
+ labels:
85
+ {{- include "scada.labels" . | nindent 4 }}
86
+ app: rabbitmq
87
+ spec:
88
+ ports:
89
+ - name: amqp
90
+ port: 5672
91
+ targetPort: amqp
92
+ - name: mqtt
93
+ port: 1883
94
+ targetPort: mqtt
95
+ - name: stomp
96
+ port: 61613
97
+ targetPort: stomp
98
+ selector:
99
+ app: rabbitmq
100
+ app.kubernetes.io/instance: {{ .Release.Name }}
101
+ ---
102
+ apiVersion: apps/v1
103
+ kind: StatefulSet
104
+ metadata:
105
+ name: {{ .Release.Name }}-rabbitmq
106
+ namespace: {{ .Release.Namespace }}
107
+ labels:
108
+ {{- include "scada.labels" . | nindent 4 }}
109
+ app: rabbitmq
110
+ spec:
111
+ serviceName: {{ .Release.Name }}-rabbitmq
112
+ replicas: 1
113
+ selector:
114
+ matchLabels:
115
+ app: rabbitmq
116
+ app.kubernetes.io/instance: {{ .Release.Name }}
117
+ template:
118
+ metadata:
119
+ labels:
120
+ {{- include "scada.labels" . | nindent 8 }}
121
+ app: rabbitmq
122
+ spec:
123
+ containers:
124
+ - name: rabbitmq
125
+ image: {{ .Values.rabbitmq.image | quote }}
126
+ ports:
127
+ - name: amqp
128
+ containerPort: 5672
129
+ - name: mqtt
130
+ containerPort: 1883
131
+ - name: stomp
132
+ containerPort: 61613
133
+ volumeMounts:
134
+ - name: config
135
+ mountPath: /etc/rabbitmq
136
+ - name: data
137
+ mountPath: /var/lib/rabbitmq
138
+ volumes:
139
+ - name: config
140
+ configMap:
141
+ name: {{ .Release.Name }}-rabbitmq
142
+ volumeClaimTemplates:
143
+ - metadata:
144
+ name: data
145
+ spec:
146
+ accessModes: ["ReadWriteOnce"]
147
+ resources:
148
+ requests:
149
+ storage: 5Gi
150
+ {{- end }}
@@ -0,0 +1,110 @@
1
+ apiVersion: apps/v1
2
+ kind: Deployment
3
+ metadata:
4
+ name: {{ .Release.Name }}-site-server
5
+ namespace: {{ .Release.Namespace }}
6
+ labels:
7
+ {{- include "scada.labels" . | nindent 4 }}
8
+ app: site-server
9
+ spec:
10
+ replicas: 1
11
+ selector:
12
+ matchLabels:
13
+ app: site-server
14
+ app.kubernetes.io/instance: {{ .Release.Name }}
15
+ template:
16
+ metadata:
17
+ labels:
18
+ {{- include "scada.labels" . | nindent 8 }}
19
+ app: site-server
20
+ spec:
21
+ {{- with .Values.pullSecret }}
22
+ imagePullSecrets:
23
+ - name: {{ . }}
24
+ {{- end }}
25
+ containers:
26
+ - name: site-server
27
+ image: {{ required "image is required" .Values.image | quote }}
28
+ {{- with .Values.command }}
29
+ command: {{ toJson . }}
30
+ {{- end }}
31
+ ports:
32
+ - name: http
33
+ containerPort: {{ .Values.service.port }}
34
+ - name: internal-api
35
+ containerPort: {{ .Values.service.internalPort }}
36
+ env:
37
+ - name: PORT
38
+ value: {{ .Values.service.port | quote }}
39
+ - name: STATE_HTTP_PORT
40
+ value: {{ .Values.service.internalPort | quote }}
41
+ {{- include "scada.linkEnv" . | nindent 12 }}
42
+ - name: SINK_PIPELINES
43
+ value: "false"
44
+ {{- if .Values.machines }}
45
+ - name: EDGE_MACHINES
46
+ value: {{ .Values.machines | toJson | quote }}
47
+ {{- end }}
48
+ {{- if .Values.sites }}
49
+ - name: EDGE_SITES
50
+ value: {{ .Values.sites | toJson | quote }}
51
+ {{- end }}
52
+ {{- range .Values.env }}
53
+ - name: {{ .name }}
54
+ value: {{ .value | quote }}
55
+ {{- end }}
56
+ readinessProbe:
57
+ httpGet:
58
+ path: /api/v1/machines
59
+ port: http
60
+ initialDelaySeconds: 5
61
+ periodSeconds: 10
62
+ livenessProbe:
63
+ httpGet:
64
+ path: /api/v1/machines
65
+ port: http
66
+ initialDelaySeconds: 15
67
+ periodSeconds: 30
68
+ resources:
69
+ {{- toYaml .Values.resources | nindent 12 }}
70
+ ---
71
+ apiVersion: v1
72
+ kind: Service
73
+ metadata:
74
+ name: {{ .Release.Name }}-site-server
75
+ namespace: {{ .Release.Namespace }}
76
+ labels:
77
+ {{- include "scada.labels" . | nindent 4 }}
78
+ app: site-server
79
+ spec:
80
+ ports:
81
+ - name: http
82
+ port: {{ .Values.service.port }}
83
+ targetPort: http
84
+ - name: internal-api
85
+ port: {{ .Values.service.internalPort }}
86
+ targetPort: internal-api
87
+ selector:
88
+ app: site-server
89
+ app.kubernetes.io/instance: {{ .Release.Name }}
90
+ {{- if gt (int .Values.service.nodePort) 0 }}
91
+ ---
92
+ apiVersion: v1
93
+ kind: Service
94
+ metadata:
95
+ name: {{ .Release.Name }}-site-server-plant-lan
96
+ namespace: {{ .Release.Namespace }}
97
+ labels:
98
+ {{- include "scada.labels" . | nindent 4 }}
99
+ app: site-server
100
+ spec:
101
+ type: NodePort
102
+ ports:
103
+ - name: http
104
+ port: {{ .Values.service.port }}
105
+ targetPort: http
106
+ nodePort: {{ .Values.service.nodePort }}
107
+ selector:
108
+ app: site-server
109
+ app.kubernetes.io/instance: {{ .Release.Name }}
110
+ {{- end }}
@@ -0,0 +1,64 @@
1
+ apiVersion: apps/v1
2
+ kind: Deployment
3
+ metadata:
4
+ name: {{ .Release.Name }}-supervisor-sink
5
+ namespace: {{ .Release.Namespace }}
6
+ labels:
7
+ {{- include "scada.labels" . | nindent 4 }}
8
+ app: supervisor-sink
9
+ spec:
10
+ replicas: 1
11
+ selector:
12
+ matchLabels:
13
+ app: supervisor-sink
14
+ app.kubernetes.io/instance: {{ .Release.Name }}
15
+ template:
16
+ metadata:
17
+ labels:
18
+ {{- include "scada.labels" . | nindent 8 }}
19
+ app: supervisor-sink
20
+ spec:
21
+ {{- with .Values.pullSecret }}
22
+ imagePullSecrets:
23
+ - name: {{ . }}
24
+ {{- end }}
25
+ containers:
26
+ - name: supervisor-sink
27
+ image: {{ required "image is required" .Values.image | quote }}
28
+ command: ["node", "node_modules/@yarkivaev/scada/src/bin/supervisor-sink.js"]
29
+ ports:
30
+ - name: state
31
+ containerPort: {{ .Values.service.internalPort }}
32
+ env:
33
+ - name: STATE_HTTP_PORT
34
+ value: {{ .Values.service.internalPort | quote }}
35
+ {{- include "scada.linkEnv" . | nindent 12 }}
36
+ readinessProbe:
37
+ tcpSocket:
38
+ port: state
39
+ initialDelaySeconds: 5
40
+ periodSeconds: 10
41
+ livenessProbe:
42
+ tcpSocket:
43
+ port: state
44
+ initialDelaySeconds: 15
45
+ periodSeconds: 30
46
+ resources:
47
+ {{- toYaml .Values.resources | nindent 12 }}
48
+ ---
49
+ apiVersion: v1
50
+ kind: Service
51
+ metadata:
52
+ name: {{ .Release.Name }}-supervisor-sink
53
+ namespace: {{ .Release.Namespace }}
54
+ labels:
55
+ {{- include "scada.labels" . | nindent 4 }}
56
+ app: supervisor-sink
57
+ spec:
58
+ ports:
59
+ - name: state
60
+ port: {{ .Values.service.internalPort }}
61
+ targetPort: state
62
+ selector:
63
+ app: supervisor-sink
64
+ app.kubernetes.io/instance: {{ .Release.Name }}
@@ -0,0 +1,30 @@
1
+ role: edge
2
+ image: ""
3
+ command: []
4
+ pullSecret: ""
5
+ machines: []
6
+ sites: []
7
+ collectors: []
8
+ env: []
9
+ service:
10
+ port: 3000
11
+ internalPort: 8081
12
+ nodePort: 0
13
+ postgres:
14
+ enabled: true
15
+ image: postgres:16
16
+ secret: scada-postgres
17
+ database: scada
18
+ rabbitmq:
19
+ enabled: true
20
+ image: rabbitmq:3.13-management
21
+ clickhouse:
22
+ enabled: false
23
+ image: clickhouse/clickhouse-server:24.8
24
+ resources:
25
+ requests:
26
+ cpu: 100m
27
+ memory: 128Mi
28
+ limits:
29
+ cpu: "1"
30
+ memory: 512Mi