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