Add podman connection support

Shameless copy of buildah connection with modifications of invocation to
fit podman CLI.

Signed-off-by: Denis Zalevskiy <dez@aiven.io>
pull/860/head
Denis Zalevskiy 3 years ago
parent 10caa4a104
commit 84c567e265
No known key found for this signature in database
GPG Key ID: 1475E1C9EEC89426

@ -367,6 +367,20 @@ Connection Methods
Filename or complete path to the ``lxc`` binary. ``PATH`` will be
searched if given as a filename. Defaults to ``lxc``.
.. currentmodule:: mitogen.parent
.. method:: Router.podman (container=None, podman_path=None, username=None, \**kwargs)
Construct a context on the local machine over a ``podman`` invocation.
Accepts all parameters accepted by :meth:`local`, in addition to:
:param str container:
The name of the Podman container to connect to.
:param str podman_path:
Filename or complete path to the ``podman`` binary. ``PATH`` will be
searched if given as a filename. Defaults to ``podman``.
:param str username:
Username to use, defaults to unset.
.. method:: Router.setns (container, kind, username=None, docker_path=None, lxc_info_path=None, machinectl_path=None, \**kwargs)
Construct a context in the style of :meth:`local`, but change the

@ -23,6 +23,7 @@ v0.3.1.dev0 (unreleased)
* :gh:issue:`869` Continuous Integration tests are now run with Tox
* :gh:issue:`869` Continuous Integration tests now cover CentOS 6 & 8, Debian 9 & 11, Ubuntu 16.04 & 20.04
* :gh:issue:`860` Add initial support for podman connection (w/o Ansible support yet)
v0.3.0 (2021-11-24)

@ -1254,6 +1254,7 @@ class Importer(object):
'minify',
'os_fork',
'parent',
'podman',
'select',
'service',
'setns',

@ -2505,6 +2505,9 @@ class Router(mitogen.core.Router):
def ssh(self, **kwargs):
return self.connect(u'ssh', **kwargs)
def podman(self, **kwargs):
return self.connect(u'podman', **kwargs)
class Reaper(object):
"""

@ -0,0 +1,74 @@
# Copyright 2019, David Wilson
# Copyright 2021, Mitogen contributors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# !mitogen: minify_safe
import logging
import mitogen.core
import mitogen.parent
LOG = logging.getLogger(__name__)
class Options(mitogen.parent.Options):
container = None
username = None
podman_path = 'podman'
def __init__(self, container=None, podman_path=None, username=None,
**kwargs):
super(Options, self).__init__(**kwargs)
assert container is not None
self.container = container
if podman_path:
self.podman_path = podman_path
if username:
self.username = username
class Connection(mitogen.parent.Connection):
options_class = Options
child_is_immediate_subprocess = False
# TODO: better way of capturing errors such as "No such container."
create_child_args = {
'merge_stdio': True
}
def _get_name(self):
return u'podman.' + self.options.container
def get_boot_command(self):
args = [self.options.podman_path, 'exec']
if self.options.username:
args += ['--user=' + self.options.username]
args += ["--interactive", "--", self.options.container]
return args + super(Connection, self).get_boot_command()

@ -0,0 +1,8 @@
#!/usr/bin/env python
import sys
import os
os.environ['ORIGINAL_ARGV'] = repr(sys.argv)
os.environ['THIS_IS_STUB_PODMAN'] = '1'
os.execv(sys.executable, sys.argv[sys.argv.index('--') + 2:])

@ -0,0 +1,52 @@
import os
import unittest2
import mitogen
import testlib
class ConstructorTest(testlib.RouterMixin, testlib.TestCase):
def test_okay(self):
stub_path = testlib.data_path('stubs/stub-podman.py')
context = self.router.podman(
container='container_name',
podman_path=stub_path,
)
stream = self.router.stream_by_id(context.context_id)
argv = eval(context.call(os.getenv, 'ORIGINAL_ARGV'))
expected_call = [
stub_path,
'exec',
'--interactive',
'--',
'container_name',
stream.conn.options.python_path
]
self.assertEquals(argv[:len(expected_call)], expected_call)
context = self.router.podman(
container='container_name',
podman_path=stub_path,
username='some_user',
)
stream = self.router.stream_by_id(context.context_id)
argv = eval(context.call(os.getenv, 'ORIGINAL_ARGV'))
expected_call = [
stub_path,
'exec',
'--user=some_user',
'--interactive',
'--',
'container_name',
stream.conn.options.python_path
]
self.assertEquals(argv[:len(expected_call)], expected_call)
if __name__ == '__main__':
unittest2.main()
Loading…
Cancel
Save