diff --git a/awx/main/models/credential/injectors.py b/awx/main/models/credential/injectors.py index 9bf7edc4a9..945077851a 100644 --- a/awx/main/models/credential/injectors.py +++ b/awx/main/models/credential/injectors.py @@ -1,4 +1,5 @@ import json +import yaml import os import stat import tempfile @@ -62,3 +63,32 @@ def vmware(cred, env, private_data_dir): env['VMWARE_PASSWORD'] = cred.get_input('password', default='') env['VMWARE_HOST'] = cred.get_input('host', default='') env['VMWARE_VALIDATE_CERTS'] = str(settings.VMWARE_VALIDATE_CERTS) + + +def _openstack_data(cred): + openstack_auth = dict(auth_url=cred.get_input('host', default=''), + username=cred.get_input('username', default=''), + password=cred.get_input('password', default=''), + project_name=cred.get_input('project', default='')) + if cred.has_input('domain'): + openstack_auth['domain_name'] = cred.get_input('domain', default='') + verify_state = cred.get_input('verify_ssl', default=True) + openstack_data = { + 'clouds': { + 'devstack': { + 'auth': openstack_auth, + 'verify': verify_state, + }, + }, + } + return openstack_data + + +def openstack(cred, env, private_data_dir): + handle, path = tempfile.mkstemp(dir=private_data_dir) + f = os.fdopen(handle, 'w') + openstack_data = _openstack_data(cred) + yaml.safe_dump(openstack_data, f, default_flow_style=False, allow_unicode=True) + f.close() + os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) + env['OS_CLIENT_CONFIG_FILE'] = path diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index ab2af142b1..057c99f325 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -59,6 +59,7 @@ from awx.main.models.notifications import ( NotificationTemplate, JobNotificationMixin, ) +from awx.main.models.credential.injectors import _openstack_data from awx.main.utils import _inventory_updates, region_sorting, get_licenser @@ -2463,25 +2464,10 @@ class openstack(PluginFileInjector): def script_name(self): return 'openstack_inventory.py' # exception - def _get_clouds_dict(self, inventory_update, credential, private_data_dir, mk_cache=True): - openstack_auth = dict(auth_url=credential.get_input('host', default=''), - username=credential.get_input('username', default=''), - password=credential.get_input('password', default=''), - project_name=credential.get_input('project', default='')) - if credential.has_input('domain'): - openstack_auth['domain_name'] = credential.get_input('domain', default='') + def _get_clouds_dict(self, inventory_update, cred, private_data_dir, mk_cache=True): + openstack_data = _openstack_data(cred) - private_state = inventory_update.source_vars_dict.get('private', True) - verify_state = credential.get_input('verify_ssl', default=True) - openstack_data = { - 'clouds': { - 'devstack': { - 'private': private_state, - 'verify': verify_state, - 'auth': openstack_auth, - }, - }, - } + openstack_data['clouds']['devstack']['private'] = inventory_update.source_vars_dict.get('private', True) if mk_cache: # Retrieve cache path from inventory update vars if available, # otherwise create a temporary cache path only for this update. @@ -2508,26 +2494,25 @@ class openstack(PluginFileInjector): openstack_data['ansible'] = ansible_variables return openstack_data - def build_script_private_data(self, inventory_update, private_data_dir): + def build_script_private_data(self, inventory_update, private_data_dir, mk_cache=True): credential = inventory_update.get_cloud_credential() private_data = {'credentials': {}} - openstack_data = self._get_clouds_dict(inventory_update, credential, private_data_dir) + openstack_data = self._get_clouds_dict(inventory_update, credential, private_data_dir, mk_cache=mk_cache) private_data['credentials'][credential] = yaml.safe_dump( openstack_data, default_flow_style=False, allow_unicode=True ) return private_data + def build_plugin_private_data(self, inventory_update, private_data_dir): + # Credentials can be passed in the same way as the script did + # but do not create the tmp cache file + return self.build_script_private_data(inventory_update, private_data_dir, mk_cache=False) + + def get_plugin_env(self, inventory_update, private_data_dir, private_data_files): + return self.get_script_env(inventory_update, private_data_dir, private_data_files) + def inventory_as_dict(self, inventory_update, private_data_dir): - credential = inventory_update.get_cloud_credential() - - openstack_data = self._get_clouds_dict(inventory_update, credential, private_data_dir, mk_cache=False) - handle, path = tempfile.mkstemp(dir=private_data_dir) - f = os.fdopen(handle, 'w') - yaml.dump(openstack_data, f, default_flow_style=False) - f.close() - os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) - def use_host_name_for_name(a_bool_maybe): if not isinstance(a_bool_maybe, bool): # Could be specified by user via "host" or "uuid" @@ -2542,7 +2527,6 @@ class openstack(PluginFileInjector): fail_on_errors=True, expand_hostvars=True, inventory_hostname=use_host_name_for_name(False), - clouds_yaml_path=[path] # why a list? it just is ) # Note: mucking with defaults will break import integrity # For the plugin, we need to use the same defaults as the old script diff --git a/awx/main/tasks.py b/awx/main/tasks.py index d7521729b0..52d176e146 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -1340,24 +1340,6 @@ class RunJob(BaseTask): if credential.has_input('ssh_public_key_data'): private_data.setdefault('certificates', {})[credential] = credential.get_input('ssh_public_key_data', default='') - if credential.kind == 'openstack': - openstack_auth = dict(auth_url=credential.get_input('host', default=''), - username=credential.get_input('username', default=''), - password=credential.get_input('password', default=''), - project_name=credential.get_input('project', default='')) - if credential.has_input('domain'): - openstack_auth['domain_name'] = credential.get_input('domain', default='') - verify_state = credential.get_input('verify_ssl', default=True) - openstack_data = { - 'clouds': { - 'devstack': { - 'auth': openstack_auth, - 'verify': verify_state, - }, - }, - } - private_data['credentials'][credential] = yaml.safe_dump(openstack_data, default_flow_style=False, allow_unicode=True) - return private_data def build_passwords(self, job, runtime_passwords): @@ -1450,9 +1432,6 @@ class RunJob(BaseTask): # Set environment variables for cloud credentials. cred_files = private_data_files.get('credentials', {}) - for cloud_cred in job.cloud_credentials: - if cloud_cred and cloud_cred.kind == 'openstack': - env['OS_CLIENT_CONFIG_FILE'] = cred_files.get(cloud_cred, '') for network_cred in job.network_credentials: env['ANSIBLE_NET_USERNAME'] = network_cred.get_input('username', default='') diff --git a/awx/main/tests/data/inventory/plugins/openstack/env.json b/awx/main/tests/data/inventory/plugins/openstack/env.json index f18da63d1c..88dfb239c3 100644 --- a/awx/main/tests/data/inventory/plugins/openstack/env.json +++ b/awx/main/tests/data/inventory/plugins/openstack/env.json @@ -1,3 +1,4 @@ { - "ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS": "never" + "ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS": "never", + "OS_CLIENT_CONFIG_FILE": "{{ file_reference }}" } \ No newline at end of file diff --git a/awx/main/tests/data/inventory/plugins/openstack/files/file_reference b/awx/main/tests/data/inventory/plugins/openstack/files/OS_CLIENT_CONFIG_FILE similarity index 100% rename from awx/main/tests/data/inventory/plugins/openstack/files/file_reference rename to awx/main/tests/data/inventory/plugins/openstack/files/OS_CLIENT_CONFIG_FILE diff --git a/awx/main/tests/data/inventory/plugins/openstack/files/openstack.yml b/awx/main/tests/data/inventory/plugins/openstack/files/openstack.yml index 2356b3c4ed..c2b6ee58f3 100644 --- a/awx/main/tests/data/inventory/plugins/openstack/files/openstack.yml +++ b/awx/main/tests/data/inventory/plugins/openstack/files/openstack.yml @@ -1,5 +1,3 @@ -clouds_yaml_path: -- {{ file_reference }} expand_hostvars: true fail_on_errors: true inventory_hostname: uuid