Skip to content

Fallback to merge patch #345

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/patch.py
Original file line number Diff line number Diff line change
@@ -99,7 +99,8 @@ async def main():
SERVICE_NAME,
SERVICE_NS,
patch,
_content_type="application/merge-patch+json", # required to force merge patch
# required to force merge patch when strategic merge patch would otherwise be used
_content_type="application/merge-patch+json",
)


10 changes: 7 additions & 3 deletions kubernetes_asyncio/client/api_client.py
Original file line number Diff line number Diff line change
@@ -539,9 +539,13 @@
if ('application/json-patch+json' in content_types and
isinstance(body, list)):
return 'application/json-patch+json'
if ('application/strategic-merge-patch+json' in content_types and
(isinstance(body, dict) or hasattr(body, "to_dict"))):
return 'application/strategic-merge-patch+json'
if isinstance(body, dict) or hasattr(body, "to_dict"):
if 'application/strategic-merge-patch+json' in content_types:
return 'application/strategic-merge-patch+json'
elif 'application/merge-patch+json' in content_types:

Check warning on line 545 in kubernetes_asyncio/client/api_client.py

Codecov / codecov/patch

kubernetes_asyncio/client/api_client.py#L542-L545

Added lines #L542 - L545 were not covered by tests
# Intended for cases where strategic merge patch is not
# supported, like when patching custom objects.
return 'application/merge-patch+json'

Check warning on line 548 in kubernetes_asyncio/client/api_client.py

Codecov / codecov/patch

kubernetes_asyncio/client/api_client.py#L548

Added line #L548 was not covered by tests

if 'application/json' in content_types or '*/*' in content_types:
return 'application/json'
90 changes: 89 additions & 1 deletion kubernetes_asyncio/e2e_test/test_client.py
Original file line number Diff line number Diff line change
@@ -17,7 +17,9 @@
from unittest import IsolatedAsyncioTestCase

from kubernetes_asyncio.client import api_client
from kubernetes_asyncio.client.api import core_v1_api
from kubernetes_asyncio.client.api import (

Check warning on line 20 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L20

Added line #L20 was not covered by tests
apiextensions_v1_api, core_v1_api, custom_objects_api,
)
from kubernetes_asyncio.e2e_test import base
from kubernetes_asyncio.stream import WsApiClient

@@ -187,6 +189,92 @@
name=name, body={}, namespace="default"
)

async def test_custom_objects_api(self):
client = api_client.ApiClient(configuration=self.config)

Check warning on line 193 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L192-L193

Added lines #L192 - L193 were not covered by tests

apiextensions_api_client = apiextensions_v1_api.ApiextensionsV1Api(client)
custom_objects_api_client = custom_objects_api.CustomObjectsApi(client)

Check warning on line 196 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L195-L196

Added lines #L195 - L196 were not covered by tests

name = 'clusterchangemes.apps.example.com'
crd_manifest = {

Check warning on line 199 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L198-L199

Added lines #L198 - L199 were not covered by tests
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": {
"name": name,
},
"spec": {
"group": "apps.example.com",
"names": {
"kind": "ClusterChangeMe",
"listKind": "ClusterChangeMeList",
"plural": "clusterchangemes",
"singular": "clusterchangeme",
},
"scope": "Cluster",
"versions": [
{
"name": "v1",
"served": True,
"storage": True,
"schema": {
"openAPIV3Schema": {
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"size": {"type": "integer"}
},
}
},
}
},
}
],
},
}
custom_object_manifest = {

Check warning on line 236 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L236

Added line #L236 was not covered by tests
'apiVersion': 'apps.example.com/v1',
'kind': 'ClusterChangeMe',
'metadata': {
'name': "changeme-name",
},
'spec': {}
}

await apiextensions_api_client.create_custom_resource_definition(

Check warning on line 245 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L245

Added line #L245 was not covered by tests
crd_manifest
)

await apiextensions_api_client.read_custom_resource_definition(

Check warning on line 249 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L249

Added line #L249 was not covered by tests
crd_manifest["metadata"]["name"]
)

await custom_objects_api_client.create_cluster_custom_object(

Check warning on line 253 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L253

Added line #L253 was not covered by tests
crd_manifest["spec"]["group"],
crd_manifest["spec"]["versions"][0]["name"],
crd_manifest["spec"]["names"]["plural"],
custom_object_manifest
)

# json merge patch (implied)
resp = await custom_objects_api_client.patch_cluster_custom_object(

Check warning on line 261 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L261

Added line #L261 was not covered by tests
group=crd_manifest["spec"]["group"],
version=crd_manifest["spec"]["versions"][0]["name"],
plural=crd_manifest["spec"]["names"]["plural"],
name=custom_object_manifest["metadata"]["name"],
body={
"spec": {
"size": 0
}
},
)
self.assertEqual(resp["spec"]["size"], 0)

Check warning on line 272 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L272

Added line #L272 was not covered by tests

await apiextensions_api_client.delete_custom_resource_definition(

Check warning on line 274 in kubernetes_asyncio/e2e_test/test_client.py

Codecov / codecov/patch

kubernetes_asyncio/e2e_test/test_client.py#L274

Added line #L274 was not covered by tests
crd_manifest["metadata"]["name"]
)

async def test_replication_controller_apis(self):
client = api_client.ApiClient(configuration=self.config)
api = core_v1_api.CoreV1Api(client)
22 changes: 13 additions & 9 deletions scripts/api_client_strategic_merge_patch.diff
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
--- /tmp/api_client.py 2024-02-25 20:40:28.143350042 +0100
+++ kubernetes_asyncio/client/api_client.py 2024-02-25 20:40:32.954201652 +0100
@@ -535,10 +535,13 @@
--- /tmp/api_client.py 2024-12-18 03:36:59.552742383 +0000
+++ kubernetes_asyncio/client/api_client.py 2024-12-18 03:36:11.062928089 +0000
@@ -535,10 +535,17 @@

content_types = [x.lower() for x in content_types]

- if (method == 'PATCH' and
- 'application/json-patch+json' in content_types and
- isinstance(body, list)):
@@ -12,9 +12,13 @@
+ if ('application/json-patch+json' in content_types and
+ isinstance(body, list)):
+ return 'application/json-patch+json'
+ if ('application/strategic-merge-patch+json' in content_types and
+ (isinstance(body, dict) or hasattr(body, "to_dict"))):
+ return 'application/strategic-merge-patch+json'

+ if isinstance(body, dict) or hasattr(body, "to_dict"):
+ if 'application/strategic-merge-patch+json' in content_types:
+ return 'application/strategic-merge-patch+json'
+ elif 'application/merge-patch+json' in content_types:
+ # Intended for cases where strategic merge patch is not
+ # supported, like when patching custom objects.
+ return 'application/merge-patch+json'

if 'application/json' in content_types or '*/*' in content_types:
return 'application/json'
2 changes: 1 addition & 1 deletion scripts/update-client.sh
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ pushd "${CLIENT_ROOT}" > /dev/null
CLIENT_ROOT=`pwd`
popd > /dev/null

TEMP_FOLDER=$(mktemp -d)
TEMP_FOLDER=$(mktemp -d)
trap "rm -rf ${TEMP_FOLDER}" EXIT SIGINT

SETTING_FILE="${TEMP_FOLDER}/settings"
Loading