From 4e654eef8cb3318d1774a2c42c77b9b3a5a4a5d9 Mon Sep 17 00:00:00 2001 From: Azad Abbasi Date: Thu, 11 Jun 2020 13:51:54 -0700 Subject: [PATCH] feat(tests): Add test infrastructure and setup.ps1 for local setup (#12719) * Add test infrastructure and setup --- .github/CODEOWNERS | 2 + sdk/iot/.gitignore | 4 + .../prerequisites/prerequisites.readme.md | 22 ++++ .../tests/prerequisites/setup.ps1 | 120 ++++++++++++++++++ sdk/iot/test-resources.json | 66 ++++++++++ sdk/iot/test.yml | 18 +++ 6 files changed, 232 insertions(+) create mode 100644 sdk/iot/.gitignore create mode 100644 sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/prerequisites.readme.md create mode 100644 sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/setup.ps1 create mode 100644 sdk/iot/test-resources.json create mode 100644 sdk/iot/test.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 446ee01e6af5..3ef9a89384da 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -32,6 +32,8 @@ /sdk/identity/ @schaabs +/sdk/iot/ @drwill-ms @timtay-microsoft @abhipsaMisra @vinagesh @azabbasi @prmathur-microsoft @bikamani @barustum + /sdk/keyvault/ @schaabs @heaths /sdk/search/ @brjohnstmsft @arv100kri @bleroy @tg-msft @heaths diff --git a/sdk/iot/.gitignore b/sdk/iot/.gitignore new file mode 100644 index 000000000000..419f8a9b81e4 --- /dev/null +++ b/sdk/iot/.gitignore @@ -0,0 +1,4 @@ +*.config.json +!*common.config.json +!*common.test.assets.config.json +*.etl diff --git a/sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/prerequisites.readme.md b/sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/prerequisites.readme.md new file mode 100644 index 000000000000..9a9f5a3e5f41 --- /dev/null +++ b/sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/prerequisites.readme.md @@ -0,0 +1,22 @@ +# Prerequisites + +## Install + +### 1. Install the latest Azure CLI package + +- If already installed, check latest version: + - Run `az --version` to make sure `azure-cli` is at least **version 2.0.8** + - If it isn't, update it +- Use this link to install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest]) + +### 2. Install the Iot extension + +- Open powershell window in admin mode. +- Run `az extension list` + - If you see azure-iot extension, update the extension by running `az extension update --name azure-iot` + - If you don't see the azure-iot extension, install it by running `az extension add --name azure-iot` +- See the top-level IoT commands with `az iot -h` + +## Maintenance + +In order to maintain the functionality of the Setup.ps1 file, make sure this document stays updated with all the required changes if you run/alter this script. diff --git a/sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/setup.ps1 b/sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/setup.ps1 new file mode 100644 index 000000000000..60ab7b7f98f4 --- /dev/null +++ b/sdk/iot/Azure.Iot.Hub.Service/tests/prerequisites/setup.ps1 @@ -0,0 +1,120 @@ +param( + [Parameter(Mandatory)] + [string] $Region, + + [Parameter(Mandatory)] + [string] $ResourceGroup, + + [Parameter(Mandatory)] + [string] $SubscriptionId, + + [Parameter()] + [string] $IotHubName, + + [Parameter()] + [string] $AppRegistrationName +) + +Function Connect-AzureSubscription() +{ + # Ensure the user is logged in + try + { + $azureContext = az account show + } + catch { } + + if (-not $azureContext) + { + Write-Host "`nPlease login to Azure..." + az login + $azureContext = az account show + } + + # Ensure the desired subscription is selected + $sub = az account show --output tsv --query id + if ($sub -ne $SubscriptionId) + { + Write-Host "`nSelecting subscription $SubscriptionId" + az account set --subscription $SubscriptionId + } + + return $azureContext +} + +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") +if (-not $isAdmin) +{ + throw "This script must be run in administrative mode." +} + +Connect-AzureSubscription + +$Region = $Region.Replace(' ', '') + +if (-not $IotHubName) +{ + $IotHubName = $ResourceGroup +} + +if (-not $AppRegistrationName) +{ + $AppRegistrationName = $ResourceGroup +} + +$appId = az ad app list --show-mine --query "[?displayName=='$AppRegistrationName'].appId" --output tsv +if (-not $appId) +{ + Write-Host "`nCreating App Registration $AppRegistrationName`n" + $appId = az ad app create --display-name $AppRegistrationName --native-app --query 'appId' --output tsv +} + +$spExists = az ad sp list --show-mine --query "[?appId=='$appId'].appId" --output tsv +if (-not $spExists) +{ + Write-Host "`nCreating service principal for app $appId`n" + az ad sp create --id $appId --output none +} + +$rgExists = az group exists --name $ResourceGroup +if ($rgExists -eq "False") +{ + Write-Host "`nCreating Resource Group $ResourceGroup in $Region`n" + az group create --name $ResourceGroup --location $Region --output none +} + +$hubExists = az iot hub list -g $ResourceGroup --query "[?name=='$IotHubName']" --output tsv --only-show-errors +if (-not $hubExists) +{ + Write-Host "`nCreating IoT Hub $IotHubName`n" + az iot hub create -n $IotHubName -g $ResourceGroup --location $Region --output none --only-show-errors +} +$iotHubHostName = az iot hub show -n $IotHubName -g $ResourceGroup --query 'properties.hostName' --output tsv --only-show-errors + +Write-Host("Set a new client secret for $appId`n") +$appSecret = az ad app credential reset --id $appId --years 2 --query 'password' --output tsv + +$user = $env:UserName +$fileName = "$user.config.json" +Write-Host("Writing user config file - $fileName`n") +$appSecretJsonEscaped = ConvertTo-Json $appSecret +$config = @" +{ + "IotHubHostName": "https://$($iotHubHostName)", + "ApplicationId": "$appId", + "ClientSecret": $appSecretJsonEscaped, + "TestMode": "Live" +} +"@ +$config | Out-File "$PSScriptRoot\..\config\$fileName" + +$userSettingsFileSuffix = ".test.assets.config.json" +$userSettingsFileName = "$user$userSettingsFileSuffix" +$userTestAssetSettingsFileName = "$PSScriptRoot\..\config\$userSettingsFileName" +if (-not (Test-Path $userTestAssetSettingsFileName)) +{ + Write-Host "Creating empty user test assets config file - $userSettingsFileName`n" + New-Item -ItemType File -Path $userTestAssetSettingsFileName -Value "{}" | Out-Null +} + +Write-Host "Done!" \ No newline at end of file diff --git a/sdk/iot/test-resources.json b/sdk/iot/test-resources.json new file mode 100644 index 000000000000..787bb9c589d9 --- /dev/null +++ b/sdk/iot/test-resources.json @@ -0,0 +1,66 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json", + "contentVersion": "1.0.0.0", + "parameters": { + "baseName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "The base resource name." + } + }, + "testApplicationOid": { + "type": "string", + "metadata": { + "description": "The client OID to grant access to test resources." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "The location of the resource. By default, this is the same as the resource group." + } + } + }, + "variables": { + "iotHubResourceId": "[resourceId('Microsoft.Devices/IotHubs', parameters('baseName'))]", + "rbacOwnerRoleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2018-09-01-preview", + "name": "[guid(resourceGroup().id)]", + "properties": { + "roleDefinitionId": "[variables('rbacOwnerRoleDefinitionId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Devices/IotHubs", + "apiVersion": "2020-03-01", + "name": "[parameters('baseName')]", + "location": "[parameters('location')]", + "sku": { + "name": "S1", + "capacity": 1 + }, + "properties": { + "eventHubEndpoints": { + "events": { + "retentionTimeInDays": 1, + "partitionCount": 4 + } + }, + "features": "None" + } + } + ], + "outputs": { + "IOT_HUB_ENDPOINT_URL": { + "type": "string", + "value": "[concat('https://', reference(variables('iotHubResourceId'), '2020-03-01').hostName)]" + } + } +} \ No newline at end of file diff --git a/sdk/iot/test.yml b/sdk/iot/test.yml new file mode 100644 index 000000000000..5ee546083eab --- /dev/null +++ b/sdk/iot/test.yml @@ -0,0 +1,18 @@ +trigger: none + +resources: + repositories: + - repository: azure-sdk-tools + type: github + name: Azure/azure-sdk-tools + endpoint: azure + +jobs: +- template: ../../eng/pipelines/templates/jobs/archetype-sdk-tests.yml + parameters: + ServiceDirectory: iot + Location: westcentralus + SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources-preview) + EnvVars: + # Runs live tests. + AZURE_IOT_TEST_MODE: Live \ No newline at end of file