Skip to content
This repository was archived by the owner on Mar 13, 2022. It is now read-only.

Commit c4de8bd

Browse files
authored
Merge pull request #93 from mitar/watch_and_logs
Making watch work with read_namespaced_pod_log
2 parents e077f88 + 972a76a commit c4de8bd

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

watch/watch.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from kubernetes import client
2121

2222
PYDOC_RETURN_LABEL = ":return:"
23+
PYDOC_FOLLOW_PARAM = ":param bool follow:"
2324

2425
# Removing this suffix from return type name should give us event's object
2526
# type. e.g., if list_namespaces() returns "NamespaceList" type,
@@ -65,7 +66,7 @@ def __init__(self, return_type=None):
6566
self._raw_return_type = return_type
6667
self._stop = False
6768
self._api_client = client.ApiClient()
68-
self.resource_version = 0
69+
self.resource_version = None
6970

7071
def stop(self):
7172
self._stop = True
@@ -78,8 +79,17 @@ def get_return_type(self, func):
7879
return return_type[:-len(TYPE_LIST_SUFFIX)]
7980
return return_type
8081

82+
def get_watch_argument_name(self, func):
83+
if PYDOC_FOLLOW_PARAM in pydoc.getdoc(func):
84+
return 'follow'
85+
else:
86+
return 'watch'
87+
8188
def unmarshal_event(self, data, return_type):
82-
js = json.loads(data)
89+
try:
90+
js = json.loads(data)
91+
except ValueError:
92+
return data
8393
js['raw_object'] = js['object']
8494
if return_type:
8595
obj = SimpleNamespace(data=json.dumps(js['raw_object']))
@@ -122,7 +132,7 @@ def stream(self, func, *args, **kwargs):
122132

123133
self._stop = False
124134
return_type = self.get_return_type(func)
125-
kwargs['watch'] = True
135+
kwargs[self.get_watch_argument_name(func)] = True
126136
kwargs['_preload_content'] = False
127137
if 'resource_version' in kwargs:
128138
self.resource_version = kwargs['resource_version']
@@ -136,9 +146,12 @@ def stream(self, func, *args, **kwargs):
136146
if self._stop:
137147
break
138148
finally:
139-
kwargs['resource_version'] = self.resource_version
140149
resp.close()
141150
resp.release_conn()
151+
if self.resource_version is not None:
152+
kwargs['resource_version'] = self.resource_version
153+
else:
154+
self._stop = True
142155

143156
if timeouts or self._stop:
144157
break

watch/watch_test.py

+29
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,35 @@ def test_watch_with_decode(self):
6767
fake_resp.close.assert_called_once()
6868
fake_resp.release_conn.assert_called_once()
6969

70+
def test_watch_for_follow(self):
71+
fake_resp = Mock()
72+
fake_resp.close = Mock()
73+
fake_resp.release_conn = Mock()
74+
fake_resp.read_chunked = Mock(
75+
return_value=[
76+
'log_line_1\n',
77+
'log_line_2\n'])
78+
79+
fake_api = Mock()
80+
fake_api.read_namespaced_pod_log = Mock(return_value=fake_resp)
81+
fake_api.read_namespaced_pod_log.__doc__ = ':param bool follow:\n:return: str'
82+
83+
w = Watch()
84+
count = 1
85+
for e in w.stream(fake_api.read_namespaced_pod_log):
86+
self.assertEqual("log_line_1", e)
87+
count += 1
88+
# make sure we can stop the watch and the last event with won't be
89+
# returned
90+
if count == 2:
91+
w.stop()
92+
93+
fake_api.read_namespaced_pod_log.assert_called_once_with(
94+
_preload_content=False, follow=True)
95+
fake_resp.read_chunked.assert_called_once_with(decode_content=False)
96+
fake_resp.close.assert_called_once()
97+
fake_resp.release_conn.assert_called_once()
98+
7099
def test_watch_resource_version_set(self):
71100
# https://github.com/kubernetes-client/python/issues/700
72101
# ensure watching from a resource version does reset to resource

0 commit comments

Comments
 (0)