mirror of
https://github.com/trycua/computer.git
synced 2026-05-06 15:12:38 -05:00
added create and delete cli
This commit is contained in:
@@ -24,6 +24,11 @@ bun run ./index.ts -- --help
|
||||
|
||||
- **VMs**
|
||||
- `cua vm list`
|
||||
- `cua vm create --os OS --configuration SIZE --region REGION` – creates a new VM
|
||||
- OS: `linux`, `windows`, `macos`
|
||||
- SIZE: `small`, `medium`, `large`
|
||||
- REGION: `north-america`, `europe`, `asia-pacific`, `south-america`
|
||||
- `cua vm delete NAME` – deletes a VM
|
||||
- `cua vm start NAME`
|
||||
- `cua vm stop NAME`
|
||||
- `cua vm restart NAME`
|
||||
|
||||
@@ -32,6 +32,106 @@ export function registerVmCommands(y: Argv) {
|
||||
printVmList(data);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"create",
|
||||
"Create a new VM",
|
||||
(y) => y
|
||||
.option("os", {
|
||||
type: "string",
|
||||
choices: ["linux", "windows", "macos"],
|
||||
demandOption: true,
|
||||
describe: "Operating system"
|
||||
})
|
||||
.option("configuration", {
|
||||
type: "string",
|
||||
choices: ["small", "medium", "large"],
|
||||
demandOption: true,
|
||||
describe: "VM size configuration"
|
||||
})
|
||||
.option("region", {
|
||||
type: "string",
|
||||
choices: ["north-america", "europe", "asia-pacific", "south-america"],
|
||||
demandOption: true,
|
||||
describe: "VM region"
|
||||
}),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const { os, configuration, region } = argv as { os: string; configuration: string; region: string };
|
||||
|
||||
const res = await http("/v1/vms", {
|
||||
token,
|
||||
method: "POST",
|
||||
body: { os, configuration, region }
|
||||
});
|
||||
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (res.status === 400) {
|
||||
console.error("Invalid request or unsupported configuration");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (res.status === 500) {
|
||||
console.error("Internal server error");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (res.status === 200) {
|
||||
// VM ready immediately
|
||||
const data = await res.json() as { status: string; name: string; password: string; host: string };
|
||||
console.log(`VM created and ready: ${data.name}`);
|
||||
console.log(`Password: ${data.password}`);
|
||||
console.log(`Host: ${data.host}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === 202) {
|
||||
// VM provisioning started
|
||||
const data = await res.json() as { status: string; name: string; job_id: string };
|
||||
console.log(`VM provisioning started: ${data.name}`);
|
||||
console.log(`Job ID: ${data.job_id}`);
|
||||
console.log("Use 'cua vm list' to monitor provisioning progress");
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(`Unexpected status: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"delete <name>",
|
||||
"Delete a VM",
|
||||
(y) => y.positional("name", { type: "string", describe: "VM name" }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
const res = await http(`/v1/vms/${encodeURIComponent(name)}`, { token, method: "DELETE" });
|
||||
|
||||
if (res.status === 202) {
|
||||
const body = await res.json().catch(() => ({})) as { status?: string };
|
||||
console.log(`VM deletion initiated: ${body.status ?? "deleting"}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === 404) {
|
||||
console.error("VM not found or not owned by you");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.error(`Unexpected status: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"start <name>",
|
||||
"Start a VM",
|
||||
|
||||
@@ -10,12 +10,12 @@ export async function writeEnvFile(cwd: string, key: string) {
|
||||
}
|
||||
|
||||
export type VmStatus = "pending" | "running" | "stopped" | "terminated" | "failed";
|
||||
export type VmItem = { name: string; password: string; status: VmStatus };
|
||||
export type VmItem = { name: string; password: string; status: VmStatus; host?: string };
|
||||
|
||||
export function printVmList(items: VmItem[]) {
|
||||
const rows: string[][] = [["NAME", "STATUS", "PASSWORD"], ...items.map(v => [v.name, String(v.status), v.password])];
|
||||
const widths: number[] = [0, 0, 0];
|
||||
for (const r of rows) for (let i = 0; i < 3; i++) widths[i] = Math.max(widths[i] ?? 0, (r[i] ?? "").length);
|
||||
const rows: string[][] = [["NAME", "STATUS", "PASSWORD", "HOST"], ...items.map(v => [v.name, String(v.status), v.password, v.host || ""])];
|
||||
const widths: number[] = [0, 0, 0, 0];
|
||||
for (const r of rows) for (let i = 0; i < 4; i++) widths[i] = Math.max(widths[i] ?? 0, (r[i] ?? "").length);
|
||||
for (const r of rows) console.log(r.map((c, i) => (c ?? "").padEnd(widths[i] ?? 0)).join(" "));
|
||||
if (items.length === 0) console.log("No VMs found");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user