diff --git a/.github/linters/.arm-ttk.psd1 b/.github/linters/.arm-ttk.psd1 index 81cbfaa..2e6e19b 100644 --- a/.github/linters/.arm-ttk.psd1 +++ b/.github/linters/.arm-ttk.psd1 @@ -11,5 +11,7 @@ 'IDs Should Be Derived From ResourceIDs' 'Parameters Must Be Referenced' 'Variables Must Be Referenced' + 'URIs Should Be Properly Constructed' + 'apiVersions Should Be Recent' ) } diff --git a/docs/DataManagementAnalytics-AzureDevOpsDeployment.md b/docs/DataManagementAnalytics-AzureDevOpsDeployment.md index 7dc8a64..99ade8e 100644 --- a/docs/DataManagementAnalytics-AzureDevOpsDeployment.md +++ b/docs/DataManagementAnalytics-AzureDevOpsDeployment.md @@ -86,6 +86,7 @@ To begin, please open the [infra/params.dev.json](/infra/params.dev.json). In th | `purviewManagedStorageId` | Specifies the Resource ID of the managed storage account of the central Purview instance. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Storage/storageAccounts/{storage-account-name}` | | `purviewManagedEventHubId` | Specifies the Resource ID of the managed Event Hub of the central Purview instance. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.EventHub/namespaces/{eventhub-namespace-name}` | | `enableRoleAssignments` | Specifies whether role assignments should be enabled. | `true` or `false` | +| `enableObservability` | Specifies whether observability capabilities should be enabled. | `true` or `false` | | `privateDnsZoneIdKeyVault` | Specifies the Resource ID of the private DNS zone for KeyVault. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net` | | `privateDnsZoneIdSynapseDev` | Specifies the Resource ID of the private DNS zone for Synapse Dev. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Network/privateDnsZones/privatelink.dev.azuresynapse.net` | | `privateDnsZoneIdSynapseSql` | Specifies the Resource ID of the private DNS zone for Synapse Sql. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Network/privateDnsZones/privatelink.sql.azuresynapse.net` | diff --git a/docs/DataManagementAnalytics-GitHubActionsDeployment.md b/docs/DataManagementAnalytics-GitHubActionsDeployment.md index 355ae7c..20fc4f8 100644 --- a/docs/DataManagementAnalytics-GitHubActionsDeployment.md +++ b/docs/DataManagementAnalytics-GitHubActionsDeployment.md @@ -77,6 +77,7 @@ To begin, please open the [infra/params.dev.json](/infra/params.dev.json). In th | `purviewManagedStorageId` | Specifies the Resource ID of the managed storage account of the central Purview instance. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Storage/storageAccounts/{storage-account-name}` | | `purviewManagedEventHubId` | Specifies the Resource ID of the managed Event Hub of the central Purview instance. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.EventHub/namespaces/{eventhub-namespace-name}` | | `enableRoleAssignments` | Specifies whether role assignments should be enabled. | `true` or `false` | +| `enableObservability` | Specifies whether observability capabilities should be enabled. | `true` or `false` | | `privateDnsZoneIdKeyVault` | Specifies the Resource ID of the private DNS zone for KeyVault. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net` | | `privateDnsZoneIdSynapseDev` | Specifies the Resource ID of the private DNS zone for Synapse Dev. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Network/privateDnsZones/privatelink.dev.azuresynapse.net` | | `privateDnsZoneIdSynapseSql` | Specifies the Resource ID of the private DNS zone for Synapse Sql. | `/subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Network/privateDnsZones/privatelink.sql.azuresynapse.net` | diff --git a/docs/reference/portal.dataProduct.json b/docs/reference/portal.dataProduct.json index fd25c24..0ebe38e 100644 --- a/docs/reference/portal.dataProduct.json +++ b/docs/reference/portal.dataProduct.json @@ -433,13 +433,21 @@ { "name": "enableSqlPool", "label": "Enable SQL Pool", - "type": "Microsoft.Common.CheckBox", - "visible": "[equals(steps('generalSettings').dataProcessingServiceDeploymentSettings.processingService, 'synapse')]", - "defaultValue": false, + "type": "Microsoft.Common.OptionsGroup", + "visible": true, "toolTip": "Enable the deployment of an Azure SQL Pool (DW100).", + "defaultValue": "No", "constraints": { - "required": false, - "validationMessage": "Enable the deployment of an Azure SQL Pool (DW100)." + "allowedValues": [ + { + "label": "Yes", + "value": "yes" + }, + { + "label": "No", + "value": "no" + } + ] } } ] @@ -564,13 +572,21 @@ { "name": "enableCosmos", "label": "Enable Azure Cosmos DB", - "type": "Microsoft.Common.CheckBox", + "type": "Microsoft.Common.OptionsGroup", "visible": true, - "defaultValue": false, "toolTip": "Enable the deployment of Azure Cosmos DB.", + "defaultValue": "Yes", "constraints": { - "required": false, - "validationMessage": "Enable the deployment of Azure Cosmos DB." + "allowedValues": [ + { + "label": "Yes", + "value": "yes" + }, + { + "label": "No", + "value": "no" + } + ] } }, { @@ -585,13 +601,61 @@ { "name": "enableRoleAssignments", "label": "Enable role assignments", - "type": "Microsoft.Common.CheckBox", + "type": "Microsoft.Common.OptionsGroup", "visible": true, - "defaultValue": false, "toolTip": "Enable role assignments.", + "defaultValue": "Yes (recommended)", + "constraints": { + "allowedValues": [ + { + "label": "Yes (recommended)", + "value": "yes" + }, + { + "label": "No", + "value": "no" + } + ] + } + } + ] + }, + { + "name": "observabilitySettings", + "label": "Observability Settings", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "observabilitySettingsText", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Specify observability settings for this deployment.", + "link": { + "label": "", + "uri": "" + } + } + }, + { + "name": "enableObservability", + "label": "Deploy Observability Extension", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "toolTip": "If 'Yes' is selected, a Log Analytics workspace as well as a set of Azure dashboards will be deployed.", + "defaultValue": "Yes (recommended)", "constraints": { - "required": false, - "validationMessage": "Enable role assignments of the Synapse MSI. Please read infobox above for more details." + "allowedValues": [ + { + "label": "Yes (recommended)", + "value": "yes" + }, + { + "label": "No", + "value": "no" + } + ] } } ] @@ -977,12 +1041,13 @@ "administratorPassword": "[if(empty(steps('generalSettings').generalSettings.administratorPassword), '', steps('generalSettings').generalSettings.administratorPassword)]", "processingService": "[if(empty(steps('generalSettings').dataProcessingServiceDeploymentSettings.processingService), '', steps('generalSettings').dataProcessingServiceDeploymentSettings.processingService)]", "synapseDefaultStorageAccountFileSystemId": "[if(empty(steps('generalSettings').dataProcessingServiceDeploymentSettings.synapseDefaultStorageAccountFileSystemId), '', steps('generalSettings').dataProcessingServiceDeploymentSettings.synapseDefaultStorageAccountFileSystemId)]", - "enableSqlPool": "[steps('generalSettings').dataProcessingServiceDeploymentSettings.enableSqlPool]", - "enableCosmos": "[steps('generalSettings').generalSettings.enableCosmos]", + "enableSqlPool": "[equals(steps('generalSettings').dataProcessingServiceDeploymentSettings.enableSqlPool, 'yes')]", + "enableCosmos": "[equals(steps('generalSettings').generalSettings.enableCosmos, 'yes')]", "purviewId": "[if(empty(steps('generalSettings').dataGovernanceSettings.purviewId.id), '', steps('generalSettings').dataGovernanceSettings.purviewId.id)]", "purviewManagedStorageId": "[if(empty(steps('generalSettings').dataGovernanceSettings.purviewId.id), '', steps('generalSettings').dataGovernanceSettings.purviewApi.properties.managedResources.storageAccount)]", "purviewManagedEventHubId": "[if(empty(steps('generalSettings').dataGovernanceSettings.purviewId.id), '', steps('generalSettings').dataGovernanceSettings.purviewApi.properties.managedResources.eventHubNamespace)]", - "enableRoleAssignments": "[steps('generalSettings').generalSettings.enableRoleAssignments]", + "enableRoleAssignments": "[equals(steps('generalSettings').generalSettings.enableRoleAssignments, 'yes')]", + "enableObservability": "[equals(steps('generalSettings').observabilitySettings.enableObservability, 'yes')]", "subnetId": "[if(empty(steps('connectivitySettings').virtualNetwork.subnetId), '', steps('connectivitySettings').virtualNetwork.subnetId)]", "privateDnsZoneIdKeyVault": "[if(empty(steps('connectivitySettings').privateDnsZones.privateDnsZoneIdKeyVault), '', steps('connectivitySettings').privateDnsZones.privateDnsZoneIdKeyVault)]", "privateDnsZoneIdSynapseDev": "[if(empty(steps('connectivitySettings').privateDnsZones.privateDnsZoneIdSynapseDev), '', steps('connectivitySettings').privateDnsZones.privateDnsZoneIdSynapseDev)]", diff --git a/infra/main.bicep b/infra/main.bicep index 531b516..d9bbfd0 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -53,6 +53,8 @@ param purviewManagedStorageId string = '' param purviewManagedEventHubId string = '' @description('Specifies whether role assignments should be enabled.') param enableRoleAssignments bool = false +@description('Specifies whether observability capabilities should be enabled.') +param enableObservability bool = true // Network parameters @description('Specifies the resource ID of the subnet to which all services will connect.') @@ -101,6 +103,7 @@ var sql001Name = '${name}-sqlserver001' var mysql001Name = '${name}-mysql001' var mariadb001Name = '${name}-mariadb001' var potsgresql001Name = '${name}-postgresql001' +var logAnalytics001Name = '${name}-la001' // Resources module keyVault001 'modules/services/keyvault.bicep' = { @@ -236,4 +239,14 @@ module postgresql001 'modules/services/postgresql.bicep' = if (sqlFlavour == 'po } } +module logAnalytics001 'modules/services/loganalytics.bicep' = if(enableObservability) { + name: 'logAnalytics001' + scope: resourceGroup() + params: { + location: location + tags: tagsJoined + logAnanalyticsName: logAnalytics001Name + } +} + // Outputs diff --git a/infra/main.json b/infra/main.json index 597c752..175a607 100644 --- a/infra/main.json +++ b/infra/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.4.1124.51302", - "templateHash": "2607815037718360205" + "templateHash": "17229161188929746269" } }, "parameters": { @@ -122,6 +122,13 @@ "description": "Specifies whether role assignments should be enabled." } }, + "enableObservability": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Specifies whether observability capabilities should be enabled." + } + }, "subnetId": { "type": "string", "metadata": { @@ -219,7 +226,8 @@ "sql001Name": "[format('{0}-sqlserver001', variables('name'))]", "mysql001Name": "[format('{0}-mysql001', variables('name'))]", "mariadb001Name": "[format('{0}-mariadb001', variables('name'))]", - "potsgresql001Name": "[format('{0}-postgresql001', variables('name'))]" + "potsgresql001Name": "[format('{0}-postgresql001', variables('name'))]", + "logAnalytics001Name": "[format('{0}-la001', variables('name'))]" }, "resources": [ { @@ -2066,6 +2074,117 @@ ] } } + }, + { + "condition": "[parameters('enableObservability')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "logAnalytics001", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[variables('tagsJoined')]" + }, + "logAnanalyticsName": { + "value": "[variables('logAnalytics001Name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1124.51302", + "templateHash": "6316627051499014174" + } + }, + "parameters": { + "location": { + "type": "string" + }, + "tags": { + "type": "object" + }, + "logAnanalyticsName": { + "type": "string" + } + }, + "variables": { + "dataFactoryAnalyticsName": "[format('{0}-adf-analytics', parameters('logAnanalyticsName'))]", + "sqlAnalyticsName": "[format('{0}-sql-analytics', parameters('logAnanalyticsName'))]" + }, + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2020-10-01", + "name": "[parameters('logAnanalyticsName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "features": {}, + "publicNetworkAccessForIngestion": "Enabled", + "publicNetworkAccessForQuery": "Enabled", + "retentionInDays": 120, + "sku": { + "name": "PerGB2018" + } + } + }, + { + "type": "Microsoft.OperationsManagement/solutions", + "apiVersion": "2015-11-01-preview", + "name": "[variables('dataFactoryAnalyticsName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "plan": { + "name": "[format('AzureDataFactoryAnalytics{0}', parameters('logAnanalyticsName'))]", + "product": "OMSGallery/AzureDataFactoryAnalytics", + "promotionCode": "", + "publisher": "Microsoft" + }, + "properties": { + "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnanalyticsName'))]" + }, + "dependsOn": [ + "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnanalyticsName'))]" + ] + }, + { + "type": "Microsoft.OperationsManagement/solutions", + "apiVersion": "2015-11-01-preview", + "name": "[variables('sqlAnalyticsName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "plan": { + "name": "[format('AzureSQLAnalytics{0}', parameters('logAnanalyticsName'))]", + "product": "OMSGallery/AzureSQLAnalytics", + "promotionCode": "", + "publisher": "Microsoft" + }, + "properties": { + "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnanalyticsName'))]" + }, + "dependsOn": [ + "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnanalyticsName'))]" + ] + } + ], + "outputs": { + "logAnalyticsWorkspaceId": { + "type": "string", + "value": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnanalyticsName'))]" + } + } + } + } } ] } \ No newline at end of file diff --git a/infra/modules/services/loganalytics.bicep b/infra/modules/services/loganalytics.bicep new file mode 100644 index 0000000..a868692 --- /dev/null +++ b/infra/modules/services/loganalytics.bicep @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// This template is used to create a Log Analytics workspace. +targetScope = 'resourceGroup' + +// Parameters +param location string +param tags object +param logAnanalyticsName string + +// Variables +var dataFactoryAnalyticsName = '${logAnanalyticsName}-adf-analytics' +var sqlAnalyticsName = '${logAnanalyticsName}-sql-analytics' + +// Resources +resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2020-10-01' = { + name: logAnanalyticsName + location: location + tags: tags + properties: { + features: {} + publicNetworkAccessForIngestion: 'Enabled' + publicNetworkAccessForQuery: 'Enabled' + retentionInDays: 120 + sku: { + name: 'PerGB2018' + } + } +} + +resource dataFactoryAnalytics 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { + name: dataFactoryAnalyticsName + location: location + tags: tags + plan: { + name: 'AzureDataFactoryAnalytics${logAnalytics.name}' + product: 'OMSGallery/AzureDataFactoryAnalytics' + promotionCode: '' + publisher: 'Microsoft' + } + properties: { + workspaceResourceId: logAnalytics.id + } +} + +resource sqlAnalytics 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { + name: sqlAnalyticsName + location: location + tags: tags + plan: { + name: 'AzureSQLAnalytics${logAnalytics.name}' + product: 'OMSGallery/AzureSQLAnalytics' + promotionCode: '' + publisher: 'Microsoft' + } + properties: { + workspaceResourceId: logAnalytics.id + } +} + +// Outputs +output logAnalyticsWorkspaceId string = logAnalytics.id diff --git a/infra/params.dev.json b/infra/params.dev.json index 1d4c04c..de13b88 100644 --- a/infra/params.dev.json +++ b/infra/params.dev.json @@ -47,6 +47,9 @@ "enableRoleAssignments": { "value": false }, + "enableObservability": { + "value": true + }, "privateDnsZoneIdKeyVault": { "value": "/subscriptions/17588eb2-2943-461a-ab3f-00a3ceac3112/resourceGroups/dmz-dev-global-dns/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" }, diff --git a/infra/params.prod.json b/infra/params.prod.json index 160d2e7..ed4eb70 100644 --- a/infra/params.prod.json +++ b/infra/params.prod.json @@ -47,6 +47,9 @@ "enableRoleAssignments": { "value": false }, + "enableObservability": { + "value": true + }, "privateDnsZoneIdKeyVault": { "value": "/subscriptions/17588eb2-2943-461a-ab3f-00a3ceac3112/resourceGroups/dmz-prd-global-dns/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" }, diff --git a/infra/params.test.json b/infra/params.test.json index a683408..7ce4633 100644 --- a/infra/params.test.json +++ b/infra/params.test.json @@ -47,6 +47,9 @@ "enableRoleAssignments": { "value": false }, + "enableObservability": { + "value": true + }, "privateDnsZoneIdKeyVault": { "value": "/subscriptions/17588eb2-2943-461a-ab3f-00a3ceac3112/resourceGroups/dmz-tst-global-dns/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" },