From 921f99c65869d10623d074f7c6c7be691db99b2c Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 11:57:04 +0100 Subject: [PATCH 01/47] client credential flow --- charts/k6-operator/templates/k6-testrun.yaml | 11 ++++- charts/k6-operator/tests/ping-graph.ts | 44 ++++++++++++++++--- charts/workflows-cluster/Chart.yaml | 2 +- .../templates/graph-proxy-k6-auth.yaml | 16 +++++++ charts/workflows-cluster/staging-values.yaml | 1 + 5 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-testrun.yaml index 732caf1b4..9108cdb0c 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-testrun.yaml @@ -13,11 +13,18 @@ spec: file: ping-graph.ts runner: env: - - name: GRAPH_PROXY_BEARER_TOKEN + - name: KEYCLOAK_CLIENT_ID valueFrom: secretKeyRef: name: graph-proxy-k6-auth - key: GRAPH_PROXY_BEARER_TOKEN + key: KEYCLOAK_CLIENT_ID + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: graph-proxy-k6-auth + key: KEYCLOAK_CLIENT_SECRET + - name: KEYCLOAK_TOKEN_URL + value: https://identity.diamond.ac.uk/realms/dls/protocol/openid-connect/token - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql resources: diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 618e9e584..c0687a282 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -1,8 +1,11 @@ -import http, { RefinedResponse, ResponseType } from 'k6/http'; +import http from 'k6/http'; import { Options } from 'k6/options'; import { fail } from 'k6'; -const url = __ENV.GRAPH_PROXY_URL ?? 'http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql'; +const graphUrl = __ENV.GRAPH_URL +const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL +const clientID = __ENV.KEYCLOAK_CLIENT_ID +const clientSecret = __ENV.KEYCLOAK_CLIENT_SECRET interface VisitInput { @@ -78,15 +81,46 @@ export const options: Options = { }; export default function(): void { - const token = __ENV.GRAPH_PROXY_BEARER_TOKEN; + if (!clientSecret) { + fail('KEYCLOAK_CLIENT_SECRET requried'); + } + if (!clientID) { + fail('KEYCLOAK_CLIENT_ID required'); + } + if (!keycloakUrl) { + fail('KEYCLOAK_TOKEN_URL required'); + } + if (!graphUrl) { + fail('GRAPH_URL required'); + } + + const tokenRes = http.post( + keycloakUrl, + { + grant_type: 'client_credentials', + client_id: clientID, + client_secret: clientSecret, + }, + { + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }, + ); + + if (tokenRes.status !== 200) { + fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); + } + + const tokenBody = JSON.parse(tokenRes.body as string); + const token = tokenBody.access_token; if (!token) { - fail('GRAPH_PROXY_BEARER_TOKEN required'); + fail('No access_token in Keycloak response'); } const payload = JSON.stringify({ query: queryExamples.listWorkflowsForVisit.query, variables: queryExamples.listWorkflowsForVisit.variables, }); + const params = { headers: { Accept: 'application/json, multipart/mixed', @@ -94,7 +128,7 @@ export default function(): void { Authorization: `Bearer ${token}`, }, }; - const res = http.post(url, payload, params); + const res = http.post(graphUrl, payload, params); console.log(`status=${res && res.status}`); console.log(`body=${res && res.body}`); } diff --git a/charts/workflows-cluster/Chart.yaml b/charts/workflows-cluster/Chart.yaml index 6deeaad9f..29af492dd 100644 --- a/charts/workflows-cluster/Chart.yaml +++ b/charts/workflows-cluster/Chart.yaml @@ -3,7 +3,7 @@ name: workflows-cluster description: A virtual cluster for Data Analysis workflows type: application -version: 0.12.1 +version: 0.12.2 dependencies: - name: common version: 2.23.0 diff --git a/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml b/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml new file mode 100644 index 000000000..338e43c30 --- /dev/null +++ b/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml @@ -0,0 +1,16 @@ +{{- if eq .Values.cluster "pollux" }} +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: graph-proxy-k6-auth + namespace: workflows +spec: + encryptedData: + KEYCLOAK_CLIENT_ID: AgBfgu/0rkkZ9sut6uYcVqFVRaBbUI7MQuTV15EzOjTKSdt22SBF2gUr9GQC+oHX5tnsqqpk3EE0kuq4FgN+Hb/bw2gUftzl/B7sZU/fcUOqcL4bHgtNdJ527B6JMFTL12CAJSSnwflteLYuNvKD4T514/c2tMdh1d+XYHuVs1nl/YxtdBVjrT3qX+G6kqaGCeaR/IYEIa7jE9y/1TH92rSt8pJq7l5k2vuKfw4U2+YHUO1+1pwdE9eFa5PQVgXIiynfcifEQn/QrsJdfKAbpq+IC+ZSoplcehBS52QQJ46MhvM5Dg5oGXX4U33UdrZHfnTeHte2odwANogg8d39Tmg9h6e78wbMTqKHSCcbKVq3OUr/yKpRk7D0hkJTfITr/PXAH1W+PuxHjd4mmFX3x1M8MizDVYsPZxlCIp0sv4Y+NJPtr0rYp5HzfnWVFy5Hef26plNUzE3NhtUAfDDXfb34u0em6Y60HEsG31M9AmPHyomQnaxM5uoNwHyGo4EuUh7n1+mDpkFUAYfqy8QLFoJ3pQymdoQqVToUc28DFNqpo40lsrrRoOUmfC2puQPn97njkw0CNGV5/TWl8kJ1GStkL3ayuFrz6xRLWgq+Ut/u1ItFVlNUwz7O8RiypA4glzqbWYJ5brsqu4x0hkc+3YDZ0CNCBdwu26kOhdqYJS6A1xTWXtk6lNunYcsajHmfIVPsxYnInQjBvZax + KEYCLOAK_CLIENT_SECRET: AgBgO0BNUsJNARu6vnnzV6fhjNhpD6vbmdBZk3xyAzll49EEwrOaJi+UQLv+K4/2bUBD+R8QXh626bQwYwcljFi36mmuDDCcj7pXv9KiQp9XXXhGAo7HuzabcAQ5wplD5YrJtkL2lb+p/Z9dAPJeDO1a2fK0Yea8dC+UDwM4GIpUPhkxdas8W3nc6TfuovdXUb/CCNOVG3xwlmM3kPD2JCgynv05fZ2WU1Mfq5i48I1kAb6bY1OtFh639L7TmwPCARb6ENa7uVkwAevSP2wxfn1eqvhKcEJ7lQMEh3x8QvGad6fKKXux77kRcCA7MzEZa/XSSzshHA6LAYjmtABtR7bHkQ+XATA22qAUGy8EFhNLSN7gw8LSyYlOVIU9B0iaMBzmRfFanJCYy6nQmDqG3TPqIqNTYj4GjxyXTY7iud6g+QqqMMxDAMuOhi7gAkmoi5BsZpdFPYgA1DF7nxyhHeE/byQcE1h77LrxZQYtr7hnPBemt3dbfdgWnVy3PLsGXLyaKYWWtyeDab5X/hOYEYa+qEpAcQvJoQR81X1qgJJYJ7febSyFM+L+GmNJ84QB4lnXw4Tc5GZMfvpNVhvG/Zc5w/9Q4jjBL5CFBR0ktgMN8uif1ElYtHXiK2CESgtc86vfk2MUABfnoyHmUb0RNOgX+Ni/qvBbo0pJq+//RR9XPPzAKVUe3Fs196hFKwhnHsU5i9o9yC/Nh9RL6GARXWicWVmoqrNhW3UHliifKyRVFA== + template: + metadata: + name: graph-proxy-k6-auth + namespace: workflows + type: Opaque +{{- end }} diff --git a/charts/workflows-cluster/staging-values.yaml b/charts/workflows-cluster/staging-values.yaml index d30c54d38..91e46714d 100644 --- a/charts/workflows-cluster/staging-values.yaml +++ b/charts/workflows-cluster/staging-values.yaml @@ -77,6 +77,7 @@ vcluster: "/postgres-argo-workflows-password": "workflows/postgres-argo-workflows-password" "/postgres-application-passwords": "workflows/postgres-application-passwords" "/postgres-initdb-script": "workflows/postgres-initdb-script" + "/graph-proxy-k6-auth": "k6/graph-proxy-k6-auth" ingress: secretName: letsencrypt-kubernetes-staging-workflows-diamond-ac-uk From 3da7304ad697e3afb67b0e3f3a1708cad3d38f25 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 13:07:37 +0100 Subject: [PATCH 02/47] remove type coercien --- charts/k6-operator/tests/ping-graph.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index c0687a282..6275a3bd5 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -106,7 +106,7 @@ export default function(): void { }, ); - if (tokenRes.status !== 200) { + if (tokenRes.status != 200) { fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); } From c871b5f3fd90ef58cf754f64f023a6e09ee5cf14 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 13:15:55 +0100 Subject: [PATCH 03/47] add tokenRes check --- charts/k6-operator/tests/ping-graph.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 6275a3bd5..c446c52bd 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -1,6 +1,6 @@ import http from 'k6/http'; import { Options } from 'k6/options'; -import { fail } from 'k6'; +import { fail, check } from 'k6'; const graphUrl = __ENV.GRAPH_URL const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL @@ -106,9 +106,13 @@ export default function(): void { }, ); - if (tokenRes.status != 200) { - fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); - } + // if (tokenRes.status !== 200) { + // fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); + // } + check(tokenRes, { + 'verify token request was valid': (r) => + r.status === 200, + }); const tokenBody = JSON.parse(tokenRes.body as string); const token = tokenBody.access_token; From b93e7bb692f7f4e7c182511e1544db8f02db6cfd Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 13:21:11 +0100 Subject: [PATCH 04/47] add logging --- charts/k6-operator/tests/ping-graph.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index c446c52bd..59d64efd6 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -135,4 +135,6 @@ export default function(): void { const res = http.post(graphUrl, payload, params); console.log(`status=${res && res.status}`); console.log(`body=${res && res.body}`); + console.log(`status=${tokenRes && tokenRes.status}`) + console.log(`body=${tokenRes && tokenRes.body}`) } From ceb04933bb372e2f65c3d3f0d0608b6a442eb318 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 13:44:07 +0100 Subject: [PATCH 05/47] abort on failed setup --- charts/k6-operator/tests/ping-graph.ts | 25 +++++++++++++++++-------- nvim.log | 0 2 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 nvim.log diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 59d64efd6..91da763c4 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -1,6 +1,7 @@ import http from 'k6/http'; import { Options } from 'k6/options'; import { fail, check } from 'k6'; +import exec from 'k6/execution'; const graphUrl = __ENV.GRAPH_URL const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL @@ -80,7 +81,7 @@ export const options: Options = { }, }; -export default function(): void { +export function setup(): { token: string } { if (!clientSecret) { fail('KEYCLOAK_CLIENT_SECRET requried'); } @@ -106,9 +107,10 @@ export default function(): void { }, ); - // if (tokenRes.status !== 200) { - // fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); - // } + if (tokenRes.status !== 200) { + fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); + } + check(tokenRes, { 'verify token request was valid': (r) => r.status === 200, @@ -117,9 +119,16 @@ export default function(): void { const tokenBody = JSON.parse(tokenRes.body as string); const token = tokenBody.access_token; if (!token) { - fail('No access_token in Keycloak response'); + exec.test.abort('No access_token in Keycloak response'); } + return { token }; +} + +export default function(data: { token: string }): void { + + + const payload = JSON.stringify({ query: queryExamples.listWorkflowsForVisit.query, variables: queryExamples.listWorkflowsForVisit.variables, @@ -129,12 +138,12 @@ export default function(): void { headers: { Accept: 'application/json, multipart/mixed', 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${data.token}`, }, }; const res = http.post(graphUrl, payload, params); console.log(`status=${res && res.status}`); console.log(`body=${res && res.body}`); - console.log(`status=${tokenRes && tokenRes.status}`) - console.log(`body=${tokenRes && tokenRes.body}`) + // console.log(`status=${data && data.status}`) + //console.log(`body=${tokenRes && tokenRes.body}`) } diff --git a/nvim.log b/nvim.log new file mode 100644 index 000000000..e69de29bb From 10eb25598cbe936d58acf92d835c5e50fe4d47c2 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 14:03:50 +0100 Subject: [PATCH 06/47] remove headers --- charts/k6-operator/templates/k6-testrun.yaml | 2 +- charts/k6-operator/tests/ping-graph.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-testrun.yaml index 9108cdb0c..3b691d1e4 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-testrun.yaml @@ -24,7 +24,7 @@ spec: name: graph-proxy-k6-auth key: KEYCLOAK_CLIENT_SECRET - name: KEYCLOAK_TOKEN_URL - value: https://identity.diamond.ac.uk/realms/dls/protocol/openid-connect/token + value: https://identity.diamond.ac.uk/realms/dls - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql resources: diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 91da763c4..801f9136b 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -102,9 +102,6 @@ export function setup(): { token: string } { client_id: clientID, client_secret: clientSecret, }, - { - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - }, ); if (tokenRes.status !== 200) { From 02cf95e6e6e12c02190a672dda1e8b4516cd951b Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 14:05:35 +0100 Subject: [PATCH 07/47] empty jeader --- charts/k6-operator/tests/ping-graph.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 801f9136b..1147e109c 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -102,6 +102,9 @@ export function setup(): { token: string } { client_id: clientID, client_secret: clientSecret, }, + { + headers: {}, + }, ); if (tokenRes.status !== 200) { From 4fa1bf5428801642367409f3d473c23a5c1e47c6 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 14:13:08 +0100 Subject: [PATCH 08/47] empty --- charts/k6-operator/templates/k6-testrun.yaml | 2 +- charts/k6-operator/tests/ping-graph.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-testrun.yaml index 3b691d1e4..9108cdb0c 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-testrun.yaml @@ -24,7 +24,7 @@ spec: name: graph-proxy-k6-auth key: KEYCLOAK_CLIENT_SECRET - name: KEYCLOAK_TOKEN_URL - value: https://identity.diamond.ac.uk/realms/dls + value: https://identity.diamond.ac.uk/realms/dls/protocol/openid-connect/token - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql resources: diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 1147e109c..f69e26f91 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -101,10 +101,7 @@ export function setup(): { token: string } { grant_type: 'client_credentials', client_id: clientID, client_secret: clientSecret, - }, - { - headers: {}, - }, + } ); if (tokenRes.status !== 200) { From 48e1387b4753135cde23f8bcd069f8680cce5f7b Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 14:15:00 +0100 Subject: [PATCH 09/47] token from dev --- charts/k6-operator/templates/k6-testrun.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-testrun.yaml index 9108cdb0c..9ebe5e190 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-testrun.yaml @@ -24,7 +24,7 @@ spec: name: graph-proxy-k6-auth key: KEYCLOAK_CLIENT_SECRET - name: KEYCLOAK_TOKEN_URL - value: https://identity.diamond.ac.uk/realms/dls/protocol/openid-connect/token + value: https://identity-dev.diamond.ac.uk/realms/dls/protocol/openid-connect/token - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql resources: From fab452fcbd0caeff976edff18a998a952bb6bfe7 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 14:18:48 +0100 Subject: [PATCH 10/47] identity test --- charts/k6-operator/templates/k6-testrun.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-testrun.yaml index 9ebe5e190..88a81b00e 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-testrun.yaml @@ -24,7 +24,7 @@ spec: name: graph-proxy-k6-auth key: KEYCLOAK_CLIENT_SECRET - name: KEYCLOAK_TOKEN_URL - value: https://identity-dev.diamond.ac.uk/realms/dls/protocol/openid-connect/token + value: https://identity-test.diamond.ac.uk/realms/dls/protocol/openid-connect/token - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql resources: From 5dd7ddc9646636421cd7534e4b761aa6ae4ed052 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 14:22:34 +0100 Subject: [PATCH 11/47] errors --- charts/k6-operator/tests/ping-graph.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index f69e26f91..0a4671bf8 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -112,6 +112,8 @@ export function setup(): { token: string } { 'verify token request was valid': (r) => r.status === 200, }); + console.log(tokenRes.status) + console.log(tokenRes.body) const tokenBody = JSON.parse(tokenRes.body as string); const token = tokenBody.access_token; From 43f4253026c074eb4416e6e062f4065b771abb0d Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 15:00:44 +0100 Subject: [PATCH 12/47] add identity-test as auth issuer --- charts/workflows-cluster/staging-values.yaml | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/charts/workflows-cluster/staging-values.yaml b/charts/workflows-cluster/staging-values.yaml index 91e46714d..83d9a274e 100644 --- a/charts/workflows-cluster/staging-values.yaml +++ b/charts/workflows-cluster/staging-values.yaml @@ -108,6 +108,29 @@ authenticationConfiguration: message: 'username cannot use reserved system: prefix' - expression: "user.groups.all(group, !group.startsWith('system:'))" message: 'groups cannot use reserved system: prefix' + - issuer: + url: https://identity-test.diamond.ac.uk/realms/dls + audiences: + - workflows-cluster-staging + - graph + audienceMatchPolicy: MatchAny + claimMappings: + username: + claim: fedid + prefix: "oidc:" + groups: + claim: groups + prefix: "oidc:" + uid: + claim: fedid + extra: + - key: 'workflows.diamond.ac.uk/posixuid' + valueExpression: 'string(claims.posix_uid)' + userValidationRules: + - expression: "!user.username.startsWith('system:')" + message: 'username cannot use reserved system: prefix' + - expression: "user.groups.all(group, !group.startsWith('system:'))" + message: 'groups cannot use reserved system: prefix' - issuer: url: https://authn.diamond.ac.uk/realms/master audiences: From 5a91522e3666e95ba5ae22cb9edd345cae458e3c Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 15:16:51 +0100 Subject: [PATCH 13/47] change keycloak request to identity-dev --- charts/k6-operator/templates/k6-testrun.yaml | 2 +- .../templates/graph-proxy-k6-auth.yaml | 4 ++-- charts/workflows-cluster/staging-values.yaml | 23 ------------------- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-testrun.yaml index 88a81b00e..9ebe5e190 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-testrun.yaml @@ -24,7 +24,7 @@ spec: name: graph-proxy-k6-auth key: KEYCLOAK_CLIENT_SECRET - name: KEYCLOAK_TOKEN_URL - value: https://identity-test.diamond.ac.uk/realms/dls/protocol/openid-connect/token + value: https://identity-dev.diamond.ac.uk/realms/dls/protocol/openid-connect/token - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql resources: diff --git a/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml b/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml index 338e43c30..359cfa868 100644 --- a/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml +++ b/charts/workflows-cluster/charts/secrets/templates/graph-proxy-k6-auth.yaml @@ -6,8 +6,8 @@ metadata: namespace: workflows spec: encryptedData: - KEYCLOAK_CLIENT_ID: AgBfgu/0rkkZ9sut6uYcVqFVRaBbUI7MQuTV15EzOjTKSdt22SBF2gUr9GQC+oHX5tnsqqpk3EE0kuq4FgN+Hb/bw2gUftzl/B7sZU/fcUOqcL4bHgtNdJ527B6JMFTL12CAJSSnwflteLYuNvKD4T514/c2tMdh1d+XYHuVs1nl/YxtdBVjrT3qX+G6kqaGCeaR/IYEIa7jE9y/1TH92rSt8pJq7l5k2vuKfw4U2+YHUO1+1pwdE9eFa5PQVgXIiynfcifEQn/QrsJdfKAbpq+IC+ZSoplcehBS52QQJ46MhvM5Dg5oGXX4U33UdrZHfnTeHte2odwANogg8d39Tmg9h6e78wbMTqKHSCcbKVq3OUr/yKpRk7D0hkJTfITr/PXAH1W+PuxHjd4mmFX3x1M8MizDVYsPZxlCIp0sv4Y+NJPtr0rYp5HzfnWVFy5Hef26plNUzE3NhtUAfDDXfb34u0em6Y60HEsG31M9AmPHyomQnaxM5uoNwHyGo4EuUh7n1+mDpkFUAYfqy8QLFoJ3pQymdoQqVToUc28DFNqpo40lsrrRoOUmfC2puQPn97njkw0CNGV5/TWl8kJ1GStkL3ayuFrz6xRLWgq+Ut/u1ItFVlNUwz7O8RiypA4glzqbWYJ5brsqu4x0hkc+3YDZ0CNCBdwu26kOhdqYJS6A1xTWXtk6lNunYcsajHmfIVPsxYnInQjBvZax - KEYCLOAK_CLIENT_SECRET: AgBgO0BNUsJNARu6vnnzV6fhjNhpD6vbmdBZk3xyAzll49EEwrOaJi+UQLv+K4/2bUBD+R8QXh626bQwYwcljFi36mmuDDCcj7pXv9KiQp9XXXhGAo7HuzabcAQ5wplD5YrJtkL2lb+p/Z9dAPJeDO1a2fK0Yea8dC+UDwM4GIpUPhkxdas8W3nc6TfuovdXUb/CCNOVG3xwlmM3kPD2JCgynv05fZ2WU1Mfq5i48I1kAb6bY1OtFh639L7TmwPCARb6ENa7uVkwAevSP2wxfn1eqvhKcEJ7lQMEh3x8QvGad6fKKXux77kRcCA7MzEZa/XSSzshHA6LAYjmtABtR7bHkQ+XATA22qAUGy8EFhNLSN7gw8LSyYlOVIU9B0iaMBzmRfFanJCYy6nQmDqG3TPqIqNTYj4GjxyXTY7iud6g+QqqMMxDAMuOhi7gAkmoi5BsZpdFPYgA1DF7nxyhHeE/byQcE1h77LrxZQYtr7hnPBemt3dbfdgWnVy3PLsGXLyaKYWWtyeDab5X/hOYEYa+qEpAcQvJoQR81X1qgJJYJ7febSyFM+L+GmNJ84QB4lnXw4Tc5GZMfvpNVhvG/Zc5w/9Q4jjBL5CFBR0ktgMN8uif1ElYtHXiK2CESgtc86vfk2MUABfnoyHmUb0RNOgX+Ni/qvBbo0pJq+//RR9XPPzAKVUe3Fs196hFKwhnHsU5i9o9yC/Nh9RL6GARXWicWVmoqrNhW3UHliifKyRVFA== + KEYCLOAK_CLIENT_ID: AgCSOzbJVQb/al9FiYSz2Y25Y6jHTtSlldwc8GvBjSnLS6w86deIOuwCDyNUfcdPJtDIVQmBZM77iRBx6N2JWcrAipQQwb534fmkVsE1p/O/gpw3CU0vdd4cGc9NCeXkSmJarcLb/+HYP7ggTc+T9r6SxqdoQ2CKTxvPWuR19//SQ92AjIspzFE0bCdEyLcHf5fkp7vWcR28wXbCxUzA/dQtNY2yMfUDQtBks9noTVeUYmcwcmTrcqrntZtSoQvup/Mz/gqaoNIQWl4FqLYo0q7v39QwtBQuuWmkrSiWpJKeick6zXHmorRyBfCl+lnWhQrF+Ajt+9Sh+rwJr49j3OrIpCYv03sekO0pnabphNiP7RrgHjXghPnGb+T5Fr2Lfm1m/hoVNEiFpuoyAAMGEWS50MK4GmGRsHJZNkvCuwDSv4Y7Dpegsw40P7E1xXMlMb5kqXO/F8jWQvMIvZ+mPFtYcwbbg6CPSimUERXueWk+BWQExvdJhfgf45r5zHmhIDgLckIVC5L6IxCpmyqKGpHmB3mcZJBMTwQOYa0hDBosCOC6Tr0CvrCh65Yt4J+n9oFCqIremY01xpykSYiiiTgT0CctFMEVDV356mGC4iAWVvV6TxNZO7e79J6RLIeFeBYzQCi4yZ23IaXIsPCjmV+92QaSzxjULzeJJbAdxsiWoYyv7/Zq07Eg/vWZ1rNIIt1PNtdsMafq3JZ2 + KEYCLOAK_CLIENT_SECRET: AgBhpvOKYOeFINnruWr+NWKyWRJLpfyTa8DI5mwWmTpETEaSrj3AU4DfaYF7uCwpQSw9P4o/zC5uZP+ccIFPUC2ptGLTOlAMklPzZhWyehg6sPJVBH02wwA8fyExOdPoUroz1JcMZYg3N3HBowRJ04t99LZYCt3Ll3xnjdAXMtm9rX5UG9u4TLu7WF2fRiCIH+jtOO/NivdCwSqSK466JnDgMDCF1EeOnmd7aszWjXQky+xU7Hbwi+VZoQrXGGJ62WPGHtqHwli8Fg/DxiYdDqI7hpgrmlgC9HNC7Eel9pKkN2ujEA6EKlZlZoAjVsORZIOUSbpOUikeFRNDfREBnbk3r8SOz16WE22+NtuN7RbLJDjgZGi7rLA9UQVRE/uJAbsGpa10wLou3p61cVWOY/ehUC7/6RfNcT14+C0UI2gpGpN2pzd48/nw4ocSJ4nv2gALE6ZkHsZpiAKddeUUZut4d8z9HB2R4VY2nKVeaCNiPSZJg44gI6E4WKDM30cQY/CSsQX3KFpYjuL8FpgLWE90QNfA/XTBO/7qP3h1TDLvoNnyFj9HDnf4riPA44qBMz0CXaDHlHKRoeYmosgix+jAyChE1UAPidb7Bf9BSXtShBx/rFTiImkoAw8ihebe/qih9RYt659GuVcv/ilu4PkYngFkrCHRxvdPhXILAg6x/cwzT7uRb4mmJ6x4Nt62Ufz3uOxtUZDq8ujYMJD2CXU7iyv8apMrCbxzDsSaiFSFlA== template: metadata: name: graph-proxy-k6-auth diff --git a/charts/workflows-cluster/staging-values.yaml b/charts/workflows-cluster/staging-values.yaml index 83d9a274e..91e46714d 100644 --- a/charts/workflows-cluster/staging-values.yaml +++ b/charts/workflows-cluster/staging-values.yaml @@ -108,29 +108,6 @@ authenticationConfiguration: message: 'username cannot use reserved system: prefix' - expression: "user.groups.all(group, !group.startsWith('system:'))" message: 'groups cannot use reserved system: prefix' - - issuer: - url: https://identity-test.diamond.ac.uk/realms/dls - audiences: - - workflows-cluster-staging - - graph - audienceMatchPolicy: MatchAny - claimMappings: - username: - claim: fedid - prefix: "oidc:" - groups: - claim: groups - prefix: "oidc:" - uid: - claim: fedid - extra: - - key: 'workflows.diamond.ac.uk/posixuid' - valueExpression: 'string(claims.posix_uid)' - userValidationRules: - - expression: "!user.username.startsWith('system:')" - message: 'username cannot use reserved system: prefix' - - expression: "user.groups.all(group, !group.startsWith('system:'))" - message: 'groups cannot use reserved system: prefix' - issuer: url: https://authn.diamond.ac.uk/realms/master audiences: From 2f525ae359e4b7119de18023bffdb9f08c9c53d2 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 21 Apr 2026 16:17:40 +0100 Subject: [PATCH 14/47] change query to non-visit specic --- charts/k6-operator/tests/ping-graph.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 0a4671bf8..dc111315d 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -8,7 +8,6 @@ const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL const clientID = __ENV.KEYCLOAK_CLIENT_ID const clientSecret = __ENV.KEYCLOAK_CLIENT_SECRET - interface VisitInput { proposalCode: string; proposalNumber: number; @@ -22,10 +21,13 @@ interface ListWorkflowsVariables { interface QueryExample { query: string; - variables: ListWorkflowsVariables; + variables?: ListWorkflowsVariables; } -const queryExamples: { listWorkflowsForVisit: QueryExample } = { +const queryExamples: { + listWorkflowsForVisit: QueryExample; + listTemplates: QueryExample; +} = { listWorkflowsForVisit: { query: ` query ListWorkflowsForVisit($visit: VisitInput!, $limit: Int) { @@ -54,6 +56,19 @@ const queryExamples: { listWorkflowsForVisit: QueryExample } = { limit: 30, }, }, + listTemplates: { + query: ` + query { + workflowTemplates { + nodes { + name + title + description + } + } + } + `, + }, }; export const options: Options = { @@ -129,8 +144,7 @@ export default function(data: { token: string }): void { const payload = JSON.stringify({ - query: queryExamples.listWorkflowsForVisit.query, - variables: queryExamples.listWorkflowsForVisit.variables, + query: queryExamples.listTemplates.query, }); const params = { From e975ed7dc4cbfd3b771fa2b1403524cac178d3f5 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 22 Apr 2026 08:43:14 +0100 Subject: [PATCH 15/47] try hardcoded token --- charts/k6-operator/tests/ping-graph.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index dc111315d..c03f8129e 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -142,6 +142,7 @@ export function setup(): { token: string } { export default function(data: { token: string }): void { + const hardToken = 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTk5XYWVHTXFDWE1QY0l3eDA4ZjBsV18wcE9EX1MwV1lGeEZqbXZ0RU1RIn0.eyJleHAiOjE3NzY4NDQ2MzAsImlhdCI6MTc3Njg0MzczMCwiYXV0aF90aW1lIjoxNzc2ODQzNjUyLCJqdGkiOiJvbnJ0YWM6ZmNlZjQxMmItYTc3OC0wOGU3LTg2ZmYtODM4Yjc4ODI3YjExIiwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS1kZXYuZGlhbW9uZC5hYy51ay9yZWFsbXMvZGxzIiwiYXVkIjpbIndvcmtmbG93cy1jbHVzdGVyLXN0YWdpbmciLCJhY2NvdW50Il0sInN1YiI6IjllZjg2ZGQ5LWUyN2MtNGNkNS1iNzc3LTY0NDI5MDA2YWUxMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndvcmtmbG93cy11aS1kZXYiLCJzaWQiOiI1ZWU3NDY1Yi0zMTZlLTQyMDAtYjk1ZS1hOTVhN2QyZjUwODYiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZGxzIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGZlZGlkIGVtYWlsIHByb2ZpbGUgcG9zaXgtdWlkIiwicG9zaXhfdWlkIjoiMTIzMzM1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1haGlyIEFiYmFzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1pMTM4MjciLCJmZWRpZCI6InVtaTEzODI3IiwiZ2l2ZW5fbmFtZSI6Ik1haGlyIiwiZmFtaWx5X25hbWUiOiJBYmJhcyIsImVtYWlsIjoibWFoaXIuYWJiYXNAZGlhbW9uZC5hYy51ayJ9.VatcvQahzypITCWG8-qdp_Ce1udlc-oVafJj5PSwBLOhk-SejcB7nozq_NPdNZCo6VGdya4hMyYf0A6RzBa3B5kR187Ki0sJlZpKJ4273r4cwi5j8F7Hz6JltT8nhOg4ypFSMbRKWozK5fBMgza6HkRr-Af4cxw4ZsW1AfI-OgKeaBWbxh2gs_JVtgcnrbNyvTh9r63zlCt9xY6Uv50P1hT_Oct_e3nTWUhzpPGC3lWR8QtfVnUH0k55m1Wn1FGLYt7D7lJ5J0gCnMzo2bJaPae-B2mnGWhPfAJaKF4X4z_uZFvgVWjlVgnTvJT0L3_mic2vjkxrfYD5gmfJRhlzcg'; const payload = JSON.stringify({ query: queryExamples.listTemplates.query, @@ -151,7 +152,7 @@ export default function(data: { token: string }): void { headers: { Accept: 'application/json, multipart/mixed', 'Content-Type': 'application/json', - Authorization: `Bearer ${data.token}`, + Authorization: `Bearer ${hardToken}`, }, }; const res = http.post(graphUrl, payload, params); From 6f640de5f856afdb3ad911241cd7b914030227eb Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 22 Apr 2026 10:06:53 +0100 Subject: [PATCH 16/47] list templates test --- charts/k6-operator/tests/ping-graph.ts | 2 +- charts/k6-operator/tests/ws-subscription.ts | 210 ++++++++++++++++++++ 2 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 charts/k6-operator/tests/ws-subscription.ts diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index c03f8129e..866c0585a 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -152,7 +152,7 @@ export default function(data: { token: string }): void { headers: { Accept: 'application/json, multipart/mixed', 'Content-Type': 'application/json', - Authorization: `Bearer ${hardToken}`, + Authorization: `Bearer ${data.token}`, }, }; const res = http.post(graphUrl, payload, params); diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts new file mode 100644 index 000000000..c439a184b --- /dev/null +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -0,0 +1,210 @@ +import http, { head } from 'k6/http'; +const diamondToken = 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTk5XYWVHTXFDWE1QY0l3eDA4ZjBsV18wcE9EX1MwV1lGeEZqbXZ0RU1RIn0.eyJleHAiOjE3NzU2NDA2MTgsImlhdCI6MTc3NTYzOTcxOCwiYXV0aF90aW1lIjoxNzc1NjM4OTk4LCJqdGkiOiJvbnJ0YWM6ZGRkODM5YjMtOWY0YS04M2I1LTIyZDMtMzBhMTMzZDBlNTI1IiwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS1kZXYuZGlhbW9uZC5hYy51ay9yZWFsbXMvZGxzIiwiYXVkIjpbIndvcmtmbG93cy1jbHVzdGVyLXN0YWdpbmciLCJhY2NvdW50Il0sInN1YiI6IjllZjg2ZGQ5LWUyN2MtNGNkNS1iNzc3LTY0NDI5MDA2YWUxMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndvcmtmbG93cy11aS1kZXYiLCJzaWQiOiIxOWVhMWM0MC04ZDgxLTQ5ZTktYTEyMS1lZGFlNDYyMGZkOTYiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZGxzIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGZlZGlkIGVtYWlsIHByb2ZpbGUgcG9zaXgtdWlkIiwicG9zaXhfdWlkIjoiMTIzMzM1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1haGlyIEFiYmFzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1pMTM4MjciLCJmZWRpZCI6InVtaTEzODI3IiwiZ2l2ZW5fbmFtZSI6Ik1haGlyIiwiZmFtaWx5X25hbWUiOiJBYmJhcyIsImVtYWlsIjoibWFoaXIuYWJiYXNAZGlhbW9uZC5hYy51ayJ9.VHC9F3dXN_Laep3Mu7_YZpm7MaK_hGmHciiMDCFHUPVwyPDLwcKJYKXVNTPriDEIGmBZoL0kT4q9govE9OZ8Q1Q0LvhjoSqXvs4wmz1DBBcGHLsey-BatkdQLhE-eQ6PFWWP8O5xtkBFb5Iv1zcg3ASjoe-tu5uMtb0svaxubfKwm8VKDzpFRNhN0yG8CDOjjyFgYyF3DoYKgozmi7VtudQSK-mnZaVbQEFgcOEZcp8XtMqdOUGQOM7dsw4fTLa7Fmr8IuYkXlYO72PJShm8JeXwuK5_siNEdjZ9h73wMHq68ej90XTjTdC5dCg_kOHgixZiG-SREf2P6C9zyWueXA'; + +interface somethingInterface { + executor: string; + startVUs?: number; + stages: [{ duration: string; target: number; }] + gracefulRampDown: string; + +} + +interface k6Config { + insecureSkipTLSVerify: boolean; + scenarios: { + ping_graph_ramp: somethingInterface; + } + thresholds: { + http_req_duration: [string]; + } +} + +export const options = { + insecureSkipTLSVerify: true, + scenarios: { + ping_graph_ramp: { + executor: 'ramping-vus', + startVUs: 0, + stages: [ + { duration: '30s', target: 10 }, + { duration: '1m', target: 50 }, + { duration: '2m', target: 100 }, + { duration: '1m', target: 200 }, + { duration: '1m', target: 300 }, + { duration: '1m', target: 500 }, + { duration: '30s', target: 0 }, + ], + gracefulRampDown: '10s', + }, + }, + thresholds: { + //http_req_failed: ['rate<0.05'], + http_req_duration: ['p(95)<2000'], + }, +}; + + +const queryExamples = { + getWorkFlow: { + query: ` + query GetWorkFlow($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + visit { + proposalCode + proposalNumber + number + } + name + } + } + `, + variables: { + visit: { + proposalCode: "mg", + proposalNumber: 36964, + number: 1, + }, + name: "yeltsa-kcir", + }, + }, + getWorkflowByName: { + query: ` + query GetWorkflowByName($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + visit { + proposalCode + proposalNumber + number + } + name + } + } + `, + variables: { + visit: { + proposalCode: "mg", + proposalNumber: 36964, + number: 1, + }, + name: "yeltsa-kcir", + }, + }, + getWorkflowStatus: { + query: ` + query GetWorkflowStatus($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + name + status { + __typename + } + } + } + `, + variables: { + visit: { + proposalCode: "mg", + proposalNumber: 36964, + number: 1, + }, + name: "yeltsa-kcir", + }, + }, + getWorkflowCreator: { + query: ` + query GetWorkflowCreator($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + name + creator { + fedid + } + } + } + `, + variables: { + visit: { + proposalCode: "mg", + proposalNumber: 36964, + number: 1, + }, + name: "yeltsa-kcir", + }, + }, + listWorkflowTemplates: { + query: ` + query ListWorkflowTemplates($first: Int) { + workflowTemplates(first: $first) { + edges { + node { + name + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + `, + variables: { + first: 10, + }, + }, + listWorkflowsForVisit: { + query: ` + query ListWorkflowsForVisit($visit: VisitInput!, $limit: Int) { + workflows(visit: $visit, limit: $limit) { + edges { + node { + name + status { + __typename + } + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + `, + variables: { + visit: { + proposalCode: "cm", + proposalNumber: 40661, + number: 1, + }, + limit: 30, + }, + }, +}; + + +const headers = { + 'Authorization': `Bearer ${diamondToken}`, + 'Content-Type': 'application/json', +}; + + +export default function() { + //const res = http.post('https://api.github.com/graphql', JSON.stringify({query: query}), {headers: headers}); + const url = 'https://staging.workflows.diamond.ac.uk/graphql'; + const payload = JSON.stringify({ + query: queryExamples.listWorkflowsForVisit.query, + variables: queryExamples.listWorkflowsForVisit.variables, + }); + const params = { + headers: { + Accept: 'application/json, multipart/mixed', + 'Content-Type': 'application/json', + Authorization: `Bearer ${diamondToken}`, + Origin: 'https://staging.workflows.diamond.ac.uk', + Referer: 'https://staging.workflows.diamond.ac.uk', + }, + }; + const res = http.post(url, payload, params) + console.log(`status=${res && res.status}`); + console.log(`body=${res && res.body}`); + res; +} + From 40564696e5f93135eabc0d662bd7096c64fd70ed Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 22 Apr 2026 10:07:18 +0100 Subject: [PATCH 17/47] remove hardcoded token --- charts/k6-operator/tests/ping-graph.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 866c0585a..dc111315d 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -142,7 +142,6 @@ export function setup(): { token: string } { export default function(data: { token: string }): void { - const hardToken = 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTk5XYWVHTXFDWE1QY0l3eDA4ZjBsV18wcE9EX1MwV1lGeEZqbXZ0RU1RIn0.eyJleHAiOjE3NzY4NDQ2MzAsImlhdCI6MTc3Njg0MzczMCwiYXV0aF90aW1lIjoxNzc2ODQzNjUyLCJqdGkiOiJvbnJ0YWM6ZmNlZjQxMmItYTc3OC0wOGU3LTg2ZmYtODM4Yjc4ODI3YjExIiwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS1kZXYuZGlhbW9uZC5hYy51ay9yZWFsbXMvZGxzIiwiYXVkIjpbIndvcmtmbG93cy1jbHVzdGVyLXN0YWdpbmciLCJhY2NvdW50Il0sInN1YiI6IjllZjg2ZGQ5LWUyN2MtNGNkNS1iNzc3LTY0NDI5MDA2YWUxMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndvcmtmbG93cy11aS1kZXYiLCJzaWQiOiI1ZWU3NDY1Yi0zMTZlLTQyMDAtYjk1ZS1hOTVhN2QyZjUwODYiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZGxzIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGZlZGlkIGVtYWlsIHByb2ZpbGUgcG9zaXgtdWlkIiwicG9zaXhfdWlkIjoiMTIzMzM1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1haGlyIEFiYmFzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1pMTM4MjciLCJmZWRpZCI6InVtaTEzODI3IiwiZ2l2ZW5fbmFtZSI6Ik1haGlyIiwiZmFtaWx5X25hbWUiOiJBYmJhcyIsImVtYWlsIjoibWFoaXIuYWJiYXNAZGlhbW9uZC5hYy51ayJ9.VatcvQahzypITCWG8-qdp_Ce1udlc-oVafJj5PSwBLOhk-SejcB7nozq_NPdNZCo6VGdya4hMyYf0A6RzBa3B5kR187Ki0sJlZpKJ4273r4cwi5j8F7Hz6JltT8nhOg4ypFSMbRKWozK5fBMgza6HkRr-Af4cxw4ZsW1AfI-OgKeaBWbxh2gs_JVtgcnrbNyvTh9r63zlCt9xY6Uv50P1hT_Oct_e3nTWUhzpPGC3lWR8QtfVnUH0k55m1Wn1FGLYt7D7lJ5J0gCnMzo2bJaPae-B2mnGWhPfAJaKF4X4z_uZFvgVWjlVgnTvJT0L3_mic2vjkxrfYD5gmfJRhlzcg'; const payload = JSON.stringify({ query: queryExamples.listTemplates.query, From 7e2c452a2562cff75c0795b0b70817bffe9bd2ad Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 28 Apr 2026 10:53:33 +0100 Subject: [PATCH 18/47] common.ts --- charts/k6-operator/tests/common.ts | 40 ++++++++++++++++++++++++++++++ nvim.log | 0 2 files changed, 40 insertions(+) create mode 100644 charts/k6-operator/tests/common.ts delete mode 100644 nvim.log diff --git a/charts/k6-operator/tests/common.ts b/charts/k6-operator/tests/common.ts new file mode 100644 index 000000000..13d7636bb --- /dev/null +++ b/charts/k6-operator/tests/common.ts @@ -0,0 +1,40 @@ +import http from 'k6/http'; +import { check, fail } from 'k6'; +import exec from 'k6/execution'; + +const graphUrl = __ENV.GRAPH_URL; +const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL; +const clientID = __ENV.KEYCLOAK_CLIENT_ID; +const clientSecret = __ENV.KEYCLOAK_CLIENT_SECRET; + +export interface SetupData { + token: string | void; +} + +export function setup(): SetupData { + if (!clientSecret) fail('KEYCLOAK_CLIENT_SECRET required'); + if (!clientID) fail('KEYCLOAK_CLIENT_ID required'); + if (!keycloakUrl) fail('KEYCLOAK_TOKEN_URL required'); + if (!graphUrl) fail('GRAPH_URL required'); + + const tokenRes = http.post(keycloakUrl, { + grant_type: 'client_credentials', + client_id: clientID, + client_secret: clientSecret, + }); + + check(tokenRes, { + 'keycloak token request succeeded': (r) => r.status === 200, + }); + + if (tokenRes.status !== 200) { + fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); + } + + const token = (JSON.parse(tokenRes.body as string) as { access_token?: string }).access_token; + if (!token) { + exec.test.abort('No access_token in Keycloak response'); + } + + return { token }; +} diff --git a/nvim.log b/nvim.log deleted file mode 100644 index e69de29bb..000000000 From ca9368ec494d3ebecbcbc828d3cfd8ef77ca2601 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 29 Apr 2026 11:11:06 +0100 Subject: [PATCH 19/47] export setup() --- charts/k6-operator/tests/common.ts | 12 ++--- charts/k6-operator/tests/ping-graph.ts | 53 +++------------------ charts/k6-operator/tests/ws-subscription.ts | 3 +- 3 files changed, 13 insertions(+), 55 deletions(-) diff --git a/charts/k6-operator/tests/common.ts b/charts/k6-operator/tests/common.ts index 13d7636bb..7da9b49d0 100644 --- a/charts/k6-operator/tests/common.ts +++ b/charts/k6-operator/tests/common.ts @@ -7,17 +7,14 @@ const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL; const clientID = __ENV.KEYCLOAK_CLIENT_ID; const clientSecret = __ENV.KEYCLOAK_CLIENT_SECRET; -export interface SetupData { - token: string | void; -} - -export function setup(): SetupData { +export function setup(): { token: string } { if (!clientSecret) fail('KEYCLOAK_CLIENT_SECRET required'); if (!clientID) fail('KEYCLOAK_CLIENT_ID required'); if (!keycloakUrl) fail('KEYCLOAK_TOKEN_URL required'); if (!graphUrl) fail('GRAPH_URL required'); - const tokenRes = http.post(keycloakUrl, { + const tokenRes = http.post( + keycloakUrl, { grant_type: 'client_credentials', client_id: clientID, client_secret: clientSecret, @@ -31,7 +28,8 @@ export function setup(): SetupData { fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); } - const token = (JSON.parse(tokenRes.body as string) as { access_token?: string }).access_token; + const tokenBody = JSON.parse(tokenRes.body as string); + const token = tokenBody.access_token; if (!token) { exec.test.abort('No access_token in Keycloak response'); } diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index dc111315d..5b5404230 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -1,12 +1,13 @@ import http from 'k6/http'; import { Options } from 'k6/options'; -import { fail, check } from 'k6'; -import exec from 'k6/execution'; +//import { fail, check } from 'k6'; +//import exec from 'k6/execution'; +export { setup } from './common.ts'; const graphUrl = __ENV.GRAPH_URL -const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL -const clientID = __ENV.KEYCLOAK_CLIENT_ID -const clientSecret = __ENV.KEYCLOAK_CLIENT_SECRET +//const keycloakUrl = __ENV.KEYCLOAK_TOKEN_URL +//const clientID = __ENV.KEYCLOAK_CLIENT_ID +//const clientSecret = __ENV.KEYCLOAK_CLIENT_SECRET interface VisitInput { proposalCode: string; @@ -96,48 +97,6 @@ export const options: Options = { }, }; -export function setup(): { token: string } { - if (!clientSecret) { - fail('KEYCLOAK_CLIENT_SECRET requried'); - } - if (!clientID) { - fail('KEYCLOAK_CLIENT_ID required'); - } - if (!keycloakUrl) { - fail('KEYCLOAK_TOKEN_URL required'); - } - if (!graphUrl) { - fail('GRAPH_URL required'); - } - - const tokenRes = http.post( - keycloakUrl, - { - grant_type: 'client_credentials', - client_id: clientID, - client_secret: clientSecret, - } - ); - - if (tokenRes.status !== 200) { - fail(`Token request failed: ${tokenRes.status} ${tokenRes.body}`); - } - - check(tokenRes, { - 'verify token request was valid': (r) => - r.status === 200, - }); - console.log(tokenRes.status) - console.log(tokenRes.body) - - const tokenBody = JSON.parse(tokenRes.body as string); - const token = tokenBody.access_token; - if (!token) { - exec.test.abort('No access_token in Keycloak response'); - } - - return { token }; -} export default function(data: { token: string }): void { diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index c439a184b..3f07363eb 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -1,5 +1,6 @@ import http, { head } from 'k6/http'; -const diamondToken = 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTk5XYWVHTXFDWE1QY0l3eDA4ZjBsV18wcE9EX1MwV1lGeEZqbXZ0RU1RIn0.eyJleHAiOjE3NzU2NDA2MTgsImlhdCI6MTc3NTYzOTcxOCwiYXV0aF90aW1lIjoxNzc1NjM4OTk4LCJqdGkiOiJvbnJ0YWM6ZGRkODM5YjMtOWY0YS04M2I1LTIyZDMtMzBhMTMzZDBlNTI1IiwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS1kZXYuZGlhbW9uZC5hYy51ay9yZWFsbXMvZGxzIiwiYXVkIjpbIndvcmtmbG93cy1jbHVzdGVyLXN0YWdpbmciLCJhY2NvdW50Il0sInN1YiI6IjllZjg2ZGQ5LWUyN2MtNGNkNS1iNzc3LTY0NDI5MDA2YWUxMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndvcmtmbG93cy11aS1kZXYiLCJzaWQiOiIxOWVhMWM0MC04ZDgxLTQ5ZTktYTEyMS1lZGFlNDYyMGZkOTYiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZGxzIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGZlZGlkIGVtYWlsIHByb2ZpbGUgcG9zaXgtdWlkIiwicG9zaXhfdWlkIjoiMTIzMzM1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1haGlyIEFiYmFzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1pMTM4MjciLCJmZWRpZCI6InVtaTEzODI3IiwiZ2l2ZW5fbmFtZSI6Ik1haGlyIiwiZmFtaWx5X25hbWUiOiJBYmJhcyIsImVtYWlsIjoibWFoaXIuYWJiYXNAZGlhbW9uZC5hYy51ayJ9.VHC9F3dXN_Laep3Mu7_YZpm7MaK_hGmHciiMDCFHUPVwyPDLwcKJYKXVNTPriDEIGmBZoL0kT4q9govE9OZ8Q1Q0LvhjoSqXvs4wmz1DBBcGHLsey-BatkdQLhE-eQ6PFWWP8O5xtkBFb5Iv1zcg3ASjoe-tu5uMtb0svaxubfKwm8VKDzpFRNhN0yG8CDOjjyFgYyF3DoYKgozmi7VtudQSK-mnZaVbQEFgcOEZcp8XtMqdOUGQOM7dsw4fTLa7Fmr8IuYkXlYO72PJShm8JeXwuK5_siNEdjZ9h73wMHq68ej90XTjTdC5dCg_kOHgixZiG-SREf2P6C9zyWueXA'; +export { setup } from './common.ts'; +const diamondToken = ''; interface somethingInterface { executor: string; From a958a2183a7c5d7c17d5f4c35db4a787bc912c35 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 29 Apr 2026 11:34:32 +0100 Subject: [PATCH 20/47] sonnet is crap --- charts/k6-operator/tests/ws-subscription.ts | 310 ++++++++------------ 1 file changed, 121 insertions(+), 189 deletions(-) diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index 3f07363eb..3b58476e3 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -1,211 +1,143 @@ -import http, { head } from 'k6/http'; +import http from 'k6/http'; +import { check, fail } from 'k6'; +import { Options } from 'k6/options'; +import * as ws from 'k6/ws'; +//import { setup } from './common.ts'; export { setup } from './common.ts'; -const diamondToken = ''; -interface somethingInterface { - executor: string; - startVUs?: number; - stages: [{ duration: string; target: number; }] - gracefulRampDown: string; +const graphUrl = __ENV.GRAPH_URL; +interface VisitInput { + proposalCode: string; + proposalNumber: number; + number: number; } -interface k6Config { - insecureSkipTLSVerify: boolean; - scenarios: { - ping_graph_ramp: somethingInterface; - } - thresholds: { - http_req_duration: [string]; - } -} +//const templateQuery = `query K6WsTemplate($templateName: String!) { workflowTemplate(name: $templateName) { name } }`; +//const subscriptionQuery = `subscription K6WsSubscription($visit: VisitInput!, $name: String!) { workflow(visit: $visit, name: $name) { status { __typename } } }`; -export const options = { - insecureSkipTLSVerify: true, - scenarios: { - ping_graph_ramp: { - executor: 'ramping-vus', - startVUs: 0, - stages: [ - { duration: '30s', target: 10 }, - { duration: '1m', target: 50 }, - { duration: '2m', target: 100 }, - { duration: '1m', target: 200 }, - { duration: '1m', target: 300 }, - { duration: '1m', target: 500 }, - { duration: '30s', target: 0 }, - ], - gracefulRampDown: '10s', - }, - }, +export const options: Options = { + vus: 1, + iterations: 1, thresholds: { - //http_req_failed: ['rate<0.05'], - http_req_duration: ['p(95)<2000'], + http_req_failed: ['rate<0.05'], }, }; -const queryExamples = { - getWorkFlow: { - query: ` - query GetWorkFlow($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - visit { - proposalCode - proposalNumber - number - } - name - } - } - `, - variables: { - visit: { - proposalCode: "mg", - proposalNumber: 36964, - number: 1, - }, - name: "yeltsa-kcir", - }, - }, - getWorkflowByName: { - query: ` - query GetWorkflowByName($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - visit { - proposalCode - proposalNumber - number - } - name - } - } - `, - variables: { - visit: { - proposalCode: "mg", - proposalNumber: 36964, - number: 1, - }, - name: "yeltsa-kcir", - }, - }, - getWorkflowStatus: { - query: ` - query GetWorkflowStatus($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - name - status { - __typename - } - } - } - `, - variables: { - visit: { - proposalCode: "mg", - proposalNumber: 36964, - number: 1, +function graphWsUrl(): string { + const explicitUrl = __ENV.GRAPH_WS_URL || __ENV.WS_URL; + if (explicitUrl) return explicitUrl; + const url = new URL(graphUrl as string); + url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'; + url.pathname = `${url.pathname.replace(/\/$/, '')}/ws`; + return url.toString(); +} + +function graphqlRequest(token: string, query: string, variables: Record, operation: string): unknown { + const response = http.post( + graphUrl as string, + JSON.stringify({ query, variables }), + { + headers: { + Accept: 'application/json, multipart/mixed', + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, }, - name: "yeltsa-kcir", + tags: { endpoint: 'graphql', scenario: 'ws_subscription', operation }, }, - }, - getWorkflowCreator: { - query: ` - query GetWorkflowCreator($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - name - creator { - fedid - } - } - } - `, - variables: { - visit: { - proposalCode: "mg", - proposalNumber: 36964, - number: 1, + ); + if (response.status !== 200) fail(`GraphQL request failed: ${response.status} ${response.body}`); + const body = response.json() as { errors?: unknown[] }; + if (body.errors?.length) fail(`GraphQL returned errors: ${JSON.stringify(body.errors)}`); + return body; +} + +export default function(data: { token: string }): void { + const visit: VisitInput = { + proposalCode: "mg", + proposalNumber: 23, + number: 1 + } + const templateName = __ENV.WS_TEMPLATE_NAME || __ENV.TINY_TEMPLATE_NAME; + if (!templateName) fail('WS_TEMPLATE_NAME or TINY_TEMPLATE_NAME required'); + const submitMutation = `mutation K6WsSubmit($templateName: String!, $visit: VisitInput!, $parameters: JSON!) { submitWorkflowTemplate(name: $templateName, visit: $visit, parameters: $parameters) { name } }`; + + const submitted = graphqlRequest( + data.token, + submitMutation, + { templateName, visit, parameters }, + 'submitWorkflowTemplate', + ) as { data?: { submitWorkflowTemplate?: { name?: string } | null } }; + const workflowName = submitted.data?.submitWorkflowTemplate?.name; + if (!workflowName) fail('Websocket subscription submission did not return a workflow name'); + + const timeoutSeconds = Number(__ENV.K6_POLL_TIMEOUT_SECONDS || '300'); + let connectionAck = false; + let nextCount = 0; + let terminalStatus: string | null = null; + let timedOut = false; + + const response = ws.connect( + graphWsUrl(), + { + headers: { + Authorization: `Bearer ${data.token}`, + 'Sec-WebSocket-Protocol': 'graphql-transport-ws', }, - name: "yeltsa-kcir", + tags: { endpoint: 'graphql_ws', scenario: 'ws_subscription' }, }, - }, - listWorkflowTemplates: { - query: ` - query ListWorkflowTemplates($first: Int) { - workflowTemplates(first: $first) { - edges { - node { - name - } - } - pageInfo { - hasNextPage - endCursor - } + (socket) => { + socket.on('open', () => { + socket.send(JSON.stringify({ type: 'connection_init', payload: { Authorization: `Bearer ${data.token}` } })); + socket.setTimeout(() => { + timedOut = true; + socket.close(); + }, timeoutSeconds * 1000); + }); + + socket.on('message', (message) => { + const frame = JSON.parse(message) as { + type: string; + payload?: { data?: { workflow?: { status?: { __typename?: string } } } }; + }; + if (frame.type === 'connection_ack') { + connectionAck = true; + socket.send(JSON.stringify({ + id: '1', + type: 'subscribe', + payload: { + operationName: 'K6WsSubscription', + query: subscriptionQuery, + variables: { visit, name: workflowName }, + }, + })); + return; } - } - `, - variables: { - first: 10, - }, - }, - listWorkflowsForVisit: { - query: ` - query ListWorkflowsForVisit($visit: VisitInput!, $limit: Int) { - workflows(visit: $visit, limit: $limit) { - edges { - node { - name - status { - __typename - } - } - } - pageInfo { - hasNextPage - endCursor + if (frame.type === 'next') { + nextCount += 1; + terminalStatus = frame.payload?.data?.workflow?.status?.__typename || null; + if ( + terminalStatus === 'WorkflowSucceededStatus' || + terminalStatus === 'WorkflowFailedStatus' || + terminalStatus === 'WorkflowErroredStatus' + ) { + socket.send(JSON.stringify({ id: '1', type: 'complete' })); + socket.close(); } } - } - `, - variables: { - visit: { - proposalCode: "cm", - proposalNumber: 40661, - number: 1, - }, - limit: 30, + }); }, - }, -}; - + ); -const headers = { - 'Authorization': `Bearer ${diamondToken}`, - 'Content-Type': 'application/json', -}; - - -export default function() { - //const res = http.post('https://api.github.com/graphql', JSON.stringify({query: query}), {headers: headers}); - const url = 'https://staging.workflows.diamond.ac.uk/graphql'; - const payload = JSON.stringify({ - query: queryExamples.listWorkflowsForVisit.query, - variables: queryExamples.listWorkflowsForVisit.variables, + check(response, { + 'websocket upgrade succeeded': (r) => r.status === 101, + }); + check({ connectionAck, nextCount, terminalStatus, timedOut }, { + 'websocket connection acknowledged': (state) => state.connectionAck, + 'websocket emitted updates': (state) => state.nextCount > 0, + 'subscription saw workflow reach terminal success': (state) => + state.terminalStatus === 'WorkflowSucceededStatus', + 'websocket did not time out': (state) => !state.timedOut, }); - const params = { - headers: { - Accept: 'application/json, multipart/mixed', - 'Content-Type': 'application/json', - Authorization: `Bearer ${diamondToken}`, - Origin: 'https://staging.workflows.diamond.ac.uk', - Referer: 'https://staging.workflows.diamond.ac.uk', - }, - }; - const res = http.post(url, payload, params) - console.log(`status=${res && res.status}`); - console.log(`body=${res && res.body}`); - res; } - From 1088192221d9cb27f230ecf25286c7ff10d368fd Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 11:10:28 +0100 Subject: [PATCH 21/47] crap cd --- charts/k6-operator/tests/ws-subscription.ts | 80 +++--- k6/graphql-ws-subscription.js | 256 ++++++++++++++++++++ 2 files changed, 303 insertions(+), 33 deletions(-) create mode 100644 k6/graphql-ws-subscription.js diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index 3b58476e3..7ba019651 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -1,8 +1,7 @@ import http from 'k6/http'; -import { check, fail } from 'k6'; +import { check, fail, JSONValue } from 'k6'; import { Options } from 'k6/options'; import * as ws from 'k6/ws'; -//import { setup } from './common.ts'; export { setup } from './common.ts'; const graphUrl = __ENV.GRAPH_URL; @@ -13,8 +12,8 @@ interface VisitInput { number: number; } -//const templateQuery = `query K6WsTemplate($templateName: String!) { workflowTemplate(name: $templateName) { name } }`; -//const subscriptionQuery = `subscription K6WsSubscription($visit: VisitInput!, $name: String!) { workflow(visit: $visit, name: $name) { status { __typename } } }`; +const submitMutation = `mutation K6WsSubmit($templateName: String!, $visit: VisitInput!, $parameters: JSON!) { submitWorkflowTemplate(name: $templateName, visit: $visit, parameters: $parameters) { name } }`; +const subscriptionQuery = `subscription K6WsSubscription($visit: VisitInput!, $name: String!) { workflow(visit: $visit, name: $name) { status { __typename } } }`; export const options: Options = { vus: 1, @@ -34,43 +33,58 @@ function graphWsUrl(): string { return url.toString(); } -function graphqlRequest(token: string, query: string, variables: Record, operation: string): unknown { - const response = http.post( - graphUrl as string, - JSON.stringify({ query, variables }), +export default function(data: { token: string }): void { + const visit: VisitInput = { + proposalCode: "cm", + proposalNumber: 40661, + number: 1 + } + const templateName = "conditional-steos" + //if (!templateName) fail('WS_TEMPLATE_NAME or TINY_TEMPLATE_NAME required'); + //const parameters = optionalJsonEnv('K6_WS_SUBMISSION_PARAMETERS'); + const parameters = {} + + const submitResponse = http.post( + graphWsUrl(), + JSON.stringify({ + query: submitMutation, + variables: { + name: templateName, + visit, + parameters, + }, + }), { headers: { - Accept: 'application/json, multipart/mixed', - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, + Authorization: `Bearer ${data.token}`, + }, + tags: { + endpoint: "graphql", + operation: "submit_workflow_template", + scenario: "graphql_ws_subscription", }, - tags: { endpoint: 'graphql', scenario: 'ws_subscription', operation }, }, ); - if (response.status !== 200) fail(`GraphQL request failed: ${response.status} ${response.body}`); - const body = response.json() as { errors?: unknown[] }; - if (body.errors?.length) fail(`GraphQL returned errors: ${JSON.stringify(body.errors)}`); - return body; -} -export default function(data: { token: string }): void { - const visit: VisitInput = { - proposalCode: "mg", - proposalNumber: 23, - number: 1 + check(submitResponse, { + "submit mutation status is 200": (res) => res && res.status === 200, + }) + let submitBody: JSONValue | undefined = undefined; + try { + submitBody = submitResponse.json(); + } catch (_err) { + fail(`submit mutation returned non-JSON body. Status=${submitResponse.status}`); + } + + if (!submitBody || typeof submitBody !== "object" || Array.isArray(submitBody)) { + fail(`submit mutation returned errors: Status=${(submitResponse.status)}`); } - const templateName = __ENV.WS_TEMPLATE_NAME || __ENV.TINY_TEMPLATE_NAME; - if (!templateName) fail('WS_TEMPLATE_NAME or TINY_TEMPLATE_NAME required'); - const submitMutation = `mutation K6WsSubmit($templateName: String!, $visit: VisitInput!, $parameters: JSON!) { submitWorkflowTemplate(name: $templateName, visit: $visit, parameters: $parameters) { name } }`; - const submitted = graphqlRequest( - data.token, - submitMutation, - { templateName, visit, parameters }, - 'submitWorkflowTemplate', - ) as { data?: { submitWorkflowTemplate?: { name?: string } | null } }; - const workflowName = submitted.data?.submitWorkflowTemplate?.name; - if (!workflowName) fail('Websocket subscription submission did not return a workflow name'); + const workflowName = submitBody.data?.submit_workflow_template?.name; + //submitBody && + //submitBody.data && + //submitBody.data.submit_workflow_template && + //submitBody.data.submit_workflow_template.name; const timeoutSeconds = Number(__ENV.K6_POLL_TIMEOUT_SECONDS || '300'); let connectionAck = false; diff --git a/k6/graphql-ws-subscription.js b/k6/graphql-ws-subscription.js new file mode 100644 index 000000000..11d18ea72 --- /dev/null +++ b/k6/graphql-ws-subscription.js @@ -0,0 +1,256 @@ +import http from "k6/http"; +import ws from "k6/ws"; +import { check, fail } from "k6"; + +function normalizeWsUrl(url) { + if (url.startsWith("https://")) { + return `wss://${url.slice("https://".length)}`; + } + if (url.startsWith("http://")) { + return `ws://${url.slice("http://".length)}`; + } + return url; +} + +const workflowSubscription = ` + subscription K6WorkflowSubscription($visit: VisitInput!, $name: String!) { + workflow(visit: $visit, name: $name) { + name + status { + __typename + } + } + } +`; + +const submitWorkflowMutation = ` + mutation sendWorkflow($name: String!, $visit: VisitInput!, $parameters: JSON!) { + submitWorkflowTemplate(name: $name, visit: $visit, parameters: $parameters) { + name + visit { + proposalCode + proposalNumber + number + } + status { + __typename + } + } + } +`; + +export const options = { + vus: 1, + iterations: 1, +}; + +export default function () { + const graphqlUrl = "https://staging.workflows.diamond.ac.uk/graphql"; + const url = normalizeWsUrl( + "wss://staging.workflows.diamond.ac.uk/graphql/ws", + ); + const token = + "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTk5XYWVHTXFDWE1QY0l3eDA4ZjBsV18wcE9EX1MwV1lGeEZqbXZ0RU1RIn0.eyJleHAiOjE3NzU2NTI1NzYsImlhdCI6MTc3NTY1MTY3NiwiYXV0aF90aW1lIjoxNzc1NjUxMjA2LCJqdGkiOiJvbnJ0YWM6MjkxYmM2ZGMtYzQ1Yy01Mzc3LTkzMzgtMWYwYjc1YTIxOTBiIiwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS1kZXYuZGlhbW9uZC5hYy51ay9yZWFsbXMvZGxzIiwiYXVkIjpbIndvcmtmbG93cy1jbHVzdGVyLXN0YWdpbmciLCJhY2NvdW50Il0sInN1YiI6IjllZjg2ZGQ5LWUyN2MtNGNkNS1iNzc3LTY0NDI5MDA2YWUxMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndvcmtmbG93cy11aS1kZXYiLCJzaWQiOiI3M2E3ZmY0OS0wNTIxLTQ3MzItYTQ1ZS04MjcxZDQ5OGFmNTgiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZGxzIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGZlZGlkIGVtYWlsIHByb2ZpbGUgcG9zaXgtdWlkIiwicG9zaXhfdWlkIjoiMTIzMzM1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1haGlyIEFiYmFzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1pMTM4MjciLCJmZWRpZCI6InVtaTEzODI3IiwiZ2l2ZW5fbmFtZSI6Ik1haGlyIiwiZmFtaWx5X25hbWUiOiJBYmJhcyIsImVtYWlsIjoibWFoaXIuYWJiYXNAZGlhbW9uZC5hYy51ayJ9.LfeK504mu1xAAgGHRPR7_JC-uIgwcINprqVZWMQ9VOFRV8pN1K4VlogZNm3B-4IjPPfRJnIiYWTVY9bg_4gXO0X84uwHyR3XwdC4escBuOUTzMf0Jsayn1jQMfrm6sTSK0EpBwfaAzK4JUy7nFvcGBsa2OsZ7cUfYfy_ik8etM4kiT3J1RnSHqb6x_8qLCyjsNpTZryzDtu819oys79R-ZoRnxXwjFvcHHFQcl_b0GqObLLAQwehnob59Wf9o_BEOoI8GlKMuI_J5K3lbaF214YW1CxdupTyXDlX23PMvjXbjvtf3yiSaDztTP7VFhyvcL4rD2gDTT3wUgOpggERJg"; + const templateName = "conditional-steps"; + const parameters = {}; + const visit = { + proposalCode: "cm", + proposalNumber: 40661, + number: 1, + }; + const submitResponse = http.post( + graphqlUrl, + JSON.stringify({ + query: submitWorkflowMutation, + variables: { + name: templateName, + visit, + parameters, + }, + }), + { + headers: { + Authorization: `Bearer ${token}`, + Accept: + "application/graphql-response+json; charset=utf-8, application/json; charset=utf-8", + "Content-Type": "application/json", + }, + tags: { + endpoint: "graphql", + operation: "submit_workflow_template", + scenario: "graphql_ws_subscription", + }, + }, + ); + + check(submitResponse, { + "submit mutation status is 200": (res) => res && res.status === 200, + }); + + let submitBody = null; + try { + submitBody = submitResponse.json(); + } catch (_err) { + fail(`submit mutation returned non-JSON body. Status=${submitResponse.status}`); + } + + if (submitBody.errors && submitBody.errors.length > 0) { + fail(`submit mutation returned errors: ${JSON.stringify(submitBody.errors)}`); + } + + const workflowName = + submitBody && + submitBody.data && + submitBody.data.submitWorkflowTemplate && + submitBody.data.submitWorkflowTemplate.name; + + if (!workflowName) { + fail(`submit mutation did not return a workflow name: ${JSON.stringify(submitBody)}`); + } + + console.log(`submitted workflow=${workflowName}`); + + let sawAck = false; + let sawNext = false; + let sawComplete = false; + let protocolError = null; + let reachedTerminalStatus = false; + let lastStatusTypename = null; + + const response = ws.connect( + url, + { + headers: { + "Sec-WebSocket-Protocol": "graphql-transport-ws", + }, + tags: { + endpoint: "graphql_ws", + operation: "workflow_subscription", + scenario: "graphql_ws_subscription", + }, + }, + function (socket) { + socket.on("open", function () { + console.log(`connected to ${url}`); + socket.send( + JSON.stringify({ + type: "connection_init", + payload: { + Authorization: `Bearer ${token}`, + }, + }), + ); + }); + + socket.on("message", function (message) { + console.log(`frame=${message}`); + let frame; + try { + frame = JSON.parse(message); + } catch (_err) { + protocolError = `non-JSON websocket frame: ${message}`; + socket.close(); + return; + } + + if (frame.type === "connection_ack") { + sawAck = true; + socket.send( + JSON.stringify({ + id: "1", + type: "subscribe", + payload: { + query: workflowSubscription, + variables: { + visit, + name: workflowName, + }, + }, + }), + ); + return; + } + + if (frame.type === "next") { + sawNext = true; + console.log(`subscription payload=${JSON.stringify(frame.payload)}`); + const status = + frame.payload && + frame.payload.data && + frame.payload.data.workflow && + frame.payload.data.workflow.status; + const statusTypename = status && status.__typename; + + if (statusTypename) { + lastStatusTypename = statusTypename; + console.log(`workflow status=${statusTypename}`); + } + + if ( + statusTypename === "WorkflowSucceededStatus" || + statusTypename === "WorkflowFailedStatus" || + statusTypename === "WorkflowErroredStatus" + ) { + reachedTerminalStatus = true; + socket.send( + JSON.stringify({ + id: "1", + type: "complete", + }), + ); + socket.close(); + } + return; + } + + if (frame.type === "complete") { + sawComplete = true; + socket.close(); + return; + } + + if (frame.type === "error") { + protocolError = `graphql-ws error frame: ${JSON.stringify(frame.payload)}`; + socket.close(); + } + }); + + socket.on("error", function (err) { + protocolError = `websocket error: ${err && err.error ? err.error() : String(err)}`; + }); + + socket.setTimeout(function () { + if (!sawNext) { + protocolError = "timed out waiting for subscription payload"; + } else if (!reachedTerminalStatus) { + protocolError = `timed out before terminal workflow status; last status=${lastStatusTypename}`; + } + socket.close(); + }, 600000); + }, + ); + + check(response, { + "websocket upgrade status is 101": (res) => res && res.status === 101, + }); + + if (!response || response.status !== 101) { + fail(`websocket upgrade failed with status=${response ? response.status : "unknown"}`); + } + + if (protocolError) { + fail(protocolError); + } + + if (!sawAck) { + fail("did not receive graphql-ws connection_ack"); + } + + if (!sawNext && !sawComplete) { + fail("subscription ended without any next or complete frame"); + } + + if (!reachedTerminalStatus) { + fail(`subscription ended before terminal workflow status; last status=${lastStatusTypename}`); + } +} From 4d7d57cebb0868b39613640a8bda05bc9be033a2 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 11:24:58 +0100 Subject: [PATCH 22/47] increase VU count for ping-graph --- charts/k6-operator/tests/ping-graph.ts | 14 +++++++------- ...s-subscription.ts => ws-subscription.ts.ignore} | 0 2 files changed, 7 insertions(+), 7 deletions(-) rename charts/k6-operator/tests/{ws-subscription.ts => ws-subscription.ts.ignore} (100%) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 5b5404230..a03492ade 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -80,13 +80,13 @@ export const options: Options = { startVUs: 0, stages: [ { duration: '60s', target: 10 }, - //{ duration: '1m', target: 50 }, - //{ duration: '2m', target: 100 }, - //{ duration: '1m', target: 200 }, - //{ duration: '1m', target: 300 }, - //{ duration: '1m', target: 500 }, - //{ duration: '1m', target: 1000 }, - //{ duration: '30s', target: 0 }, + { duration: '1m', target: 50 }, + { duration: '2m', target: 100 }, + { duration: '1m', target: 200 }, + { duration: '1m', target: 300 }, + { duration: '1m', target: 500 }, + { duration: '1m', target: 1000 }, + { duration: '30s', target: 0 }, ], gracefulRampDown: '10s', }, diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts.ignore similarity index 100% rename from charts/k6-operator/tests/ws-subscription.ts rename to charts/k6-operator/tests/ws-subscription.ts.ignore From 7871738d14e982f04ee1910e6a8e2a24580f546b Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 13:07:52 +0100 Subject: [PATCH 23/47] add new visit for k6 --- .../k6-operator/templates/sessionspace.yaml | 30 ++ charts/k6-operator/tests/ping-graph.ts | 6 +- charts/k6-operator/values.yaml | 13 + k6/graphql-ws-subscription.js | 256 ------------------ 4 files changed, 46 insertions(+), 259 deletions(-) create mode 100644 charts/k6-operator/templates/sessionspace.yaml delete mode 100644 k6/graphql-ws-subscription.js diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml new file mode 100644 index 000000000..092e4b7c5 --- /dev/null +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -0,0 +1,30 @@ +{{- if .Values.sessionspace.enabled }} +apiVersion: v1 +kind: Namespace +metadata: + annotations: + argocd.argoproj.io/sync-wave: "-1" + labels: + app.kubernetes.io/managed-by: sessionspaces + name: {{ .Values.sessionspace.name }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + annotations: + argocd.argoproj.io/sync-wave: "0" + labels: + app.kubernetes.io/managed-by: sessionspaces + workflows.argoproj.io/configmap-type: Parameter + name: sessionspaces + namespace: {{ .Values.sessionspace.name }} +data: + end_date: {{ .Values.sessionspace.endDate | quote }} + gid: {{ .Values.sessionspace.gid | quote }} + instrument: {{ .Values.sessionspace.instrument | quote }} + members: {{ .Values.sessionspace.members | toJson | squote }} + proposal_code: {{ .Values.sessionspace.proposalCode | quote }} + proposal_number: {{ .Values.sessionspace.proposalNumber | quote }} + start_date: {{ .Values.sessionspace.startDate | quote }} + visit: {{ .Values.sessionspace.visit | quote }} +{{- end }} diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index a03492ade..6a423d620 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -50,8 +50,8 @@ const queryExamples: { `, variables: { visit: { - proposalCode: 'cm', - proposalNumber: 40661, + proposalCode: 'ks', + proposalNumber: 10000, number: 1, }, limit: 30, @@ -115,7 +115,7 @@ export default function(data: { token: string }): void { }; const res = http.post(graphUrl, payload, params); console.log(`status=${res && res.status}`); - console.log(`body=${res && res.body}`); + //console.log(`body=${res && res.body}`); // console.log(`status=${data && data.status}`) //console.log(`body=${tokenRes && tokenRes.body}`) } diff --git a/charts/k6-operator/values.yaml b/charts/k6-operator/values.yaml index b9cbf014c..a99b2d726 100644 --- a/charts/k6-operator/values.yaml +++ b/charts/k6-operator/values.yaml @@ -8,3 +8,16 @@ k6-operator: limits: cpu: 2000m memory: 2Gi + +sessionspace: + enabled: true + name: ks0000-1 + proposalCode: ks + proposalNumber: "10000" + visit: "1" + instrument: b01-1 + gid: "36055" + startDate: "2026-04-30 9:00:00.0" + endDate: "2026-05-22 9:00:00.0" + members: + - https://identity-dev.diamond.ac.uk/realms/dls/k6Operator diff --git a/k6/graphql-ws-subscription.js b/k6/graphql-ws-subscription.js deleted file mode 100644 index 11d18ea72..000000000 --- a/k6/graphql-ws-subscription.js +++ /dev/null @@ -1,256 +0,0 @@ -import http from "k6/http"; -import ws from "k6/ws"; -import { check, fail } from "k6"; - -function normalizeWsUrl(url) { - if (url.startsWith("https://")) { - return `wss://${url.slice("https://".length)}`; - } - if (url.startsWith("http://")) { - return `ws://${url.slice("http://".length)}`; - } - return url; -} - -const workflowSubscription = ` - subscription K6WorkflowSubscription($visit: VisitInput!, $name: String!) { - workflow(visit: $visit, name: $name) { - name - status { - __typename - } - } - } -`; - -const submitWorkflowMutation = ` - mutation sendWorkflow($name: String!, $visit: VisitInput!, $parameters: JSON!) { - submitWorkflowTemplate(name: $name, visit: $visit, parameters: $parameters) { - name - visit { - proposalCode - proposalNumber - number - } - status { - __typename - } - } - } -`; - -export const options = { - vus: 1, - iterations: 1, -}; - -export default function () { - const graphqlUrl = "https://staging.workflows.diamond.ac.uk/graphql"; - const url = normalizeWsUrl( - "wss://staging.workflows.diamond.ac.uk/graphql/ws", - ); - const token = - "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJnTk5XYWVHTXFDWE1QY0l3eDA4ZjBsV18wcE9EX1MwV1lGeEZqbXZ0RU1RIn0.eyJleHAiOjE3NzU2NTI1NzYsImlhdCI6MTc3NTY1MTY3NiwiYXV0aF90aW1lIjoxNzc1NjUxMjA2LCJqdGkiOiJvbnJ0YWM6MjkxYmM2ZGMtYzQ1Yy01Mzc3LTkzMzgtMWYwYjc1YTIxOTBiIiwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS1kZXYuZGlhbW9uZC5hYy51ay9yZWFsbXMvZGxzIiwiYXVkIjpbIndvcmtmbG93cy1jbHVzdGVyLXN0YWdpbmciLCJhY2NvdW50Il0sInN1YiI6IjllZjg2ZGQ5LWUyN2MtNGNkNS1iNzc3LTY0NDI5MDA2YWUxMCIsInR5cCI6IkJlYXJlciIsImF6cCI6IndvcmtmbG93cy11aS1kZXYiLCJzaWQiOiI3M2E3ZmY0OS0wNTIxLTQ3MzItYTQ1ZS04MjcxZDQ5OGFmNTgiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZGxzIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGZlZGlkIGVtYWlsIHByb2ZpbGUgcG9zaXgtdWlkIiwicG9zaXhfdWlkIjoiMTIzMzM1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1haGlyIEFiYmFzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1pMTM4MjciLCJmZWRpZCI6InVtaTEzODI3IiwiZ2l2ZW5fbmFtZSI6Ik1haGlyIiwiZmFtaWx5X25hbWUiOiJBYmJhcyIsImVtYWlsIjoibWFoaXIuYWJiYXNAZGlhbW9uZC5hYy51ayJ9.LfeK504mu1xAAgGHRPR7_JC-uIgwcINprqVZWMQ9VOFRV8pN1K4VlogZNm3B-4IjPPfRJnIiYWTVY9bg_4gXO0X84uwHyR3XwdC4escBuOUTzMf0Jsayn1jQMfrm6sTSK0EpBwfaAzK4JUy7nFvcGBsa2OsZ7cUfYfy_ik8etM4kiT3J1RnSHqb6x_8qLCyjsNpTZryzDtu819oys79R-ZoRnxXwjFvcHHFQcl_b0GqObLLAQwehnob59Wf9o_BEOoI8GlKMuI_J5K3lbaF214YW1CxdupTyXDlX23PMvjXbjvtf3yiSaDztTP7VFhyvcL4rD2gDTT3wUgOpggERJg"; - const templateName = "conditional-steps"; - const parameters = {}; - const visit = { - proposalCode: "cm", - proposalNumber: 40661, - number: 1, - }; - const submitResponse = http.post( - graphqlUrl, - JSON.stringify({ - query: submitWorkflowMutation, - variables: { - name: templateName, - visit, - parameters, - }, - }), - { - headers: { - Authorization: `Bearer ${token}`, - Accept: - "application/graphql-response+json; charset=utf-8, application/json; charset=utf-8", - "Content-Type": "application/json", - }, - tags: { - endpoint: "graphql", - operation: "submit_workflow_template", - scenario: "graphql_ws_subscription", - }, - }, - ); - - check(submitResponse, { - "submit mutation status is 200": (res) => res && res.status === 200, - }); - - let submitBody = null; - try { - submitBody = submitResponse.json(); - } catch (_err) { - fail(`submit mutation returned non-JSON body. Status=${submitResponse.status}`); - } - - if (submitBody.errors && submitBody.errors.length > 0) { - fail(`submit mutation returned errors: ${JSON.stringify(submitBody.errors)}`); - } - - const workflowName = - submitBody && - submitBody.data && - submitBody.data.submitWorkflowTemplate && - submitBody.data.submitWorkflowTemplate.name; - - if (!workflowName) { - fail(`submit mutation did not return a workflow name: ${JSON.stringify(submitBody)}`); - } - - console.log(`submitted workflow=${workflowName}`); - - let sawAck = false; - let sawNext = false; - let sawComplete = false; - let protocolError = null; - let reachedTerminalStatus = false; - let lastStatusTypename = null; - - const response = ws.connect( - url, - { - headers: { - "Sec-WebSocket-Protocol": "graphql-transport-ws", - }, - tags: { - endpoint: "graphql_ws", - operation: "workflow_subscription", - scenario: "graphql_ws_subscription", - }, - }, - function (socket) { - socket.on("open", function () { - console.log(`connected to ${url}`); - socket.send( - JSON.stringify({ - type: "connection_init", - payload: { - Authorization: `Bearer ${token}`, - }, - }), - ); - }); - - socket.on("message", function (message) { - console.log(`frame=${message}`); - let frame; - try { - frame = JSON.parse(message); - } catch (_err) { - protocolError = `non-JSON websocket frame: ${message}`; - socket.close(); - return; - } - - if (frame.type === "connection_ack") { - sawAck = true; - socket.send( - JSON.stringify({ - id: "1", - type: "subscribe", - payload: { - query: workflowSubscription, - variables: { - visit, - name: workflowName, - }, - }, - }), - ); - return; - } - - if (frame.type === "next") { - sawNext = true; - console.log(`subscription payload=${JSON.stringify(frame.payload)}`); - const status = - frame.payload && - frame.payload.data && - frame.payload.data.workflow && - frame.payload.data.workflow.status; - const statusTypename = status && status.__typename; - - if (statusTypename) { - lastStatusTypename = statusTypename; - console.log(`workflow status=${statusTypename}`); - } - - if ( - statusTypename === "WorkflowSucceededStatus" || - statusTypename === "WorkflowFailedStatus" || - statusTypename === "WorkflowErroredStatus" - ) { - reachedTerminalStatus = true; - socket.send( - JSON.stringify({ - id: "1", - type: "complete", - }), - ); - socket.close(); - } - return; - } - - if (frame.type === "complete") { - sawComplete = true; - socket.close(); - return; - } - - if (frame.type === "error") { - protocolError = `graphql-ws error frame: ${JSON.stringify(frame.payload)}`; - socket.close(); - } - }); - - socket.on("error", function (err) { - protocolError = `websocket error: ${err && err.error ? err.error() : String(err)}`; - }); - - socket.setTimeout(function () { - if (!sawNext) { - protocolError = "timed out waiting for subscription payload"; - } else if (!reachedTerminalStatus) { - protocolError = `timed out before terminal workflow status; last status=${lastStatusTypename}`; - } - socket.close(); - }, 600000); - }, - ); - - check(response, { - "websocket upgrade status is 101": (res) => res && res.status === 101, - }); - - if (!response || response.status !== 101) { - fail(`websocket upgrade failed with status=${response ? response.status : "unknown"}`); - } - - if (protocolError) { - fail(protocolError); - } - - if (!sawAck) { - fail("did not receive graphql-ws connection_ack"); - } - - if (!sawNext && !sawComplete) { - fail("subscription ended without any next or complete frame"); - } - - if (!reachedTerminalStatus) { - fail(`subscription ended before terminal workflow status; last status=${lastStatusTypename}`); - } -} From b3b691e45d7ef9c543e1f00d4017aa35ce5749cc Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 13:09:29 +0100 Subject: [PATCH 24/47] change sessionspace to dev --- charts/k6-operator/staging-values.yaml | 13 +++++++++++++ charts/k6-operator/values.yaml | 12 ------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/charts/k6-operator/staging-values.yaml b/charts/k6-operator/staging-values.yaml index 9045ebc9b..50a31e928 100644 --- a/charts/k6-operator/staging-values.yaml +++ b/charts/k6-operator/staging-values.yaml @@ -8,3 +8,16 @@ k6-operator: limits: cpu: 1000m memory: 1Gi + +sessionspace: + enabled: true + name: ks0000-1 + proposalCode: ks + proposalNumber: "10000" + visit: "1" + instrument: b01-1 + gid: "36055" + startDate: "2026-04-30 9:00:00.0" + endDate: "2026-05-22 9:00:00.0" + members: + - https://identity-dev.diamond.ac.uk/realms/dls/k6Operator diff --git a/charts/k6-operator/values.yaml b/charts/k6-operator/values.yaml index a99b2d726..61312ca33 100644 --- a/charts/k6-operator/values.yaml +++ b/charts/k6-operator/values.yaml @@ -9,15 +9,3 @@ k6-operator: cpu: 2000m memory: 2Gi -sessionspace: - enabled: true - name: ks0000-1 - proposalCode: ks - proposalNumber: "10000" - visit: "1" - instrument: b01-1 - gid: "36055" - startDate: "2026-04-30 9:00:00.0" - endDate: "2026-05-22 9:00:00.0" - members: - - https://identity-dev.diamond.ac.uk/realms/dls/k6Operator From 8d80867091b61398ba1ac43da20894f9a172ab10 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 15:16:47 +0100 Subject: [PATCH 25/47] new sessionsspace? --- charts/apps/staging-values.yaml | 3 ++- charts/k6-operator/staging-values.yaml | 2 +- charts/k6-operator/templates/sessionspace.yaml | 2 +- charts/k6-operator/values.yaml | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/charts/apps/staging-values.yaml b/charts/apps/staging-values.yaml index 3c1929fc2..734fd37d2 100644 --- a/charts/apps/staging-values.yaml +++ b/charts/apps/staging-values.yaml @@ -88,5 +88,6 @@ kueue: k6Operator: enabled: true targetRevision: HEAD - extraValueFiles: [] + extraValueFiles: + - staging-values.yaml valuesObject: {} diff --git a/charts/k6-operator/staging-values.yaml b/charts/k6-operator/staging-values.yaml index 50a31e928..009a8404a 100644 --- a/charts/k6-operator/staging-values.yaml +++ b/charts/k6-operator/staging-values.yaml @@ -8,7 +8,6 @@ k6-operator: limits: cpu: 1000m memory: 1Gi - sessionspace: enabled: true name: ks0000-1 @@ -21,3 +20,4 @@ sessionspace: endDate: "2026-05-22 9:00:00.0" members: - https://identity-dev.diamond.ac.uk/realms/dls/k6Operator + diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index 092e4b7c5..77b3538dd 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -1,4 +1,4 @@ -{{- if .Values.sessionspace.enabled }} +{{- if and .Values.sessionspace .Values.sessionspace.enabled }} apiVersion: v1 kind: Namespace metadata: diff --git a/charts/k6-operator/values.yaml b/charts/k6-operator/values.yaml index 61312ca33..eada324f9 100644 --- a/charts/k6-operator/values.yaml +++ b/charts/k6-operator/values.yaml @@ -9,3 +9,5 @@ k6-operator: cpu: 2000m memory: 2Gi +sessionspace: + enabled: false From 1133ed13fbb19272444eff8b2417291a3d7946c8 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 15:35:46 +0100 Subject: [PATCH 26/47] val --- charts/k6-operator/staging-values.yaml | 2 +- .../k6-operator/templates/sessionspace.yaml | 28 ++++++++----------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/charts/k6-operator/staging-values.yaml b/charts/k6-operator/staging-values.yaml index 009a8404a..dff42e717 100644 --- a/charts/k6-operator/staging-values.yaml +++ b/charts/k6-operator/staging-values.yaml @@ -10,7 +10,7 @@ k6-operator: memory: 1Gi sessionspace: enabled: true - name: ks0000-1 + name: ks10000-1 proposalCode: ks proposalNumber: "10000" visit: "1" diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index 77b3538dd..b17042c29 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -1,30 +1,24 @@ -{{- if and .Values.sessionspace .Values.sessionspace.enabled }} apiVersion: v1 kind: Namespace metadata: - annotations: - argocd.argoproj.io/sync-wave: "-1" labels: app.kubernetes.io/managed-by: sessionspaces - name: {{ .Values.sessionspace.name }} + name: ks0000-1 --- apiVersion: v1 kind: ConfigMap +data: + end_date: "2026-05-22 9:00:00.0" + gid: "36055" + instrument: b01-1 + members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' + proposal_code: ks + proposal_number: "0000" + start_date: "2026-04-30 9:00:00.0" + visit: "1" metadata: - annotations: - argocd.argoproj.io/sync-wave: "0" labels: app.kubernetes.io/managed-by: sessionspaces workflows.argoproj.io/configmap-type: Parameter name: sessionspaces - namespace: {{ .Values.sessionspace.name }} -data: - end_date: {{ .Values.sessionspace.endDate | quote }} - gid: {{ .Values.sessionspace.gid | quote }} - instrument: {{ .Values.sessionspace.instrument | quote }} - members: {{ .Values.sessionspace.members | toJson | squote }} - proposal_code: {{ .Values.sessionspace.proposalCode | quote }} - proposal_number: {{ .Values.sessionspace.proposalNumber | quote }} - start_date: {{ .Values.sessionspace.startDate | quote }} - visit: {{ .Values.sessionspace.visit | quote }} -{{- end }} + namespace: ks0000-1 From 9d8884df8b1e305ff1c8d01dd01e2a0e4cc5e7b5 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 15:37:40 +0100 Subject: [PATCH 27/47] octal --- charts/k6-operator/templates/sessionspace.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index b17042c29..f71469f4e 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -3,7 +3,7 @@ kind: Namespace metadata: labels: app.kubernetes.io/managed-by: sessionspaces - name: ks0000-1 + name: ks10000-1 --- apiVersion: v1 kind: ConfigMap @@ -13,7 +13,7 @@ data: instrument: b01-1 members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' proposal_code: ks - proposal_number: "0000" + proposal_number: "10000" start_date: "2026-04-30 9:00:00.0" visit: "1" metadata: From a1f59e2ca43d3c5cd0e2e9b6d53c8612fc6f425d Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 15:41:07 +0100 Subject: [PATCH 28/47] 1 --- charts/k6-operator/templates/sessionspace.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index f71469f4e..2f484aef5 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -21,4 +21,4 @@ metadata: app.kubernetes.io/managed-by: sessionspaces workflows.argoproj.io/configmap-type: Parameter name: sessionspaces - namespace: ks0000-1 + namespace: ks10000-1 From cc39c99949c2ad9b4eb6b46b6e9ff64df79a9db1 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 30 Apr 2026 15:58:20 +0100 Subject: [PATCH 29/47] delete configmap-type --- charts/k6-operator/templates/sessionspace.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index 2f484aef5..de1890129 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -19,6 +19,9 @@ data: metadata: labels: app.kubernetes.io/managed-by: sessionspaces - workflows.argoproj.io/configmap-type: Parameter + #workflows.argoproj.io/configmap-type: Parameter name: sessionspaces namespace: ks10000-1 + + # rolebindings not created + # v kubectl get roles -n ks10000-1 From e503e276edb2b37188c320e7e2355fd5cf2f8aaf Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 10:08:20 +0100 Subject: [PATCH 30/47] add rolebinding --- .../k6-operator/templates/sessionspace.yaml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index de1890129..65c790cee 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -22,6 +22,37 @@ metadata: #workflows.argoproj.io/configmap-type: Parameter name: sessionspaces namespace: ks10000-1 +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: argo-workflow + namespace: ks10000-1 + ownerReferences: + - apiVersion: v1 + kind: ServiceAccount + name: argo-workflow +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argo-workflow +subjects: +- kind: ServiceAccount + name: argo-workflow + namespace: ks10000-1 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: visit-member + namespace: ks10000-1 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: visit-member +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: User + name: oidc:https://identity-dev.diamond.ac.uk/realms/dls/k6Operator # rolebindings not created # v kubectl get roles -n ks10000-1 From f08276f4c2eb3f7718104630ee66b1aed1d74ec3 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 10:18:13 +0100 Subject: [PATCH 31/47] rbs --- charts/k6-operator/templates/sessionspace.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index 65c790cee..ab97e2e9d 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -22,6 +22,7 @@ metadata: #workflows.argoproj.io/configmap-type: Parameter name: sessionspaces namespace: ks10000-1 +--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: From 23f4b3ffc513ccea555ba43655b75b915c66379e Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 10:20:21 +0100 Subject: [PATCH 32/47] rb --- .../k6-operator/templates/sessionspace.yaml | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index ab97e2e9d..0d5eeb856 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -5,24 +5,24 @@ metadata: app.kubernetes.io/managed-by: sessionspaces name: ks10000-1 --- -apiVersion: v1 -kind: ConfigMap -data: - end_date: "2026-05-22 9:00:00.0" - gid: "36055" - instrument: b01-1 - members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' - proposal_code: ks - proposal_number: "10000" - start_date: "2026-04-30 9:00:00.0" - visit: "1" -metadata: - labels: - app.kubernetes.io/managed-by: sessionspaces - #workflows.argoproj.io/configmap-type: Parameter - name: sessionspaces - namespace: ks10000-1 ---- +#apiVersion: v1 +#kind: ConfigMap +#data: +# end_date: "2026-05-22 9:00:00.0" +# gid: "36055" +# instrument: b01-1 +# members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' +# proposal_code: ks +# proposal_number: "10000" +# start_date: "2026-04-30 9:00:00.0" +# visit: "1" +#metadata: +# labels: +# app.kubernetes.io/managed-by: sessionspaces +# #workflows.argoproj.io/configmap-type: Parameter +# name: sessionspaces +# namespace: ks10000-1 +#--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: From 2cc99247a97b2ee15cd7383d14e3e1d394bab2b2 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 11:07:15 +0100 Subject: [PATCH 33/47] rmv rbc --- .../k6-operator/templates/sessionspace.yaml | 62 +++++-------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index 0d5eeb856..de1890129 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -5,55 +5,23 @@ metadata: app.kubernetes.io/managed-by: sessionspaces name: ks10000-1 --- -#apiVersion: v1 -#kind: ConfigMap -#data: -# end_date: "2026-05-22 9:00:00.0" -# gid: "36055" -# instrument: b01-1 -# members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' -# proposal_code: ks -# proposal_number: "10000" -# start_date: "2026-04-30 9:00:00.0" -# visit: "1" -#metadata: -# labels: -# app.kubernetes.io/managed-by: sessionspaces -# #workflows.argoproj.io/configmap-type: Parameter -# name: sessionspaces -# namespace: ks10000-1 -#--- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: argo-workflow - namespace: ks10000-1 - ownerReferences: - - apiVersion: v1 - kind: ServiceAccount - name: argo-workflow -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: argo-workflow -subjects: -- kind: ServiceAccount - name: argo-workflow - namespace: ks10000-1 ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding +apiVersion: v1 +kind: ConfigMap +data: + end_date: "2026-05-22 9:00:00.0" + gid: "36055" + instrument: b01-1 + members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' + proposal_code: ks + proposal_number: "10000" + start_date: "2026-04-30 9:00:00.0" + visit: "1" metadata: - name: visit-member + labels: + app.kubernetes.io/managed-by: sessionspaces + #workflows.argoproj.io/configmap-type: Parameter + name: sessionspaces namespace: ks10000-1 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: visit-member -subjects: -- apiGroup: rbac.authorization.k8s.io - kind: User - name: oidc:https://identity-dev.diamond.ac.uk/realms/dls/k6Operator # rolebindings not created # v kubectl get roles -n ks10000-1 From 2a4e61c8b2bd38af694b3d192bbe48dd8ef0180d Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 12:18:06 +0100 Subject: [PATCH 34/47] add rbac, svc and subscription test --- charts/k6-operator/templates/rbac.yaml | 32 +++++++++++++++++++ charts/k6-operator/templates/service.yaml | 15 +++++++++ ...scription.ts.ignore => ws-subscription.ts} | 29 +++++++++++------ 3 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 charts/k6-operator/templates/rbac.yaml create mode 100644 charts/k6-operator/templates/service.yaml rename charts/k6-operator/tests/{ws-subscription.ts.ignore => ws-subscription.ts} (89%) diff --git a/charts/k6-operator/templates/rbac.yaml b/charts/k6-operator/templates/rbac.yaml new file mode 100644 index 000000000..38819ce80 --- /dev/null +++ b/charts/k6-operator/templates/rbac.yaml @@ -0,0 +1,32 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: argo-workflow + namespace: ks10000-1 + ownerReferences: + - apiVersion: v1 + kind: ServiceAccount + name: argo-workflow + uid: ks12345 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argo-workflow +subjects: +- kind: ServiceAccount + name: argo-workflow + namespace: ks10000-1 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: visit-member + namespace: ks10000-1 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: visit-member +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: User + name: oidc:https://identity-dev.diamond.ac.uk/realms/dls/k6Operator diff --git a/charts/k6-operator/templates/service.yaml b/charts/k6-operator/templates/service.yaml new file mode 100644 index 000000000..76d264ccf --- /dev/null +++ b/charts/k6-operator/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/managed-by: kyverno + generate.kyverno.io/policy-name: workflows-sessionspace + generate.kyverno.io/policy-namespace: "" + generate.kyverno.io/rule-name: generate-argo-workflow-service-account + generate.kyverno.io/trigger-group: "" + generate.kyverno.io/trigger-kind: Namespace + generate.kyverno.io/trigger-namespace: "" + generate.kyverno.io/trigger-uid: 225e0bc5-1410-419d-880c-97fcc98d17bf + generate.kyverno.io/trigger-version: v1 + name: argo-workflow + namespace: ks10000-1 diff --git a/charts/k6-operator/tests/ws-subscription.ts.ignore b/charts/k6-operator/tests/ws-subscription.ts similarity index 89% rename from charts/k6-operator/tests/ws-subscription.ts.ignore rename to charts/k6-operator/tests/ws-subscription.ts index 7ba019651..e4fecc393 100644 --- a/charts/k6-operator/tests/ws-subscription.ts.ignore +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -23,6 +23,16 @@ export const options: Options = { }, }; +interface MutationResponse { + data?: { + submitWorkflowTemplate?: { + name?: string; + visit?: VisitInput; + status?: string | null; + }; + }; +} + function graphWsUrl(): string { const explicitUrl = __ENV.GRAPH_WS_URL || __ENV.WS_URL; @@ -35,11 +45,11 @@ function graphWsUrl(): string { export default function(data: { token: string }): void { const visit: VisitInput = { - proposalCode: "cm", - proposalNumber: 40661, + proposalCode: "ks", + proposalNumber: 10000, number: 1 } - const templateName = "conditional-steos" + const templateName = "example-template" //if (!templateName) fail('WS_TEMPLATE_NAME or TINY_TEMPLATE_NAME required'); //const parameters = optionalJsonEnv('K6_WS_SUBMISSION_PARAMETERS'); const parameters = {} @@ -69,9 +79,9 @@ export default function(data: { token: string }): void { check(submitResponse, { "submit mutation status is 200": (res) => res && res.status === 200, }) - let submitBody: JSONValue | undefined = undefined; + let submitBody: MutationResponse | undefined = undefined; try { - submitBody = submitResponse.json(); + submitBody = submitResponse.json() as MutationResponse; } catch (_err) { fail(`submit mutation returned non-JSON body. Status=${submitResponse.status}`); } @@ -80,11 +90,10 @@ export default function(data: { token: string }): void { fail(`submit mutation returned errors: Status=${(submitResponse.status)}`); } - const workflowName = submitBody.data?.submit_workflow_template?.name; - //submitBody && - //submitBody.data && - //submitBody.data.submit_workflow_template && - //submitBody.data.submit_workflow_template.name; + const workflowName = submitBody?.data?.submitWorkflowTemplate?.name; + if (!workflowName) { + fail(`submit mutation returned no workflows name. Status=${submitResponse.status}`); + } const timeoutSeconds = Number(__ENV.K6_POLL_TIMEOUT_SECONDS || '300'); let connectionAck = false; From a89ce3f8cd6cb08e2058a83b9a1b906fa6df51a0 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 12:29:23 +0100 Subject: [PATCH 35/47] config for ws-test --- ...estrun.yaml => k6-ping-graph-testrun.yaml} | 2 +- .../templates/k6-ws-subscription-testrun.yaml | 45 +++++++++++++++++++ charts/k6-operator/tests/ws-subscription.ts | 2 +- 3 files changed, 47 insertions(+), 2 deletions(-) rename charts/k6-operator/templates/{k6-testrun.yaml => k6-ping-graph-testrun.yaml} (98%) create mode 100644 charts/k6-operator/templates/k6-ws-subscription-testrun.yaml diff --git a/charts/k6-operator/templates/k6-testrun.yaml b/charts/k6-operator/templates/k6-ping-graph-testrun.yaml similarity index 98% rename from charts/k6-operator/templates/k6-testrun.yaml rename to charts/k6-operator/templates/k6-ping-graph-testrun.yaml index 9ebe5e190..259636a67 100644 --- a/charts/k6-operator/templates/k6-testrun.yaml +++ b/charts/k6-operator/templates/k6-ping-graph-testrun.yaml @@ -6,7 +6,7 @@ metadata: name: k6-ping-graph namespace: {{ .Release.Namespace}} spec: - parallelism: 4 + parallelism: 1 script: configMap: name: k6-configmap diff --git a/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml b/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml new file mode 100644 index 000000000..4ee8813f9 --- /dev/null +++ b/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml @@ -0,0 +1,45 @@ +# k6-resource.yml + +apiVersion: k6.io/v1alpha1 +kind: TestRun +metadata: + name: k6-ws-subscription + namespace: {{ .Release.Namespace}} +spec: + parallelism: 1 + script: + configMap: + name: k6-configmap + file: ws-subscription.ts + runner: + env: + - name: KEYCLOAK_CLIENT_ID + valueFrom: + secretKeyRef: + name: graph-proxy-k6-auth + key: KEYCLOAK_CLIENT_ID + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: graph-proxy-k6-auth + key: KEYCLOAK_CLIENT_SECRET + - name: KEYCLOAK_TOKEN_URL + value: https://identity-dev.diamond.ac.uk/realms/dls/protocol/openid-connect/token + - name: GRAPH_URL + value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi + starter: + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi + diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index e4fecc393..680540ebb 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -1,5 +1,5 @@ import http from 'k6/http'; -import { check, fail, JSONValue } from 'k6'; +import { check, fail } from 'k6'; import { Options } from 'k6/options'; import * as ws from 'k6/ws'; export { setup } from './common.ts'; From 6dd04546e131e79e447a510b7dcef7a7ae205fd9 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 12:35:16 +0100 Subject: [PATCH 36/47] ws url --- .../templates/k6-ws-subscription-testrun.yaml | 2 ++ charts/k6-operator/tests/ws-subscription.ts | 13 +++---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml b/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml index 4ee8813f9..573146950 100644 --- a/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml +++ b/charts/k6-operator/templates/k6-ws-subscription-testrun.yaml @@ -27,6 +27,8 @@ spec: value: https://identity-dev.diamond.ac.uk/realms/dls/protocol/openid-connect/token - name: GRAPH_URL value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql + - name: GRAPH_WS_URL + value: ws://graph-proxy.graph-proxy.svc.cluster.local:80/graphql/ws resources: limits: cpu: 1000m diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index 680540ebb..9c3bfc666 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -5,6 +5,7 @@ import * as ws from 'k6/ws'; export { setup } from './common.ts'; const graphUrl = __ENV.GRAPH_URL; +const graphWsUrl = __ENV.GRAPH_WS_URL; interface VisitInput { proposalCode: string; @@ -34,14 +35,6 @@ interface MutationResponse { } -function graphWsUrl(): string { - const explicitUrl = __ENV.GRAPH_WS_URL || __ENV.WS_URL; - if (explicitUrl) return explicitUrl; - const url = new URL(graphUrl as string); - url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'; - url.pathname = `${url.pathname.replace(/\/$/, '')}/ws`; - return url.toString(); -} export default function(data: { token: string }): void { const visit: VisitInput = { @@ -55,7 +48,7 @@ export default function(data: { token: string }): void { const parameters = {} const submitResponse = http.post( - graphWsUrl(), + graphUrl, JSON.stringify({ query: submitMutation, variables: { @@ -102,7 +95,7 @@ export default function(data: { token: string }): void { let timedOut = false; const response = ws.connect( - graphWsUrl(), + graphWsUrl, { headers: { Authorization: `Bearer ${data.token}`, From ca29d3f04981ca393293f22b96905caa1517ca3e Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 12:44:36 +0100 Subject: [PATCH 37/47] changes --- charts/k6-operator/tests/ws-subscription.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index 9c3bfc666..0acae4cc3 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -52,7 +52,7 @@ export default function(data: { token: string }): void { JSON.stringify({ query: submitMutation, variables: { - name: templateName, + templateName, visit, parameters, }, @@ -94,6 +94,9 @@ export default function(data: { token: string }): void { let terminalStatus: string | null = null; let timedOut = false; + if (!graphWsUrl) { + fail("GRAPH_WS_URL required"); + } const response = ws.connect( graphWsUrl, { From 884939ab45ecf82cb22fb888082eced19b2d5d09 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 12:56:15 +0100 Subject: [PATCH 38/47] add logging --- charts/k6-operator/tests/ping-graph.ts | 2 +- charts/k6-operator/tests/ws-subscription.ts | 27 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 6a423d620..325bc913a 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -115,7 +115,7 @@ export default function(data: { token: string }): void { }; const res = http.post(graphUrl, payload, params); console.log(`status=${res && res.status}`); - //console.log(`body=${res && res.body}`); + console.log(`body=${res && res.body}`); // console.log(`status=${data && data.status}`) //console.log(`body=${tokenRes && tokenRes.body}`) } diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index 0acae4cc3..a4bceda7a 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -47,6 +47,7 @@ export default function(data: { token: string }): void { //const parameters = optionalJsonEnv('K6_WS_SUBMISSION_PARAMETERS'); const parameters = {} + console.log(`submitting workflow template=${templateName} visit=${JSON.stringify(visit)} graphUrl=${graphUrl}`); const submitResponse = http.post( graphUrl, JSON.stringify({ @@ -68,6 +69,7 @@ export default function(data: { token: string }): void { }, }, ); + console.log(`submit mutation response status=${submitResponse.status}`); check(submitResponse, { "submit mutation status is 200": (res) => res && res.status === 200, @@ -75,7 +77,9 @@ export default function(data: { token: string }): void { let submitBody: MutationResponse | undefined = undefined; try { submitBody = submitResponse.json() as MutationResponse; + console.log(`submit mutation response body=${JSON.stringify(submitBody)}`); } catch (_err) { + console.log(`submit mutation non-JSON body=${String(submitResponse.body)}`); fail(`submit mutation returned non-JSON body. Status=${submitResponse.status}`); } @@ -87,6 +91,7 @@ export default function(data: { token: string }): void { if (!workflowName) { fail(`submit mutation returned no workflows name. Status=${submitResponse.status}`); } + console.log(`submitted workflow name=${workflowName}`); const timeoutSeconds = Number(__ENV.K6_POLL_TIMEOUT_SECONDS || '300'); let connectionAck = false; @@ -97,6 +102,7 @@ export default function(data: { token: string }): void { if (!graphWsUrl) { fail("GRAPH_WS_URL required"); } + console.log(`connecting websocket url=${graphWsUrl} timeoutSeconds=${timeoutSeconds}`); const response = ws.connect( graphWsUrl, { @@ -108,20 +114,24 @@ export default function(data: { token: string }): void { }, (socket) => { socket.on('open', () => { + console.log('websocket open; sending connection_init'); socket.send(JSON.stringify({ type: 'connection_init', payload: { Authorization: `Bearer ${data.token}` } })); socket.setTimeout(() => { timedOut = true; + console.log(`websocket timed out after ${timeoutSeconds}s; closing`); socket.close(); }, timeoutSeconds * 1000); }); socket.on('message', (message) => { + console.log(`websocket message=${message}`); const frame = JSON.parse(message) as { type: string; payload?: { data?: { workflow?: { status?: { __typename?: string } } } }; }; if (frame.type === 'connection_ack') { connectionAck = true; + console.log(`websocket connection_ack; subscribing workflow=${workflowName}`); socket.send(JSON.stringify({ id: '1', type: 'subscribe', @@ -136,22 +146,37 @@ export default function(data: { token: string }): void { if (frame.type === 'next') { nextCount += 1; terminalStatus = frame.payload?.data?.workflow?.status?.__typename || null; + console.log(`websocket next count=${nextCount} terminalStatus=${terminalStatus}`); if ( terminalStatus === 'WorkflowSucceededStatus' || terminalStatus === 'WorkflowFailedStatus' || - terminalStatus === 'WorkflowErroredStatus' + terminalStatus === 'WorkflowErroredStatus' || + terminalStatus === 'WorkflowRunningStatus' ) { + console.log(`websocket terminal status=${terminalStatus}; sending complete and closing`); socket.send(JSON.stringify({ id: '1', type: 'complete' })); socket.close(); } } }); + + socket.on('close', () => { + console.log('websocket closed'); + }); + + socket.on('error', (err) => { + console.log(`websocket error=${JSON.stringify(err)}`); + }); }, ); + console.log(`websocket connect response status=${response.status}`); check(response, { 'websocket upgrade succeeded': (r) => r.status === 101, }); + console.log( + `websocket final state connectionAck=${connectionAck} nextCount=${nextCount} terminalStatus=${terminalStatus} timedOut=${timedOut}`, + ); check({ connectionAck, nextCount, terminalStatus, timedOut }, { 'websocket connection acknowledged': (state) => state.connectionAck, 'websocket emitted updates': (state) => state.nextCount > 0, From ffa69242fc293603514e956abfc8ebe45b63c7ee Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 13:00:29 +0100 Subject: [PATCH 39/47] running logging --- charts/k6-operator/tests/ws-subscription.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index a4bceda7a..a61a750a0 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -147,11 +147,13 @@ export default function(data: { token: string }): void { nextCount += 1; terminalStatus = frame.payload?.data?.workflow?.status?.__typename || null; console.log(`websocket next count=${nextCount} terminalStatus=${terminalStatus}`); + if (terminalStatus === 'WorkflowRunningStatus') { + console.log(`workflow is running workflow=${workflowName}`); + } if ( terminalStatus === 'WorkflowSucceededStatus' || terminalStatus === 'WorkflowFailedStatus' || - terminalStatus === 'WorkflowErroredStatus' || - terminalStatus === 'WorkflowRunningStatus' + terminalStatus === 'WorkflowErroredStatus' ) { console.log(`websocket terminal status=${terminalStatus}; sending complete and closing`); socket.send(JSON.stringify({ id: '1', type: 'complete' })); From e98bd6d8d7b5d416b2144d18f86ea41fd30e57ec Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Fri, 1 May 2026 13:16:03 +0100 Subject: [PATCH 40/47] change timeout to 30m --- charts/k6-operator/tests/ws-subscription.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/tests/ws-subscription.ts b/charts/k6-operator/tests/ws-subscription.ts index a61a750a0..e73e77ffc 100644 --- a/charts/k6-operator/tests/ws-subscription.ts +++ b/charts/k6-operator/tests/ws-subscription.ts @@ -6,6 +6,7 @@ export { setup } from './common.ts'; const graphUrl = __ENV.GRAPH_URL; const graphWsUrl = __ENV.GRAPH_WS_URL; +const timeoutSeconds = 1800; interface VisitInput { proposalCode: string; @@ -93,7 +94,6 @@ export default function(data: { token: string }): void { } console.log(`submitted workflow name=${workflowName}`); - const timeoutSeconds = Number(__ENV.K6_POLL_TIMEOUT_SECONDS || '300'); let connectionAck = false; let nextCount = 0; let terminalStatus: string | null = null; From d2d1207d7e14a585a8ba0746d98c973974286c10 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Tue, 5 May 2026 10:40:34 +0100 Subject: [PATCH 41/47] list workflows for visit --- charts/k6-operator/tests/ping-graph.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/k6-operator/tests/ping-graph.ts b/charts/k6-operator/tests/ping-graph.ts index 325bc913a..9bc6edd44 100644 --- a/charts/k6-operator/tests/ping-graph.ts +++ b/charts/k6-operator/tests/ping-graph.ts @@ -103,7 +103,8 @@ export default function(data: { token: string }): void { const payload = JSON.stringify({ - query: queryExamples.listTemplates.query, + query: queryExamples.listWorkflowsForVisit.query, + variables: queryExamples.listWorkflowsForVisit.variables, }); const params = { From d03c8c1c4fc4c1cef436d1effced5592d7e0d219 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 6 May 2026 10:35:41 +0100 Subject: [PATCH 42/47] fake? --- .../templates/k6-operator-configmap.yaml | 1 - .../templates/k6-ping-graph-testrun.yaml | 1 - .../templates/k6-probe-configmap.yaml | 117 ++++++++++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 charts/k6-operator/templates/k6-probe-configmap.yaml diff --git a/charts/k6-operator/templates/k6-operator-configmap.yaml b/charts/k6-operator/templates/k6-operator-configmap.yaml index 4eed08079..e19d00667 100644 --- a/charts/k6-operator/templates/k6-operator-configmap.yaml +++ b/charts/k6-operator/templates/k6-operator-configmap.yaml @@ -5,4 +5,3 @@ metadata: namespace: {{ .Release.Namespace}} data: {{(.Files.Glob "tests/*.ts").AsConfig| indent 2}} - diff --git a/charts/k6-operator/templates/k6-ping-graph-testrun.yaml b/charts/k6-operator/templates/k6-ping-graph-testrun.yaml index 259636a67..c59d7d854 100644 --- a/charts/k6-operator/templates/k6-ping-graph-testrun.yaml +++ b/charts/k6-operator/templates/k6-ping-graph-testrun.yaml @@ -1,5 +1,4 @@ # k6-resource.yml - apiVersion: k6.io/v1alpha1 kind: TestRun metadata: diff --git a/charts/k6-operator/templates/k6-probe-configmap.yaml b/charts/k6-operator/templates/k6-probe-configmap.yaml new file mode 100644 index 000000000..9bb764ea3 --- /dev/null +++ b/charts/k6-operator/templates/k6-probe-configmap.yaml @@ -0,0 +1,117 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: k6-ws-map + namespace: {{ .Release.Namespace}} +data: + k6-ws-subscription-testrun.yaml: | + apiVersion: k6.io/v1alpha1 + kind: TestRun + metadata: + name: k6-ws-subscription-probe + namespace: {{ .Release.Namespace}} + spec: + parallelism: 1 + script: + configMap: + name: k6-configmap + file: ws-subscription.ts + runner: + env: + - name: KEYCLOAK_CLIENT_ID + valueFrom: + secretKeyRef: + name: graph-proxy-k6-auth + key: KEYCLOAK_CLIENT_ID + - name: KEYCLOAK_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: graph-proxy-k6-auth + key: KEYCLOAK_CLIENT_SECRET + - name: KEYCLOAK_TOKEN_URL + value: https://identity-dev.diamond.ac.uk/realms/dls/protocol/openid-connect/token + - name: GRAPH_URL + value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql + - name: GRAPH_WS_URL + value: ws://graph-proxy.graph-proxy.svc.cluster.local:80/graphql/ws + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi + starter: + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 500m + memory: 500Mi +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: k6-probe-runner +rules: + - apiGroups: + - k6.io + resources: + - testruns + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: k6-probe-runner +roleRef: + kind: Role + name: k6-probe-runner + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: k6-probe-runner + namespace: {{ .Release.Namespace}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: k6-probe-runner + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: k6-ws-cron +spec: + schedule: "*/5 * * * *" + concurrencyPolicy: Forbid + jobTemplate: + spec: + template: + spec: + serviceAccount: k6-probe-runner + containers: + - name: kubectl + image: bitnami/kubectl + volumeMounts: + - name: k6-yaml + mountPath: /tmp/ + command: + - /bin/bash + args: + - -c + - 'kubectl delete -f /tmp/k6-ws-subscription-testrun.yaml; kubectl apply -f /tmp/k6-ws-subscription-testrun.yaml' + restartPolicy: OnFailure + volumes: + - name: k6-yaml + configMap: + name: k6-ws-map From db7ba7270b9f3af97dd0fe2119cfb62e1cf5a86c Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 6 May 2026 11:08:16 +0100 Subject: [PATCH 43/47] 30 under 30 --- charts/k6-operator/templates/k6-probe-configmap.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/templates/k6-probe-configmap.yaml b/charts/k6-operator/templates/k6-probe-configmap.yaml index 9bb764ea3..26bdeb587 100644 --- a/charts/k6-operator/templates/k6-probe-configmap.yaml +++ b/charts/k6-operator/templates/k6-probe-configmap.yaml @@ -92,7 +92,7 @@ kind: CronJob metadata: name: k6-ws-cron spec: - schedule: "*/5 * * * *" + schedule: "*/30 * * * *" concurrencyPolicy: Forbid jobTemplate: spec: From 6e06d7ca4346ee04a2204103d9892185626293a7 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 6 May 2026 14:46:11 +0100 Subject: [PATCH 44/47] add user --- charts/k6-operator/templates/sessionspace.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/k6-operator/templates/sessionspace.yaml b/charts/k6-operator/templates/sessionspace.yaml index de1890129..8e75cd64d 100644 --- a/charts/k6-operator/templates/sessionspace.yaml +++ b/charts/k6-operator/templates/sessionspace.yaml @@ -11,7 +11,7 @@ data: end_date: "2026-05-22 9:00:00.0" gid: "36055" instrument: b01-1 - members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator"]' + members: '["https://identity-dev.diamond.ac.uk/realms/dls/k6Operator", "umi13827"]' proposal_code: ks proposal_number: "10000" start_date: "2026-04-30 9:00:00.0" From aa0acadec1d57394493c644e1610c45db4f5978b Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Wed, 6 May 2026 14:49:06 +0100 Subject: [PATCH 45/47] add me pls --- charts/k6-operator/templates/rbac.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/k6-operator/templates/rbac.yaml b/charts/k6-operator/templates/rbac.yaml index 38819ce80..dae5c110d 100644 --- a/charts/k6-operator/templates/rbac.yaml +++ b/charts/k6-operator/templates/rbac.yaml @@ -30,3 +30,6 @@ subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: oidc:https://identity-dev.diamond.ac.uk/realms/dls/k6Operator +- apiGroup: rbac.authorization.k8s.io + kind: User + name: oidc:umi13827 From 025acec2e52f3a68d4bb76ee1b97ad5f8bf6c895 Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 7 May 2026 11:07:32 +0100 Subject: [PATCH 46/47] AI wrote all of this. blame thomas --- charts/k6-operator/Chart.yaml | 4 ++++ charts/k6-operator/templates/k6-probe-configmap.yaml | 2 ++ 2 files changed, 6 insertions(+) diff --git a/charts/k6-operator/Chart.yaml b/charts/k6-operator/Chart.yaml index e6ad91d85..837933e33 100644 --- a/charts/k6-operator/Chart.yaml +++ b/charts/k6-operator/Chart.yaml @@ -9,3 +9,7 @@ dependencies: - name: k6-operator repository: https://grafana.github.io/helm-charts version: 4.3.0 + - name: sealed-secrets + repository: bitnamilegacy/sealed-secrets-controller + version: 2.16.0 + diff --git a/charts/k6-operator/templates/k6-probe-configmap.yaml b/charts/k6-operator/templates/k6-probe-configmap.yaml index 26bdeb587..831769f96 100644 --- a/charts/k6-operator/templates/k6-probe-configmap.yaml +++ b/charts/k6-operator/templates/k6-probe-configmap.yaml @@ -34,6 +34,8 @@ data: value: http://graph-proxy.graph-proxy.svc.cluster.local:80/graphql - name: GRAPH_WS_URL value: ws://graph-proxy.graph-proxy.svc.cluster.local:80/graphql/ws + - name: OTEL_ENDPOINT + value: https://otel.tracing.diamond.ac.uk:4318 resources: limits: cpu: 1000m From e10756bdc7f3273ac0e924903171c43ea7a46e4c Mon Sep 17 00:00:00 2001 From: Mahir Abbas Date: Thu, 7 May 2026 11:31:13 +0100 Subject: [PATCH 47/47] see. blame thomas --- charts/k6-operator/Chart.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/charts/k6-operator/Chart.yaml b/charts/k6-operator/Chart.yaml index 837933e33..855f73f5a 100644 --- a/charts/k6-operator/Chart.yaml +++ b/charts/k6-operator/Chart.yaml @@ -9,7 +9,4 @@ dependencies: - name: k6-operator repository: https://grafana.github.io/helm-charts version: 4.3.0 - - name: sealed-secrets - repository: bitnamilegacy/sealed-secrets-controller - version: 2.16.0