-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
using kubernetesresource as the raw type #4414
Conversation
182eab9
to
d44d84a
Compare
@manusa This commit shows a minimum amount of changes / breakage needed to non-generated files. The commit to the generated will be quite large, so I'm leaving that out for now - I'm also not able to generate all the extensions. For example knative fails with:
Not sure yet what is going on there. After seeing which ones currently are actually using the Map<String, Object> for raw, I can further update the generate.go files. To recap these changes are:
What they don't do:
What could be done differently:
Migrating away from directly supporting map based on these changes would be a breaking change - the user would be expected to use RawExtension instead. The biggest usability issue there is that the getter will become typed as KubernetesResource rather than Map. |
d792d10
to
9e79199
Compare
Thanks @rohanKanojia it turned out to be the go version. knative requires 1.18+. Updated to pare back where KubernetesResource is used - many of the locations where the object model specifies raw can really only have typed values. Since we don't differentiate between typed and HasMetadata, the most appropriate mapping is to still use HasMetadata. This was the conclusion for BaseKubernetesList - it also applies to Template (you can create a Template with an untyped raw value, but you can't do anything with it). So to do this more thoroughly we'd need to evaluate on a case by case basis if the raw mapping actually accept untyped values, like NamedExtension. Presumably all the places that were using Map and the previous RawExtension class, the answer is yes. Unfortunately there's nothing to indicate this ahead of time or that would be easy to capture in the generation logic - it would seemingly take special case handling like was being done for the image raw extension. This is obviously more involved that I had intended, so I'll probably take one more pass over it to see how to further minimize things. |
9e79199
to
a360833
Compare
@manusa @rohanKanojia A quick recap of the changes:
So to handle json / raw, we have in total:
Quite a mess... |
a360833
to
88423f2
Compare
63530b4
to
0b4d990
Compare
0b4d990
to
bbc5065
Compare
@andreaTP @manusa this introduces an AnyType class that is a base for IntOrString and RawExtension (which is still a KubernetesResource). Alternatively we could leave IntOrString alone and just introduce AnyType, but also make it a KubernetesResource. For now it is just an Object wrapper with some javadocs over the expected getValue types. Are there additional helper methods that we would want? |
SonarCloud Quality Gate failed. |
@shawkins thanks a lot for taking care of this, appreciated! Regarding having Regarding helper functions I think that a |
It's related more to the Java implementation rather than any explicit schema hierarchy. AnyType is simply and object wrapper - which is what IntOrString is as well. IntOrString is just type restrictions layered on AnyType.
Without additional restructuring I think those functions would need to go in same module as Serialization - so that we can reuse the same mapping logic. Converting from JsonNode should be unnecessary - any object, including JsonNode, is a valid value. That can be called out in the JavaDocs. For converting to JsonNode that would currently be Serialization.jsonMapper().valueToTree(object) - but we may not want to encourage that static usage as we'll ideally encapsulate that better. |
@DisplayName("unmarshal, with invalid YAML resource, should throw exception") | ||
void unmarshalWithInvalidResourceShouldThrowException() { |
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.
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.
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 feel that the following methods are still ambiguous:
public static <T> T unmarshal(InputStream is) {
// ...
public static <T> T unmarshal(String str) {
We probably need to clean up this class (other PR/Issue).
I see value in a Serialization.unmarshall
field that can return any instance of HasMetadata, list of HasMetadata (as a YAML multidocument 😉), or maybe even KubernetesList, but only restricted for these types.
The current behavior for the referenced methods is sort of unpredictable.
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 feel that the following methods are still ambiguous:
That's a different level of ambiguity. What I'm mostly trying to do is remove special case handling. If we have no type specified, then RawExtension makes just as much sense as throwing an exception - but allows us to remove the specialized check in Serialization.
I see value in a Serialization.unmarshall field that can return any instance of HasMetadata, list of HasMetadata, or maybe even KubernetesList, but only restricted for these types.
That seems fine to add - Serialization.unmarshallHasMetadata or another signature with a hasmetadata flag.
Related to this - a yaml list of HasMetadata is currently problematic. The root unmarshall method conversion from yaml only accounts for an object root - an array will fail with a class cast.
Description
This is an alternative to #4409 that uses KubernetesResource as the raw type, rather than object.
There are a couple of nuances.
for a little better backwards compatibility for models using Map<String, Object> it would be nice if RawExtension implemented Map<String, Object> - however that causes a problem with sundrio and results in build errors. So the usage would need to be RawExtension.fromMap(...) https://github.com/fabric8io/kubernetes-client/compare/master...shawkins:kubernetes-client:raw_kuberesource?expand=1#diff-97d49d0a6ea3655ffb6a17863e03105b6a4822eade197fcf217ba5594d33d38dR73 - or new RawExtension(map), which would also be useful if RawExtension is added to the array of buildable resources.
There are also sundrio build errors if all generated types remain KubernetesResources, so these changes see if the resource has a kind field to be considered a KubernetesResources. If it does not, then we'll just use serializable instead. That does not affect deserialization as those resources can't be deserialized by the KubernetesDeserializer. However this change touches quite a few generated classes and could have other considerations around the usage of the KuberentesResource interface.
To minimize the changes / breakage I'll back out the changes to migrate from the Map<String, Object> to KuberentesResource and save those for a major release.
Type of change
test, version modification, documentation, etc.)
Checklist