From 213cd83c8aa1909f5a1cdcb026e50b059709853f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 9 Nov 2020 19:28:04 -0500 Subject: [PATCH 01/40] Add Python 3.9 to build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .github/workflows/test.yaml | 2 +- .travis.yml | 4 ++++ setup.py | 1 + tox.ini | 4 ++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 51e315c5fd..4ab95a6c20 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index c3cb704903..24162133cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,10 @@ jobs: env: TOXENV=py38 - python: 3.8 env: TOXENV=py38-functional + - python: 3.9 + env: TOXENV=py39 + - python: 3.9 + env: TOXENV=py39-functional - stage: deploy script: skip deploy: diff --git a/setup.py b/setup.py index 22ec5b69a5..c2db8dcd78 100644 --- a/setup.py +++ b/setup.py @@ -79,5 +79,6 @@ "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", ], ) diff --git a/tox.ini b/tox.ini index 0930582f4b..8ba4c3dd8d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = - py27, py3{5,6,7,8} - py27-functional, py3{5,6,7,8}-functional + py27, py3{5,6,7,8,9} + py27-functional, py3{5,6,7,8,9}-functional [testenv] passenv = TOXENV CI TRAVIS TRAVIS_* From d03558809f1a083634141b3593a87b11fa55539e Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Sat, 14 Nov 2020 02:44:47 +0530 Subject: [PATCH 02/40] Clarify support cycles for the releases temporarily Releases are being fast tracked until we sync with the upstream releases. The older releases will continue to be maintained for that transition period or related upstream version deprecation whichever is later. Signed-off-by: Nabarun Pal --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b27a46c944..6c2335da47 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,8 @@ Kubernetes supports [three minor releases](https://github.com/kubernetes/communi Note: There would be no maintenance for alpha/beta releases except the latest one. +**Exception to the above support rule:** Since we are running behind on releases, we will support Alpha/Beta releases for a greater number of clients until we catch up with the upstream version. + ## Community, Support, Discussion If you have any problem on using the package or any suggestions, please start with reaching the [Kubernetes clients slack channel](https://kubernetes.slack.com/messages/C76GB48RK/), or filing an [issue](https://github.com/kubernetes-client/python/issues) to let us know. You can also reach the maintainers of this project at [SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery), where this project falls under. From cf3dc147d8d82ccaf5b30b320ce8f0d4df20636f Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Sat, 14 Nov 2020 02:48:32 +0530 Subject: [PATCH 03/40] Refactor the format of compatibitility matrix Signed-off-by: Nabarun Pal --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6c2335da47..c8a7e1529f 100644 --- a/README.md +++ b/README.md @@ -80,14 +80,12 @@ All APIs and Models' documentation can be found at the [Generated client's READM client-python gets increased, your code will continue to work with explicitly supported versions of Kubernetes clusters. -#### Compatibility matrix - -| | Kubernetes 1.13 | Kubernetes 1.14 | Kubernetes 1.15 | -|--------------------|-----------------|-----------------|-----------------| -| client-python 9.0 |✓ |+- |+- | -| client-python 10.0 |+- |✓ |+- | -| client-python 11.0 |+- |+- |✓ | -| client-python HEAD |+- |+- |+- | +#### Compatibility matrix of supported client versions + +- [client 9.y.z](https://pypi.org/project/kubernetes/9.0.1/): Kubernetes 1.12 or below (+-), Kubernetes 1.13 (✓), Kubernetes 1.14 or above (+-) +- [client 10.y.z](https://pypi.org/project/kubernetes/10.1.0/): Kubernetes 1.13 or below (+-), Kubernetes 1.14 (✓), Kubernetes 1.14 or above (+-) +- [client 11.y.z](https://pypi.org/project/kubernetes/11.0.0/): Kubernetes 1.14 or below (+-), Kubernetes 1.15 (✓), Kubernetes 1.16 or above (+-) +- [client 12.y.z](https://pypi.org/project/kubernetes/12.0.1/): Kubernetes 1.15 or below (+-), Kubernetes 1.16 (✓), Kubernetes 1.17 or above (+-) Key: From 3890d6d7df483ae66551d8edeae2a49b55f64353 Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Nov 2020 03:18:40 +0530 Subject: [PATCH 04/40] Add v17.14.0a1 to the compatibility matrix Signed-off-by: Nabarun Pal --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c8a7e1529f..a4fa178bb8 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ supported versions of Kubernetes clusters. - [client 10.y.z](https://pypi.org/project/kubernetes/10.1.0/): Kubernetes 1.13 or below (+-), Kubernetes 1.14 (✓), Kubernetes 1.14 or above (+-) - [client 11.y.z](https://pypi.org/project/kubernetes/11.0.0/): Kubernetes 1.14 or below (+-), Kubernetes 1.15 (✓), Kubernetes 1.16 or above (+-) - [client 12.y.z](https://pypi.org/project/kubernetes/12.0.1/): Kubernetes 1.15 or below (+-), Kubernetes 1.16 (✓), Kubernetes 1.17 or above (+-) +- [client 17.y.z](https://pypi.org/project/kubernetes/17.14.0a1/): Kubernetes 1.16 or below (+-), Kubernetes 1.17 (✓), Kubernetes 1.18 or above (+-) Key: From f0dbe3897017ae2cb7e89dde3358816e9aa2a37b Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Tue, 17 Nov 2020 03:28:22 +0530 Subject: [PATCH 05/40] Add a note about the change in client versioning schema Signed-off-by: Nabarun Pal --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index a4fa178bb8..6b4fcfe7d3 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ supported versions of Kubernetes clusters. - [client 12.y.z](https://pypi.org/project/kubernetes/12.0.1/): Kubernetes 1.15 or below (+-), Kubernetes 1.16 (✓), Kubernetes 1.17 or above (+-) - [client 17.y.z](https://pypi.org/project/kubernetes/17.14.0a1/): Kubernetes 1.16 or below (+-), Kubernetes 1.17 (✓), Kubernetes 1.18 or above (+-) +> See [here](#homogenizing-the-kubernetes-python-client-versions) for an explaination of why there is no v13-v16 release. + Key: * `✓` Exactly the same features / API objects in both client-python and the Kubernetes @@ -123,6 +125,8 @@ between client-python versions. | 12.0 | Kubernetes main repo, 1.16 branch | ✓ | | 17.0 Alpha/Beta | Kubernetes main repo, 1.17 branch | ✓ | +> See [here](#homogenizing-the-kubernetes-python-client-versions) for an explaination of why there is no v13-v16 release. + Key: * `✓` Changes in main Kubernetes repo are manually ([should be automated](https://github.com/kubernetes-client/python/issues/177)) published to client-python when they are available. @@ -134,6 +138,12 @@ Note: There would be no maintenance for alpha/beta releases except the latest on **Exception to the above support rule:** Since we are running behind on releases, we will support Alpha/Beta releases for a greater number of clients until we catch up with the upstream version. +## Homogenizing the Kubernetes Python Client versions + +The client releases v12 and before following a versioning schema where the major version was 4 integer positions behind the Kubernetes minor on which the client is based on. For example, v12.0.0 is based on Kubernetes v1.16, v11.0.0 is based on Kubernetes v1.15 and so on. + +This created a lot of confusion tracking two different version numbers for each client release. It was decided to homogenize the version scheme starting from the Kubernetes Python client based on Kubernetes v1.17. The versioning scheme of the client from this release would be vY.Z.P where Y and Z are the Kubernetes minor and patch release numbers from Kubernets v1.Y.Z and P is the client specific patch release numbers to accomodate changes and fixes done specifically to the client. For more details, refer [this issue](https://github.com/kubernetes-client/python/issues/1244). + ## Community, Support, Discussion If you have any problem on using the package or any suggestions, please start with reaching the [Kubernetes clients slack channel](https://kubernetes.slack.com/messages/C76GB48RK/), or filing an [issue](https://github.com/kubernetes-client/python/issues) to let us know. You can also reach the maintainers of this project at [SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery), where this project falls under. From 3ffa47edba00ffbb119bf86af8a3c16d6ddeb90c Mon Sep 17 00:00:00 2001 From: Nabarun Pal Date: Fri, 13 Nov 2020 18:18:50 +0530 Subject: [PATCH 06/40] Update CHANGELOG with v17.14.0a1 Signed-off-by: Nabarun Pal --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 715967adde..fc0535b602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ -# v17.0.0-snapshot +# v17.14.0a1 -Kubernetes API Version: 1.17.13 +Kubernetes API Version: 1.17.14 **Important Information:** From fd405e813dde7e54f33495b9c8f3efc48b9128ea Mon Sep 17 00:00:00 2001 From: "Patrick J. McNerthney" Date: Sun, 22 Nov 2020 10:15:47 -1000 Subject: [PATCH 07/40] Implement back end raw port test container using python. --- kubernetes/e2e_test/port_server.py | 41 +++++++++++++++++ kubernetes/e2e_test/test_client.py | 71 +++++++++++++++++++++++++----- 2 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 kubernetes/e2e_test/port_server.py diff --git a/kubernetes/e2e_test/port_server.py b/kubernetes/e2e_test/port_server.py new file mode 100644 index 0000000000..75d28528be --- /dev/null +++ b/kubernetes/e2e_test/port_server.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +import select +import socketserver +import sys +import threading +import time + + +class PortServer: + def __init__(self, port): + self.port = port + self.server = socketserver.ThreadingTCPServer(('0.0.0.0', port), self.handler) + self.server.daemon_threads = True + self.thread = threading.Thread(target=self.server.serve_forever, + name='Port %s Server' % port) + self.thread.daemon = True + self.thread.start() + + + def handler(self, request, address, server): + threading.current_thread().name = 'Port %s Handler' % self.port + rlist = [request] + echo = b'' + while True: + r, w, _x = select.select(rlist, [request] if echo else [], []) + if r: + data = request.recv(1024) + if not data: + break + echo += data + if w: + echo = echo[request.send(echo):] + + +if __name__ == '__main__': + ports = [] + for port in sys.argv[1:]: + ports.append(PortServer(int(port))) + time.sleep(10 * 60) + diff --git a/kubernetes/e2e_test/test_client.py b/kubernetes/e2e_test/test_client.py index 00e46a3776..4d367fa34c 100644 --- a/kubernetes/e2e_test/test_client.py +++ b/kubernetes/e2e_test/test_client.py @@ -13,6 +13,7 @@ # under the License. import json +import os import select import socket import time @@ -167,17 +168,64 @@ def test_portforward_raw(self): client = api_client.ApiClient(configuration=self.config) api = core_v1_api.CoreV1Api(client) + with open(os.path.join(os.path.dirname(__file__), 'port_server.py')) as fh: + port_server_py = fh.read() name = 'portforward-raw-' + short_uuid() - pod_manifest = manifest_with_command( - name, - ' '.join(( - '((while true;do nc -l -p 1234 -e /bin/cat; done)&);', - '((while true;do nc -l -p 1235 -e /bin/cat; done)&);', - 'sleep 60', - )) + resp = api.create_namespaced_config_map( + body={ + 'apiVersion': 'v1', + 'kind': 'ConfigMap', + 'metadata': { + 'name': name, + }, + 'data': { + 'port-server.py': port_server_py, + } + }, + namespace='default', + ) + resp = api.create_namespaced_pod( + body={ + 'apiVersion': 'v1', + 'kind': 'Pod', + 'metadata': { + 'name': name + }, + 'spec': { + 'containers': [ + { + 'name': 'port-server', + 'image': 'python', + 'command': [ + '/opt/port-server.py', '1234', '1235', + ], + 'volumeMounts': [ + { + 'name': 'port-server', + 'mountPath': '/opt', + 'readOnly': True, + }, + ], + 'startupProbe': { + 'tcpSocket': { + 'port': 1234, + }, + }, + }, + ], + 'volumes': [ + { + 'name': 'port-server', + 'configMap': { + 'name': name, + 'defaultMode': 0o777, + }, + }, + ], + }, + }, + namespace='default', ) - resp = api.create_namespaced_pod(body=pod_manifest, - namespace='default') self.assertEqual(name, resp.metadata.name) self.assertTrue(resp.status.phase) @@ -189,6 +237,7 @@ def test_portforward_raw(self): if resp.status.phase != 'Pending': break time.sleep(1) + self.assertEqual(resp.status.phase, 'Running') pf = portforward(api.connect_get_namespaced_pod_portforward, name, 'default', @@ -251,8 +300,8 @@ def test_portforward_raw(self): self.assertIsNone(pf.error(1234)) self.assertIsNone(pf.error(1235)) - resp = api.delete_namespaced_pod(name=name, body={}, - namespace='default') + resp = api.delete_namespaced_pod(name=name, namespace='default') + resp = api.delete_namespaced_config_map(name=name, namespace='default') def test_portforward_http(self): client = api_client.ApiClient(configuration=self.config) From d860dc5259bf3491c7711622606eb48244cade4e Mon Sep 17 00:00:00 2001 From: Arumugam Date: Wed, 2 Dec 2020 11:09:47 +0000 Subject: [PATCH 08/40] Adding Power support(ppc64le) with ci and testing to the project for architecture independent --- .travis.yml | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 24162133cb..a218cc4c24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: python -dist: xenial +dist: bionic services: - docker @@ -13,9 +13,16 @@ jobs: include: - stage: verify-tag python: 3.7 + arch: ppc64le script: > [ "v$(python -c 'from scripts.constants import CLIENT_VERSION; print(CLIENT_VERSION)')" == "${TRAVIS_TAG}" ] && [[ "${TRAVIS_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(([ab]|dev|rc)[0-9]+)?$ ]] + - stage: verify-tag + python: 3.7 + script: > + [ "v$(python -c 'from scripts.constants import CLIENT_VERSION; print(CLIENT_VERSION)')" == "${TRAVIS_TAG}" ] && + [[ "${TRAVIS_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(([ab]|dev|rc)[0-9]+)?$ ]] + - stage: test python: 2.7 env: TOXENV=update-pycodestyle @@ -60,6 +67,47 @@ jobs: repo: kubernetes-client/python distributions: sdist bdist_wheel + - stage: test + python: 2.7 + env: TOXENV=update-pycodestyle + arch: ppc64le + - python: 3.7 + env: TOXENV=docs + arch: ppc64le + - python: 2.7 + env: TOXENV=coverage,codecov + arch: ppc64le + - python: 2.7 + env: TOXENV=py27 + arch: ppc64le + - python: 3.5 + env: TOXENV=py35 + arch: ppc64le + - python: 3.6 + env: TOXENV=py36 + arch: ppc64le + - python: 3.7 + env: TOXENV=py37 + arch: ppc64le + - python: 3.8 + env: TOXENV=py38 + - python: 3.9 + env: TOXENV=py39 + arch: ppc64le + - stage: deploy + script: skip + arch: ppc64le + deploy: + provider: pypi + user: __token__ + password: + secure: gY5Rixj7mWHC9XP5qV5DfWGdX4ZVwCEUElnQA2OeIg235I3eMBqRFM4Q/SKwAG2DzgIWNKsXXVQsZHp7BAjWFMFVQloiU7zohuBRToJUim9U1RaqAjUIr4OU7JPtXenAl5zyyBdywvJiG8UZ4wmt1DBYtdpozQvOwDXvOxNTmElKh5mfDhiSsipmFr2198NtIhiRVC+CZliZsi6osUkt+G6yl9CW+SJU3otgzdaS+VBP26HO0kWHMJiDKvQoIl/Q50IqJUWieFhCLh7lSV71VNVEmM4bMcYK8cAv3zMZHo6REKHF7xrF5tzYMXqpmEGt6L798d2H4BISr6BIlYgiYCatjyE9hxih9iBzGs0XaGUUFD8u1iuzOQI76a5dapG/DixQrGD2o9Gn/Qw6Zp9USIuKZSWUn5hSobwxJUKVNy+afpaJNQUb2W9Hj+jMXAnBDodCzo3nu+QF8GN72cmk3uqVyKUVABtI4kNe3qcEx3DyKfoh7aqJrgydeaRwESKuZ41l5CA+vqXSbbNW8z1MYDYgVdwEyRFsLg6aQk5pPsxuiILaaGy13TUndhuC+GuKcW6wCDf6WpUAwwGAF8+sz4hZ1pfSUdE3F8nfDBW3Bv+G9cB/cKkWJ2vOd9httRrvir8qUc/xPP5aW4pacnfNCQ04Iep/k4PCAdYJDtVGhCY= + skip_existing: true + on: + tags: true + repo: kubernetes-client/python + distributions: sdist bdist_wheel + stages: - name: verify-tag if: (tag is present) and (type = push) From 5be9c893b3c6d15f9c4d4bfb5d70f7ab6c6c3f5b Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Tue, 5 Jan 2021 09:53:49 -0800 Subject: [PATCH 09/40] update python-base submodule --- kubernetes/base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/base b/kubernetes/base index 2da2b981ca..b002110430 160000 --- a/kubernetes/base +++ b/kubernetes/base @@ -1 +1 @@ -Subproject commit 2da2b981ca806b25487ad92d01a2164815c18517 +Subproject commit b0021104307c99bac5b2a7e353df21d864f85809 From 3b95adc8f36f442fc7065949b5c7801de50c07e3 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Tue, 5 Jan 2021 09:58:42 -0800 Subject: [PATCH 10/40] configmap-e2e: use labels --- kubernetes/e2e_test/test_client.py | 3 ++- kubernetes/e2e_test/test_watch.py | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kubernetes/e2e_test/test_client.py b/kubernetes/e2e_test/test_client.py index 4d367fa34c..af71b455a3 100644 --- a/kubernetes/e2e_test/test_client.py +++ b/kubernetes/e2e_test/test_client.py @@ -443,6 +443,7 @@ def test_configmap_apis(self): "apiVersion": "v1", "metadata": { "name": name, + "labels": {"e2e-tests": "true"}, }, "data": { "config.json": "{\"command\":\"/usr/bin/mysqld_safe\"}", @@ -466,7 +467,7 @@ def test_configmap_apis(self): resp = api.delete_namespaced_config_map( name=name, body={}, namespace='default') - resp = api.list_namespaced_config_map('default', pretty=True) + resp = api.list_namespaced_config_map('default', pretty=True, label_selector="e2e-tests=true") self.assertEqual([], resp.items) def test_node_apis(self): diff --git a/kubernetes/e2e_test/test_watch.py b/kubernetes/e2e_test/test_watch.py index 3530b8bbdf..134e9c26fd 100644 --- a/kubernetes/e2e_test/test_watch.py +++ b/kubernetes/e2e_test/test_watch.py @@ -32,6 +32,7 @@ def config_map_with_value(name, value): "kind": "ConfigMap", "metadata": { "name": name, + "labels": {"e2e-tests": "true"}, }, "data": { "key": value, @@ -57,7 +58,7 @@ def test_watch_configmaps(self): body=configmap_a, namespace='default') # list all configmaps and extract the resource version - resp = api.list_namespaced_config_map('default') + resp = api.list_namespaced_config_map('default', label_selector="e2e-tests=true") rv = resp.metadata.resource_version # create another configmap @@ -73,7 +74,7 @@ def test_watch_configmaps(self): # delete all configmaps api.delete_collection_namespaced_config_map( - namespace='default') + namespace='default', label_selector="e2e-tests=true") w = watch.Watch() # expect to observe all events happened after the initial LIST @@ -83,7 +84,8 @@ def test_watch_configmaps(self): for event in w.stream(api.list_namespaced_config_map, namespace='default', resource_version=rv, - timeout_seconds=5): + timeout_seconds=5, + label_selector="e2e-tests=true"): self.assertEqual(event['type'], expect[i]) # Kubernetes doesn't guarantee the order of the two objects # being deleted From 90931037ac2041f4029bf532e1b3d28f6053ddd1 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Mon, 11 Jan 2021 13:04:18 -0800 Subject: [PATCH 11/40] pod e2e: wait for the default service account to be created --- kubernetes/e2e_test/test_client.py | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/kubernetes/e2e_test/test_client.py b/kubernetes/e2e_test/test_client.py index af71b455a3..82d77eaf0d 100644 --- a/kubernetes/e2e_test/test_client.py +++ b/kubernetes/e2e_test/test_client.py @@ -19,15 +19,22 @@ import time import unittest import uuid +import six from kubernetes.client import api_client from kubernetes.client.api import core_v1_api from kubernetes.e2e_test import base from kubernetes.stream import stream, portforward from kubernetes.stream.ws_client import ERROR_CHANNEL +from kubernetes.client.rest import ApiException import six.moves.urllib.request as urllib_request +if six.PY3: + from http import HTTPStatus +else: + import httplib + def short_uuid(): id = str(uuid.uuid4()) return id[-12:] @@ -65,6 +72,27 @@ def test_pod_apis(self): name = 'busybox-test-' + short_uuid() pod_manifest = manifest_with_command(name, "while true;do date;sleep 5; done") + + # wait for the default service account to be created + timeout = time.time() + 30 + while True: + if time.time() > timeout: + print('timeout waiting for default service account creation') + break + try: + resp = api.read_namespaced_service_account(name='default', + namespace='default') + except ApiException as e: + if (six.PY3 and e.status != HTTPStatus.NOT_FOUND) or ( + six.PY3 is False and e.status != httplib.NOT_FOUND): + print('error: %s' % e) + self.fail(msg="unexpected error getting default service account") + print('default service not found yet: %s' % e) + time.sleep(1) + continue + self.assertEqual('default', resp.metadata.name) + break + resp = api.create_namespaced_pod(body=pod_manifest, namespace='default') self.assertEqual(name, resp.metadata.name) @@ -130,6 +158,28 @@ def test_exit_code(self): name = 'busybox-test-' + short_uuid() pod_manifest = manifest_with_command(name, "while true;do date;sleep 5; done") + + # wait for the default service account to be created + timeout = time.time() + 30 + while True: + if time.time() > timeout: + print('timeout waiting for default service account creation') + break + + try: + resp = api.read_namespaced_service_account(name='default', + namespace='default') + except ApiException as e: + if (six.PY3 and e.status != HTTPStatus.NOT_FOUND) or ( + six.PY3 is False and e.status != httplib.NOT_FOUND): + print('error: %s' % e) + self.fail(msg="unexpected error getting default service account") + print('default service not found yet: %s' % e) + time.sleep(1) + continue + self.assertEqual('default', resp.metadata.name) + break + resp = api.create_namespaced_pod(body=pod_manifest, namespace='default') self.assertEqual(name, resp.metadata.name) From bd26d85e84c1dfe7ec30e6e3a639940ddf0a9dda Mon Sep 17 00:00:00 2001 From: Sumant Date: Thu, 28 Jan 2021 18:50:23 -0500 Subject: [PATCH 12/40] Enable leaderelection --- kubernetes/__init__.py | 1 + kubernetes/leaderelection | 1 + 2 files changed, 2 insertions(+) create mode 100644 kubernetes/leaderelection diff --git a/kubernetes/__init__.py b/kubernetes/__init__.py index e8a0e2d633..1ff790d7d2 100644 --- a/kubernetes/__init__.py +++ b/kubernetes/__init__.py @@ -22,3 +22,4 @@ import kubernetes.watch import kubernetes.stream import kubernetes.utils +import kubernetes.leaderelection diff --git a/kubernetes/leaderelection b/kubernetes/leaderelection new file mode 100644 index 0000000000..30e0567f73 --- /dev/null +++ b/kubernetes/leaderelection @@ -0,0 +1 @@ +base/leaderelection \ No newline at end of file From 6eb9f7d9dca964e3c1111e72c4acc7bebe9745d0 Mon Sep 17 00:00:00 2001 From: Sumant Date: Mon, 1 Feb 2021 17:03:44 -0500 Subject: [PATCH 13/40] Adding module leaderelection from base --- kubernetes/base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/base b/kubernetes/base index b002110430..4bf72d7f0d 160000 --- a/kubernetes/base +++ b/kubernetes/base @@ -1 +1 @@ -Subproject commit b0021104307c99bac5b2a7e353df21d864f85809 +Subproject commit 4bf72d7f0dda1ecfb4a2e02f70cf9bcc700641a4 From a6655d6ebab7a1f47314ab63e921e1c9b8f4860f Mon Sep 17 00:00:00 2001 From: Invictus17 Date: Thu, 4 Feb 2021 21:23:37 -0500 Subject: [PATCH 14/40] Adding symbolic link to base/leaderelection --- kubernetes/leaderelection | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 120000 kubernetes/leaderelection diff --git a/kubernetes/leaderelection b/kubernetes/leaderelection deleted file mode 100644 index 30e0567f73..0000000000 --- a/kubernetes/leaderelection +++ /dev/null @@ -1 +0,0 @@ -base/leaderelection \ No newline at end of file diff --git a/kubernetes/leaderelection b/kubernetes/leaderelection new file mode 120000 index 0000000000..30e0567f73 --- /dev/null +++ b/kubernetes/leaderelection @@ -0,0 +1 @@ +base/leaderelection \ No newline at end of file From d7584c538c3c88f32624ce57ea48ad747d7757b8 Mon Sep 17 00:00:00 2001 From: Soumitra Kumar Date: Fri, 5 Feb 2021 15:17:53 -0800 Subject: [PATCH 15/40] Added kubernetes.leaderelection in packages list to fix No module named 'kubernetes.leaderelection' error To reproduce: Make sure to create a file outside of checked out python repo directory. $ cat hello_k8s.py import kubernetes kubernetes.config.load_kube_config() k8s = kubernetes.client.CoreV1Api() print("Listing pods with their IPs:") ret = k8s.list_pod_for_all_namespaces(watch=False) for i in ret.items: print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name)) python hello_k8s.py Traceback (most recent call last): File "hello_k8s.py", line 1, in import kubernetes File "", line 259, in load_module File "anaconda3/lib/python3.8/site-packages/kubernetes-17.0.0_snapshot-py3.8.egg/kubernetes/__init__.py", line 25, in ModuleNotFoundError: No module named 'kubernetes.leaderelection' --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ab7abf171d..e5bafcf8f5 100644 --- a/setup.py +++ b/setup.py @@ -61,7 +61,7 @@ 'kubernetes.watch', 'kubernetes.client.api', 'kubernetes.stream', 'kubernetes.client.models', 'kubernetes.utils', 'kubernetes.client.apis', - 'kubernetes.dynamic'], + 'kubernetes.dynamic', 'kubernetes.leaderelection'], include_package_data=True, long_description="Python client for kubernetes http://kubernetes.io/", classifiers=[ From fdd2e14c609ccdf6c62b1c14c65c19d086b1864a Mon Sep 17 00:00:00 2001 From: Chris Ayoub Date: Thu, 25 Feb 2021 18:56:33 -0500 Subject: [PATCH 16/40] Update base submodule --- kubernetes/base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/base b/kubernetes/base index 4bf72d7f0d..060cac10e5 160000 --- a/kubernetes/base +++ b/kubernetes/base @@ -1 +1 @@ -Subproject commit 4bf72d7f0dda1ecfb4a2e02f70cf9bcc700641a4 +Subproject commit 060cac10e53169c904e0d50b7448233829019e35 From 9a0713b2b2e4d49a22f5f673492a9bf5fd828f27 Mon Sep 17 00:00:00 2001 From: Jonas Lindner <42033762+jonasdlindner@users.noreply.github.com> Date: Mon, 1 Mar 2021 14:19:59 +0100 Subject: [PATCH 17/40] Fix Typo in examples/remote_cluster.py --- examples/remote_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/remote_cluster.py b/examples/remote_cluster.py index b72b39b4e9..a09e7ed9bb 100644 --- a/examples/remote_cluster.py +++ b/examples/remote_cluster.py @@ -20,7 +20,7 @@ def main(): - # Define the barer token we are going to use to authenticate. + # Define the bearer token we are going to use to authenticate. # See here to create the token: # https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/ aToken = "" From 44fe8bf1c202081ae25dad30197880e95691bbc4 Mon Sep 17 00:00:00 2001 From: abhiabhi94 <13880786+abhiabhi94@users.noreply.github.com> Date: Wed, 10 Mar 2021 08:08:04 +0530 Subject: [PATCH 18/40] Refactor utils - move regex compilation to the top of the module to enable caching. --- kubernetes/utils/create_from_yaml.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kubernetes/utils/create_from_yaml.py b/kubernetes/utils/create_from_yaml.py index 390131a5af..35111387df 100644 --- a/kubernetes/utils/create_from_yaml.py +++ b/kubernetes/utils/create_from_yaml.py @@ -20,6 +20,9 @@ from kubernetes import client +UPPER_FOLLOWED_BY_LOWER_RE = re.compile('(.)([A-Z][a-z]+)') +LOWER_OR_NUM_FOLLOWED_BY_UPPER_RE = re.compile('([a-z0-9])([A-Z])') + def create_from_yaml( k8s_client, @@ -155,8 +158,8 @@ def create_from_yaml_single_item( k8s_api = getattr(client, fcn_to_call)(k8s_client) # Replace CamelCased action_type into snake_case kind = yml_object["kind"] - kind = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', kind) - kind = re.sub('([a-z0-9])([A-Z])', r'\1_\2', kind).lower() + kind = UPPER_FOLLOWED_BY_LOWER_RE.sub(r'\1_\2', kind) + kind = LOWER_OR_NUM_FOLLOWED_BY_UPPER_RE.sub(r'\1_\2', kind).lower() # Expect the user to create namespaced objects more often if hasattr(k8s_api, "create_namespaced_{0}".format(kind)): # Decide which namespace we are going to put the object in, From b3e51c4820d9249fa2edcd2196e453acaebc0853 Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Tue, 23 Mar 2021 10:24:58 +0530 Subject: [PATCH 19/40] examples/pod_exec.py: fix example Use get_default_copy() API with configuration. --- examples/pod_exec.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/pod_exec.py b/examples/pod_exec.py index 6a4bf6bdb5..1e2d9195a6 100644 --- a/examples/pod_exec.py +++ b/examples/pod_exec.py @@ -117,8 +117,11 @@ def exec_commands(api_instance): def main(): config.load_kube_config() - c = Configuration() - c.assert_hostname = False + try: + c = Configuration().get_default_copy() + except AttributeError: + c = Configuration() + c.assert_hostname = False Configuration.set_default(c) core_v1 = core_v1_api.CoreV1Api() From b78db01baf038ba3ba7dd668f7ef3f98ab65ba22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 03:02:11 +0000 Subject: [PATCH 20/40] Bump actions/setup-python from v2.1.4 to v2.2.2 Bumps [actions/setup-python](https://github.com/actions/setup-python) from v2.1.4 to v2.2.2. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.1.4...dc73133d4da04e56a135ae2246682783cc7c7cb6) Signed-off-by: dependabot[bot] --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4ab95a6c20..5813b7dac5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -15,7 +15,7 @@ jobs: with: submodules: true - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.1.4 + uses: actions/setup-python@v2.2.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From 7b9e77bfd212c8e4386f284b486be1b1c0ba2946 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Mon, 19 Apr 2021 21:03:44 -0700 Subject: [PATCH 21/40] add update-submodule script --- devel/submodules.md | 4 +- scripts/update-submodule.sh | 88 +++++++++++++++++++++++++++++++++++++ scripts/util/changelog.sh | 77 ++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 2 deletions(-) create mode 100755 scripts/update-submodule.sh create mode 100755 scripts/util/changelog.sh diff --git a/devel/submodules.md b/devel/submodules.md index 68ca4eee0e..bec58b8618 100644 --- a/devel/submodules.md +++ b/devel/submodules.md @@ -23,7 +23,7 @@ git submodule update --init If you changed [kubernetes-client/python-base](https://github.com/kubernetes-client/python-base) and want to pull your changes into this repo run this command: ```bash -git submodule update --remote +scripts/update-submodule.sh ``` -Once updated, you should create a new PR to commit changes to the repository. +Create a commit "generated python-base update" and send a PR to the main repo. diff --git a/scripts/update-submodule.sh b/scripts/update-submodule.sh new file mode 100755 index 0000000000..267dcb41eb --- /dev/null +++ b/scripts/update-submodule.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Update python-base submodule and collect release notes. +# Usage: +# scripts/update-submodule.sh +# +# Create a commit "generated python-base update" and send a PR to the main repo. +# NOTE: not all python-base changes are user-facing, and you may want to remove +# some of the non-user-facing release notes from CHANGELOG.md. + +set -o errexit +set -o nounset +set -o pipefail + +repo_root="$(git rev-parse --show-toplevel)" +declare -r repo_root +cd "${repo_root}" + +source scripts/util/changelog.sh + +# TODO(roycaihw): make the script send a PR by default (standalone mode), and +# have an option to make the script reusable by other release automations. +TARGET_RELEASE=${TARGET_RELEASE:-"v$(grep "^CLIENT_VERSION = \"" scripts/constants.py | sed "s/CLIENT_VERSION = \"//g" | sed "s/\"//g")"} +SUBMODULE_SECTION=${SUBMODULE_SECTION:-"\*\*Submodule Change:\*\*"} + +# update submodule +git submodule update --remote +pulls=$(git diff --submodule | egrep -o "^ > Merge pull request #[0-9]+" | sed 's/ > Merge pull request #//g') + +# download release notes +release_notes="" +submodule_repo="kubernetes-client/python-base" +echo "Downloading release notes from submodule repo." +for pull in ${pulls}; do + pull_url="https://github.com/$submodule_repo/pull/${pull}" + echo "+++ Downloading python-base patch to /tmp/${pull}.patch" + curl -o "/tmp/${pull}.patch" -sSL "${pull_url}.patch" + subject=$(grep -m 1 "^Subject" "/tmp/${pull}.patch" | sed -e 's/Subject: \[PATCH//g' | sed 's/.*] //') + pull_uid="$submodule_repo#${pull}" + release_note="- ${subject} [${pull_uid}](${pull_url})\n" + release_notes+=${release_note} + # remove the patch file from /tmp + rm -f "/tmp/${pull}.patch" +done + +# find the place in the changelog that we want to edit +line_to_edit="1" +if util::changelog::has_release $TARGET_RELEASE; then + # the target release exists + release_first_line=$(util::changelog::find_release_start $TARGET_RELEASE) + release_last_line=$(util::changelog::find_release_end $TARGET_RELEASE) + if util::changelog::has_section_in_range "$SUBMODULE_SECTION" "$release_first_line" "$release_last_line"; then + # prepend to existing section + line_to_edit=$(($(util::changelog::find_section_in_range "$SUBMODULE_SECTION" "$release_first_line" "$release_last_line")+1)) + release_notes=${release_notes::-2} + else + # add a new section + line_to_edit=$(($(util::changelog::find_release_start $TARGET_RELEASE)+4)) + release_notes="$SUBMODULE_SECTION\n$release_notes" + fi +else + # add a new release + # TODO(roycaihw): ideally a parent script updates the generated client and + # fills in the Kubernetes API Version based on the OpenAPI spec. + release_notes="# $TARGET_RELEASE\n\nKubernetes API Version: TBD\n\n$SUBMODULE_SECTION\n$release_notes" +fi + +echo "Writing the following release notes to CHANGELOG line $line_to_edit:" +echo -e $release_notes + +# update changelog +sed -i "${line_to_edit}i${release_notes}" CHANGELOG.md + +echo "Successfully updated CHANGELOG for submodule." diff --git a/scripts/util/changelog.sh b/scripts/util/changelog.sh new file mode 100755 index 0000000000..a17d977743 --- /dev/null +++ b/scripts/util/changelog.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +changelog="$(git rev-parse --show-toplevel)/CHANGELOG.md" + +function util::changelog::has_release { + local release=$1 + return $(grep -q "^# $release$" $changelog) +} + +# find_release_start returns the number of the first line of the given release +function util::changelog::find_release_start { + local release=$1 + echo $(grep -n "^# $release$" $changelog | head -1 | cut -d: -f1) +} + +# find_release_end returns the number of the last line of the given release +function util::changelog::find_release_end { + local release=$1 + + local release_start=$(util::changelog::find_release_start $release) + local next_release_index=0 + local releases=($(grep -n "^# " $changelog | cut -d: -f1)) + for i in "${!releases[@]}"; do + if [[ "${releases[$i]}" = "$release_start" ]]; then + next_release_index=$((i+1)) + break + fi + done + # return the line before the next release + echo $((${releases[${next_release_index}]}-1)) +} + +# has_section returns if the given section exists between start and end +function util::changelog::has_section_in_range { + local section="$1" + local start=$2 + local end=$3 + + local lines=($(grep -n "$section" "$changelog" | cut -d: -f1)) + for i in "${!lines[@]}"; do + if [[ ${lines[$i]} -ge $start && ${lines[$i]} -le $end ]]; then + return 0 + fi + done + return 1 +} + +# find_section returns the number of the first line of the given section +function util::changelog::find_section_in_range { + local section="$1" + local start=$2 + local end=$3 + + local line="0" + local lines=($(grep -n "$section" "$changelog" | cut -d: -f1)) + for i in "${!lines[@]}"; do + if [[ ${lines[$i]} -ge $start && ${lines[$i]} -le $end ]]; then + line=${lines[$i]} + break + fi + done + echo $line +} From d86a47de26036d7aa2e2b12000d815bce68bb341 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Tue, 20 Apr 2021 11:01:16 -0700 Subject: [PATCH 22/40] add PR template copied from k/k. We should add the same template to python-base --- .github/PULL_REQUEST_TEMPLATE.md | 72 ++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..f6af35b429 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,72 @@ + + +#### What type of PR is this? + + + +#### What this PR does / why we need it: + +#### Which issue(s) this PR fixes: + +Fixes # + +#### Special notes for your reviewer: + +#### Does this PR introduce a user-facing change? + +```release-note + +``` + +#### Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.: + + +```docs + +``` From 83d294e2b0119127eeff2fefa8342987517d7d08 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Tue, 20 Apr 2021 16:56:30 -0700 Subject: [PATCH 23/40] fixup! add update-submodule script --- devel/submodules.md | 2 +- scripts/update-submodule.sh | 73 +++++++++++++------------------------ scripts/util/changelog.sh | 32 ++++++++++++++++ 3 files changed, 58 insertions(+), 49 deletions(-) diff --git a/devel/submodules.md b/devel/submodules.md index bec58b8618..6edca72752 100644 --- a/devel/submodules.md +++ b/devel/submodules.md @@ -26,4 +26,4 @@ If you changed [kubernetes-client/python-base](https://github.com/kubernetes-cli scripts/update-submodule.sh ``` -Create a commit "generated python-base update" and send a PR to the main repo. +After the script finishes, please create a commit "generated python-base update" and send a PR to this repository. diff --git a/scripts/update-submodule.sh b/scripts/update-submodule.sh index 267dcb41eb..86aa5a4b5a 100755 --- a/scripts/update-submodule.sh +++ b/scripts/update-submodule.sh @@ -14,13 +14,18 @@ # See the License for the specific language governing permissions and # limitations under the License. + # Update python-base submodule and collect release notes. # Usage: -# scripts/update-submodule.sh # -# Create a commit "generated python-base update" and send a PR to the main repo. -# NOTE: not all python-base changes are user-facing, and you may want to remove -# some of the non-user-facing release notes from CHANGELOG.md. +# $ scripts/update-submodule.sh +# +# # To update the release notes for a specific release (e.g. v18.17.0a1): +# $ TARGET_RELEASE="v18.17.0a1" scripts/update-submodule.sh +# +# After the script finishes, please create a commit "generated python-base update" +# and send a PR to this repository. +# TODO(roycaihw): make the script send a PR set -o errexit set -o nounset @@ -31,58 +36,30 @@ declare -r repo_root cd "${repo_root}" source scripts/util/changelog.sh +go get k8s.io/release/cmd/release-notes -# TODO(roycaihw): make the script send a PR by default (standalone mode), and -# have an option to make the script reusable by other release automations. TARGET_RELEASE=${TARGET_RELEASE:-"v$(grep "^CLIENT_VERSION = \"" scripts/constants.py | sed "s/CLIENT_VERSION = \"//g" | sed "s/\"//g")"} -SUBMODULE_SECTION=${SUBMODULE_SECTION:-"\*\*Submodule Change:\*\*"} # update submodule git submodule update --remote -pulls=$(git diff --submodule | egrep -o "^ > Merge pull request #[0-9]+" | sed 's/ > Merge pull request #//g') # download release notes -release_notes="" -submodule_repo="kubernetes-client/python-base" -echo "Downloading release notes from submodule repo." -for pull in ${pulls}; do - pull_url="https://github.com/$submodule_repo/pull/${pull}" - echo "+++ Downloading python-base patch to /tmp/${pull}.patch" - curl -o "/tmp/${pull}.patch" -sSL "${pull_url}.patch" - subject=$(grep -m 1 "^Subject" "/tmp/${pull}.patch" | sed -e 's/Subject: \[PATCH//g' | sed 's/.*] //') - pull_uid="$submodule_repo#${pull}" - release_note="- ${subject} [${pull_uid}](${pull_url})\n" - release_notes+=${release_note} - # remove the patch file from /tmp - rm -f "/tmp/${pull}.patch" -done - -# find the place in the changelog that we want to edit -line_to_edit="1" -if util::changelog::has_release $TARGET_RELEASE; then - # the target release exists - release_first_line=$(util::changelog::find_release_start $TARGET_RELEASE) - release_last_line=$(util::changelog::find_release_end $TARGET_RELEASE) - if util::changelog::has_section_in_range "$SUBMODULE_SECTION" "$release_first_line" "$release_last_line"; then - # prepend to existing section - line_to_edit=$(($(util::changelog::find_section_in_range "$SUBMODULE_SECTION" "$release_first_line" "$release_last_line")+1)) - release_notes=${release_notes::-2} - else - # add a new section - line_to_edit=$(($(util::changelog::find_release_start $TARGET_RELEASE)+4)) - release_notes="$SUBMODULE_SECTION\n$release_notes" - fi -else - # add a new release - # TODO(roycaihw): ideally a parent script updates the generated client and - # fills in the Kubernetes API Version based on the OpenAPI spec. - release_notes="# $TARGET_RELEASE\n\nKubernetes API Version: TBD\n\n$SUBMODULE_SECTION\n$release_notes" -fi - -echo "Writing the following release notes to CHANGELOG line $line_to_edit:" -echo -e $release_notes +start_sha=$(git diff | grep "^-Subproject commit " | sed 's/-Subproject commit //g') +end_sha=$(git diff | grep "^+Subproject commit " | sed 's/+Subproject commit //g') +output="/tmp/python-base-relnote.md" +release-notes --dependencies=false --org kubernetes-client --repo python-base --start-sha $start_sha --end-sha $end_sha --output $output +sed -i 's/(\[\#/(\[kubernetes-client\/python-base\#/g' $output # update changelog -sed -i "${line_to_edit}i${release_notes}" CHANGELOG.md +IFS_backup=$IFS +IFS=$'\n' +sections=($(grep "^### " $output)) +IFS=$IFS_backup +for section in "${sections[@]}"; do + # ignore section titles and empty lines; replace newline with liternal "\n" + release_notes=$(sed -n "/$section/,/###/{/###/!p}" $output | sed -n "{/^$/!p}" | sed ':a;N;$!ba;s/\n/\\n/g') + util::changelog::write_changelog "$TARGET_RELEASE" "$section" "$release_notes" +done +rm -f $output echo "Successfully updated CHANGELOG for submodule." diff --git a/scripts/util/changelog.sh b/scripts/util/changelog.sh index a17d977743..672b823369 100755 --- a/scripts/util/changelog.sh +++ b/scripts/util/changelog.sh @@ -75,3 +75,35 @@ function util::changelog::find_section_in_range { done echo $line } + +# write_changelog writes release_notes to section in target_release +function util::changelog::write_changelog { + local target_release="$1" + local section="$2" + local release_notes="$3" + + # find the place in the changelog that we want to edit + local line_to_edit="1" + if util::changelog::has_release $target_release; then + # the target release exists + release_first_line=$(util::changelog::find_release_start $target_release) + release_last_line=$(util::changelog::find_release_end $target_release) + if util::changelog::has_section_in_range "$section" "$release_first_line" "$release_last_line"; then + # prepend to existing section + line_to_edit=$(($(util::changelog::find_section_in_range "$section" "$release_first_line" "$release_last_line")+1)) + else + # add a new section; plus 4 so that the section is placed below "Kubernetes API Version" + line_to_edit=$(($(util::changelog::find_release_start $target_release)+4)) + release_notes="$section\n$release_notes\n" + fi + else + # add a new release + release_notes="# $target_release\n\nKubernetes API Version: To Be Updated\n\n$section\n$release_notes\n" + fi + + echo "Writing the following release notes to CHANGELOG line $line_to_edit:" + echo -e $release_notes + + # update changelog + sed -i "${line_to_edit}i${release_notes}" $changelog +} From 7309a45b77a92db2d4fb5d6e46a26538163c3e79 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Mon, 26 Apr 2021 11:51:37 -0700 Subject: [PATCH 24/40] configure the openapi-generator version --- scripts/update-client.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/update-client.sh b/scripts/update-client.sh index 506038429a..69ede4ecdc 100755 --- a/scripts/update-client.sh +++ b/scripts/update-client.sh @@ -21,6 +21,9 @@ set -o errexit set -o nounset set -o pipefail +# The openapi-generator version used by this client +export OPENAPI_GENERATOR_COMMIT="v4.3.0" + SCRIPT_ROOT=$(dirname "${BASH_SOURCE}") CLIENT_ROOT="${SCRIPT_ROOT}/../kubernetes" CLIENT_VERSION=$(python "${SCRIPT_ROOT}/constants.py" CLIENT_VERSION) From 68aeb30ae8f7396e4aa9e6ad46ae32e4c4bd4772 Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Tue, 27 Apr 2021 19:39:14 +0530 Subject: [PATCH 25/40] Fix CRD manifest yaml --- examples/custom_object.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/custom_object.py b/examples/custom_object.py index 55e359f5bf..98234cb28c 100644 --- a/examples/custom_object.py +++ b/examples/custom_object.py @@ -29,6 +29,19 @@ - name: v1 served: true storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + cronSpec: + type: string + image: + type: string + replicas: + type: integer scope: Namespaced names: plural: crontabs From 0e376546134fdab98a678ec055c164d45555ee70 Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Tue, 27 Apr 2021 21:04:42 +0530 Subject: [PATCH 26/40] simplify & enhance the node_labels.py example --- examples/node_labels.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/examples/node_labels.py b/examples/node_labels.py index 22ac3197ad..70936eec0e 100644 --- a/examples/node_labels.py +++ b/examples/node_labels.py @@ -13,16 +13,16 @@ # limitations under the License. """ -Changes the labels of the "minikube" node. Adds the label "foo" with value -"bar" and will overwrite the "foo" label if it already exists. Removes the -label "baz". +This example demonstrates the following: + - Get a list of all the cluster nodes + - Iterate through each node list item + - Add or overwirite label "foo" with the value "bar" + - Remove the label "baz" + - Return the list of node with updated labels """ -from pprint import pprint - from kubernetes import client, config - def main(): config.load_kube_config() @@ -35,10 +35,16 @@ def main(): "baz": None} } } - - api_response = api_instance.patch_node("minikube", body) - - pprint(api_response) + + # Creating a list of cluster nodes + node_list = api_instance.list_node() + + print("%s\t\t%s" % ("NAME", "LABELS")) + + # Patching the node labels + for node in node_list.items: + api_response = api_instance.patch_node(node.metadata.name, body) + print("%s\t%s" % (node.metadata.name, node.metadata.labels)) if __name__ == '__main__': From adac2e07062afe5639b6fd62616665725cfa8c1b Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Tue, 27 Apr 2021 22:42:51 +0530 Subject: [PATCH 27/40] improve comments --- examples/node_labels.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/node_labels.py b/examples/node_labels.py index 70936eec0e..a4038d1a98 100644 --- a/examples/node_labels.py +++ b/examples/node_labels.py @@ -36,7 +36,7 @@ def main(): } } - # Creating a list of cluster nodes + # Listing the cluster nodes node_list = api_instance.list_node() print("%s\t\t%s" % ("NAME", "LABELS")) From 41d331f990d661f71275758335a912059442ef92 Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 07:12:02 +0530 Subject: [PATCH 28/40] fix whitespaces --- examples/node_labels.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/node_labels.py b/examples/node_labels.py index a4038d1a98..7089b5acf4 100644 --- a/examples/node_labels.py +++ b/examples/node_labels.py @@ -23,6 +23,7 @@ from kubernetes import client, config + def main(): config.load_kube_config() @@ -37,8 +38,7 @@ def main(): } # Listing the cluster nodes - node_list = api_instance.list_node() - + node_list = api_instance.list_node() print("%s\t\t%s" % ("NAME", "LABELS")) # Patching the node labels From b5d41cb3eb9438ad90db3f2d4a0b376be63a4e81 Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 07:37:07 +0530 Subject: [PATCH 29/40] fix whitspaces --- examples/node_labels.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/node_labels.py b/examples/node_labels.py index 7089b5acf4..462ff9868c 100644 --- a/examples/node_labels.py +++ b/examples/node_labels.py @@ -38,9 +38,9 @@ def main(): } # Listing the cluster nodes - node_list = api_instance.list_node() + node_list = api_instance.list_node() + print("%s\t\t%s" % ("NAME", "LABELS")) - # Patching the node labels for node in node_list.items: api_response = api_instance.patch_node(node.metadata.name, body) From fca1765fa57dfe047b74594883048ee2a8f473dc Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 19:57:05 +0530 Subject: [PATCH 30/40] Create cluster_scoped_custom_object.py --- examples/cluster_scoped_custom_object.py | 147 +++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 examples/cluster_scoped_custom_object.py diff --git a/examples/cluster_scoped_custom_object.py b/examples/cluster_scoped_custom_object.py new file mode 100644 index 0000000000..d951736a2c --- /dev/null +++ b/examples/cluster_scoped_custom_object.py @@ -0,0 +1,147 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Uses a Custom Resource Definition (CRD) to create a custom object, in this case +a CronTab. This example use an example CRD from this tutorial: +https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + +Apply the following yaml manifest to create a cluster-scoped CustomResourceDefinition (CRD) + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: crontabs.stable.example.com +spec: + group: stable.example.com + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + cronSpec: + type: string + image: + type: string + replicas: + type: integer + scope: Cluster + names: + plural: crontabs + singular: crontab + kind: CronTab + shortNames: + - ct +""" + +from pprint import pprint + +from kubernetes import client, config + + +def main(): + config.load_kube_config() + + api = client.CustomObjectsApi() + + # definition of custom resource + test_resource = { + "apiVersion": "stable.example.com/v1", + "kind": "CronTab", + "metadata": {"name": "test-crontab"}, + "spec": {"cronSpec": "* * * * */5", "image": "my-awesome-cron-image"}, + } + + # patch to update the `spec.cronSpec` field + cronspec_patch = { + "spec": {"cronSpec": "* * * * */15", "image": "my-awesome-cron-image"} + } + + # patch to add the `metadata.labels` field + metadata_label_patch = { + "metadata": { + "labels": { + "foo": "bar", + } + } + } + + # create a cluster scoped resource + created_resource = api.create_cluster_custom_object( + group="stable.example.com", + version="v1", + plural="crontabs", + body=test_resource, + ) + + # get the cluster scoped resource + resource = api.get_cluster_custom_object( + group="stable.example.com", + version="v1", + name="test-crontab", + plural="crontabs", + ) + print("%s\t\t%s" % ("NAME", "SCHEDULE")) + print( + "%s\t%s\n" % + (resource["metadata"]["name"], + resource["spec"]["cronSpec"])) + + # patch the `spec.cronSpec` field of the custom resource + patched_resource = api.patch_cluster_custom_object( + group="stable.example.com", + version="v1", + plural="crontabs", + name="test-crontab", + body=cronspec_patch, + ) + print("%s\t\t%s" % ("NAME", "PATCHED_SCHEDULE")) + print( + "%s\t%s\n" % + (patched_resource["metadata"]["name"], + patched_resource["spec"]["cronSpec"])) + + # patch the `metadata.labels` field of the custom resource + patched_resource = api.patch_cluster_custom_object( + group="stable.example.com", + version="v1", + plural="crontabs", + name="test-crontab", + body=metadata_label_patch, + ) + print("%s\t\t%s" % ("NAME", "PATCHED_LABELS")) + print( + "%s\t%s\n" % + (patched_resource["metadata"]["name"], + patched_resource["metadata"]["labels"])) + + # delete the custom resource "test-crontab" + api.delete_cluster_custom_object( + group="stable.example.com", + version="v1", + name="test-crontab", + plural="crontabs", + body=client.V1DeleteOptions(), + ) + print("Resource `test-crontab` deleted!") + + +if __name__ == "__main__": + main() From 60e8c895a5ca0fe639739cfd8708564eb357f53b Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 22:09:40 +0530 Subject: [PATCH 31/40] Update node_labels.py --- examples/node_labels.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/node_labels.py b/examples/node_labels.py index 462ff9868c..f71c8126e5 100644 --- a/examples/node_labels.py +++ b/examples/node_labels.py @@ -36,10 +36,10 @@ def main(): "baz": None} } } - + # Listing the cluster nodes node_list = api_instance.list_node() - + print("%s\t\t%s" % ("NAME", "LABELS")) # Patching the node labels for node in node_list.items: From 3b54f4caa666db1e0695413a196991074ec13464 Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 22:12:17 +0530 Subject: [PATCH 32/40] Update cluster_scoped_custom_object.py --- examples/cluster_scoped_custom_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cluster_scoped_custom_object.py b/examples/cluster_scoped_custom_object.py index d951736a2c..9926a9e223 100644 --- a/examples/cluster_scoped_custom_object.py +++ b/examples/cluster_scoped_custom_object.py @@ -68,7 +68,7 @@ def main(): "metadata": {"name": "test-crontab"}, "spec": {"cronSpec": "* * * * */5", "image": "my-awesome-cron-image"}, } - + # patch to update the `spec.cronSpec` field cronspec_patch = { "spec": {"cronSpec": "* * * * */15", "image": "my-awesome-cron-image"} From cc66bc12747f40bf8b3edc22571444af4854d1af Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 22:50:22 +0530 Subject: [PATCH 33/40] correct copyright year to 2021 --- examples/cluster_scoped_custom_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cluster_scoped_custom_object.py b/examples/cluster_scoped_custom_object.py index 9926a9e223..4a1e46d162 100644 --- a/examples/cluster_scoped_custom_object.py +++ b/examples/cluster_scoped_custom_object.py @@ -1,4 +1,4 @@ -# Copyright 2019 The Kubernetes Authors. +# Copyright 2021 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From af4ea4bfbe5e0290fd77685a82106a211d61d17a Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 23:12:45 +0530 Subject: [PATCH 34/40] add more log messages --- examples/cluster_scoped_custom_object.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/cluster_scoped_custom_object.py b/examples/cluster_scoped_custom_object.py index 4a1e46d162..02b9430bf2 100644 --- a/examples/cluster_scoped_custom_object.py +++ b/examples/cluster_scoped_custom_object.py @@ -90,6 +90,7 @@ def main(): plural="crontabs", body=test_resource, ) + print("[INFO] Custom resource `test-crontab` created!\n") # get the cluster scoped resource resource = api.get_cluster_custom_object( @@ -98,7 +99,7 @@ def main(): name="test-crontab", plural="crontabs", ) - print("%s\t\t%s" % ("NAME", "SCHEDULE")) + print("%s\t\t%s" % ("NAME", "CRON-SPEC")) print( "%s\t%s\n" % (resource["metadata"]["name"], @@ -112,7 +113,8 @@ def main(): name="test-crontab", body=cronspec_patch, ) - print("%s\t\t%s" % ("NAME", "PATCHED_SCHEDULE")) + print("[INFO] Custom resource `test-crontab` patched to update the cronSpec schedule!\n") + print("%s\t\t%s" % ("NAME", "PATCHED-CRON-SPEC")) print( "%s\t%s\n" % (patched_resource["metadata"]["name"], @@ -126,6 +128,7 @@ def main(): name="test-crontab", body=metadata_label_patch, ) + print("[INFO] Custom resource `test-crontab` patched to apply new metadata labels!\n") print("%s\t\t%s" % ("NAME", "PATCHED_LABELS")) print( "%s\t%s\n" % @@ -140,7 +143,7 @@ def main(): plural="crontabs", body=client.V1DeleteOptions(), ) - print("Resource `test-crontab` deleted!") + print("[INFO] Custom resource `test-crontab` deleted!") if __name__ == "__main__": From f7a4ad98802501d3fbe26ccf84d83075fd6906df Mon Sep 17 00:00:00 2001 From: Priyanka Saggu Date: Wed, 28 Apr 2021 23:23:09 +0530 Subject: [PATCH 35/40] correct `custom object` to `custom resource (CR)` --- examples/cluster_scoped_custom_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cluster_scoped_custom_object.py b/examples/cluster_scoped_custom_object.py index 02b9430bf2..d9a5c139dd 100644 --- a/examples/cluster_scoped_custom_object.py +++ b/examples/cluster_scoped_custom_object.py @@ -13,7 +13,7 @@ # limitations under the License. """ -Uses a Custom Resource Definition (CRD) to create a custom object, in this case +Uses a Custom Resource Definition (CRD) to create a Custom Resource (CR), in this case a CronTab. This example use an example CRD from this tutorial: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ From 684544e53e5c7d7462d54ec349ace30516346732 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Thu, 29 Apr 2021 11:20:40 -0700 Subject: [PATCH 36/40] detect OS X sed and fail client generation script --- scripts/update-client.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/update-client.sh b/scripts/update-client.sh index 69ede4ecdc..f27ca60d4f 100755 --- a/scripts/update-client.sh +++ b/scripts/update-client.sh @@ -24,6 +24,22 @@ set -o pipefail # The openapi-generator version used by this client export OPENAPI_GENERATOR_COMMIT="v4.3.0" +# OS X sed doesn't support "--version". This way we can tell if OS X sed is +# used. +if ! sed --version &>/dev/null; then + # OS X sed and GNU sed aren't compatible with backup flag "-i". Namely + # sed -i ... - does not work on OS X + # sed -i'' ... - does not work on certain OS X versions + # sed -i '' ... - does not work on GNU + echo ">>> OS X sed detected, which may be incompatible with this script. Please install and use GNU sed instead: + $ brew install gnu-sed + $ brew info gnu-sed + # Find the path to the installed gnu-sed and add it to your PATH. The default + # is: + # PATH=\"/Users/\$USER/homebrew/opt/gnu-sed/libexec/gnubin:\$PATH\"" + exit 1 +fi + SCRIPT_ROOT=$(dirname "${BASH_SOURCE}") CLIENT_ROOT="${SCRIPT_ROOT}/../kubernetes" CLIENT_VERSION=$(python "${SCRIPT_ROOT}/constants.py" CLIENT_VERSION) From 9182d09457e681b187448f934eaac1045a9b962a Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Thu, 29 Apr 2021 11:41:39 -0700 Subject: [PATCH 37/40] apply-hotfixes: use commits from upstream repo instead of a forked repo --- scripts/apply-hotfixes.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/apply-hotfixes.sh b/scripts/apply-hotfixes.sh index bf866d7564..4d84203c44 100755 --- a/scripts/apply-hotfixes.sh +++ b/scripts/apply-hotfixes.sh @@ -38,7 +38,7 @@ fi # UPDATE: The commit being cherry-picked is updated since the the client generated in 1adaaecd0879d7315f48259ad8d6cbd66b835385 # differs from the initial hotfix # Ref: https://github.com/kubernetes-client/python/pull/995/commits/9959273625b999ae9a8f0679c4def2ee7d699ede -git cherry-pick -n a138dcbb7a9da972402a847ce982b027e0224e60 +git cherry-pick -n 9959273625b999ae9a8f0679c4def2ee7d699ede if [ $? -eq 0 ] then echo Succesfully patched changes for custom client behavior @@ -51,7 +51,7 @@ fi # Patching commits for enabling from kubernetes import apis # UPDATE: The commit being cherry-picked is updated to include both the commits as one # Ref: https://github.com/kubernetes-client/python/blob/0976d59d6ff206f2f428cabc7a6b7b1144843b2a/kubernetes/client/apis/__init__.py -git cherry-pick -n 228a29a982aee922831c3af4fef66a7846ce4bb8 +git cherry-pick -n 56ab983036bcb5c78eee91483c1e610da69216d1 if [ $? -eq 0 ] then echo Succesfully patched changes for enabling from kubernetes import apis From 67f9c7a97081b4526470cad53576bc3b71fa6fcc Mon Sep 17 00:00:00 2001 From: jonasdlindner Date: Thu, 29 Apr 2021 22:17:17 +0200 Subject: [PATCH 38/40] examples: comment improvement in remote_cluster.py and deployment_create.py --- examples/deployment_create.py | 4 ++++ examples/remote_cluster.py | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/deployment_create.py b/examples/deployment_create.py index ba13440ff8..e17af3b5c9 100644 --- a/examples/deployment_create.py +++ b/examples/deployment_create.py @@ -12,6 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +""" +Creates a deployment using AppsV1Api from file nginx-deployment.yaml. +""" + from os import path import yaml diff --git a/examples/remote_cluster.py b/examples/remote_cluster.py index a09e7ed9bb..84ebeb4f64 100644 --- a/examples/remote_cluster.py +++ b/examples/remote_cluster.py @@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This example demonstrate communication with a remote Kube cluster from a -# server outside of the cluster without kube client installed on it. -# The communication is secured with the use of Bearer token. +""" +This example demonstrates the communication between a remote cluster and a +server outside the cluster without kube client installed on it. +The communication is secured with the use of Bearer token. +""" from kubernetes import client, config From 9248a900557ea474779e01d9782c2179b17e8afd Mon Sep 17 00:00:00 2001 From: Yash Kumar Singh Date: Thu, 29 Apr 2021 09:44:24 +0530 Subject: [PATCH 39/40] Removed the custom_object.py file and and added namespaced_custom_object.py --- ..._object.py => namespaced_custom_object.py} | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) rename examples/{custom_object.py => namespaced_custom_object.py} (82%) diff --git a/examples/custom_object.py b/examples/namespaced_custom_object.py similarity index 82% rename from examples/custom_object.py rename to examples/namespaced_custom_object.py index 98234cb28c..6ed8175992 100644 --- a/examples/custom_object.py +++ b/examples/namespaced_custom_object.py @@ -17,7 +17,7 @@ a CronTab. This example use an example CRD from this tutorial: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ -The following yaml manifest has to be applied first: +The following yaml manifest has to be applied first for namespaced scoped CRD: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -72,6 +72,11 @@ def main(): } } + # patch to update the `spec.cronSpec` field + patch_body = { + "spec": {"cronSpec": "* * * * */10", "image": "my-awesome-cron-image"} + } + # create the resource api.create_namespaced_custom_object( group="stable.example.com", @@ -93,6 +98,18 @@ def main(): print("Resource details:") pprint(resource) + # patch the namespaced custom object to update the `spec.cronSpec` field + patch_resource = api.patch_namespaced_custom_object( + group="stable.example.com", + version="v1", + name="my-new-cron-object", + namespace="default", + plural="crontabs", + body=patch_body, + ) + print("Resource details:") + pprint(patch_resource) + # delete it api.delete_namespaced_custom_object( group="stable.example.com", From b53d54fdddd83cedfc5f42369dceadfb9f3a37d1 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Fri, 30 Apr 2021 11:01:58 -0700 Subject: [PATCH 40/40] changelog for pulling master and corresponding submodule changes --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc0535b602..38a555ab3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +# v17.17.0b1 + +Kubernetes API Version: 1.17.17 + +Changelog since v17.14.0a1: + +**New Feature:** +- Add Python 3.9 to build [kubernetes-client/python#1311](https://github.com/kubernetes-client/python/pull/1311) +- Enable leaderelection [kubernetes-client/python#1363](https://github.com/kubernetes-client/python/pull/1363) + +**Bug Fix:** +- fix: load cache error when CacheDecoder object is not callable [kubernetes-client/python-base#226](https://github.com/kubernetes-client/python-base/pull/226) +- raise exception when an empty config file is passed to load_kube_config [kubernetes-client/python-base#223](https://github.com/kubernetes-client/python-base/pull/223) +- Fix bug with Watch and 410 retries [kubernetes-client/python-base#227](https://github.com/kubernetes-client/python-base/pull/227) + # v17.14.0a1 Kubernetes API Version: 1.17.14