-
-
Notifications
You must be signed in to change notification settings - Fork 148
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
Support rootfull pods from inside #300
Labels
enhancement
New feature or request
Comments
TBH I don't think it's possible to inject |
Well, I am trying something inspired from the state machine in ssh connection |
I have the following patch as a proof of concept. If you think that it's not a too ugly solution, i'll fix my code a bit, add some tests and propose a PR. From c42e459932f49a65e66aa23f19d77ff52e4f3624 Mon Sep 17 00:00:00 2001
From: Tristan Pinaudeau <[email protected]>
Date: Tue, 21 Sep 2021 18:07:15 +0200
Subject: [PATCH 1/2] feat: enable rootfull container access
---
plugins/connection/podman.py | 59 ++++++++++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 2 deletions(-)
diff --git a/plugins/connection/podman.py b/plugins/connection/podman.py
index 68c677f..f516988 100644
--- a/plugins/connection/podman.py
+++ b/plugins/connection/podman.py
@@ -15,8 +15,11 @@ import os
import shlex
import shutil
import subprocess
+import fcntl
+import json
from ansible.errors import AnsibleError
+from ansible.module_utils.compat import selectors
from ansible.module_utils._text import to_bytes, to_native
from ansible.plugins.connection import ConnectionBase, ensure_connect
from ansible.utils.display import Display
@@ -68,6 +71,21 @@ DOCUMENTATION = '''
- name: ansible_podman_executable
env:
- name: ANSIBLE_PODMAN_EXECUTABLE
+ podman_rootless:
+ description:
+ - Is the target container rootless ?
+ type: bool
+ default: true
+ vars:
+ - name: ansible_podman_rootless
+ env:
+ - name: ANSIBLE_PODMAN_ROOTLESS
+ password:
+ description: Authentication password for the C(remote_user). Can be supplied as CLI option.
+ vars:
+ - name: ansible_password
+ - name: ansible_podman_password
+ - name: ansible_podman_pass
'''
@@ -92,6 +110,35 @@ class Connection(ConnectionBase):
self._mount_point = None
self.user = self._play_context.remote_user
display.vvvv("Using podman connection from collection")
+ self._rootless = self.get_option('podman_rootless')
+
+ def _become(self, p):
+ b_stderr = b''
+
+ timeout = 2 # TODO self.get_option('timeout')
+ for fd in (p.stdout, p.stderr):
+ fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
+
+ selector = selectors.DefaultSelector()
+ selector.register(p.stdout, selectors.EVENT_READ)
+ selector.register(p.stderr, selectors.EVENT_READ)
+
+ try:
+ poll = p.poll()
+ events = selector.select(timeout)
+
+ for key, event in events:
+ if key.fileobj == p.stderr:
+ b_chunk = p.stderr.read()
+ b_stderr += b_chunk
+
+ if b'sudo' in b_stderr:
+ become_pass = self.get_option('password')
+ p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
+ p.stdin.flush()
+
+ finally:
+ selector.close()
def _podman(self, cmd, cmd_args=None, in_data=None, use_container_id=True):
"""
@@ -106,7 +153,10 @@ class Connection(ConnectionBase):
podman_cmd = distutils.spawn.find_executable(podman_exec)
if not podman_cmd:
raise AnsibleError("%s command not found in PATH" % podman_exec)
- local_cmd = [podman_cmd]
+
+ # TODO find full sudo path (or use the become mechanism from ansible)
+ local_cmd = [podman_cmd] if self._rootless else ['sudo', '-Sk', podman_cmd]
+
if self.get_option('podman_extra_args'):
local_cmd += shlex.split(
to_native(
@@ -127,6 +177,9 @@ class Connection(ConnectionBase):
p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if not self._rootless:
+ self._become(p)
+
stdout, stderr = p.communicate(input=in_data)
display.vvvvv("STDOUT %s" % stdout)
display.vvvvv("STDERR %s" % stderr)
@@ -142,7 +195,9 @@ class Connection(ConnectionBase):
"""
super(Connection, self)._connect()
rc, self._mount_point, stderr = self._podman("mount")
- if rc != 0:
+ if not self._rootless:
+ self._mount_point = None
+ elif rc != 0:
display.vvvv("Failed to mount container %s: %s" % (self._container_id, stderr.strip()))
elif not os.listdir(self._mount_point.strip()):
display.vvvv("Failed to mount container with CGroups2: empty dir %s" % self._mount_point.strip())
--
2.33.0
From d22b1dc94b454a3ddde015b1d428e4c45763c21f Mon Sep 17 00:00:00 2001
From: Tristan Pinaudeau <[email protected]>
Date: Tue, 21 Sep 2021 18:13:06 +0200
Subject: [PATCH 2/2] fix: json lib not needed'
---
plugins/connection/podman.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/plugins/connection/podman.py b/plugins/connection/podman.py
index f516988..555e28f 100644
--- a/plugins/connection/podman.py
+++ b/plugins/connection/podman.py
@@ -16,7 +16,6 @@ import shlex
import shutil
import subprocess
import fcntl
-import json
from ansible.errors import AnsibleError
from ansible.module_utils.compat import selectors
--
2.33.0
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
/kind feature
This feature request is about the connection plugin documented here. To my knowledge it is not possible to join a rootfull container (container created with sudo). It would be nice to be able to do so. I propose adding an
ansible_podman_rootless
flag which isfalse
by default but can be set totrue
to enable a connection to a "rootfull" pod. The host sudo password may be asked via the--ask-pass
argument.Steps to test the feature:
Describe the results you received:
Describe the results you expected:
Additional information you deem important:
This feature request is following the issue ansible-community/molecule-plugins#82.
The text was updated successfully, but these errors were encountered: