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

generalization of the update matcher #2014

Merged
merged 7 commits into from
Aug 28, 2023

Conversation

shawkins
Copy link
Collaborator

This generalizes the update and match logic for fields other than spec and metadata. This should make the usage of specific subclasses unnecessary.

@shawkins shawkins marked this pull request as draft August 11, 2023 11:03
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 11, 2023
@shawkins
Copy link
Collaborator Author

I should mention that both the current logic and this logic have problems with matching stuff in the desired state that ends up being pruned. This pr does make that problem worse - if the desired state for example includes the status subresource that will be seen as a difference is it doesn't match exactly with the actual. But I don't think users should generally be doing this.

@shawkins shawkins force-pushed the generalized_match branch 2 times, most recently from 69d0048 to 97da6cf Compare August 11, 2023 14:32
@shawkins shawkins changed the title draft of a generalization of the update matcher generalization of the update matcher Aug 11, 2023
@shawkins shawkins marked this pull request as ready for review August 11, 2023 14:33
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 11, 2023
@openshift-ci openshift-ci bot requested a review from csviri August 11, 2023 14:33
@shawkins
Copy link
Collaborator Author

@metacosm @csviri there are two parts here

  • the first is to generalize the update logic. I did that initially with a custom mapper, but that complexity isn't needed we can work just over the regular map forms. We'll basically replace any top-level field in the actual with what is in the desired with special handling for the metadata. This is similar to the Jackson updateValue method, which we could consider exposing.

  • the second is to generalize the matching. Based upon all of the existing subclasses it makes the assumption that you want equality for anything on the desired that is non-spec field.

@shawkins shawkins force-pushed the generalized_match branch 2 times, most recently from 0e5b9cf to 2fbd8a0 Compare August 12, 2023 11:50
Copy link
Collaborator

@csviri csviri left a comment

Choose a reason for hiding this comment

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

Looks, good just some comments, and missing unit tests :)

// https://github.com/fabric8io/kubernetes-client/issues/3816
var specDiffJsonPatch = getDiffsImpactingPathsWithPrefixes(wholeDiffJsonPatch, SPEC);
boolean specMatch = match(equality, wholeDiffJsonPatch, ignoreList, SPEC);
if (!specMatch) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please add unit tests at least for some of the special cases we were handling before?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Same applies here GenericKubernetesResourceMatcherTest covers all of the modifications.

@shawkins shawkins force-pushed the generalized_match branch 2 times, most recently from 595f8d2 to 7bd9674 Compare August 14, 2023 12:10
@shawkins shawkins requested a review from csviri August 14, 2023 13:33
Copy link
Collaborator

@csviri csviri left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -24,6 +23,9 @@ public class GenericKubernetesResourceMatcher<R extends HasMetadata, P extends H
private static final String OP = "op";
public static final String METADATA_LABELS = "/metadata/labels";
public static final String METADATA_ANNOTATIONS = "/metadata/annotations";
// without knowing the CRD we cannot ignore status as it may not be a subresource, so if it's
// included we expect it to match
private static Set<String> NOT_OTHER_FIELDS = Set.of(SPEC, "/metadata", "/apiVersion", "/kind");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why SPEC is here? we want to match SPEC, or? I'm reading it wrong

Copy link
Collaborator

Choose a reason for hiding this comment

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

also again would add here status, since that does not need to match I think even if it is not a subresource

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Why SPEC is here? we want to match SPEC, or? I'm reading it wrong

spec and metadata have their own handling, so that's not covered by the "other fields" matching.

also again would add here status, since that does not need to match I think even if it is not a subresource

You would only want to do that if you suspect that users are including non-matching status that is not meaningful on their dependent resources. My guess would be that they are not including status, and if they are it would be because it's coming from the actual state (and would match), or that it's not a subresource and needs to be considered in matching. But if you feel strongly about it, it can be excluded.

Copy link
Collaborator

Choose a reason for hiding this comment

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

spec and metadata have their own handling, so that's not covered by the "other fields" matching.

sorry totally missed that.

Copy link
Collaborator Author

@shawkins shawkins Aug 14, 2023

Choose a reason for hiding this comment

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

Yet another tweak would be to change the logic to just walk through the diffs once and do prefix matching to determine if the change is allowable that may make things even clearer.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You would only want to do that if you suspect that users are including non-matching status that is not meaningful on their dependent resources. My guess would be that they are not including status, and if they are it would be because it's coming from the actual state (and would match), or that it's not a subresource and needs to be considered in matching. But if you feel strongly about it, it can be excluded.

So these are resources which usually created, but not managed by the controller, so in normal case we apply the desired state using SSA, that is usually the spec. We don't care about the status at all at this phase, we might case in a postCondition, or when we are setting the status for the primary resource.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't care about the status at all at this phase,

If you assume it's a subresource. If not, then you do.

Copy link
Collaborator

Choose a reason for hiding this comment

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

yep, true, but again that should not be a feature flag? we are comparing the desired with the actual, the actual would contain the status even if it is a subresource, but the desired won't, wouldn't this always fail to match in that case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we are comparing the desired with the actual, the actual would contain the status even if it is a subresource, but the desired won't, wouldn't this always fail to match in that case?

Ah, the issue you are raising is with the true parameter with https://github.com/operator-framework/java-operator-sdk/pull/2014/files#diff-3425845ceca0cbb05292b87cdceec9960b4342cefac82c18ab929a5ef22e5288R211 - if someone leaves the status unpopulated in the desired (which is expected) the exact match here will cause a problem. I must have been implicitly assuming that all are add ops would apply here, but that would obviously require a separate case. Let me make another revision and add a test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Further refactored to clarify the matching algorithm and added status as excluded.

@shawkins
Copy link
Collaborator Author

One last thought is whether you want something for the loss of the protected method updateClonedActual - a release note? Bring back a similar method, or just let people override updateResource after calling the super method?

@csviri
Copy link
Collaborator

csviri commented Aug 15, 2023

One last thought is whether you want something for the loss of the protected method updateClonedActual - a release note? Bring back a similar method, or just let people override updateResource after calling the super method?

I think overriding updateResource is good enough for now, will see about feedback, and will make it easier if there will be a lot of buzz around it.

Copy link
Collaborator

@csviri csviri left a comment

Choose a reason for hiding this comment

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

LGTM

also adding a test that removes a field not present in the desired
var clonedActual = context.getControllerConfiguration().getConfigurationService()
.getResourceCloner().clone(actual);
KubernetesSerialization kubernetesSerialization =
context.getClient().getKubernetesSerialization();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if this is opening potential issues where the cloning occurs in a different manner than here if, for some reason, the configured resource cloner has a different serialization set up… Should we remove the cloner altogether?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If this was the only instance of the cloner being used, it could be removed or deprecated. There is also a clone method on KubernetesSerialization.

@metacosm metacosm self-requested a review August 23, 2023 08:43
Copy link
Collaborator

@metacosm metacosm left a comment

Choose a reason for hiding this comment

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

LGTM apart from one comment.

@csviri csviri merged commit 6839b63 into operator-framework:next Aug 28, 2023
17 checks passed
csviri added a commit that referenced this pull request Aug 29, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Sep 4, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Sep 4, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
csviri added a commit that referenced this pull request Sep 4, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
csviri added a commit that referenced this pull request Sep 4, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Sep 11, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Sep 12, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
metacosm pushed a commit that referenced this pull request Sep 15, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Sep 18, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Sep 18, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Oct 3, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
shawkins added a commit to shawkins/java-operator-sdk that referenced this pull request Oct 4, 2023
* feat: create resource only if not exists (operator-framework#2001)

* feat: leader election callbacks (operator-framework#2015)

* discriminator improvements (operator-framework#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
Signed-off-by: Steve Hawkins <[email protected]>
csviri added a commit that referenced this pull request Oct 4, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
csviri added a commit that referenced this pull request Oct 18, 2023
* feat: create resource only if not exists (#2001)

* feat: leader election callbacks (#2015)

* discriminator improvements (#2013)

* generalization of the update matcher

* consolidating the diffs

also adding a test that removes a field not present in the desired

---------

Co-authored-by: Attila Mészáros <[email protected]>
Signed-off-by: csviri <[email protected]>
Signed-off-by: Attila Mészáros <[email protected]>
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.

3 participants