@samanbayaka/core 0.0.1

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.
package/README.md ADDED
@@ -0,0 +1,812 @@
1
+ <p align="center" style="margin: 0;">
2
+ <img style="background-color: #000; border-radius: 30%;" src="https://unpkg.com/samanbayaka/public/favicon.svg" width="256" />
3
+ </p>
4
+
5
+ # samanbayaka
6
+
7
+ This project is a modular, production-ready microservices framework built with Moleculer and Moleculer-Web latest, using NATS as a high-performance messaging transporter and AJV for robust schema validation. It provides a scalable foundation for developing distributed Node.js applications, emphasizing fault tolerance, clean architecture, and efficient service communication. The system is designed to support flexible orchestration of services while maintaining strong validation and reliability across components.
8
+
9
+ [![NPM version](https://img.shields.io/npm/v/samanbayaka.svg)](https://www.npmjs.com/package/samanbayaka)
10
+ [![License](https://img.shields.io/npm/l/samanbayaka.svg)](LICENSE)
11
+
12
+ - [Table of contents](#table-of-contents)
13
+ - [Features](#features)
14
+ - [Installation](#installation)
15
+ - [Prerequisites](#prerequisites)
16
+ - [Documentations](#documentations)
17
+ - [Errors](#errors)
18
+ - [getConfig](#getConfig)
19
+ - [loadDemo](#loadDemo)
20
+ - [registerSystemAPI](#registerSystemAPI)
21
+ - [registerEdgeAPI](#registerEdgeAPI)
22
+ - [registerServices](#registerServices)
23
+ - [registerBridgeServices](#registerBridgeServices)
24
+ - [Usage](#usage)
25
+ - [Demo](#Demo)
26
+ - [Dockers](#dockers)
27
+ - [Etcd](#etcd)
28
+
29
+ ## Features
30
+
31
+ - `Moleculer`-based framework for building microservices
32
+ - Use `NATS` transporter for high-performance message bus
33
+ - Use `Redpanda` transporter for persistent, robust, and scalable message bus with ACL support.
34
+ - In memory L1 cache and `Redis` cache for L2
35
+ - Schema validation using `AJV`
36
+ - Config-driven service initialization using `etcd`
37
+ - Create a `Demo` service to demonstrate the workflow
38
+ - Dynamically register Edge Services and Microservices
39
+ - Centralized error handling middleware
40
+ - Graceful shutdown handling `SIGINT`, `SIGTERM`
41
+
42
+ - REPL support for debugging
43
+ - Log shipping using agent like `fluentbit` to `OpenObserve`
44
+ - Metrics shipping using `Opentelemetry` to `OpenObserve`
45
+ - Token based access of restricted endpoints
46
+
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pnpm install samanbayaka
52
+ ```
53
+ Once the package is installed, you can import the library using import or require approach:
54
+ ```bash
55
+ import sbk from "samanbayaka"
56
+ ```
57
+ ## Prerequisites
58
+ It is assumed that `NATS`, `Redpanda`, `Redis`,`fluentbit`,`OpenObserve` and `etcd` are installed and properly configured. All services should be discoverable through the /etc/hosts file.
59
+ ### Minimum required Node.js version: >= 22.x.x
60
+ ```bash
61
+ node -v
62
+ nvm use 22
63
+ ```
64
+ Additionally, `OpenObserve` is used to view logs and telemetry and `fluentbit` for log shipping.
65
+
66
+ ### Environment variables
67
+
68
+
69
+ To connect to the etcd configuration server, the application requires the `SBK_CONFIG_CRED` environment variable. The etcd server listens on the default port 2379.
70
+
71
+ Export the environment variable before running the application.
72
+ ```bash
73
+ export SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>'
74
+ ```
75
+ or
76
+
77
+ To make the variable available across terminal sessions, add it to your shell configuration file.
78
+
79
+ Open your `.bashrc` file:
80
+ ```bash
81
+ nano ~/.bashrc
82
+ ```
83
+ Add the following line:
84
+ ```bash
85
+ export SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>'
86
+
87
+ ```
88
+ Save the file and reload the configuration:
89
+
90
+ ```bash
91
+ source ~/.bashrc
92
+ ```
93
+ or
94
+
95
+ You can provide the environment variable only for a single execution without exporting it.
96
+ ```bash
97
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' node index.mjs
98
+ ```
99
+
100
+
101
+ Optionally, you may verify the set environment variables.
102
+ ```bash
103
+ echo $SBK_CONFIG_CRED
104
+ ```
105
+ ### Configuration files
106
+ Create a directory to store the configuration files, then copy all configuration files from the current project path into this directory and update them as needed. Before copying, ensure that your current working directory is the project directory.
107
+ ```bash
108
+ pwd
109
+ sudo mkdir -p /usr/local/etc/<your_folder>
110
+ sudo cp config/*.*  /usr/local/etc/<your_folder>
111
+ ```
112
+ ### Log files
113
+ For production, it is recommended to create a new directory named <your_folder> under /var/log to store logs.
114
+ ```bash
115
+ sudo mkdir -p /var/log/<your_folder>
116
+ sudo chown -R $USER:$(id -gn) /var/log/<your_folder>
117
+ sudo chmod 755 /var/log/<your_folder>
118
+ ```
119
+ Optionally, you can clear the contents of the log files if they become too large by running:
120
+ ```bash
121
+ truncate -s 0 /var/log/<your_folder>/sbk-*.log
122
+ ```
123
+
124
+ ### Configure agent for log shipping
125
+ You can configure `fluentbit` as the log shipping agent to forward logs to `OpenObserve`. By default, `OpenObserve` listens on port `5080`. The `fluentbit` configuration is as follows:
126
+
127
+ Open /etc/fluent-bit/fluent-bit.conf and paste the following:
128
+ ```bash
129
+ [SERVICE]
130
+ Flush 1
131
+ Log_Level info
132
+ Daemon off
133
+ Parsers_File parsers.conf
134
+
135
+ [INPUT]
136
+ Name tail
137
+ Path /var/log/<your_folder>/*.log
138
+ Tag <your_tag_name>
139
+ DB /var/log/fluent-bit-tail.db
140
+ db.compare_filename True
141
+ Mem_Buf_Limit 50MB
142
+ Skip_Long_Lines On
143
+
144
+ [OUTPUT]
145
+ Name http
146
+ Match *
147
+ Host <your_openobserve_server_host>
148
+ Port <your_openobserve_server_port>
149
+ URI /api/default/<your_tag_name>/_json
150
+ HTTP_User <your_openobserve_user>
151
+ HTTP_Passwd <your_opeobserve_password>
152
+ Format json
153
+ Json_date_key time
154
+ Json_date_format iso8601
155
+ TLS off
156
+ compress gzip
157
+
158
+ ```
159
+
160
+
161
+ ### Setup logrotate (optional)
162
+ Create config file:
163
+ ```bash
164
+ sudo nano /etc/logrotate.d/sbk
165
+ ```
166
+ Paste this:
167
+ ```bash
168
+ /var/log/samanbayaka/sbk-*.log {
169
+ daily
170
+ rotate 14
171
+ compress
172
+ delaycompress
173
+ missingok
174
+ notifempty
175
+ copytruncate
176
+ create 0640 node node
177
+ }
178
+ ```
179
+ ### Setup SSL certificate for system endpoints
180
+ ```bash
181
+ openssl req -x509 -newkey rsa:2048 -nodes \
182
+ -keyout <your_filename>.key \
183
+ -out <your_filename>.crt \
184
+ -days 365
185
+ ```
186
+
187
+ ## Documentations
188
+
189
+ ### Errors
190
+
191
+ `sbk.Errors` exposes the Moleculer `Errors` object.
192
+
193
+ ### getConfigs
194
+
195
+ `sbk.getConfigs` is a function that returns a configuration object from a specific path of `etcd` server.
196
+
197
+
198
+ ### createDemo
199
+
200
+ `sbk.createDemo` is an asynchronous function that creates a demo service to help users understand the project.
201
+
202
+ ### registerSystemAPI
203
+
204
+ `sbk.registerSystemAPI` is an asynchronous function that registers a gateway service to expose REST APIs for system management. It is a mandatory service that must be registered for every project.
205
+
206
+
207
+ ### registerEdgeAPI
208
+
209
+ `sbk.registerEdgeAPI` is an asynchronous function that registers a gateway service to expose REST APIs for the underlying microservices.
210
+
211
+ ### registerServices
212
+
213
+ `sbk.registerServices` is an asynchronous function that registers microservices based on the business needs.
214
+
215
+ ##### Function Signature
216
+
217
+ ```js
218
+ sbk.registerServices(schema)
219
+ ```
220
+
221
+ ##### Parameter
222
+
223
+ * `schema` - An object that follows the Moleculer service schema structure.
224
+
225
+ Example:
226
+
227
+ ```js
228
+ {
229
+ name: "math",
230
+ actions: {
231
+ add: {
232
+ rest: {
233
+ method: "GET",
234
+ path: "/add"
235
+ },
236
+ openapi: {
237
+ summary: "addition",
238
+ description: "addition of two numbers",
239
+ parameters: [
240
+ {
241
+ name: "addend1",
242
+ in: "query",
243
+ description: "addend",
244
+ schema: {
245
+ type: "integer"
246
+ },
247
+ examples: [
248
+ 5,
249
+ 8
250
+ ],
251
+ },
252
+ {
253
+ name: "addend2",
254
+ in: "query",
255
+ description: "addend",
256
+ schema: {
257
+ type: "integer"
258
+ },
259
+ examples: [
260
+ 7,
261
+ 9
262
+ ],
263
+ },
264
+ ],
265
+ },
266
+ handler: async(ctx) =>{
267
+ return Number(ctx.params.query.addend1) + Number(ctx.params.query.addend2)
268
+ }
269
+ },
270
+ sub: {
271
+ rest: {
272
+ method: "POST",
273
+ path: "/sub"
274
+ },
275
+ openapi: {
276
+ summary: "substraction",
277
+ description: "substraction of two numbers",
278
+ parameters: [
279
+ {
280
+ name: "minuend",
281
+ in: "query",
282
+ description: "minuend",
283
+ schema: {
284
+ type: "integer"
285
+ },
286
+ examples: [
287
+ 15,
288
+ 18
289
+ ],
290
+ },
291
+ {
292
+ name: "subtrahend",
293
+ in: "query",
294
+ description: "subtrahend",
295
+ schema: {
296
+ type: "integer"
297
+ },
298
+ examples: [
299
+ 7,
300
+ 9
301
+ ],
302
+ },
303
+ ],
304
+ },
305
+ handler: async(ctx) =>{
306
+ return Number(ctx.params.query.minuend) - Number(ctx.params.query.subtrahend)
307
+ }
308
+ },
309
+ }
310
+ }
311
+ ```
312
+
313
+
314
+ ### registerBridgeServices
315
+
316
+ `sbk.registerBridgeServices` is an asynchronous function used to initialize and manage message brokers such as `Kafka`, `MQTT`, and `RabbitMQ`.
317
+
318
+ ##### Function Signature
319
+
320
+ ```js
321
+ sbk.registerBridgeServices(
322
+ type,
323
+ brokerOpts = {},
324
+ callback = () => {}
325
+ )
326
+ ```
327
+ ##### Parameters
328
+
329
+ * `type` *(string)* - Specifies the broker type to initialize. Supported values:
330
+
331
+ * `"kafka"`
332
+ * `"mqtt"`
333
+ * `"amqp"`
334
+
335
+ Example:
336
+
337
+ ```js
338
+ "kafka"
339
+ ```
340
+
341
+
342
+ * `brokerOpts` *(object)* - Configuration object used to initialize the broker client, producer, and consumer. Example structure:
343
+
344
+ ```js
345
+ {
346
+ name: <your_service_name>
347
+ client: {},
348
+ producer: {},
349
+ consumer: {
350
+ groupId: "all",
351
+ interMessageDelayMs: 10,
352
+ },
353
+ logLevel: "INFO",
354
+ gzip: true,
355
+ msgPack: true,
356
+ rest: false,
357
+ }
358
+ ```
359
+
360
+ Configuration Options
361
+
362
+ | Property | Type | Description |
363
+ |---|---|---|
364
+ | `name` | `string` | Only lowercase letters (a–z), digits (0–9), and hyphens (-) are allowed. |
365
+ | `client` | `object` | Broker client configuration |
366
+ | `producer` | `object` | Producer configuration |
367
+ | `consumer` | `object` | Consumer configuration |
368
+ | `consumer.groupId` | `string` | Consumer group identifier is mandatory for the consumer |
369
+ | `consumer.interMessageDelayMs` | `number` | Optional delay between messages in milliseconds |
370
+ | `logLevel` | `string` | Logging level (`NOTHING`, `ERROR`, `WARN`, `INFO`, `DEBUG`), default `NOTHING` |
371
+ | `gzip` | `boolean` | Enables message compression; only GZIP is supported, default `true` |
372
+ | `msgPack` | `boolean` | Enables MessagePack serialization, default `true` |
373
+ | `rest` | `boolean` | Enables REST end point, default `false` |
374
+
375
+
376
+ * `callback` *(function)* - Callback function executed when a message/event is received.
377
+
378
+ Arguments
379
+
380
+ | Argument | Description |
381
+ |---|---|
382
+ | `ctx` | Broker context |
383
+ | `payload` | Incoming message payload |
384
+
385
+ Example:
386
+
387
+ ```js
388
+ (ctx, payload) => {
389
+ ctx.broker.logger.debug(payload)
390
+ }
391
+ ```
392
+
393
+ ## Usage
394
+ ### Register gateway service
395
+ The `gateway` is a critical service that exposes all endpoints as REST APIs. At least one Gateway service must be running to make the REST APIs accessible.
396
+ ```bash
397
+ mkdir gateway
398
+ cd gateway
399
+ pnpm init
400
+ pnpm install samanbayaka
401
+ touch index.mjs
402
+ ```
403
+
404
+ Open `index.mjs` and paste the following:
405
+ ```bash
406
+ import sbk from "samanbayaka"
407
+ await sbk.registerEdgeAPI()
408
+ ```
409
+ ---
410
+ ### Register microservices
411
+ ```bash
412
+ mkdir <your_service_name>
413
+ cd <your_service_name>
414
+ pnpm init
415
+ pnpm install samanbayaka
416
+ touch index.mjs
417
+ ```
418
+
419
+ A microservice, such as `hello`, can be created as follows:
420
+ ```bash
421
+ mkdir hello
422
+ cd hello
423
+ pnpm init
424
+ pnpm install samanbayaka
425
+ touch index.mjs
426
+ ```
427
+
428
+ Open `index.mjs` and paste the following:
429
+ ```bash
430
+ import sbk from "samanbayaka"
431
+ await sbk.registerServices({
432
+ name: "hello",
433
+ version: "v1",
434
+
435
+ actions: {
436
+ hello: {
437
+ rest: {
438
+ method: "GET",
439
+ path: "/hello"
440
+ },
441
+
442
+ /**
443
+ * Enable caching to this action
444
+ */
445
+ cache: {
446
+
447
+ /**
448
+ * Cache entries expire after 30 seconds.
449
+ * For L1 caching, TTL should be defined as [L2_TTL, L1_TTL].
450
+ * Example: ttl: [60, 10] → L2 TTL is 60 seconds and L1 TTL is 10 seconds.
451
+ */
452
+ ttl: 30
453
+ },
454
+ handler(ctx){
455
+ return "Hello Samanbayaka"
456
+ }
457
+ },
458
+ welcome: {
459
+ rest: "GET /welcome",
460
+ handler(ctx) {
461
+ return `Welcome, ${ctx.params.query?.name || "Guest"} - ${ctx.broker.nodeID}`
462
+ }
463
+ },
464
+ },
465
+ })
466
+
467
+ ```
468
+ ---
469
+ ### Register bridge services
470
+ ##### for producer
471
+ ```bash
472
+ mkdir <your_service_name>-<type>-<topic>
473
+ cd <your_service_name>-<type>-<topic>
474
+ pnpm init
475
+ pnpm install samanbayaka
476
+ touch index.mjs
477
+ ```
478
+ An bridge service, such as a `producer` that publishes messages to the `STUDENT` topic, can be created as follows:
479
+ ```js
480
+ mkdir producer-kafka-student
481
+ cd producer-kafka-student
482
+ pnpm init
483
+ pnpm install samanbayaka
484
+ touch index.mjs
485
+ ```
486
+
487
+ Open `index.mjs` and paste the following:
488
+ ```bash
489
+ import sbk from "samanbayaka"
490
+ await sbk.registerBridgeServices(
491
+ "kafka",
492
+ {
493
+ name: "producer-kafka-student",
494
+ rest: true,
495
+ ...
496
+ },
497
+ () => {}
498
+ )
499
+ ```
500
+ In the service configuration `name` end with "`*`" i.e. `producer-kafka-student*` can capable to publish to the all topics start with `STUDENT` like `STUDENT.SCIENCE`, `STUDENT.ARTS` etc.
501
+ ```js
502
+ name: "producer-kafka-student*"
503
+ ```
504
+
505
+ If you do not expose the service as a REST API and run it as a private/internal service, either remove the `rest` property or set it to `false`.
506
+ ```js
507
+ rest: false
508
+ ```
509
+
510
+ #### for consumer
511
+ ```bash
512
+ mkdir <your_service_name>-<type>-<topic>-<group>
513
+ cd <your_service_name>-<type>-<topic>-<group>
514
+ pnpm init
515
+ pnpm install samanbayaka
516
+ touch index.mjs
517
+ ```
518
+ An bridge service, such as a `consumer` that subscribe messages from the `STUDENT` topic having group name `junior`, can be created as follows:
519
+ ```js
520
+ mkdir consumer-kafka-student-junior
521
+ cd consumer-kafka-student-junior
522
+ pnpm init
523
+ pnpm install samanbayaka
524
+ touch index.mjs
525
+ ```
526
+ Open `index.mjs` and paste the following:
527
+ ```bash
528
+ import sbk from "samanbayaka"
529
+ await sbk.registerBridgeServices(
530
+ "kafka",
531
+ {
532
+ name: "consumer-kafka-student",
533
+ consumer: {
534
+ groupId: "junior",
535
+ interMessageDelayMs: 10,
536
+ ...
537
+ },
538
+ ...
539
+ },
540
+ () => {}
541
+ )
542
+ ```
543
+ The `interMessageDelayMs` option introduces a delay between two consecutive message/event consumptions, measured in milliseconds. If you do not need any delay between message consumption, simply remove the `interMessageDelayMs` property from the consumer options.
544
+
545
+
546
+ ---
547
+
548
+ ### Run the services
549
+
550
+ * For development/testing environment
551
+
552
+ ```bash
553
+ cd <your_path>/gateway
554
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' node index.mjs
555
+ cd <your_path>/hello
556
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' node index.mjs
557
+ ```
558
+
559
+ * For production environment
560
+ ```bash
561
+ cd <your_path>/gateway
562
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
563
+ cd <your_path>/hello
564
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' node index.mjs >> /var/log/samanbayaka/sbk-${HOSTNAME}-$$.log 2>&1
565
+ ```
566
+ or
567
+ ```bash
568
+ cd <your_path>/gateway
569
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log
570
+ cd <your_path>/hello
571
+ SBK_CONFIG_CRED='<your_etcd_user> <your_etcd_pass> <your_etcd_port>' pm2 start index.mjs --name "$(basename "$PWD")" --stop-exit-codes 1 --output /var/log/samanbayaka/sbk-out-${HOSTNAME}-$$.log --error /var/log/samanbayaka/sbk-err-${HOSTNAME}-$$.log
572
+ ```
573
+
574
+ ## Demo
575
+ You can also run the demo service to better understand how microservices work in the Moleculer ecosystem and how REST APIs are exposed.
576
+ ```bash
577
+ mkdir demo
578
+ cd demo
579
+ pnpm init
580
+ pnpm install samanbayaka
581
+ touch demo.mjs
582
+ ```
583
+ Open and edit the `demo.mjs` file as follows
584
+ ```bash
585
+ import sbk from "samanbayaka"
586
+ await sbk.createDemo()
587
+ ```
588
+ Run the service, demo
589
+ ```bash
590
+ node demo.mjs
591
+ ```
592
+
593
+ ## Dockers
594
+
595
+ ### `etcd`
596
+ To manage configurations centrally, use the docker-compose.yml file to run `etcd` and all `.yml` configuration files must be deployed to /usr/local/etc/your_project_name.
597
+ ```bash
598
+ mkdir -p etcd
599
+ cd etcd
600
+ touch docker-compose.yml
601
+ export ETCD_ROOT_PW=<your_root_pass>
602
+ export ETCD_CONFIG_ADMIN_PW=<your_config_admin_pass>
603
+ sudo mkdir -p /usr/local/etc/<your_project_name>
604
+ ```
605
+
606
+ Open `docker-compose.yml` and paste the following:
607
+ ```yml
608
+ services:
609
+ etcd:
610
+ image: quay.io/coreos/etcd:v3.5.5
611
+ container_name: <your_container_name>
612
+
613
+ ports:
614
+ - "<your_api_port>:2379"
615
+ - "<your_cluster_port>:2380"
616
+
617
+ volumes:
618
+ - /usr/local/etc/<your_project_name>:/etcd-data
619
+
620
+ command:
621
+ - /usr/local/bin/etcd
622
+ - --name=etcd
623
+ - --data-dir=/etcd-data
624
+ - --listen-client-urls=http://0.0.0.0:2379
625
+ - --advertise-client-urls=http://etcd:2379
626
+ - --listen-peer-urls=http://0.0.0.0:2380
627
+ - --initial-advertise-peer-urls=http://etcd:2380
628
+ - --initial-cluster=etcd=http://etcd:2380
629
+ - --initial-cluster-state=new
630
+
631
+ restart: unless-stopped
632
+
633
+ etcd-init:
634
+ image: quay.io/coreos/etcd:v3.5.5
635
+ depends_on:
636
+ - etcd
637
+
638
+ volumes:
639
+ - /usr/local/etc/<your_project_name>:/etcd-data
640
+
641
+ environment:
642
+ - ETCDCTL_API=3
643
+
644
+ entrypoint:
645
+ - /bin/sh
646
+ - -c
647
+
648
+ command:
649
+ - |
650
+ set -e
651
+
652
+ echo "waiting for etcd..."
653
+
654
+ for i in $(seq 1 30); do
655
+ etcdctl --endpoints=http://etcd:2379 endpoint health && break
656
+ echo "retry $$i..."
657
+ sleep 2
658
+ done
659
+
660
+ echo "etcd initialized"
661
+
662
+ echo "Creating the root role"
663
+ etcdctl --endpoints=http://etcd:2379 role add root || true
664
+
665
+ echo "Creating the root user"
666
+ etcdctl --endpoints=http://etcd:2379 user add root:${ETCD_ROOT_PW} || true
667
+
668
+ echo "Granting the root role to the root user"
669
+ etcdctl --endpoints=http://etcd:2379 user grant-role root root
670
+
671
+ echo "Enable authentication"
672
+ etcdctl --endpoints=http://etcd:2379 auth enable || true
673
+
674
+ # -------------------------------------------------------
675
+
676
+ echo "Creating admin role"
677
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add admin
678
+
679
+ echo "Granting broad permissions"
680
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true admin readwrite /
681
+
682
+ echo "Creating configadmin user"
683
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add configadmin:${ETCD_CONFIG_ADMIN_PW}
684
+
685
+ echo "Assign role"
686
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role configadmin admin
687
+
688
+ # ---------------------------------------------------------
689
+
690
+ echo "Creating Roles and Granting"
691
+
692
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add default
693
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true default read /config/sbk/global/
694
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true default read /config/sbk/members/
695
+
696
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add edge
697
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true edge read /config/sbk/edge/
698
+
699
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add bridge
700
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true bridge read /config/sbk/bridge/
701
+
702
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add sap
703
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true sap read /config/sbk/sap/
704
+
705
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add dbs
706
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true dbs read /config/sbk/dbs/
707
+
708
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role add msg
709
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} role grant-permission --prefix=true msg read /config/sbk/msg/
710
+
711
+ # ---------------------------------------------------------
712
+
713
+ echo "Creating User and Assign Role"
714
+
715
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add sbk:<your_pass>
716
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role sbk default
717
+
718
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add apigw:<your_pass>
719
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role apigw default
720
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role apigw edge
721
+
722
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add msgbus:<your_pass>
723
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role msgbus default
724
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role msgbus bridge
725
+
726
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add sap:<your_pass>
727
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role sap default
728
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role sap sap
729
+
730
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add dbs:<your_pass>
731
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role dbs default
732
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role dbs dbs
733
+
734
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user add msg:<your_pass>
735
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role msg default
736
+ etcdctl --endpoints=http://etcd:2379 --user=root:${ETCD_ROOT_PW} user grant-role msg msg
737
+
738
+ # ---------------------------------------------------------
739
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sys/yaml/sysconfig "$(cat /etcd-data/sysconfig.yml)" || true
740
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sys/certs/SERVER_KEY "" || true
741
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sys/certs/SERVER_CRT "" || true
742
+
743
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/REVISION "" || true
744
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/APP_ENV development || true
745
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/LOG_LEVEL warn || true
746
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/MAX_L1_TTL 120 || true
747
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/MAX_L2_TTL 600 || true
748
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/envs/TELEMETRY false || true
749
+
750
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/broker/yaml/nats "$(cat /etcd-data/nats.yml)" || true
751
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/catcher/yaml/redis "$(cat /etcd-data/redis.yml)" || true
752
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/global/telemetry/yaml/openobserve "$(cat /etcd-data/openobserve.yml)" || true
753
+
754
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/yaml/auth "$(cat /etcd-data/auth.yml)" || true
755
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/yaml/roles "$(cat /etcd-data/roles.yml)" || true
756
+ #--------------------------------------------------
757
+ # regx pattern for allow corss site like
758
+ # abc.example.com, pqr.example.com
759
+ # and cors origins like abc.example1.com
760
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/edge/CORS "^(?:[a-zA-Z0-9-]+\\.)?(?:wbsedcl\\.in|wbsedcl\\.incom)$" || true
761
+
762
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/kafka "$(cat /etcd-data/kafka.yml)" || true
763
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/mqtt "$(cat /etcd-data/mqtt.yml)" || true
764
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/bridge/yaml/amqp "$(cat /etcd-data/amqp.yml)" || true
765
+
766
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sap/yaml/isu "$(cat /etcd-data/isu.yml)" || true
767
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/sap/yaml/erp "$(cat /etcd-data/erp.yml)" || true
768
+
769
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/gisdb "$(cat /etcd-data/gisdb.yml)" || true
770
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/geomdb "$(cat /etcd-data/geomdb.yml)" || true
771
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/acmadb "$(cat /etcd-data/acmadb.yml)" || true
772
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/isudb "$(cat /etcd-data/isudb.yml)" || true
773
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/crmdb "$(cat /etcd-data/crmdb.yml)" || true
774
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/mdasdb "$(cat /etcd-data/mdasdb.yml)" || true
775
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/route-sms "$(cat /etcd-data/route-sms.yml)" || true
776
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/route-otp "$(cat /etcd-data/route-otp.yml)" || true
777
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/dbs/pg/yaml/outlook "$(cat /etcd-data/outlook.yml)" || true
778
+
779
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/demo true || true
780
+
781
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system true || true
782
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/LOG_LEVEL error || true
783
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/MAX_L1_TTL 0 || true
784
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/system/envs/MAX_L2_TTL 0 || true
785
+
786
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/gateway true || true
787
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/gateway/envs/PORT 8765 || true
788
+
789
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/test true || true
790
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/sms add || true
791
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/email add || true
792
+ etcdctl --endpoints=http://etcd:2379 --user=configadmin:${ETCD_CONFIG_ADMIN_PW} put /config/sbk/members/dbs-pg-gisadmin add || true
793
+
794
+
795
+ #etcdctl --endpoints=http://etcd:2379 --user=<your_user>:<your_pass> get /config/sbk/ --prefix
796
+ #etcdctl --endpoints=http://etcd:2379 --user=<your_user>:<your_pass> get /config/sbk/global/app_env
797
+
798
+ echo "etcd initialization completed"
799
+ ```
800
+ Optionally verify:
801
+ ```bash
802
+ docker ps | grep '<your_container_name>'
803
+ ```
804
+ Optionally check health:
805
+ ```bash
806
+ docker exec -it <your_container_name> etcdctl --endpoints=http://etcd:2379 endpoint health
807
+ ```
808
+ ---
809
+
810
+ <p align="center" style="margin-top: 100px;">
811
+ <img src="https://moleculer.services/images/banner.png" alt="Moleculer Logo" width="600">
812
+ </p>