|
| 1 | +--- |
| 2 | +title: How to create Healthcare APIs, workspaces, FHIR and DICOM service, and IoT connectors using Azure Bicep |
| 3 | +description: This document describes how to deploy Healthcare APIs using Azure Bicep. |
| 4 | +author: stevewohl |
| 5 | +ms.service: healthcare-apis |
| 6 | +ms.subservice: fhir |
| 7 | +ms.topic: quickstart |
| 8 | +ms.date: 01/31/2022 |
| 9 | +ms.author: zxue |
| 10 | +ms.custom: mode-api |
| 11 | +--- |
| 12 | + |
| 13 | +# Deploy Healthcare APIs Using Azure Bicep |
| 14 | + |
| 15 | +In this article, you'll learn how to create Healthcare APIs, including workspaces, FHIR services, DICOM services, and IoT connectors using Azure Bicep. You can view and download the Bicep scripts used in this article in [HealthcareAPIs samples](https://github.com/microsoft/healthcare-apis-samples/blob/main/src/templates/healthcareapis.bicep). |
| 16 | + |
| 17 | +## What is Azure Bicep |
| 18 | + |
| 19 | +Bicep is built on top of Azure Resource Manager (ARM) template. Bicep immediately supports all preview and generally available (GA) versions for Azure services, including Healthcare APIs. During development, you can generate a JSON ARM template file using the `az bicep build` command. Conversely, you can decompile the JSON files to Bicep using the `az bicep decompile` command. During deployment, the Bicep CLI converts a Bicep file into an ARM template JSON. |
| 20 | + |
| 21 | +You can continue to work with JSON ARM templates, or use Bicep to develop your ARM templates. For more information on Bicep, see [What is Bicep](../azure-resource-manager/bicep/overview.md). |
| 22 | + |
| 23 | +>[!Note] |
| 24 | +>The templates and scripts in the article are tested in Visual Studio Code during the public preview. Some changes may be necessary to adapt the code to run in your environment. |
| 25 | +
|
| 26 | +## Define parameters and variables |
| 27 | + |
| 28 | +Using Bicep parameters and variables instead of hard coding names and other values allows you to debug and reuse your Bicep templates. |
| 29 | + |
| 30 | +We first define parameters with the keyword *param* for workspace, FHIR service, DICOM service, IoT connector. Also, we define parameters for Azure subscription and Azure Active Directory (Azure AD) tenant. They’re used in the CLI command line with the "--parameters" option. |
| 31 | + |
| 32 | +We then define variables for resources with the keyword *var*. Also, we define variables for properties such as the authority and the audience for the FHIR service. They’re specified and used internally in the Bicep template, and can be used in combination of parameters, Bicep functions, and other variables. Unlike parameters, they aren’t used in the CLI command line. |
| 33 | + |
| 34 | +It's important to note that one Bicep function and environment(s) are required to specify the log in URL, `https://login.microsoftonline.com`. For more information on Bicep functions, see [Deployment functions for Bicep](../azure-resource-manager/bicep/bicep-functions-deployment.md#environment). |
| 35 | + |
| 36 | +``` |
| 37 | +param workspaceName string |
| 38 | +param fhirName string |
| 39 | +param dicomName string |
| 40 | +param iotName string |
| 41 | +param tenantId string |
| 42 | +
|
| 43 | +var fhirservicename = '${workspaceName}/${fhirName}' |
| 44 | +var dicomservicename = '${workspaceName}/${dicomName}' |
| 45 | +var iotconnectorname = '${workspaceName}/${iotName}' |
| 46 | +var iotdestinationname = '${iotconnectorname}/output1' |
| 47 | +var loginURL = environment().authentication.loginEndpoint |
| 48 | +var authority = '${loginURL}${tenantId}' |
| 49 | +var audience = 'https://${workspaceName}-${fhirName}.fhir.azurehealthcareapis.com' |
| 50 | +``` |
| 51 | + |
| 52 | +## Create a workspace template |
| 53 | + |
| 54 | +To define a resource, use the keyword *resource*. For the workspace resource, the required properties include the workspace name and location. In the template, the location of the resource group is used, but you can specify a different value for the location. For the resource name, you can reference the defined parameter or variable. |
| 55 | + |
| 56 | +For more information on resource and module, see [Resource declaration in Bicep](../azure-resource-manager/bicep/resource-declaration.md). |
| 57 | + |
| 58 | +``` |
| 59 | +//Create a workspace |
| 60 | +resource exampleWorkspace 'Microsoft.HealthcareApis/workspaces@2021-06-01-preview' = { |
| 61 | + name: workspaceName |
| 62 | + location: resourceGroup().location |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +To use or reference an existing workspace without creating one, use the keyword *existing*. Specify the workspace resource name, and the existing workspace instance name for the name property. Note that a different name for the existing workspace resource is used in the template, but that is not a requirement. |
| 67 | + |
| 68 | +``` |
| 69 | +//Use an existing workspace |
| 70 | +resource exampleExistingWorkspace 'Microsoft.HealthcareApis/workspaces@2021-06-01-preview' existing = { |
| 71 | + name: workspaceName |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +You're now ready to deploy the workspace resource using the `az deployment group create` command. You can also deploy it along with its other resources, as described further later in this article. |
| 76 | + |
| 77 | +## Create a FHIR service template |
| 78 | + |
| 79 | +For the FHIR service resource, the required properties include service instance name, location, kind, and managed identity. Also, it has a dependency on the workspace resource. For the FHIR service itself, the required properties include authority and audience, which are specified in the properties element. |
| 80 | + |
| 81 | +``` |
| 82 | +resource exampleFHIR 'Microsoft.HealthcareApis/workspaces/fhirservices@2021-06-01-preview' = { |
| 83 | + name: fhirservicename |
| 84 | + location: resourceGroup().location |
| 85 | + kind: 'fhir-R4' |
| 86 | + identity: { |
| 87 | + type: 'SystemAssigned' |
| 88 | + } |
| 89 | + dependsOn: [ |
| 90 | + exampleWorkspace |
| 91 | + //exampleExistingWorkspace |
| 92 | + ] |
| 93 | + properties: { |
| 94 | + accessPolicies: [] |
| 95 | + authenticationConfiguration: { |
| 96 | + authority: authority |
| 97 | + audience: audience |
| 98 | + smartProxyEnabled: false |
| 99 | + } |
| 100 | + } |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +Similarly, you can use or reference an existing FHIR service using the keyword *existing*. |
| 105 | + |
| 106 | +``` |
| 107 | +//Use an existing FHIR service |
| 108 | +resource exampleExistingFHIR 'Microsoft.HealthcareApis/workspaces/fhirservices@2021-06-01-preview' existing = { |
| 109 | + name: fhirservicename |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +## Create a DICOM service template |
| 114 | + |
| 115 | +For the DICOM service resource, the required properties include service instance name and location, and the dependency on the workspace resource type. |
| 116 | + |
| 117 | +``` |
| 118 | +//Create DICOM service |
| 119 | +resource exampleDICOM 'Microsoft.HealthcareApis/workspaces/dicomservices@2021-06-01-preview' = { |
| 120 | + name: dicomservicename |
| 121 | + location: resourceGroup().location |
| 122 | + dependsOn: [ |
| 123 | + exampleWorkspace |
| 124 | + ] |
| 125 | + properties: {} |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +Similarly, you can use or reference an existing DICOM service using the keyword *existing*. |
| 130 | + |
| 131 | +``` |
| 132 | +//Use an existing DICOM service |
| 133 | + resource exampleExistingDICOM 'Microsoft.HealthcareApis/workspaces/dicomservices@2021-06-01-preview' existing = { |
| 134 | + name: dicomservicename |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +## Create an IoT connector template |
| 139 | + |
| 140 | +For the IoT connector resource, the required properties include IoT connector name, location, managed identity, and the dependency on the workspace. For the IoT connector itself, required properties include Azure Event Hubs namespace, Event Hubs, Event Hubs consumer group, and the device mapping. As an example, the heart rate device mapping is used in the template. |
| 141 | + |
| 142 | +``` |
| 143 | +//Create IoT connector |
| 144 | +resource exampleIoT 'Microsoft.HealthcareApis/workspaces/iotconnectors@2021-06-01-preview' = { |
| 145 | + name: iotconnectorname |
| 146 | + location: resourceGroup().location |
| 147 | + identity: { |
| 148 | + type: 'SystemAssigned' |
| 149 | + } |
| 150 | + dependsOn: [ |
| 151 | + exampleWorkspace |
| 152 | + //exampleExistingWorkspace |
| 153 | + ] |
| 154 | + properties: { |
| 155 | + ingestionEndpointConfiguration: { |
| 156 | + eventHubName: 'eventhubnamexxx' |
| 157 | + consumerGroup: 'eventhubconsumergroupxxx' |
| 158 | + fullyQualifiedEventHubNamespace: 'eventhubnamespacexxx.servicebus.windows.net' |
| 159 | + } |
| 160 | + deviceMapping: { |
| 161 | + content: { |
| 162 | + templateType: 'CollectionContent' |
| 163 | + template: [ |
| 164 | + { |
| 165 | + templateType: 'JsonPathContent' |
| 166 | + template: { |
| 167 | + typeName: 'heartrate' |
| 168 | + typeMatchExpression: '$..[?(@heartrate)]' |
| 169 | + deviceIdExpression: '$.deviceid' |
| 170 | + timestampExpression: '$.measurementdatetime' |
| 171 | + values: [ |
| 172 | + { |
| 173 | + required: 'true' |
| 174 | + valueExpression: '$.heartrate' |
| 175 | + valueName: 'Heart rate' |
| 176 | + } |
| 177 | + ] |
| 178 | + } |
| 179 | + } |
| 180 | + ] |
| 181 | + } |
| 182 | + } |
| 183 | + } |
| 184 | + } |
| 185 | +``` |
| 186 | + |
| 187 | +Similarly, you can use, or reference an existing IoT connector using the keyword *existing*. |
| 188 | + |
| 189 | +``` |
| 190 | +//Use an existing IoT |
| 191 | +resource exampleExistingIoT 'Microsoft.HealthcareApis/workspaces/iotconnectors/fhirdestinations@2021-06-01-preview' existing = { |
| 192 | + name: iotconnectorname |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +The IoT connector requires a child resource, destination, and it currently supports the FHIR service destination only. For the IoT connector destination resource, the required properties include a name, location, and the dependency on the IoT connector. For the FHIR service destination, required properties include the resolution type, which it takes a value of *Create* or *Lookup*, the FHIR service resource ID, and a FHIR resource type. As an example, the heart rate mapping for the FHIR Observation resource is used in the template. |
| 197 | + |
| 198 | +``` |
| 199 | +//Create IoT destination |
| 200 | +resource exampleIoTDestination 'Microsoft.HealthcareApis/workspaces/iotconnectors/fhirdestinations@2021-06-01-preview' = { |
| 201 | + name: iotdestinationname |
| 202 | + location: resourceGroup().location |
| 203 | + dependsOn: [ |
| 204 | + exampleIoT |
| 205 | + //exampleExistingIoT |
| 206 | + ] |
| 207 | + properties: { |
| 208 | + resourceIdentityResolutionType: 'Create' |
| 209 | + fhirServiceResourceId: exampleFHIR.id //exampleExistingFHIR.id |
| 210 | + fhirMapping: { |
| 211 | + content: { |
| 212 | + templateType: 'CollectionFhirTemplate' |
| 213 | + template: [ |
| 214 | + { |
| 215 | + templateType: 'CodeValueFhir' |
| 216 | + template: { |
| 217 | + codes: [ |
| 218 | + { |
| 219 | + code: '8867-4' |
| 220 | + system: 'http://loinc.org' |
| 221 | + display: 'Heart rate' |
| 222 | + } |
| 223 | + ] |
| 224 | + periodInterval: 60 |
| 225 | + typeName: 'heartrate' |
| 226 | + value: { |
| 227 | + defaultPeriod: 5000 |
| 228 | + unit: 'count/min' |
| 229 | + valueName: 'hr' |
| 230 | + valueType: 'SampledData' |
| 231 | + } |
| 232 | + } |
| 233 | + } |
| 234 | + ] |
| 235 | + } |
| 236 | + } |
| 237 | + } |
| 238 | +} |
| 239 | +``` |
| 240 | + |
| 241 | +## Deploy Healthcare APIs |
| 242 | + |
| 243 | +You can use the `az deployment group create` command to deploy individual Bicep template or combined templates, similar to the way you deploy Azure resources with JSON templates. Specify the resource group name, and include the parameters in the command line. With the "--parameters" option, specify the parameter and value pair as "parameter = value", and separate the parameter and value pairs by a space if more than one parameter is defined. |
| 244 | + |
| 245 | +For the Azure subscription and tenant, you can specify the values, or use CLI commands to obtain them from the current sign-in session. |
| 246 | + |
| 247 | +``` |
| 248 | +resourcegroupname=xxx |
| 249 | +location=e.g. eastus2 |
| 250 | +workspacename=xxx |
| 251 | +fhirname=xxx |
| 252 | +dicomname=xxx |
| 253 | +iotname=xxx |
| 254 | +bicepfilename=xxx.bicep |
| 255 | +#tenantid=xxx |
| 256 | +#subscriptionid=xxx |
| 257 | +subscriptionid=$(az account show --query id --output tsv) |
| 258 | +tenantid=$(az account show --subscription $subscriptionid --query tenantId --output tsv) |
| 259 | +
|
| 260 | +az deployment group create --resource-group $resourcegroupname --template-file $bicepfilename --parameters workspaceName=$workspacename fhirName=$fhirname dicomName=$dicomname iotName=$iotname tenantId=$tenantid |
| 261 | +``` |
| 262 | + |
| 263 | +Note that the child resource name such as the FHIR service includes the parent resource name, and the "dependsOn" property is required. However, when the child resource is created within the parent resource, its name does not need to include the parent resource name, and the "dependsOn" property is not required. For more info on nested resources, see [Set name and type for child resources in Bicep](../azure-resource-manager/bicep/child-resource-name-type.md). |
| 264 | + |
| 265 | +## Debugging Bicep templates |
| 266 | + |
| 267 | +You can debug Bicep templates in Visual Studio Code, or in other environments and troubleshoot issues based on the response. Also, you can review the activity log for a specific resource in the resource group while debugging. |
| 268 | + |
| 269 | +In addition, you can use the **output** value for debugging or as part of the deployment response. For example, you can define two output values to display the values of authority and audience for the FHIR service in the response. For more information, see [Outputs in Bicep](../azure-resource-manager/bicep/outputs.md). |
| 270 | + |
| 271 | +``` |
| 272 | +output stringOutput1 string = authority |
| 273 | +output stringOutput2 string = audience |
| 274 | +``` |
| 275 | + |
| 276 | +## Next steps |
| 277 | + |
| 278 | +In this article, you learned how to create Healthcare APIs, including workspaces, FHIR services, DICOM services, and IoT connectors using Bicep. You also learned how to create and debug Bicep templates. For more information about Healthcare APIs, see |
| 279 | + |
| 280 | +>[!div class="nextstepaction"] |
| 281 | +>[What is Azure Healthcare APIs](healthcare-apis-overview.md) |
0 commit comments