alasio 7.0.0 → 8.0.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/dist/cli/src/branches.js +65 -29
- package/dist/cli/src/branches.js.map +1 -1
- package/dist/cli/src/cluster/k3s.js +8 -1
- package/dist/cli/src/cluster/k3s.js.map +1 -1
- package/dist/cli/src/cluster/node.js +8 -1
- package/dist/cli/src/cluster/node.js.map +1 -1
- package/dist/cli/src/commands/init.js +54 -4
- package/dist/cli/src/commands/init.js.map +1 -1
- package/dist/cli/src/commands/lake.js +40 -6
- package/dist/cli/src/commands/lake.js.map +1 -1
- package/dist/cli/src/commands/restore-filer-store.js +40 -8
- package/dist/cli/src/commands/restore-filer-store.js.map +1 -1
- package/dist/cli/src/commands/status.js +156 -12
- package/dist/cli/src/commands/status.js.map +1 -1
- package/dist/cli/src/config.js +20 -8
- package/dist/cli/src/config.js.map +1 -1
- package/dist/cli/src/install.js +69 -15
- package/dist/cli/src/install.js.map +1 -1
- package/dist/cli/src/kept-releases.js.map +1 -1
- package/dist/cli/src/kube/api.js +9 -2
- package/dist/cli/src/kube/api.js.map +1 -1
- package/dist/cli/src/kube/apply.js +1 -1
- package/dist/cli/src/kube/apply.js.map +1 -1
- package/dist/cli/src/kube/rollout.js +58 -12
- package/dist/cli/src/kube/rollout.js.map +1 -1
- package/dist/cli/src/lake.js +124 -0
- package/dist/cli/src/lake.js.map +1 -0
- package/dist/cli/src/manifests/admission.js +43 -4
- package/dist/cli/src/manifests/admission.js.map +1 -1
- package/dist/cli/src/manifests/alasio.js +68 -15
- package/dist/cli/src/manifests/alasio.js.map +1 -1
- package/dist/cli/src/manifests/collector.js +227 -128
- package/dist/cli/src/manifests/collector.js.map +1 -1
- package/dist/cli/src/manifests/config.js +196 -15
- package/dist/cli/src/manifests/config.js.map +1 -1
- package/dist/cli/src/manifests/index.js +8 -4
- package/dist/cli/src/manifests/index.js.map +1 -1
- package/dist/cli/src/manifests/juicefs-csi.js +7 -6
- package/dist/cli/src/manifests/juicefs-csi.js.map +1 -1
- package/dist/cli/src/manifests/keda.js +2 -1
- package/dist/cli/src/manifests/keda.js.map +1 -1
- package/dist/cli/src/manifests/lake.js +336 -73
- package/dist/cli/src/manifests/lake.js.map +1 -1
- package/dist/cli/src/manifests/log.js +298 -0
- package/dist/cli/src/manifests/log.js.map +1 -0
- package/dist/cli/src/manifests/neon.js +125 -46
- package/dist/cli/src/manifests/neon.js.map +1 -1
- package/dist/cli/src/manifests/network-policies.js +130 -33
- package/dist/cli/src/manifests/network-policies.js.map +1 -1
- package/dist/cli/src/manifests/node-agent.js +14 -5
- package/dist/cli/src/manifests/node-agent.js.map +1 -1
- package/dist/cli/src/manifests/scalers.js.map +1 -1
- package/dist/cli/src/manifests/webhook.js +102 -0
- package/dist/cli/src/manifests/webhook.js.map +1 -0
- package/dist/cli/src/neon-storage.js +115 -0
- package/dist/cli/src/neon-storage.js.map +1 -0
- package/dist/cli/src/release.js +9 -6
- package/dist/cli/src/release.js.map +1 -1
- package/dist/cli/src/secrets.js +45 -4
- package/dist/cli/src/secrets.js.map +1 -1
- package/dist/cli/src/target.js +1 -1
- package/dist/cli/src/target.js.map +1 -1
- package/dist/cli/src/telegram.js +56 -10
- package/dist/cli/src/telegram.js.map +1 -1
- package/dist/cli/src/webhook.js +182 -0
- package/dist/cli/src/webhook.js.map +1 -0
- package/dist/cluster/node/pins.json +5 -0
- package/dist/neon/control/branches.js +120 -15
- package/dist/neon/control/branches.js.map +1 -1
- package/dist/neon/control/endpoints.js +9 -0
- package/dist/neon/control/endpoints.js.map +1 -1
- package/dist/neon/control/jwt.js +16 -3
- package/dist/neon/control/jwt.js.map +1 -1
- package/dist/neon/control/secrets.js +39 -6
- package/dist/neon/control/secrets.js.map +1 -1
- package/dist/src/kube/config.js +3 -1
- package/dist/src/kube/config.js.map +1 -1
- package/dist/src/kube/sandbox-shape.js +12 -2
- package/dist/src/kube/sandbox-shape.js.map +1 -1
- package/dist/src/node-agent/names.js +67 -1
- package/dist/src/node-agent/names.js.map +1 -1
- package/dist/src/telegram/deliveries.js +40 -0
- package/dist/src/telegram/deliveries.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import { runIn, runningPod } from "./commands/common.js";
|
|
3
|
+
import { kind, KubeApi } from "./kube/api.js";
|
|
4
|
+
import { NAMESPACE, neonName } from "./manifests/common.js";
|
|
5
|
+
/** The configuration asks for fewer of Neon's shards than its tenant has: Neon merges none. */
|
|
6
|
+
export class ShardsLowered extends Schema.TaggedError()("ShardsLowered", { configured: Schema.Number, current: Schema.Number }) {
|
|
7
|
+
get message() {
|
|
8
|
+
return `neon.shards is ${this.configured}, but alasio's Neon has ${this.current} shards already, and Neon merges no shards: set it to ${this.current} or more`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** The configuration asks for fewer of Neon's pageservers than are registered: alasio removes none. */
|
|
12
|
+
export class PageserversLowered extends Schema.TaggedError()("PageserversLowered", { configured: Schema.Number, current: Schema.Number }) {
|
|
13
|
+
get message() {
|
|
14
|
+
return `neon.pageserver.scaling is ${this.configured}, but alasio's Neon has ${this.current} pageservers registered, each holding shards or their secondaries, and alasio removes none: set it to ${this.current} or more`;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The storage controller, which has registered pageservers, did not say what Neon's storage
|
|
19
|
+
* holds: a configuration is not checked against it, so nothing is applied, until it runs.
|
|
20
|
+
*/
|
|
21
|
+
export class StorageUnverified extends Schema.TaggedError()("StorageUnverified", { reason: Schema.String }) {
|
|
22
|
+
get message() {
|
|
23
|
+
return `alasio applies nothing it cannot check against Neon's storage, and its storage controller did not say what it holds (${this.reason}): ` +
|
|
24
|
+
"once it runs, as alasio status says it does not, run alasio up again";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** The storage controller's container, as its Deployment runs it. */
|
|
28
|
+
const CONTAINER = "storage-controller";
|
|
29
|
+
/** Asks the storage controller for `path` of its API, in its pod: what it answered with, by its status. */
|
|
30
|
+
const asked = (pod, path) => runIn({ namespace: NAMESPACE, pod, container: CONTAINER },
|
|
31
|
+
// The token is the container's own, which the shell's own printf gives curl on its
|
|
32
|
+
// standard input, so it is on no command line; and a storage controller that does not
|
|
33
|
+
// answer holds up for 10 s at most.
|
|
34
|
+
["sh", "-c", 'printf "authorization: Bearer %s\\n" "$CONTROL_PLANE_JWT_TOKEN" | curl -sS --max-time 10 -H @- -w "\\n%{http_code}" "http://127.0.0.1:1234$0"', path]).pipe(Effect.catch((error) => Effect.fail(new StorageUnverified({ reason: error.message }))), Effect.flatMap(({ exitCode, stdout, stderr }) => {
|
|
35
|
+
if (exitCode !== 0)
|
|
36
|
+
return Effect.fail(new StorageUnverified({ reason: `asking it for ${path} failed (exit ${exitCode}): ${stderr.trim() || stdout.trim()}` }));
|
|
37
|
+
const lines = stdout.trimEnd().split("\n");
|
|
38
|
+
const status = Number(lines.pop());
|
|
39
|
+
const text = lines.join("\n");
|
|
40
|
+
return Effect.try({ try: () => ({ status, body: text ? JSON.parse(text) : null }), catch: () => new StorageUnverified({ reason: `it answered ${path} with no JSON` }) });
|
|
41
|
+
}));
|
|
42
|
+
/** The storage controller's database's pod, and its claim, which holds what it registered. */
|
|
43
|
+
const DATABASE_POD = `${neonName("controller-db")}-0`;
|
|
44
|
+
const DATABASE_CLAIM = `data-${DATABASE_POD}`;
|
|
45
|
+
/**
|
|
46
|
+
* The storage controller's database, which has held what it registered, did not answer: its
|
|
47
|
+
* pod is to run before anything is applied, as alasio status and its pod's events say why
|
|
48
|
+
* it does not.
|
|
49
|
+
*/
|
|
50
|
+
export class StorageDatabaseUnread extends Schema.TaggedError()("StorageDatabaseUnread", { reason: Schema.String }) {
|
|
51
|
+
get message() {
|
|
52
|
+
return `alasio applies nothing it cannot check against Neon's storage, and the storage controller's database, which holds what it registered, did not answer (${this.reason}): ` +
|
|
53
|
+
`once its pod runs (kubectl -n ${NAMESPACE} describe pod ${DATABASE_POD} says why it does not), run alasio up again`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Asks the storage controller's database `sql`, as its own role, in its pod: what it printed. */
|
|
57
|
+
const askedDatabase = (sql) => runIn({ namespace: NAMESPACE, pod: DATABASE_POD, container: "postgres" }, ["psql", "-U", "storage_controller", "-d", "storage_controller", "-Atc", sql]).pipe(Effect.catch((error) => Effect.fail(new StorageDatabaseUnread({ reason: error.message }))), Effect.flatMap(({ exitCode, stdout, stderr }) => exitCode === 0 ? Effect.succeed(stdout.trim()) : Effect.fail(new StorageDatabaseUnread({ reason: `psql exited with ${exitCode}: ${stderr.trim() || stdout.trim()}` }))));
|
|
58
|
+
/**
|
|
59
|
+
* Whether the storage controller has registered a pageserver, as its own database says:
|
|
60
|
+
* none where the database never held anything, its claim never bound, as before alasio first
|
|
61
|
+
* runs, or where it holds no table of nodes, or no node in it; then there is nothing to check
|
|
62
|
+
* a configuration against. One whose claim is bound is asked, and must answer.
|
|
63
|
+
*/
|
|
64
|
+
const registered = Effect.gen(function* () {
|
|
65
|
+
const kube = yield* KubeApi;
|
|
66
|
+
const claim = yield* kube.get({ ...kind("PersistentVolumeClaim"), namespace: NAMESPACE, name: DATABASE_CLAIM });
|
|
67
|
+
if (claim?.status?.phase !== "Bound" && claim?.status?.phase !== "Lost")
|
|
68
|
+
return false;
|
|
69
|
+
if ((yield* askedDatabase("select to_regclass('nodes') is not null")) !== "t")
|
|
70
|
+
return false;
|
|
71
|
+
return (yield* askedDatabase("select exists (select from nodes)")) === "t";
|
|
72
|
+
});
|
|
73
|
+
/**
|
|
74
|
+
* What Neon's storage holds, as the storage controller says it: null only where it has
|
|
75
|
+
* registered no pageserver; StorageUnverified where it has but does not say, as a
|
|
76
|
+
* configuration it would refuse must not slip through then.
|
|
77
|
+
*/
|
|
78
|
+
const storageHeld = Effect.gen(function* () {
|
|
79
|
+
const kube = yield* KubeApi;
|
|
80
|
+
if (!(yield* registered))
|
|
81
|
+
return null;
|
|
82
|
+
const pod = yield* runningPod("neon-storage-controller").pipe(Effect.catch((error) => Effect.fail(new StorageUnverified({ reason: error.message }))));
|
|
83
|
+
const nodes = yield* asked(pod, "/control/v1/node");
|
|
84
|
+
if (nodes.status !== 200 || !nodes.body)
|
|
85
|
+
return yield* new StorageUnverified({ reason: `it answered its pageservers with ${nodes.status}` });
|
|
86
|
+
const pageservers = nodes.body.length;
|
|
87
|
+
// The tenant, which the stack's setup names before neon-control makes it.
|
|
88
|
+
const encoded = (yield* kube.get({ ...kind("Secret"), namespace: NAMESPACE, name: neonName("root") }))?.data?.["secrets.json"];
|
|
89
|
+
const tenantId = encoded === undefined ? undefined : (yield* Effect.try({
|
|
90
|
+
try: () => JSON.parse(Buffer.from(encoded, "base64").toString("utf8")).tenantId,
|
|
91
|
+
catch: () => new StorageUnverified({ reason: `the Secret ${neonName("root")}'s secrets.json, which names Neon's tenant, is no JSON` }),
|
|
92
|
+
}));
|
|
93
|
+
if (!tenantId)
|
|
94
|
+
return { shards: 0, pageservers };
|
|
95
|
+
const tenant = yield* asked(pod, `/control/v1/tenant/${tenantId}`);
|
|
96
|
+
if (tenant.status === 404)
|
|
97
|
+
return { shards: 0, pageservers };
|
|
98
|
+
if (tenant.status !== 200 || !tenant.body)
|
|
99
|
+
return yield* new StorageUnverified({ reason: `it answered Neon's tenant with ${tenant.status}` });
|
|
100
|
+
return { shards: tenant.body.shards.length, pageservers };
|
|
101
|
+
});
|
|
102
|
+
/** Refuses `settings` where they ask for fewer of Neon's shards or pageservers than its storage holds, as the module says. */
|
|
103
|
+
export const checkNeonStorage = Effect.fnUntraced(function* (settings) {
|
|
104
|
+
if (!settings.neon.enabled)
|
|
105
|
+
return;
|
|
106
|
+
const held = yield* storageHeld;
|
|
107
|
+
if (!held)
|
|
108
|
+
return;
|
|
109
|
+
if (held.shards > settings.neon.shards)
|
|
110
|
+
return yield* new ShardsLowered({ configured: settings.neon.shards, current: held.shards });
|
|
111
|
+
const pageservers = settings.neon.pageserver.scaling.min;
|
|
112
|
+
if (held.pageservers > pageservers)
|
|
113
|
+
return yield* new PageserversLowered({ configured: pageservers, current: held.pageservers });
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=neon-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neon-storage.js","sourceRoot":"","sources":["../../../src/neon-storage.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/src/release.js
CHANGED
|
@@ -3,14 +3,17 @@
|
|
|
3
3
|
* version and the digests of the images it published here, with tooling/pin-release.ts,
|
|
4
4
|
* before it builds the package; this module holds nothing else.
|
|
5
5
|
*/
|
|
6
|
-
export const VERSION = "
|
|
6
|
+
export const VERSION = "8.0.0";
|
|
7
7
|
/** alasio's own images, tagged with the version and pinned by digest once released. */
|
|
8
8
|
export const IMAGES = {
|
|
9
|
-
alasio: { repository: "ghcr.io/eaucoin/alasio", tag: VERSION, digest: "sha256:
|
|
10
|
-
agent: { repository: "ghcr.io/eaucoin/alasio-agent", tag: VERSION, digest: "sha256:
|
|
11
|
-
lake: { repository: "ghcr.io/eaucoin/alasio-lake", tag: VERSION, digest: "sha256:
|
|
12
|
-
grafana: { repository: "ghcr.io/eaucoin/alasio-grafana", tag: VERSION, digest: "sha256:
|
|
9
|
+
alasio: { repository: "ghcr.io/eaucoin/alasio", tag: VERSION, digest: "sha256:6f23f01fd8d7ef9f2447993a6561cc41a6d67d072716d27d14b7a8a7a76ad27f" },
|
|
10
|
+
agent: { repository: "ghcr.io/eaucoin/alasio-agent", tag: VERSION, digest: "sha256:4a0f26bb69a83a5e9965167be9b86470433bd7c40a205a093d6a8c5b6913ea2d" },
|
|
11
|
+
lake: { repository: "ghcr.io/eaucoin/alasio-lake", tag: VERSION, digest: "sha256:6b5a65584cdbb0235df3dcb0c7b1caa5cce11b896deddf7497197975aeda105b" },
|
|
12
|
+
grafana: { repository: "ghcr.io/eaucoin/alasio-grafana", tag: VERSION, digest: "sha256:675dd5314491f703b99aa3a77ce3b398607049431a5b29775ec6e2076bd5b3f1" },
|
|
13
|
+
log: { repository: "ghcr.io/eaucoin/alasio-log", tag: VERSION, digest: "sha256:4821fc2332c5699ff2a437b8a8bef15acffc4b4d07469fc03f66a272a454ac92" },
|
|
14
|
+
collector: { repository: "ghcr.io/eaucoin/alasio-collector", tag: VERSION, digest: "sha256:e9fba725b22b50c73057d780de4fedf9fc7a78111f24d21d38d491e96f66393e" },
|
|
15
|
+
webhook: { repository: "ghcr.io/eaucoin/alasio-webhook", tag: VERSION, digest: "sha256:6d42a55a61f7758b5e0f17af291684aabcb85e23ef9a69b8023e4f58436ce237" },
|
|
13
16
|
};
|
|
14
17
|
/** The node image of the cluster in Docker: k3s with gVisor (cluster/node), pinned like the others. */
|
|
15
|
-
export const NODE_IMAGE = { repository: "ghcr.io/eaucoin/alasio-node", tag: VERSION, digest: "sha256:
|
|
18
|
+
export const NODE_IMAGE = { repository: "ghcr.io/eaucoin/alasio-node", tag: VERSION, digest: "sha256:22e5eb12c121ed7f303d3deab7bfe9e2001146f54169b0e31523cb028462fd6d" };
|
|
16
19
|
//# sourceMappingURL=release.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../../src/release.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,uFAAuF;AACvF,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAE,EAAE,UAAU,EAAE,wBAAwB,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IACjJ,KAAK,EAAE,EAAE,UAAU,EAAE,8BAA8B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IACtJ,IAAI,EAAE,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IACpJ,OAAO,EAAE,EAAE,UAAU,EAAE,gCAAgC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;CAC3J,CAAC;AAEF,uGAAuG;AACvG,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../../src/release.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,uFAAuF;AACvF,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAE,EAAE,UAAU,EAAE,wBAAwB,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IACjJ,KAAK,EAAE,EAAE,UAAU,EAAE,8BAA8B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IACtJ,IAAI,EAAE,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IACpJ,OAAO,EAAE,EAAE,UAAU,EAAE,gCAAgC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IAC1J,GAAG,EAAE,EAAE,UAAU,EAAE,4BAA4B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IAClJ,SAAS,EAAE,EAAE,UAAU,EAAE,kCAAkC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;IAC9J,OAAO,EAAE,EAAE,UAAU,EAAE,gCAAgC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE;CAC3J,CAAC;AAEF,uGAAuG;AACvG,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,UAAU,EAAE,6BAA6B,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,yEAAyE,EAAE,CAAC"}
|
package/dist/cli/src/secrets.js
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* alasio's Secrets: what an operator gives alasio that is written nowhere but the
|
|
3
|
+
* cluster, each in a Secret of alasio's own in its namespace, under a fixed name its
|
|
4
|
+
* install configuration names (./config.ts): the bot's token and the Telegram users
|
|
5
|
+
* allowed to use it, and Claude Code's token. In memory the tokens are Redacted, and only
|
|
6
|
+
* the API server is sent them.
|
|
7
|
+
*/
|
|
8
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
1
9
|
import { Effect, Redacted } from "effect";
|
|
2
|
-
import { kind, KubeApi } from "./kube/api.js";
|
|
10
|
+
import { FIELD_MANAGER, kind, KubeApi } from "./kube/api.js";
|
|
3
11
|
import { NAMESPACE } from "./manifests/common.js";
|
|
4
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* The bot's Secret: its token (`token`), the users allowed to use it (`allowedUserIds`,
|
|
14
|
+
* comma-separated), and the key its checksum is an HMAC with (`checksumKey`, botChecksum).
|
|
15
|
+
*/
|
|
5
16
|
export const TELEGRAM_SECRET = "alasio-telegram";
|
|
6
17
|
/** Claude Code's Secret: its token (`token`), from `claude setup-token`. */
|
|
7
18
|
export const CLAUDE_SECRET = "alasio-claude";
|
|
@@ -23,8 +34,38 @@ const valueOf = (found, key) => {
|
|
|
23
34
|
const encoded = found?.data?.[key];
|
|
24
35
|
return encoded === undefined ? null : Buffer.from(encoded, "base64").toString("utf8");
|
|
25
36
|
};
|
|
26
|
-
/**
|
|
27
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The checksum of the bot's Secret as alasio reads it, its token and the users it allows,
|
|
39
|
+
* which alasio's pod carries (./manifests/alasio.ts Kept): an HMAC with the Secret's own
|
|
40
|
+
* key, so that what anyone reading alasio's Deployment reads of it says nothing of either.
|
|
41
|
+
*/
|
|
42
|
+
export function botChecksum(bot, key) {
|
|
43
|
+
return createHmac("sha256", Redacted.value(key)).update(JSON.stringify([Redacted.value(bot.token), bot.allowedUserIds.join(",")])).digest("hex");
|
|
44
|
+
}
|
|
45
|
+
/** A key for botChecksum, made anew. */
|
|
46
|
+
const newChecksumKey = () => randomBytes(32).toString("base64url");
|
|
47
|
+
/** Writes the bot's Secret, keeping its checksum's key, or making one where it has none. */
|
|
48
|
+
export const writeTelegramBot = (bot) => Effect.gen(function* () {
|
|
49
|
+
const kube = yield* KubeApi;
|
|
50
|
+
const checksumKey = valueOf(yield* kube.get({ ...SECRET, namespace: NAMESPACE, name: TELEGRAM_SECRET }), "checksumKey") ?? newChecksumKey();
|
|
51
|
+
yield* kube.apply(secret(TELEGRAM_SECRET, { token: Redacted.value(bot.token), allowedUserIds: bot.allowedUserIds.join(","), checksumKey }, { [BOT_ANNOTATION]: bot.username }));
|
|
52
|
+
});
|
|
53
|
+
/** The key of the bot's Secret's checksum (botChecksum), or null where it has none, as one alasio init wrote before it had one has not. */
|
|
54
|
+
export const readBotChecksumKey = Effect.gen(function* () {
|
|
55
|
+
const kube = yield* KubeApi;
|
|
56
|
+
const key = valueOf(yield* kube.get({ ...SECRET, namespace: NAMESPACE, name: TELEGRAM_SECRET }), "checksumKey");
|
|
57
|
+
return key === null ? null : Redacted.make(key);
|
|
58
|
+
});
|
|
59
|
+
/** Gives the bot's Secret its checksum's key where it has none, beside what it holds, as up does before it renders alasio's pod. */
|
|
60
|
+
export const ensureBotChecksumKey = Effect.gen(function* () {
|
|
61
|
+
if ((yield* readBotChecksumKey) !== null)
|
|
62
|
+
return;
|
|
63
|
+
const kube = yield* KubeApi;
|
|
64
|
+
const found = yield* kube.get({ ...SECRET, namespace: NAMESPACE, name: TELEGRAM_SECRET });
|
|
65
|
+
if (!found)
|
|
66
|
+
return;
|
|
67
|
+
yield* kube.patch({ ...SECRET, namespace: NAMESPACE, name: TELEGRAM_SECRET }, { data: { checksumKey: Buffer.from(newChecksumKey(), "utf8").toString("base64") } }, FIELD_MANAGER);
|
|
68
|
+
});
|
|
28
69
|
/** Writes Claude Code's Secret. */
|
|
29
70
|
export const writeClaudeToken = (token) => Effect.flatMap(KubeApi, (kube) => kube.apply(secret(CLAUDE_SECRET, { token: Redacted.value(token) }))).pipe(Effect.asVoid);
|
|
30
71
|
/** The bot of the bot's Secret, or null when there is none. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/secrets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/secrets.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/src/target.js
CHANGED
|
@@ -32,7 +32,7 @@ export const resolveTarget = Effect.fnUntraced(function* (config) {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
const { docker } = target;
|
|
35
|
-
const install = installConfigOf(config.install, { claude: false,
|
|
35
|
+
const install = installConfigOf(config.install, { claude: false, target: "docker" });
|
|
36
36
|
if (Result.isFailure(install))
|
|
37
37
|
return yield* new OperatorConfigError({ path: config.path, reason: install.failure });
|
|
38
38
|
const hostProfile = install.success.host;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../../src/target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE3E,OAAO,EAAE,YAAY,EAA8B,MAAM,4BAA4B,CAAC;AACtF,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,eAAe,EAAuB,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACnI,OAAO,EAAE,OAAO,EAA+C,MAAM,eAAe,CAAC;AAQrF,oCAAoC;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAC,MAAsB;IAC7E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC1B,IAAI,YAAY,IAAI,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;IACzF,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3D,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;QACrB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC;gBAC5D,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5D;YACD,UAAU;SACX,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC1B,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../../src/target.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/src/telegram.js
CHANGED
|
@@ -1,27 +1,73 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Telegram's Bot API, as far as alasio's command line asks it: which bot a token is
|
|
3
|
-
* (getMe), so a token is checked before it is kept
|
|
4
|
-
*
|
|
3
|
+
* (getMe), so a token is checked before it is kept; and where Telegram delivers a bot's
|
|
4
|
+
* updates (setWebhook, deleteWebhook, getWebhookInfo), which the command line alone says,
|
|
5
|
+
* as it registers each environment's bot (./webhook.ts). It never sends a message. The API
|
|
6
|
+
* is at TELEGRAM_API_ROOT, as for alasio itself, or Telegram's own.
|
|
5
7
|
*/
|
|
6
8
|
import { Config, Context, Effect, Layer, Redacted, Schema } from "effect";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
/** A Bot API answer of `result`'s shape, or its refusal. */
|
|
10
|
+
const Answer = (result) => Schema.Union([
|
|
11
|
+
Schema.Struct({ ok: Schema.Literal(true), result }),
|
|
9
12
|
Schema.Struct({ ok: Schema.Literal(false), description: Schema.String }),
|
|
10
13
|
]);
|
|
14
|
+
const GetMeAnswer = Answer(Schema.Struct({ username: Schema.String }));
|
|
15
|
+
const DoneAnswer = Answer(Schema.Boolean);
|
|
16
|
+
const WebhookInfoAnswer = Answer(Schema.Struct({
|
|
17
|
+
url: Schema.String,
|
|
18
|
+
pending_update_count: Schema.Number,
|
|
19
|
+
last_error_date: Schema.optionalKey(Schema.Number),
|
|
20
|
+
last_error_message: Schema.optionalKey(Schema.String),
|
|
21
|
+
}));
|
|
11
22
|
/** A bot token could not be checked, or Telegram refused it. */
|
|
12
23
|
export class BotTokenError extends Schema.TaggedError()("BotTokenError", {
|
|
13
24
|
message: Schema.String,
|
|
14
25
|
}) {
|
|
15
26
|
}
|
|
27
|
+
/** Telegram could not be asked about a bot's webhook, or refused what it was asked. */
|
|
28
|
+
export class WebhookError extends Schema.TaggedError()("WebhookError", {
|
|
29
|
+
message: Schema.String,
|
|
30
|
+
}) {
|
|
31
|
+
}
|
|
32
|
+
/** The updates a bot is sent: those alasio acts on, as the webhook intake passes them on. */
|
|
33
|
+
export const ALLOWED_UPDATES = ["message", "callback_query"];
|
|
16
34
|
/** Why `cause`, a failed fetch, failed: its own cause's message, as a fetch's says only that it failed. */
|
|
17
35
|
const fetchFailure = (cause) => cause instanceof Error ? (cause.cause instanceof Error ? cause.cause.message : cause.message) : String(cause);
|
|
18
36
|
export class TelegramBotApi extends Context.Service()("alasio/TelegramBotApi") {
|
|
19
|
-
static layer = Layer.effect(TelegramBotApi, Effect.map(Config.String("TELEGRAM_API_ROOT").pipe(Config.withDefault("https://api.telegram.org")), (
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
static layer = Layer.effect(TelegramBotApi, Effect.map(Config.String("TELEGRAM_API_ROOT").pipe(Config.withDefault("https://api.telegram.org")), (configured) => {
|
|
38
|
+
const root = configured.replace(/\/$/u, "");
|
|
39
|
+
/**
|
|
40
|
+
* The bot `token`'s `method`, sent `body`, its answer as `answer` reads it; `failed`
|
|
41
|
+
* makes the error of one not answered (`why` it was not) or answered as the Bot API does not.
|
|
42
|
+
*/
|
|
43
|
+
const call = (token, method, body, answer, failed) => Effect.tryPromise({
|
|
44
|
+
try: async (signal) => (await fetch(`${root}/bot${Redacted.value(token)}/${method}`, { method: body ? "POST" : "GET", signal, ...(body ? { body } : {}) })).json(),
|
|
22
45
|
// Told by its cause alone, as the URL holds the token.
|
|
23
|
-
catch: (cause) =>
|
|
24
|
-
}).pipe(Effect.flatMap((
|
|
25
|
-
|
|
46
|
+
catch: (cause) => failed(fetchFailure(cause)),
|
|
47
|
+
}).pipe(Effect.flatMap((answered) => Schema.decodeUnknownEffect(answer)(answered).pipe(Effect.mapError(() => failed(null)))));
|
|
48
|
+
const done = (method) => (answered) => answered.ok ? Effect.void : Effect.fail(new WebhookError({ message: `Telegram refused ${method}: ${answered.description}` }));
|
|
49
|
+
const webhookError = (method) => (why) => new WebhookError({ message: why === null ? `${root} answered ${method} as Telegram's Bot API does not` : `Telegram could not be asked to ${method}: ${why}` });
|
|
50
|
+
return TelegramBotApi.of({
|
|
51
|
+
getMe: (token) => call(token, "getMe", null, GetMeAnswer, (why) => new BotTokenError({ message: why === null ? `${root} answered what Telegram's Bot API does not` : `Telegram could not be asked about the bot token: ${why}` })).pipe(Effect.flatMap((answer) => answer.ok ? Effect.succeed(answer.result.username) : Effect.fail(new BotTokenError({ message: `Telegram refused the bot token: ${answer.description}` })))),
|
|
52
|
+
setWebhook: (token, { url, certificate, secretToken, ipAddress }) => {
|
|
53
|
+
const form = new FormData();
|
|
54
|
+
form.set("url", url);
|
|
55
|
+
form.set("certificate", new Blob([certificate], { type: "application/x-pem-file" }), "certificate.pem");
|
|
56
|
+
form.set("secret_token", Redacted.value(secretToken));
|
|
57
|
+
form.set("allowed_updates", JSON.stringify(ALLOWED_UPDATES));
|
|
58
|
+
form.set("max_connections", "4");
|
|
59
|
+
form.set("drop_pending_updates", "false");
|
|
60
|
+
if (ipAddress)
|
|
61
|
+
form.set("ip_address", ipAddress);
|
|
62
|
+
return call(token, "setWebhook", form, DoneAnswer, webhookError("setWebhook")).pipe(Effect.flatMap(done("setWebhook")));
|
|
63
|
+
},
|
|
64
|
+
deleteWebhook: (token) => {
|
|
65
|
+
const form = new FormData();
|
|
66
|
+
form.set("drop_pending_updates", "false");
|
|
67
|
+
return call(token, "deleteWebhook", form, DoneAnswer, webhookError("deleteWebhook")).pipe(Effect.flatMap(done("deleteWebhook")));
|
|
68
|
+
},
|
|
69
|
+
getWebhookInfo: (token) => call(token, "getWebhookInfo", null, WebhookInfoAnswer, webhookError("getWebhookInfo")).pipe(Effect.flatMap((answer) => (answer.ok ? Effect.succeed(answer.result) : Effect.fail(new WebhookError({ message: `Telegram refused getWebhookInfo: ${answer.description}` }))))),
|
|
70
|
+
});
|
|
71
|
+
}));
|
|
26
72
|
}
|
|
27
73
|
//# sourceMappingURL=telegram.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../src/telegram.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../src/telegram.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram's deliveries to the webhook intake (./manifests/webhook.ts), as alasio's
|
|
3
|
+
* command line arranges them, it alone: alasio itself never tells Telegram anything of
|
|
4
|
+
* them. Each environment, main and each branch's, has a route in the routes Secret, which
|
|
5
|
+
* the intake reads (webhook/src/routes.ts): an unguessable path, a secret token Telegram
|
|
6
|
+
* sends with each delivery, and the users the environment allows, which the intake lets
|
|
7
|
+
* through alone. Its bot is registered once the intake serves its route: Telegram is told
|
|
8
|
+
* the route's URL on the intake's public address, the secret token, the updates alasio
|
|
9
|
+
* acts on, and the intake's certificate, uploaded, which Telegram trusts alone. alasio up
|
|
10
|
+
* registers main's again each time, with the certificate the stack's setup keeps or has
|
|
11
|
+
* just renewed (neon/control/certificate.ts); a branch environment's bot is registered as
|
|
12
|
+
* the branch is made, and told to deliver nowhere as it is deleted.
|
|
13
|
+
*/
|
|
14
|
+
import { randomBytes } from "node:crypto";
|
|
15
|
+
import { duplexPair } from "node:stream";
|
|
16
|
+
import { Duration, Effect, Redacted, Schema } from "effect";
|
|
17
|
+
import { FIELD_MANAGER, hasStatus, kind, KubeApi } from "./kube/api.js";
|
|
18
|
+
import { selectorOf } from "./kube/rollout.js";
|
|
19
|
+
import { NAMESPACE, selectorLabels } from "./manifests/common.js";
|
|
20
|
+
import { ROUTES_SECRET, TLS_SECRET, WEBHOOK_COMPONENT, WEBHOOK_HEALTH_PORT } from "./manifests/webhook.js";
|
|
21
|
+
import { TelegramBotApi } from "./telegram.js";
|
|
22
|
+
import { failingDeliveries } from "../../src/telegram/deliveries.js";
|
|
23
|
+
const SECRET = kind("Secret");
|
|
24
|
+
const POD = kind("Pod");
|
|
25
|
+
/** The webhook intake did not serve an environment's route in time, or its certificate is not there to upload. */
|
|
26
|
+
export class WebhookNotServing extends Schema.TaggedError()("WebhookNotServing", {
|
|
27
|
+
message: Schema.String,
|
|
28
|
+
}) {
|
|
29
|
+
}
|
|
30
|
+
/** The data of the Secret `found`, decoded. */
|
|
31
|
+
const dataOf = (found) => Object.fromEntries(Object.entries(found?.data ?? {}).map(([key, value]) => [key, Buffer.from(value, "base64").toString("utf8")]));
|
|
32
|
+
/** The routes Secret, as the API addresses it. */
|
|
33
|
+
const ROUTES = { ...SECRET, namespace: NAMESPACE, name: ROUTES_SECRET };
|
|
34
|
+
/** The routes Secret, holding no route: each is patched in under its environment's key alone (setRoute). */
|
|
35
|
+
const routesSecret = {
|
|
36
|
+
apiVersion: "v1",
|
|
37
|
+
kind: "Secret",
|
|
38
|
+
metadata: { name: ROUTES_SECRET, namespace: NAMESPACE, labels: { "app.kubernetes.io/managed-by": "alasio", "app.kubernetes.io/part-of": "alasio" } },
|
|
39
|
+
type: "Opaque",
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Sets `environment`'s route in the routes Secret, or takes it out where `route` is null,
|
|
43
|
+
* by a merge patch of its key alone: environments made and deleted at once each keep the
|
|
44
|
+
* others' routes, which a write of the whole Secret, from a read of it, would take out or
|
|
45
|
+
* put back. Where there is no Secret yet, it is applied first, holding no route: of
|
|
46
|
+
* environments that find none at once, the last to apply it takes out none the others
|
|
47
|
+
* have patched in.
|
|
48
|
+
*/
|
|
49
|
+
const setRoute = Effect.fnUntraced(function* (environment, route) {
|
|
50
|
+
const kube = yield* KubeApi;
|
|
51
|
+
const patch = kube.patch(ROUTES, { data: { [environment]: route && Buffer.from(JSON.stringify(route), "utf8").toString("base64") } }, FIELD_MANAGER);
|
|
52
|
+
yield* patch.pipe(Effect.catchIf(hasStatus(404), () => Effect.andThen(kube.apply(routesSecret), patch)));
|
|
53
|
+
});
|
|
54
|
+
/** The routes the Secret holds, by environment; one that does not parse is none. */
|
|
55
|
+
const readRoutes = Effect.gen(function* () {
|
|
56
|
+
const kube = yield* KubeApi;
|
|
57
|
+
const routes = {};
|
|
58
|
+
for (const [environment, text] of Object.entries(dataOf(yield* kube.get(ROUTES)))) {
|
|
59
|
+
try {
|
|
60
|
+
routes[environment] = JSON.parse(text);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Made anew below, where it is asked for.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return routes;
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* The route of `environment`, allowing `allowedUserIds`: the one it has, its users as
|
|
70
|
+
* given now, or a new one, its path and secret token random.
|
|
71
|
+
*/
|
|
72
|
+
export const ensureRoute = Effect.fnUntraced(function* (environment, allowedUserIds) {
|
|
73
|
+
const current = (yield* readRoutes)[environment];
|
|
74
|
+
const route = {
|
|
75
|
+
path: current?.path ?? `/telegram/${environment}/${randomBytes(16).toString("base64url")}`,
|
|
76
|
+
secretToken: current?.secretToken ?? randomBytes(32).toString("base64url"),
|
|
77
|
+
allowedUserIds: [...allowedUserIds],
|
|
78
|
+
};
|
|
79
|
+
yield* setRoute(environment, route);
|
|
80
|
+
return route;
|
|
81
|
+
});
|
|
82
|
+
/** Takes the route of `environment` out of the routes Secret. */
|
|
83
|
+
export const removeRoute = Effect.fnUntraced(function* (environment) {
|
|
84
|
+
if ((yield* readRoutes)[environment])
|
|
85
|
+
yield* setRoute(environment, null);
|
|
86
|
+
});
|
|
87
|
+
/** The environments the intake's pod `pod` routes, as its health port says; none where it does not answer. */
|
|
88
|
+
const routedBy = (pod) => Effect.gen(function* () {
|
|
89
|
+
const kube = yield* KubeApi;
|
|
90
|
+
const [here, there] = duplexPair();
|
|
91
|
+
// What came back once the forward ends, as the intake closes it after its answer, or it fails.
|
|
92
|
+
const answered = new Promise((resolve) => {
|
|
93
|
+
const chunks = [];
|
|
94
|
+
const ended = () => resolve(Buffer.concat(chunks).toString("utf8"));
|
|
95
|
+
here.on("data", (chunk) => chunks.push(chunk));
|
|
96
|
+
here.on("end", ended);
|
|
97
|
+
here.on("close", ended);
|
|
98
|
+
here.on("error", ended);
|
|
99
|
+
});
|
|
100
|
+
here.write("GET /environments HTTP/1.0\r\nHost: webhook\r\n\r\n");
|
|
101
|
+
yield* kube.portForward({ namespace: NAMESPACE, pod }, WEBHOOK_HEALTH_PORT, there).pipe(Effect.timeout("10 seconds"), Effect.ignore);
|
|
102
|
+
here.destroy();
|
|
103
|
+
const text = yield* Effect.promise(() => answered);
|
|
104
|
+
try {
|
|
105
|
+
const routes = JSON.parse(text.slice(text.indexOf("\r\n\r\n") + 4));
|
|
106
|
+
return routes.map(({ environment }) => environment);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
/** Waits until every running pod of the intake routes `environment`, as the kubelet hands them the routes Secret it was written in. */
|
|
113
|
+
export const awaitRouted = Effect.fnUntraced(function* (environment, { timeout }) {
|
|
114
|
+
const kube = yield* KubeApi;
|
|
115
|
+
const deadline = Date.now() + Duration.toMillis(Duration.fromInputUnsafe(timeout));
|
|
116
|
+
for (;;) {
|
|
117
|
+
const pods = (yield* kube.list(POD, { namespace: NAMESPACE, labelSelector: selectorOf(selectorLabels(WEBHOOK_COMPONENT)) }))
|
|
118
|
+
.filter(({ status, metadata }) => status?.phase === "Running" && !metadata?.deletionTimestamp);
|
|
119
|
+
const routed = yield* Effect.forEach(pods, ({ metadata }) => routedBy(metadata?.name ?? ""));
|
|
120
|
+
if (pods.length > 0 && routed.every((environments) => environments.includes(environment)))
|
|
121
|
+
return;
|
|
122
|
+
if (Date.now() > deadline) {
|
|
123
|
+
return yield* new WebhookNotServing({ message: `the webhook intake does not route ${environment} yet: its pods are not running, or have not been handed its route` });
|
|
124
|
+
}
|
|
125
|
+
yield* Effect.sleep("2 seconds");
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
/** The URL Telegram delivers `route`'s updates to, on the intake's public address and port. */
|
|
129
|
+
export const routeUrl = ({ webhook }, route) => `https://${webhook.publicAddress}${webhook.port === 443 ? "" : `:${webhook.port}`}${route.path}`;
|
|
130
|
+
/** The certificate the intake serves, which Telegram is given, as the stack's setup keeps it. */
|
|
131
|
+
const certificate = Effect.gen(function* () {
|
|
132
|
+
const kube = yield* KubeApi;
|
|
133
|
+
const cert = dataOf(yield* kube.get({ ...SECRET, namespace: NAMESPACE, name: TLS_SECRET }))["tls.crt"];
|
|
134
|
+
if (!cert)
|
|
135
|
+
return yield* new WebhookNotServing({ message: `${TLS_SECRET} holds no certificate: the stack's setup makes it as alasio up runs` });
|
|
136
|
+
return cert;
|
|
137
|
+
});
|
|
138
|
+
/** Has Telegram deliver `bot`'s updates to `route`, once the intake serves it, with the intake's certificate. */
|
|
139
|
+
export const registerBot = Effect.fnUntraced(function* (config, environment, bot, route, options) {
|
|
140
|
+
yield* awaitRouted(environment, options);
|
|
141
|
+
const telegram = yield* TelegramBotApi;
|
|
142
|
+
const address = config.webhook.publicAddress;
|
|
143
|
+
yield* telegram.setWebhook(bot.token, {
|
|
144
|
+
url: routeUrl(config, route),
|
|
145
|
+
certificate: yield* certificate,
|
|
146
|
+
secretToken: Redacted.make(route.secretToken),
|
|
147
|
+
ipAddress: /^(\d{1,3}\.){3}\d{1,3}$/u.test(address) ? address : undefined,
|
|
148
|
+
});
|
|
149
|
+
yield* Effect.logInfo(`Telegram delivers ${bot.username ? `@${bot.username}` : "the bot"}'s updates to the webhook intake, for ${environment}`);
|
|
150
|
+
});
|
|
151
|
+
/** The fix of deliveries that fail where nothing points to another. */
|
|
152
|
+
const REGISTER_AGAIN = "alasio up registers each bot again";
|
|
153
|
+
/**
|
|
154
|
+
* How a bot's deliveries fare, as its getWebhookInfo says: whether to `url`, how many
|
|
155
|
+
* wait, and where they fail (../../src/telegram/deliveries.ts) Telegram's last error and
|
|
156
|
+
* when; and their fix, null where they do not fail.
|
|
157
|
+
*/
|
|
158
|
+
export function describeDeliveries(info, url, now = Date.now()) {
|
|
159
|
+
if (info.url !== url)
|
|
160
|
+
return { line: info.url ? `delivered elsewhere, to ${info.url}: alasio up registers it again` : "not delivered: alasio up registers it", fix: REGISTER_AGAIN };
|
|
161
|
+
const failing = failingDeliveries(info, now);
|
|
162
|
+
if (failing)
|
|
163
|
+
return { line: failing.description, fix: failing.fix ?? REGISTER_AGAIN };
|
|
164
|
+
return { line: `delivered, ${info.pending_update_count} update${info.pending_update_count === 1 ? "" : "s"} waiting`, fix: null };
|
|
165
|
+
}
|
|
166
|
+
/** How each of `bots`' deliveries fare, as Telegram says: a line of each, and the fixes of those that fail, each once. */
|
|
167
|
+
export const describeBots = Effect.fnUntraced(function* (config, bots) {
|
|
168
|
+
const telegram = yield* TelegramBotApi;
|
|
169
|
+
const routes = yield* readRoutes;
|
|
170
|
+
const described = yield* Effect.forEach(bots, ({ environment, bot }) => {
|
|
171
|
+
const name = `${environment}'s bot${bot.username ? ` @${bot.username}` : ""}`;
|
|
172
|
+
const route = routes[environment];
|
|
173
|
+
if (!route)
|
|
174
|
+
return Effect.succeed({ line: `${name}: no route: alasio up gives it one`, fix: REGISTER_AGAIN });
|
|
175
|
+
return telegram.getWebhookInfo(bot.token).pipe(Effect.map((info) => describeDeliveries(info, routeUrl(config, route))), Effect.catch((error) => Effect.succeed({ line: `not asked: ${error.message}`, fix: REGISTER_AGAIN })), Effect.map(({ line, fix }) => ({ line: `${name}: ${line}`, fix })));
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
lines: ["Telegram's deliveries:", ...described.map(({ line }) => ` ${line}`)],
|
|
179
|
+
fixes: [...new Set(described.flatMap(({ fix }) => (fix === null ? [] : [fix])))],
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../../src/webhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
11
|
"gvisor": {
|
|
12
|
+
"restoresFromBucketSince": "20260921.0-eaucoin.7",
|
|
12
13
|
"releases": [
|
|
14
|
+
{
|
|
15
|
+
"release": "20260921.0-eaucoin.8",
|
|
16
|
+
"sha512": "5091e17365e49328af3f6fd79211ac645699db8cb4f39d940a2d140980dc6f9b11f1ff89944e1723c06a759617b8083d2de8d16ce848945a7f300ef8724db48b"
|
|
17
|
+
},
|
|
13
18
|
{
|
|
14
19
|
"release": "20260921.0-eaucoin.6",
|
|
15
20
|
"sha512": "86f85cca0f604e40887b6244cd9f57b3efbba760b3bdcabf066b3a408dde5b84fa2b1fc94e4db00ded989e1bb08522ad9343af8735a66b4964b3ca9b3a2c08b0"
|