mirror of
https://github.com/containers/podman.git
synced 2025-07-20 03:52:53 +08:00
Port to MacOS
* Refactor Tunnel to support selecting port for remote sshd * Refactor ssh tunnel to support MacOS version of ssh * Refactor Tunnel.close() to find and kill off zombie siblings * Add psutil dependency * Add logging setup, letting library produce debugging records * Clean up Tunnel API * Fix test_runner.sh to propagate returncode to caller Signed-off-by: Jhon Honce <jhonce@redhat.com> Closes: #1199 Approved by: rhatdan
This commit is contained in:
contrib
@ -46,6 +46,11 @@ user.
|
||||
Name of remote host. There is no default, if not given \f[C]pypodman\f[]
|
||||
attempts to connect to \f[C]\-\-remote\-socket\-path\f[] on local host.
|
||||
.PP
|
||||
\f[B]\[en]port\f[]
|
||||
.PP
|
||||
The optional port for \f[C]ssh\f[] to connect tunnel to on remote host.
|
||||
Default is None and will allow \f[C]ssh\f[] to follow it's default configuration.
|
||||
.PP
|
||||
\f[B]\[en]remote\-socket\-path\f[]
|
||||
.PP
|
||||
Path on remote host for podman service's \f[C]AF_UNIX\f[] socket. The default is
|
||||
|
@ -33,6 +33,28 @@ class HelpFormatter(argparse.RawDescriptionHelpFormatter):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class PortAction(argparse.Action):
|
||||
"""Validate port number given is positive integer."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
"""Validate input."""
|
||||
if values > 0:
|
||||
setattr(namespace, self.dest, values)
|
||||
return
|
||||
|
||||
msg = 'port numbers must be a positive integer.'
|
||||
raise argparse.ArgumentError(self, msg)
|
||||
|
||||
|
||||
class PathAction(argparse.Action):
|
||||
"""Expand user- and relative-paths."""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
"""Resolve full path value."""
|
||||
setattr(namespace, self.dest,
|
||||
os.path.abspath(os.path.expanduser(values)))
|
||||
|
||||
|
||||
class PodmanArgumentParser(argparse.ArgumentParser):
|
||||
"""Default remote podman configuration."""
|
||||
|
||||
@ -64,10 +86,17 @@ class PodmanArgumentParser(argparse.ArgumentParser):
|
||||
' (default: XDG_RUNTIME_DIR/pypodman'))
|
||||
self.add_argument(
|
||||
'--user',
|
||||
'-l',
|
||||
default=getpass.getuser(),
|
||||
help='Authenicating user on remote host. (default: %(default)s)')
|
||||
self.add_argument(
|
||||
'--host', help='name of remote host. (default: None)')
|
||||
self.add_argument(
|
||||
'--port',
|
||||
'-p',
|
||||
type=int,
|
||||
action=PortAction,
|
||||
help='port for ssh tunnel to remote host. (default: 22)')
|
||||
self.add_argument(
|
||||
'--remote-socket-path',
|
||||
metavar='PATH',
|
||||
@ -75,11 +104,14 @@ class PodmanArgumentParser(argparse.ArgumentParser):
|
||||
' (default: /run/podman/io.projectatomic.podman)'))
|
||||
self.add_argument(
|
||||
'--identity-file',
|
||||
'-i',
|
||||
metavar='PATH',
|
||||
action=PathAction,
|
||||
help=('path to ssh identity file. (default: ~user/.ssh/id_dsa)'))
|
||||
self.add_argument(
|
||||
'--config-home',
|
||||
metavar='DIRECTORY',
|
||||
action=PathAction,
|
||||
help=('home of configuration "pypodman.conf".'
|
||||
' (default: XDG_CONFIG_HOME/pypodman'))
|
||||
|
||||
@ -125,8 +157,8 @@ class PodmanArgumentParser(argparse.ArgumentParser):
|
||||
if dir_ is None:
|
||||
continue
|
||||
with suppress(OSError):
|
||||
with open(os.path.join(dir_, 'pypodman/pypodman.conf'),
|
||||
'r') as stream:
|
||||
with open(os.path.join(dir_,
|
||||
'pypodman/pypodman.conf')) as stream:
|
||||
config.update(pytoml.load(stream))
|
||||
|
||||
def reqattr(name, value):
|
||||
@ -156,6 +188,7 @@ class PodmanArgumentParser(argparse.ArgumentParser):
|
||||
'user',
|
||||
getattr(args, 'user')
|
||||
or os.environ.get('USER')
|
||||
or os.environ.get('LOGNAME')
|
||||
or config['default'].get('user')
|
||||
or getpass.getuser()
|
||||
) # yapf:disable
|
||||
@ -195,8 +228,13 @@ class PodmanArgumentParser(argparse.ArgumentParser):
|
||||
args.local_socket_path = args.remote_socket_path
|
||||
|
||||
args.local_uri = "unix:{}".format(args.local_socket_path)
|
||||
args.remote_uri = "ssh://{}@{}{}".format(args.user, args.host,
|
||||
args.remote_socket_path)
|
||||
|
||||
components = ['ssh://', args.user, '@', args.host]
|
||||
if args.port:
|
||||
components.extend((':', str(args.port)))
|
||||
components.append(args.remote_socket_path)
|
||||
|
||||
args.remote_uri = ''.join(components)
|
||||
return args
|
||||
|
||||
def exit(self, status=0, message=None):
|
||||
|
@ -2,6 +2,7 @@
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
from pypodman.lib import PodmanArgumentParser
|
||||
|
||||
@ -49,14 +50,15 @@ def main():
|
||||
|
||||
try:
|
||||
returncode = getattr(obj, args.method)()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except AttributeError as e:
|
||||
logging.critical(e, exc_info=want_tb())
|
||||
logging.warning('See subparser "%s" configuration.',
|
||||
args.subparser_name)
|
||||
returncode = 3
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except (
|
||||
CalledProcessError,
|
||||
ConnectionRefusedError,
|
||||
ConnectionResetError,
|
||||
TimeoutError,
|
||||
|
Reference in New Issue
Block a user