diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py index a0224064d..b6dab253a 100644 --- a/openstackclient/common/clientmanager.py +++ b/openstackclient/common/clientmanager.py @@ -42,16 +42,26 @@ class ClientManager(object): """Manages access to API clients, including authentication.""" identity = ClientCache(identity_client.make_client) - def __init__(self, token=None, url=None, auth_url=None, project_name=None, - project_id=None, username=None, password=None, - region_name=None, verify=True, api_version=None): + def __init__(self, token=None, url=None, auth_url=None, + domain_id=None, domain_name=None, + project_name=None, project_id=None, + username=None, password=None, + user_domain_id=None, user_domain_name=None, + project_domain_id=None, project_domain_name=None, + region_name=None, api_version=None, verify=True): self._token = token self._url = url self._auth_url = auth_url + self._domain_id = domain_id + self._domain_name = domain_name self._project_name = project_name self._project_id = project_id self._username = username self._password = password + self._user_domain_id = user_domain_id + self._user_domain_name = user_domain_name + self._project_domain_id = project_domain_id + self._project_domain_name = project_domain_name self._region_name = region_name self._api_version = api_version self._service_catalog = None diff --git a/openstackclient/identity/client.py b/openstackclient/identity/client.py index 305d4cc45..b19388ccb 100644 --- a/openstackclient/identity/client.py +++ b/openstackclient/identity/client.py @@ -46,6 +46,12 @@ def make_client(instance): client = identity_client( username=instance._username, password=instance._password, + user_domain_id=instance._user_domain_id, + user_domain_name=instance._user_domain_name, + project_domain_id=instance._project_domain_id, + project_domain_name=instance._project_domain_name, + domain_id=instance._domain_id, + domain_name=instance._domain_name, tenant_name=instance._project_name, tenant_id=instance._project_id, auth_url=instance._auth_url, diff --git a/openstackclient/shell.py b/openstackclient/shell.py index 73766a6ed..76cc3c6a9 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -143,11 +143,26 @@ class OpenStackShell(app.App): metavar='', default=env('OS_AUTH_URL'), help='Authentication URL (Env: OS_AUTH_URL)') + parser.add_argument( + '--os-domain-name', + metavar='', + default=env('OS_DOMAIN_NAME'), + help='Domain name of the requested domain-level' + 'authorization scope (Env: OS_DOMAIN_NAME)', + ) + parser.add_argument( + '--os-domain-id', + metavar='', + default=env('OS_DOMAIN_ID'), + help='Domain ID of the requested domain-level' + 'authorization scope (Env: OS_DOMAIN_ID)', + ) parser.add_argument( '--os-project-name', metavar='', default=env('OS_PROJECT_NAME', default=env('OS_TENANT_NAME')), - help='Authentication project name (Env: OS_PROJECT_NAME)', + help='Project name of the requested project-level' + 'authorization scope (Env: OS_PROJECT_NAME)', ) parser.add_argument( '--os-tenant-name', @@ -159,7 +174,8 @@ class OpenStackShell(app.App): '--os-project-id', metavar='', default=env('OS_PROJECT_ID', default=env('OS_TENANT_ID')), - help='Authentication project ID (Env: OS_PROJECT_ID)', + help='Project ID of the requested project-level' + 'authorization scope (Env: OS_PROJECT_ID)', ) parser.add_argument( '--os-tenant-id', @@ -177,6 +193,30 @@ class OpenStackShell(app.App): metavar='', default=utils.env('OS_PASSWORD'), help='Authentication password (Env: OS_PASSWORD)') + parser.add_argument( + '--os-user-domain-name', + metavar='', + default=utils.env('OS_USER_DOMAIN_NAME'), + help='Domain name of the user (Env: OS_USER_DOMAIN_NAME)') + parser.add_argument( + '--os-user-domain-id', + metavar='', + default=utils.env('OS_USER_DOMAIN_ID'), + help='Domain ID of the user (Env: OS_USER_DOMAIN_ID)') + parser.add_argument( + '--os-project-domain-name', + metavar='', + default=utils.env('OS_PROJECT_DOMAIN_NAME'), + help='Domain name of the project which is the requested ' + 'project-level authorization scope ' + '(Env: OS_PROJECT_DOMAIN_NAME)') + parser.add_argument( + '--os-project-domain-id', + metavar='', + default=utils.env('OS_PROJECT_DOMAIN_ID'), + help='Domain ID of the project which is the requested ' + 'project-level authorization scope ' + '(Env: OS_PROJECT_DOMAIN_ID)') parser.add_argument( '--os-region-name', metavar='', @@ -284,11 +324,16 @@ class OpenStackShell(app.App): " either --os-password, or env[OS_PASSWORD], " " or prompted response") - if not (self.options.os_project_id - or self.options.os_project_name): + if not ((self.options.os_project_id + or self.options.os_project_name) or + (self.options.os_domain_id + or self.options.os_domain_name)): raise exc.CommandError( - "You must provide a project id via" - " either --os-project-id or via env[OS_PROJECT_ID]") + "You must provide authentication scope as a project " + "or a domain via --os-project-id or env[OS_PROJECT_ID], " + "--os-project-name or env[OS_PROJECT_NAME], " + "--os-domain-id or env[OS_DOMAIN_ID], or" + "--os-domain-name or env[OS_DOMAIN_NAME].") if not self.options.os_auth_url: raise exc.CommandError( @@ -299,8 +344,14 @@ class OpenStackShell(app.App): token=self.options.os_token, url=self.options.os_url, auth_url=self.options.os_auth_url, + domain_id=self.options.os_domain_id, + domain_name=self.options.os_domain_name, project_name=self.options.os_project_name, project_id=self.options.os_project_id, + user_domain_id=self.options.os_user_domain_id, + user_domain_name=self.options.os_user_domain_name, + project_domain_id=self.options.os_project_domain_id, + project_domain_name=self.options.os_project_domain_name, username=self.options.os_username, password=self.options.os_password, region_name=self.options.os_region_name, diff --git a/openstackclient/tests/test_shell.py b/openstackclient/tests/test_shell.py index be9c5d49b..9253f701f 100644 --- a/openstackclient/tests/test_shell.py +++ b/openstackclient/tests/test_shell.py @@ -20,13 +20,19 @@ from openstackclient import shell from openstackclient.tests import utils -DEFAULT_USERNAME = "username" -DEFAULT_PASSWORD = "password" +DEFAULT_AUTH_URL = "http://127.0.0.1:5000/v2.0/" DEFAULT_PROJECT_ID = "xxxx-yyyy-zzzz" DEFAULT_PROJECT_NAME = "project" -DEFAULT_TOKEN = "token" +DEFAULT_DOMAIN_ID = "aaaa-bbbb-cccc" +DEFAULT_DOMAIN_NAME = "domain" +DEFAULT_USER_DOMAIN_ID = "aaaa-bbbb-cccc" +DEFAULT_USER_DOMAIN_NAME = "domain" +DEFAULT_PROJECT_DOMAIN_ID = "aaaa-bbbb-cccc" +DEFAULT_PROJECT_DOMAIN_NAME = "domain" +DEFAULT_USERNAME = "username" +DEFAULT_PASSWORD = "password" DEFAULT_REGION_NAME = "ZZ9_Plural_Z_Alpha" -DEFAULT_AUTH_URL = "http://127.0.0.1:5000/v2.0/" +DEFAULT_TOKEN = "token" DEFAULT_SERVICE_URL = "http://127.0.0.1:8771/v3.0/" DEFAULT_COMPUTE_API_VERSION = "2" @@ -78,6 +84,18 @@ class TestShell(utils.TestCase): default_args["project_id"]) self.assertEqual(_shell.options.os_project_name, default_args["project_name"]) + self.assertEqual(_shell.options.os_domain_id, + default_args["domain_id"]) + self.assertEqual(_shell.options.os_domain_name, + default_args["domain_name"]) + self.assertEqual(_shell.options.os_user_domain_id, + default_args["user_domain_id"]) + self.assertEqual(_shell.options.os_user_domain_name, + default_args["user_domain_name"]) + self.assertEqual(_shell.options.os_project_domain_id, + default_args["project_domain_id"]) + self.assertEqual(_shell.options.os_project_domain_name, + default_args["project_domain_name"]) self.assertEqual(_shell.options.os_username, default_args["username"]) self.assertEqual(_shell.options.os_password, @@ -151,6 +169,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": DEFAULT_AUTH_URL, "project_id": "", "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": "", "password": "", "region_name": "" @@ -163,6 +187,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": DEFAULT_PROJECT_ID, "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": "", "password": "", "region_name": "" @@ -175,6 +205,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": "", "project_name": DEFAULT_PROJECT_NAME, + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": "", "password": "", "region_name": "" @@ -187,6 +223,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": DEFAULT_PROJECT_ID, "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": "", "password": "", "region_name": "" @@ -199,6 +241,120 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": "", "project_name": DEFAULT_PROJECT_NAME, + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", + "username": "", + "password": "", + "region_name": "" + } + self._assert_password_auth(flag, kwargs) + + def test_only_domain_id_flow(self): + flag = "--os-domain-id " + DEFAULT_DOMAIN_ID + kwargs = { + "auth_url": "", + "project_id": "", + "project_name": "", + "domain_id": DEFAULT_DOMAIN_ID, + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", + "username": "", + "password": "", + "region_name": "" + } + self._assert_password_auth(flag, kwargs) + + def test_only_domain_name_flow(self): + flag = "--os-domain-name " + DEFAULT_DOMAIN_NAME + kwargs = { + "auth_url": "", + "project_id": "", + "project_name": "", + "domain_id": "", + "domain_name": DEFAULT_DOMAIN_NAME, + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", + "username": "", + "password": "", + "region_name": "" + } + self._assert_password_auth(flag, kwargs) + + def test_only_user_domain_id_flow(self): + flag = "--os-user-domain-id " + DEFAULT_USER_DOMAIN_ID + kwargs = { + "auth_url": "", + "project_id": "", + "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": DEFAULT_USER_DOMAIN_ID, + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", + "username": "", + "password": "", + "region_name": "" + } + self._assert_password_auth(flag, kwargs) + + def test_only_user_domain_name_flow(self): + flag = "--os-user-domain-name " + DEFAULT_USER_DOMAIN_NAME + kwargs = { + "auth_url": "", + "project_id": "", + "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": DEFAULT_USER_DOMAIN_NAME, + "project_domain_id": "", + "project_domain_name": "", + "username": "", + "password": "", + "region_name": "" + } + self._assert_password_auth(flag, kwargs) + + def test_only_project_domain_id_flow(self): + flag = "--os-project-domain-id " + DEFAULT_PROJECT_DOMAIN_ID + kwargs = { + "auth_url": "", + "project_id": "", + "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": DEFAULT_PROJECT_DOMAIN_ID, + "project_domain_name": "", + "username": "", + "password": "", + "region_name": "" + } + self._assert_password_auth(flag, kwargs) + + def test_only_project_domain_name_flow(self): + flag = "--os-project-domain-name " + DEFAULT_PROJECT_DOMAIN_NAME + kwargs = { + "auth_url": "", + "project_id": "", + "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": DEFAULT_PROJECT_DOMAIN_NAME, "username": "", "password": "", "region_name": "" @@ -211,6 +367,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": "", "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": DEFAULT_USERNAME, "password": "", "region_name": "" @@ -223,6 +385,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": "", "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": "", "password": DEFAULT_PASSWORD, "region_name": "" @@ -235,6 +403,12 @@ class TestShellPasswordAuth(TestShell): "auth_url": "", "project_id": "", "project_name": "", + "domain_id": "", + "domain_name": "", + "user_domain_id": "", + "user_domain_name": "", + "project_domain_id": "", + "project_domain_name": "", "username": "", "password": "", "region_name": DEFAULT_REGION_NAME