Skip to content

Commit 7f6fa7f

Browse files
committed
Add EtcdResult.etcd_index; minor fixes.
We added EtcdResult.etcd_index and EtcdResult.raft_index as result of parsing response headers from etcd, as requested in jplana#39. Also, we fixed the bug in the etcd.Client.write() response when updating a dir ( jplana#38), which is done by parsing the content of prevNode, which we formerly discarded. Last, this patch makes etcd.Client.update() finally work against directories, working around the unusual behaviour of the etcd server in this respect.
1 parent 092e20d commit 7f6fa7f

4 files changed

Lines changed: 28 additions & 10 deletions

File tree

src/etcd/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class EtcdResult(object):
1616
'dir': False,
1717
}
1818

19-
def __init__(self, action=None, node=None, **kwdargs):
19+
def __init__(self, action=None, node=None, prevNode=None, **kwdargs):
2020
"""
2121
Creates an EtcdResult object.
2222
@@ -38,6 +38,16 @@ def __init__(self, action=None, node=None, **kwdargs):
3838
# We keep the data in raw format, converting them only when needed
3939
self._children = node['nodes']
4040

41+
if prevNode:
42+
self._prev_node = EtcdResult(None, node=prevNode)
43+
# See issue 38: when returning a write() op etcd has a bogus result.
44+
if self._prev_node.dir and not self.dir:
45+
self.dir = True
46+
47+
def parse_headers(self, response):
48+
headers = response.getheaders()
49+
self.etcd_index = headers.get('x-etcd-index', 1)
50+
self.raft_index = headers.get('x-raft-index', 1)
4151

4252
def get_subtree(self, leaves_only=False):
4353
"""

src/etcd/client.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,17 @@ def update(self, obj):
282282
obj (etcd.EtcdResult): The object that needs updating.
283283
284284
"""
285-
return self.write(
286-
obj.key,
287-
obj.value,
288-
ttl=obj.ttl,
289-
dir=obj.dir,
290-
prevExist=True,
291-
prevIndex=obj.modifiedIndex)
285+
kwdargs = {
286+
'dir': obj.dir,
287+
'ttl': obj.ttl,
288+
'prevExist': True
289+
}
290+
291+
if not obj.dir:
292+
# prevIndex on a dir causes a 'not a file' error. d'oh!
293+
kwdargs['prevIndex'] = obj.modifiedIndex
294+
295+
return self.write(obj.key, obj.value, **kwdargs)
292296

293297

294298

@@ -511,13 +515,12 @@ def election(self):
511515

512516
def _result_from_response(self, response):
513517
""" Creates an EtcdResult from json dictionary """
514-
# TODO: add headers we obtained from the http respose to the etcd
515-
# result.
516518
try:
517519
res = json.loads(response.data.decode('utf-8'))
518520
r = etcd.EtcdResult(**res)
519521
if response.status == 201:
520522
r.newKey = True
523+
r.parse_headers(response)
521524
return r
522525
except Exception as e:
523526
raise etcd.EtcdException(

src/etcd/tests/integration/test_simple.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ def test_directory_ttl_update(self):
127127
self.client.write('/dir', None, dir=True, ttl=30)
128128
res = self.client.write('/dir', None, dir=True, ttl=31, prevExist=True)
129129
self.assertEquals(res.ttl, 31)
130+
res.ttl = 120
131+
new_res = self.client.update(res)
132+
self.assertEquals(new_res.ttl, 120)
130133

131134

132135

src/etcd/tests/unit/test_old_request.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ def __init__(self, status, data=''):
1414
self.status = status
1515
self.data = data.encode('utf-8')
1616

17+
def getheaders(self):
18+
return {}
1719

1820
class TestClientRequest(unittest.TestCase):
1921

0 commit comments

Comments
 (0)