diff --git a/.github/workflows/e2e-master.yaml b/.github/workflows/e2e-master.yaml index 8a523157d5..53e06dc528 100644 --- a/.github/workflows/e2e-master.yaml +++ b/.github/workflows/e2e-master.yaml @@ -30,7 +30,7 @@ jobs: # as we sync with Kubernetes upstream config: .github/workflows/kind-configs/cluster-1.18.yaml - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/e2e-release-11.0.yaml b/.github/workflows/e2e-release-11.0.yaml index b182be65f4..7244a938c4 100644 --- a/.github/workflows/e2e-release-11.0.yaml +++ b/.github/workflows/e2e-release-11.0.yaml @@ -30,7 +30,7 @@ jobs: # as we sync with Kubernetes upstream config: .github/workflows/kind-configs/cluster-1.15.yaml - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/e2e-release-12.0.yaml b/.github/workflows/e2e-release-12.0.yaml index 7ec467c36e..6c5110ea4b 100644 --- a/.github/workflows/e2e-release-12.0.yaml +++ b/.github/workflows/e2e-release-12.0.yaml @@ -30,7 +30,7 @@ jobs: # as we sync with Kubernetes upstream config: .github/workflows/kind-configs/cluster-1.16.yaml - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/e2e-release-17.0.yaml b/.github/workflows/e2e-release-17.0.yaml index 5294b42180..f0844814cc 100644 --- a/.github/workflows/e2e-release-17.0.yaml +++ b/.github/workflows/e2e-release-17.0.yaml @@ -30,7 +30,7 @@ jobs: # as we sync with Kubernetes upstream config: .github/workflows/kind-configs/cluster-1.17.yaml - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/e2e-release-18.0.yaml b/.github/workflows/e2e-release-18.0.yaml index 9fbc0b0a0f..a54bb52c27 100644 --- a/.github/workflows/e2e-release-18.0.yaml +++ b/.github/workflows/e2e-release-18.0.yaml @@ -30,7 +30,7 @@ jobs: # as we sync with Kubernetes upstream config: .github/workflows/kind-configs/cluster-1.18.yaml - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f83553260e..57c2bd81ba 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -4,18 +4,20 @@ on: [ push, pull_request ] jobs: build: - runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ["3.6", "3.7", "3.8", "3.10"] + include: + - python-version: "3.9" + use_coverage: 'coverage' steps: - uses: actions/checkout@v2 with: submodules: true - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 + uses: actions/setup-python@v2.3.2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -31,5 +33,18 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Install Tox and any other packages run: pip install tox - - name: Run Tox + + - name: Test without coverage + if: "! matrix.use_coverage" run: tox -e py # Run tox using the version of Python in `PATH` + + - name: Test with coverage + if: "matrix.use_coverage" + run: tox -e py-coverage + + - name: Upload coverage to Codecov + if: "matrix.use_coverage" + uses: codecov/codecov-action@v2 + with: + fail_ci_if_error: true + verbose: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd8e4ab3a..71614dd686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# v22.6.0 + +Kubernetes API Version: v1.22.6 + +### Bug or Regression +- Notable feature additions for async creation of Custom resources using dynamic Client (#1697, @venukarnati92) + +### Feature +- Add `utils.create_from_directory` for creating all yaml files in a directory (#1683, @dingyiyi0226) + # v22.6.0b1 Kubernetes API Version: v1.22.6 diff --git a/README.md b/README.md index 2edae1c6f4..3c39518e4e 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,8 @@ between client-python versions. | 20.0 | Kubernetes main repo, 1.20 branch | ✓ | | 21.0 Alpha/Beta | Kubernetes main repo, 1.21 branch | ✗ | | 21.0 | Kubernetes main repo, 1.21 branch | ✓ | -| 22.0 Alpha/Beta | Kubernetes main repo, 1.22 branch | ✓ | +| 22.0 Alpha/Beta | Kubernetes main repo, 1.22 branch | ✗ | +| 22.0 | Kubernetes main repo, 1.22 branch | ✓ | > See [here](#homogenizing-the-kubernetes-python-client-versions) for an explanation of why there is no v13-v16 release. diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..f1cc869733 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,6 @@ +# reference: https://docs.codecov.io/docs/codecovyml-reference +coverage: + status: + patch: true + project: false +comment: false diff --git a/kubernetes/README.md b/kubernetes/README.md index 68402a873f..5dfcf3ed10 100644 --- a/kubernetes/README.md +++ b/kubernetes/README.md @@ -4,7 +4,7 @@ No description provided (generated by Openapi Generator https://github.com/opena This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: - API version: release-1.22 -- Package version: 22.6.0b1 +- Package version: 22.6.0 - Build package: org.openapitools.codegen.languages.PythonClientCodegen ## Requirements. diff --git a/kubernetes/__init__.py b/kubernetes/__init__.py index 6e0de133d1..59441980da 100644 --- a/kubernetes/__init__.py +++ b/kubernetes/__init__.py @@ -14,7 +14,7 @@ __project__ = 'kubernetes' # The version is auto-updated. Please do not edit. -__version__ = "22.6.0b1" +__version__ = "22.6.0" import kubernetes.client import kubernetes.config diff --git a/kubernetes/base/dynamic/client.py b/kubernetes/base/dynamic/client.py index a81039b891..9927b0c1c0 100644 --- a/kubernetes/base/dynamic/client.py +++ b/kubernetes/base/dynamic/client.py @@ -267,7 +267,7 @@ def request(self, method, path, body=None, **params): # Authentication setting auth_settings = ['BearerToken'] - return self.client.call_api( + api_response = self.client.call_api( path, method.upper(), path_params, @@ -281,6 +281,10 @@ def request(self, method, path, body=None, **params): _preload_content=False, _return_http_data_only=params.get('_return_http_data_only', True) ) + if params.get('async_req'): + return api_response.get() + else: + return api_response def validate(self, definition, version=None, strict=False): """validate checks a kubernetes resource definition diff --git a/kubernetes/base/dynamic/test_client.py b/kubernetes/base/dynamic/test_client.py index c31270bcb8..ce05c5094c 100644 --- a/kubernetes/base/dynamic/test_client.py +++ b/kubernetes/base/dynamic/test_client.py @@ -135,6 +135,121 @@ def test_cluster_custom_resources(self): changeme_api = client.resources.get( api_version='apps.example.com/v1', kind='ClusterChangeMe') + def test_async_namespaced_custom_resources(self): + client = DynamicClient(api_client.ApiClient(configuration=self.config)) + + with self.assertRaises(ResourceNotFoundError): + changeme_api = client.resources.get( + api_version='apps.example.com/v1', kind='ChangeMe') + + crd_api = client.resources.get( + api_version='apiextensions.k8s.io/v1beta1', + kind='CustomResourceDefinition') + + name = 'changemes.apps.example.com' + + crd_manifest = { + 'apiVersion': 'apiextensions.k8s.io/v1beta1', + 'kind': 'CustomResourceDefinition', + 'metadata': { + 'name': name, + }, + 'spec': { + 'group': 'apps.example.com', + 'names': { + 'kind': 'ChangeMe', + 'listKind': 'ChangeMeList', + 'plural': 'changemes', + 'singular': 'changeme', + }, + 'scope': 'Namespaced', + 'version': 'v1', + 'subresources': { + 'status': {} + } + } + } + async_resp = crd_api.create(crd_manifest, async_req=True) + + self.assertEqual(name, async_resp.metadata.name) + self.assertTrue(async_resp.status) + + async_resp = crd_api.get( + name=name, + async_req=True + ) + self.assertEqual(name, async_resp.metadata.name) + self.assertTrue(async_resp.status) + + try: + changeme_api = client.resources.get( + api_version='apps.example.com/v1', kind='ChangeMe') + except ResourceNotFoundError: + # Need to wait a sec for the discovery layer to get updated + time.sleep(2) + changeme_api = client.resources.get( + api_version='apps.example.com/v1', kind='ChangeMe') + + async_resp = changeme_api.get(async_req=True) + self.assertEqual(async_resp.items, []) + + changeme_name = 'custom-resource' + short_uuid() + changeme_manifest = { + 'apiVersion': 'apps.example.com/v1', + 'kind': 'ChangeMe', + 'metadata': { + 'name': changeme_name, + }, + 'spec': {} + } + + async_resp = changeme_api.create(body=changeme_manifest, namespace='default', async_req=True) + self.assertEqual(async_resp.metadata.name, changeme_name) + + async_resp = changeme_api.get(name=changeme_name, namespace='default', async_req=True) + self.assertEqual(async_resp.metadata.name, changeme_name) + + changeme_manifest['spec']['size'] = 3 + async_resp = changeme_api.patch( + body=changeme_manifest, + namespace='default', + content_type='application/merge-patch+json', + async_req=True + ) + self.assertEqual(async_resp.spec.size, 3) + + async_resp = changeme_api.get(name=changeme_name, namespace='default', async_req=True) + self.assertEqual(async_resp.spec.size, 3) + + async_resp = changeme_api.get(namespace='default', async_req=True) + self.assertEqual(len(async_resp.items), 1) + + async_resp = changeme_api.get(async_req=True) + self.assertEqual(len(async_resp.items), 1) + + async_resp = changeme_api.delete( + name=changeme_name, + namespace='default', + async_req=True + ) + + async_resp = changeme_api.get(namespace='default', async_req=True) + self.assertEqual(len(async_resp.items), 0) + + async_resp = changeme_api.get(async_req=True) + self.assertEqual(len(async_resp.items), 0) + + async_resp = crd_api.delete( + name=name, + async_req=True + ) + + time.sleep(2) + client.resources.invalidate_cache() + with self.assertRaises(ResourceNotFoundError): + changeme_api = client.resources.get( + api_version='apps.example.com/v1', kind='ChangeMe') + def test_namespaced_custom_resources(self): client = DynamicClient(api_client.ApiClient(configuration=self.config)) diff --git a/kubernetes/client/__init__.py b/kubernetes/client/__init__.py index 940328777b..b1d636913d 100644 --- a/kubernetes/client/__init__.py +++ b/kubernetes/client/__init__.py @@ -14,7 +14,7 @@ from __future__ import absolute_import -__version__ = "22.6.0b1" +__version__ = "22.6.0" # import apis into sdk package from kubernetes.client.api.well_known_api import WellKnownApi diff --git a/kubernetes/client/api_client.py b/kubernetes/client/api_client.py index 35b7406b36..53e0e53b19 100644 --- a/kubernetes/client/api_client.py +++ b/kubernetes/client/api_client.py @@ -78,7 +78,7 @@ def __init__(self, configuration=None, header_name=None, header_value=None, self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/22.6.0b1/python' + self.user_agent = 'OpenAPI-Generator/22.6.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/kubernetes/client/configuration.py b/kubernetes/client/configuration.py index d366d0c232..a54dbe2072 100644 --- a/kubernetes/client/configuration.py +++ b/kubernetes/client/configuration.py @@ -350,7 +350,7 @@ def to_debug_report(self): "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: release-1.22\n"\ - "SDK Package Version: 22.6.0b1".\ + "SDK Package Version: 22.6.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/scripts/constants.py b/scripts/constants.py index b459f0487e..ea2d1ba7cf 100644 --- a/scripts/constants.py +++ b/scripts/constants.py @@ -18,13 +18,13 @@ KUBERNETES_BRANCH = "release-1.22" # client version for packaging and releasing. -CLIENT_VERSION = "22.6.0b1" +CLIENT_VERSION = "22.6.0" # Name of the release package PACKAGE_NAME = "kubernetes" # Stage of development, mainly used in setup.py's classifiers. -DEVELOPMENT_STATUS = "4 - Beta" +DEVELOPMENT_STATUS = "5 - Production/Stable" # If called directly, return the constant value given diff --git a/setup.py b/setup.py index f1263cda09..11e2fc36eb 100644 --- a/setup.py +++ b/setup.py @@ -16,9 +16,9 @@ # Do not edit these constants. They will be updated automatically # by scripts/update-client.sh. -CLIENT_VERSION = "22.6.0b1" +CLIENT_VERSION = "22.6.0" PACKAGE_NAME = "kubernetes" -DEVELOPMENT_STATUS = "4 - Beta" +DEVELOPMENT_STATUS = "5 - Production/Stable" # To install the library, run the following # diff --git a/test-requirements.txt b/test-requirements.txt index 5e6aac0889..80a5be1fd5 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -9,7 +9,6 @@ mock>=2.0.0 sphinx>=1.4 # BSD recommonmark sphinx_markdown_tables -codecov>=1.4.0 pycodestyle autopep8 isort diff --git a/tox.ini b/tox.ini index 9c7e4b7e09..8a6bdac13c 100644 --- a/tox.ini +++ b/tox.ini @@ -11,8 +11,11 @@ deps = -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt commands = python -V - !functional: pytest -vvv -s --ignore=kubernetes/e2e_test + !functional: pytest -vvv -s {env:_TOX_COVERAGE_RUN:} --ignore=kubernetes/e2e_test functional: {toxinidir}/scripts/kube-init.sh pytest -vvv -s [] + coverage: python -m coverage xml +setenv = + coverage: _TOX_COVERAGE_RUN=--cov=kubernetes/watch --cov=kubernetes/config [testenv:docs] commands = @@ -21,12 +24,3 @@ commands = [testenv:update-pycodestyle] commands = {toxinidir}/scripts/update-pycodestyle.sh - -[testenv:coverage] -commands = - python -V - pytest --cov=kubernetes/watch --cov=kubernetes/config kubernetes/watch kubernetes/config - -[testenv:codecov] -commands = - codecov