SSH-key-Manager/edit_host.py
2025-03-08 00:43:33 -06:00

124 lines
3.9 KiB
Python

import os
import asyncio
from collections import OrderedDict
from .utils import print_error, print_warning, print_info, safe_input
from .list_hosts import (
build_host_list_table,
load_config_file,
gather_host_info,
sort_by_ip
)
async def edit_host(conf_dir):
"""
Let the user update fields for an existing host in ~/.ssh/conf/<label>/config.
1) Display the unified table (No. | Host | User | Port | HostName | IP Address | Conf Directory)
2) Prompt row number or host label
3) Rewrite config with updated fields
"""
print_info("Here is the current list of hosts:\n")
headers, final_data = await build_host_list_table(conf_dir)
if not final_data:
print_warning("No hosts to edit.")
return
from tabulate import tabulate
print("\nSSH Conf Subdirectory Host List (Sorted by IP Ascending)")
print(tabulate(final_data, headers=headers, tablefmt="grid"))
choice = safe_input("Enter the row number or the Host label to edit: ")
if choice is None:
return # user canceled (Ctrl+C)
choice = choice.strip()
if not choice:
print_error("Host label or row number cannot be empty.")
return
# We replicate the approach to find the matching block
all_blocks = []
import glob
for cfile in glob.glob(os.path.join(conf_dir, "*", "config")):
all_blocks.extend(load_config_file(cfile))
results = await gather_host_info(all_blocks)
sorted_rows = sort_by_ip(results)
target_tuple = None
if choice.isdigit():
idx = int(choice)
if idx < 1 or idx > len(sorted_rows):
print_warning(f"Row number {idx} is invalid.")
return
target_tuple = sorted_rows[idx - 1]
else:
for t in sorted_rows:
if t[0] == choice: # t[0] => host_label
target_tuple = t
break
if not target_tuple:
print_warning(f"No matching Host '{choice}' found in the table.")
return
host_label = target_tuple[0]
# find the config block
found_block = None
for b in all_blocks:
if b.get("Host") == host_label:
found_block = b
break
if not found_block:
print_warning(f"No config block found for '{host_label}'.")
return
old_hostname = found_block.get("HostName", "")
old_user = found_block.get("User", "")
old_port = found_block.get("Port", "22")
old_identity = found_block.get("IdentityFile", "")
print_info("Leave a field blank to keep its current value.")
new_hostname = safe_input(f"Enter new HostName [{old_hostname}]: ")
if new_hostname is None:
return
new_hostname = new_hostname.strip()
new_user = safe_input(f"Enter new User [{old_user}]: ")
if new_user is None:
return
new_user = new_user.strip()
new_port = safe_input(f"Enter new Port [{old_port}]: ")
if new_port is None:
return
new_port = new_port.strip()
new_ident = safe_input(f"Enter new IdentityFile [{old_identity}]: ")
if new_ident is None:
return
new_ident = new_ident.strip()
final_hostname = new_hostname if new_hostname else old_hostname
final_user = new_user if new_user else old_user
final_port = new_port if new_port else old_port
final_ident = new_ident if new_ident else old_identity
# Overwrite the file
config_path = os.path.join(conf_dir, host_label, "config")
new_config_lines = [
f"Host {host_label}",
f" HostName {final_hostname}",
f" User {final_user}",
f" Port {final_port}"
]
if final_ident:
new_config_lines.append(f" IdentityFile {final_ident}")
try:
with open(config_path, "w") as f:
for line in new_config_lines:
f.write(line + "\n")
print_info(f"Updated config at: {config_path}")
except Exception as e:
print_error(f"Failed to update config: {e}")