feat!: introduce result-pattern and automatic finalizer management#980
Conversation
# Conflicts: # src/KubeOps.Abstractions/KubeOps.Abstractions.csproj
…t for builder identifier
…g (hybrid cache) - Integrated FusionCache for robust caching in resource watchers. - Enhanced default configuration with extensible settings in `OperatorSettings`. - Improved concurrency handling using `SemaphoreSlim` for entity events. - Updated tests and dependencies to reflect caching changes.
…nt entity locks - Renamed `DefaultCacheConfiguration` to `DefaultResourceWatcherCacheConfiguration` for clarity. - Introduced cache key prefix to improve cache segmentation. - Removed `ConcurrentDictionary` for entity locks to simplify concurrency management. - Refactored event handling logic for "added" and "modified" events to streamline codebase.
- Updated `ConfigureResourceWatcherEntityCache` to use `IFusionCacheBuilder` for extensibility. - Moved resource watcher cache setup logic to `WithResourceWatcherCaching` extension. - Added detailed XML comments for `EntityLoggingScope` to improve documentation. - Removed redundant `DefaultResourceWatcherCacheConfiguration`.
- Renamed `WithResourceWatcherCaching` to `WithResourceWatcherEntityCaching` for clarity. - Updated `CacheExtensions` to be `internal` to limit scope. - Removed unused dependency on `ZiggyCreatures.Caching.Fusion`.
…onstants` for consistency
- Added a new `Caching` documentation page explaining resource watcher caching with FusionCache and configuration options (in-memory and distributed). - Updated sidebar positions for `Deployment`, `Utilities`, and `Testing` to accommodate the new `Caching` page.
…usionCache details - Improved explanations for in-memory and distributed caching setups. - Added example code for customizing resource watcher cache with FusionCache. - Included references to FusionCache and Redis documentation for further guidance.
# Conflicts:
# src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs
# Conflicts:
# examples/Operator/Finalizer/FinalizerOne.cs
# src/KubeOps.Abstractions/KubeOps.Abstractions.csproj
# src/KubeOps.Operator/Builder/CacheExtensions.cs
# src/KubeOps.Operator/Constants/CacheConstants.cs
# src/KubeOps.Operator/KubeOps.Operator.csproj
# src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs
…ependency - Removed redundant requeue logic and optimized entity cache operations during deletion in `ResourceWatcher`. - Upgraded `ZiggyCreatures.FusionCache` to version `2.4.0`.
- Introduced `RequeueType` enumeration to specify requeue operation types (`Added`, `Modified`, `Deleted`). - Implemented `RequeueTypeExtensions` for mapping `WatchEventType` to `RequeueType`. - Updated requeue mechanism to include `RequeueType` in `EntityRequeue` and related methods. - Refactored `TimedEntityQueue` and related classes to support `RequeueEntry` containing both the entity and its requeue type. - Adjusted tests to incorporate `RequeueType` into entity requeue logic.
… reconciliation logic - Created `IReconciler<TEntity>` interface and its implementation to handle entity creation, modification, and deletion. - Updated `ResourceWatcher` and `EntityRequeueBackgroundService` to use `Reconciler` for reconciliation operations. - Removed redundant FusionCache dependency from `ResourceWatcher` and related classes. - Streamlined requeue mechanics and replaced entity finalization logic with `Reconciler` integration.
- Registered `IReconciler<TEntity>` and its implementation `Reconciler<TEntity>` in the service container. - Ensured proper integration with existing requeue and entity processing workflows.
…-attach/detach options - Added `AutoAttachFinalizers` and `AutoDetachFinalizers` settings in `OperatorSettings`, enabling automatic management of entity finalizers during reconciliation. - Extended `Reconciler` to respect these settings for adding and removing finalizers. - Introduced `EntityFinalizerExtensions` for streamlined finalizer handling and identifier generation. - Updated relevant interfaces and documentation for improved clarity and usability.
…ant values - Update `KubernetesEntitySyntaxReceiver` to utilize `SemanticModel` for attribute argument resolution, ensuring accurate value retrieval.
- Updated `EntityFinalizerExtensions` to correctly append "finalizer" when missing from the name. - Added unit tests to validate finalizer identifier generation, including cases for length limits and naming consistency.
- Renamed test cases and entities for improved clarity and consistency. - Added new tests for entities with no group values and entities with varying group definitions. - Adjusted expected
…interface for improved flexibility - Extracted `ITimedEntityQueue` interface from `TimedEntityQueue` implementation. - Updated all usages, including services and tests, to rely on the interface. - Added extension methods for requeue key management. - Improved code consistency and maintainability across the queue system.
…r election - Replaced `EnableLeaderElection` with `LeaderElectionType` in `OperatorSettings` for enhanced configurability. - Added `LeaderElectionType` enum with options: None, Single, and Custom. - Updated `OperatorBuilder` to handle leader election logic based on `LeaderElectionType`. - Modified `EntityRequeueBackgroundService` to public visibility and implemented proper `Dispose` logic. - Adjusted tests to reflect new leader election mechanism. - Improved code maintainability and alignment with distributed system requirements.
|
hey Christoph @buehler - sorry for pushing new changes 🙈 I just saw that there were some logs missing (and an activity) - so tried to align that for consistency. also it doesn't felt good how to "configure" custom requeue mechanism, so I mad it configurable same way as finalizer handling. this should it be for now - (except changes to the docs to reflect all the changes here - but that will be one last commit) I have two open points I'd like to discuss but will move them maybe to the discussion first. |
|
No worries. which parts do you want to discuss? |
I know these are 3 points 🤣 |
|
I wanted to chime in on 3. the potential parallel execution of watcher and requeue. |
thanks @ralf-cestusio - honestly I hadn't checked for existing issues. this 3 points weren't planned to go in to this PR :) these were just some points I'd like to discuss. |
### Description This PR ensures that admission webhooks (Mutation and Validation) use the same deserializing mechanism as the resource watcher. By using the default ASP.NET Core serializer for webhooks, inconsistent behavior could occur when processing the same resources. This change aligns the webhook deserialization with the rest of the SDK. ### Changes - Introduced AdmissionRequestModelBinder to handle deserialization using KubernetesJsonSerializer.SerializerOptions. - Applied the model binder to MutationWebhook<TEntity> and ValidationWebhook<TEntity> endpoints. - Added integration tests to verify correct model binding for entities with Kubernetes-specific serialization (e.g., [ISO8601 durations](https://github.com/kubernetes-client/csharp/blob/415161a40cd4954005e950075b9c5bc1089780c6/src/KubernetesClient/KubernetesJson.cs#L16)). --- this addresses item 1 mentioned in the discussion #980 (comment) > I think there is an issue between deserialization in the resource watcher (which is done through the Kubernetes.Client --> KubernetesJson) and the deserialzation in the admission webhooks (validate/mutate) (which is done by the default System.Text.Json). Why do I think that? We have - not sure if it's uncommon - n entity model containing some TimeSpan properties. In the KubernetesJson there is a special converter enforcing the ISO8601 duration format. (eg: PT1H if it's 1 hour). This could be proper deserialized/serialized by the KubernetesClient but with the default System.Text.Json this will fail in the validation webhook - expecting it to be eg 01:00:00 as standard timespan format. My idea was to give the admission webhooks a special modelbinder using the KubernetesJson for the deserialization - but from what I saw this is currently not possible: I asked on the KubernetsClient side: kubernetes-client/csharp#1683 --- --------- Co-authored-by: Christoph Bühler <buehler@users.noreply.github.com>
Hey Christoph @buehler
This is a comprehensive PR containing changes from integrating the operator into our cluster environment.
Summary
This PR introduces breaking changes to the KubeOps SDK, implementing a result pattern inspired by the Go operator implementation. Controllers and finalizers now return
ReconciliationResult<TEntity>enabling explicit success/failure states, centralized requeuing viaRequeueAfter, and automatic finalizer lifecycle management. Additional improvements include extensible requeue mechanisms, const value support in source generators, and configurable leader election types.Breaking Changes⚠️
1. Result Pattern
Controller and finalizer interfaces now return
Task<ReconciliationResult<TEntity>>instead ofTask:Before:
After:
The
ReconciliationResult<TEntity>provides:RequeueAftertimespan for delayed reprocessingMigration Example:
2. Namespace Reorganization
Types moved to new namespaces:
IEntityController<TEntity>:KubeOps.Abstractions.Controller→KubeOps.Abstractions.Reconciliation.ControllerIEntityFinalizer<TEntity>:KubeOps.Abstractions.Finalizer→KubeOps.Abstractions.Reconciliation.FinalizerEntityRequeue:KubeOps.Abstractions.Queue→KubeOps.Abstractions.Reconciliation.QueueIEntityRequeueFactory:KubeOps.Abstractions.Queue→KubeOps.Abstractions.Reconciliation.QueueMigration: Update using statements in your controllers and finalizers.
3. Queue Interface Changes
The internal queue interface is now public and extensible:
This enables implementing durable requeue mechanisms (e.g., backed by Redis, Service Bus, database) by overriding the default in-memory implementation.
New Features
1. Automatic Finalizer Management
Two new settings provide automatic finalizer lifecycle management:
Benefits:
2. Const Value Support in Source Generator
The syntax receiver now supports constant values in Kubernetes entity attributes:
Benefits:
3. Leader Election Type Configuration
Introduction of
LeaderElectionTypeenum for explicit leader election configuration:Configuration:
Benefits:
4. Extensible Requeue Mechanism
Introduction of
RequeueTypeenum andITimedEntityQueue<TEntity>interface:Use Cases:
Example Implementation:
5. ReconciliationContext
New context object providing metadata about reconciliation triggers:
Helps distinguish between API server events and operator-initiated requeues.
Implementation Details
Core Components
ReconciliationResult (
src/KubeOps.Abstractions/Reconciliation/ReconciliationResult{TEntity}.cs)Reconciler (
src/KubeOps.Operator/Reconciliation/Reconciler.cs)ITimedEntityQueue (
src/KubeOps.Operator/Queue/ITimedEntityQueue{TEntity}.cs)Alignment with Go Implementation
This implementation draws inspiration from controller-runtime (Go):
Testing
ReconciliationResult<TEntity>ReconciliationContext<TEntity>RequeueTypeDocumentation
Additional Notes
Migration Checklist
For operators upgrading to this version:
ReconciliationResult<TEntity>ReconciliationResult<TEntity>