@tsplc/agent 0.2.6 → 0.2.7
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.js +16 -8
- package/dist/cli.js.map +3 -3
- package/dist/index.js +16 -8
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
- package/src/agent.ts +38 -17
package/dist/cli.js
CHANGED
|
@@ -259,6 +259,7 @@ var createServerSupervisor = (options) => {
|
|
|
259
259
|
// packages/agent/src/agent.ts
|
|
260
260
|
var execute = promisify(execFile);
|
|
261
261
|
var network = "tsplc-agent";
|
|
262
|
+
var codesysNetwork = "tsplc-agent-codesys";
|
|
262
263
|
var gateway = { host: "tsplc-agent-gateway", port: 1217 };
|
|
263
264
|
var loginContainer = "tsplc-agent-login";
|
|
264
265
|
var credentialNames = {
|
|
@@ -278,13 +279,20 @@ class AgentError extends Error {
|
|
|
278
279
|
var json = (body, status = 200) => Response.json(body, { status });
|
|
279
280
|
var readJson = async (path, schema) => existsSync2(path) ? schema.parse(JSON.parse(await readFile2(path, "utf8"))) : null;
|
|
280
281
|
var docker = (...args) => execute("docker", args).then(({ stdout }) => stdout.trim());
|
|
282
|
+
var ensureNetwork = async (name, ...options) => {
|
|
283
|
+
if (!await docker("network", "ls", "--quiet", "--filter", `name=^${name}$`))
|
|
284
|
+
await docker("network", "create", ...options, name);
|
|
285
|
+
};
|
|
281
286
|
var ensureGateway = async () => {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (await docker("container", "ls", "--quiet", "--filter", `name=^${gateway.host}$`))
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
287
|
+
await ensureNetwork(network);
|
|
288
|
+
await ensureNetwork(codesysNetwork, "--internal");
|
|
289
|
+
if (!await docker("container", "ls", "--quiet", "--filter", `name=^${gateway.host}$`)) {
|
|
290
|
+
await docker("rm", "--force", gateway.host);
|
|
291
|
+
await docker("run", "--detach", "--restart", "unless-stopped", "--platform", "linux/amd64", "--network", network, "--name", gateway.host, gatewayImage);
|
|
292
|
+
}
|
|
293
|
+
const networks = await docker("inspect", "--format", "{{json .NetworkSettings.Networks}}", gateway.host);
|
|
294
|
+
if (!(codesysNetwork in JSON.parse(networks)))
|
|
295
|
+
await docker("network", "connect", codesysNetwork, gateway.host);
|
|
288
296
|
};
|
|
289
297
|
var withCredentials = async (credentials, run) => {
|
|
290
298
|
process.env[credentialNames.usernameEnv] = credentials.username;
|
|
@@ -348,7 +356,7 @@ var createAgent = async (options) => {
|
|
|
348
356
|
const controllerConfig = (release, target) => ({
|
|
349
357
|
...resolveConfig({
|
|
350
358
|
...release.manifest.config,
|
|
351
|
-
online: { network, gateway, device: target, credentials: credentialNames }
|
|
359
|
+
online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames }
|
|
352
360
|
}, join2(release.directory, "manifest.json")),
|
|
353
361
|
outDir: paths.controller
|
|
354
362
|
});
|
|
@@ -570,5 +578,5 @@ if (command === "setup") {
|
|
|
570
578
|
} else
|
|
571
579
|
throw new Error(`Unknown command ${command}.`);
|
|
572
580
|
|
|
573
|
-
//# debugId=
|
|
581
|
+
//# debugId=6AE382186C37533864756E2164756E21
|
|
574
582
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"sources": ["../src/cli.ts", "../src/agent.ts", "../src/discovery.ts", "../src/protocol.ts", "../src/releases.ts", "../src/server-process.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"#!/usr/bin/env bun\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { configureDocker, configureGateway } from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { createAgent } from \"./agent.ts\";\n\nconst usage = `tsplc-agent setup|serve [--listen host:port] [--state directory] [--server-health url]\n\nsetup Builds the CODESYS builder and gateway images. Run it once, and after updating tsPLC.\nserve Serves deployments and logins. --listen is required: use the machine's Tailscale\n address, such as 100.101.102.103:4850. TSPLC_AGENT_TOKEN must hold a shared secret of\n at least 32 characters, such as one from \\`openssl rand -hex 32\\`.`;\n\nconst { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\" },\n listen: { type: \"string\" },\n state: { type: \"string\" },\n \"server-health\": { type: \"string\" },\n },\n});\nconst command = positionals[0];\nif (!command || values.help) {\n console.log(usage);\n process.exit(0);\n}\nif (positionals.length > 1) throw new Error(\"Specify one command.\");\nif (command === \"setup\") {\n await configureDocker();\n await configureGateway();\n} else if (command === \"serve\") {\n const [, hostname, port] = /^(.+):(\\d+)$/.exec(values.listen ?? \"\") ?? [];\n if (!hostname || !port) throw new Error(\"--listen host:port is required.\");\n const token = z\n .string({ error: \"Set TSPLC_AGENT_TOKEN\" })\n .min(32, \"TSPLC_AGENT_TOKEN must be at least 32 characters\")\n .parse(process.env[\"TSPLC_AGENT_TOKEN\"]);\n const agent = await createAgent({\n state: values.state ?? join(homedir(), \".tsplc-agent\"),\n token,\n serverHealthUrl: values[\"server-health\"],\n log: (message) => console.log(`${new Date().toISOString()} ${message}`),\n });\n const server = Bun.serve({\n hostname,\n port: Number(port),\n fetch: agent.fetch,\n // Deployments stream for minutes and upload a server executable.\n idleTimeout: 0,\n maxRequestBodySize: 2 ** 30,\n });\n console.log(`tsPLC agent listening on ${server.url}`);\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const)\n process.on(signal, () => {\n void agent.stop().then(() => process.exit(0));\n });\n} else throw new Error(`Unknown command ${command}.`);\n",
|
|
6
|
-
"import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n updateController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** Builder containers reach the gateway by name on this Docker network. */\nconst network = \"tsplc-agent\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${network}$`)))\n await docker(\"network\", \"create\", network);\n if (await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`)) return;\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}; CODESYS takes minutes to start` });\n await ensureGateway();\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await withCredentials(settings.credentials, () =>\n updateController(config, kind, { initializeUser: settings.initializeUser }),\n )\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
|
|
6
|
+
"import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n updateController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** The gateway reaches controllers through this Docker network. */\nconst network = \"tsplc-agent\";\n/**\n * Builder containers reach the gateway by name on this internal network, which has no internet.\n * With internet, CODESYS asks a certificate authority about each DLL it loads, without caching\n * the answer, and opening a project takes minutes instead of seconds.\n */\nconst codesysNetwork = \"tsplc-agent-codesys\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\nconst ensureNetwork = async (name: string, ...options: string[]) => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${name}$`)))\n await docker(\"network\", \"create\", ...options, name);\n};\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n await ensureNetwork(network);\n await ensureNetwork(codesysNetwork, \"--internal\");\n if (!(await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`))) {\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n }\n // Gateways started by earlier agents are only on `network`.\n const networks = await docker(\n \"inspect\",\n \"--format\",\n \"{{json .NetworkSettings.Networks}}\",\n gateway.host,\n );\n if (!(codesysNetwork in JSON.parse(networks)))\n await docker(\"network\", \"connect\", codesysNetwork, gateway.host);\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}; CODESYS takes minutes to start` });\n await ensureGateway();\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await withCredentials(settings.credentials, () =>\n updateController(config, kind, { initializeUser: settings.initializeUser }),\n )\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
|
|
7
7
|
"import { Resolver } from \"node:dns/promises\";\nimport { createConnection } from \"node:net\";\nimport { networkInterfaces as osInterfaces } from \"node:os\";\nimport type { DiscoveredController, NetworkInterface } from \"./protocol\";\n\n/** CODESYS runtimes accept engineering connections on their TCP block driver port. */\nexport const runtimePort = 11740;\n/** A /22 is 1022 hosts: a sweep at 128 probes a time takes a few seconds. */\nconst largestPrefix = 22;\nconst probeTimeoutMs = 500;\nconst probesAtOnce = 128;\n\n/** The machine's IPv4 networks, which `discoverControllers` scans one at a time. */\nexport const networkInterfaces = (): NetworkInterface[] =>\n Object.entries(osInterfaces()).flatMap(([name, addresses]) =>\n (addresses ?? [])\n .filter((address) => address.family === \"IPv4\" && !address.internal)\n .map((address) => ({\n name,\n address: address.address,\n prefixLength: address.netmask\n .split(\".\")\n .reduce((bits, octet) => bits + Number(octet).toString(2).replaceAll(\"0\", \"\").length, 0),\n })),\n );\n\nconst toNumber = (address: string) =>\n address.split(\".\").reduce((value, octet) => value * 256 + Number(octet), 0);\nconst toAddress = (value: number) =>\n [24, 16, 8, 0].map((shift) => Math.floor(value / 2 ** shift) % 256).join(\".\");\n\n/** Every host address on the interface's subnet, except the interface's own. */\nexport const subnetHosts = ({ address, prefixLength }: NetworkInterface) => {\n if (prefixLength < largestPrefix)\n throw new Error(\n `The /${prefixLength} network is too large to scan; the limit is /${largestPrefix}.`,\n );\n const size = 2 ** (32 - prefixLength);\n const network = toNumber(address) - (toNumber(address) % size);\n // /31 and /32 networks have no network or broadcast address to skip.\n const hosts =\n size <= 2\n ? Array.from({ length: size }, (_, index) => network + index)\n : Array.from({ length: size - 2 }, (_, index) => network + index + 1);\n return hosts.map(toAddress).filter((host) => host !== address);\n};\n\nconst accepts = (host: string, port: number) =>\n new Promise<boolean>((resolve) => {\n const socket = createConnection({ host, port });\n // A silent host leaves the connection pending for the OS's own timeout, which is minutes.\n const timer = setTimeout(() => finish(false), probeTimeoutMs);\n const finish = (open: boolean) => {\n clearTimeout(timer);\n socket.destroy();\n resolve(open);\n };\n socket.once(\"connect\", () => finish(true));\n socket.once(\"error\", () => finish(false));\n });\n\nconst resolver = new Resolver({ timeout: 1000, tries: 1 });\nconst hostname = (address: string) =>\n resolver.reverse(address).then(\n (names) => names[0] ?? null,\n // Plant networks rarely have reverse DNS; the address alone identifies the controller.\n () => null,\n );\n\n/** Finds the hosts on `network` that accept CODESYS runtime connections. */\nexport const discoverControllers = async (\n network: NetworkInterface,\n port = runtimePort,\n): Promise<DiscoveredController[]> => {\n const hosts = subnetHosts(network);\n const found: DiscoveredController[] = [];\n for (let start = 0; start < hosts.length; start += probesAtOnce) {\n const batch = hosts.slice(start, start + probesAtOnce);\n const open = await Promise.all(batch.map((host) => accepts(host, port)));\n for (const [index, host] of batch.entries())\n if (open[index]) found.push({ address: host, port, hostname: await hostname(host) });\n }\n return found;\n};\n",
|
|
8
8
|
"import { z } from \"zod\";\n\n/** The controller the agent deploys to, as its runtime's TCP block driver address. */\nexport const targetSchema = z.strictObject({\n host: z.string().nonempty(),\n port: z.number().int().min(1).max(65535),\n});\nexport type Target = z.infer<typeof targetSchema>;\n\nexport const networkInterfaceSchema = z.strictObject({\n name: z.string(),\n address: z.ipv4(),\n prefixLength: z.number().int().min(0).max(32),\n});\nexport type NetworkInterface = z.infer<typeof networkInterfaceSchema>;\n\n/** A host on the scanned subnet that accepts connections on the CODESYS runtime port. */\nexport const controllerSchema = z.strictObject({\n address: z.ipv4(),\n port: z.number().int(),\n hostname: z.string().nullable(),\n});\nexport type DiscoveredController = z.infer<typeof controllerSchema>;\n\n/** The controller's user; the agent passes it to CODESYS for one operation and never stores it. */\nexport const credentialsSchema = z.strictObject({\n username: z.string().nonempty(),\n password: z.string().nonempty(),\n});\nexport type Credentials = z.infer<typeof credentialsSchema>;\n\n/** A published leaf of the deployed program, as CODESYS expressions name it. */\nexport const variableSchema = z.strictObject({ path: z.string(), type: z.string() });\nexport type Variable = z.infer<typeof variableSchema>;\n\n/**\n * What `tsplc deploy` uploads beside its files. `config` is the build config with paths\n * relative to the release: `st/`, `template.project` and `libraries/`.\n */\nexport const releaseManifestSchema = z.strictObject({\n config: z.record(z.string(), z.unknown()),\n variables: z.array(variableSchema),\n /** The server executable's path in the release, when the project builds one. */\n server: z.string().nonempty().optional(),\n});\nexport type ReleaseManifest = z.infer<typeof releaseManifestSchema>;\n\nexport const deployOptionsSchema = z.strictObject({\n credentials: credentialsSchema,\n /** A full download stops the application; without it only an online change is applied. */\n download: z.boolean(),\n initializeUser: z.boolean(),\n});\nexport type DeployOptions = z.infer<typeof deployOptionsSchema>;\n\n/** Long operations stream one of these per line. */\nexport const eventSchema = z.discriminatedUnion(\"kind\", [\n z.strictObject({ kind: z.literal(\"progress\"), message: z.string() }),\n z.strictObject({ kind: z.literal(\"done\"), result: z.unknown() }),\n z.strictObject({\n kind: z.literal(\"error\"),\n message: z.string(),\n /** The controller has no application from this agent yet, so only a full download can deploy. */\n downloadRequired: z.boolean(),\n }),\n]);\nexport type AgentEvent = z.infer<typeof eventSchema>;\n\nexport const releaseSchema = z.strictObject({\n id: z.string(),\n deployedAt: z.iso.datetime(),\n operation: z.enum([\"download\", \"online-change\"]),\n controllerIds: z.strictObject({ codeId: z.string(), dataId: z.string() }),\n /** The running server executable, relative to the releases directory. */\n server: z.string().optional(),\n});\nexport type Release = z.infer<typeof releaseSchema>;\n\nexport const statusSchema = z.strictObject({\n target: targetSchema.nullable(),\n release: releaseSchema.nullable(),\n server: z.strictObject({ executable: z.string(), running: z.boolean() }).nullable(),\n /** The open login's application state and forced expressions. */\n login: z.strictObject({ state: z.string(), forced: z.array(z.string()) }).nullable(),\n});\nexport type AgentStatus = z.infer<typeof statusSchema>;\n",
|
|
9
9
|
"import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, mkdtemp, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { z } from \"zod\";\nimport { type ReleaseManifest, releaseManifestSchema } from \"./protocol\";\n\n/** Uploaded files are named `files/<path in the release>`. */\nconst filePrefix = \"files/\";\n\nconst releasePath = (name: string) => {\n const path = posix.normalize(name.slice(filePrefix.length));\n if (posix.isAbsolute(path) || path.startsWith(\"..\") || path.includes(\"\\\\\"))\n throw new Error(`Invalid release file name: ${name}`);\n return path;\n};\n\n/** An uploaded release, from `tsplc deploy`'s form. */\nexport const readUpload = async (form: FormData) => {\n const manifest = releaseManifestSchema.parse(JSON.parse(z.string().parse(form.get(\"manifest\"))));\n const files = await Promise.all(\n [...form.entries()]\n .filter(([name]) => name.startsWith(filePrefix))\n .map(async ([name, value]) => ({\n path: releasePath(name),\n content: new Uint8Array(await z.instanceof(File).parse(value).arrayBuffer()),\n })),\n );\n if (manifest.server && !files.some((file) => file.path === manifest.server))\n throw new Error(`The release names a server ${manifest.server} it doesn't contain`);\n return { manifest, files };\n};\n\n/**\n * Stores a release under `releases/<id>`, where the id hashes its contents, so the same\n * upload twice is one release. Each release is complete before it appears.\n */\nexport const saveRelease = async (\n releases: string,\n { manifest, files }: Awaited<ReturnType<typeof readUpload>>,\n) => {\n const hash = createHash(\"sha256\").update(JSON.stringify(manifest));\n for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path)))\n hash.update(file.path).update(createHash(\"sha256\").update(file.content).digest(\"hex\"));\n const id = hash.digest(\"hex\").slice(0, 16);\n const directory = join(releases, id);\n if (!existsSync(directory)) {\n await mkdir(releases, { recursive: true });\n const staging = await mkdtemp(join(releases, \".upload-\"));\n try {\n for (const file of files) {\n await mkdir(dirname(join(staging, file.path)), { recursive: true });\n // Uploads lose their mode; the server must stay executable outside Windows.\n await writeFile(join(staging, file.path), file.content, {\n mode: file.path === manifest.server ? 0o755 : 0o644,\n });\n }\n await writeFile(join(staging, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n await rename(staging, directory);\n } catch (cause) {\n await rm(staging, { recursive: true, force: true });\n throw cause;\n }\n }\n return { id, directory, manifest };\n};\n\nexport const loadRelease = async (\n releases: string,\n id: string,\n): Promise<{ id: string; directory: string; manifest: ReleaseManifest }> => {\n const directory = join(releases, id);\n const manifest = releaseManifestSchema.parse(\n JSON.parse(await readFile(join(directory, \"manifest.json\"), \"utf8\")),\n );\n return { id, directory, manifest };\n};\n",
|
|
10
10
|
"import type { Subprocess } from \"bun\";\nimport { dirname } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nconst healthyWithinMs = 60_000;\n/** Without a health URL, a server that stays up this long counts as started. */\nconst settleMs = 5000;\nconst restartDelayMs = 2000;\n\n/**\n * Runs the deployed server executable, restarting it whenever it exits, and swaps it for\n * another release's. The server reads its own environment and secrets, as it would anywhere.\n */\nexport const createServerSupervisor = (options: {\n /** The server's `/health` route, which answers once it is listening. */\n healthUrl?: string;\n log: (message: string) => void;\n}) => {\n let current: { executable: string; process: Subprocess } | undefined;\n\n const spawn = (executable: string): Subprocess => {\n const child = Bun.spawn([executable], {\n cwd: dirname(executable),\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n onExit: (_, code) => {\n // `stop` and `replace` clear or change `current` before killing a server.\n if (current?.process !== child) return;\n options.log(`Server exited (${code}); restarting it in ${restartDelayMs / 1000} s`);\n void delay(restartDelayMs).then(() => {\n if (current?.process === child) current = { executable, process: spawn(executable) };\n });\n },\n });\n return child;\n };\n\n const start = (executable: string) => {\n current = { executable, process: spawn(executable) };\n return current.process;\n };\n\n const stop = async () => {\n const running = current;\n current = undefined;\n if (!running) return;\n running.process.kill();\n await running.process.exited;\n };\n\n const healthy = async (child: Subprocess) => {\n if (!options.healthUrl) {\n await delay(settleMs);\n return child.exitCode === null;\n }\n const deadline = Date.now() + healthyWithinMs;\n while (Date.now() < deadline && child.exitCode === null) {\n if (\n await fetch(options.healthUrl).then(\n (response) => response.ok,\n () => false,\n )\n )\n return true;\n await delay(1000);\n }\n return false;\n };\n\n return {\n start,\n stop,\n /** Replaces the running server; if the new one doesn't come up, the previous one runs again. */\n replace: async (executable: string) => {\n const previous = current?.executable;\n await stop();\n let failure: unknown;\n const started = await (async () => healthy(start(executable)))().catch((error: unknown) => {\n failure = error;\n return false;\n });\n if (started) return;\n await stop();\n if (previous) start(previous);\n const reason =\n failure instanceof Error\n ? failure.message\n : `it did not start${options.healthUrl ? ` answering ${options.healthUrl}` : \"\"}`;\n throw new Error(\n `The new server failed: ${reason}. ${previous ? \"The previous one is running again.\" : \"\"}`.trim(),\n { cause: failure },\n );\n },\n status: () =>\n current && { executable: current.executable, running: current.process.exitCode === null },\n };\n};\n"
|
|
11
11
|
],
|
|
12
|
-
"mappings": "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",
|
|
13
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "6AE382186C37533864756E2164756E21",
|
|
14
14
|
"names": []
|
|
15
15
|
}
|
package/dist/index.js
CHANGED
|
@@ -249,6 +249,7 @@ var createServerSupervisor = (options) => {
|
|
|
249
249
|
// packages/agent/src/agent.ts
|
|
250
250
|
var execute = promisify(execFile);
|
|
251
251
|
var network = "tsplc-agent";
|
|
252
|
+
var codesysNetwork = "tsplc-agent-codesys";
|
|
252
253
|
var gateway = { host: "tsplc-agent-gateway", port: 1217 };
|
|
253
254
|
var loginContainer = "tsplc-agent-login";
|
|
254
255
|
var credentialNames = {
|
|
@@ -268,13 +269,20 @@ class AgentError extends Error {
|
|
|
268
269
|
var json = (body, status = 200) => Response.json(body, { status });
|
|
269
270
|
var readJson = async (path, schema) => existsSync2(path) ? schema.parse(JSON.parse(await readFile2(path, "utf8"))) : null;
|
|
270
271
|
var docker = (...args) => execute("docker", args).then(({ stdout }) => stdout.trim());
|
|
272
|
+
var ensureNetwork = async (name, ...options) => {
|
|
273
|
+
if (!await docker("network", "ls", "--quiet", "--filter", `name=^${name}$`))
|
|
274
|
+
await docker("network", "create", ...options, name);
|
|
275
|
+
};
|
|
271
276
|
var ensureGateway = async () => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (await docker("container", "ls", "--quiet", "--filter", `name=^${gateway.host}$`))
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
await ensureNetwork(network);
|
|
278
|
+
await ensureNetwork(codesysNetwork, "--internal");
|
|
279
|
+
if (!await docker("container", "ls", "--quiet", "--filter", `name=^${gateway.host}$`)) {
|
|
280
|
+
await docker("rm", "--force", gateway.host);
|
|
281
|
+
await docker("run", "--detach", "--restart", "unless-stopped", "--platform", "linux/amd64", "--network", network, "--name", gateway.host, gatewayImage);
|
|
282
|
+
}
|
|
283
|
+
const networks = await docker("inspect", "--format", "{{json .NetworkSettings.Networks}}", gateway.host);
|
|
284
|
+
if (!(codesysNetwork in JSON.parse(networks)))
|
|
285
|
+
await docker("network", "connect", codesysNetwork, gateway.host);
|
|
278
286
|
};
|
|
279
287
|
var withCredentials = async (credentials, run) => {
|
|
280
288
|
process.env[credentialNames.usernameEnv] = credentials.username;
|
|
@@ -338,7 +346,7 @@ var createAgent = async (options) => {
|
|
|
338
346
|
const controllerConfig = (release, target) => ({
|
|
339
347
|
...resolveConfig({
|
|
340
348
|
...release.manifest.config,
|
|
341
|
-
online: { network, gateway, device: target, credentials: credentialNames }
|
|
349
|
+
online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames }
|
|
342
350
|
}, join2(release.directory, "manifest.json")),
|
|
343
351
|
outDir: paths.controller
|
|
344
352
|
});
|
|
@@ -521,5 +529,5 @@ export {
|
|
|
521
529
|
variableSchema
|
|
522
530
|
};
|
|
523
531
|
|
|
524
|
-
//# debugId=
|
|
532
|
+
//# debugId=3E53D86CAC15F1B264756E2164756E21
|
|
525
533
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/agent.ts", "../src/discovery.ts", "../src/protocol.ts", "../src/releases.ts", "../src/server-process.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n updateController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** Builder containers reach the gateway by name on this Docker network. */\nconst network = \"tsplc-agent\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${network}$`)))\n await docker(\"network\", \"create\", network);\n if (await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`)) return;\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}; CODESYS takes minutes to start` });\n await ensureGateway();\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await withCredentials(settings.credentials, () =>\n updateController(config, kind, { initializeUser: settings.initializeUser }),\n )\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
|
|
5
|
+
"import { execFile } from \"node:child_process\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n explicitDownload,\n findControllerLogin,\n gatewayImage,\n loginCommandSchema,\n openControllerLogin,\n resolveConfig,\n updateController,\n} from \"@tsplc/build\";\nimport { z } from \"zod\";\nimport { discoverControllers, networkInterfaces } from \"./discovery\";\nimport {\n type AgentEvent,\n type AgentStatus,\n type Credentials,\n credentialsSchema,\n deployOptionsSchema,\n type Release,\n releaseSchema,\n type Target,\n targetSchema,\n} from \"./protocol\";\nimport { loadRelease, readUpload, saveRelease } from \"./releases\";\nimport { createServerSupervisor } from \"./server-process\";\n\nconst execute = promisify(execFile);\n\n/** The gateway reaches controllers through this Docker network. */\nconst network = \"tsplc-agent\";\n/**\n * Builder containers reach the gateway by name on this internal network, which has no internet.\n * With internet, CODESYS asks a certificate authority about each DLL it loads, without caching\n * the answer, and opening a project takes minutes instead of seconds.\n */\nconst codesysNetwork = \"tsplc-agent-codesys\";\nconst gateway = { host: \"tsplc-agent-gateway\", port: 1217 };\nconst loginContainer = \"tsplc-agent-login\";\n/** CODESYS reads the controller user from these for one operation; the agent never stores it. */\nconst credentialNames = {\n usernameEnv: \"TSPLC_DEVICE_USERNAME\",\n passwordEnv: \"TSPLC_DEVICE_PASSWORD\",\n};\n\nclass AgentError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly downloadRequired = false,\n ) {\n super(message);\n }\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status });\n\nconst readJson = async <T>(path: string, schema: z.ZodType<T>) =>\n existsSync(path) ? schema.parse(JSON.parse(await readFile(path, \"utf8\"))) : null;\n\nconst docker = (...args: string[]) => execute(\"docker\", args).then(({ stdout }) => stdout.trim());\n\nconst ensureNetwork = async (name: string, ...options: string[]) => {\n if (!(await docker(\"network\", \"ls\", \"--quiet\", \"--filter\", `name=^${name}$`)))\n await docker(\"network\", \"create\", ...options, name);\n};\n\n/** The gateway container stays up between operations, as a CODESYS gateway service would. */\nconst ensureGateway = async () => {\n await ensureNetwork(network);\n await ensureNetwork(codesysNetwork, \"--internal\");\n if (!(await docker(\"container\", \"ls\", \"--quiet\", \"--filter\", `name=^${gateway.host}$`))) {\n await docker(\"rm\", \"--force\", gateway.host);\n await docker(\n \"run\",\n \"--detach\",\n \"--restart\",\n \"unless-stopped\",\n \"--platform\",\n \"linux/amd64\",\n \"--network\",\n network,\n \"--name\",\n gateway.host,\n gatewayImage,\n );\n }\n // Gateways started by earlier agents are only on `network`.\n const networks = await docker(\n \"inspect\",\n \"--format\",\n \"{{json .NetworkSettings.Networks}}\",\n gateway.host,\n );\n if (!(codesysNetwork in JSON.parse(networks)))\n await docker(\"network\", \"connect\", codesysNetwork, gateway.host);\n};\n\n/** Hands the controller user to CODESYS through the environment for the duration of `run`. */\nconst withCredentials = async <T>(credentials: Credentials, run: () => Promise<T>) => {\n process.env[credentialNames.usernameEnv] = credentials.username;\n process.env[credentialNames.passwordEnv] = credentials.password;\n try {\n return await run();\n } finally {\n delete process.env[credentialNames.usernameEnv];\n delete process.env[credentialNames.passwordEnv];\n }\n};\n\n/** Relays the newest controller job's progress log, which CODESYS appends to as it works. */\nconst followProgress = (controller: string, emit: (event: AgentEvent) => void) => {\n const jobs = join(controller, \".codesys/controller/jobs\");\n const since = Date.now();\n let following = true;\n const done = (async () => {\n let log: string | undefined;\n let offset = 0;\n while (following) {\n await delay(2000);\n if (!log && existsSync(jobs)) {\n for (const job of await readdir(jobs)) {\n const path = join(jobs, job, \".codesys/controller/progress.log\");\n if (existsSync(path) && (await stat(path)).mtimeMs >= since) log = path;\n }\n }\n if (!log) continue;\n const text = await readFile(log, \"utf8\");\n for (const line of text.slice(offset).split(\"\\n\").filter(Boolean))\n emit({ kind: \"progress\", message: line.replace(/^\\S+Z /, \"\") });\n offset = text.length;\n }\n })();\n return async () => {\n following = false;\n await done;\n };\n};\n\nexport interface AgentOptions {\n /** Releases, the controller's download baseline and the selected target live here. */\n state: string;\n token: string;\n /** The deployed server's health route; without it a server that stays up 5 s counts as started. */\n serverHealthUrl?: string;\n log: (message: string) => void;\n}\n\n/** The plant agent's routes. It runs one deployment or login operation at a time. */\nexport const createAgent = async (options: AgentOptions) => {\n const paths = {\n releases: join(options.state, \"releases\"),\n controller: join(options.state, \"controller\"),\n release: join(options.state, \"release.json\"),\n target: join(options.state, \"target.json\"),\n };\n await mkdir(options.state, { recursive: true });\n const server = createServerSupervisor({ healthUrl: options.serverHealthUrl, log: options.log });\n const deployed = await readJson(paths.release, releaseSchema);\n if (deployed?.server) server.start(join(paths.releases, deployed.server));\n let busy: string | undefined;\n\n const requireTarget = async () => {\n const target = await readJson(paths.target, targetSchema);\n if (!target) throw new AgentError(\"Select the controller first: tsplc target\", 409);\n return target;\n };\n\n /** The release's build config, aimed at `target` through the agent's gateway. */\n const controllerConfig = (release: Awaited<ReturnType<typeof saveRelease>>, target: Target) => ({\n ...resolveConfig(\n {\n ...release.manifest.config,\n online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },\n },\n join(release.directory, \"manifest.json\"),\n ),\n // The baseline outlives releases: an online change compares against the last download.\n outDir: paths.controller,\n });\n\n const currentRelease = async () => {\n const release = await readJson(paths.release, releaseSchema);\n if (!release) throw new AgentError(\"Nothing has been deployed yet: tsplc deploy\", 409);\n return loadRelease(paths.releases, release.id);\n };\n\n /** Streams one exclusive operation's events, then its result, as newline-delimited JSON. */\n const operation = (\n name: string,\n run: (emit: (event: AgentEvent) => void) => Promise<unknown>,\n ) => {\n if (busy) throw new AgentError(`The agent is busy with ${busy}`, 409);\n busy = name;\n const encoder = new TextEncoder();\n // A client that disconnects doesn't stop the operation; it just stops hearing about it.\n let listening = true;\n return new Response(\n new ReadableStream({\n start: async (controller) => {\n const write = (text: string) => {\n if (listening) controller.enqueue(encoder.encode(text));\n };\n const emit = (event: AgentEvent) => write(`${JSON.stringify(event)}\\n`);\n // CODESYS can stay silent for minutes; blank lines keep proxies from closing the stream.\n const heartbeat = setInterval(() => write(\"\\n\"), 15_000);\n try {\n emit({ kind: \"done\", result: await run(emit) });\n } catch (error) {\n options.log(`${name} failed: ${error instanceof Error ? error.stack : String(error)}`);\n emit({\n kind: \"error\",\n message: error instanceof Error ? error.message : String(error),\n downloadRequired:\n (error instanceof AgentError && error.downloadRequired) ||\n (error instanceof Error && error.message.includes(explicitDownload)),\n });\n } finally {\n clearInterval(heartbeat);\n busy = undefined;\n if (listening) controller.close();\n }\n },\n cancel: () => {\n listening = false;\n },\n }),\n { headers: { \"Content-Type\": \"application/x-ndjson\" } },\n );\n };\n\n const deploy = async (form: FormData) => {\n const settings = deployOptionsSchema.parse(JSON.parse(z.string().parse(form.get(\"options\"))));\n const upload = await readUpload(form);\n const target = await requireTarget();\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is open; log out before deploying: tsplc logout\", 409);\n return operation(\"a deployment\", async (emit) => {\n const release = await saveRelease(paths.releases, upload);\n const config = controllerConfig(release, target);\n if (\n !settings.download &&\n !existsSync(join(paths.controller, \".codesys/controller/current.json\"))\n )\n throw new AgentError(\n \"The controller has no application downloaded by this agent; only a full download can deploy\",\n 409,\n true,\n );\n const previous = await readJson(paths.release, releaseSchema);\n // Server paths are relative to the releases directory.\n const serverPath = release.manifest.server && `${release.id}/${release.manifest.server}`;\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Starting the new server\" });\n await server.replace(join(paths.releases, serverPath));\n }\n const kind = settings.download ? \"download\" : \"online-change\";\n emit({ kind: \"progress\", message: `Starting the ${kind}; CODESYS takes minutes to start` });\n await ensureGateway();\n const stopFollowing = followProgress(paths.controller, emit);\n const receipt = await withCredentials(settings.credentials, () =>\n updateController(config, kind, { initializeUser: settings.initializeUser }),\n )\n .catch(async (failure: unknown) => {\n if (serverPath) {\n emit({ kind: \"progress\", message: \"Restoring the previous server\" });\n await (previous?.server\n ? server.replace(join(paths.releases, previous.server))\n : server.stop());\n }\n throw failure;\n })\n .finally(stopFollowing);\n const deployedRelease: Release = {\n id: release.id,\n deployedAt: new Date().toISOString(),\n operation: kind,\n controllerIds: receipt.controllerIds,\n // A release without a server leaves the previous one running.\n server: serverPath ?? previous?.server,\n };\n await writeFile(paths.release, JSON.stringify(deployedRelease, null, 2));\n return deployedRelease;\n });\n };\n\n const openLogin = async (credentials: Credentials) => {\n const release = await currentRelease();\n const config = controllerConfig(release, await requireTarget());\n return operation(\"a login\", async (emit) => {\n if (await findControllerLogin(loginContainer))\n throw new AgentError(\"A login is already open\", 409);\n emit({ kind: \"progress\", message: \"Logging in; CODESYS takes minutes to start\" });\n await ensureGateway();\n const login = await withCredentials(credentials, () =>\n openControllerLogin(config, loginContainer),\n );\n return login.send({ command: \"state\" });\n });\n };\n\n const requireLogin = async () => {\n const login = await findControllerLogin(loginContainer);\n if (!login) throw new AgentError(\"No login is open: tsplc login\", 409);\n return login;\n };\n\n const status = async (): Promise<AgentStatus> => {\n const login = await findControllerLogin(loginContainer);\n // A login still opening has its container but doesn't answer yet.\n const state = login && (await login.ready()) && (await login.send({ command: \"state\" }));\n return {\n target: await readJson(paths.target, targetSchema),\n release: await readJson(paths.release, releaseSchema),\n server: server.status() ?? null,\n login: state && \"state\" in state ? state : null,\n };\n };\n\n const route = async (request: Request): Promise<Response> => {\n const { pathname } = new URL(request.url);\n const key = `${request.method} ${pathname}`;\n switch (key) {\n case \"GET /status\":\n return json(await status());\n case \"GET /interfaces\":\n return json(networkInterfaces());\n case \"POST /discover\": {\n const { name } = z.strictObject({ name: z.string() }).parse(await request.json());\n const selected = networkInterfaces().find((network) => network.name === name);\n if (!selected) throw new AgentError(`No IPv4 interface named ${name}`, 404);\n return json(await discoverControllers(selected));\n }\n case \"PUT /target\": {\n const target = targetSchema.parse(await request.json());\n await writeFile(paths.target, JSON.stringify(target, null, 2));\n return json(target);\n }\n case \"GET /variables\":\n return json((await currentRelease()).manifest.variables);\n case \"POST /deploy\":\n return deploy(await request.formData());\n case \"POST /login\":\n return openLogin(credentialsSchema.parse(await request.json()));\n case \"POST /login/command\":\n return json(\n await (await requireLogin()).send(loginCommandSchema.parse(await request.json())),\n );\n case \"DELETE /login\":\n await (await requireLogin()).close();\n return json({});\n default:\n return json({ error: `No route ${key}` }, 404);\n }\n };\n\n const expected = Buffer.from(`Bearer ${options.token}`);\n return {\n fetch: async (request: Request) => {\n const actual = Buffer.from(request.headers.get(\"authorization\") ?? \"\");\n if (actual.length !== expected.length || !timingSafeEqual(actual, expected))\n return json({ error: \"Unauthorized\" }, 401);\n try {\n return await route(request);\n } catch (error) {\n if (error instanceof AgentError) return json({ error: error.message }, error.status);\n if (error instanceof z.ZodError) return json({ error: z.prettifyError(error) }, 400);\n options.log(\n `${request.method} ${request.url} failed: ${error instanceof Error ? error.stack : String(error)}`,\n );\n return json({ error: error instanceof Error ? error.message : String(error) }, 500);\n }\n },\n /** Stops the supervised server; a login container keeps running for the next agent. */\n stop: () => server.stop(),\n };\n};\n",
|
|
6
6
|
"import { Resolver } from \"node:dns/promises\";\nimport { createConnection } from \"node:net\";\nimport { networkInterfaces as osInterfaces } from \"node:os\";\nimport type { DiscoveredController, NetworkInterface } from \"./protocol\";\n\n/** CODESYS runtimes accept engineering connections on their TCP block driver port. */\nexport const runtimePort = 11740;\n/** A /22 is 1022 hosts: a sweep at 128 probes a time takes a few seconds. */\nconst largestPrefix = 22;\nconst probeTimeoutMs = 500;\nconst probesAtOnce = 128;\n\n/** The machine's IPv4 networks, which `discoverControllers` scans one at a time. */\nexport const networkInterfaces = (): NetworkInterface[] =>\n Object.entries(osInterfaces()).flatMap(([name, addresses]) =>\n (addresses ?? [])\n .filter((address) => address.family === \"IPv4\" && !address.internal)\n .map((address) => ({\n name,\n address: address.address,\n prefixLength: address.netmask\n .split(\".\")\n .reduce((bits, octet) => bits + Number(octet).toString(2).replaceAll(\"0\", \"\").length, 0),\n })),\n );\n\nconst toNumber = (address: string) =>\n address.split(\".\").reduce((value, octet) => value * 256 + Number(octet), 0);\nconst toAddress = (value: number) =>\n [24, 16, 8, 0].map((shift) => Math.floor(value / 2 ** shift) % 256).join(\".\");\n\n/** Every host address on the interface's subnet, except the interface's own. */\nexport const subnetHosts = ({ address, prefixLength }: NetworkInterface) => {\n if (prefixLength < largestPrefix)\n throw new Error(\n `The /${prefixLength} network is too large to scan; the limit is /${largestPrefix}.`,\n );\n const size = 2 ** (32 - prefixLength);\n const network = toNumber(address) - (toNumber(address) % size);\n // /31 and /32 networks have no network or broadcast address to skip.\n const hosts =\n size <= 2\n ? Array.from({ length: size }, (_, index) => network + index)\n : Array.from({ length: size - 2 }, (_, index) => network + index + 1);\n return hosts.map(toAddress).filter((host) => host !== address);\n};\n\nconst accepts = (host: string, port: number) =>\n new Promise<boolean>((resolve) => {\n const socket = createConnection({ host, port });\n // A silent host leaves the connection pending for the OS's own timeout, which is minutes.\n const timer = setTimeout(() => finish(false), probeTimeoutMs);\n const finish = (open: boolean) => {\n clearTimeout(timer);\n socket.destroy();\n resolve(open);\n };\n socket.once(\"connect\", () => finish(true));\n socket.once(\"error\", () => finish(false));\n });\n\nconst resolver = new Resolver({ timeout: 1000, tries: 1 });\nconst hostname = (address: string) =>\n resolver.reverse(address).then(\n (names) => names[0] ?? null,\n // Plant networks rarely have reverse DNS; the address alone identifies the controller.\n () => null,\n );\n\n/** Finds the hosts on `network` that accept CODESYS runtime connections. */\nexport const discoverControllers = async (\n network: NetworkInterface,\n port = runtimePort,\n): Promise<DiscoveredController[]> => {\n const hosts = subnetHosts(network);\n const found: DiscoveredController[] = [];\n for (let start = 0; start < hosts.length; start += probesAtOnce) {\n const batch = hosts.slice(start, start + probesAtOnce);\n const open = await Promise.all(batch.map((host) => accepts(host, port)));\n for (const [index, host] of batch.entries())\n if (open[index]) found.push({ address: host, port, hostname: await hostname(host) });\n }\n return found;\n};\n",
|
|
7
7
|
"import { z } from \"zod\";\n\n/** The controller the agent deploys to, as its runtime's TCP block driver address. */\nexport const targetSchema = z.strictObject({\n host: z.string().nonempty(),\n port: z.number().int().min(1).max(65535),\n});\nexport type Target = z.infer<typeof targetSchema>;\n\nexport const networkInterfaceSchema = z.strictObject({\n name: z.string(),\n address: z.ipv4(),\n prefixLength: z.number().int().min(0).max(32),\n});\nexport type NetworkInterface = z.infer<typeof networkInterfaceSchema>;\n\n/** A host on the scanned subnet that accepts connections on the CODESYS runtime port. */\nexport const controllerSchema = z.strictObject({\n address: z.ipv4(),\n port: z.number().int(),\n hostname: z.string().nullable(),\n});\nexport type DiscoveredController = z.infer<typeof controllerSchema>;\n\n/** The controller's user; the agent passes it to CODESYS for one operation and never stores it. */\nexport const credentialsSchema = z.strictObject({\n username: z.string().nonempty(),\n password: z.string().nonempty(),\n});\nexport type Credentials = z.infer<typeof credentialsSchema>;\n\n/** A published leaf of the deployed program, as CODESYS expressions name it. */\nexport const variableSchema = z.strictObject({ path: z.string(), type: z.string() });\nexport type Variable = z.infer<typeof variableSchema>;\n\n/**\n * What `tsplc deploy` uploads beside its files. `config` is the build config with paths\n * relative to the release: `st/`, `template.project` and `libraries/`.\n */\nexport const releaseManifestSchema = z.strictObject({\n config: z.record(z.string(), z.unknown()),\n variables: z.array(variableSchema),\n /** The server executable's path in the release, when the project builds one. */\n server: z.string().nonempty().optional(),\n});\nexport type ReleaseManifest = z.infer<typeof releaseManifestSchema>;\n\nexport const deployOptionsSchema = z.strictObject({\n credentials: credentialsSchema,\n /** A full download stops the application; without it only an online change is applied. */\n download: z.boolean(),\n initializeUser: z.boolean(),\n});\nexport type DeployOptions = z.infer<typeof deployOptionsSchema>;\n\n/** Long operations stream one of these per line. */\nexport const eventSchema = z.discriminatedUnion(\"kind\", [\n z.strictObject({ kind: z.literal(\"progress\"), message: z.string() }),\n z.strictObject({ kind: z.literal(\"done\"), result: z.unknown() }),\n z.strictObject({\n kind: z.literal(\"error\"),\n message: z.string(),\n /** The controller has no application from this agent yet, so only a full download can deploy. */\n downloadRequired: z.boolean(),\n }),\n]);\nexport type AgentEvent = z.infer<typeof eventSchema>;\n\nexport const releaseSchema = z.strictObject({\n id: z.string(),\n deployedAt: z.iso.datetime(),\n operation: z.enum([\"download\", \"online-change\"]),\n controllerIds: z.strictObject({ codeId: z.string(), dataId: z.string() }),\n /** The running server executable, relative to the releases directory. */\n server: z.string().optional(),\n});\nexport type Release = z.infer<typeof releaseSchema>;\n\nexport const statusSchema = z.strictObject({\n target: targetSchema.nullable(),\n release: releaseSchema.nullable(),\n server: z.strictObject({ executable: z.string(), running: z.boolean() }).nullable(),\n /** The open login's application state and forced expressions. */\n login: z.strictObject({ state: z.string(), forced: z.array(z.string()) }).nullable(),\n});\nexport type AgentStatus = z.infer<typeof statusSchema>;\n",
|
|
8
8
|
"import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, mkdtemp, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { z } from \"zod\";\nimport { type ReleaseManifest, releaseManifestSchema } from \"./protocol\";\n\n/** Uploaded files are named `files/<path in the release>`. */\nconst filePrefix = \"files/\";\n\nconst releasePath = (name: string) => {\n const path = posix.normalize(name.slice(filePrefix.length));\n if (posix.isAbsolute(path) || path.startsWith(\"..\") || path.includes(\"\\\\\"))\n throw new Error(`Invalid release file name: ${name}`);\n return path;\n};\n\n/** An uploaded release, from `tsplc deploy`'s form. */\nexport const readUpload = async (form: FormData) => {\n const manifest = releaseManifestSchema.parse(JSON.parse(z.string().parse(form.get(\"manifest\"))));\n const files = await Promise.all(\n [...form.entries()]\n .filter(([name]) => name.startsWith(filePrefix))\n .map(async ([name, value]) => ({\n path: releasePath(name),\n content: new Uint8Array(await z.instanceof(File).parse(value).arrayBuffer()),\n })),\n );\n if (manifest.server && !files.some((file) => file.path === manifest.server))\n throw new Error(`The release names a server ${manifest.server} it doesn't contain`);\n return { manifest, files };\n};\n\n/**\n * Stores a release under `releases/<id>`, where the id hashes its contents, so the same\n * upload twice is one release. Each release is complete before it appears.\n */\nexport const saveRelease = async (\n releases: string,\n { manifest, files }: Awaited<ReturnType<typeof readUpload>>,\n) => {\n const hash = createHash(\"sha256\").update(JSON.stringify(manifest));\n for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path)))\n hash.update(file.path).update(createHash(\"sha256\").update(file.content).digest(\"hex\"));\n const id = hash.digest(\"hex\").slice(0, 16);\n const directory = join(releases, id);\n if (!existsSync(directory)) {\n await mkdir(releases, { recursive: true });\n const staging = await mkdtemp(join(releases, \".upload-\"));\n try {\n for (const file of files) {\n await mkdir(dirname(join(staging, file.path)), { recursive: true });\n // Uploads lose their mode; the server must stay executable outside Windows.\n await writeFile(join(staging, file.path), file.content, {\n mode: file.path === manifest.server ? 0o755 : 0o644,\n });\n }\n await writeFile(join(staging, \"manifest.json\"), JSON.stringify(manifest, null, 2));\n await rename(staging, directory);\n } catch (cause) {\n await rm(staging, { recursive: true, force: true });\n throw cause;\n }\n }\n return { id, directory, manifest };\n};\n\nexport const loadRelease = async (\n releases: string,\n id: string,\n): Promise<{ id: string; directory: string; manifest: ReleaseManifest }> => {\n const directory = join(releases, id);\n const manifest = releaseManifestSchema.parse(\n JSON.parse(await readFile(join(directory, \"manifest.json\"), \"utf8\")),\n );\n return { id, directory, manifest };\n};\n",
|
|
9
9
|
"import type { Subprocess } from \"bun\";\nimport { dirname } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nconst healthyWithinMs = 60_000;\n/** Without a health URL, a server that stays up this long counts as started. */\nconst settleMs = 5000;\nconst restartDelayMs = 2000;\n\n/**\n * Runs the deployed server executable, restarting it whenever it exits, and swaps it for\n * another release's. The server reads its own environment and secrets, as it would anywhere.\n */\nexport const createServerSupervisor = (options: {\n /** The server's `/health` route, which answers once it is listening. */\n healthUrl?: string;\n log: (message: string) => void;\n}) => {\n let current: { executable: string; process: Subprocess } | undefined;\n\n const spawn = (executable: string): Subprocess => {\n const child = Bun.spawn([executable], {\n cwd: dirname(executable),\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n onExit: (_, code) => {\n // `stop` and `replace` clear or change `current` before killing a server.\n if (current?.process !== child) return;\n options.log(`Server exited (${code}); restarting it in ${restartDelayMs / 1000} s`);\n void delay(restartDelayMs).then(() => {\n if (current?.process === child) current = { executable, process: spawn(executable) };\n });\n },\n });\n return child;\n };\n\n const start = (executable: string) => {\n current = { executable, process: spawn(executable) };\n return current.process;\n };\n\n const stop = async () => {\n const running = current;\n current = undefined;\n if (!running) return;\n running.process.kill();\n await running.process.exited;\n };\n\n const healthy = async (child: Subprocess) => {\n if (!options.healthUrl) {\n await delay(settleMs);\n return child.exitCode === null;\n }\n const deadline = Date.now() + healthyWithinMs;\n while (Date.now() < deadline && child.exitCode === null) {\n if (\n await fetch(options.healthUrl).then(\n (response) => response.ok,\n () => false,\n )\n )\n return true;\n await delay(1000);\n }\n return false;\n };\n\n return {\n start,\n stop,\n /** Replaces the running server; if the new one doesn't come up, the previous one runs again. */\n replace: async (executable: string) => {\n const previous = current?.executable;\n await stop();\n let failure: unknown;\n const started = await (async () => healthy(start(executable)))().catch((error: unknown) => {\n failure = error;\n return false;\n });\n if (started) return;\n await stop();\n if (previous) start(previous);\n const reason =\n failure instanceof Error\n ? failure.message\n : `it did not start${options.healthUrl ? ` answering ${options.healthUrl}` : \"\"}`;\n throw new Error(\n `The new server failed: ${reason}. ${previous ? \"The previous one is running again.\" : \"\"}`.trim(),\n { cause: failure },\n );\n },\n status: () =>\n current && { executable: current.executable, running: current.process.exitCode === null },\n };\n};\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "3E53D86CAC15F1B264756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsplc/agent",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "The tsPLC plant agent: deploys a program and its server to a controller on the plant network, and holds an engineering login for reads, writes and forces.",
|
package/src/agent.ts
CHANGED
|
@@ -32,8 +32,14 @@ import { createServerSupervisor } from "./server-process";
|
|
|
32
32
|
|
|
33
33
|
const execute = promisify(execFile);
|
|
34
34
|
|
|
35
|
-
/**
|
|
35
|
+
/** The gateway reaches controllers through this Docker network. */
|
|
36
36
|
const network = "tsplc-agent";
|
|
37
|
+
/**
|
|
38
|
+
* Builder containers reach the gateway by name on this internal network, which has no internet.
|
|
39
|
+
* With internet, CODESYS asks a certificate authority about each DLL it loads, without caching
|
|
40
|
+
* the answer, and opening a project takes minutes instead of seconds.
|
|
41
|
+
*/
|
|
42
|
+
const codesysNetwork = "tsplc-agent-codesys";
|
|
37
43
|
const gateway = { host: "tsplc-agent-gateway", port: 1217 };
|
|
38
44
|
const loginContainer = "tsplc-agent-login";
|
|
39
45
|
/** CODESYS reads the controller user from these for one operation; the agent never stores it. */
|
|
@@ -59,25 +65,40 @@ const readJson = async <T>(path: string, schema: z.ZodType<T>) =>
|
|
|
59
65
|
|
|
60
66
|
const docker = (...args: string[]) => execute("docker", args).then(({ stdout }) => stdout.trim());
|
|
61
67
|
|
|
68
|
+
const ensureNetwork = async (name: string, ...options: string[]) => {
|
|
69
|
+
if (!(await docker("network", "ls", "--quiet", "--filter", `name=^${name}$`)))
|
|
70
|
+
await docker("network", "create", ...options, name);
|
|
71
|
+
};
|
|
72
|
+
|
|
62
73
|
/** The gateway container stays up between operations, as a CODESYS gateway service would. */
|
|
63
74
|
const ensureGateway = async () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (await docker("container", "ls", "--quiet", "--filter", `name=^${gateway.host}$`))
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
await ensureNetwork(network);
|
|
76
|
+
await ensureNetwork(codesysNetwork, "--internal");
|
|
77
|
+
if (!(await docker("container", "ls", "--quiet", "--filter", `name=^${gateway.host}$`))) {
|
|
78
|
+
await docker("rm", "--force", gateway.host);
|
|
79
|
+
await docker(
|
|
80
|
+
"run",
|
|
81
|
+
"--detach",
|
|
82
|
+
"--restart",
|
|
83
|
+
"unless-stopped",
|
|
84
|
+
"--platform",
|
|
85
|
+
"linux/amd64",
|
|
86
|
+
"--network",
|
|
87
|
+
network,
|
|
88
|
+
"--name",
|
|
89
|
+
gateway.host,
|
|
90
|
+
gatewayImage,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
// Gateways started by earlier agents are only on `network`.
|
|
94
|
+
const networks = await docker(
|
|
95
|
+
"inspect",
|
|
96
|
+
"--format",
|
|
97
|
+
"{{json .NetworkSettings.Networks}}",
|
|
78
98
|
gateway.host,
|
|
79
|
-
gatewayImage,
|
|
80
99
|
);
|
|
100
|
+
if (!(codesysNetwork in JSON.parse(networks)))
|
|
101
|
+
await docker("network", "connect", codesysNetwork, gateway.host);
|
|
81
102
|
};
|
|
82
103
|
|
|
83
104
|
/** Hands the controller user to CODESYS through the environment for the duration of `run`. */
|
|
@@ -155,7 +176,7 @@ export const createAgent = async (options: AgentOptions) => {
|
|
|
155
176
|
...resolveConfig(
|
|
156
177
|
{
|
|
157
178
|
...release.manifest.config,
|
|
158
|
-
online: { network, gateway, device: target, credentials: credentialNames },
|
|
179
|
+
online: { network: codesysNetwork, gateway, device: target, credentials: credentialNames },
|
|
159
180
|
},
|
|
160
181
|
join(release.directory, "manifest.json"),
|
|
161
182
|
),
|