1

I am trying to create an ARM template that will provision multiple webservers with directly accessible ports. For instance I want a VM to have either port 9001 or 9002 open based on what the index of the VM is.

I am struggling to get the frontendPort parameter to accept a function. Here is the documentation that I have used.

Here is what the relevant portion of my template looks like:

"inboundNatRules": [
{
    "copy": {
        "name": "natCopy",
        "count": "[parameters('numberOfVms')]"
    },
    "name": "[concat('directHttps-', copyIndex())]",
    "properties": {
        "frontendIPConfiguration": {
            "id": "[concat(variables('lbID'),'/frontendIPConfigurations/LoadBalancerFrontEnd')]"
        },
        "frontendPort": "[add(9001, copyIndex())]",
        "backendPort": 9001,
        "enableFloatingIP": false,
        "idleTimeoutInMinutes": 4,
        "protocol": "Tcp",
        "backendIPConfiguration": {
            "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('vmNicName'), copyIndex()), 'ipconfig')]"
        }
    }
}

]

I was hoping that the this particular port would result in either "9001", or "9002".

"frontendPort": "[add(9001, copyIndex())]"

Instead, I see an error in Visual Studio's Intellisense, and when I try to deploy the solution.

VS Intellisense Error

Create template deployment 'deploymenttemplate-0107-1555'.
New-AzureRmResourceGroupDeployment : Resource Microsoft.Network/loadBalancers 'webserverLb'
failed with message 'Unable to process template language expressions for resource
'/subscriptions/some random guid/resourceGroups/webservers/providers/Microsoft.Network/loadBalancers/webserverLb'
at line '102' and column '10'. 'The template function 'copyIndex' is not expected at this location.
The function can only be used in a resource with copy specified.

Long story short, I'm simply trying to have the same number of NAT rules as I have VM's in the template, and dynamically assign the external port number.

Please let me know if I can provide any more information. Thank you.

JTaub
  • 1,273
  • 11
  • 16

4 Answers4

0

Try:

[Concat(900,CopyIndex(1))]

which will offset the index (0 based) and give you the number you want.

kenorb
  • 155,785
  • 88
  • 678
  • 743
0

This is the syntax that works for copying the NAT rules (I am adding an RDP rule on the standard back-end port):

    "copy": [
    {
        "name": "inboundNatRules",
        "count": "[parameters('numberOfWebInstances')]",
        "input": {
            "name": "[concat(parameters('lbNatRulePrefix'), copyindex('inboundNatRules'))]",
            "properties": {
                "frontendIPConfiguration": {
                    "id": "[variables('lbFrontEndIpId')]"
                },
                "frontendPort": "[add(50001, copyIndex('inboundNatRules'))]",
                "backendPort": 3389,
                "enableFloatingIP": false,
                "idleTimeoutInMinutes": 4,
                "protocol": "tcp"
            }
        }
    }
],

And then to apply the rules to the NIC, you actually need to add some code on the NIC itself. The following is for both LB rules and NAT rules:

    "loadBalancerBackendAddressPools": [
    {
        "id": "[concat(variables('lbID'), '/backendAddressPools/', parameters('lbPoolName'))]"
    }
],
"loadBalancerInboundNatRules": [
    {
        "id": "[concat(variables('lbID'),'/inboundNatRules/' , parameters('lbNatRulePrefix'), copyindex())]"
    }
]
DivineOps
  • 1,656
  • 16
  • 17
0
#Your script is wrong it should you are writing copyindex() but you need to pass the name of rule it should work. 


"inboundNatRules": [
{
    "copy": {
        "name": "natCopy",
        "count": "[parameters('numberOfVms')]"
    },
    "name": "[concat('directHttps-', copyIndex(natCopy,1))]",
    "properties": {
        "frontendIPConfiguration": {
            "id": "[concat(variables('lbID'),'/frontendIPConfigurations/LoadBalancerFrontEnd')]"
        },
        "frontendPort": "[add(9001, copyIndex(natCopy,1))]",
        "backendPort": 9001,
        "enableFloatingIP": false,
        "idleTimeoutInMinutes": 4,
        "protocol": "Tcp",
        "backendIPConfiguration": {
            "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('vmNicName'), copyIndex(natCopy,1)), 'ipconfig')]"
        }
    }
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 22 '22 at 18:08
-1
$LoadBalancer = Get-AzureRmLoadBalancer -ResourceGroupName $ResourceGroupName -Name $LoadBalancerName
$publicIP1 = Get-AzureRmPublicIpAddress -name $pipName -resourcegroupname $ResourceGroupName
$frontendIP1 = Get-AzureRmLoadBalancerFrontendIpConfig -LoadBalancer $LoadBalancer -Name $FrontendIpConfigName
$LoadBalancer | Add-AzureRmLoadBalancerInboundNatRuleConfig -Name "nat_rule_tcp_IP1_49157" -FrontendIpConfiguration $frontendIP1 -IdleTimeoutInMinutes 4  -Protocol TCP -FrontendPort 49157 -BackendPort 49157 | Set-AzureRmLoadBalancer
Skeezwiz
  • 31
  • 7