Skip to content

Commit 4dad36e

Browse files
amerjusupovicCopilotzhiyuanliang-ms
authored
Add environment variable to disable feature management schema compatibility logic (#676)
* add environment variable, unit test * remove comments * Update src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs Co-authored-by: Copilot <[email protected]> * fix unit test * update comments * move bool parsing logic outside try * fix formatting * add environment variable class * update * update --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Zhiyuan Liang <[email protected]> Co-authored-by: Zhiyuan Liang <[email protected]>
1 parent bb8fbbb commit 4dad36e

File tree

6 files changed

+113
-5
lines changed

6 files changed

+113
-5
lines changed

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public AzureAppConfigurationProvider(IConfigurationClientManager configClientMan
146146
string requestTracingDisabled = null;
147147
try
148148
{
149-
requestTracingDisabled = Environment.GetEnvironmentVariable(RequestTracingConstants.RequestTracingDisabledEnvironmentVariable);
149+
requestTracingDisabled = Environment.GetEnvironmentVariable(EnvironmentVariables.DisableRequestTracing);
150150
}
151151
catch (SecurityException) { }
152152

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace Microsoft.Extensions.Configuration.AzureAppConfiguration
55
{
66
internal class RequestTracingConstants
77
{
8-
public const string RequestTracingDisabledEnvironmentVariable = "AZURE_APP_CONFIGURATION_TRACING_DISABLED";
98
public const string AzureFunctionEnvironmentVariable = "FUNCTIONS_EXTENSION_VERSION";
109
public const string AzureWebAppEnvironmentVariable = "WEBSITE_SITE_NAME";
1110
public const string ContainerAppEnvironmentVariable = "CONTAINER_APP_NAME";
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
//
4+
namespace Microsoft.Extensions.Configuration.AzureAppConfiguration
5+
{
6+
/// <summary>
7+
/// Environment variables used to configure Azure App Configuration provider behavior.
8+
/// </summary>
9+
internal static class EnvironmentVariables
10+
{
11+
/// <summary>
12+
/// Environment variable to disable Feature Management schema compatibility.
13+
/// The value of this variable is a boolean string, e.g. "true" or "false".
14+
/// When set to "true", schema compatibility checks for feature flags are disabled,
15+
/// and all feature flags will be interpreted using the Microsoft Feature Flags schema.
16+
/// </summary>
17+
public const string DisableFmSchemaCompatibility = "AZURE_APP_CONFIGURATION_FM_SCHEMA_COMPATIBILITY_DISABLED";
18+
19+
/// <summary>
20+
/// Environment variable to disable request tracing.
21+
/// The value of this variable is a boolean string, e.g. "true" or "false".
22+
/// </summary>
23+
public const string DisableRequestTracing = "AZURE_APP_CONFIGURATION_TRACING_DISABLED";
24+
}
25+
}

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Linq;
1010
using System.Net.Mime;
1111
using System.Security.Cryptography;
12+
using System.Security;
1213
using System.Text;
1314
using System.Text.Json;
1415
using System.Threading;
@@ -20,10 +21,21 @@ internal class FeatureManagementKeyValueAdapter : IKeyValueAdapter
2021
{
2122
private FeatureFlagTracing _featureFlagTracing;
2223
private int _featureFlagIndex = 0;
24+
private bool _fmSchemaCompatibilityDisabled = false;
2325

2426
public FeatureManagementKeyValueAdapter(FeatureFlagTracing featureFlagTracing)
2527
{
2628
_featureFlagTracing = featureFlagTracing ?? throw new ArgumentNullException(nameof(featureFlagTracing));
29+
30+
string fmSchemaCompatibilityDisabled = null;
31+
32+
try
33+
{
34+
fmSchemaCompatibilityDisabled = Environment.GetEnvironmentVariable(EnvironmentVariables.DisableFmSchemaCompatibility);
35+
}
36+
catch (SecurityException) { }
37+
38+
_fmSchemaCompatibilityDisabled = bool.TryParse(fmSchemaCompatibilityDisabled, out bool disabled) ? disabled : false;
2739
}
2840

2941
public Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(ConfigurationSetting setting, Uri endpoint, Logger logger, CancellationToken cancellationToken)
@@ -33,7 +45,10 @@ public Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(Configura
3345
var keyValues = new List<KeyValuePair<string, string>>();
3446

3547
// Check if we need to process the feature flag using the microsoft schema
36-
if ((featureFlag.Variants != null && featureFlag.Variants.Any()) || featureFlag.Allocation != null || featureFlag.Telemetry != null)
48+
if (_fmSchemaCompatibilityDisabled ||
49+
(featureFlag.Variants != null && featureFlag.Variants.Any()) ||
50+
featureFlag.Allocation != null ||
51+
featureFlag.Telemetry != null)
3752
{
3853
keyValues = ProcessMicrosoftSchemaFeatureFlag(featureFlag, setting, endpoint);
3954
}

tests/Tests.AzureAppConfiguration/Unit/FeatureManagementTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,6 +2291,75 @@ public void ThrowsOnIncorrectJsonTypes()
22912291
}
22922292
}
22932293

2294+
[Fact]
2295+
public void EnvironmentVariableForcesMicrosoftSchemaForAllFlags()
2296+
{
2297+
var mixedSchemaFlags = new List<ConfigurationSetting>
2298+
{
2299+
_kv,
2300+
_variantFeatureFlagCollection[0]
2301+
};
2302+
2303+
var mockResponse = new Mock<Response>();
2304+
var mockClient = new Mock<ConfigurationClient>(MockBehavior.Strict);
2305+
2306+
mockClient.Setup(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
2307+
.Returns(new MockAsyncPageable(mixedSchemaFlags));
2308+
2309+
try
2310+
{
2311+
// Act - Set environment variable to force Microsoft schema
2312+
Environment.SetEnvironmentVariable(EnvironmentVariables.DisableFmSchemaCompatibility, "true");
2313+
2314+
var config = new ConfigurationBuilder()
2315+
.AddAzureAppConfiguration(options =>
2316+
{
2317+
options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);
2318+
options.UseFeatureFlags();
2319+
})
2320+
.Build();
2321+
2322+
// Assert - Both flags should be in Microsoft schema format
2323+
// First flag (would be in .NET schema without environment variable) should now be in Microsoft schema
2324+
Assert.Equal("Beta", config["feature_management:feature_flags:0:id"]);
2325+
Assert.Equal("True", config["feature_management:feature_flags:0:enabled"]);
2326+
Assert.Equal("Browser", config["feature_management:feature_flags:0:conditions:client_filters:0:name"]);
2327+
Assert.Equal("Firefox", config["feature_management:feature_flags:0:conditions:client_filters:0:parameters:AllowedBrowsers:0"]);
2328+
2329+
// Second flag (always Microsoft schema) should still be in Microsoft schema
2330+
Assert.Equal("VariantsFeature1", config["feature_management:feature_flags:1:id"]);
2331+
Assert.Equal("True", config["feature_management:feature_flags:1:enabled"]);
2332+
Assert.Equal("Big", config["feature_management:feature_flags:1:variants:0:name"]);
2333+
Assert.Equal("600px", config["feature_management:feature_flags:1:variants:0:configuration_value"]);
2334+
2335+
// Verify .NET schema paths are NOT present
2336+
Assert.Null(config["FeatureManagement:myFeature:EnabledFor:0:Name"]);
2337+
Assert.Null(config["FeatureManagement:VariantsFeature1:EnabledFor:0:Name"]);
2338+
}
2339+
finally
2340+
{
2341+
// Cleanup - Reset environment variable
2342+
Environment.SetEnvironmentVariable("AZURE_APP_CONFIGURATION_FM_SCHEMA_COMPATIBILITY_DISABLED", null);
2343+
}
2344+
2345+
// Act - Verify normal behavior when environment variable is not set
2346+
var configWithoutEnvVar = new ConfigurationBuilder()
2347+
.AddAzureAppConfiguration(options =>
2348+
{
2349+
options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);
2350+
options.UseFeatureFlags();
2351+
})
2352+
.Build();
2353+
2354+
// First flag (no variants) should be in .NET schema
2355+
Assert.Equal("Browser", configWithoutEnvVar["FeatureManagement:Beta:EnabledFor:0:Name"]);
2356+
Assert.Equal("Firefox", configWithoutEnvVar["FeatureManagement:Beta:EnabledFor:0:Parameters:AllowedBrowsers:0"]);
2357+
2358+
// Second flag (has variants) should be in Microsoft schema
2359+
Assert.Equal("VariantsFeature1", configWithoutEnvVar["feature_management:feature_flags:0:id"]);
2360+
Assert.Equal("Big", configWithoutEnvVar["feature_management:feature_flags:0:variants:0:name"]);
2361+
}
2362+
22942363
Response<ConfigurationSetting> GetIfChanged(ConfigurationSetting setting, bool onlyIfChanged, CancellationToken cancellationToken)
22952364
{
22962365
return Response.FromValue(FirstKeyValue, new MockResponse(200));

tests/Tests.AzureAppConfiguration/Unit/Tests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public void TestTurnOffRequestTracing()
273273
var options = new AzureAppConfigurationOptions();
274274
options.ClientOptions.Transport = mockTransport;
275275

276-
Environment.SetEnvironmentVariable(RequestTracingConstants.RequestTracingDisabledEnvironmentVariable, "True");
276+
Environment.SetEnvironmentVariable(EnvironmentVariables.DisableRequestTracing, "True");
277277

278278
var clientManager = TestHelpers.CreateMockedConfigurationClientManager(options);
279279
var config = new ConfigurationBuilder()
@@ -296,7 +296,7 @@ public void TestTurnOffRequestTracing()
296296
options.ClientOptions.Transport = mockTransport;
297297

298298
// Delete the request tracing environment variable
299-
Environment.SetEnvironmentVariable(RequestTracingConstants.RequestTracingDisabledEnvironmentVariable, null);
299+
Environment.SetEnvironmentVariable(EnvironmentVariables.DisableRequestTracing, null);
300300
Environment.SetEnvironmentVariable(RequestTracingConstants.AzureFunctionEnvironmentVariable, "v1.0");
301301

302302
var clientManager1 = TestHelpers.CreateMockedConfigurationClientManager(options);

0 commit comments

Comments
 (0)