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

Merge patch v1.30.3 #2497

Merged
merged 3 commits into from
Oct 19, 2023
Merged
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
10 changes: 9 additions & 1 deletion docs/CHANGELOG-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

## Unreleased

What's changed since v1.30.2:
What's changed since v1.30.3:

- Engineering:
- Bump development tools to .NET 7.0 SDK by @BernieWhite.
[#1870](https://github.com/Azure/PSRule.Rules.Azure/issues/1870)

## v1.30.3

What's changed since v1.30.2:

- Bug fixes:
- Fixed nullable parameters for built-in types by @BernieWhite.
[#2488](https://github.com/Azure/PSRule.Rules.Azure/issues/2488)

## v1.30.2

What's changed since v1.30.1:
Expand Down
20 changes: 19 additions & 1 deletion src/PSRule.Rules.Azure/Data/Template/TemplateVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using PSRule.Rules.Azure.Configuration;
using PSRule.Rules.Azure.Pipeline;
using PSRule.Rules.Azure.Resources;
using YamlDotNet.Core.Tokens;

namespace PSRule.Rules.Azure.Data.Template
{
Expand Down Expand Up @@ -66,6 +67,7 @@ internal abstract class TemplateVisitor : ResourceManagerVisitor
private const string PROPERTY_DEFINITIONS = "definitions";
private const string PROPERTY_REF = "$ref";
private const string PROPERTY_ROOTDEPLOYMENT = "rootDeployment";
private const string PROPERTY_NULLABLE = "nullable";

internal sealed class TemplateContext : ITemplateContext
{
Expand Down Expand Up @@ -960,7 +962,8 @@ private static bool TryParameter(TemplateContext context, string parameterName,
return parameter == null ||
TryParameterAssignment(context, parameterName, parameter) ||
TryParameterDefaultValue(context, parameterName, parameter) ||
TryParameterDefault(context, parameterName, parameter);
TryParameterDefault(context, parameterName, parameter) ||
TryParameterNullable(context, parameterName, parameter);
}

private static bool TryParameterAssignment(TemplateContext context, string parameterName, JObject parameter)
Expand Down Expand Up @@ -1003,6 +1006,21 @@ private static bool TryParameterDefault(TemplateContext context, string paramete
return true;
}

/// <summary>
/// Handle cases when the parameter has been marked as nullable.
/// </summary>
private static bool TryParameterNullable(TemplateContext context, string parameterName, JObject parameter)
{
if (!parameter.TryBoolProperty(PROPERTY_NULLABLE, out var nullable) || !nullable.HasValue)
return false;

if (!TryParameterType(context, parameter, out var type))
throw ThrowTemplateParameterException(parameterName);

AddParameterFromType(context, parameterName, type.Value, JToken.Parse("null"));
return true;
}

private static bool TryParameterType(ITemplateContext context, JObject parameter, out ParameterType? value)
{
value = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@
<None Update="Tests.Bicep.24.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tests.Bicep.27.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tests.Bicep.3.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
11 changes: 11 additions & 0 deletions tests/PSRule.Rules.Azure.Tests/TemplateVisitorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,17 @@ public void ArrayContains()
Assert.Equal("Standard", resources[10]["properties"]["pricingTier"].Value<string>());
}

[Fact]
public void NullableParameters()
{
var resources = ProcessTemplate(GetSourcePath("Tests.Bicep.27.json"), null, out _);
Assert.Equal(3, resources.Length);

var actual = resources[2];
Assert.Equal("Microsoft.Storage/storageAccounts", actual["type"].Value<string>());
Assert.Equal("TLS1_2", actual["properties"]["minimumTlsVersion"].Value<string>());
}

#region Helper methods

private static string GetSourcePath(string fileName)
Expand Down
7 changes: 7 additions & 0 deletions tests/PSRule.Rules.Azure.Tests/Tests.Bicep.27.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

module child 'Tests.Bicep.27.child.bicep' = {
name: 'child'
params: {}
}
35 changes: 35 additions & 0 deletions tests/PSRule.Rules.Azure.Tests/Tests.Bicep.27.child.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

param minTLSVersion string?
// param corsRules corsRule

// type corsRule = {
// allowedHeaders: string[]
// allowedMethods: string[]
// allowedOrigins: string[]
// exposedHeaders: string[]
// maxAgeInSeconds: int
// }[]?

resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'test'
#disable-next-line no-loc-expr-outside-params
location: resourceGroup().location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
minimumTlsVersion: minTLSVersion ?? 'TLS1_2'
}

// resource blob 'blobServices' = {
// name: 'default'
// properties: {
// cors: {
// corsRules: corsRules ?? []
// }
// }
// }
}
58 changes: 58 additions & 0 deletions tests/PSRule.Rules.Azure.Tests/Tests.Bicep.27.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.22.6.54827",
"templateHash": "3111791179159915120"
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"name": "child",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"parameters": {},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"languageVersion": "2.0",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.22.6.54827",
"templateHash": "965836287794218595"
}
},
"parameters": {
"minTLSVersion": {
"type": "string",
"nullable": true
}
},
"resources": {
"storage": {
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "test",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"minimumTlsVersion": "[coalesce(parameters('minTLSVersion'), 'TLS1_2')]"
}
}
}
}
}
}
]
}