From 6a678183fa3e865b6d2281146ef98a20031048b9 Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:45:16 +0200 Subject: [PATCH 1/3] Add JSON tests to guard against upcoming changes in .NET 10 --- .../ConfigureEnvironmentEndpointOptions.cs | 6 +-- .../ConfigureManagementOptions.cs | 3 ++ .../Environment/EnvironmentActuatorTest.cs | 32 +++++++++++++++ .../Endpoint.Test/ManagementOptionsTest.cs | 39 +++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/Management/src/Endpoint/Actuators/Environment/ConfigureEnvironmentEndpointOptions.cs b/src/Management/src/Endpoint/Actuators/Environment/ConfigureEnvironmentEndpointOptions.cs index 1fe8c537e3..e7efadfe24 100644 --- a/src/Management/src/Endpoint/Actuators/Environment/ConfigureEnvironmentEndpointOptions.cs +++ b/src/Management/src/Endpoint/Actuators/Environment/ConfigureEnvironmentEndpointOptions.cs @@ -26,9 +26,6 @@ public override void Configure(EnvironmentEndpointOptions options) base.Configure(options); - // It's not possible to distinguish between null and an empty list in configuration. - // See https://github.com/dotnet/extensions/issues/1341. - // As a workaround, we interpret a single empty string element to clear the defaults. if (options.KeysToSanitize.Count == 0) { foreach (string defaultKey in DefaultKeysToSanitize) @@ -38,6 +35,9 @@ public override void Configure(EnvironmentEndpointOptions options) } else if (options.KeysToSanitize is [""]) { + // When binding a collection property from a JSON configuration file, setting the key to null or an empty + // collection is ignored. As a workaround, we interpret a single empty string element to clear the defaults. + options.KeysToSanitize.Clear(); } } diff --git a/src/Management/src/Endpoint/Configuration/ConfigureManagementOptions.cs b/src/Management/src/Endpoint/Configuration/ConfigureManagementOptions.cs index c027fc58f1..262bda91e3 100644 --- a/src/Management/src/Endpoint/Configuration/ConfigureManagementOptions.cs +++ b/src/Management/src/Endpoint/Configuration/ConfigureManagementOptions.cs @@ -117,6 +117,9 @@ public void Configure(Exposure options) } else { + // When binding a collection property from a JSON configuration file, setting the key to null or an empty + // collection is ignored. As a workaround, we interpret a single empty string element to clear the defaults. + if (options.Include is [""]) { includes.Clear(); diff --git a/src/Management/test/Endpoint.Test/Actuators/Environment/EnvironmentActuatorTest.cs b/src/Management/test/Endpoint.Test/Actuators/Environment/EnvironmentActuatorTest.cs index de2585330a..13fe635f8b 100644 --- a/src/Management/test/Endpoint.Test/Actuators/Environment/EnvironmentActuatorTest.cs +++ b/src/Management/test/Endpoint.Test/Actuators/Environment/EnvironmentActuatorTest.cs @@ -109,6 +109,38 @@ public async Task Can_clear_default_keys_to_sanitize() options.KeysToSanitize.Should().BeEmpty(); } + [Fact] + public async Task Can_clear_default_keys_to_sanitize_via_JSON() + { + const string appSettings = """ + { + "Management": { + "Endpoints": { + "Env": { + "KeysToSanitize": [ + "" + ] + } + } + } + } + """; + + await using var stream = TextConverter.ToStream(appSettings); + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddJsonStream(stream); + IConfiguration configuration = configurationBuilder.Build(); + + var services = new ServiceCollection(); + services.AddSingleton(configuration); + services.AddEnvironmentActuator(); + await using ServiceProvider serviceProvider = services.BuildServiceProvider(true); + + EnvironmentEndpointOptions options = serviceProvider.GetRequiredService>().Value; + + options.KeysToSanitize.Should().BeEmpty(); + } + [Theory] [InlineData(HostBuilderType.Host)] [InlineData(HostBuilderType.WebHost)] diff --git a/src/Management/test/Endpoint.Test/ManagementOptionsTest.cs b/src/Management/test/Endpoint.Test/ManagementOptionsTest.cs index b3d56225fd..096108dd39 100644 --- a/src/Management/test/Endpoint.Test/ManagementOptionsTest.cs +++ b/src/Management/test/Endpoint.Test/ManagementOptionsTest.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Steeltoe.Common.Json; +using Steeltoe.Common.TestResources; using Steeltoe.Management.Endpoint.Actuators.Info; using Steeltoe.Management.Endpoint.Actuators.Loggers; using Steeltoe.Management.Endpoint.Actuators.Refresh; @@ -186,6 +187,44 @@ public async Task Can_clear_default_exposure() options.Exposure.Exclude.Should().BeEmpty(); } + [Fact] + public async Task Can_clear_default_exposure_via_JSON() + { + const string appSettings = """ + { + "Management": { + "Endpoints": { + "Actuator": { + "Exposure": { + "Include": [ + "" + ], + "Exclude": [ + "" + ] + } + } + } + } + } + """; + + await using var stream = TextConverter.ToStream(appSettings); + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddJsonStream(stream); + IConfiguration configuration = configurationBuilder.Build(); + + var services = new ServiceCollection(); + services.AddSingleton(configuration); + services.AddInfoActuator(); + await using ServiceProvider serviceProvider = services.BuildServiceProvider(true); + + ManagementOptions options = serviceProvider.GetRequiredService>().Value; + + options.Exposure.Include.Should().BeEmpty(); + options.Exposure.Exclude.Should().BeEmpty(); + } + [Fact] public async Task Can_clear_default_exposure_with_Spring_syntax() { From 18400a038745e46f2dfcc96798e6365183a28db1 Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:46:52 +0200 Subject: [PATCH 2/3] Fix invalid test --- .../SpringBootEnvironmentVariableProviderTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Configuration/test/SpringBoot.Test/SpringBootEnvironmentVariableProviderTest.cs b/src/Configuration/test/SpringBoot.Test/SpringBootEnvironmentVariableProviderTest.cs index 617dba8b31..ac78944af9 100644 --- a/src/Configuration/test/SpringBoot.Test/SpringBootEnvironmentVariableProviderTest.cs +++ b/src/Configuration/test/SpringBoot.Test/SpringBootEnvironmentVariableProviderTest.cs @@ -118,9 +118,9 @@ public void TryGet_Array() provider.TryGet("a:b:c:2:s:t", out value).Should().BeTrue(); value.Should().BeEmpty(); - provider.TryGet("a:b:c:3:u", out _).Should().BeFalse(); + provider.TryGet("a:b:c:2:u", out _).Should().BeFalse(); - provider.TryGet("a:b:c:3:v:w", out _).Should().BeFalse(); + provider.TryGet("a:b:c:2:v:w", out _).Should().BeFalse(); } [Fact] From 96e6aa82ffb13ca22dea3c58acd6ec92d817ad3f Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:07:29 +0200 Subject: [PATCH 3/3] Apply fix from .NET 10 analyzer --- .../src/ConfigServer/ConfigServerConfigurationProvider.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Configuration/src/ConfigServer/ConfigServerConfigurationProvider.cs b/src/Configuration/src/ConfigServer/ConfigServerConfigurationProvider.cs index 98be9996da..cbb723915d 100644 --- a/src/Configuration/src/ConfigServer/ConfigServerConfigurationProvider.cs +++ b/src/Configuration/src/ConfigServer/ConfigServerConfigurationProvider.cs @@ -830,11 +830,8 @@ public void Dispose() _refreshTimer?.Dispose(); _refreshTimer = null; - if (_timerTickLock != null) - { - _timerTickLock.Dispose(); - _timerTickLock = null; - } + _timerTickLock?.Dispose(); + _timerTickLock = null; if (_ownsHttpClientHandler) {