From 7e6459c9e28cebad7ec940f5aa74d9241e6976e2 Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Wed, 3 Sep 2025 12:45:30 +0200 Subject: [PATCH 1/2] Improve Configuration tests (#1582) * Add JSON tests to guard against upcoming changes in .NET 10 * Fix invalid test * Apply fix from .NET 10 analyzer --- .../ConfigServerConfigurationProvider.cs | 7 +--- ...ringBootEnvironmentVariableProviderTest.cs | 4 +- .../ConfigureEnvironmentEndpointOptions.cs | 6 +-- .../ConfigureManagementOptions.cs | 3 ++ .../Environment/EnvironmentActuatorTest.cs | 32 +++++++++++++++ .../Endpoint.Test/ManagementOptionsTest.cs | 39 +++++++++++++++++++ 6 files changed, 81 insertions(+), 10 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) { 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] 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 46805e0bf8cbb32524ea9810af1f0a9aa69e8b23 Mon Sep 17 00:00:00 2001 From: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> Date: Wed, 3 Sep 2025 16:26:10 +0200 Subject: [PATCH 2/2] Update Steeltoe 3.x version compatibility in README (#1583) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0aa28b0373..5146ac1d60 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ In addition to the [feature documentation](https://steeltoe.io/api), we have bui | Steeltoe Version | .NET Version | | --- | --- | | 4.x | .NET 8 - 9 | -| 3.x | .NET Core 3.1 - .NET 6 | +| 3.x | .NET Core 3.1 - .NET 8 | +| 3.x (Steeltoe.Stream) | .NET Core 3.1 - .NET 6 | | 2.x | .NET Framework 4.6.1+ | For more details, see [Supported Versions on the Wiki](https://github.com/SteeltoeOSS/Steeltoe/wiki/Steeltoe-Support-Versions).