cyberia 3.0.3 → 3.2.5
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/{.env.production → .env.example} +20 -4
- package/.github/workflows/engine-cyberia.cd.yml +43 -10
- package/.github/workflows/engine-cyberia.ci.yml +48 -26
- package/.github/workflows/ghpkg.ci.yml +5 -5
- package/.github/workflows/gitlab.ci.yml +1 -1
- package/.github/workflows/hardhat.ci.yml +82 -0
- package/.github/workflows/npmpkg.ci.yml +60 -14
- package/.github/workflows/publish.ci.yml +26 -7
- package/.github/workflows/publish.cyberia.ci.yml +5 -5
- package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -7
- package/.github/workflows/pwa-microservices-template-test.ci.yml +4 -4
- package/.github/workflows/release.cd.yml +14 -8
- package/.vscode/extensions.json +9 -8
- package/.vscode/settings.json +3 -2
- package/CHANGELOG.md +643 -1
- package/CLI-HELP.md +132 -57
- package/Dockerfile +4 -2
- package/README.md +347 -22
- package/WHITE-PAPER.md +1540 -0
- package/bin/build.js +21 -12
- package/bin/cyberia.js +2640 -106
- package/bin/deploy.js +258 -372
- package/bin/file.js +5 -1
- package/bin/index.js +2640 -106
- package/bin/vs.js +3 -3
- package/conf.js +169 -105
- package/deployment.yaml +236 -20
- package/hardhat/.env.example +31 -0
- package/hardhat/README.md +531 -0
- package/hardhat/WHITE-PAPER.md +1540 -0
- package/hardhat/contracts/ObjectLayerToken.sol +391 -0
- package/hardhat/deployments/.gitkeep +0 -0
- package/hardhat/deployments/hardhat-ObjectLayerToken.json +11 -0
- package/hardhat/hardhat.config.js +136 -0
- package/hardhat/ignition/modules/ObjectLayerToken.js +21 -0
- package/hardhat/networks/besu-object-layer.network.json +138 -0
- package/hardhat/package-lock.json +4323 -0
- package/hardhat/package.json +36 -0
- package/hardhat/scripts/deployObjectLayerToken.js +98 -0
- package/hardhat/test/ObjectLayerToken.js +592 -0
- package/hardhat/types/ethers-contracts/ObjectLayerToken.ts +690 -0
- package/hardhat/types/ethers-contracts/common.ts +92 -0
- package/hardhat/types/ethers-contracts/factories/ObjectLayerToken__factory.ts +1055 -0
- package/hardhat/types/ethers-contracts/factories/index.ts +4 -0
- package/hardhat/types/ethers-contracts/hardhat.d.ts +47 -0
- package/hardhat/types/ethers-contracts/index.ts +6 -0
- package/jsdoc.dd-cyberia.json +68 -0
- package/jsdoc.json +65 -49
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -4
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +5 -4
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +562 -0
- package/manifests/deployment/dd-cyberia-development/proxy.yaml +297 -0
- package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +132 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +88 -74
- package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
- package/manifests/deployment/playwright/deployment.yaml +1 -1
- package/manifests/pv-pvc-dd.yaml +1 -1
- package/nodemon.json +1 -1
- package/package.json +60 -48
- package/proxy.yaml +118 -10
- package/pv-pvc.yaml +132 -0
- package/scripts/k3s-node-setup.sh +1 -1
- package/scripts/ports-ls.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +47 -1
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +17 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +5 -0
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +80 -7
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +93 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.model.js +36 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +29 -0
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +51 -0
- package/src/api/cyberia-entity/cyberia-entity.controller.js +74 -0
- package/src/api/cyberia-entity/cyberia-entity.model.js +24 -0
- package/src/api/cyberia-entity/cyberia-entity.router.js +27 -0
- package/src/api/cyberia-entity/cyberia-entity.service.js +42 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +368 -0
- package/src/api/cyberia-instance/cyberia-instance.controller.js +92 -0
- package/src/api/cyberia-instance/cyberia-instance.model.js +84 -0
- package/src/api/cyberia-instance/cyberia-instance.router.js +63 -0
- package/src/api/cyberia-instance/cyberia-instance.service.js +191 -0
- package/src/api/cyberia-instance/cyberia-portal-connector.js +486 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +74 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.defaults.js +413 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +228 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +27 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +42 -0
- package/src/api/cyberia-map/cyberia-map.controller.js +79 -0
- package/src/api/cyberia-map/cyberia-map.model.js +30 -0
- package/src/api/cyberia-map/cyberia-map.router.js +40 -0
- package/src/api/cyberia-map/cyberia-map.service.js +74 -0
- package/src/api/document/document.service.js +1 -1
- package/src/api/file/file.controller.js +3 -1
- package/src/api/file/file.ref.json +18 -0
- package/src/api/file/file.service.js +28 -5
- package/src/api/ipfs/ipfs.controller.js +4 -25
- package/src/api/ipfs/ipfs.model.js +43 -34
- package/src/api/ipfs/ipfs.router.js +8 -13
- package/src/api/ipfs/ipfs.service.js +56 -104
- package/src/api/object-layer/README.md +347 -22
- package/src/api/object-layer/object-layer.controller.js +6 -2
- package/src/api/object-layer/object-layer.model.js +12 -8
- package/src/api/object-layer/object-layer.router.js +698 -42
- package/src/api/object-layer/object-layer.service.js +119 -37
- package/src/api/object-layer-render-frames/object-layer-render-frames.model.js +1 -2
- package/src/api/user/user.router.js +10 -5
- package/src/api/user/user.service.js +15 -14
- package/src/cli/baremetal.js +6 -10
- package/src/cli/cloud-init.js +0 -3
- package/src/cli/cluster.js +7 -7
- package/src/cli/db.js +723 -857
- package/src/cli/deploy.js +215 -105
- package/src/cli/env.js +34 -5
- package/src/cli/fs.js +5 -4
- package/src/cli/image.js +0 -3
- package/src/cli/index.js +83 -15
- package/src/cli/kubectl.js +211 -0
- package/src/cli/monitor.js +5 -6
- package/src/cli/release.js +284 -0
- package/src/cli/repository.js +708 -62
- package/src/cli/run.js +371 -151
- package/src/cli/secrets.js +73 -2
- package/src/cli/ssh.js +1 -1
- package/src/cli/test.js +3 -3
- package/src/client/Cryptokoyn.index.js +3 -4
- package/src/client/CyberiaPortal.index.js +3 -4
- package/src/client/Default.index.js +3 -4
- package/src/client/Itemledger.index.js +4 -963
- package/src/client/Underpost.index.js +3 -4
- package/src/client/components/core/AgGrid.js +20 -5
- package/src/client/components/core/Alert.js +2 -2
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/CalendarCore.js +2 -2
- package/src/client/components/core/Content.js +22 -3
- package/src/client/components/core/Docs.js +30 -6
- package/src/client/components/core/DropDown.js +137 -17
- package/src/client/components/core/FileExplorer.js +71 -4
- package/src/client/components/core/Input.js +1 -1
- package/src/client/components/core/Keyboard.js +2 -2
- package/src/client/components/core/LogIn.js +2 -2
- package/src/client/components/core/LogOut.js +2 -2
- package/src/client/components/core/Modal.js +20 -7
- package/src/client/components/core/Panel.js +0 -1
- package/src/client/components/core/PanelForm.js +19 -19
- package/src/client/components/core/RichText.js +1 -2
- package/src/client/components/core/SocketIo.js +82 -29
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +143 -95
- package/src/client/components/core/Webhook.js +40 -7
- package/src/client/components/cryptokoyn/AppStoreCryptokoyn.js +5 -0
- package/src/client/components/cryptokoyn/LogInCryptokoyn.js +3 -3
- package/src/client/components/cryptokoyn/LogOutCryptokoyn.js +2 -2
- package/src/client/components/cryptokoyn/MenuCryptokoyn.js +3 -3
- package/src/client/components/cryptokoyn/SocketIoCryptokoyn.js +3 -51
- package/src/client/components/cyberia/InstanceEngineCyberia.js +700 -0
- package/src/client/components/cyberia/MapEngineCyberia.js +1359 -2
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +17 -6
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +92 -54
- package/src/client/components/cyberia-portal/AppStoreCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/CommonCyberiaPortal.js +217 -30
- package/src/client/components/cyberia-portal/CssCyberiaPortal.js +44 -2
- package/src/client/components/cyberia-portal/LogInCyberiaPortal.js +3 -4
- package/src/client/components/cyberia-portal/LogOutCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/MenuCyberiaPortal.js +104 -9
- package/src/client/components/cyberia-portal/RoutesCyberiaPortal.js +5 -0
- package/src/client/components/cyberia-portal/SocketIoCyberiaPortal.js +3 -49
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/LogInDefault.js +3 -3
- package/src/client/components/default/LogOutDefault.js +2 -2
- package/src/client/components/default/MenuDefault.js +5 -5
- package/src/client/components/default/SocketIoDefault.js +3 -51
- package/src/client/components/itemledger/AppStoreItemledger.js +5 -0
- package/src/client/components/itemledger/LogInItemledger.js +3 -3
- package/src/client/components/itemledger/LogOutItemledger.js +2 -2
- package/src/client/components/itemledger/MenuItemledger.js +3 -3
- package/src/client/components/itemledger/SocketIoItemledger.js +3 -51
- package/src/client/components/underpost/AppStoreUnderpost.js +5 -0
- package/src/client/components/underpost/CssUnderpost.js +59 -0
- package/src/client/components/underpost/LogInUnderpost.js +6 -3
- package/src/client/components/underpost/LogOutUnderpost.js +4 -2
- package/src/client/components/underpost/MenuUnderpost.js +104 -18
- package/src/client/components/underpost/RoutesUnderpost.js +2 -0
- package/src/client/components/underpost/SocketIoUnderpost.js +3 -51
- package/src/client/public/cryptokoyn/assets/logo/base-icon.png +0 -0
- package/src/client/public/cryptokoyn/browserconfig.xml +12 -0
- package/src/client/public/cryptokoyn/microdata.json +85 -0
- package/src/client/public/cryptokoyn/site.webmanifest +57 -0
- package/src/client/public/cryptokoyn/sitemap +3 -3
- package/src/client/public/default/sitemap +3 -3
- package/src/client/public/itemledger/browserconfig.xml +2 -2
- package/src/client/public/itemledger/manifest.webmanifest +4 -4
- package/src/client/public/itemledger/microdata.json +71 -0
- package/src/client/public/itemledger/sitemap +3 -3
- package/src/client/public/itemledger/yandex-browser-manifest.json +2 -2
- package/src/client/public/test/sitemap +3 -3
- package/src/client/services/core/core.service.js +20 -8
- package/src/client/services/cyberia-dialogue/cyberia-dialogue.service.js +105 -0
- package/src/client/services/cyberia-entity/cyberia-entity.management.js +57 -0
- package/src/client/services/cyberia-entity/cyberia-entity.service.js +105 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +194 -0
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +122 -0
- package/src/client/services/cyberia-instance-conf/cyberia-instance-conf.service.js +105 -0
- package/src/client/services/cyberia-map/cyberia-map.management.js +193 -0
- package/src/client/services/cyberia-map/cyberia-map.service.js +126 -0
- package/src/client/services/instance/instance.management.js +2 -2
- package/src/client/services/ipfs/ipfs.service.js +3 -23
- package/src/client/services/object-layer/object-layer.management.js +3 -3
- package/src/client/services/object-layer/object-layer.service.js +21 -0
- package/src/client/services/user/user.management.js +2 -2
- package/src/client/ssr/body/404.js +15 -11
- package/src/client/ssr/body/500.js +15 -11
- package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
- package/src/client/ssr/head/PwaItemledger.js +60 -0
- package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
- package/src/client/ssr/pages/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/pages/Test.js +11 -10
- package/src/client.build.js +0 -3
- package/src/client.dev.js +0 -3
- package/src/db/DataBaseProvider.js +17 -2
- package/src/db/mariadb/MariaDB.js +14 -9
- package/src/db/mongo/MongooseDB.js +17 -1
- package/src/grpc/cyberia/OFF_CHAIN_ECONOMY.md +305 -0
- package/src/grpc/cyberia/README.md +326 -0
- package/src/grpc/cyberia/grpc-server.js +530 -0
- package/src/index.js +24 -1
- package/src/proxy.js +0 -3
- package/src/runtime/express/Dockerfile +4 -0
- package/src/runtime/express/Express.js +33 -10
- package/src/runtime/lampp/Dockerfile +13 -2
- package/src/runtime/lampp/Lampp.js +33 -17
- package/src/runtime/wp/Dockerfile +68 -0
- package/src/runtime/wp/Wp.js +639 -0
- package/src/server/auth.js +36 -15
- package/src/server/backup.js +39 -12
- package/src/server/besu-genesis-generator.js +1630 -0
- package/src/server/client-build-docs.js +133 -17
- package/src/server/client-build-live.js +9 -18
- package/src/server/client-build.js +229 -101
- package/src/server/client-dev-server.js +14 -13
- package/src/server/client-formatted.js +109 -57
- package/src/server/conf.js +391 -164
- package/src/server/cron.js +27 -24
- package/src/server/dns.js +29 -12
- package/src/server/downloader.js +0 -2
- package/src/server/ipfs-client.js +24 -1
- package/src/server/logger.js +27 -9
- package/src/server/object-layer.js +217 -103
- package/src/server/peer.js +8 -2
- package/src/server/process.js +1 -50
- package/src/server/proxy.js +4 -8
- package/src/server/runtime.js +30 -9
- package/src/server/semantic-layer-generator-floor.js +359 -0
- package/src/server/semantic-layer-generator-skin.js +1294 -0
- package/src/server/semantic-layer-generator.js +116 -555
- package/src/server/ssr.js +0 -3
- package/src/server/start.js +19 -12
- package/src/server/tls.js +0 -2
- package/src/server.js +0 -4
- package/src/ws/IoInterface.js +1 -10
- package/src/ws/IoServer.js +14 -33
- package/src/ws/core/channels/core.ws.chat.js +65 -20
- package/src/ws/core/channels/core.ws.mailer.js +113 -32
- package/src/ws/core/channels/core.ws.stream.js +90 -31
- package/src/ws/core/core.ws.connection.js +12 -33
- package/src/ws/core/core.ws.emit.js +10 -26
- package/src/ws/core/core.ws.server.js +25 -58
- package/src/ws/default/channels/default.ws.main.js +53 -12
- package/src/ws/default/default.ws.connection.js +26 -13
- package/src/ws/default/default.ws.server.js +30 -12
- package/.env.development +0 -43
- package/.env.test +0 -43
- package/hardhat/contracts/CryptoKoyn.sol +0 -59
- package/hardhat/contracts/ItemLedger.sol +0 -73
- package/hardhat/contracts/Lock.sol +0 -34
- package/hardhat/hardhat.config.cjs +0 -45
- package/hardhat/ignition/modules/Lock.js +0 -18
- package/hardhat/networks/cryptokoyn-itemledger.network.json +0 -29
- package/hardhat/scripts/deployCryptokoyn.cjs +0 -25
- package/hardhat/scripts/deployItemledger.cjs +0 -25
- package/hardhat/test/Lock.js +0 -126
- package/hardhat/white-paper.md +0 -581
- package/src/client/components/cryptokoyn/CommonCryptokoyn.js +0 -29
- package/src/client/components/cryptokoyn/ElementsCryptokoyn.js +0 -38
- package/src/client/components/cyberia-portal/ElementsCyberiaPortal.js +0 -38
- package/src/client/components/default/ElementsDefault.js +0 -38
- package/src/client/components/itemledger/CommonItemledger.js +0 -29
- package/src/client/components/itemledger/ElementsItemledger.js +0 -38
- package/src/client/components/underpost/CommonUnderpost.js +0 -29
- package/src/client/components/underpost/ElementsUnderpost.js +0 -38
- package/src/ws/core/management/core.ws.chat.js +0 -8
- package/src/ws/core/management/core.ws.mailer.js +0 -16
- package/src/ws/core/management/core.ws.stream.js +0 -8
- package/src/ws/default/management/default.ws.main.js +0 -8
- package/white-paper.md +0 -581
package/src/cli/deploy.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Config,
|
|
12
12
|
deployRangePortFactory,
|
|
13
13
|
getDataDeploy,
|
|
14
|
+
loadConfServerJson,
|
|
14
15
|
loadReplicas,
|
|
15
16
|
pathPortAssignmentFactory,
|
|
16
17
|
} from '../server/conf.js';
|
|
@@ -131,22 +132,16 @@ class UnderpostDeploy {
|
|
|
131
132
|
cmd = [
|
|
132
133
|
`npm install -g npm@11.2.0`,
|
|
133
134
|
`npm install -g underpost`,
|
|
134
|
-
`underpost secret underpost --create-from-
|
|
135
|
-
`underpost start --build --run
|
|
135
|
+
`underpost secret underpost --create-from-env`,
|
|
136
|
+
`underpost start --build --run ${deployId} ${env}`,
|
|
136
137
|
];
|
|
137
138
|
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
138
|
-
if (!volumes)
|
|
139
|
-
volumes = [
|
|
140
|
-
{
|
|
141
|
-
volumeMountPath: '/etc/config',
|
|
142
|
-
volumeName: 'config-volume',
|
|
143
|
-
configMap: 'underpost-config',
|
|
144
|
-
},
|
|
145
|
-
];
|
|
139
|
+
if (!volumes) volumes = [];
|
|
146
140
|
const confVolume = fs.existsSync(`./engine-private/conf/${deployId}/conf.volume.json`)
|
|
147
141
|
? JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.volume.json`, 'utf8'))
|
|
148
142
|
: [];
|
|
149
143
|
volumes = volumes.concat(confVolume);
|
|
144
|
+
const containerImage = image ? image : `localhost/rockylinux9-underpost:v${packageJson.version}`;
|
|
150
145
|
return `apiVersion: apps/v1
|
|
151
146
|
kind: Deployment
|
|
152
147
|
metadata:
|
|
@@ -154,6 +149,7 @@ metadata:
|
|
|
154
149
|
namespace: ${namespace ? namespace : 'default'}
|
|
155
150
|
labels:
|
|
156
151
|
app: ${deployId}-${env}-${suffix}
|
|
152
|
+
deploy-id: ${deployId}-${env}
|
|
157
153
|
spec:
|
|
158
154
|
replicas: ${replicas}
|
|
159
155
|
selector:
|
|
@@ -163,10 +159,14 @@ spec:
|
|
|
163
159
|
metadata:
|
|
164
160
|
labels:
|
|
165
161
|
app: ${deployId}-${env}-${suffix}
|
|
162
|
+
deploy-id: ${deployId}-${env}
|
|
166
163
|
spec:
|
|
167
164
|
containers:
|
|
168
165
|
- name: ${deployId}-${env}-${suffix}
|
|
169
|
-
image: ${
|
|
166
|
+
image: ${containerImage}
|
|
167
|
+
envFrom:
|
|
168
|
+
- secretRef:
|
|
169
|
+
name: underpost-config
|
|
170
170
|
${
|
|
171
171
|
resources
|
|
172
172
|
? ` resources:
|
|
@@ -182,13 +182,17 @@ ${
|
|
|
182
182
|
- /bin/sh
|
|
183
183
|
- -c
|
|
184
184
|
- >
|
|
185
|
-
${cmd.join(
|
|
185
|
+
${cmd.join(' &&\n ')}
|
|
186
186
|
|
|
187
|
-
${
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
187
|
+
${
|
|
188
|
+
volumes.length > 0
|
|
189
|
+
? Underpost.deploy
|
|
190
|
+
.volumeFactory(volumes.map((v) => ((v.version = `${deployId}-${env}-${suffix}`), v)))
|
|
191
|
+
.render.split(`\n`)
|
|
192
|
+
.map((l) => ' ' + l)
|
|
193
|
+
.join(`\n`)
|
|
194
|
+
: ''
|
|
195
|
+
}
|
|
192
196
|
---
|
|
193
197
|
apiVersion: v1
|
|
194
198
|
kind: Service
|
|
@@ -230,7 +234,7 @@ spec:
|
|
|
230
234
|
if (!deployId) continue;
|
|
231
235
|
const confServer = loadReplicas(
|
|
232
236
|
deployId,
|
|
233
|
-
|
|
237
|
+
loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`),
|
|
234
238
|
);
|
|
235
239
|
const router = await Underpost.deploy.routerFactory(deployId, env);
|
|
236
240
|
const pathPortAssignmentData = await pathPortAssignmentFactory(deployId, router, confServer);
|
|
@@ -259,6 +263,35 @@ ${Underpost.deploy
|
|
|
259
263
|
}
|
|
260
264
|
fs.writeFileSync(`./engine-private/conf/${deployId}/build/${env}/deployment.yaml`, deploymentYamlParts, 'utf8');
|
|
261
265
|
|
|
266
|
+
Underpost.deploy.buildGrpcServiceManifest({
|
|
267
|
+
deployId,
|
|
268
|
+
env,
|
|
269
|
+
confServer,
|
|
270
|
+
namespace: options.namespace,
|
|
271
|
+
traffic: options.traffic && typeof options.traffic === 'string' ? options.traffic.split(',') : ['blue'],
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const confVolume = fs.existsSync(`./engine-private/conf/${deployId}/conf.volume.json`)
|
|
275
|
+
? JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.volume.json`, 'utf8'))
|
|
276
|
+
: [];
|
|
277
|
+
if (confVolume.length > 0) {
|
|
278
|
+
let volumeYaml = '';
|
|
279
|
+
for (const deploymentVersion of deploymentVersions) {
|
|
280
|
+
for (const volume of confVolume) {
|
|
281
|
+
if (!volume.claimName) continue;
|
|
282
|
+
const pvcId = `${volume.claimName}-${deployId}-${env}-${deploymentVersion}`;
|
|
283
|
+
const pvId = pvcId.replace(/^pvc-/, 'pv-');
|
|
284
|
+
const hostPath = `/home/dd/engine/volume/${pvId}`;
|
|
285
|
+
volumeYaml += `---\n${Underpost.deploy.persistentVolumeFactory({
|
|
286
|
+
pvcId,
|
|
287
|
+
namespace: options.namespace,
|
|
288
|
+
hostPath,
|
|
289
|
+
})}\n`;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
fs.writeFileSync(`./engine-private/conf/${deployId}/build/${env}/pv-pvc.yaml`, volumeYaml, 'utf8');
|
|
293
|
+
}
|
|
294
|
+
|
|
262
295
|
let proxyYaml = '';
|
|
263
296
|
let secretYaml = '';
|
|
264
297
|
const customServices = fs.existsSync(`./engine-private/conf/${deployId}/conf.services.json`)
|
|
@@ -335,7 +368,7 @@ ${Underpost.deploy
|
|
|
335
368
|
const yamlPath = `./engine-private/conf/${deployId}/build/${env}/secret.yaml`;
|
|
336
369
|
fs.writeFileSync(yamlPath, secretYaml, 'utf8');
|
|
337
370
|
} else {
|
|
338
|
-
const deploymentsFiles = ['Dockerfile', 'proxy.yaml', 'deployment.yaml'];
|
|
371
|
+
const deploymentsFiles = ['Dockerfile', 'proxy.yaml', 'deployment.yaml', 'pv-pvc.yaml'];
|
|
339
372
|
for (const file of deploymentsFiles) {
|
|
340
373
|
if (fs.existsSync(`./engine-private/conf/${deployId}/build/${env}/${file}`)) {
|
|
341
374
|
fs.copyFileSync(
|
|
@@ -347,6 +380,67 @@ ${Underpost.deploy
|
|
|
347
380
|
}
|
|
348
381
|
}
|
|
349
382
|
},
|
|
383
|
+
/**
|
|
384
|
+
* Builds and writes a gRPC ClusterIP service YAML for a deployment.
|
|
385
|
+
* Scans conf.server.json for gRPC ports and emits grpc-service.yaml under
|
|
386
|
+
* `engine-private/conf/<deployId>/build/<env>/`. The selector always uses the
|
|
387
|
+
* explicit `app: <deployId>-<env>-<traffic>` label to target only the active
|
|
388
|
+
* colour (blue or green).
|
|
389
|
+
* @param {string} deployId - Deployment ID.
|
|
390
|
+
* @param {string} env - Environment ('development' or 'production').
|
|
391
|
+
* @param {object} confServer - Parsed conf.server.json content.
|
|
392
|
+
* @param {string} [namespace='default'] - Kubernetes namespace.
|
|
393
|
+
* @param {string[]} [traffic=['blue']] - Active traffic colour(s) ('blue', 'green', or both).
|
|
394
|
+
* @param {string|null} [host=null] - Specific host to scan for gRPC ports. If null, all hosts are scanned.
|
|
395
|
+
* @returns {string|null} - Path to the written YAML file, or null if no gRPC ports found.
|
|
396
|
+
* @memberof UnderpostDeploy
|
|
397
|
+
*/
|
|
398
|
+
buildGrpcServiceManifest({ deployId, env, confServer, namespace = 'default', traffic = ['blue'], host = null }) {
|
|
399
|
+
const grpcPorts = new Set();
|
|
400
|
+
const hostsToScan = host ? [host] : Object.keys(confServer);
|
|
401
|
+
for (const h of hostsToScan) {
|
|
402
|
+
if (!confServer[h]) continue;
|
|
403
|
+
for (const path of Object.keys(confServer[h])) {
|
|
404
|
+
const grpc = confServer[h][path].grpc;
|
|
405
|
+
if (grpc && grpc.port) grpcPorts.add(parseInt(grpc.port));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (grpcPorts.size === 0) return null;
|
|
409
|
+
const grpcPortsList = [...grpcPorts]
|
|
410
|
+
.map(
|
|
411
|
+
(port) => ` - name: grpc-${port}
|
|
412
|
+
protocol: TCP
|
|
413
|
+
port: ${port}
|
|
414
|
+
targetPort: ${port}`,
|
|
415
|
+
)
|
|
416
|
+
.join('\n');
|
|
417
|
+
let grpcServiceYaml = '';
|
|
418
|
+
for (const color of traffic) {
|
|
419
|
+
const grpcServiceName = `${deployId}-grpc-service-${env}-${color}`;
|
|
420
|
+
const selectorYaml = `app: ${deployId}-${env}-${color}`;
|
|
421
|
+
grpcServiceYaml += `---
|
|
422
|
+
apiVersion: v1
|
|
423
|
+
kind: Service
|
|
424
|
+
metadata:
|
|
425
|
+
name: ${grpcServiceName}
|
|
426
|
+
namespace: ${namespace}
|
|
427
|
+
labels:
|
|
428
|
+
app: ${grpcServiceName}
|
|
429
|
+
spec:
|
|
430
|
+
type: ClusterIP
|
|
431
|
+
selector:
|
|
432
|
+
${selectorYaml}
|
|
433
|
+
ports:
|
|
434
|
+
${grpcPortsList}
|
|
435
|
+
`;
|
|
436
|
+
logger.info(
|
|
437
|
+
`gRPC ClusterIP service YAML written: ${grpcServiceName} (selector: ${selectorYaml}, ports: ${[...grpcPorts].join(', ')})`,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
const yamlPath = `./engine-private/conf/${deployId}/build/${env}/grpc-service.yaml`;
|
|
441
|
+
fs.writeFileSync(yamlPath, grpcServiceYaml, 'utf8');
|
|
442
|
+
return yamlPath;
|
|
443
|
+
},
|
|
350
444
|
/**
|
|
351
445
|
* Builds a Certificate resource for a host using cert-manager.
|
|
352
446
|
* @param {string} host - Hostname for which the certificate is being built.
|
|
@@ -385,7 +479,7 @@ spec:
|
|
|
385
479
|
// kubectl get deploy,sts,svc,configmap,secret -n default -o yaml --export > default.yaml
|
|
386
480
|
const hostTest = options?.hostTest
|
|
387
481
|
? options.hostTest
|
|
388
|
-
: Object.keys(
|
|
482
|
+
: Object.keys(loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`))[0];
|
|
389
483
|
const info = shellExec(`sudo kubectl get HTTPProxy/${hostTest} -n ${options.namespace} -o yaml`, {
|
|
390
484
|
silent: true,
|
|
391
485
|
stdout: true,
|
|
@@ -456,6 +550,10 @@ spec:
|
|
|
456
550
|
* @param {string} [options.kindType] - Type of Kubernetes resource to retrieve information for.
|
|
457
551
|
* @param {number} [options.port] - Port number for exposing the deployment.
|
|
458
552
|
* @param {string} [options.cmd] - Custom initialization command for deploymentYamlPartsFactory (comma-separated commands).
|
|
553
|
+
* @param {boolean} [options.k3s] - Whether to use k3s cluster context.
|
|
554
|
+
* @param {boolean} [options.kubeadm] - Whether to use kubeadm cluster context.
|
|
555
|
+
* @param {boolean} [options.kind] - Whether to use kind cluster context.
|
|
556
|
+
* @param {boolean} [options.gitClean] - Whether to run git clean on volume mount paths before copying.
|
|
459
557
|
* @returns {Promise<void>} - Promise that resolves when the deployment process is complete.
|
|
460
558
|
* @memberof UnderpostDeploy
|
|
461
559
|
*/
|
|
@@ -493,6 +591,10 @@ spec:
|
|
|
493
591
|
port: 0,
|
|
494
592
|
exposePort: 0,
|
|
495
593
|
cmd: '',
|
|
594
|
+
k3s: false,
|
|
595
|
+
kubeadm: false,
|
|
596
|
+
kind: false,
|
|
597
|
+
gitClean: false,
|
|
496
598
|
},
|
|
497
599
|
) {
|
|
498
600
|
const namespace = options.namespace ? options.namespace : 'default';
|
|
@@ -531,7 +633,7 @@ EOF`);
|
|
|
531
633
|
env,
|
|
532
634
|
traffic: Underpost.deploy.getCurrentTraffic(deployId, { namespace }),
|
|
533
635
|
router: await Underpost.deploy.routerFactory(deployId, env),
|
|
534
|
-
pods: await Underpost.
|
|
636
|
+
pods: await Underpost.kubectl.get(deployId),
|
|
535
637
|
instances,
|
|
536
638
|
});
|
|
537
639
|
}
|
|
@@ -550,7 +652,7 @@ EOF`);
|
|
|
550
652
|
if (!(options.versions && typeof options.versions === 'string')) options.versions = 'blue,green';
|
|
551
653
|
if (!options.replicas) options.replicas = 1;
|
|
552
654
|
if (options.sync)
|
|
553
|
-
getDataDeploy({
|
|
655
|
+
await getDataDeploy({
|
|
554
656
|
buildSingleReplica: true,
|
|
555
657
|
});
|
|
556
658
|
if (options.buildManifest === true) await Underpost.deploy.buildManifest(deployList, env, options);
|
|
@@ -573,7 +675,7 @@ EOF`);
|
|
|
573
675
|
if (!deployId) continue;
|
|
574
676
|
if (options.expose === true) {
|
|
575
677
|
const kindType = options.kindType ? options.kindType : 'svc';
|
|
576
|
-
const svc = Underpost.
|
|
678
|
+
const svc = Underpost.kubectl.get(deployId, kindType)[0];
|
|
577
679
|
const port = options.exposePort
|
|
578
680
|
? parseInt(options.exposePort)
|
|
579
681
|
: options.port
|
|
@@ -591,7 +693,7 @@ EOF`);
|
|
|
591
693
|
continue;
|
|
592
694
|
}
|
|
593
695
|
|
|
594
|
-
const confServer =
|
|
696
|
+
const confServer = loadConfServerJson(`./engine-private/conf/${deployId}/conf.server.json`);
|
|
595
697
|
const confVolume = fs.existsSync(`./engine-private/conf/${deployId}/conf.volume.json`)
|
|
596
698
|
? JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.volume.json`, 'utf8'))
|
|
597
699
|
: [];
|
|
@@ -612,6 +714,8 @@ EOF`);
|
|
|
612
714
|
version,
|
|
613
715
|
namespace,
|
|
614
716
|
nodeName: options.node ? options.node : env === 'development' ? 'kind-worker' : os.hostname(),
|
|
717
|
+
clusterContext: options.k3s ? 'k3s' : options.kubeadm ? 'kubeadm' : 'kind',
|
|
718
|
+
gitClean: options.gitClean || false,
|
|
615
719
|
});
|
|
616
720
|
}
|
|
617
721
|
|
|
@@ -630,8 +734,11 @@ EOF`);
|
|
|
630
734
|
: `manifests/deployment/${deployId}-${env}`;
|
|
631
735
|
|
|
632
736
|
if (!options.remove) {
|
|
633
|
-
if (!options.disableUpdateDeployment)
|
|
737
|
+
if (!options.disableUpdateDeployment) {
|
|
634
738
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml -n ${namespace}`);
|
|
739
|
+
const grpcServicePath = `./${manifestsPath}/grpc-service.yaml`;
|
|
740
|
+
if (fs.existsSync(grpcServicePath)) shellExec(`sudo kubectl apply -f ${grpcServicePath} -n ${namespace}`);
|
|
741
|
+
}
|
|
635
742
|
if (!options.disableUpdateProxy)
|
|
636
743
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml -n ${namespace}`);
|
|
637
744
|
|
|
@@ -649,65 +756,6 @@ EOF`);
|
|
|
649
756
|
` + renderHosts,
|
|
650
757
|
);
|
|
651
758
|
},
|
|
652
|
-
/**
|
|
653
|
-
* Retrieves information about a deployment.
|
|
654
|
-
* @param {string} deployId - Deployment ID for which information is being retrieved.
|
|
655
|
-
* @param {string} kindType - Type of Kubernetes resource to retrieve information for (e.g. 'pods').
|
|
656
|
-
* @param {string} namespace - Kubernetes namespace to retrieve information from.
|
|
657
|
-
* @returns {Array<object>} - Array of objects containing information about the deployment.
|
|
658
|
-
* @memberof UnderpostDeploy
|
|
659
|
-
*/
|
|
660
|
-
get(deployId, kindType = 'pods', namespace = '') {
|
|
661
|
-
const raw = shellExec(
|
|
662
|
-
`sudo kubectl get ${kindType}${namespace ? ` -n ${namespace}` : ` --all-namespaces`} -o wide`,
|
|
663
|
-
{
|
|
664
|
-
stdout: true,
|
|
665
|
-
disableLog: true,
|
|
666
|
-
silent: true,
|
|
667
|
-
},
|
|
668
|
-
);
|
|
669
|
-
|
|
670
|
-
const heads = raw
|
|
671
|
-
.split(`\n`)[0]
|
|
672
|
-
.split(' ')
|
|
673
|
-
.filter((_r) => _r.trim());
|
|
674
|
-
|
|
675
|
-
const pods = raw
|
|
676
|
-
.split(`\n`)
|
|
677
|
-
.filter((r) => (deployId ? r.match(deployId) : r.trim() && !r.match('NAME')))
|
|
678
|
-
.map((r) => r.split(' ').filter((_r) => _r.trim()));
|
|
679
|
-
|
|
680
|
-
const result = [];
|
|
681
|
-
|
|
682
|
-
for (const row of pods) {
|
|
683
|
-
const pod = {};
|
|
684
|
-
let index = -1;
|
|
685
|
-
for (const head of heads) {
|
|
686
|
-
index++;
|
|
687
|
-
pod[head] = row[index];
|
|
688
|
-
}
|
|
689
|
-
result.push(pod);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
return result;
|
|
693
|
-
},
|
|
694
|
-
|
|
695
|
-
/**
|
|
696
|
-
* Checks if a container file exists in a pod.
|
|
697
|
-
* @param {object} options - Options for the check.
|
|
698
|
-
* @param {string} options.podName - Name of the pod to check.
|
|
699
|
-
* @param {string} options.path - Path to the container file to check.
|
|
700
|
-
* @returns {boolean} - True if the container file exists, false otherwise.
|
|
701
|
-
* @memberof UnderpostDeploy
|
|
702
|
-
*/
|
|
703
|
-
existsContainerFile({ podName, path }) {
|
|
704
|
-
const result = shellExec(`kubectl exec ${podName} -- test -f ${path} && echo "true" || echo "false"`, {
|
|
705
|
-
stdout: true,
|
|
706
|
-
disableLog: true,
|
|
707
|
-
silent: true,
|
|
708
|
-
}).trim();
|
|
709
|
-
return result === 'true';
|
|
710
|
-
},
|
|
711
759
|
/**
|
|
712
760
|
* Checks the status of a deployment.
|
|
713
761
|
* @param {string} deployId - Deployment ID for which the status is being checked.
|
|
@@ -720,7 +768,7 @@ EOF`);
|
|
|
720
768
|
*/
|
|
721
769
|
async checkDeploymentReadyStatus(deployId, env, traffic, ignoresNames = [], namespace = 'default') {
|
|
722
770
|
const cmd = `underpost config get container-status`;
|
|
723
|
-
const pods = Underpost.
|
|
771
|
+
const pods = Underpost.kubectl.get(`${deployId}-${env}-${traffic}`, 'pods', namespace);
|
|
724
772
|
const readyPods = [];
|
|
725
773
|
const notReadyPods = [];
|
|
726
774
|
for (const pod of pods) {
|
|
@@ -746,15 +794,16 @@ EOF`);
|
|
|
746
794
|
};
|
|
747
795
|
},
|
|
748
796
|
/**
|
|
749
|
-
* Creates a
|
|
750
|
-
*
|
|
751
|
-
* @param {string}
|
|
797
|
+
* Creates a Kubernetes Secret for a deployment (replaces configMap for secret data).
|
|
798
|
+
* Secrets are mounted as tmpfs (never written to node disk) and support RBAC restrictions.
|
|
799
|
+
* @param {string} env - Environment for which the secret is being created.
|
|
800
|
+
* @param {string} [namespace='default'] - Kubernetes namespace for the secret.
|
|
752
801
|
* @memberof UnderpostDeploy
|
|
753
802
|
*/
|
|
754
803
|
configMap(env, namespace = 'default') {
|
|
755
|
-
shellExec(`kubectl delete
|
|
804
|
+
shellExec(`kubectl delete secret underpost-config -n ${namespace} --ignore-not-found`);
|
|
756
805
|
shellExec(
|
|
757
|
-
`kubectl create
|
|
806
|
+
`kubectl create secret generic underpost-config --from-env-file=/home/dd/engine/engine-private/conf/dd-cron/.env.${env} --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
|
|
758
807
|
);
|
|
759
808
|
},
|
|
760
809
|
/**
|
|
@@ -792,6 +841,9 @@ EOF`);
|
|
|
792
841
|
|
|
793
842
|
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml -n ${namespace}`);
|
|
794
843
|
|
|
844
|
+
const grpcServicePath = `./engine-private/conf/${deployId}/build/${env}/grpc-service.yaml`;
|
|
845
|
+
if (fs.existsSync(grpcServicePath)) shellExec(`kubectl apply -f ${grpcServicePath} -n ${namespace}`);
|
|
846
|
+
|
|
795
847
|
Underpost.env.set(`${deployId}-${env}-traffic`, targetTraffic);
|
|
796
848
|
},
|
|
797
849
|
|
|
@@ -807,6 +859,8 @@ EOF`);
|
|
|
807
859
|
* @param {string} options.version - Version of the deployment.
|
|
808
860
|
* @param {string} options.namespace - Kubernetes namespace for the deployment.
|
|
809
861
|
* @param {string} options.nodeName - Node name for the deployment.
|
|
862
|
+
* @param {string} [options.clusterContext='kind'] - Cluster context type ('kind', 'kubeadm', or 'k3s').
|
|
863
|
+
* @param {boolean} [options.gitClean=false] - Whether to run git clean on volumeMountPath before copying.
|
|
810
864
|
* @memberof UnderpostDeploy
|
|
811
865
|
*/
|
|
812
866
|
deployVolume(
|
|
@@ -817,6 +871,8 @@ EOF`);
|
|
|
817
871
|
version: '',
|
|
818
872
|
namespace: '',
|
|
819
873
|
nodeName: '',
|
|
874
|
+
clusterContext: 'kind',
|
|
875
|
+
gitClean: false,
|
|
820
876
|
},
|
|
821
877
|
) {
|
|
822
878
|
if (!volume.claimName) {
|
|
@@ -824,19 +880,26 @@ EOF`);
|
|
|
824
880
|
return;
|
|
825
881
|
}
|
|
826
882
|
const { deployId, env, version, namespace } = options;
|
|
883
|
+
const clusterContext = options.clusterContext || 'kind';
|
|
827
884
|
const pvcId = `${volume.claimName}-${deployId}-${env}-${version}`;
|
|
828
885
|
const pvId = `${volume.claimName.replace('pvc-', 'pv-')}-${deployId}-${env}-${version}`;
|
|
829
886
|
const rootVolumeHostPath = `/home/dd/engine/volume/${pvId}`;
|
|
887
|
+
if (options.gitClean && volume.volumeMountPath) {
|
|
888
|
+
Underpost.repo.clean({ paths: [volume.volumeMountPath] });
|
|
889
|
+
}
|
|
830
890
|
if (options.nodeName) {
|
|
831
891
|
if (!fs.existsSync(rootVolumeHostPath)) fs.mkdirSync(rootVolumeHostPath, { recursive: true });
|
|
832
892
|
fs.copySync(volume.volumeMountPath, rootVolumeHostPath);
|
|
833
|
-
} else {
|
|
893
|
+
} else if (clusterContext === 'kind') {
|
|
834
894
|
shellExec(`docker exec -i kind-worker bash -c "mkdir -p ${rootVolumeHostPath}"`);
|
|
835
895
|
// shellExec(`docker cp ${volume.volumeMountPath} kind-worker:${rootVolumeHostPath}`);
|
|
836
896
|
shellExec(`tar -C ${volume.volumeMountPath} -c . | docker cp - kind-worker:${rootVolumeHostPath}`);
|
|
837
897
|
shellExec(
|
|
838
898
|
`docker exec -i kind-worker bash -c "chown -R 1000:1000 ${rootVolumeHostPath}; chmod -R 755 ${rootVolumeHostPath}"`,
|
|
839
899
|
);
|
|
900
|
+
} else {
|
|
901
|
+
if (!fs.existsSync(rootVolumeHostPath)) fs.mkdirSync(rootVolumeHostPath, { recursive: true });
|
|
902
|
+
fs.copySync(volume.volumeMountPath, rootVolumeHostPath);
|
|
840
903
|
}
|
|
841
904
|
shellExec(`kubectl delete pvc ${pvcId} -n ${namespace} --ignore-not-found`);
|
|
842
905
|
shellExec(`kubectl delete pv ${pvId} --ignore-not-found`);
|
|
@@ -844,6 +907,7 @@ EOF`);
|
|
|
844
907
|
${Underpost.deploy.persistentVolumeFactory({
|
|
845
908
|
hostPath: rootVolumeHostPath,
|
|
846
909
|
pvcId,
|
|
910
|
+
namespace,
|
|
847
911
|
})}
|
|
848
912
|
EOF
|
|
849
913
|
`);
|
|
@@ -858,6 +922,8 @@ EOF
|
|
|
858
922
|
* @param {string} volume.volumeType - Type of the volume (e.g. 'Directory').
|
|
859
923
|
* @param {string|null} volume.claimName - Name of the persistent volume claim (if applicable).
|
|
860
924
|
* @param {string|null} volume.configMap - Name of the config map (if applicable).
|
|
925
|
+
* @param {string|null} volume.secret - Name of the Kubernetes Secret (if applicable). Mounts as readOnly.
|
|
926
|
+
* @param {boolean} [volume.emptyDir=false] - If true, uses an emptyDir volume (writable tmpfs).
|
|
861
927
|
* @returns {object} - Object containing the rendered volume mounts and volumes.
|
|
862
928
|
* @memberof UnderpostDeploy
|
|
863
929
|
*/
|
|
@@ -879,7 +945,17 @@ EOF
|
|
|
879
945
|
let _volumes = `
|
|
880
946
|
volumes:`;
|
|
881
947
|
volumes.map((volumeData) => {
|
|
882
|
-
let {
|
|
948
|
+
let {
|
|
949
|
+
volumeName,
|
|
950
|
+
volumeMountPath,
|
|
951
|
+
volumeHostPath,
|
|
952
|
+
volumeType,
|
|
953
|
+
claimName,
|
|
954
|
+
configMap,
|
|
955
|
+
secret,
|
|
956
|
+
emptyDir,
|
|
957
|
+
version,
|
|
958
|
+
} = volumeData;
|
|
883
959
|
if (version) {
|
|
884
960
|
volumeName = `${volumeName}-${version}`;
|
|
885
961
|
claimName = claimName ? `${claimName}-${version}` : null;
|
|
@@ -887,18 +963,23 @@ EOF
|
|
|
887
963
|
_volumeMounts += `
|
|
888
964
|
- name: ${volumeName}
|
|
889
965
|
mountPath: ${volumeMountPath}
|
|
890
|
-
`;
|
|
966
|
+
${secret ? ` readOnly: true\n` : ''}`;
|
|
891
967
|
|
|
892
968
|
_volumes += `
|
|
893
969
|
- name: ${volumeName}
|
|
894
970
|
${
|
|
895
|
-
|
|
896
|
-
? `
|
|
971
|
+
emptyDir
|
|
972
|
+
? ` emptyDir: {}`
|
|
973
|
+
: secret
|
|
974
|
+
? ` secret:
|
|
975
|
+
secretName: ${secret}`
|
|
976
|
+
: configMap
|
|
977
|
+
? ` configMap:
|
|
897
978
|
name: ${configMap}`
|
|
898
|
-
|
|
899
|
-
|
|
979
|
+
: claimName
|
|
980
|
+
? ` persistentVolumeClaim:
|
|
900
981
|
claimName: ${claimName}`
|
|
901
|
-
|
|
982
|
+
: ` hostPath:
|
|
902
983
|
path: ${volumeHostPath}
|
|
903
984
|
type: ${volumeType}
|
|
904
985
|
`
|
|
@@ -914,15 +995,44 @@ EOF
|
|
|
914
995
|
* @param {object} options - Options for the persistent volume and claim creation.
|
|
915
996
|
* @param {string} options.hostPath - Host path for the persistent volume.
|
|
916
997
|
* @param {string} options.pvcId - Persistent volume claim ID.
|
|
998
|
+
* @param {string} [options.namespace='default'] - Kubernetes namespace for the PVC claimRef.
|
|
917
999
|
* @returns {string} - YAML configuration for the persistent volume and claim.
|
|
918
1000
|
* @memberof UnderpostDeploy
|
|
919
1001
|
*/
|
|
920
|
-
persistentVolumeFactory({ hostPath, pvcId }) {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
1002
|
+
persistentVolumeFactory({ hostPath, pvcId, namespace = 'default' }) {
|
|
1003
|
+
const pvId = pvcId.replace(/^pvc-/, 'pv-');
|
|
1004
|
+
return `apiVersion: v1
|
|
1005
|
+
kind: PersistentVolume
|
|
1006
|
+
metadata:
|
|
1007
|
+
name: ${pvId}
|
|
1008
|
+
spec:
|
|
1009
|
+
capacity:
|
|
1010
|
+
storage: 5Gi
|
|
1011
|
+
accessModes:
|
|
1012
|
+
- ReadWriteOnce
|
|
1013
|
+
persistentVolumeReclaimPolicy: Retain
|
|
1014
|
+
storageClassName: manual
|
|
1015
|
+
claimRef:
|
|
1016
|
+
apiVersion: v1
|
|
1017
|
+
kind: PersistentVolumeClaim
|
|
1018
|
+
name: ${pvcId}
|
|
1019
|
+
namespace: ${namespace}
|
|
1020
|
+
hostPath:
|
|
1021
|
+
path: ${hostPath}
|
|
1022
|
+
type: DirectoryOrCreate
|
|
1023
|
+
---
|
|
1024
|
+
apiVersion: v1
|
|
1025
|
+
kind: PersistentVolumeClaim
|
|
1026
|
+
metadata:
|
|
1027
|
+
name: ${pvcId}
|
|
1028
|
+
spec:
|
|
1029
|
+
accessModes:
|
|
1030
|
+
- ReadWriteOnce
|
|
1031
|
+
storageClassName: manual
|
|
1032
|
+
volumeName: ${pvId}
|
|
1033
|
+
resources:
|
|
1034
|
+
requests:
|
|
1035
|
+
storage: 5Gi`;
|
|
926
1036
|
},
|
|
927
1037
|
|
|
928
1038
|
/**
|
|
@@ -989,7 +1099,7 @@ ${renderHosts}`,
|
|
|
989
1099
|
async monitorReadyRunner(deployId, env, targetTraffic, ignorePods = [], namespace = 'default', outLogType = '') {
|
|
990
1100
|
let checkStatusIteration = 0;
|
|
991
1101
|
const checkStatusIterationMsDelay = 1000;
|
|
992
|
-
const maxIterations =
|
|
1102
|
+
const maxIterations = 3000;
|
|
993
1103
|
const deploymentId = `${deployId}-${env}-${targetTraffic}`;
|
|
994
1104
|
const iteratorTag = `[${deploymentId}]`;
|
|
995
1105
|
logger.info('Deployment init', { deployId, env, targetTraffic, checkStatusIterationMsDelay, namespace });
|
package/src/cli/env.js
CHANGED
|
@@ -10,12 +10,23 @@ import { loggerFactory } from '../server/logger.js';
|
|
|
10
10
|
import dotenv from 'dotenv';
|
|
11
11
|
import { pbcopy } from '../server/process.js';
|
|
12
12
|
|
|
13
|
-
dotenv.config();
|
|
14
|
-
|
|
15
13
|
const logger = loggerFactory(import.meta);
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
|
-
*
|
|
16
|
+
* Guards an env file path against stale directory artifacts.
|
|
17
|
+
* Removes the path if it exists as a directory (e.g. `.env/` created by a previous EISDIR bug).
|
|
18
|
+
* @param {string} envPath - The path to the environment file.
|
|
19
|
+
* @memberof UnderpostEnv
|
|
20
|
+
*/
|
|
21
|
+
const guardEnvPath = (envPath) => {
|
|
22
|
+
if (fs.existsSync(envPath) && !fs.statSync(envPath).isFile()) {
|
|
23
|
+
logger.warn(`Removing stale directory at env path: ${envPath}`);
|
|
24
|
+
fs.removeSync(envPath);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @class UnderpostRootEnv
|
|
19
30
|
* @description Manages the environment variables of the underpost root.
|
|
20
31
|
* @memberof UnderpostEnv
|
|
21
32
|
*/
|
|
@@ -33,6 +44,7 @@ class UnderpostRootEnv {
|
|
|
33
44
|
*/
|
|
34
45
|
set(key, value, options = { deployId: '', build: false }) {
|
|
35
46
|
const _set = (envPath, key, value) => {
|
|
47
|
+
guardEnvPath(envPath);
|
|
36
48
|
let env = {};
|
|
37
49
|
if (fs.existsSync(envPath)) env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
38
50
|
env[key] = value;
|
|
@@ -41,13 +53,16 @@ class UnderpostRootEnv {
|
|
|
41
53
|
if (options.build) {
|
|
42
54
|
const deployIdList = options.deployId
|
|
43
55
|
? [options.deployId]
|
|
44
|
-
: fs.
|
|
56
|
+
: fs.existsSync(`./engine-private/deploy/dd.router`)
|
|
57
|
+
? fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',')
|
|
58
|
+
: [DEFAULT_DEPLOY_ID];
|
|
45
59
|
for (const deployId of deployIdList)
|
|
46
60
|
for (const envFile of ['test', 'development', 'production'])
|
|
47
61
|
_set(`./engine-private/conf/${deployId}/.env.${envFile}`, key, value);
|
|
48
62
|
return;
|
|
49
63
|
}
|
|
50
64
|
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
65
|
+
fs.ensureDirSync(exeRootPath);
|
|
51
66
|
const envPath = `${exeRootPath}/.env`;
|
|
52
67
|
_set(envPath, key, value);
|
|
53
68
|
},
|
|
@@ -60,6 +75,7 @@ class UnderpostRootEnv {
|
|
|
60
75
|
delete(key) {
|
|
61
76
|
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
62
77
|
const envPath = `${exeRootPath}/.env`;
|
|
78
|
+
guardEnvPath(envPath);
|
|
63
79
|
let env = {};
|
|
64
80
|
if (fs.existsSync(envPath)) env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
65
81
|
delete env[key];
|
|
@@ -79,7 +95,7 @@ class UnderpostRootEnv {
|
|
|
79
95
|
get(key, value, options = { plain: false, disableLog: false, copy: false }) {
|
|
80
96
|
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
81
97
|
const envPath = `${exeRootPath}/.env`;
|
|
82
|
-
if (!fs.existsSync(envPath)) {
|
|
98
|
+
if (!fs.existsSync(envPath) || !fs.statSync(envPath).isFile()) {
|
|
83
99
|
logger.warn(`Empty environment variables`);
|
|
84
100
|
return undefined;
|
|
85
101
|
}
|
|
@@ -101,6 +117,7 @@ class UnderpostRootEnv {
|
|
|
101
117
|
list(key, value, options = {}) {
|
|
102
118
|
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
103
119
|
const envPath = `${exeRootPath}/.env`;
|
|
120
|
+
guardEnvPath(envPath);
|
|
104
121
|
if (!fs.existsSync(envPath)) {
|
|
105
122
|
logger.warn(`Empty environment variables`);
|
|
106
123
|
return {};
|
|
@@ -136,7 +153,19 @@ class UnderpostRootEnv {
|
|
|
136
153
|
const envPath = `${exeRootPath}/.env`;
|
|
137
154
|
fs.removeSync(envPath);
|
|
138
155
|
},
|
|
156
|
+
/**
|
|
157
|
+
* @method isInsideContainer
|
|
158
|
+
* @description Detects whether the current process is running inside a container.
|
|
159
|
+
* Checks for Kubernetes service injection or Docker's .dockerenv marker.
|
|
160
|
+
* @returns {boolean} True if running inside a container.
|
|
161
|
+
* @memberof UnderpostEnv
|
|
162
|
+
*/
|
|
163
|
+
isInsideContainer() {
|
|
164
|
+
return !!process.env.KUBERNETES_SERVICE_HOST || fs.existsSync('/.dockerenv');
|
|
165
|
+
},
|
|
139
166
|
};
|
|
140
167
|
}
|
|
141
168
|
|
|
142
169
|
export default UnderpostRootEnv;
|
|
170
|
+
|
|
171
|
+
export { guardEnvPath };
|