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

fix: @SchemaSwap can only be used once #4354

Merged
merged 2 commits into from Sep 8, 2022

Conversation

xRodney
Copy link
Contributor

@xRodney xRodney commented Aug 26, 2022

Description

@SchemaSwap is now repeatable, so multiple modifications can be applied from the same resource root.
Fixed a bug when the swap was "used up" after just one usage, meaning that if the referenced type was used multiple times in object hierarchy, only the first one was swapped.

Fixes #4350

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change
  • Chore (non-breaking change which doesn't affect codebase;
    test, version modification, documentation, etc.)

Checklist

  • Code contributed by me aligns with current project license: Apache 2.0
  • I Added CHANGELOG entry regarding this change
  • I have implemented unit tests to cover my changes
  • I have added/updated the javadocs and other documentation accordingly
  • No new bugs, code smells, etc. in SonarCloud report
  • I tested my code in Kubernetes
  • I tested my code in OpenShift

@xRodney xRodney marked this pull request as ready for review August 26, 2022 08:27
Copy link
Member

@andreaTP andreaTP left a comment

Choose a reason for hiding this comment

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

@xRodney Thanks a lot for this PR!
I really like the overall changes that you did 🙂 , I added a few notes to be discussed.

A few additional requests, since you are fixing a bug can you add test cases for the relevant situations where the current implementation is failing (what you already described in the issue):

  • SchemaSwap should be applied to all occurrences in the hierarchy
  • SchemaSwap should be applied to deeply nested structures (e.g. 3 or more levels down)
  • SchemaSwap should fail if the field name is not matched

@@ -239,11 +256,9 @@ private T internalFromImpl(TypeDef definition, Set<String> visited, List<Interna
continue;
}

final PropertyFacade facade = new PropertyFacade(property, accessors, currentSchemaSwaps);
ClassRef potentialSchemaSwap = schemaSwaps.lookupAndMark(definition.toReference(), name).orElse(null);
Copy link
Member

Choose a reason for hiding this comment

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

If I correctly follow this change, here you cannot mark just yet the SchemaSwap as used, as it will mark the annotation to be "used" even in this condition:

  • Matched Class
  • The Class doesn't have the specified Property (e.g. a matching field)

This operation should be performed only after process has been called on the PropertyFacade (and the SchemaSwap has been matched).

Copy link
Contributor Author

@xRodney xRodney Aug 26, 2022

Choose a reason for hiding this comment

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

schemaSwapt.lookupAndMark accepts two arguments, the second being the property name. (Line 253: String name = property.getName();)
So I'm not sure I understand your concern?
Btw, I thought the case of "matched class, unmatched field" is being tested in JsonSchemaTest.shouldThrowIfSchemaSwapHasUnmatchedField. This test is still passing and I only extended it with assert on the error message. But the error is still thrown.

Copy link
Contributor Author

@xRodney xRodney Aug 26, 2022

Choose a reason for hiding this comment

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

Or is your concern that the name could be overriden by @JsonProperty & friends? IMHO it makes more sense for the fieldName parameter to reference the fields as is defined in Java, but that's just my opinion.

Copy link
Member

Choose a reason for hiding this comment

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

it makes more sense for the fieldName parameter to reference the fields as is defined in Java, but that's just my opinion.

This makes sense, but, using name might not be the name extracted by the PropertyFacade constructor:

propertyOrAccessors.add(PropertyOrAccessor.fromProperty(property));
Method method = potentialAccessors.get("is" + capitalized);
if (method != null) {
propertyOrAccessors.add(PropertyOrAccessor.fromMethod(method, name));
}
method = potentialAccessors.get("get" + capitalized);
if (method != null) {
propertyOrAccessors.add(PropertyOrAccessor.fromMethod(method, name));
}
method = potentialAccessors.get("set" + capitalized);
if (method != null) {
propertyOrAccessors.add(PropertyOrAccessor.fromMethod(method, name));
}

in some cases, the PropertyFacade is extracting the field name from constructor/getter/setter
and this implementation will not respect the extracted name as opposed to the underlying field name.
We can either refactor the logic and use the PropertyFacade name extraction logic everywhere or simply document this different behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see, and the only way how that can happen is a @JsonProperty on the field itself or getter (get* or is*) or setter.
I can only say that to me, as the user of the library, would never occur that fieldName could reference the name after transformations.
Maybe it's because the word "field" is used, whose meaning in Java is well defined and is different from the term "property". (Field is a class variable, property is a getter/setter pair - which often is backed by a field). Also the annotation is @JsonProperty, not "JsonField".
Or maybe it's because the reason I am dealing with @SchemaSwaps in the first place is that I cannot place annotations (like @JsonProperty) on the field directly.
So with your permission, I will add Javadocs on @SchemaSwap, describing the currently implemented behaviour.

Copy link
Member

Choose a reason for hiding this comment

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

To me, this "limitation" is totally fine, please just make it explicit in this doc:
https://github.com/fabric8io/kubernetes-client/blob/master/doc/CRD-generator.md#iofabric8crdgeneratorannotationschemaswap

mentioning something along the lines:

the name of the field is restricted to the original fieldName and should be backed by a matching concrete field of the matching class. Getters, setters, and constructors are not taken into consideration.

cc. @metacosm to check if he is on board with this decision.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that should be fine but this should be documented as a breaking change, though…

Copy link
Member

Choose a reason for hiding this comment

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

I agree that it "might" be breaking, but, at the same time, this PR is solving some fundamental issues with the implementation and I doubt anyone else is using it just yet.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we can add a line to the Changelog for reference, wdyt?

@xRodney
Copy link
Contributor Author

xRodney commented Aug 26, 2022

I have pushed one more test for deeply nested hierarchies, which also tests that the Swap is applied multiple times.
As for the third case you mentioned, when name is not matched, I believe that case is already covered by a pre-existing test, but let's discuss that in that other thread.

Copy link
Member

@andreaTP andreaTP left a comment

Choose a reason for hiding this comment

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

Thanks again for this effort @xRodney !
LGTM, but let's wait for a little to see if @metacosm wanna chip in.

@andreaTP andreaTP requested a review from metacosm August 26, 2022 15:42
@andreaTP
Copy link
Member

@xRodney can you please fix the issues with the CI? mvn spotless:apply -f crd-generator/pom.xml should make it automatically.

@xRodney
Copy link
Contributor Author

xRodney commented Aug 26, 2022

Hey @andreaTP, thanks to you, too for your help.
I did the reformat and also at the last minute I noticed I forgot to delete the now unused InternalSchemaSwap inner class. And that led to realization that I can move the logic of validateRemainingSchemaSwaps into the new class InternalSchemaSwaps, so its inner class no longer leaks out and can be renamed back to Value.
And last but not least, I squashed everything into one commit.
So I'll wait for the CI to finish and for @metacosm's review and we're ready to take off.

@xRodney
Copy link
Contributor Author

xRodney commented Aug 30, 2022

Hi @andreaTP, it appears that you need to run the CI for me, with me being a first-time contributor? If so, could you please do it, so that we know if we are in the green?

@@ -239,11 +256,9 @@ private T internalFromImpl(TypeDef definition, Set<String> visited, List<Interna
continue;
}

final PropertyFacade facade = new PropertyFacade(property, accessors, currentSchemaSwaps);
ClassRef potentialSchemaSwap = schemaSwaps.lookupAndMark(definition.toReference(), name).orElse(null);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that should be fine but this should be documented as a breaking change, though…

@xRodney
Copy link
Contributor Author

xRodney commented Sep 3, 2022

I have updated the changelog and added the breaking change as requested. In the latest iteration I have also added a few more tests about the case when targetType is void. And also rebased.
Please, run the CI one more time and if it passes, I think we are ready for merge.

@andreaTP
Copy link
Member

andreaTP commented Sep 5, 2022

@xRodney we merged another PR slightly conflicting with the changes in this PR.
Would you mind rebasing? Please keep your JavaDoc style as it's much better 🙂

Ping me and I will run the CI to validate and eventually move this forward 👍 thanks a lot for your effort!

@xRodney
Copy link
Contributor Author

xRodney commented Sep 5, 2022

Sure, it's done

@andreaTP
Copy link
Member

andreaTP commented Sep 5, 2022

Unfortunately, the CI failure seems to be legit, @xRodney can you have a look?

@SchemaSwap is now repeatable, so multiple modifications can be applied from the same resource root.
Fixed a bug when the swap was "used up" after just one usage, meaning that if the referenced type was used multiple times in object hierarchy, only the first one was swapped.

Fixes fabric8io#4350
@xRodney
Copy link
Contributor Author

xRodney commented Sep 6, 2022

Oops, missing import. Sorry about that, it's fixed now.

Copy link
Member

@andreaTP andreaTP left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@sonarcloud
Copy link

sonarcloud bot commented Sep 7, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 4 Code Smells

81.1% 81.1% Coverage
0.0% 0.0% Duplication

@andreaTP andreaTP merged commit caabb75 into fabric8io:master Sep 8, 2022
@andreaTP
Copy link
Member

andreaTP commented Sep 8, 2022

thanks @xRodney !

@manusa manusa added this to the 6.2.0 milestone Sep 8, 2022
@xRodney xRodney deleted the bugfix/schema-swap branch September 12, 2022 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@SchemaSwap can only be used once
4 participants