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

🐛 Metadata only objects should always preserve GroupVersionKind #1484

Merged
merged 1 commit into from Apr 27, 2021

Conversation

vincepri
Copy link
Member

@vincepri vincepri commented Apr 19, 2021

Currently we have a bug that GVK information is not passed into mapping
functions when using the OnlyMetadata option in the builder. This patch
adds a wrapper that preserves the GVK information when events come in.

This issue is most likely caused by kubernetes/kubernetes#80609
which we have been bumping into every once in a while here and there.

Signed-off-by: Vince Prignano vincepri@vmware.com

/hold

for further review

@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Apr 19, 2021
@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Apr 19, 2021
@vincepri
Copy link
Member Author

/retest

1 similar comment
@vincepri
Copy link
Member Author

/retest

Copy link
Contributor

@DirectXMan12 DirectXMan12 left a comment

Choose a reason for hiding this comment

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

It occurs to me -- we manually construct a WithoutConversionCodecFactory, and as per kubernetes/kubernetes#80609, that's the thing, eventually, that's actually stripping the GVK. Could we just construct our own NegotiatedSerializer instead that doesn't do this and just uses the decoder directly?

Something like

cfg.NegotiatedSerializer = WithoutConversionGVKCodecFactory{CodecFactory: codecs}

// then just implement the required methods similarly to the existing codec factory, except without using WithoutVersionDecoder

Comment on lines 413 to 415
if _, err := apiutil.GVKForObject(o, mgr.GetScheme()); err != nil {
Expect(err).NotTo(HaveOccurred())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: don't use the if

Suggested change
if _, err := apiutil.GVKForObject(o, mgr.GetScheme()); err != nil {
Expect(err).NotTo(HaveOccurred())
}
_, err := apiutil.GVKForObject(o, mgr.GetScheme())
Expect(err).NotTo(HaveOccurred())

Copy link
Contributor

Choose a reason for hiding this comment

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

also, just check directly with GetObjectKind -- no need for GVKForObject, because we shouldn't need to use the scheme.

Copy link
Contributor

Choose a reason for hiding this comment

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

(and add a note as to why you're checking)

Copy link
Contributor

Choose a reason for hiding this comment

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

also, assertions in other goroutines need defer GinkgoRecover() at the top, but it's probably better to check check this when we pull it off the channel, or add a explict test case for it to better describe the desired behavior:

Context("when requesting For, Owns, and Watches as metadata", func() {
  It("should watch in metadata-only form", func() { /* existing test */ })

  It("should have GVK set on the metadata passed to the handlers", func() { /* new test */ })
})

// WrapPartialObjectMetadataHandler wraps an event handler for partial metadata objects
// which restores the GVK for PartialObjectMetadata objects which loses this information when
// events come from the informer code.
func WrapPartialObjectMetadataHandler(o *metav1.PartialObjectMetadata, hdl EventHandler) EventHandler {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I'm comfortable exposing this in our public API -- it seems a bit hacky, and I don't want to guarantee it'll stick around as the exact implementation.

@vincepri vincepri changed the title 🐛 PartialMetadataObject should preserve GVK information [WIP] 🐛 PartialMetadataObject should preserve GVK information Apr 20, 2021
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 20, 2021
@vincepri vincepri changed the title [WIP] 🐛 PartialMetadataObject should preserve GVK information [WIP] 🐛 Metadata and Unstructured objects should always preserve GVK info Apr 20, 2021
@vincepri vincepri force-pushed the wrapmetaonly branch 6 times, most recently from 4553e57 to 927d2bc Compare April 27, 2021 15:11
@vincepri vincepri changed the title [WIP] 🐛 Metadata and Unstructured objects should always preserve GVK info 🐛 Metadata only objects should always preserve GVK info Apr 27, 2021
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 27, 2021
@vincepri vincepri changed the title 🐛 Metadata only objects should always preserve GVK info 🐛 Metadata only objects should always preserve GroupVersionKind Apr 27, 2021
@vincepri
Copy link
Member Author

vincepri commented Apr 27, 2021

@DirectXMan12 @alvaroaleman A little update on this issue, while the NegotiatedSerializer would have been a good solution to explore, it's way too complicated and there are limitations coming from client-go and how the serializers are being used; moreover, the api-server when querying for a metadata object returns TypeMeta filled as:

TypeMeta: {
  Kind: "PartialObjectMetadata",
  APIVersion: "meta.k8s.io/v1",
}

Which seems to be the expected behavior described in the associated KEP.

For this reason, I updated this PR to follow a different approach: in the client and cache code we now make sure to always preserve the type information coming from the client. We were already doing something similar for Patch/Update on all calls in client.go file, I extended that behavior for Get/List calls when a PartialObjectMetadata[List] object is detected. In addition, the cache now makes sure to preserve the GVK when a new handler is passed in which should cover most if not all uses for the metadata objects.

The only one discrepancy I can think about between the metadata client and the unstructured one is for List calls: the unstructured client when querying a apps/v1 DeploymentList for example it returns each item in the list with TypeMeta information filled in (apps/v1 Deployment for the example). Should we do the same for Metadata List calls? If so, how can we reliably get the TypeMeta information of an object in a List GVK? Added logic in client.go to preserve the TypeMeta for each item as well using TrimSuffix as we're using everywhere else.

Note: The unstructured client already behaves properly and its default (forced) serializer makes sure to not clear the TypeMeta information.

@vincepri
Copy link
Member Author

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 27, 2021
return rest.RESTClientFor(createRestConfig(gvk, isUnstructured, baseConfig, codecs))
}

// SerializerWithDecodedGVK is a CodecFactory that overrides the DecoderToVersion of a WithoutConversionCodecFactory
Copy link
Member

Choose a reason for hiding this comment

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

Can we unexport this? IMHO it is an implementation detail and doesn't really have any use for others or does it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done!

Signed-off-by: Vince Prignano <vincepri@vmware.com>
Copy link
Member

@alvaroaleman alvaroaleman left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Apr 27, 2021
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: alvaroaleman, vincepri

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

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [alvaroaleman,vincepri]

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

@vincepri
Copy link
Member Author

/milestone v0.9.x

@k8s-ci-robot k8s-ci-robot added this to the v0.9.x milestone Apr 27, 2021
@k8s-ci-robot k8s-ci-robot merged commit 2d19f01 into kubernetes-sigs:master Apr 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. 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

4 participants