From 33ff70d1513d00e3665ef09928645eb9e1466577 Mon Sep 17 00:00:00 2001 From: Marcus Kimpenhaus Date: Tue, 2 Dec 2025 21:55:45 +0100 Subject: [PATCH 1/6] fix: optimize finalizer attachment and test status change in integration test --- .../Reconciliation/Reconciler.cs | 7 +++++-- .../EntityController.Integration.Test.cs | 20 ++++++++++++++----- .../IntegrationTestCollection.cs | 4 ++-- .../V1OperatorIntegrationTestEntity.cs | 7 ++++++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/KubeOps.Operator/Reconciliation/Reconciler.cs b/src/KubeOps.Operator/Reconciliation/Reconciler.cs index 15608a34..5cc03323 100644 --- a/src/KubeOps.Operator/Reconciliation/Reconciler.cs +++ b/src/KubeOps.Operator/Reconciliation/Reconciler.cs @@ -137,14 +137,17 @@ await entityQueue if (operatorSettings.AutoAttachFinalizers) { - var finalizers = scope.ServiceProvider.GetKeyedServices>(KeyedService.AnyKey); + var finalizers = scope.ServiceProvider.GetKeyedServices>(KeyedService.AnyKey).ToArray(); foreach (var finalizer in finalizers) { entity.AddFinalizer(finalizer.GetIdentifierName(entity)); } - entity = await client.UpdateAsync(entity, cancellationToken); + if (finalizers.Length > 0) + { + entity = await client.UpdateAsync(entity, cancellationToken); + } } var controller = scope.ServiceProvider.GetRequiredService>(); diff --git a/test/KubeOps.Operator.Test/Controller/EntityController.Integration.Test.cs b/test/KubeOps.Operator.Test/Controller/EntityController.Integration.Test.cs index fee650d9..c8c21f1c 100644 --- a/test/KubeOps.Operator.Test/Controller/EntityController.Integration.Test.cs +++ b/test/KubeOps.Operator.Test/Controller/EntityController.Integration.Test.cs @@ -16,7 +16,7 @@ namespace KubeOps.Operator.Test.Controller; -public class EntityControllerIntegrationTest : IntegrationTestBase +public sealed class EntityControllerIntegrationTest : IntegrationTestBase { private readonly InvocationCounter _mock = new(); private readonly IKubernetesClient _client = new KubernetesClient.KubernetesClient(); @@ -25,7 +25,7 @@ public class EntityControllerIntegrationTest : IntegrationTestBase [Fact] public async Task Should_Call_Reconcile_On_New_Entity() { - await _client.CreateAsync(new V1OperatorIntegrationTestEntity("test-entity", "username", _ns.Namespace)); + await _client.CreateAsync(new V1OperatorIntegrationTestEntity("test-entity", "username", _ns.Namespace, true)); await _mock.WaitForInvocations; _mock.Invocations.Count.Should().Be(1); @@ -119,12 +119,22 @@ protected override void ConfigureHost(HostApplicationBuilder builder) .AddController(); } - private class TestController(InvocationCounter svc) : IEntityController + private sealed class TestController( + InvocationCounter svc, + IKubernetesClient client) : IEntityController { - public Task> ReconcileAsync(V1OperatorIntegrationTestEntity entity, CancellationToken cancellationToken) + public async Task> ReconcileAsync(V1OperatorIntegrationTestEntity entity, CancellationToken cancellationToken) { + if (entity.Spec.CouldChangeStatus) + { + // status change: issue 1001 (https://github.com/dotnet/dotnet-operator-sdk/issues/1001) + entity.Status.Status = "reconciled"; + entity = await client.UpdateStatusAsync(entity, cancellationToken); + } + svc.Invocation(entity); - return Task.FromResult(ReconciliationResult.Success(entity)); + + return ReconciliationResult.Success(entity); } public Task> DeletedAsync(V1OperatorIntegrationTestEntity entity, CancellationToken cancellationToken) diff --git a/test/KubeOps.Operator.Test/IntegrationTestCollection.cs b/test/KubeOps.Operator.Test/IntegrationTestCollection.cs index fba46a9d..549408d8 100644 --- a/test/KubeOps.Operator.Test/IntegrationTestCollection.cs +++ b/test/KubeOps.Operator.Test/IntegrationTestCollection.cs @@ -59,12 +59,12 @@ public sealed class TestNamespaceProvider : IAsyncLifetime private readonly IKubernetesClient _client = new KubernetesClient.KubernetesClient(); private V1Namespace _namespace = null!; - public string Namespace { get; } = Guid.NewGuid().ToString().ToLower(); + public string Namespace { get; } = $"kubeops-{Guid.NewGuid().ToString().ToLower()}"; public async Task InitializeAsync() { _namespace = - await _client.CreateAsync(new V1Namespace() + await _client.CreateAsync(new V1Namespace { Metadata = new() { Name = Namespace }, }.Initialize()); diff --git a/test/KubeOps.Operator.Test/TestEntities/V1OperatorIntegrationTestEntity.cs b/test/KubeOps.Operator.Test/TestEntities/V1OperatorIntegrationTestEntity.cs index 3e9547c4..dd31c6b4 100644 --- a/test/KubeOps.Operator.Test/TestEntities/V1OperatorIntegrationTestEntity.cs +++ b/test/KubeOps.Operator.Test/TestEntities/V1OperatorIntegrationTestEntity.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. +using System.Text.Json.Serialization; + using k8s.Models; using KubeOps.Abstractions.Entities; @@ -18,10 +20,11 @@ public V1OperatorIntegrationTestEntity() Kind = "OperatorIntegrationTest"; } - public V1OperatorIntegrationTestEntity(string name, string username, string ns) : this() + public V1OperatorIntegrationTestEntity(string name, string username, string ns, bool couldChangeStatus = false) : this() { Metadata.Name = name; Spec.Username = username; + Spec.CouldChangeStatus = couldChangeStatus; Metadata.NamespaceProperty = ns; } @@ -30,6 +33,8 @@ public V1OperatorIntegrationTestEntity(string name, string username, string ns) public sealed class EntitySpec { public string Username { get; set; } = string.Empty; + + public bool CouldChangeStatus { get; set; } } public sealed class EntityStatus From 54c2668de2cd8d601d775706d31d0e764e5797b2 Mon Sep 17 00:00:00 2001 From: Marcus Kimpenhaus Date: Thu, 11 Dec 2025 14:07:04 +0100 Subject: [PATCH 2/6] revert: checking for any finalizer - as this is covered by kubernetes --- src/KubeOps.Operator/Reconciliation/Reconciler.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/KubeOps.Operator/Reconciliation/Reconciler.cs b/src/KubeOps.Operator/Reconciliation/Reconciler.cs index 5cc03323..3dc9be61 100644 --- a/src/KubeOps.Operator/Reconciliation/Reconciler.cs +++ b/src/KubeOps.Operator/Reconciliation/Reconciler.cs @@ -4,7 +4,6 @@ using k8s; using k8s.Models; - using KubeOps.Abstractions.Builder; using KubeOps.Abstractions.Reconciliation; using KubeOps.Abstractions.Reconciliation.Controller; @@ -12,10 +11,8 @@ using KubeOps.KubernetesClient; using KubeOps.Operator.Constants; using KubeOps.Operator.Queue; - using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; - using ZiggyCreatures.Caching.Fusion; namespace KubeOps.Operator.Reconciliation; @@ -137,17 +134,14 @@ await entityQueue if (operatorSettings.AutoAttachFinalizers) { - var finalizers = scope.ServiceProvider.GetKeyedServices>(KeyedService.AnyKey).ToArray(); + var finalizers = scope.ServiceProvider.GetKeyedServices>(KeyedService.AnyKey); foreach (var finalizer in finalizers) { entity.AddFinalizer(finalizer.GetIdentifierName(entity)); } - if (finalizers.Length > 0) - { - entity = await client.UpdateAsync(entity, cancellationToken); - } + entity = await client.UpdateAsync(entity, cancellationToken); } var controller = scope.ServiceProvider.GetRequiredService>(); @@ -202,4 +196,4 @@ await entityQueue return ReconciliationResult.Success(entity, result.RequeueAfter); } -} +} \ No newline at end of file From 74f73fb7a11c568ca7b2798d091cdd88d89038ba Mon Sep 17 00:00:00 2001 From: Marcus Kimpenhaus Date: Thu, 11 Dec 2025 14:08:15 +0100 Subject: [PATCH 3/6] fix: whitspacing/line breaks --- src/KubeOps.Operator/Reconciliation/Reconciler.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/KubeOps.Operator/Reconciliation/Reconciler.cs b/src/KubeOps.Operator/Reconciliation/Reconciler.cs index 3dc9be61..a376cee1 100644 --- a/src/KubeOps.Operator/Reconciliation/Reconciler.cs +++ b/src/KubeOps.Operator/Reconciliation/Reconciler.cs @@ -162,8 +162,7 @@ await entityQueue // which implies that there is at least a single finalizer var identifier = entity.Finalizers()[0]; - if (scope.ServiceProvider.GetKeyedService>(identifier) is not - { } finalizer) + if (scope.ServiceProvider.GetKeyedService>(identifier) is not { } finalizer) { logger.LogInformation( """Entity "{Kind}/{Name}" is finalizing but this operator has no registered finalizers for the identifier {FinalizerIdentifier}.""", From 2358728bf3e47d1286e09b98330cd68ed05c876d Mon Sep 17 00:00:00 2001 From: Marcus Kimpenhaus Date: Thu, 11 Dec 2025 14:11:35 +0100 Subject: [PATCH 4/6] fix: improve formatting of finalizer service check in Reconciler --- src/KubeOps.Operator/Reconciliation/Reconciler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/KubeOps.Operator/Reconciliation/Reconciler.cs b/src/KubeOps.Operator/Reconciliation/Reconciler.cs index a376cee1..3dc9be61 100644 --- a/src/KubeOps.Operator/Reconciliation/Reconciler.cs +++ b/src/KubeOps.Operator/Reconciliation/Reconciler.cs @@ -162,7 +162,8 @@ await entityQueue // which implies that there is at least a single finalizer var identifier = entity.Finalizers()[0]; - if (scope.ServiceProvider.GetKeyedService>(identifier) is not { } finalizer) + if (scope.ServiceProvider.GetKeyedService>(identifier) is not + { } finalizer) { logger.LogInformation( """Entity "{Kind}/{Name}" is finalizing but this operator has no registered finalizers for the identifier {FinalizerIdentifier}.""", From 4bfd4f5e1a7f9882622386664404e65695b5143d Mon Sep 17 00:00:00 2001 From: Marcus Kimpenhaus Date: Thu, 11 Dec 2025 14:29:34 +0100 Subject: [PATCH 5/6] fix: add missing newline at end of Reconciler.cs file --- src/KubeOps.Operator/Reconciliation/Reconciler.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/KubeOps.Operator/Reconciliation/Reconciler.cs b/src/KubeOps.Operator/Reconciliation/Reconciler.cs index 3dc9be61..b49a93c9 100644 --- a/src/KubeOps.Operator/Reconciliation/Reconciler.cs +++ b/src/KubeOps.Operator/Reconciliation/Reconciler.cs @@ -4,6 +4,7 @@ using k8s; using k8s.Models; + using KubeOps.Abstractions.Builder; using KubeOps.Abstractions.Reconciliation; using KubeOps.Abstractions.Reconciliation.Controller; @@ -11,8 +12,10 @@ using KubeOps.KubernetesClient; using KubeOps.Operator.Constants; using KubeOps.Operator.Queue; + using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; + using ZiggyCreatures.Caching.Fusion; namespace KubeOps.Operator.Reconciliation; From 33320392a391dcdab555c4c70fdecd520d1c763c Mon Sep 17 00:00:00 2001 From: Marcus Kimpenhaus Date: Thu, 11 Dec 2025 14:31:27 +0100 Subject: [PATCH 6/6] Update Reconciler.cs --- src/KubeOps.Operator/Reconciliation/Reconciler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KubeOps.Operator/Reconciliation/Reconciler.cs b/src/KubeOps.Operator/Reconciliation/Reconciler.cs index b49a93c9..15608a34 100644 --- a/src/KubeOps.Operator/Reconciliation/Reconciler.cs +++ b/src/KubeOps.Operator/Reconciliation/Reconciler.cs @@ -199,4 +199,4 @@ await entityQueue return ReconciliationResult.Success(entity, result.RequeueAfter); } -} \ No newline at end of file +}