refactored code
This commit is contained in:
parent
73429771d4
commit
414266eefc
6 changed files with 315 additions and 404 deletions
165
edit_host.py
165
edit_host.py
|
@ -2,98 +2,31 @@ import os
|
|||
import asyncio
|
||||
from collections import OrderedDict
|
||||
from .utils import print_error, print_warning, print_info, safe_input
|
||||
from .list_hosts import list_hosts, load_config_file, check_ssh_port
|
||||
from .list_hosts import (
|
||||
build_host_list_table,
|
||||
load_config_file,
|
||||
gather_host_info,
|
||||
sort_by_ip
|
||||
)
|
||||
|
||||
async def get_all_host_blocks(conf_dir):
|
||||
"""
|
||||
Similar to list_hosts, but returns the list of host blocks + a table of results.
|
||||
We'll build a table ourselves so we can map row numbers to actual host labels.
|
||||
"""
|
||||
import glob
|
||||
import socket
|
||||
|
||||
pattern = os.path.join(conf_dir, "*", "config")
|
||||
conf_files = sorted(glob.glob(pattern))
|
||||
|
||||
all_blocks = []
|
||||
for conf_file in conf_files:
|
||||
blocks = load_config_file(conf_file)
|
||||
all_blocks.extend(blocks)
|
||||
|
||||
# If no blocks found, return empty
|
||||
if not all_blocks:
|
||||
return []
|
||||
|
||||
# We want to do a partial version of check_host to get row data
|
||||
# so we can display the table right here and keep track of each block’s host label.
|
||||
# But let's do it similarly to list_hosts:
|
||||
|
||||
table_rows = []
|
||||
for idx, b in enumerate(all_blocks, start=1):
|
||||
host_label = b.get("Host", "N/A")
|
||||
hostname = b.get("HostName", "N/A")
|
||||
user = b.get("User", "N/A")
|
||||
port = int(b.get("Port", "22"))
|
||||
identity_file = b.get("IdentityFile", "N/A")
|
||||
|
||||
# Identity check
|
||||
if identity_file != "N/A":
|
||||
expanded_identity = os.path.expanduser(identity_file)
|
||||
identity_exists = os.path.isfile(expanded_identity)
|
||||
else:
|
||||
identity_exists = False
|
||||
|
||||
# IP resolution
|
||||
try:
|
||||
ip_address = socket.gethostbyname(hostname)
|
||||
except socket.error:
|
||||
ip_address = None
|
||||
|
||||
# Port check
|
||||
if ip_address:
|
||||
port_open = await asyncio.wait_for(check_ssh_port(ip_address, port), timeout=1)
|
||||
else:
|
||||
port_open = False
|
||||
|
||||
# Colors for display (optional, or we can keep it simple):
|
||||
ip_display = f"\033[0;32m{ip_address}\033[0m" if ip_address else "\033[0;31mN/A\033[0m"
|
||||
port_display = f"\033[0;32m{port}\033[0m" if port_open else f"\033[0;31m{port}\033[0m"
|
||||
identity_disp= f"\033[0;32m{identity_file}\033[0m" if identity_exists else f"\033[0;31m{identity_file}\033[0m"
|
||||
|
||||
row = [
|
||||
idx,
|
||||
host_label,
|
||||
user,
|
||||
port_display,
|
||||
hostname,
|
||||
ip_display,
|
||||
identity_disp
|
||||
]
|
||||
table_rows.append(row)
|
||||
|
||||
# Print the table
|
||||
from tabulate import tabulate
|
||||
headers = ["No.", "Host", "User", "Port", "HostName", "IP Address", "IdentityFile"]
|
||||
print("\nSSH Conf Subdirectory Host List")
|
||||
print(tabulate(table_rows, headers=headers, tablefmt="grid"))
|
||||
|
||||
return all_blocks
|
||||
|
||||
def edit_host(conf_dir):
|
||||
async def edit_host(conf_dir):
|
||||
"""
|
||||
Let the user update fields for an existing host in ~/.ssh/conf/<label>/config.
|
||||
The user may type either the row number OR the actual host label.
|
||||
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
|
||||
"""
|
||||
|
||||
# 1) Gather + display the current host list
|
||||
print_info("Here is the current list of hosts:\n")
|
||||
all_blocks = asyncio.run(get_all_host_blocks(conf_dir))
|
||||
|
||||
if not all_blocks:
|
||||
print_warning("No hosts found to edit.")
|
||||
headers, final_data = await build_host_list_table(conf_dir)
|
||||
if not final_data:
|
||||
print_warning("No hosts to edit.")
|
||||
return
|
||||
|
||||
# 2) Prompt for which host to edit (by label or row number)
|
||||
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)
|
||||
|
@ -102,43 +35,47 @@ def edit_host(conf_dir):
|
|||
print_error("Host label or row number cannot be empty.")
|
||||
return
|
||||
|
||||
# Check if user typed a digit -> row number
|
||||
target_block = None
|
||||
# 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():
|
||||
row_idx = int(choice)
|
||||
# Validate index
|
||||
if row_idx < 1 or row_idx > len(all_blocks):
|
||||
print_warning(f"Invalid row number {row_idx}.")
|
||||
idx = int(choice)
|
||||
if idx < 1 or idx > len(sorted_rows):
|
||||
print_warning(f"Row number {idx} is invalid.")
|
||||
return
|
||||
target_block = all_blocks[row_idx - 1] # zero-based
|
||||
target_tuple = sorted_rows[idx - 1]
|
||||
else:
|
||||
# The user typed a host label
|
||||
# We must search all_blocks for a matching Host
|
||||
for b in all_blocks:
|
||||
if b.get("Host") == choice:
|
||||
target_block = b
|
||||
for t in sorted_rows:
|
||||
if t[0] == choice: # t[0] => host_label
|
||||
target_tuple = t
|
||||
break
|
||||
if not target_block:
|
||||
print_warning(f"No matching host label '{choice}' found.")
|
||||
if not target_tuple:
|
||||
print_warning(f"No matching Host '{choice}' found in the table.")
|
||||
return
|
||||
|
||||
# Now we have a target_block with existing data
|
||||
host_label = target_block.get("Host", "")
|
||||
if not host_label:
|
||||
print_warning("This host block has no label. Cannot edit.")
|
||||
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
|
||||
|
||||
# Derive the config path
|
||||
host_dir = os.path.join(conf_dir, host_label)
|
||||
config_path = os.path.join(host_dir, "config")
|
||||
if not os.path.isfile(config_path):
|
||||
print_warning(f"No config file found at {config_path}; cannot edit this host.")
|
||||
return
|
||||
|
||||
old_hostname = target_block.get("HostName", "")
|
||||
old_user = target_block.get("User", "")
|
||||
old_port = target_block.get("Port", "22")
|
||||
old_identity = target_block.get("IdentityFile", "")
|
||||
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.")
|
||||
|
||||
|
@ -167,6 +104,8 @@ def edit_host(conf_dir):
|
|||
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}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue