Skip to content
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

Docker* connection plugins: add working_dir and privileged options #943

Merged
merged 4 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/943-connection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- "docker, docker_api connection plugins - allow to determine the working directory when executing commands with the new ``working_dir`` option (https://github.com/ansible-collections/community.docker/pull/943)."
- "docker, docker_api connection plugins - allow to execute commands with extended privileges with the new ``privileges`` option (https://github.com/ansible-collections/community.docker/pull/943)."
39 changes: 39 additions & 0 deletions plugins/connection/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,33 @@
- name: ansible_docker_extra_env
type: dict
version_added: 3.12.0
working_dir:
description:
- The directory inside the container to run commands in.
- Requires Docker CLI version 18.06 or later.
env:
- name: ANSIBLE_DOCKER_WORKING_DIR
ini:
- key: working_dir
section: docker_connection
vars:
- name: ansible_docker_working_dir
type: string
version_added: 3.12.0
privileged:
description:
- Whether commands should be run with extended privileges.
- B(Note) that this allows command to potentially break out of the container. Use with care!
env:
- name: ANSIBLE_DOCKER_PRIVILEGED
ini:
- key: privileged
section: docker_connection
vars:
- name: ansible_docker_privileged
type: boolean
default: false
version_added: 3.12.0
'''

import fcntl
Expand Down Expand Up @@ -239,6 +266,18 @@ def _build_exec_cmd(self, cmd):
)
local_cmd += [b'-e', b'%s=%s' % (to_bytes(k, errors='surrogate_or_strict'), to_bytes(v, errors='surrogate_or_strict'))]

if self.get_option('working_dir') is not None:
local_cmd += [b'-w', to_bytes(self.get_option('working_dir'), errors='surrogate_or_strict')]
if self.docker_version != u'dev' and LooseVersion(self.docker_version) < LooseVersion(u'18.06'):
# https://github.com/docker/cli/pull/732, first appeared in release 18.06.0
raise AnsibleConnectionFailure(
'Providing the working directory requires Docker CLI version 18.06 or newer. You have Docker CLI version {0}.'
.format(self.docker_version)
)

if self.get_option('privileged'):
local_cmd += [b'--privileged']

# -i is needed to keep stdin open which allows pipelining to work
local_cmd += [b'-i', self.get_option('remote_addr')] + cmd

Expand Down
40 changes: 39 additions & 1 deletion plugins/connection/docker_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,33 @@
- name: ansible_docker_extra_env
type: dict
version_added: 3.12.0
working_dir:
description:
- The directory inside the container to run commands in.
- Requires Docker API version 1.35 or later.
env:
- name: ANSIBLE_DOCKER_WORKING_DIR
ini:
- key: working_dir
section: docker_connection
vars:
- name: ansible_docker_working_dir
type: string
version_added: 3.12.0
privileged:
description:
- Whether commands should be run with extended privileges.
- B(Note) that this allows command to potentially break out of the container. Use with care!
env:
- name: ANSIBLE_DOCKER_PRIVILEGED
ini:
- key: privileged
section: docker_connection
vars:
- name: ansible_docker_privileged
type: boolean
default: false
version_added: 3.12.0
'''

import os
Expand Down Expand Up @@ -116,6 +143,8 @@

from ansible_collections.community.docker.plugins.module_utils._api.errors import APIError, DockerException, NotFound

from ansible_collections.community.docker.plugins.module_utils.version import LooseVersion

MIN_DOCKER_API = None


Expand Down Expand Up @@ -210,7 +239,7 @@ def exec_command(self, cmd, in_data=None, sudoable=False):
data = {
'Container': self.get_option('remote_addr'),
'User': self.get_option('remote_user') or '',
'Privileged': False,
'Privileged': self.get_option('privileged'),
'Tty': False,
'AttachStdin': need_stdin,
'AttachStdout': True,
Expand All @@ -233,6 +262,15 @@ def exec_command(self, cmd, in_data=None, sudoable=False):
)
data['Env'].append(u'{0}={1}'.format(to_text(k, errors='surrogate_or_strict'), to_text(v, errors='surrogate_or_strict')))

if self.get_option('working_dir') is not None:
data['WorkingDir'] = self.get_option('working_dir')
if self.client.docker_api_version < LooseVersion('1.35'):
raise AnsibleConnectionFailure(
'Providing the working directory requires Docker API version 1.35 or newer.'
' The Docker daemon the connection is using has API version {0}.'
.format(self.client.docker_api_version_str)
)

exec_data = self._call_client(lambda: self.client.post_json_to_json('/containers/{0}/exec', self.get_option('remote_addr'), data=data))
exec_id = exec_data['Id']

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/targets/connection_docker/aliases
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
# SPDX-License-Identifier: GPL-3.0-or-later

azp/4
skip/docker # coverage does not work if we're inside a docker container, since we cannot access this container's /tmp dir from the new container
skip/docker # coverage does not work if we're inside a docker container, since we cannot access this container's /tmp dir from the new container; also privileged doesn't work
destructive
2 changes: 2 additions & 0 deletions tests/integration/targets/connection_docker/runme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ cat > test_connection.inventory << EOF
[docker]
docker-no-pipelining ansible_pipelining=false
docker-pipelining ansible_pipelining=true
docker-working-dir ansible_docker_working_dir=/home
docker-privileged ansible_docker_privileged=true

[docker:vars]
ansible_host=docker-connection-test-container${CONTAINER_SUFFIX}
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/targets/connection_docker_api/aliases
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
# SPDX-License-Identifier: GPL-3.0-or-later

azp/4
skip/docker # coverage does not work if we're inside a docker container, since we cannot access this container's /tmp dir from the new container
skip/docker # coverage does not work if we're inside a docker container, since we cannot access this container's /tmp dir from the new container; also privileged doesn't work
destructive
2 changes: 2 additions & 0 deletions tests/integration/targets/connection_docker_api/runme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ cat > test_connection.inventory << EOF
[docker_api]
docker_api-no-pipelining ansible_pipelining=false
docker_api-pipelining ansible_pipelining=true
docker_api-working-dir ansible_docker_working_dir=/home
docker_api-privileged ansible_docker_privileged=true

[docker_api:vars]
ansible_host=docker-connection-test-container${CONTAINER_SUFFIX}
Expand Down
Loading