-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
content-type for patch commands #959
Conversation
kubernetes/e2e_test/test_client.py
Outdated
@@ -55,9 +55,12 @@ class TestClient(unittest.TestCase): | |||
def setUpClass(cls): | |||
cls.config = base.get_e2e_configuration() | |||
|
|||
def setUp(self): | |||
self.client = api_client.ApiClient(configuration=self.config, | |||
prefered_content_type="application/strategic-merge-patch+json") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use it as a default to make it backward compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assume you meant to have it as default in the ApiClient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, defaulting to one content type doesn't make it backward compatible, since the old behavior was picking one of the two content types based on the body
type. We have to keep the old behavior if we want to avoid breaking the old clients
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO backward compatibility is not possible, because current behavior doesn't work for custom resources. If we assume that strategic-merg-patch is more common we can set is as a default. Other clients will have to change the preferred content type only...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO backward compatibility is not possible, because current behavior doesn't work for custom resources
the current behavior allows JSON patch for custom resources, right? Can we keep the following behavior if prefered_content_type
is None?
- for native types, a client can send
json-patch+json
if the body is a list, orstrategic-merge-patch+json
if the body is a map - for custom resources, a client can send
merge-patch+json
only
In future, we need to allow a client to send merge-patch+json
and apply-patch+yaml
for both native types and custom resources as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I prepare changes for such approach.
I see one drawbacks - we'll keep the "magic" logic in rest.py and it won't be such generic to add it to the open-generator. But let's discuss it later with the code.
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the select_header_content_type
takes the body and method as well then it can be intelligent about it's choice. We should be prepared for that custom resources will support strategic merge in the future when such strategy is defined in the CRD. So it is still a good idea to introduce the option to set the preferred type.
Note that the previous supported type for custom resources was application/merge-patch+json
and not json-patch+json
which was newly added. So if you should have a default for custom objects you should select application/merge-patch+json
if you want backward compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the previous supported type for custom resources was application/merge-patch+json and not json-patch+json which was newly added. So if you should have a default for custom objects you should select application/merge-patch+json if you want backward compatibility
Ah yes, you're right. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I’m leaning towards to expose content_type to each request (for patch mainly) to bypass the select_content_type function. This function now accepts "method" and "body" to try to select the better header. K8s introduces strategic-merge-patch which is k8s specific and this part has to be patched - instead of patching rest.py. Let me know what you think. Thanks.
kubernetes/e2e_test/test_client.py
Outdated
@@ -55,9 +55,12 @@ class TestClient(unittest.TestCase): | |||
def setUpClass(cls): | |||
cls.config = base.get_e2e_configuration() | |||
|
|||
def setUp(self): | |||
self.client = api_client.ApiClient(configuration=self.config, | |||
prefered_content_type="application/strategic-merge-patch+json") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, defaulting to one content type doesn't make it backward compatible, since the old behavior was picking one of the two content types based on the body
type. We have to keep the old behavior if we want to avoid breaking the old clients
examples/custom_object.py
Outdated
api = client.CustomObjectsApi() | ||
# passing prefered_content_type to choose the required type of patch | ||
api_client = client.ApiClient(prefered_content_type="application/merge-patch+json") | ||
api = client.CustomObjectsApi(api_client) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if someone wants to send different types of patch in their client? Is it possible to expose an argument in each API to specify the content type for each request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can add it to each patch method but I thought that something like the default-content-type could help to write more consistent code. I've never mixed type of patch in my code yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm okay with either way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've dropped preferred_content _type
option - it didn't support situation where different type of methods have different valid content types.
namespace="default", | ||
plural="crontabs", | ||
body={'image': 'my-awesome-cron-image:2'}, | ||
content_type="application/merge-patch+json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter is not necessary - select_header_content_type can manage with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Custom resources support JSON patch, so this parameter can be used to hint JSON patch / JSON merge patch, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about application/apply-patch+yaml
? Why aren't we allowing to override from the caller?
header_params['Content-Type'] = self.api_client.\ | ||
select_header_content_type(['application/merge-patch+json']) | ||
header_params['Content-Type'] = params.get('content_type', self.api_client.\ | ||
select_header_content_type(['application/merge-patch+json']), 'PATCH', body_params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all started due to that we added 'application/json-patch+json' for custom objects, so should that not be part of the list of available content types?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also assuming this is an example on the changes to all the patch methods, since there are several more in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, should be but this PR uses current code from master branch (https://github.com/kubernetes-client/python/blob/master/kubernetes/client/apis/custom_objects_api.py#L1659). AFAIK @roycaihw removed this option when the problem appeared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I use this PR to discuss final solution and then I will change the openapi-generator to add this to all methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed 'application/json-patch+json' from custom objects because the existing select_header_content_type couldn't support it without breaking old clients. With this change from @tomplus, we should be able to add 'application/json-patch+json' for custom objects
@roycaihw Could you take a look at the last concept? I'd like to prepare generator to manage with it. Thanks. |
Issues go stale after 90d of inactivity. If this issue is safe to close now please do so with Send feedback to sig-testing, kubernetes/test-infra and/or fejta. |
/remove-lifecycle stale |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tomplus Sorry for the late response. I have some small questions to clarify. Overall I think the interface looks good.
namespace="default", | ||
plural="crontabs", | ||
body={'image': 'my-awesome-cron-image:2'}, | ||
content_type="application/merge-patch+json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Custom resources support JSON patch, so this parameter can be used to hint JSON patch / JSON merge patch, right?
if 'application/strategic-merge-patch+json' in content_types: | ||
return 'application/strategic-merge-patch+json' | ||
# --- | ||
return 'application/merge-patch+json' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most native types support both strategic merge patch and JSON merge patch. Just to clarify, if a client wants to send JSON merge patch, it has to use the content_type
parameter to hint, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's hard to detect which type of patch has been sent so it's better to expose content_type explicit.
header_params['Content-Type'] = self.api_client.\ | ||
select_header_content_type(['application/json-patch+json', 'application/merge-patch+json', 'application/strategic-merge-patch+json']) | ||
header_params['Content-Type'] = params.get('content_type', self.api_client.\ | ||
select_header_content_type(['application/json-patch+json', 'application/merge-patch+json', 'application/strategic-merge-patch+json'], 'PATCH', body_params)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kubernetes recently added a new type application/apply-patch+yaml
. However it's likely hard to auto-detect the yaml type based on the body
header_params['Content-Type'] = self.api_client.\ | ||
select_header_content_type(['application/merge-patch+json']) | ||
header_params['Content-Type'] = params.get('content_type', self.api_client.\ | ||
select_header_content_type(['application/merge-patch+json']), 'PATCH', body_params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed 'application/json-patch+json' from custom objects because the existing select_header_content_type couldn't support it without breaking old clients. With this change from @tomplus, we should be able to add 'application/json-patch+json' for custom objects
Issues go stale after 90d of inactivity. If this issue is safe to close now please do so with Send feedback to sig-testing, kubernetes/test-infra and/or fejta. |
/remove-lifecycle stale |
Any update on this? this would be really handy for me. |
Reference: - [kubernetes-client#866](kubernetes-client#866) - [kubernetes-client#959](kubernetes-client#959) Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
Reference: - [kubernetes-client#866](kubernetes-client#866) - [kubernetes-client#959](kubernetes-client#959) Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
Reference: - [kubernetes-client#866](kubernetes-client#866) - [kubernetes-client#959](kubernetes-client#959) Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
/remove-lifecycle stale |
The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs. This bot triages issues and PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs. This bot triages issues and PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
/remove-lifecycle rotten |
The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs. This bot triages issues and PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs. This bot triages issues and PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
/remove-lifecycle rotten |
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
So, we switched to golang.. |
The Kubernetes project currently lacks enough active contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle rotten |
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /close |
@k8s-triage-robot: Closed this PR. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/reopen |
@arcivanov: You can't reopen an issue/PR unless you authored it or you are a collaborator. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Reference: - [#866](kubernetes-client/python#866) - [#959](kubernetes-client/python#959) Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
Reference: - [#866](kubernetes-client/python#866) - [#959](kubernetes-client/python#959) Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
Hi all.
In this PR I'd like to discuss possible solution for problems with selecting content-type when K8s' objects are patching. This problem is nicely documented in #866 and tomplus/kubernetes_asyncio#68
This idea is to introduce a new parameter in ApiClient to be able to control a return from the
select_header_content_type
method and remove the problematic detection from rest.py. Optionally we can add this as an argument to each patch method.It'll be breaking change if an application uses patch_* methods.
Please take a look. If we accept the solution I prepare PR in openapi-generator and temporary patch for this repo.
cc: @roycaihw @yliaog @HaraldGustafsson @nolar
Thanks.