Skip to content

Commit 84c567e

Browse files
committed
Add podman connection support
Shameless copy of buildah connection with modifications of invocation to fit podman CLI. Signed-off-by: Denis Zalevskiy <[email protected]>
1 parent 10caa4a commit 84c567e

File tree

7 files changed

+153
-0
lines changed

7 files changed

+153
-0
lines changed

docs/api.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,20 @@ Connection Methods
367367
Filename or complete path to the ``lxc`` binary. ``PATH`` will be
368368
searched if given as a filename. Defaults to ``lxc``.
369369

370+
.. currentmodule:: mitogen.parent
371+
.. method:: Router.podman (container=None, podman_path=None, username=None, \**kwargs)
372+
373+
Construct a context on the local machine over a ``podman`` invocation.
374+
Accepts all parameters accepted by :meth:`local`, in addition to:
375+
376+
:param str container:
377+
The name of the Podman container to connect to.
378+
:param str podman_path:
379+
Filename or complete path to the ``podman`` binary. ``PATH`` will be
380+
searched if given as a filename. Defaults to ``podman``.
381+
:param str username:
382+
Username to use, defaults to unset.
383+
370384
.. method:: Router.setns (container, kind, username=None, docker_path=None, lxc_info_path=None, machinectl_path=None, \**kwargs)
371385

372386
Construct a context in the style of :meth:`local`, but change the

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ v0.3.1.dev0 (unreleased)
2323

2424
* :gh:issue:`869` Continuous Integration tests are now run with Tox
2525
* :gh:issue:`869` Continuous Integration tests now cover CentOS 6 & 8, Debian 9 & 11, Ubuntu 16.04 & 20.04
26+
* :gh:issue:`860` Add initial support for podman connection (w/o Ansible support yet)
2627

2728

2829
v0.3.0 (2021-11-24)

mitogen/core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,7 @@ class Importer(object):
12541254
'minify',
12551255
'os_fork',
12561256
'parent',
1257+
'podman',
12571258
'select',
12581259
'service',
12591260
'setns',

mitogen/parent.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2505,6 +2505,9 @@ def sudo(self, **kwargs):
25052505
def ssh(self, **kwargs):
25062506
return self.connect(u'ssh', **kwargs)
25072507

2508+
def podman(self, **kwargs):
2509+
return self.connect(u'podman', **kwargs)
2510+
25082511

25092512
class Reaper(object):
25102513
"""

mitogen/podman.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright 2019, David Wilson
2+
# Copyright 2021, Mitogen contributors
3+
#
4+
# Redistribution and use in source and binary forms, with or without
5+
# modification, are permitted provided that the following conditions are met:
6+
#
7+
# 1. Redistributions of source code must retain the above copyright notice,
8+
# this list of conditions and the following disclaimer.
9+
#
10+
# 2. Redistributions in binary form must reproduce the above copyright notice,
11+
# this list of conditions and the following disclaimer in the documentation
12+
# and/or other materials provided with the distribution.
13+
#
14+
# 3. Neither the name of the copyright holder nor the names of its contributors
15+
# may be used to endorse or promote products derived from this software without
16+
# specific prior written permission.
17+
#
18+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
# POSSIBILITY OF SUCH DAMAGE.
29+
30+
# !mitogen: minify_safe
31+
32+
import logging
33+
34+
import mitogen.core
35+
import mitogen.parent
36+
37+
38+
LOG = logging.getLogger(__name__)
39+
40+
41+
class Options(mitogen.parent.Options):
42+
container = None
43+
username = None
44+
podman_path = 'podman'
45+
46+
def __init__(self, container=None, podman_path=None, username=None,
47+
**kwargs):
48+
super(Options, self).__init__(**kwargs)
49+
assert container is not None
50+
self.container = container
51+
if podman_path:
52+
self.podman_path = podman_path
53+
if username:
54+
self.username = username
55+
56+
57+
class Connection(mitogen.parent.Connection):
58+
options_class = Options
59+
child_is_immediate_subprocess = False
60+
61+
# TODO: better way of capturing errors such as "No such container."
62+
create_child_args = {
63+
'merge_stdio': True
64+
}
65+
66+
def _get_name(self):
67+
return u'podman.' + self.options.container
68+
69+
def get_boot_command(self):
70+
args = [self.options.podman_path, 'exec']
71+
if self.options.username:
72+
args += ['--user=' + self.options.username]
73+
args += ["--interactive", "--", self.options.container]
74+
return args + super(Connection, self).get_boot_command()

tests/data/stubs/stub-podman.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env python
2+
3+
import sys
4+
import os
5+
6+
os.environ['ORIGINAL_ARGV'] = repr(sys.argv)
7+
os.environ['THIS_IS_STUB_PODMAN'] = '1'
8+
os.execv(sys.executable, sys.argv[sys.argv.index('--') + 2:])

tests/podman_test.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import os
2+
import unittest2
3+
4+
import mitogen
5+
6+
import testlib
7+
8+
9+
class ConstructorTest(testlib.RouterMixin, testlib.TestCase):
10+
def test_okay(self):
11+
stub_path = testlib.data_path('stubs/stub-podman.py')
12+
13+
context = self.router.podman(
14+
container='container_name',
15+
podman_path=stub_path,
16+
)
17+
stream = self.router.stream_by_id(context.context_id)
18+
19+
argv = eval(context.call(os.getenv, 'ORIGINAL_ARGV'))
20+
expected_call = [
21+
stub_path,
22+
'exec',
23+
'--interactive',
24+
'--',
25+
'container_name',
26+
stream.conn.options.python_path
27+
]
28+
self.assertEquals(argv[:len(expected_call)], expected_call)
29+
30+
context = self.router.podman(
31+
container='container_name',
32+
podman_path=stub_path,
33+
username='some_user',
34+
)
35+
stream = self.router.stream_by_id(context.context_id)
36+
37+
argv = eval(context.call(os.getenv, 'ORIGINAL_ARGV'))
38+
expected_call = [
39+
stub_path,
40+
'exec',
41+
'--user=some_user',
42+
'--interactive',
43+
'--',
44+
'container_name',
45+
stream.conn.options.python_path
46+
]
47+
self.assertEquals(argv[:len(expected_call)], expected_call)
48+
49+
50+
51+
if __name__ == '__main__':
52+
unittest2.main()

0 commit comments

Comments
 (0)