@superyachttimes/cli 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/nodejs-api-env.d.ts +2 -0
- package/dist/commands/nodejs-api-env.d.ts.map +1 -0
- package/dist/commands/nodejs-api-env.js +152 -0
- package/dist/commands/nodejs-api-env.js.map +1 -0
- package/dist/commands/nodejs-api-hosts.d.ts +20 -0
- package/dist/commands/nodejs-api-hosts.d.ts.map +1 -0
- package/dist/commands/nodejs-api-hosts.js +48 -0
- package/dist/commands/nodejs-api-hosts.js.map +1 -0
- package/dist/commands/recreate-nodejs-api.d.ts +6 -0
- package/dist/commands/recreate-nodejs-api.d.ts.map +1 -1
- package/dist/commands/recreate-nodejs-api.js +22 -106
- package/dist/commands/recreate-nodejs-api.js.map +1 -1
- package/dist/commands/rollback-nodejs-api.d.ts +6 -0
- package/dist/commands/rollback-nodejs-api.d.ts.map +1 -0
- package/dist/commands/rollback-nodejs-api.js +62 -0
- package/dist/commands/rollback-nodejs-api.js.map +1 -0
- package/dist/github/packages.d.ts +7 -0
- package/dist/github/packages.d.ts.map +1 -0
- package/dist/github/packages.js +23 -0
- package/dist/github/packages.js.map +1 -0
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/portainer/api.d.ts +7 -0
- package/dist/portainer/api.d.ts.map +1 -1
- package/dist/portainer/api.js +34 -0
- package/dist/portainer/api.js.map +1 -1
- package/dist/portainer/env.d.ts +30 -0
- package/dist/portainer/env.d.ts.map +1 -0
- package/dist/portainer/env.js +88 -0
- package/dist/portainer/env.js.map +1 -0
- package/dist/portainer/image.d.ts +22 -0
- package/dist/portainer/image.d.ts.map +1 -0
- package/dist/portainer/image.js +42 -0
- package/dist/portainer/image.js.map +1 -0
- package/dist/portainer/recreate.d.ts +18 -0
- package/dist/portainer/recreate.d.ts.map +1 -0
- package/dist/portainer/recreate.js +143 -0
- package/dist/portainer/recreate.js.map +1 -0
- package/dist/portainer/urls.d.ts +2 -0
- package/dist/portainer/urls.d.ts.map +1 -1
- package/dist/portainer/urls.js +2 -0
- package/dist/portainer/urls.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs-api-env.d.ts","sourceRoot":"","sources":["../../src/commands/nodejs-api-env.ts"],"names":[],"mappings":"AAsJA,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhE"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
2
|
+
import { loadConfig } from "../config.js";
|
|
3
|
+
import * as portainer from "../portainer/api.js";
|
|
4
|
+
import { applyEnvChanges, assertValidKey, envValue, hasChanges, parseAssignments, summariseEnv, } from "../portainer/env.js";
|
|
5
|
+
import { recreateContainer } from "../portainer/recreate.js";
|
|
6
|
+
const USAGE = `Usage:
|
|
7
|
+
syt-cli nodejs-api-env list [--show KEY]
|
|
8
|
+
syt-cli nodejs-api-env set KEY=VALUE [KEY=VALUE...] [--dry-run] [--yes]
|
|
9
|
+
syt-cli nodejs-api-env unset KEY [KEY...] [--dry-run] [--yes]
|
|
10
|
+
|
|
11
|
+
Changes recreate each api-nodejs container one host at a time, with the same
|
|
12
|
+
image (no pull). Existing values are never printed except with list --show.`;
|
|
13
|
+
const hostLabel = (instance) => new URL(instance.portainerUrl).hostname.split(".")[0];
|
|
14
|
+
async function readEnv(instance) {
|
|
15
|
+
const container = await portainer.getContainer({
|
|
16
|
+
portainerUrl: instance.portainerUrl,
|
|
17
|
+
portainerEndpointId: instance.portainerEndpointId,
|
|
18
|
+
portainerApiKey: instance.portainerApiKey,
|
|
19
|
+
portainerContainerName: instance.portainerContainerName,
|
|
20
|
+
});
|
|
21
|
+
return container.Config.Env ?? [];
|
|
22
|
+
}
|
|
23
|
+
async function list(instances, show) {
|
|
24
|
+
const hosts = await Promise.all(instances.map(async (i) => ({ host: hostLabel(i), env: await readEnv(i) })));
|
|
25
|
+
if (show) {
|
|
26
|
+
for (const h of hosts) {
|
|
27
|
+
const value = envValue(h.env, show);
|
|
28
|
+
console.log(`${h.host} ${show}=${value === undefined ? "(not set)" : value}`);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const row of summariseEnv(hosts)) {
|
|
33
|
+
const note = row.status === "missing"
|
|
34
|
+
? ` missing on ${row.missingOn.join(", ")}`
|
|
35
|
+
: row.status === "differs"
|
|
36
|
+
? " differs between hosts"
|
|
37
|
+
: "";
|
|
38
|
+
console.log(`${row.name}${note}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function change(instances, changes, opts) {
|
|
42
|
+
const plan = await Promise.all(instances.map(async (instance) => {
|
|
43
|
+
const { outcomes } = applyEnvChanges(await readEnv(instance), changes);
|
|
44
|
+
return { instance, outcomes };
|
|
45
|
+
}));
|
|
46
|
+
for (const { instance, outcomes } of plan) {
|
|
47
|
+
const parts = Object.entries(outcomes).map(([k, o]) => `${k} ${o}`);
|
|
48
|
+
console.log(`${hostLabel(instance)}: ${parts.join(", ")}`);
|
|
49
|
+
}
|
|
50
|
+
const todo = plan.filter((p) => hasChanges(p.outcomes));
|
|
51
|
+
if (todo.length === 0) {
|
|
52
|
+
console.log("\nNothing to change.");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (opts.dryRun) {
|
|
56
|
+
console.log(`\nDry run: ${todo.length} host(s) would be recreated.`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!opts.yes) {
|
|
60
|
+
const ok = await confirm({
|
|
61
|
+
message: `Recreate ${todo.length} host(s) one at a time (same image, no pull)?`,
|
|
62
|
+
default: false,
|
|
63
|
+
});
|
|
64
|
+
if (!ok) {
|
|
65
|
+
console.log("Aborted.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const [i, { instance }] of todo.entries()) {
|
|
70
|
+
const prefix = `[${hostLabel(instance)}]`;
|
|
71
|
+
const log = (msg) => console.log(`${prefix} ${msg}`);
|
|
72
|
+
try {
|
|
73
|
+
await recreateContainer(instance, {
|
|
74
|
+
pull: false,
|
|
75
|
+
transformEnv: (env) => applyEnvChanges(env, changes).env,
|
|
76
|
+
log,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
throw new Error(`${prefix} failed: ${err.message}. ${i}/${todo.length} host(s) were changed; the rest were not touched.`);
|
|
81
|
+
}
|
|
82
|
+
const after = applyEnvChanges(await readEnv(instance), changes).outcomes;
|
|
83
|
+
if (hasChanges(after)) {
|
|
84
|
+
throw new Error(`${prefix} recreated, but the env does not match the requested change`);
|
|
85
|
+
}
|
|
86
|
+
log("Done.");
|
|
87
|
+
}
|
|
88
|
+
console.log(`\n${todo.length} host(s) updated.`);
|
|
89
|
+
}
|
|
90
|
+
function parseFlags(args) {
|
|
91
|
+
const rest = [];
|
|
92
|
+
let dryRun = false;
|
|
93
|
+
let yes = false;
|
|
94
|
+
let show;
|
|
95
|
+
for (let i = 0; i < args.length; i++) {
|
|
96
|
+
const a = args[i];
|
|
97
|
+
if (a === "--dry-run")
|
|
98
|
+
dryRun = true;
|
|
99
|
+
else if (a === "--yes" || a === "-y")
|
|
100
|
+
yes = true;
|
|
101
|
+
else if (a === "--show")
|
|
102
|
+
show = args[++i];
|
|
103
|
+
else
|
|
104
|
+
rest.push(a);
|
|
105
|
+
}
|
|
106
|
+
return { rest, dryRun, yes, show };
|
|
107
|
+
}
|
|
108
|
+
async function promptForArgs() {
|
|
109
|
+
const action = await select({
|
|
110
|
+
message: "What do you want to do?",
|
|
111
|
+
choices: [
|
|
112
|
+
{ name: "List variable names", value: "list" },
|
|
113
|
+
{ name: "Show one variable's value", value: "show" },
|
|
114
|
+
{ name: "Set a variable", value: "set" },
|
|
115
|
+
{ name: "Unset a variable", value: "unset" },
|
|
116
|
+
],
|
|
117
|
+
});
|
|
118
|
+
if (action === "list")
|
|
119
|
+
return ["list"];
|
|
120
|
+
if (action === "show")
|
|
121
|
+
return ["list", "--show", await input({ message: "Variable name" })];
|
|
122
|
+
if (action === "set")
|
|
123
|
+
return ["set", await input({ message: "KEY=VALUE" })];
|
|
124
|
+
return ["unset", await input({ message: "Variable name" })];
|
|
125
|
+
}
|
|
126
|
+
export async function nodejsApiEnv(argv) {
|
|
127
|
+
const args = argv.length > 0 ? argv : await promptForArgs();
|
|
128
|
+
const [sub, ...restArgs] = args;
|
|
129
|
+
const { rest, dryRun, yes, show } = parseFlags(restArgs);
|
|
130
|
+
const instances = loadConfig().nodejsApi;
|
|
131
|
+
switch (sub) {
|
|
132
|
+
case "list":
|
|
133
|
+
if (show !== undefined)
|
|
134
|
+
assertValidKey(show);
|
|
135
|
+
await list(instances, show);
|
|
136
|
+
return;
|
|
137
|
+
case "set":
|
|
138
|
+
if (rest.length === 0)
|
|
139
|
+
throw new Error(`Nothing to set.\n\n${USAGE}`);
|
|
140
|
+
await change(instances, { set: parseAssignments(rest), unset: [] }, { dryRun, yes });
|
|
141
|
+
return;
|
|
142
|
+
case "unset":
|
|
143
|
+
if (rest.length === 0)
|
|
144
|
+
throw new Error(`Nothing to unset.\n\n${USAGE}`);
|
|
145
|
+
rest.forEach(assertValidKey);
|
|
146
|
+
await change(instances, { set: {}, unset: rest }, { dryRun, yes });
|
|
147
|
+
return;
|
|
148
|
+
default:
|
|
149
|
+
throw new Error(USAGE);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=nodejs-api-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs-api-env.js","sourceRoot":"","sources":["../../src/commands/nodejs-api-env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PortainerInstance } from "../config.js";
|
|
2
|
+
export declare const hostLabel: (instance: PortainerInstance) => string;
|
|
3
|
+
export interface HostImage {
|
|
4
|
+
instance: PortainerInstance;
|
|
5
|
+
host: string;
|
|
6
|
+
image: string;
|
|
7
|
+
repo: string;
|
|
8
|
+
tag: string;
|
|
9
|
+
}
|
|
10
|
+
/** The image each api-nodejs container currently runs. */
|
|
11
|
+
export declare function currentImages(instances: PortainerInstance[]): Promise<HostImage[]>;
|
|
12
|
+
/** The single repository all hosts run; throws when they differ. */
|
|
13
|
+
export declare function sharedRepo(hosts: HostImage[]): string;
|
|
14
|
+
/**
|
|
15
|
+
* Pull and recreate every container one host at a time, so the API never
|
|
16
|
+
* loses more than one host. Stops at the first failure (its old container is
|
|
17
|
+
* restored). `image` overrides the image; omit it to re-pull the current one.
|
|
18
|
+
*/
|
|
19
|
+
export declare function rollOut(instances: PortainerInstance[], image?: string): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=nodejs-api-hosts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs-api-hosts.d.ts","sourceRoot":"","sources":["../../src/commands/nodejs-api-hosts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAKtD,eAAO,MAAM,SAAS,GAAI,UAAU,iBAAiB,WACE,CAAC;AAExD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,0DAA0D;AAC1D,wBAAsB,aAAa,CAAC,SAAS,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAaxF;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAQrD;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB3F"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as portainer from "../portainer/api.js";
|
|
2
|
+
import { splitImage } from "../portainer/image.js";
|
|
3
|
+
import { recreateContainer } from "../portainer/recreate.js";
|
|
4
|
+
export const hostLabel = (instance) => new URL(instance.portainerUrl).hostname.split(".")[0];
|
|
5
|
+
/** The image each api-nodejs container currently runs. */
|
|
6
|
+
export async function currentImages(instances) {
|
|
7
|
+
return Promise.all(instances.map(async (instance) => {
|
|
8
|
+
const container = await portainer.getContainer({
|
|
9
|
+
portainerUrl: instance.portainerUrl,
|
|
10
|
+
portainerEndpointId: instance.portainerEndpointId,
|
|
11
|
+
portainerApiKey: instance.portainerApiKey,
|
|
12
|
+
portainerContainerName: instance.portainerContainerName,
|
|
13
|
+
});
|
|
14
|
+
const image = container.Config.Image;
|
|
15
|
+
return { instance, host: hostLabel(instance), image, ...splitImage(image) };
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
/** The single repository all hosts run; throws when they differ. */
|
|
19
|
+
export function sharedRepo(hosts) {
|
|
20
|
+
const repos = new Set(hosts.map((h) => h.repo));
|
|
21
|
+
if (repos.size !== 1) {
|
|
22
|
+
throw new Error(`hosts run different images: ${hosts.map((h) => `${h.host}=${h.image}`).join(", ")}`);
|
|
23
|
+
}
|
|
24
|
+
return [...repos][0];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Pull and recreate every container one host at a time, so the API never
|
|
28
|
+
* loses more than one host. Stops at the first failure (its old container is
|
|
29
|
+
* restored). `image` overrides the image; omit it to re-pull the current one.
|
|
30
|
+
*/
|
|
31
|
+
export async function rollOut(instances, image) {
|
|
32
|
+
const total = instances.length;
|
|
33
|
+
for (const [i, instance] of instances.entries()) {
|
|
34
|
+
const prefix = `[${instance.portainerUrl} (${instance.portainerContainerName})]`;
|
|
35
|
+
const log = (msg) => console.log(`${prefix} ${msg}`);
|
|
36
|
+
log("Starting...");
|
|
37
|
+
try {
|
|
38
|
+
await recreateContainer(instance, { pull: true, image, log });
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
throw new Error(`${prefix} failed: ${err.message}. ${i}/${total} instance(s) were recreated; the rest were not touched.`);
|
|
42
|
+
}
|
|
43
|
+
log("Done.");
|
|
44
|
+
}
|
|
45
|
+
console.log();
|
|
46
|
+
console.log(`All ${total} instance(s) completed successfully.`);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=nodejs-api-hosts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs-api-hosts.js","sourceRoot":"","sources":["../../src/commands/nodejs-api-hosts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,SAAS,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAA2B,EAAE,EAAE,CACvD,IAAI,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAUxD,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAA8B;IAChE,OAAO,OAAO,CAAC,GAAG,CAChB,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC/B,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC;YAC7C,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;YACjD,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,sBAAsB,EAAE,QAAQ,CAAC,sBAAsB;SACxD,CAAC,CAAC;QACH,MAAM,KAAK,GAAW,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;QAC7C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9E,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,+BAA+B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACrF,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,SAA8B,EAAE,KAAc;IAC1E,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC;IAC/B,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAAC,sBAAsB,IAAI,CAAC;QACjF,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC;QAC7D,GAAG,CAAC,aAAa,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,iBAAiB,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,YAAa,GAAa,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,yDAAyD,CACpH,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,sCAAsC,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull and recreate every api-nodejs container, one host at a time. When any
|
|
3
|
+
* host is pinned to a tag other than `latest` (e.g. after a rollback), ask
|
|
4
|
+
* whether to move all hosts back to `latest`; otherwise the pinned tag is
|
|
5
|
+
* re-pulled as is.
|
|
6
|
+
*/
|
|
1
7
|
export declare function recreateNodejsApi(): Promise<void>;
|
|
2
8
|
//# sourceMappingURL=recreate-nodejs-api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recreate-nodejs-api.d.ts","sourceRoot":"","sources":["../../src/commands/recreate-nodejs-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recreate-nodejs-api.d.ts","sourceRoot":"","sources":["../../src/commands/recreate-nodejs-api.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBvD"}
|
|
@@ -1,113 +1,29 @@
|
|
|
1
|
+
import { confirm } from "@inquirer/prompts";
|
|
1
2
|
import { loadConfig } from "../config.js";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
...config,
|
|
10
|
-
HostConfig: hostConfig,
|
|
11
|
-
name,
|
|
12
|
-
NetworkingConfig: {
|
|
13
|
-
EndpointsConfig: networks,
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
async function recreateInstance(instance, log) {
|
|
18
|
-
const { portainerUrl, portainerEndpointId, portainerApiKey, portainerRegistryAuth, portainerContainerName, } = instance;
|
|
19
|
-
const common = { portainerUrl, portainerEndpointId, portainerApiKey };
|
|
20
|
-
// [Step 1] Get the container information
|
|
21
|
-
log("[Step 1] Get the container information");
|
|
22
|
-
const container = await portainer.getContainer({
|
|
23
|
-
...common,
|
|
24
|
-
portainerContainerName,
|
|
25
|
-
});
|
|
26
|
-
const oldContainerId = container.Id;
|
|
27
|
-
// [Step 2] Pull the latest image
|
|
28
|
-
log("[Step 2] Pull the latest image");
|
|
29
|
-
await portainer.pullImage({
|
|
30
|
-
...common,
|
|
31
|
-
portainerRegistryAuth,
|
|
32
|
-
image: container.Config.Image,
|
|
33
|
-
});
|
|
34
|
-
// [Step 3] Stop the current container
|
|
35
|
-
log("[Step 3] Stop the current container");
|
|
36
|
-
await portainer.stopContainer({
|
|
37
|
-
...common,
|
|
38
|
-
portainerContainerId: oldContainerId,
|
|
39
|
-
});
|
|
40
|
-
// [Step 4] Rename the current container
|
|
41
|
-
log("[Step 4] Rename the current container");
|
|
42
|
-
await portainer.renameContainer({
|
|
43
|
-
...common,
|
|
44
|
-
portainerContainerId: oldContainerId,
|
|
45
|
-
name: `${portainerContainerName}-old`,
|
|
46
|
-
});
|
|
47
|
-
// [Step 5] Create a new container
|
|
48
|
-
log("[Step 5] Create a new container");
|
|
49
|
-
const newContainerConfig = buildNewContainerConfig(container, portainerContainerName);
|
|
50
|
-
const newContainer = await portainer.createContainer({
|
|
51
|
-
...common,
|
|
52
|
-
name: portainerContainerName,
|
|
53
|
-
config: newContainerConfig,
|
|
54
|
-
});
|
|
55
|
-
const newContainerId = newContainer.Id;
|
|
56
|
-
// [Step 6] Connect to networks
|
|
57
|
-
log("[Step 6] Connect to networks");
|
|
58
|
-
const networks = (container.NetworkSettings?.Networks ?? {});
|
|
59
|
-
await Promise.all(Object.keys(networks).map((networkName) => portainer.connectContainerToNetwork({
|
|
60
|
-
...common,
|
|
61
|
-
portainerContainerId: newContainerId,
|
|
62
|
-
networkName,
|
|
63
|
-
})));
|
|
64
|
-
// [Step 7] Start the new container
|
|
65
|
-
log("[Step 7] Start the new container");
|
|
66
|
-
await portainer.startContainer({
|
|
67
|
-
...common,
|
|
68
|
-
portainerContainerId: newContainerId,
|
|
69
|
-
});
|
|
70
|
-
// [Step 8] Update the resource controller
|
|
71
|
-
log("[Step 8] Update the resource controller");
|
|
72
|
-
const resourceControl = container.Portainer?.ResourceControl;
|
|
73
|
-
if (resourceControl) {
|
|
74
|
-
await portainer.updateResourceControl({
|
|
75
|
-
portainerUrl,
|
|
76
|
-
portainerApiKey,
|
|
77
|
-
resourceControlId: resourceControl.Id,
|
|
78
|
-
data: {
|
|
79
|
-
AdministratorsOnly: resourceControl.AdministratorsOnly,
|
|
80
|
-
Public: resourceControl.Public,
|
|
81
|
-
Users: resourceControl.UserAccesses.map((a) => a.UserId),
|
|
82
|
-
Teams: resourceControl.TeamAccesses,
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
// [Step 9] Delete the old container
|
|
87
|
-
log("[Step 9] Delete the old container");
|
|
88
|
-
await portainer.deleteContainer({
|
|
89
|
-
...common,
|
|
90
|
-
portainerContainerId: oldContainerId,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
3
|
+
import { currentImages, rollOut, sharedRepo } from "./nodejs-api-hosts.js";
|
|
4
|
+
/**
|
|
5
|
+
* Pull and recreate every api-nodejs container, one host at a time. When any
|
|
6
|
+
* host is pinned to a tag other than `latest` (e.g. after a rollback), ask
|
|
7
|
+
* whether to move all hosts back to `latest`; otherwise the pinned tag is
|
|
8
|
+
* re-pulled as is.
|
|
9
|
+
*/
|
|
93
10
|
export async function recreateNodejsApi() {
|
|
94
11
|
const config = loadConfig();
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
console.
|
|
12
|
+
const hosts = await currentImages(config.nodejsApi);
|
|
13
|
+
const pinned = hosts.filter((h) => h.tag !== "latest");
|
|
14
|
+
let image;
|
|
15
|
+
if (pinned.length > 0) {
|
|
16
|
+
console.log("Not on latest:");
|
|
17
|
+
for (const h of pinned)
|
|
18
|
+
console.log(` ${h.host} ${h.tag}`);
|
|
19
|
+
const back = await confirm({ message: "Switch back to latest?", default: true });
|
|
20
|
+
if (back) {
|
|
21
|
+
image = `${sharedRepo(hosts)}:latest`;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.log("Keeping the current tag(s); re-pulling them as they are.");
|
|
108
25
|
}
|
|
109
|
-
throw new Error(`${failed.length}/${results.length} instance(s) failed`);
|
|
110
26
|
}
|
|
111
|
-
|
|
27
|
+
await rollOut(config.nodejsApi, image);
|
|
112
28
|
}
|
|
113
29
|
//# sourceMappingURL=recreate-nodejs-api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recreate-nodejs-api.js","sourceRoot":"","sources":["../../src/commands/recreate-nodejs-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"recreate-nodejs-api.js","sourceRoot":"","sources":["../../src/commands/recreate-nodejs-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;IAEvD,IAAI,KAAyB,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACjF,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Put every api-nodejs container on one release tag (e.g. to roll back),
|
|
3
|
+
* chosen from the tags in GHCR or passed as an argument. One host at a time.
|
|
4
|
+
*/
|
|
5
|
+
export declare function rollbackNodejsApi(args?: string[]): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=rollback-nodejs-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback-nodejs-api.d.ts","sourceRoot":"","sources":["../../src/commands/rollback-nodejs-api.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA6C1E"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { confirm, select } from "@inquirer/prompts";
|
|
2
|
+
import { loadConfig } from "../config.js";
|
|
3
|
+
import { listPackageVersions } from "../github/packages.js";
|
|
4
|
+
import { releaseTags } from "../portainer/image.js";
|
|
5
|
+
import { currentImages, rollOut, sharedRepo } from "./nodejs-api-hosts.js";
|
|
6
|
+
const MENU_SIZE = 15;
|
|
7
|
+
/** `ghcr.io/<org>/<name>` → { org, name }. */
|
|
8
|
+
function ghcrPackage(repo) {
|
|
9
|
+
const match = repo.match(/^ghcr\.io\/([^/]+)\/(.+)$/);
|
|
10
|
+
if (!match)
|
|
11
|
+
throw new Error(`${repo} is not a ghcr.io image; can't list its tags`);
|
|
12
|
+
return { org: match[1], name: match[2] };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Put every api-nodejs container on one release tag (e.g. to roll back),
|
|
16
|
+
* chosen from the tags in GHCR or passed as an argument. One host at a time.
|
|
17
|
+
*/
|
|
18
|
+
export async function rollbackNodejsApi(args = []) {
|
|
19
|
+
const config = loadConfig();
|
|
20
|
+
const hosts = await currentImages(config.nodejsApi);
|
|
21
|
+
const repo = sharedRepo(hosts);
|
|
22
|
+
console.log("Live now:");
|
|
23
|
+
for (const h of hosts)
|
|
24
|
+
console.log(` ${h.host} ${h.tag}`);
|
|
25
|
+
console.log();
|
|
26
|
+
const { org, name } = ghcrPackage(repo);
|
|
27
|
+
const { tags, latest } = releaseTags(await listPackageVersions(org, name));
|
|
28
|
+
if (tags.length === 0)
|
|
29
|
+
throw new Error(`no release tags found for ${org}/${name}`);
|
|
30
|
+
const live = new Set(hosts.map((h) => h.tag));
|
|
31
|
+
let tag = args[0];
|
|
32
|
+
if (tag) {
|
|
33
|
+
if (tag !== "latest" && !tags.includes(tag)) {
|
|
34
|
+
throw new Error(`${tag} is not one of the latest release tags (${tags.slice(0, 5).join(", ")}, …)`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const label = (t) => {
|
|
39
|
+
const marks = [live.has(t) && "live", t === latest && "latest"].filter(Boolean);
|
|
40
|
+
return marks.length ? `${t} (${marks.join(", ")})` : t;
|
|
41
|
+
};
|
|
42
|
+
tag = await select({
|
|
43
|
+
message: "Roll the API to which release?",
|
|
44
|
+
choices: [
|
|
45
|
+
{ name: `latest${latest ? ` → ${latest}` : ""}${live.has("latest") ? " (live)" : ""}`, value: "latest" },
|
|
46
|
+
...tags.slice(0, MENU_SIZE).map((t) => ({ name: label(t), value: t })),
|
|
47
|
+
],
|
|
48
|
+
pageSize: MENU_SIZE + 1,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const image = `${repo}:${tag}`;
|
|
52
|
+
const ok = await confirm({
|
|
53
|
+
message: `Roll ${hosts.length} host(s) to ${image}?`,
|
|
54
|
+
default: false,
|
|
55
|
+
});
|
|
56
|
+
if (!ok) {
|
|
57
|
+
console.log("Aborted; nothing changed.");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
await rollOut(config.nodejsApi, image);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=rollback-nodejs-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback-nodejs-api.js","sourceRoot":"","sources":["../../src/commands/rollback-nodejs-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAE3E,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,8CAA8C;AAC9C,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACtD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,8CAA8C,CAAC,CAAC;IACnF,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAiB,EAAE;IACzD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAE/B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC;IAEnF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,2CAA2C,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtG,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE;YAC1B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,KAAK,MAAM,IAAI,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC,CAAC;QACF,GAAG,GAAG,MAAM,MAAM,CAAC;YACjB,OAAO,EAAE,gCAAgC;YACzC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;gBACzG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;aACvE;YACD,QAAQ,EAAE,SAAS,GAAG,CAAC;SACxB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;IAC/B,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC;QACvB,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,eAAe,KAAK,GAAG;QACpD,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PackageVersion } from "../portainer/image.js";
|
|
2
|
+
/**
|
|
3
|
+
* The newest 100 versions of a GHCR container package, via the local `gh`
|
|
4
|
+
* login (needs the read:packages scope). Newest first.
|
|
5
|
+
*/
|
|
6
|
+
export declare function listPackageVersions(org: string, name: string): Promise<PackageVersion[]>;
|
|
7
|
+
//# sourceMappingURL=packages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packages.d.ts","sourceRoot":"","sources":["../../src/github/packages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,EAAE,CAAC,CAe3B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const run = promisify(execFile);
|
|
4
|
+
/**
|
|
5
|
+
* The newest 100 versions of a GHCR container package, via the local `gh`
|
|
6
|
+
* login (needs the read:packages scope). Newest first.
|
|
7
|
+
*/
|
|
8
|
+
export async function listPackageVersions(org, name) {
|
|
9
|
+
const path = `/orgs/${encodeURIComponent(org)}/packages/container/${encodeURIComponent(name)}/versions?per_page=100`;
|
|
10
|
+
try {
|
|
11
|
+
const { stdout } = await run("gh", ["api", path], { maxBuffer: 20 * 1024 * 1024 });
|
|
12
|
+
return JSON.parse(stdout);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
const e = err;
|
|
16
|
+
if (e.code === "ENOENT") {
|
|
17
|
+
throw new Error("the GitHub CLI (gh) is not installed; install it and run `gh auth login`");
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`could not list tags for ${org}/${name} via gh: ${(e.stderr || e.message).trim()}. ` +
|
|
20
|
+
"Run `gh auth login` (or `gh auth refresh -s read:packages`) and try again.");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=packages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packages.js","sourceRoot":"","sources":["../../src/github/packages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAW,EACX,IAAY;IAEZ,MAAM,IAAI,GAAG,SAAS,kBAAkB,CAAC,GAAG,CAAC,uBAAuB,kBAAkB,CAAC,IAAI,CAAC,wBAAwB,CAAC;IACrH,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAqB,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,GAAkD,CAAC;QAC7D,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,IAAI,KAAK,CACb,2BAA2B,GAAG,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI;YAClF,4EAA4E,CAC/E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,9 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { select } from "@inquirer/prompts";
|
|
6
6
|
import { collapseLastModified } from "./commands/collapse-last-modified.js";
|
|
7
7
|
import { createApiKey } from "./commands/create-api-key.js";
|
|
8
|
+
import { nodejsApiEnv } from "./commands/nodejs-api-env.js";
|
|
8
9
|
import { recreateNodejsApi } from "./commands/recreate-nodejs-api.js";
|
|
10
|
+
import { rollbackNodejsApi } from "./commands/rollback-nodejs-api.js";
|
|
9
11
|
import { restartEc2 } from "./commands/restart-ec2.js";
|
|
10
12
|
import { syncEc2IpsToCloudflare } from "./commands/sync-ec2-ips-cloudflare.js";
|
|
11
13
|
import { syncEc2ToRoute53 } from "./commands/sync-ec2-route53.js";
|
|
@@ -19,7 +21,9 @@ function printHelp() {
|
|
|
19
21
|
console.log("Commands:");
|
|
20
22
|
console.log(" collapse-last-modified Collapse last-modified yacht likes");
|
|
21
23
|
console.log(" create-api-key Create a new API key");
|
|
24
|
+
console.log(" nodejs-api-env List, set or unset env vars on the Node.js API containers");
|
|
22
25
|
console.log(" recreate-nodejs-api Recreate Node.js API containers via Portainer");
|
|
26
|
+
console.log(" rollback-nodejs-api Roll the Node.js API containers to a chosen release tag");
|
|
23
27
|
console.log(" restart-ec2 Restart (reboot) one or more EC2 servers");
|
|
24
28
|
console.log(" sync-ec2-ips-cloudflare Sync EC2 egress IPs to a Cloudflare WAF rule");
|
|
25
29
|
console.log(" sync-ec2-route53 Sync running EC2 public IPs to Route53 infra records");
|
|
@@ -38,7 +42,7 @@ if (args.includes("--help") || args.includes("-h")) {
|
|
|
38
42
|
printHelp();
|
|
39
43
|
process.exit(0);
|
|
40
44
|
}
|
|
41
|
-
async function runCommand(cmd) {
|
|
45
|
+
async function runCommand(cmd, cmdArgs = []) {
|
|
42
46
|
switch (cmd) {
|
|
43
47
|
case "collapse-last-modified":
|
|
44
48
|
await collapseLastModified();
|
|
@@ -46,9 +50,15 @@ async function runCommand(cmd) {
|
|
|
46
50
|
case "create-api-key":
|
|
47
51
|
await createApiKey();
|
|
48
52
|
break;
|
|
53
|
+
case "nodejs-api-env":
|
|
54
|
+
await nodejsApiEnv(cmdArgs);
|
|
55
|
+
break;
|
|
49
56
|
case "recreate-nodejs-api":
|
|
50
57
|
await recreateNodejsApi();
|
|
51
58
|
break;
|
|
59
|
+
case "rollback-nodejs-api":
|
|
60
|
+
await rollbackNodejsApi(cmdArgs);
|
|
61
|
+
break;
|
|
52
62
|
case "restart-ec2":
|
|
53
63
|
await restartEc2();
|
|
54
64
|
break;
|
|
@@ -78,11 +88,21 @@ async function showMenu() {
|
|
|
78
88
|
value: "create-api-key",
|
|
79
89
|
description: "Create a new API key",
|
|
80
90
|
},
|
|
91
|
+
{
|
|
92
|
+
name: "nodejs-api-env",
|
|
93
|
+
value: "nodejs-api-env",
|
|
94
|
+
description: "List, set or unset env vars on the Node.js API containers",
|
|
95
|
+
},
|
|
81
96
|
{
|
|
82
97
|
name: "recreate-nodejs-api",
|
|
83
98
|
value: "recreate-nodejs-api",
|
|
84
99
|
description: "Recreate Node.js API containers via Portainer",
|
|
85
100
|
},
|
|
101
|
+
{
|
|
102
|
+
name: "rollback-nodejs-api",
|
|
103
|
+
value: "rollback-nodejs-api",
|
|
104
|
+
description: "Roll the Node.js API containers to a chosen release tag",
|
|
105
|
+
},
|
|
86
106
|
{
|
|
87
107
|
name: "Restart EC2 servers",
|
|
88
108
|
value: "restart-ec2",
|
|
@@ -103,7 +123,7 @@ async function showMenu() {
|
|
|
103
123
|
await runCommand(chosen);
|
|
104
124
|
}
|
|
105
125
|
if (command) {
|
|
106
|
-
runCommand(command).catch((err) => {
|
|
126
|
+
runCommand(command, args.slice(1)).catch((err) => {
|
|
107
127
|
console.error(`Error: ${err.message}`);
|
|
108
128
|
process.exit(1);
|
|
109
129
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAC7D,CAAC;AAEF,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,gFAAgF,CAAC,CAAC;IAC9F,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAExB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnD,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAW;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/portainer/api.d.ts
CHANGED
|
@@ -61,4 +61,11 @@ export declare function deleteContainer(opts: {
|
|
|
61
61
|
portainerApiKey: string;
|
|
62
62
|
portainerContainerId: string;
|
|
63
63
|
}): Promise<void>;
|
|
64
|
+
export declare function execInContainer(opts: {
|
|
65
|
+
portainerUrl: string;
|
|
66
|
+
portainerEndpointId: string;
|
|
67
|
+
portainerApiKey: string;
|
|
68
|
+
portainerContainerId: string;
|
|
69
|
+
cmd: string[];
|
|
70
|
+
}): Promise<string>;
|
|
64
71
|
//# sourceMappingURL=api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/portainer/api.ts"],"names":[],"mappings":"AA0CA,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;CAEhC,GAAG,OAAO,CAAC,GAAG,CAAC,CASf;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAGD,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CAEjB,GAAG,OAAO,CAAC,GAAG,CAAC,CASf;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAahB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE;QACJ,kBAAkB,EAAE,OAAO,CAAC;QAC5B,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,EAAE,OAAO,EAAE,CAAC;KAClB,CAAC;CACH,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB"}
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/portainer/api.ts"],"names":[],"mappings":"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"}
|
package/dist/portainer/api.js
CHANGED
|
@@ -71,4 +71,38 @@ export async function updateResourceControl(opts) {
|
|
|
71
71
|
export async function deleteContainer(opts) {
|
|
72
72
|
await request(urls.containerDeleteUrl(opts.portainerUrl, opts.portainerEndpointId, opts.portainerContainerId), { method: "DELETE", apiKey: opts.portainerApiKey });
|
|
73
73
|
}
|
|
74
|
+
// Docker multiplexes stdout/stderr when the exec has no TTY: each frame is an
|
|
75
|
+
// 8-byte header (stream type, 3 zero bytes, uint32 BE length) followed by the
|
|
76
|
+
// payload. Concatenate the payloads.
|
|
77
|
+
function demultiplex(buf) {
|
|
78
|
+
const parts = [];
|
|
79
|
+
let offset = 0;
|
|
80
|
+
while (offset + 8 <= buf.length) {
|
|
81
|
+
const size = buf.readUInt32BE(offset + 4);
|
|
82
|
+
parts.push(buf.subarray(offset + 8, offset + 8 + size));
|
|
83
|
+
offset += 8 + size;
|
|
84
|
+
}
|
|
85
|
+
return offset === 0 ? buf.toString("utf-8") : Buffer.concat(parts).toString("utf-8");
|
|
86
|
+
}
|
|
87
|
+
export async function execInContainer(opts) {
|
|
88
|
+
const exec = (await request(urls.containerExecUrl(opts.portainerUrl, opts.portainerEndpointId, opts.portainerContainerId), {
|
|
89
|
+
method: "POST",
|
|
90
|
+
apiKey: opts.portainerApiKey,
|
|
91
|
+
body: { AttachStdout: true, AttachStderr: true, Cmd: opts.cmd },
|
|
92
|
+
}));
|
|
93
|
+
const url = urls.execStartUrl(opts.portainerUrl, opts.portainerEndpointId, exec.Id);
|
|
94
|
+
const res = await fetch(url, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: {
|
|
97
|
+
"X-API-Key": opts.portainerApiKey,
|
|
98
|
+
"Content-Type": "application/json",
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify({ Detach: false, Tty: false }),
|
|
101
|
+
});
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
const text = await res.text().catch(() => "");
|
|
104
|
+
throw new Error(`Portainer API error: POST ${url} → ${res.status} ${res.statusText}${text ? `\n${text}` : ""}`);
|
|
105
|
+
}
|
|
106
|
+
return demultiplex(Buffer.from(await res.arrayBuffer()));
|
|
107
|
+
}
|
|
74
108
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/portainer/api.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/portainer/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type EnvOutcome = "added" | "changed" | "unchanged" | "removed" | "absent";
|
|
2
|
+
export interface EnvChanges {
|
|
3
|
+
set: Record<string, string>;
|
|
4
|
+
unset: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function assertValidKey(key: string): void;
|
|
7
|
+
export declare function parseAssignments(args: string[]): Record<string, string>;
|
|
8
|
+
export declare function applyEnvChanges(env: string[], changes: EnvChanges): {
|
|
9
|
+
env: string[];
|
|
10
|
+
outcomes: Record<string, EnvOutcome>;
|
|
11
|
+
};
|
|
12
|
+
export declare function hasChanges(outcomes: Record<string, EnvOutcome>): boolean;
|
|
13
|
+
export type EnvSummaryRow = {
|
|
14
|
+
name: string;
|
|
15
|
+
status: "same" | "differs";
|
|
16
|
+
} | {
|
|
17
|
+
name: string;
|
|
18
|
+
status: "missing";
|
|
19
|
+
missingOn: string[];
|
|
20
|
+
};
|
|
21
|
+
export declare function summariseEnv(hosts: {
|
|
22
|
+
host: string;
|
|
23
|
+
env: string[];
|
|
24
|
+
}[]): EnvSummaryRow[];
|
|
25
|
+
export declare function envValue(env: string[], key: string): string | undefined;
|
|
26
|
+
export declare function probePort(config: {
|
|
27
|
+
Env?: string[];
|
|
28
|
+
ExposedPorts?: Record<string, unknown>;
|
|
29
|
+
}): number | null;
|
|
30
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/portainer/env.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAOD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAIhD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWvE;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,EAAE,UAAU,GAClB;IAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CAAE,CA2BzD;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,OAAO,CAIxE;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE7D,wBAAgB,YAAY,CAC1B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,GACvC,aAAa,EAAE,CAajB;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMvE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE;IAChC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC,GAAG,MAAM,GAAG,IAAI,CAMhB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Pure helpers for editing a Docker container's Env array (["KEY=VALUE", ...]).
|
|
2
|
+
// Nothing here prints or returns an existing value: most of these are secrets.
|
|
3
|
+
const KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
4
|
+
function splitEntry(entry) {
|
|
5
|
+
const i = entry.indexOf("=");
|
|
6
|
+
return i === -1 ? [entry, ""] : [entry.slice(0, i), entry.slice(i + 1)];
|
|
7
|
+
}
|
|
8
|
+
export function assertValidKey(key) {
|
|
9
|
+
if (!KEY_PATTERN.test(key)) {
|
|
10
|
+
throw new Error(`Invalid environment variable name: "${key}"`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function parseAssignments(args) {
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const arg of args) {
|
|
16
|
+
if (!arg.includes("=")) {
|
|
17
|
+
throw new Error(`Expected KEY=VALUE, got "${arg}"`);
|
|
18
|
+
}
|
|
19
|
+
const [key, value] = splitEntry(arg);
|
|
20
|
+
assertValidKey(key);
|
|
21
|
+
result[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
export function applyEnvChanges(env, changes) {
|
|
26
|
+
const outcomes = {};
|
|
27
|
+
const pending = new Map(Object.entries(changes.set));
|
|
28
|
+
const unset = new Set(changes.unset);
|
|
29
|
+
const result = [];
|
|
30
|
+
for (const entry of env) {
|
|
31
|
+
const [key, value] = splitEntry(entry);
|
|
32
|
+
if (pending.has(key)) {
|
|
33
|
+
const next = pending.get(key);
|
|
34
|
+
outcomes[key] = next === value ? "unchanged" : "changed";
|
|
35
|
+
result.push(`${key}=${next}`);
|
|
36
|
+
pending.delete(key);
|
|
37
|
+
}
|
|
38
|
+
else if (unset.has(key)) {
|
|
39
|
+
outcomes[key] = "removed";
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
result.push(entry);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const [key, value] of pending) {
|
|
46
|
+
outcomes[key] = "added";
|
|
47
|
+
result.push(`${key}=${value}`);
|
|
48
|
+
}
|
|
49
|
+
for (const key of unset) {
|
|
50
|
+
if (!(key in outcomes))
|
|
51
|
+
outcomes[key] = "absent";
|
|
52
|
+
}
|
|
53
|
+
return { env: result, outcomes };
|
|
54
|
+
}
|
|
55
|
+
export function hasChanges(outcomes) {
|
|
56
|
+
return Object.values(outcomes).some((o) => o === "added" || o === "changed" || o === "removed");
|
|
57
|
+
}
|
|
58
|
+
export function summariseEnv(hosts) {
|
|
59
|
+
const maps = hosts.map((h) => ({
|
|
60
|
+
host: h.host,
|
|
61
|
+
values: new Map(h.env.map(splitEntry)),
|
|
62
|
+
}));
|
|
63
|
+
const names = [...new Set(maps.flatMap((m) => [...m.values.keys()]))].sort();
|
|
64
|
+
return names.map((name) => {
|
|
65
|
+
const missingOn = maps.filter((m) => !m.values.has(name)).map((m) => m.host);
|
|
66
|
+
if (missingOn.length > 0)
|
|
67
|
+
return { name, status: "missing", missingOn };
|
|
68
|
+
const distinct = new Set(maps.map((m) => m.values.get(name)));
|
|
69
|
+
return { name, status: distinct.size === 1 ? "same" : "differs" };
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export function envValue(env, key) {
|
|
73
|
+
for (const entry of env) {
|
|
74
|
+
const [k, v] = splitEntry(entry);
|
|
75
|
+
if (k === key)
|
|
76
|
+
return v;
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
export function probePort(config) {
|
|
81
|
+
const fromEnv = Number(envValue(config.Env ?? [], "PORT"));
|
|
82
|
+
if (Number.isInteger(fromEnv) && fromEnv > 0)
|
|
83
|
+
return fromEnv;
|
|
84
|
+
const first = Object.keys(config.ExposedPorts ?? {})[0];
|
|
85
|
+
const port = first ? Number(first.split("/")[0]) : NaN;
|
|
86
|
+
return Number.isInteger(port) && port > 0 ? port : null;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/portainer/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** A Docker image reference split into repository and tag (default "latest"). */
|
|
2
|
+
export declare function splitImage(ref: string): {
|
|
3
|
+
repo: string;
|
|
4
|
+
tag: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function withTag(ref: string, tag: string): string;
|
|
7
|
+
export interface PackageVersion {
|
|
8
|
+
metadata?: {
|
|
9
|
+
container?: {
|
|
10
|
+
tags?: string[];
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Release tags (plain X.Y.Z) from GHCR package versions, newest first, and
|
|
16
|
+
* the release tag that shares an image with "latest", if any.
|
|
17
|
+
*/
|
|
18
|
+
export declare function releaseTags(versions: PackageVersion[]): {
|
|
19
|
+
tags: string[];
|
|
20
|
+
latest: string | undefined;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/portainer/image.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CASrE;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;SAAE,CAAA;KAAE,CAAC;CAChD;AAaD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG;IACvD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAYA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** A Docker image reference split into repository and tag (default "latest"). */
|
|
2
|
+
export function splitImage(ref) {
|
|
3
|
+
const noDigest = ref.split("@")[0];
|
|
4
|
+
const lastSlash = noDigest.lastIndexOf("/");
|
|
5
|
+
const lastColon = noDigest.lastIndexOf(":");
|
|
6
|
+
// A colon before the last slash belongs to a registry port, not a tag.
|
|
7
|
+
if (lastColon > lastSlash) {
|
|
8
|
+
return { repo: noDigest.slice(0, lastColon), tag: noDigest.slice(lastColon + 1) };
|
|
9
|
+
}
|
|
10
|
+
return { repo: noDigest, tag: "latest" };
|
|
11
|
+
}
|
|
12
|
+
export function withTag(ref, tag) {
|
|
13
|
+
return `${splitImage(ref).repo}:${tag}`;
|
|
14
|
+
}
|
|
15
|
+
const RELEASE = /^\d+\.\d+\.\d+$/;
|
|
16
|
+
function compareDesc(a, b) {
|
|
17
|
+
const pa = a.split(".").map(Number);
|
|
18
|
+
const pb = b.split(".").map(Number);
|
|
19
|
+
for (let i = 0; i < 3; i++) {
|
|
20
|
+
if (pa[i] !== pb[i])
|
|
21
|
+
return pb[i] - pa[i];
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Release tags (plain X.Y.Z) from GHCR package versions, newest first, and
|
|
27
|
+
* the release tag that shares an image with "latest", if any.
|
|
28
|
+
*/
|
|
29
|
+
export function releaseTags(versions) {
|
|
30
|
+
const tags = new Set();
|
|
31
|
+
let latest;
|
|
32
|
+
for (const version of versions) {
|
|
33
|
+
const vtags = version.metadata?.container?.tags ?? [];
|
|
34
|
+
const releases = vtags.filter((t) => RELEASE.test(t));
|
|
35
|
+
releases.forEach((t) => tags.add(t));
|
|
36
|
+
if (vtags.includes("latest") && releases.length > 0) {
|
|
37
|
+
latest = [...releases].sort(compareDesc)[0];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { tags: [...tags].sort(compareDesc), latest };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/portainer/image.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC5C,uEAAuE;IACvE,IAAI,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;IACpF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,GAAW;IAC9C,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;AAC1C,CAAC;AAMD,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAElC,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,QAA0B;IAIpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,MAA0B,CAAC;IAC/B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PortainerInstance } from "../config.js";
|
|
2
|
+
export interface RecreateOptions {
|
|
3
|
+
/** Pull the container's image tag before recreating (deploys new code). */
|
|
4
|
+
pull: boolean;
|
|
5
|
+
/** Create the new container from this image instead of the current one. */
|
|
6
|
+
image?: string;
|
|
7
|
+
/** Rewrite the Env array; omit to keep it as is. */
|
|
8
|
+
transformEnv?: (env: string[]) => string[];
|
|
9
|
+
log: (msg: string) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Recreate one container from its own config. Steps: inspect → (pull) → stop
|
|
13
|
+
* → rename to <name>-old → create → start → probe → copy resource control →
|
|
14
|
+
* delete old. Any failure after the stop restores the old container and
|
|
15
|
+
* throws, so the host is never left without a running container.
|
|
16
|
+
*/
|
|
17
|
+
export declare function recreateContainer(instance: PortainerInstance, options: RecreateOptions): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=recreate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recreate.d.ts","sourceRoot":"","sources":["../../src/portainer/recreate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAOtD,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,OAAO,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5B;AA2BD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAiIf"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as portainer from "./api.js";
|
|
2
|
+
import { probePort } from "./env.js";
|
|
3
|
+
const PROBE_INTERVAL_MS = 5_000;
|
|
4
|
+
const PROBE_ATTEMPTS = 18; // 90 s
|
|
5
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
6
|
+
/**
|
|
7
|
+
* Ask the container itself whether it answers HTTP on its port. Any status
|
|
8
|
+
* counts as ready — the point is that the process is up and listening.
|
|
9
|
+
*/
|
|
10
|
+
async function probe(common, containerId, port) {
|
|
11
|
+
const script = `fetch("http://localhost:${port}/").then(r=>console.log("STATUS",r.status)).catch(e=>console.log("ERR",e.message))`;
|
|
12
|
+
try {
|
|
13
|
+
const out = await portainer.execInContainer({
|
|
14
|
+
...common,
|
|
15
|
+
portainerContainerId: containerId,
|
|
16
|
+
cmd: ["node", "-e", script],
|
|
17
|
+
});
|
|
18
|
+
const match = out.match(/STATUS (\d+)/);
|
|
19
|
+
return match ? match[1] : null;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Recreate one container from its own config. Steps: inspect → (pull) → stop
|
|
27
|
+
* → rename to <name>-old → create → start → probe → copy resource control →
|
|
28
|
+
* delete old. Any failure after the stop restores the old container and
|
|
29
|
+
* throws, so the host is never left without a running container.
|
|
30
|
+
*/
|
|
31
|
+
export async function recreateContainer(instance, options) {
|
|
32
|
+
const { portainerUrl, portainerEndpointId, portainerApiKey, portainerRegistryAuth, portainerContainerName: name, } = instance;
|
|
33
|
+
const common = { portainerUrl, portainerEndpointId, portainerApiKey };
|
|
34
|
+
const { log } = options;
|
|
35
|
+
log("Inspect the container");
|
|
36
|
+
const container = await portainer.getContainer({
|
|
37
|
+
...common,
|
|
38
|
+
portainerContainerName: name,
|
|
39
|
+
});
|
|
40
|
+
const oldId = container.Id;
|
|
41
|
+
const image = options.image ?? container.Config.Image;
|
|
42
|
+
if (options.pull) {
|
|
43
|
+
log(`Pull ${image}`);
|
|
44
|
+
await portainer.pullImage({
|
|
45
|
+
...common,
|
|
46
|
+
portainerRegistryAuth,
|
|
47
|
+
image,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const env = container.Config.Env ?? [];
|
|
51
|
+
const config = {
|
|
52
|
+
...container.Config,
|
|
53
|
+
Image: image,
|
|
54
|
+
// OCI labels (version, revision, created) come from the image; keeping the
|
|
55
|
+
// old container's copies would mask the new image's values.
|
|
56
|
+
Labels: Object.fromEntries(Object.entries((container.Config.Labels ?? {})).filter(([key]) => !key.startsWith("org.opencontainers.image."))),
|
|
57
|
+
Env: options.transformEnv ? options.transformEnv(env) : env,
|
|
58
|
+
HostConfig: container.HostConfig,
|
|
59
|
+
NetworkingConfig: {
|
|
60
|
+
EndpointsConfig: container.NetworkSettings?.Networks ?? {},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
const port = probePort(config);
|
|
64
|
+
log("Stop and rename the current container");
|
|
65
|
+
await portainer.stopContainer({ ...common, portainerContainerId: oldId });
|
|
66
|
+
await portainer.renameContainer({
|
|
67
|
+
...common,
|
|
68
|
+
portainerContainerId: oldId,
|
|
69
|
+
name: `${name}-old`,
|
|
70
|
+
});
|
|
71
|
+
let newId;
|
|
72
|
+
try {
|
|
73
|
+
log("Create and start the new container");
|
|
74
|
+
const created = await portainer.createContainer({ ...common, name, config });
|
|
75
|
+
newId = created.Id;
|
|
76
|
+
const fresh = await portainer.getContainer({
|
|
77
|
+
...common,
|
|
78
|
+
portainerContainerName: newId,
|
|
79
|
+
});
|
|
80
|
+
const attached = new Set(Object.keys(fresh.NetworkSettings?.Networks ?? {}));
|
|
81
|
+
for (const networkName of Object.keys(container.NetworkSettings?.Networks ?? {})) {
|
|
82
|
+
if (attached.has(networkName))
|
|
83
|
+
continue;
|
|
84
|
+
await portainer.connectContainerToNetwork({
|
|
85
|
+
...common,
|
|
86
|
+
portainerContainerId: newId,
|
|
87
|
+
networkName,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
await portainer.startContainer({ ...common, portainerContainerId: newId });
|
|
91
|
+
if (port === null) {
|
|
92
|
+
log("No port to probe (no PORT env, no exposed port); waiting 15 s for it to stay up");
|
|
93
|
+
await sleep(15_000);
|
|
94
|
+
const state = await portainer.getContainer({ ...common, portainerContainerName: newId });
|
|
95
|
+
if (state.State?.Status !== "running") {
|
|
96
|
+
throw new Error(`new container is ${state.State?.Status}, not running`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
log(`Wait for the new container to answer on :${port}`);
|
|
101
|
+
let status = null;
|
|
102
|
+
for (let i = 0; i < PROBE_ATTEMPTS && status === null; i++) {
|
|
103
|
+
await sleep(PROBE_INTERVAL_MS);
|
|
104
|
+
status = await probe(common, newId, port);
|
|
105
|
+
}
|
|
106
|
+
if (status === null) {
|
|
107
|
+
throw new Error(`new container did not answer on :${port} within 90 s`);
|
|
108
|
+
}
|
|
109
|
+
log(`New container answers (HTTP ${status})`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
log(`FAILED: ${err.message} — restoring the old container`);
|
|
114
|
+
if (newId) {
|
|
115
|
+
await portainer.stopContainer({ ...common, portainerContainerId: newId }).catch(() => { });
|
|
116
|
+
await portainer
|
|
117
|
+
.renameContainer({ ...common, portainerContainerId: newId, name: `${name}-failed` })
|
|
118
|
+
.catch(() => { });
|
|
119
|
+
}
|
|
120
|
+
await portainer.renameContainer({ ...common, portainerContainerId: oldId, name });
|
|
121
|
+
await portainer.startContainer({ ...common, portainerContainerId: oldId });
|
|
122
|
+
log(`Old container restored${newId ? `; the failed one is kept as ${name}-failed` : ""}`);
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
const resourceControl = container.Portainer?.ResourceControl;
|
|
126
|
+
if (resourceControl) {
|
|
127
|
+
log("Copy the Portainer resource control");
|
|
128
|
+
await portainer.updateResourceControl({
|
|
129
|
+
portainerUrl,
|
|
130
|
+
portainerApiKey,
|
|
131
|
+
resourceControlId: resourceControl.Id,
|
|
132
|
+
data: {
|
|
133
|
+
AdministratorsOnly: resourceControl.AdministratorsOnly,
|
|
134
|
+
Public: resourceControl.Public,
|
|
135
|
+
Users: resourceControl.UserAccesses.map((a) => a.UserId),
|
|
136
|
+
Teams: resourceControl.TeamAccesses,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
log("Delete the old container");
|
|
141
|
+
await portainer.deleteContainer({ ...common, portainerContainerId: oldId });
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=recreate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recreate.js","sourceRoot":"","sources":["../../src/portainer/recreate.ts"],"names":[],"mappings":"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"}
|
package/dist/portainer/urls.d.ts
CHANGED
|
@@ -7,4 +7,6 @@ export declare const networkConnectUrl: (baseUrl: string, endpointId: string, ne
|
|
|
7
7
|
export declare const imagePullUrl: (baseUrl: string, endpointId: string, image: string) => string;
|
|
8
8
|
export declare const containerDeleteUrl: (baseUrl: string, endpointId: string, containerId: string) => string;
|
|
9
9
|
export declare const resourceControlsUrl: (baseUrl: string, resourceControlId: number) => string;
|
|
10
|
+
export declare const containerExecUrl: (baseUrl: string, endpointId: string, containerId: string) => string;
|
|
11
|
+
export declare const execStartUrl: (baseUrl: string, endpointId: string, execId: string) => string;
|
|
10
12
|
//# sourceMappingURL=urls.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/portainer/urls.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,eAAe,MAAM,WAC+C,CAAC;AAEvE,eAAO,MAAM,gBAAgB,GAC3B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WAC+C,CAAC;AAErE,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WACgD,CAAC;AAEtE,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,EACnB,MAAM,MAAM,WAEkE,CAAC;AAEjF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,MAAM,MAAM,WACsD,CAAC;AAErE,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WACgD,CAAC;AAEtE,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,OAAO,MAAM,WACuD,CAAC;AAEvE,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WACyD,CAAC;AAE/E,eAAO,MAAM,mBAAmB,GAC9B,SAAS,MAAM,EACf,mBAAmB,MAAM,WACiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/portainer/urls.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,eAAe,MAAM,WAC+C,CAAC;AAEvE,eAAO,MAAM,gBAAgB,GAC3B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WAC+C,CAAC;AAErE,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WACgD,CAAC;AAEtE,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,EACnB,MAAM,MAAM,WAEkE,CAAC;AAEjF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,MAAM,MAAM,WACsD,CAAC;AAErE,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WACgD,CAAC;AAEtE,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,OAAO,MAAM,WACuD,CAAC;AAEvE,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WACyD,CAAC;AAE/E,eAAO,MAAM,mBAAmB,GAC9B,SAAS,MAAM,EACf,mBAAmB,MAAM,WACiC,CAAC;AAE7D,eAAO,MAAM,gBAAgB,GAC3B,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,aAAa,MAAM,WAC+C,CAAC;AAErE,eAAO,MAAM,YAAY,GACvB,SAAS,MAAM,EACf,YAAY,MAAM,EAClB,QAAQ,MAAM,WAC0C,CAAC"}
|
package/dist/portainer/urls.js
CHANGED
|
@@ -8,4 +8,6 @@ export const networkConnectUrl = (baseUrl, endpointId, networkName) => `${docker
|
|
|
8
8
|
export const imagePullUrl = (baseUrl, endpointId, image) => `${docker(baseUrl, endpointId)}/images/create?fromImage=${image}`;
|
|
9
9
|
export const containerDeleteUrl = (baseUrl, endpointId, containerId) => `${docker(baseUrl, endpointId)}/containers/${containerId}?v=1&force=true`;
|
|
10
10
|
export const resourceControlsUrl = (baseUrl, resourceControlId) => `${baseUrl}/api/resource_controls/${resourceControlId}`;
|
|
11
|
+
export const containerExecUrl = (baseUrl, endpointId, containerId) => `${docker(baseUrl, endpointId)}/containers/${containerId}/exec`;
|
|
12
|
+
export const execStartUrl = (baseUrl, endpointId, execId) => `${docker(baseUrl, endpointId)}/exec/${execId}/start`;
|
|
11
13
|
//# sourceMappingURL=urls.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/portainer/urls.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAE,EAAE,CACrD,GAAG,OAAO,kBAAkB,UAAU,SAAS,CAAC;AAElD,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAe,EACf,UAAkB,EAClB,aAAqB,EACrB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,aAAa,OAAO,CAAC;AAEvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,OAAO,CAAC;AAErE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,QAAQ,CAAC;AAEtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,IAAY,EACZ,EAAE,CACF,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,gBAAgB,IAAI,EAAE,CAAC;AAEjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,UAAkB,EAClB,IAAY,EACZ,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,2BAA2B,IAAI,EAAE,CAAC;AAErE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,WAAW,UAAU,CAAC;AAEtE,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,4BAA4B,KAAK,EAAE,CAAC;AAEvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,iBAAiB,CAAC;AAE/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,OAAe,EACf,iBAAyB,EACzB,EAAE,CAAC,GAAG,OAAO,0BAA0B,iBAAiB,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/portainer/urls.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAE,EAAE,CACrD,GAAG,OAAO,kBAAkB,UAAU,SAAS,CAAC;AAElD,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAe,EACf,UAAkB,EAClB,aAAqB,EACrB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,aAAa,OAAO,CAAC;AAEvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,OAAO,CAAC;AAErE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,QAAQ,CAAC;AAEtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,IAAY,EACZ,EAAE,CACF,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,gBAAgB,IAAI,EAAE,CAAC;AAEjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,UAAkB,EAClB,IAAY,EACZ,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,2BAA2B,IAAI,EAAE,CAAC;AAErE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,aAAa,WAAW,UAAU,CAAC;AAEtE,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAe,EACf,UAAkB,EAClB,KAAa,EACb,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,4BAA4B,KAAK,EAAE,CAAC;AAEvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,iBAAiB,CAAC;AAE/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,OAAe,EACf,iBAAyB,EACzB,EAAE,CAAC,GAAG,OAAO,0BAA0B,iBAAiB,EAAE,CAAC;AAE7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAe,EACf,UAAkB,EAClB,WAAmB,EACnB,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,eAAe,WAAW,OAAO,CAAC;AAErE,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,OAAe,EACf,UAAkB,EAClB,MAAc,EACd,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,MAAM,QAAQ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superyachttimes/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "SuperYachtTimes CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"syt-cli": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"!dist/**/*.test.*"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsc",
|
|
@@ -15,7 +16,8 @@
|
|
|
15
16
|
"clean": "rm -rf dist",
|
|
16
17
|
"prepublishOnly": "npm run clean && npm run build",
|
|
17
18
|
"push": "npm login && npm publish --scope @superyachttimes --access public",
|
|
18
|
-
"ship": "bash scripts/ship.sh"
|
|
19
|
+
"ship": "bash scripts/ship.sh",
|
|
20
|
+
"test": "tsc && node --test \"dist/**/*.test.js\""
|
|
19
21
|
},
|
|
20
22
|
"engines": {
|
|
21
23
|
"node": ">=20"
|