cloudwire 0.1.0__py3-none-any.whl

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.
cloudwire/cli.py ADDED
@@ -0,0 +1,86 @@
1
+ """CLI entry point for CloudWire."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import socket
7
+ import threading
8
+ import webbrowser
9
+
10
+ import click
11
+ import uvicorn
12
+
13
+ from . import __version__
14
+
15
+
16
+ def _port_is_available(host: str, port: int) -> bool:
17
+ """Return True if the port is free to bind on the given host."""
18
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
19
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
20
+ try:
21
+ sock.bind((host, port))
22
+ return True
23
+ except OSError:
24
+ return False
25
+
26
+
27
+ @click.command()
28
+ @click.option("--port", default=8080, show_default=True, help="Local port to listen on.")
29
+ @click.option("--host", default="127.0.0.1", show_default=True, help="Bind address. Never expose 0.0.0.0 on untrusted networks.")
30
+ @click.option("--profile", default=None, envvar="AWS_PROFILE", help="AWS credentials profile from ~/.aws/credentials.")
31
+ @click.option("--region", default="us-east-1", show_default=True, envvar="AWS_DEFAULT_REGION", help="Default AWS region.")
32
+ @click.option("--no-browser", is_flag=True, default=False, help="Do not open the browser automatically.")
33
+ @click.option("--print-url", is_flag=True, default=False, help="Print the URL to stdout and exit (useful for SSH tunnels).")
34
+ @click.version_option(version=__version__, prog_name="cloudwire")
35
+ def main(port: int, host: str, profile: str | None, region: str, no_browser: bool, print_url: bool) -> None:
36
+ """Scan and visualize your AWS infrastructure as an interactive graph.
37
+
38
+ AWS credentials are read from the standard credential chain:
39
+ environment variables, ~/.aws/credentials profiles, and instance metadata.
40
+ Tools like saml2aws, aws-vault, and aws sso login all write to ~/.aws/credentials
41
+ and work automatically.
42
+
43
+ \b
44
+ Examples:
45
+ cloudwire # use default AWS profile
46
+ cloudwire --profile staging # use a named profile
47
+ cloudwire --region eu-west-1 # override region
48
+ cloudwire --port 9000 --no-browser # custom port, skip auto-open
49
+ cloudwire --print-url # print URL only (SSH tunnel use case)
50
+ """
51
+ url = f"http://localhost:{port}"
52
+
53
+ # --print-url: just output the URL and exit (for scripting / SSH tunnels)
54
+ if print_url:
55
+ click.echo(url)
56
+ return
57
+
58
+ if profile:
59
+ os.environ["AWS_PROFILE"] = profile
60
+
61
+ # Only set region if not already in environment
62
+ os.environ.setdefault("AWS_DEFAULT_REGION", region)
63
+
64
+ # Port conflict check — fail fast with a clear message
65
+ if not _port_is_available(host, port):
66
+ raise click.ClickException(
67
+ f"Port {port} is already in use. Try a different port with --port <number>."
68
+ )
69
+
70
+ click.echo("")
71
+ click.echo(f" cloudwire {__version__}")
72
+ click.echo(f" Running at → {url}")
73
+ click.echo(" Press Ctrl+C to stop.\n")
74
+
75
+ if not no_browser:
76
+ threading.Timer(1.5, lambda: webbrowser.open(url)).start()
77
+
78
+ try:
79
+ uvicorn.run(
80
+ "cloudwire.app.main:app",
81
+ host=host,
82
+ port=port,
83
+ log_level="warning",
84
+ )
85
+ except KeyboardInterrupt:
86
+ click.echo("\n Stopped.")