cyberia 3.2.22 → 3.2.70
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.example +127 -68
- package/.github/workflows/cyberia-client.cd.yml +40 -0
- package/.github/workflows/cyberia-server.cd.yml +40 -0
- package/.github/workflows/docker-image.cyberia-client.ci.yml +49 -0
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +48 -0
- package/.github/workflows/docker-image.cyberia-server.ci.yml +69 -0
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +69 -0
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +52 -0
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +52 -0
- package/.github/workflows/engine-cyberia.cd.yml +33 -24
- package/.github/workflows/engine-cyberia.ci.yml +13 -3
- package/.github/workflows/ghpkg.ci.yml +88 -1
- package/.github/workflows/gitlab.ci.yml +1 -1
- package/.github/workflows/hardhat.ci.yml +1 -1
- package/.github/workflows/npmpkg.ci.yml +10 -7
- package/.github/workflows/publish.ci.yml +2 -2
- package/.github/workflows/publish.cyberia.ci.yml +5 -16
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -8
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/CHANGELOG.md +301 -1
- package/CLI-HELP.md +71 -6
- package/Dockerfile +141 -43
- package/Dockerfile.dev +143 -0
- package/Dockerfile.test +165 -0
- package/README.md +1 -1
- package/baremetal/commission-workflows.json +1 -0
- package/bin/build.js +31 -0
- package/bin/cyberia.js +1080 -184
- package/bin/deploy.js +2 -2
- package/bin/index.js +1080 -184
- package/bump.config.js +1 -0
- package/compose.env +131 -0
- package/conf.js +18 -1
- package/deployment.yaml +2 -2
- package/docker-compose.yml +316 -0
- package/hardhat/hardhat.config.js +2 -2
- package/hardhat/package-lock.json +620 -2041
- package/hardhat/package.json +7 -5
- package/hardhat/scripts/deployObjectLayerToken.js +18 -18
- package/hardhat/test/ObjectLayerToken.js +378 -274
- package/ipfs/configure-ipfs.sh +13 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-cyberia-development/grpc-service.yaml +17 -0
- package/manifests/deployment/dd-cyberia-development/pv-pvc.yaml +32 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/mongodb/entrypoint.sh +76 -0
- package/nginx.conf +87 -0
- package/package.json +31 -19
- package/pv-pvc.yaml +32 -0
- package/scripts/disk-clean.sh +85 -60
- package/scripts/kubeadm-node-setup.sh +317 -0
- package/scripts/rocky-kickstart.sh +877 -185
- package/scripts/rpmfusion-ffmpeg-setup.sh +26 -50
- package/scripts/test-monitor.sh +3 -5
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +43 -7
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +17 -25
- package/src/api/cyberia-action/cyberia-action.controller.js +19 -0
- package/src/api/cyberia-action/cyberia-action.model.js +21 -29
- package/src/api/cyberia-action/cyberia-action.router.js +42 -7
- package/src/api/cyberia-action/cyberia-action.service.js +20 -4
- package/src/api/cyberia-client-hints/cyberia-client-hints.model.js +58 -57
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +37 -6
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +8 -2
- package/src/api/cyberia-entity/cyberia-entity.router.js +39 -7
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +74 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.model.js +67 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +63 -0
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +46 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +62 -10
- package/src/api/cyberia-instance/cyberia-instance.model.js +32 -2
- package/src/api/cyberia-instance/cyberia-instance.router.js +6 -6
- package/src/api/cyberia-instance/cyberia-world-generator.js +116 -3
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +3 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +39 -7
- package/src/api/cyberia-map/cyberia-map.router.js +21 -6
- package/src/api/cyberia-quest/cyberia-quest.controller.js +38 -0
- package/src/api/cyberia-quest/cyberia-quest.router.js +47 -7
- package/src/api/cyberia-quest/cyberia-quest.service.js +59 -4
- package/src/api/cyberia-saga/cyberia-saga.controller.js +74 -0
- package/src/api/cyberia-saga/cyberia-saga.model.js +59 -0
- package/src/api/cyberia-saga/cyberia-saga.router.js +63 -0
- package/src/api/cyberia-saga/cyberia-saga.service.js +42 -0
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +551 -129
- package/src/api/cyberia-skill/cyberia-skill.controller.js +74 -0
- package/src/api/cyberia-skill/cyberia-skill.model.js +50 -0
- package/src/api/cyberia-skill/cyberia-skill.router.js +63 -0
- package/src/api/cyberia-skill/cyberia-skill.service.js +42 -0
- package/src/api/ipfs/ipfs.service.js +28 -15
- package/src/api/object-layer/object-layer.router.js +25 -15
- package/src/api/object-layer/object-layer.service.js +15 -20
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +39 -7
- package/src/cli/baremetal.js +717 -16
- package/src/cli/cluster.js +80 -5
- package/src/cli/deploy.js +127 -11
- package/src/cli/docker-compose.js +648 -0
- package/src/cli/env.js +11 -2
- package/src/cli/fs.js +75 -30
- package/src/cli/image.js +129 -51
- package/src/cli/index.js +110 -6
- package/src/cli/kickstart.js +142 -20
- package/src/cli/release.js +46 -4
- package/src/cli/repository.js +238 -33
- package/src/cli/run.js +520 -114
- package/src/cli/secrets.js +82 -48
- package/src/cli/ssh.js +234 -0
- package/src/cli/static.js +2 -2
- package/src/client/components/cyberia/ActionEngineCyberia.js +1867 -0
- package/src/client/components/cyberia/EntityEngineCyberia.js +585 -0
- package/src/client/components/cyberia/InstanceEngineCyberia.js +219 -13
- package/src/client/components/cyberia/MapEngineCyberia.js +154 -71
- package/src/client/components/cyberia/ObjectLayerEngineModal.js +40 -63
- package/src/client/components/cyberia/ObjectLayerEngineViewer.js +34 -20
- package/src/client/components/cyberia/SharedDefaultsCyberia.js +195 -4
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +66 -0
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +8 -0
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +8 -0
- package/src/client/public/cyberia-docs/ACTION-SYSTEM.md +45 -27
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +3 -3
- package/src/client/public/cyberia-docs/CYBERIA-CLIENT.md +39 -22
- package/src/client/public/cyberia-docs/CYBERIA-LORE.md +88 -0
- package/src/client/public/cyberia-docs/CYBERIA-SAGA.md +394 -0
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +8 -1
- package/src/client/public/cyberia-docs/CYBERIA.md +1 -1
- package/src/client/public/cyberia-docs/QUEST-SYSTEM.md +5 -5
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/services/cyberia-entity-type-default/cyberia-entity-type-default.service.js +99 -0
- package/src/client/services/cyberia-instance/cyberia-instance.management.js +2 -2
- package/src/client/services/cyberia-map/cyberia-map.management.js +2 -2
- package/src/client/services/cyberia-saga/cyberia-saga.service.js +99 -0
- package/src/client/services/cyberia-skill/cyberia-skill.service.js +99 -0
- package/src/client/services/object-layer/object-layer.management.js +6 -6
- package/src/{server → client-builder}/client-build-docs.js +15 -5
- package/src/{server → client-builder}/client-build-live.js +3 -3
- package/src/{server → client-builder}/client-build.js +25 -22
- package/src/{server → client-builder}/client-dev-server.js +3 -3
- package/src/{server → client-builder}/client-icons.js +2 -2
- package/src/{server → client-builder}/ssr.js +5 -5
- package/src/client.build.js +1 -3
- package/src/client.dev.js +1 -1
- package/src/db/mongo/MongoBootstrap.js +12 -12
- package/src/grpc/cyberia/grpc-server.js +255 -70
- package/src/index.js +12 -1
- package/src/mailer/EmailRender.js +1 -1
- package/src/{server → projects/cyberia}/atlas-sprite-sheet-generator.js +2 -2
- package/src/{server → projects/cyberia}/besu-genesis-generator.js +3 -3
- package/src/projects/cyberia/catalog-cyberia.js +81 -0
- package/src/projects/cyberia/gemini-client.js +175 -0
- package/src/projects/cyberia/generate-saga.js +2107 -0
- package/src/{server → projects/cyberia}/ipfs-client.js +2 -2
- package/src/{server → projects/cyberia}/object-layer.js +12 -108
- package/src/{server → projects/cyberia}/semantic-layer-generator-floor.js +1 -1
- package/src/{server → projects/cyberia}/semantic-layer-generator-resource.js +1 -1
- package/src/{server → projects/cyberia}/semantic-layer-generator-skin.js +1 -1
- package/src/{server → projects/cyberia}/semantic-layer-generator.js +2 -2
- package/src/{server → projects/cyberia}/shape-generator.js +2 -2
- package/src/{server → projects/underpost}/catalog-underpost.js +1 -2
- package/src/runtime/cyberia-client/Dockerfile +27 -61
- package/src/runtime/cyberia-client/Dockerfile.dev +20 -12
- package/src/runtime/cyberia-server/Dockerfile +21 -20
- package/src/runtime/cyberia-server/Dockerfile.dev +17 -8
- package/src/runtime/engine-cyberia/Dockerfile +143 -0
- package/src/runtime/engine-cyberia/Dockerfile.dev +143 -0
- package/src/runtime/engine-cyberia/Dockerfile.test +165 -0
- package/src/runtime/engine-cyberia/compose.env +131 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +316 -0
- package/src/runtime/engine-cyberia/ipfs/configure-ipfs.sh +13 -0
- package/src/runtime/engine-cyberia/mongodb/entrypoint.sh +76 -0
- package/src/runtime/engine-cyberia/nginx.conf +87 -0
- package/src/runtime/express/Express.js +2 -2
- package/src/runtime/nginx/Nginx.js +250 -0
- package/src/server/catalog.js +9 -14
- package/src/server/conf.js +3 -6
- package/src/server/runtime-status.js +18 -1
- package/src/server/start.js +12 -2
- package/src/server.js +6 -2
- package/test/cyberia-instance-conf-defaults.test.js +140 -0
- package/test/deploy-monitor.test.js +26 -10
- package/test/shape-generator.test.js +7 -1
- package/typedoc.dd-cyberia.json +3 -1
- package/typedoc.json +3 -1
- /package/src/client/ssr/{Render.js → RootDocument.js} +0 -0
- /package/src/{server → client-builder}/client-formatted.js +0 -0
package/src/cli/fs.js
CHANGED
|
@@ -64,6 +64,31 @@ class UnderpostFileStorage {
|
|
|
64
64
|
writeStorageConf(storage, storageConf) {
|
|
65
65
|
if (storage) fs.writeFileSync(storageConf, JSON.stringify(storage, null, 4), 'utf8');
|
|
66
66
|
},
|
|
67
|
+
/**
|
|
68
|
+
* @method gitTrack
|
|
69
|
+
* @description Optional, non-fatal Git tracking layer. Any Git error is logged and swallowed
|
|
70
|
+
* so it can never interrupt or roll back the canonical `storage.*.json` workflow.
|
|
71
|
+
* @param {string} gitPath - The working directory to stage/commit.
|
|
72
|
+
* @param {object} [options] - Tracking options.
|
|
73
|
+
* @param {boolean} [options.init=false] - If true, initialize a local repo before staging.
|
|
74
|
+
* @param {string} [options.message=''] - Explicit commit message; when omitted, `underpost cmt` is used.
|
|
75
|
+
* @memberof UnderpostFileStorage
|
|
76
|
+
*/
|
|
77
|
+
gitTrack(gitPath, options = { init: false, message: '' }) {
|
|
78
|
+
try {
|
|
79
|
+
if (options.init === true) Underpost.repo.initLocalRepo({ path: gitPath });
|
|
80
|
+
shellExec(`cd ${gitPath} && git add .`, { silentOnError: true, silent: true, disableLog: true });
|
|
81
|
+
if (options.message)
|
|
82
|
+
shellExec(`cd ${gitPath} && git commit -m "${options.message}"`, {
|
|
83
|
+
silentOnError: true,
|
|
84
|
+
silent: true,
|
|
85
|
+
disableLog: true,
|
|
86
|
+
});
|
|
87
|
+
else shellExec(`underpost cmt ${gitPath} feat`, { silentOnError: true, silent: true, disableLog: true });
|
|
88
|
+
} catch (error) {
|
|
89
|
+
logger.warn('git tracking skipped (non-fatal)', { gitPath, error: error?.message });
|
|
90
|
+
}
|
|
91
|
+
},
|
|
67
92
|
/**
|
|
68
93
|
* @method recursiveCallback
|
|
69
94
|
* @description Recursively processes files and directories based on the provided options.
|
|
@@ -95,6 +120,17 @@ class UnderpostFileStorage {
|
|
|
95
120
|
) {
|
|
96
121
|
const { storage, storageConf } = Underpost.fs.getStorageConf(options);
|
|
97
122
|
|
|
123
|
+
// ── Single-file handling: when path is a file (not a directory), use parent dir
|
|
124
|
+
// as the git working directory and process just that one file. ──────────────
|
|
125
|
+
let isSingleFile = false;
|
|
126
|
+
let parentDir = path;
|
|
127
|
+
let singleFileName = '';
|
|
128
|
+
if (fs.existsSync(path) && !fs.statSync(path).isDirectory()) {
|
|
129
|
+
isSingleFile = true;
|
|
130
|
+
parentDir = dir.dirname(path);
|
|
131
|
+
singleFileName = path.split('/').pop();
|
|
132
|
+
}
|
|
133
|
+
|
|
98
134
|
// In recursive remove mode, delete every tracked storage key under the requested path,
|
|
99
135
|
// even when local files/directories are already missing.
|
|
100
136
|
if (options.rm === true) {
|
|
@@ -114,6 +150,7 @@ class UnderpostFileStorage {
|
|
|
114
150
|
|
|
115
151
|
if (hasPathFilter && options.force === true && fs.existsSync(basePath)) fs.removeSync(basePath);
|
|
116
152
|
|
|
153
|
+
// Storage is canonical: persist the removal before any (optional) git tracking runs.
|
|
117
154
|
Underpost.fs.writeStorageConf(storage, storageConf);
|
|
118
155
|
|
|
119
156
|
if (associatedPaths.length === 0)
|
|
@@ -125,22 +162,31 @@ class UnderpostFileStorage {
|
|
|
125
162
|
});
|
|
126
163
|
|
|
127
164
|
if (options.git === true) {
|
|
128
|
-
const gitPath = hasPathFilter ?
|
|
129
|
-
|
|
130
|
-
shellExec(`underpost cmt ${gitPath} feat`, {
|
|
131
|
-
silentOnError: true,
|
|
132
|
-
silent: true,
|
|
133
|
-
disableLog: true,
|
|
134
|
-
});
|
|
165
|
+
const gitPath = !hasPathFilter ? '.' : isSingleFile ? parentDir : basePath;
|
|
166
|
+
Underpost.fs.gitTrack(gitPath);
|
|
135
167
|
}
|
|
136
168
|
|
|
137
169
|
return;
|
|
138
170
|
}
|
|
139
171
|
|
|
140
|
-
|
|
172
|
+
// For single files, run getDeleteFiles against the parent directory to avoid
|
|
173
|
+
// trying to `cd` into a file.
|
|
174
|
+
const gitContextPath = isSingleFile ? parentDir : path;
|
|
175
|
+
// Detecting locally-deleted files is a best-effort enhancement backed by git; if the path is
|
|
176
|
+
// not a repo (or git is unavailable) it must not block the canonical storage workflow.
|
|
177
|
+
let deleteFiles = [];
|
|
178
|
+
if (options.pull !== true) {
|
|
179
|
+
try {
|
|
180
|
+
deleteFiles = Underpost.repo.getDeleteFiles(gitContextPath);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
logger.warn('delete detection skipped (git unavailable)', { path: gitContextPath, error: error?.message });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// When processing a single file, only consider it for deletion
|
|
141
187
|
for (const relativePath of deleteFiles) {
|
|
142
|
-
const _path = path + '/' + relativePath;
|
|
143
|
-
if (_path in storage) {
|
|
188
|
+
const _path = isSingleFile ? (relativePath === singleFileName ? path : null) : path + '/' + relativePath;
|
|
189
|
+
if (_path && _path in storage) {
|
|
144
190
|
await Underpost.fs.delete(_path);
|
|
145
191
|
delete storage[_path];
|
|
146
192
|
}
|
|
@@ -156,18 +202,21 @@ class UnderpostFileStorage {
|
|
|
156
202
|
if (pullSkipCount > 0) logger.warn(`Pull skipped ${pullSkipCount} files that already exist`);
|
|
157
203
|
// Only run git init/commit when the caller explicitly requests git tracking (--git flag).
|
|
158
204
|
// For bundle pulls into ./build the git step is unwanted and would error on a non-repo path.
|
|
159
|
-
if (options.git === true) {
|
|
160
|
-
Underpost.repo.initLocalRepo({ path });
|
|
161
|
-
shellExec(`cd ${path} && git add . && git commit -m "Base pull state"`, {
|
|
162
|
-
silentOnError: true,
|
|
163
|
-
});
|
|
164
|
-
}
|
|
205
|
+
if (options.git === true) Underpost.fs.gitTrack(gitContextPath, { init: true, message: 'Base pull state' });
|
|
165
206
|
} else {
|
|
166
|
-
|
|
167
|
-
|
|
207
|
+
let files;
|
|
208
|
+
if (isSingleFile) {
|
|
209
|
+
// Single file: treat the file itself as the sole item to process
|
|
210
|
+
files = [singleFileName];
|
|
211
|
+
} else {
|
|
212
|
+
files =
|
|
213
|
+
options.git === true
|
|
214
|
+
? Underpost.repo.getChangedFiles(gitContextPath)
|
|
215
|
+
: await fs.readdir(path, { recursive: true });
|
|
216
|
+
}
|
|
168
217
|
for (const relativePath of files) {
|
|
169
|
-
const _path = path + '/' + relativePath;
|
|
170
|
-
if (fs.statSync(_path).isDirectory()) {
|
|
218
|
+
const _path = isSingleFile ? path : path + '/' + relativePath;
|
|
219
|
+
if (fs.existsSync(_path) && fs.statSync(_path).isDirectory()) {
|
|
171
220
|
if (options.pull === true && !fs.existsSync(_path)) fs.mkdirSync(_path, { recursive: true });
|
|
172
221
|
continue;
|
|
173
222
|
} else if (!(_path in storage) || options.force === true) {
|
|
@@ -176,15 +225,9 @@ class UnderpostFileStorage {
|
|
|
176
225
|
} else logger.warn('File already exists', _path);
|
|
177
226
|
}
|
|
178
227
|
}
|
|
228
|
+
// Storage is canonical and always persisted; git is an optional layer on top.
|
|
179
229
|
Underpost.fs.writeStorageConf(storage, storageConf);
|
|
180
|
-
if (options.git === true)
|
|
181
|
-
shellExec(`cd ${path} && git add .`);
|
|
182
|
-
shellExec(`underpost cmt ${path} feat`, {
|
|
183
|
-
silentOnError: true,
|
|
184
|
-
silent: true,
|
|
185
|
-
disableLog: true,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
230
|
+
if (options.git === true) Underpost.fs.gitTrack(gitContextPath);
|
|
188
231
|
},
|
|
189
232
|
/**
|
|
190
233
|
* @method callback
|
|
@@ -206,10 +249,12 @@ class UnderpostFileStorage {
|
|
|
206
249
|
path,
|
|
207
250
|
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, git: false, omitUnzip: false },
|
|
208
251
|
) {
|
|
209
|
-
|
|
252
|
+
// rm always routes through recursiveCallback so storage.*.json is updated regardless of
|
|
253
|
+
// --recursive/--git. The bare `delete` primitive only removes the remote asset and would
|
|
254
|
+
// otherwise leave the tracked storage key orphaned.
|
|
255
|
+
if (options.recursive === true || options.git === true || options.rm === true)
|
|
210
256
|
return await Underpost.fs.recursiveCallback(path, options);
|
|
211
257
|
if (options.pull === true) return await Underpost.fs.pull(path, options);
|
|
212
|
-
if (options.rm === true) return await Underpost.fs.delete(path, options);
|
|
213
258
|
return await Underpost.fs.upload(path, options);
|
|
214
259
|
},
|
|
215
260
|
/**
|
package/src/cli/image.js
CHANGED
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import fs from 'fs-extra';
|
|
8
|
+
import os from 'os';
|
|
9
|
+
import nodePath from 'path';
|
|
10
|
+
import crypto from 'crypto';
|
|
8
11
|
import { loggerFactory } from '../server/logger.js';
|
|
9
12
|
import Underpost from '../index.js';
|
|
10
|
-
import { getNpmRootPath
|
|
13
|
+
import { getNpmRootPath } from '../server/conf.js';
|
|
11
14
|
import { shellExec } from '../server/process.js';
|
|
12
15
|
|
|
13
16
|
const logger = loggerFactory(import.meta);
|
|
@@ -23,59 +26,32 @@ class UnderpostImage {
|
|
|
23
26
|
static API = {
|
|
24
27
|
/**
|
|
25
28
|
* @method pullBaseImages
|
|
26
|
-
* @description
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @param {boolean} [options.k3s=false] - If true, load image into K3s cluster.
|
|
32
|
-
* @param {string} [options.path=''] - Path to the Dockerfile context.
|
|
33
|
-
* @param {boolean} [options.dev=false] - If true, use development mode.
|
|
34
|
-
* @param {string} [options.version=''] - Version tag for the image.
|
|
35
|
-
* @param {string} [options.imageName=''] - Custom name for the image.
|
|
29
|
+
* @description Ensures the base image prerequisites for the runtime Dockerfiles
|
|
30
|
+
* are present on the host (currently `docker.io/rockylinux/rockylinux:9`). This
|
|
31
|
+
* only pulls — it does NOT build. Builds run with `podman build --pull=never`,
|
|
32
|
+
* so the base must exist locally beforehand; that is the sole purpose of this
|
|
33
|
+
* step. Combine with `--build` in the same command to pull-then-build.
|
|
36
34
|
* @memberof UnderpostImage
|
|
37
35
|
*/
|
|
38
|
-
pullBaseImages(
|
|
39
|
-
|
|
40
|
-
kind: false,
|
|
41
|
-
kubeadm: false,
|
|
42
|
-
k3s: false,
|
|
43
|
-
path: '',
|
|
44
|
-
dev: false,
|
|
45
|
-
version: '',
|
|
46
|
-
imageName: '',
|
|
47
|
-
},
|
|
48
|
-
) {
|
|
49
|
-
shellExec(`sudo podman pull docker.io/library/rockylinux:9`);
|
|
50
|
-
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
51
|
-
const baseCommandOption = options.dev ? ' --dev' : '';
|
|
52
|
-
const IMAGE_NAME = options.imageName
|
|
53
|
-
? `options.imageName${options.version ? `:${options.version}` : ''}`
|
|
54
|
-
: `rockylinux9-underpost:${options.version ? options.version : Underpost.version}`;
|
|
55
|
-
let LOAD_TYPE = '';
|
|
56
|
-
if (options.kind === true) LOAD_TYPE = `--kind`;
|
|
57
|
-
else if (options.kubeadm === true) LOAD_TYPE = `--kubeadm`;
|
|
58
|
-
else if (options.k3s === true) LOAD_TYPE = `--k3s`;
|
|
59
|
-
shellExec(
|
|
60
|
-
`${baseCommand} image${baseCommandOption} --build --podman-save --reset --image-path=. --path ${
|
|
61
|
-
options.path ? options.path : getUnderpostRootPath()
|
|
62
|
-
} --image-name=${IMAGE_NAME} ${LOAD_TYPE}`,
|
|
63
|
-
);
|
|
36
|
+
pullBaseImages() {
|
|
37
|
+
shellExec(`sudo podman pull docker.io/rockylinux/rockylinux:9`);
|
|
64
38
|
},
|
|
65
39
|
/**
|
|
66
40
|
* @method build
|
|
67
41
|
* @description Builds a Docker image using Podman, optionally saves it as a tar archive,
|
|
68
|
-
* and loads it into a specified
|
|
42
|
+
* and loads it into a specified target (Kind, Kubeadm, or K3s cluster, or the local
|
|
43
|
+
* Docker store for Docker Compose).
|
|
69
44
|
* @param {object} options - Options for building and loading images.
|
|
70
45
|
* @param {string} [options.path=''] - The path to the directory containing the Dockerfile.
|
|
71
46
|
* @param {string} [options.imageName=''] - The name and tag for the image (e.g., 'my-app:latest').
|
|
72
47
|
* @param {string} [options.version=''] - Version tag for the image.
|
|
73
|
-
* @param {string} [options.
|
|
48
|
+
* @param {string} [options.imageOutPath=''] - Directory to save the image tar file.
|
|
74
49
|
* @param {string} [options.dockerfileName=''] - Name of the Dockerfile (defaults to 'Dockerfile').
|
|
75
50
|
* @param {boolean} [options.podmanSave=false] - If true, save the image as a tar archive using Podman.
|
|
76
51
|
* @param {boolean} [options.kind=false] - If true, load the image archive into a Kind cluster.
|
|
77
52
|
* @param {boolean} [options.kubeadm=false] - If true, load the image archive into a Kubeadm cluster (uses 'ctr').
|
|
78
53
|
* @param {boolean} [options.k3s=false] - If true, load the image archive into a K3s cluster (uses 'k3s ctr').
|
|
54
|
+
* @param {boolean} [options.dockerCompose=false] - If true, load the image archive into the local Docker store for Docker Compose.
|
|
79
55
|
* @param {boolean} [options.reset=false] - If true, perform a no-cache build.
|
|
80
56
|
* @param {boolean} [options.dev=false] - If true, use development mode.
|
|
81
57
|
* @memberof UnderpostImage
|
|
@@ -85,42 +61,144 @@ class UnderpostImage {
|
|
|
85
61
|
path: '',
|
|
86
62
|
imageName: '',
|
|
87
63
|
version: '',
|
|
88
|
-
|
|
64
|
+
imageOutPath: '',
|
|
89
65
|
dockerfileName: '',
|
|
90
66
|
podmanSave: false,
|
|
91
67
|
kind: false,
|
|
92
68
|
kubeadm: false,
|
|
93
69
|
k3s: false,
|
|
70
|
+
dockerCompose: false,
|
|
94
71
|
reset: false,
|
|
95
72
|
dev: false,
|
|
96
73
|
},
|
|
97
74
|
) {
|
|
98
|
-
let {
|
|
75
|
+
let {
|
|
76
|
+
path,
|
|
77
|
+
imageName,
|
|
78
|
+
version,
|
|
79
|
+
imageOutPath,
|
|
80
|
+
dockerfileName,
|
|
81
|
+
podmanSave,
|
|
82
|
+
kind,
|
|
83
|
+
kubeadm,
|
|
84
|
+
k3s,
|
|
85
|
+
dockerCompose,
|
|
86
|
+
reset,
|
|
87
|
+
dev,
|
|
88
|
+
} = options;
|
|
99
89
|
if (!path) path = '.';
|
|
100
90
|
if (!imageName) imageName = `rockylinux9-underpost:${Underpost.version}`;
|
|
101
|
-
if (!
|
|
91
|
+
if (!imageOutPath) imageOutPath = '.';
|
|
102
92
|
if (imageName.match('/')) imageName = imageName.split('/')[1];
|
|
103
93
|
if (!version) version = 'latest';
|
|
104
94
|
version = imageName && imageName.match(':') ? '' : `:${version}`;
|
|
105
95
|
const podManImg = `localhost/${imageName}${version}`;
|
|
106
|
-
if (
|
|
107
|
-
fs.mkdirSync(
|
|
108
|
-
const tarFile = `${
|
|
96
|
+
if (imageOutPath && typeof imageOutPath === 'string' && !fs.existsSync(imageOutPath))
|
|
97
|
+
fs.mkdirSync(imageOutPath, { recursive: true });
|
|
98
|
+
const tarFile = `${imageOutPath}/${imageName.replace(':', '_')}.tar`;
|
|
109
99
|
let cache = '';
|
|
110
100
|
if (reset === true) cache += ' --rm --no-cache';
|
|
101
|
+
|
|
102
|
+
// Forward GitHub credentials from the host environment into the build as
|
|
103
|
+
// podman/BuildKit secrets (`--secret id=...,src=...`), matching the
|
|
104
|
+
// `RUN --mount=type=secret,id=github_*` contract in the runtime
|
|
105
|
+
// Dockerfiles (e.g. src/runtime/engine-cyberia). Secrets are written to
|
|
106
|
+
// short-lived 0600 temp files and removed right after the build — they are
|
|
107
|
+
// never passed as build-args (which would persist in image history) nor
|
|
108
|
+
// baked into any layer.
|
|
109
|
+
const secretTmpFiles = [];
|
|
110
|
+
const secretFlags = [];
|
|
111
|
+
const addBuildSecret = (id, value) => {
|
|
112
|
+
if (!value) return;
|
|
113
|
+
const file = nodePath.join(os.tmpdir(), `underpost-secret-${id}-${crypto.randomBytes(6).toString('hex')}`);
|
|
114
|
+
fs.writeFileSync(file, String(value), { mode: 0o600 });
|
|
115
|
+
secretTmpFiles.push(file);
|
|
116
|
+
secretFlags.push(`--secret id=${id},src=${file}`);
|
|
117
|
+
};
|
|
118
|
+
// addBuildSecret('github_token', process.env.GITHUB_TOKEN);
|
|
119
|
+
addBuildSecret('github_username', process.env.GITHUB_USERNAME);
|
|
120
|
+
// Cloudinary creds power build-time asset pulls (`node bin fs --pull`).
|
|
121
|
+
// addBuildSecret('cloudinary_cloud_name', process.env.CLOUDINARY_CLOUD_NAME);
|
|
122
|
+
// addBuildSecret('cloudinary_api_key', process.env.CLOUDINARY_API_KEY);
|
|
123
|
+
// addBuildSecret('cloudinary_api_secret', process.env.CLOUDINARY_API_SECRET);
|
|
124
|
+
const secretArgs = secretFlags.length ? ` ${secretFlags.join(' ')}` : '';
|
|
125
|
+
if (secretFlags.length)
|
|
126
|
+
logger.info('Passing host GitHub credentials as build secrets', { ids: secretFlags.length });
|
|
127
|
+
|
|
111
128
|
if (path)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
129
|
+
try {
|
|
130
|
+
shellExec(
|
|
131
|
+
`cd ${path} && sudo podman build -f ./${
|
|
132
|
+
dockerfileName && typeof dockerfileName === 'string' ? dockerfileName : 'Dockerfile'
|
|
133
|
+
} -t ${imageName} --pull=never --cap-add=CAP_AUDIT_WRITE${cache}${secretArgs} --network host`,
|
|
134
|
+
);
|
|
135
|
+
} finally {
|
|
136
|
+
for (const file of secretTmpFiles) {
|
|
137
|
+
try {
|
|
138
|
+
fs.removeSync(file);
|
|
139
|
+
} catch {
|
|
140
|
+
/* best-effort cleanup */
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Loading into any target requires the tar archive, so imply the save when
|
|
145
|
+
// one is set (kind/kubeadm/k3s/docker-compose) even if --podman-save was omitted.
|
|
146
|
+
const loadTarget = kind === true || kubeadm === true || k3s === true || dockerCompose === true;
|
|
147
|
+
if (podmanSave === true || loadTarget) {
|
|
118
148
|
if (fs.existsSync(tarFile)) fs.removeSync(tarFile);
|
|
119
149
|
shellExec(`podman save -o ${tarFile} ${podManImg}`);
|
|
120
150
|
}
|
|
121
151
|
if (kind === true) shellExec(`sudo kind load image-archive ${tarFile}`);
|
|
122
152
|
else if (kubeadm === true) shellExec(`sudo ctr -n k8s.io images import ${tarFile}`);
|
|
123
153
|
else if (k3s === true) shellExec(`sudo k3s ctr images import ${tarFile}`);
|
|
154
|
+
// Independent of any cluster target: make the local image available to the
|
|
155
|
+
// Docker daemon so `docker compose` can resolve it (e.g. ENGINE_CYBERIA_IMAGE).
|
|
156
|
+
if (dockerCompose === true) shellExec(`sudo docker load -i ${tarFile}`);
|
|
157
|
+
},
|
|
158
|
+
/**
|
|
159
|
+
* @method importTar
|
|
160
|
+
* @description Loads a pre-built image tar archive into each enabled target
|
|
161
|
+
* without building anything. Mirrors the load step of {@link build}, but
|
|
162
|
+
* the archive is supplied directly via `--import-tar <tar-path>` and every
|
|
163
|
+
* enabled target flag is honored (the same archive is loaded into each), so
|
|
164
|
+
* `--kind --docker-compose` loads it into both.
|
|
165
|
+
* @param {object} options - CLI options.
|
|
166
|
+
* @param {string} options.importTar - Path to the image tar archive (e.g. `./image-v1.0.0.tar`).
|
|
167
|
+
* @param {boolean} [options.kind] - Load into the Kind cluster (`kind load image-archive`).
|
|
168
|
+
* @param {boolean} [options.kubeadm] - Import into kubeadm containerd (`ctr -n k8s.io images import`).
|
|
169
|
+
* @param {boolean} [options.k3s] - Import into k3s containerd (`k3s ctr images import`).
|
|
170
|
+
* @param {boolean} [options.dockerCompose] - Load into the local Docker daemon (`docker load`) for Docker Compose.
|
|
171
|
+
* @returns {void}
|
|
172
|
+
* @memberof UnderpostImage
|
|
173
|
+
*/
|
|
174
|
+
importTar(options = { importTar: '', kind: false, kubeadm: false, k3s: false, dockerCompose: false }) {
|
|
175
|
+
const { importTar, kind, kubeadm, k3s, dockerCompose } = options;
|
|
176
|
+
if (!importTar || typeof importTar !== 'string' || !fs.existsSync(importTar)) {
|
|
177
|
+
logger.error('image --import-tar: archive not found', { importTar });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const targets = [];
|
|
181
|
+
if (kind === true) {
|
|
182
|
+
shellExec(`sudo kind load image-archive ${importTar}`);
|
|
183
|
+
targets.push('kind');
|
|
184
|
+
}
|
|
185
|
+
if (kubeadm === true) {
|
|
186
|
+
shellExec(`sudo ctr -n k8s.io images import ${importTar}`);
|
|
187
|
+
targets.push('kubeadm');
|
|
188
|
+
}
|
|
189
|
+
if (k3s === true) {
|
|
190
|
+
shellExec(`sudo k3s ctr images import ${importTar}`);
|
|
191
|
+
targets.push('k3s');
|
|
192
|
+
}
|
|
193
|
+
if (dockerCompose === true) {
|
|
194
|
+
shellExec(`sudo docker load -i ${importTar}`);
|
|
195
|
+
targets.push('docker-compose');
|
|
196
|
+
}
|
|
197
|
+
if (targets.length === 0)
|
|
198
|
+
logger.warn(
|
|
199
|
+
'image --import-tar: no target enabled; combine with --kind, --kubeadm, --k3s and/or --docker-compose',
|
|
200
|
+
);
|
|
201
|
+
else logger.info('image --import-tar: archive loaded', { importTar, targets });
|
|
124
202
|
},
|
|
125
203
|
/**
|
|
126
204
|
* @method getCurrentLoaded
|
package/src/cli/index.js
CHANGED
|
@@ -110,16 +110,18 @@ program
|
|
|
110
110
|
.option('--cached', 'Commit staged changes only or context.')
|
|
111
111
|
.option('--hashes <hashes>', 'Comma-separated list of specific file hashes of commits.')
|
|
112
112
|
.option('--extension <extension>', 'specific file extensions of commits.')
|
|
113
|
-
.option(
|
|
114
|
-
'--changelog [latest-n]',
|
|
115
|
-
'Print plain the changelog of the specified number of latest n commits, if no number is provided it will get the changelog to latest ci integration',
|
|
116
|
-
)
|
|
113
|
+
.option('--changelog', 'Print the plain changelog of the last N commits (see --from-n-commit, default 1).')
|
|
117
114
|
.option('--changelog-build', 'Builds a CHANGELOG.md file based on the commit history')
|
|
118
115
|
.option('--changelog-min-version <version>', 'Sets the minimum version limit for --changelog-build (default: 2.85.0)')
|
|
119
116
|
.option(
|
|
120
117
|
'--changelog-no-hash',
|
|
121
118
|
'Excludes commit hashes from the generated changelog entries (used with --changelog-build).',
|
|
122
119
|
)
|
|
120
|
+
.option(
|
|
121
|
+
'--changelog-msg',
|
|
122
|
+
'Print the sanitized, commit-ready changelog message of the last N commits (see --from-n-commit, default 1). Empty when there are no tagged entries.',
|
|
123
|
+
)
|
|
124
|
+
.option('--from-n-commit <n>', 'Number of latest commits to include in --changelog/--changelog-msg (default: 1).')
|
|
123
125
|
.option('--unpush', 'With --log, automatically sets range to unpushed commits ahead of remote.')
|
|
124
126
|
.option('-b', 'Shows the current Git branch name.')
|
|
125
127
|
.option('-p [branch]', 'Shows the reflog for the specified branch.')
|
|
@@ -132,6 +134,12 @@ program
|
|
|
132
134
|
'--has-changes',
|
|
133
135
|
'Prints "1" if there are staged or unstaged git changes in the repository, empty string otherwise.',
|
|
134
136
|
)
|
|
137
|
+
.option('--remote-url', 'Prints the current git remote URL (origin) in plain text.')
|
|
138
|
+
.option(
|
|
139
|
+
'--switch-repo <url>',
|
|
140
|
+
'Switches the git remote (origin) to <url> and force-pulls the target branch, overwriting the current working tree (discards local commits and tracked changes). Accepts a full URL or "owner/repo".',
|
|
141
|
+
)
|
|
142
|
+
.option('--target-branch <branch>', 'Target branch for --switch-repo (default: master).')
|
|
135
143
|
.description('Manages commits to a GitHub repository, supporting various commit types and options.')
|
|
136
144
|
.action(Underpost.repo.commit);
|
|
137
145
|
|
|
@@ -330,6 +338,10 @@ program
|
|
|
330
338
|
'Enables TLS in the Contour HTTPProxy virtualhost without requiring a production ClusterIssuer.',
|
|
331
339
|
)
|
|
332
340
|
.option('--node <node>', 'Sets optional node for deployment operations.')
|
|
341
|
+
.option(
|
|
342
|
+
'--ssh-key-path <path>',
|
|
343
|
+
'Private key path for node SSH operations. Currently used when shipping a hostPath volume to a remote target node over SSH. Defaults to engine-private/deploy/id_rsa.',
|
|
344
|
+
)
|
|
333
345
|
.option(
|
|
334
346
|
'--build-manifest',
|
|
335
347
|
'Builds Kubernetes YAML manifests, including deployments, services, proxies, and secrets.',
|
|
@@ -424,25 +436,31 @@ program
|
|
|
424
436
|
.option('--rm <image-id>', 'Removes specified Underpost Dockerfile images.')
|
|
425
437
|
.option('--path [path]', 'The path to the Dockerfile directory.')
|
|
426
438
|
.option('--image-name [image-name]', 'Sets a custom name for the Docker image.')
|
|
427
|
-
.option('--image-path [image-path]', 'Sets the output path for the tar image archive.')
|
|
439
|
+
.option('--image-out-path [image-out-path]', 'Sets the output path for the tar image archive.')
|
|
428
440
|
.option('--dockerfile-name [dockerfile-name]', 'Sets a custom name for the Dockerfile.')
|
|
429
441
|
.option('--podman-save', 'Exports the built image as a tar file using Podman.')
|
|
430
|
-
.option('--pull-base', 'Pulls base
|
|
442
|
+
.option('--pull-base', 'Pulls the base image prerequisites (rockylinux:9) on the host; combine with --build.')
|
|
431
443
|
.option('--spec', 'Get current cached list of container images used by all pods')
|
|
432
444
|
.option('--namespace <namespace>', 'Kubernetes namespace for image operations (defaults to "default").')
|
|
433
445
|
.option('--kind', 'Set kind cluster env image context management.')
|
|
434
446
|
.option('--kubeadm', 'Set kubeadm cluster env image context management.')
|
|
435
447
|
.option('--k3s', 'Set k3s cluster env image context management.')
|
|
448
|
+
.option('--docker-compose', 'Load the built image tar into the local Docker store for Docker Compose availability.')
|
|
436
449
|
.option('--node-name', 'Set node name for kubeadm or k3s cluster env image context management.')
|
|
437
450
|
.option('--reset', 'Performs a build without using the cache.')
|
|
438
451
|
.option('--dev', 'Use development mode.')
|
|
439
452
|
.option('--pull-dockerhub <dockerhub-image>', 'Sets a custom Docker Hub image for base image pulls.')
|
|
453
|
+
.option(
|
|
454
|
+
'--import-tar <tar-path>',
|
|
455
|
+
'Load a pre-built image tar archive (e.g. ./image-v1.0.0.tar) into the enabled target(s) without building. Combine with --kind, --kubeadm, --k3s and/or --docker-compose; the archive is loaded into each enabled one.',
|
|
456
|
+
)
|
|
440
457
|
.description('Manages Docker images, including building, saving, and loading into Kubernetes clusters.')
|
|
441
458
|
.action(async (options) => {
|
|
442
459
|
if (options.rm) Underpost.image.rm({ ...options, imageName: options.rm });
|
|
443
460
|
if (options.ls) Underpost.image.list({ ...options, log: true });
|
|
444
461
|
if (options.pullBase) Underpost.image.pullBaseImages(options);
|
|
445
462
|
if (options.build) Underpost.image.build(options);
|
|
463
|
+
if (options.importTar) Underpost.image.importTar(options);
|
|
446
464
|
if (options.pullDockerhub)
|
|
447
465
|
Underpost.image.pullDockerHubImage({ ...options, dockerhubImage: options.pullDockerhub });
|
|
448
466
|
});
|
|
@@ -630,6 +648,10 @@ program
|
|
|
630
648
|
.option('--replicas <replicas>', 'Sets a custom number of replicas for deployment.')
|
|
631
649
|
.option('--pod-name <pod-name>', 'Optional: Specifies the pod name for execution.')
|
|
632
650
|
.option('--node-name <node-name>', 'Optional: Specifies the node name for execution.')
|
|
651
|
+
.option(
|
|
652
|
+
'--ssh-key-path <path>',
|
|
653
|
+
'Optional: Private key path for node SSH operations, forwarded to volume shipping over SSH. Defaults to engine-private/deploy/id_rsa.',
|
|
654
|
+
)
|
|
633
655
|
.option('--port <port>', 'Optional: Specifies the port for execution.')
|
|
634
656
|
.option('--etc-hosts', 'Enables etc-hosts context for the runner execution.')
|
|
635
657
|
.option('--volume-host-path <volume-host-path>', 'Optional: Specifies the volume host path for test execution.')
|
|
@@ -678,6 +700,7 @@ program
|
|
|
678
700
|
.option('--kubeadm', 'Sets the kubeadm cluster context for the runner execution.')
|
|
679
701
|
.option('--k3s', 'Sets the k3s cluster context for the runner execution.')
|
|
680
702
|
.option('--kind', 'Sets the kind cluster context for the runner execution.')
|
|
703
|
+
.option('--traffic <traffic>', 'Blue/green traffic colour to bake into generated manifests (default: blue).')
|
|
681
704
|
.option('--git-clean', 'Runs git clean on volume mount paths before copying.')
|
|
682
705
|
.option('--deploy-id <deploy-id>', 'Sets deploy id context for the runner execution.')
|
|
683
706
|
.option('--user <user>', 'Sets user context for the runner execution.')
|
|
@@ -738,6 +761,43 @@ program
|
|
|
738
761
|
.description('Runs specified scripts using various runners.')
|
|
739
762
|
.action(Underpost.run.callback);
|
|
740
763
|
|
|
764
|
+
program
|
|
765
|
+
.command('docker-compose')
|
|
766
|
+
.argument('[target]', 'Optional service name for --logs, --shell, --restart, or --build.')
|
|
767
|
+
.option('--install', 'Install Docker Engine and the Compose v2 plugin on RHEL/Rocky hosts.')
|
|
768
|
+
.option(
|
|
769
|
+
'--reset',
|
|
770
|
+
'Comprehensive teardown (equivalent to cluster --reset): removes all stack containers, the network, named volumes (destroys data), orphans, and generated artifacts.',
|
|
771
|
+
)
|
|
772
|
+
.option('--force', 'Force reinstall (--install), remove volumes (--down), or also drop the env-file (--reset).')
|
|
773
|
+
.option(
|
|
774
|
+
'--deploy-id <deploy-id>',
|
|
775
|
+
"Deployment to run as the app container (default: dd-default). 'dd-default' self-bootstraps a fresh engine; any other id runs the standard 'underpost start' command (mirrors src/cli/deploy.js).",
|
|
776
|
+
)
|
|
777
|
+
.option(
|
|
778
|
+
'--docker-compose-id <docker-compose-id>',
|
|
779
|
+
'Selects a canonical custom-workflow stack at engine-private/conf/<deploy-id>/docker-compose/<docker-compose-id>/ ' +
|
|
780
|
+
'(docker-compose.yml + compose.env + nginx.conf, used as-is; nginx/env generation is skipped). ' +
|
|
781
|
+
'e.g. --deploy-id dd-cyberia --docker-compose-id cyberia for the Cyberia MMO ecosystem.',
|
|
782
|
+
)
|
|
783
|
+
.option('--env <env>', 'Deployment environment for non-default deploy ids (default: development).')
|
|
784
|
+
.option('--generate', 'Render dynamic supporting files (nginx router config, env-file, app-command override).')
|
|
785
|
+
.option('--up', 'Start the full stack detached (regenerates config first).')
|
|
786
|
+
.option('--down', 'Stop and remove containers (and orphans).')
|
|
787
|
+
.option('--volumes', 'With --down, also remove named volumes (destroys persisted data).')
|
|
788
|
+
.option('--restart', 'Restart services (optionally a single [target]).')
|
|
789
|
+
.option('--build', 'With --up rebuild images; alone, rebuilds images with --no-cache.')
|
|
790
|
+
.option('--pull', 'Pull upstream images for all services.')
|
|
791
|
+
.option('--logs', 'Follow logs for all services (optionally a single [target]).')
|
|
792
|
+
.option('--status', 'Show a formatted status table of services.')
|
|
793
|
+
.option('--shell', 'Open an interactive shell in [target] (default: app).')
|
|
794
|
+
.option('--exec <subcommand>', 'General-purpose passthrough docker compose subcommand.')
|
|
795
|
+
.option('--compose-file <path>', 'Path to the compose file (default: docker-compose.yml).')
|
|
796
|
+
.option('--env-file <path>', 'Path to the compose env-file (default: docker/compose.env).')
|
|
797
|
+
.option('--nginx-conf <path>', 'Path to the generated nginx config (default: docker/nginx/default.conf).')
|
|
798
|
+
.description('General-purpose Docker Compose development pipeline (mirrors the Kubernetes dev stack).')
|
|
799
|
+
.action(Underpost.dockerCompose.callback);
|
|
800
|
+
|
|
741
801
|
program
|
|
742
802
|
.command('lxd')
|
|
743
803
|
.argument(
|
|
@@ -856,6 +916,42 @@ program
|
|
|
856
916
|
.option('--remove-machines <system-ids>', 'Removes baremetal machines by comma-separated system IDs, or use "all"')
|
|
857
917
|
.option('--clear-discovered', 'Clears all discovered baremetal machines from the database.')
|
|
858
918
|
.option('--commission', 'Init workflow for commissioning a physical machine.')
|
|
919
|
+
.option(
|
|
920
|
+
'--install-disk [device]',
|
|
921
|
+
'Explicit target install disk for Rocky deployment (e.g. /dev/nvme0n1). Omit or leave empty to auto-detect the internal disk.',
|
|
922
|
+
)
|
|
923
|
+
.option(
|
|
924
|
+
'--no-auto-install',
|
|
925
|
+
'Disables the ephemeral runtime AUTO_INSTALL fallback (controller must trigger install).',
|
|
926
|
+
)
|
|
927
|
+
.option('--no-remote-install', 'Skips the controller-side remote install orchestration over SSH.')
|
|
928
|
+
.option(
|
|
929
|
+
'--worker',
|
|
930
|
+
'Post-install infra role: join the deployed node as a Kubernetes worker (requires --control <ip>). Without this flag the node is set up as a control-plane.',
|
|
931
|
+
)
|
|
932
|
+
.option('--control <ip>', 'Control-plane IP the worker node joins (used with --worker for kubeadm infra setup).')
|
|
933
|
+
.option(
|
|
934
|
+
'--ssh-key-dir <dir>',
|
|
935
|
+
'Directory holding the SSH key pair used for commissioning/orchestration (expects <dir>/id_rsa and <dir>/id_rsa.pub). Overrides the workflow "sshKeyDir"; defaults to engine-private/deploy. Supports a leading ~.',
|
|
936
|
+
)
|
|
937
|
+
.option(
|
|
938
|
+
'--deploy-id <deploy-id>',
|
|
939
|
+
'Deployment ID whose user key pair is used for SSH (key from engine-private/conf/<deploy-id>/users/<user>/id_rsa). Same user↔deployId↔key convention as the ssh command.',
|
|
940
|
+
)
|
|
941
|
+
.option(
|
|
942
|
+
'--user <user>',
|
|
943
|
+
'SSH user paired with --deploy-id for key resolution and the login user on an existing control-plane (defaults to root). Mirrors the ssh command --user.',
|
|
944
|
+
)
|
|
945
|
+
.option(
|
|
946
|
+
'--engine-repo <url>',
|
|
947
|
+
'Custom engine repo cloned + normalized to /home/dd/engine on the node (default: <GITHUB_USERNAME>/engine).',
|
|
948
|
+
)
|
|
949
|
+
.option('--engine-branch <branch>', 'Branch of the engine repo to clone on the node.')
|
|
950
|
+
.option(
|
|
951
|
+
'--engine-private-repo <url>',
|
|
952
|
+
'Custom private repo cloned + normalized to /home/dd/engine/engine-private on the node (default: <GITHUB_USERNAME>/engine-<id>-private).',
|
|
953
|
+
)
|
|
954
|
+
.option('--engine-private-branch <branch>', 'Branch of the engine-private repo to clone on the node.')
|
|
859
955
|
.option(
|
|
860
956
|
'--bootstrap-http-server-run',
|
|
861
957
|
'Runs a temporary bootstrap HTTP server for generic purposes such as serving iPXE scripts or ISO images during commissioning.',
|
|
@@ -896,6 +992,14 @@ program
|
|
|
896
992
|
)
|
|
897
993
|
.option('--dev', 'Sets the development context environment for baremetal operations.')
|
|
898
994
|
.option('--ls', 'Lists available boot resources and machines.')
|
|
995
|
+
.option(
|
|
996
|
+
'--resume-infra-setup',
|
|
997
|
+
'Skip commissioning, OS install, and all bootstrapping; resume only the SSH-based infra setup (kubeadm join/init) on a node that already has the OS installed and is reachable via SSH.',
|
|
998
|
+
)
|
|
999
|
+
.option(
|
|
1000
|
+
'--resume-join',
|
|
1001
|
+
'Skip everything except the kubeadm join command. Assumes engine, Node.js, CRI-O, kubelet, and kubeadm are already installed. Only retrieves a fresh join token from the control-plane and runs kubeadm join.',
|
|
1002
|
+
)
|
|
899
1003
|
.description(
|
|
900
1004
|
'Manages baremetal server operations, including installation, database setup, commissioning, and user management.',
|
|
901
1005
|
)
|