From 2948ac7e42449a1949cf7881cb5343f36aac9fc9 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 17 Dec 2024 17:53:38 +0100 Subject: [PATCH 01/16] utkast til test av post transmission --- .../performancetest_common/createDialog.js | 67 +++++++++++++++++++ .../performancetest_common/simpleSearch.js | 3 +- .../performancetest_data/01-create-dialog.js | 9 +++ .../create-transmission.js | 65 ++++++++++++++++++ .../performance/create-transmissions.js | 37 ++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 tests/k6/tests/performancetest_data/create-transmission.js create mode 100644 tests/k6/tests/serviceowner/performance/create-transmissions.js diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index 0768e4030..ffc9a800d 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -6,6 +6,7 @@ import { describe } from "../../common/describe.js"; import { postSO, purgeSO } from "../../common/request.js"; import { expect } from "../../common/testimports.js"; import dialogToInsert from "../performancetest_data/01-create-dialog.js"; +import { default as transmissionToInsert } from "../performancetest_data/create-transmission.js"; /** * Creates a dialog. @@ -30,6 +31,7 @@ export function createDialog(serviceOwner, endUser, traceCalls) { describe('create dialog', () => { let r = postSO('dialogs', dialogToInsert(endUser.ssn, endUser.resource), paramsWithToken); + console.log(r.body); expect(r.status, 'response status').to.equal(201); }); @@ -72,3 +74,68 @@ export function createAndRemoveDialog(serviceOwner, endUser, traceCalls) { } }); } + +/** + * Creates a dialog and add a number of transmissions + * + * @param {Object} serviceOwner - The service owner object. + * @param {Object} endUser - The end user object. + */ +export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions) { + var traceparent = uuidv4(); + + var paramsWithToken = { + headers: { + Authorization: "Bearer " + serviceOwner.token, + traceparent: traceparent + }, + tags: { name: 'create dialog' } + }; + if (traceCalls) { + paramsWithToken.tags.traceparent = traceparent; + paramsWithToken.tags.enduser = endUser.ssn; + } + + let dialogId = 0; + describe('create dialog', () => { + let r = postSO('dialogs', dialogToInsert(endUser.ssn, endUser.resource), paramsWithToken); + dialogId = r.json(); + expect(r.status, 'response status').to.equal(201); + }); + + console.log(dialogId); + let relatedTransmissionId = 0; + for (let i = 0; i < numberOfTransmissions; i++) { + + relatedTransmissionId = createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls); + if (i%100 === 0) { + relatedTransmissionId = 0; + } + } + +} + +export function createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls) { + var traceparent = uuidv4(); + + var paramsWithToken = { + headers: { + Authorization: "Bearer " + serviceOwner.token, + traceparent: traceparent + }, + tags: { name: 'create transmission' } + }; + + + describe('create transmission', () => { + if (relatedTransmissionId == 0) { + console.log('creating new transmission-thread'); + } + + let r = postSO('dialogs/' + dialogId + '/transmissions', transmissionToInsert(relatedTransmissionId), paramsWithToken); + console.log(r.body); + expect(r.status, 'response status').to.equal(201); + return r.json(); + }); +} + diff --git a/tests/k6/tests/performancetest_common/simpleSearch.js b/tests/k6/tests/performancetest_common/simpleSearch.js index 8e0f7ef0c..0826ad0dc 100644 --- a/tests/k6/tests/performancetest_common/simpleSearch.js +++ b/tests/k6/tests/performancetest_common/simpleSearch.js @@ -20,7 +20,7 @@ function retrieveDialogContent(response, paramsWithToken, getFunction = getEU) { if (!items?.length) return; const dialogId = items[0].id; if (!dialogId) return; - + console.log("Found dialog with id " + dialogId); getContent(dialogId, paramsWithToken, 'get dialog', '', getFunction); getContentChain(dialogId, paramsWithToken, 'get dialog activities', 'get dialog activity', '/activities/', getFunction); getContentChain(dialogId, paramsWithToken, 'get seenlogs', 'get seenlog', '/seenlog/', getFunction); @@ -99,6 +99,7 @@ export function getContentChain(dialogId, paramsWithToken, tag, subtag, endpoint }; let d = getUrl('dialogs/' + dialogId + endpoint, listParams, getFunction); let json = d.json(); + console.log("Found " + json.length + " " + tag + " for endpoint " + dialogId + endpoint); if (json.length > 0) { const detailParams = { ...paramsWithToken, diff --git a/tests/k6/tests/performancetest_data/01-create-dialog.js b/tests/k6/tests/performancetest_data/01-create-dialog.js index 551d324cc..b444afa93 100644 --- a/tests/k6/tests/performancetest_data/01-create-dialog.js +++ b/tests/k6/tests/performancetest_data/01-create-dialog.js @@ -54,5 +54,14 @@ export default function (endUser, resource) { let payload = createDialogPayload(); payload.serviceResource = "urn:altinn:resource:" +resource; payload.party = "urn:altinn:person:identifier-no:" + endUser; + + // const firstTransmission = payload.transmissions[0]; + // const copyOfFirstTransmission = { ...firstTransmission }; + // for (let i = 0; i < 155; i++) { + // payload.transmissions.push(copyOfFirstTransmission); + // } + // console.log(payload.transmissions.length); + // console.log(endUser, resource); + return cleanUp(payload); } diff --git a/tests/k6/tests/performancetest_data/create-transmission.js b/tests/k6/tests/performancetest_data/create-transmission.js new file mode 100644 index 000000000..927e917e7 --- /dev/null +++ b/tests/k6/tests/performancetest_data/create-transmission.js @@ -0,0 +1,65 @@ + +import { uuidv4 } from "../../common/uuid.js"; + +export default function (relatedTransmissionId) { + let transmission = { + "id": uuidv4, + "createdAt": "2024-12-13T12:29:04.540Z", + "authorizationAttribute": "element1", + "extendedType": "string", + "type": "Information", + "sender": { + "actorType": "serviceOwner" + }, + "content": { + "title": { + "value": [ + { + "value": "Forsendelsestittel", + "languageCode": "nb" + }, + { + "languageCode": "en", + "value": "Transmission title" + } + ], + }, + "summary": { + "value": [ + { + "languageCode": "nb", + "value": "Forsendelse oppsummering" + }, + { + "languageCode": "en", + "value": "Transmission summary" + } + ], + } + }, + "attachments": [ + { + "displayName": [ + { + "languageCode": "nb", + "value": "Forsendelse visningsnavn" + }, + { + "languageCode": "en", + "value": "Transmission attachment display name" + } + ], + "urls": [ + { + "url": "https://digdir.apps.tt02.altinn.no/some-other-url", + "consumerType": "Gui" + } + ] + } + ] + } + if (relatedTransmissionId != 0) { + transmission.relatedTransmissionId = relatedTransmissionId; + } + return transmission; +} \ No newline at end of file diff --git a/tests/k6/tests/serviceowner/performance/create-transmissions.js b/tests/k6/tests/serviceowner/performance/create-transmissions.js new file mode 100644 index 000000000..af268336e --- /dev/null +++ b/tests/k6/tests/serviceowner/performance/create-transmissions.js @@ -0,0 +1,37 @@ +/** + * Performance test for creating a dialog + * Run: k6 run tests/k6/tests/serviceowner/performance/create-dialog.js --vus 1 --iterations 1 + */ +import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; +import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js'; +import { createTransmissions } from '../../performancetest_common/createDialog.js'; +import { serviceOwners, endUsers } from '../../performancetest_common/readTestdata.js'; + +export let options = { + summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'], + thresholds: getDefaultThresholds(['http_req_duration', 'http_reqs'],['create dialog', 'create transmission']) +}; + +const isSingleUserMode = (__ENV.isSingleUserMode ?? 'false') === 'true'; +const traceCalls = (__ENV.traceCalls ?? 'false') === 'true'; +const numberOfTransmissions = (__ENV.numberOfTransmissions ?? '10'); + +export default function() { + if (!endUsers || endUsers.length === 0) { + throw new Error('No end users loaded for testing'); + } + if (!serviceOwners || serviceOwners.length === 0) { + throw new Error('No service owners loaded for testing'); + } + + if (isSingleUserMode) { + createTransmissions(serviceOwners[0], endUsers[0], traceCalls, numberOfTransmissions); + } + else { + let serviceOwner = randomItem(serviceOwners); + for (let i = 0; i < endUsers.length; i++) { + createTransmissions(serviceOwner, endUsers[i], traceCalls, numberOfTransmissions); + } + } + } + From c767619c088d90465a41c68aa5fab3144b7ec01b Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 12:48:39 +0100 Subject: [PATCH 02/16] Added script to run tests from k8s and file to generate tokens on the fly --- .../tests/performancetest_common/getTokens.js | 23 ++++ tests/k6/tests/scripts/run-test-in-k8s.sh | 112 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/k6/tests/performancetest_common/getTokens.js create mode 100755 tests/k6/tests/scripts/run-test-in-k8s.sh diff --git a/tests/k6/tests/performancetest_common/getTokens.js b/tests/k6/tests/performancetest_common/getTokens.js new file mode 100644 index 000000000..7dc73858f --- /dev/null +++ b/tests/k6/tests/performancetest_common/getTokens.js @@ -0,0 +1,23 @@ +import { fetchToken } from "../../common/token.js"; + +const tokenGeneratorEnv = __ENV.API_ENVIRONMENT || 'yt01'; +const tokenTtl = 3600 + +export function getEnterpriseToken(serviceOwner) { + var tokenOptions = { + scopes: serviceOwner.scopes, + orgName: serviceOwner.org, + orgNo: serviceOwner.orgno + } + const url = `http://altinn-testtools-token-generator.azurewebsites.net/api/GetEnterpriseToken?env=${tokenGeneratorEnv}&scopes=${encodeURIComponent(tokenOptions.scopes)}&org=${tokenOptions.orgName}&orgNo=${tokenOptions.orgNo}&ttl=${tokenTtl}`; + return fetchToken(url, tokenOptions, `service owner (orgno:${tokenOptions.orgNo} orgName:${tokenOptions.orgName} tokenGeneratorEnv:${tokenGeneratorEnv})`); +} + +export function getPersonalToken(endUser) { + var tokenOptions = { + scopes: endUser.scopes, + ssn: endUser.ssn + } + const url = `http://altinn-testtools-token-generator.azurewebsites.net/api/GetPersonalToken?env=${tokenGeneratorEnv}&scopes=${encodeURIComponent(tokenOptions.scopes)}&pid=${tokenOptions.ssn}&ttl=${tokenTtl}`; + return fetchToken(url, tokenOptions, `end user (ssn:${tokenOptions.ssn}, tokenGeneratorEnv:${tokenGeneratorEnv})`); + } diff --git a/tests/k6/tests/scripts/run-test-in-k8s.sh b/tests/k6/tests/scripts/run-test-in-k8s.sh new file mode 100755 index 000000000..3a5452a75 --- /dev/null +++ b/tests/k6/tests/scripts/run-test-in-k8s.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +tokengenuser=${TOKEN_GENERATOR_USERNAME} +tokengenpasswd=${TOKEN_GENERATOR_PASSWORD} + +help() { + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " -f, --filename Specify the filename of the k6 script archive" + echo " -c, --configmapname Specify the name of the configmap to create" + echo " -n, --name Specify the name of the test run" + echo " -v, --vus Specify the number of virtual users" + echo " -d, --duration Specify the duration of the test" + echo " -p, --parallelism Specify the level of parallelism" + echo " -h, --help Show this help message" + exit 0 +} + +print_logs() { + POD_LABEL="k6-test=$name" + K8S_CONTEXT="k6tests-cluster" + K8S_NAMESPACE="default" + + for pod in $(kubectl --context "$K8S_CONTEXT" -n "$K8S_NAMESPACE" get pods -l "$POD_LABEL" -o name); do + if [[ $pod != *"initializer"* ]]; then + echo --------------------------- + echo $pod + echo --------------------------- + kubectl --context "$K8S_CONTEXT" -n "$K8S_NAMESPACE" logs --tail=-1 $pod + fi + done +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + help + ;; + -f|--filename) + filename="$2" + shift 2 + ;; + -c|--configmapname) + configmapname="$2" + shift 2 + ;; + -n|--name) + name="$2" + shift 2 + ;; + -v|--vus) + vus="$2" + shift 2 + ;; + -d|--duration) + duration="$2" + shift 2 + ;; + -p|--parallelism) + parallelism="$2" + shift 2 + ;; + *) + echo "Invalid option: $1" + help + exit 1 + ;; + esac +done + +k6 archive $filename -e API_VERSION=v1 -e API_ENVIRONMENT=yt01 -e TOKEN_GENERATOR_USERNAME=$tokengenuser -e TOKEN_GENERATOR_PASSWORD=$tokengenpasswd +# Create configmap from archive.tar +kubectl create configmap $configmapname --from-file=archive.tar + +# Create the config.yml file from a string +cat < config.yml +apiVersion: k6.io/v1alpha1 +kind: TestRun +metadata: + name: $name +spec: + arguments: --out experimental-prometheus-rw --vus=$vus --duration=$duration + parallelism: $parallelism + script: + configMap: + name: $configmapname + file: archive.tar + runner: + env: + - name: K6_PROMETHEUS_RW_SERVER_URL + value: "http://kube-prometheus-stack-prometheus.monitoring:9090/api/v1/write" + metadata: + labels: + k6-test: $name +EOF +# Apply the config.yml configuration +kubectl apply -f config.yml + +# Wait for the job to finish +wait_timeout="${duration}100s" +kubectl --context k6tests-cluster wait --for=jsonpath='{.status.stage}'=finished testrun/$name --timeout=$wait_timeout + +# Print the logs of the pods +print_logs +# Delete the search-dialog.yml configuration +kubectl delete -f config.yml + +# Delete the configmap +kubectl delete configmap $configmapname + +# Delete the archive.tar and the config.yml files +rm archive.tar config.yml \ No newline at end of file From 5a11b9102b20ed1fe7dd76ba48f3d5597ff6d350 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 12:51:19 +0100 Subject: [PATCH 03/16] export the fetchToken function --- tests/k6/common/token.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/k6/common/token.js b/tests/k6/common/token.js index c1f69ad34..2700f284f 100644 --- a/tests/k6/common/token.js +++ b/tests/k6/common/token.js @@ -31,7 +31,7 @@ function getCacheKey(tokenType, tokenOptions) { return `${tokenType}|${tokenOptions.scopes}|${tokenOptions.orgName}|${tokenOptions.orgNo}|${tokenOptions.ssn}`; } -function fetchToken(url, tokenOptions, type) { +export function fetchToken(url, tokenOptions, type) { const currentTime = Math.floor(Date.now() / 1000); const cacheKey = getCacheKey(type, tokenOptions); From b41548188b00077c2d13dfb9fab36bcf12845d21 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 12:52:44 +0100 Subject: [PATCH 04/16] Create tokens on the fly --- .../k6/tests/enduser/performance/enduser-search.js | 8 ++++---- .../k6/tests/performancetest_common/createDialog.js | 13 +++++++------ .../k6/tests/performancetest_common/readTestdata.js | 13 +------------ .../k6/tests/performancetest_common/simpleSearch.js | 9 ++++----- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/tests/k6/tests/enduser/performance/enduser-search.js b/tests/k6/tests/enduser/performance/enduser-search.js index 41f1b0d7c..306f21586 100644 --- a/tests/k6/tests/enduser/performance/enduser-search.js +++ b/tests/k6/tests/enduser/performance/enduser-search.js @@ -1,6 +1,6 @@ import { enduserSearch } from '../../performancetest_common/simpleSearch.js' import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js'; -import { endUsersWithTokens } from '../../performancetest_common/readTestdata.js'; +import { endUsers } from '../../performancetest_common/readTestdata.js'; const isSingleUserMode = (__ENV.isSingleUserMode ?? 'false') === 'true'; const traceCalls = (__ENV.traceCalls ?? 'false') === 'true'; @@ -20,16 +20,16 @@ export let options = { }; export default function() { - if (!endUsersWithTokens || endUsersWithTokens.length === 0) { + if (!endUsers || endUsers.length === 0) { throw new Error('No end users loaded for testing'); } if (isSingleUserMode) { - enduserSearch(endUsersWithTokens[0], traceCalls); + enduserSearch(endUsers[0], traceCalls); } else { for (let i = 0; i < endUsersWithTokens.length; i++) { - enduserSearch(endUsersWithTokens[i], traceCalls); + enduserSearch(endUsers[i], traceCalls); } } } diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index ffc9a800d..fafeae817 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -7,6 +7,7 @@ import { postSO, purgeSO } from "../../common/request.js"; import { expect } from "../../common/testimports.js"; import dialogToInsert from "../performancetest_data/01-create-dialog.js"; import { default as transmissionToInsert } from "../performancetest_data/create-transmission.js"; +import { getEnterpriseToken } from "./getTokens.js"; /** * Creates a dialog. @@ -14,16 +15,18 @@ import { default as transmissionToInsert } from "../performancetest_data/create- * @param {Object} serviceOwner - The service owner object. * @param {Object} endUser - The end user object. */ + export function createDialog(serviceOwner, endUser, traceCalls) { var traceparent = uuidv4(); var paramsWithToken = { headers: { - Authorization: "Bearer " + serviceOwner.token, + Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent }, tags: { name: 'create dialog' } }; + if (traceCalls) { paramsWithToken.tags.traceparent = traceparent; paramsWithToken.tags.enduser = endUser.ssn; @@ -31,10 +34,8 @@ export function createDialog(serviceOwner, endUser, traceCalls) { describe('create dialog', () => { let r = postSO('dialogs', dialogToInsert(endUser.ssn, endUser.resource), paramsWithToken); - console.log(r.body); expect(r.status, 'response status').to.equal(201); }); - } /** @@ -47,7 +48,7 @@ export function createAndRemoveDialog(serviceOwner, endUser, traceCalls) { var traceparent = uuidv4(); var paramsWithToken = { headers: { - Authorization: "Bearer " + serviceOwner.token, + Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent }, tags: { name: 'create dialog' } @@ -86,7 +87,7 @@ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfT var paramsWithToken = { headers: { - Authorization: "Bearer " + serviceOwner.token, + Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent }, tags: { name: 'create dialog' } @@ -120,7 +121,7 @@ export function createTransmission(dialogId, relatedTransmissionId, serviceOwner var paramsWithToken = { headers: { - Authorization: "Bearer " + serviceOwner.token, + Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent }, tags: { name: 'create transmission' } diff --git a/tests/k6/tests/performancetest_common/readTestdata.js b/tests/k6/tests/performancetest_common/readTestdata.js index 538c292a3..39dbbea70 100644 --- a/tests/k6/tests/performancetest_common/readTestdata.js +++ b/tests/k6/tests/performancetest_common/readTestdata.js @@ -23,12 +23,11 @@ function readCsv(filename) { } } -const filenameServiceowners = '../performancetest_data/.serviceowners-with-tokens.csv'; if (!__ENV.API_ENVIRONMENT) { throw new Error('API_ENVIRONMENT must be set'); } const filenameEndusers = `../performancetest_data/endusers-${__ENV.API_ENVIRONMENT}.csv`; -const filenameEndusersWithTokens = '../performancetest_data/.endusers-with-tokens.csv'; +const filenameServiceowners = `../performancetest_data/serviceowners-${__ENV.API_ENVIRONMENT}.csv`; /** * SharedArray variable that stores the service owners data. @@ -53,14 +52,4 @@ export const endUsers = new SharedArray('endUsers', function () { return readCsv(filenameEndusers); }); -/** - * SharedArray variable that stores the end users with tokens data. - * The data is parsed from the CSV file specified by the filenameEndusersWithTokens variable. - * - * @name endUsersWithTokens - * @type {SharedArray} - */ -export const endUsersWithTokens = new SharedArray('endUsersWithTokens', function () { - return readCsv(filenameEndusersWithTokens); -}); diff --git a/tests/k6/tests/performancetest_common/simpleSearch.js b/tests/k6/tests/performancetest_common/simpleSearch.js index 0826ad0dc..b39f6470f 100644 --- a/tests/k6/tests/performancetest_common/simpleSearch.js +++ b/tests/k6/tests/performancetest_common/simpleSearch.js @@ -7,6 +7,7 @@ import { expect, expectStatusFor } from "../../common/testimports.js"; import { describe } from '../../common/describe.js'; import { getEU, postGQ, getSO } from '../../common/request.js'; import { getGraphqlParty } from '../performancetest_data/graphql-search.js'; +import { getEnterpriseToken, getPersonalToken } from './getTokens.js'; /** * Retrieves the content for a dialog. @@ -20,7 +21,6 @@ function retrieveDialogContent(response, paramsWithToken, getFunction = getEU) { if (!items?.length) return; const dialogId = items[0].id; if (!dialogId) return; - console.log("Found dialog with id " + dialogId); getContent(dialogId, paramsWithToken, 'get dialog', '', getFunction); getContentChain(dialogId, paramsWithToken, 'get dialog activities', 'get dialog activity', '/activities/', getFunction); getContentChain(dialogId, paramsWithToken, 'get seenlogs', 'get seenlog', '/seenlog/', getFunction); @@ -45,7 +45,7 @@ export function enduserSearch(enduser, traceCalls) { var traceparent = uuidv4(); let paramsWithToken = { headers: { - Authorization: "Bearer " + enduser.token, + Authorization: "Bearer " + getPersonalToken(enduser), traceparent: traceparent }, tags: { name: 'enduser search' } @@ -99,7 +99,6 @@ export function getContentChain(dialogId, paramsWithToken, tag, subtag, endpoint }; let d = getUrl('dialogs/' + dialogId + endpoint, listParams, getFunction); let json = d.json(); - console.log("Found " + json.length + " " + tag + " for endpoint " + dialogId + endpoint); if (json.length > 0) { const detailParams = { ...paramsWithToken, @@ -133,7 +132,7 @@ export function graphqlSearch(enduser, traceCalls) { let traceparent = uuidv4(); let paramsWithToken = { headers: { - Authorization: "Bearer " + enduser.token, + Authorization: "Bearer " + getPersonalToken(enduser), traceparent: traceparent, 'User-Agent': 'dialogporten-k6-graphql-search' }, @@ -161,7 +160,7 @@ export function serviceownerSearch(serviceowner, enduser, tag_name, traceCalls, let traceparent = uuidv4(); let paramsWithToken = { headers: { - Authorization: "Bearer " + serviceowner.token, + Authorization: "Bearer " + getEnterpriseToken(serviceowner), traceparent: traceparent }, tags: { name: tag_name } From 5b959baf6d6eec68070a02d5a0d27e8ea7bcde59 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 13:13:42 +0100 Subject: [PATCH 05/16] fix workflows --- .github/workflows/ci-cd-yt01.yml | 4 ---- .github/workflows/dispatch-k6-performance.yml | 13 ------------- .../workflows/workflow-run-k6-performance.yml | 19 ------------------- .../performancetest_data/01-create-dialog.js | 8 -------- 4 files changed, 44 deletions(-) diff --git a/.github/workflows/ci-cd-yt01.yml b/.github/workflows/ci-cd-yt01.yml index a047d1a68..74a8f5df3 100644 --- a/.github/workflows/ci-cd-yt01.yml +++ b/.github/workflows/ci-cd-yt01.yml @@ -150,8 +150,6 @@ jobs: secrets: TOKEN_GENERATOR_USERNAME: ${{ secrets.TOKEN_GENERATOR_USERNAME }} TOKEN_GENERATOR_PASSWORD: ${{ secrets.TOKEN_GENERATOR_PASSWORD }} - K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }} - K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }} strategy: max-parallel: 1 @@ -166,8 +164,6 @@ jobs: apiVersion: v1 vus: 1 duration: 30s - tokens: both - numberOfTokens: 100 testSuitePath: ${{ matrix.files }} permissions: checks: write diff --git a/.github/workflows/dispatch-k6-performance.yml b/.github/workflows/dispatch-k6-performance.yml index 87dbd26a8..866b5980a 100644 --- a/.github/workflows/dispatch-k6-performance.yml +++ b/.github/workflows/dispatch-k6-performance.yml @@ -16,16 +16,6 @@ on: - test - staging - yt01 - tokens: - description: 'Tokens to generate; for create dialog, search, none, or both' - required: true - default: 'both' - type: choice - options: - - both - - enterprise - - personal - - none tag: description: 'tag the performance test' required: true @@ -61,13 +51,10 @@ jobs: secrets: TOKEN_GENERATOR_USERNAME: ${{ secrets.TOKEN_GENERATOR_USERNAME }} TOKEN_GENERATOR_PASSWORD: ${{ secrets.TOKEN_GENERATOR_PASSWORD }} - K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }} - K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }} with: environment: ${{ inputs.environment }} apiVersion: ${{ inputs.apiVersion }} testSuitePath: ${{ inputs.testSuitePath }} vus: ${{ fromJson(inputs.vus) }} duration: ${{ inputs.duration }} - tokens: ${{ inputs.tokens }} diff --git a/.github/workflows/workflow-run-k6-performance.yml b/.github/workflows/workflow-run-k6-performance.yml index 88a839e6c..23a320adc 100644 --- a/.github/workflows/workflow-run-k6-performance.yml +++ b/.github/workflows/workflow-run-k6-performance.yml @@ -18,27 +18,11 @@ on: duration: required: true type: string - tokens: - required: true - type: string - numberOfTokens: - required: false - type: number - default: 0 - ttl: - required: false - type: number - default: 3600 secrets: TOKEN_GENERATOR_USERNAME: required: true TOKEN_GENERATOR_PASSWORD: required: true - K6_CLOUD_TOKEN: - required: true - K6_CLOUD_PROJECT_ID: - required: true - jobs: k6-test: runs-on: ubuntu-latest @@ -53,7 +37,6 @@ jobs: uses: grafana/setup-k6-action@v1 - name: Run K6 tests (${{ inputs.testSuitePath }}) run: | - ./tests/k6/tests/scripts/generate_tokens.sh ./tests/k6/tests/performancetest_data ${{ inputs.tokens }} ${{ inputs.numberOfTokens }} ${{ inputs.ttl }} echo "Running k6 test suite ${{ inputs.testSuitePath }} with ${{ inputs.vus }} VUs for ${{ inputs.duration }}" k6 run ${{ inputs.testSuitePath }} --quiet --log-output=stdout --include-system-env-vars \ --vus=${{ inputs.vus }} --duration=${{ inputs.duration }} --out csv=./results.csv @@ -63,5 +46,3 @@ jobs: API_VERSION: ${{ inputs.apiVersion }} TOKEN_GENERATOR_USERNAME: ${{ secrets.TOKEN_GENERATOR_USERNAME }} TOKEN_GENERATOR_PASSWORD: ${{ secrets.TOKEN_GENERATOR_PASSWORD }} - K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }} - K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }} diff --git a/tests/k6/tests/performancetest_data/01-create-dialog.js b/tests/k6/tests/performancetest_data/01-create-dialog.js index b444afa93..cd467a456 100644 --- a/tests/k6/tests/performancetest_data/01-create-dialog.js +++ b/tests/k6/tests/performancetest_data/01-create-dialog.js @@ -55,13 +55,5 @@ export default function (endUser, resource) { payload.serviceResource = "urn:altinn:resource:" +resource; payload.party = "urn:altinn:person:identifier-no:" + endUser; - // const firstTransmission = payload.transmissions[0]; - // const copyOfFirstTransmission = { ...firstTransmission }; - // for (let i = 0; i < 155; i++) { - // payload.transmissions.push(copyOfFirstTransmission); - // } - // console.log(payload.transmissions.length); - // console.log(endUser, resource); - return cleanUp(payload); } From 43f145bbd8056e293df503daa998b74f955e70a1 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 13:29:27 +0100 Subject: [PATCH 06/16] do not use endUsersWithTokens anymore --- tests/k6/tests/enduser/performance/enduser-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/k6/tests/enduser/performance/enduser-search.js b/tests/k6/tests/enduser/performance/enduser-search.js index 306f21586..ed20030e1 100644 --- a/tests/k6/tests/enduser/performance/enduser-search.js +++ b/tests/k6/tests/enduser/performance/enduser-search.js @@ -28,7 +28,7 @@ export default function() { enduserSearch(endUsers[0], traceCalls); } else { - for (let i = 0; i < endUsersWithTokens.length; i++) { + for (let i = 0; i < endUsers.length; i++) { enduserSearch(endUsers[i], traceCalls); } } From 63d32caa46bf352365f96dab219b253c4d2ca04e Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 13:33:36 +0100 Subject: [PATCH 07/16] do not use endUsersWithTokens anymore --- tests/k6/tests/graphql/performance/graphql-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/k6/tests/graphql/performance/graphql-search.js b/tests/k6/tests/graphql/performance/graphql-search.js index d634dbfc9..b9eeaab7a 100644 --- a/tests/k6/tests/graphql/performance/graphql-search.js +++ b/tests/k6/tests/graphql/performance/graphql-search.js @@ -4,7 +4,7 @@ */ import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js'; -import { endUsersWithTokens as endUsers } from '../../performancetest_common/readTestdata.js'; +import { endUsers } from '../../performancetest_common/readTestdata.js'; import { graphqlSearch } from "../../performancetest_common/simpleSearch.js"; const isSingleUserMode = (__ENV.isSingleUserMode ?? 'false') === 'true'; From ba5ff24407dc9f846eacfd0b22f221e57d5afa27 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 14:02:15 +0100 Subject: [PATCH 08/16] removed some debug --- tests/k6/tests/performancetest_common/createDialog.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index fafeae817..b0a9b82c3 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -104,7 +104,6 @@ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfT expect(r.status, 'response status').to.equal(201); }); - console.log(dialogId); let relatedTransmissionId = 0; for (let i = 0; i < numberOfTransmissions; i++) { @@ -126,15 +125,9 @@ export function createTransmission(dialogId, relatedTransmissionId, serviceOwner }, tags: { name: 'create transmission' } }; - describe('create transmission', () => { - if (relatedTransmissionId == 0) { - console.log('creating new transmission-thread'); - } - let r = postSO('dialogs/' + dialogId + '/transmissions', transmissionToInsert(relatedTransmissionId), paramsWithToken); - console.log(r.body); expect(r.status, 'response status').to.equal(201); return r.json(); }); From 80c4801cd440e795d9706a7f922dc91c115374eb Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 7 Jan 2025 14:21:28 +0100 Subject: [PATCH 09/16] TTL env variable and added create-transmissions to dispatch menu --- .github/workflows/dispatch-k6-performance.yml | 1 + tests/k6/tests/performancetest_common/getTokens.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dispatch-k6-performance.yml b/.github/workflows/dispatch-k6-performance.yml index 866b5980a..020d1299a 100644 --- a/.github/workflows/dispatch-k6-performance.yml +++ b/.github/workflows/dispatch-k6-performance.yml @@ -42,6 +42,7 @@ on: - 'tests/k6/tests/serviceowner/performance/serviceowner-search.js' - 'tests/k6/tests/enduser/performance/enduser-search.js' - 'tests/k6/tests/graphql/performance/graphql-search.js' + - 'tests/k6/tests/serviceowner/performance/create-transmissions.js' run-name: ${{ inputs.tag }} vus ${{ inputs.vus }} duration ${{ inputs.duration }} jobs: diff --git a/tests/k6/tests/performancetest_common/getTokens.js b/tests/k6/tests/performancetest_common/getTokens.js index 7dc73858f..cb45573a4 100644 --- a/tests/k6/tests/performancetest_common/getTokens.js +++ b/tests/k6/tests/performancetest_common/getTokens.js @@ -1,7 +1,7 @@ import { fetchToken } from "../../common/token.js"; const tokenGeneratorEnv = __ENV.API_ENVIRONMENT || 'yt01'; -const tokenTtl = 3600 +const tokenTtl = __ENV.TTL || 3600; export function getEnterpriseToken(serviceOwner) { var tokenOptions = { From aa658af8fa5bf108a0f8bf6a932334304de3928e Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Wed, 8 Jan 2025 06:10:19 +0100 Subject: [PATCH 10/16] configurable number og transmissions per thread --- tests/k6/tests/performancetest_common/createDialog.js | 5 +++-- .../serviceowner/performance/create-transmissions.js | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index b0a9b82c3..4e7c60403 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -82,7 +82,7 @@ export function createAndRemoveDialog(serviceOwner, endUser, traceCalls) { * @param {Object} serviceOwner - The service owner object. * @param {Object} endUser - The end user object. */ -export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions) { +export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread) { var traceparent = uuidv4(); var paramsWithToken = { @@ -108,7 +108,8 @@ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfT for (let i = 0; i < numberOfTransmissions; i++) { relatedTransmissionId = createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls); - if (i%100 === 0) { + // Max transmissions in thread reached, start new thread + if (i%maxTransmissionsInThread === 0) { relatedTransmissionId = 0; } } diff --git a/tests/k6/tests/serviceowner/performance/create-transmissions.js b/tests/k6/tests/serviceowner/performance/create-transmissions.js index af268336e..9879c4987 100644 --- a/tests/k6/tests/serviceowner/performance/create-transmissions.js +++ b/tests/k6/tests/serviceowner/performance/create-transmissions.js @@ -1,6 +1,6 @@ /** - * Performance test for creating a dialog - * Run: k6 run tests/k6/tests/serviceowner/performance/create-dialog.js --vus 1 --iterations 1 + * Performance test for creating dialogs with transmissions + * Run: k6 run tests/k6/tests/serviceowner/performance/create-transmissions.js --vus 1 --iterations 1 -e numberOfTransmissions=100 */ import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js'; @@ -15,6 +15,7 @@ export let options = { const isSingleUserMode = (__ENV.isSingleUserMode ?? 'false') === 'true'; const traceCalls = (__ENV.traceCalls ?? 'false') === 'true'; const numberOfTransmissions = (__ENV.numberOfTransmissions ?? '10'); +const maxTransmissionsInThread = (__ENV.maxTransmissionsInThread ?? '100'); export default function() { if (!endUsers || endUsers.length === 0) { @@ -25,12 +26,12 @@ export default function() { } if (isSingleUserMode) { - createTransmissions(serviceOwners[0], endUsers[0], traceCalls, numberOfTransmissions); + createTransmissions(serviceOwners[0], endUsers[0], traceCalls, numberOfTransmissions, maxTransmissionsInThread); } else { let serviceOwner = randomItem(serviceOwners); for (let i = 0; i < endUsers.length; i++) { - createTransmissions(serviceOwner, endUsers[i], traceCalls, numberOfTransmissions); + createTransmissions(serviceOwner, endUsers[i], traceCalls, numberOfTransmissions, maxTransmissionsInThread); } } } From 90f408be872a32918099e949a85d2589d097a907 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Wed, 8 Jan 2025 06:44:33 +0100 Subject: [PATCH 11/16] fix according to sonarqube --- tests/k6/tests/performancetest_common/createDialog.js | 8 ++++---- tests/k6/tests/performancetest_common/getTokens.js | 4 ++-- .../serviceowner/performance/create-transmissions.js | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index 4e7c60403..aa5fa8966 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -83,9 +83,9 @@ export function createAndRemoveDialog(serviceOwner, endUser, traceCalls) { * @param {Object} endUser - The end user object. */ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread) { - var traceparent = uuidv4(); + let traceparent = uuidv4(); - var paramsWithToken = { + let paramsWithToken = { headers: { Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent @@ -117,9 +117,9 @@ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfT } export function createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls) { - var traceparent = uuidv4(); + let traceparent = uuidv4(); - var paramsWithToken = { + let paramsWithToken = { headers: { Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent diff --git a/tests/k6/tests/performancetest_common/getTokens.js b/tests/k6/tests/performancetest_common/getTokens.js index cb45573a4..b1aeaeb6b 100644 --- a/tests/k6/tests/performancetest_common/getTokens.js +++ b/tests/k6/tests/performancetest_common/getTokens.js @@ -4,7 +4,7 @@ const tokenGeneratorEnv = __ENV.API_ENVIRONMENT || 'yt01'; const tokenTtl = __ENV.TTL || 3600; export function getEnterpriseToken(serviceOwner) { - var tokenOptions = { + const tokenOptions = { scopes: serviceOwner.scopes, orgName: serviceOwner.org, orgNo: serviceOwner.orgno @@ -14,7 +14,7 @@ export function getEnterpriseToken(serviceOwner) { } export function getPersonalToken(endUser) { - var tokenOptions = { + const tokenOptions = { scopes: endUser.scopes, ssn: endUser.ssn } diff --git a/tests/k6/tests/serviceowner/performance/create-transmissions.js b/tests/k6/tests/serviceowner/performance/create-transmissions.js index 9879c4987..393c127ed 100644 --- a/tests/k6/tests/serviceowner/performance/create-transmissions.js +++ b/tests/k6/tests/serviceowner/performance/create-transmissions.js @@ -7,7 +7,7 @@ import { getDefaultThresholds } from '../../performancetest_common/getDefaultThr import { createTransmissions } from '../../performancetest_common/createDialog.js'; import { serviceOwners, endUsers } from '../../performancetest_common/readTestdata.js'; -export let options = { +export const options = { summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'], thresholds: getDefaultThresholds(['http_req_duration', 'http_reqs'],['create dialog', 'create transmission']) }; @@ -30,9 +30,9 @@ export default function() { } else { let serviceOwner = randomItem(serviceOwners); - for (let i = 0; i < endUsers.length; i++) { - createTransmissions(serviceOwner, endUsers[i], traceCalls, numberOfTransmissions, maxTransmissionsInThread); - } + for (const endUser of endUsers) { + createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread); + } } } From 776b76b41f4cd63458fd676043b8ab2601ae582a Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Wed, 8 Jan 2025 07:43:12 +0100 Subject: [PATCH 12/16] fixes suggested by coderabbit --- .../graphql/performance/graphql-search.js | 2 +- .../performancetest_common/createDialog.js | 4 +- .../tests/performancetest_common/getTokens.js | 4 +- .../create-transmission.js | 6 +- tests/k6/tests/scripts/run-test-in-k8s.sh | 57 +++++++++++++++---- 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/tests/k6/tests/graphql/performance/graphql-search.js b/tests/k6/tests/graphql/performance/graphql-search.js index b9eeaab7a..91a615788 100644 --- a/tests/k6/tests/graphql/performance/graphql-search.js +++ b/tests/k6/tests/graphql/performance/graphql-search.js @@ -17,7 +17,7 @@ const traceCalls = (__ENV.traceCalls ?? 'false') === 'true'; * @property {string[]} summaryTrendStats - The summary trend statistics to include in the test results. * @property {object} thresholds - The thresholds for the test metrics. */ -export let options = { +export const options = { summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'], thresholds: getDefaultThresholds(['http_req_duration', 'http_reqs'],['graphql search']) }; diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index aa5fa8966..a1eaf5aa6 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -127,10 +127,12 @@ export function createTransmission(dialogId, relatedTransmissionId, serviceOwner tags: { name: 'create transmission' } }; + let newRelatedTransmissionId; describe('create transmission', () => { let r = postSO('dialogs/' + dialogId + '/transmissions', transmissionToInsert(relatedTransmissionId), paramsWithToken); expect(r.status, 'response status').to.equal(201); - return r.json(); + newRelatedTransmissionId = r.json(); }); + return newRelatedTransmissionId; } diff --git a/tests/k6/tests/performancetest_common/getTokens.js b/tests/k6/tests/performancetest_common/getTokens.js index b1aeaeb6b..20a49cd46 100644 --- a/tests/k6/tests/performancetest_common/getTokens.js +++ b/tests/k6/tests/performancetest_common/getTokens.js @@ -9,7 +9,7 @@ export function getEnterpriseToken(serviceOwner) { orgName: serviceOwner.org, orgNo: serviceOwner.orgno } - const url = `http://altinn-testtools-token-generator.azurewebsites.net/api/GetEnterpriseToken?env=${tokenGeneratorEnv}&scopes=${encodeURIComponent(tokenOptions.scopes)}&org=${tokenOptions.orgName}&orgNo=${tokenOptions.orgNo}&ttl=${tokenTtl}`; + const url = `https://altinn-testtools-token-generator.azurewebsites.net/api/GetEnterpriseToken?env=${tokenGeneratorEnv}&scopes=${encodeURIComponent(tokenOptions.scopes)}&org=${tokenOptions.orgName}&orgNo=${tokenOptions.orgNo}&ttl=${tokenTtl}`; return fetchToken(url, tokenOptions, `service owner (orgno:${tokenOptions.orgNo} orgName:${tokenOptions.orgName} tokenGeneratorEnv:${tokenGeneratorEnv})`); } @@ -18,6 +18,6 @@ export function getPersonalToken(endUser) { scopes: endUser.scopes, ssn: endUser.ssn } - const url = `http://altinn-testtools-token-generator.azurewebsites.net/api/GetPersonalToken?env=${tokenGeneratorEnv}&scopes=${encodeURIComponent(tokenOptions.scopes)}&pid=${tokenOptions.ssn}&ttl=${tokenTtl}`; + const url = `https://altinn-testtools-token-generator.azurewebsites.net/api/GetPersonalToken?env=${tokenGeneratorEnv}&scopes=${encodeURIComponent(tokenOptions.scopes)}&pid=${tokenOptions.ssn}&ttl=${tokenTtl}`; return fetchToken(url, tokenOptions, `end user (ssn:${tokenOptions.ssn}, tokenGeneratorEnv:${tokenGeneratorEnv})`); } diff --git a/tests/k6/tests/performancetest_data/create-transmission.js b/tests/k6/tests/performancetest_data/create-transmission.js index 927e917e7..cf7413475 100644 --- a/tests/k6/tests/performancetest_data/create-transmission.js +++ b/tests/k6/tests/performancetest_data/create-transmission.js @@ -1,10 +1,10 @@ -import { uuidv4 } from "../../common/uuid.js"; +import { uuidv7 } from "../../common/uuid.js"; export default function (relatedTransmissionId) { let transmission = { - "id": uuidv4, - "createdAt": "2024-12-13T12:29:04.540Z", + "id": uuidv7(), + "createdAt": new Date().toISOString(), "authorizationAttribute": "element1", "extendedType": "string", "type": "Information", diff --git a/tests/k6/tests/scripts/run-test-in-k8s.sh b/tests/k6/tests/scripts/run-test-in-k8s.sh index 3a5452a75..15f4d1a08 100755 --- a/tests/k6/tests/scripts/run-test-in-k8s.sh +++ b/tests/k6/tests/scripts/run-test-in-k8s.sh @@ -3,6 +3,12 @@ tokengenuser=${TOKEN_GENERATOR_USERNAME} tokengenpasswd=${TOKEN_GENERATOR_PASSWORD} +# Validate required environment variables +if [ -z "$TOKEN_GENERATOR_USERNAME" ] || [ -z "$TOKEN_GENERATOR_PASSWORD" ]; then + echo "Error: TOKEN_GENERATOR_USERNAME and TOKEN_GENERATOR_PASSWORD must be set" + exit 1 +fi + help() { echo "Usage: $0 [OPTIONS]" echo "Options:" @@ -18,9 +24,14 @@ help() { print_logs() { POD_LABEL="k6-test=$name" - K8S_CONTEXT="k6tests-cluster" - K8S_NAMESPACE="default" - + K8S_CONTEXT="${K8S_CONTEXT:-k6tests-cluster}" + K8S_NAMESPACE="${K8S_NAMESPACE:-default}" + LOG_TIMEOUT="${LOG_TIMEOUT:-60}" + # Verify kubectl access + if ! kubectl --context "$K8S_CONTEXT" -n "$K8S_NAMESPACE" get pods &>/dev/null; then + echo "Error: Failed to access Kubernetes cluster" + return 1 + fi for pod in $(kubectl --context "$K8S_CONTEXT" -n "$K8S_NAMESPACE" get pods -l "$POD_LABEL" -o name); do if [[ $pod != *"initializer"* ]]; then echo --------------------------- @@ -68,6 +79,21 @@ while [[ $# -gt 0 ]]; do esac done +# Validate required arguments +missing_args=() +[ -z "$filename" ] && missing_args+=("filename (-f)") +[ -z "$configmapname" ] && missing_args+=("configmapname (-c)") +[ -z "$name" ] && missing_args+=("name (-n)") +[ -z "$vus" ] && missing_args+=("vus (-v)") +[ -z "$duration" ] && missing_args+=("duration (-d)") +[ -z "$parallelism" ] && missing_args+=("parallelism (-p)") + +if [ ${#missing_args[@]} -ne 0 ]; then + echo "Error: Missing required arguments: ${missing_args[*]}" + help + exit 1 +fi + k6 archive $filename -e API_VERSION=v1 -e API_ENVIRONMENT=yt01 -e TOKEN_GENERATOR_USERNAME=$tokengenuser -e TOKEN_GENERATOR_PASSWORD=$tokengenpasswd # Create configmap from archive.tar kubectl create configmap $configmapname --from-file=archive.tar @@ -102,11 +128,22 @@ kubectl --context k6tests-cluster wait --for=jsonpath='{.status.stage}'=finished # Print the logs of the pods print_logs -# Delete the search-dialog.yml configuration -kubectl delete -f config.yml - -# Delete the configmap -kubectl delete configmap $configmapname -# Delete the archive.tar and the config.yml files -rm archive.tar config.yml \ No newline at end of file +cleanup() { + local exit_code=$? + echo "Cleaning up resources..." + + if [ -f "config.yml" ]; then + kubectl delete -f config.yml --ignore-not-found || true + rm -f config.yml + fi + + if kubectl get configmap $configmapname &>/dev/null; then + kubectl delete configmap $configmapname --ignore-not-found || true + fi + + rm -f archive.tar + + exit $exit_code +} +trap cleanup EXIT \ No newline at end of file From 61ac85330ad15326b1578e811256630a73db56e3 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Wed, 8 Jan 2025 07:53:16 +0100 Subject: [PATCH 13/16] fixes suggested by coderabbit --- tests/k6/tests/scripts/run-test-in-k8s.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/k6/tests/scripts/run-test-in-k8s.sh b/tests/k6/tests/scripts/run-test-in-k8s.sh index 15f4d1a08..c86590f98 100755 --- a/tests/k6/tests/scripts/run-test-in-k8s.sh +++ b/tests/k6/tests/scripts/run-test-in-k8s.sh @@ -94,9 +94,17 @@ if [ ${#missing_args[@]} -ne 0 ]; then exit 1 fi -k6 archive $filename -e API_VERSION=v1 -e API_ENVIRONMENT=yt01 -e TOKEN_GENERATOR_USERNAME=$tokengenuser -e TOKEN_GENERATOR_PASSWORD=$tokengenpasswd -# Create configmap from archive.tar -kubectl create configmap $configmapname --from-file=archive.tar +# Create the k6 archive +if ! k6 archive $filename -e API_VERSION=v1 -e API_ENVIRONMENT=yt01 -e TOKEN_GENERATOR_USERNAME=$tokengenuser -e TOKEN_GENERATOR_PASSWORD=$tokengenpasswd; then + echo "Error: Failed to create k6 archive" + exit 1 +fi +# Create the configmap from the archive +if ! kubectl create configmap $configmapname --from-file=archive.tar; then + echo "Error: Failed to create configmap" + rm archive.tar + exit 1 +fi # Create the config.yml file from a string cat < config.yml From 636757666c2a25c5112d2efe6e51d110aae51e19 Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Wed, 8 Jan 2025 13:31:42 +0100 Subject: [PATCH 14/16] added testid --- .../k6/tests/performancetest_common/createDialog.js | 12 ++++++------ tests/k6/tests/scripts/run-test-in-k8s.sh | 7 ++++++- .../serviceowner/performance/create-transmissions.js | 6 +++--- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/k6/tests/performancetest_common/createDialog.js b/tests/k6/tests/performancetest_common/createDialog.js index a1eaf5aa6..08e9d32e1 100644 --- a/tests/k6/tests/performancetest_common/createDialog.js +++ b/tests/k6/tests/performancetest_common/createDialog.js @@ -82,15 +82,15 @@ export function createAndRemoveDialog(serviceOwner, endUser, traceCalls) { * @param {Object} serviceOwner - The service owner object. * @param {Object} endUser - The end user object. */ -export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread) { +export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread, testid) { let traceparent = uuidv4(); - + let paramsWithToken = { headers: { Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent }, - tags: { name: 'create dialog' } + tags: { name: 'create dialog', testid: testid } }; if (traceCalls) { paramsWithToken.tags.traceparent = traceparent; @@ -107,7 +107,7 @@ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfT let relatedTransmissionId = 0; for (let i = 0; i < numberOfTransmissions; i++) { - relatedTransmissionId = createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls); + relatedTransmissionId = createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls, testid); // Max transmissions in thread reached, start new thread if (i%maxTransmissionsInThread === 0) { relatedTransmissionId = 0; @@ -116,7 +116,7 @@ export function createTransmissions(serviceOwner, endUser, traceCalls, numberOfT } -export function createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls) { +export function createTransmission(dialogId, relatedTransmissionId, serviceOwner, traceCalls, testid) { let traceparent = uuidv4(); let paramsWithToken = { @@ -124,7 +124,7 @@ export function createTransmission(dialogId, relatedTransmissionId, serviceOwner Authorization: "Bearer " + getEnterpriseToken(serviceOwner), traceparent: traceparent }, - tags: { name: 'create transmission' } + tags: { name: 'create transmission', testid: testid } }; let newRelatedTransmissionId; diff --git a/tests/k6/tests/scripts/run-test-in-k8s.sh b/tests/k6/tests/scripts/run-test-in-k8s.sh index c86590f98..0873f5a4d 100755 --- a/tests/k6/tests/scripts/run-test-in-k8s.sh +++ b/tests/k6/tests/scripts/run-test-in-k8s.sh @@ -93,9 +93,11 @@ if [ ${#missing_args[@]} -ne 0 ]; then help exit 1 fi +# Set testid to name + timestamp +testid="${name}_$(date '+%Y%m%dT%H%M%S')" # Create the k6 archive -if ! k6 archive $filename -e API_VERSION=v1 -e API_ENVIRONMENT=yt01 -e TOKEN_GENERATOR_USERNAME=$tokengenuser -e TOKEN_GENERATOR_PASSWORD=$tokengenpasswd; then +if ! k6 archive $filename -e API_VERSION=v1 -e API_ENVIRONMENT=yt01 -e TOKEN_GENERATOR_USERNAME=$tokengenuser -e TOKEN_GENERATOR_PASSWORD=$tokengenpasswd -e TESTID=$testid; then echo "Error: Failed to create k6 archive" exit 1 fi @@ -123,9 +125,12 @@ spec: env: - name: K6_PROMETHEUS_RW_SERVER_URL value: "http://kube-prometheus-stack-prometheus.monitoring:9090/api/v1/write" + - name: K6_PROMETHEUS_RW_TREND_STATS + value: "avg,min,med,max,p(95),p(99),p(99.5),p(99.9),count" metadata: labels: k6-test: $name + EOF # Apply the config.yml configuration kubectl apply -f config.yml diff --git a/tests/k6/tests/serviceowner/performance/create-transmissions.js b/tests/k6/tests/serviceowner/performance/create-transmissions.js index 393c127ed..00380fd97 100644 --- a/tests/k6/tests/serviceowner/performance/create-transmissions.js +++ b/tests/k6/tests/serviceowner/performance/create-transmissions.js @@ -16,6 +16,7 @@ const isSingleUserMode = (__ENV.isSingleUserMode ?? 'false') === 'true'; const traceCalls = (__ENV.traceCalls ?? 'false') === 'true'; const numberOfTransmissions = (__ENV.numberOfTransmissions ?? '10'); const maxTransmissionsInThread = (__ENV.maxTransmissionsInThread ?? '100'); +const testid = (__ENV.TESTID ?? 'createTransmissions'); export default function() { if (!endUsers || endUsers.length === 0) { @@ -24,14 +25,13 @@ export default function() { if (!serviceOwners || serviceOwners.length === 0) { throw new Error('No service owners loaded for testing'); } - if (isSingleUserMode) { - createTransmissions(serviceOwners[0], endUsers[0], traceCalls, numberOfTransmissions, maxTransmissionsInThread); + createTransmissions(serviceOwners[0], endUsers[0], traceCalls, numberOfTransmissions, maxTransmissionsInThread, testid); } else { let serviceOwner = randomItem(serviceOwners); for (const endUser of endUsers) { - createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread); + createTransmissions(serviceOwner, endUser, traceCalls, numberOfTransmissions, maxTransmissionsInThread, testid); } } } From 632ee73e04862b579261f0edc99e07792d0a8e9e Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 14 Jan 2025 08:06:27 +0100 Subject: [PATCH 15/16] Fix readmes and remove generate_tokens.sh --- README.md | 2 +- tests/k6/README.md | 8 ++ tests/k6/tests/enduser/performance/README.md | 29 ++--- tests/k6/tests/graphql/performance/README.md | 27 +---- tests/k6/tests/scripts/generate_tokens.sh | 111 ------------------ .../tests/serviceowner/performance/README.md | 31 ++--- 6 files changed, 30 insertions(+), 178 deletions(-) delete mode 100755 tests/k6/tests/scripts/generate_tokens.sh diff --git a/README.md b/README.md index 2b85f2a90..0e76ffc63 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ dotnet ef migrations add TestMigration Besides ordinary unit and integration tests, there are test suites for both functional and non-functional end-to-end tests implemented with [K6](https://k6.io/). -See `tests/k6/README.md` for more information. +See [tests/k6/README.md](tests/k6/README.md) for more information. ## Health Checks diff --git a/tests/k6/README.md b/tests/k6/README.md index b47da07df..c2d043be8 100644 --- a/tests/k6/README.md +++ b/tests/k6/README.md @@ -23,6 +23,14 @@ Run `Get-Help .\run.ps1` or `./run.sh --help` for usage information. The scripts will use locally installed `k6` if available. Failing that, it will attempt to use Docker with [grafana/k6](https://hub.docker.com/r/grafana/k6) +## Performance tests + +For information about the performance tests, see the following README files: + +- [ServiceOwner](tests/serviceowner/performance/README.md) +- [GraphQL](tests/graphql/performance/README.md) +- [EndUser](tests/enduser/performance/README.md) + ## Test suites Various test suites are defined withing the `suites` directory. A suite consists of diff --git a/tests/k6/tests/enduser/performance/README.md b/tests/k6/tests/enduser/performance/README.md index 0a88e425a..9a9810e36 100644 --- a/tests/k6/tests/enduser/performance/README.md +++ b/tests/k6/tests/enduser/performance/README.md @@ -10,7 +10,7 @@ The test file associated with this performance test is - `enduser-search.js` ## Test description -The test has a list of enduser (ssn) with pre-generated tokens, and the following endpoints are visited in +The test has a list of enduser (ssn), and the following endpoints are visited in sequence for each enduser: - api/v1/enduser/dialogs?Party=urn:altinn:person:identifier-no:`` - api/v1/enduser/dialogs/`` @@ -28,19 +28,14 @@ sequence for each enduser: ```shell cd tests/k6/tests/enduser/performance ``` -2. Generate tokens using the script below. Make sure to replace ``, `` and `` with your desired values: -```shell -TOKEN_GENERATOR_USERNAME= \ -TOKEN_GENERATOR_PASSWORD= API_ENVIRONMENT= \ -../../scripts/generate_tokens.sh ../../performancetest_data personal -``` -3. Run the test using the following command. Replace ``, ``, and `` with the desired values: +2. Run the test using the following command. Replace ``, ``, and `` with the desired values: ```shell +TOKEN_GENERATOR_USERNAME= TOKEN_GENERATOR_PASSWORD= \ k6 run enduser-search.js -e API_VERSION=v1 \ -e API_ENVIRONMENT= \ --vus= --duration= ``` -4. Refer to the k6 documentation for more information on usage. +3. Refer to the k6 documentation for more information on usage. ### From GitHub Actions To run the performance test using GitHub Actions, follow these steps: @@ -56,26 +51,16 @@ To run the performance test locally using GitHub Actions and act, perform the fo ```file TOKEN_GENERATOR_USERNAME: TOKEN_GENERATOR_PASSWORD: -K6_CLOUD_PROJECT_ID=** -K6_CLOUD_TOKEN=** -K6_PROMETHEUS_RW_USERNAME=** -K6_PROMETHEUS_RW_PASSWORD=** -K6_PROMETHEUS_RW_SERVER_URL=** ``` - Replace `` and ``, same as for generating tokens above. Fill in the K6_* values if available, - used for reporting to Grafana cloud + Replace `` and ``, same as for generating tokens above. ##### IMPORTANT: Ensure this file is added to .gitignore to prevent accidental commits of sensitive information. Never commit actual credentials to version control. 4. Run `act` using the command below. Replace `` and `` with the desired values: ```shell act workflow_dispatch -j k6-performance -s GITHUB_TOKEN=`gh auth token` \ --container-architecture linux/amd64 --artifact-server-path $HOME/.act \ --input vus= --input duration= \ ---input testSuitePath=tests/k6/tests/enduser/performance/enduser-search.js \ ---input tokens=personal +--input testSuitePath=tests/k6/tests/enduser/performance/enduser-search.js ``` ## Test Results -Test results can be found in GitHub action run log and in App Insights. We are prepared for exporting results to grafana, but so far results are exported to a private grafana instance only, as can be seen from the `.secrets`listed earlier - -## TODO -Fix reporting +Test results can be found in GitHub action run log, grafana and in App Insights. diff --git a/tests/k6/tests/graphql/performance/README.md b/tests/k6/tests/graphql/performance/README.md index 0faa92506..011f45af3 100644 --- a/tests/k6/tests/graphql/performance/README.md +++ b/tests/k6/tests/graphql/performance/README.md @@ -15,19 +15,14 @@ The test file associated with this performance test is ```shell cd tests/k6/tests/graphql/performance ``` -2. Generate tokens using the script below. Make sure to replace ``, `` and `()` with your desired values: -```shell -TOKEN_GENERATOR_USERNAME= \ -TOKEN_GENERATOR_PASSWORD= API_ENVIRONMENT=<(test|staging|yt01)> \ -../../scripts/generate_tokens.sh ../../performancetest_data personal -``` -3. Run the test using the following command. Replace `<(test|staging|yt01)>`, ``, and `` with the desired values: +2. Run the test using the following command. Replace `<(test|staging|yt01)>`, ``, and `` with the desired values: ```shell +TOKEN_GENERATOR_USERNAME= TOKEN_GENERATOR_PASSWORD= \ k6 run graphql-search.js -e API_VERSION=v1 \ -e API_ENVIRONMENT=<(test|staging|yt01)> \ --vus= --duration= ``` -4. Refer to the k6 documentation for more information on usage. +3. Refer to the k6 documentation for more information on usage. ### From GitHub Actions To run the performance test using GitHub Actions, follow these steps: 1. Go to the [GitHub Actions](https://github.com/digdir/dialogporten/actions/workflows/dispatch-k6-performance.yml) page. @@ -42,26 +37,16 @@ To run the performance test locally using GitHub Actions and act, perform the fo ```file TOKEN_GENERATOR_USERNAME: TOKEN_GENERATOR_PASSWORD: -K6_CLOUD_PROJECT_ID=** -K6_CLOUD_TOKEN=** -K6_PROMETHEUS_RW_USERNAME=** -K6_PROMETHEUS_RW_PASSWORD=** -K6_PROMETHEUS_RW_SERVER_URL=** ``` - Replace `` and ``, same as for generating tokens above. Fill in the K6_* values if available, - used for reporting to Grafana cloud + Replace `` and ``, same as for generating tokens above. ##### IMPORTANT: Ensure this file is added to .gitignore to prevent accidental commits of sensitive information. Never commit actual credentials to version control. 4. Run `act` using the command below. Replace `` and `` with the desired values: ```shell act workflow_dispatch -j k6-performance -s GITHUB_TOKEN=`gh auth token` \ --container-architecture linux/amd64 --artifact-server-path $HOME/.act \ --input vus= --input duration= \ ---input testSuitePath=tests/k6/tests/graphql/performance/graphql-search.js \ ---input tokens=personal +--input testSuitePath=tests/k6/tests/graphql/performance/graphql-search.js ``` ## Test Results -Test results can be found in GitHub action run log and in App Insights. We are prepared for exporting results to grafana, but so far results are exported to a private grafana instance only, as can be seen from the `.secrets`listed earlier - -## TODO -Fix reporting +Test results can be found in GitHub action run log, grafana and in App Insights. \ No newline at end of file diff --git a/tests/k6/tests/scripts/generate_tokens.sh b/tests/k6/tests/scripts/generate_tokens.sh deleted file mode 100755 index f9d39ab9a..000000000 --- a/tests/k6/tests/scripts/generate_tokens.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash - -# Check if required environment variables are set -if [ -z "$TOKEN_GENERATOR_USERNAME" ] || [ -z "$TOKEN_GENERATOR_PASSWORD" ] || [ -z "$API_ENVIRONMENT" ]; then - echo "Error: TOKEN_GENERATOR_USERNAME, TOKEN_GENERATOR_PASSWORD, and API_ENVIRONMENT must be set" - exit 1 -fi - -# Function to display usage information -usage() { - echo "Usage: $0 " - echo " : Path to the test data files" - echo " : Type of tokens to generate (both, enterprise, or personal)" - echo " : limit number of tokens to generate. 0 means generate all" - echo " : Time to live in seconds for the generated tokens" - echo "Example: $0 /path/to/testdata both 10 3600" - exit 1 -} - -# Validate arguments -if [ $# -ne 4 ]; then - usage -fi - -tokengenuser=${TOKEN_GENERATOR_USERNAME} -tokengenpasswd=${TOKEN_GENERATOR_PASSWORD} - -env="" -case $API_ENVIRONMENT in - "test") - env="at21" ;; - "staging") - env="tt02" ;; - "yt01") - env="yt01" ;; - *) - echo "Error: Unknown api environment $API_ENVIRONMENT" - exit 1 ;; -esac - -testdatafilepath=$1 -tokens=$2 -limit=$3 -ttl=$4 - -# Validate tokens argument -if [[ ! "$tokens" =~ ^(both|enterprise|personal)$ ]]; then - echo "Error: Invalid token type. Must be 'both', 'enterprise', or 'personal'." - usage -fi - -serviceowner_datafile="$testdatafilepath/serviceowners-$API_ENVIRONMENT.csv" -serviceowner_tokenfile="$testdatafilepath/.serviceowners-with-tokens.csv" -enduser_datafile="$testdatafilepath/endusers-$API_ENVIRONMENT.csv" -enduser_tokenfile="$testdatafilepath/.endusers-with-tokens.csv" - -if [ "$tokens" = "both" ] || [ "$tokens" = "enterprise" ]; then - if [ ! -f "$serviceowner_datafile" ]; then - echo "Error: Input file not found: $serviceowner_datafile" - exit 1 - fi - echo "org,orgno,scopes,resource,token" > $serviceowner_tokenfile - generated=0 - while IFS=, read -r org orgno scopes resource - do - if [ $limit -gt 0 ] && [ $generated -ge $limit ]; then - break - fi - url="https://altinn-testtools-token-generator.azurewebsites.net/api/GetEnterpriseToken?org=$org&env=$env&orgno=$orgno&ttl=$ttl" - token=$(curl -s -f --get --data-urlencode "scopes=$scopes" $url -u "$tokengenuser:$tokengenpasswd" ) - if [ $? -ne 0 ]; then - echo "Error: Failed to generate enterprise token for: $env, $org, $orgno, $scopes " - continue - fi - echo "$org,$orgno,$scopes,$resource,$token" >> $serviceowner_tokenfile - status=$? - if [ $status -ne 0 ]; then - echo "Error: Failed to write enterprise token to file for: $env, $org, $orgno, $scopes" - else - ((generated++)) - fi - done < <(tail -n +2 $serviceowner_datafile) -fi - -if [ "$tokens" = "both" ] || [ "$tokens" = "personal" ]; then - if [ ! -f "$enduser_datafile" ]; then - echo "Error: Input file not found: $enduser_datafile" - exit 1 - fi - echo "ssn,resource,scopes,token" > $enduser_tokenfile - generated=0 - while IFS=, read -r ssn resource scopes - do - if [ $limit -gt 0 ] && [ $generated -ge $limit ]; then - break - fi - url="https://altinn-testtools-token-generator.azurewebsites.net/api/GetPersonalToken?env=$env&scopes=$scopes&pid=$ssn&ttl=$ttl" - token=$(curl -s -f $url -u "$tokengenuser:$tokengenpasswd" ) - if [ $? -ne 0 ]; then - echo "Error: Failed to generate personal token for: $ssn, $scopes " - continue - fi - echo "$ssn,$resource,$scopes,$token" >> $enduser_tokenfile - status=$? - if [ $status -ne 0 ]; then - echo "Error: Failed to write personal token to file for: $ssn, $scopes" - else - ((generated++)) - fi - done < <(tail -n +2 $enduser_datafile) -fi diff --git a/tests/k6/tests/serviceowner/performance/README.md b/tests/k6/tests/serviceowner/performance/README.md index 4155dfb6f..240592131 100644 --- a/tests/k6/tests/serviceowner/performance/README.md +++ b/tests/k6/tests/serviceowner/performance/README.md @@ -10,6 +10,7 @@ Before running the performance test, make sure you have met the following prereq The test files associated with this performance test are - `create-dialog.js` - `create-remove-dialog.js` +- `create-transmissions.js` - `serviceowner-search.js` - `purge-dialogs.js` (used for cleanup after test) @@ -21,19 +22,14 @@ To run the performance test, follow the instructions below: ```shell cd tests/k6/tests/serviceowner/performance ``` -2. Generate tokens using the script below. Make sure to replace ``, `` and `<(test|staging|yt01)>` with your actual desired values: -```shell -TOKEN_GENERATOR_USERNAME= \ -TOKEN_GENERATOR_PASSWORD= API_ENVIRONMENT=<(test|staging|yt01)> \ -../../scripts/generate_tokens.sh ../../performancetest_data both -``` -3. Run the test using the following command. Replace ``, `<(test|staging|yt01)>`, ``, and `` with the desired values: +2. Run the test using the following command. Replace ``, `<(test|staging|yt01)>`, ``, and `` with the desired values: ```shell +TOKEN_GENERATOR_USERNAME= TOKEN_GENERATOR_PASSWORD= \ k6 run -e API_VERSION=v1 \ -e API_ENVIRONMENT=<(test|staging|yt01)> \ --vus= --duration= ``` -4. Refer to the k6 documentation for more information on usage. +3. Refer to the k6 documentation for more information on usage. #### From GitHub Actions To run the performance test using GitHub Actions, follow these steps: @@ -49,22 +45,15 @@ To run the performance test locally using GitHub Actions and act, perform the fo ```file TOKEN_GENERATOR_USERNAME: TOKEN_GENERATOR_PASSWORD: -K6_CLOUD_PROJECT_ID=** -K6_CLOUD_TOKEN=** -K6_PROMETHEUS_RW_USERNAME=** -K6_PROMETHEUS_RW_PASSWORD=** -K6_PROMETHEUS_RW_SERVER_URL=** ``` - Replace `` and ``, same as for generating tokens above. Fill in the K6_* values if available, - used for reporting to Grafana cloud + Replace `` and ``, same as for generating tokens above. ##### IMPORTANT: Ensure this file is added to .gitignore to prevent accidental commits of sensitive information. Never commit actual credentials to version control. 4. Run `act` using the command below. Replace ``, ``, `` and `<(personal|enterprise|both)>` with the desired values: ```shell act workflow_dispatch -j k6-performance -s GITHUB_TOKEN=`gh auth token` \ --container-architecture linux/amd64 --artifact-server-path $HOME/.act \ --input vus= --input duration= \ ---input testSuitePath= \ ---input tokens=<(personal|enterprise|both)> +--input testSuitePath= ``` Example of command: @@ -72,8 +61,7 @@ Example of command: act workflow_dispatch -j k6-performance -s GITHUB_TOKEN=`gh auth token` \ --container-architecture linux/amd64 --artifact-server-path $HOME/.act \ --input vus=10 --input duration=5m \ ---input testSuitePath=tests/k6/tests/serviceowner/performance/create-dialog.js \ ---input tokens=enterprise +--input testSuitePath=tests/k6/tests/serviceowner/performance/create-dialog.js ``` #### Clean up @@ -97,7 +85,4 @@ Replace `<(test|staging|yt01)>` with the appropriate environment where the test This script will remove any dialogs created during the performance test, ensuring a clean state for future tests. ### Test Results -The test results can be found in the GitHub Actions run log and in App Insights. Currently, the results are exported to a private Grafana instance. Refer to the `.secrets` file mentioned earlier for more details. - -### TODO -- Fix reporting +The test results can be found in the GitHub Actions run log, grafana and in App Insights. From 9ca52eb9155764aafc4be9668643a47827b64a6d Mon Sep 17 00:00:00 2001 From: Dagfinn Olsen Date: Tue, 14 Jan 2025 09:10:14 +0100 Subject: [PATCH 16/16] fixed relative paths --- tests/k6/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/k6/README.md b/tests/k6/README.md index c2d043be8..9484e43cb 100644 --- a/tests/k6/README.md +++ b/tests/k6/README.md @@ -27,9 +27,9 @@ The scripts will use locally installed `k6` if available. Failing that, it will For information about the performance tests, see the following README files: -- [ServiceOwner](tests/serviceowner/performance/README.md) -- [GraphQL](tests/graphql/performance/README.md) -- [EndUser](tests/enduser/performance/README.md) +- [ServiceOwner](./tests/serviceowner/performance/README.md) +- [GraphQL](./tests/graphql/performance/README.md) +- [EndUser](./tests/enduser/performance/README.md) ## Test suites