I am using below ARM template to create Application Gateway. When I deploy it for the first time everything works. When I redeploy it (as a part of continuous deployment in the same env) it fails and I see the Listeners get deleted which were present previously and the SSL certificate also gets deleted.
Is there any option I can update the sub-resources present in ARM template based on a criteria something like not to update the listener if SSL cert is already present. I am updating some of the properties like creating rules and probe after creation of application gateway and not using ARM template.
ARM Template for reference-
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"applicationgateway_platform": {
"defaultValue": "",
"type": "String",
"maxLength": 6
},
"applicationgateway_location_shortname": {
"defaultValue": "",
"type": "String",
"maxLength": 3
},
"applicationgateway_project": {
"defaultValue": "",
"type": "String",
"maxLength": 6
},
"applicationgateway_environment": {
"defaultValue": "",
"type": "String",
"maxLength": 7
},
"applicationgateway_uniqueid": {
"defaultValue": "1",
"type": "String",
"maxLength": "1"
},
"vnetName": {
"type": "string",
"metadata": {
"description": "Name of the Virtual Network"
}
},
"subnetName": {
"type": "string",
"metadata": {
"description": "Name of subnet"
}
},
"vnetResourceGroup": {
"type": "string",
"defaultValue": "[resourceGroup().name]",
"metadata": {
"description": "Name of Resource group where Vnet and subnet resides"
}
},
"applicationGatewayTier": {
"type": "string",
"allowedValues": [
"Standard_v2",
"WAF_v2"
],
"defaultValue": "WAF_v2",
"metadata": {
"description": "application gateway tier"
}
},
"frontendPort": {
"type": "int",
"defaultValue": 80,
"metadata": {
"description": "application gateway front end port"
}
},
"secureFrontendPort": {
"type": "int",
"defaultValue": 443,
"metadata": {
"description": "application gateway secure front end port"
}
},
"backendPort": {
"type": "int",
"defaultValue": 80,
"metadata": {
"description": "application gateway back end port"
}
},
"applicationGatewayAutoScaleMinimumCapacity": {
"type": "int",
"defaultValue": 1,
"metadata": {
"description": "Minimum appgateway instance to be running always"
}
},
"applicationGatewayAutoScaleMaximumCapacity": {
"type": "int",
"defaultValue": 10,
"metadata": {
"description": "Maximum appgateway instance that it can scale up."
}
}
},
"variables": {
"basename": "[concat(parameters('applicationgateway_platform'), '-', parameters('applicationgateway_project'), '-', parameters('applicationgateway_location_shortname'), '-', parameters('applicationgateway_environment'))]",
"applicationGatewayName": "[concat(variables('basename'), '-ag-', parameters('applicationgateway_uniqueid'))]",
"publicIPAddressName": "[concat(variables('basename'),'-agip-',parameters('applicationgateway_uniqueid'))]",
"subnetRef": "[concat(resourceId(parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName')), '/subnets/', parameters('subnetName'))]",
"publicIPRef": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
"webApplicationFirewallConfigurationProperties": {
"enabled": true,
"firewallMode": "Detection",
"ruleSetType": "OWASP",
"ruleSetVersion": "3.0"
},
"apiVersion": "2019-09-01"
},
"resources": [
{
"apiVersion": "[variables('apiVersion')]",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard"
},
"zones": [],
"properties": {
"publicIPAllocationMethod": "Static",
"dnsSettings": {
"domainNameLabel": "[variables('applicationGatewayName')]"
}
}
},
{
"apiVersion": "[variables('apiVersion')]",
"name": "[variables('applicationGatewayName')]",
"type": "Microsoft.Network/applicationGateways",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('publicIPRef')]"
],
"properties": {
"sku": {
"name": "[parameters('applicationGatewayTier')]",
"tier": "[parameters('applicationGatewayTier')]"
},
"gatewayIPConfigurations": [
{
"name": "appGatewayIpConfig",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
],
"frontendIPConfigurations": [
{
"name": "appGatewayFrontendIP",
"properties": {
"PublicIPAddress": {
"id": "[variables('publicIPRef')]"
}
}
}
],
"frontendPorts": [
{
"name": "appGatewayFrontendPort",
"properties": {
"Port": "[parameters('frontendPort')]"
}
},
{
"name": "appGatewaySecurePort",
"properties": {
"Port": "[parameters('secureFrontendPort')]"
}
}
],
"backendAddressPools": [
{
"name": "appGatewayBackendPool",
"properties": {
"BackendAddresses": []
}
}
],
"backendHttpSettingsCollection": [
{
"name": "appGatewayBackendHttpSettings",
"properties": {
"Port": "[parameters('backendPort')]",
"Protocol": "Http",
"CookieBasedAffinity": "disabled",
"requestTimeout": 20
}
}
],
"httpListeners": [
{
"name": "appGatewayHttpListener",
"properties": {
"FrontendIpConfiguration": {
"Id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('applicationGatewayName')), '/frontendIPConfigurations/appGatewayFrontendIP')]"
},
"FrontendPort": {
"Id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('applicationGatewayName')), '/frontendPorts/appGatewayFrontendPort')]"
},
"Protocol": "Http",
"SslCertificate": null
}
}
],
"requestRoutingRules": [
{
"Name": "basicRule",
"properties": {
"RuleType": "Basic",
"httpListener": {
"id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('applicationGatewayName')), '/httpListeners/appGatewayHttpListener')]"
},
"backendAddressPool": {
"id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('applicationGatewayName')), '/backendAddressPools/appGatewayBackendPool')]"
},
"backendHttpSettings": {
"id": "[concat(resourceId('Microsoft.Network/applicationGateways', variables('applicationGatewayName')), '/backendHttpSettingsCollection/appGatewayBackendHttpSettings')]"
}
}
}
],
"enableHttp2": false,
"sslCertificates": [],
"probes": [],
"autoscaleConfiguration": {
"minCapacity": "[parameters('applicationGatewayAutoScaleMinimumCapacity')]",
"maxCapacity": "[parameters('applicationGatewayAutoScaleMaximumCapacity')]"
},
"webApplicationFirewallConfiguration": "[if(equals(toUpper(parameters('applicationGatewayTier')), 'WAF_V2'), variables('webApplicationFirewallConfigurationProperties'), json('null'))]"
}
}
]
}
By default, Resource Manager deployment uses incremental mode. In incremental mode, Resource Manager leaves unchanged resources that exist in the resource group but aren't specified in the template.
However, when redeploying an existing resource in incremental mode, the outcome is different. Specify all properties for the resource, not just the ones you're updating. A common misunderstanding is to think properties that aren't specified are left unchanged. If you don't specify certain properties, Resource Manager interprets the update as overwriting those values.
So, if you want some properties to leave unchanged when redeploying the template, you can specify certain properties (listeners for HTTPS, rules for HTTPS, SSL certificate) in your template. Here is a quickstart template for an end to end SSL with an application gateway that you can refer to.
To update a resource in an Azure Resource Manager template, you could follow the link for more details.
First, you must reference the resource once in the template to create it and then reference the resource by the same name to update it later. However, if two resources have the same name in a template, Resource Manager throws an exception. To avoid this error, specify the updated resource in a second template that's either linked or included as a subtemplate using the Microsoft.Resources/deployments resource type.
Second, you must either specify the name of the existing property to change or a new name for a property to add in the nested template. You must also specify the original properties and their original values. If you fail to provide the original properties and values, Resource Manager assumes you want to create a new resource and deletes the original resource.