From dd06b366147978db2330848dea6af2d9d9479cc9 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Thu, 18 Jul 2019 16:26:21 -0700 Subject: [PATCH 1/4] DEMO: checkout custom_objects_api from v10.0.0 --- kubernetes/client/apis/custom_objects_api.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kubernetes/client/apis/custom_objects_api.py b/kubernetes/client/apis/custom_objects_api.py index 35b576f06a..90236a3620 100644 --- a/kubernetes/client/apis/custom_objects_api.py +++ b/kubernetes/client/apis/custom_objects_api.py @@ -1657,7 +1657,7 @@ def patch_cluster_custom_object_with_http_info(self, group, version, plural, nam # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/merge-patch+json']) + select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -1781,7 +1781,7 @@ def patch_cluster_custom_object_scale_with_http_info(self, group, version, plura # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/merge-patch+json']) + select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -1905,7 +1905,7 @@ def patch_cluster_custom_object_status_with_http_info(self, group, version, plur # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/merge-patch+json']) + select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -2036,7 +2036,7 @@ def patch_namespaced_custom_object_with_http_info(self, group, version, namespac # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/merge-patch+json']) + select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -2167,7 +2167,7 @@ def patch_namespaced_custom_object_scale_with_http_info(self, group, version, na # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/merge-patch+json']) + select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -2298,7 +2298,7 @@ def patch_namespaced_custom_object_status_with_http_info(self, group, version, n # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/merge-patch+json']) + select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) # Authentication setting auth_settings = ['BearerToken'] From d1a9426bb51a92eed7926035594bc2f0be110c57 Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Thu, 18 Jul 2019 17:20:57 -0700 Subject: [PATCH 2/4] add E2E test exercising CRD and CR APIs --- kubernetes/e2e_test/test_client.py | 62 ++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/kubernetes/e2e_test/test_client.py b/kubernetes/e2e_test/test_client.py index 57000b9827..ddaa2ca0c1 100644 --- a/kubernetes/e2e_test/test_client.py +++ b/kubernetes/e2e_test/test_client.py @@ -19,6 +19,8 @@ from kubernetes.client import api_client from kubernetes.client.apis import core_v1_api +from kubernetes.client.apis import apiextensions_v1beta1_api +from kubernetes.client.apis import custom_objects_api from kubernetes.e2e_test import base from kubernetes.stream import stream from kubernetes.stream.ws_client import ERROR_CHANNEL @@ -234,3 +236,63 @@ def test_node_apis(self): node = api.read_node(name=item.metadata.name) self.assertTrue(len(node.metadata.labels) > 0) self.assertTrue(isinstance(node.metadata.labels, dict)) + + def test_custom_objects_apis(self): + """ + It should be able to create and patch a namespaced custom object. + """ + client = api_client.ApiClient(configuration=self.config) + crd_api = apiextensions_v1beta1_api.ApiextensionsV1beta1Api(client) + cr_api = custom_objects_api.CustomObjectsApi(client) + + # create a CRD that defines a namespace-scoped custom resource Foo + # TODO: The test objects in this test file are unstructured. Verify + # if it makes more sense to switch to typed objects defined under + # kubernetes.client.models + group_prefix = 'test-crd-' + short_uuid() + group = group_prefix + '.test.e2e.com' + api_version = group + '/v1' + name = 'foos.' + group + test_crd = { + 'kind': 'CustomResourceDefinition', + 'apiVersion': 'apiextensions.k8s.io/v1beta1', + 'metadata': { + 'name': name, + }, + 'spec': { + 'group': group, + 'versions': [{ + 'name': 'v1', + 'served': True, + 'storage': True + }], + 'names': { + 'kind': 'Foo', + 'plural': 'foos' + }, + 'scope': 'Namespaced' + } + } + resp = crd_api.create_custom_resource_definition(body=test_crd) + self.assertEqual(name, resp.metadata.name) + print('E2E test CRD created') + + # wait for the CRD to be ready + time.sleep(5) + + # create a custom object + name = 'test-foo-' + short_uuid() + resp = cr_api.create_namespaced_custom_object(group=group, + version='v1', + plural='foos', + namespace='default', + body={'kind':'Foo', 'apiVersion':api_version, 'metadata':{'name':name}}) + print('E2E test CR created') + + # perform an emtpy JSON merge patch on the custom object + resp = cr_api.patch_namespaced_custom_object(group=group, + version='v1', + plural='foos', + namespace='default', + name=name, + body={}) From ba8b9fa16fe37c98890afc3d4c3bf5dc0656feaf Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Thu, 18 Jul 2019 17:37:35 -0700 Subject: [PATCH 3/4] workaround for CRD conditions validation --- .../client/models/v1beta1_custom_resource_definition_status.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/kubernetes/client/models/v1beta1_custom_resource_definition_status.py b/kubernetes/client/models/v1beta1_custom_resource_definition_status.py index 4b10a8a619..067ee3f59b 100644 --- a/kubernetes/client/models/v1beta1_custom_resource_definition_status.py +++ b/kubernetes/client/models/v1beta1_custom_resource_definition_status.py @@ -101,9 +101,6 @@ def conditions(self, conditions): :param conditions: The conditions of this V1beta1CustomResourceDefinitionStatus. :type: list[V1beta1CustomResourceDefinitionCondition] """ - if conditions is None: - raise ValueError("Invalid value for `conditions`, must not be `None`") - self._conditions = conditions @property From d87424c1857e869facddaa2d63d59886e301451f Mon Sep 17 00:00:00 2001 From: Haowei Cai Date: Thu, 18 Jul 2019 17:29:30 -0700 Subject: [PATCH 4/4] hotfix: switch the order of content-type, so JSON merge patch is used by default --- kubernetes/client/apis/custom_objects_api.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kubernetes/client/apis/custom_objects_api.py b/kubernetes/client/apis/custom_objects_api.py index 90236a3620..12848a9157 100644 --- a/kubernetes/client/apis/custom_objects_api.py +++ b/kubernetes/client/apis/custom_objects_api.py @@ -1657,7 +1657,7 @@ def patch_cluster_custom_object_with_http_info(self, group, version, plural, nam # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) + select_header_content_type(['application/merge-patch+json', 'application/json-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -1781,7 +1781,7 @@ def patch_cluster_custom_object_scale_with_http_info(self, group, version, plura # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) + select_header_content_type(['application/merge-patch+json', 'application/json-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -1905,7 +1905,7 @@ def patch_cluster_custom_object_status_with_http_info(self, group, version, plur # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) + select_header_content_type(['application/merge-patch+json', 'application/json-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -2036,7 +2036,7 @@ def patch_namespaced_custom_object_with_http_info(self, group, version, namespac # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) + select_header_content_type(['application/merge-patch+json', 'application/json-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -2167,7 +2167,7 @@ def patch_namespaced_custom_object_scale_with_http_info(self, group, version, na # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) + select_header_content_type(['application/merge-patch+json', 'application/json-patch+json']) # Authentication setting auth_settings = ['BearerToken'] @@ -2298,7 +2298,7 @@ def patch_namespaced_custom_object_status_with_http_info(self, group, version, n # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.\ - select_header_content_type(['application/json-patch+json', 'application/merge-patch+json']) + select_header_content_type(['application/merge-patch+json', 'application/json-patch+json']) # Authentication setting auth_settings = ['BearerToken']