diff --git a/mistralclient/auth/keystone.py b/mistralclient/auth/keystone.py index 4e567b44..aa633a64 100644 --- a/mistralclient/auth/keystone.py +++ b/mistralclient/auth/keystone.py @@ -171,7 +171,7 @@ class KeystoneAuthHandler(mistral_auth.AuthHandler): api.TARGET_AUTH_URI: target_auth_url, api.TARGET_SERVICE_CATALOG: jsonutils.dumps( target_auth.get_access( - target_session)._data['access']) + target_session).service_catalog.catalog) }) return auth_response diff --git a/mistralclient/shell.py b/mistralclient/shell.py index 399f92b1..57b8f7b6 100644 --- a/mistralclient/shell.py +++ b/mistralclient/shell.py @@ -569,6 +569,23 @@ class MistralShell(app.App): if self.options.password or self.options.token: self.options.auth_url = 'http://localhost:35357/v3' + if (self.options.auth_type == 'keystone' and + not self.options.auth_url.endswith("/v2.0")): + # Assume that keystone V3 is used and try to be more user-friendly, + # i.e provide default values for domains + if (not self.options.project_domain_id and + not self.options.project_domain_name): + self.options.project_domain_id = "default" + if (not self.options.user_domain_id and + not self.options.user_domain_name): + self.options.user_domain_id = "default" + if (not self.options.target_project_domain_id and + not self.options.target_project_domain_name): + self.options.target_project_domain_id = "default" + if (not self.options.target_user_domain_id and + not self.options.target_user_domain_name): + self.options.target_user_domain_id = "default" + # bash-completion should not require authentification. if do_help or ('bash-completion' in argv): self.options.auth_url = None diff --git a/mistralclient/tests/functional/cli/base.py b/mistralclient/tests/functional/cli/base.py index b870b151..9dc842e3 100644 --- a/mistralclient/tests/functional/cli/base.py +++ b/mistralclient/tests/functional/cli/base.py @@ -120,8 +120,18 @@ class MistralCLIAuth(base.ClientTestBase): project_name = credentials(project)['tenant_name'] admin_clients = self._get_clients() + + # TODO(mfedosin): when bug #1719687 is closed we should provide + # domain names in related parameters, not just as abstract flags + flags = "--os-user-domain-name default " \ + "--os-project-domain-name default " \ + "--os-identity-api-version 3" projects = self.parser.listing( - admin_clients.openstack('project show', params=project_name) + admin_clients.openstack( + 'project show', + params=project_name, + flags=flags + ) ) return [o['Value'] for o in projects if o['Field'] == 'id'][0] diff --git a/mistralclient/tests/unit/test_shell.py b/mistralclient/tests/unit/test_shell.py index d9397649..7221540f 100644 --- a/mistralclient/tests/unit/test_shell.py +++ b/mistralclient/tests/unit/test_shell.py @@ -255,3 +255,65 @@ class TestShell(base.BaseShellTests): params = client_mock.call_args self.assertEqual('default', params[1]['target_project_domain_name']) + + @mock.patch('mistralclient.api.client.client') + def test_no_domains_keystone_v3(self, client_mock): + self.shell( + '--os-auth-url=https://127.0.0.1:35357/v3 ' + '--os-username=admin ' + '--os-password=1234 ' + 'workbook-list' + ) + self.assertTrue(client_mock.called) + params = client_mock.call_args + self.assertEqual('https://127.0.0.1:35357/v3', params[1]['auth_url']) + # For keystone v3 'default' values are automatically substituted for + # project_domain_id and user_domain_id, if nothing was provided + self.assertEqual('default', params[1]['project_domain_id']) + self.assertEqual('default', params[1]['user_domain_id']) + self.assertEqual('default', params[1]['target_project_domain_id']) + self.assertEqual('default', params[1]['target_user_domain_id']) + + @mock.patch('mistralclient.api.client.client') + def test_with_domain_names_keystone_v3(self, client_mock): + self.shell( + '--os-auth-url=https://127.0.0.1:35357/v3 ' + '--os-username=admin ' + '--os-password=1234 ' + '--os-project-domain-name=fake_domain ' + '--os-user-domain-name=fake_domain ' + '--os-target-project-domain-name=fake_domain ' + '--os-target-user-domain-name=fake_domain ' + 'workbook-list' + ) + self.assertTrue(client_mock.called) + params = client_mock.call_args + self.assertEqual('https://127.0.0.1:35357/v3', params[1]['auth_url']) + # No need to substitute values for project_domain_id and + # user_domain_id if related domain names were provided + self.assertEqual('', params[1]['project_domain_id']) + self.assertEqual('', params[1]['user_domain_id']) + self.assertEqual('fake_domain', params[1]['project_domain_name']) + self.assertEqual('fake_domain', params[1]['user_domain_name']) + self.assertEqual( + 'fake_domain', + params[1]['target_project_domain_name'] + ) + self.assertEqual('fake_domain', params[1]['target_user_domain_name']) + + @mock.patch('mistralclient.api.client.client') + def test_no_domains_keystone_v2(self, client_mock): + self.shell( + '--os-auth-url=https://127.0.0.1:35357/v2.0 ' + '--os-username=admin ' + '--os-password=1234 ' + 'workbook-list' + ) + self.assertTrue(client_mock.called) + params = client_mock.call_args + self.assertEqual('https://127.0.0.1:35357/v2.0', params[1]['auth_url']) + # For keystone v2 nothing is substituted + self.assertEqual('', params[1]['project_domain_id']) + self.assertEqual('', params[1]['user_domain_id']) + self.assertEqual('', params[1]['target_project_domain_id']) + self.assertEqual('', params[1]['target_user_domain_id'])