@intentic/providers 1.18.0
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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +72 -0
- package/dist/app.js.map +1 -0
- package/dist/authentik-api.d.ts +23 -0
- package/dist/authentik-api.d.ts.map +1 -0
- package/dist/authentik-api.js +67 -0
- package/dist/authentik-api.js.map +1 -0
- package/dist/authentik-client.d.ts +4 -0
- package/dist/authentik-client.d.ts.map +1 -0
- package/dist/authentik-client.js +50 -0
- package/dist/authentik-client.js.map +1 -0
- package/dist/authentik.d.ts +4 -0
- package/dist/authentik.d.ts.map +1 -0
- package/dist/authentik.js +132 -0
- package/dist/authentik.js.map +1 -0
- package/dist/backing-ssh.d.ts +8 -0
- package/dist/backing-ssh.d.ts.map +1 -0
- package/dist/backing-ssh.js +44 -0
- package/dist/backing-ssh.js.map +1 -0
- package/dist/backup-restore.d.ts +15 -0
- package/dist/backup-restore.d.ts.map +1 -0
- package/dist/backup-restore.js +49 -0
- package/dist/backup-restore.js.map +1 -0
- package/dist/backup.d.ts +4 -0
- package/dist/backup.d.ts.map +1 -0
- package/dist/backup.js +150 -0
- package/dist/backup.js.map +1 -0
- package/dist/cf-route.d.ts +5 -0
- package/dist/cf-route.d.ts.map +1 -0
- package/dist/cf-route.js +74 -0
- package/dist/cf-route.js.map +1 -0
- package/dist/ci.d.ts +4 -0
- package/dist/ci.d.ts.map +1 -0
- package/dist/ci.js +151 -0
- package/dist/ci.js.map +1 -0
- package/dist/cloudflare-api.d.ts +85 -0
- package/dist/cloudflare-api.d.ts.map +1 -0
- package/dist/cloudflare-api.js +110 -0
- package/dist/cloudflare-api.js.map +1 -0
- package/dist/cloudflare.d.ts +4 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +29 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/deploy-hook.d.ts +4 -0
- package/dist/deploy-hook.d.ts.map +1 -0
- package/dist/deploy-hook.js +79 -0
- package/dist/deploy-hook.js.map +1 -0
- package/dist/deployment.d.ts +4 -0
- package/dist/deployment.d.ts.map +1 -0
- package/dist/deployment.js +103 -0
- package/dist/deployment.js.map +1 -0
- package/dist/discord-api.d.ts +31 -0
- package/dist/discord-api.d.ts.map +1 -0
- package/dist/discord-api.js +85 -0
- package/dist/discord-api.js.map +1 -0
- package/dist/discord.d.ts +4 -0
- package/dist/discord.d.ts.map +1 -0
- package/dist/discord.js +133 -0
- package/dist/discord.js.map +1 -0
- package/dist/forgejo-api.d.ts +209 -0
- package/dist/forgejo-api.d.ts.map +1 -0
- package/dist/forgejo-api.fake.d.ts +3 -0
- package/dist/forgejo-api.fake.d.ts.map +1 -0
- package/dist/forgejo-api.fake.js +31 -0
- package/dist/forgejo-api.fake.js.map +1 -0
- package/dist/forgejo-api.js +181 -0
- package/dist/forgejo-api.js.map +1 -0
- package/dist/forgejo-notify.d.ts +4 -0
- package/dist/forgejo-notify.d.ts.map +1 -0
- package/dist/forgejo-notify.js +103 -0
- package/dist/forgejo-notify.js.map +1 -0
- package/dist/forgejo-org.d.ts +4 -0
- package/dist/forgejo-org.d.ts.map +1 -0
- package/dist/forgejo-org.js +43 -0
- package/dist/forgejo-org.js.map +1 -0
- package/dist/forgejo-runner.d.ts +4 -0
- package/dist/forgejo-runner.d.ts.map +1 -0
- package/dist/forgejo-runner.js +111 -0
- package/dist/forgejo-runner.js.map +1 -0
- package/dist/forgejo-team.d.ts +4 -0
- package/dist/forgejo-team.d.ts.map +1 -0
- package/dist/forgejo-team.js +68 -0
- package/dist/forgejo-team.js.map +1 -0
- package/dist/forgejo-user.d.ts +4 -0
- package/dist/forgejo-user.d.ts.map +1 -0
- package/dist/forgejo-user.js +50 -0
- package/dist/forgejo-user.js.map +1 -0
- package/dist/forgejo.d.ts +4 -0
- package/dist/forgejo.d.ts.map +1 -0
- package/dist/forgejo.js +169 -0
- package/dist/forgejo.js.map +1 -0
- package/dist/garage-bucket.d.ts +4 -0
- package/dist/garage-bucket.d.ts.map +1 -0
- package/dist/garage-bucket.js +92 -0
- package/dist/garage-bucket.js.map +1 -0
- package/dist/garage.d.ts +4 -0
- package/dist/garage.d.ts.map +1 -0
- package/dist/garage.js +124 -0
- package/dist/garage.js.map +1 -0
- package/dist/gh-ci.d.ts +4 -0
- package/dist/gh-ci.d.ts.map +1 -0
- package/dist/gh-ci.js +153 -0
- package/dist/gh-ci.js.map +1 -0
- package/dist/gh-deployment.d.ts +4 -0
- package/dist/gh-deployment.d.ts.map +1 -0
- package/dist/gh-deployment.js +92 -0
- package/dist/gh-deployment.js.map +1 -0
- package/dist/gh-repo.d.ts +4 -0
- package/dist/gh-repo.d.ts.map +1 -0
- package/dist/gh-repo.js +52 -0
- package/dist/gh-repo.js.map +1 -0
- package/dist/github-api.d.ts +70 -0
- package/dist/github-api.d.ts.map +1 -0
- package/dist/github-api.js +120 -0
- package/dist/github-api.js.map +1 -0
- package/dist/github.d.ts +4 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +34 -0
- package/dist/github.js.map +1 -0
- package/dist/guarded-update.d.ts +14 -0
- package/dist/guarded-update.d.ts.map +1 -0
- package/dist/guarded-update.js +25 -0
- package/dist/guarded-update.js.map +1 -0
- package/dist/host.d.ts +4 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +48 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs.d.ts +23 -0
- package/dist/inputs.d.ts.map +1 -0
- package/dist/inputs.js +34 -0
- package/dist/inputs.js.map +1 -0
- package/dist/komodo-api.d.ts +150 -0
- package/dist/komodo-api.d.ts.map +1 -0
- package/dist/komodo-api.js +104 -0
- package/dist/komodo-api.js.map +1 -0
- package/dist/komodo-notify.d.ts +4 -0
- package/dist/komodo-notify.d.ts.map +1 -0
- package/dist/komodo-notify.js +88 -0
- package/dist/komodo-notify.js.map +1 -0
- package/dist/komodo-periphery.d.ts +4 -0
- package/dist/komodo-periphery.d.ts.map +1 -0
- package/dist/komodo-periphery.js +92 -0
- package/dist/komodo-periphery.js.map +1 -0
- package/dist/komodo-server.d.ts +4 -0
- package/dist/komodo-server.d.ts.map +1 -0
- package/dist/komodo-server.js +54 -0
- package/dist/komodo-server.js.map +1 -0
- package/dist/komodo-user.d.ts +4 -0
- package/dist/komodo-user.d.ts.map +1 -0
- package/dist/komodo-user.js +66 -0
- package/dist/komodo-user.js.map +1 -0
- package/dist/komodo.d.ts +4 -0
- package/dist/komodo.d.ts.map +1 -0
- package/dist/komodo.js +222 -0
- package/dist/komodo.js.map +1 -0
- package/dist/postgres-database.d.ts +4 -0
- package/dist/postgres-database.d.ts.map +1 -0
- package/dist/postgres-database.js +88 -0
- package/dist/postgres-database.js.map +1 -0
- package/dist/postgres.d.ts +4 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/postgres.js +95 -0
- package/dist/postgres.js.map +1 -0
- package/dist/providers.d.ts +21 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +86 -0
- package/dist/providers.js.map +1 -0
- package/dist/repo.d.ts +4 -0
- package/dist/repo.d.ts.map +1 -0
- package/dist/repo.js +80 -0
- package/dist/repo.js.map +1 -0
- package/dist/signoz.d.ts +4 -0
- package/dist/signoz.d.ts.map +1 -0
- package/dist/signoz.js +386 -0
- package/dist/signoz.js.map +1 -0
- package/dist/ssh-probe.d.ts +5 -0
- package/dist/ssh-probe.d.ts.map +1 -0
- package/dist/ssh-probe.js +22 -0
- package/dist/ssh-probe.js.map +1 -0
- package/dist/ssh.d.ts +27 -0
- package/dist/ssh.d.ts.map +1 -0
- package/dist/ssh.js +79 -0
- package/dist/ssh.js.map +1 -0
- package/dist/tunnel.d.ts +5 -0
- package/dist/tunnel.d.ts.map +1 -0
- package/dist/tunnel.js +126 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/valkey-namespace.d.ts +4 -0
- package/dist/valkey-namespace.d.ts.map +1 -0
- package/dist/valkey-namespace.js +78 -0
- package/dist/valkey-namespace.js.map +1 -0
- package/dist/valkey.d.ts +4 -0
- package/dist/valkey.d.ts.map +1 -0
- package/dist/valkey.js +94 -0
- package/dist/valkey.js.map +1 -0
- package/dist/workspace.d.ts +4 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +97 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { forgejoApi } from "./forgejo-api.js";
|
|
3
|
+
import { parseInputs } from "./inputs.js";
|
|
4
|
+
const forgejoOrgSchema = z.object({
|
|
5
|
+
forgejoUrl: z.string(),
|
|
6
|
+
adminUser: z.string(),
|
|
7
|
+
adminPassword: z.string(),
|
|
8
|
+
org: z.string(),
|
|
9
|
+
});
|
|
10
|
+
const parse = (inputs) => parseInputs(forgejoOrgSchema, inputs, "forgejo-org");
|
|
11
|
+
export const createForgejoOrgProvider = (api = forgejoApi) => ({
|
|
12
|
+
read: async (inputs, ctx) => {
|
|
13
|
+
if (typeof inputs["forgejoUrl"] !== "string") {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const parsed = parse(inputs);
|
|
17
|
+
try {
|
|
18
|
+
const exists = await api.findOrg({ baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword, org: parsed.org });
|
|
19
|
+
return exists ? { outputs: {} } : undefined;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
ctx.log(`forgejo-org "${ctx.id}": forgejo not reachable yet, treating as not-yet-created: ${String(error)}`);
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
diff: () => ({ action: "noop" }),
|
|
27
|
+
apply: async (inputs) => {
|
|
28
|
+
const parsed = parse(inputs);
|
|
29
|
+
const auth = { baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword };
|
|
30
|
+
if (!(await api.findOrg({ ...auth, org: parsed.org }))) {
|
|
31
|
+
await api.createOrg({ ...auth, org: parsed.org });
|
|
32
|
+
}
|
|
33
|
+
return {};
|
|
34
|
+
},
|
|
35
|
+
delete: async (inputs) => {
|
|
36
|
+
if (typeof inputs["forgejoUrl"] !== "string") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const parsed = parse(inputs);
|
|
40
|
+
await api.deleteOrg({ baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword, org: parsed.org });
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=forgejo-org.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-org.js","sourceRoot":"","sources":["../src/forgejo-org.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;CAClB,CAAC,CAAC;AAEH,MAAM,KAAK,GAAG,CAAC,MAAsB,EAAoB,EAAE,CAAC,WAAW,CAAC,gBAAgB,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAKjH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,MAAkB,UAAU,EAAY,EAAE,CAAC,CAAC;IACjF,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QACxB,IAAI,OAAO,MAAM,CAAC,YAAY,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC3C,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1I,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,GAAG,CAAC,GAAG,CAAC,gBAAgB,GAAG,CAAC,EAAE,8DAA8D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC7G,OAAO,SAAS,CAAC;QACrB,CAAC;IACL,CAAC;IACD,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAChC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC;QACpG,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;YACrD,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACrB,IAAI,OAAO,MAAM,CAAC,YAAY,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC3C,OAAO;QACX,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IACjI,CAAC;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-runner.d.ts","sourceRoot":"","sources":["../src/forgejo-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,kBAAkB,CAAC;AAGjE,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,UAAU,CAAC;AA8DxD,eAAO,MAAM,2BAA2B,GAAI,WAAU,WAAyB,KAAG,QAmFhF,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { parseInputs, sshSchema, sshTarget } from "./inputs.js";
|
|
3
|
+
import { sshExecutor } from "./ssh.js";
|
|
4
|
+
const runnerSchema = sshSchema.extend({ instanceUrl: z.string(), token: z.string(), image: z.string(), jobImage: z.string() });
|
|
5
|
+
const parse = (inputs) => parseInputs(runnerSchema, inputs, "forgejo-runner");
|
|
6
|
+
const CONTAINER = "intentic-forgejo-runner";
|
|
7
|
+
const CONFIG_DIR = "/opt/intentic/runner";
|
|
8
|
+
const runnerConfig = (dockerBin, buildxPlugin, jobImage) => [
|
|
9
|
+
"runner:",
|
|
10
|
+
` labels: [ "docker:docker://${jobImage}" ]`,
|
|
11
|
+
"container:",
|
|
12
|
+
" network: host",
|
|
13
|
+
" docker_host: automount",
|
|
14
|
+
` options: -v ${dockerBin}:/usr/local/bin/docker:ro -v ${buildxPlugin}:/usr/local/lib/docker/cli-plugins/docker-buildx:ro`,
|
|
15
|
+
" valid_volumes:",
|
|
16
|
+
` - ${dockerBin}`,
|
|
17
|
+
` - ${buildxPlugin}`,
|
|
18
|
+
"",
|
|
19
|
+
].join("\n");
|
|
20
|
+
const running = async (session) => {
|
|
21
|
+
const result = await session.exec(`docker ps --filter "name=^${CONTAINER}$" --format '{{.Names}}'`);
|
|
22
|
+
return result.stdout.trim() === CONTAINER;
|
|
23
|
+
};
|
|
24
|
+
const registeredTo = async (session, instanceUrl) => {
|
|
25
|
+
const result = await session.exec(`docker exec ${CONTAINER} cat /data/.runner 2>/dev/null || true`);
|
|
26
|
+
return result.stdout.includes(instanceUrl);
|
|
27
|
+
};
|
|
28
|
+
const runningImage = async (session) => {
|
|
29
|
+
const result = await session.exec(`docker inspect --format '{{.Config.Image}}' ${CONTAINER} 2>/dev/null || true`);
|
|
30
|
+
return result.stdout.trim();
|
|
31
|
+
};
|
|
32
|
+
const configuredJobImage = async (session) => {
|
|
33
|
+
const result = await session.exec(`cat ${CONFIG_DIR}/config.yaml 2>/dev/null || true`);
|
|
34
|
+
const match = result.stdout.match(/docker:\/\/(\S+?)"/);
|
|
35
|
+
return match?.[1] ?? "";
|
|
36
|
+
};
|
|
37
|
+
export const createForgejoRunnerProvider = (executor = sshExecutor) => ({
|
|
38
|
+
read: async (inputs, ctx) => {
|
|
39
|
+
const parsed = parse(inputs);
|
|
40
|
+
let session;
|
|
41
|
+
try {
|
|
42
|
+
session = await executor.connect(sshTarget(parsed));
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
ctx.log(`forgejo-runner "${ctx.id}": host not reachable over SSH, treating as not-yet-created: ${String(error)}`);
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
if (!(await running(session)) || !(await registeredTo(session, parsed.instanceUrl))) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
return { outputs: {}, detail: { image: await runningImage(session), jobImage: await configuredJobImage(session) } };
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await session.dispose();
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
diff: (inputs, observed) => {
|
|
59
|
+
const parsed = parse(inputs);
|
|
60
|
+
if (observed.detail?.["image"] !== parsed.image) {
|
|
61
|
+
return { action: "update", reason: `forgejo-runner image differs (running ${String(observed.detail?.["image"])}, want ${parsed.image})` };
|
|
62
|
+
}
|
|
63
|
+
if (observed.detail?.["jobImage"] !== parsed.jobImage) {
|
|
64
|
+
return {
|
|
65
|
+
action: "update",
|
|
66
|
+
reason: `forgejo-runner job image differs (config ${String(observed.detail?.["jobImage"])}, want ${parsed.jobImage})`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return { action: "noop" };
|
|
70
|
+
},
|
|
71
|
+
apply: async (inputs, _observed, ctx) => {
|
|
72
|
+
const parsed = parse(inputs);
|
|
73
|
+
const session = await executor.connect(sshTarget(parsed));
|
|
74
|
+
try {
|
|
75
|
+
const dockerBin = (await session.exec("command -v docker")).stdout.trim();
|
|
76
|
+
if (dockerBin === "") {
|
|
77
|
+
throw new Error("forgejo-runner: no docker CLI found on the host (CI builds the app image with the host daemon)");
|
|
78
|
+
}
|
|
79
|
+
const buildxPlugin = (await session.exec("find /usr/local/libexec/docker/cli-plugins /usr/libexec/docker/cli-plugins /usr/lib/docker/cli-plugins /usr/local/lib/docker/cli-plugins -name docker-buildx 2>/dev/null | head -1")).stdout.trim();
|
|
80
|
+
if (buildxPlugin === "") {
|
|
81
|
+
throw new Error("forgejo-runner: no docker buildx plugin found on the host (the CI build-push step needs it)");
|
|
82
|
+
}
|
|
83
|
+
await session.exec(`mkdir -p ${CONFIG_DIR}`);
|
|
84
|
+
await session.exec(`cat > ${CONFIG_DIR}/config.yaml <<'CFG'\n${runnerConfig(dockerBin, buildxPlugin, parsed.jobImage)}CFG`);
|
|
85
|
+
await session.exec(`docker rm -f ${CONTAINER} 2>/dev/null || true`);
|
|
86
|
+
const run = await session.exec(`docker run -d --restart unless-stopped --network host --user root --name ${CONTAINER} --label intentic.id=${ctx.id} ` +
|
|
87
|
+
`-v ${CONTAINER}-data:/data -v /var/run/docker.sock:/var/run/docker.sock -v ${CONFIG_DIR}/config.yaml:/config.yaml:ro ${parsed.image} ` +
|
|
88
|
+
`sh -c "forgejo-runner register --no-interactive --config /config.yaml --instance ${parsed.instanceUrl} --token ${parsed.token} && forgejo-runner daemon --config /config.yaml"`);
|
|
89
|
+
if (run.code !== 0) {
|
|
90
|
+
throw new Error(`failed to start forgejo-runner on host: exited ${run.code}: ${run.stderr.trim()}`);
|
|
91
|
+
}
|
|
92
|
+
return {};
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await session.dispose();
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
delete: async (inputs) => {
|
|
99
|
+
const parsed = parse(inputs);
|
|
100
|
+
const session = await executor.connect(sshTarget(parsed));
|
|
101
|
+
try {
|
|
102
|
+
await session.exec(`docker rm -f ${CONTAINER} 2>/dev/null || true`);
|
|
103
|
+
await session.exec(`docker volume rm ${CONTAINER}-data 2>/dev/null || true`);
|
|
104
|
+
await session.exec(`rm -rf ${CONFIG_DIR}`);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
await session.dispose();
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=forgejo-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-runner.js","sourceRoot":"","sources":["../src/forgejo-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-team.d.ts","sourceRoot":"","sources":["../src/forgejo-team.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,kBAAkB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAwBnD,eAAO,MAAM,yBAAyB,GAAI,MAAK,UAAuB,KAAG,QAmDvE,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { forgejoApi } from "./forgejo-api.js";
|
|
3
|
+
import { parseInputs } from "./inputs.js";
|
|
4
|
+
const forgejoTeamSchema = z.object({
|
|
5
|
+
forgejoUrl: z.string(),
|
|
6
|
+
adminUser: z.string(),
|
|
7
|
+
adminPassword: z.string(),
|
|
8
|
+
org: z.string(),
|
|
9
|
+
name: z.string(),
|
|
10
|
+
permission: z.string(),
|
|
11
|
+
members: z.array(z.string()),
|
|
12
|
+
repos: z.array(z.object({ owner: z.string(), name: z.string() })),
|
|
13
|
+
});
|
|
14
|
+
const parse = (inputs) => parseInputs(forgejoTeamSchema, inputs, "forgejo-team");
|
|
15
|
+
export const createForgejoTeamProvider = (api = forgejoApi) => ({
|
|
16
|
+
read: async (inputs, ctx) => {
|
|
17
|
+
if (typeof inputs["forgejoUrl"] !== "string") {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const parsed = parse(inputs);
|
|
21
|
+
try {
|
|
22
|
+
const team = await api.findTeam({
|
|
23
|
+
baseUrl: parsed.forgejoUrl,
|
|
24
|
+
user: parsed.adminUser,
|
|
25
|
+
password: parsed.adminPassword,
|
|
26
|
+
org: parsed.org,
|
|
27
|
+
name: parsed.name,
|
|
28
|
+
});
|
|
29
|
+
return team === undefined ? undefined : { outputs: {}, detail: { permission: team.permission } };
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
ctx.log(`forgejo-team "${ctx.id}": forgejo not reachable yet, treating as not-yet-created: ${String(error)}`);
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
diff: (inputs, observed) => {
|
|
37
|
+
if (observed.detail?.["permission"] !== parse(inputs).permission) {
|
|
38
|
+
return { action: "update", reason: "team permission differs from desired" };
|
|
39
|
+
}
|
|
40
|
+
return { action: "noop" };
|
|
41
|
+
},
|
|
42
|
+
apply: async (inputs) => {
|
|
43
|
+
const parsed = parse(inputs);
|
|
44
|
+
const auth = { baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword };
|
|
45
|
+
const existing = await api.findTeam({ ...auth, org: parsed.org, name: parsed.name });
|
|
46
|
+
const teamId = existing?.id ?? (await api.createTeam({ ...auth, org: parsed.org, name: parsed.name, permission: parsed.permission })).id;
|
|
47
|
+
for (const username of parsed.members) {
|
|
48
|
+
await api.addTeamMember({ ...auth, teamId, username });
|
|
49
|
+
}
|
|
50
|
+
for (const repo of parsed.repos) {
|
|
51
|
+
await api.addTeamRepo({ ...auth, teamId, org: repo.owner, name: repo.name });
|
|
52
|
+
}
|
|
53
|
+
return {};
|
|
54
|
+
},
|
|
55
|
+
delete: async (inputs) => {
|
|
56
|
+
if (typeof inputs["forgejoUrl"] !== "string") {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const parsed = parse(inputs);
|
|
60
|
+
const auth = { baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword };
|
|
61
|
+
const existing = await api.findTeam({ ...auth, org: parsed.org, name: parsed.name });
|
|
62
|
+
if (existing === undefined) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await api.deleteTeam({ ...auth, teamId: existing.id });
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=forgejo-team.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-team.js","sourceRoot":"","sources":["../src/forgejo-team.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-user.d.ts","sourceRoot":"","sources":["../src/forgejo-user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,kBAAkB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAoBnD,eAAO,MAAM,yBAAyB,GAAI,MAAK,UAAuB,KAAG,QAmCvE,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { forgejoApi } from "./forgejo-api.js";
|
|
3
|
+
import { parseInputs } from "./inputs.js";
|
|
4
|
+
const forgejoUserSchema = z.object({
|
|
5
|
+
forgejoUrl: z.string(),
|
|
6
|
+
adminUser: z.string(),
|
|
7
|
+
adminPassword: z.string(),
|
|
8
|
+
username: z.string(),
|
|
9
|
+
email: z.string(),
|
|
10
|
+
accountPassword: z.string(),
|
|
11
|
+
});
|
|
12
|
+
const parse = (inputs) => parseInputs(forgejoUserSchema, inputs, "forgejo-user");
|
|
13
|
+
export const createForgejoUserProvider = (api = forgejoApi) => ({
|
|
14
|
+
read: async (inputs, ctx) => {
|
|
15
|
+
if (typeof inputs["forgejoUrl"] !== "string") {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const parsed = parse(inputs);
|
|
19
|
+
try {
|
|
20
|
+
const exists = await api.findUser({
|
|
21
|
+
baseUrl: parsed.forgejoUrl,
|
|
22
|
+
user: parsed.adminUser,
|
|
23
|
+
password: parsed.adminPassword,
|
|
24
|
+
username: parsed.username,
|
|
25
|
+
});
|
|
26
|
+
return exists ? { outputs: {} } : undefined;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
ctx.log(`forgejo-user "${ctx.id}": forgejo not reachable yet, treating as not-yet-created: ${String(error)}`);
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
diff: () => ({ action: "noop" }),
|
|
34
|
+
apply: async (inputs) => {
|
|
35
|
+
const parsed = parse(inputs);
|
|
36
|
+
const auth = { baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword };
|
|
37
|
+
if (!(await api.findUser({ ...auth, username: parsed.username }))) {
|
|
38
|
+
await api.createUser({ ...auth, username: parsed.username, email: parsed.email, accountPassword: parsed.accountPassword });
|
|
39
|
+
}
|
|
40
|
+
return {};
|
|
41
|
+
},
|
|
42
|
+
delete: async (inputs) => {
|
|
43
|
+
if (typeof inputs["forgejoUrl"] !== "string") {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const parsed = parse(inputs);
|
|
47
|
+
await api.deleteUser({ baseUrl: parsed.forgejoUrl, user: parsed.adminUser, password: parsed.adminPassword, username: parsed.username });
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=forgejo-user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo-user.js","sourceRoot":"","sources":["../src/forgejo-user.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo.d.ts","sourceRoot":"","sources":["../src/forgejo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,kBAAkB,CAAC;AAIjE,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,UAAU,CAAC;AAkFxD,eAAO,MAAM,qBAAqB,GAAI,WAAU,WAAyB,KAAG,QAyH1E,CAAC"}
|
package/dist/forgejo.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { guardedUpdate } from "./guarded-update.js";
|
|
3
|
+
import { parseInputs, sshSchema, sshTarget } from "./inputs.js";
|
|
4
|
+
import { sshExecutor } from "./ssh.js";
|
|
5
|
+
const forgejoSchema = sshSchema.extend({
|
|
6
|
+
internalIp: z.string(),
|
|
7
|
+
domain: z.string(),
|
|
8
|
+
adminUser: z.string(),
|
|
9
|
+
adminPassword: z.string(),
|
|
10
|
+
image: z.string(),
|
|
11
|
+
guardRepo: z.string().optional(),
|
|
12
|
+
resticImage: z.string().optional(),
|
|
13
|
+
});
|
|
14
|
+
const parse = (inputs) => parseInputs(forgejoSchema, inputs, "forgejo");
|
|
15
|
+
const CONTAINER = "intentic-forgejo";
|
|
16
|
+
const HTTP_PORT = 3000;
|
|
17
|
+
const STATE_DIR = "/opt/intentic/forgejo";
|
|
18
|
+
const TOKEN_FILE = `${STATE_DIR}/runner-token`;
|
|
19
|
+
const GIT_TOKEN_FILE = `${STATE_DIR}/git-token`;
|
|
20
|
+
const PKG_TOKEN_FILE = `${STATE_DIR}/packages-token`;
|
|
21
|
+
const READY_TIMEOUT_MS = 120_000;
|
|
22
|
+
const READY_INTERVAL_MS = 3_000;
|
|
23
|
+
const internalUrl = (parsed) => `http://${parsed.internalIp}:${HTTP_PORT}`;
|
|
24
|
+
const outputsFor = (parsed, runnerToken, gitToken, packagesToken) => ({
|
|
25
|
+
url: `https://${parsed.domain}`,
|
|
26
|
+
internalUrl: internalUrl(parsed),
|
|
27
|
+
runnerToken,
|
|
28
|
+
gitToken,
|
|
29
|
+
packagesToken,
|
|
30
|
+
});
|
|
31
|
+
const running = async (session) => {
|
|
32
|
+
const result = await session.exec(`docker ps --filter "name=^${CONTAINER}$" --format '{{.Names}}'`);
|
|
33
|
+
return result.stdout.trim() === CONTAINER;
|
|
34
|
+
};
|
|
35
|
+
const runningImage = async (session) => {
|
|
36
|
+
const result = await session.exec(`docker inspect --format '{{.Config.Image}}' ${CONTAINER} 2>/dev/null || true`);
|
|
37
|
+
return result.stdout.trim();
|
|
38
|
+
};
|
|
39
|
+
const healthy = async (session) => {
|
|
40
|
+
const result = await session.exec(`docker exec ${CONTAINER} wget -q --spider http://localhost:${HTTP_PORT}/api/healthz`);
|
|
41
|
+
return result.code === 0;
|
|
42
|
+
};
|
|
43
|
+
const persisted = async (session, file) => {
|
|
44
|
+
const result = await session.exec(`cat ${file} 2>/dev/null || true`);
|
|
45
|
+
return result.stdout.trim();
|
|
46
|
+
};
|
|
47
|
+
const waitHealthy = async (session) => {
|
|
48
|
+
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
49
|
+
for (;;) {
|
|
50
|
+
if (await healthy(session)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (Date.now() >= deadline) {
|
|
54
|
+
throw new Error(`forgejo did not become healthy within ${READY_TIMEOUT_MS}ms`);
|
|
55
|
+
}
|
|
56
|
+
await new Promise((resolve) => setTimeout(resolve, READY_INTERVAL_MS));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
export const createForgejoProvider = (executor = sshExecutor) => ({
|
|
60
|
+
read: async (inputs, ctx) => {
|
|
61
|
+
const parsed = parse(inputs);
|
|
62
|
+
let session;
|
|
63
|
+
try {
|
|
64
|
+
session = await executor.connect(sshTarget(parsed));
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
ctx.log(`forgejo "${ctx.id}": host not reachable over SSH, treating as not-yet-created: ${String(error)}`);
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
if (!(await running(session)) || !(await healthy(session))) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const runnerToken = await persisted(session, TOKEN_FILE);
|
|
75
|
+
const gitToken = await persisted(session, GIT_TOKEN_FILE);
|
|
76
|
+
const packagesToken = await persisted(session, PKG_TOKEN_FILE);
|
|
77
|
+
if (runnerToken === "" || gitToken === "" || packagesToken === "") {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return { outputs: outputsFor(parsed, runnerToken, gitToken, packagesToken), detail: { image: await runningImage(session) } };
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
await session.dispose();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
diff: (inputs, observed) => {
|
|
87
|
+
const desired = parse(inputs).image;
|
|
88
|
+
if (observed.detail?.["image"] !== desired) {
|
|
89
|
+
return { action: "update", reason: `forgejo image differs (running ${String(observed.detail?.["image"])}, want ${desired})` };
|
|
90
|
+
}
|
|
91
|
+
return { action: "noop" };
|
|
92
|
+
},
|
|
93
|
+
apply: async (inputs, observed, ctx) => {
|
|
94
|
+
const parsed = parse(inputs);
|
|
95
|
+
const session = await executor.connect(sshTarget(parsed));
|
|
96
|
+
try {
|
|
97
|
+
await session.exec(`mkdir -p ${STATE_DIR}`);
|
|
98
|
+
const bringUp = async (image) => {
|
|
99
|
+
await session.exec(`docker rm -f ${CONTAINER} 2>/dev/null || true`);
|
|
100
|
+
const run = await session.exec(`docker run -d --restart unless-stopped --network host --name ${CONTAINER} --label intentic.id=${ctx.id} ` +
|
|
101
|
+
`-v ${CONTAINER}-data:/data ` +
|
|
102
|
+
`-e FORGEJO__security__INSTALL_LOCK=true -e FORGEJO__database__DB_TYPE=sqlite3 ` +
|
|
103
|
+
`-e FORGEJO__server__ROOT_URL=https://${parsed.domain} -e FORGEJO__server__DOMAIN=${parsed.domain} ${image}`);
|
|
104
|
+
if (run.code !== 0) {
|
|
105
|
+
throw new Error(`failed to start forgejo on host: exited ${run.code}: ${run.stderr.trim()}`);
|
|
106
|
+
}
|
|
107
|
+
await waitHealthy(session);
|
|
108
|
+
};
|
|
109
|
+
const oldImage = observed?.detail?.["image"];
|
|
110
|
+
if (observed !== undefined && parsed.guardRepo !== undefined && parsed.resticImage !== undefined && typeof oldImage === "string") {
|
|
111
|
+
await guardedUpdate({
|
|
112
|
+
session,
|
|
113
|
+
repo: parsed.guardRepo,
|
|
114
|
+
resticImage: parsed.resticImage,
|
|
115
|
+
volumes: [`${CONTAINER}-data`],
|
|
116
|
+
tag: `intentic-preupdate-${ctx.id}`,
|
|
117
|
+
recreate: () => bringUp(parsed.image),
|
|
118
|
+
stop: async () => {
|
|
119
|
+
await session.exec(`docker rm -f ${CONTAINER} 2>/dev/null || true`);
|
|
120
|
+
},
|
|
121
|
+
rollback: () => bringUp(oldImage),
|
|
122
|
+
log: ctx.log,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
await bringUp(parsed.image);
|
|
127
|
+
}
|
|
128
|
+
const admin = await session.exec(`docker exec -u git ${CONTAINER} forgejo admin user create --admin --username ${parsed.adminUser} ` +
|
|
129
|
+
`--password ${parsed.adminPassword} --email ${parsed.adminUser}@${parsed.domain}`);
|
|
130
|
+
if (admin.code !== 0 && !admin.stderr.includes("already exists")) {
|
|
131
|
+
throw new Error(`failed to create forgejo admin: exited ${admin.code}: ${admin.stderr.trim()}`);
|
|
132
|
+
}
|
|
133
|
+
await session.exec(`test -f ${TOKEN_FILE} || docker exec -u git ${CONTAINER} forgejo actions generate-runner-token > ${TOKEN_FILE}`);
|
|
134
|
+
await session.exec(`test -f ${GIT_TOKEN_FILE} || docker exec -u git ${CONTAINER} forgejo admin user generate-access-token ` +
|
|
135
|
+
`--username ${parsed.adminUser} --token-name intentic-komodo --scopes read:repository --raw > ${GIT_TOKEN_FILE}`);
|
|
136
|
+
await session.exec(`test -f ${PKG_TOKEN_FILE} || docker exec -u git ${CONTAINER} forgejo admin user generate-access-token ` +
|
|
137
|
+
`--username ${parsed.adminUser} --token-name intentic-packages --scopes write:package,read:package --raw > ${PKG_TOKEN_FILE}`);
|
|
138
|
+
const runnerToken = await persisted(session, TOKEN_FILE);
|
|
139
|
+
const gitToken = await persisted(session, GIT_TOKEN_FILE);
|
|
140
|
+
const packagesToken = await persisted(session, PKG_TOKEN_FILE);
|
|
141
|
+
if (runnerToken === "") {
|
|
142
|
+
throw new Error("forgejo runner token was not persisted");
|
|
143
|
+
}
|
|
144
|
+
if (gitToken === "") {
|
|
145
|
+
throw new Error("forgejo git access token was not persisted");
|
|
146
|
+
}
|
|
147
|
+
if (packagesToken === "") {
|
|
148
|
+
throw new Error("forgejo packages access token was not persisted");
|
|
149
|
+
}
|
|
150
|
+
return outputsFor(parsed, runnerToken, gitToken, packagesToken);
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
await session.dispose();
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
delete: async (inputs) => {
|
|
157
|
+
const parsed = parse(inputs);
|
|
158
|
+
const session = await executor.connect(sshTarget(parsed));
|
|
159
|
+
try {
|
|
160
|
+
await session.exec(`docker rm -f ${CONTAINER} 2>/dev/null || true`);
|
|
161
|
+
await session.exec(`docker volume rm ${CONTAINER}-data 2>/dev/null || true`);
|
|
162
|
+
await session.exec(`rm -rf ${STATE_DIR}`);
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
await session.dispose();
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=forgejo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgejo.js","sourceRoot":"","sources":["../src/forgejo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"garage-bucket.d.ts","sourceRoot":"","sources":["../src/garage-bucket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,kBAAkB,CAAC;AAKjE,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,UAAU,CAAC;AA4CzD,eAAO,MAAM,0BAA0B,GAAI,WAAU,WAAyB,KAAG,QA2D/E,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { containerId } from "./backing-ssh.js";
|
|
3
|
+
import { parseInputs, sshSchema, sshTarget } from "./inputs.js";
|
|
4
|
+
import { sshExecutor } from "./ssh.js";
|
|
5
|
+
const BIN = "/garage";
|
|
6
|
+
const bucketSchema = sshSchema.extend({
|
|
7
|
+
instance: z.string(),
|
|
8
|
+
endpoint: z.string(),
|
|
9
|
+
bucket: z.string(),
|
|
10
|
+
keyName: z.string(),
|
|
11
|
+
});
|
|
12
|
+
const parse = (inputs) => parseInputs(bucketSchema, inputs, "garage-bucket");
|
|
13
|
+
const garage = async (session, cid, args) => {
|
|
14
|
+
const result = await session.exec(`docker exec ${cid} ${BIN} ${args}`);
|
|
15
|
+
if (result.code !== 0) {
|
|
16
|
+
throw new Error(`garage ${args.split(" ")[0]} failed (${result.code}): ${result.stderr.trim()}`);
|
|
17
|
+
}
|
|
18
|
+
return result.stdout.trim();
|
|
19
|
+
};
|
|
20
|
+
const readKey = async (session, cid, keyName) => {
|
|
21
|
+
const info = (await session.exec(`docker exec ${cid} ${BIN} key info --show-secret ${keyName}`)).stdout;
|
|
22
|
+
const field = (label) => info.match(new RegExp(`${label}:\\s*(\\S+)`))?.[1] ?? "";
|
|
23
|
+
return { accessKey: field("Key ID"), secretKey: field("Secret key") };
|
|
24
|
+
};
|
|
25
|
+
const outputsFor = (parsed, key) => ({
|
|
26
|
+
endpoint: parsed.endpoint,
|
|
27
|
+
accessKey: key.accessKey,
|
|
28
|
+
secretKey: key.secretKey,
|
|
29
|
+
bucket: parsed.bucket,
|
|
30
|
+
});
|
|
31
|
+
export const createGarageBucketProvider = (executor = sshExecutor) => ({
|
|
32
|
+
read: async (inputs, ctx) => {
|
|
33
|
+
const parsed = parse(inputs);
|
|
34
|
+
let session;
|
|
35
|
+
try {
|
|
36
|
+
session = await executor.connect(sshTarget(parsed));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
ctx.log(`garage-bucket "${ctx.id}": host not reachable over SSH, treating as not-yet-created: ${String(error)}`);
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const cid = await containerId(session, parsed.instance);
|
|
44
|
+
if (cid === "") {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const info = await session.exec(`docker exec ${cid} ${BIN} bucket info ${parsed.bucket}`);
|
|
48
|
+
if (info.code !== 0) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return { outputs: outputsFor(parsed, await readKey(session, cid, parsed.keyName)) };
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await session.dispose();
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
diff: () => ({ action: "noop" }),
|
|
58
|
+
apply: async (inputs, _observed, ctx) => {
|
|
59
|
+
const parsed = parse(inputs);
|
|
60
|
+
const session = await executor.connect(sshTarget(parsed));
|
|
61
|
+
try {
|
|
62
|
+
const cid = await containerId(session, parsed.instance);
|
|
63
|
+
if (cid === "") {
|
|
64
|
+
throw new Error(`garage-bucket "${ctx.id}": instance "${parsed.instance}" is not running`);
|
|
65
|
+
}
|
|
66
|
+
await session.exec(`docker exec ${cid} ${BIN} bucket create ${parsed.bucket} 2>/dev/null || true`);
|
|
67
|
+
await session.exec(`docker exec ${cid} ${BIN} key create ${parsed.keyName} 2>/dev/null || true`);
|
|
68
|
+
await garage(session, cid, `bucket allow --read --write ${parsed.bucket} --key ${parsed.keyName}`);
|
|
69
|
+
return outputsFor(parsed, await readKey(session, cid, parsed.keyName));
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await session.dispose();
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
delete: async (inputs, ctx) => {
|
|
76
|
+
const parsed = parse(inputs);
|
|
77
|
+
const session = await executor.connect(sshTarget(parsed));
|
|
78
|
+
try {
|
|
79
|
+
const cid = await containerId(session, parsed.instance);
|
|
80
|
+
if (cid === "") {
|
|
81
|
+
ctx.log(`garage-bucket "${ctx.id}": instance "${parsed.instance}" already gone; nothing to drop`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
await session.exec(`docker exec ${cid} ${BIN} bucket delete --yes ${parsed.bucket} 2>/dev/null || true`);
|
|
85
|
+
await session.exec(`docker exec ${cid} ${BIN} key delete --yes ${parsed.keyName} 2>/dev/null || true`);
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await session.dispose();
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=garage-bucket.js.map
|