diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index ace3e31d8..fc5cf3134 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -10,6 +10,7 @@ Current package versions:
- Format IPv6 endpoints correctly when rewriting configration strings ([#2813 by mgravell](https://github.com/StackExchange/StackExchange.Redis/pull/2813))
- Update default Redis version from 4.0.0 to 6.0.0 for Azure Redis resources ([#2810 by philon-msft](https://github.com/StackExchange/StackExchange.Redis/pull/2810))
+- Detect Azure Managed Redis caches and tune default connection settings for them ([#2818 by philon-msft](https://github.com/StackExchange/StackExchange.Redis/pull/2818))
## 2.8.16
diff --git a/src/StackExchange.Redis/Configuration/AzureOptionsProvider.cs b/src/StackExchange.Redis/Configuration/AzureOptionsProvider.cs
index dcdb9f26a..fb01f0704 100644
--- a/src/StackExchange.Redis/Configuration/AzureOptionsProvider.cs
+++ b/src/StackExchange.Redis/Configuration/AzureOptionsProvider.cs
@@ -21,7 +21,7 @@ public class AzureOptionsProvider : DefaultOptionsProvider
public override Version DefaultVersion => RedisFeatures.v6_0_0;
///
- /// List of domains known to be Azure Redis, so we can light up some helpful functionality
+ /// Lists of domains known to be Azure Redis, so we can light up some helpful functionality
/// for minimizing downtime during maintenance events and such.
///
private static readonly string[] azureRedisDomains = new[]
@@ -29,23 +29,40 @@ public class AzureOptionsProvider : DefaultOptionsProvider
".redis.cache.windows.net",
".redis.cache.chinacloudapi.cn",
".redis.cache.usgovcloudapi.net",
- ".redis.cache.cloudapi.de",
".redisenterprise.cache.azure.net",
};
+ private static readonly string[] azureManagedRedisDomains = new[]
+ {
+ ".redis.azure.net",
+ ".redis.chinacloudapi.cn",
+ ".redis.usgovcloudapi.net",
+ };
+
///
public override bool IsMatch(EndPoint endpoint)
{
if (endpoint is DnsEndPoint dnsEp)
{
- foreach (var host in azureRedisDomains)
+ if (IsHostInDomains(dnsEp.Host, azureRedisDomains) || IsHostInDomains(dnsEp.Host, azureManagedRedisDomains))
{
- if (dnsEp.Host.EndsWith(host, StringComparison.InvariantCultureIgnoreCase))
- {
- return true;
- }
+ return true;
}
}
+
+ return false;
+ }
+
+ private bool IsHostInDomains(string hostName, string[] domains)
+ {
+ foreach (var domain in domains)
+ {
+ if (hostName.EndsWith(domain, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return true;
+ }
+ }
+
return false;
}
@@ -65,6 +82,10 @@ public override bool GetDefaultSsl(EndPointCollection endPoints)
{
return true;
}
+ if (dns.Port == 10000 && IsHostInDomains(dns.Host, azureManagedRedisDomains))
+ {
+ return true; // SSL is enabled by default on AMR caches
+ }
break;
case IPEndPoint ip:
if (ip.Port == 6380)
diff --git a/tests/StackExchange.Redis.Tests/ConfigTests.cs b/tests/StackExchange.Redis.Tests/ConfigTests.cs
index 75f6d25f4..4db6b1163 100644
--- a/tests/StackExchange.Redis.Tests/ConfigTests.cs
+++ b/tests/StackExchange.Redis.Tests/ConfigTests.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Pipelines;
@@ -25,7 +26,6 @@ public class ConfigTests : TestBase
public ConfigTests(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
public Version DefaultVersion = new(3, 0, 0);
- public Version DefaultAzureVersion = new(6, 0, 0);
[Fact]
public void ExpectedFields()
@@ -132,12 +132,21 @@ public void SslProtocols_InvalidValue()
Assert.Throws(() => ConfigurationOptions.Parse("myhost,sslProtocols=InvalidSslProtocol"));
}
- [Fact]
- public void ConfigurationOptionsDefaultForAzure()
- {
- var options = ConfigurationOptions.Parse("contoso.redis.cache.windows.net");
- Assert.True(options.DefaultVersion.Equals(DefaultAzureVersion));
+ [Theory]
+ [InlineData("contoso.redis.cache.windows.net:6380", true)]
+ [InlineData("contoso.REDIS.CACHE.chinacloudapi.cn:6380", true)] // added a few upper case chars to validate comparison
+ [InlineData("contoso.redis.cache.usgovcloudapi.net:6380", true)]
+ [InlineData("contoso.redisenterprise.cache.azure.net:10000", false)]
+ [InlineData("contoso.redis.azure.net:10000", true)]
+ [InlineData("contoso.redis.chinacloudapi.cn:10000", true)]
+ [InlineData("contoso.redis.usgovcloudapi.net:10000", true)]
+ public void ConfigurationOptionsDefaultForAzure(string hostAndPort, bool sslShouldBeEnabled)
+ {
+ Version defaultAzureVersion = new(6, 0, 0);
+ var options = ConfigurationOptions.Parse(hostAndPort);
+ Assert.True(options.DefaultVersion.Equals(defaultAzureVersion));
Assert.False(options.AbortOnConnectFail);
+ Assert.Equal(sslShouldBeEnabled, options.Ssl);
}
[Fact]
@@ -148,31 +157,6 @@ public void ConfigurationOptionsForAzureWhenSpecified()
Assert.True(options.AbortOnConnectFail);
}
- [Fact]
- public void ConfigurationOptionsDefaultForAzureChina()
- {
- // added a few upper case chars to validate comparison
- var options = ConfigurationOptions.Parse("contoso.REDIS.CACHE.chinacloudapi.cn");
- Assert.True(options.DefaultVersion.Equals(DefaultAzureVersion));
- Assert.False(options.AbortOnConnectFail);
- }
-
- [Fact]
- public void ConfigurationOptionsDefaultForAzureGermany()
- {
- var options = ConfigurationOptions.Parse("contoso.redis.cache.cloudapi.de");
- Assert.True(options.DefaultVersion.Equals(DefaultAzureVersion));
- Assert.False(options.AbortOnConnectFail);
- }
-
- [Fact]
- public void ConfigurationOptionsDefaultForAzureUSGov()
- {
- var options = ConfigurationOptions.Parse("contoso.redis.cache.usgovcloudapi.net");
- Assert.True(options.DefaultVersion.Equals(DefaultAzureVersion));
- Assert.False(options.AbortOnConnectFail);
- }
-
[Fact]
public void ConfigurationOptionsDefaultForNonAzure()
{
diff --git a/tests/StackExchange.Redis.Tests/DefaultOptionsTests.cs b/tests/StackExchange.Redis.Tests/DefaultOptionsTests.cs
index 74e52b96d..8c35ab3e1 100644
--- a/tests/StackExchange.Redis.Tests/DefaultOptionsTests.cs
+++ b/tests/StackExchange.Redis.Tests/DefaultOptionsTests.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Configuration;
using System.Linq;
using System.Net;
using System.Threading;
@@ -65,6 +66,21 @@ public void IsMatchOnDomain()
Assert.IsType(provider);
}
+ [Theory]
+ [InlineData("contoso.redis.cache.windows.net")]
+ [InlineData("contoso.REDIS.CACHE.chinacloudapi.cn")] // added a few upper case chars to validate comparison
+ [InlineData("contoso.redis.cache.usgovcloudapi.net")]
+ [InlineData("contoso.redisenterprise.cache.azure.net")]
+ [InlineData("contoso.redis.azure.net")]
+ [InlineData("contoso.redis.chinacloudapi.cn")]
+ [InlineData("contoso.redis.usgovcloudapi.net")]
+ public void IsMatchOnAzureDomain(string hostName)
+ {
+ var epc = new EndPointCollection(new List() { new DnsEndPoint(hostName, 0) });
+ var provider = DefaultOptionsProvider.GetProvider(epc);
+ Assert.IsType(provider);
+ }
+
[Fact]
public void AllOverridesFromDefaultsProp()
{