diff options
author | Simo Sorce <simo@redhat.com> | 2015-10-01 18:19:02 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2015-10-19 12:18:10 -0400 |
commit | a94ac9cec35e12765bba61409cf4db88f564af4c (patch) | |
tree | f49eb76daf77270755c7c1335a963500e73e5b22 | |
parent | 58d434e0fea2b2f9544e7ef1fba07bf50e07b7c0 (diff) | |
download | custodia-a94ac9cec35e12765bba61409cf4db88f564af4c.tar.gz custodia-a94ac9cec35e12765bba61409cf4db88f564af4c.tar.xz custodia-a94ac9cec35e12765bba61409cf4db88f564af4c.zip |
Add client classes to query custodia servers
This makes it simpler to use a custodia server, whether exposed over
HTTP, HTTPS or a unix socket with the http+unix schema.
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Christian Heimes <cheimes@redhat.com>
-rw-r--r-- | custodia/client.py | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/custodia/client.py b/custodia/client.py new file mode 100644 index 0000000..d4b9c1a --- /dev/null +++ b/custodia/client.py @@ -0,0 +1,133 @@ +# Copyright (C) 2015 Custodia Project Contributors - see LICENSE file + +import socket + +import requests + +from requests.adapters import HTTPAdapter +from requests.compat import unquote, urlparse + +from requests.packages.urllib3.connection import HTTPConnection +from requests.packages.urllib3.connectionpool import HTTPConnectionPool + + +class HTTPUnixConnection(HTTPConnection): + + def __init__(self, host, timeout=60, **kwargs): + super(HTTPConnection, self).__init__('localhost') + self.unix_socket = host + self.timeout = timeout + + def connect(self): + s = socket.socket(family=socket.AF_UNIX) + s.settimeout(self.timeout) + s.connect(self.unix_socket) + self.sock = s + + +class HTTPUnixConnectionPool(HTTPConnectionPool): + + scheme = 'http+unix' + ConnectionCls = HTTPUnixConnection + + +class HTTPUnixAdapter(HTTPAdapter): + + def get_connection(self, url, proxies=None): + # proxies, silently ignored + path = unquote(urlparse(url).netloc) + return HTTPUnixConnectionPool(path) + + +DEFAULT_HEADERS = {'Content-Type': 'application/json'} + + +class CustodiaHTTPClient(object): + + def __init__(self, url): + self.session = requests.Session() + self.session.mount('http+unix://', HTTPUnixAdapter()) + self.headers = dict(DEFAULT_HEADERS) + self.url = url + + def set_simple_auth_keys(self, name, key, + name_header='CUSTODIA_AUTH_ID', + key_header='CUSTODIA_AUTH_KEY'): + self.headers[name_header] = name + self.headers[key_header] = key + + def _join_url(self, path): + return self.url.rstrip('/') + '/' + path.lstrip('/') + + def _add_headers(self, **kwargs): + headers = kwargs.get('headers', None) + if headers is None: + headers = dict() + headers.update(self.headers) + return headers + + def _request(self, cmd, path, **kwargs): + url = self._join_url(path) + kwargs['headers'] = self._add_headers(**kwargs) + return cmd(url, **kwargs) + + def delete(self, path, **kwargs): + return self._request(self.session.delete, path, **kwargs) + + def get(self, path, **kwargs): + return self._request(self.session.get, path, **kwargs) + + def head(self, path, **kwargs): + return self._request(self.session.head, path, **kwargs) + + def patch(self, path, **kwargs): + return self._request(self.session.patch, path, **kwargs) + + def post(self, path, **kwargs): + return self._request(self.session.post, path, **kwargs) + + def put(self, path, **kwargs): + return self._request(self.session.put, path, **kwargs) + + +class CustodiaClient(CustodiaHTTPClient): + + def create_container(self, name): + r = self.post(name if name.endswith('/') else name + '/') + r.raise_for_status() + return r + + def delete_container(self, name): + r = self.delete(name if name.endswith('/') else name + '/') + r.raise_for_status() + return r + + def list_container(self, name): + r = self.get(name if name.endswith('/') else name + '/') + r.raise_for_status() + return r + + def get_key(self, name): + r = self.get(name) + r.raise_for_status() + return r + + def set_key(self, name, data_to_json): + r = self.put(name, json=data_to_json) + r.raise_for_status() + return r + + def del_key(self, name): + r = self.delete(name) + r.raise_for_status() + return r + + def get_simple_key(self, name): + simple = self.get_key(name).json() + ktype = simple.get("type", None) + if ktype != "simple": + raise TypeError("Invalid key type: %s" % ktype) + return simple["value"] + + def set_simple_key(self, name, value): + self.set_key(name, {"type": "simple", "value": value}) |