diff --git a/openvidu-deployment/community/singlenode/azure/createUiDefinition.json b/openvidu-deployment/community/singlenode/azure/createUiDefinition.json index 9edde06a..b506085d 100644 --- a/openvidu-deployment/community/singlenode/azure/createUiDefinition.json +++ b/openvidu-deployment/community/singlenode/azure/createUiDefinition.json @@ -39,7 +39,7 @@ }, { "name": "parameters SSL", - "label": "Parameters for Domain and SSL certificate configuration", + "label": "Domain and SSL certificate configuration", "elements": [ { "name": "certificateType", @@ -176,7 +176,7 @@ }, { "name": "parameters INSTANCE", - "label": "Parameters for OpenVidu instance configuration", + "label": "OpenVidu instance configuration", "elements": [ { "name": "instanceType", @@ -249,7 +249,7 @@ }, { "name": "parameters STORAGE", - "label": "Parameters for Storage Account configuration", + "label": "Storage Account configuration", "elements": [ { "name": "storageAccountName", @@ -287,7 +287,7 @@ }, { "name": "parameters TURN", - "label": "(Optional) Parameters for TURN server configuration with TLS", + "label": "(Optional) TURN server configuration with TLS", "elements": [ { "name": "turnDomainName", diff --git a/openvidu-deployment/pro/elastic/azure/cf-openvidu-elastic.bicep b/openvidu-deployment/pro/elastic/azure/cf-openvidu-elastic.bicep index 5650dfbe..6cc249e5 100644 --- a/openvidu-deployment/pro/elastic/azure/cf-openvidu-elastic.bicep +++ b/openvidu-deployment/pro/elastic/azure/cf-openvidu-elastic.bicep @@ -16,10 +16,7 @@ and an Elastic IP, you can use this option to generate a Let's Encrypt certifica param certificateType string = 'selfsigned' @description('Previously created Public IP address for the OpenVidu Deployment. Blank will generate a public IP') -param publicIpAddress string = '' - -@description('Name of the PublicIPAddress resource in your azure if you have a resource of publicIPAddress') -param publicIpAddressResourceName string = '' +param publicIpAddressObject object @description('Domain name for the OpenVidu Deployment. Blank will generate default domain') param domainName string = '' @@ -282,7 +279,7 @@ param adminUsername string @description('SSH Key or password for the Virtual Machine') @secure() -param adminSshKey string +param adminSshKey object @description('Number of initial media nodes to deploy') param initialNumberOfMediaNodes int = 1 @@ -298,29 +295,12 @@ param scaleTargetCPU int = 50 /*------------------------------------------- VARIABLES AND VALIDATIONS -------------------------------------------*/ -var isEmptyIp = publicIpAddress == '' -var ipSegments = split(publicIpAddress, '.') -var isFourSegments = length(ipSegments) == 4 -var seg1valid = isEmptyIp ? true : int(ipSegments[0]) >= 0 && int(ipSegments[0]) <= 255 -var seg2valid = isEmptyIp ? true : int(ipSegments[1]) >= 0 && int(ipSegments[1]) <= 255 -var seg3valid = isEmptyIp ? true : int(ipSegments[2]) >= 0 && int(ipSegments[2]) <= 255 -var seg4valid = isEmptyIp ? true : int(ipSegments[3]) >= 0 && int(ipSegments[3]) <= 255 -var isValidIP = !isEmptyIp && isFourSegments && seg1valid && seg2valid && seg3valid && seg4valid +var isEmptyIp = publicIpAddressObject.newOrExistingOrNone == 'none' var isEmptyDomain = domainName == '' -var domainParts = split(domainName, '.') -var validNumberParts = length(domainParts) >= 2 -var allPartsValid = [ - for part in domainParts: length(part) >= 1 && length(part) <= 63 && !empty(part) && part == toLower(part) && !contains( - part, - '--' - ) && empty(replace(part, '[a-z0-9-]', '')) -] - -var isDomainValid = !isEmptyDomain && validNumberParts && !contains(allPartsValid, false) var masterNodeVMSettings = { - vmName: '${stackName}-VN-MasterNode' + vmName: '${stackName}-VM-MasterNode' osDiskType: 'StandardSSD_LRS' ubuntuOSVersion: { publisher: 'Canonical' @@ -334,7 +314,7 @@ var masterNodeVMSettings = { publicKeys: [ { path: '/home/${adminUsername}/.ssh/authorized_keys' - keyData: adminSshKey + keyData: adminSshKey.sshPublicKey } ] } @@ -356,7 +336,7 @@ var mediaNodeVMSettings = { publicKeys: [ { path: '/home/${adminUsername}/.ssh/authorized_keys' - keyData: adminSshKey + keyData: adminSshKey.sshPublicKey } ] } @@ -1079,7 +1059,6 @@ resource openviduMasterNode 'Microsoft.Compute/virtualMachines@2023-09-01' = { osProfile: { computerName: masterNodeVMSettings.vmName adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: masterNodeVMSettings.linuxConfiguration } userData: base64(userDataMasterNode) @@ -1315,7 +1294,6 @@ resource openviduScaleSetMediaNode 'Microsoft.Compute/virtualMachineScaleSets@20 osProfile: { computerNamePrefix: mediaNodeVMSettings.vmName adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: mediaNodeVMSettings.linuxConfiguration } networkProfile: { @@ -1541,8 +1519,16 @@ resource publicIP_OV 'Microsoft.Network/publicIPAddresses@2023-11-01' = if (isEm } } -resource publicIP_OV_ifNotEmpty 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (!isEmptyIp == true) { - name: publicIpAddressResourceName +var ipExists = publicIpAddressObject.newOrExistingOrNone == 'existing' + +resource publicIP_OV_ifExisting 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (ipExists == true) { + name: publicIpAddressObject.name +} + +var ipNew = publicIpAddressObject.newOrExistingOrNone == 'new' + +resource publicIP_OV_ifNew 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (ipNew == true) { + name: publicIpAddressObject.name } resource vnet_OV 'Microsoft.Network/virtualNetworks@2023-11-01' = { @@ -1598,7 +1584,7 @@ resource netInterfaceMasterNode 'Microsoft.Network/networkInterfaces@2023-11-01' } ] publicIPAddress: { - id: isEmptyIp ? publicIP_OV.id : publicIP_OV_ifNotEmpty.id + id: isEmptyIp ? publicIP_OV.id : ipNew ? publicIP_OV_ifNew.id : publicIP_OV_ifExisting.id properties: { deleteOption: 'Delete' } @@ -2070,16 +2056,3 @@ resource blobContainer 'Microsoft.Storage/storageAccounts/blobServices/container publicAccess: 'None' } } - -/*------------------------------------------- OUTPUTS -------------------------------------------*/ - -output ipValidationStatus string = isValidIP ? 'IP address is valid' : 'IP address not valid' - -output domainValidationStatus string = isDomainValid ? 'Domain is valid' : 'Domain is not valid' - -output ownCertValidationStatus string = (certificateType == 'owncert' && ownPrivateCertificate != '' && ownPublicCertificate != '') - ? 'owncert selected and valid' - : 'You need to fill \'Own Public Certificate\' and \'Own Private Certificate\'' -output letsEncryptValidationStatus string = (certificateType == 'letsencrypt' && letsEncryptEmail != '') - ? 'letsEncrypt selected and valid' - : 'You need to fill \'Lets Encrypt Email\'' diff --git a/openvidu-deployment/pro/elastic/azure/createUiDefinition.json b/openvidu-deployment/pro/elastic/azure/createUiDefinition.json index 0193fca9..93419505 100644 --- a/openvidu-deployment/pro/elastic/azure/createUiDefinition.json +++ b/openvidu-deployment/pro/elastic/azure/createUiDefinition.json @@ -7,7 +7,7 @@ "steps": [ { "name": "basics", - "label": "Basics", + "label": "Provide a Resource Group and a Stack Name", "elements": [ { "name": "resourceScope", @@ -35,7 +35,13 @@ }, "infoMessages": [], "visible": true - }, + } + ] + }, + { + "name": "parameters SSL", + "label": "Domain and SSL certificate configuration", + "elements": [ { "name": "certificateType", "type": "Microsoft.Common.DropDown", @@ -65,49 +71,41 @@ "visible": true }, { - "name": "publicIpAddress", - "type": "Microsoft.Common.TextBox", - "label": "Public Ip Address", - "subLabel": "", - "defaultValue": "", - "toolTip": "Previously created Public IP address for the OpenVidu Deployment. Blank will generate a public IP", - "constraints": { - "required": false, - "regex": "", - "validationMessage": "", - "validations": [] + "name": "publicIpAddressObject", + "type": "Microsoft.Network.PublicIpAddressCombo", + "label": { + "publicIpAddress": "Public IP address" }, - "infoMessages": [], - "visible": true - }, - { - "name": "publicIpAddressResourceName", - "type": "Microsoft.Common.TextBox", - "label": "Public Ip Address Resource Name", - "subLabel": "", - "defaultValue": "", - "toolTip": "Name of the PublicIPAddress resource in your azure if you have a resource of publicIPAddress", - "constraints": { - "required": false, - "regex": "", - "validationMessage": "", - "validations": [] + "toolTip": { + "publicIpAddress": "Previously created Public IP address for the OpenVidu Deployment. Blank will generate a public IP" + }, + "defaultValue": { + "publicIpAddressName": "" + }, + "options": { + "hideNone": false, + "hideDomainNameLabel": true, + "hideExisting": false }, - "infoMessages": [], "visible": true }, { "name": "domainName", "type": "Microsoft.Common.TextBox", "label": "Domain Name", - "subLabel": "", + "subLabel": "\nDomain name for the OpenVidu Deployment. Blank will generate default domain", "defaultValue": "", - "toolTip": "Domain name for the OpenVidu Deployment. Blank will generate default domain", + "toolTip": "", "constraints": { "required": false, - "regex": "", - "validationMessage": "", - "validations": [] + "regex": "^$|^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$", + "validationMessage": "Please enter a valid domain name or leave it blank to generate", + "validations": [ + { + "isValid": "[if(or(equals(steps('parameters SSL').certificateType, 'letsencrypt'), equals(steps('parameters SSL').certificateType, 'owncert')), not(empty(steps('parameters SSL').domainName)), true)]", + "message": "You need to fill this parameter because you've selected another certificate type that is not selfsigned." + } + ] }, "infoMessages": [], "visible": true @@ -116,14 +114,19 @@ "name": "ownPublicCertificate", "type": "Microsoft.Common.TextBox", "label": "Own Public Certificate", - "subLabel": "", + "subLabel": "If certificate type is 'owncert', this parameter will be used to specify the public certificate", "defaultValue": "", - "toolTip": "If certificate type is 'owncert', this parameter will be used to specify the public certificate", + "toolTip": "", "constraints": { "required": false, "regex": "", "validationMessage": "", - "validations": [] + "validations": [ + { + "isValid": "[if(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters SSL').ownPublicCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type." + } + ] }, "infoMessages": [], "visible": true @@ -132,14 +135,19 @@ "name": "ownPrivateCertificate", "type": "Microsoft.Common.TextBox", "label": "Own Private Certificate", - "subLabel": "", + "subLabel": "If certificate type is 'owncert', this parameter will be used to specify the private certificate", "defaultValue": "", - "toolTip": "If certificate type is 'owncert', this parameter will be used to specify the private certificate", + "toolTip": "", "constraints": { "required": false, "regex": "", "validationMessage": "", - "validations": [] + "validations": [ + { + "isValid": "[if(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters SSL').ownPrivateCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type." + } + ] }, "infoMessages": [], "visible": true @@ -148,66 +156,29 @@ "name": "letsEncryptEmail", "type": "Microsoft.Common.TextBox", "label": "Lets Encrypt Email", - "subLabel": "", + "subLabel": "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications", "defaultValue": "", - "toolTip": "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications", + "toolTip": "", "constraints": { "required": false, "regex": "", "validationMessage": "", - "validations": [] + "validations": [ + { + "isValid": "[if(equals(steps('parameters SSL').certificateType, 'letsencrypt'), not(empty(steps('parameters SSL').letsEncryptEmail)), true)]", + "message": "You need to fill this parameter because you've selected letsencrypt certificate type." + } + ] }, "infoMessages": [], "visible": true - }, - { - "name": "turnDomainName", - "type": "Microsoft.Common.TextBox", - "label": "Turn Domain Name", - "subLabel": "", - "defaultValue": "", - "toolTip": "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls", - "constraints": { - "required": false, - "regex": "", - "validationMessage": "", - "validations": [] - }, - "infoMessages": [], - "visible": true - }, - { - "name": "turnOwnPublicCertificate", - "type": "Microsoft.Common.TextBox", - "label": "Turn Own Public Certificate", - "subLabel": "", - "defaultValue": "", - "toolTip": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified.", - "constraints": { - "required": false, - "regex": "", - "validationMessage": "", - "validations": [] - }, - "infoMessages": [], - "visible": true - }, - { - "name": "turnOwnPrivateCertificate", - "type": "Microsoft.Common.TextBox", - "label": "Turn Own Private Certificate", - "subLabel": "", - "defaultValue": "", - "toolTip": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified.", - "constraints": { - "required": false, - "regex": "", - "validationMessage": "", - "validations": [] - }, - "infoMessages": [], - "visible": true - }, + } + ] + }, + { + "name": "parameters OPENVIDU", + "label": "OpenVidu Elastic configuration", + "elements": [ { "name": "openviduLicense", "type": "Microsoft.Common.PasswordBox", @@ -232,9 +203,9 @@ "name": "rtcEngine", "type": "Microsoft.Common.DropDown", "label": "Rtc Engine", - "subLabel": "", + "subLabel": "RTCEngine media engine to use", "defaultValue": "pion", - "toolTip": "RTCEngine media engine to use", + "toolTip": "", "constraints": { "required": false, "allowedValues": [ @@ -251,913 +222,72 @@ }, "infoMessages": [], "visible": true - }, + } + ] + }, + { + "name": "parameters INSTANCE", + "label": "Master and Media node configuration", + "elements": [ { "name": "masterNodeInstanceType", - "type": "Microsoft.Common.DropDown", + "type": "Microsoft.Compute.SizeSelector", "label": "Master Node Instance Type", - "subLabel": "", - "defaultValue": "Standard_B2s", - "toolTip": "Specifies the EC2 instance type for your OpenVidu Master Node", + "toolTip": "Specifies the Azure instance type for your OpenVidu Master Node", + "recommendedSizes": [ + "Standard_B2s" + ], "constraints": { - "required": false, - "allowedValues": [ - { - "label": "Standard_B1s", - "value": "Standard_B1s" - }, - { - "label": "Standard_B1ms", - "value": "Standard_B1ms" - }, - { - "label": "Standard_B2s", - "value": "Standard_B2s" - }, - { - "label": "Standard_B2ms", - "value": "Standard_B2ms" - }, - { - "label": "Standard_B4ms", - "value": "Standard_B4ms" - }, - { - "label": "Standard_B8ms", - "value": "Standard_B8ms" - }, - { - "label": "Standard_D2_v3", - "value": "Standard_D2_v3" - }, - { - "label": "Standard_D4_v3", - "value": "Standard_D4_v3" - }, - { - "label": "Standard_D8_v3", - "value": "Standard_D8_v3" - }, - { - "label": "Standard_D16_v3", - "value": "Standard_D16_v3" - }, - { - "label": "Standard_D32_v3", - "value": "Standard_D32_v3" - }, - { - "label": "Standard_D48_v3", - "value": "Standard_D48_v3" - }, - { - "label": "Standard_D64_v3", - "value": "Standard_D64_v3" - }, - { - "label": "Standard_D2_v4", - "value": "Standard_D2_v4" - }, - { - "label": "Standard_D4_v4", - "value": "Standard_D4_v4" - }, - { - "label": "Standard_D8_v4", - "value": "Standard_D8_v4" - }, - { - "label": "Standard_D16_v4", - "value": "Standard_D16_v4" - }, - { - "label": "Standard_D32_v4", - "value": "Standard_D32_v4" - }, - { - "label": "Standard_D48_v4", - "value": "Standard_D48_v4" - }, - { - "label": "Standard_D64_v4", - "value": "Standard_D64_v4" - }, - { - "label": "Standard_D96_v4", - "value": "Standard_D96_v4" - }, - { - "label": "Standard_D2_v5", - "value": "Standard_D2_v5" - }, - { - "label": "Standard_D4_v5", - "value": "Standard_D4_v5" - }, - { - "label": "Standard_D8_v5", - "value": "Standard_D8_v5" - }, - { - "label": "Standard_D16_v5", - "value": "Standard_D16_v5" - }, - { - "label": "Standard_D32_v5", - "value": "Standard_D32_v5" - }, - { - "label": "Standard_D48_v5", - "value": "Standard_D48_v5" - }, - { - "label": "Standard_D64_v5", - "value": "Standard_D64_v5" - }, - { - "label": "Standard_D96_v5", - "value": "Standard_D96_v5" - }, - { - "label": "Standard_F2", - "value": "Standard_F2" - }, - { - "label": "Standard_F4", - "value": "Standard_F4" - }, - { - "label": "Standard_F8", - "value": "Standard_F8" - }, - { - "label": "Standard_F16", - "value": "Standard_F16" - }, - { - "label": "Standard_F32", - "value": "Standard_F32" - }, - { - "label": "Standard_F64", - "value": "Standard_F64" - }, - { - "label": "Standard_F72", - "value": "Standard_F72" - }, - { - "label": "Standard_F2s_v2", - "value": "Standard_F2s_v2" - }, - { - "label": "Standard_F4s_v2", - "value": "Standard_F4s_v2" - }, - { - "label": "Standard_F8s_v2", - "value": "Standard_F8s_v2" - }, - { - "label": "Standard_F16s_v2", - "value": "Standard_F16s_v2" - }, - { - "label": "Standard_F32s_v2", - "value": "Standard_F32s_v2" - }, - { - "label": "Standard_F64s_v2", - "value": "Standard_F64s_v2" - }, - { - "label": "Standard_F72s_v2", - "value": "Standard_F72s_v2" - }, - { - "label": "Standard_E2_v3", - "value": "Standard_E2_v3" - }, - { - "label": "Standard_E4_v3", - "value": "Standard_E4_v3" - }, - { - "label": "Standard_E8_v3", - "value": "Standard_E8_v3" - }, - { - "label": "Standard_E16_v3", - "value": "Standard_E16_v3" - }, - { - "label": "Standard_E32_v3", - "value": "Standard_E32_v3" - }, - { - "label": "Standard_E48_v3", - "value": "Standard_E48_v3" - }, - { - "label": "Standard_E64_v3", - "value": "Standard_E64_v3" - }, - { - "label": "Standard_E96_v3", - "value": "Standard_E96_v3" - }, - { - "label": "Standard_E2_v4", - "value": "Standard_E2_v4" - }, - { - "label": "Standard_E4_v4", - "value": "Standard_E4_v4" - }, - { - "label": "Standard_E8_v4", - "value": "Standard_E8_v4" - }, - { - "label": "Standard_E16_v4", - "value": "Standard_E16_v4" - }, - { - "label": "Standard_E32_v4", - "value": "Standard_E32_v4" - }, - { - "label": "Standard_E48_v4", - "value": "Standard_E48_v4" - }, - { - "label": "Standard_E64_v4", - "value": "Standard_E64_v4" - }, - { - "label": "Standard_E2_v5", - "value": "Standard_E2_v5" - }, - { - "label": "Standard_E4_v5", - "value": "Standard_E4_v5" - }, - { - "label": "Standard_E8_v5", - "value": "Standard_E8_v5" - }, - { - "label": "Standard_E16_v5", - "value": "Standard_E16_v5" - }, - { - "label": "Standard_E32_v5", - "value": "Standard_E32_v5" - }, - { - "label": "Standard_E48_v5", - "value": "Standard_E48_v5" - }, - { - "label": "Standard_E64_v5", - "value": "Standard_E64_v5" - }, - { - "label": "Standard_E96_v5", - "value": "Standard_E96_v5" - }, - { - "label": "Standard_M64", - "value": "Standard_M64" - }, - { - "label": "Standard_M128", - "value": "Standard_M128" - }, - { - "label": "Standard_M208ms_v2", - "value": "Standard_M208ms_v2" - }, - { - "label": "Standard_M416ms_v2", - "value": "Standard_M416ms_v2" - }, - { - "label": "Standard_L4s_v2", - "value": "Standard_L4s_v2" - }, - { - "label": "Standard_L8s_v2", - "value": "Standard_L8s_v2" - }, - { - "label": "Standard_L16s_v2", - "value": "Standard_L16s_v2" - }, - { - "label": "Standard_L32s_v2", - "value": "Standard_L32s_v2" - }, - { - "label": "Standard_L64s_v2", - "value": "Standard_L64s_v2" - }, - { - "label": "Standard_L80s_v2", - "value": "Standard_L80s_v2" - }, - { - "label": "Standard_NC6", - "value": "Standard_NC6" - }, - { - "label": "Standard_NC12", - "value": "Standard_NC12" - }, - { - "label": "Standard_NC24", - "value": "Standard_NC24" - }, - { - "label": "Standard_NC24r", - "value": "Standard_NC24r" - }, - { - "label": "Standard_ND6s", - "value": "Standard_ND6s" - }, - { - "label": "Standard_ND12s", - "value": "Standard_ND12s" - }, - { - "label": "Standard_ND24s", - "value": "Standard_ND24s" - }, - { - "label": "Standard_ND24rs", - "value": "Standard_ND24rs" - }, - { - "label": "Standard_NV6", - "value": "Standard_NV6" - }, - { - "label": "Standard_NV12", - "value": "Standard_NV12" - }, - { - "label": "Standard_NV24", - "value": "Standard_NV24" - }, - { - "label": "Standard_H8", - "value": "Standard_H8" - }, - { - "label": "Standard_H16", - "value": "Standard_H16" - }, - { - "label": "Standard_H16r", - "value": "Standard_H16r" - }, - { - "label": "Standard_H16mr", - "value": "Standard_H16mr" - }, - { - "label": "Standard_HB120rs_v2", - "value": "Standard_HB120rs_v2" - }, - { - "label": "Standard_HC44rs", - "value": "Standard_HC44rs" - }, - { - "label": "Standard_DC2s", - "value": "Standard_DC2s" - }, - { - "label": "Standard_DC4s", - "value": "Standard_DC4s" - }, - { - "label": "Standard_DC2s_v2", - "value": "Standard_DC2s_v2" - }, - { - "label": "Standard_DC4s_v2", - "value": "Standard_DC4s_v2" - }, - { - "label": "Standard_DC8s_v2", - "value": "Standard_DC8s_v2" - }, - { - "label": "Standard_DC16s_v2", - "value": "Standard_DC16s_v2" - }, - { - "label": "Standard_DC32s_v2", - "value": "Standard_DC32s_v2" - }, - { - "label": "Standard_A1_v2", - "value": "Standard_A1_v2" - }, - { - "label": "Standard_A2_v2", - "value": "Standard_A2_v2" - }, - { - "label": "Standard_A4_v2", - "value": "Standard_A4_v2" - }, - { - "label": "Standard_A8_v2", - "value": "Standard_A8_v2" - }, - { - "label": "Standard_A2m_v2", - "value": "Standard_A2m_v2" - }, - { - "label": "Standard_A4m_v2", - "value": "Standard_A4m_v2" - }, - { - "label": "Standard_A8m_v2", - "value": "Standard_A8m_v2" - } - ], - "validations": [] + "allowedSizes": [], + "excludedSizes": [], + "numAvailabilityZonesRequired": 3, + "zone": "3" }, - "infoMessages": [], + "options": { + "hideDiskTypeFilter": false + }, + "osPlatform": "Linux", "visible": true }, { "name": "mediaNodeInstanceType", - "type": "Microsoft.Common.DropDown", + "type": "Microsoft.Compute.SizeSelector", "label": "Media Node Instance Type", - "subLabel": "", - "defaultValue": "Standard_B2s", - "toolTip": "Specifies the EC2 instance type for your OpenVidu Media Nodes", + "toolTip": "Specifies the Azure instance type for your OpenVidu Media Nodes", + "recommendedSizes": [ + "Standard_B2s", + "Standard_B4ms" + ], "constraints": { - "required": false, - "allowedValues": [ - { - "label": "Standard_B1s", - "value": "Standard_B1s" - }, - { - "label": "Standard_B1ms", - "value": "Standard_B1ms" - }, - { - "label": "Standard_B2s", - "value": "Standard_B2s" - }, - { - "label": "Standard_B2ms", - "value": "Standard_B2ms" - }, - { - "label": "Standard_B4ms", - "value": "Standard_B4ms" - }, - { - "label": "Standard_B8ms", - "value": "Standard_B8ms" - }, - { - "label": "Standard_D2_v3", - "value": "Standard_D2_v3" - }, - { - "label": "Standard_D4_v3", - "value": "Standard_D4_v3" - }, - { - "label": "Standard_D8_v3", - "value": "Standard_D8_v3" - }, - { - "label": "Standard_D16_v3", - "value": "Standard_D16_v3" - }, - { - "label": "Standard_D32_v3", - "value": "Standard_D32_v3" - }, - { - "label": "Standard_D48_v3", - "value": "Standard_D48_v3" - }, - { - "label": "Standard_D64_v3", - "value": "Standard_D64_v3" - }, - { - "label": "Standard_D2_v4", - "value": "Standard_D2_v4" - }, - { - "label": "Standard_D4_v4", - "value": "Standard_D4_v4" - }, - { - "label": "Standard_D8_v4", - "value": "Standard_D8_v4" - }, - { - "label": "Standard_D16_v4", - "value": "Standard_D16_v4" - }, - { - "label": "Standard_D32_v4", - "value": "Standard_D32_v4" - }, - { - "label": "Standard_D48_v4", - "value": "Standard_D48_v4" - }, - { - "label": "Standard_D64_v4", - "value": "Standard_D64_v4" - }, - { - "label": "Standard_D96_v4", - "value": "Standard_D96_v4" - }, - { - "label": "Standard_D2_v5", - "value": "Standard_D2_v5" - }, - { - "label": "Standard_D4_v5", - "value": "Standard_D4_v5" - }, - { - "label": "Standard_D8_v5", - "value": "Standard_D8_v5" - }, - { - "label": "Standard_D16_v5", - "value": "Standard_D16_v5" - }, - { - "label": "Standard_D32_v5", - "value": "Standard_D32_v5" - }, - { - "label": "Standard_D48_v5", - "value": "Standard_D48_v5" - }, - { - "label": "Standard_D64_v5", - "value": "Standard_D64_v5" - }, - { - "label": "Standard_D96_v5", - "value": "Standard_D96_v5" - }, - { - "label": "Standard_F2", - "value": "Standard_F2" - }, - { - "label": "Standard_F4", - "value": "Standard_F4" - }, - { - "label": "Standard_F8", - "value": "Standard_F8" - }, - { - "label": "Standard_F16", - "value": "Standard_F16" - }, - { - "label": "Standard_F32", - "value": "Standard_F32" - }, - { - "label": "Standard_F64", - "value": "Standard_F64" - }, - { - "label": "Standard_F72", - "value": "Standard_F72" - }, - { - "label": "Standard_F2s_v2", - "value": "Standard_F2s_v2" - }, - { - "label": "Standard_F4s_v2", - "value": "Standard_F4s_v2" - }, - { - "label": "Standard_F8s_v2", - "value": "Standard_F8s_v2" - }, - { - "label": "Standard_F16s_v2", - "value": "Standard_F16s_v2" - }, - { - "label": "Standard_F32s_v2", - "value": "Standard_F32s_v2" - }, - { - "label": "Standard_F64s_v2", - "value": "Standard_F64s_v2" - }, - { - "label": "Standard_F72s_v2", - "value": "Standard_F72s_v2" - }, - { - "label": "Standard_E2_v3", - "value": "Standard_E2_v3" - }, - { - "label": "Standard_E4_v3", - "value": "Standard_E4_v3" - }, - { - "label": "Standard_E8_v3", - "value": "Standard_E8_v3" - }, - { - "label": "Standard_E16_v3", - "value": "Standard_E16_v3" - }, - { - "label": "Standard_E32_v3", - "value": "Standard_E32_v3" - }, - { - "label": "Standard_E48_v3", - "value": "Standard_E48_v3" - }, - { - "label": "Standard_E64_v3", - "value": "Standard_E64_v3" - }, - { - "label": "Standard_E96_v3", - "value": "Standard_E96_v3" - }, - { - "label": "Standard_E2_v4", - "value": "Standard_E2_v4" - }, - { - "label": "Standard_E4_v4", - "value": "Standard_E4_v4" - }, - { - "label": "Standard_E8_v4", - "value": "Standard_E8_v4" - }, - { - "label": "Standard_E16_v4", - "value": "Standard_E16_v4" - }, - { - "label": "Standard_E32_v4", - "value": "Standard_E32_v4" - }, - { - "label": "Standard_E48_v4", - "value": "Standard_E48_v4" - }, - { - "label": "Standard_E64_v4", - "value": "Standard_E64_v4" - }, - { - "label": "Standard_E2_v5", - "value": "Standard_E2_v5" - }, - { - "label": "Standard_E4_v5", - "value": "Standard_E4_v5" - }, - { - "label": "Standard_E8_v5", - "value": "Standard_E8_v5" - }, - { - "label": "Standard_E16_v5", - "value": "Standard_E16_v5" - }, - { - "label": "Standard_E32_v5", - "value": "Standard_E32_v5" - }, - { - "label": "Standard_E48_v5", - "value": "Standard_E48_v5" - }, - { - "label": "Standard_E64_v5", - "value": "Standard_E64_v5" - }, - { - "label": "Standard_E96_v5", - "value": "Standard_E96_v5" - }, - { - "label": "Standard_M64", - "value": "Standard_M64" - }, - { - "label": "Standard_M128", - "value": "Standard_M128" - }, - { - "label": "Standard_M208ms_v2", - "value": "Standard_M208ms_v2" - }, - { - "label": "Standard_M416ms_v2", - "value": "Standard_M416ms_v2" - }, - { - "label": "Standard_L4s_v2", - "value": "Standard_L4s_v2" - }, - { - "label": "Standard_L8s_v2", - "value": "Standard_L8s_v2" - }, - { - "label": "Standard_L16s_v2", - "value": "Standard_L16s_v2" - }, - { - "label": "Standard_L32s_v2", - "value": "Standard_L32s_v2" - }, - { - "label": "Standard_L64s_v2", - "value": "Standard_L64s_v2" - }, - { - "label": "Standard_L80s_v2", - "value": "Standard_L80s_v2" - }, - { - "label": "Standard_NC6", - "value": "Standard_NC6" - }, - { - "label": "Standard_NC12", - "value": "Standard_NC12" - }, - { - "label": "Standard_NC24", - "value": "Standard_NC24" - }, - { - "label": "Standard_NC24r", - "value": "Standard_NC24r" - }, - { - "label": "Standard_ND6s", - "value": "Standard_ND6s" - }, - { - "label": "Standard_ND12s", - "value": "Standard_ND12s" - }, - { - "label": "Standard_ND24s", - "value": "Standard_ND24s" - }, - { - "label": "Standard_ND24rs", - "value": "Standard_ND24rs" - }, - { - "label": "Standard_NV6", - "value": "Standard_NV6" - }, - { - "label": "Standard_NV12", - "value": "Standard_NV12" - }, - { - "label": "Standard_NV24", - "value": "Standard_NV24" - }, - { - "label": "Standard_H8", - "value": "Standard_H8" - }, - { - "label": "Standard_H16", - "value": "Standard_H16" - }, - { - "label": "Standard_H16r", - "value": "Standard_H16r" - }, - { - "label": "Standard_H16mr", - "value": "Standard_H16mr" - }, - { - "label": "Standard_HB120rs_v2", - "value": "Standard_HB120rs_v2" - }, - { - "label": "Standard_HC44rs", - "value": "Standard_HC44rs" - }, - { - "label": "Standard_DC2s", - "value": "Standard_DC2s" - }, - { - "label": "Standard_DC4s", - "value": "Standard_DC4s" - }, - { - "label": "Standard_DC2s_v2", - "value": "Standard_DC2s_v2" - }, - { - "label": "Standard_DC4s_v2", - "value": "Standard_DC4s_v2" - }, - { - "label": "Standard_DC8s_v2", - "value": "Standard_DC8s_v2" - }, - { - "label": "Standard_DC16s_v2", - "value": "Standard_DC16s_v2" - }, - { - "label": "Standard_DC32s_v2", - "value": "Standard_DC32s_v2" - }, - { - "label": "Standard_A1_v2", - "value": "Standard_A1_v2" - }, - { - "label": "Standard_A2_v2", - "value": "Standard_A2_v2" - }, - { - "label": "Standard_A4_v2", - "value": "Standard_A4_v2" - }, - { - "label": "Standard_A8_v2", - "value": "Standard_A8_v2" - }, - { - "label": "Standard_A2m_v2", - "value": "Standard_A2m_v2" - }, - { - "label": "Standard_A4m_v2", - "value": "Standard_A4m_v2" - }, - { - "label": "Standard_A8m_v2", - "value": "Standard_A8m_v2" - } - ], - "validations": [] + "allowedSizes": [], + "excludedSizes": [], + "numAvailabilityZonesRequired": 3, + "zone": "3" }, - "infoMessages": [], + "options": { + "hideDiskTypeFilter": false + }, + "osPlatform": "Linux", "visible": true }, { "name": "adminUsername", "type": "Microsoft.Common.TextBox", "label": "Admin Username", - "subLabel": "", + "subLabel": "Username for the Virtual Machine.", "defaultValue": "", - "toolTip": "Username for the Virtual Machine.", + "toolTip": "", "constraints": { "required": true, "regex": "", "validationMessage": "", "validations": [ { - "isValid": "[or(or(empty(steps('basics').adminUsername),and(not(startsWith(steps('basics').adminUsername,'[[')),startsWith(steps('basics').adminUsername,'['),endsWith(steps('basics').adminUsername,']'),greater(indexOf(steps('basics').adminUsername,'('),-1),greater(indexOf(steps('basics').adminUsername,')'),-1))),and(not(regex(steps('basics').adminUsername,'/[\\\\/\\\"\\\"\\[\\]:|<>+=;,$ ?*@]+/')),not(endsWith(steps('basics').adminUsername,'.'))),regex(steps('basics').adminUsername,'^[a-zA-Z0-9-]+$'))]", + "isValid": "[or(or(empty(steps('parameters INSTANCE').adminUsername),and(not(startsWith(steps('parameters INSTANCE').adminUsername,'[[')),startsWith(steps('parameters INSTANCE').adminUsername,'['),endsWith(steps('parameters INSTANCE').adminUsername,']'),greater(indexOf(steps('parameters INSTANCE').adminUsername,'('),-1),greater(indexOf(steps('parameters INSTANCE').adminUsername,')'),-1))),and(not(regex(steps('parameters INSTANCE').adminUsername,'/[\\\\/\\\"\\\"\\[\\]:|<>+=;,$ ?*@]+/')),not(endsWith(steps('parameters INSTANCE').adminUsername,'.'))),regex(steps('parameters INSTANCE').adminUsername,'^[a-zA-Z0-9-]+$'))]", "message": "User name cannot contain special characters \\/\\\"[]:|<>+=;,?*@ or end with '.', and must be between 1 and 15 characters." }, { - "isValid": "[or(or(empty(steps('basics').adminUsername),and(not(startsWith(steps('basics').adminUsername,'[[')),startsWith(steps('basics').adminUsername,'['),endsWith(steps('basics').adminUsername,']'),greater(indexOf(steps('basics').adminUsername,'('),-1),greater(indexOf(steps('basics').adminUsername,')'),-1))),equals(length(filter(parse('[\"administrator\", \"admin\", \"user\", \"user1\", \"test\", \"user2\", \"test1\", \"user3\", \"admin1\", \"1\", \"123\", \"a\", \"actuser\", \"adm\", \"admin2\", \"aspnet\", \"backup\", \"console\", \"david\", \"guest\", \"john\", \"owner\", \"root\", \"server\", \"sql\", \"support\", \"support_388945a0\", \"sys\", \"test2\", \"test3\", \"user4\", \"user5\"]'),(item) => equals(toLower(item),toLower(steps('basics').adminUsername)))),0))]", + "isValid": "[or(or(empty(steps('parameters INSTANCE').adminUsername),and(not(startsWith(steps('parameters INSTANCE').adminUsername,'[[')),startsWith(steps('parameters INSTANCE').adminUsername,'['),endsWith(steps('parameters INSTANCE').adminUsername,']'),greater(indexOf(steps('parameters INSTANCE').adminUsername,'('),-1),greater(indexOf(steps('parameters INSTANCE').adminUsername,')'),-1))),equals(length(filter(parse('[\"administrator\", \"admin\", \"user\", \"user1\", \"test\", \"user2\", \"test1\", \"user3\", \"admin1\", \"1\", \"123\", \"a\", \"actuser\", \"adm\", \"admin2\", \"aspnet\", \"backup\", \"console\", \"david\", \"guest\", \"john\", \"owner\", \"root\", \"server\", \"sql\", \"support\", \"support_388945a0\", \"sys\", \"test2\", \"test3\", \"user4\", \"user5\"]'),(item) => equals(toLower(item),toLower(steps('parameters INSTANCE').adminUsername)))),0))]", "message": "The specified username is not allowed. Please choose a different value." } ] @@ -1167,31 +297,38 @@ }, { "name": "adminSshKey", - "type": "Microsoft.Common.PasswordBox", + "type": "Microsoft.Compute.CredentialsCombo", "label": { - "password": "Admin Ssh Key", - "confirmPassword": "Confirm password" + "authenticationType": "Authentication type", + "sshPublicKey": "SSH public key" + }, + "toolTip": { + "authenticationType": "", + "sshPublicKey": "SSH Key for the Instances of Media and Master nodes." }, - "defaultValue": "", - "toolTip": "SSH Key or password for the Virtual Machine", "constraints": { - "required": true, - "regex": "", - "validationMessage": "", - "validations": [] + "required": true }, "options": { - "hideConfirmation": true + "hideConfirmation": true, + "hidePassword": true }, + "osPlatform": "Linux", "visible": true - }, + } + ] + }, + { + "name": "parameters SCALING", + "label": "Media Nodes Sacle Set configuration", + "elements": [ { "name": "initialNumberOfMediaNodes", "type": "Microsoft.Common.TextBox", "label": "Initial Number Of Media Nodes", - "subLabel": "", + "subLabel": "Number of initial media nodes to deploy", "defaultValue": "1", - "toolTip": "Number of initial media nodes to deploy", + "toolTip": "", "constraints": { "required": false, "regex": "", @@ -1205,9 +342,9 @@ "name": "minNumberOfMediaNodes", "type": "Microsoft.Common.TextBox", "label": "Min Number Of Media Nodes", - "subLabel": "", + "subLabel": "Minimum number of media nodes to deploy", "defaultValue": "1", - "toolTip": "Minimum number of media nodes to deploy", + "toolTip": "", "constraints": { "required": false, "regex": "", @@ -1221,9 +358,9 @@ "name": "maxNumberOfMediaNodes", "type": "Microsoft.Common.TextBox", "label": "Max Number Of Media Nodes", - "subLabel": "", + "subLabel": "Maximum number of media nodes to deploy", "defaultValue": "5", - "toolTip": "Maximum number of media nodes to deploy", + "toolTip": "", "constraints": { "required": false, "regex": "", @@ -1237,9 +374,9 @@ "name": "scaleTargetCPU", "type": "Microsoft.Common.TextBox", "label": "Scale Target CPU", - "subLabel": "", + "subLabel": "Target CPU percentage to scale up or down", "defaultValue": "50", - "toolTip": "Target CPU percentage to scale up or down", + "toolTip": "", "constraints": { "required": false, "regex": "", @@ -1263,15 +400,15 @@ "validations": [] }, "infoMessages": [], - "visible": true + "visible": false }, { "name": "automationAccountName", "type": "Microsoft.Common.TextBox", "label": "Automation Account Name", - "subLabel": "", + "subLabel": "Automation Account Name to create a runbook inside it for scale in", "defaultValue": "", - "toolTip": "Automation Account Name to create a runbook inside it for scale in", + "toolTip": "", "constraints": { "required": true, "regex": "", @@ -1280,14 +417,20 @@ }, "infoMessages": [], "visible": true - }, + } + ] + }, + { + "name": "parameters STORAGE", + "label": "Storage Account configuration", + "elements": [ { "name": "storageAccountName", "type": "Microsoft.Common.TextBox", "label": "Storage Account Name", - "subLabel": "", + "subLabel": "Name of an existing storage account. It is essential that this parameter is filled just when you want to save recordings and still using the same container after an update. If not specified, a new storage account will be generated.", "defaultValue": "", - "toolTip": "Name of the existing storage account. It is essential that this parameter is filled just when you want to save recordings and still using the same container after an update. If not specified, a new storage account will be generated.", + "toolTip": "", "constraints": { "required": false, "regex": "", @@ -1301,9 +444,9 @@ "name": "containerName", "type": "Microsoft.Common.TextBox", "label": "Container Name", - "subLabel": "", + "subLabel": "Name of the bucket where OpenVidu will store the recordings, if an Storage Account Name is specified this parameter will act as the container name for the recordings that exists in the Storage Account. If not specified, a default bucket will be created.", "defaultValue": "", - "toolTip": "Name of the bucket where OpenVidu will store the recordings. If not specified, a default bucket will be created.", + "toolTip": "", "constraints": { "required": false, "regex": "", @@ -1314,6 +457,70 @@ "visible": true } ] + }, + { + "name": "parameters TURN", + "label": "(Optional) TURN server configuration with TLS", + "elements": [ + { + "name": "turnDomainName", + "type": "Microsoft.Common.TextBox", + "label": "Turn Domain Name", + "subLabel": "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "turnOwnPublicCertificate", + "type": "Microsoft.Common.TextBox", + "label": "Turn Own Public Certificate", + "subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPublicCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "turnOwnPrivateCertificate", + "type": "Microsoft.Common.TextBox", + "label": "Turn Own Private Certificate", + "subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPrivateCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name." + } + ] + }, + "infoMessages": [], + "visible": true + } + ] } ] }, @@ -1323,30 +530,29 @@ "resourceGroupId": "[steps('basics').resourceScope.resourceGroup.id]", "parameters": { "stackName": "[steps('basics').stackName]", - "certificateType": "[steps('basics').certificateType]", - "publicIpAddress": "[steps('basics').publicIpAddress]", - "publicIpAddressResourceName": "[steps('basics').publicIpAddressResourceName]", - "domainName": "[steps('basics').domainName]", - "ownPublicCertificate": "[steps('basics').ownPublicCertificate]", - "ownPrivateCertificate": "[steps('basics').ownPrivateCertificate]", - "letsEncryptEmail": "[steps('basics').letsEncryptEmail]", - "turnDomainName": "[steps('basics').turnDomainName]", - "turnOwnPublicCertificate": "[steps('basics').turnOwnPublicCertificate]", - "turnOwnPrivateCertificate": "[steps('basics').turnOwnPrivateCertificate]", - "openviduLicense": "[steps('basics').openviduLicense]", - "rtcEngine": "[steps('basics').rtcEngine]", - "masterNodeInstanceType": "[steps('basics').masterNodeInstanceType]", - "mediaNodeInstanceType": "[steps('basics').mediaNodeInstanceType]", - "adminUsername": "[steps('basics').adminUsername]", - "adminSshKey": "[steps('basics').adminSshKey]", - "initialNumberOfMediaNodes": "[steps('basics').initialNumberOfMediaNodes]", - "minNumberOfMediaNodes": "[steps('basics').minNumberOfMediaNodes]", - "maxNumberOfMediaNodes": "[steps('basics').maxNumberOfMediaNodes]", - "scaleTargetCPU": "[steps('basics').scaleTargetCPU]", - "datetime": "[steps('basics').datetime]", - "automationAccountName": "[steps('basics').automationAccountName]", - "storageAccountName": "[steps('basics').storageAccountName]", - "containerName": "[steps('basics').containerName]" + "certificateType": "[steps('parameters SSL').certificateType]", + "publicIpAddressObject": "[steps('parameters SSL').publicIpAddressObject]", + "domainName": "[steps('parameters SSL').domainName]", + "ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]", + "ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]", + "letsEncryptEmail": "[steps('parameters SSL').letsEncryptEmail]", + "turnDomainName": "[steps('parameters TURN').turnDomainName]", + "turnOwnPublicCertificate": "[steps('parameters TURN').turnOwnPublicCertificate]", + "turnOwnPrivateCertificate": "[steps('parameters TURN').turnOwnPrivateCertificate]", + "openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]", + "rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]", + "masterNodeInstanceType": "[steps('parameters INSTANCE').masterNodeInstanceType]", + "mediaNodeInstanceType": "[steps('parameters INSTANCE').mediaNodeInstanceType]", + "adminUsername": "[steps('parameters INSTANCE').adminUsername]", + "adminSshKey": "[steps('parameters INSTANCE').adminSshKey]", + "initialNumberOfMediaNodes": "[steps('parameters SCALING').initialNumberOfMediaNodes]", + "minNumberOfMediaNodes": "[steps('parameters SCALING').minNumberOfMediaNodes]", + "maxNumberOfMediaNodes": "[steps('parameters SCALING').maxNumberOfMediaNodes]", + "scaleTargetCPU": "[steps('parameters SCALING').scaleTargetCPU]", + "datetime": "[steps('parameters SCALING').datetime]", + "automationAccountName": "[steps('parameters SCALING').automationAccountName]", + "storageAccountName": "[steps('parameters STORAGE').storageAccountName]", + "containerName": "[steps('parameters STORAGE').containerName]" } } } diff --git a/openvidu-deployment/pro/ha/azure/cf-openvidu-ha.bicep b/openvidu-deployment/pro/ha/azure/cf-openvidu-ha.bicep index ac830755..b9059ba1 100644 --- a/openvidu-deployment/pro/ha/azure/cf-openvidu-ha.bicep +++ b/openvidu-deployment/pro/ha/azure/cf-openvidu-ha.bicep @@ -28,7 +28,7 @@ param ownPrivateCertificate string = '' param letsEncryptEmail string = '' @description('Name of the PublicIPAddress resource in Azure when using certificateType \'owncert\' or \'letsencrypt\'') -param publicIpAddressResourceName string = '' +param publicIpAddressObject object @description('(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls') param turnDomainName string = '' @@ -40,7 +40,10 @@ param turnOwnPublicCertificate string = '' param turnOwnPrivateCertificate string = '' @description('Name of the PublicIPAddress resource in Azure when using TURN server with TLS') -param turnPublicIpAddressResourceName string = '' +param turnPublicIpAddressObject object = { + name: '' + id: '' +} @description('Visit https://openvidu.io/account') @secure() @@ -285,7 +288,7 @@ param adminUsername string @description('SSH Key for the Virtual Machine.') @secure() -param adminSshKey string +param adminSshKey object @description('Number of initial media nodes to deploy') param initialNumberOfMediaNodes int = 1 @@ -316,7 +319,7 @@ var masterNodeVMSettings = { publicKeys: [ { path: '/home/${adminUsername}/.ssh/authorized_keys' - keyData: adminSshKey + keyData: adminSshKey.sshPublicKey } ] } @@ -338,7 +341,7 @@ var mediaNodeVMSettings = { publicKeys: [ { path: '/home/${adminUsername}/.ssh/authorized_keys' - keyData: adminSshKey + keyData: adminSshKey.sshPublicKey } ] } @@ -1264,7 +1267,6 @@ resource openviduMasterNode1 'Microsoft.Compute/virtualMachines@2023-09-01' = { osProfile: { computerName: '${stackName}-VM-MasterNode1' adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: masterNodeVMSettings.linuxConfiguration } userData: base64(userDataMasterNode1) @@ -1299,7 +1301,6 @@ resource openviduMasterNode2 'Microsoft.Compute/virtualMachines@2023-09-01' = { osProfile: { computerName: '${stackName}-VM-MasterNode2' adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: masterNodeVMSettings.linuxConfiguration } userData: base64(userDataMasterNode2) @@ -1335,7 +1336,6 @@ resource openviduMasterNode3 'Microsoft.Compute/virtualMachines@2023-09-01' = { osProfile: { computerName: '${stackName}-VM-MasterNode3' adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: masterNodeVMSettings.linuxConfiguration } userData: base64(userDataMasterNode3) @@ -1371,7 +1371,6 @@ resource openviduMasterNode4 'Microsoft.Compute/virtualMachines@2023-09-01' = { osProfile: { computerName: '${stackName}-VM-MasterNode4' adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: masterNodeVMSettings.linuxConfiguration } userData: base64(userDataMasterNode4) @@ -1613,7 +1612,6 @@ resource openviduScaleSetMediaNode 'Microsoft.Compute/virtualMachineScaleSets@20 osProfile: { computerNamePrefix: mediaNodeVMSettings.vmName adminUsername: adminUsername - adminPassword: adminSshKey linuxConfiguration: mediaNodeVMSettings.linuxConfiguration } networkProfile: { @@ -1822,8 +1820,8 @@ resource scaleInActivityLogRule 'Microsoft.Insights/activityLogAlerts@2020-10-01 /*------------------------------------------- NETWORK -------------------------------------------*/ -var isEmptyIp = publicIpAddressResourceName == '' -var turnIsEmptyIp = turnPublicIpAddressResourceName == '' +var isEmptyIp = publicIpAddressObject.newOrExistingOrNone == '' +var turnIsEmptyIp = turnPublicIpAddressObject.newOrExistingOrNone == '' var lbName = '${stackName}-loadBalancer' var lbFrontEndName = 'LoadBalancerFrontEnd' var lbBackendPoolNameMasterNode = 'LoadBalancerBackEndMasterNode' @@ -1840,8 +1838,16 @@ resource publicIPAddressLoadBalancer 'Microsoft.Network/publicIPAddresses@2024-0 } } -resource publicIP_LoadBalancer_ifNotEmpty 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (!isEmptyIp == true) { - name: publicIpAddressResourceName +var ipExists = publicIpAddressObject.newOrExistingOrNone == 'existing' + +resource publicIP_LoadBalancer_ifExisting 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (ipExists == true) { + name: publicIpAddressObject.name +} + +var ipNew = publicIpAddressObject.newOrExistingOrNone == 'new' + +resource publicIP_LoadBalancer_ifNew 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (ipNew == true) { + name: publicIpAddressObject.name } resource publicIPAddressTurnTLSLoadBalancer 'Microsoft.Network/publicIPAddresses@2024-05-01' = if (turnTLSIsEnabled == true) { @@ -1856,8 +1862,16 @@ resource publicIPAddressTurnTLSLoadBalancer 'Microsoft.Network/publicIPAddresses } } -resource publicIP_TurnTLSLoadBalancer_ifNotEmpty 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (!turnIsEmptyIp && turnTLSIsEnabled == true) { - name: publicIpAddressResourceName +var ipTURNExists = publicIpAddressObject.newOrExistingOrNone == 'existing' + +resource publicIP_TurnTLSLoadBalancer_ifExisting 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (ipTURNExists && turnTLSIsEnabled == true) { + name: publicIpAddressObject.name +} + +var ipTURNNew = publicIpAddressObject.newOrExistingOrNone == 'new' + +resource publicIP_TurnTLSLoadBalancer_ifNew 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (ipTURNNew && turnTLSIsEnabled == true) { + name: publicIpAddressObject.name } resource LoadBalancer 'Microsoft.Network/loadBalancers@2024-05-01' = { @@ -1872,7 +1886,9 @@ resource LoadBalancer 'Microsoft.Network/loadBalancers@2024-05-01' = { name: lbFrontEndName properties: { publicIPAddress: { - id: isEmptyIp ? publicIPAddressLoadBalancer.id : publicIP_LoadBalancer_ifNotEmpty.id + id: isEmptyIp + ? publicIPAddressLoadBalancer.id + : ipNew ? publicIP_LoadBalancer_ifNew.id : publicIP_LoadBalancer_ifExisting.id } } } @@ -1990,7 +2006,9 @@ resource TurnTLSLoadbalancer 'Microsoft.Network/loadBalancers@2024-05-01' = if ( privateIPAllocationMethod: 'Dynamic' privateIPAddressVersion: 'IPv4' publicIPAddress: { - id: turnIsEmptyIp ? publicIPAddressLoadBalancer.id : publicIP_TurnTLSLoadBalancer_ifNotEmpty.id + id: turnIsEmptyIp + ? publicIPAddressTurnTLSLoadBalancer.id + : ipTURNNew ? publicIP_TurnTLSLoadBalancer_ifNew.id : publicIP_TurnTLSLoadBalancer_ifExisting.id } } } diff --git a/openvidu-deployment/pro/ha/azure/createUiDefinition.json b/openvidu-deployment/pro/ha/azure/createUiDefinition.json index e69de29b..67720be3 100644 --- a/openvidu-deployment/pro/ha/azure/createUiDefinition.json +++ b/openvidu-deployment/pro/ha/azure/createUiDefinition.json @@ -0,0 +1,595 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2021-09-09/uiFormDefinition.schema.json", + "view": { + "kind": "Form", + "properties": { + "title": "OpenVidu High Availability deployment", + "steps": [ + { + "name": "basics", + "label": "Provide a Resource Group and a Stack Name", + "elements": [ + { + "name": "resourceScope", + "type": "Microsoft.Common.ResourceScope", + "location": { + "resourceTypes": [ + "microsoft.insights/autoscalesettings", + "microsoft.storage/storageaccounts", + "microsoft.resources/resourcegroups" + ] + } + }, + { + "name": "stackName", + "type": "Microsoft.Common.TextBox", + "label": "Stack Name", + "subLabel": "", + "defaultValue": "", + "toolTip": "Stack name", + "constraints": { + "required": true, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + } + ] + }, + { + "name": "parameters SSL", + "label": "Domain and SSL certificate configuration", + "elements": [ + { + "name": "certificateType", + "type": "Microsoft.Common.DropDown", + "label": "Certificate Type", + "subLabel": "", + "defaultValue": "selfsigned", + "toolTip": "[[selfsigned] Not recommended for production use. If you don't have a FQDN, (DomainName parameter) you can use this option to generate a self-signed certificate.\n[owncert] Valid for productions environments. If you have a FQDN, (DomainName parameter)\nand an Elastic IP, you can use this option to use your own certificate.\n[letsencrypt] Valid for production environments. If you have a FQDN, (DomainName parameter)\nand an Elastic IP, you can use this option to generate a Let's Encrypt certificate.\n", + "constraints": { + "required": false, + "allowedValues": [ + { + "label": "selfsigned", + "value": "selfsigned" + }, + { + "label": "owncert", + "value": "owncert" + }, + { + "label": "letsencrypt", + "value": "letsencrypt" + } + ], + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "publicIpAddressObject", + "type": "Microsoft.Network.PublicIpAddressCombo", + "label": { + "publicIpAddress": "Public IP address" + }, + "toolTip": { + "publicIpAddress": "Name of the PublicIPAddress resource in Azure when using certificateType 'owncert' or 'letsencrypt'" + }, + "defaultValue": { + "publicIpAddressName": "" + }, + "options": { + "hideNone": false, + "hideDomainNameLabel": true, + "hideExisting": false + }, + "visible": true + }, + { + "name": "domainName", + "type": "Microsoft.Common.TextBox", + "label": "Domain Name", + "subLabel": "Domain name for the OpenVidu Deployment.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": true, + "regex": "^$|^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(or(equals(steps('parameters SSL').certificateType, 'letsencrypt'), equals(steps('parameters SSL').certificateType, 'owncert')), not(empty(steps('parameters SSL').domainName)), true)]", + "message": "You need to fill this parameter because you've selected another certificate type that is not selfsigned." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "ownPublicCertificate", + "type": "Microsoft.Common.TextBox", + "label": "Own Public Certificate", + "subLabel": "If certificate type is 'owncert', this parameter will be used to specify the public certificate", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters SSL').ownPublicCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "ownPrivateCertificate", + "type": "Microsoft.Common.TextBox", + "label": "Own Private Certificate", + "subLabel": "If certificate type is 'owncert', this parameter will be used to specify the private certificate", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters SSL').ownPrivateCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "letsEncryptEmail", + "type": "Microsoft.Common.TextBox", + "label": "Lets Encrypt Email", + "subLabel": "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(equals(steps('parameters SSL').certificateType, 'letsencrypt'), not(empty(steps('parameters SSL').letsEncryptEmail)), true)]", + "message": "You need to fill this parameter because you've selected letsencrypt certificate type." + } + ] + }, + "infoMessages": [], + "visible": true + } + ] + }, + { + "name": "parameters OPENVIDU", + "label": "OpenVidu High Availability configuration", + "elements": [ + { + "name": "openviduLicense", + "type": "Microsoft.Common.PasswordBox", + "label": { + "password": "Openvidu License", + "confirmPassword": "Confirm password" + }, + "defaultValue": "", + "toolTip": "Visit https://openvidu.io/account", + "constraints": { + "required": true, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "options": { + "hideConfirmation": true + }, + "visible": true + }, + { + "name": "rtcEngine", + "type": "Microsoft.Common.DropDown", + "label": "Rtc Engine", + "subLabel": "RTCEngine media engine to use", + "defaultValue": "pion", + "toolTip": "", + "constraints": { + "required": false, + "allowedValues": [ + { + "label": "pion", + "value": "pion" + }, + { + "label": "mediasoup", + "value": "mediasoup" + } + ], + "validations": [] + }, + "infoMessages": [], + "visible": true + } + ] + }, + { + "name": "parameters INSTANCE", + "label": "Master and Media node configuration", + "elements": [ + { + "name": "masterNodeInstanceType", + "type": "Microsoft.Compute.SizeSelector", + "label": "Master Node Instance Type", + "toolTip": "Specifies the Azure instance type for your OpenVidu Master Node", + "recommendedSizes": [ + "Standard_B2s" + ], + "constraints": { + "allowedSizes": [], + "excludedSizes": [], + "numAvailabilityZonesRequired": 3, + "zone": "3" + }, + "options": { + "hideDiskTypeFilter": false + }, + "osPlatform": "Linux", + "visible": true + }, + { + "name": "masterNodesDiskSize", + "type": "Microsoft.Common.Slider", + "min": 70, + "max": 200, + "label": "Master Nodes Disk Size", + "subLabel": "GB", + "defaultValue": 100, + "showStepMarkers": false, + "toolTip": "Size of the disk in GB", + "constraints": { + "required": false + }, + "visible": true + }, + { + "name": "mediaNodeInstanceType", + "type": "Microsoft.Compute.SizeSelector", + "label": "Media Node Instance Type", + "toolTip": "Specifies the Azure instance type for your OpenVidu Media Nodes", + "recommendedSizes": [ + "Standard_B2s", + "Standard_B4ms" + ], + "constraints": { + "allowedSizes": [], + "excludedSizes": [], + "numAvailabilityZonesRequired": 3, + "zone": "3" + }, + "options": { + "hideDiskTypeFilter": false + }, + "osPlatform": "Linux", + "visible": true + }, + { + "name": "adminUsername", + "type": "Microsoft.Common.TextBox", + "label": "Admin Username", + "subLabel": "Username for the Virtual Machine.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": true, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[or(or(empty(steps('parameters INSTANCE').adminUsername),and(not(startsWith(steps('parameters INSTANCE').adminUsername,'[[')),startsWith(steps('parameters INSTANCE').adminUsername,'['),endsWith(steps('parameters INSTANCE').adminUsername,']'),greater(indexOf(steps('parameters INSTANCE').adminUsername,'('),-1),greater(indexOf(steps('parameters INSTANCE').adminUsername,')'),-1))),and(not(regex(steps('parameters INSTANCE').adminUsername,'/[\\\\/\\\"\\\"\\[\\]:|<>+=;,$ ?*@]+/')),not(endsWith(steps('parameters INSTANCE').adminUsername,'.'))),regex(steps('parameters INSTANCE').adminUsername,'^[a-zA-Z0-9-]+$'))]", + "message": "User name cannot contain special characters \\/\\\"[]:|<>+=;,?*@ or end with '.', and must be between 1 and 15 characters." + }, + { + "isValid": "[or(or(empty(steps('parameters INSTANCE').adminUsername),and(not(startsWith(steps('parameters INSTANCE').adminUsername,'[[')),startsWith(steps('parameters INSTANCE').adminUsername,'['),endsWith(steps('parameters INSTANCE').adminUsername,']'),greater(indexOf(steps('parameters INSTANCE').adminUsername,'('),-1),greater(indexOf(steps('parameters INSTANCE').adminUsername,')'),-1))),equals(length(filter(parse('[\"administrator\", \"admin\", \"user\", \"user1\", \"test\", \"user2\", \"test1\", \"user3\", \"admin1\", \"1\", \"123\", \"a\", \"actuser\", \"adm\", \"admin2\", \"aspnet\", \"backup\", \"console\", \"david\", \"guest\", \"john\", \"owner\", \"root\", \"server\", \"sql\", \"support\", \"support_388945a0\", \"sys\", \"test2\", \"test3\", \"user4\", \"user5\"]'),(item) => equals(toLower(item),toLower(steps('parameters INSTANCE').adminUsername)))),0))]", + "message": "The specified username is not allowed. Please choose a different value." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "adminSshKey", + "type": "Microsoft.Compute.CredentialsCombo", + "label": { + "authenticationType": "Authentication type", + "sshPublicKey": "SSH public key" + }, + "toolTip": { + "authenticationType": "", + "sshPublicKey": "SSH Key for the Instances of Media and Master nodes." + }, + "constraints": { + "required": true + }, + "options": { + "hideConfirmation": true, + "hidePassword": true + }, + "osPlatform": "Linux", + "visible": true + } + ] + }, + { + "name": "parameters SCALING", + "label": "Media Nodes Sacle Set configuration", + "elements": [ + { + "name": "initialNumberOfMediaNodes", + "type": "Microsoft.Common.TextBox", + "label": "Initial Number Of Media Nodes", + "subLabel": "Number of initial media nodes to deploy", + "defaultValue": "1", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "minNumberOfMediaNodes", + "type": "Microsoft.Common.TextBox", + "label": "Min Number Of Media Nodes", + "subLabel": "Minimum number of media nodes to deploy", + "defaultValue": "1", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "maxNumberOfMediaNodes", + "type": "Microsoft.Common.TextBox", + "label": "Max Number Of Media Nodes", + "subLabel": "Maximum number of media nodes to deploy", + "defaultValue": "5", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "scaleTargetCPU", + "type": "Microsoft.Common.TextBox", + "label": "Scale Target CPU", + "subLabel": "Target CPU percentage to scale up or down", + "defaultValue": "50", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "datetime", + "type": "Microsoft.Common.TextBox", + "label": "Datetime", + "subLabel": "", + "defaultValue": "[[utcNow('u')]", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": false + }, + { + "name": "automationAccountName", + "type": "Microsoft.Common.TextBox", + "label": "Automation Account Name", + "subLabel": "Automation Account Name to create a runbook inside it for scale in", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": true, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + } + ] + }, + { + "name": "parameters STORAGE", + "label": "Storage Account configuration", + "elements": [ + { + "name": "storageAccountName", + "type": "Microsoft.Common.TextBox", + "label": "Storage Account Name", + "subLabel": "Name of an existing storage account. It is essential that this parameter is filled just when you want to save recordings and still using the same container after an update. If not specified, a new storage account will be generated.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "containerName", + "type": "Microsoft.Common.TextBox", + "label": "Container Name", + "subLabel": "Name of the bucket where OpenVidu will store the recordings, if an Storage Account Name is specified this parameter will act as the container name for the recordings that exists in the Storage Account. If not specified, a default bucket will be created.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + } + ] + }, + { + "name": "parameters TURN", + "label": "(Optional) TURN server configuration with TLS", + "elements": [ + { + "name": "turnDomainName", + "type": "Microsoft.Common.TextBox", + "label": "Turn Domain Name", + "subLabel": "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "turnOwnPublicCertificate", + "type": "Microsoft.Common.TextBox", + "label": "Turn Own Public Certificate", + "subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPublicCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "turnOwnPrivateCertificate", + "type": "Microsoft.Common.TextBox", + "label": "Turn Own Private Certificate", + "subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified.", + "defaultValue": "", + "toolTip": "", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "", + "validations": [ + { + "isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPrivateCertificate)), true)]", + "message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name." + } + ] + }, + "infoMessages": [], + "visible": true + }, + { + "name": "turnPublicIpAddressObject", + "type": "Microsoft.Network.PublicIpAddressCombo", + "label": { + "publicIpAddress": "Turn Public Ip Address" + }, + "toolTip": { + "publicIpAddress": "Name of the PublicIPAddress resource in Azure when using TURN server with TLS" + }, + "defaultValue": { + "publicIpAddressName": "" + }, + "options": { + "hideNone": false, + "hideDomainNameLabel": true, + "hideExisting": false + }, + "visible": true + } + ] + } + ] + }, + "outputs": { + "kind": "ResourceGroup", + "location": "[steps('basics').resourceScope.location.name]", + "resourceGroupId": "[steps('basics').resourceScope.resourceGroup.id]", + "parameters": { + "stackName": "[steps('basics').stackName]", + "certificateType": "[steps('parameters SSL').certificateType]", + "domainName": "[steps('parameters SSL').domainName]", + "ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]", + "ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]", + "letsEncryptEmail": "[steps('parameters SSL').letsEncryptEmail]", + "publicIpAddressObject": "[steps('parameters SSL').publicIpAddressObject]", + "turnDomainName": "[steps('parameters TURN').turnDomainName]", + "turnOwnPublicCertificate": "[steps('parameters TURN').turnOwnPublicCertificate]", + "turnOwnPrivateCertificate": "[steps('parameters TURN').turnOwnPrivateCertificate]", + "turnPublicIpAddressObject": "[steps('parameters TURN').turnPublicIpAddressObject]", + "openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]", + "rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]", + "masterNodeInstanceType": "[steps('parameters INSTANCE').masterNodeInstanceType]", + "masterNodesDiskSize": "[steps('parameters INSTANCE').masterNodesDiskSize]", + "mediaNodeInstanceType": "[steps('parameters INSTANCE').mediaNodeInstanceType]", + "adminUsername": "[steps('parameters INSTANCE').adminUsername]", + "adminSshKey": "[steps('parameters INSTANCE').adminSshKey]", + "initialNumberOfMediaNodes": "[steps('parameters SCALING').initialNumberOfMediaNodes]", + "minNumberOfMediaNodes": "[steps('parameters SCALING').minNumberOfMediaNodes]", + "maxNumberOfMediaNodes": "[steps('parameters SCALING').maxNumberOfMediaNodes]", + "scaleTargetCPU": "[steps('parameters SCALING').scaleTargetCPU]", + "datetime": "[steps('parameters SCALING').datetime]", + "automationAccountName": "[steps('parameters SCALING').automationAccountName]", + "storageAccountName": "[steps('parameters STORAGE').storageAccountName]", + "containerName": "[steps('parameters STORAGE').containerName]" + } + } + } +} \ No newline at end of file