diff --git a/Modules/CognitiveServices/2.0/Pipeline/cognitive.services.azuredevops.ci.yaml b/Modules/CognitiveServices/2.0/Pipeline/cognitive.services.azuredevops.ci.yaml new file mode 100644 index 0000000..0bbc119 --- /dev/null +++ b/Modules/CognitiveServices/2.0/Pipeline/cognitive.services.azuredevops.ci.yaml @@ -0,0 +1,35 @@ +name: $(Build.DefinitionName)-$(SourceBranchName)-$(Date:yyyyMMdd).$(Rev:rr) + +variables: + ModuleName: CognitiveServices + ModuleVersion: 2.0 + RepoName: azure-devops + ModulePath: modules/$(ModuleName)/$(ModuleVersion) + ArtifactName: contents + +resources: + repositories: + - repository: main + type: git + name: '$(RepoName)' + +trigger: + branches: + include: + - master + - '*' + paths: + include: + - modules/CognitiveServices/2.0 + +jobs: +- job: BuildModule + displayName: Build Module + workspace: + clean: all + + steps: + - template: /azure-devops/ci/buildmodule.yaml + parameters: + ModulePath: $(ModulePath) + ArtifactName: $(ArtifactName) \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/Pipeline/git_placeholder.md b/Modules/CognitiveServices/2.0/Pipeline/git_placeholder.md deleted file mode 100644 index e69de29..0000000 diff --git a/Modules/CognitiveServices/2.0/Scripts/cognitive.services.akv.secrects.ps1 b/Modules/CognitiveServices/2.0/Scripts/cognitive.services.akv.secrects.ps1 new file mode 100644 index 0000000..46e3f84 --- /dev/null +++ b/Modules/CognitiveServices/2.0/Scripts/cognitive.services.akv.secrects.ps1 @@ -0,0 +1,136 @@ +<# + .NOTES + ============================================================================================== + Copyright(c) Microsoft Corporation. All rights reserved. + + Microsoft Consulting Services - AzureCAT - VDC Toolkit (v2.0) + + File: cognitive.services.akv.secrects.ps1 + + Purpose: Set Cognitive Services Secrets Automation Script + + Version: 2.0.0.0 - 1st September 2019 - Azure Virtual Datacenter Development Team + ============================================================================================== + + .SYNOPSIS + Set Cognitive Services Key Vault Secrets Automation Script + + .DESCRIPTION + Set Cognitive Services Key Vault Secrets Automation Script + + Deployment steps of the script are outlined below. + 1) Set Azure KeyVault Parameters + 2) Set Cognitive Services Parameters + 3) Create Azure KeyVault Secret + + .PARAMETER keyVaultName + Specify the Azure KeyVault Name parameter. + + .PARAMETER cognitiveServicesName + Specify the Cognitive Services Name output parameter. + + .PARAMETER cognitiveServicesResourceId + Specify the Cognitive Services ResourceId output parameter. + + .PARAMETER cognitiveServicesResourceGroup + Specify the Cognitive Services ResourceGroup output parameter. + + .EXAMPLE + Default: + C:\PS>.\analysis.services.akv.secrects.ps1 + -keyVaultName "$(keyVaultName)" + -cognitiveServicesName "$(cognitiveServicesName)" + -cognitiveServicesResourceId "$(cognitiveServicesResourceId)" + -cognitiveServicesResourceGroup "$(cognitiveServicesResourceGroup)" +#> + +#Requires -Version 5 +#Requires -Module Az.KeyVault + +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [string]$keyVaultName, + + [Parameter(Mandatory = $false)] + [string]$cognitiveServicesName, + + [Parameter(Mandatory = $false)] + [string]$cognitiveServicesResourceId, + + [Parameter(Mandatory = $false)] + [string]$cognitiveServicesResourceGroup +) + +#region - Key Vault Parameters +if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['keyVaultName'])) +{ + Write-Output "KeyVault Name: $keyVaultName" + $kVSecretParameters = @{ } + + #region - Cognitive Services Parameters + if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['cognitiveServicesName'])) + { + Write-Output "Cognitive Services Name : $cognitiveServicesName" + $kVSecretParameters.Add("cognitiveServices--Name", $($cognitiveServicesName)) + } + else + { + Write-Output "Cognitive Services Name: []" + } + + if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['cognitiveServicesResourceId'])) + { + Write-Output "cognitiveServices ResourceId : $cognitiveServicesResourceId" + $kVSecretParameters.Add("cognitiveServices--ResourceId", $($cognitiveServicesResourceId)) + } + else + { + Write-Output "Cognitive Services ResourceId: []" + } + + if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['cognitiveServicesResourceGroup'])) + { + Write-Output "Cognitive Services ResourceGroup : $cognitiveServicesResourceGroup" + $kVSecretParameters.Add("cognitiveServices--ResourceGroup", $($cognitiveServicesResourceGroup)) + } + else + { + Write-Output "Cognitive Services ResourceGroup: []" + } + #endregion + + #region - Set Azure KeyVault Secret + $kVSecretParameters.Keys | ForEach-Object { + $key = $psitem + $value = $kVSecretParameters.Item($psitem) + + if (-not [string]::IsNullOrWhiteSpace($value)) + { + Write-Output "Key Vault Secret: $key : $value" + + $value = $kVSecretParameters.Item($psitem) + + Write-Output "Setting Secret for $key" + $paramSetAzKeyVaultSecret = @{ + VaultName = $keyVaultName + Name = $key + SecretValue = (ConvertTo-SecureString $value -AsPlainText -Force) + Verbose = $true + ErrorAction = 'SilentlyContinue' + } + Set-AzKeyVaultSecret @paramSetAzKeyVaultSecret + } + else + { + Write-Output "KeyVault Secret: []" + } + } + #endregion +} +else +{ + Write-Output "KeyVault Name: []" +} +#endregion \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/Scripts/git_placeholder.md b/Modules/CognitiveServices/2.0/Scripts/git_placeholder.md deleted file mode 100644 index e69de29..0000000 diff --git a/Modules/CognitiveServices/2.0/Tests/git_placeholder.md b/Modules/CognitiveServices/2.0/Tests/git_placeholder.md deleted file mode 100644 index e69de29..0000000 diff --git a/Modules/CognitiveServices/2.0/Tests/module.tests.ps1 b/Modules/CognitiveServices/2.0/Tests/module.tests.ps1 new file mode 100644 index 0000000..fdcdc65 --- /dev/null +++ b/Modules/CognitiveServices/2.0/Tests/module.tests.ps1 @@ -0,0 +1,171 @@ +<# + .NOTES + ============================================================================================== + Copyright(c) Microsoft Corporation. All rights reserved. + + Microsoft Consulting Services - AzureCAT - VDC Toolkit (v2.0) + + File: module.tests.ps1 + + Purpose: Pester - Test Application Insights ARM Templates + + Version: 2.0.0.0 - 1st September 2019 - Azure Virtual Datacenter Development Team + ============================================================================================== + + .SYNOPSIS + This script contains functionality used to test Cognitive Services ARM template synatax. + + .DESCRIPTION + This script contains functionality used to test Cognitive Services ARM template synatax. + + Deployment steps of the script are outlined below. + 1) Test Template File Syntax + 2) Test Parameter File Syntax + 3) Test Template and Parameter File Compactibility +#> + +#Requires -Version 5 + +#region Parameters +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +$here = Join-Path -Path $here -ChildPath ".." +$template = Split-Path -Leaf $here + +#region - Template File Test Cases +$templateFileTestCases = @() +ForEach ($file in (Get-ChildItem (Join-Path -Path "$here" -ChildPath "deploy.json") -Recurse | Select-Object -ExpandProperty Name)) { + $templateFileTestCases += @{ TemplateFile = $file } +} +#endregion + +#region - Parameter File Test Cases +$parameterFileTestCases = @() +ForEach ($file in (Get-ChildItem (Join-Path -Path "$here" -ChildPath "Tests" -AdditionalChildPath @("*parameters.json")) -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name)) { + $parameterFileTestCases += @{ ParameterFile = Join-Path -Path "Tests" $file } +} +#endregion + +#region - Module Test Cases +$modules = @() +ForEach ($file in (Get-ChildItem (Join-Path -Path "$here" -ChildPath "deploy.json"))) { + $module = [PSCustomObject]@{ + 'Template' = $null + 'Parameters' = $null + } + $module.Template = $file.FullName + + $parameters = @() + ForEach ($parameterFile in (Get-ChildItem (Join-Path -Path "$here" -ChildPath "Tests" -AdditionalChildPath @("*parameters.json")) -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name)) { + $parameters += (Join-Path -Path "$here" -ChildPath "Tests" -AdditionalChildPath @("$ParameterFile")) + } + $Module.Parameters = $Parameters + $Modules += @{Module = $Module} +} +#endregion + +#endregion + +#region - Run Pester Test Script +Describe "Template: $template - Cognitive Services" -Tags -Unit { + + #region - Template File Syntax + Context "Template File Syntax" { + + It "Has a JSON template file" { + (Join-Path -Path "$here" -ChildPath "deploy.json") | Should -Exist + } + + It "Converts from JSON and has the expected properties" -TestCases $templateFileTestCases { + param($templateFile) + $expectedProperties = '$schema', + 'contentVersion', + 'parameters', + 'variables', + 'resources', + 'outputs' | Sort-Object + $templateProperties = (Get-Content (Join-Path -Path "$here" -ChildPath "$templateFile") ` + | ConvertFrom-Json -ErrorAction SilentlyContinue) ` + | Get-Member -MemberType NoteProperty ` + | Sort-Object -Property Name ` + | ForEach-Object Name + $templateProperties | Should -Be $expectedProperties + } + } + #endregion + + #region - Parameter File Syntax + Context "Parameter File Syntax" { + + It "Parameter file does not contains the expected properties" -TestCases $parameterFileTestCases { + param($parameterFile) + $expectedProperties = '$schema', + 'contentVersion', + 'parameters' | Sort-Object + Write-Output $parameterFile + Join-Path -Path "$here" -ChildPath "$parameterFile" | Write-Output + $templateFileProperties = (Get-Content (Join-Path -Path "$here" -ChildPath "$parameterFile") ` + | ConvertFrom-Json -ErrorAction SilentlyContinue) ` + | Get-Member -MemberType NoteProperty ` + | Sort-Object -Property Name ` + | ForEach-Object Name + $templateFileProperties | Should -Be $expectedProperties + } + } + #endregion + + #region - Template and Parameter Compactibility + Context "Template and Parameter Compactibility" { + + It "Is count of required parameters in template file equal or lesser than count of all parameters in parameters file" -TestCases $modules { + param($module) + $requiredParametersInTemplateFile = (Get-Content "$($module.Template)" ` + | ConvertFrom-Json -ErrorAction SilentlyContinue).Parameters.PSObject.Properties ` + | Where-Object -FilterScript { -not ($psitem.Value.PSObject.Properties.Name -eq "defaultValue")} ` + | Sort-Object -Property Name ` + | ForEach-Object Name + ForEach ( $parameter in $module.Parameters ) { + $allParametersInParametersFile = (Get-Content $parameter ` + | ConvertFrom-Json -ErrorAction SilentlyContinue).Parameters.PSObject.Properties ` + | Sort-Object -Property Name ` + | ForEach-Object Name + $requiredParametersInTemplateFile.Count | Should -Not -BeGreaterThan $allParametersInParametersFile.Count + } + } + + It "Has all parameters in parameters file existing in template file" -TestCases $modules { + param($module) + $allParametersInTemplateFile = (Get-Content "$($module.Template)" ` + | ConvertFrom-Json -ErrorAction SilentlyContinue).Parameters.PSObject.Properties ` + | Sort-Object -Property Name ` + | ForEach-Object Name + ForEach ($parameter in $module.Parameters) { + Write-Output "File analyzed: $parameter" + $allParametersInParametersFile = (Get-Content $parameter ` + | ConvertFrom-Json -ErrorAction SilentlyContinue).Parameters.PSObject.Properties ` + | Sort-Object -Property Name ` + | ForEach-Object Name + $result = @($allParametersInParametersFile| Where-Object {$allParametersInTemplateFile -notcontains $psitem}) + Write-Output "Invalid parameters: $(ConvertTo-Json $result)" + @($allParametersInParametersFile| Where-Object {$allParametersInTemplateFile -notcontains $psitem}).Count | Should -Be 0 + } + } + + It "Has required parameters in template file existing in parameters file" -TestCases $modules { + param($module) + $requiredParametersInTemplateFile = (Get-Content "$($module.Template)" ` + | ConvertFrom-Json -ErrorAction SilentlyContinue).Parameters.PSObject.Properties ` + | Where-Object -FilterScript { -not ($psitem.Value.PSObject.Properties.Name -eq "defaultValue") } ` + | Sort-Object -Property Name ` + | ForEach-Object Name + ForEach ($parameter in $module.Parameters ) { + $allParametersInParametersFile = (Get-Content $parameter ` + | ConvertFrom-Json -ErrorAction SilentlyContinue).Parameters.PSObject.Properties ` + | Sort-Object -Property Name ` + | ForEach-Object Name + @($requiredParametersInTemplateFile| Where-Object {$allParametersInParametersFile -notcontains $psitem}).Count | Should -Be 0 + } + } + } + #endregion +} +#endregion \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/Tests/output.tests.ps1 b/Modules/CognitiveServices/2.0/Tests/output.tests.ps1 new file mode 100644 index 0000000..8d64aba --- /dev/null +++ b/Modules/CognitiveServices/2.0/Tests/output.tests.ps1 @@ -0,0 +1,81 @@ +<# + .NOTES + ============================================================================================== + Copyright(c) Microsoft Corporation. All rights reserved. + + Microsoft Consulting Services - AzureCAT - VDC Toolkit (v2.0) + + File: output.tests.ps1 + + Purpose: Test - Cognitive Services ARM Template Output Variables + + Version: 2.0.0.0 - 1st September 2019 - Azure Virtual Datacenter Development Team + ============================================================================================== + + .SYNOPSIS + This script contains functionality used to test Cognitive Services ARM Templates output variables. + + .DESCRIPTION + This script contains functionality used to test Cognitive Services ARM Templates output variables. + + Deployment steps of the script are outlined below. + 1) Outputs Variable Logic from pipeline + + .PARAMETER cognitiveServicesName + Specify the Cognitive Services Name output parameter. + + .PARAMETER cognitiveServicesResourceId + Specify the Cognitive Services ResourceId output parameter. + + .PARAMETER cognitiveServicesResourceGroup + Specify the Cognitive Services ResourceGroup output parameter. + + .EXAMPLE + Default: + C:\PS>.\output.tests.ps1 + -cognitiveServicesName "$(cognitiveServicesName)" + -cognitiveServicesResourceId "$(cognitiveServicesResourceId)" + -cognitiveServicesResourceGroup "$(cognitiveServicesResourceGroup)" +#> + +#Requires -Version 5 + +[CmdletBinding()] +param +( + [Parameter(Mandatory = $false)] + [string]$cognitiveServicesName, + + [Parameter(Mandatory = $false)] + [string]$cognitiveServicesResourceId, + + [Parameter(Mandatory = $false)] + [string]$cognitiveServicesResourceGroup +) + +if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['cognitiveServicesName'])) +{ + Write-Output "Cognitive Services Name: $($cognitiveServicesName)" +} +else +{ + Write-Output "Cognitive Services Name: []" +} + +if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['cognitiveServicesResourceId'])) +{ + Write-Output "Cognitive Services ResourceId: $($cognitiveServicesResourceId)" +} +else +{ + Write-Output "Cognitive Services ResourceId: []" +} + +if (-not [string]::IsNullOrWhiteSpace($PSBoundParameters['cognitiveServicesResourceGroup'])) +{ + Write-Output "Cognitive Services Resource Group: $($cognitiveServicesResourceGroup)" +} +else +{ + Write-Output "Cognitive Services Resource Group: []" +} \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/cognitive.services.parameters.json b/Modules/CognitiveServices/2.0/Tests/test.parameters.json similarity index 71% rename from Modules/CognitiveServices/2.0/cognitive.services.parameters.json rename to Modules/CognitiveServices/2.0/Tests/test.parameters.json index 9c313f0..ed43246 100644 --- a/Modules/CognitiveServices/2.0/cognitive.services.parameters.json +++ b/Modules/CognitiveServices/2.0/Tests/test.parameters.json @@ -2,5 +2,8 @@ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { + "accountName": { + "value": "testaccountName" + } } } \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/_README.md b/Modules/CognitiveServices/2.0/_README.md deleted file mode 100644 index 2454927..0000000 --- a/Modules/CognitiveServices/2.0/_README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Cognitve Services - -This template deploys an Cognitve Services Translation API. - -https://docs.microsoft.com/en-us/azure/templates/microsoft.cognitiveservices/allversions - - -## Resources - -The following Resources are deployed. - -+ **Cognitive Services** : Accounts - - -## Parameters - -+ **accountName** - Display name of Text Translation API account -+ **sku** - SKU for TextTranslation API -+ **location** - Location for all resources - - -## Outputs - -There is no Outputs in this module - - -## Scripts - -There is no Scripts in this module \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/cognitive.services.deploy.json b/Modules/CognitiveServices/2.0/cognitive.services.deploy.json deleted file mode 100644 index 3517ed6..0000000 --- a/Modules/CognitiveServices/2.0/cognitive.services.deploy.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "accountName": { - "type": "string", - "defaultValue": "translate", - "metadata": { - "description": "Display name of Text Translation API account" - } - }, - "sku": { - "type": "string", - "allowedValues": [ - "F0", - "S1", - "S2", - "S3", - "S4" - ], - "defaultValue": "F0", - "metadata": { - "description": "SKU for TextTranslation API" - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Location for all resources" - } - } - }, - "variables": {}, - "resources": [ - { - "type": "Microsoft.CognitiveServices/accounts", - "apiVersion": "2017-04-18", - "name": "[parameters('accountName')]", - "location": "[parameters('location')]", - "kind": "TextTranslation", - "properties": {}, - "sku": { - "name": "[parameters('sku')]" - } - } - ], - "outputs": {} -} \ No newline at end of file diff --git a/Modules/CognitiveServices/2.0/deploy.json b/Modules/CognitiveServices/2.0/deploy.json new file mode 100644 index 0000000..9f585b1 --- /dev/null +++ b/Modules/CognitiveServices/2.0/deploy.json @@ -0,0 +1,130 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "accountName": { + "type": "string", + "metadata": { + "description": "Required. The name of Text Translation API account" + } + }, + "sku": { + "type": "string", + "defaultValue": "S0", + "metadata": { + "description": "Optional. sku for Text Translation API" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the Azure Analysis Services server" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution id (GUID). This GUID must be previously registered" + } + }, + "tagEnvironment": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Environment" + } + }, + "tagProject": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the project" + } + }, + "tagApplication": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The name of the application" + } + }, + "tagOwner": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The business owner for the application" + } + }, + "tagOwnerEmail": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The Email address of the business owner for the application" + } + } + }, + "variables": { + "cognitiveServicesName": "[parameters('accountName')]", + "cognitiveServicesResourceId": "[resourceId('Microsoft.CognitiveServices/accounts',parameters('accountName'))]", + "pidName": "[concat('pid-', parameters('cuaId'))]" + }, + "resources": [ + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2018-02-01", + "name": "[variables('pidName')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.CognitiveServices/accounts", + "apiVersion": "2017-04-18", + "name": "[parameters('accountName')]", + "kind": "TextTranslation", + "location": "[parameters('location')]", + "tags": { + "Environment": "[parameters('tagEnvironment')]", + "Application": "[parameters('tagApplication')]", + "Project": "[parameters('tagProject')]", + "Owner": "[parameters('tagOwner')]", + "OwnerEmail": "[parameters('tagOwnerEmail')]" + }, + "sku": { + "name": "[parameters('sku')]" + }, + "properties": {} + } + ], + "outputs": { + "cognitiveServicesName": { + "type": "string", + "value": "[variables('cognitiveServicesName')]", + "metadata": { + "description": "The Name of the Cognitive Services" + } + }, + "cognitiveServicesResourceId": { + "type": "string", + "value": "[variables('cognitiveServicesResourceId')]", + "metadata": { + "description": "The Resource Id of the Cognitive Services" + } + }, + "cognitiveServicesResourceGroup": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group with the Cognitive Services" + } + } + } +} diff --git a/Modules/CognitiveServices/2.0/readme.md b/Modules/CognitiveServices/2.0/readme.md new file mode 100644 index 0000000..1c7f1a6 --- /dev/null +++ b/Modules/CognitiveServices/2.0/readme.md @@ -0,0 +1,45 @@ +# Cognitve Services + +This module deploys Cognitve Services Translation API. + +## Resources + +The following Resources are deployed. + ++ **Microsoft.CognitiveServices/accounts** + +## Parameters + +| Parameter Name | Default Value | Required | Description | +| :- | :- | :- |:- | +| `accountName` || **Required** |The name of Text Translation API account +| `sku` | S0| **Optional** | sku for Text Translation API +| `location` || **Optional** | Location of the Azure Analysis Services server +| `cuaId` || **Optional** | Customer Usage Attribution Id (GUID). This GUID must be previously registered +| `tagEnvironment` || **Optional** | The name of the Environment +| `tagProject` || **Optional** | The name of the project +| `tagApplication` || **Optional** | The name of the application +| `tagOwner` || **Optional** | The business owner for the application +| `tagOwnerEmail` || **Optional** | The Email address of the business owner for the application + +## Outputs + +| Output Name | Description | +| :- | :- | +| `cognitiveServicesName` | Cognitive Services Name output parameter +| `cognitiveServicesResourceId` | Cognitive Services ResourceId output parameter +| `cognitiveServicesResourceGroup` | Cognitive Services ResourceGroup output parameter + +## Scripts + +| Script Name | Description | +| :- | :- | +| `cognitive.services.akv.secrects.ps1` | Set Cognitive Services KeyVault Secrets Automation Script + +## Considerations + ++ There is no deployment considerations for this Module + +## Additional resources + +[Microsoft Cognitve Services template reference](https://docs.microsoft.com/en-us/azure/templates/microsoft.cognitiveservices/allversions)