Skip to content

Commit ee4384f

Browse files
Fix bug with nullable array params/outputs (#24174)
1 parent d399046 commit ee4384f

File tree

15 files changed

+383
-766
lines changed

15 files changed

+383
-766
lines changed

src/Resources/ResourceManager/SdkExtensions/NewResourcesExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ private static void SetDeploymentProperties(PSDeploymentObject deploymentObject,
324324
Dictionary<string, DeploymentVariable> outputs = JsonConvert.DeserializeObject<Dictionary<string, DeploymentVariable>>(properties.Outputs.ToString());
325325
// Continue deserialize if the type of Value in DeploymentVariable is array
326326
outputs?.Values.ForEach(dv => {
327-
if ("Array".Equals(dv?.Type))
327+
if ("Array".Equals(dv?.Type) && dv?.Value != null)
328328
{
329329
dv.Value = JsonConvert.DeserializeObject<object[]>(dv.Value.ToString());
330330
}
@@ -337,7 +337,7 @@ private static void SetDeploymentProperties(PSDeploymentObject deploymentObject,
337337
Dictionary<string, DeploymentVariable> parameters = JsonConvert.DeserializeObject<Dictionary<string, DeploymentVariable>>(properties.Parameters.ToString());
338338
// Continue deserialize if the type of Value in DeploymentVariable is array
339339
parameters?.Values.ForEach(dv => {
340-
if ("Array".Equals(dv?.Type))
340+
if ("Array".Equals(dv?.Type) && dv?.Value != null)
341341
{
342342
dv.Value = JsonConvert.DeserializeObject<object[]>(dv.Value.ToString());
343343
}

src/Resources/ResourceManager/SdkModels/DeploymentStacks/PSDeploymentStack.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ internal static Dictionary<string, DeploymentVariable> FormatMappedObject(object
171171
// Continue deserialize if the type of Value in DeploymentVariable is array.
172172
mappedDeploymentVariables?.Values.ForEach(dv =>
173173
{
174-
if ("Array".Equals(dv?.Type))
174+
if ("Array".Equals(dv?.Type) && dv?.Value != null)
175175
{
176176
dv.Value = JsonConvert.DeserializeObject<object[]>(dv.Value.ToString());
177177
}

src/Resources/ResourceManager/Utilities/BicepUtility.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ private string RunBicepCommand(string arguments, string minimalVersionRequiremen
212212
}
213213

214214
// print warning message
215-
if (!string.IsNullOrEmpty(output.Stderr))
215+
if (!string.IsNullOrWhiteSpace(output.Stderr))
216216
{
217217
writeWarning?.Invoke(output.Stderr);
218218
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
param location string = resourceGroup().location
2+
param baseName string
3+
param dnsPrefix string
4+
param linuxAdminUsername string
5+
param sshRSAPublicKey string
6+
7+
var osDiskSizeGB = 0
8+
var agentCount = 3
9+
var agentVMSize = 'standard_f2s_v2' //'Standard_DS2_v2'
10+
var resourceNamee = toLower('${baseName}${uniqueString(resourceGroup().id)}')
11+
12+
resource aks 'Microsoft.ContainerService/managedClusters@2020-09-01' = {
13+
name: resourceNamee
14+
location: location
15+
properties: {
16+
dnsPrefix: dnsPrefix
17+
agentPoolProfiles: [
18+
{
19+
name: 'agentpool'
20+
osDiskSizeGB: osDiskSizeGB
21+
count: agentCount
22+
vmSize: agentVMSize
23+
osType: 'Linux'
24+
mode: 'System'
25+
}
26+
]
27+
linuxProfile: {
28+
adminUsername: linuxAdminUsername
29+
ssh: {
30+
publicKeys: [
31+
{
32+
keyData: sshRSAPublicKey
33+
}
34+
]
35+
}
36+
}
37+
}
38+
identity: {
39+
type: 'SystemAssigned'
40+
}
41+
}
42+
43+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
44+
name: resourceNamee
45+
location: location
46+
properties: {
47+
sku: {
48+
family: 'A'
49+
name: 'standard'
50+
}
51+
tenantId: subscription().tenantId
52+
accessPolicies: []
53+
enabledForTemplateDeployment: true
54+
}
55+
}
56+
57+
resource secret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
58+
parent: keyVault
59+
name: 'kubeconfig'
60+
properties: {
61+
value: aks.listClusterAdminCredential().kubeconfigs[0].value
62+
}
63+
}
64+
65+
output keyVaultId string = keyVault.id
66+
output secretName string = secret.name
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"experimentalFeaturesEnabled": {
3-
"paramsFiles": true
3+
"extensibility": true
44
}
55
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
@secure()
2+
param kubeConfig string
3+
4+
provider '[email protected]' with {
5+
kubeConfig: kubeConfig
6+
namespace: 'default'
7+
}
8+
9+
var backName = 'azure-vote-back'
10+
var backPort = 6379
11+
12+
var frontName = 'azure-vote-front'
13+
var frontPort = 80
14+
15+
@description('Application back-end deployment (redis)')
16+
resource backDeploy 'apps/Deployment@v1' = {
17+
metadata: {
18+
name: backName
19+
}
20+
spec: {
21+
replicas: 1
22+
selector: {
23+
matchLabels: {
24+
app: backName
25+
}
26+
}
27+
template: {
28+
metadata: {
29+
labels: {
30+
app: backName
31+
}
32+
}
33+
spec: {
34+
containers: [
35+
{
36+
name: backName
37+
image: 'mcr.microsoft.com/oss/bitnami/redis:6.0.8'
38+
env: [
39+
{
40+
name: 'ALLOW_EMPTY_PASSWORD'
41+
value: 'yes'
42+
}
43+
]
44+
resources: {
45+
requests: {
46+
cpu: '100m'
47+
memory: '128Mi'
48+
}
49+
limits: {
50+
cpu: '250m'
51+
memory: '256Mi'
52+
}
53+
}
54+
ports: [
55+
{
56+
containerPort: backPort
57+
name: 'redis'
58+
}
59+
]
60+
}
61+
]
62+
}
63+
}
64+
}
65+
}
66+
67+
@description('Configure back-end service')
68+
resource backSvc 'core/Service@v1' = {
69+
metadata: {
70+
name: backName
71+
}
72+
spec: {
73+
ports: [
74+
{
75+
port: backPort
76+
}
77+
]
78+
selector: {
79+
app: backName
80+
}
81+
}
82+
}
83+
84+
@description('Application front-end deployment (website)')
85+
resource frontDeploy 'apps/Deployment@v1' = {
86+
metadata: {
87+
name: frontName
88+
}
89+
spec: {
90+
replicas: 1
91+
selector: {
92+
matchLabels: {
93+
app: frontName
94+
}
95+
}
96+
template: {
97+
metadata: {
98+
labels: {
99+
app: frontName
100+
}
101+
}
102+
spec: {
103+
nodeSelector: {
104+
'beta.kubernetes.io/os': 'linux'
105+
}
106+
containers: [
107+
{
108+
name: frontName
109+
image: 'mcr.microsoft.com/azuredocs/azure-vote-front:v1'
110+
resources: {
111+
requests: {
112+
cpu: '100m'
113+
memory: '128Mi'
114+
}
115+
limits: {
116+
cpu: '250m'
117+
memory: '256Mi'
118+
}
119+
}
120+
ports: [
121+
{
122+
containerPort: frontPort
123+
}
124+
]
125+
env: [
126+
{
127+
name: 'REDIS'
128+
value: backName
129+
}
130+
]
131+
}
132+
]
133+
}
134+
}
135+
}
136+
}
137+
138+
@description('Configure front-end service')
139+
resource frontSvc 'core/Service@v1' = {
140+
metadata: {
141+
name: frontName
142+
}
143+
spec: {
144+
type: 'LoadBalancer'
145+
ports: [
146+
{
147+
port: frontPort
148+
}
149+
]
150+
selector: {
151+
app: frontName
152+
}
153+
}
154+
}

src/Resources/Resources.Test/Resources/DeploymentTests/NoErrorEmitted/main.bicep

Whitespace-only changes.

src/Resources/Resources.Test/Resources/DeploymentTests/NullableParametersAreNotRequired/main.bicep

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,12 @@ type nullableCustomType = {
2020
type customTypeWithRequired = customType!
2121

2222
param optionalRequiredCustomType customTypeWithRequired?
23+
24+
// repro for https://github.com/Azure/bicep/issues/13350
25+
type nullableArrayOfObjectsType = {
26+
property1: string
27+
}[]?
28+
29+
param param1 nullableArrayOfObjectsType
30+
31+
output output1 nullableArrayOfObjectsType = param1
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
@description('Location for all resources.')
2+
param location string = resourceGroup().location
3+
4+
var storageAccountName = 'storage${uniqueString(resourceGroup().id)}'
5+
var endpointName = 'endpoint-${uniqueString(resourceGroup().id)}'
6+
var profileName = 'cdn-${uniqueString(resourceGroup().id)}'
7+
var storageAccountHostName = replace(replace(storageAccount.properties.primaryEndpoints.blob, 'https://', ''), '/', '')
8+
9+
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-01-01' = {
10+
name: storageAccountName
11+
location: location
12+
tags: {
13+
displayName: storageAccountName
14+
}
15+
kind: 'StorageV2'
16+
sku: {
17+
name: 'Standard_LRS'
18+
}
19+
}
20+
21+
resource cdnProfile 'Microsoft.Cdn/profiles@2020-09-01' = {
22+
name: profileName
23+
location: location
24+
tags: {
25+
displayName: profileName
26+
}
27+
sku: {
28+
name: 'Standard_Verizon'
29+
}
30+
}
31+
32+
resource endpoint 'Microsoft.Cdn/profiles/endpoints@2020-09-01' = {
33+
parent: cdnProfile
34+
name: endpointName
35+
location: location
36+
tags: {
37+
displayName: endpointName
38+
}
39+
properties: {
40+
originHostHeader: storageAccountHostName
41+
isHttpAllowed: true
42+
isHttpsAllowed: true
43+
queryStringCachingBehavior: 'IgnoreQueryString'
44+
contentTypesToCompress: [
45+
'text/plain'
46+
'text/html'
47+
'text/css'
48+
'application/x-javascript'
49+
'text/javascript'
50+
]
51+
isCompressionEnabled: true
52+
origins: [
53+
{
54+
name: 'origin1'
55+
properties: {
56+
hostName: storageAccountHostName
57+
}
58+
}
59+
]
60+
}
61+
}
62+
63+
output hostName string = endpoint.properties.hostName
64+
output originHostHeader string = endpoint.properties.originHostHeader

0 commit comments

Comments
 (0)