Skip to content

Commit 6a1d2c9

Browse files
committed
Added support for identity files in the CLI and TUI.
Added support for forward ports. Excplicitly declared password and start commands to be NotYetImplemented.
1 parent 9081155 commit 6a1d2c9

File tree

4 files changed

+112
-12
lines changed

4 files changed

+112
-12
lines changed

cli/sshaman_cli.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ def initialize_sample(config_path):
4949
@click.argument('alias')
5050
@click.argument('host')
5151
@click.argument('user')
52-
@click.option('--port', required=False, default=22)
53-
@click.option('--identity_file', required=False, default='')
54-
@click.option('--password', required=False, default='')
55-
@click.option('--forward_ports', required=False)
56-
@click.option('--start_commands', required=False)
52+
@click.option('--port', '-p', required=False, default=22)
53+
@click.option('--identity_file', '-i', required=False, default='')
54+
@click.option('--password', '-P', required=False, default='')
55+
@click.option('--forward_ports', '-fp', required=False, multiple=True)
56+
@click.option('--start_commands', '-sc', required=False, multiple=True)
5757
@click.option('--config_path', required=False)#, default='')
5858
def add_server(group_path, alias, host, user, port=22, config_path=CONFIG_PATH, **kwargs):
5959
"""Add a server to a group."""

management/sshman.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ def add_server(self, group_path, alias, host, user, port, **kwargs):
6363
"""
6464
last_group = self.make_group(group_path)
6565

66+
if kwargs.get('forward_ports'):
67+
kwargs['forward_ports'] = list(kwargs['forward_ports'])
68+
69+
if kwargs.get('start_commands'):
70+
raise NotImplementedError("Start commands are not supported yet.")
71+
kwargs['start_commands'] = list(kwargs['start_commands'])
72+
6673
# Create a server and add it to the last group
6774
server_data = {'alias': alias,
6875
'host': host,
@@ -76,6 +83,4 @@ def add_server(self, group_path, alias, host, user, port, **kwargs):
7683
server_data['start_commands'] = ['']
7784

7885
server = Server(**server_data)
79-
from pprint import pprint
80-
pprint(server.dict())
8186
last_group.add_server(server)

tui/ssh_connections/ssh_connect.py

+77-4
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,93 @@ def retrieve_file(config_path):
5050

5151
with open(config_path, "r") as json_file:
5252
config = json.load(json_file)
53+
if config.get('user') is None:
54+
config['user'] = get_user_from_os()
55+
56+
if config.get('password'):
57+
raise NotImplementedError("Password authentication is not supported yet.")
58+
59+
if config.get('identity_file'):
60+
config['identity_file'] = find_identity_file(config['identity_file'])
61+
else:
62+
# Declare the default identity file of id_rsa
63+
config['identity_file'] = os.path.join(get_user_ssh_dir_from_home(), 'id_rsa')
64+
5365
return config
5466

5567

68+
def get_user_from_os():
69+
"""
70+
Attempt to get the user from the OS; assumes that the user you are trying to connect is the same as the user
71+
that is invoking the command.
72+
:return:
73+
"""
74+
return os.getlogin()
75+
76+
77+
def get_user_ssh_dir_from_home():
78+
"""
79+
Gets the SSH directory for the current user.
80+
:return:
81+
"""
82+
return os.path.join(os.path.expanduser('~'), '.ssh')
83+
84+
85+
def find_identity_file(identity_file):
86+
"""
87+
Finds the identity file from the SSH directory.
88+
:param identity_file:
89+
:return:
90+
"""
91+
# Determine if the identity file is just the name of a file or if it's a path:
92+
if os.path.isabs(identity_file) or identity_file.startswith('~'):
93+
if os.path.exists(identity_file):
94+
return identity_file
95+
else:
96+
raise FileNotFoundError(f"Identity file not found: {identity_file}")
97+
else:
98+
ssh_dir = get_user_ssh_dir_from_home()
99+
identity_file_path = os.path.join(ssh_dir, identity_file)
100+
if os.path.exists(identity_file_path):
101+
return identity_file_path
102+
else:
103+
raise FileNotFoundError(f"Identity file not found: {identity_file_path}")
104+
105+
def remove_double_spaces(string):
106+
"""
107+
Removes double spaces from a string.
108+
:param string:
109+
:return:
110+
"""
111+
return ' '.join(string.split())
112+
56113
def connect_shell(config_path):
57114
config = retrieve_file(config_path)
58-
command = f"ssh {config['user']}@{config['host']} -p {config['port']}"
59-
print(f'Running: {command}')
115+
116+
fp = ''
117+
if config.get('forward_ports'):
118+
for p in config['forward_ports']:
119+
fp += f' -L {p} '
120+
121+
idf = f'-i {config["identity_file"]}'
122+
123+
command = f"ssh {fp} {idf} {config['user']}@{config['host']} -p {config['port']}"
124+
command = remove_double_spaces(command)
125+
126+
if config.get('start_commands'):
127+
raise NotImplementedError("Start commands are not supported yet.")
128+
command = [command] + config['start_commands']
129+
60130
return command
61131

62132

63133
def connect_sftp(config_path):
64134
config = retrieve_file(config_path)
65-
command = f"sftp -P {config['port']} {config['user']}@{config['host']} "
66-
print(f'Running: {command}')
135+
136+
idf = f"-i {config['identity_file']} "
137+
138+
command = f"sftp {idf} -P {config['port']} {config['user']}@{config['host']} "
139+
command = remove_double_spaces(command)
67140
return command
68141

69142

tui/tree.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
python code_browser.py PATH
77
"""
88
import json
9+
import logging
910
import subprocess
1011
from rich.syntax import Syntax
1112
from rich.traceback import Traceback
13+
import sys
1214

1315
from textual.app import App, ComposeResult
1416
from textual.containers import Container, VerticalScroll
@@ -133,4 +135,24 @@ def main():
133135

134136
if getattr(app, 'command', False):
135137
print(dynamic_data)
136-
subprocess.run(dynamic_data, shell=True)
138+
# Run the commands in the shell if multiple are specified
139+
if isinstance(dynamic_data, list):
140+
for i, command in enumerate(dynamic_data):
141+
if i == 0:
142+
# Fail if the command does not successfully run
143+
error = subprocess.run(command, shell=True, capture_output=True)
144+
if error.returncode != 0:
145+
ssh_err = f"\nError Connecting to Server:\n{error.stderr.decode('utf-8')}"
146+
print(ssh_err)
147+
sys.exit(error.returncode)
148+
else:
149+
error = subprocess.run(command, shell=True)
150+
if error.returncode != 0:
151+
ssh_err = error.stderr.decode('utf-8')
152+
error_msg = f"Error running command: {command} after connecting to the server."
153+
error_msg += '\n{}'.format(ssh_err)
154+
raise RuntimeError(error_msg)
155+
156+
# Otherwise, just connect:
157+
elif isinstance(dynamic_data, str):
158+
subprocess.run(dynamic_data, shell=True)

0 commit comments

Comments
 (0)