diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/generateArmTemplate.ps1 b/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/generateArmTemplate.ps1 new file mode 100644 index 0000000000000..8176d353331f0 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/generateArmTemplate.ps1 @@ -0,0 +1,2 @@ +$bicepFile = Join-Path -Path $PSScriptRoot -ChildPath "../../../test-resources.bicep" +bicep build $bicepFile \ No newline at end of file diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/prerequisite readme.md b/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/prerequisite readme.md index f1c7d57a9eae8..31822a792c68b 100644 --- a/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/prerequisite readme.md +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/test/resources/prerequisite/prerequisite readme.md @@ -13,13 +13,26 @@ - If it isn't, update it - Use this link to install [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest]) -## Delete +### Install Bicep -To delete the digital twins instance, you need to first delete the endpoint added by the script (the service doesn't yet support cascading delete). +- Install using the instructions in [bicep](https://github.com/Azure/bicep/blob/main/docs/installing.md) +- Note that to deploy Bicep files, use Bicep CLI version 0.3.1 or later. To check your Bicep CLI version, run: -1. To do this, run the command `az dt endpoint delete -n
-g --en someEventHubEndpoint`. -1. If you have other endpoints that have been added outside this script, you can discover them with the command `az dt endpoint list -n
-g `. -1. Then delete them with the same command in step 1. +```bash +bicep --version +``` + +### Run the setup script + +The script outputs [test-resources.bicep](https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/digitaltwins/test-resources.bicep) file in the root folder [digitaltwins](https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/digitaltwins) + +- `.\setup.ps1` + +### Generate the ARM template + +The ARM template [test-resources.json](https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/digitaltwins/test-resources.json) is generated from the [test-resources.bicep](https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/digitaltwins/test-resources.bicep) file by running the following script + +- `.\generateArmTemplate.ps1` ## Maintenance diff --git a/sdk/digitaltwins/test-resources.bicep b/sdk/digitaltwins/test-resources.bicep new file mode 100644 index 0000000000000..3868d3b9420cd --- /dev/null +++ b/sdk/digitaltwins/test-resources.bicep @@ -0,0 +1,96 @@ +@description('The client OID to grant access to test resources.') +param testApplicationOid string + +@minLength(6) +@maxLength(50) +@description('The base resource name.') +param baseName string = resourceGroup().name + +@description('The location of the resource. By default, this is the same as the resource group.') +param location string = resourceGroup().location + +var rbacOwnerRoleDefinitionId = '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' +var adtOwnerRoleDefinitionId = '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2018-09-01-preview' = { + name: guid(resourceGroup().id) + properties: { + roleDefinitionId: rbacOwnerRoleDefinitionId + principalId: testApplicationOid + } +} + +resource digitaltwin 'Microsoft.DigitalTwins/digitalTwinsInstances@2020-03-01-preview' = { + name: baseName + location: location + sku: { + name: 'S1' + } + properties: {} +} + +resource digitaltwinRoleAssignment 'Microsoft.DigitalTwins/digitalTwinsInstances/providers/roleAssignments@2020-03-01-preview' = { + name: '${digitaltwin.name}/Microsoft.Authorization/${guid(uniqueString(baseName))}' + properties: { + roleDefinitionId: adtOwnerRoleDefinitionId + principalId: testApplicationOid + } +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2018-01-01-preview' = { + name: baseName + location: location + sku: { + name: 'Standard' + tier: 'Standard' + capacity: 1 + } + properties: { + zoneRedundant: false + isAutoInflateEnabled: false + maximumThroughputUnits: 0 + kafkaEnabled: false + } +} + +resource eventHubNamespaceEventHub 'Microsoft.EventHub/namespaces/eventhubs@2017-04-01' = { + name: '${eventHubNamespace.name}/${baseName}' + properties: { + messageRetentionInDays: 7 + partitionCount: 4 + status: 'Active' + } +} + +resource eventHubNamespaceAuthRules 'Microsoft.EventHub/namespaces/AuthorizationRules@2017-04-01' = { + name: '${eventHubNamespace.name}/RootManageSharedAccessKey' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +} + +resource eventHubNamespaceEventHubAuthRules 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules@2017-04-01' = { + name: '${eventHubNamespaceEventHub.name}/owner' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +} + +resource digitaltwinEndpoints 'Microsoft.DigitalTwins/digitalTwinsInstances/endpoints@2020-03-01-preview' = { + name: '${digitaltwin.name}/someEventHubEndpoint' + properties: { + endpointType: 'EventHub' + 'connectionString-PrimaryKey': listKeys(eventHubNamespaceEventHubAuthRules.id, '2017-04-01').primaryConnectionString + 'connectionString-SecondaryKey': listKeys(eventHubNamespaceEventHubAuthRules.id, '2017-04-01').secondaryConnectionString + } +} + +output DIGITALTWINS_URL string = 'https://${digitaltwin.properties.hostName}' diff --git a/sdk/digitaltwins/test-resources.json b/sdk/digitaltwins/test-resources.json index 5d830cf1169de..1664a25e61bd2 100644 --- a/sdk/digitaltwins/test-resources.json +++ b/sdk/digitaltwins/test-resources.json @@ -1,21 +1,28 @@ { - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.63.48766", + "templateHash": "14469093771711807520" + } + }, "parameters": { - "baseName": { + "testApplicationOid": { "type": "string", - "minLength": 6, - "maxLength": 50, - "defaultValue": "[resourceGroup().name]", "metadata": { - "description": "The base resource name." + "description": "The client OID to grant access to test resources." } }, - "testApplicationOid": { + "baseName": { "type": "string", + "defaultValue": "[resourceGroup().name]", "metadata": { - "description": "The client OID to grant access to test resources." - } + "description": "The base resource name." + }, + "maxLength": 50, + "minLength": 6 }, "location": { "type": "string", @@ -25,13 +32,10 @@ } } }, + "functions": [], "variables": { - "digitalTwinInstanceResourceId": "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('baseName'))]", - "namespaceResourceId": "[resourceId('Microsoft.EventHub/namespaces', parameters('baseName'))]", - "eventHubResourceId": "[resourceId('Microsoft.EventHub/namespaces/eventhubs', parameters('baseName'), parameters('baseName'))]", - "eventHubAuthorizationResourceId": "[resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', parameters('baseName'), parameters('baseName'), 'owner')]", - "rbacOwnerRoleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", - "AdtOwnerRoleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]" + "rbacOwnerRoleDefinitionId": "[format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635', subscription().subscriptionId)]", + "adtOwnerRoleDefinitionId": "[format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe', subscription().subscriptionId)]" }, "resources": [ { @@ -56,13 +60,13 @@ { "type": "Microsoft.DigitalTwins/digitalTwinsInstances/providers/roleAssignments", "apiVersion": "2020-03-01-preview", - "name": "[concat(parameters('baseName'),'/Microsoft.Authorization/', guid(uniqueString(parameters('baseName'))))]", + "name": "[format('{0}/Microsoft.Authorization/{1}', parameters('baseName'), guid(uniqueString(parameters('baseName'))))]", "properties": { - "roleDefinitionId": "[variables('AdtOwnerRoleDefinitionId')]", + "roleDefinitionId": "[variables('adtOwnerRoleDefinitionId')]", "principalId": "[parameters('testApplicationOid')]" }, "dependsOn": [ - "[variables('digitalTwinInstanceResourceId')]" + "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('baseName'))]" ] }, { @@ -79,77 +83,71 @@ "zoneRedundant": false, "isAutoInflateEnabled": false, "maximumThroughputUnits": 0, - "kafkaEnabled": true + "kafkaEnabled": false } }, { "type": "Microsoft.EventHub/namespaces/eventhubs", "apiVersion": "2017-04-01", - "name": "[concat(parameters('baseName'), '/', parameters('baseName'))]", - "location": "[parameters('location')]", - "dependsOn": [ - "[variables('namespaceResourceId')]" - ], + "name": "[format('{0}/{1}', parameters('baseName'), parameters('baseName'))]", "properties": { "messageRetentionInDays": 7, "partitionCount": 4, "status": "Active" - } + }, + "dependsOn": [ + "[resourceId('Microsoft.EventHub/namespaces', parameters('baseName'))]" + ] }, { - "type": "Microsoft.EventHub/namespaces/AuthorizationRules", + "type": "Microsoft.EventHub/namespaces/authorizationRules", "apiVersion": "2017-04-01", - "name": "[concat(parameters('baseName'), '/RootManageSharedAccessKey')]", - "location": "[parameters('location')]", - "dependsOn": [ - "[variables('namespaceResourceId')]" - ], + "name": "[format('{0}/RootManageSharedAccessKey', parameters('baseName'))]", "properties": { "rights": [ "Listen", "Manage", "Send" ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.EventHub/namespaces', parameters('baseName'))]" + ] }, { "type": "Microsoft.EventHub/namespaces/eventhubs/authorizationRules", "apiVersion": "2017-04-01", - "name": "[concat(parameters('baseName'), '/', parameters('baseName'), '/owner')]", - "location": "[parameters('location')]", - "dependsOn": [ - "[variables('namespaceResourceId')]", - "[variables('eventHubResourceId')]" - ], + "name": "[format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName')))]", "properties": { "rights": [ + "Listen", "Manage", - "Send", - "Listen" + "Send" ] - } + }, + "dependsOn": [ + "[resourceId('Microsoft.EventHub/namespaces/eventhubs', split(format('{0}/{1}', parameters('baseName'), parameters('baseName')), '/')[0], split(format('{0}/{1}', parameters('baseName'), parameters('baseName')), '/')[1])]" + ] }, { "type": "Microsoft.DigitalTwins/digitalTwinsInstances/endpoints", "apiVersion": "2020-03-01-preview", - "name": "[concat(parameters('baseName'), '/someEventHubEndpoint')]", - "dependsOn": [ - "[variables('digitalTwinInstanceResourceId')]", - "[variables('namespaceResourceId')]", - "[variables('eventHubResourceId')]", - "[variables('eventHubAuthorizationResourceId')]" - ], + "name": "[format('{0}/someEventHubEndpoint', parameters('baseName'))]", "properties": { "endpointType": "EventHub", - "connectionString-PrimaryKey": "[listKeys(variables('eventHubAuthorizationResourceId'),'2017-04-01').primaryConnectionString]", - "connectionString-SecondaryKey": "[listKeys(variables('eventHubAuthorizationResourceId'),'2017-04-01').secondaryConnectionString]" - } + "connectionString-PrimaryKey": "[listKeys(resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[0], split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[1], split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[2]), '2017-04-01').primaryConnectionString]", + "connectionString-SecondaryKey": "[listKeys(resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[0], split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[1], split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[2]), '2017-04-01').secondaryConnectionString]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('baseName'))]", + "[resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules', split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[0], split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[1], split(format('{0}/owner', format('{0}/{1}', parameters('baseName'), parameters('baseName'))), '/')[2])]" + ] } ], "outputs": { "DIGITALTWINS_URL": { "type": "string", - "value": "[concat('https://', reference(variables('digitalTwinInstanceResourceId'), '2020-03-01-preview').hostName)]" + "value": "[format('https://{0}', reference(resourceId('Microsoft.DigitalTwins/digitalTwinsInstances', parameters('baseName'))).hostName)]" } } -} +} \ No newline at end of file