Skip to content

Commit

Permalink
Refactor adapters, Duplicate Auth Method (#232)
Browse files Browse the repository at this point in the history
* Move basic method implemention to base class

* Move business logic of auth module to Adapter class

This will allow future additions of seperate auth method classes to reuse the logic.

* Fill out request method docstrings

* Revert accidental reordering of close method in class

* Look on my two actively used Python major versions...

ye Mighty, and despair! Nothing consistent remains. Round the versions
Of that colossal community, opinionated and nerdy
The varied and competing docstring standards stretch far away.

* NotImplemented error NotImplementedError
  • Loading branch information
jeffwecan committed Jul 27, 2018
1 parent 1332cfb commit 3071f86
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 61 deletions.
110 changes: 64 additions & 46 deletions hvac/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,14 @@

logger = logging.getLogger(__name__)

DEFAULT_BASE_URI = 'http://localhost:8200'


class Adapter(object):
"""Abstract base class used when constructing adapters for use with the Client class."""
__metaclass__ = ABCMeta

@staticmethod
def urljoin(*args):
"""Joins given arguments into a url. Trailing and leading slashes are stripped for each argument.
:param args: Multiple parts of a URL to be combined into one string.
:type args: str
:return: Full URL combining all provided arguments
:rtype: str
"""

return '/'.join(map(lambda x: str(x).strip('/'), args))

@abstractmethod
def close(self):
raise NotImplemented

@abstractmethod
def get(self, url, **kwargs):
raise NotImplemented

@abstractmethod
def post(self, url, **kwargs):
raise NotImplemented

@abstractmethod
def put(self, url, **kwargs):
raise NotImplemented

@abstractmethod
def delete(self, url, **kwargs):
raise NotImplemented

@abstractmethod
def request(self, method, url, headers=None, **kwargs):
raise NotImplemented


class Request(Adapter):
"""The Request adapter class"""

def __init__(self, base_uri='http://localhost:8200', token=None, cert=None, verify=True, timeout=30, proxies=None,
def __init__(self, base_uri=DEFAULT_BASE_URI, token=None, cert=None, verify=True, timeout=30, proxies=None,
allow_redirects=True, session=None):
"""Create a new request adapter instance.
Expand Down Expand Up @@ -96,6 +58,18 @@ def __init__(self, base_uri='http://localhost:8200', token=None, cert=None, veri
'proxies': proxies,
}

@staticmethod
def urljoin(*args):
"""Joins given arguments into a url. Trailing and leading slashes are stripped for each argument.
:param args: Multiple parts of a URL to be combined into one string.
:type args: str | unicode
:return: Full URL combining all provided arguments
:rtype: str | unicode
"""

return '/'.join(map(lambda x: str(x).strip('/'), args))

def close(self):
"""Close the underlying Requests session.
"""
Expand All @@ -106,7 +80,7 @@ def get(self, url, **kwargs):
:param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri
attribute.
:type url: str
:type url: str | unicode
:param kwargs: Additional keyword arguments to include in the requests call.
:type kwargs: dict
:return: The response of the request.
Expand All @@ -119,7 +93,7 @@ def post(self, url, **kwargs):
:param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri
attribute.
:type url: str
:type url: str | unicode
:param kwargs: Additional keyword arguments to include in the requests call.
:type kwargs: dict
:return: The response of the request.
Expand All @@ -132,7 +106,7 @@ def put(self, url, **kwargs):
:param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri
attribute.
:type url: str
:type url: str | unicode
:param kwargs: Additional keyword arguments to include in the requests call.
:type kwargs: dict
:return: The response of the request.
Expand All @@ -145,22 +119,66 @@ def delete(self, url, **kwargs):
:param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri
attribute.
:type url: str
:type url: str | unicode
:param kwargs: Additional keyword arguments to include in the requests call.
:type kwargs: dict
:return: The response of the request.
:rtype: requests.Response
"""
return self.request('delete', url, **kwargs)

def auth(self, url, use_token=True, **kwargs):
"""Performs a request (typically to a path prefixed with "/v1/auth") and optionaly stores the client token sent
in the resulting Vault response for use by the :py:meth:`hvac.adapters.Adapter` instance under the _adapater
Client attribute.
:param url: Path to send the authentication request to.
:type url: str | unicode
:param use_token: if True, uses the token in the response received from the auth request to set the "token"
attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapater Client attribute.
:type use_token: bool
:param kwargs: Additional keyword arguments to include in the params sent with the request.
:type kwargs: dict
:return: The response of the auth request.
:rtype: requests.Response
"""
response = self.post(url, **kwargs).json()

if use_token:
self.token = response['auth']['client_token']

return response

@abstractmethod
def request(self, method, url, headers=None, **kwargs):
"""Main method for routing HTTP requests to the configured Vault base_uri. Intended to be implement by subclasses.
:param method: HTTP method to use with the request. E.g., GET, POST, etc.
:type method: str
:param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri
attribute.
:type url: str | unicode
:param headers: Additional headers to include with the request.
:type headers: dict
:param kwargs: Additional keyword arguments to include in the requests call.
:type kwargs: dict
:return: The response of the request.
:rtype: requests.Response
"""
raise NotImplementedError


class Request(Adapter):
"""The Request adapter class"""

def request(self, method, url, headers=None, **kwargs):
"""Main method for routing HTTP requests to the configured Vault base_uri.
:param method: HTTP method to use with the request. E.g., GET, POST, etc.
:type method: str
:param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri
attribute.
:type url: str
:type url: str | unicode
:param headers: Additional headers to include with the request.
:type headers: dict
:param kwargs: Additional keyword arguments to include in the requests call.
Expand Down
32 changes: 17 additions & 15 deletions hvac/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1702,23 +1702,25 @@ def auth_cubbyhole(self, token):
return self.auth('/v1/sys/wrapping/unwrap')

def auth(self, url, use_token=True, **kwargs):
"""
"""Performs a request (typically to a path prefixed with "/v1/auth") and optionaly stores the client token sent
in the resulting Vault response for use by the :py:meth:`hvac.adapters.Adapter` instance under the _adapater
Client attribute.
:param url:
:type url:
:param use_token:
:type use_token:
:param kwargs:
:type kwargs:
:return:
:rtype:
:param url: Path to send the authentication request to.
:type url: str | unicode
:param use_token: if True, uses the token in the response received from the auth request to set the "token"
attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapater Client attribute.
:type use_token: bool
:param kwargs: Additional keyword arguments to include in the params sent with the request.
:type kwargs: dict
:return: The response of the auth request.
:rtype: requests.Response
"""
response = self._adapter.post(url, **kwargs).json()

if use_token:
self.token = response['auth']['client_token']

return response
return self._adapter.auth(
url=url,
use_token=use_token,
**kwargs
)

def list_auth_backends(self):
"""GET /sys/auth
Expand Down

0 comments on commit 3071f86

Please sign in to comment.