Skip to content

Commit

Permalink
update how callback plugin gets copied and added to job container
Browse files Browse the repository at this point in the history
when in containerized environment
- always copy callback plugin to private_data_dir/artifacts/{job_id}/callback
- appending to `ANSIBLE_CALLBACK_PLUGINS` with the runner callback plugin location (from private_data/artifacts)
- unused method `utils.callback_mount`
- update unit test

Signed-off-by: Hao Liu <haoli@redhat.com>
Co-Authored-By: Alan Rominger <arominge@redhat.com>
  • Loading branch information
TheRealHaoLiu and AlanCoding committed Jun 6, 2022
1 parent e723a54 commit a08300a
Show file tree
Hide file tree
Showing 8 changed files with 18 additions and 40 deletions.
17 changes: 11 additions & 6 deletions ansible_runner/config/_base.py
Expand Up @@ -23,6 +23,7 @@
import re
import stat
import tempfile
import shutil

from base64 import b64encode
from uuid import uuid4
Expand All @@ -39,7 +40,6 @@
from ansible_runner.defaults import registry_auth_prefix
from ansible_runner.loader import ArtifactLoader
from ansible_runner.utils import (
callback_mount,
get_callback_dir,
open_fifo_write,
args2cmdline,
Expand Down Expand Up @@ -224,6 +224,7 @@ def _prepare_env(self, runner_mode='pexpect'):
self.env['AWX_ISOLATED_DATA_DIR'] = artifact_dir
if self.fact_cache_type == 'jsonfile':
self.env['ANSIBLE_CACHE_PLUGIN_CONNECTION'] = os.path.join(artifact_dir, 'fact_cache')

else:
# seed env with existing shell env
self.env = os.environ.copy()
Expand Down Expand Up @@ -262,7 +263,15 @@ def _prepare_env(self, runner_mode='pexpect'):
self.fact_cache = os.path.join(self.artifact_dir, self.settings['fact_cache'])

# Use local callback directory
if not self.containerized:
if self.containerized:
# when containerized, copy the callback dir to $pirvate_data_dir/artifacts/<job_id>/callback
# than append to env['Ansible_CALLBACK_PLUGINS'] with the copyied location
callback_dir = os.path.join(self.artifact_dir, 'callback')
shutil.copytree(get_callback_dir(), callback_dir)

container_callback_dir = os.path.join("/runner/artifacts", "{}".format(self.ident), "callback")
self.env['ANSIBLE_CALLBACK_PLUGINS'] = ':'.join(filter(None, (self.env.get('ANSIBLE_CALLBACK_PLUGINS'), container_callback_dir)))
else:
callback_dir = self.env.get('AWX_LIB_DIRECTORY', os.getenv('AWX_LIB_DIRECTORY'))
if callback_dir is None:
callback_dir = get_callback_dir()
Expand Down Expand Up @@ -504,10 +513,6 @@ def wrap_args_for_containerization(self, args, execution_mode, cmdline_args):
# custom show paths inside private_data_dir do not make sense
self._update_volume_mount_paths(new_args, "{}".format(self.private_data_dir), dst_mount_path="/runner", labels=":Z")

# Mount the stdout callback plugin from the ansible-runner code base
mount_paths = callback_mount(copy_if_needed=True)
self._update_volume_mount_paths(new_args, mount_paths[0], dst_mount_path=mount_paths[1], labels=":Z")

if self.container_auth_data:
# Pull in the necessary registry auth info, if there is a container cred
self.registry_auth_path, registry_auth_conf_file = self._generate_container_auth_dir(self.container_auth_data)
Expand Down
21 changes: 0 additions & 21 deletions ansible_runner/utils/__init__.py
Expand Up @@ -61,27 +61,6 @@ def is_dir_owner(directory):
return bool(current_user == callback_owner)


def callback_mount(copy_if_needed=False):
'''
Return a tuple that gives mount points for the standard out callback
in the form of (<host location>, <location in container>)
if copy_if_needed is set, and the install is owned by another user,
it will copy the plugin to a tmpdir for the mount in anticipation of SELinux problems
'''
container_dot_ansible = '/home/runner/.ansible'
rel_path = ('callback', '',)
host_path = os.path.join(get_plugin_dir(), *rel_path)
if copy_if_needed:
callback_dir = get_callback_dir()
if not is_dir_owner(callback_dir):
tmp_path = tempfile.mkdtemp(prefix='ansible_runner_plugins_')
register_for_cleanup(tmp_path)
host_path = os.path.join(tmp_path, 'callback')
shutil.copytree(callback_dir, host_path)
container_path = os.path.join(container_dot_ansible, 'plugins', *rel_path)
return (host_path, container_path)


class Bunch(object):

'''
Expand Down
2 changes: 0 additions & 2 deletions test/unit/config/test__base.py
Expand Up @@ -13,7 +13,6 @@
from ansible_runner.config._base import BaseConfig, BaseExecutionMode
from ansible_runner.loader import ArtifactLoader
from ansible_runner.exceptions import ConfigurationError
from ansible_runner.utils import callback_mount

try:
Pattern = re._pattern_type
Expand Down Expand Up @@ -331,7 +330,6 @@ def test_containerization_settings(tmp_path, runtime, mocker):
expected_command_start.extend([
'-v', '{}/artifacts/:/runner/artifacts/:Z'.format(rc.private_data_dir),
'-v', '{}/:/runner/:Z'.format(rc.private_data_dir),
'-v', '{0}:{1}:Z'.format(*callback_mount()),
'--env-file', '{}/env.list'.format(rc.artifact_dir),
])

Expand Down
3 changes: 1 addition & 2 deletions test/unit/config/test_ansible_cfg.py
Expand Up @@ -6,7 +6,7 @@
from ansible_runner.config.ansible_cfg import AnsibleCfgConfig
from ansible_runner.config._base import BaseExecutionMode
from ansible_runner.exceptions import ConfigurationError
from ansible_runner.utils import get_executable_path, callback_mount
from ansible_runner.utils import get_executable_path


def test_ansible_cfg_init_defaults(tmp_path, patch_private_data_dir):
Expand Down Expand Up @@ -91,7 +91,6 @@ def test_prepare_config_command_with_containerization(tmp_path, runtime, mocker)
expected_command_start.extend([
'-v', '{}/artifacts/:/runner/artifacts/:Z'.format(rc.private_data_dir),
'-v', '{}/:/runner/:Z'.format(rc.private_data_dir),
'-v', '{0}:{1}:Z'.format(*callback_mount()),
'--env-file', '{}/env.list'.format(rc.artifact_dir),
])

Expand Down
2 changes: 0 additions & 2 deletions test/unit/config/test_command.py
Expand Up @@ -6,7 +6,6 @@
from ansible_runner.config.command import CommandConfig
from ansible_runner.config._base import BaseExecutionMode
from ansible_runner.exceptions import ConfigurationError
from ansible_runner.utils import callback_mount


def test_ansible_config_defaults(tmp_path, patch_private_data_dir):
Expand Down Expand Up @@ -106,7 +105,6 @@ def test_prepare_run_command_with_containerization(tmp_path, runtime, mocker):
expected_command_start.extend([
'-v', '{}/artifacts/:/runner/artifacts/:Z'.format(rc.private_data_dir),
'-v', '{}/:/runner/:Z'.format(rc.private_data_dir),
'-v', '{0}:{1}:Z'.format(*callback_mount()),
'--env-file', '{}/env.list'.format(rc.artifact_dir),
])

Expand Down
4 changes: 1 addition & 3 deletions test/unit/config/test_doc.py
Expand Up @@ -6,7 +6,7 @@
from ansible_runner.config.doc import DocConfig
from ansible_runner.config._base import BaseExecutionMode
from ansible_runner.exceptions import ConfigurationError
from ansible_runner.utils import get_executable_path, callback_mount
from ansible_runner.utils import get_executable_path


def test_ansible_doc_defaults(tmp_path, patch_private_data_dir):
Expand Down Expand Up @@ -101,7 +101,6 @@ def test_prepare_plugin_docs_command_with_containerization(tmp_path, runtime, mo
expected_command_start.extend([
'-v', '{}/artifacts/:/runner/artifacts/:Z'.format(rc.private_data_dir),
'-v', '{}/:/runner/:Z'.format(rc.private_data_dir),
'-v', '{0}:{1}:Z'.format(*callback_mount()),
'--env-file', '{}/env.list'.format(rc.artifact_dir),
])

Expand Down Expand Up @@ -170,7 +169,6 @@ def test_prepare_plugin_list_command_with_containerization(tmp_path, runtime, mo
expected_command_start.extend([
'-v', '{}/artifacts/:/runner/artifacts/:Z'.format(rc.private_data_dir),
'-v', '{}/:/runner/:Z'.format(rc.private_data_dir),
'-v', '{0}:{1}:Z'.format(*callback_mount()),
'--env-file', '{}/env.list'.format(rc.artifact_dir),
])

Expand Down
3 changes: 1 addition & 2 deletions test/unit/config/test_inventory.py
Expand Up @@ -6,7 +6,7 @@
from ansible_runner.config.inventory import InventoryConfig
from ansible_runner.config._base import BaseExecutionMode
from ansible_runner.exceptions import ConfigurationError
from ansible_runner.utils import get_executable_path, callback_mount
from ansible_runner.utils import get_executable_path


def test_ansible_inventory_init_defaults(tmp_path, patch_private_data_dir):
Expand Down Expand Up @@ -126,7 +126,6 @@ def test_prepare_inventory_command_with_containerization(tmp_path, runtime, mock
expected_command_start.extend([
'-v', '{}/artifacts/:/runner/artifacts/:Z'.format(rc.private_data_dir),
'-v', '{}/:/runner/:Z'.format(rc.private_data_dir),
'-v', '{0}:{1}:Z'.format(*callback_mount()),
'--env-file', '{}/env.list'.format(rc.artifact_dir),
])

Expand Down
6 changes: 4 additions & 2 deletions test/unit/config/test_runner.py
Expand Up @@ -14,7 +14,6 @@
from ansible_runner.interface import init_runner
from ansible_runner.loader import ArtifactLoader
from ansible_runner.exceptions import ConfigurationError
from ansible_runner.utils import callback_mount

try:
Pattern = re._pattern_type
Expand Down Expand Up @@ -715,6 +714,10 @@ def test_containerization_settings(tmp_path, runtime, mocker):
mock_containerized = mocker.patch('ansible_runner.runner_config.RunnerConfig.containerized', new_callable=mocker.PropertyMock)
mock_containerized.return_value = True

# In this test get_callback_dir() will not return a callback plugin dir that exist
# mock shutil.copytree to just return True instead of trying to copy
mocker.patch('shutil.copytree', return_value=True)

rc = RunnerConfig(tmp_path)
rc.ident = 'foo'
rc.playbook = 'main.yaml'
Expand All @@ -733,7 +736,6 @@ def test_containerization_settings(tmp_path, runtime, mocker):

expected_command_start = [runtime, 'run', '--rm', '--tty', '--interactive', '--workdir', '/runner/project'] + \
['-v', '{}/:/runner/:Z'.format(rc.private_data_dir)] + \
['-v', '{0}:{1}:Z'.format(*callback_mount())] + \
['-v', '/host1/:/container1/', '-v', '/host2/:/container2/'] + \
['--env-file', '{}/env.list'.format(rc.artifact_dir)] + \
extra_container_args + \
Expand Down

0 comments on commit a08300a

Please sign in to comment.