Repository: ansible/ansible
Pull request: podman - fix rootless container copy no pause
Signed-off-by: Adam Miller <admiller@redhat.com>

##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
Fixes #66263
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
- Bugfix Pull Request

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below -->
podman




Problem statement:
ansible + podman connector not working
##### SUMMARY

When using ansible with the podman connector (rootless container as user), I am not able to execute any commands.

##### ISSUE TYPE

- Bug Report

##### COMPONENT NAME

podman connector plugin

##### ANSIBLE VERSION
```
ansible 2.9.2
  config file = None
  configured module search path = ['/var/home/dschier/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /var/home/dschier/.venv-python3/lib64/python3.7/site-packages/ansible
  executable location = /var/home/dschier/.venv-python3/bin/ansible
  python version = 3.7.5 (default, Dec 15 2019, 17:54:26) [GCC 9.2.1 20190827 (Red Hat 9.2.1-1)]
```

##### CONFIGURATION

##### OS / ENVIRONMENT

- Fedora 31
- Podman 1.6.2
- Ansible 2.9.2 (via pip / virtualenv)

##### STEPS TO REPRODUCE

1. Start a container as user

```
podman run -d --rm --name instance fedora:31 sleep 300
```

2. Execute some ansible

```
ansible instance -c podman -m setup -i inventory
```

##### EXPECTED RESULTS

```
ansible gathers the facts
```

##### ACTUAL RESULTS

```
ansible 2.9.2
  config file = None
  configured module search path = ['/var/home/dschier/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /var/home/dschier/.venv-python3/lib64/python3.7/site-packages/ansible
  executable location = /var/home/dschier/.venv-python3/bin/ansible
  python version = 3.7.5 (default, Dec 15 2019, 17:54:26) [GCC 9.2.1 20190827 (Red Hat 9.2.1-1)]
No config file found; using defaults
setting up inventory plugins
host_list declined parsing /var/home/dschier/Projects/while-true-do/ansible-testing/inventory as it did not pass its verify_file() method
script declined parsing /var/home/dschier/Projects/while-true-do/ansible-testing/inventory as it did not pass its verify_file() method
auto declined parsing /var/home/dschier/Projects/while-true-do/ansible-testing/inventory as it did not pass its verify_file() method
Parsed /var/home/dschier/Projects/while-true-do/ansible-testing/inventory inventory source with ini plugin
Loading callback plugin minimal of type stdout, v2.0 from /var/home/dschier/.venv-python3/lib64/python3.7/site-packages/ansible/plugins/callback/minimal.py
META: ran handlers
<instance> RUN [b'podman', b'mount', b'instance']
Failed to mount container instance: b'Error: cannot mount using driver overlay in rootless mode'
<instance> RUN [b'podman', b'exec', b'instance', b'/bin/sh', b'-c', b'echo ~ && sleep 0']
<instance> RUN [b'podman', b'exec', b'instance', b'/bin/sh', b'-c', b'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1578473717.9823112-75096948351551 `" && echo ansible-tmp-1578473717.9823112-75096948351551="` echo /root/.ansible/tmp/ansible-tmp-1578473717.9823112-75096948351551 `" ) && sleep 0']
<instance> Attempting python interpreter discovery
<instance> RUN [b'podman', b'exec', b'instance', b'/bin/sh', b'-c', b"echo PLATFORM; uname; echo FOUND; command -v '/usr/bin/python'; command -v 'python3.7'; command -v 'python3.6'; command -v 'python3.5'; command -v 'python2.7'; command -v 'python2.6'; command -v '/usr/libexec/platform-python'; command -v '/usr/bin/python3'; command -v 'python'; echo ENDFOUND && sleep 0"]
<instance> RUN [b'podman', b'exec', b'instance', b'/bin/sh', b'-c', b'/usr/bin/python3.7 && sleep 0']
[WARNING]: Unhandled error in Python interpreter discovery for host instance: Expecting value: line 1 column 1 (char 0)

Using module file /var/home/dschier/.venv-python3/lib64/python3.7/site-packages/ansible/modules/system/setup.py
<instance> PUT /var/home/dschier/.ansible/tmp/ansible-local-232076i4n4mlw/tmpmbdk1qd0 TO /root/.ansible/tmp/ansible-tmp-1578473717.9823112-75096948351551/AnsiballZ_setup.py
<instance> RUN [b'podman', b'cp', b'/var/home/dschier/.ansible/tmp/ansible-local-232076i4n4mlw/tmpmbdk1qd0', b'instance:/root/.ansible/tmp/ansible-tmp-1578473717.9823112-75096948351551/AnsiballZ_setup.py']
instance | FAILED! => {
    "msg": "Failed to copy file from /var/home/dschier/.ansible/tmp/ansible-local-232076i4n4mlw/tmpmbdk1qd0 to /root/.ansible/tmp/ansible-tmp-1578473717.9823112-75096948351551/AnsiballZ_setup.py in container instance\nb'Error: cannot copy into running rootless container with pause set - pass --pause=false to force copying\\n'"
}

```

Hints from issue discussion:
I have also opened an issue for the podman team:

https://github.com/containers/libpod/issues/4813
cc @EmilienM @sshnaidm
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
@daniel-wtd answered you in libpod issue, I think it's better to discuss there

Commit message: podman - fix rootless container copy no pause

Fixes #66263

Signed-off-by: Adam Miller <admiller@redhat.com>

Patch to review:
diff --git a/changelogs/fragments/66263-podman-connection-no-pause-rootless.yml b/changelogs/fragments/66263-podman-connection-no-pause-rootless.yml
new file mode 100644
index 00000000000000..1c3df6c8d73c88
--- /dev/null
+++ b/changelogs/fragments/66263-podman-connection-no-pause-rootless.yml
@@ -0,0 +1,2 @@
+bugfixes:
+  - podman connection plugin - fix to handle the new default copy pause rootless containers from upstream
diff --git a/lib/ansible/plugins/connection/podman.py b/lib/ansible/plugins/connection/podman.py
index cc166d0b16308a..a4dc585f822756 100644
--- a/lib/ansible/plugins/connection/podman.py
+++ b/lib/ansible/plugins/connection/podman.py
@@ -163,10 +163,18 @@ def put_file(self, in_path, out_path):
         display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id)
         if not self._mount_point:
             rc, stdout, stderr = self._podman(
-                "cp", [in_path, self._container_id + ":" + out_path], use_container_id=False)
+                "cp", [in_path, self._container_id + ":" + out_path], use_container_id=False
+            )
             if rc != 0:
-                raise AnsibleError("Failed to copy file from %s to %s in container %s\n%s" % (
-                    in_path, out_path, self._container_id, stderr))
+                if to_native('cannot copy into running rootless container with pause set' in to_native(stderr)):
+                    rc, stdout, stderr = self._podman(
+                        "cp", ["--pause=false", in_path, self._container_id + ":" + out_path], use_container_id=False
+                    )
+                    if rc != 0:
+                        raise AnsibleError(
+                            "Failed to copy file from %s to %s in container %s\n%s" % (
+                                in_path, out_path, self._container_id, stderr)
+                        )
         else:
             real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict')
             shutil.copyfile(


Code review comments:
diff_hunk: @@ -0,0 +1,2 @@
+bugfixes:
+  - podman connection plugin - fix to handle the new default copy pause rootless containers from upstream
path: changelogs/fragments/66263-podman-connection-no-pause-rootless.yml
text: @user1:
```suggestion
  - podman connection plugin - fix to handle the new default copy pause rootless containers from upstream (https://github.com/ansible/ansible/issues/66263)
```

diff_hunk: @@ -163,10 +163,18 @@ def put_file(self, in_path, out_path):
         display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id)
         if not self._mount_point:
             rc, stdout, stderr = self._podman(
-                "cp", [in_path, self._container_id + ":" + out_path], use_container_id=False)
+                "cp", [in_path, self._container_id + ":" + out_path], use_container_id=False
+            )
             if rc != 0:
-                raise AnsibleError("Failed to copy file from %s to %s in container %s\n%s" % (
-                    in_path, out_path, self._container_id, stderr))
+                if to_native('cannot copy into running rootless container with pause set' in to_native(stderr)):
path: lib/ansible/plugins/connection/podman.py
text: @user1:
You shouldn't need to use `to_native()` on an already native string. I'm also not sure if `to_native()` was meant to wrap the whole conditional statement. That seems like it would result in `'False'` or `'True'` which is a truthy string.
```suggestion
                if 'cannot copy into running rootless container with pause set' in to_native(stderr):
```

@author:
I wasn't thinking about wrapping the whole thing for truthy strings, was just on a `to_native()` roll and threw on where we don't need one. Thanks!