@or3/cloud 0.1.64 → 0.1.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/cli.mjs +19 -8
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -92,6 +92,12 @@ carry a deployment-local authentication tag, so an altered or foreign archive
|
|
|
92
92
|
cannot supply configuration or executable Compose assets. Every mutating
|
|
93
93
|
command holds one deployment-wide lease; do not delete `.or3-cloud` lock or
|
|
94
94
|
recovery files by hand.
|
|
95
|
+
Update recovery reads the authenticated pre-update snapshot recorded in
|
|
96
|
+
`backupPath`/`backupId`; restore and rollback recovery use their separate
|
|
97
|
+
`previousBackupPath`/`previousBackupId` snapshot. Recovery restores that snapshot,
|
|
98
|
+
including its data and release assets, before clearing the pending operation.
|
|
99
|
+
Legacy `adopt-source-*` directories are preserved outside managed backup
|
|
100
|
+
retention and are not treated as authenticated restore points.
|
|
95
101
|
Backup artifacts are allocated in that journal before archiving, fully
|
|
96
102
|
revalidated before success is reported, and safely removed by `recover` if a
|
|
97
103
|
hard interruption leaves an incomplete artifact. A standalone backup and a
|
package/dist/cli.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { createReadStream, createWriteStream, existsSync, readFileSync } from "n
|
|
|
11
11
|
import {
|
|
12
12
|
chmod,
|
|
13
13
|
copyFile,
|
|
14
|
+
lstat,
|
|
14
15
|
mkdir,
|
|
15
16
|
open,
|
|
16
17
|
readFile,
|
|
@@ -30,7 +31,7 @@ import { fileURLToPath } from "node:url";
|
|
|
30
31
|
import { createGunzip } from "node:zlib";
|
|
31
32
|
var execFile = promisify(execFileCallback);
|
|
32
33
|
var PACKAGE_ROOT = resolve(fileURLToPath(new URL("../", import.meta.url)));
|
|
33
|
-
var PACKAGE_VERSION = "0.1.
|
|
34
|
+
var PACKAGE_VERSION = "0.1.65";
|
|
34
35
|
var IMAGE_REPOSITORY = "ghcr.io/saluana/or3-chat";
|
|
35
36
|
var ASSET_ROOT = resolve(fileURLToPath(new URL("../assets/", import.meta.url)));
|
|
36
37
|
var STATE_SCHEMA_VERSION = 1;
|
|
@@ -1835,6 +1836,9 @@ async function enumerateBackups(directory) {
|
|
|
1835
1836
|
}
|
|
1836
1837
|
const result = [];
|
|
1837
1838
|
for (const entry of entries) {
|
|
1839
|
+
if (/^adopt-source-[0-9A-Za-z-]+$/.test(entry) && (await lstat(join(backupsRoot, entry))).isDirectory()) {
|
|
1840
|
+
continue;
|
|
1841
|
+
}
|
|
1838
1842
|
if (!BACKUP_ID_PATTERN.test(entry)) {
|
|
1839
1843
|
throw new Error(`Backup store contains an unexpected artifact ${join(backupsRoot, entry)}. Refusing to use it for retention; inspect or remove it explicitly.`);
|
|
1840
1844
|
}
|
|
@@ -2996,7 +3000,15 @@ async function resolveBackup(directory, value) {
|
|
|
2996
3000
|
throw new Error(`Backup ${value} was not found in ${deploymentPaths(directory).backups}.`);
|
|
2997
3001
|
return resolve(candidate);
|
|
2998
3002
|
}
|
|
2999
|
-
|
|
3003
|
+
function assertDashboardOperatorMounts(mounts, directory) {
|
|
3004
|
+
const destinations = new Set(mounts.map((mount) => mount.Destination));
|
|
3005
|
+
for (const destination of ["/var/run/docker.sock", resolve(directory), "/run/or3-operator"]) {
|
|
3006
|
+
if (!destinations.has(destination))
|
|
3007
|
+
throw new Error(`Dashboard operator is missing its required ${destination} mount.`);
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
async function recordedBackupPath(directory, pending) {
|
|
3011
|
+
const previous = pending.operation !== "update";
|
|
3000
3012
|
const path = previous ? pending.previousBackupPath : pending.backupPath;
|
|
3001
3013
|
const backupId = previous ? pending.previousBackupId : pending.backupId;
|
|
3002
3014
|
const resolved = path ? resolve(path) : backupId ? await resolveBackup(directory, backupId) : undefined;
|
|
@@ -3021,7 +3033,7 @@ async function restorePreMutationSnapshot(directory, state, env) {
|
|
|
3021
3033
|
const pending = state.incompleteOperation;
|
|
3022
3034
|
if (!pending)
|
|
3023
3035
|
throw new Error("No incomplete operation is available to restore.");
|
|
3024
|
-
const previous = await recordedBackupPath(directory, pending
|
|
3036
|
+
const previous = await recordedBackupPath(directory, pending);
|
|
3025
3037
|
await updatePending(directory, state, { phase: "restoring-previous" });
|
|
3026
3038
|
if (pending.recreateDataVolume) {
|
|
3027
3039
|
await restoreBackupData(directory, state, env, previous.path, { recreateDataVolume: true });
|
|
@@ -3309,11 +3321,7 @@ async function doctorCommand(directory) {
|
|
|
3309
3321
|
if (state.deploymentId && container.Config?.Labels?.["io.or3.cloud.deployment-id"] !== state.deploymentId) {
|
|
3310
3322
|
throw new Error("Dashboard operator deployment identity does not match managed state.");
|
|
3311
3323
|
}
|
|
3312
|
-
|
|
3313
|
-
for (const destination of ["/var/run/docker.sock", "/deployment", "/run/or3-operator"]) {
|
|
3314
|
-
if (!destinations.has(destination))
|
|
3315
|
-
throw new Error(`Dashboard operator is missing its required ${destination} mount.`);
|
|
3316
|
-
}
|
|
3324
|
+
assertDashboardOperatorMounts(container.Mounts ?? [], resolved);
|
|
3317
3325
|
const ipcDirectory = await stat(paths.operatorIpc);
|
|
3318
3326
|
const operatorSocket = await stat(join(paths.operatorIpc, "operator.sock"));
|
|
3319
3327
|
const operatorUid = Number(env.OR3_OPERATOR_UID);
|
|
@@ -4634,11 +4642,13 @@ export {
|
|
|
4634
4642
|
restoreManagedAssets,
|
|
4635
4643
|
requiredArchiveSpace,
|
|
4636
4644
|
redact,
|
|
4645
|
+
recordedBackupPath,
|
|
4637
4646
|
purgeVolumesFromState,
|
|
4638
4647
|
parseFlags,
|
|
4639
4648
|
parseEnv,
|
|
4640
4649
|
managedAssetNames,
|
|
4641
4650
|
isVersion,
|
|
4651
|
+
enumerateBackups,
|
|
4642
4652
|
dashboardOperatorHandoffArgs,
|
|
4643
4653
|
copyAssets,
|
|
4644
4654
|
checkResolvedLoopbackBinding,
|
|
@@ -4652,6 +4662,7 @@ export {
|
|
|
4652
4662
|
assertPurgeBackupFreshness,
|
|
4653
4663
|
assertImageReleaseLabels,
|
|
4654
4664
|
assertEnoughFreeSpace,
|
|
4665
|
+
assertDashboardOperatorMounts,
|
|
4655
4666
|
assertCommandPositionals,
|
|
4656
4667
|
assertCommandFlags,
|
|
4657
4668
|
assertBackupMatchesDeployment,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@or3/cloud",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.65",
|
|
4
4
|
"description": "Install and operate the OR3 Cloud container distribution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
"or3Cloud": {
|
|
19
19
|
"dashboardUpdateProtocol": 1,
|
|
20
20
|
"dashboardUpdateMinimumSourceVersion": "0.1.40",
|
|
21
|
-
"imageDigest": "sha256:
|
|
22
|
-
"operatorImageDigest": "sha256:
|
|
23
|
-
"sourceRevision": "
|
|
21
|
+
"imageDigest": "sha256:cce2c2331419dbb2e2d0b17e0a7da0c9f3106b3c6dc30f680a6d9f145f0c6c6e",
|
|
22
|
+
"operatorImageDigest": "sha256:b8732a186a6bcfbd47f93333b7ed90991b20f4dd569ec08aec509e9f21ab6561",
|
|
23
|
+
"sourceRevision": "19b8889981b2f5f958c23679887a9a4bebd0f58c"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|