From e9f2a14ebd5beb83a9ab06fa0ba623b01e16d98a Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Thu, 13 Mar 2025 13:34:12 -0400 Subject: [PATCH] Fix root container path for project updates in K8s Modifies to_container_path to accept an optional container_root parameter. Normally this defaults to /runner, but in K8S environments, project updates run from the private_data_dir, e.g. /tmp/awx_1_123abc, not /runner. In that situation, we just pass in private_data_dir as the container_root. --------- Signed-off-by: Seth Foster Co-authored-by: TVo --- awx/main/models/credential/__init__.py | 7 +++++-- awx/main/tasks/jobs.py | 6 +++++- awx/main/utils/execution_environments.py | 6 ++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/awx/main/models/credential/__init__.py b/awx/main/models/credential/__init__.py index e43defe730..f4135656e0 100644 --- a/awx/main/models/credential/__init__.py +++ b/awx/main/models/credential/__init__.py @@ -491,7 +491,7 @@ class CredentialType(CommonModelNameNotUnique): def load_plugin(cls, ns, plugin): ManagedCredentialType(namespace=ns, name=plugin.name, kind='external', inputs=plugin.inputs) - def inject_credential(self, credential, env, safe_env, args, private_data_dir): + def inject_credential(self, credential, env, safe_env, args, private_data_dir, container_root=None): """ Inject credential data into the environment variables and arguments passed to `ansible-playbook` @@ -515,6 +515,9 @@ class CredentialType(CommonModelNameNotUnique): :param private_data_dir: a temporary directory to store files generated by `file` injectors (like config files or key files) + + :param container_root: root directory inside of container to mount the + private data directory to """ if not self.injectors: if self.managed and credential.credential_type.namespace in dir(builtin_injectors): @@ -618,7 +621,7 @@ class CredentialType(CommonModelNameNotUnique): extra_vars = build_extra_vars(self.injectors.get('extra_vars', {})) if extra_vars: path = build_extra_vars_file(extra_vars, private_data_dir) - container_path = to_container_path(path, private_data_dir) + container_path = to_container_path(path, private_data_dir, container_root=container_root) args.extend(['-e', '@%s' % container_path]) diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index ff4ddf606c..ebfce7b03b 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -520,9 +520,13 @@ class BaseTask(object): credentials = self.build_credentials_list(self.instance) + container_root = None + if settings.IS_K8S and isinstance(self.instance, ProjectUpdate): + container_root = private_data_dir + for credential in credentials: if credential: - credential.credential_type.inject_credential(credential, env, self.safe_cred_env, args, private_data_dir) + credential.credential_type.inject_credential(credential, env, self.safe_cred_env, args, private_data_dir, container_root=container_root) self.runner_callback.safe_env.update(self.safe_cred_env) diff --git a/awx/main/utils/execution_environments.py b/awx/main/utils/execution_environments.py index 1bd2a4ca64..106aff84a8 100644 --- a/awx/main/utils/execution_environments.py +++ b/awx/main/utils/execution_environments.py @@ -79,7 +79,7 @@ def get_default_pod_spec(): CONTAINER_ROOT = '/runner' -def to_container_path(path, private_data_dir): +def to_container_path(path, private_data_dir, container_root=None): """Given a path inside of the host machine filesystem, this returns the expected path which would be observed by the job running inside of the EE container. @@ -87,9 +87,11 @@ def to_container_path(path, private_data_dir): """ if not os.path.isabs(private_data_dir): raise RuntimeError('The private_data_dir path must be absolute') + if container_root is None: + container_root = CONTAINER_ROOT # due to how tempfile.mkstemp works, we are probably passed a resolved path, but unresolved private_data_dir resolved_path = Path(path).resolve() resolved_pdd = Path(private_data_dir).resolve() if resolved_pdd != resolved_path and resolved_pdd not in resolved_path.parents: raise RuntimeError(f'Cannot convert path {resolved_path} unless it is a subdir of {resolved_pdd}') - return str(resolved_path).replace(str(resolved_pdd), CONTAINER_ROOT, 1) + return str(resolved_path).replace(str(resolved_pdd), container_root, 1)