@vellumai/cli 0.5.13 → 0.5.14
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/AGENTS.md +6 -0
- package/package.json +1 -1
- package/src/__tests__/teleport.test.ts +829 -0
- package/src/commands/hatch.ts +8 -3
- package/src/commands/ps.ts +1 -1
- package/src/commands/recover.ts +13 -4
- package/src/commands/rollback.ts +0 -9
- package/src/commands/teleport.ts +746 -0
- package/src/commands/upgrade.ts +0 -11
- package/src/commands/wake.ts +17 -4
- package/src/index.ts +3 -0
- package/src/lib/assistant-config.ts +3 -2
- package/src/lib/docker.ts +2 -146
- package/src/lib/local.ts +32 -2
- package/src/lib/upgrade-lifecycle.ts +0 -11
package/src/commands/upgrade.ts
CHANGED
|
@@ -13,8 +13,6 @@ import {
|
|
|
13
13
|
captureImageRefs,
|
|
14
14
|
GATEWAY_INTERNAL_PORT,
|
|
15
15
|
dockerResourceNames,
|
|
16
|
-
migrateCesSecurityFiles,
|
|
17
|
-
migrateGatewaySecurityFiles,
|
|
18
16
|
startContainers,
|
|
19
17
|
stopContainers,
|
|
20
18
|
} from "../lib/docker";
|
|
@@ -417,12 +415,6 @@ async function upgradeDocker(
|
|
|
417
415
|
}
|
|
418
416
|
}
|
|
419
417
|
|
|
420
|
-
console.log("🔄 Migrating security files to gateway volume...");
|
|
421
|
-
await migrateGatewaySecurityFiles(res, (msg) => console.log(msg));
|
|
422
|
-
|
|
423
|
-
console.log("🔄 Migrating credential files to CES security volume...");
|
|
424
|
-
await migrateCesSecurityFiles(res, (msg) => console.log(msg));
|
|
425
|
-
|
|
426
418
|
console.log("🚀 Starting upgraded containers...");
|
|
427
419
|
await startContainers(
|
|
428
420
|
{
|
|
@@ -522,9 +514,6 @@ async function upgradeDocker(
|
|
|
522
514
|
|
|
523
515
|
await stopContainers(res);
|
|
524
516
|
|
|
525
|
-
await migrateGatewaySecurityFiles(res, (msg) => console.log(msg));
|
|
526
|
-
await migrateCesSecurityFiles(res, (msg) => console.log(msg));
|
|
527
|
-
|
|
528
517
|
await startContainers(
|
|
529
518
|
{
|
|
530
519
|
signingKey,
|
package/src/commands/wake.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
resolveTargetAssistant,
|
|
6
|
+
saveAssistantEntry,
|
|
7
|
+
} from "../lib/assistant-config.js";
|
|
5
8
|
import { dockerResourceNames, wakeContainers } from "../lib/docker.js";
|
|
6
9
|
import { isProcessAlive, stopProcessByPidFile } from "../lib/process";
|
|
7
10
|
import {
|
|
11
|
+
generateLocalSigningKey,
|
|
8
12
|
isAssistantWatchModeAvailable,
|
|
9
13
|
isGatewayWatchModeAvailable,
|
|
10
14
|
startLocalDaemon,
|
|
@@ -106,8 +110,17 @@ export async function wake(): Promise<void> {
|
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
|
|
113
|
+
// Reuse the lockfile-persisted signing key so client actor tokens survive
|
|
114
|
+
// daemon/gateway restarts. Generate and persist a new one only on first wake.
|
|
115
|
+
let signingKey = resources.signingKey;
|
|
116
|
+
if (!signingKey) {
|
|
117
|
+
signingKey = generateLocalSigningKey();
|
|
118
|
+
entry.resources = { ...resources, signingKey };
|
|
119
|
+
saveAssistantEntry(entry);
|
|
120
|
+
}
|
|
121
|
+
|
|
109
122
|
if (!daemonRunning) {
|
|
110
|
-
await startLocalDaemon(watch, resources, { foreground });
|
|
123
|
+
await startLocalDaemon(watch, resources, { foreground, signingKey });
|
|
111
124
|
}
|
|
112
125
|
|
|
113
126
|
// Start gateway
|
|
@@ -127,13 +140,13 @@ export async function wake(): Promise<void> {
|
|
|
127
140
|
`Gateway running (pid ${pid}) — restarting in watch mode...`,
|
|
128
141
|
);
|
|
129
142
|
await stopProcessByPidFile(gatewayPidFile, "gateway");
|
|
130
|
-
await startGateway(watch, resources);
|
|
143
|
+
await startGateway(watch, resources, { signingKey });
|
|
131
144
|
}
|
|
132
145
|
} else {
|
|
133
146
|
console.log(`Gateway already running (pid ${pid}).`);
|
|
134
147
|
}
|
|
135
148
|
} else {
|
|
136
|
-
await startGateway(watch, resources);
|
|
149
|
+
await startGateway(watch, resources, { signingKey });
|
|
137
150
|
}
|
|
138
151
|
}
|
|
139
152
|
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { rollback } from "./commands/rollback";
|
|
|
15
15
|
import { setup } from "./commands/setup";
|
|
16
16
|
import { sleep } from "./commands/sleep";
|
|
17
17
|
import { ssh } from "./commands/ssh";
|
|
18
|
+
import { teleport } from "./commands/teleport";
|
|
18
19
|
import { tunnel } from "./commands/tunnel";
|
|
19
20
|
import { upgrade } from "./commands/upgrade";
|
|
20
21
|
import { use } from "./commands/use";
|
|
@@ -44,6 +45,7 @@ const commands = {
|
|
|
44
45
|
setup,
|
|
45
46
|
sleep,
|
|
46
47
|
ssh,
|
|
48
|
+
teleport,
|
|
47
49
|
tunnel,
|
|
48
50
|
upgrade,
|
|
49
51
|
use,
|
|
@@ -76,6 +78,7 @@ function printHelp(): void {
|
|
|
76
78
|
console.log(" setup Configure API keys interactively");
|
|
77
79
|
console.log(" sleep Stop the assistant process");
|
|
78
80
|
console.log(" ssh SSH into a remote assistant instance");
|
|
81
|
+
console.log(" teleport Transfer assistant data between environments");
|
|
79
82
|
console.log(" tunnel Create a tunnel for a locally hosted assistant");
|
|
80
83
|
console.log(" upgrade Upgrade an assistant to a newer version");
|
|
81
84
|
console.log(" use Set the active assistant for commands");
|
|
@@ -43,6 +43,9 @@ export interface LocalInstanceResources {
|
|
|
43
43
|
cesPort: number;
|
|
44
44
|
/** Absolute path to the daemon PID file */
|
|
45
45
|
pidFile: string;
|
|
46
|
+
/** Persisted HMAC signing key (hex). Survives daemon/gateway restarts so
|
|
47
|
+
* client actor tokens remain valid across `wake` cycles. */
|
|
48
|
+
signingKey?: string;
|
|
46
49
|
[key: string]: unknown;
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -77,8 +80,6 @@ export interface AssistantEntry {
|
|
|
77
80
|
sshUser?: string;
|
|
78
81
|
zone?: string;
|
|
79
82
|
hatchedAt?: string;
|
|
80
|
-
/** Name of the shared volume backing BASE_DATA_DIR for containerised instances. */
|
|
81
|
-
volume?: string;
|
|
82
83
|
/** Per-instance resource config. Present for local entries in multi-instance setups. */
|
|
83
84
|
resources?: LocalInstanceResources;
|
|
84
85
|
/** PID of the file watcher process for docker instances hatched with --watch. */
|
package/src/lib/docker.ts
CHANGED
|
@@ -306,8 +306,6 @@ export function dockerResourceNames(instanceName: string) {
|
|
|
306
306
|
assistantContainer: `${instanceName}-assistant`,
|
|
307
307
|
cesContainer: `${instanceName}-credential-executor`,
|
|
308
308
|
cesSecurityVolume: `${instanceName}-ces-sec`,
|
|
309
|
-
/** @deprecated Legacy — no longer created for new instances. Retained for migration of existing instances. */
|
|
310
|
-
dataVolume: `${instanceName}-data`,
|
|
311
309
|
gatewayContainer: `${instanceName}-gateway`,
|
|
312
310
|
gatewaySecurityVolume: `${instanceName}-gateway-sec`,
|
|
313
311
|
network: `${instanceName}-net`,
|
|
@@ -363,7 +361,6 @@ export async function retireDocker(name: string): Promise<void> {
|
|
|
363
361
|
// network may not exist
|
|
364
362
|
}
|
|
365
363
|
for (const vol of [
|
|
366
|
-
res.dataVolume,
|
|
367
364
|
res.socketVolume,
|
|
368
365
|
res.workspaceVolume,
|
|
369
366
|
res.cesSecurityVolume,
|
|
@@ -519,6 +516,8 @@ export function serviceDockerRunArgs(opts: {
|
|
|
519
516
|
"-v",
|
|
520
517
|
`${res.socketVolume}:/run/ces-bootstrap`,
|
|
521
518
|
"-e",
|
|
519
|
+
"IS_CONTAINERIZED=false",
|
|
520
|
+
"-e",
|
|
522
521
|
`VELLUM_ASSISTANT_NAME=${instanceName}`,
|
|
523
522
|
"-e",
|
|
524
523
|
"VELLUM_CLOUD=docker",
|
|
@@ -629,148 +628,6 @@ export function serviceDockerRunArgs(opts: {
|
|
|
629
628
|
};
|
|
630
629
|
}
|
|
631
630
|
|
|
632
|
-
/**
|
|
633
|
-
* Check whether a Docker volume exists.
|
|
634
|
-
* Returns true if the volume exists, false otherwise.
|
|
635
|
-
*/
|
|
636
|
-
async function dockerVolumeExists(volumeName: string): Promise<boolean> {
|
|
637
|
-
try {
|
|
638
|
-
await execOutput("docker", ["volume", "inspect", volumeName]);
|
|
639
|
-
return true;
|
|
640
|
-
} catch {
|
|
641
|
-
return false;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
/**
|
|
646
|
-
* Migrate trust.json and actor-token-signing-key from the data volume
|
|
647
|
-
* (old location: /data/.vellum/protected/) to the gateway security volume
|
|
648
|
-
* (new location: /gateway-security/).
|
|
649
|
-
*
|
|
650
|
-
* Uses a temporary busybox container that mounts both volumes. The migration
|
|
651
|
-
* is idempotent: it only copies a file when the source exists on the data
|
|
652
|
-
* volume and the destination does not yet exist on the gateway security volume.
|
|
653
|
-
*
|
|
654
|
-
* Skips migration entirely if the data volume does not exist (new instances
|
|
655
|
-
* no longer create one).
|
|
656
|
-
*/
|
|
657
|
-
export async function migrateGatewaySecurityFiles(
|
|
658
|
-
res: ReturnType<typeof dockerResourceNames>,
|
|
659
|
-
log: (msg: string) => void,
|
|
660
|
-
): Promise<void> {
|
|
661
|
-
// New instances don't have a data volume — nothing to migrate.
|
|
662
|
-
if (!(await dockerVolumeExists(res.dataVolume))) {
|
|
663
|
-
log(" No data volume found — skipping gateway security migration.");
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
const migrationContainer = `${res.gatewayContainer}-migration`;
|
|
668
|
-
const filesToMigrate = ["trust.json", "actor-token-signing-key"];
|
|
669
|
-
|
|
670
|
-
// Remove any leftover migration container from a previous interrupted run.
|
|
671
|
-
try {
|
|
672
|
-
await exec("docker", ["rm", "-f", migrationContainer]);
|
|
673
|
-
} catch {
|
|
674
|
-
// container may not exist
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
for (const fileName of filesToMigrate) {
|
|
678
|
-
const src = `/data/.vellum/protected/${fileName}`;
|
|
679
|
-
const dst = `/gateway-security/${fileName}`;
|
|
680
|
-
|
|
681
|
-
try {
|
|
682
|
-
// Run a busybox container that checks source exists and destination
|
|
683
|
-
// does not, then copies. The shell exits 0 whether or not a copy
|
|
684
|
-
// happens, so the migration is always safe to re-run.
|
|
685
|
-
await exec("docker", [
|
|
686
|
-
"run",
|
|
687
|
-
"--rm",
|
|
688
|
-
"--name",
|
|
689
|
-
migrationContainer,
|
|
690
|
-
"-v",
|
|
691
|
-
`${res.dataVolume}:/data:ro`,
|
|
692
|
-
"-v",
|
|
693
|
-
`${res.gatewaySecurityVolume}:/gateway-security`,
|
|
694
|
-
"busybox",
|
|
695
|
-
"sh",
|
|
696
|
-
"-c",
|
|
697
|
-
`if [ -f "${src}" ] && [ ! -f "${dst}" ]; then cp "${src}" "${dst}" && echo "migrated"; else echo "skipped"; fi`,
|
|
698
|
-
]);
|
|
699
|
-
log(` ${fileName}: checked`);
|
|
700
|
-
} catch (err) {
|
|
701
|
-
// Non-fatal — log and continue. The gateway will create fresh files
|
|
702
|
-
// if they don't exist.
|
|
703
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
704
|
-
log(` ${fileName}: migration failed (${message}), continuing...`);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
/**
|
|
710
|
-
* Migrate keys.enc and store.key from the data volume
|
|
711
|
-
* (old location: /data/.vellum/protected/) to the CES security volume
|
|
712
|
-
* (new location: /ces-security/).
|
|
713
|
-
*
|
|
714
|
-
* Uses a temporary busybox container that mounts both volumes. The migration
|
|
715
|
-
* is idempotent: it only copies a file when the source exists on the data
|
|
716
|
-
* volume and the destination does not yet exist on the CES security volume.
|
|
717
|
-
* Migrated files are chowned to 1001:1001 (the CES service user).
|
|
718
|
-
*
|
|
719
|
-
* Skips migration entirely if the data volume does not exist (new instances
|
|
720
|
-
* no longer create one).
|
|
721
|
-
*/
|
|
722
|
-
export async function migrateCesSecurityFiles(
|
|
723
|
-
res: ReturnType<typeof dockerResourceNames>,
|
|
724
|
-
log: (msg: string) => void,
|
|
725
|
-
): Promise<void> {
|
|
726
|
-
// New instances don't have a data volume — nothing to migrate.
|
|
727
|
-
if (!(await dockerVolumeExists(res.dataVolume))) {
|
|
728
|
-
log(" No data volume found — skipping CES security migration.");
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
const migrationContainer = `${res.cesContainer}-migration`;
|
|
733
|
-
const filesToMigrate = ["keys.enc", "store.key"];
|
|
734
|
-
|
|
735
|
-
// Remove any leftover migration container from a previous interrupted run.
|
|
736
|
-
try {
|
|
737
|
-
await exec("docker", ["rm", "-f", migrationContainer]);
|
|
738
|
-
} catch {
|
|
739
|
-
// container may not exist
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
for (const fileName of filesToMigrate) {
|
|
743
|
-
const src = `/data/.vellum/protected/${fileName}`;
|
|
744
|
-
const dst = `/ces-security/${fileName}`;
|
|
745
|
-
|
|
746
|
-
try {
|
|
747
|
-
// Run a busybox container that checks source exists and destination
|
|
748
|
-
// does not, then copies and sets ownership. The shell exits 0 whether
|
|
749
|
-
// or not a copy happens, so the migration is always safe to re-run.
|
|
750
|
-
await exec("docker", [
|
|
751
|
-
"run",
|
|
752
|
-
"--rm",
|
|
753
|
-
"--name",
|
|
754
|
-
migrationContainer,
|
|
755
|
-
"-v",
|
|
756
|
-
`${res.dataVolume}:/data:ro`,
|
|
757
|
-
"-v",
|
|
758
|
-
`${res.cesSecurityVolume}:/ces-security`,
|
|
759
|
-
"busybox",
|
|
760
|
-
"sh",
|
|
761
|
-
"-c",
|
|
762
|
-
`if [ -f "${src}" ] && [ ! -f "${dst}" ]; then cp "${src}" "${dst}" && chown 1001:1001 "${dst}" && echo "migrated"; else echo "skipped"; fi`,
|
|
763
|
-
]);
|
|
764
|
-
log(` ${fileName}: checked`);
|
|
765
|
-
} catch (err) {
|
|
766
|
-
// Non-fatal — log and continue. The CES will start without
|
|
767
|
-
// credentials if they don't exist.
|
|
768
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
769
|
-
log(` ${fileName}: migration failed (${message}), continuing...`);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
|
|
774
631
|
/** The order in which services must be started. */
|
|
775
632
|
export const SERVICE_START_ORDER: ServiceName[] = [
|
|
776
633
|
"assistant",
|
|
@@ -1202,7 +1059,6 @@ export async function hatchDocker(
|
|
|
1202
1059
|
cloud: "docker",
|
|
1203
1060
|
species,
|
|
1204
1061
|
hatchedAt: new Date().toISOString(),
|
|
1205
|
-
volume: res.dataVolume,
|
|
1206
1062
|
serviceGroupVersion: cliPkg.version ? `v${cliPkg.version}` : undefined,
|
|
1207
1063
|
containerInfo: {
|
|
1208
1064
|
assistantImage: imageTags.assistant,
|
package/src/lib/local.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFileSync, execSync, spawn } from "child_process";
|
|
2
|
+
import { randomBytes } from "crypto";
|
|
2
3
|
import {
|
|
3
4
|
existsSync,
|
|
4
5
|
mkdirSync,
|
|
@@ -192,9 +193,24 @@ function resolveDaemonMainPath(assistantIndex: string): string {
|
|
|
192
193
|
return join(dirname(assistantIndex), "daemon", "main.ts");
|
|
193
194
|
}
|
|
194
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Generate a fresh signing key for a local hatch session.
|
|
198
|
+
*
|
|
199
|
+
* Both the daemon and gateway must use the same HMAC signing key so JWT
|
|
200
|
+
* tokens minted by one can be verified by the other. The CLI generates
|
|
201
|
+
* an ephemeral key each time and passes it as `ACTOR_TOKEN_SIGNING_KEY`
|
|
202
|
+
* to both processes — the daemon and gateway each persist it on their
|
|
203
|
+
* own terms (the `.vellum/` directory layout is their concern, not the
|
|
204
|
+
* CLI's).
|
|
205
|
+
*/
|
|
206
|
+
export function generateLocalSigningKey(): string {
|
|
207
|
+
return randomBytes(32).toString("hex");
|
|
208
|
+
}
|
|
209
|
+
|
|
195
210
|
type DaemonStartOptions = {
|
|
196
211
|
foreground?: boolean;
|
|
197
212
|
defaultWorkspaceConfigPath?: string;
|
|
213
|
+
signingKey?: string;
|
|
198
214
|
};
|
|
199
215
|
|
|
200
216
|
async function startDaemonFromSource(
|
|
@@ -267,6 +283,9 @@ async function startDaemonFromSource(
|
|
|
267
283
|
RUNTIME_HTTP_PORT: process.env.RUNTIME_HTTP_PORT || "7821",
|
|
268
284
|
VELLUM_CLOUD: "local",
|
|
269
285
|
VELLUM_DEV: "1",
|
|
286
|
+
...(options?.signingKey
|
|
287
|
+
? { ACTOR_TOKEN_SIGNING_KEY: options.signingKey }
|
|
288
|
+
: {}),
|
|
270
289
|
};
|
|
271
290
|
if (resources) {
|
|
272
291
|
env.BASE_DATA_DIR = resources.instanceDir;
|
|
@@ -385,6 +404,9 @@ async function startDaemonWatchFromSource(
|
|
|
385
404
|
...process.env,
|
|
386
405
|
RUNTIME_HTTP_PORT: process.env.RUNTIME_HTTP_PORT || "7821",
|
|
387
406
|
VELLUM_DEV: "1",
|
|
407
|
+
...(options?.signingKey
|
|
408
|
+
? { ACTOR_TOKEN_SIGNING_KEY: options.signingKey }
|
|
409
|
+
: {}),
|
|
388
410
|
};
|
|
389
411
|
if (resources) {
|
|
390
412
|
env.BASE_DATA_DIR = resources.instanceDir;
|
|
@@ -970,6 +992,10 @@ export async function startLocalDaemon(
|
|
|
970
992
|
delete daemonEnv.QDRANT_URL;
|
|
971
993
|
}
|
|
972
994
|
|
|
995
|
+
if (options?.signingKey) {
|
|
996
|
+
daemonEnv.ACTOR_TOKEN_SIGNING_KEY = options.signingKey;
|
|
997
|
+
}
|
|
998
|
+
|
|
973
999
|
// Write a sentinel PID file before spawning so concurrent hatch() calls
|
|
974
1000
|
// see the file and fall through to the isDaemonResponsive() port check
|
|
975
1001
|
// instead of racing to spawn a duplicate daemon.
|
|
@@ -1081,6 +1107,7 @@ export async function startLocalDaemon(
|
|
|
1081
1107
|
export async function startGateway(
|
|
1082
1108
|
watch: boolean = false,
|
|
1083
1109
|
resources?: LocalInstanceResources,
|
|
1110
|
+
options?: { signingKey?: string },
|
|
1084
1111
|
): Promise<string> {
|
|
1085
1112
|
const effectiveGatewayPort = resources?.gatewayPort ?? GATEWAY_PORT;
|
|
1086
1113
|
|
|
@@ -1117,9 +1144,12 @@ export async function startGateway(
|
|
|
1117
1144
|
...(process.env as Record<string, string>),
|
|
1118
1145
|
RUNTIME_HTTP_PORT: String(effectiveDaemonPort),
|
|
1119
1146
|
GATEWAY_PORT: String(effectiveGatewayPort),
|
|
1147
|
+
...(options?.signingKey
|
|
1148
|
+
? { ACTOR_TOKEN_SIGNING_KEY: options.signingKey }
|
|
1149
|
+
: {}),
|
|
1120
1150
|
...(watch ? { VELLUM_DEV: "1" } : {}),
|
|
1121
|
-
// Set BASE_DATA_DIR so the gateway loads the correct
|
|
1122
|
-
//
|
|
1151
|
+
// Set BASE_DATA_DIR so the gateway loads the correct credentials and
|
|
1152
|
+
// workspace config for this instance (mirrors the daemon env setup).
|
|
1123
1153
|
...(resources ? { BASE_DATA_DIR: resources.instanceDir } : {}),
|
|
1124
1154
|
};
|
|
1125
1155
|
// The gateway reads the ingress URL from the workspace config file via
|
|
@@ -9,8 +9,6 @@ import {
|
|
|
9
9
|
DOCKER_READY_TIMEOUT_MS,
|
|
10
10
|
dockerResourceNames,
|
|
11
11
|
GATEWAY_INTERNAL_PORT,
|
|
12
|
-
migrateCesSecurityFiles,
|
|
13
|
-
migrateGatewaySecurityFiles,
|
|
14
12
|
startContainers,
|
|
15
13
|
stopContainers,
|
|
16
14
|
} from "./docker.js";
|
|
@@ -573,12 +571,6 @@ export async function performDockerRollback(
|
|
|
573
571
|
await stopContainers(res);
|
|
574
572
|
console.log("✅ Containers stopped\n");
|
|
575
573
|
|
|
576
|
-
console.log("🔄 Migrating security files to gateway volume...");
|
|
577
|
-
await migrateGatewaySecurityFiles(res, (msg) => console.log(msg));
|
|
578
|
-
|
|
579
|
-
console.log("🔄 Migrating credential files to CES security volume...");
|
|
580
|
-
await migrateCesSecurityFiles(res, (msg) => console.log(msg));
|
|
581
|
-
|
|
582
574
|
console.log("🚀 Starting containers with target version...");
|
|
583
575
|
await startContainers(
|
|
584
576
|
{
|
|
@@ -700,9 +692,6 @@ export async function performDockerRollback(
|
|
|
700
692
|
|
|
701
693
|
await stopContainers(res);
|
|
702
694
|
|
|
703
|
-
await migrateGatewaySecurityFiles(res, (msg) => console.log(msg));
|
|
704
|
-
await migrateCesSecurityFiles(res, (msg) => console.log(msg));
|
|
705
|
-
|
|
706
695
|
await startContainers(
|
|
707
696
|
{
|
|
708
697
|
signingKey,
|