Change keystoneclient to keystoneauth in docs
This was simply the result of: find -type f | xargs sed -i 's/keystoneclient/keystoneauth/g' find -type f | xargs sed -i 's/python-keystoneauth/keystoneauth/g' in the docs directory to fix the build failure. Will look at a doc rewrite soon. Change-Id: I05d4be12f31ea47e917dc79e50d17b174bf89938
This commit is contained in:
parent
49a223a370
commit
581f4cd493
|
@ -62,9 +62,9 @@ qthelp:
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-keystoneclient.qhcp"
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/keystoneauth.qhcp"
|
||||||
@echo "To view the help file:"
|
@echo "To view the help file:"
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-keystoneclient.qhc"
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/keystoneauth.qhc"
|
||||||
|
|
||||||
latex:
|
latex:
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
|
|
@ -35,10 +35,10 @@ def run_apidoc(app):
|
||||||
run_already = True
|
run_already = True
|
||||||
|
|
||||||
package_dir = path.abspath(path.join(app.srcdir, '..', '..',
|
package_dir = path.abspath(path.join(app.srcdir, '..', '..',
|
||||||
'keystoneclient'))
|
'keystoneauth'))
|
||||||
source_dir = path.join(app.srcdir, 'api')
|
source_dir = path.join(app.srcdir, 'api')
|
||||||
apidoc.main(['apidoc', package_dir, '-f',
|
apidoc.main(['apidoc', package_dir, '-f',
|
||||||
'-H', 'keystoneclient Modules',
|
'-H', 'keystoneauth Modules',
|
||||||
'-o', source_dir])
|
'-o', source_dir])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,13 +28,13 @@ V2 Identity Plugins
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Standard V2 identity plugins are defined in the module:
|
Standard V2 identity plugins are defined in the module:
|
||||||
:py:mod:`keystoneclient.auth.identity.v2`
|
:py:mod:`keystoneauth.auth.identity.v2`
|
||||||
|
|
||||||
They include:
|
They include:
|
||||||
|
|
||||||
- :py:class:`~keystoneclient.auth.identity.v2.Password`: Authenticate against
|
- :py:class:`~keystoneauth.auth.identity.v2.Password`: Authenticate against
|
||||||
a V2 identity service using a username and password.
|
a V2 identity service using a username and password.
|
||||||
- :py:class:`~keystoneclient.auth.identity.v2.Token`: Authenticate against a
|
- :py:class:`~keystoneauth.auth.identity.v2.Token`: Authenticate against a
|
||||||
V2 identity service using an existing token.
|
V2 identity service using an existing token.
|
||||||
|
|
||||||
V2 identity plugins must use an auth_url that points to the root of a V2
|
V2 identity plugins must use an auth_url that points to the root of a V2
|
||||||
|
@ -44,23 +44,23 @@ V3 Identity Plugins
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Standard V3 identity plugins are defined in the module
|
Standard V3 identity plugins are defined in the module
|
||||||
:py:mod:`keystoneclient.auth.identity.v3`.
|
:py:mod:`keystoneauth.auth.identity.v3`.
|
||||||
|
|
||||||
V3 Identity plugins are slightly different from their V2 counterparts as a V3
|
V3 Identity plugins are slightly different from their V2 counterparts as a V3
|
||||||
authentication request can contain multiple authentication methods. To handle
|
authentication request can contain multiple authentication methods. To handle
|
||||||
this V3 defines a number of different
|
this V3 defines a number of different
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.AuthMethod` classes:
|
:py:class:`~keystoneauth.auth.identity.v3.AuthMethod` classes:
|
||||||
|
|
||||||
- :py:class:`~keystoneclient.auth.identity.v3.PasswordMethod`: Authenticate
|
- :py:class:`~keystoneauth.auth.identity.v3.PasswordMethod`: Authenticate
|
||||||
against a V3 identity service using a username and password.
|
against a V3 identity service using a username and password.
|
||||||
- :py:class:`~keystoneclient.auth.identity.v3.TokenMethod`: Authenticate against
|
- :py:class:`~keystoneauth.auth.identity.v3.TokenMethod`: Authenticate against
|
||||||
a V2 identity service using an existing token.
|
a V2 identity service using an existing token.
|
||||||
|
|
||||||
The :py:class:`~keystoneclient.auth.identity.v3.AuthMethod` objects are then
|
The :py:class:`~keystoneauth.auth.identity.v3.AuthMethod` objects are then
|
||||||
passed to the :py:class:`~keystoneclient.auth.identity.v3.Auth` plugin::
|
passed to the :py:class:`~keystoneauth.auth.identity.v3.Auth` plugin::
|
||||||
|
|
||||||
>>> from keystoneclient import session
|
>>> from keystoneauth import session
|
||||||
>>> from keystoneclient.auth.identity import v3
|
>>> from keystoneauth.auth.identity import v3
|
||||||
>>> password = v3.PasswordMethod(username='user',
|
>>> password = v3.PasswordMethod(username='user',
|
||||||
... password='password')
|
... password='password')
|
||||||
>>> auth = v3.Auth(auth_url='http://my.keystone.com:5000/v3',
|
>>> auth = v3.Auth(auth_url='http://my.keystone.com:5000/v3',
|
||||||
|
@ -69,15 +69,15 @@ passed to the :py:class:`~keystoneclient.auth.identity.v3.Auth` plugin::
|
||||||
>>> sess = session.Session(auth=auth)
|
>>> sess = session.Session(auth=auth)
|
||||||
|
|
||||||
As in the majority of cases you will only want to use one
|
As in the majority of cases you will only want to use one
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.AuthMethod` there are also helper
|
:py:class:`~keystoneauth.auth.identity.v3.AuthMethod` there are also helper
|
||||||
authentication plugins for the various
|
authentication plugins for the various
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.AuthMethod` which can be used more
|
:py:class:`~keystoneauth.auth.identity.v3.AuthMethod` which can be used more
|
||||||
like the V2 plugins:
|
like the V2 plugins:
|
||||||
|
|
||||||
- :py:class:`~keystoneclient.auth.identity.v3.Password`: Authenticate using
|
- :py:class:`~keystoneauth.auth.identity.v3.Password`: Authenticate using
|
||||||
only a :py:class:`~keystoneclient.auth.identity.v3.PasswordMethod`.
|
only a :py:class:`~keystoneauth.auth.identity.v3.PasswordMethod`.
|
||||||
- :py:class:`~keystoneclient.auth.identity.v3.Token`: Authenticate using only a
|
- :py:class:`~keystoneauth.auth.identity.v3.Token`: Authenticate using only a
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.TokenMethod`.
|
:py:class:`~keystoneauth.auth.identity.v3.TokenMethod`.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ like the V2 plugins:
|
||||||
>>> sess = session.Session(auth=auth)
|
>>> sess = session.Session(auth=auth)
|
||||||
|
|
||||||
This will have exactly the same effect as using the single
|
This will have exactly the same effect as using the single
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.PasswordMethod` above.
|
:py:class:`~keystoneauth.auth.identity.v3.PasswordMethod` above.
|
||||||
|
|
||||||
V3 identity plugins must use an auth_url that points to the root of a V3
|
V3 identity plugins must use an auth_url that points to the root of a V3
|
||||||
identity server URL, i.e.: `http://hostname:5000/v3`.
|
identity server URL, i.e.: `http://hostname:5000/v3`.
|
||||||
|
@ -97,7 +97,7 @@ Version Independent Identity Plugins
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
Standard version independent identity plugins are defined in the module
|
Standard version independent identity plugins are defined in the module
|
||||||
:py:mod:`keystoneclient.auth.identity.generic`.
|
:py:mod:`keystoneauth.auth.identity.generic`.
|
||||||
|
|
||||||
For the cases of plugins that exist under both the identity V2 and V3 APIs
|
For the cases of plugins that exist under both the identity V2 and V3 APIs
|
||||||
there is an abstraction to allow the plugin to determine which of the V2 and V3
|
there is an abstraction to allow the plugin to determine which of the V2 and V3
|
||||||
|
@ -105,9 +105,9 @@ APIs are supported by the server and use the most appropriate API.
|
||||||
|
|
||||||
These plugins are:
|
These plugins are:
|
||||||
|
|
||||||
- :py:class:`~keystoneclient.auth.identity.generic.Password`: Authenticate
|
- :py:class:`~keystoneauth.auth.identity.generic.Password`: Authenticate
|
||||||
using a user/password against either v2 or v3 API.
|
using a user/password against either v2 or v3 API.
|
||||||
- :py:class:`~keystoneclient.auth.identity.generic.Token`: Authenticate using
|
- :py:class:`~keystoneauth.auth.identity.generic.Token`: Authenticate using
|
||||||
an existing token against either v2 or v3 API.
|
an existing token against either v2 or v3 API.
|
||||||
|
|
||||||
These plugins work by first querying the identity server to determine available
|
These plugins work by first querying the identity server to determine available
|
||||||
|
@ -124,7 +124,7 @@ same provided token and endpoint is available. This is useful in situations
|
||||||
where you have an ``ADMIN_TOKEN`` or in testing when you specifically know the
|
where you have an ``ADMIN_TOKEN`` or in testing when you specifically know the
|
||||||
endpoint you want to communicate with.
|
endpoint you want to communicate with.
|
||||||
|
|
||||||
It can be found at :py:class:`keystoneclient.auth.token_endpoint.Token`.
|
It can be found at :py:class:`keystoneauth.auth.token_endpoint.Token`.
|
||||||
|
|
||||||
|
|
||||||
V3 OAuth 1.0a Plugins
|
V3 OAuth 1.0a Plugins
|
||||||
|
@ -132,13 +132,13 @@ V3 OAuth 1.0a Plugins
|
||||||
|
|
||||||
There also exists a plugin for OAuth 1.0a authentication. We provide a helper
|
There also exists a plugin for OAuth 1.0a authentication. We provide a helper
|
||||||
authentication plugin at:
|
authentication plugin at:
|
||||||
:py:class:`~keystoneclient.v3.contrib.oauth1.auth.OAuth`.
|
:py:class:`~keystoneauth.v3.contrib.oauth1.auth.OAuth`.
|
||||||
The plugin requires the OAuth consumer's key and secret, as well as the OAuth
|
The plugin requires the OAuth consumer's key and secret, as well as the OAuth
|
||||||
access token's key and secret. For example::
|
access token's key and secret. For example::
|
||||||
|
|
||||||
>>> from keystoneclient.v3.contrib.oauth1 import auth
|
>>> from keystoneauth.v3.contrib.oauth1 import auth
|
||||||
>>> from keystoneclient import session
|
>>> from keystoneauth import session
|
||||||
>>> from keystoneclient.v3 import client
|
>>> from keystoneauth.v3 import client
|
||||||
>>> a = auth.OAuth('http://my.keystone.com:5000/v3',
|
>>> a = auth.OAuth('http://my.keystone.com:5000/v3',
|
||||||
... consumer_key=consumer_id,
|
... consumer_key=consumer_id,
|
||||||
... consumer_secret=consumer_secret,
|
... consumer_secret=consumer_secret,
|
||||||
|
@ -153,14 +153,14 @@ Loading Plugins by Name
|
||||||
In auth_token middleware and for some service to service communication it is
|
In auth_token middleware and for some service to service communication it is
|
||||||
possible to specify a plugin to load via name. The authentication options that
|
possible to specify a plugin to load via name. The authentication options that
|
||||||
are available are then specific to the plugin that you specified. Currently the
|
are available are then specific to the plugin that you specified. Currently the
|
||||||
authentication plugins that are available in `keystoneclient` are:
|
authentication plugins that are available in `keystoneauth` are:
|
||||||
|
|
||||||
- password: :py:class:`keystoneclient.auth.identity.generic.Password`
|
- password: :py:class:`keystoneauth.auth.identity.generic.Password`
|
||||||
- token: :py:class:`keystoneclient.auth.identity.generic.Token`
|
- token: :py:class:`keystoneauth.auth.identity.generic.Token`
|
||||||
- v2password: :py:class:`keystoneclient.auth.identity.v2.Password`
|
- v2password: :py:class:`keystoneauth.auth.identity.v2.Password`
|
||||||
- v2token: :py:class:`keystoneclient.auth.identity.v2.Token`
|
- v2token: :py:class:`keystoneauth.auth.identity.v2.Token`
|
||||||
- v3password: :py:class:`keystoneclient.auth.identity.v3.Password`
|
- v3password: :py:class:`keystoneauth.auth.identity.v3.Password`
|
||||||
- v3token: :py:class:`keystoneclient.auth.identity.v3.Token`
|
- v3token: :py:class:`keystoneauth.auth.identity.v3.Token`
|
||||||
|
|
||||||
|
|
||||||
Creating Authentication Plugins
|
Creating Authentication Plugins
|
||||||
|
@ -175,43 +175,43 @@ for the existing Identity mechanisms. As the V2 identity API is essentially
|
||||||
frozen, it is expected that new plugins are for the V3 API.
|
frozen, it is expected that new plugins are for the V3 API.
|
||||||
|
|
||||||
To implement a new V3 plugin that can be combined with others you should
|
To implement a new V3 plugin that can be combined with others you should
|
||||||
implement the base :py:class:`keystoneclient.auth.identity.v3.AuthMethod` class
|
implement the base :py:class:`keystoneauth.auth.identity.v3.AuthMethod` class
|
||||||
and implement the
|
and implement the
|
||||||
:py:meth:`~keystoneclient.auth.identity.v3.AuthMethod.get_auth_data` function.
|
:py:meth:`~keystoneauth.auth.identity.v3.AuthMethod.get_auth_data` function.
|
||||||
If your Plugin cannot be used in conjunction with existing
|
If your Plugin cannot be used in conjunction with existing
|
||||||
:py:class:`keystoneclient.auth.identity.v3.AuthMethod` then you should just
|
:py:class:`keystoneauth.auth.identity.v3.AuthMethod` then you should just
|
||||||
override :py:class:`keystoneclient.auth.identity.v3.Auth` directly.
|
override :py:class:`keystoneauth.auth.identity.v3.Auth` directly.
|
||||||
|
|
||||||
The new :py:class:`~keystoneclient.auth.identity.v3.AuthMethod` should take all
|
The new :py:class:`~keystoneauth.auth.identity.v3.AuthMethod` should take all
|
||||||
the required parameters via
|
the required parameters via
|
||||||
:py:meth:`~keystoneclient.auth.identity.v3.AuthMethod.__init__` and return from
|
:py:meth:`~keystoneauth.auth.identity.v3.AuthMethod.__init__` and return from
|
||||||
:py:meth:`~keystoneclient.auth.identity.v3.AuthMethod.get_auth_data` a tuple
|
:py:meth:`~keystoneauth.auth.identity.v3.AuthMethod.get_auth_data` a tuple
|
||||||
with the unique identifier of this plugin (e.g. *password*) and a dictionary
|
with the unique identifier of this plugin (e.g. *password*) and a dictionary
|
||||||
containing the payload of values to send to the authentication server. The
|
containing the payload of values to send to the authentication server. The
|
||||||
session, calling auth object and request headers are also passed to this
|
session, calling auth object and request headers are also passed to this
|
||||||
function so that the plugin may use or manipulate them.
|
function so that the plugin may use or manipulate them.
|
||||||
|
|
||||||
You should also provide a class that inherits from
|
You should also provide a class that inherits from
|
||||||
:py:class:`keystoneclient.auth.identity.v3.Auth` with an instance of your new
|
:py:class:`keystoneauth.auth.identity.v3.Auth` with an instance of your new
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.AuthMethod` as the `auth_methods`
|
:py:class:`~keystoneauth.auth.identity.v3.AuthMethod` as the `auth_methods`
|
||||||
parameter to :py:class:`keystoneclient.auth.identity.v3.Auth`.
|
parameter to :py:class:`keystoneauth.auth.identity.v3.Auth`.
|
||||||
|
|
||||||
By convention (and like above) these are named `PluginType` and
|
By convention (and like above) these are named `PluginType` and
|
||||||
`PluginTypeMethod` (for example
|
`PluginTypeMethod` (for example
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.Password` and
|
:py:class:`~keystoneauth.auth.identity.v3.Password` and
|
||||||
:py:class:`~keystoneclient.auth.identity.v3.PasswordMethod`).
|
:py:class:`~keystoneauth.auth.identity.v3.PasswordMethod`).
|
||||||
|
|
||||||
|
|
||||||
Creating a Custom Plugin
|
Creating a Custom Plugin
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
To implement an entirely new plugin you should implement the base class
|
To implement an entirely new plugin you should implement the base class
|
||||||
:py:class:`keystoneclient.auth.base.BaseAuthPlugin` and provide the
|
:py:class:`keystoneauth.auth.base.BaseAuthPlugin` and provide the
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.get_endpoint`,
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.get_endpoint`,
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.get_token` and
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.get_token` and
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.invalidate` functions.
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.invalidate` functions.
|
||||||
|
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.get_token` is called to
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.get_token` is called to
|
||||||
retrieve the string token from a plugin. It is intended that a plugin will
|
retrieve the string token from a plugin. It is intended that a plugin will
|
||||||
cache a received token and so if the token is still valid then it should be
|
cache a received token and so if the token is still valid then it should be
|
||||||
re-used rather than fetching a new one. A session object is provided with which
|
re-used rather than fetching a new one. A session object is provided with which
|
||||||
|
@ -219,19 +219,19 @@ the plugin can contact it's server. (Note: use `authenticated=False` when
|
||||||
making those requests or it will end up being called recursively). The return
|
making those requests or it will end up being called recursively). The return
|
||||||
value should be the token as a string.
|
value should be the token as a string.
|
||||||
|
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.get_endpoint` is called to
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.get_endpoint` is called to
|
||||||
determine a base URL for a particular service's requests. The keyword arguments
|
determine a base URL for a particular service's requests. The keyword arguments
|
||||||
provided to the function are those that are given by the `endpoint_filter`
|
provided to the function are those that are given by the `endpoint_filter`
|
||||||
variable in :py:meth:`keystoneclient.session.Session.request`. A session object
|
variable in :py:meth:`keystoneauth.session.Session.request`. A session object
|
||||||
is also provided so that the plugin may contact an external source to determine
|
is also provided so that the plugin may contact an external source to determine
|
||||||
the endpoint. Again this will be generally be called once per request and so
|
the endpoint. Again this will be generally be called once per request and so
|
||||||
it is up to the plugin to cache these responses if appropriate. The return
|
it is up to the plugin to cache these responses if appropriate. The return
|
||||||
value should be the base URL to communicate with.
|
value should be the base URL to communicate with.
|
||||||
|
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.invalidate` should also be
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.invalidate` should also be
|
||||||
implemented to clear the current user credentials so that on the next
|
implemented to clear the current user credentials so that on the next
|
||||||
:py:meth:`~keystoneclient.auth.base.BaseAuthPlugin.get_token` call a new token
|
:py:meth:`~keystoneauth.auth.base.BaseAuthPlugin.get_token` call a new token
|
||||||
can be retrieved.
|
can be retrieved.
|
||||||
|
|
||||||
The most simple example of a plugin is the
|
The most simple example of a plugin is the
|
||||||
:py:class:`keystoneclient.auth.token_endpoint.Token` plugin.
|
:py:class:`keystoneauth.auth.token_endpoint.Token` plugin.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# python-keystoneclient documentation build configuration file, created by
|
# keystoneauth documentation build configuration file, created by
|
||||||
# sphinx-quickstart on Sun Dec 6 14:19:25 2009.
|
# sphinx-quickstart on Sun Dec 6 14:19:25 2009.
|
||||||
#
|
#
|
||||||
# This file is execfile()d with the current directory set to its containing
|
# This file is execfile()d with the current directory set to its containing
|
||||||
|
@ -65,13 +65,13 @@ source_suffix = '.rst'
|
||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = 'python-keystoneclient'
|
project = 'keystoneauth'
|
||||||
copyright = 'OpenStack Contributors'
|
copyright = 'OpenStack Contributors'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
# built documents.
|
# built documents.
|
||||||
version_info = pbr.version.VersionInfo('python-keystoneclient')
|
version_info = pbr.version.VersionInfo('keystoneauth')
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = version_info.version_string()
|
version = version_info.version_string()
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
@ -196,7 +196,7 @@ html_last_updated_fmt = os.popen(git_cmd).read()
|
||||||
#html_file_suffix = ''
|
#html_file_suffix = ''
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = 'python-keystoneclientdoc'
|
htmlhelp_basename = 'keystoneauthdoc'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output -------------------------------------------------
|
# -- Options for LaTeX output -------------------------------------------------
|
||||||
|
@ -211,8 +211,8 @@ htmlhelp_basename = 'python-keystoneclientdoc'
|
||||||
# (source start file, target name, title, author, documentclass [howto/manual])
|
# (source start file, target name, title, author, documentclass [howto/manual])
|
||||||
# .
|
# .
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
('index', 'python-keystoneclient.tex',
|
('index', 'keystoneauth.tex',
|
||||||
'python-keystoneclient Documentation',
|
'keystoneauth Documentation',
|
||||||
'Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss',
|
'Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss',
|
||||||
'manual'),
|
'manual'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,7 @@ Python bindings to the OpenStack Identity API (Keystone)
|
||||||
|
|
||||||
This is a client for OpenStack Identity API. There's a Python API for
|
This is a client for OpenStack Identity API. There's a Python API for
|
||||||
:doc:`Identity API v3 <using-api-v3>` and :doc:`v2 <using-api-v2>` (the
|
:doc:`Identity API v3 <using-api-v3>` and :doc:`v2 <using-api-v2>` (the
|
||||||
:mod:`keystoneclient` modules), and a command-line script (installed as
|
:mod:`keystoneauth` modules), and a command-line script (installed as
|
||||||
:doc:`keystone <man/keystone>`).
|
:doc:`keystone <man/keystone>`).
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
|
@ -31,11 +31,11 @@ Contributing
|
||||||
============
|
============
|
||||||
|
|
||||||
Code is hosted `on GitHub`_. Submit bugs to the Keystone project on
|
Code is hosted `on GitHub`_. Submit bugs to the Keystone project on
|
||||||
`Launchpad`_. Submit code to the ``openstack/python-keystoneclient`` project
|
`Launchpad`_. Submit code to the ``openstack/keystoneauth`` project
|
||||||
using `Gerrit`_.
|
using `Gerrit`_.
|
||||||
|
|
||||||
.. _on GitHub: https://github.com/openstack/python-keystoneclient
|
.. _on GitHub: https://github.com/openstack/keystoneauth
|
||||||
.. _Launchpad: https://launchpad.net/python-keystoneclient
|
.. _Launchpad: https://launchpad.net/keystoneauth
|
||||||
.. _Gerrit: http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
.. _Gerrit: http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||||
|
|
||||||
Run tests with ``python setup.py test``.
|
Run tests with ``python setup.py test``.
|
||||||
|
|
|
@ -155,4 +155,4 @@ BUGS
|
||||||
====
|
====
|
||||||
|
|
||||||
Keystone client is hosted in Launchpad so you can view current bugs at
|
Keystone client is hosted in Launchpad so you can view current bugs at
|
||||||
https://bugs.launchpad.net/python-keystoneclient/.
|
https://bugs.launchpad.net/keystoneauth/.
|
||||||
|
|
|
@ -15,23 +15,23 @@ The main concepts in the Identity v2 API are:
|
||||||
|
|
||||||
The V2 client API lets you query and make changes through
|
The V2 client API lets you query and make changes through
|
||||||
managers. For example, to manipulate tenants, you interact with a
|
managers. For example, to manipulate tenants, you interact with a
|
||||||
``keystoneclient.v2_0.tenants.TenantManager`` object.
|
``keystoneauth.v2_0.tenants.TenantManager`` object.
|
||||||
|
|
||||||
You obtain access to managers via attributes of the
|
You obtain access to managers via attributes of the
|
||||||
``keystoneclient.v2_0.client.Client`` object. For example, the ``tenants``
|
``keystoneauth.v2_0.client.Client`` object. For example, the ``tenants``
|
||||||
attribute of the ``Client`` class is a tenant manager::
|
attribute of the ``Client`` class is a tenant manager::
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> keystone = client.Client(...)
|
>>> keystone = client.Client(...)
|
||||||
>>> keystone.tenants.list() # List tenants
|
>>> keystone.tenants.list() # List tenants
|
||||||
|
|
||||||
You create a valid ``keystoneclient.v2_0.client.Client`` object by passing
|
You create a valid ``keystoneauth.v2_0.client.Client`` object by passing
|
||||||
authentication data to the constructor. Authentication and examples of common
|
authentication data to the constructor. Authentication and examples of common
|
||||||
tasks are provided below.
|
tasks are provided below.
|
||||||
|
|
||||||
You can generally expect that when the client needs to propagate an exception
|
You can generally expect that when the client needs to propagate an exception
|
||||||
it will raise an instance of subclass of
|
it will raise an instance of subclass of
|
||||||
``keystoneclient.exceptions.ClientException``
|
``keystoneauth.exceptions.ClientException``
|
||||||
|
|
||||||
Authenticating
|
Authenticating
|
||||||
==============
|
==============
|
||||||
|
@ -45,7 +45,7 @@ endpoint and using the admin token (sometimes referred to as the service
|
||||||
token). The token is specified as the ``admin_token`` configuration option in
|
token). The token is specified as the ``admin_token`` configuration option in
|
||||||
your keystone.conf config file, which is typically in /etc/keystone::
|
your keystone.conf config file, which is typically in /etc/keystone::
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> token = '012345SECRET99TOKEN012345'
|
>>> token = '012345SECRET99TOKEN012345'
|
||||||
>>> endpoint = 'http://192.168.206.130:35357/v2.0'
|
>>> endpoint = 'http://192.168.206.130:35357/v2.0'
|
||||||
>>> keystone = client.Client(token=token, endpoint=endpoint)
|
>>> keystone = client.Client(token=token, endpoint=endpoint)
|
||||||
|
@ -54,7 +54,7 @@ If you have a username and password, authentication is done against the
|
||||||
public endpoint. You must also specify a tenant that is associated with the
|
public endpoint. You must also specify a tenant that is associated with the
|
||||||
user::
|
user::
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> username='adminUser'
|
>>> username='adminUser'
|
||||||
>>> password='secreetword'
|
>>> password='secreetword'
|
||||||
>>> tenant_name='openstackDemo'
|
>>> tenant_name='openstackDemo'
|
||||||
|
@ -67,7 +67,7 @@ Creating tenants
|
||||||
|
|
||||||
This example will create a tenant named *openStackDemo*::
|
This example will create a tenant named *openStackDemo*::
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> keystone = client.Client(...)
|
>>> keystone = client.Client(...)
|
||||||
>>> keystone.tenants.create(tenant_name="openstackDemo",
|
>>> keystone.tenants.create(tenant_name="openstackDemo",
|
||||||
... description="Default Tenant", enabled=True)
|
... description="Default Tenant", enabled=True)
|
||||||
|
@ -79,7 +79,7 @@ Creating users
|
||||||
This example will create a user named *adminUser* with a password *secretword*
|
This example will create a user named *adminUser* with a password *secretword*
|
||||||
in the opoenstackDemo tenant. We first need to retrieve the tenant::
|
in the opoenstackDemo tenant. We first need to retrieve the tenant::
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> keystone = client.Client(...)
|
>>> keystone = client.Client(...)
|
||||||
>>> tenants = keystone.tenants.list()
|
>>> tenants = keystone.tenants.list()
|
||||||
>>> my_tenant = [x for x in tenants if x.name=='openstackDemo'][0]
|
>>> my_tenant = [x for x in tenants if x.name=='openstackDemo'][0]
|
||||||
|
@ -93,7 +93,7 @@ Creating roles and adding users
|
||||||
This example will create an admin role and add the *my_user* user to that
|
This example will create an admin role and add the *my_user* user to that
|
||||||
role, but only for the *my_tenant* tenant:
|
role, but only for the *my_tenant* tenant:
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> keystone = client.Client(...)
|
>>> keystone = client.Client(...)
|
||||||
>>> role = keystone.roles.create('admin')
|
>>> role = keystone.roles.create('admin')
|
||||||
>>> my_tenant = ...
|
>>> my_tenant = ...
|
||||||
|
@ -106,7 +106,7 @@ Creating services and endpoints
|
||||||
This example will create the service and corresponding endpoint for the
|
This example will create the service and corresponding endpoint for the
|
||||||
Compute service::
|
Compute service::
|
||||||
|
|
||||||
>>> from keystoneclient.v2_0 import client
|
>>> from keystoneauth.v2_0 import client
|
||||||
>>> keystone = client.Client(...)
|
>>> keystone = client.Client(...)
|
||||||
>>> service = keystone.services.create(name="nova", service_type="compute",
|
>>> service = keystone.services.create(name="nova", service_type="compute",
|
||||||
... description="Nova Compute Service")
|
... description="Nova Compute Service")
|
||||||
|
|
|
@ -7,90 +7,90 @@ Introduction
|
||||||
|
|
||||||
The main concepts in the Identity v3 API are:
|
The main concepts in the Identity v3 API are:
|
||||||
|
|
||||||
* :py:mod:`~keystoneclient.v3.credentials`
|
* :py:mod:`~keystoneauth.v3.credentials`
|
||||||
* :py:mod:`~keystoneclient.v3.domains`
|
* :py:mod:`~keystoneauth.v3.domains`
|
||||||
* :py:mod:`~keystoneclient.v3.endpoints`
|
* :py:mod:`~keystoneauth.v3.endpoints`
|
||||||
* :py:mod:`~keystoneclient.v3.groups`
|
* :py:mod:`~keystoneauth.v3.groups`
|
||||||
* :py:mod:`~keystoneclient.v3.policies`
|
* :py:mod:`~keystoneauth.v3.policies`
|
||||||
* :py:mod:`~keystoneclient.v3.projects`
|
* :py:mod:`~keystoneauth.v3.projects`
|
||||||
* :py:mod:`~keystoneclient.v3.regions`
|
* :py:mod:`~keystoneauth.v3.regions`
|
||||||
* :py:mod:`~keystoneclient.v3.role_assignments`
|
* :py:mod:`~keystoneauth.v3.role_assignments`
|
||||||
* :py:mod:`~keystoneclient.v3.roles`
|
* :py:mod:`~keystoneauth.v3.roles`
|
||||||
* :py:mod:`~keystoneclient.v3.services`
|
* :py:mod:`~keystoneauth.v3.services`
|
||||||
* :py:mod:`~keystoneclient.v3.tokens`
|
* :py:mod:`~keystoneauth.v3.tokens`
|
||||||
* :py:mod:`~keystoneclient.v3.users`
|
* :py:mod:`~keystoneauth.v3.users`
|
||||||
|
|
||||||
The :py:mod:`keystoneclient.v3.client` API lets you query and make changes
|
The :py:mod:`keystoneauth.v3.client` API lets you query and make changes
|
||||||
through ``managers``. For example, to manipulate a project (formerly
|
through ``managers``. For example, to manipulate a project (formerly
|
||||||
called tenant), you interact with a
|
called tenant), you interact with a
|
||||||
:py:class:`keystoneclient.v3.projects.ProjectManager` object.
|
:py:class:`keystoneauth.v3.projects.ProjectManager` object.
|
||||||
|
|
||||||
You obtain access to managers through attributes of a
|
You obtain access to managers through attributes of a
|
||||||
:py:class:`keystoneclient.v3.client.Client` object. For example, the
|
:py:class:`keystoneauth.v3.client.Client` object. For example, the
|
||||||
``projects`` attribute of a ``Client`` object is a projects manager::
|
``projects`` attribute of a ``Client`` object is a projects manager::
|
||||||
|
|
||||||
>>> from keystoneclient.v3 import client
|
>>> from keystoneauth.v3 import client
|
||||||
>>> keystone = client.Client(...)
|
>>> keystone = client.Client(...)
|
||||||
>>> keystone.projects.list() # List projects
|
>>> keystone.projects.list() # List projects
|
||||||
|
|
||||||
While it is possible to instantiate a
|
While it is possible to instantiate a
|
||||||
:py:class:`keystoneclient.v3.client.Client` object (as done above for
|
:py:class:`keystoneauth.v3.client.Client` object (as done above for
|
||||||
clarity), the recommended approach is to use the discovery mechanism
|
clarity), the recommended approach is to use the discovery mechanism
|
||||||
provided by the :py:class:`keystoneclient.client.Client` class. The
|
provided by the :py:class:`keystoneauth.client.Client` class. The
|
||||||
appropriate class will be instantiated depending on the API versions
|
appropriate class will be instantiated depending on the API versions
|
||||||
available::
|
available::
|
||||||
|
|
||||||
>>> from keystoneclient import client
|
>>> from keystoneauth import client
|
||||||
>>> keystone =
|
>>> keystone =
|
||||||
... client.Client(auth_url='http://localhost:5000', ...)
|
... client.Client(auth_url='http://localhost:5000', ...)
|
||||||
>>> type(keystone)
|
>>> type(keystone)
|
||||||
<class 'keystoneclient.v3.client.Client'>
|
<class 'keystoneauth.v3.client.Client'>
|
||||||
|
|
||||||
One can force the use of a specific version of the API, either by
|
One can force the use of a specific version of the API, either by
|
||||||
using the ``version`` keyword argument::
|
using the ``version`` keyword argument::
|
||||||
|
|
||||||
>>> from keystoneclient import client
|
>>> from keystoneauth import client
|
||||||
>>> keystone = client.Client(auth_url='http://localhost:5000',
|
>>> keystone = client.Client(auth_url='http://localhost:5000',
|
||||||
version=(2,), ...)
|
version=(2,), ...)
|
||||||
>>> type(keystone)
|
>>> type(keystone)
|
||||||
<class 'keystoneclient.v2_0.client.Client'>
|
<class 'keystoneauth.v2_0.client.Client'>
|
||||||
>>> keystone = client.Client(auth_url='http://localhost:5000',
|
>>> keystone = client.Client(auth_url='http://localhost:5000',
|
||||||
version=(3,), ...)
|
version=(3,), ...)
|
||||||
>>> type(keystone)
|
>>> type(keystone)
|
||||||
<class 'keystoneclient.v3.client.Client'>
|
<class 'keystoneauth.v3.client.Client'>
|
||||||
|
|
||||||
Or by specifying directly the specific API version authentication URL
|
Or by specifying directly the specific API version authentication URL
|
||||||
as the auth_url keyword argument::
|
as the auth_url keyword argument::
|
||||||
|
|
||||||
>>> from keystoneclient import client
|
>>> from keystoneauth import client
|
||||||
>>> keystone =
|
>>> keystone =
|
||||||
... client.Client(auth_url='http://localhost:5000/v2.0', ...)
|
... client.Client(auth_url='http://localhost:5000/v2.0', ...)
|
||||||
>>> type(keystone)
|
>>> type(keystone)
|
||||||
<class 'keystoneclient.v2_0.client.Client'>
|
<class 'keystoneauth.v2_0.client.Client'>
|
||||||
>>> keystone =
|
>>> keystone =
|
||||||
... client.Client(auth_url='http://localhost:5000/v3', ...)
|
... client.Client(auth_url='http://localhost:5000/v3', ...)
|
||||||
>>> type(keystone)
|
>>> type(keystone)
|
||||||
<class 'keystoneclient.v3.client.Client'>
|
<class 'keystoneauth.v3.client.Client'>
|
||||||
|
|
||||||
Upon successful authentication, a :py:class:`keystoneclient.v3.client.Client`
|
Upon successful authentication, a :py:class:`keystoneauth.v3.client.Client`
|
||||||
object is returned (when using the Identity v3 API). Authentication and
|
object is returned (when using the Identity v3 API). Authentication and
|
||||||
examples of common tasks are provided below.
|
examples of common tasks are provided below.
|
||||||
|
|
||||||
You can generally expect that when the client needs to propagate an
|
You can generally expect that when the client needs to propagate an
|
||||||
exception it will raise an instance of subclass of
|
exception it will raise an instance of subclass of
|
||||||
``keystoneclient.exceptions.ClientException`` (see
|
``keystoneauth.exceptions.ClientException`` (see
|
||||||
:py:class:`keystoneclient.openstack.common.apiclient.exceptions.ClientException`)
|
:py:class:`keystoneauth.openstack.common.apiclient.exceptions.ClientException`)
|
||||||
|
|
||||||
Authenticating Using Sessions
|
Authenticating Using Sessions
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
Instantiate a :py:class:`keystoneclient.v3.client.Client` using a
|
Instantiate a :py:class:`keystoneauth.v3.client.Client` using a
|
||||||
:py:class:`~keystoneclient.session.Session` to provide the authentication
|
:py:class:`~keystoneauth.session.Session` to provide the authentication
|
||||||
plugin, SSL/TLS certificates, and other data::
|
plugin, SSL/TLS certificates, and other data::
|
||||||
|
|
||||||
>>> from keystoneclient.auth.identity import v3
|
>>> from keystoneauth.auth.identity import v3
|
||||||
>>> from keystoneclient import session
|
>>> from keystoneauth import session
|
||||||
>>> from keystoneclient.v3 import client
|
>>> from keystoneauth.v3 import client
|
||||||
>>> auth = v3.Password(auth_url='https://my.keystone.com:5000/v3',
|
>>> auth = v3.Password(auth_url='https://my.keystone.com:5000/v3',
|
||||||
... user_id='myuserid',
|
... user_id='myuserid',
|
||||||
... password='mypassword',
|
... password='mypassword',
|
||||||
|
@ -109,7 +109,7 @@ The *deprecated* way to authenticate is to pass the username, the user's domain
|
||||||
name (which will default to 'Default' if it is not specified), and a
|
name (which will default to 'Default' if it is not specified), and a
|
||||||
password::
|
password::
|
||||||
|
|
||||||
>>> from keystoneclient import client
|
>>> from keystoneauth import client
|
||||||
>>> auth_url = 'http://localhost:5000'
|
>>> auth_url = 'http://localhost:5000'
|
||||||
>>> username = 'adminUser'
|
>>> username = 'adminUser'
|
||||||
>>> user_domain_name = 'Default'
|
>>> user_domain_name = 'Default'
|
||||||
|
@ -118,7 +118,7 @@ password::
|
||||||
... username=username, password=password,
|
... username=username, password=password,
|
||||||
... user_domain_name=user_domain_name)
|
... user_domain_name=user_domain_name)
|
||||||
|
|
||||||
A :py:class:`~keystoneclient.session.Session` should be passed to the Client
|
A :py:class:`~keystoneauth.session.Session` should be passed to the Client
|
||||||
instead. Using a Session you're not limited to authentication using a username
|
instead. Using a Session you're not limited to authentication using a username
|
||||||
and password but can take advantage of other more secure authentication
|
and password but can take advantage of other more secure authentication
|
||||||
methods.
|
methods.
|
||||||
|
@ -126,7 +126,7 @@ methods.
|
||||||
You may optionally specify a domain or project (along with its project
|
You may optionally specify a domain or project (along with its project
|
||||||
domain name), to obtain a scoped token::
|
domain name), to obtain a scoped token::
|
||||||
|
|
||||||
>>> from keystoneclient import client
|
>>> from keystoneauth import client
|
||||||
>>> auth_url = 'http://localhost:5000'
|
>>> auth_url = 'http://localhost:5000'
|
||||||
>>> username = 'adminUser'
|
>>> username = 'adminUser'
|
||||||
>>> user_domain_name = 'Default'
|
>>> user_domain_name = 'Default'
|
||||||
|
|
|
@ -5,8 +5,8 @@ Using Sessions
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
The :py:class:`keystoneclient.session.Session` class was introduced into
|
The :py:class:`keystoneauth.session.Session` class was introduced into
|
||||||
keystoneclient as an attempt to bring a unified interface to the various
|
keystoneauth as an attempt to bring a unified interface to the various
|
||||||
OpenStack clients that share common authentication and request parameters
|
OpenStack clients that share common authentication and request parameters
|
||||||
between a variety of services.
|
between a variety of services.
|
||||||
|
|
||||||
|
@ -53,11 +53,11 @@ asked for a valid token. If a valid token is available it will be used
|
||||||
otherwise the authentication plugin may attempt to contact the authentication
|
otherwise the authentication plugin may attempt to contact the authentication
|
||||||
service and fetch a new one.
|
service and fetch a new one.
|
||||||
|
|
||||||
An example from keystoneclient::
|
An example from keystoneauth::
|
||||||
|
|
||||||
>>> from keystoneclient.auth.identity import v3
|
>>> from keystoneauth.auth.identity import v3
|
||||||
>>> from keystoneclient import session
|
>>> from keystoneauth import session
|
||||||
>>> from keystoneclient.v3 import client
|
>>> from keystoneauth.v3 import client
|
||||||
|
|
||||||
>>> auth = v3.Password(auth_url='https://my.keystone.com:5000/v2.0',
|
>>> auth = v3.Password(auth_url='https://my.keystone.com:5000/v2.0',
|
||||||
... username='myuser',
|
... username='myuser',
|
||||||
|
@ -72,16 +72,16 @@ As clients adopt this means of operating they will be created in a similar
|
||||||
fashion by passing the Session object to the client's constructor.
|
fashion by passing the Session object to the client's constructor.
|
||||||
|
|
||||||
|
|
||||||
Migrating keystoneclient to use a Session
|
Migrating keystoneauth to use a Session
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
By using a session with a keystoneclient Client we presume that you have opted
|
By using a session with a keystoneauth Client we presume that you have opted
|
||||||
in to new behavior defined by the session. For example authentication is now
|
in to new behavior defined by the session. For example authentication is now
|
||||||
on-demand rather than on creation. To allow this change in behavior there are
|
on-demand rather than on creation. To allow this change in behavior there are
|
||||||
a number of functions that have changed behavior or are no longer available.
|
a number of functions that have changed behavior or are no longer available.
|
||||||
|
|
||||||
For example the
|
For example the
|
||||||
:py:meth:`keystoneclient.httpclient.HTTPClient.authenticate` method used
|
:py:meth:`keystoneauth.httpclient.HTTPClient.authenticate` method used
|
||||||
to be able to always re-authenticate the current client and fetch a new token.
|
to be able to always re-authenticate the current client and fetch a new token.
|
||||||
As this is now controlled by the Session and not the client this has changed,
|
As this is now controlled by the Session and not the client this has changed,
|
||||||
however the function will still exist to provide compatibility with older
|
however the function will still exist to provide compatibility with older
|
||||||
|
@ -91,7 +91,7 @@ Likewise certain parameters such as ``user_id`` and ``auth_token`` that used to
|
||||||
be available on the client object post authentication will remain
|
be available on the client object post authentication will remain
|
||||||
uninitialized.
|
uninitialized.
|
||||||
|
|
||||||
When converting an application to use a session object with keystoneclient you
|
When converting an application to use a session object with keystoneauth you
|
||||||
should be aware of the possibility of changes to authentication and
|
should be aware of the possibility of changes to authentication and
|
||||||
authentication parameters and make sure to test your code thoroughly. It should
|
authentication parameters and make sure to test your code thoroughly. It should
|
||||||
have no impact on the typical CRUD interaction with the client.
|
have no impact on the typical CRUD interaction with the client.
|
||||||
|
@ -188,7 +188,7 @@ While authentication plugins will endeavour to maintain a consistent set of
|
||||||
arguments for an ``endpoint_filter`` the concept of an authentication plugin is
|
arguments for an ``endpoint_filter`` the concept of an authentication plugin is
|
||||||
purposefully generic and a specific mechanism may not know how to interpret
|
purposefully generic and a specific mechanism may not know how to interpret
|
||||||
certain arguments and ignore them. For example the
|
certain arguments and ignore them. For example the
|
||||||
:py:class:`keystoneclient.auth.token_endpoint.Token` plugin (which is used when
|
:py:class:`keystoneauth.auth.token_endpoint.Token` plugin (which is used when
|
||||||
you want to always use a specific endpoint and token combination) will always
|
you want to always use a specific endpoint and token combination) will always
|
||||||
return the same endpoint regardless of the parameters to ``endpoint_filter`` or
|
return the same endpoint regardless of the parameters to ``endpoint_filter`` or
|
||||||
a custom OpenStack authentication mechanism may not have the concept of
|
a custom OpenStack authentication mechanism may not have the concept of
|
||||||
|
|
Loading…
Reference in New Issue