diff --git a/.gitignore b/.gitignore index ecfd17ea9..17398612b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,11 @@ crash.log # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan # example: *tfplan* *plan* +!src/bicep/** *.plan* # Mac files .DS_Store + +# Ignore deploymentVariables.json as it is specific to a single instantiation of MLZ +src/bicep/examples/deploymentVariables.json diff --git a/src/bicep/examples/README.md b/src/bicep/examples/README.md index 5b305e5cd..0bc5519d1 100644 --- a/src/bicep/examples/README.md +++ b/src/bicep/examples/README.md @@ -2,11 +2,57 @@ In this directory are examples of how to add and extend functionality on-top of MissionLZ. -You [must first deploy MissionLZ](../README.md#Deployment), then you can deploy these examples. +You [must first deploy MissionLZ](../README.md#Deployment), then you can deploy these examples. Since most examples re-use outputs from the base deployment of MLZ, we make use of the [shared variable file pattern](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/patterns-shared-variable-file) to make it easier to share common variables across all of the examples. + +## Example Explanations Example | Description ------- | ----------- [Remote Access](./remoteAccess) | Adds a Bastion Host and a virtual machine to serve as a jumpbox into the network [New Workload](./newWorkload) | Adds a new Spoke Network and peers it to the Hub Network routing all traffic to the Azure Firewall -[Azure Sentinel](./sentinel) | A Terraform module that adds an Azure Sentinel solution to a Log Analytics Workspace +[Azure Sentinel](./sentinel) | A Terraform module that adds an Azure Sentinel solution to a Log Analytics Workspace. Sentinel can also be deployed via bicep and the base deployment of mlz.bicep by using the boolean param '-deploySentinel'. +[Inherit Tags](./inheritTags) | Adds or replaces a specified tag and value from the parent resource group when any resource is created or updated. +[appServicePlan](./appServicePlan) | Deploys an App Service Plan (AKA: Web Server Cluster) to support simple web accessible linux docker containers with optional dynamic auto scaling. + +## Shared Variable File Pattern (deploymentVariables.json) + +The shared variable file pattern reduced the repeition of shared values in a library of bicep files. This pattern is utilized for all examples modules though in almost all cases you can over-ride the shared variable value by supplying custom parameter values at run time. + +Shown below are two ways by which the shared variable file (deploymentVariables.json) can be generated. The first utilizing PowerShell Core and the second using the Azure CLI. A deployment of mlz.bicep is required, please make note of the name and region of the deployment. + +### PowerShell Core + +Shown below are step by step instructions for generated the needed deploymentVariables.json file utilizing PowerShell Core and the Auzre PowerShell module. PowerShell and the Azure PowerShell module are open-source and avaliable for all major operating systems. + +* [Get PowerShell Core](https://github.com/PowerShell/PowerShell/releases) +* [Get Azure PowerShell](https://docs.microsoft.com/en-us/powershell/azure/install-az-ps) +* [Getting Started with Azure PowerShell](https://docs.microsoft.com/en-us/powershell/azure/get-started-azureps) + +Execute the following commands from '.\src\bicep\examples\' + +```PowerShell +Connect-AzAccount +(Get-AzSubscriptionDeployment -Name MLZDeploymentName).outputs | ConvertTo-Json | Out-File -FilePath .\deploymentVariables.json +``` + +Replace "MLZDeploymentName" with your deployment name. If you do not know your deployment name then log into the Azure management portal, browse to 'Subscriptions', select the subscription MLZ was deployed into, and then look at 'Deployments' to obtain the deployment name. + +Place the 'deploymentVariables.json' file '.\src\bicep\examples\' folder. + +### Azure CLI + +Shown below are step by step instructions for generated the needed deploymentVariables.json file utilizing the Azure CLI. The Azure CLI is open-source and avaliable for all major operating systems. + +* [Get Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) +* [Getting started with Azure CLI](https://docs.microsoft.com/en-us/cli/azure/get-started-with-azure-cli) + +Execute the following commands from '.\src\bicep\examples\' + +```Azure CLI +az login +az deployment sub show -n MLZDeploymentName --query properties.outputs >> ./deploymentVariables.json +``` + +Replace "MLZDeploymentName" with your deployment name. If you do not know your deployment name then log into the [Azure management portal](https://portal.azure.com), browse to 'Subscriptions', select the subscription MLZ was deployed into, and then look at 'Deployments' to obtain the deployment name. +Place the 'deploymentVariables.json' file '.\src\bicep\examples\' folder. For a specific example of a Bicep template utilizing 'deploymentVariables.json', take a look at [.\appServicePlan\appService.bicep](.\appServicePlan\appService.bicep) diff --git a/src/bicep/examples/appServicePlan/README.md b/src/bicep/examples/appServicePlan/README.md new file mode 100644 index 000000000..8fb0cb3cb --- /dev/null +++ b/src/bicep/examples/appServicePlan/README.md @@ -0,0 +1,63 @@ +# App Service Plan Example + +This example deploys an App Service Plan (AKA: Web Server Cluster) to support simple web accessible linux docker containers. It also optionally supports the use of dynamic (up and down) scale settings based on CPU percentage up to a max of 10 compute instances. + +Read on to understand what this example does, and when you're ready, collect all of the pre-requisites, then deploy the example. + +## What this example does + +### Deploys an Azure App Service Plan + +The docs on Azure App Service Plans: . This sample shows how to deploy using Bicep and utilizes the shared file variable pattern to support the deployment. By default, this template will deploy resources into standard default MLZ subscriptions and resource groups. + +The subscription and resource group can be changed by providing the resource group name (Param: targetResourceGroup) and ensuring that the Azure context is set the proper subscription. + +## Pre-requisites + +1. A Mission LZ deployment (a deployment of mlz.bicep) +2. The outputs from a deployment of mlz.bicep (./src/bicep/examples/deploymentVariables.json). + +See below for information on how to create the appropriate deployment variables file for use with this template. + +### Template Parameters + +Template Parameters Name | Description +-----------------------| ----------- +appServicePlanName | The name of the App Service Plan. If not specified, the name will default to the MLZ default naming pattern. +targetResourceGroup | The name of the resource group where the App Service Plan will be deployed. If not specified, the resource group name will default to the shared services MLZ resource group name and subscription. +enableAutoScale | A true/false value that determines if dynamic auto scale is enabled. If set to "true", dynamic auto scale is enabled up to a maximum of 10 compute instances based on CPU percentage exceeding 70% for 10 minutes. Will also scale down if CPU percentage is below 30% for 10 minutes. If set to "false", the App Service Plan will statically maintain two compute instances indefinitely. + +### Generate MLZ Variable File (deploymentVariables.json) + +For instructions on generating 'deploymentVariables.json' using both Azure PowerShell and Azure CLI, please see the [README at the root of the examples folder](..\README.md). + +Place the resulting 'deploymentVariables.json' file within the ./src/bicep/examples folder. + +### Deploying App Service Plan + +Connect to the appropriate Azure Environment and set appropriate context, see getting started with Azure PowerShell for help if needed. The commands below assume you are deploying in Azure Commercial and show the entire process from deploying MLZ and then adding an Azure App Service Plan post-deployment. + +```PowerShell +cd .\src\bicep +Connect-AzAccount +New-AzSubscriptionDeployment -Name contoso -TemplateFile .\mlz.bicep -resourcePrefix 'contoso' -Location 'eastus' +cd .\examples +(Get-AzSubscriptionDeployment -Name contoso).outputs | ConvertTo-Json | Out-File -FilePath .\deploymentVariables.json +cd .\AppServicePlan +New-AzSubscriptionDeployment -DeploymentName deployAppServicePlan -TemplateFile .\appService.bicep -Location 'eastus' +``` + +```Azure CLI +az login +cd src/bicep +az deployment sub create -n contoso -f mlz.bicep -l eastus --parameters resourcePrefix=contoso +cd examples +az deployment sub show -n contoso --query properties.outputs > ./deploymentVariables.json +cd appServicePlan +az deployment sub create -n deployAppServicePlan -f appService.bicep -l eastus +``` + +### References + +* +* diff --git a/src/bicep/examples/appServicePlan/appService.bicep b/src/bicep/examples/appServicePlan/appService.bicep new file mode 100644 index 000000000..d308d6333 --- /dev/null +++ b/src/bicep/examples/appServicePlan/appService.bicep @@ -0,0 +1,52 @@ +/* +Deployes a web server farm(aka: App Service Plan) to support web container deployments for Linux. +Optionally enable dynamic auto scaling based on CPU Percentages using 'enableAutoScale' true/false +*/ +targetScope = 'subscription' + +param mlzDeploymentVariables object = json(loadTextContent('../deploymentVariables.json')) + +@description('The name of the web server farm which will be created. If unchanged or not specified, the MLZ resource prefix + "--ASP" will be utilized.') +param appServicePlanName string = '${mlzDeploymentVariables.mlzResourcePrefix.Value}-asp' + +@description('The name of the resource group in which the app service plan will be deployed. If unchanged or not specified, the MLZ shared services resource group is used.') +param targetResourceGroup string = '${mlzDeploymentVariables.spokes.Value[2].resourceGroupName}' + +@description('If true, enables dynamic scale-in & scale-out based on CPU percentages. If false, then compute instances remain static with 2 instances supporting all traffic') +param enableAutoScale bool = true + +@description('Defines the performance tier of your web farm. By default the performance scale will be premium 2nd generation version 2 "p2v2". Another value would be standard generation 2 "s2".') +param appServiceSkuName string = 'p2v2' + +var targetSubscriptionId_Var = targetResourceGroup == '${mlzDeploymentVariables.spokes.Value[2].resourceGroupName}' ? '${mlzDeploymentVariables.spokes.Value[2].subscriptionId}' : subscription().subscriptionId +var location = deployment().location +var kind = 'linux' +var capacity = 2 + +resource targetASPResourceGroup 'Microsoft.Resources/resourceGroups@2020-10-01' = { + name: targetResourceGroup + location: location +} + +module appServicePlan 'modules/appServicePlan.bicep' = { + name: appServicePlanName + scope: resourceGroup(targetSubscriptionId_Var, targetASPResourceGroup.name) + params: { + location: location + svcPlanName: appServicePlanName + sku: appServiceSkuName + capacity: capacity + kind: kind + } +} +module appServicePlanSettings 'modules/appServiceSettings.bicep' = if (enableAutoScale) { + name: 'appServicePlanSettingsName' + scope: resourceGroup(targetSubscriptionId_Var, targetASPResourceGroup.name) + params: { + location: location + svcPlanName: appServicePlan.outputs.svcPlanName + svcPlanNameID: appServicePlan.outputs.svcPlanID + } +} +output appServicePlanName string = appServicePlanName +output resourceGroupName string = targetResourceGroup diff --git a/src/bicep/examples/appServicePlan/appService.json b/src/bicep/examples/appServicePlan/appService.json new file mode 100644 index 000000000..8606f29b7 --- /dev/null +++ b/src/bicep/examples/appServicePlan/appService.json @@ -0,0 +1,343 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1008.15138", + "templateHash": "2691389334860595334" + } + }, + "parameters": { + "mlzDeploymentVariables": { + "type": "object", + "defaultValue": "[json('{\r\n \"mlzResourcePrefix\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"contoso\"\r\n },\r\n \"firewallPrivateIPAddress\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"10.0.100.4\"\r\n },\r\n \"hub\": {\r\n \"Type\": \"Object\",\r\n \"Value\": {\r\n \"subscriptionId\": \"093847b0-f0dd-428f-a0b0-bd4245b99339\",\r\n \"resourceGroupName\": \"contoso-hub\",\r\n \"resourceGroupResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-hub\",\r\n \"virtualNetworkName\": \"hub-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-hub/providers/Microsoft.Network/virtualNetworks/hub-vnet\",\r\n \"subnetName\": \"hub-vnet/hub-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-hub/providers/Microsoft.Network/virtualNetworks/hub-vnet/subnets/hub-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.100.128/27\",\r\n \"networkSecurityGroupName\": \"hub-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-hub/providers/Microsoft.Network/networkSecurityGroups/hub-nsg\"\r\n }\r\n },\r\n \"logAnalyticsWorkspaceName\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"contoso-laws\"\r\n },\r\n \"logAnalyticsWorkspaceResourceId\": {\r\n \"Type\": \"String\",\r\n \"Value\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-operations/providers/Microsoft.OperationalInsights/workspaces/contoso-laws\"\r\n },\r\n \"spokes\": {\r\n \"Type\": \"Array\",\r\n \"Value\": [\r\n {\r\n \"name\": \"operations\",\r\n \"subscriptionId\": \"093847b0-f0dd-428f-a0b0-bd4245b99339\",\r\n \"resourceGroupName\": \"contoso-operations\",\r\n \"resourceGroupId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-operations\",\r\n \"virtualNetworkName\": \"operations-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-operations/providers/Microsoft.Network/virtualNetworks/operations-vnet\",\r\n \"subnetName\": \"operations-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-operations/providers/Microsoft.Network/virtualNetworks/operations-vnet/subnets/operations-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.115.0/27\",\r\n \"networkSecurityGroupName\": \"operations-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-operations/providers/Microsoft.Network/networkSecurityGroups/operations-nsg\"\r\n },\r\n {\r\n \"name\": \"identity\",\r\n \"subscriptionId\": \"093847b0-f0dd-428f-a0b0-bd4245b99339\",\r\n \"resourceGroupName\": \"contoso-identity\",\r\n \"resourceGroupId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-identity\",\r\n \"virtualNetworkName\": \"identity-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-identity/providers/Microsoft.Network/virtualNetworks/identity-vnet\",\r\n \"subnetName\": \"identity-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-identity/providers/Microsoft.Network/virtualNetworks/identity-vnet/subnets/identity-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.110.0/27\",\r\n \"networkSecurityGroupName\": \"identity-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-identity/providers/Microsoft.Network/networkSecurityGroups/identity-nsg\"\r\n },\r\n {\r\n \"name\": \"sharedServices\",\r\n \"subscriptionId\": \"093847b0-f0dd-428f-a0b0-bd4245b99339\",\r\n \"resourceGroupName\": \"contoso-sharedServices\",\r\n \"resourceGroupId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-sharedServices\",\r\n \"virtualNetworkName\": \"sharedServices-vnet\",\r\n \"virtualNetworkResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-sharedServices/providers/Microsoft.Network/virtualNetworks/sharedServices-vnet\",\r\n \"subnetName\": \"sharedServices-subnet\",\r\n \"subnetResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-sharedServices/providers/Microsoft.Network/virtualNetworks/sharedServices-vnet/subnets/sharedServices-subnet\",\r\n \"subnetAddressPrefix\": \"10.0.120.0/27\",\r\n \"networkSecurityGroupName\": \"sharedServices-nsg\",\r\n \"networkSecurityGroupResourceId\": \"/subscriptions/093847b0-f0dd-428f-a0b0-bd4245b99339/resourceGroups/contoso-sharedServices/providers/Microsoft.Network/networkSecurityGroups/sharedServices-nsg\"\r\n }\r\n ]\r\n }\r\n}\r\n')]" + }, + "appServicePlanName": { + "type": "string", + "defaultValue": "[format('{0}-asp', parameters('mlzDeploymentVariables').mlzResourcePrefix.Value)]", + "metadata": { + "description": "The name of the web server farm which will be created. If unchanged or not specified, the MLZ resource prefix + \"--ASP\" will be utilized." + } + }, + "targetResourceGroup": { + "type": "string", + "defaultValue": "[format('{0}', parameters('mlzDeploymentVariables').spokes.Value[2].resourceGroupName)]", + "metadata": { + "description": "The name of the resource group in which the app service plan will be deployed. If unchanged or not specified, the MLZ shared services resource group is used." + } + }, + "enableAutoScale": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "If true, enables dynamic scale-in & scale-out based on CPU percentages. If false, then compute instances remain static with 2 instances supporting all traffic" + } + } + }, + "functions": [], + "variables": { + "targetSubscriptionId_Var": "[if(equals(parameters('targetResourceGroup'), format('{0}', parameters('mlzDeploymentVariables').spokes.Value[2].resourceGroupName)), format('{0}', parameters('mlzDeploymentVariables').spokes.Value[2].subscriptionId), subscription().subscriptionId)]", + "location": "[deployment().location]", + "kind": "linux", + "capacity": 2, + "sku": "premium" + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2020-10-01", + "name": "[parameters('targetResourceGroup')]", + "location": "[variables('location')]" + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "[parameters('appServicePlanName')]", + "subscriptionId": "[variables('targetSubscriptionId_Var')]", + "resourceGroup": "[parameters('targetResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[variables('location')]" + }, + "svcPlanName": { + "value": "[parameters('appServicePlanName')]" + }, + "sku": { + "value": "[variables('sku')]" + }, + "capacity": { + "value": "[variables('capacity')]" + }, + "kind": { + "value": "[variables('kind')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1008.15138", + "templateHash": "14684044973590456081" + } + }, + "parameters": { + "svcPlanName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "capacity": { + "type": "int", + "defaultValue": 2 + }, + "kind": { + "type": "string" + }, + "sku": { + "type": "string" + }, + "svcPlanSize": { + "type": "string", + "defaultValue": "P2v2", + "metadata": { + "description": "The instance size of the app." + } + } + }, + "functions": [], + "variables": { + "reserved": "[if(equals(parameters('kind'), 'linux'), true(), false())]" + }, + "resources": [ + { + "type": "Microsoft.Web/serverfarms", + "apiVersion": "2020-12-01", + "name": "[parameters('svcPlanName')]", + "location": "[parameters('location')]", + "kind": "[parameters('kind')]", + "sku": { + "name": "[parameters('svcPlanSize')]", + "tier": "[parameters('sku')]", + "capacity": "[parameters('capacity')]" + }, + "properties": { + "reserved": "[variables('reserved')]" + } + } + ], + "outputs": { + "svcPlanName": { + "type": "string", + "value": "[parameters('svcPlanName')]" + }, + "svcPlanID": { + "type": "string", + "value": "[resourceId('Microsoft.Web/serverfarms', parameters('svcPlanName'))]" + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('targetResourceGroup'))]" + ] + }, + { + "condition": "[parameters('enableAutoScale')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "appServicePlanSettingsName", + "subscriptionId": "[variables('targetSubscriptionId_Var')]", + "resourceGroup": "[parameters('targetResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[variables('location')]" + }, + "svcPlanName": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('targetSubscriptionId_Var'), parameters('targetResourceGroup')), 'Microsoft.Resources/deployments', parameters('appServicePlanName')), '2020-06-01').outputs.svcPlanName.value]" + }, + "svcPlanNameID": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('targetSubscriptionId_Var'), parameters('targetResourceGroup')), 'Microsoft.Resources/deployments', parameters('appServicePlanName')), '2020-06-01').outputs.svcPlanID.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1008.15138", + "templateHash": "7636819529925623419" + } + }, + "parameters": { + "svcPlanName": { + "type": "string" + }, + "svcPlanNameID": { + "type": "string" + }, + "location": { + "type": "string" + }, + "minimumCapacity": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "The minimum capacity. Autoscale engine will ensure the instance count is at least this value." + } + }, + "maximumCapacity": { + "type": "int", + "defaultValue": 10, + "metadata": { + "description": "The maximum capacity. Autoscale engine will ensure the instance count is not greater than this value." + } + }, + "defaultCapacity": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "The default capacity. Autoscale engine will preventively set the instance count to be this value if it can not find any metric data." + } + }, + "metricName": { + "type": "string", + "defaultValue": "CpuPercentage", + "metadata": { + "description": "The metric name." + } + }, + "metricThresholdToScaleOut": { + "type": "int", + "defaultValue": 70, + "metadata": { + "description": "The metric upper threshold. If the metric value is above this threshold then autoscale engine will initiate scale out action." + } + }, + "metricThresholdToScaleIn": { + "type": "int", + "defaultValue": 30, + "metadata": { + "description": "The metric lower threshold. If the metric value is below this threshold then autoscale engine will initiate scale in action." + } + }, + "changePercentScaleOut": { + "type": "int", + "defaultValue": 20, + "metadata": { + "description": "The percentage to increase the instance count when autoscale engine is initiating scale out action." + } + }, + "changePercentScaleIn": { + "type": "int", + "defaultValue": 10, + "metadata": { + "description": "The percentage to decrease the instance count when autoscale engine is initiating scale in action." + } + }, + "autoscaleEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "A boolean to indicate whether the autoscale policy is enabled or disabled." + } + } + }, + "functions": [], + "variables": { + "settingName_var": "[format('{0}-setting', toLower(parameters('svcPlanName')))]", + "targetResourceId": "[parameters('svcPlanNameID')]" + }, + "resources": [ + { + "type": "Microsoft.Insights/autoscalesettings", + "apiVersion": "2015-04-01", + "name": "[variables('settingName_var')]", + "location": "[parameters('location')]", + "properties": { + "profiles": [ + { + "name": "DefaultAutoscaleProfile", + "capacity": { + "minimum": "[string(parameters('minimumCapacity'))]", + "maximum": "[string(parameters('maximumCapacity'))]", + "default": "[string(parameters('defaultCapacity'))]" + }, + "rules": [ + { + "metricTrigger": { + "metricName": "[parameters('metricName')]", + "metricResourceUri": "[variables('targetResourceId')]", + "timeGrain": "PT5M", + "statistic": "Average", + "timeWindow": "PT10M", + "timeAggregation": "Average", + "operator": "GreaterThan", + "threshold": "[parameters('metricThresholdToScaleOut')]" + }, + "scaleAction": { + "direction": "Increase", + "type": "PercentChangeCount", + "value": "[string(parameters('changePercentScaleOut'))]", + "cooldown": "PT20M" + } + }, + { + "metricTrigger": { + "metricName": "[parameters('metricName')]", + "metricResourceUri": "[variables('targetResourceId')]", + "timeGrain": "PT5M", + "statistic": "Average", + "timeWindow": "PT10M", + "timeAggregation": "Average", + "operator": "LessThan", + "threshold": "[parameters('metricThresholdToScaleIn')]" + }, + "scaleAction": { + "direction": "Decrease", + "type": "PercentChangeCount", + "value": "[string(parameters('changePercentScaleIn'))]", + "cooldown": "PT20M" + } + } + ] + } + ], + "enabled": "[parameters('autoscaleEnabled')]", + "targetResourceUri": "[variables('targetResourceId')]" + } + } + ] + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('targetSubscriptionId_Var'), parameters('targetResourceGroup')), 'Microsoft.Resources/deployments', parameters('appServicePlanName'))]", + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('targetResourceGroup'))]" + ] + } + ], + "outputs": { + "appServicePlanName": { + "type": "string", + "value": "[parameters('appServicePlanName')]" + }, + "resourceGroupName": { + "type": "string", + "value": "[parameters('targetResourceGroup')]" + } + } +} \ No newline at end of file diff --git a/src/bicep/examples/appServicePlan/modules/appServicePlan.bicep b/src/bicep/examples/appServicePlan/modules/appServicePlan.bicep new file mode 100644 index 000000000..99383940e --- /dev/null +++ b/src/bicep/examples/appServicePlan/modules/appServicePlan.bicep @@ -0,0 +1,23 @@ +param svcPlanName string +param location string +param capacity int = 2 +param kind string +param sku string + +var reserved = kind == 'linux' ? true : false + +resource svcPlanName_resource 'Microsoft.Web/serverfarms@2020-12-01' = { + name: svcPlanName + location: location + kind: kind + sku: { + name: sku + capacity: capacity + } + properties: { + reserved: reserved + } +} + +output svcPlanName string = svcPlanName_resource.name +output svcPlanID string = svcPlanName_resource.id diff --git a/src/bicep/examples/appServicePlan/modules/appServiceSettings.bicep b/src/bicep/examples/appServicePlan/modules/appServiceSettings.bicep new file mode 100644 index 000000000..8450007c5 --- /dev/null +++ b/src/bicep/examples/appServicePlan/modules/appServiceSettings.bicep @@ -0,0 +1,90 @@ +param svcPlanName string +param svcPlanNameID string +param location string + +@description('The minimum capacity. Autoscale engine will ensure the instance count is at least this value.') +param minimumCapacity int = 2 + +@description('The maximum capacity. Autoscale engine will ensure the instance count is not greater than this value.') +param maximumCapacity int = 10 + +@description('The default capacity. Autoscale engine will preventively set the instance count to be this value if it can not find any metric data.') +param defaultCapacity int = 2 + +@description('The metric name.') +param metricName string = 'CpuPercentage' + +@description('The metric upper threshold. If the metric value is above this threshold then autoscale engine will initiate scale out action.') +param metricThresholdToScaleOut int = 70 + +@description('The metric lower threshold. If the metric value is below this threshold then autoscale engine will initiate scale in action.') +param metricThresholdToScaleIn int = 30 + +@description('The percentage to increase the instance count when autoscale engine is initiating scale out action.') +param changePercentScaleOut int = 20 + +@description('The percentage to decrease the instance count when autoscale engine is initiating scale in action.') +param changePercentScaleIn int = 10 + +@description('A boolean to indicate whether the autoscale policy is enabled or disabled.') +param autoscaleEnabled bool = true + +var settingName_var = '${toLower(svcPlanName)}-setting' +var targetResourceId = svcPlanNameID + +resource settingName 'Microsoft.Insights/autoscalesettings@2015-04-01' = { + name: settingName_var + location: location + properties: { + profiles: [ + { + name: 'DefaultAutoscaleProfile' + capacity: { + minimum: string(minimumCapacity) + maximum: string(maximumCapacity) + default: string(defaultCapacity) + } + rules: [ + { + metricTrigger: { + metricName: metricName + metricResourceUri: targetResourceId + timeGrain: 'PT5M' + statistic: 'Average' + timeWindow: 'PT10M' + timeAggregation: 'Average' + operator: 'GreaterThan' + threshold: metricThresholdToScaleOut + } + scaleAction: { + direction: 'Increase' + type: 'PercentChangeCount' + value: string(changePercentScaleOut) + cooldown: 'PT20M' + } + } + { + metricTrigger: { + metricName: metricName + metricResourceUri: targetResourceId + timeGrain: 'PT5M' + statistic: 'Average' + timeWindow: 'PT10M' + timeAggregation: 'Average' + operator: 'LessThan' + threshold: metricThresholdToScaleIn + } + scaleAction: { + direction: 'Decrease' + type: 'PercentChangeCount' + value: string(changePercentScaleIn) + cooldown: 'PT20M' + } + } + ] + } + ] + enabled: autoscaleEnabled + targetResourceUri: targetResourceId + } +} diff --git a/src/bicep/mlz.bicep b/src/bicep/mlz.bicep index 3a28d1015..d733b63a4 100644 --- a/src/bicep/mlz.bicep +++ b/src/bicep/mlz.bicep @@ -590,7 +590,7 @@ var spokes = [ ] // outputs - +output mlzResourcePrefix string = resourcePrefix output firewallPrivateIPAddress string = hubNetwork.outputs.firewallPrivateIPAddress output hub object = { diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index b6e5ed9b2..afcce18ac 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.4.1008.15138", - "templateHash": "17151661725468237381" + "templateHash": "8860935919538003927" } }, "parameters": { @@ -5783,6 +5783,10 @@ } ], "outputs": { + "mlzResourcePrefix": { + "type": "string", + "value": "[parameters('resourcePrefix')]" + }, "firewallPrivateIPAddress": { "type": "string", "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), parameters('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('nowUtc'))), '2020-06-01').outputs.firewallPrivateIPAddress.value]"