diff --git a/awx/main/models/credential/__init__.py b/awx/main/models/credential/__init__.py index 1701c1fb24..85800b4029 100644 --- a/awx/main/models/credential/__init__.py +++ b/awx/main/models/credential/__init__.py @@ -799,6 +799,10 @@ ManagedCredentialType( 'id': 'project', 'label': ugettext_noop('Project (Tenant Name)'), 'type': 'string', + }, { + 'id': 'project_domain_name', + 'label': ugettext_noop('Project (Domain Name)'), + 'type': 'string', }, { 'id': 'domain', 'label': ugettext_noop('Domain Name'), diff --git a/awx/main/models/credential/injectors.py b/awx/main/models/credential/injectors.py index cdf193f8e9..15b8229ea2 100644 --- a/awx/main/models/credential/injectors.py +++ b/awx/main/models/credential/injectors.py @@ -77,6 +77,8 @@ def _openstack_data(cred): username=cred.get_input('username', default=''), password=cred.get_input('password', default=''), project_name=cred.get_input('project', default='')) + if cred.has_input('project_domain_name'): + openstack_auth['project_domain_name'] = cred.get_input('project_domain_name', default='') if cred.has_input('domain'): openstack_auth['domain_name'] = cred.get_input('domain', default='') verify_state = cred.get_input('verify_ssl', default=True) diff --git a/awx/main/tests/data/inventory/plugins/openstack/files/file_reference b/awx/main/tests/data/inventory/plugins/openstack/files/file_reference index daf13976f4..895a1eb8a8 100644 --- a/awx/main/tests/data/inventory/plugins/openstack/files/file_reference +++ b/awx/main/tests/data/inventory/plugins/openstack/files/file_reference @@ -8,6 +8,7 @@ clouds: auth_url: https://foo.invalid domain_name: fooo password: fooo + project_domain_name: fooo project_name: fooo username: fooo private: false diff --git a/awx/main/tests/data/inventory/scripts/openstack/files/file_reference b/awx/main/tests/data/inventory/scripts/openstack/files/file_reference index 92a624965e..57b5f18197 100644 --- a/awx/main/tests/data/inventory/scripts/openstack/files/file_reference +++ b/awx/main/tests/data/inventory/scripts/openstack/files/file_reference @@ -10,6 +10,7 @@ clouds: auth_url: https://foo.invalid domain_name: fooo password: fooo + project_domain_name: fooo project_name: fooo username: fooo private: false diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index e7e208d9a3..bd3245871e 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -183,6 +183,51 @@ def test_openstack_client_config_generation(mocker, source, expected, private_da } +@pytest.mark.parametrize("source,expected", [ + (None, True), (False, False), (True, True) +]) +def test_openstack_client_config_generation_with_project_domain_name(mocker, source, expected, private_data_dir): + update = tasks.RunInventoryUpdate() + credential_type = CredentialType.defaults['openstack']() + inputs = { + 'host': 'https://keystone.openstack.example.org', + 'username': 'demo', + 'password': 'secrete', + 'project': 'demo-project', + 'domain': 'my-demo-domain', + 'project_domain_name': 'project-domain', + } + if source is not None: + inputs['verify_ssl'] = source + credential = Credential(pk=1, credential_type=credential_type, inputs=inputs) + + inventory_update = mocker.Mock(**{ + 'source': 'openstack', + 'source_vars_dict': {}, + 'get_cloud_credential': mocker.Mock(return_value=credential), + 'get_extra_credentials': lambda x: [], + 'ansible_virtualenv_path': '/venv/foo' + }) + cloud_config = update.build_private_data(inventory_update, private_data_dir) + cloud_credential = yaml.safe_load( + cloud_config.get('credentials')[credential] + ) + assert cloud_credential['clouds'] == { + 'devstack': { + 'auth': { + 'auth_url': 'https://keystone.openstack.example.org', + 'password': 'secrete', + 'project_name': 'demo-project', + 'username': 'demo', + 'domain_name': 'my-demo-domain', + 'project_domain_name': 'project-domain', + }, + 'verify': expected, + 'private': True, + } + } + + @pytest.mark.parametrize("source,expected", [ (False, False), (True, True) ])