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

Implement provider declaration aliasing #12127

Merged
merged 21 commits into from
Oct 23, 2023
Merged
17 changes: 11 additions & 6 deletions src/Bicep.Cli.IntegrationTests/BuildCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,18 @@ public async Task Build_Valid_SingleFile_WithTemplateSpecReference_ShouldSucceed
actualLocation: compiledFilePath);
}

[TestMethod]
public async Task Provider_Artifacts_Restore_From_Registry_ShouldSucceed()
[DataTestMethod]
[DataRow("br:mcr.microsoft.com/bicep/providers/az", true)]
[DataRow("br/public:az", true)]
//[DataRow("br/contoso:az", true)]
// Negative
//[DataRow("az", false)]
public async Task Build_Valid_SingleFile_WithProviderDeclarationStatement(string providerDeclarationSyntax, bool shouldSucceed)
{
// SETUP
// 1. create a mock registry client
var registryUri = new Uri($"https://{LanguageConstants.BicepPublicMcrRegistry}");
var repository = $"bicep/providers/az";
var repository = "bicep/providers/az";
var (clientFactory, blobClients) = DataSetsExtensions.CreateMockRegistryClients(false, (registryUri, repository));
var myClient = blobClients[(registryUri, repository)];

Expand Down Expand Up @@ -142,8 +147,8 @@ public async Task Provider_Artifacts_Restore_From_Registry_ShouldSucceed()
await myClient.UploadBlobAsync(new MemoryStream());

// 3. create a main.bicep and save it to a output directory
var bicepFile = """
import 'az@2.0.0'
var bicepFile = $"""
import '{providerDeclarationSyntax}@2.0.0'
""";
var tempDirectory = FileHelper.GetUniqueTestOutputPath(TestContext);
Directory.CreateDirectory(tempDirectory);
Expand All @@ -161,7 +166,7 @@ public async Task Provider_Artifacts_Restore_From_Registry_ShouldSucceed()
// 6. assert 'bicep build' completed successfully
using (new AssertionScope())
{
result.Should().Be(0);
result.Should().Be(shouldSucceed ? 0 : 1);
output.Should().BeEmpty();
AssertNoErrors(error);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Bicep.Core.IntegrationTests/ExtensibilityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ param connectionString string
public void Az_namespace_can_be_used_without_configuration()
{
var result = CompilationHelper.Compile(Services, @"
import '[email protected]'
import 'br/public:[email protected]'
");

result.Should().GenerateATemplate();
Expand All @@ -635,7 +635,7 @@ public void Az_namespace_can_be_used_without_configuration()
public void Az_namespace_errors_with_configuration()
{
var result = CompilationHelper.Compile(Services, @"
import '[email protected]' with {}
import 'br/public:[email protected]' with {}
");

result.Should().NotGenerateATemplate();
Expand Down
20 changes: 10 additions & 10 deletions src/Bicep.Core.IntegrationTests/ImportTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public TestNamespaceProvider(Dictionary<string, Func<string, NamespaceType>> bui
public void Imports_are_disabled_unless_feature_is_enabled()
{
var result = CompilationHelper.Compile(@"
import '[email protected]'
import 'br/public:[email protected]'
");
result.Should().HaveDiagnostics(new[] {
("BCP203", DiagnosticLevel.Error, "Using import statements requires enabling EXPERIMENTAL feature \"Extensibility\"."),
Expand All @@ -74,7 +74,7 @@ public void Import_statement_parse_diagnostics_are_guiding()
});

result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' blahblah
import 'br/public:[email protected]' blahblah
");
result.Should().HaveDiagnostics(new[] {
("BCP305", DiagnosticLevel.Error, "Expected the \"with\" keyword, \"as\" keyword, or a new line character at this location."),
Expand Down Expand Up @@ -108,7 +108,7 @@ public void Import_statement_parse_diagnostics_are_guiding()
});

result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' as
import 'br/public:[email protected]' as
");
result.Should().HaveDiagnostics(new[] {
("BCP202", DiagnosticLevel.Error, "Expected an import alias name at this location."),
Expand All @@ -130,7 +130,7 @@ public void Imports_return_error_with_unrecognized_namespace()
public void Import_configuration_is_blocked_by_default()
{
var result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' with {
import 'br/public:[email protected]' with {
foo: 'bar'
}
");
Expand All @@ -143,7 +143,7 @@ public void Import_configuration_is_blocked_by_default()
public void Using_import_statements_frees_up_the_namespace_symbol()
{
var result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' as newAz
import 'br/public:[email protected]' as newAz

var az = 'Fake AZ!'
var myRg = newAz.resourceGroup()
Expand All @@ -159,7 +159,7 @@ public void Using_import_statements_frees_up_the_namespace_symbol()
public void You_can_swap_imported_namespaces_if_you_really_really_want_to()
{
var result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' as sys
import 'br/public:[email protected]' as sys
import '[email protected]' as az
asilverman marked this conversation as resolved.
Show resolved Hide resolved

var myRg = sys.resourceGroup()
Expand All @@ -176,7 +176,7 @@ public void You_can_swap_imported_namespaces_if_you_really_really_want_to()
public void Overwriting_single_built_in_namespace_with_import_is_prohibited()
{
var result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' as sys
import 'br/public:[email protected]' as sys

var myRg = sys.resourceGroup()

Expand All @@ -190,8 +190,8 @@ public void Overwriting_single_built_in_namespace_with_import_is_prohibited()
public void Singleton_imports_cannot_be_used_multiple_times()
{
var result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]' as az1
import '[email protected]' as az2
import 'br/public:[email protected]' as az1
import 'br/public:[email protected]' as az2

import '[email protected]' as sys1
import '[email protected]' as sys2
Expand All @@ -209,7 +209,7 @@ public void Singleton_imports_cannot_be_used_multiple_times()
public void Import_names_must_not_conflict_with_other_symbols()
{
var result = CompilationHelper.Compile(ServicesWithImports, @"
import '[email protected]'
import 'br/public:[email protected]'
import '[email protected]' with {
kubeConfig: ''
namespace: ''
Expand Down
6 changes: 3 additions & 3 deletions src/Bicep.Core.IntegrationTests/RegistryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public async Task ModuleRestoreWithStuckFileLockShouldFailAfterTimeout(IEnumerab
dispatcher.GetArtifactRestoreStatus(moduleReference, out _).Should().Be(ArtifactRestoreStatus.Unknown);
}

dispatcher.TryGetLocalModuleEntryPointUri(moduleReferences[0]).IsSuccess(out var moduleFileUri).Should().BeTrue();
dispatcher.TryGetLocalArtifactEntryPointUri(moduleReferences[0]).IsSuccess(out var moduleFileUri).Should().BeTrue();
moduleFileUri.Should().NotBeNull();

var moduleFilePath = moduleFileUri!.LocalPath;
Expand Down Expand Up @@ -318,7 +318,7 @@ public async Task ForceModuleRestoreWithStuckFileLockShouldFailAfterTimeout(IEnu
dispatcher.GetArtifactRestoreStatus(moduleReference, out _).Should().Be(ArtifactRestoreStatus.Unknown);
}

dispatcher.TryGetLocalModuleEntryPointUri(moduleReferences[0]).IsSuccess(out var moduleFileUri).Should().BeTrue();
dispatcher.TryGetLocalArtifactEntryPointUri(moduleReferences[0]).IsSuccess(out var moduleFileUri).Should().BeTrue();
moduleFileUri.Should().NotBeNull();

var moduleFilePath = moduleFileUri!.LocalPath;
Expand Down Expand Up @@ -395,7 +395,7 @@ public async Task ForceModuleRestoreShouldRestoreAllModules(IEnumerable<External
dispatcher.GetArtifactRestoreStatus(moduleReference, out _).Should().Be(ArtifactRestoreStatus.Unknown);
}

dispatcher.TryGetLocalModuleEntryPointUri(moduleReferences[0]).IsSuccess(out var moduleFileUri).Should().BeTrue();
dispatcher.TryGetLocalArtifactEntryPointUri(moduleReferences[0]).IsSuccess(out var moduleFileUri).Should().BeTrue();
moduleFileUri.Should().NotBeNull();

var moduleFilePath = moduleFileUri!.LocalPath;
Expand Down
3 changes: 2 additions & 1 deletion src/Bicep.Core.Samples/DataSetsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Threading.Tasks;
using Bicep.Core.Configuration;
using Bicep.Core.FileSystem;
using Bicep.Core.Registry.Oci;
using Bicep.Core.Modules;
using Bicep.Core.Registry;
using Bicep.Core.Semantics;
Expand Down Expand Up @@ -72,7 +73,7 @@ public static Mock<IContainerRegistryClientFactory> CreateMockRegistryClients(Im
{
var target = publishInfo.Metadata.Target;

if (!dispatcher.TryGetModuleReference(target, RandomFileUri()).IsSuccess(out var @ref) || @ref is not OciModuleReference targetReference)
if (!dispatcher.TryGetModuleReference(target, RandomFileUri()).IsSuccess(out var @ref) || @ref is not OciArtifactReference targetReference)
{
throw new InvalidOperationException($"Module '{moduleName}' has an invalid target reference '{target}'. Specify a reference to an OCI artifact.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import '[email protected]'
import 'br/public:[email protected]'

output str string = 'foo'
1 change: 1 addition & 0 deletions src/Bicep.Core.UnitTests/BicepTestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public static RootConfiguration CreateMockConfiguration(Dictionary<string, objec
["cloud.profiles.AzureCloud.activeDirectoryAuthority"] = "https://example.invalid",
["cloud.credentialPrecedence"] = new[] { "AzureCLI", "AzurePowerShell" },
["moduleAliases"] = new Dictionary<string, object>(),
["providerAliases"] = new Dictionary<string, object>(),
["analyzers"] = new Dictionary<string, object>(),
["experimentalFeaturesEnabled"] = new Dictionary<string, bool>(),
["formatting"] = new Dictionary<string, bool>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ public void GetBuiltInConfiguration_NoParameter_ReturnsBuiltInConfigurationWithA
}
}
},
"providerAliases": {
"br": {
"public": {
"registry": "mcr.microsoft.com",
"providerPath": "bicep/providers"
}
}
},
"analyzers": {
"core": {
"verbose": false,
Expand Down Expand Up @@ -168,6 +176,14 @@ public void GetBuiltInConfiguration_DisableAllAnalyzers_ReturnsBuiltInConfigurat
}
}
},
"providerAliases": {
"br": {
"public": {
"registry": "mcr.microsoft.com",
"providerPath": "bicep/providers"
}
}
},
"analyzers": {},
"experimentalFeaturesEnabled": {
"symbolicNameCodegen": false,
Expand Down Expand Up @@ -234,6 +250,14 @@ public void GetBuiltInConfiguration_DisableAnalyzers_ReturnsBuiltInConfiguration
}
}
},
"providerAliases": {
"br": {
"public": {
"registry": "mcr.microsoft.com",
"providerPath": "bicep/providers"
}
}
},
"analyzers": {
"core": {
"verbose": false,
Expand Down Expand Up @@ -483,6 +507,14 @@ public void GetConfiguration_ValidCustomConfiguration_OverridesBuiltInConfigurat
}
}
},
"providerAliases": {
"br": {
"public": {
"registry": "mcr.microsoft.com",
"providerPath": "bicep/providers"
}
}
},
"analyzers": {
"core": {
"enabled": false,
Expand Down Expand Up @@ -573,6 +605,14 @@ public void GetConfiguration_ValidCustomConfiguration_OverridesBuiltInConfigurat
}
}
},
"providerAliases": {
"br": {
"public": {
"registry": "mcr.microsoft.com",
"providerPath": "bicep/providers"
}
}
},
"analyzers": {
"core": {
"verbose": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public void RootConfiguration_LeadingTildeInCacheRootDirectory_ExpandPath(string
var configuration = new RootConfiguration(
BicepTestConstants.BuiltInConfiguration.Cloud,
BicepTestConstants.BuiltInConfiguration.ModuleAliases,
BicepTestConstants.BuiltInConfiguration.ProviderAliases,
BicepTestConstants.BuiltInConfiguration.Analyzers,
cacheRootDirectory,
BicepTestConstants.BuiltInConfiguration.ExperimentalFeaturesEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public void If_OutputReferencesSecureParamProperty_ShouldFail(string text, param
CompileAndTest(text, OnCompileErrors.IncludeErrors, expectedMessages, config => new(
config.Cloud,
config.ModuleAliases,
config.ProviderAliases,
config.Analyzers,
config.CacheRootDirectory,
config.ExperimentalFeaturesEnabled with { UserDefinedTypes = true },
Expand Down Expand Up @@ -228,6 +229,7 @@ public void If_OutputReferencesParamWithSecureProperty_ShouldFail(string text, p
CompileAndTest(text, OnCompileErrors.IncludeErrors, expectedMessages, config => new(
config.Cloud,
config.ModuleAliases,
config.ProviderAliases,
config.Analyzers,
config.CacheRootDirectory,
config.ExperimentalFeaturesEnabled with { UserDefinedTypes = true },
Expand Down Expand Up @@ -279,6 +281,7 @@ public void If_OutputReferencesNonSecureParamProperty_ShouldPass(string text, pa
CompileAndTest(text, OnCompileErrors.IncludeErrors, expectedMessages, config => new(
config.Cloud,
config.ModuleAliases,
config.ProviderAliases,
config.Analyzers,
config.CacheRootDirectory,
config.ExperimentalFeaturesEnabled with { UserDefinedTypes = true },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ private static RootConfiguration CreateConfigurationWithFakeToday(RootConfigurat
return new RootConfiguration(
original.Cloud,
original.ModuleAliases,
original.ProviderAliases,
new AnalyzersConfiguration(
JsonElementFactory.CreateElement(@"
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Bicep.Core.Configuration;
using Bicep.Core.FileSystem;
using Bicep.Core.Modules;
using Bicep.Core.Registry.Oci;
using Bicep.Core.UnitTests.Assertions;
using FluentAssertions;
using FluentAssertions.Execution;
Expand Down Expand Up @@ -103,7 +104,7 @@ public void ValidReferenceShouldBeUriParseable(ValidCase @case)
[DataTestMethod]
public void InvalidReferencesShouldProduceExpectedError(string value, string expectedCode, string expectedError)
{
OciModuleReference.TryParse(null, value, BicepTestConstants.BuiltInConfigurationWithAllAnalyzersDisabled, RandomFileUri()).IsSuccess(out var @ref, out var failureBuilder).Should().BeFalse();
OciArtifactReference.TryParse(OciArtifactReferenceType.Module, null, value, BicepTestConstants.BuiltInConfigurationWithAllAnalyzersDisabled, RandomFileUri()).IsSuccess(out var @ref, out var failureBuilder).Should().BeFalse();
@ref.Should().BeNull();
failureBuilder!.Should().NotBeNull();

Expand Down Expand Up @@ -145,7 +146,7 @@ public void MismatchedReferencesShouldNotBeEqual(string package1, string package
[DataRow("foo bar ÄÄÄ")]
public void TryParse_InvalidAliasName_ReturnsFalseAndSetsErrorDiagnostic(string aliasName)
{
OciModuleReference.TryParse(aliasName, "", BicepTestConstants.BuiltInConfiguration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeFalse();
OciArtifactReference.TryParse(OciArtifactReferenceType.Module, aliasName, "", BicepTestConstants.BuiltInConfiguration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeFalse();

reference.Should().BeNull();
errorBuilder!.Should().HaveCode("BCP211");
Expand All @@ -159,7 +160,7 @@ public void TryParse_AliasNotInConfiguration_ReturnsFalseAndSetsErrorDiagnostic(
{
var configuration = BicepTestConstants.CreateMockConfiguration(configurationPath: configurationPath);

OciModuleReference.TryParse(aliasName, referenceValue, configuration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeFalse();
OciArtifactReference.TryParse(OciArtifactReferenceType.Module, aliasName, referenceValue, configuration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeFalse();

reference.Should().BeNull();
errorBuilder!.Should().NotBeNull();
Expand All @@ -171,7 +172,7 @@ public void TryParse_AliasNotInConfiguration_ReturnsFalseAndSetsErrorDiagnostic(
[DynamicData(nameof(GetInvalidAliasData), DynamicDataSourceType.Method)]
public void TryParse_InvalidAlias_ReturnsFalseAndSetsErrorDiagnostic(string aliasName, string referenceValue, RootConfiguration configuration, string expectedCode, string expectedMessage)
{
OciModuleReference.TryParse(aliasName, referenceValue, configuration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeFalse();
OciArtifactReference.TryParse(OciArtifactReferenceType.Module, aliasName, referenceValue, configuration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeFalse();

reference.Should().BeNull();
errorBuilder!.Should().NotBeNull();
Expand All @@ -183,22 +184,22 @@ public void TryParse_InvalidAlias_ReturnsFalseAndSetsErrorDiagnostic(string alia
[DynamicData(nameof(GetValidAliasData), DynamicDataSourceType.Method)]
public void TryGetModuleReference_ValidAlias_ReplacesReferenceValue(string aliasName, string referenceValue, string fullyQualifiedReferenceValue, RootConfiguration configuration)
{
OciModuleReference.TryParse(aliasName, referenceValue, configuration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeTrue();
OciArtifactReference.TryParse(OciArtifactReferenceType.Module, aliasName, referenceValue, configuration, RandomFileUri()).IsSuccess(out var reference, out var errorBuilder).Should().BeTrue();

reference.Should().NotBeNull();
reference!.FullyQualifiedReference.Should().Be(fullyQualifiedReferenceValue);
}


private static OciModuleReference Parse(string package)
private static OciArtifactReference Parse(string package)
{
OciModuleReference.TryParse(null, package, BicepTestConstants.BuiltInConfigurationWithAllAnalyzersDisabled, RandomFileUri()).IsSuccess(out var parsed, out var failureBuilder).Should().BeTrue();
OciArtifactReference.TryParse(OciArtifactReferenceType.Module, null, package, BicepTestConstants.BuiltInConfigurationWithAllAnalyzersDisabled, RandomFileUri()).IsSuccess(out var parsed, out var failureBuilder).Should().BeTrue();
failureBuilder!.Should().BeNull();
parsed.Should().NotBeNull();
return parsed!;
}

private static (OciModuleReference, OciModuleReference) ParsePair(string first, string second) => (Parse(first), Parse(second));
private static (OciArtifactReference, OciArtifactReference) ParsePair(string first, string second) => (Parse(first), Parse(second));

private static IEnumerable<object[]> GetValidCases()
{
Expand Down
Loading
Loading