diff --git a/doc/source/man/openstack.rst b/doc/source/man/openstack.rst index 16f0bc4764..1023c603c6 100644 --- a/doc/source/man/openstack.rst +++ b/doc/source/man/openstack.rst @@ -83,6 +83,8 @@ OPTIONS :option:`--os-XXXX-api-version` Additional API version options will be available depending on the installed API libraries. +:option:`--os-trust-id` + id of the trust to use as a trustee user COMMANDS ======== @@ -181,21 +183,23 @@ The following environment variables can be set to alter the behaviour of :progra :envvar:`OS_CACERT` CA certificate bundle file -:envvar:`OS_COMPUTE_API_VERISON` +:envvar:`OS_COMPUTE_API_VERSION` Compute API version (Default: 2) -:envvar:`OS_IDENTITY_API_VERISON` +:envvar:`OS_IDENTITY_API_VERSION` Identity API version (Default: 2.0) -:envvar:`OS_IMAGE_API_VERISON` +:envvar:`OS_IMAGE_API_VERSION` Image API version (Default: 1) -:envvar:`OS_VOLUME_API_VERISON` +:envvar:`OS_VOLUME_API_VERSION` Volume API version (Default: 1) -:envvar:`OS_XXXX_API_VERISON` +:envvar:`OS_XXXX_API_VERSION` Additional API version options will be available depending on the installed API libraries. +:envvar:`OS_TRUST_ID` + id of the trust to use as a trustee user BUGS ==== diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py index 353a0a1988..b310f3acdc 100644 --- a/openstackclient/common/clientmanager.py +++ b/openstackclient/common/clientmanager.py @@ -48,7 +48,8 @@ class ClientManager(object): 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): + region_name=None, api_version=None, verify=True, + trust_id=None): self._token = token self._url = url self._auth_url = auth_url @@ -64,6 +65,7 @@ class ClientManager(object): self._project_domain_name = project_domain_name self._region_name = region_name self._api_version = api_version + self._trust_id = trust_id self._service_catalog = None # verify is the Requests-compatible form diff --git a/openstackclient/identity/client.py b/openstackclient/identity/client.py index b58098e90a..32a2c23b79 100644 --- a/openstackclient/identity/client.py +++ b/openstackclient/identity/client.py @@ -43,6 +43,7 @@ def make_client(instance): token=instance._token, cacert=instance._cacert, insecure=instance._insecure, + trust_id=instance._trust_id, ) else: LOG.debug('instantiating identity client: password flow') @@ -61,6 +62,7 @@ def make_client(instance): region_name=instance._region_name, cacert=instance._cacert, insecure=instance._insecure, + trust_id=instance._trust_id, ) instance.auth_ref = client.auth_ref return client diff --git a/openstackclient/shell.py b/openstackclient/shell.py index 6aae1a682e..b1a991848e 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -326,6 +326,13 @@ class OpenStackShell(app.App): help='Identity API version, default=' + identity_client.DEFAULT_IDENTITY_API_VERSION + ' (Env: OS_IDENTITY_API_VERSION)') + parser.add_argument( + '--os-trust-id', + metavar='', + default=utils.env('OS_TRUST_ID'), + help='Trust ID to use when authenticating. ' + 'This can only be used with Keystone v3 API ' + '(Env: OS_TRUST_ID)') return parser @@ -373,19 +380,35 @@ class OpenStackShell(app.App): 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)): + or self.options.os_domain_name) or + self.options.os_trust_id): raise exc.CommandError( "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].") + "--os-domain-name or env[OS_DOMAIN_NAME], or " + "--os-trust-id or env[OS_TRUST_ID].") if not self.options.os_auth_url: raise exc.CommandError( "You must provide an auth url via" " either --os-auth-url or via env[OS_AUTH_URL]") + if (self.options.os_trust_id and + self.options.os_identity_api_version != '3'): + raise exc.CommandError( + "Trusts can only be used with Identity API v3") + + if (self.options.os_trust_id and + ((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( + "Authentication cannot be scoped to multiple targets. " + "Pick one of project, domain or trust.") + self.client_manager = clientmanager.ClientManager( token=self.options.os_token, url=self.options.os_url, @@ -403,6 +426,7 @@ class OpenStackShell(app.App): region_name=self.options.os_region_name, verify=self.verify, api_version=self.api_version, + trust_id=self.options.os_trust_id, ) return diff --git a/openstackclient/tests/test_shell.py b/openstackclient/tests/test_shell.py index 2ee8503a97..dfb8021a51 100644 --- a/openstackclient/tests/test_shell.py +++ b/openstackclient/tests/test_shell.py @@ -104,6 +104,8 @@ class TestShell(utils.TestCase): default_args["password"]) self.assertEqual(_shell.options.os_region_name, default_args["region_name"]) + self.assertEqual(_shell.options.os_trust_id, + default_args["trust_id"]) def _assert_token_auth(self, cmd_options, default_args): with mock.patch("openstackclient.shell.OpenStackShell.initialize_app", @@ -181,7 +183,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -199,7 +202,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -217,7 +221,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -235,7 +240,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -253,7 +259,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -271,7 +278,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -289,7 +297,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -307,7 +316,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -325,7 +335,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -343,7 +354,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -361,7 +373,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": DEFAULT_PROJECT_DOMAIN_NAME, "username": "", "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -379,7 +392,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": DEFAULT_USERNAME, "password": "", - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -397,7 +411,8 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": DEFAULT_PASSWORD, - "region_name": "" + "region_name": "", + "trust_id": "", } self._assert_password_auth(flag, kwargs) @@ -415,7 +430,27 @@ class TestShellPasswordAuth(TestShell): "project_domain_name": "", "username": "", "password": "", - "region_name": DEFAULT_REGION_NAME + "region_name": DEFAULT_REGION_NAME, + "trust_id": "", + } + self._assert_password_auth(flag, kwargs) + + def test_only_trust_id_flow(self): + flag = "--os-trust-id " + "1234" + kwargs = { + "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": "", + "trust_id": "1234", } self._assert_password_auth(flag, kwargs)