Docker* connection plugins: allow to pass extra environment variables when running commands (#940)

* Allow to pass extra environment variables when running commands.

* Make compatible with older Python.

* Remove env and ini sources for extra_env.
This commit is contained in:
Felix Fontein 2024-07-25 21:26:15 +02:00 committed by GitHub
parent 0fe84b510b
commit 7464002bc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 1 deletions

View File

@ -0,0 +1,2 @@
minor_changes:
- "docker, docker_api connection plugins - allow to pass extra environment variables when executing commands with the new ``extra_env`` option (https://github.com/ansible-collections/community.docker/issues/937, https://github.com/ansible-collections/community.docker/pull/940)."

View File

@ -75,6 +75,23 @@ options:
cli:
- name: timeout
type: integer
extra_env:
description:
- Provide extra environment variables to set when running commands in the Docker container.
- This option can currently only be provided as Ansible variables due to limitations of
ansible-core's configuration manager.
# env:
# - name: ANSIBLE_DOCKER_EXTRA_ENV
# ini:
# - key: extra_env
# section: docker_connection
# ansible-core's config manager does NOT support converting JSON strings (or other things) to dictionaries,
# it only accepts actual dictionaries (which don't happen to come from env and ini vars). So there's no way
# to actually provide this parameter from env and ini sources... :-(
vars:
- name: ansible_docker_extra_env
type: dict
version_added: 3.12.0
'''
import fcntl
@ -83,8 +100,9 @@ import os.path
import subprocess
import re
from ansible.errors import AnsibleError, AnsibleFileNotFound
from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleConnectionFailure
from ansible.module_utils.six.moves import shlex_quote
from ansible.module_utils.six import string_types
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.plugins.connection import ConnectionBase, BUFSIZE
@ -210,6 +228,17 @@ class Connection(ConnectionBase):
if self.remote_user is not None:
local_cmd += [b'-u', self.remote_user]
if self.get_option('extra_env'):
for k, v in self.get_option('extra_env').items():
for val, what in ((k, 'Key'), (v, 'Value')):
if not isinstance(val, string_types):
raise AnsibleConnectionFailure(
'Non-string {0} found for extra_env option. Ambiguous env options must be '
'wrapped in quotes to avoid them being interpreted. {1}: {2!r}'
.format(what.lower(), what, val)
)
local_cmd += [b'-e', b'%s=%s' % (to_bytes(k, errors='surrogate_or_strict'), to_bytes(v, errors='surrogate_or_strict'))]
# -i is needed to keep stdin open which allows pipelining to work
local_cmd += [b'-i', self.get_option('remote_addr')] + cmd

View File

@ -69,6 +69,23 @@ options:
cli:
- name: timeout
type: integer
extra_env:
description:
- Provide extra environment variables to set when running commands in the Docker container.
- This option can currently only be provided as Ansible variables due to limitations of
ansible-core's configuration manager.
# env:
# - name: ANSIBLE_DOCKER_EXTRA_ENV
# ini:
# - key: extra_env
# section: docker_connection
# ansible-core's config manager does NOT support converting JSON strings (or other things) to dictionaries,
# it only accepts actual dictionaries (which don't happen to come from env and ini vars). So there's no way
# to actually provide this parameter from env and ini sources... :-(
vars:
- name: ansible_docker_extra_env
type: dict
version_added: 3.12.0
'''
import os
@ -76,6 +93,7 @@ import os.path
from ansible.errors import AnsibleFileNotFound, AnsibleConnectionFailure
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.six import string_types
from ansible.plugins.connection import ConnectionBase
from ansible.utils.display import Display
@ -203,6 +221,18 @@ class Connection(ConnectionBase):
if 'detachKeys' in self.client._general_configs:
data['detachKeys'] = self.client._general_configs['detachKeys']
if self.get_option('extra_env'):
data['Env'] = []
for k, v in self.get_option('extra_env').items():
for val, what in ((k, 'Key'), (v, 'Value')):
if not isinstance(val, string_types):
raise AnsibleConnectionFailure(
'Non-string {0} found for extra_env option. Ambiguous env options must be '
'wrapped in quotes to avoid them being interpreted. {1}: {2!r}'
.format(what.lower(), what, val)
)
data['Env'].append(u'{0}={1}'.format(to_text(k, errors='surrogate_or_strict'), to_text(v, errors='surrogate_or_strict')))
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']