Fix for k8s client annotation

This commit changes the behaviour of k8s client
while annotating. K8s client should not throw exceptions
if there are conflicts in data and resourceVersion
is different. It should resolve conflicts properly
and try to patch annotations once again changing
resourceVersion.

If data is the same in process of annotating, then
k8s client should not annotate many times.

Change-Id: I7d981b59ecdae7fe434fe580f2f342cc4621198e
Signed-off-by: Danil Golov <d.golov@samsung.com>
This commit is contained in:
Danil Golov 2019-07-12 19:04:32 +03:00
parent 295f8f103f
commit ed1017829d
2 changed files with 28 additions and 20 deletions

View File

@ -218,15 +218,16 @@ class K8sClient(object):
'annotations', {})
for k, v in annotations.items():
if v != retrieved_annotations.get(k, v):
if v != retrieved_annotations.get(k):
break
else:
# No conflicting annotations found. Retry patching
resource_version = new_version
continue
LOG.debug("Annotations for %(path)s already present: "
"%(names)s", {'path': path,
'names': retrieved_annotations})
LOG.debug("Annotations for %(path)s already present: "
"%(names)s", {'path': path,
'names': retrieved_annotations})
return retrieved_annotations
# Retry patching with updated resourceVersion
resource_version = new_version
continue
LOG.error("Exception response, headers: %(headers)s, "
"content: %(content)s, text: %(text)s"

View File

@ -179,7 +179,6 @@ class TestK8sClient(test_base.TestCase):
'annotations': annotations,
'resourceVersion': new_resource_version}}
conflicting_data = jsonutils.dumps(conflicting_obj, sort_keys=True)
good_data = jsonutils.dumps(good_obj, sort_keys=True)
m_resp_conflict = mock.MagicMock()
m_resp_conflict.ok = False
@ -198,10 +197,6 @@ class TestK8sClient(test_base.TestCase):
mock.call(self.base_url + path,
data=conflicting_data,
headers=mock.ANY,
cert=(None, None), verify=False),
mock.call(self.base_url + path,
data=good_data,
headers=mock.ANY,
cert=(None, None), verify=False)])
@mock.patch('itertools.count')
@ -262,23 +257,35 @@ class TestK8sClient(test_base.TestCase):
actual_obj = {'metadata': {
'annotations': {'a1': 'v2'},
'resourceVersion': new_resource_version}}
good_obj = {'metadata': {
'annotations': annotations,
'resourceVersion': new_resource_version}}
conflicting_data = jsonutils.dumps(conflicting_obj, sort_keys=True)
good_data = jsonutils.dumps(good_obj, sort_keys=True)
m_resp_conflict = mock.MagicMock()
m_resp_conflict.ok = False
m_resp_conflict.status_code = requests.codes.conflict
m_patch.return_value = m_resp_conflict
m_resp_good = mock.MagicMock()
m_resp_good.ok = True
m_resp_good.json.return_value = conflicting_obj
m_patch.side_effect = [m_resp_conflict, m_resp_good]
with mock.patch.object(self.client, 'get') as m_get:
m_get.return_value = actual_obj
self.assertRaises(exc.K8sClientException,
self.client.annotate,
path, annotations,
resource_version=resource_version)
m_patch.assert_called_once_with(self.base_url + path,
data=conflicting_data,
headers=mock.ANY,
cert=(None, None), verify=False)
self.assertEqual(annotations, self.client.annotate(
path, annotations,
resource_version=resource_version))
m_patch.assert_has_calls([
mock.call(self.base_url + path,
data=conflicting_data,
headers=mock.ANY,
cert=(None, None), verify=False),
mock.call(self.base_url + path,
data=good_data,
headers=mock.ANY,
cert=(None, None), verify=False)])
@mock.patch('itertools.count')
@mock.patch('requests.patch')