From e2ab5cc2c8c1b2a70e1657f5a0e89eb62e8e6aab Mon Sep 17 00:00:00 2001 From: Kyle MacLeod Date: Thu, 19 Aug 2021 11:09:53 -0400 Subject: [PATCH] Patch watch.py in python-kubernetes package Patch the python2-kubernetes-8.0.0-8.el7.noarch.rpm with recent bug fix commits required for proper kubernetes watch functionality. Patches watch.py up to commit 10ae476 in the 'base' repo (kubernetes-client/python-base). Commits are taken from the cloned github repo, saved in patch format, and applied as a patch to the source RPM. Reference: https://github.com/kubernetes-client/python-base/commits/master/watch/watch.py This patch includes commits beginning with d56fdbc, up to and including 10ae476 Testing: - Built and testing on local distributed cloud system - Similar testing to this patch but ased on locally modified package has been done on 1000 subcloud system - Examine/compare contents of installed package vs. expected - Generating events which trigger the watch conditions - Monitor watches for proper behaviour on expiry Story: 2008960 Task: 43053 Signed-off-by: Kyle MacLeod Change-Id: I7ad78957b6ef61e7204c45f482f201d5c281385b --- centos_pkg_dirs | 1 + centos_srpms_centos.lst | 1 + .../python-kubernetes/centos/build_srpm.data | 1 + .../0001-Include-watch.py-bug-fixes.patch | 95 +++++++++++++++++++ .../centos/meta_patches/PATCH_ORDER | 1 + .../patches/0001-Verify-Boilerplate-fix.patch | 22 +++++ ...ng-with-a-specified-resource-version.patch | 41 ++++++++ ...ch-work-with-read_namespaced_pod_log.patch | 76 +++++++++++++++ .../0004-Don-t-use-break-inside-finally.patch | 26 +++++ ...angs-from-Python-modules-and-checker.patch | 31 ++++++ ...rshal_event-when-data-is-not-a-JSON-.patch | 28 ++++++ ...top-unmarshalling-when-streaming-log.patch | 54 +++++++++++ .../0008-Retry-watch-if-request-expires.patch | 81 ++++++++++++++++ ...9-Fix-a-Python-2-compatibility-issue.patch | 60 ++++++++++++ .../0010-Fixes-codestyle-failures.patch | 31 ++++++ ...11-Fix-Watch-retries-with-410-errors.patch | 46 +++++++++ ...-client-python-issue-1047-ResponseNo.patch | 31 ++++++ ...of-decoding-error-for-BOOKMARK-event.patch | 29 ++++++ python/python-kubernetes/centos/srpm_path | 1 + 19 files changed, 656 insertions(+) create mode 100644 python/python-kubernetes/centos/build_srpm.data create mode 100644 python/python-kubernetes/centos/meta_patches/0001-Include-watch.py-bug-fixes.patch create mode 100644 python/python-kubernetes/centos/meta_patches/PATCH_ORDER create mode 100644 python/python-kubernetes/centos/patches/0001-Verify-Boilerplate-fix.patch create mode 100644 python/python-kubernetes/centos/patches/0002-fix-watching-with-a-specified-resource-version.patch create mode 100644 python/python-kubernetes/centos/patches/0003-Making-watch-work-with-read_namespaced_pod_log.patch create mode 100644 python/python-kubernetes/centos/patches/0004-Don-t-use-break-inside-finally.patch create mode 100644 python/python-kubernetes/centos/patches/0005-Remove-all-shebangs-from-Python-modules-and-checker.patch create mode 100644 python/python-kubernetes/centos/patches/0006-Fixed-Watch.unmarshal_event-when-data-is-not-a-JSON-.patch create mode 100644 python/python-kubernetes/centos/patches/0007-watch-stream-stop-unmarshalling-when-streaming-log.patch create mode 100644 python/python-kubernetes/centos/patches/0008-Retry-watch-if-request-expires.patch create mode 100644 python/python-kubernetes/centos/patches/0009-Fix-a-Python-2-compatibility-issue.patch create mode 100644 python/python-kubernetes/centos/patches/0010-Fixes-codestyle-failures.patch create mode 100644 python/python-kubernetes/centos/patches/0011-Fix-Watch-retries-with-410-errors.patch create mode 100644 python/python-kubernetes/centos/patches/0012-Fixes-kubernetes-client-python-issue-1047-ResponseNo.patch create mode 100644 python/python-kubernetes/centos/patches/0013-quick-fix-of-decoding-error-for-BOOKMARK-event.patch create mode 100644 python/python-kubernetes/centos/srpm_path diff --git a/centos_pkg_dirs b/centos_pkg_dirs index 751368a92..f292a955f 100644 --- a/centos_pkg_dirs +++ b/centos_pkg_dirs @@ -64,6 +64,7 @@ kubernetes/armada-helm-toolkit kubernetes/armada kubernetes/k8s-pod-recovery kubernetes/plugins/isolcpus-device-plugin +python/python-kubernetes grub/grubby base/dpkg base/cluster-resource-agents diff --git a/centos_srpms_centos.lst b/centos_srpms_centos.lst index 24fccabd4..5b260e384 100644 --- a/centos_srpms_centos.lst +++ b/centos_srpms_centos.lst @@ -28,6 +28,7 @@ puppet-staging-1.0.4-1.b466d93git.el7.src.rpm puppet-stdlib-4.18.0-2.el7.src.rpm python-docker-3.3.0-1.el7.src.rpm python-keyring-5.7.1-1.el7.src.rpm +python-kubernetes-8.0.0-8.el7.src.rpm python-psycopg2-2.5.1-3.el7.src.rpm python-voluptuous-0.8.9-1.el7.src.rpm resource-agents-4.1.1-12.el7_6.7.src.rpm diff --git a/python/python-kubernetes/centos/build_srpm.data b/python/python-kubernetes/centos/build_srpm.data new file mode 100644 index 000000000..69abd61b8 --- /dev/null +++ b/python/python-kubernetes/centos/build_srpm.data @@ -0,0 +1 @@ +TIS_PATCH_VER=PKG_GITREVCOUNT diff --git a/python/python-kubernetes/centos/meta_patches/0001-Include-watch.py-bug-fixes.patch b/python/python-kubernetes/centos/meta_patches/0001-Include-watch.py-bug-fixes.patch new file mode 100644 index 000000000..24d028537 --- /dev/null +++ b/python/python-kubernetes/centos/meta_patches/0001-Include-watch.py-bug-fixes.patch @@ -0,0 +1,95 @@ +From b33ab116b3a32578131712e9a450eb6c88782ef6 Mon Sep 17 00:00:00 2001 +From: Kyle MacLeod +Date: Tue, 17 Aug 2021 10:25:31 -0400 +Subject: [PATCH] Include watch.py bug fixes + +Patches watch.py up to commit 10ae476 in the 'base' repo +(kubernetes-client/python-base). +--- + SPECS/python-kubernetes.spec | 45 +++++++++++++++++++++++++++++++++--- + 1 file changed, 42 insertions(+), 3 deletions(-) + +diff --git a/SPECS/python-kubernetes.spec b/SPECS/python-kubernetes.spec +index 87c48ca..1c6fb59 100644 +--- a/SPECS/python-kubernetes.spec ++++ b/SPECS/python-kubernetes.spec +@@ -21,7 +21,7 @@ Source2: make-adal-optional.patch + + Name: python-%{library} + Version: 8.0.0 +-Release: 8%{?dist} ++Release: 8.el7%{?_tis_dist}.%{tis_patch_ver} + Summary: Python client for the kubernetes API. + License: ASL 2.0 + URL: https://pypi.python.org/pypi/kubernetes +@@ -30,6 +30,20 @@ Source0: https://github.com/kubernetes-incubator/client-python/archive/v%{ver + Source1: https://github.com/kubernetes-client/python-base/archive/83ebb9d5fdc0d46bbb2e30afcd8eec42c5da4ad1.tar.gz + BuildArch: noarch + ++Source3: 0001-Verify-Boilerplate-fix.patch ++Source4: 0002-fix-watching-with-a-specified-resource-version.patch ++Source5: 0003-Making-watch-work-with-read_namespaced_pod_log.patch ++Source6: 0004-Don-t-use-break-inside-finally.patch ++Source7: 0005-Remove-all-shebangs-from-Python-modules-and-checker.patch ++Source8: 0006-Fixed-Watch.unmarshal_event-when-data-is-not-a-JSON-.patch ++Source9: 0007-watch-stream-stop-unmarshalling-when-streaming-log.patch ++Source10: 0008-Retry-watch-if-request-expires.patch ++Source11: 0009-Fix-a-Python-2-compatibility-issue.patch ++Source12: 0010-Fixes-codestyle-failures.patch ++Source13: 0011-Fix-Watch-retries-with-410-errors.patch ++Source14: 0012-Fixes-kubernetes-client-python-issue-1047-ResponseNo.patch ++Source15: 0013-quick-fix-of-decoding-error-for-BOOKMARK-event.patch ++ + %if 0%{?with_python2} + %package -n python2-%{library} + Summary: Kubernetes Python Client +@@ -133,11 +147,34 @@ mv python-base-83ebb9d5fdc0d46bbb2e30afcd8eec42c5da4ad1 base + %if 0%{?rhel} == 7 + patch -p1 < %{SOURCE2} + %endif ++ ++# Apply StarlingX patches. ++# The patches are taken from the context of the 'base' directory ++# which is a git submodule. ++# We have to use redirection since we can't run the patches ++# via autosetup due to the above tarball extraction: ++pushd base ++patch -p1 < %{SOURCE3} ++patch -p1 < %{SOURCE4} ++patch -p1 < %{SOURCE5} ++patch -p1 < %{SOURCE6} ++patch -p1 < %{SOURCE7} ++patch -p1 < %{SOURCE8} ++patch -p1 < %{SOURCE9} ++patch -p1 < %{SOURCE10} ++patch -p1 < %{SOURCE11} ++patch -p1 < %{SOURCE12} ++patch -p1 < %{SOURCE13} ++patch -p1 < %{SOURCE14} ++patch -p1 < %{SOURCE15} ++popd + popd + + %build + %if 0%{?with_python2} +-%py2_build ++# NOTE: py2_build macro is called py_build in our loadbuild servers ++# %py2_build ++%py_build + %endif + %if 0%{?with_python3} + %py3_build +@@ -159,7 +196,9 @@ sphinx-build doc/source/ html + + %install + %if 0%{?with_python2} +-%py2_install ++# NOTE: py2_install macro is called py_install in our loadbuild servers ++# %py2_install ++%py_install + cp -pr kubernetes/test %{buildroot}%{python2_sitelib}/%{library}/ + cp -pr kubernetes/e2e_test %{buildroot}%{python2_sitelib}/%{library}/ + %endif +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/meta_patches/PATCH_ORDER b/python/python-kubernetes/centos/meta_patches/PATCH_ORDER new file mode 100644 index 000000000..926ba153e --- /dev/null +++ b/python/python-kubernetes/centos/meta_patches/PATCH_ORDER @@ -0,0 +1 @@ +0001-Include-watch.py-bug-fixes.patch diff --git a/python/python-kubernetes/centos/patches/0001-Verify-Boilerplate-fix.patch b/python/python-kubernetes/centos/patches/0001-Verify-Boilerplate-fix.patch new file mode 100644 index 000000000..6b83785b1 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0001-Verify-Boilerplate-fix.patch @@ -0,0 +1,22 @@ +From d56fdbc0cc33a6c8e4782c93b50c56c889fb3fa3 Mon Sep 17 00:00:00 2001 +From: Neha Yadav +Date: Wed, 5 Dec 2018 22:22:59 +0530 +Subject: [PATCH 01/13] Verify Boilerplate fix + +--- + watch/watch.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/watch/watch.py b/watch/watch.py +index 21899dd..fb4c1ab 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -1,3 +1,5 @@ ++#!/usr/bin/env python ++ + # Copyright 2016 The Kubernetes Authors. + # + # Licensed under the Apache License, Version 2.0 (the "License"); +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0002-fix-watching-with-a-specified-resource-version.patch b/python/python-kubernetes/centos/patches/0002-fix-watching-with-a-specified-resource-version.patch new file mode 100644 index 000000000..215dfb6f3 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0002-fix-watching-with-a-specified-resource-version.patch @@ -0,0 +1,41 @@ +From 3c30a3099336a5976074c18ea61814646689b4a8 Mon Sep 17 00:00:00 2001 +From: Julian Taylor +Date: Sat, 19 Jan 2019 12:38:57 +0100 +Subject: [PATCH 02/13] fix watching with a specified resource version + +The watch code reset the version to the last found in the +response. +When you first list existing objects and then start watching from that +resource version the existing versions are older than the version you +wanted and the watch starts from the wrong version after the first +restart. +This leads to for example already deleted objects ending in the stream +again. + +Fix this by setting the minimum resource version to reset from to the +input resource version. As long as k8s returns all objects in order in +the watch this should work. +We cannot use the integer value of the resource version to order it as +one should be treat the value as opaque. + +Closes https://github.com/kubernetes-client/python/issues/700 +--- + watch/watch.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/watch/watch.py b/watch/watch.py +index 21899dd..a9c315c 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -122,6 +122,8 @@ class Watch(object): + return_type = self.get_return_type(func) + kwargs['watch'] = True + kwargs['_preload_content'] = False ++ if 'resource_version' in kwargs: ++ self.resource_version = kwargs['resource_version'] + + timeouts = ('timeout_seconds' in kwargs) + while True: +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0003-Making-watch-work-with-read_namespaced_pod_log.patch b/python/python-kubernetes/centos/patches/0003-Making-watch-work-with-read_namespaced_pod_log.patch new file mode 100644 index 000000000..db0516091 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0003-Making-watch-work-with-read_namespaced_pod_log.patch @@ -0,0 +1,76 @@ +From 8e6f0435a38e24aac700d9ebac700bdf6138ba8c Mon Sep 17 00:00:00 2001 +From: Mitar +Date: Mon, 15 Oct 2018 23:57:46 -0700 +Subject: [PATCH 03/13] Making watch work with read_namespaced_pod_log. + +Fixes https://github.com/kubernetes-client/python/issues/199. +--- + watch/watch.py | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index bdf24f1..79b2358 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -20,6 +20,7 @@ import pydoc + from kubernetes import client + + PYDOC_RETURN_LABEL = ":return:" ++PYDOC_FOLLOW_PARAM = ":param bool follow:" + + # Removing this suffix from return type name should give us event's object + # type. e.g., if list_namespaces() returns "NamespaceList" type, +@@ -65,7 +66,7 @@ class Watch(object): + self._raw_return_type = return_type + self._stop = False + self._api_client = client.ApiClient() +- self.resource_version = 0 ++ self.resource_version = None + + def stop(self): + self._stop = True +@@ -78,8 +79,17 @@ class Watch(object): + return return_type[:-len(TYPE_LIST_SUFFIX)] + return return_type + ++ def get_watch_argument_name(self, func): ++ if PYDOC_FOLLOW_PARAM in pydoc.getdoc(func): ++ return 'follow' ++ else: ++ return 'watch' ++ + def unmarshal_event(self, data, return_type): +- js = json.loads(data) ++ try: ++ js = json.loads(data) ++ except ValueError: ++ return data + js['raw_object'] = js['object'] + if return_type: + obj = SimpleNamespace(data=json.dumps(js['raw_object'])) +@@ -122,7 +132,7 @@ class Watch(object): + + self._stop = False + return_type = self.get_return_type(func) +- kwargs['watch'] = True ++ kwargs[self.get_watch_argument_name(func)] = True + kwargs['_preload_content'] = False + if 'resource_version' in kwargs: + self.resource_version = kwargs['resource_version'] +@@ -136,9 +146,12 @@ class Watch(object): + if self._stop: + break + finally: +- kwargs['resource_version'] = self.resource_version + resp.close() + resp.release_conn() ++ if self.resource_version is not None: ++ kwargs['resource_version'] = self.resource_version ++ else: ++ break + + if timeouts or self._stop: + break +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0004-Don-t-use-break-inside-finally.patch b/python/python-kubernetes/centos/patches/0004-Don-t-use-break-inside-finally.patch new file mode 100644 index 000000000..7086d63b1 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0004-Don-t-use-break-inside-finally.patch @@ -0,0 +1,26 @@ +From 972a76a83d0133b45db03495b0f9fd05ed2b94a3 Mon Sep 17 00:00:00 2001 +From: Mitar +Date: Wed, 20 Feb 2019 23:56:38 -0800 +Subject: [PATCH 04/13] Don't use break inside finally. + +It swallows exceptions. +--- + watch/watch.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/watch/watch.py b/watch/watch.py +index 79b2358..5966eac 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -151,7 +151,7 @@ class Watch(object): + if self.resource_version is not None: + kwargs['resource_version'] = self.resource_version + else: +- break ++ self._stop = True + + if timeouts or self._stop: + break +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0005-Remove-all-shebangs-from-Python-modules-and-checker.patch b/python/python-kubernetes/centos/patches/0005-Remove-all-shebangs-from-Python-modules-and-checker.patch new file mode 100644 index 000000000..288a1da82 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0005-Remove-all-shebangs-from-Python-modules-and-checker.patch @@ -0,0 +1,31 @@ +From c941d74b3745550fc886ebf20e40725aa4722f5c Mon Sep 17 00:00:00 2001 +From: Oz N Tiram +Date: Tue, 20 Aug 2019 22:25:57 +0200 +Subject: [PATCH 05/13] Remove all shebangs from Python modules and checker + +As discussed, Python modules which aren't intended to be invoked +as scripts should not include a shebang line. + +Update CONTRIBUTING.md and the checker script. +This script now includes a list SKIP_FILES for files that +should not be checked for boilerplate template. +The tests will now fail if a Python module has a shebang line. +Scripts which should have a shebang line and exists in the directory +`hack` can be ignored by adding them to the SKIP_FILES list. +--- + watch/watch.py | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index 5966eac..77b9794 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -1,5 +1,3 @@ +-#!/usr/bin/env python +- + # Copyright 2016 The Kubernetes Authors. + # + # Licensed under the Apache License, Version 2.0 (the "License"); +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0006-Fixed-Watch.unmarshal_event-when-data-is-not-a-JSON-.patch b/python/python-kubernetes/centos/patches/0006-Fixed-Watch.unmarshal_event-when-data-is-not-a-JSON-.patch new file mode 100644 index 000000000..68fbd557a --- /dev/null +++ b/python/python-kubernetes/centos/patches/0006-Fixed-Watch.unmarshal_event-when-data-is-not-a-JSON-.patch @@ -0,0 +1,28 @@ +From f11587d0e3cedf645ba12fe4dfd7971ee7162c9d Mon Sep 17 00:00:00 2001 +From: Alexey Volkov +Date: Thu, 17 Oct 2019 17:40:20 -0700 +Subject: [PATCH 06/13] Fixed Watch.unmarshal_event when data is not a + JSON-serialized object + +Fixes https://github.com/kubernetes-client/python/issues/982 +Fixes https://github.com/kubernetes-client/python/issues/983 +--- + watch/watch.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/watch/watch.py b/watch/watch.py +index 77b9794..ba87de9 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -88,6 +88,8 @@ class Watch(object): + js = json.loads(data) + except ValueError: + return data ++ if not (isinstance(js, dict) and 'object' in js): ++ return data + js['raw_object'] = js['object'] + if return_type: + obj = SimpleNamespace(data=json.dumps(js['raw_object'])) +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0007-watch-stream-stop-unmarshalling-when-streaming-log.patch b/python/python-kubernetes/centos/patches/0007-watch-stream-stop-unmarshalling-when-streaming-log.patch new file mode 100644 index 000000000..2cb3e903a --- /dev/null +++ b/python/python-kubernetes/centos/patches/0007-watch-stream-stop-unmarshalling-when-streaming-log.patch @@ -0,0 +1,54 @@ +From ea11e44daf06e38a9b49c5f8cc41f19447d79bfe Mon Sep 17 00:00:00 2001 +From: Haowei Cai +Date: Fri, 21 Feb 2020 15:19:35 -0800 +Subject: [PATCH 07/13] watch stream: stop unmarshalling when streaming log + +--- + watch/watch.py | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index ba87de9..fe7a924 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -84,12 +84,7 @@ class Watch(object): + return 'watch' + + def unmarshal_event(self, data, return_type): +- try: +- js = json.loads(data) +- except ValueError: +- return data +- if not (isinstance(js, dict) and 'object' in js): +- return data ++ js = json.loads(data) + js['raw_object'] = js['object'] + if return_type: + obj = SimpleNamespace(data=json.dumps(js['raw_object'])) +@@ -132,7 +127,8 @@ class Watch(object): + + self._stop = False + return_type = self.get_return_type(func) +- kwargs[self.get_watch_argument_name(func)] = True ++ watch_arg = self.get_watch_argument_name(func) ++ kwargs[watch_arg] = True + kwargs['_preload_content'] = False + if 'resource_version' in kwargs: + self.resource_version = kwargs['resource_version'] +@@ -142,7 +138,12 @@ class Watch(object): + resp = func(*args, **kwargs) + try: + for line in iter_resp_lines(resp): +- yield self.unmarshal_event(line, return_type) ++ # unmarshal when we are receiving events from watch, ++ # return raw string when we are streaming log ++ if watch_arg == "watch": ++ yield self.unmarshal_event(line, return_type) ++ else: ++ yield line + if self._stop: + break + finally: +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0008-Retry-watch-if-request-expires.patch b/python/python-kubernetes/centos/patches/0008-Retry-watch-if-request-expires.patch new file mode 100644 index 000000000..97af1c691 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0008-Retry-watch-if-request-expires.patch @@ -0,0 +1,81 @@ +From 06e48c585c003742ff42fb1995ec18e85226055e Mon Sep 17 00:00:00 2001 +From: Mitar +Date: Mon, 11 Feb 2019 00:23:39 -0800 +Subject: [PATCH 08/13] Retry watch if request expires. + +--- + watch/watch.py | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index fe7a924..f67dbe4 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -12,6 +12,7 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + ++import http + import json + import pydoc + +@@ -86,7 +87,7 @@ class Watch(object): + def unmarshal_event(self, data, return_type): + js = json.loads(data) + js['raw_object'] = js['object'] +- if return_type: ++ if return_type and js['type'] != 'ERROR': + obj = SimpleNamespace(data=json.dumps(js['raw_object'])) + js['object'] = self._api_client.deserialize(obj, return_type) + if hasattr(js['object'], 'metadata'): +@@ -102,6 +103,14 @@ class Watch(object): + def stream(self, func, *args, **kwargs): + """Watch an API resource and stream the result back via a generator. + ++ Note that watching an API resource can expire. The method tries to ++ resume automatically once from the last result, but if that last result ++ is too old as well, an `ApiException` exception will be thrown with ++ ``code`` 410. In that case you have to recover yourself, probably ++ by listing the API resource to obtain the latest state and then ++ watching from that state on by setting ``resource_version`` to ++ one returned from listing. ++ + :param func: The API function pointer. Any parameter to the function + can be passed after this parameter. + +@@ -134,6 +143,7 @@ class Watch(object): + self.resource_version = kwargs['resource_version'] + + timeouts = ('timeout_seconds' in kwargs) ++ retry_after_410 = False + while True: + resp = func(*args, **kwargs) + try: +@@ -141,7 +151,23 @@ class Watch(object): + # unmarshal when we are receiving events from watch, + # return raw string when we are streaming log + if watch_arg == "watch": +- yield self.unmarshal_event(line, return_type) ++ event = self.unmarshal_event(line, return_type) ++ if isinstance(event, dict) \ ++ and event['type'] == 'ERROR': ++ obj = event['raw_object'] ++ # Current request expired, let's retry, ++ # but only if we have not already retried. ++ if not retry_after_410 and \ ++ obj['code'] == http.HTTPStatus.GONE: ++ retry_after_410 = True ++ break ++ else: ++ reason = "%s: %s" % (obj['reason'], obj['message']) ++ raise client.rest.ApiException(status=obj['code'], ++ reason=reason) ++ else: ++ retry_after_410 = False ++ yield event + else: + yield line + if self._stop: +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0009-Fix-a-Python-2-compatibility-issue.patch b/python/python-kubernetes/centos/patches/0009-Fix-a-Python-2-compatibility-issue.patch new file mode 100644 index 000000000..cc7c3c442 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0009-Fix-a-Python-2-compatibility-issue.patch @@ -0,0 +1,60 @@ +From a54f404366c0800497f8b62122d7be77c143297f Mon Sep 17 00:00:00 2001 +From: Nabarun Pal +Date: Thu, 16 Jul 2020 14:02:12 +0530 +Subject: [PATCH 09/13] Fix a Python 2 compatibility issue + +PR #133 introduces the usage of `http` module for checking the status +code for `GONE` HTTP status. However, this doesn't work in Python 2.7. + +This commit checks if the interpreter is Python 2 and imports the +status code from `httplib` module instead and unifies the approach +to the checks. + +Signed-off-by: Nabarun Pal +--- + watch/watch.py | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index f67dbe4..6410dfa 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -12,9 +12,9 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-import http + import json + import pydoc ++import sys + + from kubernetes import client + +@@ -29,6 +29,15 @@ PYDOC_FOLLOW_PARAM = ":param bool follow:" + TYPE_LIST_SUFFIX = "List" + + ++PY2 = sys.version_info[0] == 2 ++if PY2: ++ import httplib ++ HTTP_STATUS_GONE = httplib.GONE ++else: ++ import http ++ HTTP_STATUS_GONE = http.HTTPStatus.GONE ++ ++ + class SimpleNamespace: + + def __init__(self, **kwargs): +@@ -158,7 +167,7 @@ class Watch(object): + # Current request expired, let's retry, + # but only if we have not already retried. + if not retry_after_410 and \ +- obj['code'] == http.HTTPStatus.GONE: ++ obj['code'] == HTTP_STATUS_GONE: + retry_after_410 = True + break + else: +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0010-Fixes-codestyle-failures.patch b/python/python-kubernetes/centos/patches/0010-Fixes-codestyle-failures.patch new file mode 100644 index 000000000..d33f729b1 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0010-Fixes-codestyle-failures.patch @@ -0,0 +1,31 @@ +From b68ca3055178e31a5d87a0a98780e4987a4d23ae Mon Sep 17 00:00:00 2001 +From: Nabarun Pal +Date: Thu, 16 Jul 2020 14:08:44 +0530 +Subject: [PATCH 10/13] Fixes codestyle failures + +Signed-off-by: Nabarun Pal +--- + watch/watch.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index 6410dfa..3058ed9 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -171,9 +171,10 @@ class Watch(object): + retry_after_410 = True + break + else: +- reason = "%s: %s" % (obj['reason'], obj['message']) +- raise client.rest.ApiException(status=obj['code'], +- reason=reason) ++ reason = "%s: %s" % ( ++ obj['reason'], obj['message']) ++ raise client.rest.ApiException( ++ status=obj['code'], reason=reason) + else: + retry_after_410 = False + yield event +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0011-Fix-Watch-retries-with-410-errors.patch b/python/python-kubernetes/centos/patches/0011-Fix-Watch-retries-with-410-errors.patch new file mode 100644 index 000000000..2ec9985d2 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0011-Fix-Watch-retries-with-410-errors.patch @@ -0,0 +1,46 @@ +From ebea7e343046d7afbbdc0e199294d5c79ae87362 Mon Sep 17 00:00:00 2001 +From: Chris Ayoub +Date: Thu, 25 Feb 2021 00:27:33 -0500 +Subject: [PATCH 11/13] Fix Watch retries with 410 errors + +--- + watch/watch.py | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/watch/watch.py b/watch/watch.py +index 3058ed9..b432778 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -151,7 +151,9 @@ class Watch(object): + if 'resource_version' in kwargs: + self.resource_version = kwargs['resource_version'] + +- timeouts = ('timeout_seconds' in kwargs) ++ # Do not attempt retries if user specifies a timeout. ++ # We want to ensure we are returning within that timeout. ++ disable_retries = ('timeout_seconds' in kwargs) + retry_after_410 = False + while True: + resp = func(*args, **kwargs) +@@ -164,9 +166,9 @@ class Watch(object): + if isinstance(event, dict) \ + and event['type'] == 'ERROR': + obj = event['raw_object'] +- # Current request expired, let's retry, ++ # Current request expired, let's retry, (if enabled) + # but only if we have not already retried. +- if not retry_after_410 and \ ++ if not disable_retries and not retry_after_410 and \ + obj['code'] == HTTP_STATUS_GONE: + retry_after_410 = True + break +@@ -190,5 +192,5 @@ class Watch(object): + else: + self._stop = True + +- if timeouts or self._stop: ++ if self._stop or disable_retries: + break +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0012-Fixes-kubernetes-client-python-issue-1047-ResponseNo.patch b/python/python-kubernetes/centos/patches/0012-Fixes-kubernetes-client-python-issue-1047-ResponseNo.patch new file mode 100644 index 000000000..b95198946 --- /dev/null +++ b/python/python-kubernetes/centos/patches/0012-Fixes-kubernetes-client-python-issue-1047-ResponseNo.patch @@ -0,0 +1,31 @@ +From 90399663f378b33227f723d3f0c1677965b6d96b Mon Sep 17 00:00:00 2001 +From: Darren Hague +Date: Thu, 8 Apr 2021 13:49:46 +0100 +Subject: [PATCH 12/13] Fixes kubernetes-client/python issue 1047 + "ResponseNotChunked from watch" + +In recent versions of K8S (>1.16?), when a `Watch.stream()` call uses a +resource_version which is too old the resulting 410 error is wrapped in JSON +and returned in a non-chunked 200 response. Using `resp.stream()` instead of +`resp.read_chunked()` automatically handles the response being either chunked or +non-chunked. +--- + watch/watch.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/watch/watch.py b/watch/watch.py +index b432778..3bbb770 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -53,7 +53,7 @@ def _find_return_type(func): + + def iter_resp_lines(resp): + prev = "" +- for seg in resp.read_chunked(decode_content=False): ++ for seg in resp.stream(amt=None, decode_content=False): + if isinstance(seg, bytes): + seg = seg.decode('utf8') + seg = prev + seg +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/patches/0013-quick-fix-of-decoding-error-for-BOOKMARK-event.patch b/python/python-kubernetes/centos/patches/0013-quick-fix-of-decoding-error-for-BOOKMARK-event.patch new file mode 100644 index 000000000..17938425b --- /dev/null +++ b/python/python-kubernetes/centos/patches/0013-quick-fix-of-decoding-error-for-BOOKMARK-event.patch @@ -0,0 +1,29 @@ +From 10ae4760b53a917116ae7525a7bbc94f35632cfb Mon Sep 17 00:00:00 2001 +From: Yu Liao +Date: Mon, 12 Apr 2021 17:17:42 -0700 +Subject: [PATCH 13/13] quick fix of decoding error for BOOKMARK event + +--- + watch/watch.py | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/watch/watch.py b/watch/watch.py +index 3bbb770..71fd459 100644 +--- a/watch/watch.py ++++ b/watch/watch.py +@@ -96,7 +96,11 @@ class Watch(object): + def unmarshal_event(self, data, return_type): + js = json.loads(data) + js['raw_object'] = js['object'] +- if return_type and js['type'] != 'ERROR': ++ # BOOKMARK event is treated the same as ERROR for a quick fix of ++ # decoding exception ++ # TODO: make use of the resource_version in BOOKMARK event for more ++ # efficient WATCH ++ if return_type and js['type'] != 'ERROR' and js['type'] != 'BOOKMARK': + obj = SimpleNamespace(data=json.dumps(js['raw_object'])) + js['object'] = self._api_client.deserialize(obj, return_type) + if hasattr(js['object'], 'metadata'): +-- +2.25.1 + diff --git a/python/python-kubernetes/centos/srpm_path b/python/python-kubernetes/centos/srpm_path new file mode 100644 index 000000000..1e85d6453 --- /dev/null +++ b/python/python-kubernetes/centos/srpm_path @@ -0,0 +1 @@ +mirror:Source/python-kubernetes-8.0.0-8.el7.src.rpm