refactor: rename package from mytoolkit to bin
- Move all source files from mytoolkit/ to bin/ - Update entry point and build config in pyproject.toml - Add pillow and pypdf dependencies - Update README and .gitignore paths - Remove unused subprocess import in pdf.py - Clean up duplicate imports in pdf merge command
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
"""SSH connection utilities."""
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from bin.config import config
|
||||
from bin.utils import handle_errors
|
||||
|
||||
|
||||
def _get_hosts() -> dict:
|
||||
"""Get SSH hosts from config."""
|
||||
hosts = {}
|
||||
for key in config.get_all().keys():
|
||||
if key.startswith("ssh_") and not key.endswith("_port") and not key.endswith("_key"):
|
||||
name = key[4:] # Remove 'ssh_' prefix
|
||||
host = config.get(f"ssh_{name}")
|
||||
port = config.get(f"ssh_{name}_port") or "22"
|
||||
key_file = config.get(f"ssh_{name}_key")
|
||||
if host:
|
||||
hosts[name] = {"host": host, "port": int(port)}
|
||||
if key_file:
|
||||
hosts[name]["key"] = key_file
|
||||
return hosts
|
||||
|
||||
|
||||
def _build_ssh_base_cmd(host_config: dict) -> list[str]:
|
||||
"""Build base SSH command with host and port."""
|
||||
cmd = ["ssh", "-p", str(host_config["port"])]
|
||||
|
||||
if "key" in host_config:
|
||||
key_path = Path(host_config["key"]).expanduser()
|
||||
cmd.extend(["-i", str(key_path)])
|
||||
|
||||
cmd.append(host_config["host"])
|
||||
return cmd
|
||||
|
||||
|
||||
@click.group(name="ssh")
|
||||
def ssh_cmd():
|
||||
"""SSH connection utilities."""
|
||||
pass
|
||||
|
||||
|
||||
@ssh_cmd.command("connect")
|
||||
@click.argument("name")
|
||||
@handle_errors
|
||||
def connect(name):
|
||||
"""Connect to a configured host."""
|
||||
hosts = _get_hosts()
|
||||
if name not in hosts:
|
||||
click.echo(f"Unknown host: {name}", err=True)
|
||||
click.echo(f"Available: {', '.join(hosts.keys())}", err=True)
|
||||
raise click.Exit(1)
|
||||
|
||||
cmd = _build_ssh_base_cmd(hosts[name])
|
||||
click.secho(f"Connecting to {name}...", fg="cyan")
|
||||
subprocess.run(cmd)
|
||||
|
||||
|
||||
@ssh_cmd.command("tunnel")
|
||||
@click.argument("name")
|
||||
@click.option("--local-port", "-l", default=11111, help="Local port")
|
||||
@click.option("--remote-port", "-r", default=11111, help="Remote port")
|
||||
@handle_errors
|
||||
def tunnel(name, local_port, remote_port):
|
||||
"""Create SSH tunnel with port forwarding."""
|
||||
hosts = _get_hosts()
|
||||
if name not in hosts:
|
||||
click.echo(f"Unknown host: {name}", err=True)
|
||||
raise click.Exit(1)
|
||||
|
||||
host_config = hosts[name]
|
||||
cmd = ["ssh", "-p", str(host_config["port"]), "-L", f"{local_port}:localhost:{remote_port}"]
|
||||
|
||||
if "key" in host_config:
|
||||
key_path = Path(host_config["key"]).expanduser()
|
||||
cmd.extend(["-i", str(key_path)])
|
||||
|
||||
cmd.append(host_config["host"])
|
||||
|
||||
click.secho(f"Creating tunnel {local_port} -> {remote_port} on {name}...", fg="cyan")
|
||||
click.secho(f"Command: {' '.join(cmd)}", fg="dim")
|
||||
subprocess.run(cmd)
|
||||
|
||||
|
||||
@ssh_cmd.command("list")
|
||||
def list_hosts():
|
||||
"""List configured SSH hosts."""
|
||||
hosts = _get_hosts()
|
||||
click.secho("Configured hosts:", fg="cyan")
|
||||
for name, host_config in sorted(hosts.items()):
|
||||
click.echo(f" {name:12} {host_config['host']}:{host_config['port']}")
|
||||
|
||||
|
||||
@ssh_cmd.command("cmd")
|
||||
@click.argument("name")
|
||||
@click.argument("command")
|
||||
@handle_errors
|
||||
def run_cmd(name, command):
|
||||
"""Run a command on remote host."""
|
||||
hosts = _get_hosts()
|
||||
if name not in hosts:
|
||||
click.echo(f"Unknown host: {name}", err=True)
|
||||
raise click.Exit(1)
|
||||
|
||||
cmd = _build_ssh_base_cmd(hosts[name])
|
||||
cmd.append(command)
|
||||
|
||||
subprocess.run(cmd)
|
||||
Reference in New Issue
Block a user