From ea7b4bc51095b80e2ce16fa848d14f10d60845e1 Mon Sep 17 00:00:00 2001 From: heoelri Date: Thu, 20 Jul 2023 11:00:18 +0200 Subject: [PATCH] Update Azure Load Test ApiVersion (#984) * bump load test apiversion * Component updates (#983) * Bump hashicorp/azurerm in /src/infra/monitoring/grafana/terraform/stamps Bumps [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) from 3.58.0 to 3.59.0. - [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases) - [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-provider-azurerm/compare/v3.58.0...v3.59.0) --- updated-dependencies: - dependency-name: hashicorp/azurerm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump hashicorp/azurerm in /src/infra/workload/globalresources Bumps [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) from 3.55.0 to 3.59.0. - [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases) - [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-provider-azurerm/compare/v3.55.0...v3.59.0) --- updated-dependencies: - dependency-name: hashicorp/azurerm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump hashicorp/azurerm Bumps [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) from 3.55.0 to 3.59.0. - [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases) - [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-provider-azurerm/compare/v3.55.0...v3.59.0) --- updated-dependencies: - dependency-name: hashicorp/azurerm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump grafana/grafana in /src/infra/monitoring/grafana Bumps grafana/grafana from 9.5.1 to 9.5.3. --- updated-dependencies: - dependency-name: grafana/grafana dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump hashicorp/azurerm in /src/testing/userload-generator/infra Bumps [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) from 3.55.0 to 3.59.0. - [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases) - [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-provider-azurerm/compare/v3.55.0...v3.59.0) --- updated-dependencies: - dependency-name: hashicorp/azurerm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump hashicorp/azurerm in /src/testing/loadtest-locust/infra Bumps [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) from 3.55.0 to 3.59.0. - [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases) - [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-provider-azurerm/compare/v3.55.0...v3.59.0) --- updated-dependencies: - dependency-name: hashicorp/azurerm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump hashicorp/azurerm in /src/infra/workload/releaseunit Bumps [hashicorp/azurerm](https://github.com/hashicorp/terraform-provider-azurerm) from 3.55.0 to 3.59.0. - [Release notes](https://github.com/hashicorp/terraform-provider-azurerm/releases) - [Changelog](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/terraform-provider-azurerm/compare/v3.55.0...v3.59.0) --- updated-dependencies: - dependency-name: hashicorp/azurerm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * api changes * update api * move to native azurerm * tf update * fix url * more api updates * update * fixes * fix * fixes * no auto stop * fix * fix * fixes * no comp * fixes * updates * fix script * higher criteria * update tf cli * var location * wait for test result * tf down * tf down * or * eq * fix * component back * uncomment * stop timeout run * reset numbers * cleanup * multiregion * eastus2 * maybe norway * missing file * 1 instance * use httpclient * times fix * fix more * shorten * shorten another * update base * single --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastian --- .ado/pipelines/config/configuration.yaml | 8 +- .../config/loadtest-baseline-chaos.json | 60 ++++++------ .../config/loadtest-baseline-normal.json | 60 ++++++------ .../templates/stages-loadtest-azure.yaml | 91 ++++++++++++------- .../grafana/terraform/globalresources/main.tf | 2 +- .../grafana/terraform/stamps/main.tf | 2 +- src/infra/workload/globalresources/main.tf | 2 +- src/infra/workload/releaseunit/main.tf | 4 +- .../releaseunit/modules/stamp/main.tf | 4 +- src/testing/loadtest-azure/infra/main.tf | 40 ++------ .../scripts/appcomponents-add-to-loadtest.ps1 | 67 +++++++------- .../loadtest-azure/scripts/catalog-test.jmx | 3 +- .../scripts/file-upload-to-loadtest.ps1 | 30 +++--- .../loadtest-azure/scripts/file-verify.ps1 | 2 +- .../scripts/loadtest-create.ps1 | 22 ++++- .../scripts/loadtest-delete.ps1 | 4 +- .../scripts/loadtest-get-files.ps1 | 10 +- .../scripts/loadtest-get-results.ps1 | 4 +- .../scripts/loadtest-get-run.ps1 | 4 +- .../loadtest-azure/scripts/loadtest-run.ps1 | 19 +--- .../loadtest-azure/scripts/loadtest-stop.ps1 | 33 +++++++ .../loadtest-azure/scripts/loadtests-get.ps1 | 28 ------ src/testing/loadtest-locust/infra/main.tf | 2 +- src/testing/userload-generator/infra/main.tf | 2 +- 24 files changed, 245 insertions(+), 258 deletions(-) create mode 100644 src/testing/loadtest-azure/scripts/loadtest-stop.ps1 delete mode 100644 src/testing/loadtest-azure/scripts/loadtests-get.ps1 diff --git a/.ado/pipelines/config/configuration.yaml b/.ado/pipelines/config/configuration.yaml index 95b6031b9..45db73ebf 100644 --- a/.ado/pipelines/config/configuration.yaml +++ b/.ado/pipelines/config/configuration.yaml @@ -44,11 +44,11 @@ variables: # Microsoft Azure Load Test (MALT) configuration - name: 'azureLoadTestApiVersion' # data plane - value: '2022-06-01-preview' + value: '2023-04-01-preview' +- name: 'azureLoadTestLocation' + value: 'uksouth' - name: 'azureLoadTestEngineInstances' - value: 2 -- name: 'azureLoadTestVUsers' - value: 100 + value: 1 - name: 'azureLoadTestDurationSeconds' value: 660 - name: 'azureLoadTestUserThreads' diff --git a/.ado/pipelines/config/loadtest-baseline-chaos.json b/.ado/pipelines/config/loadtest-baseline-chaos.json index 76431045e..cf4362a48 100644 --- a/.ado/pipelines/config/loadtest-baseline-chaos.json +++ b/.ado/pipelines/config/loadtest-baseline-chaos.json @@ -1,36 +1,28 @@ -[ - { - "passFailMetrics": { - "ece127bc-6271-4a70-93f6-758c56a3f11c": { - "clientmetric": "requests_per_sec", - "aggregate": "avg", - "condition": "<", - "value": 1200.0, - "result": null, - "actualValue": 0.0, - "requestName": null, - "action": "continue" - }, - "ac6c5e62-647a-4a1a-b001-b961e384891f": { - "action": "continue", - "actualValue": 0.0, - "aggregate": "avg", - "clientmetric": "response_time_ms", - "condition": ">", - "requestName": null, - "result": null, - "value": 75.0 - }, - "a7ab8dec-07e6-4870-911c-4505382b8511": { - "action": "continue", - "actualValue": 0.0, - "aggregate": "percentage", - "clientmetric": "error", - "condition": ">", - "requestName": null, - "result": null, - "value": 50.0 - } +{ + "passFailMetrics": { + "ece127bc-6271-4a70-93f6-758c56a3f11c": { + "clientMetric": "requests_per_sec", + "aggregate": "avg", + "condition": "<", + "value": 1200.0, + "requestName": null, + "action": "continue" + }, + "ac6c5e62-647a-4a1a-b001-b961e384891f": { + "action": "continue", + "aggregate": "avg", + "clientMetric": "response_time_ms", + "condition": ">", + "requestName": null, + "value": 200.0 + }, + "a7ab8dec-07e6-4870-911c-4505382b8511": { + "action": "continue", + "aggregate": "percentage", + "clientMetric": "error", + "condition": ">", + "requestName": null, + "value": 50.0 } } -] +} \ No newline at end of file diff --git a/.ado/pipelines/config/loadtest-baseline-normal.json b/.ado/pipelines/config/loadtest-baseline-normal.json index 7af4518fd..ae16e5ab0 100644 --- a/.ado/pipelines/config/loadtest-baseline-normal.json +++ b/.ado/pipelines/config/loadtest-baseline-normal.json @@ -1,36 +1,28 @@ -[ - { - "passFailMetrics": { - "ece127bc-6271-4a70-93f6-758c56a3f12c": { - "clientmetric": "requests_per_sec", - "aggregate": "avg", - "condition": "<", - "value": 1200.0, - "result": null, - "actualValue": 0.0, - "requestName": null, - "action": "continue" - }, - "ac6c5e62-647a-4a1a-b001-b961e384892f": { - "action": "continue", - "actualValue": 0.0, - "aggregate": "avg", - "clientmetric": "response_time_ms", - "condition": ">", - "requestName": null, - "result": null, - "value": 75.0 - }, - "a7ab8dec-07e6-4870-911c-4505382b85f1": { - "action": "continue", - "actualValue": 0.0, - "aggregate": "percentage", - "clientmetric": "error", - "condition": ">", - "requestName": null, - "result": null, - "value": 0.0 - } +{ + "passFailMetrics": { + "ece127bc-6271-4a70-93f6-758c56a3f12c": { + "clientMetric": "requests_per_sec", + "aggregate": "avg", + "condition": "<", + "value": 1200.0, + "requestName": null, + "action": "continue" + }, + "ac6c5e62-647a-4a1a-b001-b961e384892f": { + "action": "continue", + "aggregate": "avg", + "clientMetric": "response_time_ms", + "condition": ">", + "requestName": null, + "value": 100.0 + }, + "a7ab8dec-07e6-4870-911c-4505382b85f1": { + "action": "continue", + "aggregate": "percentage", + "clientMetric": "error", + "condition": ">", + "requestName": null, + "value": 1.0 } } -] +} \ No newline at end of file diff --git a/.ado/pipelines/templates/stages-loadtest-azure.yaml b/.ado/pipelines/templates/stages-loadtest-azure.yaml index 3ad30d0f9..a94ecf912 100644 --- a/.ado/pipelines/templates/stages-loadtest-azure.yaml +++ b/.ado/pipelines/templates/stages-loadtest-azure.yaml @@ -50,7 +50,8 @@ stages: customPrefix: '${{ parameters.customPrefix }}' environment: '$(environment)' customAttributes: '-var=queued_by="$(Build.QueuedBy)" - -var=branch="$(sourceBranch)"' + -var=branch="$(sourceBranch)" + -var=location="$(azureLoadTestLocation)"' # Parsing the Terraform output for the MALT service deployment - template: steps-parse-terraform-output.yaml @@ -120,8 +121,8 @@ stages: arguments: -apiEndpoint "$(azureLoadTestDataPlaneURI)" ` -apiVersion "$(azureLoadTestApiVersion)" ` - -loadTestDisplayName "$(get-date -f "yyyy-MM-dd hh:ss") load test for build $(Build.BuildId)" ` - -loadTestDescription "Pipeline-embedded load test for $(Build.BuildId) ($(get-date -f "dd/MM/yyyy hh:ss"))" ` + -loadTestDisplayName "Load test run for build $(Build.BuildId)" ` + -loadTestDescription "Pipeline-embedded load test for $(Build.BuildId) ($(get-date -AsUTC -f "yyyy-MM-ddTHH:mm:ssZ"))" ` -loadTestTargetUrl "$(azureLoadTestTargetFQDN)" ` -loadTestUserThreads "$(azureLoadTestUserThreads)" ` -loadTestDurationSeconds "$(azureLoadTestDurationSeconds)" ` @@ -149,13 +150,13 @@ stages: foreach($stamp in $releaseUnitInfraDeployOutput.stamp_properties.value) { echo "**************************** REGION: $($stamp.location) ****************************" + echo "*** Adding $($stamp.aks_cluster_id) as app component" + ./src/testing/loadtest-azure/scripts/appcomponents-add-to-loadtest.ps1 ` -loadTestId "$(loadTestId)" ` -apiEndpoint "$(azureLoadTestDataPlaneURI)" ` -apiVersion "$(azureLoadTestApiVersion)" ` -resourceId "$($stamp.aks_cluster_id)" - - echo "*** Adding $($stamp.aks_cluster_id)" } # upload a jmx file for the previously created azure load test with an auto-generated testFileId @@ -177,7 +178,7 @@ stages: # start azure load test - task: AzureCLI@2 - displayName: 'Run Azure Load Test' + displayName: 'Start Azure Load Test' inputs: azureSubscription: '$(azureServiceConnection)' scriptType: pscore @@ -187,9 +188,8 @@ stages: -loadTestId "$(loadTestId)" ` -apiEndpoint "$(azureLoadTestDataPlaneURI)" ` -apiVersion "$(azureLoadTestApiVersion)" ` - -testRunName "$(get-date -f "yyyy-MM-dd hh:ss") Load Test run triggered by ADO" ` + -testRunName "$(get-date -f "yyyy-MM-ddTHH:mm:ssZ") run triggered by ADO" ` -testRunDescription "Pipeline executed load test run" ` - -testRunVUsers "$(azureLoadTestVUsers)" ` -pipeline $true ` -verbose:$true @@ -203,9 +203,18 @@ stages: scriptLocation: inlineScript inlineScript: | + # set retry wait time in seconds + $retryWaitSeconds = 90 + + # set timeout in minutes + $timeoutMinutes = 45 + + #create a variable to sum up time in seconds + $totalTime = 0 + do { - echo "*** Waiting additional 90 seconds for the load test run to complete.." - start-sleep -seconds 90 + echo "*** Waiting additional $retryWaitSeconds seconds for the load test run to complete.." + start-sleep -seconds $retryWaitSeconds $result = $(System.DefaultWorkingDirectory)/src/testing/loadtest-azure/scripts/loadtest-get-run.ps1 ` -apiEndpoint "$(azureLoadTestDataPlaneURI)" ` -apiVersion "$(azureLoadTestApiVersion)" ` @@ -217,16 +226,26 @@ stages: throw "*** ERROR: Test run $(testRunId) ended in $($result.status) state." } else { # test is still running - echo "*** Test Run $(testRunId) is in status $testRunStatus" + echo "*** Test Run $(testRunId) is in status $testRunStatus Test Result: $($result.testResult)" } - $resultUrl = ($result).testArtifacts.outputArtifacts.resultUrl.url - $logsUrl = ($result).testArtifacts.outputArtifacts.logsUrl.url + $totalTime += $retryWaitSeconds - # todo - timeout? - } while ($result.status -ne "DONE") + if($totalTime -gt ($timeoutMinutes * 60)) + { + echo "*** Test run $(testRunId) did not finish in $timeoutMinutes minutes. Canceling test run..." + # Stop run + $(System.DefaultWorkingDirectory)/src/testing/loadtest-azure/scripts/loadtest-stop.ps1 ` + -apiEndpoint "$(azureLoadTestDataPlaneURI)" ` + -apiVersion "$(azureLoadTestApiVersion)" ` + -testRunId "$(testRunId)" + throw "*** ERROR: Test run $(testRunId) did not finish in $timeoutMinutes minutes. Test Run Status: $testRunStatus Test Result: $($result.testResult)" + } + + # Wait until test is done and the rest result (evaluation of the test criteria is done) + } while ($result.status -ne "DONE" -or $result.testResult -eq "NOT_APPLICABLE") - echo "*** Test Run $(testRunId) was completed. Test Run Status: $testRunStatus Test Status: $($result.testResult)" + echo "*** Test Run $(testRunId) was completed. Test Run Status: $testRunStatus Test Result: $($result.testResult)" echo "*** Portal URL: $($result.portalUrl)" # throw an error when testResult is FAILED @@ -235,7 +254,7 @@ stages: } - task: AzureCLI@2 - displayName: 'RESULTS: Download and convert JMeter results' + displayName: 'RESULTS: Download Load Test results' condition: succeeded() inputs: azureSubscription: $(azureServiceConnection) @@ -252,19 +271,18 @@ stages: -apiVersion "$(azureLoadTestApiVersion)" ` -testRunId "$(testRunId)" - $resultUrl = ($result).testArtifacts.outputArtifacts.resultUrl.url - $logsUrl = ($result).testArtifacts.outputArtifacts.logsUrl.url + $resultUrl = ($result).testArtifacts.outputArtifacts.resultFileInfo.url + $logsUrl = ($result).testArtifacts.outputArtifacts.logsFileInfo.url - if ( (!$resultUrl) -and (!$logsUrl) ) { + if ( (!$resultUrl) -or (!$logsUrl) ) { echo "*** Either resultUrl ($resultUrl) or logsUrl ($logsUrl) is empty. Retry $i/3" Start-Sleep -seconds 15 } else { echo "*** Received resultUrl ($resultUrl) and logsUrl ($logsUrl)" - $i=3 # set to 3 to end the loop + $i = 3 # set to 3 to end the loop } - $i++ - } while ( ($i -le 3) -and (($logsUrl) -and ($resultUrl)) ) + } while ( $i -le 3 ) if ( ($resultUrl) -and ($logsUrl) ) { New-Item -Path results -ItemType "directory" -Force @@ -276,20 +294,22 @@ stages: throw "*** ERROR: Either logsUrl ($logsUrl) or resultUrl ($resultUrl) is empty." } - #wget https://raw.githubusercontent.com/Azure-Samples/jmeter-aci-terraform/main/scripts/jtl_junit_converter.py -O $(System.DefaultWorkingDirectory)/junit-converter.py + # Conversion of JMeter results to JUnit format currently not being used due to long runtime duration of the script + # + # wget https://raw.githubusercontent.com/Azure-Samples/jmeter-aci-terraform/main/scripts/jtl_junit_converter.py -O $(System.DefaultWorkingDirectory)/junit-converter.py - if (Test-Path results/results.zip) { - Expand-Archive -Path results/results.zip -DestinationPath results + # if (Test-Path results/results.zip) { + # Expand-Archive -Path results/results.zip -DestinationPath results - # merge multiple csv files - # Get-ChildItem -Filter results/*.csv | Import-Csv | Export-Csv results/testreport.csv -NoTypeInformation -Append + # # merge multiple csv files + # Get-ChildItem -Filter results/*.csv | Import-Csv | Export-Csv results/testreport.csv -NoTypeInformation -Append - #$JMETER_RESULTS="results/testreport.csv" - #$JUNIT_RESULTS="output.xml" - #python3 junit-converter.py $JMETER_RESULTS $JUNIT_RESULTS - } else { - echo "Skipping result data conversion. results.zip was not found." - } + # $JMETER_RESULTS="results/testreport.csv" + # $JUNIT_RESULTS="output.xml" + # python3 junit-converter.py $JMETER_RESULTS $JUNIT_RESULTS + # } else { + # echo "Skipping result data conversion. results.zip was not found." + # } - task: PublishTestResults@2 @@ -317,4 +337,5 @@ stages: terraformStorageResourceGroupName: '$(terraformResourceGroup)' terraformStateFilename: 'terraform-azurelt-${{ parameters.customPrefix }}.state' terraformWorkingDirectory: '${{ parameters.terraformWorkingDirectory }}' - customAttributes: '-var=prefix="${{ parameters.customPrefix }}"' + customAttributes: '-var=prefix="${{ parameters.customPrefix }}" + -var=location="$(azureLoadTestLocation)"' diff --git a/src/infra/monitoring/grafana/terraform/globalresources/main.tf b/src/infra/monitoring/grafana/terraform/globalresources/main.tf index 7684b5a28..d3da0f9a9 100644 --- a/src/infra/monitoring/grafana/terraform/globalresources/main.tf +++ b/src/infra/monitoring/grafana/terraform/globalresources/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } } diff --git a/src/infra/monitoring/grafana/terraform/stamps/main.tf b/src/infra/monitoring/grafana/terraform/stamps/main.tf index 2ea92ffd0..6c3dedb91 100644 --- a/src/infra/monitoring/grafana/terraform/stamps/main.tf +++ b/src/infra/monitoring/grafana/terraform/stamps/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } } diff --git a/src/infra/workload/globalresources/main.tf b/src/infra/workload/globalresources/main.tf index f5a91927a..15dd9c2fc 100644 --- a/src/infra/workload/globalresources/main.tf +++ b/src/infra/workload/globalresources/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } azapi = { source = "Azure/azapi" diff --git a/src/infra/workload/releaseunit/main.tf b/src/infra/workload/releaseunit/main.tf index 23ff8945c..a76f5636d 100644 --- a/src/infra/workload/releaseunit/main.tf +++ b/src/infra/workload/releaseunit/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } azapi = { source = "Azure/azapi" - version = "1.5.0" + version = "1.7.0" } } diff --git a/src/infra/workload/releaseunit/modules/stamp/main.tf b/src/infra/workload/releaseunit/modules/stamp/main.tf index 6718d5303..36a5c973f 100644 --- a/src/infra/workload/releaseunit/modules/stamp/main.tf +++ b/src/infra/workload/releaseunit/modules/stamp/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } azapi = { source = "Azure/azapi" - version = "1.5.0" + version = "1.7.0" } } } diff --git a/src/testing/loadtest-azure/infra/main.tf b/src/testing/loadtest-azure/infra/main.tf index 6a80e0f2f..b582e17ec 100644 --- a/src/testing/loadtest-azure/infra/main.tf +++ b/src/testing/loadtest-azure/infra/main.tf @@ -2,11 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" - } - azapi = { - source = "azure/azapi" - version = "1.7.0" + version = "3.65.0" } } @@ -25,44 +21,22 @@ resource "azurerm_resource_group" "deployment" { tags = merge(local.default_tags, { "LastDeployedAt" = timestamp() }) } -resource "azapi_resource" "azurerm_load_test" { - type = "Microsoft.LoadTestService/loadTests@2022-04-15-preview" - name = "${local.prefix}-azloadtest" - parent_id = azurerm_resource_group.deployment.id - - location = azurerm_resource_group.deployment.location +resource "azurerm_load_test" "loadtest" { + name = "${local.prefix}-azloadtest" + location = azurerm_resource_group.deployment.location + resource_group_name = azurerm_resource_group.deployment.name tags = local.default_tags - - response_export_values = ["properties.dataPlaneURI"] } output "azureLoadTestName" { - value = azapi_resource.azurerm_load_test.name + value = azurerm_load_test.loadtest.name } output "azureLoadTestDataPlaneURI" { - value = jsondecode(azapi_resource.azurerm_load_test.output).properties.dataPlaneURI + value = azurerm_load_test.loadtest.data_plane_uri } -### Currently deployed via AzAPI ### -# -# resource "azurerm_load_test" "deployment" { -# name = "${local.prefix}-azloadtest" -# resource_group_name = azurerm_resource_group.deployment.name -# location = azurerm_resource_group.deployment.location - -# tags = local.default_tags -# } - -# output "azureLoadTestName" { -# value = azurerm_load_test.deployment.name -# } - -# output "azureLoadTestDataPlaneURI" { -# value = azurerm_load_test.deployment.dataplane_uri -# } - output "azureLoadResourceGroup" { value = azurerm_resource_group.deployment.name } \ No newline at end of file diff --git a/src/testing/loadtest-azure/scripts/appcomponents-add-to-loadtest.ps1 b/src/testing/loadtest-azure/scripts/appcomponents-add-to-loadtest.ps1 index a7af7b595..3f8c23372 100644 --- a/src/testing/loadtest-azure/scripts/appcomponents-add-to-loadtest.ps1 +++ b/src/testing/loadtest-azure/scripts/appcomponents-add-to-loadtest.ps1 @@ -13,7 +13,7 @@ param [string] $apiEndpoint, # Load Test data plane api version - [string] $apiVersion = "2022-06-01-preview" + [string] $apiVersion = "2023-04-01-preview" ) . "$PSScriptRoot/common.ps1" @@ -36,30 +36,24 @@ function validateResourceId($resourceId) { return $true } -if (!(validateResourceId -resourceId $resourceId)) { - throw "No valid resourceId provided." -} - function AppComponent { - param - ( - [string] $resourceName, - [string] $resourceId, - [string] $resourceType, - [string] $loadTestId - ) - - $result = @" - { - "testId": "$loadTestId", - "value": { - "$resourceId": { - "resourceName": "$resourceName", - "resourceId": "$resourceId", - "resourceType": "$resourceType" - } - } - } + param + ( + [string] $resourceName, + [string] $resourceId, + [string] $resourceType + ) + + $result = @" + { + "components": { + "$resourceId": { + "resourceName": "$resourceName", + "resourceId": "$resourceId", + "resourceType": "$resourceType" + } + } + } "@ return $result @@ -67,15 +61,26 @@ function AppComponent { # Split Azure ResourceID $resource = $resourceId.split("/") -$resourceType = $resource[6]+"/"+$resource[7] # combine resource type like Microsoft.ContainerService/managedCluster +$resourceType = $resource[6] + "/" + $resource[7] # combine resource type like Microsoft.ContainerService/managedCluster + +$testDataFileName = $loadTestId + ".txt" + +if (!(validateResourceId -resourceId $resourceId)) { + throw "No valid resourceId provided." +} $testDataFileName = $loadTestId + ".txt" -AppComponent -resourceName $resource[8] ` - -resourceType $resourceType ` - -resourceId $resourceId ` - -loadTestId $loadTestId | Out-File $testDataFileName -Encoding utf8 -$urlRoot = "https://" + $apiEndpoint + "/appcomponents/" + $loadTestId +$appComponent = AppComponent -resourceName $resource[8] ` + -resourceType $resourceType ` + -resourceId $resourceId + +Write-Verbose "*** App component request body:" +$appComponent + +$appComponent | Out-File $testDataFileName -Encoding utf8 + +$urlRoot = "https://{0}/tests/{1}/app-components" -f $apiEndpoint, $loadTestId Write-Verbose "*** Load test service data plane: $urlRoot" # Create a new load test resource or update existing, if loadTestId already exists @@ -83,7 +88,7 @@ az rest --url $urlRoot ` --method PATCH ` --skip-authorization-header ` --headers ('@' + $accessTokenFileName) "Content-Type=application/merge-patch+json" ` - --url-parameters testId=$loadTestId api-version=$apiVersion ` + --url-parameters api-version=$apiVersion ` --body ('@' + $testDataFileName) ` $verbose #-o none diff --git a/src/testing/loadtest-azure/scripts/catalog-test.jmx b/src/testing/loadtest-azure/scripts/catalog-test.jmx index 5ad7ca500..a5bd32d7b 100644 --- a/src/testing/loadtest-azure/scripts/catalog-test.jmx +++ b/src/testing/loadtest-azure/scripts/catalog-test.jmx @@ -60,7 +60,8 @@ 6 - + + HttpClient4 diff --git a/src/testing/loadtest-azure/scripts/file-upload-to-loadtest.ps1 b/src/testing/loadtest-azure/scripts/file-upload-to-loadtest.ps1 index fa156e9fe..dd1ebbd3f 100644 --- a/src/testing/loadtest-azure/scripts/file-upload-to-loadtest.ps1 +++ b/src/testing/loadtest-azure/scripts/file-upload-to-loadtest.ps1 @@ -9,14 +9,14 @@ param [string] $apiEndpoint, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview", + [string] $apiVersion = "2023-04-01-preview", # Filename to upload [Parameter(Mandatory = $true)] [string] $testFileName, # Test File ID is auto-generated when not set (default) - [string] $testFileId = (New-Guid).toString(), + [string] $testFileId = "$(New-Guid).jmx", # optional - expose outputs as pipeline variables [bool] $pipeline = $false, @@ -33,27 +33,21 @@ if (!(Test-Path $testFileName -PathType leaf)) { trow "File $testFileName does not exist" } -$urlRoot = "https://{0}/loadtests/{1}/files/{2}" -f $apiEndpoint, $loadTestId, $testFileId - -# Following is to get Invoke-RestMethod to work -$url = "{0}?api-version={1}" -f $urlRoot, $apiVersion +$urlRoot = "https://{0}/tests/{1}/files/{2}" -f $apiEndpoint, $loadTestId, $testFileId Write-Verbose "*** Load test service data plane: $urlRoot" -# Secure string to use access token with Invoke-RestMethod in Powershell -$accessTokenSecure = ConvertTo-SecureString -String $accessToken -AsPlainText -Force - -$result = Invoke-RestMethod ` - -Uri $url ` - -Method PUT ` - -Authentication Bearer ` - -Token $accessTokenSecure ` - -Form @{ file = Get-Item $testFileName } ` - -Verbose:$verbose -Debug +$result = az rest --url $urlRoot ` + --method PUT ` + --skip-authorization-header ` + --headers ('@' + $accessTokenFileName) "Content-Type=application/octet-stream" ` + --url-parameters api-version=$apiVersion fileType="JMX_FILE" ` + --body ('@' + $testFileName) ` + --output json $verbose | ConvertFrom-Json # export pipeline variables if($pipeline) { - echo "##vso[task.setvariable variable=fileId]$($result.fileId)" # contains the fileId for in-pipeline usage + echo "##vso[task.setvariable variable=fileId]$($result.fileName)" # contains the fileName for in-pipeline usage } else { $result } @@ -65,7 +59,7 @@ if($wait) { $fileStatus = (& $PSScriptRoot\loadtest-get-files.ps1 -apiEndpoint $apiEndpoint ` -loadTestId $loadTestId ` - -fileId $($result.fileId) ` + -fileId $($result.fileName) ` -keepToken $true) if ($fileStatus.validationStatus -ne "VALIDATION_SUCCESS") { Write-Verbose "*** Waiting another 10s for file validation to complete $($fileStatus.validationStatus)" diff --git a/src/testing/loadtest-azure/scripts/file-verify.ps1 b/src/testing/loadtest-azure/scripts/file-verify.ps1 index e444ed756..b6380fe04 100644 --- a/src/testing/loadtest-azure/scripts/file-verify.ps1 +++ b/src/testing/loadtest-azure/scripts/file-verify.ps1 @@ -9,7 +9,7 @@ param [string] $apiEndpoint, # Load Test data plane api version - [string] $apiVersion = "2022-06-01-preview" + [string] $apiVersion = "2023-04-01-preview" ) . "$PSScriptRoot/common.ps1" diff --git a/src/testing/loadtest-azure/scripts/loadtest-create.ps1 b/src/testing/loadtest-azure/scripts/loadtest-create.ps1 index cab1dda9e..c82ce91aa 100644 --- a/src/testing/loadtest-azure/scripts/loadtest-create.ps1 +++ b/src/testing/loadtest-azure/scripts/loadtest-create.ps1 @@ -32,7 +32,7 @@ param [string] $passFailCriteria, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview", + [string] $apiVersion = "2023-04-01-preview", # optional - expose outputs as pipeline variables [bool] $pipeline = $false @@ -55,13 +55,19 @@ function GetTestBody { { "displayName": "$loadTestDisplayName", "description": "$loadTestDescription", - "loadTestConfig": { + "loadTestConfiguration": { "engineInstances": $engineInstances }, "environmentVariables": { "target_url": "$loadTestTargetUrl", "threads": $loadTestUserThreads, "load_duration_seconds": $loadTestDurationSeconds + }, + "autoStopCriteria": { + "autoStopEnabled": false, + "isAutoStopEnabled": false, + "errorRate": 90, + "errorRateTimeWindow": 60 } } "@ @@ -96,7 +102,10 @@ if ($passFailCriteria) { $body | Out-File $testDataFileName -Encoding utf8 -$urlRoot = "https://{0}/loadtests/{1}" -f $apiEndpoint, $loadTestId +Write-Verbose "*** Test request body" +$body + +$urlRoot = "https://{0}/tests/{1}" -f $apiEndpoint, $loadTestId Write-Verbose "*** Load test service data plane: $urlRoot" # Create a new load test resource or update existing, if loadTestId already exists @@ -104,10 +113,15 @@ az rest --url $urlRoot ` --method PATCH ` --skip-authorization-header ` --headers ('@' + $accessTokenFileName) "Content-Type=application/merge-patch+json" ` - --url-parameters testId=$loadTestId api-version=$apiVersion ` + --url-parameters api-version=$apiVersion ` --body ('@' + $testDataFileName) ` --output none $verbose +if($LastExitCode -ne 0) +{ + throw "*** Error on creating load test instance!" +} + # Outputs and exports for pipeline usage if($pipeline) { echo "##vso[task.setvariable variable=loadTestId]$loadTestId" # contains the loadTestId for in-pipeline usage diff --git a/src/testing/loadtest-azure/scripts/loadtest-delete.ps1 b/src/testing/loadtest-azure/scripts/loadtest-delete.ps1 index 67b9c5020..31e0b4e15 100644 --- a/src/testing/loadtest-azure/scripts/loadtest-delete.ps1 +++ b/src/testing/loadtest-azure/scripts/loadtest-delete.ps1 @@ -9,7 +9,7 @@ param [string] $apiEndpoint, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview" + [string] $apiVersion = "2023-04-01-preview" ) if (!$loadTestId) { @@ -18,7 +18,7 @@ if (!$loadTestId) { . ./common.ps1 -$urlRoot = "https://{0}/loadtests/{1}" -f $apiEndpoint,$loadTestId +$urlRoot = "https://{0}/tests/{1}" -f $apiEndpoint,$loadTestId az rest --url $urlRoot ` --method DELETE ` diff --git a/src/testing/loadtest-azure/scripts/loadtest-get-files.ps1 b/src/testing/loadtest-azure/scripts/loadtest-get-files.ps1 index 76f218c76..18c0e3818 100644 --- a/src/testing/loadtest-azure/scripts/loadtest-get-files.ps1 +++ b/src/testing/loadtest-azure/scripts/loadtest-get-files.ps1 @@ -9,20 +9,18 @@ param [string] $apiEndpoint, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview", + [string] $apiVersion = "2023-04-01-preview", # optional - request an individual file via its fileId [string] $fileId, # optional - keep access token when used embedded - [bool] $keepToken = $false, - - [int] $maxPageSize + [bool] $keepToken = $false ) . "$PSScriptRoot/common.ps1" -$urlRoot = "https://{0}/loadtests/{1}/files" -f $apiEndpoint, $loadTestId +$urlRoot = "https://{0}/tests/{1}/files" -f $apiEndpoint, $loadTestId if ($fileId) { $urlRoot = "{0}/{1}" -f $urlRoot,$fileId @@ -32,7 +30,7 @@ az rest --url $urlRoot ` --method GET ` --skip-authorization-header ` --headers ('@' + $accessTokenFileName) ` - --url-parameters api-version=$apiVersion maxPageSize=$maxPageSize ` + --url-parameters api-version=$apiVersion ` $verbose --output json | convertFrom-Json if (!$keepToken) { diff --git a/src/testing/loadtest-azure/scripts/loadtest-get-results.ps1 b/src/testing/loadtest-azure/scripts/loadtest-get-results.ps1 index 030f106a6..229ba0cd1 100644 --- a/src/testing/loadtest-azure/scripts/loadtest-get-results.ps1 +++ b/src/testing/loadtest-azure/scripts/loadtest-get-results.ps1 @@ -8,14 +8,14 @@ param [string] $apiEndpoint, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview", + [string] $apiVersion = "2023-04-01-preview", [string] $testRunId ) . "$PSScriptRoot/common.ps1" -$urlRoot = "https://" + $apiEndpoint + "/testruns/" + $testRunId + "/clientMetrics" +$urlRoot = "https://{0}/test-runs/{1}/clientMetrics" -f $apiEndpoint, $testRunId # Following is to get Invoke-RestMethod to work $url = $urlRoot + "?api-version=" + $apiVersion diff --git a/src/testing/loadtest-azure/scripts/loadtest-get-run.ps1 b/src/testing/loadtest-azure/scripts/loadtest-get-run.ps1 index a5603aa90..aba3f9de7 100644 --- a/src/testing/loadtest-azure/scripts/loadtest-get-run.ps1 +++ b/src/testing/loadtest-azure/scripts/loadtest-get-run.ps1 @@ -9,12 +9,12 @@ param [string] $apiEndpoint, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview" + [string] $apiVersion = "2023-04-01-preview" ) . "$PSScriptRoot/common.ps1" -$urlRoot = "https://{0}/testruns/{1}" -f $apiEndpoint, $testRunId +$urlRoot = "https://{0}/test-runs/{1}" -f $apiEndpoint, $testRunId $url = $urlRoot + "?api-version=" + $apiVersion diff --git a/src/testing/loadtest-azure/scripts/loadtest-run.ps1 b/src/testing/loadtest-azure/scripts/loadtest-run.ps1 index 7d0a64d36..27e306f32 100644 --- a/src/testing/loadtest-azure/scripts/loadtest-run.ps1 +++ b/src/testing/loadtest-azure/scripts/loadtest-run.ps1 @@ -9,7 +9,7 @@ param [string] $apiEndpoint, # optional - load test data plane api version - [string] $apiVersion = "2022-06-01-preview", + [string] $apiVersion = "2023-04-01-preview", # Load Test run displayname [Parameter(Mandatory=$true)] @@ -18,8 +18,6 @@ param # Load test run description [string] $testRunDescription, - [int] $testRunVUsers = 1, - # optional - expose outputs as pipeline variables [bool] $pipeline = $false ) @@ -31,18 +29,14 @@ function GetTestRunBody { ( [string] $testId, [string] $testRunName, - [string] $description, - [string] $testRunId, - [int] $vusers + [string] $description ) $result = @" { "testId": "$testId", - "testRunId": "$testRunId", "displayName": "$testRunName", - "description": "$testRunDescription", - "vusers": $vusers + "description": "$testRunDescription" } "@ @@ -50,23 +44,20 @@ function GetTestRunBody { } $testRunId = (New-Guid).toString() -$urlRoot = "https://{0}/testruns/{1}" -f $apiEndpoint,$testRunId +$urlRoot = "https://{0}/test-runs/{1}" -f $apiEndpoint,$testRunId Write-Verbose "*** Load test service data plane: $urlRoot" # Prep load test run body $testRunData = GetTestRunBody ` -testId $loadTestId ` -testRunName $testRunName ` - -testRunDescription $testRunDescription ` - -testRunId $testRunId ` - -vusers $testRunVUsers + -testRunDescription $testRunDescription # Following is to get Invoke-RestMethod to work $url = $urlRoot + "?api-version=" + $apiVersion $header = @{ 'Content-Type'='application/merge-patch+json' - 'testRunId'="$testRunId" } # Secure string to use access token with Invoke-RestMethod in Powershell diff --git a/src/testing/loadtest-azure/scripts/loadtest-stop.ps1 b/src/testing/loadtest-azure/scripts/loadtest-stop.ps1 new file mode 100644 index 000000000..4ad5a4470 --- /dev/null +++ b/src/testing/loadtest-azure/scripts/loadtest-stop.ps1 @@ -0,0 +1,33 @@ +param +( + [Parameter(Mandatory=$true)] + [string] $loadTestId, + + # Load Test data plane endpoint + [Parameter(Mandatory=$true)] + [string] $apiEndpoint, + + # optional - load test data plane api version + [string] $apiVersion = "2023-04-01-preview", + + [string] $testRunId +) + +. "$PSScriptRoot/common.ps1" + +$urlRoot = "https://" + $apiEndpoint + "/test-runs/" + $testRunId + ":stop" + +# Following is to get Invoke-RestMethod to work +$url = $urlRoot + "?api-version=" + $apiVersion + +# Secure string to use access token with Invoke-RestMethod in Powershell +$accessTokenSecure = ConvertTo-SecureString -String $accessToken -AsPlainText -Force + +Invoke-RestMethod ` + -Uri $url ` + -Method POST ` + -Authentication Bearer ` + -Token $accessTokenSecure ` + -Verbose:$verbose + +Remove-Item $accessTokenFileName diff --git a/src/testing/loadtest-azure/scripts/loadtests-get.ps1 b/src/testing/loadtest-azure/scripts/loadtests-get.ps1 deleted file mode 100644 index aab589b27..000000000 --- a/src/testing/loadtest-azure/scripts/loadtests-get.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -# loadtests-get.ps1 | List existing load tests -param -( - [Parameter(Mandatory=$true)] - [string] $loadTestId, - - # Load Test data plane endpoint - [Parameter(Mandatory=$true)] - [string] $apiEndpoint, - - # optional - expose outputs as pipeline variables - [bool] $pipeline = $false - - [int] $maxPageSize -) - -. "$PSScriptRoot/common.ps1" - -$urlRoot = "https://{0}/loadtests/{1}" -f $apiEndpoint,$loadTestId - -az rest --url $urlRoot ` - --method GET ` - --skip-authorization-header ` - --headers ('@' + $accessTokenFileName) ` - --url-parameters api-version="$apiVersion" maxPageSize=$maxPageSize ` - $verbose - -Remove-Item $accessTokenFileName diff --git a/src/testing/loadtest-locust/infra/main.tf b/src/testing/loadtest-locust/infra/main.tf index 35179eec0..1e63c7687 100644 --- a/src/testing/loadtest-locust/infra/main.tf +++ b/src/testing/loadtest-locust/infra/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } } diff --git a/src/testing/userload-generator/infra/main.tf b/src/testing/userload-generator/infra/main.tf index ee9203e0c..fe95f5d45 100644 --- a/src/testing/userload-generator/infra/main.tf +++ b/src/testing/userload-generator/infra/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "3.63.0" + version = "3.65.0" } }