@cardelli/ambit 0.3.1 → 0.3.3
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/README.md +32 -13
- package/esm/cli/commands/list/apps.d.ts +2 -0
- package/esm/cli/commands/list/apps.d.ts.map +1 -0
- package/esm/cli/commands/list/apps.js +72 -0
- package/esm/cli/commands/list/index.d.ts +2 -0
- package/esm/cli/commands/list/index.d.ts.map +1 -0
- package/esm/cli/commands/list/index.js +62 -0
- package/esm/cli/commands/list/networks.d.ts +2 -0
- package/esm/cli/commands/list/networks.d.ts.map +1 -0
- package/esm/cli/commands/{list.js → list/networks.js} +17 -27
- package/esm/cli/commands/status/app.d.ts +2 -0
- package/esm/cli/commands/status/app.d.ts.map +1 -0
- package/esm/cli/commands/status/app.js +141 -0
- package/esm/cli/commands/status/index.d.ts +2 -0
- package/esm/cli/commands/status/index.d.ts.map +1 -0
- package/esm/cli/commands/status/index.js +68 -0
- package/esm/cli/commands/status/network.d.ts +2 -0
- package/esm/cli/commands/status/network.d.ts.map +1 -0
- package/esm/cli/commands/status/network.js +104 -0
- package/esm/cli/commands/status/networks.d.ts +2 -0
- package/esm/cli/commands/status/networks.d.ts.map +1 -0
- package/esm/cli/commands/status/networks.js +62 -0
- package/esm/deno.js +1 -1
- package/esm/lib/cli.d.ts.map +1 -1
- package/esm/lib/cli.js +4 -13
- package/esm/main.d.ts +2 -2
- package/esm/main.d.ts.map +1 -1
- package/esm/main.js +5 -2
- package/esm/schemas/fly.d.ts +84 -4
- package/esm/schemas/fly.d.ts.map +1 -1
- package/esm/schemas/fly.js +34 -2
- package/esm/util/discovery.d.ts +4 -1
- package/esm/util/discovery.d.ts.map +1 -1
- package/esm/util/discovery.js +3 -0
- package/package.json +1 -1
- package/esm/cli/commands/list.d.ts +0 -2
- package/esm/cli/commands/list.d.ts.map +0 -1
- package/esm/cli/commands/status.d.ts +0 -2
- package/esm/cli/commands/status.d.ts.map +0 -1
- package/esm/cli/commands/status.js +0 -334
package/README.md
CHANGED
|
@@ -160,32 +160,51 @@ These work with all three modes.
|
|
|
160
160
|
| `-y`, `--yes` | Skip confirmation prompts |
|
|
161
161
|
| `--json` | Machine-readable JSON output |
|
|
162
162
|
|
|
163
|
-
### `ambit
|
|
163
|
+
### `ambit list networks|apps`
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
#### `ambit list networks`
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
Lists all networks and their routers in a table showing the network name, app name, region, machine state, Tailscale connectivity status, and ACL tag.
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
| Flag | Description |
|
|
170
|
+
| ----------------- | ------------------------------ |
|
|
171
|
+
| `--org <org>` | Fly.io organization slug |
|
|
172
|
+
| `--json` | Machine-readable JSON output |
|
|
173
|
+
|
|
174
|
+
#### `ambit list apps <network>`
|
|
175
|
+
|
|
176
|
+
Lists all workload apps on a specific network in a table showing the app name, region, and machine state.
|
|
170
177
|
|
|
171
178
|
| Flag | Description |
|
|
172
179
|
| ----------------- | ------------------------------ |
|
|
173
180
|
| `--org <org>` | Fly.io organization slug |
|
|
174
181
|
| `--json` | Machine-readable JSON output |
|
|
175
182
|
|
|
176
|
-
|
|
183
|
+
### `ambit status [networks|network|app]`
|
|
177
184
|
|
|
178
|
-
|
|
185
|
+
Without a subcommand, defaults to showing all networks (same as `status networks`).
|
|
179
186
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
| `--org <org>` | Fly.io organization slug |
|
|
184
|
-
| `--json` | Machine-readable JSON output |
|
|
187
|
+
#### `ambit status networks`
|
|
188
|
+
|
|
189
|
+
Shows a summary table of all networks and their routers.
|
|
185
190
|
|
|
186
|
-
|
|
191
|
+
| Flag | Description |
|
|
192
|
+
| ----------------- | ------------------------------ |
|
|
193
|
+
| `--org <org>` | Fly.io organization slug |
|
|
194
|
+
| `--json` | Machine-readable JSON output |
|
|
195
|
+
|
|
196
|
+
#### `ambit status network <name>`
|
|
197
|
+
|
|
198
|
+
Shows detailed status for a specific network: machine state, SOCKS proxy, Tailscale IP, subnet, and apps on the network.
|
|
199
|
+
|
|
200
|
+
| Flag | Description |
|
|
201
|
+
| ----------------- | ------------------------------ |
|
|
202
|
+
| `--org <org>` | Fly.io organization slug |
|
|
203
|
+
| `--json` | Machine-readable JSON output |
|
|
187
204
|
|
|
188
|
-
|
|
205
|
+
#### `ambit status app <app>.<network>`
|
|
206
|
+
|
|
207
|
+
Shows detailed status for a specific app: machines, Flycast IPs, and the backing router.
|
|
189
208
|
|
|
190
209
|
| Flag | Description |
|
|
191
210
|
| ----------------- | ------------------------------ |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/apps.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,QAAQ,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAqE3D,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// List Apps — List All Workload Apps on a Network
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
5
|
+
import { Table } from "../../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
|
|
6
|
+
import { bold } from "../../../lib/cli.js";
|
|
7
|
+
import { checkArgs } from "../../../lib/args.js";
|
|
8
|
+
import { createOutput } from "../../../lib/output.js";
|
|
9
|
+
import { findRouterApp, listWorkloadAppsOnNetwork, } from "../../../util/discovery.js";
|
|
10
|
+
import { initSession } from "../../../util/session.js";
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// List Apps Command
|
|
13
|
+
// =============================================================================
|
|
14
|
+
export const listApps = async (argv) => {
|
|
15
|
+
const opts = { string: ["org"], boolean: ["help", "json"] };
|
|
16
|
+
const args = parseArgs(argv, opts);
|
|
17
|
+
checkArgs(args, opts, "ambit list apps");
|
|
18
|
+
if (args.help) {
|
|
19
|
+
console.log(`
|
|
20
|
+
${bold("ambit list apps")} - List Apps on a Network
|
|
21
|
+
|
|
22
|
+
${bold("USAGE")}
|
|
23
|
+
ambit list apps <network> [--org <org>] [--json]
|
|
24
|
+
|
|
25
|
+
${bold("OPTIONS")}
|
|
26
|
+
--org <org> Fly.io organization slug
|
|
27
|
+
--json Output as JSON
|
|
28
|
+
|
|
29
|
+
${bold("EXAMPLES")}
|
|
30
|
+
ambit list apps browsers
|
|
31
|
+
ambit list apps browsers --json
|
|
32
|
+
`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const out = createOutput(args.json);
|
|
36
|
+
const network = typeof args._[0] === "string" ? args._[0] : undefined;
|
|
37
|
+
if (!network) {
|
|
38
|
+
return out.die("Missing Network Name. Usage: ambit list apps <network>");
|
|
39
|
+
}
|
|
40
|
+
const { fly, org } = await initSession(out, {
|
|
41
|
+
json: args.json,
|
|
42
|
+
org: args.org,
|
|
43
|
+
});
|
|
44
|
+
const router = await findRouterApp(fly, org, network);
|
|
45
|
+
if (!router) {
|
|
46
|
+
return out.die(`No Network Found: '${network}'`);
|
|
47
|
+
}
|
|
48
|
+
const workloads = await listWorkloadAppsOnNetwork(fly, org, network);
|
|
49
|
+
if (workloads.length === 0) {
|
|
50
|
+
out.blank()
|
|
51
|
+
.text(`No Apps Found on Network '${network}'.`)
|
|
52
|
+
.dim(" Deploy one with: ambit deploy <app>.<network>")
|
|
53
|
+
.blank();
|
|
54
|
+
out.done({ network, apps: [] });
|
|
55
|
+
out.print();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
out.blank().header(`Apps on '${network}'`).blank();
|
|
59
|
+
const rows = workloads.map((w) => [w.appName, w.status]);
|
|
60
|
+
const table = new Table()
|
|
61
|
+
.header(["App", "Status"])
|
|
62
|
+
.body(rows)
|
|
63
|
+
.indent(2)
|
|
64
|
+
.padding(2);
|
|
65
|
+
out.text(table.toString());
|
|
66
|
+
out.blank();
|
|
67
|
+
out.done({
|
|
68
|
+
network,
|
|
69
|
+
apps: workloads.map((w) => ({ appName: w.appName, status: w.status })),
|
|
70
|
+
});
|
|
71
|
+
out.print();
|
|
72
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// List Command - List Networks or Apps
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import * as dntShim from "../../../_dnt.shims.js";
|
|
5
|
+
import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
6
|
+
import { bold } from "../../../lib/cli.js";
|
|
7
|
+
import { registerCommand } from "../../mod.js";
|
|
8
|
+
import { listNetworks } from "./networks.js";
|
|
9
|
+
import { listApps } from "./apps.js";
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Top-Level Help
|
|
12
|
+
// =============================================================================
|
|
13
|
+
const showListHelp = () => {
|
|
14
|
+
console.log(`
|
|
15
|
+
${bold("ambit list")} - List Networks or Apps
|
|
16
|
+
|
|
17
|
+
${bold("USAGE")}
|
|
18
|
+
ambit list networks [options]
|
|
19
|
+
ambit list apps <network> [options]
|
|
20
|
+
|
|
21
|
+
${bold("SUBCOMMANDS")}
|
|
22
|
+
networks List all networks and their routers
|
|
23
|
+
apps List workload apps on a specific network
|
|
24
|
+
|
|
25
|
+
${bold("OPTIONS")}
|
|
26
|
+
--org <org> Fly.io organization slug
|
|
27
|
+
--json Output as JSON
|
|
28
|
+
|
|
29
|
+
${bold("EXAMPLES")}
|
|
30
|
+
ambit list networks
|
|
31
|
+
ambit list apps browsers
|
|
32
|
+
ambit list apps browsers --json
|
|
33
|
+
|
|
34
|
+
Run 'ambit list networks --help' or 'ambit list apps --help' for details.
|
|
35
|
+
`);
|
|
36
|
+
};
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// Dispatcher
|
|
39
|
+
// =============================================================================
|
|
40
|
+
const list = async (argv) => {
|
|
41
|
+
const subcommand = typeof argv[0] === "string" ? argv[0] : undefined;
|
|
42
|
+
if (subcommand === "networks")
|
|
43
|
+
return listNetworks(argv.slice(1));
|
|
44
|
+
if (subcommand === "apps")
|
|
45
|
+
return listApps(argv.slice(1));
|
|
46
|
+
const args = parseArgs(argv, { boolean: ["help"] });
|
|
47
|
+
if (args.help) {
|
|
48
|
+
showListHelp();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
showListHelp();
|
|
52
|
+
dntShim.Deno.exit(1);
|
|
53
|
+
};
|
|
54
|
+
// =============================================================================
|
|
55
|
+
// Register Command
|
|
56
|
+
// =============================================================================
|
|
57
|
+
registerCommand({
|
|
58
|
+
name: "list",
|
|
59
|
+
description: "List networks or apps",
|
|
60
|
+
usage: "ambit list networks|apps [options]",
|
|
61
|
+
run: list,
|
|
62
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"networks.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/networks.ts"],"names":[],"mappings":"AAqEA,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CA2B/D,CAAC"}
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
|
-
// List
|
|
2
|
+
// List Networks — List All Discovered Routers Across Networks
|
|
3
3
|
// =============================================================================
|
|
4
|
-
import { parseArgs } from "
|
|
5
|
-
import { Table } from "
|
|
6
|
-
import { bold } from "
|
|
7
|
-
import { checkArgs } from "
|
|
8
|
-
import { createOutput } from "
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { initSession } from "../../util/session.js";
|
|
4
|
+
import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
5
|
+
import { Table } from "../../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
|
|
6
|
+
import { bold } from "../../../lib/cli.js";
|
|
7
|
+
import { checkArgs } from "../../../lib/args.js";
|
|
8
|
+
import { createOutput } from "../../../lib/output.js";
|
|
9
|
+
import { discoverRouters } from "../../../util/discovery.js";
|
|
10
|
+
import { initSession } from "../../../util/session.js";
|
|
12
11
|
// =============================================================================
|
|
13
12
|
// Stage: Render
|
|
14
13
|
// =============================================================================
|
|
15
14
|
const stageRender = (out, routers) => {
|
|
16
15
|
if (routers.length === 0) {
|
|
17
16
|
out.blank()
|
|
18
|
-
.text("No
|
|
17
|
+
.text("No Networks Found.")
|
|
19
18
|
.dim(" Create one with: ambit create <network>")
|
|
20
19
|
.blank();
|
|
21
20
|
out.done({ routers: [] });
|
|
22
21
|
out.print();
|
|
23
22
|
return;
|
|
24
23
|
}
|
|
25
|
-
out.blank().header("
|
|
24
|
+
out.blank().header("Networks").blank();
|
|
26
25
|
const rows = routers.map((r) => {
|
|
27
26
|
const tsStatus = r.tailscale
|
|
28
27
|
? (r.tailscale.online ? "online" : "offline")
|
|
@@ -31,14 +30,14 @@ const stageRender = (out, routers) => {
|
|
|
31
30
|
return [
|
|
32
31
|
r.network,
|
|
33
32
|
r.appName,
|
|
33
|
+
r.status,
|
|
34
34
|
r.machine?.region ?? "-",
|
|
35
|
-
r.machine?.state ?? "unknown",
|
|
36
35
|
tsStatus,
|
|
37
36
|
tag,
|
|
38
37
|
];
|
|
39
38
|
});
|
|
40
39
|
const table = new Table()
|
|
41
|
-
.header(["Network", "App", "
|
|
40
|
+
.header(["Network", "App", "Status", "Region", "Tailscale", "Tag"])
|
|
42
41
|
.body(rows)
|
|
43
42
|
.indent(2)
|
|
44
43
|
.padding(2);
|
|
@@ -48,18 +47,18 @@ const stageRender = (out, routers) => {
|
|
|
48
47
|
out.print();
|
|
49
48
|
};
|
|
50
49
|
// =============================================================================
|
|
51
|
-
// List Command
|
|
50
|
+
// List Networks Command
|
|
52
51
|
// =============================================================================
|
|
53
|
-
const
|
|
52
|
+
export const listNetworks = async (argv) => {
|
|
54
53
|
const opts = { string: ["org"], boolean: ["help", "json"] };
|
|
55
54
|
const args = parseArgs(argv, opts);
|
|
56
|
-
checkArgs(args, opts, "ambit list");
|
|
55
|
+
checkArgs(args, opts, "ambit list networks");
|
|
57
56
|
if (args.help) {
|
|
58
57
|
console.log(`
|
|
59
|
-
${bold("ambit list")} - List All
|
|
58
|
+
${bold("ambit list networks")} - List All Networks
|
|
60
59
|
|
|
61
60
|
${bold("USAGE")}
|
|
62
|
-
ambit list [--org <org>] [--json]
|
|
61
|
+
ambit list networks [--org <org>] [--json]
|
|
63
62
|
|
|
64
63
|
${bold("OPTIONS")}
|
|
65
64
|
--org <org> Fly.io organization slug
|
|
@@ -75,12 +74,3 @@ ${bold("OPTIONS")}
|
|
|
75
74
|
const routers = await discoverRouters(out, fly, tailscale, org);
|
|
76
75
|
stageRender(out, routers);
|
|
77
76
|
};
|
|
78
|
-
// =============================================================================
|
|
79
|
-
// Register Command
|
|
80
|
-
// =============================================================================
|
|
81
|
-
registerCommand({
|
|
82
|
-
name: "list",
|
|
83
|
-
description: "List all discovered routers across networks",
|
|
84
|
-
usage: "ambit list [--org <org>] [--json]",
|
|
85
|
-
run: list,
|
|
86
|
-
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/app.ts"],"names":[],"mappings":"AA4JA,eAAO,MAAM,SAAS,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAyD5D,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Status App — Show App Status
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
5
|
+
import { bold } from "../../../lib/cli.js";
|
|
6
|
+
import { checkArgs } from "../../../lib/args.js";
|
|
7
|
+
import { createOutput } from "../../../lib/output.js";
|
|
8
|
+
import { findRouterApp, findWorkloadApp, getRouterMachineInfo, getRouterTailscaleInfo, } from "../../../util/discovery.js";
|
|
9
|
+
import { initSession } from "../../../util/session.js";
|
|
10
|
+
import { SOCKS_PROXY_PORT } from "../../../util/constants.js";
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Detailed App View
|
|
13
|
+
// =============================================================================
|
|
14
|
+
const stageAppStatus = async (fly, tailscale, app, network, org, json) => {
|
|
15
|
+
const out = createOutput(json);
|
|
16
|
+
const workload = await findWorkloadApp(fly, org, app, network);
|
|
17
|
+
if (!workload) {
|
|
18
|
+
return out.die(`App '${app}' Not Found on Network '${network}'`);
|
|
19
|
+
}
|
|
20
|
+
const machines = await fly.machines.list(workload.appName);
|
|
21
|
+
const ips = await fly.ips.list(workload.appName);
|
|
22
|
+
const mappedMachines = machines.map((m) => ({
|
|
23
|
+
id: m.id,
|
|
24
|
+
region: m.region,
|
|
25
|
+
state: m.state,
|
|
26
|
+
privateIp: m.private_ip,
|
|
27
|
+
}));
|
|
28
|
+
const mappedIps = ips.map((ip) => ({
|
|
29
|
+
address: ip.Address,
|
|
30
|
+
type: ip.Type,
|
|
31
|
+
network: ip.Network?.Name,
|
|
32
|
+
}));
|
|
33
|
+
const router = await findRouterApp(fly, org, network);
|
|
34
|
+
out.blank()
|
|
35
|
+
.header(`Ambit Status: ${app}.${network}`)
|
|
36
|
+
.blank()
|
|
37
|
+
.text(` App: ${bold(app)}`)
|
|
38
|
+
.text(` Network: ${network}`)
|
|
39
|
+
.text(` Fly App: ${workload.appName}`)
|
|
40
|
+
.text(` Status: ${workload.status}`)
|
|
41
|
+
.blank();
|
|
42
|
+
if (machines.length === 0) {
|
|
43
|
+
out.text(" Machines: None");
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
out.header(" Machines").blank();
|
|
47
|
+
for (const m of machines) {
|
|
48
|
+
out.text(` ${m.id} ${m.region} ${m.state}${m.private_ip ? ` ${m.private_ip}` : ""}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
out.blank();
|
|
52
|
+
const flycastIps = ips.filter((ip) => ip.Type === "private_v6");
|
|
53
|
+
const publicIps = ips.filter((ip) => ip.Type !== "private_v6");
|
|
54
|
+
if (flycastIps.length > 0) {
|
|
55
|
+
out.header(" Flycast IPs").blank();
|
|
56
|
+
for (const ip of flycastIps) {
|
|
57
|
+
out.text(` ${ip.Address} (network: ${ip.Network?.Name ?? "default"})`);
|
|
58
|
+
}
|
|
59
|
+
out.blank();
|
|
60
|
+
}
|
|
61
|
+
if (publicIps.length > 0) {
|
|
62
|
+
out.header(" Public IPs (Warning: Ambit Apps Should Not Have Public IPs)")
|
|
63
|
+
.blank();
|
|
64
|
+
for (const ip of publicIps) {
|
|
65
|
+
out.text(` ${ip.Address} ${ip.Type}`);
|
|
66
|
+
}
|
|
67
|
+
out.blank();
|
|
68
|
+
}
|
|
69
|
+
if (router) {
|
|
70
|
+
const routerMachine = await getRouterMachineInfo(fly, router.appName);
|
|
71
|
+
const ts = await getRouterTailscaleInfo(tailscale, router.appName);
|
|
72
|
+
out.header(" Router").blank()
|
|
73
|
+
.text(` App: ${router.appName}`)
|
|
74
|
+
.text(` State: ${routerMachine?.state ?? "unknown"}`)
|
|
75
|
+
.text(` Tailscale: ${ts ? (ts.online ? "online" : "offline") : "not found"}`);
|
|
76
|
+
if (routerMachine?.privateIp) {
|
|
77
|
+
out.text(` SOCKS Proxy: socks5://[${routerMachine.privateIp}]:${SOCKS_PROXY_PORT}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
out.text(" Router: Not Found");
|
|
82
|
+
}
|
|
83
|
+
out.blank();
|
|
84
|
+
out.done({
|
|
85
|
+
app,
|
|
86
|
+
network,
|
|
87
|
+
flyAppName: workload.appName,
|
|
88
|
+
machines: mappedMachines,
|
|
89
|
+
ips: mappedIps,
|
|
90
|
+
router,
|
|
91
|
+
});
|
|
92
|
+
out.print();
|
|
93
|
+
};
|
|
94
|
+
// =============================================================================
|
|
95
|
+
// Status App Subcommand
|
|
96
|
+
// =============================================================================
|
|
97
|
+
export const statusApp = async (argv) => {
|
|
98
|
+
const opts = {
|
|
99
|
+
string: ["org"],
|
|
100
|
+
boolean: ["help", "json"],
|
|
101
|
+
};
|
|
102
|
+
const args = parseArgs(argv, opts);
|
|
103
|
+
checkArgs(args, opts, "ambit status app");
|
|
104
|
+
if (args.help) {
|
|
105
|
+
console.log(`
|
|
106
|
+
${bold("ambit status app")} - Show App Status
|
|
107
|
+
|
|
108
|
+
${bold("USAGE")}
|
|
109
|
+
ambit status app <app>.<network> [--org <org>] [--json]
|
|
110
|
+
|
|
111
|
+
${bold("OPTIONS")}
|
|
112
|
+
--org <org> Fly.io organization slug
|
|
113
|
+
--json Output as JSON
|
|
114
|
+
|
|
115
|
+
${bold("EXAMPLES")}
|
|
116
|
+
ambit status app my-app.browsers
|
|
117
|
+
ambit status app my-app.browsers --json
|
|
118
|
+
`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const out = createOutput(args.json);
|
|
122
|
+
const appArg = args._[0];
|
|
123
|
+
if (!appArg || typeof appArg !== "string") {
|
|
124
|
+
return out.die("Missing App Name. Usage: ambit status app <app>.<network>");
|
|
125
|
+
}
|
|
126
|
+
if (!appArg.includes(".")) {
|
|
127
|
+
return out.die(`Missing Network. Use: ambit status app ${appArg}.<network>`);
|
|
128
|
+
}
|
|
129
|
+
const parts = appArg.split(".");
|
|
130
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
131
|
+
return out.die(`'${appArg}' Should Have Exactly One Dot, Like my-app.my-network`);
|
|
132
|
+
}
|
|
133
|
+
const app = parts[0];
|
|
134
|
+
const network = parts[1];
|
|
135
|
+
const prereqOut = createOutput(args.json);
|
|
136
|
+
const { fly, tailscale, org } = await initSession(prereqOut, {
|
|
137
|
+
json: args.json,
|
|
138
|
+
org: args.org,
|
|
139
|
+
});
|
|
140
|
+
await stageAppStatus(fly, tailscale, app, network, org, args.json);
|
|
141
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Status Command - Show Network, App, and Router Status
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
5
|
+
import { bold } from "../../../lib/cli.js";
|
|
6
|
+
import { registerCommand } from "../../mod.js";
|
|
7
|
+
import { statusNetworks } from "./networks.js";
|
|
8
|
+
import { statusNetwork } from "./network.js";
|
|
9
|
+
import { statusApp } from "./app.js";
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Top-Level Help
|
|
12
|
+
// =============================================================================
|
|
13
|
+
const showStatusHelp = () => {
|
|
14
|
+
console.log(`
|
|
15
|
+
${bold("ambit status")} - Show Network, App, and Router Status
|
|
16
|
+
|
|
17
|
+
${bold("USAGE")}
|
|
18
|
+
ambit status [options]
|
|
19
|
+
ambit status networks [options]
|
|
20
|
+
ambit status network <name> [options]
|
|
21
|
+
ambit status app <app>.<network> [options]
|
|
22
|
+
|
|
23
|
+
${bold("SUBCOMMANDS")}
|
|
24
|
+
networks Show summary of all networks — default when no subcommand given
|
|
25
|
+
network Show detailed status for a specific network
|
|
26
|
+
app Show a specific app's status
|
|
27
|
+
|
|
28
|
+
${bold("OPTIONS")}
|
|
29
|
+
--org <org> Fly.io organization slug
|
|
30
|
+
--json Output as JSON
|
|
31
|
+
|
|
32
|
+
${bold("EXAMPLES")}
|
|
33
|
+
ambit status
|
|
34
|
+
ambit status networks
|
|
35
|
+
ambit status network browsers
|
|
36
|
+
ambit status app my-app.browsers
|
|
37
|
+
|
|
38
|
+
Run 'ambit status networks --help', 'ambit status network --help',
|
|
39
|
+
or 'ambit status app --help' for details.
|
|
40
|
+
`);
|
|
41
|
+
};
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// Dispatcher
|
|
44
|
+
// =============================================================================
|
|
45
|
+
const status = async (argv) => {
|
|
46
|
+
const subcommand = typeof argv[0] === "string" ? argv[0] : undefined;
|
|
47
|
+
if (subcommand === "networks")
|
|
48
|
+
return statusNetworks(argv.slice(1));
|
|
49
|
+
if (subcommand === "network")
|
|
50
|
+
return statusNetwork(argv.slice(1));
|
|
51
|
+
if (subcommand === "app")
|
|
52
|
+
return statusApp(argv.slice(1));
|
|
53
|
+
const args = parseArgs(argv, { boolean: ["help"] });
|
|
54
|
+
if (args.help) {
|
|
55
|
+
showStatusHelp();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
return statusNetworks(argv);
|
|
59
|
+
};
|
|
60
|
+
// =============================================================================
|
|
61
|
+
// Register Command
|
|
62
|
+
// =============================================================================
|
|
63
|
+
registerCommand({
|
|
64
|
+
name: "status",
|
|
65
|
+
description: "Show network, app, and router status",
|
|
66
|
+
usage: "ambit status [networks|network|app] [<name>] [--org <org>] [--json]",
|
|
67
|
+
run: status,
|
|
68
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/network.ts"],"names":[],"mappings":"AAgHA,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAsChE,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Status Network — Show Detailed Status for a Single Network
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
5
|
+
import { bold } from "../../../lib/cli.js";
|
|
6
|
+
import { checkArgs } from "../../../lib/args.js";
|
|
7
|
+
import { createOutput } from "../../../lib/output.js";
|
|
8
|
+
import { findRouterApp, getRouterMachineInfo, getRouterTailscaleInfo, listWorkloadAppsOnNetwork, } from "../../../util/discovery.js";
|
|
9
|
+
import { initSession } from "../../../util/session.js";
|
|
10
|
+
import { SOCKS_PROXY_PORT } from "../../../util/constants.js";
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Detailed View
|
|
13
|
+
// =============================================================================
|
|
14
|
+
const stageNetworkStatus = async (fly, tailscale, network, org, json) => {
|
|
15
|
+
const out = createOutput(json);
|
|
16
|
+
const app = await findRouterApp(fly, org, network);
|
|
17
|
+
if (!app) {
|
|
18
|
+
return out.die(`No Router Found for Network '${network}'`);
|
|
19
|
+
}
|
|
20
|
+
const machine = await getRouterMachineInfo(fly, app.appName);
|
|
21
|
+
const ts = await getRouterTailscaleInfo(tailscale, app.appName);
|
|
22
|
+
const tag = ts?.tags?.[0] ?? null;
|
|
23
|
+
out.blank()
|
|
24
|
+
.header("Ambit Status: Network")
|
|
25
|
+
.blank()
|
|
26
|
+
.text(` Network: ${bold(app.network)}`)
|
|
27
|
+
.text(` TLD: *.${app.network}`)
|
|
28
|
+
.text(` Tag: ${tag ?? "unknown"}`)
|
|
29
|
+
.text(` Status: ${app.status}`)
|
|
30
|
+
.blank()
|
|
31
|
+
.text(` Router App: ${app.appName}`)
|
|
32
|
+
.text(` Region: ${machine?.region ?? "unknown"}`)
|
|
33
|
+
.text(` Machine State: ${machine?.state ?? "no machines"}`)
|
|
34
|
+
.text(` Private IP: ${machine?.privateIp ?? "unknown"}`)
|
|
35
|
+
.text(` SOCKS Proxy: ${machine?.privateIp
|
|
36
|
+
? `socks5://[${machine.privateIp}]:${SOCKS_PROXY_PORT}`
|
|
37
|
+
: "unknown"}`);
|
|
38
|
+
if (machine?.subnet) {
|
|
39
|
+
out.text(` Subnet: ${machine.subnet}`);
|
|
40
|
+
}
|
|
41
|
+
out.blank();
|
|
42
|
+
if (ts) {
|
|
43
|
+
out.text(` Tailscale IP: ${ts.ip}`)
|
|
44
|
+
.text(` Online: ${ts.online ? "yes" : "no"}`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
out.text(" Tailscale: Not Found in Tailnet");
|
|
48
|
+
}
|
|
49
|
+
// Show workload apps on this network
|
|
50
|
+
const workloads = await listWorkloadAppsOnNetwork(fly, org, network);
|
|
51
|
+
if (workloads.length > 0) {
|
|
52
|
+
out.blank().header(" Apps on Network").blank();
|
|
53
|
+
for (const w of workloads) {
|
|
54
|
+
const machines = await fly.machines.list(w.appName);
|
|
55
|
+
const state = machines[0]?.state ?? "no machines";
|
|
56
|
+
const region = machines[0]?.region ?? "-";
|
|
57
|
+
out.text(` ${w.appName} ${region} ${state}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
out.blank();
|
|
61
|
+
out.done({
|
|
62
|
+
network: app.network,
|
|
63
|
+
router: app,
|
|
64
|
+
machine,
|
|
65
|
+
tag,
|
|
66
|
+
tailscale: ts,
|
|
67
|
+
});
|
|
68
|
+
out.print();
|
|
69
|
+
};
|
|
70
|
+
// =============================================================================
|
|
71
|
+
// Status Network Subcommand
|
|
72
|
+
// =============================================================================
|
|
73
|
+
export const statusNetwork = async (argv) => {
|
|
74
|
+
const opts = { string: ["org"], boolean: ["help", "json"] };
|
|
75
|
+
const args = parseArgs(argv, opts);
|
|
76
|
+
checkArgs(args, opts, "ambit status network");
|
|
77
|
+
if (args.help) {
|
|
78
|
+
console.log(`
|
|
79
|
+
${bold("ambit status network")} - Show Detailed Status for a Network
|
|
80
|
+
|
|
81
|
+
${bold("USAGE")}
|
|
82
|
+
ambit status network <name> [--org <org>] [--json]
|
|
83
|
+
|
|
84
|
+
${bold("OPTIONS")}
|
|
85
|
+
--org <org> Fly.io organization slug
|
|
86
|
+
--json Output as JSON
|
|
87
|
+
|
|
88
|
+
${bold("EXAMPLES")}
|
|
89
|
+
ambit status network browsers
|
|
90
|
+
`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const out = createOutput(args.json);
|
|
94
|
+
const network = typeof args._[0] === "string" ? args._[0] : undefined;
|
|
95
|
+
if (!network) {
|
|
96
|
+
return out.die("Missing Network Name. Usage: ambit status network <name>");
|
|
97
|
+
}
|
|
98
|
+
const prereqOut = createOutput(args.json);
|
|
99
|
+
const { fly, tailscale, org } = await initSession(prereqOut, {
|
|
100
|
+
json: args.json,
|
|
101
|
+
org: args.org,
|
|
102
|
+
});
|
|
103
|
+
await stageNetworkStatus(fly, tailscale, network, org, args.json);
|
|
104
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"networks.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/networks.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAwDjE,CAAC"}
|