mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 18:07:36 -02:30
Merge pull request #9505 from shanemcd/inventory_import-podman
Update inventory_import to run inside of an EE Option 2 identified in #9504 Reviewed-by: Ryan Petrello <None>
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
# Python
|
# Python
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import fnmatch
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -34,11 +33,7 @@ from awx.main.utils.safe_yaml import sanitize_jinja
|
|||||||
|
|
||||||
# other AWX imports
|
# other AWX imports
|
||||||
from awx.main.models.rbac import batch_role_ancestor_rebuilding
|
from awx.main.models.rbac import batch_role_ancestor_rebuilding
|
||||||
# TODO: remove proot utils once we move to running inv. updates in containers
|
|
||||||
from awx.main.utils import (
|
from awx.main.utils import (
|
||||||
check_proot_installed,
|
|
||||||
wrap_args_with_proot,
|
|
||||||
build_proot_temp_dir,
|
|
||||||
ignore_inventory_computed_fields,
|
ignore_inventory_computed_fields,
|
||||||
get_licenser
|
get_licenser
|
||||||
)
|
)
|
||||||
@@ -89,27 +84,6 @@ class AnsibleInventoryLoader(object):
|
|||||||
else:
|
else:
|
||||||
self.venv_path = settings.ANSIBLE_VENV_PATH
|
self.venv_path = settings.ANSIBLE_VENV_PATH
|
||||||
|
|
||||||
def build_env(self):
|
|
||||||
env = dict(os.environ.items())
|
|
||||||
env['VIRTUAL_ENV'] = self.venv_path
|
|
||||||
env['PATH'] = os.path.join(self.venv_path, "bin") + ":" + env['PATH']
|
|
||||||
# Set configuration items that should always be used for updates
|
|
||||||
for key, value in STANDARD_INVENTORY_UPDATE_ENV.items():
|
|
||||||
if key not in env:
|
|
||||||
env[key] = value
|
|
||||||
venv_libdir = os.path.join(self.venv_path, "lib")
|
|
||||||
env.pop('PYTHONPATH', None) # default to none if no python_ver matches
|
|
||||||
for version in os.listdir(venv_libdir):
|
|
||||||
if fnmatch.fnmatch(version, 'python[23].*'):
|
|
||||||
if os.path.isdir(os.path.join(venv_libdir, version)):
|
|
||||||
env['PYTHONPATH'] = os.path.join(venv_libdir, version, "site-packages") + ":"
|
|
||||||
break
|
|
||||||
# For internal inventory updates, these are not reported in the job_env API
|
|
||||||
logger.info('Using VIRTUAL_ENV: {}'.format(env['VIRTUAL_ENV']))
|
|
||||||
logger.info('Using PATH: {}'.format(env['PATH']))
|
|
||||||
logger.info('Using PYTHONPATH: {}'.format(env.get('PYTHONPATH', None)))
|
|
||||||
return env
|
|
||||||
|
|
||||||
def get_path_to_ansible_inventory(self):
|
def get_path_to_ansible_inventory(self):
|
||||||
venv_exe = os.path.join(self.venv_path, 'bin', 'ansible-inventory')
|
venv_exe = os.path.join(self.venv_path, 'bin', 'ansible-inventory')
|
||||||
if os.path.exists(venv_exe):
|
if os.path.exists(venv_exe):
|
||||||
@@ -128,66 +102,29 @@ class AnsibleInventoryLoader(object):
|
|||||||
return shutil.which('ansible-inventory')
|
return shutil.which('ansible-inventory')
|
||||||
|
|
||||||
def get_base_args(self):
|
def get_base_args(self):
|
||||||
# get ansible-inventory absolute path for running in bubblewrap/proot, in Popen
|
bargs = ['podman', 'run', '--user=root', '--quiet']
|
||||||
ansible_inventory_path = self.get_path_to_ansible_inventory()
|
bargs.extend(['-v', '{0}:{0}:Z'.format(self.source)])
|
||||||
# NOTE: why do we add "python" to the start of these args?
|
for key, value in STANDARD_INVENTORY_UPDATE_ENV.items():
|
||||||
# the script that runs ansible-inventory specifies a python interpreter
|
bargs.extend(['-e', '{0}={1}'.format(key, value)])
|
||||||
# that makes no sense in light of the fact that we put all the dependencies
|
bargs.extend([settings.AWX_CONTAINER_GROUP_DEFAULT_IMAGE])
|
||||||
# inside of /var/lib/awx/venv/ansible, so we override the specified interpreter
|
bargs.extend(['ansible-inventory', '-i', self.source])
|
||||||
# https://github.com/ansible/ansible/issues/50714
|
|
||||||
bargs = ['python', ansible_inventory_path, '-i', self.source]
|
|
||||||
bargs.extend(['--playbook-dir', functioning_dir(self.source)])
|
bargs.extend(['--playbook-dir', functioning_dir(self.source)])
|
||||||
if self.verbosity:
|
if self.verbosity:
|
||||||
# INFO: -vvv, DEBUG: -vvvvv, for inventory, any more than 3 makes little difference
|
# INFO: -vvv, DEBUG: -vvvvv, for inventory, any more than 3 makes little difference
|
||||||
bargs.append('-{}'.format('v' * min(5, self.verbosity * 2 + 1)))
|
bargs.append('-{}'.format('v' * min(5, self.verbosity * 2 + 1)))
|
||||||
|
bargs.append('--list')
|
||||||
logger.debug('Using base command: {}'.format(' '.join(bargs)))
|
logger.debug('Using base command: {}'.format(' '.join(bargs)))
|
||||||
return bargs
|
return bargs
|
||||||
|
|
||||||
# TODO: Remove this once we move to running ansible-inventory in containers
|
|
||||||
# and don't need proot for process isolation anymore
|
|
||||||
def get_proot_args(self, cmd, env):
|
|
||||||
cwd = os.getcwd()
|
|
||||||
if not check_proot_installed():
|
|
||||||
raise RuntimeError("proot is not installed but is configured for use")
|
|
||||||
|
|
||||||
kwargs = {}
|
|
||||||
# we cannot safely store tmp data in source dir or trust script contents
|
|
||||||
if env['AWX_PRIVATE_DATA_DIR']:
|
|
||||||
# If this is non-blank, file credentials are being used and we need access
|
|
||||||
private_data_dir = functioning_dir(env['AWX_PRIVATE_DATA_DIR'])
|
|
||||||
logger.debug("Using private credential data in '{}'.".format(private_data_dir))
|
|
||||||
kwargs['private_data_dir'] = private_data_dir
|
|
||||||
self.tmp_private_dir = build_proot_temp_dir()
|
|
||||||
logger.debug("Using fresh temporary directory '{}' for isolation.".format(self.tmp_private_dir))
|
|
||||||
kwargs['proot_temp_dir'] = self.tmp_private_dir
|
|
||||||
kwargs['proot_show_paths'] = [functioning_dir(self.source), settings.AWX_ANSIBLE_COLLECTIONS_PATHS]
|
|
||||||
logger.debug("Running from `{}` working directory.".format(cwd))
|
|
||||||
|
|
||||||
if self.venv_path != settings.ANSIBLE_VENV_PATH:
|
|
||||||
kwargs['proot_custom_virtualenv'] = self.venv_path
|
|
||||||
|
|
||||||
return wrap_args_with_proot(cmd, cwd, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def command_to_json(self, cmd):
|
def command_to_json(self, cmd):
|
||||||
data = {}
|
data = {}
|
||||||
stdout, stderr = '', ''
|
stdout, stderr = '', ''
|
||||||
env = self.build_env()
|
|
||||||
|
|
||||||
# TODO: remove proot args once inv. updates run in containers
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
if (('AWX_PRIVATE_DATA_DIR' in env) and
|
|
||||||
getattr(settings, 'AWX_PROOT_ENABLED', False)):
|
|
||||||
cmd = self.get_proot_args(cmd, env)
|
|
||||||
|
|
||||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
|
|
||||||
stdout, stderr = proc.communicate()
|
stdout, stderr = proc.communicate()
|
||||||
stdout = smart_text(stdout)
|
stdout = smart_text(stdout)
|
||||||
stderr = smart_text(stderr)
|
stderr = smart_text(stderr)
|
||||||
|
|
||||||
# TODO: can be removed when proot is removed
|
|
||||||
if self.tmp_private_dir:
|
|
||||||
shutil.rmtree(self.tmp_private_dir, True)
|
|
||||||
|
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
raise RuntimeError('%s failed (rc=%d) with stdout:\n%s\nstderr:\n%s' % (
|
raise RuntimeError('%s failed (rc=%d) with stdout:\n%s\nstderr:\n%s' % (
|
||||||
'ansible-inventory', proc.returncode, stdout, stderr))
|
'ansible-inventory', proc.returncode, stdout, stderr))
|
||||||
@@ -205,9 +142,10 @@ class AnsibleInventoryLoader(object):
|
|||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
base_args = self.get_base_args()
|
base_args = self.get_base_args()
|
||||||
|
|
||||||
logger.info('Reading Ansible inventory source: %s', self.source)
|
logger.info('Reading Ansible inventory source: %s', self.source)
|
||||||
|
|
||||||
return self.command_to_json(base_args + ['--list'])
|
return self.command_to_json(base_args)
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
|||||||
Reference in New Issue
Block a user