{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "TemplateUsage": {
      "type": "string",
      "allowedValues": [
        "FirstVM",
        "AdditionalVM"
      ],
      "defaultValue": "FirstVM",
      "metadata": {
        "description": "FirstVM option should be selected when creating a network and a VM for the first time. AdditionalVM option should be selected when a new VM is being added to a network previously created using this template"
      }
    },
    "vnetName": {
      "type": "string",
      "defaultValue": "VNet",
      "metadata": {
        "description": "Virtual Network Name"
      }
    },
    "vnetAddressPrefix": {
      "type": "string",
      "defaultValue": "192.168.35.0/24",
      "metadata": {
        "description": "Virtual Network address prefix"
      }
    },
    "Subnets": {
      "type": "array",
      "defaultValue": [
        {
          "name": "Subnet",
          "prefix": "192.168.35.0/26"
        }
      ],
      "metadata": {
        "description": "Subnets names and address prefixes. The first specified subnet will be assigned to a VM"
      }
    },
    "publicIPaddress": {
      "type": "string",
      "allowedValues": [
        "Create",
        "No"
      ],
      "defaultValue": "Create",
      "metadata": {
        "description": "Create a static public IP address for a VM. Without a public IP address, there is no direct access to a VM"
      }
    },
    "accessAddressPrefix": {
      "type": "string",
      "defaultValue": "*",
      "metadata": {
        "description": "An IP address or a subnet permitted to access the VM. Only the specified IP address will have access to TCP port 22 (SSH on Ubuntu VM) or to TCP port 3389 (RDP on Windows VM)"
      }
    },
    "vmName": {
      "type": "string",
      "defaultValue": "vm",
      "metadata": {
        "description": "Virtual Machine Name"
      }
    },
    "OS": {
      "type": "string",
      "allowedValues": [
        "Windows2019",
        "Windows2016",
        "Ubuntu18.10",
        "Ubuntu18.04"
      ],
      "defaultValue": "Windows2016",
      "metadata": {
        "description": "OS type for the VM"
      }
    },
    "OSdisk": {
      "type": "string",
      "allowedValues": [
        "StandardHDD",
        "StandardSSD"
      ],
      "defaultValue": "StandardHDD",
      "metadata": {
        "description": "Type of OS disk (managed)"
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_B1s",
      "metadata": {
        "description": "Virtual Machine size (hardware)"
      }
    },
    "userName": {
      "type": "string",
      "defaultValue": "vm-user",
      "metadata": {
        "description": "User account name for the VM"
      }
    },
    "userPassword": {
      "type": "string",
      "defaultValue": "setpassword",
      "metadata": {
        "description": "Password for the user account"
      }
    },
    "sshKey": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Optional: public SSH key for the user account"
      }
    },
    "sshKeyOnly": {
      "type": "string",
      "allowedValues": [
        "Yes",
        "No"
      ],
      "defaultValue": "No",
      "metadata": {
        "description": "Only use SSH key authentication on Ubuntu"
      }
    },
    "availabilitySet": {
      "type": "string",
      "allowedValues": [
        "Create",
        "No"
      ],
      "defaultValue": "Create",
      "metadata": {
        "description": "Create an availability set for the VM"
      }
    },
    "avSetUDcount": {
      "type": "string",
      "defaultValue": "2",
      "metadata": {
        "description": "Availability Set Update Domain count"
      }
    },
    "avSetFDcount": {
      "type": "string",
      "defaultValue": "2",
      "metadata": {
        "description": "Availability Set Fault Domain count"
      }
    },
	  "tags": {
      "type": "object",
      "defaultValue": {"ProjectName":"Project"},
      "metadata": {
        "description": "Tags for the resources"
      }
    }
  },
  "variables": {
    "avSetId": {
      "id": "[resourceId('Microsoft.Compute/availabilitySets/', concat(parameters('vmName'),'-av'))]"
    },
    "diagstorage": "[concat('diagstorage', uniqueString(resourceGroup().id))]",
    "publicIpId": {
      "id": "[resourceId('Microsoft.Network/publicIPAddresses/', concat(parameters('vmName'),'-pip'))]"
    },
    "linuxCfg": {
      "disablePasswordAuthentication": "[if(equals(parameters('sshKeyOnly'), 'Yes'), 'true', 'false')]",
      "ssh": {
        "publicKeys": [
          {
            "path": "[concat('/home/', parameters('userName'), '/.ssh/authorized_keys')]",
            "keyData": "[parameters('sshKey')]"
          }
        ]
      }
    },
    "osType": "[if(equals(parameters('OS'), 'Windows2019'), 'Windows', if(equals(parameters('OS'), 'Windows2016'), 'Windows', if(equals(parameters('OS'), 'Ubuntu18.10'), 'Ubuntu', if(equals(parameters('OS'), 'Ubuntu18.04'), 'Ubuntu', 'Windows'))))]",
    "osPub": "[if(equals(variables('osType'), 'Windows'), 'MicrosoftWindowsServer', 'Canonical')]",
    "osOffer": "[if(equals(variables('osType'), 'Windows'), 'WindowsServer', 'UbuntuServer')]",
    "osSku": "[if(equals(parameters('OS'), 'Windows2019'), '2019-Datacenter', if(equals(parameters('OS'), 'Windows2016'), '2016-Datacenter', if(equals(parameters('OS'), 'Ubuntu18.10'), '18.10', if(equals(parameters('OS'), 'Ubuntu18.04'), '18.04-LTS', '2016-Datacenter'))))]",
    "ImageRfc": {
      "publisher": "[variables('osPub')]",
      "offer": "[variables('osOffer')]",
      "sku": "[variables('osSku')]",
      "version": "latest"
    },
    "osDiskType": "[if(equals(parameters('OSdisk'), 'StandardSSD'), 'StandardSSD_LRS', 'Standard_LRS')]"
  },
  "resources": [
    {
      "condition": "[equals(parameters('TemplateUsage'),'FirstVM')]",
      "apiVersion": "2018-11-01",
      "name": "[parameters('vnetName')]",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "copy": [
          {
            "name": "subnets",
            "count": "[length(parameters('Subnets'))]",
            "input": {
              "name": "[parameters('Subnets')[copyIndex('subnets')].name]",
              "properties": {
                "addressPrefix": "[parameters('Subnets')[copyIndex('subnets')].prefix]"
              }
            }
          }
        ]
      }
    },
    {
      "name": "[concat(parameters('vmName'),'-nsg')]",
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2018-11-01",
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "properties": {
        "securityRules": [
          {
            "name": "[if(equals(variables('osType'), 'Windows'), 'AllowRDP', 'AllowSSH')]",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "[parameters('accessAddressPrefix')]",
              "sourcePortRange": "*",
              "direction": "Inbound",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "[if(equals(variables('osType'), 'Windows'), '3389', '22')]",
              "access": "Allow",
              "priority": 100
            }
          }
        ]
      }
    },
    {
      "name": "[concat(parameters('vmName'),'-pip')]",
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2018-11-01",
      "condition": "[equals(parameters('publicIPaddress'),'Create')]",
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "sku": {
        "name": "Standard"
      },
      "properties": {
        "publicIPAllocationMethod": "Static"
      }
    },
    {
      "name": "[variables('diagstorage')]",
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2018-11-01",
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "kind": "Storage",
      "sku": {
        "name": "Standard_LRS"
      },
      "properties": {}
    },
    {
      "name": "[concat(parameters('vmName'),'-nic')]",
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2018-11-01",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks/', parameters('vnetName'))]",
        "[resourceId('Microsoft.Network/publicIPAddresses/', concat(parameters('vmName'),'-pip'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups/', concat(parameters('vmName'),'-nsg'))]"
      ],
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "IPconfiguration",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": "[if(equals(parameters('publicIPaddress'), 'Create'), variables('publicIpId'), json('null'))]",
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets/', parameters('vnetName'), parameters('Subnets')[0].name)]"
              }
            }
          }
        ],
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups/', concat(parameters('vmName'),'-nsg'))]"
        }
      }
    },
    {
      "name": "[concat(parameters('vmName'),'-av')]",
      "type": "Microsoft.Compute/availabilitySets",
      "apiVersion": "2019-03-01",
      "condition": "[equals(parameters('availabilitySet'),'Create')]",
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "properties": {
        "platformUpdateDomainCount": "[parameters('avSetUDcount')]",
        "platformFaultDomainCount": "[parameters('avSetFDcount')]"
      },
      "sku": {
        "name": "Aligned"
      }
    },
    {
      "name": "[parameters('vmName')]",
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2019-03-01",
      "location": "[resourceGroup().location]",
      "tags": "[parameters('tags')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'),'-nic'))]",
        "[resourceId('Microsoft.Compute/availabilitySets/', concat(parameters('vmName'),'-av'))]",
        "[resourceId('Microsoft.Storage/storageAccounts/', variables('diagstorage'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces/', concat(parameters('vmName'),'-nic'))]"
            }

          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[concat('https://', variables('diagstorage'), '.blob.core.windows.net/')]"
          }
        },
        "availabilitySet": "[if(equals(parameters('availabilitySet'), 'Create'), variables('avSetId'), json('null'))]",
        "storageProfile": {
          "osDisk": {
            "createOption": "fromImage",
            "managedDisk": {
                "storageAccountType": "[variables('osDiskType')]"
            }
          },
          "ImageReference": "[variables('ImageRfc')]"
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('userName')]",
          "adminPassword": "[if(empty(parameters('sshKey')), parameters('userPassword'), if(equals(parameters('sshKeyOnly'), 'Yes'), if(equals(variables('osType'), 'Ubuntu'), json('null'), parameters('userPassword')), parameters('userPassword')))]",
          "LinuxConfiguration": "[if(empty(parameters('sshKey')), json('null'), if(equals(variables('osType'), 'Ubuntu'), variables('linuxCfg'), json('null')))]"
        }
      }
    }
  ],
  "outputs": {
    "VM's OS": {
      "type": "string",
      "value" : "[parameters('OS')]"
    },
    "Access the VM over": {
      "type": "string",
      "value" : "[if(equals(variables('osType'), 'Windows'), 'RDP', 'SSH')]"
    },
    "VM's static Public IP address": {
      "type": "string",
      "condition": "[equals(parameters('publicIPaddress'),'Create')]",
      "value" : "[reference(concat(parameters('vmName'),'-pip')).ipAddress]"
    },
    "VM's dynamic Private IP address": {
      "type": "string",
      "value": "[reference(concat(parameters('vmName'),'-nic')).ipConfigurations[0].properties.privateIPAddress]"
    }
  }
}
