Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<!-- Nuget Package Version Settings -->

<PropertyGroup>
<OfficialVersion>8.5.0-preview</OfficialVersion>
<OfficialVersion>8.6.0-preview</OfficialVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<!-- Nuget Package Version Settings -->

<PropertyGroup>
<OfficialVersion>8.5.0-preview</OfficialVersion>
<OfficialVersion>8.6.0-preview</OfficialVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,27 @@ public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context
return HealthCheckResult.Unhealthy(HealthCheckConstants.NoProviderFoundMessage);
}

HealthCheckResult worstResult = HealthCheckResult.Healthy();

foreach (IHealthCheck healthCheck in _healthChecks)
{
var result = await healthCheck.CheckHealthAsync(context, cancellationToken).ConfigureAwait(false);

// Keep track of the worst health status found
// HealthStatus enum is ordered: Unhealthy(0) < Degraded(1) < Healthy(2)
if (result.Status < worstResult.Status)
{
worstResult = result;
}

// If an Unhealthy status is found, short-circuit since that's the worst possible
if (result.Status == HealthStatus.Unhealthy)
{
return result;
}
}

return HealthCheckResult.Healthy();
return worstResult;
}

private void FindHealthChecks(IConfigurationRoot configurationRoot, List<IHealthCheck> healthChecks)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,15 +576,17 @@ public void ProcessPushNotification(PushNotification pushNotification, TimeSpan?

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
HealthStatus failureStatus = context.Registration?.FailureStatus ?? HealthStatus.Unhealthy;

if (!_lastSuccessfulAttempt.HasValue)
{
return HealthCheckResult.Unhealthy(HealthCheckConstants.LoadNotCompletedMessage);
return new HealthCheckResult(status: failureStatus, description: HealthCheckConstants.LoadNotCompletedMessage);
}

if (_lastFailedAttempt.HasValue &&
_lastSuccessfulAttempt.Value < _lastFailedAttempt.Value)
{
return HealthCheckResult.Unhealthy(HealthCheckConstants.RefreshFailedMessage);
return new HealthCheckResult(status: failureStatus, description: HealthCheckConstants.RefreshFailedMessage);
}

return HealthCheckResult.Healthy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ private void FindRefreshers(IConfigurationRoot configurationRoot, ILoggerFactory
{
foreach (IConfigurationProvider provider in configurationRoot.Providers)
{
if (provider is AzureAppConfigurationProvider appConfigurationProvider)
if (provider is IConfigurationRefresher configurationRefresher)
{
appConfigurationProvider.LoggerFactory = loggerFactory;
refreshers.Add(appConfigurationProvider);
refreshers.Add(configurationRefresher);

if (configurationRefresher is AzureAppConfigurationProvider azureAppConfigurationProvider)
{
azureAppConfigurationProvider.LoggerFactory = loggerFactory;
}
}
else if (provider is ChainedConfigurationProvider chainedProvider)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public static async Task<bool> HaveCollectionsChanged(
LabelFilter = keyValueSelector.LabelFilter
};

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

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

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

Expand All @@ -15,7 +15,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Data.AppConfiguration" Version="1.7.0" />
<PackageReference Include="Azure.Data.AppConfiguration" Version="1.8.0" />
<PackageReference Include="Azure.Messaging.EventGrid" Version="5.0.0" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.8.0" />
<PackageReference Include="DnsClient" Version="1.7.0" />
Expand All @@ -38,7 +38,7 @@
<!-- Nuget Package Version Settings -->

<PropertyGroup>
<OfficialVersion>8.5.0-preview</OfficialVersion>
<OfficialVersion>8.6.0-preview</OfficialVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">
Expand Down
18 changes: 11 additions & 7 deletions tests/Tests.AzureAppConfiguration/Unit/AfdTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,12 @@ public async Task AfdTests_RegisterAllRefresh()
var mockAsyncPageable4 = new MockAsyncPageable(keyValueCollection3, null, 3, responses4);

mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Returns(mockAsyncPageable1)
.Returns(mockAsyncPageable2)
.Returns(mockAsyncPageable3)
.Returns(mockAsyncPageable4);
.Returns(mockAsyncPageable1) // initial load
.Returns(mockAsyncPageable3); // reload after change detected

mockClient.SetupSequence(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Returns(mockAsyncPageable2) // first check - stale, should not refresh
.Returns(mockAsyncPageable3); // second check - should trigger refresh

var afdEndpoint = new Uri("https://test.b01.azurefd.net");
IConfigurationRefresher refresher = null;
Expand Down Expand Up @@ -381,10 +383,12 @@ public async Task AfdTests_FeatureFlagsRefresh()
mockClient.SetupSequence(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Returns(mockAsyncPageable1) // default load configuration settings
.Returns(mockAsyncPageable1) // load feature flag
.Returns(mockAsyncPageable3) // reload after change detected
.Returns(mockAsyncPageable3); // reload feature flags

mockClient.SetupSequence(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Returns(mockAsyncPageable2) // watch request, should not trigger refresh
.Returns(mockAsyncPageable3) // watch request, should trigger refresh
.Returns(mockAsyncPageable3) // default load configuration settings
.Returns(mockAsyncPageable3); // load feature flag
.Returns(mockAsyncPageable3); // watch request, should trigger refresh

var afdEndpoint = new Uri("https://test.b01.azurefd.net");
IConfigurationRefresher refresher = null;
Expand Down
50 changes: 47 additions & 3 deletions tests/Tests.AzureAppConfiguration/Unit/FeatureManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,10 @@ public async Task WatchesFeatureFlags()
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

IConfigurationRefresher refresher = null;
var config = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
Expand Down Expand Up @@ -849,6 +853,10 @@ public async Task WatchesFeatureFlagsUsingCacheExpirationInterval()
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

var cacheExpirationInterval = TimeSpan.FromSeconds(1);

IConfigurationRefresher refresher = null;
Expand Down Expand Up @@ -923,6 +931,10 @@ public async Task SkipRefreshIfRefreshIntervalHasNotElapsed()
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

IConfigurationRefresher refresher = null;
var config = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
Expand Down Expand Up @@ -994,6 +1006,10 @@ public async Task SkipRefreshIfCacheNotExpired()
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

IConfigurationRefresher refresher = null;
var config = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
Expand Down Expand Up @@ -1072,7 +1088,7 @@ public void PreservesDefaultQuery()
options.UseFeatureFlags();
}).Build();

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

Assert.True(performedDefaultQuery);
Expand Down Expand Up @@ -1100,7 +1116,7 @@ public void QueriesFeatureFlags()
})
.Build();

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

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

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(new List<ConfigurationSetting> { _kv }))
.Returns(mockAsyncPageable);

IConfigurationRefresher refresher = null;
var config = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
Expand All @@ -1134,7 +1154,8 @@ public async Task DoesNotUseEtagForFeatureFlagRefresh()
Thread.Sleep(RefreshInterval);

await refresher.TryRefreshAsync();
mockClient.Verify(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()), Times.Exactly(3));
mockClient.Verify(c => c.GetConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()), Times.Exactly(2));
mockClient.Verify(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()), Times.Once());
}

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

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlagCollection.Where(s =>
(s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1) ||
(s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix2) && s.Label == label2 && s.Key != FeatureManagementConstants.FeatureFlagMarker + "App2_Feature3")).ToList()))
.Returns(mockAsyncPageable);

var config = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
{
Expand Down Expand Up @@ -1739,6 +1766,11 @@ public async Task SelectAndRefreshSingleFeatureFlag()
s.Key.Equals(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1).ToList()))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlagCollection.Where(s =>
s.Key.Equals(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1).ToList()))
.Returns(mockAsyncPageable);

var config = new ConfigurationBuilder()
.AddAzureAppConfiguration(options =>
{
Expand Down Expand Up @@ -1802,6 +1834,10 @@ public async Task ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefre
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny<ConfigurationSetting>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((Func<ConfigurationSetting, bool, CancellationToken, Response<ConfigurationSetting>>)GetIfChanged);

Expand Down Expand Up @@ -1886,6 +1922,10 @@ public async Task ValidateFeatureFlagsUnchangedLogged()
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny<ConfigurationSetting>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((Func<ConfigurationSetting, bool, CancellationToken, Response<ConfigurationSetting>>)GetIfChanged);

Expand Down Expand Up @@ -1964,6 +2004,10 @@ public async Task MapTransformFeatureFlagWithRefresh()
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.CheckConfigurationSettingsAsync(It.IsAny<SettingSelector>(), It.IsAny<CancellationToken>()))
.Callback(() => mockAsyncPageable.UpdateCollection(featureFlags))
.Returns(mockAsyncPageable);

mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny<ConfigurationSetting>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((Func<ConfigurationSetting, bool, CancellationToken, Response<ConfigurationSetting>>)GetIfChanged);

Expand Down
Loading
Loading