@ornncompute/cli 0.1.2 → 0.1.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 +69 -18
- package/package.json +2 -2
- package/src/api-client.mjs +17 -1
- package/src/cli.mjs +2796 -315
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Ornn CLI
|
|
2
2
|
|
|
3
|
-
Command-line access for Ornn
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Command-line access for Ornn compute workflows: browse Listings, buy capacity,
|
|
4
|
+
bid in Exchange, manage GPU reservations, launch VM or Bare Metal machines,
|
|
5
|
+
create Kubernetes or Slurm clusters, manage private networks and storage
|
|
6
|
+
volumes, attach SSH keys, SSH into launched machines, watch machine health
|
|
7
|
+
metrics, and view billing readouts.
|
|
6
8
|
|
|
7
9
|
For the end-user install, browser-login, command, and troubleshooting guide, see
|
|
8
10
|
the [`docs/cli.md`](../../docs/cli.md) guide.
|
|
@@ -28,38 +30,87 @@ ornn help [command]
|
|
|
28
30
|
ornn login [--auth-base <url>] [--no-browser] [--timeout <seconds>]
|
|
29
31
|
ornn whoami [--json]
|
|
30
32
|
ornn status [--json]
|
|
31
|
-
ornn
|
|
32
|
-
ornn
|
|
33
|
+
ornn listings list [--gpu-type <type>] [--facility <name>] [--operator <name>] [--json]
|
|
34
|
+
ornn listings show <listing-id> [--open] [--json]
|
|
33
35
|
ornn buy <listing-id> [--no-open] [--json]
|
|
34
|
-
ornn
|
|
35
|
-
ornn
|
|
36
|
-
ornn
|
|
37
|
-
ornn
|
|
38
|
-
ornn
|
|
39
|
-
ornn
|
|
40
|
-
ornn
|
|
41
|
-
ornn
|
|
36
|
+
ornn exchange create <listing-id> --gpu-count <n> --min-gpu-count <n> --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd> [--no-open] [--json]
|
|
37
|
+
ornn exchange list [--json]
|
|
38
|
+
ornn exchange show <bid-id> [--open] [--json]
|
|
39
|
+
ornn exchange update <bid-id> --gpu-count <n> --min-gpu-count <n> --start-date <yyyy-mm-dd> --end-date <yyyy-mm-dd> --price <usd>
|
|
40
|
+
ornn exchange withdraw <bid-id>
|
|
41
|
+
ornn gpus list [--status <status>] [--json]
|
|
42
|
+
ornn gpus show <reservation-id> [--open] [--json]
|
|
43
|
+
ornn gpus checkout <reservation-id> [--no-open] [--json]
|
|
44
|
+
ornn nodes list [--json]
|
|
45
|
+
ornn nodes show <node-id> [--json]
|
|
46
|
+
ornn nodes launch <reservation-id> --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--network public|private] [--storage-load-drive-id <id>] [--storage-save-drive-id <id>] [--wait] [--json]
|
|
47
|
+
ornn nodes wait <node-or-reservation-id> [--timeout <seconds>] [--json]
|
|
48
|
+
ornn nodes start <node-id> [--json]
|
|
49
|
+
ornn nodes stop <node-id> [--json]
|
|
50
|
+
ornn nodes teardown <node-id> [--json]
|
|
51
|
+
ornn nodes revoke <node-id> [--json]
|
|
52
|
+
ornn nodes ssh-command <node-or-reservation-id> [--json]
|
|
53
|
+
ornn nodes keys attach <node-id> --key <path|id|label> [--json]
|
|
54
|
+
ornn nodes keys list <node-id> [--json]
|
|
55
|
+
ornn ssh <node-or-reservation-id> [--print] [--identity-file <path>] [--user <name>] [--json]
|
|
56
|
+
ornn metrics nodes [--json]
|
|
57
|
+
ornn metrics node <node-id> [--json]
|
|
58
|
+
ornn metrics history <node-id> [--start <iso>] [--end <iso>] [--max-points <n>] [--json]
|
|
59
|
+
ornn metrics watch <node-id> [--interval <seconds>] [--count <n>] [--timeout <seconds>] [--json]
|
|
60
|
+
ornn clusters list [--json]
|
|
61
|
+
ornn clusters reservations [--json]
|
|
62
|
+
ornn clusters eligible-nodes <reservation-id> [--type kubernetes|slurm] [--network public|private] [--json]
|
|
63
|
+
ornn clusters create <reservation-id> --type kubernetes|slurm [--network public|private] [--node <node-id>] [--node-count <n>] [--wait] [--json]
|
|
64
|
+
ornn clusters show <reservation-id> [--type kubernetes|slurm] [--json]
|
|
65
|
+
ornn clusters wait <reservation-id> [--type kubernetes|slurm] [--timeout <seconds>] [--json]
|
|
66
|
+
ornn clusters credentials <reservation-id> [--type kubernetes|slurm] [--json]
|
|
67
|
+
ornn clusters kubeconfig <reservation-id> [--output <path>] [--json]
|
|
68
|
+
ornn clusters ssh-command <reservation-id> [--identity-file <path>] [--user <name>] [--json]
|
|
69
|
+
ornn clusters ssh <reservation-id> [--print] [--identity-file <path>] [--user <name>] [--json]
|
|
70
|
+
ornn clusters add-node <reservation-id> --node <node-id> [--json]
|
|
71
|
+
ornn clusters remove-node <reservation-id> --node <node-id> [--json]
|
|
72
|
+
ornn clusters teardown <reservation-id> [--type kubernetes|slurm] [--json]
|
|
73
|
+
ornn networks list [--json]
|
|
74
|
+
ornn networks show <network-id> [--json]
|
|
75
|
+
ornn networks create --name <name> [--cidr <cidr>] [--description <text>] [--json]
|
|
76
|
+
ornn networks update <network-id> [--name <name>] [--description <text>] [--clear-description] [--json]
|
|
77
|
+
ornn networks delete <network-id> [--json]
|
|
78
|
+
ornn networks reservation <reservation-id> [--json]
|
|
79
|
+
ornn networks attach <reservation-id> --network <network-id> [--json]
|
|
80
|
+
ornn networks detach <reservation-id> [--json]
|
|
81
|
+
ornn storage volumes list [--json]
|
|
82
|
+
ornn storage volumes show <drive-id> [--json]
|
|
83
|
+
ornn storage volumes create --name <name> [--source <drive-id>] [--json]
|
|
84
|
+
ornn storage volumes refresh <drive-id> [--json]
|
|
85
|
+
ornn storage volumes clear <drive-id> [--json]
|
|
86
|
+
ornn storage volumes delete <drive-id> [--json]
|
|
87
|
+
ornn keys list [--json]
|
|
88
|
+
ornn keys add [<public-key-file>] [--public-key <key>] [--label <label>] [--json]
|
|
89
|
+
ornn keys delete <key-id> [--json]
|
|
42
90
|
ornn access show <reservation-id> [--json]
|
|
43
|
-
ornn access activate <reservation-id> --
|
|
91
|
+
ornn access activate <reservation-id> --key <path|id|label> [--mode bare-metal|vm] [--username <name>] [--network public|private] [--storage-load-drive-id <id>] [--storage-save-drive-id <id>] [--wait] [--no-open] [--json]
|
|
44
92
|
ornn access push-keys <reservation-id> --ssh-key-id <id> [--json]
|
|
45
93
|
ornn access keys list <reservation-id> [--json]
|
|
46
94
|
ornn access keys add <reservation-id> --public-key <key> [--label <label>] [--json]
|
|
47
95
|
ornn access keys add <reservation-id> --public-key-file <path> [--label <label>] [--json]
|
|
48
96
|
ornn access keys push <reservation-id> --ssh-key-id <id> [--json]
|
|
49
97
|
ornn access keys status <reservation-id> [--json]
|
|
50
|
-
ornn resale browse [--json]
|
|
51
|
-
ornn resale list <reservation-id> --ask-price <usd> [--no-open] [--json]
|
|
52
|
-
ornn resale update <reservation-id> --ask-price <usd> [--no-open] [--json]
|
|
53
|
-
ornn resale delist <reservation-id> [--no-open] [--json]
|
|
54
98
|
ornn ssh-keys list [--json]
|
|
55
99
|
ornn ssh-keys add --public-key <key> [--label <label>] [--json]
|
|
56
100
|
ornn ssh-keys add --public-key-file <path> [--label <label>] [--json]
|
|
57
101
|
ornn ssh-keys delete <key-id> [--json]
|
|
102
|
+
ornn billing summary [--json]
|
|
103
|
+
ornn billing invoices [--json]
|
|
104
|
+
ornn billing showback --start <yyyy-mm-dd> --end <yyyy-mm-dd> [--json]
|
|
58
105
|
ornn billing open [--no-open] [--json]
|
|
59
106
|
ornn api <get|post|patch|put|delete> <compute-path> [--data <json>] [--raw]
|
|
60
107
|
ornn logout
|
|
61
108
|
```
|
|
62
109
|
|
|
110
|
+
UI aliases are first-class in the CLI: `listings` maps to the older
|
|
111
|
+
`availability` command, `exchange` maps to `bid`, and `gpus` maps to
|
|
112
|
+
`reservations`. The older command names remain available for scripts.
|
|
113
|
+
|
|
63
114
|
Commands print concise human-readable output by default. Use `--json` on
|
|
64
115
|
read/show/list commands and transaction handoffs when you need structured
|
|
65
116
|
stdout for scripts. Errors and login/browser progress go to stderr.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ornncompute/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Command-line interface for Ornn
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Command-line interface for Ornn compute access workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"ornn": "bin/ornn.js"
|
package/src/api-client.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadAuthSession } from "./auth-store.mjs";
|
|
1
|
+
import { clearAuthSession, loadAuthSession } from "./auth-store.mjs";
|
|
2
2
|
import { resolveAuthBaseUrl } from "./device-auth.mjs";
|
|
3
3
|
|
|
4
4
|
export class CliApiError extends Error {
|
|
@@ -70,12 +70,18 @@ export async function cliRequest({
|
|
|
70
70
|
if (raw) {
|
|
71
71
|
const text = await response.text();
|
|
72
72
|
if (!response.ok) {
|
|
73
|
+
await handleAuthExpiry({ env, response, hadToken: Boolean(authSession?.accessToken) });
|
|
73
74
|
throw new CliApiError(text || response.statusText, { status: response.status });
|
|
74
75
|
}
|
|
75
76
|
return text;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const text = await response.text();
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
// Clear a dead token before parsing, so a 401 with a non-JSON body
|
|
82
|
+
// (e.g. a gateway/WAF error page) still triggers the re-login flow.
|
|
83
|
+
await handleAuthExpiry({ env, response, hadToken: Boolean(authSession?.accessToken) });
|
|
84
|
+
}
|
|
79
85
|
const data = text ? parseJson(text, url.toString(), response) : null;
|
|
80
86
|
if (!response.ok) {
|
|
81
87
|
const detail = data?.detail ?? data?.error ?? response.statusText;
|
|
@@ -119,6 +125,16 @@ function parseJson(text, url, response) {
|
|
|
119
125
|
}
|
|
120
126
|
}
|
|
121
127
|
|
|
128
|
+
async function handleAuthExpiry({ env, response, hadToken }) {
|
|
129
|
+
if (response.status !== 401 || !hadToken) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
await clearAuthSession({ env });
|
|
133
|
+
throw new CliApiError("Your Ornn session has expired or was revoked. Run `ornn login` to sign in again.", {
|
|
134
|
+
status: 401,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
122
138
|
function detailMessage(detail) {
|
|
123
139
|
if (typeof detail === "string") {
|
|
124
140
|
return detail;
|