Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static IEnumerable<object[]> ResourceFallbackProperties
yield return new object[] { "managedByExtended", "[]" };
yield return new object[] { "extendedLocation", "{'type': 'NotSpecified'}" };
yield return new object[] { "zones", "[]" };
yield return new object[] { "placement", "{'zonePlacementPolicy': 'Any'}" };
yield return new object[] { "plan", "{}" };
yield return new object[] { "eTag", "''" };
yield return new object[] { "scale", "{'capacity': 1}" };
Expand All @@ -49,6 +50,7 @@ public static IEnumerable<object[]> ModuleFallbackProperties
yield return new object[] { "managedByExtended", "[]" };
yield return new object[] { "extendedLocation", "{'type': 'NotSpecified'}" };
yield return new object[] { "zones", "[]" };
yield return new object[] { "placement", "{'zonePlacementPolicy': 'Any'}" };
yield return new object[] { "plan", "{}" };
yield return new object[] { "eTag", "''" };
yield return new object[] { "scale", "{'capacity': 1}" };
Expand Down Expand Up @@ -557,5 +559,32 @@ public void Test_Issue5960_case9()
("BCP036", DiagnosticLevel.Warning, "The property \"kind\" expected a value of type \"'val1' | 'val2'\" but the provided value is of type \"'otherValue'\". If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues.")
});
}

// https://github.com/Azure/bicep/issues/20171
[TestMethod]
public void Placement_property_can_be_used_to_author_a_virtual_machine_scale_set_without_generating_diagnostics()
{
var compilation = Services.BuildCompilation(@"
resource vmss 'Test.Compute/virtualMachineScaleSets@2020-01-01' = {
name: 'vmss'
location: resourceGroup().location
sku: {
name: 'Standard_D2s_v3'
tier: 'Standard'
capacity: 3
}
placement: {
zonePlacementPolicy: 'Any'
}
properties: {
overprovision: true
upgradePolicy: {
mode: 'Manual'
}
}
}
");
compilation.Should().NotHaveAnyDiagnostics();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ type hello = {

type typoInPropertyName = resourceInput<'Microsoft.Storage/storageAccounts@2023-01-01'>.nom
//@[005:023) [no-unused-types (Warning)] Type "typoInPropertyName" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName|
//@[088:091) [BCP053 (Error)] The type "Microsoft.Storage/storageAccounts" does not contain property "nom". Available properties include "apiVersion", "asserts", "dependsOn", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "plan", "properties", "scale", "sku", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |nom|
//@[088:091) [BCP053 (Error)] The type "Microsoft.Storage/storageAccounts" does not contain property "nom". Available properties include "apiVersion", "asserts", "dependsOn", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "placement", "plan", "properties", "scale", "sku", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |nom|
type typoInPropertyName2 = resourceInput<'Microsoft.KeyVault/vaults@2022-07-01'>.properties.accessPolicies[*].tenatId
//@[005:024) [no-unused-types (Warning)] Type "typoInPropertyName2" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-types) |typoInPropertyName2|
//@[110:117) [BCP083 (Error)] The type "AccessPolicyEntry" does not contain property "tenatId". Did you mean "tenantId"? (bicep https://aka.ms/bicep/core-diagnostics#BCP083) |tenatId|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ resource incorrectPropertiesKey 'Microsoft.Resources/deploymentScripts@2020-10-0

var mock = incorrectPropertiesKey.p
//@[004:008) [no-unused-vars (Warning)] Variable "mock" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |mock|
//@[034:035) [BCP053 (Error)] The type "AzureCLI" does not contain property "p". Available properties include "apiVersion", "asserts", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "plan", "properties", "scale", "sku", "systemData", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |p|
//@[034:035) [BCP053 (Error)] The type "AzureCLI" does not contain property "p". Available properties include "apiVersion", "asserts", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "placement", "plan", "properties", "scale", "sku", "systemData", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |p|

resource incorrectPropertiesKey2 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
kind: 'AzureCLI'
Expand Down Expand Up @@ -2189,7 +2189,7 @@ resource issue3000stg 'Microsoft.Storage/storageAccounts@2021-04-01' = {

var issue3000stgMadeUpProperty = issue3000stg.madeUpProperty
//@[004:030) [no-unused-vars (Warning)] Variable "issue3000stgMadeUpProperty" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |issue3000stgMadeUpProperty|
//@[046:060) [BCP053 (Error)] The type "Microsoft.Storage/storageAccounts" does not contain property "madeUpProperty". Available properties include "apiVersion", "asserts", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "plan", "properties", "scale", "sku", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |madeUpProperty|
//@[046:060) [BCP053 (Error)] The type "Microsoft.Storage/storageAccounts" does not contain property "madeUpProperty". Available properties include "apiVersion", "asserts", "eTag", "extendedLocation", "id", "identity", "kind", "location", "managedBy", "managedByExtended", "name", "placement", "plan", "properties", "scale", "sku", "tags", "type", "zones". (bicep https://aka.ms/bicep/core-diagnostics#BCP053) |madeUpProperty|
var issue3000stgManagedBy = issue3000stg.managedBy
//@[004:025) [no-unused-vars (Warning)] Variable "issue3000stgManagedBy" is declared but never used. (bicep core linter https://aka.ms/bicep/linter-diagnostics#no-unused-vars) |issue3000stgManagedBy|
//@[041:050) [BCP187 (Warning)] The property "managedBy" does not exist in the resource or type definition, although it might still be valid. If this is a resource type definition inaccuracy, report it using https://aka.ms/bicep-type-issues. (bicep https://aka.ms/bicep/core-diagnostics#BCP187) |managedBy|
Expand Down
45 changes: 45 additions & 0 deletions src/Bicep.Core.UnitTests/Utils/BuiltInTestTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,50 @@ private static ResourceTypeComponents FallbackPropertyTestsType()
), null));
}

private static ResourceTypeComponents VirtualMachineScaleSetsTestsType()
{
// Models the shape of Microsoft.Compute/virtualMachineScaleSets, including the "placement" property
// (https://github.com/Azure/bicep/issues/20171), to verify that a realistic resource can be authored
// using the "placement" top-level property without generating any diagnostics.
var resourceType = ResourceTypeReference.Parse("Test.Compute/virtualMachineScaleSets@2020-01-01");

var skuType = new ObjectType("Sku", TypeSymbolValidationFlags.Default, new[] {
new NamedTypeProperty("name", LanguageConstants.String, TypePropertyFlags.None, "The sku name."),
new NamedTypeProperty("tier", LanguageConstants.String, TypePropertyFlags.None, "The sku tier."),
new NamedTypeProperty("capacity", LanguageConstants.Int, TypePropertyFlags.None, "The sku capacity."),
}, null);

var upgradePolicyType = new ObjectType("UpgradePolicy", TypeSymbolValidationFlags.Default, new[] {
new NamedTypeProperty("mode", LanguageConstants.String, TypePropertyFlags.None, "The upgrade mode."),
}, null);

var propertiesType = new ObjectType("Properties", TypeSymbolValidationFlags.WarnOnPropertyTypeMismatch, new[] {
new NamedTypeProperty("overprovision", LanguageConstants.Bool, TypePropertyFlags.None, "Whether to overprovision the scale set."),
new NamedTypeProperty("upgradePolicy", upgradePolicyType, TypePropertyFlags.None, "The upgrade policy."),
}, null);

var placementType = new ObjectType("Placement", TypeSymbolValidationFlags.Default, new[] {
new NamedTypeProperty("zonePlacementPolicy", TypeHelper.CreateTypeUnion(
TypeFactory.CreateStringLiteralType("NotSpecified"),
TypeFactory.CreateStringLiteralType("Any"),
TypeFactory.CreateStringLiteralType("None"),
TypeFactory.CreateStringLiteralType("Auto"),
LanguageConstants.String), TypePropertyFlags.Required, "The zone placement policy."),
new NamedTypeProperty("includeZones", new TypedArrayType(LanguageConstants.String, TypeSymbolValidationFlags.Default), TypePropertyFlags.None, "The zones to include."),
new NamedTypeProperty("excludeZones", new TypedArrayType(LanguageConstants.String, TypeSymbolValidationFlags.Default), TypePropertyFlags.None, "The zones to exclude."),
}, null);

return new ResourceTypeComponents(resourceType, ResourceScope.ResourceGroup, ResourceScope.None, ResourceFlags.None,
new ObjectType(resourceType.FormatName(), TypeSymbolValidationFlags.Default,
AzResourceTypeProvider.GetCommonResourceProperties(resourceType).Concat(new[] {
new NamedTypeProperty("location", LanguageConstants.String, TypePropertyFlags.None, "location property"),
new NamedTypeProperty("sku", skuType, TypePropertyFlags.None, "sku property"),
new NamedTypeProperty("zones", new TypedArrayType(LanguageConstants.String, TypeSymbolValidationFlags.Default), TypePropertyFlags.None, "zones property"),
new NamedTypeProperty("placement", placementType, TypePropertyFlags.None, "placement property"),
new NamedTypeProperty("properties", propertiesType, TypePropertyFlags.Required, "properties property"),
}), null));
}

private static ResourceTypeComponents ListFunctionsType()
{
var resourceType = ResourceTypeReference.Parse("Test.Rp/listFuncTests@2020-01-01");
Expand Down Expand Up @@ -252,6 +296,7 @@ private static ResourceTypeComponents ListFunctionsType()
DiscriminatedPropertiesTestsType2(),
FallbackPropertyTestsType(),
ListFunctionsType(),
VirtualMachineScaleSetsTestsType(),
];

public static INamespaceProvider Create()
Expand Down
15 changes: 15 additions & 0 deletions src/Bicep.Core/TypeSystem/Providers/Az/AzResourceTypeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public static readonly ImmutableSortedSet<string> ReadWriteDeployTimeConstantPro
"managedBy",
"extendedLocation",
"zones",
"placement",
"plan",
ResourceSkuPropertyName,
"identity",
Expand Down Expand Up @@ -162,6 +163,20 @@ public static IEnumerable<NamedTypeProperty> KnownTopLevelResourceProperties()

yield return new NamedTypeProperty("zones", stringArray);

var zonePlacementPolicyType = TypeHelper.CreateTypeUnion(
TypeFactory.CreateStringLiteralType("NotSpecified"),
TypeFactory.CreateStringLiteralType("Any"),
TypeFactory.CreateStringLiteralType("None"),
TypeFactory.CreateStringLiteralType("Auto"),
LanguageConstants.String);

yield return new NamedTypeProperty("placement", new ObjectType("placement", TypeSymbolValidationFlags.Default, new[]
{
new NamedTypeProperty("zonePlacementPolicy", zonePlacementPolicyType, TypePropertyFlags.Required),
new NamedTypeProperty("includeZones", stringArray),
new NamedTypeProperty("excludeZones", stringArray),
}, null));

yield return new NamedTypeProperty("plan", LanguageConstants.Object);

yield return new NamedTypeProperty("eTag", LanguageConstants.String);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,11 @@ param newParameter {
managedByExtended: string[]
name: string
parent: object? /* Microsoft.Compute/virtualMachines */
placement: {
excludeZones: string[]
includeZones: string[]
zonePlacementPolicy: string /* 'Any' | 'Auto' | 'None' | 'NotSpecified' | string */
}
plan: object
properties: {
autoUpgradeMinorVersion: bool?
Expand Down
Loading
Loading