Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add retries to SDK download in VerifyDotnetFolderContents test #6281

Merged
merged 3 commits into from
Feb 26, 2025
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
95 changes: 42 additions & 53 deletions tests/Microsoft.DotNet.Docker.Tests/SdkImageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Polly;
using Polly.Retry;
using SharpCompress.Common;
using SharpCompress.Readers;
using Xunit;
using Xunit.Abstractions;

#nullable enable
namespace Microsoft.DotNet.Docker.Tests
{
[Trait("Category", "sdk")]
Expand All @@ -25,6 +28,21 @@ public class SdkImageTests : ProductImageTests
private static readonly Dictionary<string, IEnumerable<SdkContentFileInfo>> s_sdkContentsCache =
new Dictionary<string, IEnumerable<SdkContentFileInfo>>();

private static readonly RetryStrategyOptions s_sdkDownloadRetryStrategy =
new()
{
BackoffType = DelayBackoffType.Exponential,
MaxRetryAttempts = 4,
Delay = TimeSpan.FromSeconds(3),
};

private static readonly ResiliencePipeline s_sdkDownloadPipeline =
new ResiliencePipelineBuilder()
.AddRetry(s_sdkDownloadRetryStrategy)
.Build();

private static readonly HttpClient s_httpClient = CreateHttpClient();

public SdkImageTests(ITestOutputHelper outputHelper)
: base(outputHelper)
{
Expand All @@ -36,8 +54,6 @@ public static IEnumerable<object[]> GetImageData()
{
return TestData.GetImageData(DotNetImageRepo.SDK)
.Where(imageData => !imageData.IsDistroless)
// Filter the image data down to the distinct SDK OSes
.Distinct(new SdkImageDataEqualityComparer())
.Select(imageData => new object[] { imageData });
}

Expand Down Expand Up @@ -118,7 +134,7 @@ public void VerifyEnvironmentVariables(ProductImageData imageData)
[MemberData(nameof(GetImageData))]
public void VerifyPowerShellScenario_DefaultUser(ProductImageData imageData)
{
PowerShellScenario_Execute(imageData, null);
PowerShellScenario_Execute(imageData, string.Empty);
}

[DotNetTheory]
Expand Down Expand Up @@ -276,21 +292,14 @@ private async Task<IEnumerable<SdkContentFileInfo>> GetExpectedSdkContentsAsync(
string sdkUrl = GetSdkUrl(imageData);
OutputHelper.WriteLine("Downloading SDK archive: " + sdkUrl);

if (!s_sdkContentsCache.TryGetValue(sdkUrl, out IEnumerable<SdkContentFileInfo> files))
if (!s_sdkContentsCache.TryGetValue(sdkUrl, out IEnumerable<SdkContentFileInfo>? files))
{
string sdkFile = Path.GetTempFileName();

using HttpClient httpClient = new();

if (Config.IsInternal)
await s_sdkDownloadPipeline.ExecuteAsync(async cancellationToken =>
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "",
Config.InternalAccessToken))));
}

await httpClient.DownloadFileAsync(new Uri(sdkUrl), sdkFile);
await s_httpClient.DownloadFileAsync(new Uri(sdkUrl), sdkFile);
});

files = EnumerateArchiveContents(sdkFile)
.OrderBy(file => file.Path)
Expand Down Expand Up @@ -347,7 +356,7 @@ private string GetSdkUrl(ProductImageData imageData)
return url;
}

private void PowerShellScenario_Execute(ProductImageData imageData, string optionalArgs)
private void PowerShellScenario_Execute(ProductImageData imageData, string? optionalArgs = null)
{
string image = imageData.GetImage(DotNetImageRepo.SDK, DockerHelper);

Expand All @@ -368,52 +377,17 @@ private void PowerShellScenario_Execute(ProductImageData imageData, string optio
Assert.Equal(output, bool.TrueString, ignoreCase: true);
}

private class SdkImageDataEqualityComparer : IEqualityComparer<ProductImageData>
private record SdkContentFileInfo
{
public bool Equals([AllowNull] ProductImageData x, [AllowNull] ProductImageData y)
{
if (x is null && y is null)
{
return true;
}

if (x is null && !(y is null))
{
return false;
}

if (!(x is null) && y is null)
{
return false;
}

return x.VersionString == y.VersionString &&
x.SdkOS == y.SdkOS &&
x.Arch == y.Arch;
}
public string Path { get; init; }
public string Sha512 { get; init; }

public int GetHashCode([DisallowNull] ProductImageData obj)
{
return $"{obj.VersionString}-{obj.SdkOS}-{obj.Arch}".GetHashCode();
}
}

private class SdkContentFileInfo : IComparable<SdkContentFileInfo>
{
public SdkContentFileInfo(string path, string sha512)
{
Path = NormalizePath(path);
Sha512 = sha512.ToLower();
}

public string Path { get; }
public string Sha512 { get; }

public int CompareTo([AllowNull] SdkContentFileInfo other)
{
return (Path + Sha512).CompareTo(other.Path + other.Sha512);
}

private static string NormalizePath(string path)
{
return path
Expand All @@ -424,5 +398,20 @@ private static string NormalizePath(string path)
.ToLower();
}
}

private static HttpClient CreateHttpClient()
{
var client = new HttpClient();

if (Config.IsInternal)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "",
Config.InternalAccessToken))));
};

return client;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Polly;
using Polly.CircuitBreaker;
using Polly.Retry;
using Xunit.Abstractions;

Expand Down
Loading