Skip to content
This repository has been archived by the owner on Aug 21, 2020. It is now read-only.

Commit

Permalink
Add a "create" method for the client
Browse files Browse the repository at this point in the history
Adds a "create" method to the client, which verifies
that the key did not exists in the key-value store,
before assigning the new value to the key
  • Loading branch information
lihiwish authored and dims committed Aug 30, 2017
1 parent a5f22d4 commit 868e854
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
36 changes: 36 additions & 0 deletions etcd3gw/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,42 @@ def lock(self, id=str(uuid.uuid4()), ttl=DEFAULT_TIMEOUT):
"""
return Lock(id, ttl=ttl, client=self)

def create(self, key, value):
"""Atomically create the given key only if the key doesn't exist.
This verifies that the create_revision of a key equales to 0, then
creates the key with the value.
This operation takes place in a transaction.
:param key: key in etcd to create
:param value: value of the key
:type value: bytes or string
:returns: status of transaction, ``True`` if the create was
successful, ``False`` otherwise
:rtype: bool
"""
base64_key = _encode(key)
base64_value = _encode(value)
txn = {
'compare': [{
'key': base64_key,
'result': 'EQUAL',
'target': 'CREATE',
'create_revision': 0
}],
'success': [{
'request_put': {
'key': base64_key,
'value': base64_value,
}
}],
'failure': []
}
result = self.transaction(txn)
if 'succeeded' in result:
return result['succeeded']
return False

def put(self, key, value, lease=None):
"""Put puts the given key into the key-value store.
Expand Down
25 changes: 25 additions & 0 deletions etcd3gw/tests/test_etcd3gw.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,28 @@ def test_client_locks(self):
self.assertTrue(lock.release())
self.assertFalse(lock.release())
self.assertFalse(lock.is_acquired())

@unittest.skipUnless(
_is_etcd3_running(), "etcd3 is not available")
def test_create_success(self):
key = '/foo/unique' + str(uuid.uuid4())
# Verify that key is empty
self.assertEqual([], self.client.get(key))

status = self.client.create(key, 'bar')
# Verify that key is 'bar'
self.assertEqual(['bar'], self.client.get(key))
self.assertTrue(status)

@unittest.skipUnless(
_is_etcd3_running(), "etcd3 is not available")
def test_create_fail(self):
key = '/foo/' + str(uuid.uuid4())
# Assign value to the key
self.client.put(key, 'bar')
self.assertEqual(['bar'], self.client.get(key))

status = self.client.create(key, 'goo')
# Verify that key is still 'bar'
self.assertEqual(['bar'], self.client.get(key))
self.assertFalse(status)

0 comments on commit 868e854

Please sign in to comment.