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

[ACR] Add performance tests for common scenarios #21229

Merged
merged 7 commits into from
May 21, 2021
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Containers.ContainerR
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core", "..\..\core\Azure.Core\src\Azure.Core.csproj", "{F62DCD51-5101-4427-B6C9-C24974F9DD3F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Containers.ContainerRegistry.Perf", "perf\Azure.Containers.ContainerRegistry.Perf\Azure.Containers.ContainerRegistry.Perf.csproj", "{D8B4B378-8339-44AB-BBEC-056B82A15A0A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -45,6 +47,10 @@ Global
{F62DCD51-5101-4427-B6C9-C24974F9DD3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F62DCD51-5101-4427-B6C9-C24974F9DD3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F62DCD51-5101-4427-B6C9-C24974F9DD3F}.Release|Any CPU.Build.0 = Release|Any CPU
{D8B4B378-8339-44AB-BBEC-056B82A15A0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8B4B378-8339-44AB-BBEC-056B82A15A0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8B4B378-8339-44AB-BBEC-056B82A15A0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8B4B378-8339-44AB-BBEC-056B82A15A0A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Management.ContainerRegistry" VersionOverride="4.0.0" />
<PackageReference Include="Microsoft.Azure.Management.ContainerRegistry.Fluent"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\src\Azure.Containers.ContainerRegistry.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\..\..\..\common\Perf\Azure.Test.Perf\Azure.Test.Perf.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Azure.Test.Perf;
using Microsoft.Azure.Management.ContainerRegistry;
using Microsoft.Azure.Management.ContainerRegistry.Models;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using Task = System.Threading.Tasks.Task;

namespace Azure.Containers.ContainerRegistry.Perf
{
public abstract class ContainerRegistryPerfTest<TOptions> : PerfTest<TOptions> where TOptions : PerfOptions
annelo-msft marked this conversation as resolved.
Show resolved Hide resolved
{
public ContainerRegistryPerfTest(TOptions options) : base(options)
{
}

public async Task ImportImage(string registry, string repository, string tag)
{
await ImportImage(registry, repository, new List<string>() { tag });
}

public async Task ImportImage(string registry, string repository, List<string> tags)
annelo-msft marked this conversation as resolved.
Show resolved Hide resolved
{
var credential = new AzureCredentials(
new ServicePrincipalLoginInformation
{
ClientId = PerfTestEnvironment.Instance.ClientId,
ClientSecret = PerfTestEnvironment.Instance.ClientSecret,
},
PerfTestEnvironment.Instance.TenantId,
AzureEnvironment.AzureGlobalCloud);

var managementClient = new ContainerRegistryManagementClient(credential.WithDefaultSubscription(PerfTestEnvironment.Instance.SubscriptionId));
managementClient.SubscriptionId = PerfTestEnvironment.Instance.SubscriptionId;

var importSource = new ImportSource
{
SourceImage = repository,
RegistryUri = "registry.hub.docker.com"
};

var targetTags = tags.Select(tag => $"{repository}:{tag}");

await managementClient.Registries.ImportImageAsync(
resourceGroupName: PerfTestEnvironment.Instance.ResourceGroup,
registryName: registry,
parameters:
new ImportImageParameters
{
Mode = ImportMode.Force,
Source = importSource,
TargetTags = targetTags.ToList()
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Azure.Core.TestFramework;

namespace Azure.Containers.ContainerRegistry.Perf
{
/// <summary>
/// Represents the ambient environment in which the test suite is being run, offering access to information such as environment variables.
/// </summary>
internal sealed class PerfTestEnvironment : TestEnvironment
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the ContainerRegistryEnvironment be used instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses recorded variables? Honestly, I was following the README and Search and FormRecognizer examples. Beyond a small amount of code duplication, is it a concern?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think it is a concern - I was mostly curious why there was a separate TestEnvironment. I see that you don't actually have a dependency on your test project from here so it may not make sense to do so.

FWIW, I don't think it would matter that the environment uses Recorded variables as the RecordedTestMode? Mode property would end up being null (I think).

{
/// <summary>
/// The shared instance of the <see cref="PerfTestEnvironment"/> to be used during test runs.
/// </summary>
public static PerfTestEnvironment Instance { get; } = new PerfTestEnvironment();

/// <summary>
/// The endpoint of the Container Registry resource to test against.
/// </summary>
/// <value>The endpoint, read from the "CONTAINERREGISTRY_ENDPOINT" environment variable.</value>
public string Endpoint => GetRecordedVariable("CONTAINERREGISTRY_ENDPOINT");

/// <summary>
/// The name of the registry to test against.
/// </summary>
/// <value>The registry name, read from the "CONTAINERREGISTRY_REGISTRY_NAME" environment variable.</value>
public string Registry => GetRecordedVariable("CONTAINERREGISTRY_REGISTRY_NAME");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Reflection;
using Azure.Test.Perf;

await PerfProgram.Main(Assembly.GetEntryAssembly(), args);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Azure Container Registry performance tests

This folder contains performance tests for the [Azure Container Registry client library for .NET](https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/containerregistry/Azure.Containers.ContainerRegistry) and its associated ecosystem. The artifacts in this library are intended to be used primarily with the Azure SDK engineering system's testing infrastructure, but may also be run as stand-alone applications from the command line.

## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

Please see our [contributing guide](https://github.com/Azure/azure-sdk-for-net/blob/master/CONTRIBUTING.md) for more information.

![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Fcontainerregistry%2FAzure.Containers.ContainerRegistry.Perf%2FREADME.png)
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Azure.Containers.ContainerRegistry;
using Azure.Test.Perf;

namespace Azure.Containers.ContainerRegistry.Perf
{
public sealed class ListArtifacts : ContainerRegistryPerfTest<PerfOptions>
{
private readonly ContainerRegistryClient _client;

public ListArtifacts(PerfOptions options) : base(options)
{
_client = new ContainerRegistryClient(new Uri(PerfTestEnvironment.Instance.Endpoint), PerfTestEnvironment.Instance.Credential);
}

public override async Task GlobalSetupAsync()
{
// Global setup code that runs once at the beginning of test execution.
await base.GlobalSetupAsync();

string repository = $"library/node";
string tag = "test-perf";

await ImportImage(PerfTestEnvironment.Instance.Registry, repository, tag);
}

public override async Task SetupAsync()
{
// Individual test-level setup code that runs for each instance of the test.
await base.SetupAsync();
}

public override async Task CleanupAsync()
{
// Individual test-level cleanup code that runs for each instance of the test.
await base.CleanupAsync();
}

public override async Task GlobalCleanupAsync()
{
// Global cleanup code that runs once at the end of test execution.
await base.GlobalCleanupAsync();
}
annelo-msft marked this conversation as resolved.
Show resolved Hide resolved

public override void Run(CancellationToken cancellationToken)
{
var artifactNames = new List<string>();

var repository = _client.GetRepository($"library/node");
annelo-msft marked this conversation as resolved.
Show resolved Hide resolved
foreach (var manifest in repository.GetManifests())
{
var artifact = _client.GetArtifact($"library/node", manifest.Digest);
artifactNames.Add(artifact.FullyQualifiedName);
annelo-msft marked this conversation as resolved.
Show resolved Hide resolved
}
}

public override async Task RunAsync(CancellationToken cancellationToken)
{
var artifactNames = new List<string>();

var repository = _client.GetRepository($"library/node");
await foreach (var manifest in repository.GetManifestsAsync())
{
var artifact = _client.GetArtifact($"library/node", manifest.Digest);
artifactNames.Add(artifact.FullyQualifiedName);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Azure.Containers.ContainerRegistry;
using Azure.Test.Perf;

namespace Azure.Containers.ContainerRegistry.Perf
{
public sealed class ListRepositories : ContainerRegistryPerfTest<PerfOptions>
annelo-msft marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly ContainerRegistryClient _client;

public ListRepositories(PerfOptions options) : base(options)
{
_client = new ContainerRegistryClient(new Uri(PerfTestEnvironment.Instance.Endpoint), PerfTestEnvironment.Instance.Credential);
}

public override async Task GlobalSetupAsync()
{
// Global setup code that runs once at the beginning of test execution.
await base.GlobalSetupAsync();
}

public override async Task SetupAsync()
{
// Individual test-level setup code that runs for each instance of the test.
await base.SetupAsync();
}

public override async Task CleanupAsync()
{
// Individual test-level cleanup code that runs for each instance of the test.
await base.CleanupAsync();
}

public override async Task GlobalCleanupAsync()
{
// Global cleanup code that runs once at the end of test execution.
await base.GlobalCleanupAsync();
}

public override void Run(CancellationToken cancellationToken)
{
var names = new List<string>();
foreach (var repositoryName in _client.GetRepositoryNames())
{
names.Add(repositoryName);
}
}

public override async Task RunAsync(CancellationToken cancellationToken)
{
var names = new List<string>();
await foreach (var repositoryName in _client.GetRepositoryNamesAsync())
{
names.Add(repositoryName);
}
}
}
}