Skip to content

Commit 68931b9

Browse files
Merge pull request #727 from Azure/preview
Merge preview to release/preview/v8
2 parents a3fed9a + f7ddab6 commit 68931b9

12 files changed

Lines changed: 166 additions & 22 deletions

File tree

src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<!-- Nuget Package Version Settings -->
2222

2323
<PropertyGroup>
24-
<OfficialVersion>8.5.0-preview</OfficialVersion>
24+
<OfficialVersion>8.6.0-preview</OfficialVersion>
2525
</PropertyGroup>
2626

2727
<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">

src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<!-- Nuget Package Version Settings -->
2525

2626
<PropertyGroup>
27-
<OfficialVersion>8.5.0-preview</OfficialVersion>
27+
<OfficialVersion>8.6.0-preview</OfficialVersion>
2828
</PropertyGroup>
2929

3030
<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,27 @@ public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context
3737
return HealthCheckResult.Unhealthy(HealthCheckConstants.NoProviderFoundMessage);
3838
}
3939

40+
HealthCheckResult worstResult = HealthCheckResult.Healthy();
41+
4042
foreach (IHealthCheck healthCheck in _healthChecks)
4143
{
4244
var result = await healthCheck.CheckHealthAsync(context, cancellationToken).ConfigureAwait(false);
4345

46+
// Keep track of the worst health status found
47+
// HealthStatus enum is ordered: Unhealthy(0) < Degraded(1) < Healthy(2)
48+
if (result.Status < worstResult.Status)
49+
{
50+
worstResult = result;
51+
}
52+
53+
// If an Unhealthy status is found, short-circuit since that's the worst possible
4454
if (result.Status == HealthStatus.Unhealthy)
4555
{
4656
return result;
4757
}
4858
}
4959

50-
return HealthCheckResult.Healthy();
60+
return worstResult;
5161
}
5262

5363
private void FindHealthChecks(IConfigurationRoot configurationRoot, List<IHealthCheck> healthChecks)

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,15 +576,17 @@ public void ProcessPushNotification(PushNotification pushNotification, TimeSpan?
576576

577577
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
578578
{
579+
HealthStatus failureStatus = context.Registration?.FailureStatus ?? HealthStatus.Unhealthy;
580+
579581
if (!_lastSuccessfulAttempt.HasValue)
580582
{
581-
return HealthCheckResult.Unhealthy(HealthCheckConstants.LoadNotCompletedMessage);
583+
return new HealthCheckResult(status: failureStatus, description: HealthCheckConstants.LoadNotCompletedMessage);
582584
}
583585

584586
if (_lastFailedAttempt.HasValue &&
585587
_lastSuccessfulAttempt.Value < _lastFailedAttempt.Value)
586588
{
587-
return HealthCheckResult.Unhealthy(HealthCheckConstants.RefreshFailedMessage);
589+
return new HealthCheckResult(status: failureStatus, description: HealthCheckConstants.RefreshFailedMessage);
588590
}
589591

590592
return HealthCheckResult.Healthy();

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ private void FindRefreshers(IConfigurationRoot configurationRoot, ILoggerFactory
6363
{
6464
foreach (IConfigurationProvider provider in configurationRoot.Providers)
6565
{
66-
if (provider is AzureAppConfigurationProvider appConfigurationProvider)
66+
if (provider is IConfigurationRefresher configurationRefresher)
6767
{
68-
appConfigurationProvider.LoggerFactory = loggerFactory;
69-
refreshers.Add(appConfigurationProvider);
68+
refreshers.Add(configurationRefresher);
69+
70+
if (configurationRefresher is AzureAppConfigurationProvider azureAppConfigurationProvider)
71+
{
72+
azureAppConfigurationProvider.LoggerFactory = loggerFactory;
73+
}
7074
}
7175
else if (provider is ChainedConfigurationProvider chainedProvider)
7276
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public static async Task<bool> HaveCollectionsChanged(
9595
LabelFilter = keyValueSelector.LabelFilter
9696
};
9797

98-
AsyncPageable<ConfigurationSetting> pageable = client.GetConfigurationSettingsAsync(selector, cancellationToken);
98+
AsyncPageable<ConfigurationSetting> pageable = client.CheckConfigurationSettingsAsync(selector, cancellationToken);
9999

100100
using IEnumerator<WatchedPage> existingPageWatcherEnumerator = pageWatchers.GetEnumerator();
101101

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<Import Project="..\..\build\NugetProperties.props" />
44

@@ -15,7 +15,7 @@
1515
</PropertyGroup>
1616

1717
<ItemGroup>
18-
<PackageReference Include="Azure.Data.AppConfiguration" Version="1.7.0" />
18+
<PackageReference Include="Azure.Data.AppConfiguration" Version="1.8.0" />
1919
<PackageReference Include="Azure.Messaging.EventGrid" Version="5.0.0" />
2020
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.8.0" />
2121
<PackageReference Include="DnsClient" Version="1.7.0" />
@@ -38,7 +38,7 @@
3838
<!-- Nuget Package Version Settings -->
3939

4040
<PropertyGroup>
41-
<OfficialVersion>8.5.0-preview</OfficialVersion>
41+
<OfficialVersion>8.6.0-preview</OfficialVersion>
4242
</PropertyGroup>
4343

4444
<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">

tests/Tests.AzureAppConfiguration/Unit/AfdTests.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,12 @@ public async Task AfdTests_RegisterAllRefresh()
242242
var mockAsyncPageable4 = new MockAsyncPageable(keyValueCollection3, null, 3, responses4);
243243

244244
mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
245-
.Returns(mockAsyncPageable1)
246-
.Returns(mockAsyncPageable2)
247-
.Returns(mockAsyncPageable3)
248-
.Returns(mockAsyncPageable4);
245+
.Returns(mockAsyncPageable1) // initial load
246+
.Returns(mockAsyncPageable3); // reload after change detected
247+
248+
mockClient.SetupSequence(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
249+
.Returns(mockAsyncPageable2) // first check - stale, should not refresh
250+
.Returns(mockAsyncPageable3); // second check - should trigger refresh
249251

250252
var afdEndpoint = new Uri("https://test.b01.azurefd.net");
251253
IConfigurationRefresher refresher = null;
@@ -381,10 +383,12 @@ public async Task AfdTests_FeatureFlagsRefresh()
381383
mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
382384
.Returns(mockAsyncPageable1) // default load configuration settings
383385
.Returns(mockAsyncPageable1) // load feature flag
386+
.Returns(mockAsyncPageable3) // reload after change detected
387+
.Returns(mockAsyncPageable3); // reload feature flags
388+
389+
mockClient.SetupSequence(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
384390
.Returns(mockAsyncPageable2) // watch request, should not trigger refresh
385-
.Returns(mockAsyncPageable3) // watch request, should trigger refresh
386-
.Returns(mockAsyncPageable3) // default load configuration settings
387-
.Returns(mockAsyncPageable3); // load feature flag
391+
.Returns(mockAsyncPageable3); // watch request, should trigger refresh
388392

389393
var afdEndpoint = new Uri("https://test.b01.azurefd.net");
390394
IConfigurationRefresher refresher = null;

tests/Tests.AzureAppConfiguration/Unit/FeatureManagementTests.cs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,10 @@ public async Task WatchesFeatureFlags()
777777
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
778778
.Returns(mockAsyncPageable);
779779

780+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
781+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
782+
.Returns(mockAsyncPageable);
783+
780784
IConfigurationRefresher refresher = null;
781785
var config = new ConfigurationBuilder()
782786
.AddAzureAppConfiguration(options =>
@@ -849,6 +853,10 @@ public async Task WatchesFeatureFlagsUsingCacheExpirationInterval()
849853
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
850854
.Returns(mockAsyncPageable);
851855

856+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
857+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
858+
.Returns(mockAsyncPageable);
859+
852860
var cacheExpirationInterval = TimeSpan.FromSeconds(1);
853861

854862
IConfigurationRefresher refresher = null;
@@ -923,6 +931,10 @@ public async Task SkipRefreshIfRefreshIntervalHasNotElapsed()
923931
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
924932
.Returns(mockAsyncPageable);
925933

934+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
935+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
936+
.Returns(mockAsyncPageable);
937+
926938
IConfigurationRefresher refresher = null;
927939
var config = new ConfigurationBuilder()
928940
.AddAzureAppConfiguration(options =>
@@ -994,6 +1006,10 @@ public async Task SkipRefreshIfCacheNotExpired()
9941006
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
9951007
.Returns(mockAsyncPageable);
9961008

1009+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
1010+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
1011+
.Returns(mockAsyncPageable);
1012+
9971013
IConfigurationRefresher refresher = null;
9981014
var config = new ConfigurationBuilder()
9991015
.AddAzureAppConfiguration(options =>
@@ -1072,7 +1088,7 @@ public void PreservesDefaultQuery()
10721088
options.UseFeatureFlags();
10731089
}).Build();
10741090

1075-
bool performedDefaultQuery = mockTransport.Requests.Any(r => r.Uri.PathAndQuery.Contains("key=%2A&label=%00"));
1091+
bool performedDefaultQuery = mockTransport.Requests.Any(r => r.Uri.PathAndQuery.Contains("/kv?api-version=2023-11-01&key=%2A&label=%00"));
10761092
bool queriedFeatureFlags = mockTransport.Requests.Any(r => r.Uri.PathAndQuery.Contains(Uri.EscapeDataString(FeatureManagementConstants.FeatureFlagMarker)));
10771093

10781094
Assert.True(performedDefaultQuery);
@@ -1100,7 +1116,7 @@ public void QueriesFeatureFlags()
11001116
})
11011117
.Build();
11021118

1103-
bool performedDefaultQuery = mockTransport.Requests.Any(r => r.Uri.PathAndQuery.Contains("key=%2A&label=%00"));
1119+
bool performedDefaultQuery = mockTransport.Requests.Any(r => r.Uri.PathAndQuery.Contains("/kv?api-version=2023-11-01&key=%2A&label=%00"));
11041120
bool queriedFeatureFlags = mockTransport.Requests.Any(r => r.Uri.PathAndQuery.Contains(Uri.EscapeDataString(FeatureManagementConstants.FeatureFlagMarker)));
11051121

11061122
Assert.True(performedDefaultQuery);
@@ -1118,6 +1134,10 @@ public async Task DoesNotUseEtagForFeatureFlagRefresh()
11181134
.Callback(() => mockAsyncPageable.UpdateCollection(new List<ConfigurationSetting> { _kv }))
11191135
.Returns(mockAsyncPageable);
11201136

1137+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
1138+
.Callback(() => mockAsyncPageable.UpdateCollection(new List<ConfigurationSetting> { _kv }))
1139+
.Returns(mockAsyncPageable);
1140+
11211141
IConfigurationRefresher refresher = null;
11221142
var config = new ConfigurationBuilder()
11231143
.AddAzureAppConfiguration(options =>
@@ -1134,7 +1154,8 @@ public async Task DoesNotUseEtagForFeatureFlagRefresh()
11341154
Thread.Sleep(RefreshInterval);
11351155

11361156
await refresher.TryRefreshAsync();
1137-
mockClient.Verify(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()), Times.Exactly(3));
1157+
mockClient.Verify(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()), Times.Exactly(2));
1158+
mockClient.Verify(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()), Times.Once());
11381159
}
11391160

11401161
[Fact]
@@ -1569,6 +1590,12 @@ public async Task DifferentCacheExpirationsForMultipleFeatureFlagRegistrations()
15691590
(s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix2) && s.Label == label2 && s.Key != FeatureManagementConstants.FeatureFlagMarker + "App2_Feature3")).ToList()))
15701591
.Returns(mockAsyncPageable);
15711592

1593+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
1594+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlagCollection.Where(s =>
1595+
(s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1) ||
1596+
(s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix2) && s.Label == label2 && s.Key != FeatureManagementConstants.FeatureFlagMarker + "App2_Feature3")).ToList()))
1597+
.Returns(mockAsyncPageable);
1598+
15721599
var config = new ConfigurationBuilder()
15731600
.AddAzureAppConfiguration(options =>
15741601
{
@@ -1739,6 +1766,11 @@ public async Task SelectAndRefreshSingleFeatureFlag()
17391766
s.Key.Equals(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1).ToList()))
17401767
.Returns(mockAsyncPageable);
17411768

1769+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
1770+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlagCollection.Where(s =>
1771+
s.Key.Equals(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1).ToList()))
1772+
.Returns(mockAsyncPageable);
1773+
17421774
var config = new ConfigurationBuilder()
17431775
.AddAzureAppConfiguration(options =>
17441776
{
@@ -1802,6 +1834,10 @@ public async Task ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefre
18021834
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
18031835
.Returns(mockAsyncPageable);
18041836

1837+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
1838+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
1839+
.Returns(mockAsyncPageable);
1840+
18051841
mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny<ConfigurationSetting>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
18061842
.ReturnsAsync((Func<ConfigurationSetting, bool, CancellationToken, Response<ConfigurationSetting>>)GetIfChanged);
18071843

@@ -1886,6 +1922,10 @@ public async Task ValidateFeatureFlagsUnchangedLogged()
18861922
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
18871923
.Returns(mockAsyncPageable);
18881924

1925+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
1926+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
1927+
.Returns(mockAsyncPageable);
1928+
18891929
mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny<ConfigurationSetting>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
18901930
.ReturnsAsync((Func<ConfigurationSetting, bool, CancellationToken, Response<ConfigurationSetting>>)GetIfChanged);
18911931

@@ -1964,6 +2004,10 @@ public async Task MapTransformFeatureFlagWithRefresh()
19642004
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
19652005
.Returns(mockAsyncPageable);
19662006

2007+
mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
2008+
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
2009+
.Returns(mockAsyncPageable);
2010+
19672011
mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny<ConfigurationSetting>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
19682012
.ReturnsAsync((Func<ConfigurationSetting, bool, CancellationToken, Response<ConfigurationSetting>>)GetIfChanged);
19692013

0 commit comments

Comments
 (0)