From 95d4070b486d01e5e3b60485c263148b9cb243ee Mon Sep 17 00:00:00 2001 From: Hocine Hacherouf Date: Wed, 8 Mar 2023 20:08:49 +0100 Subject: [PATCH 1/3] Add iotedge-lorawan-starterkit bicep templates folder on gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index a0b152c2e..b38b0f982 100644 --- a/.gitignore +++ b/.gitignore @@ -316,3 +316,6 @@ Temporary Items # End of https://www.toptal.com/developers/gitignore/api/macos src/AzureIoTHub.Portal/Client/assets/package-lock.json src/AzureIoTHub.Portal/Server/appsettings.Development.json + +# Folder for iotedge-lorawan-starterkit bicep templates +iotedge-lorawan-starterkit/ From 810b9311aa81ff9c0e414f8e7b5037bc70f1f269 Mon Sep 17 00:00:00 2001 From: Hocine Hacherouf Date: Wed, 8 Mar 2023 20:09:25 +0100 Subject: [PATCH 2/3] Refactor and remove duplication on bicep templates #1653 --- templates/azuredeploy.bicep | 62 ++++++++++++------ templates/portalDeployWithLoRa.bicep | 83 +++++++++++++++++++++---- templates/portalDeployWithoutLoRa.bicep | 51 ++++++++++----- 3 files changed, 150 insertions(+), 46 deletions(-) diff --git a/templates/azuredeploy.bicep b/templates/azuredeploy.bicep index d56cc8806..d9827acab 100644 --- a/templates/azuredeploy.bicep +++ b/templates/azuredeploy.bicep @@ -74,23 +74,21 @@ param ideasAuthenticationHeader string = 'Ocp-Apim-Subscription-Key' @description('Authentication token to interact with Awesome-Ideas. Required when ideasEnabled is true') param ideasAuthenticationToken string = '' -var starterKitDeploymentName = 'lorawan-starter-kit' var portalWithLoRaDeploymentName = 'iothub-portal-with-lora' var portalWithoutLoRaDeploymentName = 'iothub-portal-without-lora' -module starterKitDeployment '../iotedge-lorawan-starterkit/TemplateBicep/main.bicep' = if (isLoRaFeatureEnabled) { - name: starterKitDeploymentName - params: { - location: location - uniqueSolutionPrefix: uniqueSolutionPrefix - edgeGatewayName: edgeGatewayName - deployDevice: deployDevice - resetPin: resetPin - region: region - spiSpeed: spiSpeed - spiDev: spiDev - } -} +var pgsqlServerName = '${uniqueSolutionPrefix}pgsql' +var iotHubName = '${uniqueSolutionPrefix}hub' +var dpsName = '${uniqueSolutionPrefix}dps' +var siteName = '${uniqueSolutionPrefix}portal' +var servicePlanName = '${uniqueSolutionPrefix}asp' +var storageAccountName = '${uniqueSolutionPrefix}storage' +var iotHubOwnerPolicyName = 'iothubowner' +var provisioningserviceownerPolicyName = 'provisioningserviceowner' +var deviceImageContainerName = 'device-images' +var iamScopeName = 'API.Access' +var storageAccountId = '${resourceGroup().id}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}' +var appInsightName = '${uniqueSolutionPrefix}insight' module portalWithLoRaDeployment './portalDeployWithLoRa.bicep' = if (isLoRaFeatureEnabled) { name: portalWithLoRaDeploymentName @@ -107,17 +105,31 @@ module portalWithLoRaDeployment './portalDeployWithLoRa.bicep' = if (isLoRaFeatu ideasUrl: ideasUrl ideasAuthenticationHeader: ideasAuthenticationHeader ideasAuthenticationToken: ideasAuthenticationToken + edgeGatewayName: edgeGatewayName + deployDevice: deployDevice + resetPin: resetPin + region: region + spiSpeed: spiSpeed + spiDev: spiDev + appInsightName: appInsightName + deviceImageContainerName: deviceImageContainerName + dpsName: dpsName + iamScopeName: iamScopeName + iotHubName: iotHubName + iotHubOwnerPolicyName: iotHubOwnerPolicyName + pgsqlServerName: pgsqlServerName + provisioningserviceownerPolicyName: provisioningserviceownerPolicyName + servicePlanName: servicePlanName + siteName: siteName + storageAccountId: storageAccountId + storageAccountName: storageAccountName } - dependsOn: [ - starterKitDeployment - ] } module portalWithoutLoRaDeployment './portalDeployWithoutLoRa.bicep' = if (!isLoRaFeatureEnabled) { name: portalWithoutLoRaDeploymentName params: { location: location - uniqueSolutionPrefix: uniqueSolutionPrefix pgsqlAdminLogin: pgsqlAdminLogin pgsqlAdminPassword: pgsqlAdminPassword openIdAuthority: openIdAuthority @@ -128,5 +140,17 @@ module portalWithoutLoRaDeployment './portalDeployWithoutLoRa.bicep' = if (!isLo ideasUrl: ideasUrl ideasAuthenticationHeader: ideasAuthenticationHeader ideasAuthenticationToken: ideasAuthenticationToken + appInsightName: appInsightName + deviceImageContainerName: deviceImageContainerName + dpsName: dpsName + iamScopeName: iamScopeName + iotHubName: iotHubName + iotHubOwnerPolicyName: iotHubOwnerPolicyName + pgsqlServerName: pgsqlServerName + provisioningserviceownerPolicyName: provisioningserviceownerPolicyName + servicePlanName: servicePlanName + siteName: siteName + storageAccountId: storageAccountId + storageAccountName: storageAccountName } -} \ No newline at end of file +} diff --git a/templates/portalDeployWithLoRa.bicep b/templates/portalDeployWithLoRa.bicep index e759bbcde..46b55a80c 100644 --- a/templates/portalDeployWithLoRa.bicep +++ b/templates/portalDeployWithLoRa.bicep @@ -35,22 +35,81 @@ param ideasAuthenticationHeader string = 'Ocp-Apim-Subscription-Key' @description('Authentication token to interact with Awesome-Ideas. Required when ideasEnabled is true') param ideasAuthenticationToken string = '' -var pgsqlServerName = '${uniqueSolutionPrefix}pgsql' -var iotHubName = '${uniqueSolutionPrefix}hub' -var dpsName = '${uniqueSolutionPrefix}dps' -var siteName = '${uniqueSolutionPrefix}portal' -var servicePlanName = '${uniqueSolutionPrefix}asp' +@description('The name of the Edge gateway') +param edgeGatewayName string + +@description('Provision a final LoRa device in the IoT hub in addition to the gateway') +param deployDevice bool + +@description('Provide the reset pin value of your gateway. Please refer to the doc if you are unfamiliar with the value') +param resetPin int + +@description('In what region is your gateway deployed?') +@allowed(['EU863', 'US902', 'AS923-1', 'AS923-2', 'AS923-3', 'CN470RP1', 'CN470RP2', 'AU915']) +param region string = 'EU863' + +@description('[In Mbps] Custom SPI speed for your gateway, currently only supported for ARM gateways') +@allowed([8,2]) +param spiSpeed int = 8 + +@description('SPI Dev version for x86 based gateway') +@allowed([0,1,2]) +param spiDev int = 0 + +@description('PostgreSQL Server Name') +param pgsqlServerName string + +@description('IotHub Name') +param iotHubName string + +@description('DPS Name') +param dpsName string + +@description('Site Name') +param siteName string + +@description('Service Plan Name') +param servicePlanName string + +@description('Storage Account Name') +param storageAccountName string + +@description('IotHub Owner Policy Name') +param iotHubOwnerPolicyName string + +@description('Provisioning Service Owner Policy Name') +param provisioningserviceownerPolicyName string + +@description('Device Image Container Name') +param deviceImageContainerName string + +@description('IAM Scope Name') +param iamScopeName string + +@description('Storage Account Id') +param storageAccountId string + +@description('App Insight Name') +param appInsightName string + var functionAppName = '${uniqueSolutionPrefix}function' -var storageAccountName = '${uniqueSolutionPrefix}storage' -var iotHubOwnerPolicyName = 'iothubowner' -var provisioningserviceownerPolicyName = 'provisioningserviceowner' -var deviceImageContainerName = 'device-images' -var iamScopeName = 'API.Access' -var storageAccountId = '${resourceGroup().id}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}' -var appInsightName = '${uniqueSolutionPrefix}insight' var functionAppDefaultHost = '${resourceId('Microsoft.Web/sites', functionAppName)}/host/default/' var ioTHubEventHubConsumerGroupName = 'iothub-portal' +module starterKitDeployment '../iotedge-lorawan-starterkit/TemplateBicep/main.bicep' = { + name: 'lorawan-starter-kit' + params: { + location: location + uniqueSolutionPrefix: uniqueSolutionPrefix + edgeGatewayName: edgeGatewayName + deployDevice: deployDevice + resetPin: resetPin + region: region + spiSpeed: spiSpeed + spiDev: spiDev + } +} + resource iotHub 'Microsoft.Devices/IotHubs@2021-07-02' existing = { name: iotHubName } diff --git a/templates/portalDeployWithoutLoRa.bicep b/templates/portalDeployWithoutLoRa.bicep index 0049eb18b..222d6a04e 100644 --- a/templates/portalDeployWithoutLoRa.bicep +++ b/templates/portalDeployWithoutLoRa.bicep @@ -1,9 +1,6 @@ @description('Location for the resources.') param location string -@description('Prefix used for resource names. Should be unique as this will also be used for domain names.') -param uniqueSolutionPrefix string - @description('PostgreSQL user') param pgsqlAdminLogin string = concat(uniqueString(resourceGroup().id, newGuid())) @@ -35,18 +32,42 @@ param ideasAuthenticationHeader string = 'Ocp-Apim-Subscription-Key' @description('Authentication token to interact with Awesome-Ideas. Required when ideasEnabled is true') param ideasAuthenticationToken string = '' -var pgsqlServerName = '${uniqueSolutionPrefix}pgsql' -var iotHubName = '${uniqueSolutionPrefix}hub' -var dpsName = '${uniqueSolutionPrefix}dps' -var siteName = '${uniqueSolutionPrefix}portal' -var servicePlanName = '${uniqueSolutionPrefix}asp' -var storageAccountName = '${uniqueSolutionPrefix}storage' -var iotHubOwnerPolicyName = 'iothubowner' -var provisioningserviceownerPolicyName = 'provisioningserviceowner' -var deviceImageContainerName = 'device-images' -var iamScopeName = 'API.Access' -var storageAccountId = '${resourceGroup().id}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}' -var appInsightName = '${uniqueSolutionPrefix}insight' +@description('PostgreSQL Server Name') +param pgsqlServerName string + +@description('IotHub Name') +param iotHubName string + +@description('DPS Name') +param dpsName string + +@description('Site Name') +param siteName string + +@description('Service Plan Name') +param servicePlanName string + +@description('Storage Account Name') +param storageAccountName string + +@description('IotHub Owner Policy Name') +param iotHubOwnerPolicyName string + +@description('Provisioning Service Owner Policy Name') +param provisioningserviceownerPolicyName string + +@description('Device Image Container Name') +param deviceImageContainerName string + +@description('IAM Scope Name') +param iamScopeName string + +@description('Storage Account Id') +param storageAccountId string + +@description('App Insight Name') +param appInsightName string + module iotHub './iothub.bicep' = { name: 'iotHub' From 202a0e058683047487772fc4376bb8e0f1de5d65 Mon Sep 17 00:00:00 2001 From: Hocine Hacherouf Date: Wed, 8 Mar 2023 23:06:52 +0100 Subject: [PATCH 3/3] Fix refactoring of bicep templates --- templates/azuredeploy.bicep | 13 +- ...thLoRa.bicep => portal_with_lorawan.bicep} | 45 +----- .../portal_with_lorawan_and_starter_kit.bicep | 141 ++++++++++++++++++ ...oRa.bicep => portal_without_lorawan.bicep} | 0 4 files changed, 153 insertions(+), 46 deletions(-) rename templates/{portalDeployWithLoRa.bicep => portal_with_lorawan.bicep} (77%) create mode 100644 templates/portal_with_lorawan_and_starter_kit.bicep rename templates/{portalDeployWithoutLoRa.bicep => portal_without_lorawan.bicep} (100%) diff --git a/templates/azuredeploy.bicep b/templates/azuredeploy.bicep index d9827acab..ed59f221c 100644 --- a/templates/azuredeploy.bicep +++ b/templates/azuredeploy.bicep @@ -74,9 +74,6 @@ param ideasAuthenticationHeader string = 'Ocp-Apim-Subscription-Key' @description('Authentication token to interact with Awesome-Ideas. Required when ideasEnabled is true') param ideasAuthenticationToken string = '' -var portalWithLoRaDeploymentName = 'iothub-portal-with-lora' -var portalWithoutLoRaDeploymentName = 'iothub-portal-without-lora' - var pgsqlServerName = '${uniqueSolutionPrefix}pgsql' var iotHubName = '${uniqueSolutionPrefix}hub' var dpsName = '${uniqueSolutionPrefix}dps' @@ -89,9 +86,10 @@ var deviceImageContainerName = 'device-images' var iamScopeName = 'API.Access' var storageAccountId = '${resourceGroup().id}/providers/Microsoft.Storage/storageAccounts/${storageAccountName}' var appInsightName = '${uniqueSolutionPrefix}insight' +var functionAppName = '${uniqueSolutionPrefix}function' -module portalWithLoRaDeployment './portalDeployWithLoRa.bicep' = if (isLoRaFeatureEnabled) { - name: portalWithLoRaDeploymentName +module portalWithLoRaDeployment './portal_with_lorawan_and_starter_kit.bicep' = if (isLoRaFeatureEnabled) { + name: 'iothub-portal-with-lorawan' params: { location: location uniqueSolutionPrefix: uniqueSolutionPrefix @@ -123,11 +121,12 @@ module portalWithLoRaDeployment './portalDeployWithLoRa.bicep' = if (isLoRaFeatu siteName: siteName storageAccountId: storageAccountId storageAccountName: storageAccountName + functionAppName: functionAppName } } -module portalWithoutLoRaDeployment './portalDeployWithoutLoRa.bicep' = if (!isLoRaFeatureEnabled) { - name: portalWithoutLoRaDeploymentName +module portalWithoutLoRaDeployment './portal_without_lorawan.bicep' = if (!isLoRaFeatureEnabled) { + name: 'iothub-portal-without-lorawan' params: { location: location pgsqlAdminLogin: pgsqlAdminLogin diff --git a/templates/portalDeployWithLoRa.bicep b/templates/portal_with_lorawan.bicep similarity index 77% rename from templates/portalDeployWithLoRa.bicep rename to templates/portal_with_lorawan.bicep index 46b55a80c..1f2cc5a7b 100644 --- a/templates/portalDeployWithLoRa.bicep +++ b/templates/portal_with_lorawan.bicep @@ -1,9 +1,6 @@ @description('Location for the resources.') param location string -@description('Prefix used for resource names. Should be unique as this will also be used for domain names.') -param uniqueSolutionPrefix string - @description('PostgreSQL user') param pgsqlAdminLogin string = concat(uniqueString(resourceGroup().id, newGuid())) @@ -35,27 +32,6 @@ param ideasAuthenticationHeader string = 'Ocp-Apim-Subscription-Key' @description('Authentication token to interact with Awesome-Ideas. Required when ideasEnabled is true') param ideasAuthenticationToken string = '' -@description('The name of the Edge gateway') -param edgeGatewayName string - -@description('Provision a final LoRa device in the IoT hub in addition to the gateway') -param deployDevice bool - -@description('Provide the reset pin value of your gateway. Please refer to the doc if you are unfamiliar with the value') -param resetPin int - -@description('In what region is your gateway deployed?') -@allowed(['EU863', 'US902', 'AS923-1', 'AS923-2', 'AS923-3', 'CN470RP1', 'CN470RP2', 'AU915']) -param region string = 'EU863' - -@description('[In Mbps] Custom SPI speed for your gateway, currently only supported for ARM gateways') -@allowed([8,2]) -param spiSpeed int = 8 - -@description('SPI Dev version for x86 based gateway') -@allowed([0,1,2]) -param spiDev int = 0 - @description('PostgreSQL Server Name') param pgsqlServerName string @@ -92,24 +68,12 @@ param storageAccountId string @description('App Insight Name') param appInsightName string -var functionAppName = '${uniqueSolutionPrefix}function' +@description('Function App Name') +param functionAppName string + var functionAppDefaultHost = '${resourceId('Microsoft.Web/sites', functionAppName)}/host/default/' var ioTHubEventHubConsumerGroupName = 'iothub-portal' -module starterKitDeployment '../iotedge-lorawan-starterkit/TemplateBicep/main.bicep' = { - name: 'lorawan-starter-kit' - params: { - location: location - uniqueSolutionPrefix: uniqueSolutionPrefix - edgeGatewayName: edgeGatewayName - deployDevice: deployDevice - resetPin: resetPin - region: region - spiSpeed: spiSpeed - spiDev: spiDev - } -} - resource iotHub 'Microsoft.Devices/IotHubs@2021-07-02' existing = { name: iotHubName } @@ -120,6 +84,9 @@ module ioTHubEventHubConsumerGroup './iothub_eventhub_consumer_group.bicep' = { iotHubName: iotHubName ioTHubEventHubConsumerGroupName: ioTHubEventHubConsumerGroupName } + dependsOn: [ + iotHub + ] } module storageAccountName_default_deviceImageContainer './blob_container.bicep' = { diff --git a/templates/portal_with_lorawan_and_starter_kit.bicep b/templates/portal_with_lorawan_and_starter_kit.bicep new file mode 100644 index 000000000..e9ba15575 --- /dev/null +++ b/templates/portal_with_lorawan_and_starter_kit.bicep @@ -0,0 +1,141 @@ +@description('Location for the resources.') +param location string + +@description('Prefix used for resource names. Should be unique as this will also be used for domain names.') +param uniqueSolutionPrefix string + +@description('PostgreSQL user') +param pgsqlAdminLogin string = concat(uniqueString(resourceGroup().id, newGuid())) + +@description('PostgreSQL password') +@secure() +param pgsqlAdminPassword string = '${uniqueString(resourceGroup().id, newGuid())}x!' + +@description('The Open ID Authority') +param openIdAuthority string + +@description('The Open ID metadata Url from the Identity provider') +param openIdMetadataURL string + +@description('The client ID for the B2C tenant') +param clientId string + +@description('The API client ID for the B2C tenant') +param apiClientId string + +@description('To enable Awesome-Ideas feature when set to true') +param ideasEnabled bool = false + +@description('Url of Awesome-Ideas, to publish ideas submitted by users. Required when ideasEnabled is true') +param ideasUrl string = '' + +@description('Authentication header to interact with Awesome-Ideas. Required when ideasEnabled is true') +param ideasAuthenticationHeader string = 'Ocp-Apim-Subscription-Key' + +@description('Authentication token to interact with Awesome-Ideas. Required when ideasEnabled is true') +param ideasAuthenticationToken string = '' + +@description('The name of the Edge gateway') +param edgeGatewayName string + +@description('Provision a final LoRa device in the IoT hub in addition to the gateway') +param deployDevice bool + +@description('Provide the reset pin value of your gateway. Please refer to the doc if you are unfamiliar with the value') +param resetPin int + +@description('In what region is your gateway deployed?') +@allowed(['EU863', 'US902', 'AS923-1', 'AS923-2', 'AS923-3', 'CN470RP1', 'CN470RP2', 'AU915']) +param region string = 'EU863' + +@description('[In Mbps] Custom SPI speed for your gateway, currently only supported for ARM gateways') +@allowed([8,2]) +param spiSpeed int = 8 + +@description('SPI Dev version for x86 based gateway') +@allowed([0,1,2]) +param spiDev int = 0 + +@description('PostgreSQL Server Name') +param pgsqlServerName string + +@description('IotHub Name') +param iotHubName string + +@description('DPS Name') +param dpsName string + +@description('Site Name') +param siteName string + +@description('Service Plan Name') +param servicePlanName string + +@description('Storage Account Name') +param storageAccountName string + +@description('IotHub Owner Policy Name') +param iotHubOwnerPolicyName string + +@description('Provisioning Service Owner Policy Name') +param provisioningserviceownerPolicyName string + +@description('Device Image Container Name') +param deviceImageContainerName string + +@description('IAM Scope Name') +param iamScopeName string + +@description('Storage Account Id') +param storageAccountId string + +@description('App Insight Name') +param appInsightName string + +@description('Function App Name') +param functionAppName string + +module starterKitDeployment '../iotedge-lorawan-starterkit/TemplateBicep/main.bicep' = { + name: 'lorawan-starter-kit' + params: { + location: location + uniqueSolutionPrefix: uniqueSolutionPrefix + edgeGatewayName: edgeGatewayName + deployDevice: deployDevice + resetPin: resetPin + region: region + spiSpeed: spiSpeed + spiDev: spiDev + } +} + +module portalWithLoRaWAN './portal_with_lorawan.bicep' = { + name: 'portal-with-lorawan' + params: { + location: location + pgsqlAdminLogin: pgsqlAdminLogin + pgsqlAdminPassword: pgsqlAdminPassword + openIdAuthority: openIdAuthority + openIdMetadataURL: openIdMetadataURL + apiClientId: apiClientId + clientId: clientId + ideasEnabled: ideasEnabled + ideasUrl: ideasUrl + ideasAuthenticationHeader: ideasAuthenticationHeader + ideasAuthenticationToken: ideasAuthenticationToken + appInsightName: appInsightName + deviceImageContainerName: deviceImageContainerName + dpsName: dpsName + iamScopeName: iamScopeName + iotHubName: iotHubName + iotHubOwnerPolicyName: iotHubOwnerPolicyName + pgsqlServerName: pgsqlServerName + provisioningserviceownerPolicyName: provisioningserviceownerPolicyName + servicePlanName: servicePlanName + siteName: siteName + storageAccountId: storageAccountId + storageAccountName: storageAccountName + functionAppName: functionAppName + } + dependsOn: [ starterKitDeployment ] +} diff --git a/templates/portalDeployWithoutLoRa.bicep b/templates/portal_without_lorawan.bicep similarity index 100% rename from templates/portalDeployWithoutLoRa.bicep rename to templates/portal_without_lorawan.bicep