underpost 3.2.5 → 3.2.8
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/.github/workflows/release.cd.yml +1 -2
- package/CHANGELOG.md +251 -1
- package/CLI-HELP.md +26 -13
- package/Dockerfile +0 -4
- package/README.md +3 -3
- package/bin/build.js +13 -3
- package/bin/deploy.js +570 -1
- package/bin/file.js +5 -0
- package/conf.js +11 -2
- package/jsconfig.json +1 -1
- 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-default-development/deployment.yaml +2 -6
- package/manifests/deployment/dd-test-development/deployment.yaml +136 -66
- package/manifests/deployment/dd-test-development/proxy.yaml +41 -5
- package/package.json +20 -11
- package/src/api/core/core.controller.js +10 -10
- package/src/api/core/core.service.js +10 -10
- package/src/api/default/default.controller.js +10 -10
- package/src/api/default/default.service.js +10 -10
- package/src/api/document/document.controller.js +12 -12
- package/src/api/document/document.model.js +10 -16
- package/src/api/file/file.controller.js +8 -8
- package/src/api/file/file.model.js +10 -10
- package/src/api/file/file.service.js +36 -36
- package/src/api/test/test.controller.js +8 -8
- package/src/api/test/test.service.js +8 -8
- package/src/api/user/guest.service.js +99 -0
- package/src/api/user/user.controller.js +6 -6
- package/src/api/user/user.model.js +8 -13
- package/src/api/user/user.service.js +3 -20
- package/src/cli/deploy.js +33 -30
- package/src/cli/fs.js +62 -5
- package/src/cli/image.js +43 -1
- package/src/cli/index.js +5 -1
- package/src/cli/release.js +57 -1
- package/src/cli/repository.js +35 -3
- package/src/cli/run.js +300 -35
- package/src/cli/ssh.js +1 -1
- package/src/cli/static.js +43 -115
- package/src/client/Default.index.js +21 -33
- package/src/client/components/core/404.js +4 -4
- package/src/client/components/core/500.js +4 -4
- package/src/client/components/core/Account.js +73 -60
- package/src/client/components/core/AgGrid.js +23 -33
- package/src/client/components/core/Alert.js +12 -13
- package/src/client/components/core/AppStore.js +1 -1
- package/src/client/components/core/Auth.js +20 -32
- package/src/client/components/core/Badge.js +7 -13
- package/src/client/components/core/BtnIcon.js +15 -17
- package/src/client/components/core/CalendarCore.js +42 -63
- package/src/client/components/core/Chat.js +13 -15
- package/src/client/components/core/ClientEvents.js +87 -0
- package/src/client/components/core/ColorPaletteElement.js +309 -0
- package/src/client/components/core/Content.js +17 -14
- package/src/client/components/core/Css.js +15 -71
- package/src/client/components/core/CssCore.js +12 -16
- package/src/client/components/core/D3Chart.js +4 -4
- package/src/client/components/core/Docs.js +60 -59
- package/src/client/components/core/DropDown.js +69 -91
- package/src/client/components/core/EventBus.js +92 -0
- package/src/client/components/core/EventsUI.js +14 -17
- package/src/client/components/core/FileExplorer.js +102 -234
- package/src/client/components/core/FullScreen.js +47 -75
- package/src/client/components/core/Input.js +24 -69
- package/src/client/components/core/Keyboard.js +25 -18
- package/src/client/components/core/KeyboardAvoidance.js +145 -0
- package/src/client/components/core/LoadingAnimation.js +25 -31
- package/src/client/components/core/LogIn.js +41 -41
- package/src/client/components/core/LogOut.js +23 -14
- package/src/client/components/core/Modal.js +397 -176
- package/src/client/components/core/NotificationManager.js +14 -18
- package/src/client/components/core/Panel.js +54 -50
- package/src/client/components/core/PanelForm.js +25 -125
- package/src/client/components/core/Polyhedron.js +110 -214
- package/src/client/components/core/PublicProfile.js +39 -32
- package/src/client/components/core/Recover.js +52 -48
- package/src/client/components/core/Responsive.js +88 -32
- package/src/client/components/core/RichText.js +9 -18
- package/src/client/components/core/Router.js +24 -3
- package/src/client/components/core/SearchBox.js +37 -37
- package/src/client/components/core/SignUp.js +39 -30
- package/src/client/components/core/SocketIo.js +31 -2
- package/src/client/components/core/SocketIoHandler.js +6 -6
- package/src/client/components/core/ToggleSwitch.js +8 -20
- package/src/client/components/core/ToolTip.js +5 -17
- package/src/client/components/core/Translate.js +56 -59
- package/src/client/components/core/Validator.js +26 -16
- package/src/client/components/core/Wallet.js +15 -26
- package/src/client/components/core/Worker.js +140 -25
- package/src/client/components/core/windowGetDimensions.js +7 -7
- package/src/client/components/default/{MenuDefault.js → AppShellDefault.js} +87 -87
- package/src/client/components/default/CssDefault.js +12 -12
- package/src/client/components/default/LogInDefault.js +6 -4
- package/src/client/components/default/LogOutDefault.js +6 -4
- package/src/client/components/default/RouterDefault.js +47 -0
- package/src/client/components/default/SettingsDefault.js +4 -4
- package/src/client/components/default/SignUpDefault.js +6 -4
- package/src/client/components/default/TranslateDefault.js +3 -3
- package/src/client/services/core/core.service.js +17 -49
- package/src/client/services/default/default.management.js +139 -242
- package/src/client/services/default/default.service.js +10 -16
- package/src/client/services/document/document.service.js +14 -19
- package/src/client/services/file/file.service.js +8 -13
- package/src/client/services/test/test.service.js +8 -13
- package/src/client/services/user/guest.service.js +79 -0
- package/src/client/services/user/user.management.js +5 -5
- package/src/client/services/user/user.service.js +14 -20
- package/src/client/ssr/body/404.js +3 -3
- package/src/client/ssr/body/500.js +3 -3
- package/src/client/ssr/body/CacheControl.js +5 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +19 -12
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +19 -20
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +15 -16
- package/src/client/ssr/offline/Maintenance.js +12 -11
- package/src/client/ssr/offline/NoNetworkConnection.js +3 -3
- package/src/client/ssr/pages/Test.js +2 -2
- package/src/client/sw/core.sw.js +212 -0
- package/src/index.js +1 -1
- package/src/runtime/express/Dockerfile +4 -4
- package/src/runtime/lampp/Dockerfile +8 -7
- package/src/runtime/wp/Dockerfile +11 -17
- package/src/server/client-build-docs.js +45 -46
- package/src/server/client-build.js +334 -60
- package/src/server/client-formatted.js +47 -16
- package/src/server/conf.js +5 -4
- package/src/server/ipfs-client.js +232 -91
- package/src/server/process.js +13 -27
- package/src/server/start.js +6 -3
- package/src/server/valkey.js +134 -235
- package/tsconfig.docs.json +15 -0
- package/typedoc.json +20 -0
- package/jsdoc.json +0 -52
- package/src/client/components/core/ColorPalette.js +0 -5267
- package/src/client/components/core/JoyStick.js +0 -80
- package/src/client/components/default/RoutesDefault.js +0 -49
- package/src/client/sw/default.sw.js +0 -127
- package/src/client/sw/template.sw.js +0 -84
package/src/cli/run.js
CHANGED
|
@@ -93,7 +93,6 @@ const logger = loggerFactory(import.meta);
|
|
|
93
93
|
* @property {boolean} kubeadm - Whether to run in kubeadm mode.
|
|
94
94
|
* @property {boolean} kind - Whether to run in kind mode.
|
|
95
95
|
* @property {boolean} k3s - Whether to run in k3s mode.
|
|
96
|
-
* @property {string} logType - The type of log to generate.
|
|
97
96
|
* @property {string} hosts - The hosts to use.
|
|
98
97
|
* @property {string} deployId - The deployment ID.
|
|
99
98
|
* @property {string} instanceId - The instance ID.
|
|
@@ -158,7 +157,6 @@ const DEFAULT_OPTION = {
|
|
|
158
157
|
kubeadm: false,
|
|
159
158
|
kind: false,
|
|
160
159
|
k3s: false,
|
|
161
|
-
logType: '',
|
|
162
160
|
hosts: '',
|
|
163
161
|
deployId: '',
|
|
164
162
|
instanceId: '',
|
|
@@ -490,21 +488,6 @@ class UnderpostRun {
|
|
|
490
488
|
: await Underpost.release.pwa(sanitizedMessage, options);
|
|
491
489
|
pbcopy(triggerCmd + ' && cd /home/dd/engine');
|
|
492
490
|
},
|
|
493
|
-
/**
|
|
494
|
-
* @method template-deploy-image
|
|
495
|
-
* @description Dispatches the Docker image CI workflow for the `engine` repository.
|
|
496
|
-
* @param {string} path - The input value, identifier, or path for the operation.
|
|
497
|
-
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
498
|
-
* @memberof UnderpostRun
|
|
499
|
-
*/
|
|
500
|
-
'template-deploy-image': (path, options = DEFAULT_OPTION) => {
|
|
501
|
-
Underpost.repo.dispatchWorkflow({
|
|
502
|
-
repo: `${process.env.GITHUB_USERNAME}/engine`,
|
|
503
|
-
workflowFile: 'docker-image.ci.yml',
|
|
504
|
-
ref: 'master',
|
|
505
|
-
inputs: {},
|
|
506
|
-
});
|
|
507
|
-
},
|
|
508
491
|
/**
|
|
509
492
|
* @method docker-image
|
|
510
493
|
* @description Dispatches the Docker image CI workflow (`docker-image.ci.yml`) for the `engine` repository via `workflow_dispatch`.
|
|
@@ -515,7 +498,7 @@ class UnderpostRun {
|
|
|
515
498
|
'docker-image': (path, options = DEFAULT_OPTION) => {
|
|
516
499
|
Underpost.repo.dispatchWorkflow({
|
|
517
500
|
repo: `${process.env.GITHUB_USERNAME}/engine`,
|
|
518
|
-
workflowFile:
|
|
501
|
+
workflowFile: `docker-image${path ? `.${path}` : ''}.ci.yml`,
|
|
519
502
|
ref: 'master',
|
|
520
503
|
inputs: {},
|
|
521
504
|
});
|
|
@@ -652,7 +635,7 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
|
|
|
652
635
|
sync: async (path, options = DEFAULT_OPTION) => {
|
|
653
636
|
// Dev usage: node bin run --dev --build sync dd-default
|
|
654
637
|
const env = options.dev ? 'development' : 'production';
|
|
655
|
-
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
638
|
+
const baseCommand = 'node bin'; // options.dev ? 'node bin' : 'underpost';
|
|
656
639
|
const baseClusterCommand = options.dev ? ' --dev' : '';
|
|
657
640
|
const clusterFlag = options.k3s ? ' --k3s' : options.kind ? ' --kind' : ' --kubeadm';
|
|
658
641
|
const defaultPath = [
|
|
@@ -669,6 +652,15 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
|
|
|
669
652
|
image = image ? image : defaultPath[3];
|
|
670
653
|
node = node ? node : defaultPath[4];
|
|
671
654
|
shellExec(`${baseCommand} cluster --ns-use ${options.namespace}`);
|
|
655
|
+
|
|
656
|
+
if (image && !image.startsWith('localhost'))
|
|
657
|
+
Underpost.image.pullDockerHubImage({
|
|
658
|
+
dockerhubImage: image,
|
|
659
|
+
kind: options.kind || (!options.nodeName && !options.kubeadm && !options.k3s),
|
|
660
|
+
kubeadm: options.nodeName || options.kubeadm,
|
|
661
|
+
k3s: options.k3s,
|
|
662
|
+
});
|
|
663
|
+
|
|
672
664
|
if (isDeployRunnerContext(path, options)) {
|
|
673
665
|
if (!options.disablePrivateConfUpdate) {
|
|
674
666
|
const { validVersion } = Underpost.repo.privateConfUpdate(deployId);
|
|
@@ -928,12 +920,17 @@ echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com
|
|
|
928
920
|
image: _image,
|
|
929
921
|
fromPort: _fromPort,
|
|
930
922
|
toPort: _toPort,
|
|
923
|
+
fromDebugPort: _fromDebugPort,
|
|
924
|
+
toDebugPort: _toDebugPort,
|
|
931
925
|
cmd: _cmd,
|
|
932
926
|
volumes: _volumes,
|
|
933
927
|
metadata: _metadata,
|
|
934
928
|
} = instance;
|
|
935
929
|
if (id !== _id) continue;
|
|
936
930
|
const _deployId = `${deployId}-${_id}`;
|
|
931
|
+
// Use debug ports in development when defined, fall back to production ports.
|
|
932
|
+
if (env === 'development' && _fromDebugPort) _fromPort = _fromDebugPort;
|
|
933
|
+
if (env === 'development' && _toDebugPort) _toPort = _toDebugPort;
|
|
937
934
|
const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
|
|
938
935
|
hostTest: _host,
|
|
939
936
|
namespace: options.namespace,
|
|
@@ -1003,12 +1000,17 @@ EOF
|
|
|
1003
1000
|
image: _image,
|
|
1004
1001
|
fromPort: _fromPort,
|
|
1005
1002
|
toPort: _toPort,
|
|
1003
|
+
fromDebugPort: _fromDebugPort,
|
|
1004
|
+
toDebugPort: _toDebugPort,
|
|
1006
1005
|
cmd: _cmd,
|
|
1007
1006
|
volumes: _volumes,
|
|
1008
1007
|
metadata: _metadata,
|
|
1009
1008
|
} = instance;
|
|
1010
1009
|
if (id !== _id) continue;
|
|
1011
1010
|
const _deployId = `${deployId}-${_id}`;
|
|
1011
|
+
// Use debug ports in development when defined, fall back to production ports.
|
|
1012
|
+
if (env === 'development' && _fromDebugPort) _fromPort = _fromDebugPort;
|
|
1013
|
+
if (env === 'development' && _toDebugPort) _toPort = _toDebugPort;
|
|
1012
1014
|
etcHosts.push(_host);
|
|
1013
1015
|
if (options.expose) continue;
|
|
1014
1016
|
// Examples images:
|
|
@@ -1016,12 +1018,13 @@ EOF
|
|
|
1016
1018
|
// `localhost/rockylinux9-underpost:${Underpost.version}`
|
|
1017
1019
|
if (!_image) _image = `underpost/underpost-engine:${Underpost.version}`;
|
|
1018
1020
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1021
|
+
if (_image && !_image.startsWith('localhost'))
|
|
1022
|
+
Underpost.image.pullDockerHubImage({
|
|
1023
|
+
dockerhubImage: _image,
|
|
1024
|
+
kind: options.kind || (!options.nodeName && !options.kubeadm && !options.k3s),
|
|
1025
|
+
kubeadm: options.nodeName || options.kubeadm,
|
|
1026
|
+
k3s: options.k3s,
|
|
1027
|
+
});
|
|
1025
1028
|
|
|
1026
1029
|
const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
|
|
1027
1030
|
hostTest: _host,
|
|
@@ -1095,7 +1098,6 @@ EOF
|
|
|
1095
1098
|
targetTraffic,
|
|
1096
1099
|
ignorePods,
|
|
1097
1100
|
options.namespace,
|
|
1098
|
-
options.logType,
|
|
1099
1101
|
);
|
|
1100
1102
|
|
|
1101
1103
|
if (!ready) {
|
|
@@ -1115,6 +1117,153 @@ EOF
|
|
|
1115
1117
|
}
|
|
1116
1118
|
},
|
|
1117
1119
|
|
|
1120
|
+
/**
|
|
1121
|
+
* @method instance-build-manifest
|
|
1122
|
+
* @description Builds a Kubernetes Deployment + Service manifest for a specific instance entry
|
|
1123
|
+
* from `conf.instances.json` and writes it to a file.
|
|
1124
|
+
* Traffic colour is automatically chosen as the opposite of the current live colour (blue/green),
|
|
1125
|
+
* defaulting to `blue` when no deployment is running yet.
|
|
1126
|
+
*
|
|
1127
|
+
* If `--build` is supplied the image is built from the project Dockerfile and loaded into the
|
|
1128
|
+
* cluster before the manifest is written (kind by default; `--kubeadm` / `--k3s` override).
|
|
1129
|
+
*
|
|
1130
|
+
* @param {string} path - Comma-separated: `deployId,instanceId[,projectPath]`.
|
|
1131
|
+
* `projectPath` is the root directory that contains the `Dockerfile` (e.g. `./cyberia-client`).
|
|
1132
|
+
* Artifacts are written to `<projectPath>/manifests/<env>/Dockerfile` and
|
|
1133
|
+
* `<projectPath>/manifests/<env>/deployment.yaml`.
|
|
1134
|
+
* In production, files are also copied to `<projectPath>/Dockerfile` and
|
|
1135
|
+
* `<projectPath>/deployment.yaml`.
|
|
1136
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
1137
|
+
* @memberof UnderpostRun
|
|
1138
|
+
*/
|
|
1139
|
+
'instance-build-manifest': (path, options = DEFAULT_OPTION) => {
|
|
1140
|
+
const env = options.dev ? 'development' : 'production';
|
|
1141
|
+
let [deployId, id, projectPath] = path.split(',');
|
|
1142
|
+
const rootPath = projectPath ? projectPath : '.';
|
|
1143
|
+
const envManifestPath = `${rootPath}/manifests/deployments/${id}-${env}`;
|
|
1144
|
+
const outputPath = `${envManifestPath}/deployment.yaml`;
|
|
1145
|
+
const dockerfileManifestPath = `${envManifestPath}/Dockerfile`;
|
|
1146
|
+
|
|
1147
|
+
fs.mkdirpSync(envManifestPath);
|
|
1148
|
+
|
|
1149
|
+
const confInstances = JSON.parse(
|
|
1150
|
+
fs.readFileSync(`./engine-private/conf/${deployId}/conf.instances.json`, 'utf8'),
|
|
1151
|
+
);
|
|
1152
|
+
|
|
1153
|
+
const instance = confInstances.find((i) => i.id === id);
|
|
1154
|
+
if (!instance) {
|
|
1155
|
+
logger.error(`Instance with id '${id}' not found in conf.instances.json for deployId '${deployId}'`);
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
let {
|
|
1160
|
+
id: _id,
|
|
1161
|
+
host: _host,
|
|
1162
|
+
path: _path,
|
|
1163
|
+
image: _image,
|
|
1164
|
+
fromPort: _fromPort,
|
|
1165
|
+
toPort: _toPort,
|
|
1166
|
+
fromDebugPort: _fromDebugPort,
|
|
1167
|
+
toDebugPort: _toDebugPort,
|
|
1168
|
+
cmd: _cmd,
|
|
1169
|
+
volumes: _volumes,
|
|
1170
|
+
metadata: _metadata,
|
|
1171
|
+
runtime: _runtime,
|
|
1172
|
+
} = instance;
|
|
1173
|
+
|
|
1174
|
+
// Resolve Dockerfile source: use runtime-specific path when instance defines a runtime.
|
|
1175
|
+
const dockerfileSourcePath = _runtime ? `src/runtime/${_runtime}/Dockerfile` : `${rootPath}/Dockerfile`;
|
|
1176
|
+
if (fs.existsSync(dockerfileSourcePath)) {
|
|
1177
|
+
fs.copyFileSync(dockerfileSourcePath, dockerfileManifestPath);
|
|
1178
|
+
} else {
|
|
1179
|
+
logger.warn(`[instance-build-manifest] Dockerfile not found at ${dockerfileSourcePath}`);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
const _deployId = `${deployId}-${_id}`;
|
|
1183
|
+
if (!_image) _image = `underpost/underpost-engine:${Underpost.version}`;
|
|
1184
|
+
// Use debug ports in development when defined, fall back to production ports.
|
|
1185
|
+
if (env === 'development' && _fromDebugPort) _fromPort = _fromDebugPort;
|
|
1186
|
+
if (env === 'development' && _toDebugPort) _toPort = _toDebugPort;
|
|
1187
|
+
|
|
1188
|
+
// Build image from projectPath Dockerfile and load into cluster when --build is set.
|
|
1189
|
+
if (options.build && projectPath) {
|
|
1190
|
+
const isKind = !options.kubeadm && !options.k3s;
|
|
1191
|
+
Underpost.image.build({
|
|
1192
|
+
path: projectPath,
|
|
1193
|
+
imageName: _image,
|
|
1194
|
+
podmanSave: true,
|
|
1195
|
+
imagePath: projectPath,
|
|
1196
|
+
kind: isKind,
|
|
1197
|
+
kubeadm: !!options.kubeadm,
|
|
1198
|
+
k3s: !!options.k3s,
|
|
1199
|
+
reset: !!options.reset,
|
|
1200
|
+
dev: options.dev,
|
|
1201
|
+
});
|
|
1202
|
+
logger.info(`[instance-build-manifest] Image built and loaded`, {
|
|
1203
|
+
image: _image,
|
|
1204
|
+
cluster: isKind ? 'kind' : options.kubeadm ? 'kubeadm' : 'k3s',
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// Determine target traffic: opposite of current, or 'blue' if nothing is running yet.
|
|
1209
|
+
const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
|
|
1210
|
+
hostTest: _host,
|
|
1211
|
+
namespace: options.namespace,
|
|
1212
|
+
});
|
|
1213
|
+
const targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : 'blue';
|
|
1214
|
+
|
|
1215
|
+
// Resolve {{grpc-service-dns}} using the parent deploy's current (or default) traffic.
|
|
1216
|
+
const parentTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace }) || 'blue';
|
|
1217
|
+
const resolvedCmd = _cmd[env].map((c) =>
|
|
1218
|
+
c.replaceAll(
|
|
1219
|
+
'{{grpc-service-dns}}',
|
|
1220
|
+
`${deployId}-grpc-service-${env}-${parentTraffic}.${options.namespace || 'default'}.svc.cluster.local:50051`,
|
|
1221
|
+
),
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
const deploymentYaml =
|
|
1225
|
+
`---\n` +
|
|
1226
|
+
Underpost.deploy
|
|
1227
|
+
.deploymentYamlPartsFactory({
|
|
1228
|
+
deployId: _deployId,
|
|
1229
|
+
env,
|
|
1230
|
+
suffix: targetTraffic,
|
|
1231
|
+
resources: Underpost.deploy.resourcesFactory(options),
|
|
1232
|
+
replicas: options.replicas,
|
|
1233
|
+
image: _image,
|
|
1234
|
+
namespace: options.namespace,
|
|
1235
|
+
volumes: _volumes,
|
|
1236
|
+
cmd: resolvedCmd,
|
|
1237
|
+
})
|
|
1238
|
+
.replace('{{ports}}', buildKindPorts(_fromPort, _toPort));
|
|
1239
|
+
|
|
1240
|
+
fs.writeFileSync(outputPath, deploymentYaml, 'utf8');
|
|
1241
|
+
logger.info(`[instance-build-manifest] Manifest written to ${outputPath}`, {
|
|
1242
|
+
deployId: _deployId,
|
|
1243
|
+
env,
|
|
1244
|
+
traffic: targetTraffic,
|
|
1245
|
+
image: _image,
|
|
1246
|
+
});
|
|
1247
|
+
|
|
1248
|
+
if (env === 'production') {
|
|
1249
|
+
if (fs.existsSync(dockerfileManifestPath)) {
|
|
1250
|
+
fs.copyFileSync(dockerfileManifestPath, `${rootPath}/Dockerfile`);
|
|
1251
|
+
}
|
|
1252
|
+
fs.copyFileSync(outputPath, `${rootPath}/deployment.yaml`);
|
|
1253
|
+
logger.info('[instance-build-manifest] Production artifacts copied to project root', {
|
|
1254
|
+
rootPath,
|
|
1255
|
+
dockerfile: `${rootPath}/Dockerfile`,
|
|
1256
|
+
deployment: `${rootPath}/deployment.yaml`,
|
|
1257
|
+
});
|
|
1258
|
+
const ciSrc = `./.github/workflows/docker-image.${_runtime}.ci.yml`;
|
|
1259
|
+
if (fs.existsSync(ciSrc)) {
|
|
1260
|
+
if (!fs.existsSync(`${rootPath}/.github/workflows`)) fs.mkdirpSync(`${rootPath}/.github/workflows`);
|
|
1261
|
+
fs.copyFileSync(ciSrc, `${rootPath}/.github/workflows/docker-image.${_runtime}.ci.yml`);
|
|
1262
|
+
logger.info(`[instance-build-manifest] CI workflow copied`, { src: ciSrc });
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
},
|
|
1266
|
+
|
|
1118
1267
|
/**
|
|
1119
1268
|
* @method ls-deployments
|
|
1120
1269
|
* @description Retrieves and logs a table of Kubernetes deployments using `Underpost.deploy.get`.
|
|
@@ -1920,6 +2069,16 @@ EOF
|
|
|
1920
2069
|
|
|
1921
2070
|
shellCd('/home/dd/engine');
|
|
1922
2071
|
},
|
|
2072
|
+
/**
|
|
2073
|
+
* @method pull-rocky-image
|
|
2074
|
+
* @description Pulls the base `rockylinux:9` image from Docker Hub via Podman.
|
|
2075
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
2076
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
2077
|
+
* @memberof UnderpostRun
|
|
2078
|
+
*/
|
|
2079
|
+
'pull-rocky-image': (path, options = DEFAULT_OPTION) => {
|
|
2080
|
+
shellExec(`sudo podman pull docker.io/library/rockylinux:9`);
|
|
2081
|
+
},
|
|
1923
2082
|
/**
|
|
1924
2083
|
* @method rmi
|
|
1925
2084
|
* @description Forces the removal of all local Podman images (`podman rmi $(podman images -qa) --force`).
|
|
@@ -1949,13 +2108,6 @@ EOF
|
|
|
1949
2108
|
} else shellExec(`sudo kill -9 $(lsof -t -i:${_path})`);
|
|
1950
2109
|
}
|
|
1951
2110
|
},
|
|
1952
|
-
/**
|
|
1953
|
-
* @method secret
|
|
1954
|
-
* @description Creates an Underpost secret named 'underpost' from a file, defaulting to `/home/dd/engine/engine-private/conf/dd-cron/.env.production` if no path is provided.
|
|
1955
|
-
* @param {string} path - The input value, identifier, or path for the operation (used as the optional path to the secret file).
|
|
1956
|
-
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
1957
|
-
* @memberof UnderpostRun
|
|
1958
|
-
*/
|
|
1959
2111
|
/**
|
|
1960
2112
|
* @method generate-pass
|
|
1961
2113
|
* @description Generates a cryptographically secure random password that satisfies all validatePassword
|
|
@@ -1992,10 +2144,16 @@ EOF
|
|
|
1992
2144
|
if (options.copy) pbcopy(password);
|
|
1993
2145
|
else console.log(password);
|
|
1994
2146
|
},
|
|
1995
|
-
|
|
2147
|
+
/**
|
|
2148
|
+
* @method secret
|
|
2149
|
+
* @description Creates an Underpost secret named 'underpost' from a file, defaulting to `/home/dd/engine/engine-private/conf/dd-cron/.env.production` if no path is provided.
|
|
2150
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the optional path to the secret file).
|
|
2151
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
2152
|
+
* @memberof UnderpostRun
|
|
2153
|
+
*/
|
|
1996
2154
|
secret: (path, options = DEFAULT_OPTION) => {
|
|
1997
2155
|
const secretPath = path ? path : `/home/dd/engine/engine-private/conf/dd-cron/.env.production`;
|
|
1998
|
-
const command =
|
|
2156
|
+
const command = `${options.dev ? 'node bin' : 'underpost'} secret underpost --create-from-file ${secretPath}`;
|
|
1999
2157
|
shellExec(command);
|
|
2000
2158
|
},
|
|
2001
2159
|
/**
|
|
@@ -2166,6 +2324,113 @@ EOF`;
|
|
|
2166
2324
|
if (options.logs) shellExec(`kubectl logs -f ${podName} -n ${namespace}`, { async: true });
|
|
2167
2325
|
}
|
|
2168
2326
|
},
|
|
2327
|
+
|
|
2328
|
+
/**
|
|
2329
|
+
* @method push-bundle
|
|
2330
|
+
* @description Builds the client zip for the specified deployment, splits it into parts, and uploads to file storage.
|
|
2331
|
+
* Steps: set env, build+split zip, switch to cron env, upload parts to storage.
|
|
2332
|
+
* @param {string} path - Optional `fsPath.splitOption` string.
|
|
2333
|
+
* Examples: `build` (default split 8), `build.16` (split 16 MB), `build.none-split` (no split flag).
|
|
2334
|
+
* @param {Object} options - The default underpost runner options for customizing workflow.
|
|
2335
|
+
* @param {string} [options.deployId] - Override deploy ID.
|
|
2336
|
+
* @param {boolean} [options.dev] - Use development environment; defaults to production.
|
|
2337
|
+
* @memberof UnderpostRun
|
|
2338
|
+
*/
|
|
2339
|
+
'push-bundle': (path = '', options = DEFAULT_OPTION) => {
|
|
2340
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
2341
|
+
const env = options.dev ? 'development' : 'production';
|
|
2342
|
+
const deployId = options.deployId || 'dd-default';
|
|
2343
|
+
const pathParts = (path || '').split('.');
|
|
2344
|
+
const fsPath = (pathParts[0] || '').trim() || 'build';
|
|
2345
|
+
const splitOption = (pathParts[1] || '').trim();
|
|
2346
|
+
|
|
2347
|
+
let splitFlag = '--split 8';
|
|
2348
|
+
if (splitOption) {
|
|
2349
|
+
if (splitOption === 'none-split') {
|
|
2350
|
+
splitFlag = '';
|
|
2351
|
+
} else {
|
|
2352
|
+
const splitMb = Number(splitOption);
|
|
2353
|
+
if (Number.isFinite(splitMb) && splitMb > 0) {
|
|
2354
|
+
splitFlag = `--split ${splitMb}`;
|
|
2355
|
+
} else {
|
|
2356
|
+
logger.warn('push-bundle: invalid split option, using default split 8', {
|
|
2357
|
+
path,
|
|
2358
|
+
splitOption,
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
shellExec(`${baseCommand} env ${deployId} ${env}`);
|
|
2365
|
+
shellExec(`${baseCommand} client ${deployId} --build-zip${splitFlag ? ` ${splitFlag}` : ''}`);
|
|
2366
|
+
shellExec(
|
|
2367
|
+
`${baseCommand} fs ${fsPath} --recursive --deploy-id ${deployId} --storage-file-path engine-private/conf/${deployId}/storage.bundle.json --force`,
|
|
2368
|
+
);
|
|
2369
|
+
},
|
|
2370
|
+
|
|
2371
|
+
/**
|
|
2372
|
+
* @method pull-bundle
|
|
2373
|
+
* @description Downloads split zip parts from file storage, merges and extracts them, and moves the result into the public directory.
|
|
2374
|
+
* Steps: set cron env, download parts (omit-unzip), merge zip, unzip, remove zip, move to public/<host>.
|
|
2375
|
+
* @param {string} path - Optional host name(s) used to locate zip(s) and as public destination(s) (e.g. 'underpost.net' or 'a.com,b.com').
|
|
2376
|
+
* If omitted, hosts are loaded from `engine-private/conf/<deployId>/conf.server.json`.
|
|
2377
|
+
* @param {Object} options - The default underpost runner options for customizing workflow.
|
|
2378
|
+
* @param {string} [options.deployId] - Deploy ID for storage lookup (defaults to 'dd-default').
|
|
2379
|
+
* @param {boolean} [options.dev] - Use development environment; defaults to production.
|
|
2380
|
+
* @memberof UnderpostRun
|
|
2381
|
+
*/
|
|
2382
|
+
'pull-bundle': (path = '', options = DEFAULT_OPTION) => {
|
|
2383
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
2384
|
+
const env = options.dev ? 'development' : 'production';
|
|
2385
|
+
const deployId = options.deployId || 'dd-default';
|
|
2386
|
+
const confServerPath = `./engine-private/conf/${deployId}/conf.server.json`;
|
|
2387
|
+
const hosts = path
|
|
2388
|
+
? path
|
|
2389
|
+
.split(',')
|
|
2390
|
+
.map((h) => h.trim())
|
|
2391
|
+
.filter(Boolean)
|
|
2392
|
+
: fs.existsSync(confServerPath)
|
|
2393
|
+
? Object.keys(loadConfServerJson(confServerPath))
|
|
2394
|
+
: [];
|
|
2395
|
+
|
|
2396
|
+
if (hosts.length === 0) {
|
|
2397
|
+
logger.error('pull-bundle: no hosts resolved', {
|
|
2398
|
+
deployId,
|
|
2399
|
+
path,
|
|
2400
|
+
confServerPath,
|
|
2401
|
+
});
|
|
2402
|
+
return;
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
shellExec(`${baseCommand} env ${deployId} ${env}`);
|
|
2406
|
+
if (!fs.existsSync('./build')) fs.mkdirSync('./build', { recursive: true });
|
|
2407
|
+
shellExec(
|
|
2408
|
+
`${baseCommand} fs build --recursive --deploy-id ${deployId} --storage-file-path engine-private/conf/${deployId}/storage.bundle.json --pull --omit-unzip`,
|
|
2409
|
+
);
|
|
2410
|
+
for (const host of hosts) {
|
|
2411
|
+
const zipPath = `build/${host}-.zip`;
|
|
2412
|
+
const hasZip = fs.existsSync(zipPath);
|
|
2413
|
+
const hasParts =
|
|
2414
|
+
fs.existsSync('./build') &&
|
|
2415
|
+
fs
|
|
2416
|
+
.readdirSync('./build')
|
|
2417
|
+
.some((name) => name.startsWith(`${host}-.zip.part`) || name.startsWith(`${host}-.zip-part`));
|
|
2418
|
+
|
|
2419
|
+
if (!hasZip && !hasParts) {
|
|
2420
|
+
logger.warn(`Bundle not found for host '${host}'. Skipping host.`, {
|
|
2421
|
+
zipPath,
|
|
2422
|
+
deployId,
|
|
2423
|
+
});
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
if (hasParts) shellExec(`${baseCommand} client --merge-zip ${zipPath}`);
|
|
2428
|
+
shellExec(`${baseCommand} client --unzip ${zipPath}`);
|
|
2429
|
+
shellExec(`sudo rm -rf ${zipPath}`);
|
|
2430
|
+
if (fs.existsSync(`public/${host}`)) shellExec(`sudo rm -rf public/${host}`);
|
|
2431
|
+
shellExec(`sudo mv build/${host} public/${host}`);
|
|
2432
|
+
}
|
|
2433
|
+
},
|
|
2169
2434
|
};
|
|
2170
2435
|
|
|
2171
2436
|
static API = {
|
package/src/cli/ssh.js
CHANGED
|
@@ -315,7 +315,7 @@ EOF`);
|
|
|
315
315
|
console.log(`group_name : password_x : GID(Internal Group ID) : user_list`.blue);
|
|
316
316
|
console.log(filter ? groupsOut.replaceAll(filter, filter.red) : groupsOut);
|
|
317
317
|
console.log('Users'.bold.blue);
|
|
318
|
-
console.log(`
|
|
318
|
+
console.log(`user : x : UID : GID : GECOS : home_dir : shell`.blue);
|
|
319
319
|
console.log(filter ? usersOut.replaceAll(filter, filter.red) : usersOut);
|
|
320
320
|
}
|
|
321
321
|
|