Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional alias parameter to host config #355

Merged
merged 57 commits into from
Aug 20, 2022
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d7c6933
added alias parameter
simonfelding Aug 2, 2022
f3a11de
added alias parameter
simonfelding Aug 2, 2022
2024ac3
fix syntax error
simonfelding Aug 2, 2022
d657374
added alias parameter
simonfelding Aug 2, 2022
ac085bc
fix: alias is optional
simonfelding Aug 2, 2022
f02b6c6
add alias parameter to self
simonfelding Aug 2, 2022
35f11e8
add test: if alias passes through properly
simonfelding Aug 2, 2022
e17d3c9
update alias passthrough test
simonfelding Aug 2, 2022
0892b6b
update alias test - look in output, not client
simonfelding Aug 2, 2022
afa6c92
add alias parameter
simonfelding Aug 2, 2022
207dedc
add alias parameter
simonfelding Aug 2, 2022
42a077b
added alias parameter
simonfelding Aug 2, 2022
694fbc9
added alias parameter
simonfelding Aug 2, 2022
d48593f
add alias parameter
simonfelding Aug 2, 2022
8b9c021
added alias parameter
simonfelding Aug 2, 2022
23d070a
look for alias in client instead
simonfelding Aug 2, 2022
ce298fd
test
simonfelding Aug 2, 2022
433daa4
pass alias to run_command
simonfelding Aug 2, 2022
e6501f0
look for alias in output
simonfelding Aug 2, 2022
26fc4f6
update docstring
simonfelding Aug 2, 2022
074eded
add alias parameter to run_command
simonfelding Aug 2, 2022
5929b9d
add alias to open_shell
simonfelding Aug 2, 2022
ad5a813
update alias test
simonfelding Aug 2, 2022
e158623
add alias to alias
simonfelding Aug 2, 2022
3e6db9b
remove alias from open_shell, add to init..
simonfelding Aug 2, 2022
1a66230
update alias test
simonfelding Aug 2, 2022
5aff92e
update alias test
simonfelding Aug 2, 2022
40887ed
add test for duplicate aliases
simonfelding Aug 2, 2022
dcc438d
dumb syntax error
simonfelding Aug 2, 2022
11d78f8
another dumb syntax error
simonfelding Aug 2, 2022
c24cd5d
fix alias duplicate test
simonfelding Aug 2, 2022
a8d36a1
fix unpacking of _host_clients tuple
simonfelding Aug 2, 2022
afdd018
another dumb syntax error - it's getting late..
simonfelding Aug 2, 2022
eb51220
fix alias test.
simonfelding Aug 2, 2022
e0e42a4
this cant work because of how the rest works
simonfelding Aug 2, 2022
694ad1e
alias should be per host
simonfelding Aug 6, 2022
afb88b4
add alias passthrough test
simonfelding Aug 6, 2022
0f7c44d
test alias passthrough
simonfelding Aug 6, 2022
4401bdd
cleanup
simonfelding Aug 6, 2022
48c85bb
fix dumb error
simonfelding Aug 6, 2022
b3c7604
test client needs auth
simonfelding Aug 6, 2022
9370e3e
fix test error with lists
simonfelding Aug 6, 2022
69504ac
make alias test more interpretable
simonfelding Aug 6, 2022
b8ecb72
the actual interpretability improvement
simonfelding Aug 6, 2022
1a51f36
get alias for host with error
simonfelding Aug 6, 2022
b05c490
i hope this gets the config for the correct host
simonfelding Aug 6, 2022
fc48899
make flake happy
simonfelding Aug 6, 2022
72ef36d
fix alias for errors
simonfelding Aug 6, 2022
91ae75e
reintroduce magic
simonfelding Aug 6, 2022
de4bbe8
no alias if host config is not set
simonfelding Aug 6, 2022
860fed1
now it works???
simonfelding Aug 6, 2022
607c2ec
Update tests/test_host_config.py
pkittenis Aug 20, 2022
0387a63
Update pssh/config.py
pkittenis Aug 20, 2022
e02013f
Update pssh/clients/native/single.py
pkittenis Aug 20, 2022
b40ffe2
Update pssh/clients/ssh/single.py
pkittenis Aug 20, 2022
402f74f
Update pssh/config.py
pkittenis Aug 20, 2022
5b1be0e
Update pssh/output.py
pkittenis Aug 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions pssh/clients/base/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ def _get_output_from_cmds(self, cmds, raise_error=False):

def _get_output_from_greenlet(self, cmd_i, cmd, raise_error=False):
host = self.hosts[cmd_i]
alias = self._get_host_config(cmd_i, host).alias
try:
host_out = cmd.get()
return host_out
Expand All @@ -239,8 +240,7 @@ def _get_output_from_greenlet(self, cmd_i, cmd, raise_error=False):
ex = Timeout()
if raise_error:
raise ex
return HostOutput(host, None, None, None,
exception=ex)
return HostOutput(host, None, None, None, exception=ex, alias=alias)

def get_last_output(self, cmds=None):
"""Get output for last commands executed by ``run_command``.
Expand Down Expand Up @@ -272,6 +272,7 @@ def _get_host_config(self, host_i, host):
gssapi_server_identity=self.gssapi_server_identity,
gssapi_client_identity=self.gssapi_client_identity,
gssapi_delegate_credentials=self.gssapi_delegate_credentials,
alias=None,
)
return config
elif not isinstance(self.host_config, list):
Expand Down
5 changes: 3 additions & 2 deletions pssh/clients/base/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class BaseSSHClient(object):

def __init__(self, host,
user=None, password=None, port=None,
pkey=None,
pkey=None, alias=None,
num_retries=DEFAULT_RETRIES,
retry_delay=RETRY_DELAY,
allow_agent=True, timeout=None,
Expand All @@ -171,6 +171,7 @@ def __init__(self, host,
):
self._auth_thread_pool = _auth_thread_pool
self.host = host
self.alias = alias
self.user = user if user else getuser()
self.password = password
self.port = port if port else 22
Expand Down Expand Up @@ -409,7 +410,7 @@ def _make_host_output(self, channel, encoding, read_timeout):
stdout=BufferData(rw_buffer=_stdout_buffer, reader=_stdout_reader),
stderr=BufferData(rw_buffer=_stderr_buffer, reader=_stderr_reader))
host_out = HostOutput(
host=self.host, channel=channel, stdin=Stdin(channel, self),
host=self.host, alias=self.alias, channel=channel, stdin=Stdin(channel, self),
client=self, encoding=encoding, read_timeout=read_timeout,
buffers=_buffers,
)
Expand Down
1 change: 1 addition & 0 deletions pssh/clients/native/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ def _make_ssh_client(self, host, cfg, _pkey_data):
_client = SSHClient(
host, user=cfg.user or self.user, password=cfg.password or self.password, port=cfg.port or self.port,
pkey=_pkey_data, num_retries=cfg.num_retries or self.num_retries,
alias=cfg.alias,
timeout=cfg.timeout or self.timeout,
allow_agent=cfg.allow_agent or self.allow_agent, retry_delay=cfg.retry_delay or self.retry_delay,
proxy_host=cfg.proxy_host or self.proxy_host,
Expand Down
11 changes: 7 additions & 4 deletions pssh/clients/native/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class SSHClient(BaseSSHClient):

def __init__(self, host,
user=None, password=None, port=None,
pkey=None,
pkey=None, alias=None,
num_retries=DEFAULT_RETRIES,
retry_delay=RETRY_DELAY,
allow_agent=True, timeout=None,
Expand All @@ -70,6 +70,8 @@ def __init__(self, host,
:type user: str
:param password: Password to use for password authentication.
:type password: str
:param alias: Use an alias for this host.
:type alias: str or int
pkittenis marked this conversation as resolved.
Show resolved Hide resolved
:param port: SSH port to connect to. Defaults to SSH default (22)
:type port: int
:param pkey: Private key file path to use for authentication. Path must
Expand Down Expand Up @@ -115,6 +117,7 @@ def __init__(self, host,
self.keepalive_seconds = keepalive_seconds
self._keepalive_greenlet = None
self._proxy_client = None
self.alias = alias
self.host = host
self.port = port if port is not None else 22
if proxy_host is not None:
Expand All @@ -133,7 +136,7 @@ def __init__(self, host,
proxy_host = '127.0.0.1'
self._chan_lock = RLock()
super(SSHClient, self).__init__(
host, user=user, password=password, port=port, pkey=pkey,
host, user=user, password=password, alias=alias, port=port, pkey=pkey,
num_retries=num_retries, retry_delay=retry_delay,
allow_agent=allow_agent, _auth_thread_pool=_auth_thread_pool,
timeout=timeout,
Expand All @@ -146,7 +149,7 @@ def _shell(self, channel):
return self._eagain(channel.shell)

def _connect_proxy(self, proxy_host, proxy_port, proxy_pkey,
user=None, password=None,
user=None, password=None, alias=None,
num_retries=DEFAULT_RETRIES,
retry_delay=RETRY_DELAY,
allow_agent=True, timeout=None,
Expand All @@ -156,7 +159,7 @@ def _connect_proxy(self, proxy_host, proxy_port, proxy_pkey,
assert isinstance(self.port, int)
try:
self._proxy_client = SSHClient(
proxy_host, port=proxy_port, pkey=proxy_pkey,
proxy_host, port=proxy_port, pkey=proxy_pkey, alias=alias,
num_retries=num_retries, user=user, password=password,
retry_delay=retry_delay, allow_agent=allow_agent,
timeout=timeout, forward_ssh_agent=forward_ssh_agent,
Expand Down
1 change: 1 addition & 0 deletions pssh/clients/ssh/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ def _make_ssh_client(self, host, cfg, _pkey_data):
_client = SSHClient(
host, user=cfg.user or self.user, password=cfg.password or self.password, port=cfg.port or self.port,
pkey=_pkey_data, num_retries=cfg.num_retries or self.num_retries,
alias=cfg.alias,
timeout=cfg.timeout or self.timeout,
allow_agent=cfg.allow_agent or self.allow_agent, retry_delay=cfg.retry_delay or self.retry_delay,
_auth_thread_pool=cfg.auth_thread_pool or self._auth_thread_pool,
Expand Down
6 changes: 4 additions & 2 deletions pssh/clients/ssh/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SSHClient(BaseSSHClient):

def __init__(self, host,
user=None, password=None, port=None,
pkey=None,
pkey=None, alias=None,
cert_file=None,
num_retries=DEFAULT_RETRIES,
retry_delay=RETRY_DELAY,
Expand All @@ -60,6 +60,8 @@ def __init__(self, host,
:type password: str
:param port: SSH port to connect to. Defaults to SSH default (22)
:type port: int
:param alias: Use an alias for this host.
:type alias: str or int
pkittenis marked this conversation as resolved.
Show resolved Hide resolved
:param pkey: Private key file path to use for authentication. Path must
be either absolute path or relative to user home directory
like ``~/<path>``.
Expand Down Expand Up @@ -114,7 +116,7 @@ def __init__(self, host,
self.gssapi_client_identity = gssapi_client_identity
self.gssapi_delegate_credentials = gssapi_delegate_credentials
super(SSHClient, self).__init__(
host, user=user, password=password, port=port, pkey=pkey,
host, user=user, password=password, port=port, pkey=pkey, alias=alias,
num_retries=num_retries, retry_delay=retry_delay,
allow_agent=allow_agent,
_auth_thread_pool=_auth_thread_pool,
Expand Down
9 changes: 7 additions & 2 deletions pssh/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ class HostConfig(object):
Used to hold individual configuration for each host in ParallelSSHClient host list.
"""
__slots__ = ('user', 'port', 'password', 'private_key', 'allow_agent',
'num_retries', 'retry_delay', 'timeout', 'identity_auth',
'alias', 'num_retries', 'retry_delay', 'timeout', 'identity_auth',
'proxy_host', 'proxy_port', 'proxy_user', 'proxy_password', 'proxy_pkey',
'keepalive_seconds', 'ipv6_only', 'cert_file', 'auth_thread_pool', 'gssapi_auth',
'gssapi_server_identity', 'gssapi_client_identity', 'gssapi_delegate_credentials',
'forward_ssh_agent',
)

def __init__(self, user=None, port=None, password=None, private_key=None,
allow_agent=None, num_retries=None, retry_delay=None, timeout=None,
allow_agent=None, alias=None, num_retries=None, retry_delay=None, timeout=None,
identity_auth=None,
proxy_host=None, proxy_port=None, proxy_user=None, proxy_password=None,
proxy_pkey=None,
Expand All @@ -58,6 +58,8 @@ def __init__(self, user=None, port=None, password=None, private_key=None,
:type private_key: str
:param allow_agent: Enable/disable SSH agent authentication.
:type allow_agent: bool
:param alias: Use an alias for this host.
:type alias: str or int
:param num_retries: Number of retry attempts before giving up on connection
and SSH operations.
:type num_retries: int
Expand Down Expand Up @@ -103,6 +105,7 @@ def __init__(self, user=None, port=None, password=None, private_key=None,
self.password = password
self.private_key = private_key
self.allow_agent = allow_agent
self.alias = alias
self.num_retries = num_retries
self.timeout = timeout
self.retry_delay = retry_delay
Expand Down Expand Up @@ -130,6 +133,8 @@ def _sanity_checks(self):
raise ValueError("Port %s is not an integer" % (self.port,))
if self.password is not None and not isinstance(self.password, str):
raise ValueError("Password %s is not a string" % (self.password,))
if self.alias is not None and not isinstance(self.alias, (str, int)):
pkittenis marked this conversation as resolved.
Show resolved Hide resolved
raise ValueError("Alias %s is not a string or integer" % (self.alias,))
pkittenis marked this conversation as resolved.
Show resolved Hide resolved
if self.private_key is not None and not (
isinstance(self.private_key, str) or isinstance(self.private_key, bytes)
):
Expand Down
12 changes: 8 additions & 4 deletions pssh/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ class HostOutput(object):
"""Host output"""

__slots__ = ('host', 'channel', 'stdin',
'client', 'exception', 'encoding', 'read_timeout',
'buffers',
'client', 'alias', 'exception',
'encoding', 'read_timeout', 'buffers',
)

def __init__(self, host, channel, stdin,
client, exception=None, encoding='utf-8', read_timeout=None,
client, alias=None, exception=None, encoding='utf-8', read_timeout=None,
buffers=None):
"""
:param host: Host name output is for
Expand All @@ -71,6 +71,8 @@ def __init__(self, host, channel, stdin,
:type stdin: :py:func:`file`-like object
:param client: `SSHClient` output is coming from.
:type client: :py:class:`pssh.clients.base.single.BaseSSHClient`
:param alias: Host alias.
:type alias: str or int
pkittenis marked this conversation as resolved.
Show resolved Hide resolved
:param exception: Exception from host if any
:type exception: :py:class:`Exception` or ``None``
:param read_timeout: Timeout in seconds for reading from buffers.
Expand All @@ -82,6 +84,7 @@ def __init__(self, host, channel, stdin,
self.channel = channel
self.stdin = stdin
self.client = client
self.alias = alias
self.exception = exception
self.encoding = encoding
self.read_timeout = read_timeout
Expand Down Expand Up @@ -117,12 +120,13 @@ def exit_code(self):

def __repr__(self):
return "\thost={host}{linesep}" \
"\talias={alias}{linesep}" \
"\texit_code={exit_code}{linesep}" \
"\tchannel={channel}{linesep}" \
"\texception={exception}{linesep}" \
"\tencoding={encoding}{linesep}" \
"\tread_timeout={read_timeout}".format(
host=self.host, channel=self.channel,
host=self.host, alias=self.alias, channel=self.channel,
exception=self.exception, linesep=linesep,
exit_code=self.exit_code, encoding=self.encoding, read_timeout=self.read_timeout,
)
Expand Down
5 changes: 5 additions & 0 deletions tests/native/test_parallel_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -930,19 +930,22 @@ def test_host_config(self):
servers = []
password = 'overriden_pass'
fake_key = 'FAKE KEY'
aliases = [f"alias for host {host_i}" for host_i, _ in enumerate(hosts)]
for host_i, (host, port) in enumerate(hosts):
server = OpenSSHServer(listen_ip=host, port=port)
server.start_server()
host_config[host_i].port = port
host_config[host_i].user = self.user
host_config[host_i].password = password
host_config[host_i].private_key = self.user_key
host_config[host_i].alias = aliases[host_i]
servers.append(server)
host_config[1].private_key = fake_key
client = ParallelSSHClient([h for h, _ in hosts],
host_config=host_config,
num_retries=1)
output = client.run_command(self.cmd, stop_on_errors=False)

client.join(output)
self.assertEqual(len(hosts), len(output))
try:
Expand All @@ -954,6 +957,8 @@ def test_host_config(self):
self.assertEqual(client._host_clients[0, hosts[0][0]].user, self.user)
self.assertEqual(client._host_clients[0, hosts[0][0]].password, password)
self.assertEqual(client._host_clients[0, hosts[0][0]].pkey, open(os.path.abspath(self.user_key), 'rb').read())
self.assertEqual(set(aliases), set([client.alias for client in output]))

for server in servers:
server.stop()

Expand Down
7 changes: 7 additions & 0 deletions tests/native/test_single_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ def test_execute(self):
exit_code = host_out.channel.get_exit_status()
self.assertEqual(host_out.exit_code, 0)
self.assertEqual(expected, output)

def test_alias(self):
client = SSHClient(self.host, port=self.port,
pkey=self.user_key, num_retries=1,
alias='test')
host_out = client.run_command(self.cmd)
self.assertEqual(host_out.alias, 'test')

def test_open_session_timeout(self):
client = SSHClient(self.host, port=self.port,
Expand Down
5 changes: 4 additions & 1 deletion tests/test_host_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def test_host_config_entries(self):
user = 'user'
port = 22
password = 'password'
alias = 'alias'
private_key = 'private key'
allow_agent = False
num_retries = 1
Expand All @@ -43,7 +44,7 @@ def test_host_config_entries(self):
gssapi_client_identity = 'some_id'
gssapi_delegate_credentials = True
cfg = HostConfig(
user=user, port=port, password=password, private_key=private_key,
user=user, port=port, password=password, alias=alias, private_key=private_key,
allow_agent=allow_agent, num_retries=num_retries, retry_delay=retry_delay,
timeout=timeout, identity_auth=identity_auth, proxy_host=proxy_host,
ipv6_only=ipv6_only,
Expand All @@ -59,6 +60,7 @@ def test_host_config_entries(self):
self.assertEqual(cfg.user, user)
self.assertEqual(cfg.port, port)
self.assertEqual(cfg.password, password)
self.assertEqual(cfg.alias, alias)
self.assertEqual(cfg.private_key, private_key)
self.assertEqual(cfg.allow_agent, allow_agent)
self.assertEqual(cfg.num_retries, num_retries)
Expand All @@ -79,6 +81,7 @@ def test_host_config_bad_entries(self):
self.assertRaises(ValueError, HostConfig, user=22)
self.assertRaises(ValueError, HostConfig, password=22)
self.assertRaises(ValueError, HostConfig, port='22')
self.assertRaises(ValueError, HostConfig, alias=2.2)
pkittenis marked this conversation as resolved.
Show resolved Hide resolved
self.assertRaises(ValueError, HostConfig, private_key=1)
self.assertRaises(ValueError, HostConfig, allow_agent=1)
self.assertRaises(ValueError, HostConfig, num_retries='')
Expand Down