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

Removing generated ResourceHandlers #3327

Merged
merged 3 commits into from Jul 28, 2021
Merged

Conversation

shawkins
Copy link
Contributor

@shawkins shawkins commented Jul 17, 2021

Description

Before I go too far down this path, I wanted to solicit some feedback. The initial changes to just refine the usage of CustomResource (the first two commits - which had not yet rationalized the SharedInformerFactory) made me want to see what things would look like without any generated ResourceHandlers. This pr has that work mostly completed for the kubernetes/openshift client modules - there are more validations and tests that should be added, but the kubernetes-tests run cleanly.

The idea is to replace the generated classes with ResourceHandlerImpl and ResourceOperationsImpl (which is also used by the resources/customResources dsl entry points). This means that any HasMetadata that is properly annotated can be used as a Resource - whether it's custom, built-in, or from a different client version provided HasMetadata and the annotations are compatible. Some of the SharedInformerFactory logic could be re-targeted to this as well.

The downsides to this approach:

  • it means that instances of the generated resourcehandlers / operations don't exist, so you have to use static Handlers methods to obtain them.
  • has reflective association/usage of Builders (based upon similar to the logic for automatically obtaining custom list type)
  • requires explicit registration of specialty HasMetadataOperations - which for now was put as a static block in BaseKubernetesClient and DefaultOpenShiftClient. This allows those operations to be used from the NamespaceVisitFromServer* classes rather than the default ResourceOperationsImpl.

Not really related to these changes it appears that OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableImpl is not being used.

I'm also thinking it would be good to have more guardrails on KubernetesDeserializer.registerCustomKind given its static nature.

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

Copy link
Member

@iocanel iocanel left a comment

Choose a reason for hiding this comment

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

I like where this is going.
This will reduce the size of the client.
If we manage to completely eliminate the use of velocity transformations we will further reduce the number of transitives too.

The tricky part seemed to be the handling of custom impls, which you seem to handle already with the static block.

+1

@@ -132,6 +127,21 @@
* It is thread safe.
*/
public abstract class BaseKubernetesClient<C extends Client> extends BaseClient implements GenericKubernetesClient<C> {

static {
Handlers.register(Pod.class, PodOperationsImpl::new);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps the Handlers class could be generated during the build process so that we don't need to manually register new ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are a couple of approaches to be weighed:

  • something generated - but that will need the some templating mechanism, which we should otherwise be able to remove
  • just a reflective association by convention similar to List and Builder classes - bit it seemed more involved to determine the package name, so I didn't take that approach yet. There is some validation logic in my next commit thought that could easily determine if an OperationsImpl is not being picked up by the Handler system that would be applicable here.
  • more logic around the initialization - this is what I've started to added in the next commit. If the *ExtensionAdapter class uses references the *Client then that can trigger the static block to register the handlers. Alternatively that registration logic could be moved onto the *ExtensionAdapter (which is probably a better option than the former).

@shawkins
Copy link
Contributor Author

This next commit rationalizes the SharedInformerFactory logic and updates the ServiceCatalog client to the new approach. The DefaultSharedIndexInformerTest.testCustomResourceInformerWithDifferentVersions is not working yet because the direct usage of the OperationContext means that I'll need to add logic to override the ResourceDefinitionContext.

@centos-ci
Copy link

Can one of the admins verify this patch?

@shawkins
Copy link
Contributor Author

I've combined the last two commits and updated things mentioned in the last couple of comments to where this now compiles and runs through the kubernetes-tests

@shawkins shawkins force-pushed the cr_refinement branch 3 times, most recently from 2fd9243 to 201487d Compare July 19, 2021 12:16
@shawkins
Copy link
Contributor Author

@rohanKanojia @manusa this now should be pretty representative of these changes - it should build without error not withstanding the latest unsuccessful run. With this only the SharedInformerFactory.sharedIndexInformerFor(Class apiTypeClass, long resyncPeriodInMillis) is not deprecated.

@shawkins shawkins marked this pull request as ready for review July 19, 2021 22:30
@manusa
Copy link
Member

manusa commented Jul 20, 2021

I haven't deeply reviewed it, but I really like what's going on.

@metacosm
Copy link
Collaborator

I haven't deeply reviewed it, but I really like what's going on.

Same here, though I see several Todos in different spots… Are these expected to be addressed in subsequent PRs or is this PR still a work in progress?

@shawkins
Copy link
Contributor Author

@metacosm @manusa I've resolved the TODOs that seem important for now. The ones that remain are a reminder about KubernetesDeserializer type registration and a reminder to remove some of the remaining overlap between the SharedInformerFactory and BaseOperation wrt creating informers. I can change those comments if needed.

- deprecated methods dealing with CustomResources, and added resources
methods where appropriate.  This means that nearly every method on
sharedinformerfactory is now deprecated
- replaced CustomResourceDefinitionContext with
ResourceDefinitionContext in the api where appropriate
- what were generated handlers are now obtained through Handlers methods
- passing the type/listType to the base HasMetadataOperation to validate
that the operation is registered
- moved OperationImpl registration onto the ExtensionAdapters
@shawkins
Copy link
Contributor Author

Took a pass through to rebase and cleanup the import changes.

  • The things to look at for review - deprecated / new methods on KubernetesClient and SharedInformerFactory

There's nothing special about the CustomResource base class after these changes, so methods dealing with CustomResources have been deprecated, and similar methods involving "resources" were added. This means that nearly every method on sharedinformerfactory is now deprecated

  • replaced CustomResourceDefinitionContext with ResourceDefinitionContext in the api where appropriate

Does that seem like a good classname?

  • what were generated handlers are now obtained through Handlers methods,

  • There's new reflective access was added for Builders. Where we look for List/Builder classes was expanded to include the classloader of the type itself.

  • We're now passing the type/listType to the base HasMetadataOperation to validate
    that the operation is registered

  • moved OperationImpl registration onto the ExtensionAdapters, with a static block in BaseKubernetesClient to load the default operations and trigger the load of all the others.

@shawkins shawkins mentioned this pull request Jul 23, 2021
11 tasks
@shawkins
Copy link
Contributor Author

@manusa I'm afraid that keeping this up-to-date will become a full-time job. If possible let's come up with a plan for inclusion to minimize conflicts.

cr_refinement

# Conflicts:
#	kubernetes-client/src/main/java/io/fabric8/kubernetes/client/BaseKubernetesClient.java
#	kubernetes-client/src/main/java/io/fabric8/kubernetes/client/V1AdmissionRegistrationAPIGroupClient.java
#	kubernetes-client/src/main/java/io/fabric8/kubernetes/client/V1beta1AdmissionRegistrationAPIGroupClient.java
@manusa manusa requested review from metacosm and iocanel July 27, 2021 09:33
}

@Override
public NonNamespaceOperation<ClusterTask, ClusterTaskList, Resource<ClusterTask>> clusterTasks() {
return new ClusterTaskOperationsImpl(this.getHttpClient(), this.getConfiguration());
return Handlers.getOperation(ClusterTask.class, ClusterTaskList.class, this.getHttpClient(), this.getConfiguration());
Copy link
Member

Choose a reason for hiding this comment

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

#3327 (review)

I'm confused now. I assumed this was possible until I saw the code in the linked comment. Now I don't get why in those lines we can follow the same procedure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You could. ClusterServiceBrokerOperationsImpl will be registered so you can get it through Handlers. However I was attempting to create the minimal changes at first, which would just be to remove the usage of the generated ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Captured as #3357

@metacosm
Copy link
Collaborator

Initial tests look positive though, surprisingly, for the same app, the native binary size is larger now than it previously was… For comparison, the same code went from 122 MB with 5.4.1 to 138MB with 5.6 to 140MB with 5.7-SNAPSHOT and this PR, which is quite surprising to me. :(

@shawkins
Copy link
Contributor Author

which is quite surprising to me. :(

It is surprising but indicates that the native compilation is very efficient. So the takeaway is that the jar sizes should go down, but the native doesn't really change.

@sonarcloud
Copy link

sonarcloud bot commented Jul 27, 2021

SonarCloud Quality Gate failed.    Quality Gate failed

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

35.8% 35.8% Coverage
4.1% 4.1% Duplication

Copy link
Member

@manusa manusa left a comment

Choose a reason for hiding this comment

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

LGTM, thx!

image 😍

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.

None yet

6 participants