Упражнение. Добавление этапа тестирования в конвейер
Команда обеспечения безопасности компании по продаже игрушек попросила вас убедиться в том, что веб-сайт доступен только по протоколу HTTPS. В этом упражнении вы настроите конвейер для выполнения теста дыма, который проверяет требование команды безопасности.
В процессе вы:
- Добавьте в репозиторий сценарий теста.
- Обновите определение конвейера и добавьте этап тестирования.
- Запустите конвейер и понаблюдайте за сбоем теста.
- Исправьте файл Bicep и понаблюдайте за успешным выполнением конвейера.
Добавление сценария теста
Здесь вы добавите тестовый скрипт, чтобы убедиться, что веб-сайт доступен при использовании HTTPS и недоступен при использовании небезопасного протокола HTTP.
В Visual Studio Code создайте новый файл Website.Tests.ps1 в папке deploy.
Вставьте в файл приведенный ниже тестовый код.
param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $HostName ) Describe 'Toy Website' { It 'Serves pages over HTTPS' { $request = [System.Net.WebRequest]::Create("https://$HostName/") $request.AllowAutoRedirect = $false $request.GetResponse().StatusCode | Should -Be 200 -Because "the website requires HTTPS" } It 'Does not serves pages over HTTP' { $request = [System.Net.WebRequest]::Create("http://$HostName/") $request.AllowAutoRedirect = $false $request.GetResponse().StatusCode | Should -BeGreaterOrEqual 300 -Because "HTTP is not secure" } }
Этот код представляет собой тестовый файл Pester. Для этого требуется параметр с именем
$HostName
. Он выполняет два теста для имени узла:- Попробуйте подключиться к веб-сайту по протоколу HTTPS. Тест считается пройденным, если сервер возвращает код состояния HTTP-ответа в диапазоне от 200 до 299, что говорит об успешном подключении.
- Попробуйте подключиться к веб-сайту по протоколу HTTP. Тест считается пройденным, если сервер возвращает код состояния HTTP-ответа от 300.
Для целей этого упражнения необязательно полностью понимать тестовый файл и принцип его работы. Мы предоставим ссылки в сводке, чтобы узнать больше, если вы хотите.
Публикация выходных данных файла Bicep в качестве выходной переменной этапа
Сценарий теста, созданный на предыдущих шагах, требует имя узла для проверки. Файл Bicep уже содержит выходные данные, однако прежде чем использовать его в тестах проверки сборки, необходимо опубликовать его в качестве выходной переменной этапа.
В Visual Studio Code откройте файл azure-pipelines.yml в папке deploy.
На этапе развертывания обновите шаг развертывания, чтобы передать выходные данные в переменную:
- task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: $(ServiceConnectionName) deploymentName: $(Build.BuildNumber) location: $(deploymentDefaultLocation) resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) deploymentOutputs: deploymentOutputs
Теперь процесс развертывания использует ту же задачу, что и раньше, но все выходные данные развертываний сохраняются в переменной конвейера с именем
deploymentOutputs
. Выходная переменная создается в формате JSON.Чтобы преобразовать выходные данные из формата JSON в переменные конвейера, добавьте следующий шаг скрипта под шагом развертывания:
- bash: | echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
Если развертывание завершается успешно, скрипт получает доступ к значению выходных данных каждого развертывания Bicep. Скрипт использует
jq
средство для доступа к соответствующей части выходных данных JSON. Затем значение публикуется в выходной переменной этапа с тем же именем, что и выходные данные развертывания Bicep.Примечание.
Pester и JQ предварительно установлены на агентах Microsoft для Azure Pipelines. Для их использования в шаге скрипта ничего делать не нужно.
Сохраните файл.
Добавление этапа тестирования состояния в конвейер
Теперь можно добавить этап тестирования состояния, на котором выполняются тесты.
В нижней части файла добавьте следующее определение этапа тестирования состояния.
- stage: SmokeTest jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ]
Этот код определяет этап и задание. Он также создает переменную в задании с именем
appServiceAppHostName
. Эта переменная принимает значение из выходной переменной, созданной в предыдущем разделе.В нижней части файла добавьте следующее определение шага на этапе тестирования состояния.
steps: - task: PowerShell@2 name: RunSmokeTests displayName: Run smoke tests inputs: targetType: inline script: | $container = New-PesterContainer ` -Path 'deploy/Website.Tests.ps1' ` -Data @{ HostName = '$(appServiceAppHostName)' } Invoke-Pester ` -Container $container ` -CI
На этом шаге выполняется сценарий PowerShell для тестирования сценария, написанного ранее, с помощью средства тестирования Pester.
В нижней части файла добавьте следующее определение шага на этапе тестирования состояния.
- task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
Этот шаг принимает файл результатов теста, который создает Pester, и публикует его как результаты теста конвейера. Вы увидите, как отображаются результаты в ближайшее время.
Обратите внимание, что определение шага включает
condition: always()
. Это условие означает, что Azure Pipelines должен всегда публиковать результаты теста, даже если на предыдущем шаге произошел сбой. Это условие важно, так как любой неудачный тест приведет к сбою тестового шага, и обычно конвейер останавливается после сбоя.Сохраните файл.
Проверка и фиксация определения конвейера
Убедитесь, что файл azure-pipelines.yml соответствует следующему коду:
trigger: batch: true branches: include: - main pool: vmImage: ubuntu-latest variables: - name: deploymentDefaultLocation value: westus3 stages: - stage: Lint jobs: - job: LintCode displayName: Lint code steps: - script: | az bicep build --file deploy/main.bicep name: LintBicepCode displayName: Run Bicep linter - stage: Validate jobs: - job: ValidateBicepCode displayName: Validate Bicep code steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: $(ServiceConnectionName) location: $(deploymentDefaultLocation) deploymentMode: Validation resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) - stage: Preview jobs: - job: PreviewAzureChanges displayName: Preview Azure changes steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: $(ServiceConnectionName) scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group $(ResourceGroupName) \ --template-file deploy/main.bicep \ --parameters environmentType=$(EnvironmentType) - stage: Deploy jobs: - deployment: DeployWebsite displayName: Deploy website environment: Website strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: $(ServiceConnectionName) deploymentName: $(Build.BuildNumber) location: $(deploymentDefaultLocation) resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs) - stage: SmokeTest jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ] steps: - task: PowerShell@2 name: RunSmokeTests displayName: Run smoke tests inputs: targetType: inline script: | $container = New-PesterContainer ` -Path 'deploy/Website.Tests.ps1' ` -Data @{ HostName = '$(appServiceAppHostName)' } Invoke-Pester ` -Container $container ` -CI - task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
Если нет, обновите его в соответствии с этим примером, а затем сохраните.
Зафиксируйте и отправьте изменения в репозиторий Git, выполнив следующие команды в терминале Visual Studio Code:
git add . git commit -m "Add test stage" git push
Запуск конвейера и проверка результата теста
В браузере перейдите к конвейеру.
Выберите последнее выполнение конвейера.
Подождите, пока конвейер завершит этапы анализа кода, проверки и предварительного просмотра. Хотя Azure Pipelines автоматически обновляет страницу с учетом последнего состояния, рекомендуется периодически обновлять страницу.
Нажмите кнопку Обзор и выберите Утвердить.
Дождитесь завершения выполнения конвейера.
Обратите внимание, что этап развертывания успешно завершен. Этап тестирования состояния завершается ошибкой.
Перейдите на вкладку Тесты.
Обратите внимание, что в сводке теста показано, что выполнены два теста. Один из них завершился с ошибкой, другой — успешно. У непройденного теста есть примечание: Toy Website. Не обслуживает страницы по HTTP.
Это означает, что веб-сайт был неправильно настроен и не отвечает требованиям вашей группы безопасности.
Обновление файла Bicep
Теперь, когда вы узнали, что определение Bicep не соответствует требованиям группы безопасности, вы исправите его.
В Visual Studio Code откройте файл main.bicep в папке deploy.
Найдите определение для приложения Службы приложений Azure и обновите его, включив свойство
httpsOnly
в областьproperties
:resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = { name: appServiceAppName location: location properties: { serverFarmId: appServicePlan.id httpsOnly: true siteConfig: { appSettings: [ { name: 'APPINSIGHTS_INSTRUMENTATIONKEY' value: applicationInsights.properties.InstrumentationKey } { name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' value: applicationInsights.properties.ConnectionString } ] } } }
Сохраните файл.
Зафиксируйте и отправьте изменения в репозиторий Git, выполнив следующие команды в терминале Visual Studio Code:
git add . git commit -m "Configure HTTPS on website" git push
Повторный запуск конвейера
В браузере перейдите к конвейеру.
Выберите последний запуск.
Подождите, пока конвейер завершит этапы анализа кода, проверки и предварительного просмотра. Хотя Azure Pipelines автоматически обновляет страницу с учетом последнего состояния, рекомендуется периодически обновлять страницу.
Выберите этап предварительной версии и снова просмотрите результаты "что если".
Обратите внимание, что команда "что, если" обнаружила изменение в значении свойства
httpsOnly
:Resource and property changes are indicated with these symbols: + Create ~ Modify = Nochange The deployment will update the following scope: Scope: /subscriptions/f0750bbe-ea75-4ae5-b24d-a92ca601da2c/resourceGroups/ToyWebsiteTest ~ Microsoft.Web/sites/toy-website-nbfnedv766snk [2021-01-15] + properties.siteConfig.localMySqlEnabled: false + properties.siteConfig.netFrameworkVersion: "v4.6" ~ properties.httpsOnly: false => true = Microsoft.Insights/components/toywebsite [2020-02-02] = Microsoft.Storage/storageAccounts/mystoragenbfnedv766snk [2021-04-01] = Microsoft.Web/serverfarms/toy-website [2021-01-15] Resource changes: 1 to modify, 3 no change.
Вернитесь к выполнению конвейера.
Нажмите кнопку "Рецензирование ", а затем нажмите кнопку "Утвердить".
Дождитесь завершения выполнения конвейера.
Обратите внимание, что весь конвейер завершается успешно, включая этап тестирования состояния. Это означает, что оба теста пройдены.
Очистка ресурсов
Теперь, когда вы завершили упражнение, можно удалить ресурсы, чтобы не оплачивать их.
В окне терминала Visual Studio Code выполните следующую команду:
az group delete --resource-group ToyWebsiteTest --yes --no-wait
Группа ресурсов удалится в фоновом режиме.
Remove-AzResourceGroup -Name ToyWebsiteTest -Force