1

I have a bicep template that has a parameter of type "array". The array I'm trying to give it is an array of objects. Here is a sample Bicep, where I'm taking an array and outputting parts of it in various ways.

param rulesFromJson array

output FirstElement object = rulesFromJson[0]
output inputArray array = rulesFromJson
output FirstElementName string = rulesFromJson[0].name

Here is a sample parameters file:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "rulesFromJson": {
        "value": [
            {
              "ruleType": "NetworkRule",
              "name": "hello"
            },
            {
              "ruleType": "NetworkRule",
              "name": "goodbye"
            }
          ]
      }
    }
  }

If I run this using the following command, I get a reasonable output:

New-AzResourceGroupDeployment -TemplateFile .\NetTest.bicep -ResourceGroupName 'ericNetworking' -TemplateParameterFile .\FWPolicyParam.json

DeploymentName          : NetTest
ResourceGroupName       : ericNetworking
ProvisioningState       : Succeeded
Timestamp               : 4/29/2022 5:14:06 PM
Mode                    : Incremental
TemplateLink            : 
Parameters              : 
                          Name             Type                       Value
                          ===============  =========================  ==========
                          rulesFromJson    Array                      [{"ruleType":"NetworkRule","name":"hello"},{"ruleType":"NetworkRule","name":"goodbye"}]

Outputs                 : 
                          Name                Type                       Value
                          ==================  =========================  ==========
                          firstElement        Object                     {"ruleType":"NetworkRule","name":"hello"}
                          inputArray          Array                      [{"ruleType":"NetworkRule","name":"hello"},{"ruleType":"NetworkRule","name":"goodbye"}]
                          firstElementName    String                     "hello"

But I want to feed the parameter in using -TemplateParameterObject instead of using a parameter file. So let's construct an object identical to what was in the parameter file and feed it in:

$objArray1 = @()
$objArray1 += [pscustomobject]@{ruleType='NetworkRule';name='hello'}
$objArray1 += [pscustomobject]@{ruleType='NetworkRule';name='goodbye'}

New-AzResourceGroupDeployment -TemplateFile .\NetTest.bicep -ResourceGroupName 'ericNetworking' -TemplateParameterObject @{rulesFromJson = $objArray1}

So far as I can see, this should do the same thing. But instead I get an error.

New-AzResourceGroupDeployment: 1:24:37 PM - The deployment 'NetTest' failed with error(s). Showing 1 out of 1 error(s).
Status Message: The template output 'FirstElementName' is not valid: The language expression property 'name' doesn't exist, available properties are ''.. (Code:DeploymentOutputEvaluationFailed)
CorrelationId: xxxxxx

DeploymentName          : NetTest
ResourceGroupName       : ericNetworking
ProvisioningState       : Failed
Timestamp               : 4/29/2022 5:24:32 PM
Mode                    : Incremental
TemplateLink            : 
Parameters              : 
                          Name             Type                       Value
                          ===============  =========================  ==========
                          rulesFromJson    Array                      [{},{}]

Outputs                 : 
DeploymentDebugLogLevel : 

What am I doing wrong here? Have I formatted my input array improperly? I note that in the output above, the value of the rulesFromJson parameter contains an array with two blank objects, which is strange.

EricAsh
  • 41
  • 1
  • 5
  • The error is from the template *output*, which executes after the template runs. That tells me your input was at least acceptable. Could you share the output code from the bicep file? – joelforsyth Apr 29 '22 at 17:51
  • The input may have been accepted, but look at the Parameters section of the output. It shows a two-element array with empty objects. They weren't actually empty when I passed them in but Bicep sees them as empty. If I put some resource in the Bicep that try doing something with the parameter, that errors out. Sample: "Unable to process template language expressions for resource... at line '19' and column '9'. 'The language expression property 'ruleType' doesn't exist, available properties are ''.' (Code:InvalidTemplate)" – EricAsh Apr 29 '22 at 20:17
  • This might be a scoping issue. If you’re literally outputting the parameter you passed in, it may not be available when the arm finishes. Output is intended to be a result of the arm. It’s saying there’s nothing there because the properties are nothing – joelforsyth Apr 29 '22 at 23:53
  • That seems unlikely - the parameters show in the Outputs when I pass them in via a parameter file. It's only when I pass them with -TemplateParameterObject that it shows the partially empty output. – EricAsh May 02 '22 at 12:05
  • OH! I think I understand better now, sorry about that. I'll add an answer for a possible solution. – joelforsyth May 02 '22 at 13:00
  • Actually, have you tried just not including the parameter file? The template parameter object should be sufficient as long as all of the parameters are represented. I wonder if your value is getting overwritten by the parameter file. – joelforsyth May 02 '22 at 13:10

1 Answers1

3

When a bicep parameter is of type 'object', and the input is passed via -TemplateParameterObject, it apparently expects not a traditional PowerShell Object but rather a Hashtable.

To use my example bicep file above, you could construct a valid parameter and run it like this:

$objArray1 = @()
$objArray1 += @{ruleType='NetworkRule';name='hello'}
$objArray1 += @{ruleType='NetworkRule';name='goodbye'}

New-AzResourceGroupDeployment -TemplateFile .\NetTest.bicep -ResourceGroupName 'ericNetworking' -TemplateParameterObject @{rulesFromJson = $objArray1}

Since I had a command that was giving me powershell objects, I ended up converting it to a Hashtable as described here: PSCustomObject to Hashtable

EricAsh
  • 41
  • 1
  • 5