client: Add REST client library
parent
d4dfb3cafd
commit
61eb0f1ee6
|
@ -0,0 +1,130 @@
|
|||
from __future__ import unicode_literals
|
||||
from . import host
|
||||
from six.moves import urllib
|
||||
import codecs
|
||||
import json
|
||||
import os
|
||||
import six
|
||||
|
||||
|
||||
DEFAULT_BASEURL = os.environ.get('ROUSE_URL', 'http://localhost/rouse')
|
||||
|
||||
|
||||
class RouseError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class PUTRequest(urllib.request.Request):
|
||||
|
||||
def get_method(self):
|
||||
return 'PUT'
|
||||
|
||||
|
||||
class DELETERequest(urllib.request.Request):
|
||||
|
||||
def get_method(self):
|
||||
return 'DELETE'
|
||||
|
||||
|
||||
class Rouse(object):
|
||||
|
||||
def __init__(self, baseurl=DEFAULT_BASEURL):
|
||||
self.baseurl = baseurl.rstrip('/')
|
||||
|
||||
def request(self, path, query=None, data=None, method=None):
|
||||
if data is not None:
|
||||
data = urllib.parse.urlencode([(k, v if v is not None else '')
|
||||
for k, v in six.iteritems(data)])
|
||||
data = data.encode('utf-8')
|
||||
url = urllib.parse.urljoin(self.baseurl, path)
|
||||
if query:
|
||||
url += '?' + urllib.parse.urlencode(
|
||||
[(k, v if v is not None else '')
|
||||
for k, v in six.iteritems(query)]
|
||||
)
|
||||
|
||||
if method == 'DELETE':
|
||||
req = DELETERequest(url, data)
|
||||
elif method == 'PUT':
|
||||
req = PUTRequest(url, data)
|
||||
else:
|
||||
req = urllib.request.Request(url, data)
|
||||
try:
|
||||
res = urllib.request.urlopen(req)
|
||||
except urllib.error.HTTPError as e:
|
||||
try:
|
||||
content_length = int(e.info()['Content-Length'])
|
||||
except (KeyError, ValueError):
|
||||
content_length = 0
|
||||
if content_length:
|
||||
err = json.load(codecs.getreader('utf-8')(e))['error']
|
||||
raise RouseError(err)
|
||||
try:
|
||||
try:
|
||||
content_length = int(res.info()['Content-Length'])
|
||||
except (KeyError, ValueError):
|
||||
content_length = 0
|
||||
if content_length:
|
||||
return json.load(codecs.getreader('utf-8')(res))
|
||||
finally:
|
||||
res.close()
|
||||
|
||||
def delete(self, path, **keywords):
|
||||
return self.request(path, keywords, method='DELETE')
|
||||
|
||||
def get(self, path, **keywords):
|
||||
return self.request(path, keywords)
|
||||
|
||||
def post(self, path, **keywords):
|
||||
return self.request(path, data=keywords)
|
||||
|
||||
def put(self, path, **keywords):
|
||||
return self.request(path, data=keywords, method='PUT')
|
||||
|
||||
|
||||
class Host(host.Host):
|
||||
|
||||
def __init__(self, macaddr=None, ipaddr=None, hostname=None):
|
||||
self.id = None
|
||||
self.macaddr = macaddr
|
||||
self.ipaddr = ipaddr
|
||||
self.hostname = hostname
|
||||
self.rouse = None
|
||||
|
||||
@classmethod
|
||||
def find(cls, rouse, **keywords):
|
||||
for item in rouse.get('/', **keywords):
|
||||
host = cls.from_dict(item)
|
||||
host.rouse = rouse
|
||||
yield host
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data):
|
||||
self = cls()
|
||||
self.__dict__.update(data)
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
def get(cls, rouse, id):
|
||||
host = cls.from_dict(rouse.get('/{}'.format(id)))
|
||||
host.rouse = rouse
|
||||
return host
|
||||
|
||||
def add(self, rouse):
|
||||
self.rouse = rouse
|
||||
self.id = self.rouse.post('/', **self.as_dict())['id']
|
||||
|
||||
def as_dict(self):
|
||||
data = self.__dict__.copy()
|
||||
del data['id']
|
||||
del data['rouse']
|
||||
for key in data:
|
||||
if key.startswith('_'):
|
||||
del data[key]
|
||||
return data
|
||||
|
||||
def delete(self):
|
||||
self.rouse.delete('/{}'.format(self.id))
|
||||
|
||||
def update(self):
|
||||
self.rouse.put('/{}'.format(self.id), **self.as_dict())
|
Loading…
Reference in New Issue