diff --git a/etcd3gw/client.py b/etcd3gw/client.py index 1a74c0c..6d9ab73 100644 --- a/etcd3gw/client.py +++ b/etcd3gw/client.py @@ -12,11 +12,13 @@ import base64 import json +import uuid import requests import six from etcd3gw.lease import Lease +from etcd3gw.lock import Lock from etcd3gw.utils import _encode from etcd3gw.utils import DEFAULT_TIMEOUT @@ -48,6 +50,9 @@ class Client(object): json={"TTL": ttl, "ID": 0}) return Lease(int(result['ID']), client=self) + def lock(self, id=str(uuid.uuid4()), ttl=DEFAULT_TIMEOUT): + return Lock(id, ttl=ttl, client=self) + def put(self, key, value, lease=None): payload = { "key": _encode(key), diff --git a/etcd3gw/lease.py b/etcd3gw/lease.py index c58e820..7c6b354 100644 --- a/etcd3gw/lease.py +++ b/etcd3gw/lease.py @@ -39,5 +39,6 @@ class Lease(object): result = self.client.post(self.client.get_url("/kv/lease/timetolive"), json={"ID": self.id, "keys": True}) + keys = result['keys'] if 'keys' in result else [] return [base64.b64decode(six.b(key)).decode('utf-8') - for key in result['keys']] + for key in keys] diff --git a/etcd3gw/tests/test_etcd3gw.py b/etcd3gw/tests/test_etcd3gw.py index fa758f9..6c667dd 100644 --- a/etcd3gw/tests/test_etcd3gw.py +++ b/etcd3gw/tests/test_etcd3gw.py @@ -18,6 +18,7 @@ Tests for `etcd3gw` module. """ from testtools.testcase import unittest +import time import urllib3 from etcd3gw.client import Client @@ -33,8 +34,46 @@ def _is_etcd3_running(): class TestEtcd3Gateway(base.TestCase): + @classmethod + def setUpClass(cls): + cls.client = Client() + @unittest.skipUnless( _is_etcd3_running(), "etcd3 is not available") - def test_something(self): - client = Client() - self.assertIsNotNone(client.status()) + def test_client_status(self): + response = self.client.status() + self.assertIsNotNone(response) + self.assertIn('version', response) + self.assertIn('header', response) + self.assertIn('cluster_id', response['header']) + + @unittest.skipUnless( + _is_etcd3_running(), "etcd3 is not available") + def test_client_lease(self): + lease = self.client.lease(ttl=60) + self.assertIsNotNone(lease) + + ttl = lease.ttl() + self.assertTrue(0 <= ttl <= 60) + + keys = lease.keys() + self.assertEqual([], keys) + + ttl = lease.refresh() + self.assertTrue(0 <= ttl <= 60) + + self.assertTrue(lease.revoke()) + + @unittest.skipUnless( + _is_etcd3_running(), "etcd3 is not available") + def test_client_locks(self): + lock = self.client.lock(id='xyz-%s' % time.clock(), ttl=60) + self.assertIsNotNone(lock) + + self.assertTrue(lock.acquire()) + ttl = lock.refresh() + self.assertTrue(0 <= ttl <= 60) + + self.assertTrue(lock.is_acquired()) + self.assertTrue(lock.release()) + self.assertFalse(lock.is_acquired())