sandflare-cli 2.0.26__tar.gz → 2.0.28__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sandflare-cli
3
- Version: 2.0.26
3
+ Version: 2.0.28
4
4
  Summary: Sandflare CLI — manage Firecracker microVM sandboxes
5
5
  License: MIT
6
6
  Keywords: sandflare,sandbox,microvm,ai,firecracker
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sandflare-cli"
7
- version = "2.0.26"
7
+ version = "2.0.28"
8
8
  description = "Sandflare CLI — manage Firecracker microVM sandboxes"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -276,6 +276,62 @@ def sandbox_browser(args):
276
276
  die(f"Unknown browser action: {action}. Valid: screenshot, navigate, text, html, elements, click, type, key, url, start")
277
277
 
278
278
 
279
+ # ── Database commands ─────────────────────────────────────────────────────────
280
+
281
+ def db_create(args):
282
+ body: dict = {}
283
+ if args.label:
284
+ body["label"] = args.label
285
+ if args.size:
286
+ body["size"] = args.size
287
+ result = api("POST", "/databases", body)
288
+ db_id = result.get("exec_id") or result.get("sandbox_id") or result.get("id", "")
289
+ label = result.get("label", "")
290
+ psql_url = result.get("psql_url", "")
291
+ ok(f"Database \033[1m{label or db_id}\033[0m created.")
292
+ if psql_url:
293
+ # Print masked URL for display, then the full one for scripting
294
+ masked = psql_url[:30] + "…" + psql_url[-20:] if len(psql_url) > 55 else psql_url
295
+ info(f"Connection: {masked}")
296
+ print(psql_url)
297
+
298
+
299
+ def db_list(_args):
300
+ result = api("GET", "/databases")
301
+ items = (result or {}).get("databases", [])
302
+ if not items:
303
+ info("No databases found.")
304
+ return
305
+ print_table(
306
+ ["ID", "LABEL", "STATUS", "SIZE", "CREATED"],
307
+ [
308
+ [
309
+ (item.get("exec_id") or item.get("id") or "")[:18],
310
+ item.get("label", ""),
311
+ item.get("status", ""),
312
+ f"{item.get('memory_mb', 0) // 1024}GB" if item.get("memory_mb") else "",
313
+ (item.get("created_at", "") or "")[:10],
314
+ ]
315
+ for item in items
316
+ ],
317
+ [36, 20, 10, 6, 12],
318
+ )
319
+
320
+
321
+ def db_delete(args):
322
+ api("DELETE", f"/databases/{args.id}")
323
+ ok(f"Database \033[1m{args.id}\033[0m deleted.")
324
+
325
+
326
+ def db_url(args):
327
+ """Print the raw psql connection URL — useful for piping to psql."""
328
+ result = api("GET", f"/databases/{args.id}")
329
+ url = result.get("psql_url", "")
330
+ if not url:
331
+ die("No psql_url in response. Database may still be starting.")
332
+ print(url)
333
+
334
+
279
335
  def keys_list(_args):
280
336
  result = api("GET", "/api-keys")
281
337
  items = result if isinstance(result, list) else result.get("keys", [])
@@ -572,9 +628,28 @@ def main():
572
628
  template_delete_parser.add_argument("id", help="Template ID (tpl-xxxxxxxx)")
573
629
  template_delete_parser.set_defaults(func=template_delete)
574
630
 
631
+ db_parser = sub.add_parser("database", aliases=["db"], help="Manage persistent PostgreSQL databases")
632
+ db_sub = db_parser.add_subparsers(dest="action", metavar="<action>")
633
+
634
+ db_create_parser = db_sub.add_parser("create", help="Create a new database")
635
+ db_create_parser.add_argument("--label", "-l", help="Friendly label")
636
+ db_create_parser.add_argument("--size", "-s", default="nano", choices=["nano", "small", "medium"], help="Size (default: nano)")
637
+ db_create_parser.set_defaults(func=db_create)
638
+
639
+ db_list_parser = db_sub.add_parser("list", aliases=["ls"], help="List databases")
640
+ db_list_parser.set_defaults(func=db_list)
641
+
642
+ db_delete_parser = db_sub.add_parser("delete", aliases=["rm", "del"], help="Delete a database")
643
+ db_delete_parser.add_argument("id", help="Database ID")
644
+ db_delete_parser.set_defaults(func=db_delete)
645
+
646
+ db_url_parser = db_sub.add_parser("url", help="Print the psql connection URL")
647
+ db_url_parser.add_argument("id", help="Database ID")
648
+ db_url_parser.set_defaults(func=db_url)
649
+
575
650
  args = parser.parse_args()
576
651
  if not hasattr(args, "func"):
577
- for subparser in [sandbox_parser, keys_parser, config_parser, template_parser]:
652
+ for subparser in [sandbox_parser, keys_parser, config_parser, template_parser, db_parser]:
578
653
  if args.resource in (
579
654
  getattr(subparser, "prog", "").split()[-1:] + list(subparser._option_string_actions.get("aliases", []))
580
655
  ):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sandflare-cli
3
- Version: 2.0.26
3
+ Version: 2.0.28
4
4
  Summary: Sandflare CLI — manage Firecracker microVM sandboxes
5
5
  License: MIT
6
6
  Keywords: sandflare,sandbox,microvm,ai,firecracker
File without changes
File without changes