Skip to content

Commit 679fd15

Browse files
committed
start implementing using commit, tags, and copy to local per-user oci registry
1 parent 1910527 commit 679fd15

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

src/packages/project-runner/run/podman.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Runner based on podman.
44

55
import getLogger from "@cocalc/backend/logger";
66
import { nodePath } from "./mounts";
7-
import { isValidUUID } from "@cocalc/util/misc";
7+
import { isValidUUID, replace_all } from "@cocalc/util/misc";
88
import { ensureConfFilesExists, setupDataPath, writeSecretToken } from "./util";
99
import { getEnvironment } from "./env";
1010
import { mkdir } from "fs/promises";
@@ -23,6 +23,8 @@ const children: { [project_id: string]: any } = {};
2323

2424
const GRACE_PERIOD = 2000;
2525

26+
const info: { [project_id: string]: { home: string } } = {};
27+
2628
export async function start({
2729
project_id,
2830
config,
@@ -39,7 +41,10 @@ export async function start({
3941
return;
4042
}
4143

44+
const image = await getImage({ project_id, config });
4245
const home = await mountHome(project_id);
46+
info[project_id] = { home };
47+
4348
await mkdir(home, { recursive: true });
4449
await ensureConfFilesExists(home);
4550
const env = getEnvironment({
@@ -76,7 +81,7 @@ export async function start({
7681
args.push("-e", `${name}=${env[name]}`);
7782
}
7883

79-
args.push(config?.image ?? DEFAULT_IMAGE);
84+
args.push(image);
8085
args.push(nodePath);
8186
args.push(script, "--init", "project_init.sh");
8287

@@ -148,6 +153,59 @@ export async function close() {
148153
await Promise.all(v);
149154
}
150155

156+
export async function getImage({ project_id, config }): Promise<string> {
157+
const { stdout } = await executeCode({
158+
err_on_exit: true,
159+
command: "podman",
160+
args: [
161+
"images",
162+
"--filter",
163+
`reference=localhost/project/${project_id}`,
164+
"--format=json",
165+
],
166+
});
167+
const v = JSON.parse(stdout);
168+
return v[0]?.Names?.[0] ?? config?.image ?? DEFAULT_IMAGE;
169+
}
170+
171+
function nowTag() {
172+
let s = new Date().toISOString();
173+
const i = s.lastIndexOf(":");
174+
s = s.slice(0, i);
175+
return replace_all(s, ":", "-");
176+
}
177+
178+
export async function save({
179+
project_id,
180+
tag,
181+
}: {
182+
project_id: string;
183+
tag?: string;
184+
}) {
185+
const home = info[project_id]?.home ?? (await mountHome(project_id));
186+
const oci = join(home, ".oci");
187+
await mkdir(oci, { recursive: true });
188+
tag ??= nowTag();
189+
const name = `localhost/project/${project_id}:${tag}`;
190+
await executeCode({
191+
err_on_exit: true,
192+
command: "podman",
193+
// in seconds; can be long if lots of files/data
194+
timeout: 60 * 10,
195+
args: ["commit", `project-${project_id}`, name],
196+
});
197+
await executeCode({
198+
err_on_exit: true,
199+
command: "skopeo",
200+
timeout: 60 * 10,
201+
args: [
202+
"copy",
203+
`containers-storage:${name}`,
204+
`oci:${oci}:project-${project_id}-${tag}`,
205+
],
206+
});
207+
}
208+
151209
// important because it kills all
152210
// the processes that were spawned
153211
process.once("exit", close);

0 commit comments

Comments
 (0)