Skip to content
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

Closed

Conversation

tomplus
Copy link
Member

@tomplus tomplus commented Sep 22, 2019

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.

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Sep 22, 2019
@k8s-ci-robot k8s-ci-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Sep 22, 2019
@@ -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")
Copy link
Member Author

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.

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?

Copy link
Member

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

Copy link
Member Author

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...

Copy link
Member

@roycaihw roycaihw Sep 23, 2019

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?

  1. for native types, a client can send json-patch+json if the body is a list, or strategic-merge-patch+json if the body is a map
  2. 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

Copy link
Member Author

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.

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.

Copy link
Member

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!

Copy link
Member Author

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.

@@ -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")
Copy link
Member

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

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)
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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

Copy link
Member Author

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.

kubernetes/client/api_client.py Outdated Show resolved Hide resolved
kubernetes/client/api_client.py Outdated Show resolved Hide resolved
namespace="default",
plural="crontabs",
body={'image': 'my-awesome-cron-image:2'},
content_type="application/merge-patch+json"
Copy link
Member Author

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.

Copy link
Member

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly.

Copy link
Contributor

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)

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?

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.

Copy link
Member Author

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.

Copy link
Member Author

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.

Copy link
Member

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

@tomplus
Copy link
Member Author

tomplus commented Nov 8, 2019

@roycaihw Could you take a look at the last concept? I'd like to prepare generator to manage with it. Thanks.

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Feb 6, 2020
@tomplus
Copy link
Member Author

tomplus commented Feb 6, 2020

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Feb 6, 2020
Copy link
Member

@roycaihw roycaihw left a 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"
Copy link
Member

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'
Copy link
Member

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?

Copy link
Member Author

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))
Copy link
Member

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)
Copy link
Member

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

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 18, 2020
@tomplus
Copy link
Member Author

tomplus commented May 18, 2020

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 18, 2020
@lizfeed
Copy link

lizfeed commented Jun 15, 2020

Any update on this? this would be really handy for me.

palnabarun added a commit to palnabarun/python that referenced this pull request Jun 22, 2020
palnabarun added a commit to palnabarun/python that referenced this pull request Jun 22, 2020
palnabarun added a commit to palnabarun/python that referenced this pull request Jul 16, 2020
@tomplus
Copy link
Member Author

tomplus commented Jun 7, 2022

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jun 7, 2022
@k8s-triage-robot
Copy link

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:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle stale
  • Mark this issue or PR as rotten with /lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Sep 5, 2022
@k8s-triage-robot
Copy link

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:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle rotten

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Oct 5, 2022
@spolcyn
Copy link

spolcyn commented Oct 5, 2022

/remove-lifecycle rotten

@k8s-ci-robot k8s-ci-robot removed the lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. label Oct 5, 2022
@k8s-triage-robot
Copy link

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:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle stale
  • Mark this issue or PR as rotten with /lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 3, 2023
@k8s-triage-robot
Copy link

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:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle rotten

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Feb 2, 2023
@aslafy-z
Copy link

aslafy-z commented Feb 2, 2023

/remove-lifecycle rotten

@k8s-ci-robot k8s-ci-robot removed the lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. label Feb 2, 2023
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all PRs.

This bot triages PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the PR is closed

You can:

  • Mark this PR as fresh with /remove-lifecycle stale
  • Close this PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 4, 2023
@aslafy-z
Copy link

aslafy-z commented May 4, 2023

So, we switched to golang..

@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough active contributors to adequately respond to all PRs.

This bot triages PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the PR is closed

You can:

  • Mark this PR as fresh with /remove-lifecycle rotten
  • Close this PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle rotten

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Jun 3, 2023
@k8s-triage-robot
Copy link

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:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the PR is closed

You can:

  • Reopen this PR with /reopen
  • Mark this PR as fresh with /remove-lifecycle rotten
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/close

@k8s-ci-robot
Copy link
Contributor

@k8s-triage-robot: Closed this PR.

In response to this:

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:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the PR is closed

You can:

  • Reopen this PR with /reopen
  • Mark this PR as fresh with /remove-lifecycle rotten
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/close

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.

@arcivanov
Copy link
Contributor

/reopen

@k8s-ci-robot
Copy link
Contributor

@arcivanov: You can't reopen an issue/PR unless you authored it or you are a collaborator.

In response to this:

/reopen

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.

bh717 pushed a commit to bh717/python-dapp that referenced this pull request Apr 1, 2024
Reference:
- [#866](kubernetes-client/python#866)
- [#959](kubernetes-client/python#959)

Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
bh717 pushed a commit to bh717/python-dapp that referenced this pull request Apr 1, 2024
Reference:
- [#866](kubernetes-client/python#866)
- [#959](kubernetes-client/python#959)

Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet