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

[FEAT] - Centralized management of provider versions using bicepconfig.json #13078

Merged
merged 89 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
9087e18
rename variable since it operates on other artifacts that are not mod…
Jan 21, 2024
d09a014
add plumbing to support resolution from config data
Jan 22, 2024
50f0a8d
try to deserialize the config contents
Jan 22, 2024
39ac777
improve devcontainer
Jan 24, 2024
ee82ebb
update definitions to match design
Jan 25, 2024
3f3b094
Add provider configuration basic support
Jan 26, 2024
c6e291c
make builtIn mutually eclusive with other properties
Jan 26, 2024
74434fe
add implicit providers model
Jan 26, 2024
9773cec
add tests
Jan 26, 2024
b5195da
add tests
Jan 26, 2024
a9dbdc3
Merge branch 'main' of https://github.com/Azure/bicep into asilverman…
Jan 26, 2024
8476cb3
add schema tests
Jan 26, 2024
7a17e2b
add tests
Jan 26, 2024
e113277
remove unintentionally commited files
Jan 27, 2024
875f546
add tests
Jan 27, 2024
f394b89
add more tests
Jan 27, 2024
88cbd2c
fix logic to coerce the value of builtin
Jan 27, 2024
ddcd9ef
remove unnecessary using
Jan 27, 2024
a33bd50
add some more changes
Jan 30, 2024
b55c828
add new member to sourcefile groupping builder
asilverman Jan 30, 2024
76fbf17
handle implicit provider artifacts
asilverman Jan 31, 2024
4fc2a53
add descriptors to sourcefilegrouppingbuilder
asilverman Jan 31, 2024
ff53bb7
Refactor resource type provider factory and loader
asilverman Feb 1, 2024
2fd777f
Refactor configuration and provider classes
asilverman Feb 1, 2024
7d1ba18
Update providerDescriptor parameter type in code
asilverman Feb 1, 2024
0aae6de
Fix namespace identifier in code
asilverman Feb 1, 2024
48ac6e5
Merge branch 'main' of https://github.com/Azure/bicep into asilverman…
asilverman Feb 1, 2024
246652b
fix packages.lock.json
asilverman Feb 1, 2024
95ba766
Fix namespace identifier in ImportSpecificationTest and ProviderNames…
asilverman Feb 1, 2024
2bdf196
Refactor constructor parameters in ProviderNamespaceSymbol.cs
asilverman Feb 1, 2024
16a3d61
adding tests
asilverman Feb 2, 2024
3632b68
Refactor provider descriptor retrieval and add support for identifier…
Feb 2, 2024
0b86cf8
Generalize test
Feb 2, 2024
f07be76
add comment
Feb 2, 2024
9087813
Update ImportSpecificationTests
Feb 2, 2024
8f166af
Fix tests
Feb 2, 2024
29f8f2c
use language constant
Feb 2, 2024
42e56ad
Fix formatting issues and update method names
Feb 5, 2024
b2b26cc
Add test for loading built-in Az namespace from configuration
Feb 5, 2024
7b76fa9
Refactor RootConfiguration class constructor and properties
Feb 5, 2024
9950588
Add SystemTextJson.JsonDiffPatch.MSTest package
Feb 5, 2024
d89acef
Refactor provider configuration handling
Feb 5, 2024
ce3b670
Update provider error message in unit tests
Feb 5, 2024
900135d
Fix compilation errors and update configuration
Feb 5, 2024
cb84ecc
Add tests for loading external Az namespace from configuration
Feb 5, 2024
c312147
Add test for inlined Az namespace alias not specified in config
Feb 5, 2024
60831f8
adding more changes
Feb 6, 2024
245ef0d
more changes
Feb 6, 2024
5e59dd1
Fix provider namespace deprecation warnings and update error messages
Feb 7, 2024
69e3d01
Add test for ConfigManagedProviderDeclarationSyntax
Feb 7, 2024
620e35c
fixes
Feb 7, 2024
05c79b4
Fix provider import deprecation warnings and improve source file grou…
Feb 8, 2024
efe68f9
Refactor code to improve performance and readability
Feb 8, 2024
64c03e2
Fix SourceSyntax accessibility
Feb 8, 2024
89cef15
Fix provider specification errors and update error codes
Feb 8, 2024
ed941dc
changes
Feb 12, 2024
b9f9224
Fix parser instantiation and add error handling
Feb 12, 2024
61212cb
Remove unused test method and fix completion test assertion
Feb 13, 2024
3aa11ff
Remove SystemTextJson.JsonDiffPatch.MSTest package reference
Feb 13, 2024
243316d
Fix import specification syntax factory
Feb 13, 2024
f1a4809
Fix using declarations and provider specification syntax
Feb 13, 2024
ba62425
Add deep equality check for JSON configuration
Feb 13, 2024
0646710
Merge branch 'asilverman/central-mgmt-of-providers'
Feb 13, 2024
6e27f52
Fix provider specification handling
Feb 13, 2024
bf15fca
make tests pass
Feb 14, 2024
4194bad
fix tests
Feb 14, 2024
19bc534
fix tests
Feb 14, 2024
923c443
Remove unnecessary code to clear test results
Feb 14, 2024
63a7e60
fixes
Feb 15, 2024
3fb74c9
Merge remote-tracking branch 'origin/main' into asilverman/central-mg…
Feb 15, 2024
a500226
Update Microsoft.NET.ILLink.Tasks to version 8.0.1
Feb 15, 2024
37ca7ae
Update Microsoft.NET.ILLink.Tasks to version 8.0.2
Feb 16, 2024
a90651d
Merge branch 'asilverman/central-mgmt-of-providers' of https://github…
Feb 16, 2024
3474da3
Merge branch 'main' of https://github.com/Azure/bicep into asilverman…
Feb 16, 2024
adf9501
Enable dynamic type loading in bicepconfig.json for live tests
Feb 16, 2024
7c3023b
Update settings.json, Parser class, BuildCommandTests, OutputsTests, …
Feb 19, 2024
a491d28
Fix integration test and update module parameter type
Feb 19, 2024
fe40ae5
Refactor code formatting in OutputsTests.cs
Feb 19, 2024
a431466
Remove test results and temporary files
Feb 20, 2024
23ebf70
Merge branch 'asilverman/central-mgmt-of-providers' of https://github…
Feb 20, 2024
0cd11ec
address pr comments
Feb 22, 2024
69cc659
address pr comments
Feb 22, 2024
f444cc2
address pr comments
Feb 23, 2024
da82d48
Merge branch 'main' of https://github.com/Azure/bicep into asilverman…
Feb 26, 2024
fd20405
revert use of language constants
Feb 26, 2024
9e77c23
The most significant changes involve updates to error messages and ha…
Feb 27, 2024
aa17e93
Merge branches 'asilverman/central-mgmt-of-providers' and 'main' of h…
Feb 27, 2024
b7dbb9c
address pr comments
Feb 27, 2024
adb8430
address pr comments
Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ dotnet_sort_system_directives_first = true

# Expression-level preferences
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
# IDE0005: Using directive is unnecessary.
# IDE0005: [Using directive is unnecessary](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005)
dotnet_diagnostic.IDE0005.severity = suggestion
14 changes: 13 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,17 @@
"yaml.schemas": {
"https://json.schemastore.org/github-workflow.json": "/.github/workflows/*.yml"
},
"dotnet.defaultSolution": "Bicep.sln"
"dotnet.defaultSolution": "Bicep.sln",
"cSpell.words": [
"azureacr",
"bicepconfig",
"contoso",
"Decorable",
"Interpolable",
"Newtonsoft",
"outdir",
"outfile",
"outputdir",
"sarif"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
},
"experimentalFeaturesEnabled": {
"extensibility": true,
"dynamicTypeLoading": true,
"providerRegistry": true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
},
"experimentalFeaturesEnabled": {
"extensibility": true,
"dynamicTypeLoading": true,
"providerRegistry": true
}
}
6 changes: 3 additions & 3 deletions src/Bicep.Cli.IntegrationTests/BuildCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public async Task Build_Valid_SingleFile_WithTemplateSpecReference_ShouldSucceed
[DataRow("br/mcr:az", true, LanguageConstants.BicepPublicMcrRegistry)]
[DataRow("br:contoso.azurecr.io/bicep/providers/az", true, "contoso.azurecr.io")]
// Negative
[DataRow("az", false)]
asilverman marked this conversation as resolved.
Show resolved Hide resolved
// [DataRow("az", false)] - commented out while we graciously deprecate the legacy provider declaration syntax.
[DataRow("br:invalid.azureacr.io/bicep/providers/az", false)]
[DataRow("br/unknown:az", false)]
public async Task Build_Valid_SingleFile_WithProviderDeclarationStatement(
Expand Down Expand Up @@ -138,7 +138,7 @@ public async Task Build_Valid_SingleFile_WithTemplateSpecReference_ShouldSucceed
var bicepFilePath = Path.Combine(tempDirectory, "main.bicep");
File.WriteAllText(bicepFilePath, bicepFile);

var bicepConfigFile = $$"""
var bicepConfigFile = """
{
"providerAliases" : {
"br": {
Expand Down Expand Up @@ -392,7 +392,7 @@ public async Task Build_WithOutFile_ShouldSucceed()
}

[TestMethod]
public async Task Build_WithNonExistantOutDir_ShouldFail_WithExpectedErrorMessage()
public async Task Build_WithNonExistentOutDir_ShouldFail_WithExpectedErrorMessage()
{
var bicepPath = FileHelper.SaveResultFile(
TestContext,
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Cli/Commands/RestoreCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public async Task<int> RunAsync(RestoreArguments args)
var inputUri = ArgumentHelper.GetFileUri(args.InputFile);

var compilation = compiler.CreateCompilationWithoutRestore(inputUri, markAllForRestore: args.ForceModulesRestore);
var restoreDiagnostics = await this.compiler.Restore(compilation, force: args.ForceModulesRestore);
var restoreDiagnostics = await this.compiler.Restore(compilation, forceArtifactRestore: args.ForceModulesRestore);

var summary = diagnosticLogger.LogDiagnostics(DiagnosticOptions.Default, restoreDiagnostics);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Bicep.Core.UnitTests;
using Bicep.Core.UnitTests.Utils;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Bicep.Core.UnitTests.Assertions;
using Bicep.Core.Diagnostics;

namespace Bicep.Core.IntegrationTests
{
[TestClass]
public class CentralizedProviderVersionManagementTests : TestBase
{
private ServiceBuilder Services => new ServiceBuilder()
.WithFeatureOverrides(new(
ExtensibilityEnabled: true,
DynamicTypeLoadingEnabled: true,
MicrosoftGraphPreviewEnabled: true));

[TestMethod]
[DynamicData(nameof(ProvidersConfig_SupportForConfigManagedProviderDeclarationSyntax_When_ProviderIsBuiltIn_TestCases))]
public void ProvidersConfig_SupportForConfigManagedProviderDeclarationSyntax_When_ProviderIsBuiltIn(string providerIdentifier, bool shouldSucceed, (string code, DiagnosticLevel level, string message)[] expectedDiagnostics)
{
var result = CompilationHelper.Compile(Services, @$"
provider {providerIdentifier}
");

if (shouldSucceed)
{
result.Should().NotHaveAnyDiagnostics();
return;
}
result.Should().HaveDiagnostics(expectedDiagnostics);
}

public static IEnumerable<object[]> ProvidersConfig_SupportForConfigManagedProviderDeclarationSyntax_When_ProviderIsBuiltIn_TestCases
{
get
{
(string, DiagnosticLevel, string)[] emptyDiagnostics = [];
yield return new object[] {
"sys",
true,
emptyDiagnostics };
yield return new object[] {
"microsoftGraph",
true,
emptyDiagnostics };
yield return new object[] {
"az",
true,
emptyDiagnostics };
yield return new object[] {
"kubernetes",
false,
new (string, DiagnosticLevel, string)[] {
("BCP206", DiagnosticLevel.Error, "Provider namespace \"kubernetes\" requires configuration, but none was provided.") } };
}
}
}
}
149 changes: 125 additions & 24 deletions src/Bicep.Core.IntegrationTests/DynamicAzTypesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ private async Task<ServiceBuilder> GetServices()
return services;
}

private async Task<ServiceBuilder> ServicesWithTestProviderArtifact(ArtifactRegistryAddress artifactRegistryAddress, BinaryData artifactPayload)
{
(var clientFactory, var blobClients) = RegistryUtils.CreateMockRegistryClients(artifactRegistryAddress.ClientDescriptor());

(_, var client) = blobClients.First();
var blobResult = await client.UploadBlobAsync(artifactPayload);
var manifest = BicepTestConstants.GetBicepProviderManifest(
blobResult.Value.Digest,
blobResult.Value.SizeInBytes);
await client.SetManifestAsync(manifest, artifactRegistryAddress.ProviderVersion);

var cacheRoot = FileHelper.GetUniqueTestOutputPath(TestContext);
Directory.CreateDirectory(cacheRoot);

return new ServiceBuilder()
.WithFeatureOverrides(new(
ExtensibilityEnabled: true,
DynamicTypeLoadingEnabled: true,
CacheRootDirectory: cacheRoot))
.WithContainerRegistryClientFactory(clientFactory);
}

[TestMethod]
public async Task Az_namespace_can_be_used_without_configuration()
{
Expand Down Expand Up @@ -79,11 +101,11 @@ public async Task Az_namespace_can_be_used_with_bicepconfig_provider_alias()
{
var services = await GetServices();

services = services.WithConfigurationPatch(c => c.WithProviderAlias($$"""
services = services.WithConfigurationPatch(c => c.WithProviderAlias("""
{
"br": {
"customAlias": {
"registry": "{{LanguageConstants.BicepPublicMcrRegistry}}",
"registry": "mcr.microsoft.com",
"providerPath": "bicep/providers"
}
}
Expand All @@ -100,18 +122,41 @@ public async Task Az_namespace_can_be_used_with_bicepconfig_provider_alias()

[TestMethod]
public async Task Az_namespace_specified_using_legacy_declaration_syntax_yields_diagnostic()
{
var services = new ServiceBuilder()
.WithFeatureOverrides(new(ExtensibilityEnabled: true, DynamicTypeLoadingEnabled: true));

var result = await CompilationHelper.RestoreAndCompile(services, @$"
provider 'az@{BicepTestConstants.BuiltinAzProviderVersion}'
");
result.Should().NotGenerateATemplate();
result.Should().HaveDiagnostics(
new[] {
("BCP201", DiagnosticLevel.Error, """
Expected a provider specification string of with a valid format at this location. Valid formats:
* "br:<providerRegistryHost>/<providerRepositoryPath>@<providerVersion>"
* "br/<providerAlias>:<providerName>@<providerVersion>"
"""),
("BCP084", DiagnosticLevel.Error,
"The symbolic name \"az\" is reserved. Please use a different symbolic name. Reserved namespaces are \"az\", \"sys\".")
});
}

[TestMethod]
public async Task Inlined_Az_namespace_alias_is_not_specified_in_config_yields_diagnostic()
{
var services = new ServiceBuilder()
.WithFeatureOverrides(new(ExtensibilityEnabled: true, DynamicTypeLoadingEnabled: true));

var result = await CompilationHelper.RestoreAndCompile(services, @"
provider 'az@0.2.661'
provider 'br/notFound:az@0.2.661'
");

result.Should().NotGenerateATemplate();
result.Should().HaveDiagnostics(
new[] {
("BCP304", DiagnosticLevel.Error, "Invalid provider specifier string. Specify a valid provider of format \"<providerName>@<providerVersion>\"."),
("BCP379", DiagnosticLevel.Error, "The OCI artifact provider alias name \"notFound\" does not exist in the built-in Bicep configuration."),
("BCP084", DiagnosticLevel.Error, "The symbolic name \"az\" is reserved. Please use a different symbolic name. Reserved namespaces are \"az\", \"sys\".")
});

}
Expand Down Expand Up @@ -155,36 +200,20 @@ public async Task Bicep_module_artifact_specified_in_provider_declaration_syntax
string innerErrorMessage)
{
// ARRANGE
var testArtifact = new ArtifactRegistryAddress("biceptestdf.azurecr.io", "bicep/providers/az", "0.0.0-corruptpng");
(var clientFactory, var blobClients) = RegistryUtils.CreateMockRegistryClients(testArtifact.ClientDescriptor());

(_, var client) = blobClients.First();
var blobResult = await client.UploadBlobAsync(payload);
var manifest = BicepTestConstants.GetBicepProviderManifest(
blobResult.Value.Digest,
blobResult.Value.SizeInBytes);
await client.SetManifestAsync(manifest, testArtifact.ProviderVersion);
var testArtifactAddress = new ArtifactRegistryAddress("biceptestdf.azurecr.io", "bicep/providers/az", "0.0.0-corruptpng");

var cacheRoot = FileHelper.GetUniqueTestOutputPath(TestContext);
Directory.CreateDirectory(cacheRoot);

var services = new ServiceBuilder()
.WithFeatureOverrides(new(
ExtensibilityEnabled: true,
DynamicTypeLoadingEnabled: true,
CacheRootDirectory: cacheRoot))
.WithContainerRegistryClientFactory(clientFactory);
var services = await ServicesWithTestProviderArtifact(testArtifactAddress, payload);

// ACT
var result = await CompilationHelper.RestoreAndCompile(services, @$"
provider '{testArtifact.ToSpecificationString('@')}'
provider '{testArtifactAddress.ToSpecificationString('@')}'
");

// ASSERT
result.Should().NotGenerateATemplate();
result.Should().HaveDiagnostics(new[]
{
("BCP192", DiagnosticLevel.Error, $"Unable to restore the artifact with reference \"{testArtifact.ToSpecificationString(':')}\": The OCI artifact is not a valid Bicep artifact. {innerErrorMessage}"),
("BCP192", DiagnosticLevel.Error, $"Unable to restore the artifact with reference \"{testArtifactAddress.ToSpecificationString(':')}\": The OCI artifact is not a valid Bicep artifact. {innerErrorMessage}"),
("BCP084", DiagnosticLevel.Error, "The symbolic name \"az\" is reserved. Please use a different symbolic name. Reserved namespaces are \"az\", \"sys\".")
});

Expand Down Expand Up @@ -298,5 +327,77 @@ public static IEnumerable<object[]> ArtifactRegistryCorruptedPackageNegativeTest
"Value cannot be null. (Parameter 'source')"
};
}

[TestMethod]
public async Task External_Az_namespace_can_be_loaded_from_configuration()
{
var services = await GetServices();
// Built-In Config contains the following entry:
// {
// "implicitProviders": ["az"]
// }
services = services.WithConfigurationPatch(c => c.WithProvidersConfiguration($$"""
{
"az": {
"source": "{{LanguageConstants.BicepPublicMcrRegistry}}/bicep/providers/az",
"version": "{{BicepTestConstants.BuiltinAzProviderVersion}}"
}
}
"""));
var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$"
provider az
"));

result.Should().GenerateATemplate();
}

[TestMethod]
public async Task BuiltIn_Az_namespace_can_be_loaded_from_configuration()
{
var services = await GetServices();
// Built-In Config contains the following entries:
// {
// "providers": {
// "az": {
// "builtIn": true
// }
// },
// "implicitProviders": ["az"]
// }
var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$"
provider az
"));

result.Should().GenerateATemplate();
}

[TestMethod]
public async Task Az_namespace_can_be_loaded_dynamically_using_provider_configuration()
{
//ARRANGE
var artifactRegistryAddress = new ArtifactRegistryAddress(
"fake.azurecr.io",
"fake/path/az",
"1.0.0-fake");
var services = await ServicesWithTestProviderArtifact(
artifactRegistryAddress,
ThirdPartyTypeHelper.GetTypesTgzBytesFromFiles(("index.json", """{"resources": {}, "resourceFunctions": {}}""")));
services = services.WithConfigurationPatch(c => c.WithProvidersConfiguration($$"""
{
"az": {
"source": "{{artifactRegistryAddress.RegistryAddress}}/{{artifactRegistryAddress.RepositoryPath}}",
"version": "{{artifactRegistryAddress.ProviderVersion}}"
}
}
"""));
//ACT
var result = await CompilationHelper.RestoreAndCompile(services, ("main.bicep", @$"
provider az
"));
//ASSERT
result.Should().GenerateATemplate();
result.Template.Should().NotBeNull();
result.Template.Should().HaveValueAtPath("$.imports.az.version", artifactRegistryAddress.ProviderVersion);
}
}
}
2 changes: 1 addition & 1 deletion src/Bicep.Core.IntegrationTests/ExamplesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private async Task RunExampleTest(EmbeddedFile embeddedBicep, FeatureProviderOve
{
DiagnosticAssertions.DoWithDiagnosticAnnotations(
file,
diagnostics.Where(x => !IsPermittedMissingTypeDiagnostic(x)),
diagnostics.Where(d => !IsPermittedMissingTypeDiagnostic(d)).Where(d => !d.Code.Equals("BCP395")),
diagnostics =>
{
diagnostics.Should().BeEmpty("{0} should not have warnings or errors", file.FileUri.LocalPath);
Expand Down