Skip to content

feat: add opt-in toggle for managedFields inclusion in deserialization#4746

Open
YuqiGuo105 wants to merge 1 commit intokubernetes-client:masterfrom
YuqiGuo105:feat/managed-fields-include-toggle
Open

feat: add opt-in toggle for managedFields inclusion in deserialization#4746
YuqiGuo105 wants to merge 1 commit intokubernetes-client:masterfrom
YuqiGuo105:feat/managed-fields-include-toggle

Conversation

@YuqiGuo105
Copy link
Copy Markdown

Summary

Since 22.0.0, V1MetadataExclusionStrategy has silently excluded managedFields from Gson (de)serialization by default to reduce noise. This broke users who rely on managedFields data and there was no supported way to re-enable them.

Closes #3995


Workflow: Before this fix

managedFields were silently dropped on every API response with no recourse:

// managedFields always empty, even when the server returns them
V1DeploymentList list = appsApi.listNamespacedDeployment(ns).execute();
List<V1ManagedFieldsEntry> fields =
    list.getItems().get(0).getMetadata().getManagedFields(); // []

The only workaround was reflection-based hacking into Gson's private factories field.

Workflow: After this fix

Call JSON.setIncludeManagedFields(true) once at startup to opt in. Everything else is unchanged:

// At application startup (once):
JSON.setIncludeManagedFields(true);

// Then use the API as normal — managedFields will be populated:
V1DeploymentList list = appsApi.listNamespacedDeployment(ns).execute();
List<V1ManagedFieldsEntry> fields =
    list.getItems().get(0).getMetadata().getManagedFields(); // [fleetagent, kubectl-rollout, ...]

To restore the default (exclude managedFields):

JSON.setIncludeManagedFields(false);

The default remains false (managedFields excluded) so all existing users are unaffected.


Changes

File Change
V1MetadataExclusionStrategy.java Add boolean includeManagedFields constructor param; when true, shouldSkipField() returns false immediately (no exclusion)
JSON.java Add static includeManagedFields flag (default false); extract 700-line static {} into initGson() helper; add public static setIncludeManagedFields(boolean) that flips the flag and reinitialises the shared Gson instance
JSONTest.java Three new tests: default exclusion, opt-in inclusion, and restoration of default after toggling
scripts/patches/json.diff Updated patch so the changes survive future OpenAPI code regeneration

@k8s-ci-robot k8s-ci-robot added the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label May 7, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: YuqiGuo105
Once this PR has been reviewed and has the lgtm label, please assign brendandburns for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented May 7, 2026

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: YuqiGuo105 / name: Yuqi Guo (642de36)

@k8s-ci-robot
Copy link
Copy Markdown
Contributor

Welcome @YuqiGuo105!

It looks like this is your first PR to kubernetes-client/java 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-client/java has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label May 7, 2026
@YuqiGuo105 YuqiGuo105 force-pushed the feat/managed-fields-include-toggle branch from c939470 to 684d221 Compare May 7, 2026 05:11
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label May 7, 2026
@k8s-triage-robot
Copy link
Copy Markdown

Unknown CLA label state. Rechecking for CLA labels.

Send feedback to sig-contributor-experience at kubernetes/community.

/check-cla
/easycla

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label May 7, 2026
@brendandburns
Copy link
Copy Markdown
Contributor

This file is auto generated from Kubernetes swagger, I think the fact that the field is missing means that the field must be missing from the swagger. We should fix that in the upstream swagger.

@YuqiGuo105
Copy link
Copy Markdown
Author

This file is auto generated from Kubernetes swagger, I think the fact that the field is missing means that the field must be missing from the swagger. We should fix that in the upstream swagger.

Thanks for reviewing! I want to clarify the root cause — this is not a swagger / code generation issue.

The managedFields field is present in both the upstream swagger and the generated V1ObjectMeta.java (line 105). The server also returns the field in the HTTP response body (confirmed by the reporter in the linked issue).

The data is being silently dropped during Gson deserialization by V1MetadataExclusionStrategy — a hand-written (non-generated) class that tells Gson to skip the managedFields field on V1ObjectMeta. This strategy is injected into the generated JSON.java via json.diff after each code generation run.

This was an intentional change introduced in 22.0.0 with no public opt-out API, which is what broke the users in the linked issue. This PR adds a simple toggle (JSON.setIncludeManagedFields(true)) while keeping the default behavior unchanged.

gson = gsonBuilder.create();
}

static {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think this part of the change is necessary (the method refactor etc) please remove.

import io.kubernetes.client.openapi.models.V1ObjectMeta;

public class V1MetadataExclusionStrategy implements com.google.gson.ExclusionStrategy {
private final boolean includeManagedFields;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Rather than modifying this class, let's just not add the exclusion strategy if includeManagedFields is true in the JSON class below.

Since 22.0.0, V1MetadataExclusionStrategy has excluded managedFields from
Gson (de)serialization by default to reduce noise. This broke users who
rely on managedFields data. There was no supported way to re-enable them.

Before this change, managedFields were silently dropped on every API
response even when the server returned them. The only workaround required
reflection-based hacking into Gson private internals.

After this change, call JSON.setIncludeManagedFields(true) once at startup
to opt in. The default remains false so all existing users are unaffected.

Changes:
- V1MetadataExclusionStrategy: add boolean includeManagedFields constructor
  param; when true, shouldSkipField() skips the exclusion check entirely
- JSON: add static includeManagedFields flag (default false); extract the
  700-line static initializer into initGson() helper; add public static
  setIncludeManagedFields(boolean) that flips the flag and reinitialises
  the shared Gson instance
- JSONTest: three new tests covering default exclusion, opt-in inclusion,
  and restoration of default after toggling
- scripts/patches/json.diff: updated to include the new hunks so the
  changes survive future OpenAPI code regeneration
@YuqiGuo105 YuqiGuo105 force-pushed the feat/managed-fields-include-toggle branch from 684d221 to 642de36 Compare May 9, 2026 01:30
@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 9, 2026
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. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

managedFields not populated since 22.0.0

4 participants