Skip to content

Commit

Permalink
Support completions for private ACR modules
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenWeatherford committed Feb 5, 2025
1 parent 93c5975 commit 657444f
Show file tree
Hide file tree
Showing 101 changed files with 4,024 additions and 1,939 deletions.
2 changes: 1 addition & 1 deletion src/Bicep.Cli.IntegrationTests/BuildCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public async Task Build_Valid_SingleFile_WithDigestReference_ShouldSucceed()
var client = new FakeRegistryBlobClient();

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), registryUri, repository)).Returns(client);
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), registryUri, repository)).Returns(client);

var templateSpecRepositoryFactory = BicepTestConstants.TemplateSpecRepositoryFactory;

Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Cli.IntegrationTests/BuildParamsCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ public async Task Build_bicepparam_should_fail_with_error_diagnostics_for_regist

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), new Uri("https://mockregistry.io"), "parameters/basic"))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), new Uri("https://mockregistry.io"), "parameters/basic"))
.Returns(client.Object);

var templateSpecRepositoryFactory = StrictMock.Of<ITemplateSpecRepositoryFactory>();
Expand Down
5 changes: 3 additions & 2 deletions src/Bicep.Cli.IntegrationTests/LintCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
using Bicep.Cli.UnitTests;
using Bicep.Core.Configuration;
using Bicep.Core.Registry;
using Bicep.Core.Registry.PublicRegistry;
using Bicep.Core.Registry.Catalog;
using Bicep.Core.Samples;
using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Mock;
using Bicep.Core.UnitTests.Mock.Registry;
using Bicep.Core.UnitTests.Mock.Registry.Catalog;
using Bicep.Core.UnitTests.Registry;
using Bicep.Core.UnitTests.Utils;
using FluentAssertions;
Expand Down Expand Up @@ -113,7 +114,7 @@ public async Task Lint_Valid_SingleFile_WithDigestReference_ShouldSucceed()
var client = new FakeRegistryBlobClient();

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), registryUri, repository)).Returns(client);
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), registryUri, repository)).Returns(client);

var settings = new InvocationSettings(new(TestContext, RegistryEnabled: true), clientFactory.Object, BicepTestConstants.TemplateSpecRepositoryFactory);

Expand Down
12 changes: 6 additions & 6 deletions src/Bicep.Cli.IntegrationTests/PublishCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public async Task Publish_AllValidDataSets_ShouldSucceed(string testName, DataSe
var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled);

// mock client factory caches the clients
var testClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration, registryUri, repository);
var testClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration.Cloud, registryUri, repository);

var settings = new InvocationSettings(new(TestContext, RegistryEnabled: true), clientFactory, templateSpecRepositoryFactory);

Expand Down Expand Up @@ -262,7 +262,7 @@ public async Task Publish_ValidArmTemplateFile_AllValidDataSets_ShouldSucceed(Da
var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled);

// mock client factory caches the clients
var testClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration, registryUri, repository);
var testClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration.Cloud, registryUri, repository);

var settings = new InvocationSettings(new(TestContext, RegistryEnabled: true), clientFactory, templateSpecRepositoryFactory);

Expand Down Expand Up @@ -316,7 +316,7 @@ public async Task Publish_ValidArmTemplateFile_WithSource_ShouldFail()
var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled);

// mock client factory caches the clients
var testClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration, registryUri, repository);
var testClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration.Cloud, registryUri, repository);

var settings = new InvocationSettings(new(TestContext, RegistryEnabled: true), clientFactory, templateSpecRepositoryFactory);

Expand Down Expand Up @@ -344,7 +344,7 @@ public async Task Publish_RequestFailedException_ShouldFail()

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), new Uri("https://fake"), "fake"))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), new Uri("https://fake"), "fake"))
.Returns(client.Object);

var templateSpecRepositoryFactory = StrictMock.Of<ITemplateSpecRepositoryFactory>();
Expand Down Expand Up @@ -376,7 +376,7 @@ public async Task Publish_AggregateExceptionWithInnerRequestFailedExceptions_Sho

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), new Uri("https://fake"), "fake"))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), new Uri("https://fake"), "fake"))
.Returns(client.Object);

var templateSpecRepositoryFactory = StrictMock.Of<ITemplateSpecRepositoryFactory>();
Expand Down Expand Up @@ -452,7 +452,7 @@ public async Task Publish_BicepModule_WithDescriptionAndDocUri_ShouldPlaceDescri
var repository = $"test/{moduleName}".ToLowerInvariant();

var clientFactory = RegistryHelper.CreateMockRegistryClient(new RepoDescriptor(registryStr, repository, ["v1"]));
var blobClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration, registryUri, repository);
var blobClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration.Cloud, registryUri, repository);

await RegistryHelper.PublishModuleToRegistryAsync(
new ServiceBuilder(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public async Task Publish_extension_should_succeed()
var version = "0.0.1";

var clientFactory = RegistryHelper.CreateMockRegistryClient(new RepoDescriptor(registryStr, repository, ["tag"]));
var fakeBlobClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration, registryUri, repository);
var fakeBlobClient = (FakeRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration.Cloud, registryUri, repository);

var indexPath = Path.Combine(outputDirectory, "index.json");
var settings = new InvocationSettings(new(TestContext, RegistryEnabled: true), clientFactory, BicepTestConstants.TemplateSpecRepositoryFactory);
Expand Down
16 changes: 8 additions & 8 deletions src/Bicep.Cli.IntegrationTests/RestoreCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ public async Task Restore_ShouldSucceedWithAnonymousClient(string testName, Data
// this will force fallback to the anonymous client
var clientFactoryForRestore = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactoryForRestore
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), It.IsAny<Uri>(), It.IsAny<string>()))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), It.IsAny<Uri>(), It.IsAny<string>()))
.Returns(clientWithCredentialUnavailable.Object);

// anonymous client creation will redirect to the working client factory containing mock published modules
clientFactoryForRestore
.Setup(m => m.CreateAnonymousBlobClient(It.IsAny<RootConfiguration>(), It.IsAny<Uri>(), It.IsAny<string>()))
.Returns<RootConfiguration, Uri, string>(clientFactory.CreateAnonymousBlobClient);
.Setup(m => m.CreateAnonymousBlobClient(It.IsAny<CloudConfiguration>(), It.IsAny<Uri>(), It.IsAny<string>()))
.Returns<CloudConfiguration, Uri, string>(clientFactory.CreateAnonymousBlobClient);

var settings = new InvocationSettings(new(TestContext, RegistryEnabled: dataSet.HasExternalModules), clientFactoryForRestore.Object, templateSpecRepositoryFactory);
TestContext.WriteLine($"Cache root = {settings.FeatureOverrides!.CacheRootDirectory}");
Expand Down Expand Up @@ -310,7 +310,7 @@ public async Task Restore_With_Force_Should_Overwrite_Existing_Cache(bool publis
var client = new FakeRegistryBlobClient();

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), registryUri, repository)).Returns(client);
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), registryUri, repository)).Returns(client);

var templateSpecRepositoryFactory = BicepTestConstants.TemplateSpecRepositoryFactory;

Expand Down Expand Up @@ -431,7 +431,7 @@ public async Task Restore_ByDigest_ShouldSucceed(bool publishSource)
var client = new FakeRegistryBlobClient();

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), registryUri, repository)).Returns(client);
clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), registryUri, repository)).Returns(client);

var templateSpecRepositoryFactory = BicepTestConstants.TemplateSpecRepositoryFactory;

Expand Down Expand Up @@ -518,7 +518,7 @@ public async Task Restore_AggregateExceptionWithInnerRequestFailedExceptions_Sho

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), new Uri("https://fake"), "fake"))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), new Uri("https://fake"), "fake"))
.Returns(client.Object);

var templateSpecRepositoryFactory = StrictMock.Of<ITemplateSpecRepositoryFactory>();
Expand Down Expand Up @@ -550,7 +550,7 @@ public async Task Restore_RequestFailedException_ShouldFail()

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), new Uri("https://fake"), "fake"))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), new Uri("https://fake"), "fake"))
.Returns(client.Object);

var templateSpecRepositoryFactory = StrictMock.Of<ITemplateSpecRepositoryFactory>();
Expand Down Expand Up @@ -579,7 +579,7 @@ public async Task Restore_bicepparam_should_fail_with_error_diagnostics_for_regi

var clientFactory = StrictMock.Of<IContainerRegistryClientFactory>();
clientFactory
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<RootConfiguration>(), new Uri("https://mockregistry.io"), "parameters/basic"))
.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny<CloudConfiguration>(), new Uri("https://mockregistry.io"), "parameters/basic"))
.Returns(client.Object);

var templateSpecRepositoryFactory = StrictMock.Of<ITemplateSpecRepositoryFactory>();
Expand Down
15 changes: 8 additions & 7 deletions src/Bicep.Cli.IntegrationTests/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
using Bicep.Core.Extensions;
using Bicep.Core.FileSystem;
using Bicep.Core.Registry;
using Bicep.Core.Registry.PublicRegistry;
using Bicep.Core.Registry.Catalog.Implementation;
using Bicep.Core.Registry.Catalog.Implementation.PublicRegistries;
using Bicep.Core.Text;
using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Features;
Expand All @@ -23,14 +24,14 @@ namespace Bicep.Cli.IntegrationTests
{
public abstract class TestBase : Bicep.Core.UnitTests.TestBase
{
private static BicepCompiler CreateCompiler(IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicModuleIndexClient? moduleMetadataClient)
private static BicepCompiler CreateCompiler(IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicModuleIndexHttpClient? moduleMetadataClient)
=> ServiceBuilder.Create(
services =>
{
services
.AddSingleton(clientFactory)
.AddSingleton(templateSpecRepositoryFactory)
.AddSingleton<IPublicModuleMetadataProvider, PublicModuleMetadataProvider>();
.AddRegistryCatalogServices();

IServiceCollectionExtensions.AddMockHttpClientIfNotNull(services, moduleMetadataClient);
}
Expand All @@ -49,21 +50,21 @@ protected record InvocationSettings
public IContainerRegistryClientFactory ClientFactory { get; init; }
public ITemplateSpecRepositoryFactory TemplateSpecRepositoryFactory { get; init; }
public IEnvironment? Environment { get; init; }
public IPublicModuleIndexClient ModuleMetadataClient { get; init; }
public IPublicModuleIndexHttpClient ModuleMetadataClient { get; init; }

public InvocationSettings(
FeatureProviderOverrides? FeatureOverrides = null,
IContainerRegistryClientFactory? ClientFactory = null,
ITemplateSpecRepositoryFactory? TemplateSpecRepositoryFactory = null,
IEnvironment? Environment = null,
IPublicModuleIndexClient? ModuleMetadataClient = null)
IPublicModuleIndexHttpClient? ModuleMetadataClient = null)
{
this.FeatureOverrides = FeatureOverrides;
this.ClientFactory = ClientFactory ?? Repository.Create<IContainerRegistryClientFactory>().Object;
this.TemplateSpecRepositoryFactory = TemplateSpecRepositoryFactory ?? Repository.Create<ITemplateSpecRepositoryFactory>().Object;
this.Environment = Environment;

this.ModuleMetadataClient = ModuleMetadataClient ?? StrictMock.Of<IPublicModuleIndexClient>().Object;
this.ModuleMetadataClient = ModuleMetadataClient ?? StrictMock.Of<IPublicModuleIndexHttpClient>().Object;
}
}

Expand Down Expand Up @@ -109,7 +110,7 @@ protected static void AssertNoErrors(string error)
}
}

protected static async Task<IEnumerable<string>> GetAllDiagnostics(string bicepFilePath, IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicModuleIndexClient? moduleMetadataClient = null)
protected static async Task<IEnumerable<string>> GetAllDiagnostics(string bicepFilePath, IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicModuleIndexHttpClient? moduleMetadataClient = null)
{
var compilation = await CreateCompiler(clientFactory, templateSpecRepositoryFactory, moduleMetadataClient).CreateCompilation(PathHelper.FilePathToFileUrl(bicepFilePath));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
using Bicep.Core.Modules;
using Bicep.Core.Registry;
using Bicep.Core.Registry.Oci;
using Bicep.Core.Registry.PublicRegistry;
using Bicep.Core.Registry.Catalog;
using Bicep.Core.Samples;
using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Assertions;
Expand All @@ -26,7 +26,9 @@
using FluentAssertions.Execution;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Bicep.Core.UnitTests.Mock.Registry.Catalog;
using static Bicep.Core.UnitTests.Utils.RegistryHelper;
using Bicep.Core.Registry.Catalog.Implementation.PublicRegistries;

namespace Bicep.Cli.IntegrationTests;

Expand All @@ -41,7 +43,7 @@ public class UseRecentModuleVersionsIntegrationTests : TestBase

private class Options(string CacheRoot)
{
private IPublicModuleIndexClient? _metadataClient = null;
private IPublicModuleIndexHttpClient? _metadataClient = null;
private string? _config = null;

public string Bicep { get; init; } = "/* bicep contents */";
Expand Down Expand Up @@ -75,7 +77,7 @@ public string? BicepConfig
}

// Automatically created from ModulesMetadata by default (set manually for testing)
internal IPublicModuleIndexClient MetadataClient
internal IPublicModuleIndexHttpClient MetadataClient
{
set
{
Expand All @@ -85,7 +87,7 @@ internal IPublicModuleIndexClient MetadataClient
ModulesMetadata.Select(mm => new PublicModuleIndexEntry(
mm.module,
[.. mm.versions],
new Dictionary<string, PublicModuleProperties>().ToImmutableDictionary()))).Object;
new Dictionary<string, PublicModuleIndexProperties>().ToImmutableDictionary()))).Object;
}

}
Expand All @@ -112,26 +114,6 @@ private async Task<CliResult> Test(Options options)
return await Bicep(settings, "lint", mainFile, options.NoRestore ? "--no-restore" : null);
}

[TestMethod]
public async Task IfLevelIsOff_ShouldNotDownloadModuleMetadata()
{
var result = await Test(new Options(CacheRoot)
{
Bicep = """
module m1 '{PREFIX}/fake/avm/res/app/container-app:0.2.0' = {
name: 'm1'
}
""".Replace("{PREFIX}", PREFIX),
DiagnosticLevel = "off",
PublishedModules = [$"{PREFIX}/fake/avm/res/app/container-app:0.2.0"],
MetadataClient = PublicModuleIndexHttpClientMocks.CreateToThrow(new Exception("unit test failed: shouldn't try to download in this scenario")).Object,
});

result.Should().NotHaveStderr();
result.Should().HaveStdout("");
result.Should().Succeed();
}

[TestMethod]
// We don't currently cache to disk, but rather on every check to restore modules.
public async Task IfNoRestoreSpecified_ThenShouldNotDownloadMetadata_AndShouldFailBecauseNoCache()
Expand Down
7 changes: 4 additions & 3 deletions src/Bicep.Cli.IntegrationTests/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -737,10 +737,10 @@
},
"Microsoft.VisualStudio.Threading": {
"type": "Transitive",
"resolved": "17.10.48",
"contentHash": "7onkbbE0AOAhxKe+ZAa2NMzo4R5G4qypZmNIE0GhBohT/tl6e5aLnLx4Gg6trf6SUn3DfLRowMtNe5Q+PmhKgQ==",
"resolved": "17.12.19",
"contentHash": "eLiGMkMYyaSguqHs3lsrFxy3tAWSLuPEL2pIWRcADMDVAs2xqm3dr1d9QYjiEusTgiClF9KD6OB2NdZP72Oy0Q==",
"dependencies": {
"Microsoft.VisualStudio.Threading.Analyzers": "17.10.48",
"Microsoft.VisualStudio.Threading.Analyzers": "17.12.19",
"Microsoft.VisualStudio.Validation": "17.8.8"
}
},
Expand Down Expand Up @@ -1602,6 +1602,7 @@
"Microsoft.Extensions.Http": "[8.0.1, )",
"Microsoft.Graph.Bicep.Types": "[0.1.7-preview, )",
"Microsoft.PowerPlatform.ResourceStack": "[7.0.0.2080, )",
"Microsoft.VisualStudio.Threading": "[17.12.19, )",
"Newtonsoft.Json": "[13.0.3, )",
"Semver": "[3.0.0, )",
"SharpYaml": "[2.1.1, )",
Expand Down
Loading

0 comments on commit 657444f

Please sign in to comment.