Fix and enable Gating on H404
Enable gating on the Hacking H404 check - docstring should start with a summary. Change-Id: I80612a15bd11f689e9e9f4dc2ff812138630ddbd
This commit is contained in:

committed by
Morgan Fainberg

parent
0e11cf03cf
commit
dc5c33a9e5
@@ -34,9 +34,8 @@ except NameError:
|
|||||||
|
|
||||||
|
|
||||||
def getid(obj):
|
def getid(obj):
|
||||||
"""
|
"""Abstracts the common pattern of allowing both an object or an object's
|
||||||
Abstracts the common pattern of allowing both an object or an object's ID
|
ID (UUID) as a parameter when dealing with relationships.
|
||||||
(UUID) as a parameter when dealing with relationships.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Try to return the object's UUID first, if we have a UUID.
|
# Try to return the object's UUID first, if we have a UUID.
|
||||||
@@ -75,9 +74,8 @@ def filter_kwargs(f):
|
|||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
class Manager(object):
|
||||||
"""
|
"""Managers interact with a particular type of API (servers, flavors,
|
||||||
Managers interact with a particular type of API (servers, flavors, images,
|
images, etc.) and provide CRUD operations for them.
|
||||||
etc.) and provide CRUD operations for them.
|
|
||||||
"""
|
"""
|
||||||
resource_class = None
|
resource_class = None
|
||||||
|
|
||||||
@@ -138,8 +136,7 @@ class Manager(object):
|
|||||||
|
|
||||||
|
|
||||||
class ManagerWithFind(Manager):
|
class ManagerWithFind(Manager):
|
||||||
"""
|
"""Like a `Manager`, but with additional `find()`/`findall()` methods.
|
||||||
Like a `Manager`, but with additional `find()`/`findall()` methods.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__metaclass__ = abc.ABCMeta
|
__metaclass__ = abc.ABCMeta
|
||||||
@@ -149,8 +146,7 @@ class ManagerWithFind(Manager):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def find(self, **kwargs):
|
def find(self, **kwargs):
|
||||||
"""
|
"""Find a single item with attributes matching ``**kwargs``.
|
||||||
Find a single item with attributes matching ``**kwargs``.
|
|
||||||
|
|
||||||
This isn't very efficient: it loads the entire list then filters on
|
This isn't very efficient: it loads the entire list then filters on
|
||||||
the Python side.
|
the Python side.
|
||||||
@@ -167,8 +163,7 @@ class ManagerWithFind(Manager):
|
|||||||
return rl[0]
|
return rl[0]
|
||||||
|
|
||||||
def findall(self, **kwargs):
|
def findall(self, **kwargs):
|
||||||
"""
|
"""Find all items with attributes matching ``**kwargs``.
|
||||||
Find all items with attributes matching ``**kwargs``.
|
|
||||||
|
|
||||||
This isn't very efficient: it loads the entire list then filters on
|
This isn't very efficient: it loads the entire list then filters on
|
||||||
the Python side.
|
the Python side.
|
||||||
@@ -287,9 +282,7 @@ class CrudManager(Manager):
|
|||||||
|
|
||||||
@filter_kwargs
|
@filter_kwargs
|
||||||
def find(self, **kwargs):
|
def find(self, **kwargs):
|
||||||
"""
|
"""Find a single item with attributes matching ``**kwargs``."""
|
||||||
Find a single item with attributes matching ``**kwargs``.
|
|
||||||
"""
|
|
||||||
url = self.build_url(dict_args_in_out=kwargs)
|
url = self.build_url(dict_args_in_out=kwargs)
|
||||||
|
|
||||||
rl = self._list(
|
rl = self._list(
|
||||||
@@ -310,8 +303,7 @@ class CrudManager(Manager):
|
|||||||
|
|
||||||
|
|
||||||
class Resource(object):
|
class Resource(object):
|
||||||
"""
|
"""A resource represents a particular instance of an object (tenant, user,
|
||||||
A resource represents a particular instance of an object (tenant, user,
|
|
||||||
etc). This is pretty much just a bag for attributes.
|
etc). This is pretty much just a bag for attributes.
|
||||||
|
|
||||||
:param manager: Manager object
|
:param manager: Manager object
|
||||||
|
@@ -28,10 +28,9 @@ import six
|
|||||||
|
|
||||||
|
|
||||||
class Ec2Signer(object):
|
class Ec2Signer(object):
|
||||||
"""
|
"""Utility class which adds allows a request to be signed with an AWS style
|
||||||
Utility class which adds allows a request to be signed with an AWS style
|
|
||||||
signature, which can then be used for authentication via the keystone ec2
|
signature, which can then be used for authentication via the keystone ec2
|
||||||
authentication extension
|
authentication extension.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, secret_key):
|
def __init__(self, secret_key):
|
||||||
@@ -41,9 +40,9 @@ class Ec2Signer(object):
|
|||||||
self.hmac_256 = hmac.new(self.secret_key, digestmod=hashlib.sha256)
|
self.hmac_256 = hmac.new(self.secret_key, digestmod=hashlib.sha256)
|
||||||
|
|
||||||
def _v4_creds(self, credentials):
|
def _v4_creds(self, credentials):
|
||||||
"""
|
"""Detect if the credentials are for a v4 signed request, since AWS
|
||||||
Detect if the credentials are for a v4 signed request, since AWS
|
|
||||||
removed the SignatureVersion field from the v4 request spec...
|
removed the SignatureVersion field from the v4 request spec...
|
||||||
|
|
||||||
This expects a dict of the request headers to be passed in the
|
This expects a dict of the request headers to be passed in the
|
||||||
credentials dict, since the recommended way to pass v4 creds is
|
credentials dict, since the recommended way to pass v4 creds is
|
||||||
via the 'Authorization' header
|
via the 'Authorization' header
|
||||||
@@ -127,9 +126,8 @@ class Ec2Signer(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _canonical_qs(params):
|
def _canonical_qs(params):
|
||||||
"""
|
"""Construct a sorted, correctly encoded query string as required for
|
||||||
Construct a sorted, correctly encoded query string as required for
|
_calc_signature_2 and _calc_signature_4.
|
||||||
_calc_signature_2 and _calc_signature_4
|
|
||||||
"""
|
"""
|
||||||
keys = params.keys()
|
keys = params.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
@@ -164,8 +162,7 @@ class Ec2Signer(object):
|
|||||||
hashlib.sha256).digest()
|
hashlib.sha256).digest()
|
||||||
|
|
||||||
def signature_key(datestamp, region_name, service_name):
|
def signature_key(datestamp, region_name, service_name):
|
||||||
"""
|
"""Signature key derivation, see
|
||||||
Signature key derivation, see
|
|
||||||
http://docs.aws.amazon.com/general/latest/gr/
|
http://docs.aws.amazon.com/general/latest/gr/
|
||||||
signature-v4-examples.html#signature-v4-examples-python
|
signature-v4-examples.html#signature-v4-examples-python
|
||||||
"""
|
"""
|
||||||
@@ -177,8 +174,9 @@ class Ec2Signer(object):
|
|||||||
return k_signing
|
return k_signing
|
||||||
|
|
||||||
def auth_param(param_name):
|
def auth_param(param_name):
|
||||||
"""
|
"""Get specified auth parameter.
|
||||||
Get specified auth parameter, provided via one of:
|
|
||||||
|
Provided via one of:
|
||||||
- the Authorization header
|
- the Authorization header
|
||||||
- the X-Amz-* query parameters
|
- the X-Amz-* query parameters
|
||||||
"""
|
"""
|
||||||
@@ -191,8 +189,8 @@ class Ec2Signer(object):
|
|||||||
return param_str
|
return param_str
|
||||||
|
|
||||||
def date_param():
|
def date_param():
|
||||||
"""
|
"""Get the X-Amz-Date' value, which can be either a header
|
||||||
Get the X-Amz-Date' value, which can be either a header or paramter
|
or parameter.
|
||||||
|
|
||||||
Note AWS supports parsing the Date header also, but this is not
|
Note AWS supports parsing the Date header also, but this is not
|
||||||
currently supported here as it will require some format mangling
|
currently supported here as it will require some format mangling
|
||||||
|
@@ -42,9 +42,8 @@ class NoUniqueMatch(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class ClientException(Exception):
|
class ClientException(Exception):
|
||||||
"""
|
"""The base exception class for all exceptions this library raises."""
|
||||||
The base exception class for all exceptions this library raises.
|
|
||||||
"""
|
|
||||||
def __init__(self, code, message=None, details=None):
|
def __init__(self, code, message=None, details=None):
|
||||||
self.code = code
|
self.code = code
|
||||||
self.message = message or self.__class__.message
|
self.message = message or self.__class__.message
|
||||||
@@ -55,24 +54,21 @@ class ClientException(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class BadRequest(ClientException):
|
class BadRequest(ClientException):
|
||||||
"""
|
"""HTTP 400 - Bad request: you sent some malformed data."""
|
||||||
HTTP 400 - Bad request: you sent some malformed data.
|
|
||||||
"""
|
|
||||||
http_status = 400
|
http_status = 400
|
||||||
message = "Bad request"
|
message = "Bad request"
|
||||||
|
|
||||||
|
|
||||||
class Unauthorized(ClientException):
|
class Unauthorized(ClientException):
|
||||||
"""
|
"""HTTP 401 - Unauthorized: bad credentials."""
|
||||||
HTTP 401 - Unauthorized: bad credentials.
|
|
||||||
"""
|
|
||||||
http_status = 401
|
http_status = 401
|
||||||
message = "Unauthorized"
|
message = "Unauthorized"
|
||||||
|
|
||||||
|
|
||||||
class Forbidden(ClientException):
|
class Forbidden(ClientException):
|
||||||
"""
|
"""HTTP 403 - Forbidden: your credentials do not allow access to this
|
||||||
HTTP 403 - Forbidden: your credentials don't give you access to this
|
|
||||||
resource.
|
resource.
|
||||||
"""
|
"""
|
||||||
http_status = 403
|
http_status = 403
|
||||||
@@ -80,32 +76,26 @@ class Forbidden(ClientException):
|
|||||||
|
|
||||||
|
|
||||||
class NotFound(ClientException):
|
class NotFound(ClientException):
|
||||||
"""
|
"""HTTP 404 - Not found."""
|
||||||
HTTP 404 - Not found
|
|
||||||
"""
|
|
||||||
http_status = 404
|
http_status = 404
|
||||||
message = "Not found"
|
message = "Not found"
|
||||||
|
|
||||||
|
|
||||||
class MethodNotAllowed(ClientException):
|
class MethodNotAllowed(ClientException):
|
||||||
"""
|
"""HTTP 405 - Method not allowed."""
|
||||||
HTTP 405 - Method not allowed
|
|
||||||
"""
|
|
||||||
http_status = 405
|
http_status = 405
|
||||||
message = "Method not allowed"
|
message = "Method not allowed"
|
||||||
|
|
||||||
|
|
||||||
class Conflict(ClientException):
|
class Conflict(ClientException):
|
||||||
"""
|
"""HTTP 409 - Conflict."""
|
||||||
HTTP 409 - Conflict
|
|
||||||
"""
|
|
||||||
http_status = 409
|
http_status = 409
|
||||||
message = "Conflict"
|
message = "Conflict"
|
||||||
|
|
||||||
|
|
||||||
class OverLimit(ClientException):
|
class OverLimit(ClientException):
|
||||||
"""
|
"""HTTP 413 - Over limit: you're over the API limits for this time
|
||||||
HTTP 413 - Over limit: you're over the API limits for this time period.
|
period.
|
||||||
"""
|
"""
|
||||||
http_status = 413
|
http_status = 413
|
||||||
message = "Over limit"
|
message = "Over limit"
|
||||||
@@ -113,17 +103,15 @@ class OverLimit(ClientException):
|
|||||||
|
|
||||||
# NotImplemented is a python keyword.
|
# NotImplemented is a python keyword.
|
||||||
class HTTPNotImplemented(ClientException):
|
class HTTPNotImplemented(ClientException):
|
||||||
"""
|
"""HTTP 501 - Not Implemented: the server does not support this
|
||||||
HTTP 501 - Not Implemented: the server does not support this operation.
|
operation.
|
||||||
"""
|
"""
|
||||||
http_status = 501
|
http_status = 501
|
||||||
message = "Not Implemented"
|
message = "Not Implemented"
|
||||||
|
|
||||||
|
|
||||||
class ServiceUnavailable(ClientException):
|
class ServiceUnavailable(ClientException):
|
||||||
"""
|
"""HTTP 503 - Service Unavailable: The server is currently unavailable."""
|
||||||
HTTP 503 - Service Unavailable: The server is currently unavailable.
|
|
||||||
"""
|
|
||||||
http_status = 503
|
http_status = 503
|
||||||
message = "Service Unavailable"
|
message = "Service Unavailable"
|
||||||
|
|
||||||
@@ -146,9 +134,8 @@ _code_map = dict((c.http_status, c) for c in [BadRequest,
|
|||||||
|
|
||||||
|
|
||||||
def from_response(response, body=None):
|
def from_response(response, body=None):
|
||||||
"""
|
"""Return an instance of a ClientException or subclass
|
||||||
Return an instance of an ClientException or subclass
|
based on a requests response.
|
||||||
based on an requests response.
|
|
||||||
|
|
||||||
Usage::
|
Usage::
|
||||||
|
|
||||||
|
@@ -442,8 +442,8 @@ class OpenStackIdentityShell(object):
|
|||||||
return shell_v2_0.CLIENT_CLASS
|
return shell_v2_0.CLIENT_CLASS
|
||||||
|
|
||||||
def do_bash_completion(self, args):
|
def do_bash_completion(self, args):
|
||||||
"""
|
"""Prints all of the commands and options to stdout.
|
||||||
Prints all of the commands and options to stdout.
|
|
||||||
The keystone.bash_completion script doesn't have to hard code them.
|
The keystone.bash_completion script doesn't have to hard code them.
|
||||||
"""
|
"""
|
||||||
commands = set()
|
commands = set()
|
||||||
@@ -460,9 +460,7 @@ class OpenStackIdentityShell(object):
|
|||||||
@utils.arg('command', metavar='<subcommand>', nargs='?',
|
@utils.arg('command', metavar='<subcommand>', nargs='?',
|
||||||
help='Display help for <subcommand>')
|
help='Display help for <subcommand>')
|
||||||
def do_help(self, args):
|
def do_help(self, args):
|
||||||
"""
|
"""Display help about this program or one of its subcommands."""
|
||||||
Display help about this program or one of its subcommands.
|
|
||||||
"""
|
|
||||||
if getattr(args, 'command', None):
|
if getattr(args, 'command', None):
|
||||||
if args.command in self.subcommands:
|
if args.command in self.subcommands:
|
||||||
self.subcommands[args.command].print_help()
|
self.subcommands[args.command].print_help()
|
||||||
|
@@ -113,10 +113,10 @@ def unauthenticated(f):
|
|||||||
|
|
||||||
|
|
||||||
def isunauthenticated(f):
|
def isunauthenticated(f):
|
||||||
"""
|
"""Checks to see if the function is marked as not requiring authentication
|
||||||
Checks to see if the function is marked as not requiring authentication
|
with the @unauthenticated decorator.
|
||||||
with the @unauthenticated decorator. Returns True if decorator is
|
|
||||||
set to True, False otherwise.
|
Returns True if decorator is set to True, False otherwise.
|
||||||
"""
|
"""
|
||||||
return getattr(f, 'unauthenticated', False)
|
return getattr(f, 'unauthenticated', False)
|
||||||
|
|
||||||
@@ -135,9 +135,8 @@ def hash_signed_token(signed_text):
|
|||||||
|
|
||||||
|
|
||||||
def prompt_for_password():
|
def prompt_for_password():
|
||||||
"""
|
"""Prompt user for password if not provided so the password
|
||||||
Prompt user for password if not provided so the password
|
doesn't show up in the bash history.
|
||||||
doesn't show up in the bash history.
|
|
||||||
"""
|
"""
|
||||||
if not (hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()):
|
if not (hasattr(sys.stdin, 'isatty') and sys.stdin.isatty()):
|
||||||
# nothing to do
|
# nothing to do
|
||||||
|
@@ -28,8 +28,8 @@ class CredentialsManager(base.ManagerWithFind):
|
|||||||
resource_class = EC2
|
resource_class = EC2
|
||||||
|
|
||||||
def create(self, user_id, tenant_id):
|
def create(self, user_id, tenant_id):
|
||||||
"""
|
"""Create a new access/secret pair for the user/tenant pair.
|
||||||
Create a new access/secret pair for the user/tenant pair
|
|
||||||
:rtype: object of type :class:`EC2`
|
:rtype: object of type :class:`EC2`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -39,24 +39,22 @@ class CredentialsManager(base.ManagerWithFind):
|
|||||||
params, "credential")
|
params, "credential")
|
||||||
|
|
||||||
def list(self, user_id):
|
def list(self, user_id):
|
||||||
"""
|
"""Get a list of access/secret pairs for a user_id.
|
||||||
Get a list of access/secret pairs for a user_id
|
|
||||||
:rtype: list of :class:`EC2`
|
:rtype: list of :class:`EC2`
|
||||||
"""
|
"""
|
||||||
return self._list("/users/%s/credentials/OS-EC2" % user_id,
|
return self._list("/users/%s/credentials/OS-EC2" % user_id,
|
||||||
"credentials")
|
"credentials")
|
||||||
|
|
||||||
def get(self, user_id, access):
|
def get(self, user_id, access):
|
||||||
"""
|
"""Get the access/secret pair for a given access key.
|
||||||
Get the access/secret pair for a given access key
|
|
||||||
:rtype: object of type :class:`EC2`
|
:rtype: object of type :class:`EC2`
|
||||||
"""
|
"""
|
||||||
return self._get("/users/%s/credentials/OS-EC2/%s" %
|
return self._get("/users/%s/credentials/OS-EC2/%s" %
|
||||||
(user_id, base.getid(access)), "credential")
|
(user_id, base.getid(access)), "credential")
|
||||||
|
|
||||||
def delete(self, user_id, access):
|
def delete(self, user_id, access):
|
||||||
"""
|
"""Delete an access/secret pair for a user."""
|
||||||
Delete an access/secret pair for a user
|
|
||||||
"""
|
|
||||||
return self._delete("/users/%s/credentials/OS-EC2/%s" %
|
return self._delete("/users/%s/credentials/OS-EC2/%s" %
|
||||||
(user_id, base.getid(access)))
|
(user_id, base.getid(access)))
|
||||||
|
@@ -34,22 +34,16 @@ class RoleManager(base.ManagerWithFind):
|
|||||||
return self._get("/OS-KSADM/roles/%s" % base.getid(role), "role")
|
return self._get("/OS-KSADM/roles/%s" % base.getid(role), "role")
|
||||||
|
|
||||||
def create(self, name):
|
def create(self, name):
|
||||||
"""
|
"""Create a role."""
|
||||||
Create a role.
|
|
||||||
"""
|
|
||||||
params = {"role": {"name": name}}
|
params = {"role": {"name": name}}
|
||||||
return self._create('/OS-KSADM/roles', params, "role")
|
return self._create('/OS-KSADM/roles', params, "role")
|
||||||
|
|
||||||
def delete(self, role):
|
def delete(self, role):
|
||||||
"""
|
"""Delete a role."""
|
||||||
Delete a role.
|
|
||||||
"""
|
|
||||||
return self._delete("/OS-KSADM/roles/%s" % base.getid(role))
|
return self._delete("/OS-KSADM/roles/%s" % base.getid(role))
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
"""
|
"""List all available roles."""
|
||||||
List all available roles.
|
|
||||||
"""
|
|
||||||
return self._list("/OS-KSADM/roles", "roles")
|
return self._list("/OS-KSADM/roles", "roles")
|
||||||
|
|
||||||
def roles_for_user(self, user, tenant=None):
|
def roles_for_user(self, user, tenant=None):
|
||||||
|
@@ -75,10 +75,7 @@ class TenantManager(base.ManagerWithFind):
|
|||||||
return self._get("/tenants/%s" % tenant_id, "tenant")
|
return self._get("/tenants/%s" % tenant_id, "tenant")
|
||||||
|
|
||||||
def create(self, tenant_name, description=None, enabled=True, **kwargs):
|
def create(self, tenant_name, description=None, enabled=True, **kwargs):
|
||||||
"""
|
"""Create a new tenant."""
|
||||||
Create a new tenant.
|
|
||||||
|
|
||||||
"""
|
|
||||||
params = {"tenant": {"name": tenant_name,
|
params = {"tenant": {"name": tenant_name,
|
||||||
"description": description,
|
"description": description,
|
||||||
"enabled": enabled}}
|
"enabled": enabled}}
|
||||||
@@ -91,8 +88,7 @@ class TenantManager(base.ManagerWithFind):
|
|||||||
return self._create('/tenants', params, "tenant")
|
return self._create('/tenants', params, "tenant")
|
||||||
|
|
||||||
def list(self, limit=None, marker=None):
|
def list(self, limit=None, marker=None):
|
||||||
"""
|
"""Get a list of tenants.
|
||||||
Get a list of tenants.
|
|
||||||
|
|
||||||
:param integer limit: maximum number to return. (optional)
|
:param integer limit: maximum number to return. (optional)
|
||||||
:param string marker: use when specifying a limit and making
|
:param string marker: use when specifying a limit and making
|
||||||
@@ -125,9 +121,7 @@ class TenantManager(base.ManagerWithFind):
|
|||||||
|
|
||||||
def update(self, tenant_id, tenant_name=None, description=None,
|
def update(self, tenant_id, tenant_name=None, description=None,
|
||||||
enabled=None, **kwargs):
|
enabled=None, **kwargs):
|
||||||
"""
|
"""Update a tenant with a new name and description."""
|
||||||
Update a tenant with a new name and description.
|
|
||||||
"""
|
|
||||||
body = {"tenant": {'id': tenant_id}}
|
body = {"tenant": {'id': tenant_id}}
|
||||||
if tenant_name is not None:
|
if tenant_name is not None:
|
||||||
body['tenant']['name'] = tenant_name
|
body['tenant']['name'] = tenant_name
|
||||||
@@ -145,9 +139,7 @@ class TenantManager(base.ManagerWithFind):
|
|||||||
return self._create("/tenants/%s" % tenant_id, body, "tenant")
|
return self._create("/tenants/%s" % tenant_id, body, "tenant")
|
||||||
|
|
||||||
def delete(self, tenant):
|
def delete(self, tenant):
|
||||||
"""
|
"""Delete a tenant."""
|
||||||
Delete a tenant.
|
|
||||||
"""
|
|
||||||
return self._delete("/tenants/%s" % (base.getid(tenant)))
|
return self._delete("/tenants/%s" % (base.getid(tenant)))
|
||||||
|
|
||||||
def list_users(self, tenant):
|
def list_users(self, tenant):
|
||||||
|
@@ -39,8 +39,7 @@ class UserManager(base.ManagerWithFind):
|
|||||||
return self._get("/users/%s" % base.getid(user), "user")
|
return self._get("/users/%s" % base.getid(user), "user")
|
||||||
|
|
||||||
def update(self, user, **kwargs):
|
def update(self, user, **kwargs):
|
||||||
"""
|
"""Update user data.
|
||||||
Update user data.
|
|
||||||
|
|
||||||
Supported arguments include ``name``, ``email``, and ``enabled``.
|
Supported arguments include ``name``, ``email``, and ``enabled``.
|
||||||
"""
|
"""
|
||||||
@@ -52,9 +51,7 @@ class UserManager(base.ManagerWithFind):
|
|||||||
return self._update(url, params, "user")
|
return self._update(url, params, "user")
|
||||||
|
|
||||||
def update_enabled(self, user, enabled):
|
def update_enabled(self, user, enabled):
|
||||||
"""
|
"""Update enabled-ness."""
|
||||||
Update enabled-ness
|
|
||||||
"""
|
|
||||||
params = {"user": {"id": base.getid(user),
|
params = {"user": {"id": base.getid(user),
|
||||||
"enabled": enabled}}
|
"enabled": enabled}}
|
||||||
|
|
||||||
@@ -62,9 +59,7 @@ class UserManager(base.ManagerWithFind):
|
|||||||
"user")
|
"user")
|
||||||
|
|
||||||
def update_password(self, user, password):
|
def update_password(self, user, password):
|
||||||
"""
|
"""Update password."""
|
||||||
Update password
|
|
||||||
"""
|
|
||||||
params = {"user": {"id": base.getid(user),
|
params = {"user": {"id": base.getid(user),
|
||||||
"password": password}}
|
"password": password}}
|
||||||
|
|
||||||
@@ -72,9 +67,7 @@ class UserManager(base.ManagerWithFind):
|
|||||||
params, "user")
|
params, "user")
|
||||||
|
|
||||||
def update_own_password(self, origpasswd, passwd):
|
def update_own_password(self, origpasswd, passwd):
|
||||||
"""
|
"""Update password."""
|
||||||
Update password
|
|
||||||
"""
|
|
||||||
params = {"user": {"password": passwd,
|
params = {"user": {"password": passwd,
|
||||||
"original_password": origpasswd}}
|
"original_password": origpasswd}}
|
||||||
|
|
||||||
@@ -84,9 +77,7 @@ class UserManager(base.ManagerWithFind):
|
|||||||
management=False)
|
management=False)
|
||||||
|
|
||||||
def update_tenant(self, user, tenant):
|
def update_tenant(self, user, tenant):
|
||||||
"""
|
"""Update default tenant."""
|
||||||
Update default tenant.
|
|
||||||
"""
|
|
||||||
params = {"user": {"id": base.getid(user),
|
params = {"user": {"id": base.getid(user),
|
||||||
"tenantId": base.getid(tenant)}}
|
"tenantId": base.getid(tenant)}}
|
||||||
|
|
||||||
@@ -96,9 +87,7 @@ class UserManager(base.ManagerWithFind):
|
|||||||
params, "user")
|
params, "user")
|
||||||
|
|
||||||
def create(self, name, password, email, tenant_id=None, enabled=True):
|
def create(self, name, password, email, tenant_id=None, enabled=True):
|
||||||
"""
|
"""Create a user."""
|
||||||
Create a user.
|
|
||||||
"""
|
|
||||||
# FIXME(ja): email should be optional, keystone currently requires it
|
# FIXME(ja): email should be optional, keystone currently requires it
|
||||||
params = {"user": {"name": name,
|
params = {"user": {"name": name,
|
||||||
"password": password,
|
"password": password,
|
||||||
@@ -108,14 +97,11 @@ class UserManager(base.ManagerWithFind):
|
|||||||
return self._create('/users', params, "user")
|
return self._create('/users', params, "user")
|
||||||
|
|
||||||
def delete(self, user):
|
def delete(self, user):
|
||||||
"""
|
"""Delete a user."""
|
||||||
Delete a user.
|
|
||||||
"""
|
|
||||||
return self._delete("/users/%s" % base.getid(user))
|
return self._delete("/users/%s" % base.getid(user))
|
||||||
|
|
||||||
def list(self, tenant_id=None, limit=None, marker=None):
|
def list(self, tenant_id=None, limit=None, marker=None):
|
||||||
"""
|
"""Get a list of users (optionally limited to a tenant).
|
||||||
Get a list of users (optionally limited to a tenant)
|
|
||||||
|
|
||||||
:rtype: list of :class:`User`
|
:rtype: list of :class:`User`
|
||||||
"""
|
"""
|
||||||
|
@@ -23,9 +23,7 @@ def assert_has_keys(dict, required=[], optional=[]):
|
|||||||
class FakeClient(object):
|
class FakeClient(object):
|
||||||
|
|
||||||
def assert_called(self, method, url, body=None, pos=-1):
|
def assert_called(self, method, url, body=None, pos=-1):
|
||||||
"""
|
"""Assert than an API method was just called."""
|
||||||
Assert than an API method was just called.
|
|
||||||
"""
|
|
||||||
expected = (method, url)
|
expected = (method, url)
|
||||||
called = self.callstack[pos][0:2]
|
called = self.callstack[pos][0:2]
|
||||||
|
|
||||||
@@ -38,9 +36,7 @@ class FakeClient(object):
|
|||||||
assert self.callstack[pos][2] == body
|
assert self.callstack[pos][2] == body
|
||||||
|
|
||||||
def assert_called_anytime(self, method, url, body=None):
|
def assert_called_anytime(self, method, url, body=None):
|
||||||
"""
|
"""Assert than an API method was called anytime in the test."""
|
||||||
Assert than an API method was called anytime in the test.
|
|
||||||
"""
|
|
||||||
expected = (method, url)
|
expected = (method, url)
|
||||||
|
|
||||||
assert self.callstack, ("Expected %s %s but no calls were made." %
|
assert self.callstack, ("Expected %s %s but no calls were made." %
|
||||||
|
@@ -105,8 +105,9 @@ class Ec2SignerTest(testtools.TestCase):
|
|||||||
self.assertEqual(signature, expected)
|
self.assertEqual(signature, expected)
|
||||||
|
|
||||||
def test_generate_v4(self):
|
def test_generate_v4(self):
|
||||||
"""
|
"""Test v4 generator with data from AWS docs example.
|
||||||
Test v4 generator with data from AWS docs example, see:
|
|
||||||
|
see:
|
||||||
http://docs.aws.amazon.com/general/latest/gr/
|
http://docs.aws.amazon.com/general/latest/gr/
|
||||||
sigv4-create-canonical-request.html
|
sigv4-create-canonical-request.html
|
||||||
and
|
and
|
||||||
@@ -145,9 +146,7 @@ class Ec2SignerTest(testtools.TestCase):
|
|||||||
self.assertEqual(signature, expected)
|
self.assertEqual(signature, expected)
|
||||||
|
|
||||||
def test_generate_v4_port(self):
|
def test_generate_v4_port(self):
|
||||||
"""
|
"""Test v4 generator with host:port format."""
|
||||||
Test v4 generator with host:port format
|
|
||||||
"""
|
|
||||||
# Create a new signer object with the AWS example key
|
# Create a new signer object with the AWS example key
|
||||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||||
signer = Ec2Signer(secret)
|
signer = Ec2Signer(secret)
|
||||||
@@ -181,10 +180,9 @@ class Ec2SignerTest(testtools.TestCase):
|
|||||||
self.assertEqual(signature, expected)
|
self.assertEqual(signature, expected)
|
||||||
|
|
||||||
def test_generate_v4_port_strip(self):
|
def test_generate_v4_port_strip(self):
|
||||||
"""
|
"""Test v4 generator with host:port format, but for an old
|
||||||
Test v4 generator with host:port format, but for an old
|
|
||||||
(<2.9.3) version of boto, where the port should be stripped
|
(<2.9.3) version of boto, where the port should be stripped
|
||||||
to match boto behavior
|
to match boto behavior.
|
||||||
"""
|
"""
|
||||||
# Create a new signer object with the AWS example key
|
# Create a new signer object with the AWS example key
|
||||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||||
@@ -220,9 +218,8 @@ class Ec2SignerTest(testtools.TestCase):
|
|||||||
self.assertEqual(expected, signature)
|
self.assertEqual(expected, signature)
|
||||||
|
|
||||||
def test_generate_v4_port_nostrip(self):
|
def test_generate_v4_port_nostrip(self):
|
||||||
"""
|
"""Test v4 generator with host:port format, but for an new
|
||||||
Test v4 generator with host:port format, but for an new
|
(>=2.9.3) version of boto, where the port should not be stripped.
|
||||||
(>=2.9.3) version of boto, where the port should not be stripped
|
|
||||||
"""
|
"""
|
||||||
# Create a new signer object with the AWS example key
|
# Create a new signer object with the AWS example key
|
||||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||||
|
@@ -54,8 +54,7 @@ class KeyringTest(utils.TestCase):
|
|||||||
keyring.set_keyring(MemoryKeyring())
|
keyring.set_keyring(MemoryKeyring())
|
||||||
|
|
||||||
def test_no_keyring_key(self):
|
def test_no_keyring_key(self):
|
||||||
"""
|
"""Ensure that we get no value back if we don't have use_keyring
|
||||||
Ensure that we get no value back if we don't have use_keyring
|
|
||||||
set in the client.
|
set in the client.
|
||||||
"""
|
"""
|
||||||
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
||||||
|
2
tox.ini
2
tox.ini
@@ -34,6 +34,6 @@ downloadcache = ~/cache/pip
|
|||||||
# H302: import only modules
|
# H302: import only modules
|
||||||
# H304: no relative imports
|
# H304: no relative imports
|
||||||
# H404: multi line docstring should start with a summary
|
# H404: multi line docstring should start with a summary
|
||||||
ignore = F811,F821,F841,H102,H302,H304,H404
|
ignore = F811,F821,F841,H102,H302,H304
|
||||||
show-source = True
|
show-source = True
|
||||||
exclude = .venv,.tox,dist,doc,*egg,build
|
exclude = .venv,.tox,dist,doc,*egg,build
|
||||||
|
Reference in New Issue
Block a user