Merge "Switch to none auth for standalone mode"
This commit is contained in:
commit
5b9d7b9d50
|
@ -10,146 +10,120 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from keystoneauth1 import loading as kaloading
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironicclient.common.i18n import _
|
||||
from ironicclient import exc
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
def get_client(api_version, os_auth_token=None, ironic_url=None,
|
||||
os_username=None, os_password=None, os_auth_url=None,
|
||||
os_project_id=None, os_project_name=None, os_tenant_id=None,
|
||||
os_tenant_name=None, os_region_name=None,
|
||||
os_user_domain_id=None, os_user_domain_name=None,
|
||||
os_project_domain_id=None, os_project_domain_name=None,
|
||||
os_service_type=None, os_endpoint_type=None,
|
||||
insecure=None, timeout=None, os_cacert=None, ca_file=None,
|
||||
os_cert=None, cert_file=None, os_key=None, key_file=None,
|
||||
os_ironic_api_version=None, max_retries=None,
|
||||
retry_interval=None, session=None, **ignored_kwargs):
|
||||
|
||||
# TODO(vdrok): remove in Stein
|
||||
def convert_keystoneauth_opts(kwargs):
|
||||
old_to_new_names = {
|
||||
('os_auth_token',): 'token',
|
||||
('os_username',): 'username',
|
||||
('os_password',): 'password',
|
||||
('os_auth_url',): 'auth_url',
|
||||
('os_project_id',): 'project_id',
|
||||
('os_project_name',): 'project_name',
|
||||
('os_tenant_id',): 'tenant_id',
|
||||
('os_tenant_name',): 'tenant_name',
|
||||
('os_region_name',): 'region_name',
|
||||
('os_user_domain_id',): 'user_domain_id',
|
||||
('os_user_domain_name',): 'user_domain_name',
|
||||
('os_project_domain_id',): 'project_domain_id',
|
||||
('os_project_domain_name',): 'project_domain_name',
|
||||
('os_service_type',): 'service_type',
|
||||
('os_endpoint_type',): 'interface',
|
||||
('ironic_url',): 'endpoint',
|
||||
('os_cacert', 'ca_file'): 'cafile',
|
||||
('os_cert', 'cert_file'): 'certfile',
|
||||
('os_key', 'key_file'): 'keyfile'
|
||||
}
|
||||
for olds, new in old_to_new_names.items():
|
||||
for old in olds:
|
||||
if kwargs.get(old):
|
||||
LOG.warning('The argument "%s" passed to get_client is '
|
||||
'deprecated and will be removed in Stein release, '
|
||||
'please use "%s" instead.', old, new)
|
||||
kwargs.setdefault(new, kwargs[old])
|
||||
|
||||
|
||||
def get_client(api_version, auth_type=None, os_ironic_api_version=None,
|
||||
max_retries=None, retry_interval=None, **kwargs):
|
||||
"""Get an authenticated client, based on the credentials.
|
||||
|
||||
:param api_version: the API version to use. Valid value: '1'.
|
||||
:param os_auth_token: pre-existing token to re-use
|
||||
:param ironic_url: ironic API endpoint
|
||||
:param os_username: name of a user
|
||||
:param os_password: user's password
|
||||
:param os_auth_url: endpoint to authenticate against
|
||||
:param os_tenant_name: name of a tenant (deprecated in favour of
|
||||
os_project_name)
|
||||
:param os_tenant_id: ID of a tenant (deprecated in favour of
|
||||
os_project_id)
|
||||
:param os_project_name: name of a project
|
||||
:param os_project_id: ID of a project
|
||||
:param os_region_name: name of a keystone region
|
||||
:param os_user_domain_name: name of a domain the user belongs to
|
||||
:param os_user_domain_id: ID of a domain the user belongs to
|
||||
:param os_project_domain_name: name of a domain the project belongs to
|
||||
:param os_project_domain_id: ID of a domain the project belongs to
|
||||
:param os_service_type: the type of service to lookup the endpoint for
|
||||
:param os_endpoint_type: the type (exposure) of the endpoint
|
||||
:param insecure: allow insecure SSL (no cert verification)
|
||||
:param timeout: allows customization of the timeout for client HTTP
|
||||
requests
|
||||
:param os_cacert: path to cacert file
|
||||
:param ca_file: path to cacert file, deprecated in favour of os_cacert
|
||||
:param os_cert: path to cert file
|
||||
:param cert_file: path to cert file, deprecated in favour of os_cert
|
||||
:param os_key: path to key file
|
||||
:param key_file: path to key file, deprecated in favour of os_key
|
||||
:param os_ironic_api_version: ironic API version to use or a list of
|
||||
available API versions to attempt to negotiate.
|
||||
:param auth_type: type of keystoneauth auth plugin loader to use.
|
||||
:param os_ironic_api_version: ironic API version to use.
|
||||
:param max_retries: Maximum number of retries in case of conflict error
|
||||
:param retry_interval: Amount of time (in seconds) between retries in case
|
||||
of conflict error
|
||||
:param session: Keystone session to use
|
||||
:param ignored_kwargs: all the other params that are passed. Left for
|
||||
backwards compatibility. They are ignored.
|
||||
of conflict error.
|
||||
:param kwargs: all the other params that are passed to keystoneauth.
|
||||
"""
|
||||
# TODO(TheJulia): At some point, we should consider possibly noting
|
||||
# the "latest" flag for os_ironic_api_version to cause the client to
|
||||
# auto-negotiate to the greatest available version, however we do not
|
||||
# have the ability yet for a caller to cap the version, and will hold
|
||||
# off doing so until then.
|
||||
os_service_type = os_service_type or 'baremetal'
|
||||
os_endpoint_type = os_endpoint_type or 'publicURL'
|
||||
project_id = (os_project_id or os_tenant_id)
|
||||
project_name = (os_project_name or os_tenant_name)
|
||||
kwargs = {
|
||||
convert_keystoneauth_opts(kwargs)
|
||||
if auth_type is None:
|
||||
if 'endpoint' in kwargs:
|
||||
if 'token' in kwargs:
|
||||
auth_type = 'admin_token'
|
||||
else:
|
||||
auth_type = 'none'
|
||||
elif 'token' in kwargs and 'auth_url' in kwargs:
|
||||
auth_type = 'token'
|
||||
else:
|
||||
auth_type = 'password'
|
||||
session = kwargs.get('session')
|
||||
if not session:
|
||||
loader = kaloading.get_plugin_loader(auth_type)
|
||||
loader_options = loader.get_options()
|
||||
# option.name looks like 'project-name', while dest will be the actual
|
||||
# argument name to which the value will be passed to (project_name)
|
||||
auth_options = [o.dest for o in loader_options]
|
||||
# Include deprecated names as well
|
||||
auth_options.extend([d.dest for o in loader_options
|
||||
for d in o.deprecated])
|
||||
auth_kwargs = {k: v for (k, v) in kwargs.items() if k in auth_options}
|
||||
auth_plugin = loader.load_from_options(**auth_kwargs)
|
||||
# Let keystoneauth do the necessary parameter conversions
|
||||
session_loader = kaloading.session.Session()
|
||||
session_opts = {k: v for (k, v) in kwargs.items() if k in
|
||||
[o.dest for o in session_loader.get_conf_options()]}
|
||||
session = session_loader.load_from_options(auth=auth_plugin,
|
||||
**session_opts)
|
||||
|
||||
endpoint = kwargs.get('endpoint')
|
||||
if not endpoint:
|
||||
try:
|
||||
# endpoint will be used to get hostname
|
||||
# and port that will be used for API version caching.
|
||||
endpoint = session.get_endpoint(
|
||||
service_type=kwargs.get('service_type') or 'baremetal',
|
||||
interface=kwargs.get('interface') or 'publicURL',
|
||||
region_name=kwargs.get('region_name')
|
||||
)
|
||||
except Exception as e:
|
||||
raise exc.AmbiguousAuthSystem(
|
||||
_('Must provide Keystone credentials or user-defined '
|
||||
'endpoint, error was: %s') % e)
|
||||
|
||||
ironicclient_kwargs = {
|
||||
'os_ironic_api_version': os_ironic_api_version,
|
||||
'max_retries': max_retries,
|
||||
'retry_interval': retry_interval,
|
||||
'session': session,
|
||||
'endpoint_override': endpoint
|
||||
}
|
||||
endpoint = ironic_url
|
||||
cacert = os_cacert or ca_file
|
||||
cert = os_cert or cert_file
|
||||
key = os_key or key_file
|
||||
if os_auth_token and endpoint:
|
||||
kwargs.update({
|
||||
'token': os_auth_token,
|
||||
'insecure': insecure,
|
||||
'ca_file': cacert,
|
||||
'cert_file': cert,
|
||||
'key_file': key,
|
||||
'timeout': timeout,
|
||||
})
|
||||
elif os_auth_url:
|
||||
auth_type = 'password'
|
||||
auth_kwargs = {
|
||||
'auth_url': os_auth_url,
|
||||
'project_id': project_id,
|
||||
'project_name': project_name,
|
||||
'user_domain_id': os_user_domain_id,
|
||||
'user_domain_name': os_user_domain_name,
|
||||
'project_domain_id': os_project_domain_id,
|
||||
'project_domain_name': os_project_domain_name,
|
||||
}
|
||||
if os_username and os_password:
|
||||
auth_kwargs.update({
|
||||
'username': os_username,
|
||||
'password': os_password,
|
||||
})
|
||||
elif os_auth_token:
|
||||
auth_type = 'token'
|
||||
auth_kwargs.update({
|
||||
'token': os_auth_token,
|
||||
})
|
||||
# Create new session only if it was not passed in
|
||||
if not session:
|
||||
loader = kaloading.get_plugin_loader(auth_type)
|
||||
auth_plugin = loader.load_from_options(**auth_kwargs)
|
||||
# Let keystoneauth do the necessary parameter conversions
|
||||
session = kaloading.session.Session().load_from_options(
|
||||
auth=auth_plugin, insecure=insecure, cacert=cacert,
|
||||
cert=cert, key=key, timeout=timeout,
|
||||
)
|
||||
|
||||
exception_msg = _('Must provide Keystone credentials or user-defined '
|
||||
'endpoint and token')
|
||||
if not endpoint:
|
||||
if session:
|
||||
try:
|
||||
# Pass the endpoint, it will be used to get hostname
|
||||
# and port that will be used for API version caching. It will
|
||||
# be also set as endpoint_override.
|
||||
endpoint = session.get_endpoint(
|
||||
service_type=os_service_type,
|
||||
interface=os_endpoint_type,
|
||||
region_name=os_region_name
|
||||
)
|
||||
except Exception as e:
|
||||
raise exc.AmbiguousAuthSystem(
|
||||
_('%(message)s, error was: %(error)s') %
|
||||
{'message': exception_msg, 'error': e})
|
||||
else:
|
||||
# Neither session, nor valid auth parameters provided
|
||||
raise exc.AmbiguousAuthSystem(exception_msg)
|
||||
|
||||
# Always pass the session
|
||||
kwargs['session'] = session
|
||||
|
||||
return Client(api_version, endpoint, **kwargs)
|
||||
return Client(api_version, **ironicclient_kwargs)
|
||||
|
||||
|
||||
def Client(version, *args, **kwargs):
|
||||
|
|
|
@ -81,11 +81,11 @@ def _extract_error_json(body):
|
|||
return error_json
|
||||
|
||||
|
||||
def get_server(endpoint):
|
||||
"""Extract and return the server & port that we're connecting to."""
|
||||
if endpoint is None:
|
||||
def get_server(url):
|
||||
"""Extract and return the server & port."""
|
||||
if url is None:
|
||||
return None, None
|
||||
parts = urlparse.urlparse(endpoint)
|
||||
parts = urlparse.urlparse(url)
|
||||
return parts.hostname, str(parts.port)
|
||||
|
||||
|
||||
|
@ -205,7 +205,10 @@ class VersionNegotiationMixin(object):
|
|||
LOG.debug('Negotiated API version is %s', negotiated_ver)
|
||||
|
||||
# Cache the negotiated version for this server
|
||||
host, port = get_server(self.endpoint)
|
||||
# TODO(vdrok): get rid of self.endpoint attribute in Stein
|
||||
endpoint_override = (getattr(self, 'endpoint_override', None) or
|
||||
getattr(self, 'endpoint', None))
|
||||
host, port = get_server(endpoint_override)
|
||||
filecache.save_data(host=host, port=port, data=negotiated_ver)
|
||||
|
||||
return negotiated_ver
|
||||
|
@ -266,6 +269,8 @@ def with_retries(func):
|
|||
class HTTPClient(VersionNegotiationMixin):
|
||||
|
||||
def __init__(self, endpoint, **kwargs):
|
||||
LOG.warning('HTTPClient class is deprecated and will be removed '
|
||||
'in Stein release, please use SessionClient instead.')
|
||||
self.endpoint = endpoint
|
||||
self.endpoint_trimmed = _trim_endpoint_api_version(endpoint)
|
||||
self.auth_token = kwargs.get('token')
|
||||
|
@ -556,13 +561,19 @@ class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter):
|
|||
api_version_select_state,
|
||||
max_retries,
|
||||
retry_interval,
|
||||
endpoint,
|
||||
endpoint=None,
|
||||
**kwargs):
|
||||
self.os_ironic_api_version = os_ironic_api_version
|
||||
self.api_version_select_state = api_version_select_state
|
||||
self.conflict_max_retries = max_retries
|
||||
self.conflict_retry_interval = retry_interval
|
||||
self.endpoint = endpoint
|
||||
# TODO(vdrok): remove this conditional in Stein
|
||||
if endpoint and not kwargs.get('endpoint_override'):
|
||||
LOG.warning('Passing "endpoint" argument to SessionClient '
|
||||
'constructor is deprecated, such possibility will be '
|
||||
'removed in Stein. Please use "endpoint_override" '
|
||||
'instead.')
|
||||
self.endpoint = endpoint
|
||||
|
||||
super(SessionClient, self).__init__(**kwargs)
|
||||
|
||||
|
@ -662,8 +673,7 @@ class SessionClient(VersionNegotiationMixin, adapter.LegacyJsonAdapter):
|
|||
return self._http_request(url, method, **kwargs)
|
||||
|
||||
|
||||
def _construct_http_client(endpoint=None,
|
||||
session=None,
|
||||
def _construct_http_client(session=None,
|
||||
token=None,
|
||||
auth_ref=None,
|
||||
os_ironic_api_version=DEFAULT_VER,
|
||||
|
@ -679,8 +689,8 @@ def _construct_http_client(endpoint=None,
|
|||
if session:
|
||||
kwargs.setdefault('service_type', 'baremetal')
|
||||
kwargs.setdefault('user_agent', 'python-ironicclient')
|
||||
kwargs.setdefault('interface', kwargs.pop('endpoint_type', None))
|
||||
kwargs.setdefault('endpoint_override', endpoint)
|
||||
kwargs.setdefault('interface', kwargs.pop('endpoint_type',
|
||||
'publicURL'))
|
||||
|
||||
ignored = {'token': token,
|
||||
'auth_ref': auth_ref,
|
||||
|
@ -702,10 +712,11 @@ def _construct_http_client(endpoint=None,
|
|||
api_version_select_state=api_version_select_state,
|
||||
max_retries=max_retries,
|
||||
retry_interval=retry_interval,
|
||||
endpoint=endpoint,
|
||||
**kwargs)
|
||||
else:
|
||||
endpoint = None
|
||||
if kwargs:
|
||||
endpoint = kwargs.pop('endpoint_override', None)
|
||||
LOG.warning('The following arguments are being ignored when '
|
||||
'constructing the client: %s'), ', '.join(kwargs)
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ def make_client(instance):
|
|||
region_name=instance._region_name,
|
||||
# NOTE(vdrok): This will be set as endpoint_override, and the Client
|
||||
# class will be able to do the version stripping if needed
|
||||
endpoint=instance.get_endpoint_for_service_type(
|
||||
endpoint_override=instance.get_endpoint_for_service_type(
|
||||
API_NAME, interface=instance.interface,
|
||||
region_name=instance._region_name
|
||||
)
|
||||
|
|
|
@ -98,59 +98,75 @@ class IronicShell(object):
|
|||
help=_('DEPRECATED! Use --os-cacert.'))
|
||||
|
||||
parser.add_argument('--os-username',
|
||||
dest='username',
|
||||
default=cliutils.env('OS_USERNAME'),
|
||||
help=_('Defaults to env[OS_USERNAME]'))
|
||||
|
||||
parser.add_argument('--os_username',
|
||||
dest='username',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-password',
|
||||
dest='password',
|
||||
default=cliutils.env('OS_PASSWORD'),
|
||||
help=_('Defaults to env[OS_PASSWORD]'))
|
||||
|
||||
parser.add_argument('--os_password',
|
||||
dest='password',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-tenant-id',
|
||||
dest='tenant_id',
|
||||
default=cliutils.env('OS_TENANT_ID'),
|
||||
help=_('Defaults to env[OS_TENANT_ID]'))
|
||||
|
||||
parser.add_argument('--os_tenant_id',
|
||||
dest='tenant_id',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-tenant-name',
|
||||
dest='tenant_name',
|
||||
default=cliutils.env('OS_TENANT_NAME'),
|
||||
help=_('Defaults to env[OS_TENANT_NAME]'))
|
||||
|
||||
parser.add_argument('--os_tenant_name',
|
||||
dest='tenant_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-auth-url',
|
||||
dest='auth_url',
|
||||
default=cliutils.env('OS_AUTH_URL'),
|
||||
help=_('Defaults to env[OS_AUTH_URL]'))
|
||||
|
||||
parser.add_argument('--os_auth_url',
|
||||
dest='auth_url',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-region-name',
|
||||
dest='region_name',
|
||||
default=cliutils.env('OS_REGION_NAME'),
|
||||
help=_('Defaults to env[OS_REGION_NAME]'))
|
||||
|
||||
parser.add_argument('--os_region_name',
|
||||
dest='region_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-auth-token',
|
||||
dest='token',
|
||||
default=cliutils.env('OS_AUTH_TOKEN'),
|
||||
help=_('Defaults to env[OS_AUTH_TOKEN]'))
|
||||
|
||||
parser.add_argument('--os_auth_token',
|
||||
dest='token',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--ironic-url',
|
||||
dest='endpoint',
|
||||
default=cliutils.env('IRONIC_URL'),
|
||||
help=_('Defaults to env[IRONIC_URL]'))
|
||||
|
||||
parser.add_argument('--ironic_url',
|
||||
dest='endpoint',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--ironic-api-version',
|
||||
|
@ -164,15 +180,17 @@ class IronicShell(object):
|
|||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-service-type',
|
||||
dest='service_type',
|
||||
default=cliutils.env('OS_SERVICE_TYPE'),
|
||||
help=_('Defaults to env[OS_SERVICE_TYPE] or '
|
||||
'"baremetal"'))
|
||||
|
||||
parser.add_argument('--os_service_type',
|
||||
dest='service_type',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-endpoint',
|
||||
dest='ironic_url',
|
||||
dest='endpoint',
|
||||
default=cliutils.env('OS_SERVICE_ENDPOINT'),
|
||||
help=_('Specify an endpoint to use instead of '
|
||||
'retrieving one from the service catalog '
|
||||
|
@ -180,26 +198,31 @@ class IronicShell(object):
|
|||
'Defaults to env[OS_SERVICE_ENDPOINT].'))
|
||||
|
||||
parser.add_argument('--os_endpoint',
|
||||
dest='ironic_url',
|
||||
dest='endpoint',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-endpoint-type',
|
||||
dest='interface',
|
||||
default=cliutils.env('OS_ENDPOINT_TYPE'),
|
||||
help=_('Defaults to env[OS_ENDPOINT_TYPE] or '
|
||||
'"publicURL"'))
|
||||
|
||||
parser.add_argument('--os_endpoint_type',
|
||||
dest='interface',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-user-domain-id',
|
||||
dest='user_domain_id',
|
||||
default=cliutils.env('OS_USER_DOMAIN_ID'),
|
||||
help=_('Defaults to env[OS_USER_DOMAIN_ID].'))
|
||||
|
||||
parser.add_argument('--os-user-domain-name',
|
||||
dest='user_domain_name',
|
||||
default=cliutils.env('OS_USER_DOMAIN_NAME'),
|
||||
help=_('Defaults to env[OS_USER_DOMAIN_NAME].'))
|
||||
|
||||
parser.add_argument('--os-project-id',
|
||||
dest='project_id',
|
||||
default=cliutils.env('OS_PROJECT_ID'),
|
||||
help=_('Another way to specify tenant ID. '
|
||||
'This option is mutually exclusive with '
|
||||
|
@ -207,6 +230,7 @@ class IronicShell(object):
|
|||
'Defaults to env[OS_PROJECT_ID].'))
|
||||
|
||||
parser.add_argument('--os-project-name',
|
||||
dest='project_name',
|
||||
default=cliutils.env('OS_PROJECT_NAME'),
|
||||
help=_('Another way to specify tenant name. '
|
||||
'This option is mutually exclusive with '
|
||||
|
@ -214,10 +238,12 @@ class IronicShell(object):
|
|||
'Defaults to env[OS_PROJECT_NAME].'))
|
||||
|
||||
parser.add_argument('--os-project-domain-id',
|
||||
dest='project_domain_id',
|
||||
default=cliutils.env('OS_PROJECT_DOMAIN_ID'),
|
||||
help=_('Defaults to env[OS_PROJECT_DOMAIN_ID].'))
|
||||
|
||||
parser.add_argument('--os-project-domain-name',
|
||||
dest='project_domain_name',
|
||||
default=cliutils.env('OS_PROJECT_DOMAIN_NAME'),
|
||||
help=_('Defaults to env[OS_PROJECT_DOMAIN_NAME].'))
|
||||
|
||||
|
@ -354,38 +380,39 @@ class IronicShell(object):
|
|||
self.do_bash_completion()
|
||||
return 0
|
||||
|
||||
if not (args.os_auth_token and (args.ironic_url or args.os_auth_url)):
|
||||
if not args.os_username:
|
||||
# Assume password auth if it does not seem like none, admin_token or
|
||||
# token auth
|
||||
if not args.endpoint and not (args.token and args.auth_url):
|
||||
if not args.username:
|
||||
raise exc.CommandError(_("You must provide a username via "
|
||||
"either --os-username or via "
|
||||
"env[OS_USERNAME]"))
|
||||
|
||||
if not args.os_password:
|
||||
if not args.password:
|
||||
# No password, If we've got a tty, try prompting for it
|
||||
if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
|
||||
# Check for Ctl-D
|
||||
try:
|
||||
args.os_password = getpass.getpass(
|
||||
args.password = getpass.getpass(
|
||||
'OpenStack Password: ')
|
||||
except EOFError:
|
||||
pass
|
||||
# No password because we didn't have a tty or the
|
||||
# user Ctl-D when prompted.
|
||||
if not args.os_password:
|
||||
if not args.password:
|
||||
raise exc.CommandError(_("You must provide a password via "
|
||||
"either --os-password, "
|
||||
"env[OS_PASSWORD], "
|
||||
"or prompted response"))
|
||||
|
||||
if not (args.os_tenant_id or args.os_tenant_name or
|
||||
args.os_project_id or args.os_project_name):
|
||||
if not (args.tenant_id or args.tenant_name or
|
||||
args.project_id or args.project_name):
|
||||
raise exc.CommandError(
|
||||
_("You must provide a project name or"
|
||||
" project id via --os-project-name, --os-project-id,"
|
||||
" env[OS_PROJECT_ID] or env[OS_PROJECT_NAME]. You may"
|
||||
" use os-project and os-tenant interchangeably."))
|
||||
" env[OS_PROJECT_ID] or env[OS_PROJECT_NAME]."))
|
||||
|
||||
if not args.os_auth_url:
|
||||
if not args.auth_url:
|
||||
raise exc.CommandError(_("You must provide an auth url via "
|
||||
"either --os-auth-url or via "
|
||||
"env[OS_AUTH_URL]"))
|
||||
|
@ -397,17 +424,29 @@ class IronicShell(object):
|
|||
raise exc.CommandError(_("You must provide value >= 1 for "
|
||||
"--retry-interval"))
|
||||
client_args = (
|
||||
'os_auth_token', 'ironic_url', 'os_username', 'os_password',
|
||||
'os_auth_url', 'os_project_id', 'os_project_name', 'os_tenant_id',
|
||||
'os_tenant_name', 'os_region_name', 'os_user_domain_id',
|
||||
'os_user_domain_name', 'os_project_domain_id',
|
||||
'os_project_domain_name', 'os_service_type', 'os_endpoint_type',
|
||||
'os_cacert', 'os_cert', 'os_key', 'max_retries', 'retry_interval',
|
||||
'timeout', 'insecure'
|
||||
'token', 'endpoint', 'username', 'password', 'auth_url',
|
||||
'project_id', 'project_name', 'tenant_id', 'tenant_name',
|
||||
'region_name', 'user_domain_id', 'user_domain_name',
|
||||
'project_domain_id', 'project_domain_name', 'service_type',
|
||||
'interface', 'max_retries', 'retry_interval', 'timeout', 'insecure'
|
||||
)
|
||||
kwargs = {}
|
||||
for key in client_args:
|
||||
kwargs[key] = getattr(args, key)
|
||||
value = getattr(args, key)
|
||||
# NOTE(vdrok): check for both None and ''. If the default value
|
||||
# for option is set using cliutils.env function, default empty
|
||||
# value is ''. If the default is not set explicitly, it is None.
|
||||
if value not in (None, ''):
|
||||
kwargs[key] = value
|
||||
# NOTE(vdrok): this is to workaround the fact that these options are
|
||||
# named differently in keystoneauth, depending on whether they are
|
||||
# provided through CLI or loaded from conf options, here we unify them.
|
||||
for cli_ssl_opt, conf_ssl_opt in [
|
||||
('os_cacert', 'cafile'), ('os_cert', 'certfile'),
|
||||
('os_key', 'keyfile')]:
|
||||
value = getattr(args, cli_ssl_opt)
|
||||
if value not in (None, ''):
|
||||
kwargs[conf_ssl_opt] = value
|
||||
kwargs['os_ironic_api_version'] = os_ironic_api_version
|
||||
client = ironicclient.client.get_client(api_major_version, **kwargs)
|
||||
if options.ironic_api_version in ('1', 'latest'):
|
||||
|
|
|
@ -327,6 +327,11 @@ class VersionNegotiationMixinTest(utils.BaseTestCase):
|
|||
|
||||
class HttpClientTest(utils.BaseTestCase):
|
||||
|
||||
@mock.patch.object(http.LOG, 'warning', autospec=True)
|
||||
def test_http_client_deprecation(self, log_mock):
|
||||
http.HTTPClient('http://localhost')
|
||||
self.assertIn('deprecated', log_mock.call_args[0][0])
|
||||
|
||||
def test_url_generation_trailing_slash_in_base(self):
|
||||
client = http.HTTPClient('http://localhost/')
|
||||
url = client._make_connection_url('/v1/resources')
|
||||
|
@ -594,6 +599,13 @@ class HttpClientTest(utils.BaseTestCase):
|
|||
|
||||
class SessionClientTest(utils.BaseTestCase):
|
||||
|
||||
@mock.patch.object(http.LOG, 'warning', autospec=True)
|
||||
def test_session_client_endpoint_deprecation(self, log_mock):
|
||||
http.SessionClient(os_ironic_api_version=1, session=mock.Mock(),
|
||||
api_version_select_state='user', max_retries=5,
|
||||
retry_interval=5, endpoint='abc')
|
||||
self.assertIn('deprecated', log_mock.call_args[0][0])
|
||||
|
||||
def test_server_exception_empty_body(self):
|
||||
error_body = _get_error_body()
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class MakeClientTest(testtools.TestCase):
|
|||
allow_api_version_downgrade=False,
|
||||
session=instance.session,
|
||||
region_name=instance._region_name,
|
||||
endpoint='endpoint')
|
||||
endpoint_override='endpoint')
|
||||
instance.get_endpoint_for_service_type.assert_called_once_with(
|
||||
'baremetal', region_name=instance._region_name,
|
||||
interface=instance.interface)
|
||||
|
@ -54,7 +54,7 @@ class MakeClientTest(testtools.TestCase):
|
|||
allow_api_version_downgrade=True,
|
||||
session=instance.session,
|
||||
region_name=instance._region_name,
|
||||
endpoint='endpoint')
|
||||
endpoint_override='endpoint')
|
||||
instance.get_endpoint_for_service_type.assert_called_once_with(
|
||||
'baremetal', region_name=instance._region_name,
|
||||
interface=instance.interface)
|
||||
|
@ -72,7 +72,7 @@ class MakeClientTest(testtools.TestCase):
|
|||
allow_api_version_downgrade=True,
|
||||
session=instance.session,
|
||||
region_name=instance._region_name,
|
||||
endpoint='endpoint')
|
||||
endpoint_override='endpoint')
|
||||
instance.get_endpoint_for_service_type.assert_called_once_with(
|
||||
'baremetal', region_name=instance._region_name,
|
||||
interface=instance.interface)
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
|
||||
import mock
|
||||
|
||||
from keystoneauth1 import identity
|
||||
from keystoneauth1 import loading as kaloading
|
||||
from keystoneauth1 import token_endpoint
|
||||
|
||||
from ironicclient import client as iroclient
|
||||
from ironicclient.common import filecache
|
||||
|
@ -24,39 +26,42 @@ from ironicclient.v1 import client as v1
|
|||
|
||||
class ClientTest(utils.BaseTestCase):
|
||||
|
||||
def test_get_client_with_auth_token_ironic_url(self):
|
||||
kwargs = {
|
||||
'ironic_url': 'http://ironic.example.org:6385/',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
}
|
||||
client = iroclient.get_client('1', **kwargs)
|
||||
|
||||
self.assertEqual('USER_AUTH_TOKEN', client.http_client.auth_token)
|
||||
self.assertEqual('http://ironic.example.org:6385/',
|
||||
client.http_client.endpoint)
|
||||
|
||||
@mock.patch.object(iroclient.LOG, 'warning', autospec=True)
|
||||
@mock.patch.object(filecache, 'retrieve_data', autospec=True)
|
||||
@mock.patch.object(kaloading.session, 'Session', autospec=True)
|
||||
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
|
||||
def _test_get_client(self, mock_ks_loader, mock_ks_session,
|
||||
mock_retrieve_data, version=None,
|
||||
auth='password', **kwargs):
|
||||
mock_retrieve_data, warn_mock, version=None,
|
||||
auth='password', warn_mock_call_count=0, **kwargs):
|
||||
session = mock_ks_session.return_value.load_from_options.return_value
|
||||
session.get_endpoint.return_value = 'http://localhost:6385/v1/f14b4123'
|
||||
|
||||
class Opt(object):
|
||||
def __init__(self, name):
|
||||
self.dest = name
|
||||
|
||||
session_loader_options = [
|
||||
Opt('insecure'), Opt('cafile'), Opt('certfile'), Opt('keyfile'),
|
||||
Opt('timeout')]
|
||||
mock_ks_session.return_value.get_conf_options.return_value = (
|
||||
session_loader_options)
|
||||
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
|
||||
mock_retrieve_data.return_value = version
|
||||
|
||||
client = iroclient.get_client('1', **kwargs)
|
||||
self.assertEqual(warn_mock_call_count, warn_mock.call_count)
|
||||
iroclient.convert_keystoneauth_opts(kwargs)
|
||||
|
||||
mock_ks_loader.assert_called_once_with(auth)
|
||||
session_opts = {k: v for (k, v) in kwargs.items() if k in
|
||||
[o.dest for o in session_loader_options]}
|
||||
mock_ks_session.return_value.load_from_options.assert_called_once_with(
|
||||
auth='auth', timeout=kwargs.get('timeout'),
|
||||
insecure=kwargs.get('insecure'), cert=kwargs.get('cert'),
|
||||
cacert=kwargs.get('cacert'), key=kwargs.get('key'))
|
||||
session.get_endpoint.assert_called_once_with(
|
||||
service_type=kwargs.get('os_service_type') or 'baremetal',
|
||||
interface=kwargs.get('os_endpoint_type') or 'publicURL',
|
||||
region_name=kwargs.get('os_region_name'))
|
||||
auth='auth', **session_opts)
|
||||
if not {'endpoint', 'ironic_url'}.intersection(kwargs):
|
||||
session.get_endpoint.assert_called_once_with(
|
||||
service_type=kwargs.get('service_type') or 'baremetal',
|
||||
interface=kwargs.get('interface') or 'publicURL',
|
||||
region_name=kwargs.get('region_name'))
|
||||
if 'os_ironic_api_version' in kwargs:
|
||||
# NOTE(TheJulia): This does not test the negotiation logic
|
||||
# as a request must be triggered in order for any verison
|
||||
|
@ -71,6 +76,35 @@ class ClientTest(utils.BaseTestCase):
|
|||
port='6385')
|
||||
self.assertEqual(version or v1.DEFAULT_VER,
|
||||
client.http_client.os_ironic_api_version)
|
||||
return client
|
||||
|
||||
def test_get_client_only_ironic_url(self):
|
||||
kwargs = {'ironic_url': 'http://localhost:6385/v1'}
|
||||
client = self._test_get_client(auth='none',
|
||||
warn_mock_call_count=1, **kwargs)
|
||||
self.assertIsInstance(client.http_client, http.SessionClient)
|
||||
self.assertEqual('http://localhost:6385/v1',
|
||||
client.http_client.endpoint_override)
|
||||
|
||||
def test_get_client_only_endpoint(self):
|
||||
kwargs = {'endpoint': 'http://localhost:6385/v1'}
|
||||
client = self._test_get_client(auth='none', **kwargs)
|
||||
self.assertIsInstance(client.http_client, http.SessionClient)
|
||||
self.assertEqual('http://localhost:6385/v1',
|
||||
client.http_client.endpoint_override)
|
||||
|
||||
def test_get_client_with_auth_token_ironic_url(self):
|
||||
kwargs = {
|
||||
'ironic_url': 'http://localhost:6385/v1',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
}
|
||||
|
||||
client = self._test_get_client(auth='admin_token',
|
||||
warn_mock_call_count=2, **kwargs)
|
||||
|
||||
self.assertIsInstance(client.http_client, http.SessionClient)
|
||||
self.assertEqual('http://localhost:6385/v1',
|
||||
client.http_client.endpoint_override)
|
||||
|
||||
def test_get_client_no_auth_token(self):
|
||||
kwargs = {
|
||||
|
@ -80,7 +114,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': '',
|
||||
}
|
||||
self._test_get_client(**kwargs)
|
||||
self._test_get_client(warn_mock_call_count=4, **kwargs)
|
||||
|
||||
def test_get_client_service_and_endpoint_type_defaults(self):
|
||||
kwargs = {
|
||||
|
@ -92,7 +126,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
'os_service_type': '',
|
||||
'os_endpoint_type': ''
|
||||
}
|
||||
self._test_get_client(**kwargs)
|
||||
self._test_get_client(warn_mock_call_count=4, **kwargs)
|
||||
|
||||
def test_get_client_with_region_no_auth_token(self):
|
||||
kwargs = {
|
||||
|
@ -103,20 +137,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': '',
|
||||
}
|
||||
self._test_get_client(**kwargs)
|
||||
|
||||
def test_get_client_no_url(self):
|
||||
kwargs = {
|
||||
'os_project_name': 'PROJECT_NAME',
|
||||
'os_username': 'USERNAME',
|
||||
'os_password': 'PASSWORD',
|
||||
'os_auth_url': '',
|
||||
}
|
||||
self.assertRaises(exc.AmbiguousAuthSystem, iroclient.get_client,
|
||||
'1', **kwargs)
|
||||
# test the alias as well to ensure backwards compatibility
|
||||
self.assertRaises(exc.AmbigiousAuthSystem, iroclient.get_client,
|
||||
'1', **kwargs)
|
||||
self._test_get_client(warn_mock_call_count=5, **kwargs)
|
||||
|
||||
def test_get_client_incorrect_auth_params(self):
|
||||
kwargs = {
|
||||
|
@ -125,37 +146,35 @@ class ClientTest(utils.BaseTestCase):
|
|||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
}
|
||||
self.assertRaises(exc.AmbiguousAuthSystem, iroclient.get_client,
|
||||
'1', **kwargs)
|
||||
'1', warn_mock_call_count=3, **kwargs)
|
||||
|
||||
def test_get_client_with_api_version_latest(self):
|
||||
kwargs = {
|
||||
'os_project_name': 'PROJECT_NAME',
|
||||
'os_username': 'USERNAME',
|
||||
'os_password': 'PASSWORD',
|
||||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': '',
|
||||
'project_name': 'PROJECT_NAME',
|
||||
'username': 'USERNAME',
|
||||
'password': 'PASSWORD',
|
||||
'auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_ironic_api_version': "latest",
|
||||
}
|
||||
self._test_get_client(**kwargs)
|
||||
|
||||
def test_get_client_with_api_version_list(self):
|
||||
kwargs = {
|
||||
'os_project_name': 'PROJECT_NAME',
|
||||
'os_username': 'USERNAME',
|
||||
'os_password': 'PASSWORD',
|
||||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': '',
|
||||
'project_name': 'PROJECT_NAME',
|
||||
'username': 'USERNAME',
|
||||
'password': 'PASSWORD',
|
||||
'auth_url': 'http://localhost:35357/v2.0',
|
||||
'auth_token': '',
|
||||
'os_ironic_api_version': ['1.1', '1.99'],
|
||||
}
|
||||
self._test_get_client(**kwargs)
|
||||
|
||||
def test_get_client_with_api_version_numeric(self):
|
||||
kwargs = {
|
||||
'os_project_name': 'PROJECT_NAME',
|
||||
'os_username': 'USERNAME',
|
||||
'os_password': 'PASSWORD',
|
||||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': '',
|
||||
'project_name': 'PROJECT_NAME',
|
||||
'username': 'USERNAME',
|
||||
'password': 'PASSWORD',
|
||||
'auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_ironic_api_version': "1.4",
|
||||
}
|
||||
self._test_get_client(**kwargs)
|
||||
|
@ -165,26 +184,25 @@ class ClientTest(utils.BaseTestCase):
|
|||
# Make sure we don't coincidentally succeed
|
||||
self.assertNotEqual(v1.DEFAULT_VER, version)
|
||||
kwargs = {
|
||||
'os_project_name': 'PROJECT_NAME',
|
||||
'os_username': 'USERNAME',
|
||||
'os_password': 'PASSWORD',
|
||||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': '',
|
||||
'project_name': 'PROJECT_NAME',
|
||||
'username': 'USERNAME',
|
||||
'password': 'PASSWORD',
|
||||
'auth_url': 'http://localhost:35357/v2.0',
|
||||
}
|
||||
self._test_get_client(version=version, **kwargs)
|
||||
|
||||
def test_get_client_with_auth_token(self):
|
||||
kwargs = {
|
||||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
'auth_url': 'http://localhost:35357/v2.0',
|
||||
'token': 'USER_AUTH_TOKEN',
|
||||
}
|
||||
self._test_get_client(auth='token', **kwargs)
|
||||
|
||||
def test_get_client_with_region_name_auth_token(self):
|
||||
kwargs = {
|
||||
'os_auth_url': 'http://localhost:35357/v2.0',
|
||||
'os_region_name': 'REGIONONE',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
'auth_url': 'http://localhost:35357/v2.0',
|
||||
'region_name': 'REGIONONE',
|
||||
'token': 'USER_AUTH_TOKEN',
|
||||
}
|
||||
self._test_get_client(auth='token', **kwargs)
|
||||
|
||||
|
@ -209,46 +227,60 @@ class ClientTest(utils.BaseTestCase):
|
|||
'1', **kwargs)
|
||||
|
||||
@mock.patch.object(kaloading.session, 'Session', autospec=True)
|
||||
@mock.patch.object(kaloading, 'get_plugin_loader', autospec=True)
|
||||
def _test_loader_arguments_passed_correctly(
|
||||
self, mock_ks_loader, mock_ks_session,
|
||||
passed_kwargs, expected_kwargs):
|
||||
self, mock_ks_session, passed_kwargs, expected_kwargs,
|
||||
loader_class):
|
||||
session = mock_ks_session.return_value.load_from_options.return_value
|
||||
session.get_endpoint.return_value = 'http://localhost:6385/v1/f14b4123'
|
||||
mock_ks_loader.return_value.load_from_options.return_value = 'auth'
|
||||
|
||||
iroclient.get_client('1', **passed_kwargs)
|
||||
with mock.patch.object(loader_class, '__init__',
|
||||
autospec=True) as init_mock:
|
||||
init_mock.return_value = None
|
||||
iroclient.get_client('1', **passed_kwargs)
|
||||
iroclient.convert_keystoneauth_opts(passed_kwargs)
|
||||
|
||||
mock_ks_loader.return_value.load_from_options.assert_called_once_with(
|
||||
**expected_kwargs)
|
||||
init_mock.assert_called_once_with(mock.ANY, **expected_kwargs)
|
||||
session_opts = {k: v for (k, v) in passed_kwargs.items() if k in
|
||||
['insecure', 'cacert', 'cert', 'key', 'timeout']}
|
||||
mock_ks_session.return_value.load_from_options.assert_called_once_with(
|
||||
auth='auth', timeout=passed_kwargs.get('timeout'),
|
||||
insecure=passed_kwargs.get('insecure'),
|
||||
cert=passed_kwargs.get('cert'),
|
||||
cacert=passed_kwargs.get('cacert'), key=passed_kwargs.get('key'))
|
||||
session.get_endpoint.assert_called_once_with(
|
||||
service_type=passed_kwargs.get('os_service_type') or 'baremetal',
|
||||
interface=passed_kwargs.get('os_endpoint_type') or 'publicURL',
|
||||
region_name=passed_kwargs.get('os_region_name'))
|
||||
auth=mock.ANY, **session_opts)
|
||||
if 'ironic_url' not in passed_kwargs:
|
||||
service_type = passed_kwargs.get('service_type') or 'baremetal'
|
||||
interface = passed_kwargs.get('interface') or 'publicURL'
|
||||
session.get_endpoint.assert_called_once_with(
|
||||
service_type=service_type, interface=interface,
|
||||
region_name=passed_kwargs.get('region_name'))
|
||||
|
||||
def test_loader_arguments_admin_token(self):
|
||||
passed_kwargs = {
|
||||
'ironic_url': 'http://localhost:6385/v1',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
}
|
||||
expected_kwargs = {
|
||||
'endpoint': 'http://localhost:6385/v1',
|
||||
'token': 'USER_AUTH_TOKEN'
|
||||
}
|
||||
self._test_loader_arguments_passed_correctly(
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs,
|
||||
loader_class=token_endpoint.Token
|
||||
)
|
||||
|
||||
def test_loader_arguments_token(self):
|
||||
passed_kwargs = {
|
||||
'os_auth_url': 'http://localhost:35357/v3',
|
||||
'os_region_name': 'REGIONONE',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
'os_project_name': 'admin'
|
||||
}
|
||||
expected_kwargs = {
|
||||
'auth_url': 'http://localhost:35357/v3',
|
||||
'project_id': None,
|
||||
'project_name': None,
|
||||
'user_domain_id': None,
|
||||
'user_domain_name': None,
|
||||
'project_domain_id': None,
|
||||
'project_domain_name': None,
|
||||
'project_name': 'admin',
|
||||
'token': 'USER_AUTH_TOKEN'
|
||||
}
|
||||
self._test_loader_arguments_passed_correctly(
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs)
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs,
|
||||
loader_class=identity.Token
|
||||
)
|
||||
|
||||
def test_loader_arguments_password_tenant_name(self):
|
||||
passed_kwargs = {
|
||||
|
@ -262,17 +294,16 @@ class ClientTest(utils.BaseTestCase):
|
|||
}
|
||||
expected_kwargs = {
|
||||
'auth_url': 'http://localhost:35357/v3',
|
||||
'project_id': None,
|
||||
'project_name': 'PROJECT',
|
||||
'user_domain_id': 'DEFAULT',
|
||||
'user_domain_name': None,
|
||||
'project_domain_id': 'DEFAULT',
|
||||
'project_domain_name': None,
|
||||
'username': 'user',
|
||||
'password': '1234'
|
||||
}
|
||||
self._test_loader_arguments_passed_correctly(
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs)
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs,
|
||||
loader_class=identity.Password
|
||||
)
|
||||
|
||||
def test_loader_arguments_password_project_id(self):
|
||||
passed_kwargs = {
|
||||
|
@ -287,47 +318,35 @@ class ClientTest(utils.BaseTestCase):
|
|||
expected_kwargs = {
|
||||
'auth_url': 'http://localhost:35357/v3',
|
||||
'project_id': '1000',
|
||||
'project_name': None,
|
||||
'user_domain_id': None,
|
||||
'user_domain_name': 'domain1',
|
||||
'project_domain_id': None,
|
||||
'project_domain_name': 'domain1',
|
||||
'username': 'user',
|
||||
'password': '1234'
|
||||
}
|
||||
self._test_loader_arguments_passed_correctly(
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs)
|
||||
passed_kwargs=passed_kwargs, expected_kwargs=expected_kwargs,
|
||||
loader_class=identity.Password
|
||||
)
|
||||
|
||||
@mock.patch.object(iroclient, 'Client', autospec=True)
|
||||
@mock.patch.object(kaloading.session, 'Session', autospec=True)
|
||||
def test_correct_arguments_passed_to_client_constructor_noauth_mode(
|
||||
self, mock_ks_session, mock_client):
|
||||
session = mock_ks_session.return_value.load_from_options.return_value
|
||||
kwargs = {
|
||||
'ironic_url': 'http://ironic.example.org:6385/',
|
||||
'os_auth_token': 'USER_AUTH_TOKEN',
|
||||
'os_ironic_api_version': 'latest',
|
||||
'insecure': True,
|
||||
'max_retries': 10,
|
||||
'retry_interval': 10,
|
||||
'os_cacert': 'data'
|
||||
}
|
||||
iroclient.get_client('1', **kwargs)
|
||||
mock_client.assert_called_once_with(
|
||||
'1', 'http://ironic.example.org:6385/',
|
||||
**{
|
||||
'os_ironic_api_version': 'latest',
|
||||
'max_retries': 10,
|
||||
'retry_interval': 10,
|
||||
'token': 'USER_AUTH_TOKEN',
|
||||
'insecure': True,
|
||||
'ca_file': 'data',
|
||||
'cert_file': None,
|
||||
'key_file': None,
|
||||
'timeout': None,
|
||||
'session': None
|
||||
}
|
||||
'1', **{'os_ironic_api_version': 'latest',
|
||||
'max_retries': None,
|
||||
'retry_interval': None,
|
||||
'session': session,
|
||||
'endpoint_override': 'http://ironic.example.org:6385/'}
|
||||
)
|
||||
self.assertFalse(mock_ks_session.called)
|
||||
self.assertFalse(session.get_endpoint.called)
|
||||
|
||||
@mock.patch.object(iroclient, 'Client', autospec=True)
|
||||
@mock.patch.object(kaloading.session, 'Session', autospec=True)
|
||||
|
@ -345,13 +364,11 @@ class ClientTest(utils.BaseTestCase):
|
|||
}
|
||||
iroclient.get_client('1', **kwargs)
|
||||
mock_client.assert_called_once_with(
|
||||
'1', session.get_endpoint.return_value,
|
||||
**{
|
||||
'os_ironic_api_version': None,
|
||||
'max_retries': None,
|
||||
'retry_interval': None,
|
||||
'session': session,
|
||||
}
|
||||
'1', **{'os_ironic_api_version': None,
|
||||
'max_retries': None,
|
||||
'retry_interval': None,
|
||||
'session': session,
|
||||
'endpoint_override': session.get_endpoint.return_value}
|
||||
)
|
||||
|
||||
@mock.patch.object(iroclient, 'Client', autospec=True)
|
||||
|
@ -364,13 +381,11 @@ class ClientTest(utils.BaseTestCase):
|
|||
}
|
||||
iroclient.get_client('1', **kwargs)
|
||||
mock_client.assert_called_once_with(
|
||||
'1', session.get_endpoint.return_value,
|
||||
**{
|
||||
'os_ironic_api_version': None,
|
||||
'max_retries': None,
|
||||
'retry_interval': None,
|
||||
'session': session,
|
||||
}
|
||||
'1', **{'os_ironic_api_version': None,
|
||||
'max_retries': None,
|
||||
'retry_interval': None,
|
||||
'session': session,
|
||||
'endpoint_override': session.get_endpoint.return_value}
|
||||
)
|
||||
self.assertFalse(mock_ks_session.called)
|
||||
|
||||
|
|
|
@ -39,6 +39,13 @@ FAKE_ENV = {'OS_USERNAME': 'username',
|
|||
'OS_PROJECT_NAME': 'project_name',
|
||||
'OS_AUTH_URL': V2_URL}
|
||||
|
||||
FAKE_ENV_WITH_SSL = FAKE_ENV.copy()
|
||||
FAKE_ENV_WITH_SSL.update({
|
||||
'OS_CACERT': 'cacert',
|
||||
'OS_CERT': 'cert',
|
||||
'OS_KEY': 'key',
|
||||
})
|
||||
|
||||
FAKE_ENV_KEYSTONE_V2 = {
|
||||
'OS_USERNAME': 'username',
|
||||
'OS_PASSWORD': 'password',
|
||||
|
@ -162,16 +169,10 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, 'node-list')
|
||||
expected_kwargs = {
|
||||
'ironic_url': '', 'os_auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'os_tenant_id': '', 'os_tenant_name': '',
|
||||
'os_username': FAKE_ENV['OS_USERNAME'], 'os_user_domain_id': '',
|
||||
'os_user_domain_name': '', 'os_password': FAKE_ENV['OS_PASSWORD'],
|
||||
'os_auth_token': '', 'os_project_id': '',
|
||||
'os_project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'os_project_domain_id': '',
|
||||
'os_project_domain_name': '', 'os_region_name': '',
|
||||
'os_service_type': '', 'os_endpoint_type': '', 'os_cacert': None,
|
||||
'os_cert': None, 'os_key': None,
|
||||
'auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'username': FAKE_ENV['OS_USERNAME'],
|
||||
'password': FAKE_ENV['OS_PASSWORD'],
|
||||
'project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
|
@ -181,6 +182,32 @@ class ShellTest(utils.BaseTestCase):
|
|||
# Make sure we are actually prompted.
|
||||
mock_getpass.assert_called_with('OpenStack Password: ')
|
||||
|
||||
@mock.patch.object(client, 'get_client', autospec=True,
|
||||
side_effect=keystone_exc.ConnectFailure)
|
||||
@mock.patch('sys.stdin', side_effect=mock.MagicMock, autospec=True)
|
||||
@mock.patch('getpass.getpass', return_value='password', autospec=True)
|
||||
def test_password(self, mock_getpass, mock_stdin, mock_client):
|
||||
self.make_env(environ_dict=FAKE_ENV_WITH_SSL)
|
||||
# We will get a ConnectFailure because there is no keystone.
|
||||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, 'node-list')
|
||||
expected_kwargs = {
|
||||
'auth_url': FAKE_ENV_WITH_SSL['OS_AUTH_URL'],
|
||||
'username': FAKE_ENV_WITH_SSL['OS_USERNAME'],
|
||||
'password': FAKE_ENV_WITH_SSL['OS_PASSWORD'],
|
||||
'project_name': FAKE_ENV_WITH_SSL['OS_PROJECT_NAME'],
|
||||
'cafile': FAKE_ENV_WITH_SSL['OS_CACERT'],
|
||||
'certfile': FAKE_ENV_WITH_SSL['OS_CERT'],
|
||||
'keyfile': FAKE_ENV_WITH_SSL['OS_KEY'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'timeout': 600,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
'insecure': False
|
||||
}
|
||||
mock_client.assert_called_once_with(1, **expected_kwargs)
|
||||
self.assertFalse(mock_getpass.called)
|
||||
|
||||
@mock.patch.object(client, 'get_client', autospec=True,
|
||||
side_effect=keystone_exc.ConnectFailure)
|
||||
@mock.patch('getpass.getpass', return_value='password', autospec=True)
|
||||
|
@ -190,23 +217,49 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, 'node-list')
|
||||
expected_kwargs = {
|
||||
'ironic_url': '',
|
||||
'os_auth_url': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_URL'],
|
||||
'os_tenant_id': '',
|
||||
'os_tenant_name': '',
|
||||
'os_username': '', 'os_user_domain_id': '',
|
||||
'os_user_domain_name': '', 'os_password': '',
|
||||
'os_auth_token': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN'],
|
||||
'os_project_id': '',
|
||||
'os_project_name': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_PROJECT_NAME'],
|
||||
'os_project_domain_id': '', 'os_project_domain_name': '',
|
||||
'os_region_name': '', 'os_service_type': '',
|
||||
'os_endpoint_type': '', 'os_cacert': None, 'os_cert': None,
|
||||
'os_key': None, 'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'auth_url': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_URL'],
|
||||
'token': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN'],
|
||||
'project_name': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_PROJECT_NAME'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'timeout': 600,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
'insecure': False
|
||||
}
|
||||
mock_client.assert_called_once_with(1, **expected_kwargs)
|
||||
self.assertFalse(mock_getpass.called)
|
||||
|
||||
@mock.patch.object(client, 'get_client', autospec=True)
|
||||
@mock.patch('getpass.getpass', return_value='password', autospec=True)
|
||||
def test_admin_token_auth(self, mock_getpass, mock_client):
|
||||
self.make_env(environ_dict={
|
||||
'IRONIC_URL': 'http://192.168.1.1/v1',
|
||||
'OS_AUTH_TOKEN': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN']})
|
||||
expected_kwargs = {
|
||||
'endpoint': 'http://192.168.1.1/v1',
|
||||
'token': FAKE_ENV_KEYSTONE_V2_TOKEN['OS_AUTH_TOKEN'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'timeout': 600,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
'insecure': False
|
||||
}
|
||||
self.shell('node-list')
|
||||
mock_client.assert_called_once_with(1, **expected_kwargs)
|
||||
self.assertFalse(mock_getpass.called)
|
||||
|
||||
@mock.patch.object(client, 'get_client', autospec=True)
|
||||
@mock.patch('getpass.getpass', return_value='password', autospec=True)
|
||||
def test_none_auth(self, mock_getpass, mock_client):
|
||||
self.make_env(environ_dict={'IRONIC_URL': 'http://192.168.1.1/v1'})
|
||||
expected_kwargs = {
|
||||
'endpoint': 'http://192.168.1.1/v1',
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
'timeout': 600, 'insecure': False
|
||||
}
|
||||
self.shell('node-list')
|
||||
mock_client.assert_called_once_with(1, **expected_kwargs)
|
||||
self.assertFalse(mock_getpass.called)
|
||||
|
||||
|
@ -274,16 +327,10 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, 'node-list')
|
||||
expected_kwargs = {
|
||||
'ironic_url': '', 'os_auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'os_tenant_id': '', 'os_tenant_name': '',
|
||||
'os_username': FAKE_ENV['OS_USERNAME'], 'os_user_domain_id': '',
|
||||
'os_user_domain_name': '', 'os_password': FAKE_ENV['OS_PASSWORD'],
|
||||
'os_auth_token': '', 'os_project_id': '',
|
||||
'os_project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'os_project_domain_id': '',
|
||||
'os_project_domain_name': '', 'os_region_name': '',
|
||||
'os_service_type': '', 'os_endpoint_type': '', 'os_cacert': None,
|
||||
'os_cert': None, 'os_key': None,
|
||||
'auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'username': FAKE_ENV['OS_USERNAME'],
|
||||
'password': FAKE_ENV['OS_PASSWORD'],
|
||||
'project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'os_ironic_api_version': '1.10',
|
||||
|
@ -300,16 +347,10 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, 'node-list')
|
||||
expected_kwargs = {
|
||||
'ironic_url': '', 'os_auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'os_tenant_id': '', 'os_tenant_name': '',
|
||||
'os_username': FAKE_ENV['OS_USERNAME'], 'os_user_domain_id': '',
|
||||
'os_user_domain_name': '', 'os_password': FAKE_ENV['OS_PASSWORD'],
|
||||
'os_auth_token': '', 'os_project_id': '',
|
||||
'os_project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'os_project_domain_id': '',
|
||||
'os_project_domain_name': '', 'os_region_name': '',
|
||||
'os_service_type': '', 'os_endpoint_type': '', 'os_cacert': None,
|
||||
'os_cert': None, 'os_key': None,
|
||||
'auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'username': FAKE_ENV['OS_USERNAME'],
|
||||
'password': FAKE_ENV['OS_PASSWORD'],
|
||||
'project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
|
@ -326,16 +367,10 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, '--ironic-api-version 1.11 node-list')
|
||||
expected_kwargs = {
|
||||
'ironic_url': '', 'os_auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'os_tenant_id': '', 'os_tenant_name': '',
|
||||
'os_username': FAKE_ENV['OS_USERNAME'], 'os_user_domain_id': '',
|
||||
'os_user_domain_name': '', 'os_password': FAKE_ENV['OS_PASSWORD'],
|
||||
'os_auth_token': '', 'os_project_id': '',
|
||||
'os_project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'os_project_domain_id': '',
|
||||
'os_project_domain_name': '', 'os_region_name': '',
|
||||
'os_service_type': '', 'os_endpoint_type': '', 'os_cacert': None,
|
||||
'os_cert': None, 'os_key': None,
|
||||
'auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'username': FAKE_ENV['OS_USERNAME'],
|
||||
'password': FAKE_ENV['OS_PASSWORD'],
|
||||
'project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'os_ironic_api_version': '1.11',
|
||||
|
@ -352,16 +387,10 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.assertRaises(keystone_exc.ConnectFailure,
|
||||
self.shell, '--ironic-api-version 1 node-list')
|
||||
expected_kwargs = {
|
||||
'ironic_url': '', 'os_auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'os_tenant_id': '', 'os_tenant_name': '',
|
||||
'os_username': FAKE_ENV['OS_USERNAME'], 'os_user_domain_id': '',
|
||||
'os_user_domain_name': '', 'os_password': FAKE_ENV['OS_PASSWORD'],
|
||||
'os_auth_token': '', 'os_project_id': '',
|
||||
'os_project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'os_project_domain_id': '',
|
||||
'os_project_domain_name': '', 'os_region_name': '',
|
||||
'os_service_type': '', 'os_endpoint_type': '', 'os_cacert': None,
|
||||
'os_cert': None, 'os_key': None,
|
||||
'auth_url': FAKE_ENV['OS_AUTH_URL'],
|
||||
'username': FAKE_ENV['OS_USERNAME'],
|
||||
'password': FAKE_ENV['OS_PASSWORD'],
|
||||
'project_name': FAKE_ENV['OS_PROJECT_NAME'],
|
||||
'max_retries': http.DEFAULT_MAX_RETRIES,
|
||||
'retry_interval': http.DEFAULT_RETRY_INTERVAL,
|
||||
'os_ironic_api_version': ironic_shell.LATEST_VERSION,
|
||||
|
|
|
@ -31,7 +31,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
os_ironic_api_version=os_ironic_api_version)
|
||||
|
||||
http_client_mock.assert_called_once_with(
|
||||
endpoint, token=token,
|
||||
endpoint_override=endpoint, token=token,
|
||||
os_ironic_api_version=os_ironic_api_version,
|
||||
api_version_select_state='user')
|
||||
|
||||
|
@ -45,7 +45,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
allow_api_version_downgrade=True)
|
||||
|
||||
http_client_mock.assert_called_once_with(
|
||||
endpoint, token=token,
|
||||
token=token, endpoint_override=endpoint,
|
||||
os_ironic_api_version=os_ironic_api_version,
|
||||
api_version_select_state='default')
|
||||
|
||||
|
@ -70,7 +70,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
|
||||
cache_mock.assert_called_once_with(host='ironic', port='6385')
|
||||
http_client_mock.assert_called_once_with(
|
||||
endpoint, token=token,
|
||||
endpoint_override=endpoint, token=token,
|
||||
os_ironic_api_version=os_ironic_api_version,
|
||||
api_version_select_state='cached')
|
||||
|
||||
|
@ -84,7 +84,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
|
||||
cache_mock.assert_called_once_with(host='ironic', port='6385')
|
||||
http_client_mock.assert_called_once_with(
|
||||
endpoint, token=token,
|
||||
endpoint_override=endpoint, token=token,
|
||||
os_ironic_api_version=client.DEFAULT_VER,
|
||||
api_version_select_state='default')
|
||||
|
||||
|
@ -92,8 +92,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
self.assertRaises(exc.EndpointException,
|
||||
client.Client,
|
||||
session='fake_session',
|
||||
insecure=True,
|
||||
endpoint_override='http://ironic:6385')
|
||||
insecure=True)
|
||||
|
||||
def test_client_initialized_managers(self, http_client_mock):
|
||||
cl = client.Client('http://ironic:6385', token='safe_token',
|
||||
|
@ -113,7 +112,7 @@ class ClientTest(utils.BaseTestCase):
|
|||
|
||||
cl.negotiate_api_version()
|
||||
http_client_mock.assert_called_once_with(
|
||||
endpoint, api_version_select_state='user',
|
||||
api_version_select_state='user', endpoint_override=endpoint,
|
||||
os_ironic_api_version='latest', token=token)
|
||||
# TODO(TheJulia): We should verify that negotiate_version
|
||||
# is being called in the client and returns a version,
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from ironicclient.common import filecache
|
||||
from ironicclient.common import http
|
||||
from ironicclient.common.http import DEFAULT_VER
|
||||
|
@ -26,20 +28,29 @@ from ironicclient.v1 import portgroup
|
|||
from ironicclient.v1 import volume_connector
|
||||
from ironicclient.v1 import volume_target
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Client(object):
|
||||
"""Client for the Ironic v1 API.
|
||||
|
||||
:param string endpoint: A user-supplied endpoint URL for the ironic
|
||||
service.
|
||||
service. DEPRECATED, use endpoint_override instead.
|
||||
:param string endpoint_override: A user-supplied endpoint URL for the
|
||||
ironic service.
|
||||
:param function token: Provides token for authentication.
|
||||
:param integer timeout: Allows customization of the timeout for client
|
||||
http requests. (optional)
|
||||
"""
|
||||
|
||||
def __init__(self, endpoint=None, *args, **kwargs):
|
||||
def __init__(self, endpoint=None, endpoint_override=None, *args, **kwargs):
|
||||
"""Initialize a new client for the Ironic v1 API."""
|
||||
allow_downgrade = kwargs.pop('allow_api_version_downgrade', False)
|
||||
if endpoint_override is None and endpoint is not None:
|
||||
LOG.warning('Passing "endpoint" parameter to Client constructor '
|
||||
'is deprecated, and it will be removed in Stein '
|
||||
'release. Please use "endpoint_override" instead.')
|
||||
endpoint_override = endpoint
|
||||
if kwargs.get('os_ironic_api_version'):
|
||||
# TODO(TheJulia): We should sanity check os_ironic_api_version
|
||||
# against our maximum suported version, so the client fails
|
||||
|
@ -58,14 +69,14 @@ class Client(object):
|
|||
else:
|
||||
kwargs['api_version_select_state'] = "user"
|
||||
else:
|
||||
if not endpoint:
|
||||
if not endpoint_override:
|
||||
raise exc.EndpointException(
|
||||
_("Must provide 'endpoint' if os_ironic_api_version "
|
||||
"isn't specified"))
|
||||
_("Must provide 'endpoint_override' if "
|
||||
"'os_ironic_api_version' isn't specified"))
|
||||
|
||||
# If the user didn't specify a version, use a cached version if
|
||||
# one has been stored
|
||||
host, netport = http.get_server(endpoint)
|
||||
host, netport = http.get_server(endpoint_override)
|
||||
saved_version = filecache.retrieve_data(host=host, port=netport)
|
||||
if saved_version:
|
||||
kwargs['api_version_select_state'] = "cached"
|
||||
|
@ -74,8 +85,8 @@ class Client(object):
|
|||
kwargs['api_version_select_state'] = "default"
|
||||
kwargs['os_ironic_api_version'] = DEFAULT_VER
|
||||
|
||||
self.http_client = http._construct_http_client(
|
||||
endpoint, *args, **kwargs)
|
||||
kwargs['endpoint_override'] = endpoint_override
|
||||
self.http_client = http._construct_http_client(*args, **kwargs)
|
||||
|
||||
self.chassis = chassis.ChassisManager(self.http_client)
|
||||
self.node = node.NodeManager(self.http_client)
|
||||
|
|
|
@ -46,7 +46,7 @@ openstacksdk==0.11.2
|
|||
os-client-config==1.28.0
|
||||
os-service-types==1.2.0
|
||||
os-testr==1.0.0
|
||||
osc-lib==1.8.0
|
||||
osc-lib==1.10.0
|
||||
oslo.concurrency==3.25.0
|
||||
oslo.config==5.2.0
|
||||
oslo.context==2.19.2
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
The client now supports ``none`` authorization method, which should be
|
||||
used if the Identity service is not present in the deployment that the
|
||||
client talks to. To use it:
|
||||
|
||||
- openstack baremetal CLI -- supported starting with ``osc-lib`` version
|
||||
``1.10.0``, by providing ``--os-auth-type none`` and ``--os-endpoint``
|
||||
argument to ``openstack`` command
|
||||
|
||||
- ironic CLI -- just specify the ``--ironic-url`` or ``--os-endpoint``
|
||||
argument in the ``ironic`` command (or set the corresponding environment
|
||||
variable)
|
||||
|
||||
- python API -- specify the ``endpoint_override`` argument to the
|
||||
``client.get_client()`` method (in addition to the required
|
||||
``api_version``)
|
||||
deprecations:
|
||||
- |
|
||||
``common.http.HTTPClient`` class is deprecated and will be removed in
|
||||
the Stein release. If you initialize the ironic client via
|
||||
``v1.client.Client`` class directly, please pass the `keystoneauth
|
||||
<https://docs.openstack.org/keystoneauth/latest/>`_ session to the Client
|
||||
constructor, so that ``common.http.SessionClient`` is used instead.
|
||||
- |
|
||||
As part of standardizing argument naming to the one used by `keystoneauth
|
||||
<https://docs.openstack.org/keystoneauth/latest/>`_, the following
|
||||
arguments to ``client.get_client`` method are deprecated and will be
|
||||
removed in Stein release:
|
||||
|
||||
* ``os_auth_token``: use ``token`` instead
|
||||
|
||||
* ``os_username``: use ``username`` instead
|
||||
|
||||
* ``os_password``: use ``password`` instead
|
||||
|
||||
* ``os_auth_url``: use ``auth_url`` instead
|
||||
|
||||
* ``os_project_id``: use ``project_id`` instead
|
||||
|
||||
* ``os_project_name``: use ``project_name`` instead
|
||||
|
||||
* ``os_tenant_id``: use ``tenant_id`` instead
|
||||
|
||||
* ``os_tenant_name``: use ``tenant_name`` instead
|
||||
|
||||
* ``os_region_name``: use ``region_name`` instead
|
||||
|
||||
* ``os_user_domain_id``: use ``user_domain_id`` instead
|
||||
|
||||
* ``os_user_domain_name``: use ``user_domain_name`` instead
|
||||
|
||||
* ``os_project_domain_id``: use ``project_domain_id`` instead
|
||||
|
||||
* ``os_project_domain_name``: use ``project_domain_name`` instead
|
||||
|
||||
* ``os_service_type``: use ``service_type`` instead
|
||||
|
||||
* ``os_endpoint_type``: use ``interface`` instead
|
||||
|
||||
* ``ironic_url``: use ``endpoint`` instead
|
||||
|
||||
* ``os_cacert``, ``ca_file``: use ``cafile`` instead
|
||||
|
||||
* ``os_cert``, ``cert_file``: use ``certfile`` instead
|
||||
|
||||
* ``os_key``, ``key_file``: use ``keyfile`` instead
|
||||
- |
|
||||
The ``endpoint`` argument to the ``v1.client.Client`` constructor is
|
||||
deprecated and will be removed in Stein release. Instead, please use the
|
||||
standard `keystoneauth <https://docs.openstack.org/keystoneauth/latest/>`_
|
||||
argument name ``endpoint_override``.
|
|
@ -6,7 +6,7 @@ appdirs>=1.3.0 # MIT License
|
|||
dogpile.cache>=0.6.2 # BSD
|
||||
jsonschema<3.0.0,>=2.6.0 # MIT
|
||||
keystoneauth1>=3.4.0 # Apache-2.0
|
||||
osc-lib>=1.8.0 # Apache-2.0
|
||||
osc-lib>=1.10.0 # Apache-2.0
|
||||
oslo.i18n>=3.15.3 # Apache-2.0
|
||||
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
||||
oslo.utils>=3.33.0 # Apache-2.0
|
||||
|
|
Loading…
Reference in New Issue