From 27b254015eb203ccc4d1d5c27aa06eec846c0a2c Mon Sep 17 00:00:00 2001 From: sylvain senechal Date: Tue, 17 Feb 2026 15:38:13 +0100 Subject: [PATCH 1/9] run zenko node tests in codespace Issue: ZENKO-5181 --- .devcontainer/devcontainer.json | 1 + tests/zenko_tests/README.md | 19 +++++ .../node_tests/run-node-tests-locally.sh | 75 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100755 tests/zenko_tests/node_tests/run-node-tests-locally.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6af23450aa..19cf7b1653 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,6 +13,7 @@ "ghcr.io/devcontainers/features/docker-in-docker": {}, "ghcr.io/devcontainers/features/github-cli:1": {}, "ghcr.io/devcontainers/features/node:1": {}, + "ghcr.io/devcontainers/features/python:1": {}, "ghcr.io/devcontainers/features/sshd:1": {}, "ghcr.io/devcontainers-extra/features/kind:1": {}, "ghcr.io/devcontainers/features/aws-cli:1": {}, diff --git a/tests/zenko_tests/README.md b/tests/zenko_tests/README.md index 5932fa1d40..9223ea7868 100644 --- a/tests/zenko_tests/README.md +++ b/tests/zenko_tests/README.md @@ -1,9 +1,28 @@ # Table of contents +- [How to run node tests in a Codespace](#how-to-run-node-tests-locally-in-a-codespace) - [How to write iam policy e2e tests](#how-to-write-iam-policy-e2e-tests) - [How to run zenko end2end test locally with zenko-operator](#how-to-run-zenko-end2end-test-locally-with-zenko-operator) - [How to run zenko end2end test locally with cloudserver and vault](#how-to-run-zenko-end2end-test-locally-with-cloudserver-and-vault) +# How to run node tests locally in a Codespace + +```bash +cd tests/zenko_tests/node_tests + +# Run a specific test with grep +./run-node-tests-locally.sh "should list objects in V2 format" "cloudserver/bucketGetV2" + +# Run all tests in a folder +./run-node-tests-locally.sh "" "cloudserver" + +# Build and use a custom image +docker build -t my-e2e:local ../ +./run-node-tests-locally.sh "should list objects" "cloudserver" my-e2e:local +``` + +To switch images, delete the pod first: `kubectl delete pod node-tests-local` + # How to write iam policy e2e tests All iam policy controlled tests go under `node_tests/iam_policies`, diff --git a/tests/zenko_tests/node_tests/run-node-tests-locally.sh b/tests/zenko_tests/node_tests/run-node-tests-locally.sh new file mode 100755 index 0000000000..b21a25718a --- /dev/null +++ b/tests/zenko_tests/node_tests/run-node-tests-locally.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Script to run mocha node tests from a GitHub Codespace +# Uses a persistent pod with kubectl cp to sync local changes +# +# Usage: ./run-node-tests-locally.sh [image] +# +# Examples: +# ./run-node-tests-locally.sh "should list objects" "cloudserver/bucketGetV2" +# ./run-node-tests-locally.sh "should list objects" "cloudserver" my-e2e:local +# ./run-node-tests-locally.sh "" "smoke_tests" # Run all smoke tests +# ./run-node-tests-locally.sh "" "cloudserver" # Run all cloudserver tests +# +# If you need to use a different image, delete pod first: +# kubectl delete pod node-tests-local + +set -e + +ZENKO_NAME=${ZENKO_NAME:-end2end} +IMAGE_NAME="${3:-ghcr.io/scality/zenko/zenko-e2e:latest}" +POD_NAME="node-tests-local" + +TEST_GREP="${1:-should list objects in V2 format}" +TEST_PATH="${2:-cloudserver}" + +ZENKO_ACCESS_KEY=$(kubectl get secret end2end-management-account-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) +ZENKO_SECRET_KEY=$(kubectl get secret end2end-management-account-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) + +CLOUDSERVER_ENDPOINT="http://${ZENKO_NAME}-connector-s3api.default.svc.cluster.local:80" +VAULT_ENDPOINT="http://${ZENKO_NAME}-management-vault-iam-admin-api:80" +VAULT_STS_ENDPOINT="http://${ZENKO_NAME}-connector-vault-sts-api:80" +BACKBEAT_API_ENDPOINT="http://${ZENKO_NAME}-management-backbeat-api.default.svc.cluster.local:80" + +# Path inside the zenko-e2e container +CONTAINER_PATH="/usr/local/bin/tests/node_tests" + +if ! kubectl get pod "$POD_NAME" &>/dev/null; then + echo "Loading image into kind cluster, can take 1~3 minutes" + kind load docker-image "$IMAGE_NAME" --name kind || true + + kubectl run "$POD_NAME" \ + --image="$IMAGE_NAME" \ + --restart=Never \ + --image-pull-policy=IfNotPresent \ + --command -- sleep infinity + kubectl wait --for=condition=Ready pod/"$POD_NAME" --timeout=5m +fi + +# Copy local test files so that ongoing changes are included +kubectl exec "$POD_NAME" -- rm -rf "$CONTAINER_PATH"/cloudserver "$CONTAINER_PATH"/backbeat "$CONTAINER_PATH"/smoke_tests "$CONTAINER_PATH"/iam_policies "$CONTAINER_PATH"/utils +kubectl cp ./cloudserver "$POD_NAME":"$CONTAINER_PATH"/cloudserver +kubectl cp ./backbeat "$POD_NAME":"$CONTAINER_PATH"/backbeat +kubectl cp ./smoke_tests "$POD_NAME":"$CONTAINER_PATH"/smoke_tests +kubectl cp ./iam_policies "$POD_NAME":"$CONTAINER_PATH"/iam_policies +kubectl cp ./utils "$POD_NAME":"$CONTAINER_PATH"/utils +kubectl cp ./s3SDK.js "$POD_NAME":"$CONTAINER_PATH"/s3SDK.js +kubectl cp ./stsSDK.js "$POD_NAME":"$CONTAINER_PATH"/stsSDK.js +kubectl cp ./VaultClient.js "$POD_NAME":"$CONTAINER_PATH"/VaultClient.js +kubectl cp ./init_test.js "$POD_NAME":"$CONTAINER_PATH"/init_test.js + +kubectl exec "$POD_NAME" -- env \ + ZENKO_ACCESS_KEY="$ZENKO_ACCESS_KEY" \ + ZENKO_SECRET_KEY="$ZENKO_SECRET_KEY" \ + CLOUDSERVER_ENDPOINT="$CLOUDSERVER_ENDPOINT" \ + VAULT_ENDPOINT="$VAULT_ENDPOINT" \ + VAULT_STS_ENDPOINT="$VAULT_STS_ENDPOINT" \ + BACKBEAT_API_ENDPOINT="$BACKBEAT_API_ENDPOINT" \ + sh -c "cd $CONTAINER_PATH && \ + npx mocha \ + --exit \ + --timeout 10000 \ + --recursive \ + --grep '$TEST_GREP' \ + '$TEST_PATH'" + From 11d9d1982fd0a51146c1c9bfbb21d1d6ca98e095 Mon Sep 17 00:00:00 2001 From: sylvain senechal Date: Tue, 17 Feb 2026 15:38:43 +0100 Subject: [PATCH 2/9] cleanup unused files related to docker-entrypoint Issue: ZENKO-5181 --- tests/zenko_tests/Dockerfile | 5 --- tests/zenko_tests/docker-entrypoint.sh | 41 ----------------------- tests/zenko_tests/node_tests/npm_chain.sh | 15 --------- tests/zenko_tests/wait_for_ceph.sh | 11 ------ 4 files changed, 72 deletions(-) delete mode 100644 tests/zenko_tests/docker-entrypoint.sh delete mode 100755 tests/zenko_tests/node_tests/npm_chain.sh delete mode 100644 tests/zenko_tests/wait_for_ceph.sh diff --git a/tests/zenko_tests/Dockerfile b/tests/zenko_tests/Dockerfile index 6c7e80f244..c1f3be52b7 100644 --- a/tests/zenko_tests/Dockerfile +++ b/tests/zenko_tests/Dockerfile @@ -43,12 +43,7 @@ RUN python3 -m pip install -r /tmp/requirements.txt tox && \ rm -rf /tmp/npm-* && \ rm -rf /var/cache/apk/* -COPY ./node_tests/npm_chain.sh ./docker-entrypoint.sh ./wait_for_ceph.sh /usr/local/bin/ -RUN chmod +x /usr/local/bin/npm_chain.sh /usr/local/bin/docker-entrypoint.sh /usr/local/bin/wait_for_ceph.sh - # Copy Tests COPY . /usr/local/bin/tests/ WORKDIR /usr/local/bin/tests - -CMD [ "docker-entrypoint.sh" ] diff --git a/tests/zenko_tests/docker-entrypoint.sh b/tests/zenko_tests/docker-entrypoint.sh deleted file mode 100644 index 11da706a8b..0000000000 --- a/tests/zenko_tests/docker-entrypoint.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -EXIT_STATUS="0" - -enter_and_run() { - local old_cwd="$(pwd)" - cd "$1" - sh -c "$2" - if [ "$?" -ne "0" ]; then - EXIT_STATUS="1" - echo "$2 have failed" - fi - cd "$old_cwd" -} - -echo 'Waiting for ceph' -sh wait_for_ceph.sh zenko-ceph-ceph-in-a-box - -# Setup our environment -python3 create_buckets.py -if [ "$?" -ne "0" ]; then - exit 1 -fi - -# Run the tests -echo "Running test stage: $STAGE" -if [ "$STAGE" = 'python-tests' ]; then - enter_and_run python_tests "./run.sh $PYTHON_ARGS" -elif [ "$STAGE" = 'node-tests-01' ]; then - enter_and_run node_tests "npm_chain.sh test_aws_crr test_api test_location_quota test_bucket_get_v2 test_ingestion_oob_s3c test_bucket_policy" -elif [ "$STAGE" = 'node-tests-02' ]; then - enter_and_run node_tests "npm_chain.sh test_gcp_crr test_azure_crr test_one_to_many test_lifecycle test_crr_pause_resume" -else - enter_and_run python_tests "./run.sh $PYTHON_ARGS" - # test_crr runs "test_aws_crr test_gcp_crr test_azure_crr test_one_to_many" - enter_and_run node_tests "npm_chain.sh test_crr test_api test_crr_pause_resume test_location_quota test_bucket_get_v2 test_bucket_policy" -fi - -python3 cleans3c.py - -exit "$EXIT_STATUS" diff --git a/tests/zenko_tests/node_tests/npm_chain.sh b/tests/zenko_tests/node_tests/npm_chain.sh deleted file mode 100755 index 768d558a15..0000000000 --- a/tests/zenko_tests/node_tests/npm_chain.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -EXIT_STATUS="0" - -while [ ! -z "$1" ]; do - echo "npm run $1" - npm run "$1" - status="$?" - if [ "$status" -gt 0 ]; then - echo "command: npm run $1 failed with exit code $status" >&2 - EXIT_STATUS="1" - fi - shift -done -exit "$EXIT_STATUS" diff --git a/tests/zenko_tests/wait_for_ceph.sh b/tests/zenko_tests/wait_for_ceph.sh deleted file mode 100644 index 0037cd9492..0000000000 --- a/tests/zenko_tests/wait_for_ceph.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# This script is needed because RADOS Gateway -# will open the port before beginning to serve traffic -# causing wait_for_local_port.bash to exit immediately - -EP="zenko-ceph-ceph-in-a-box" -echo "Waiting for ceph at $EP" -while [ -z "$(curl $EP 2>/dev/null)" ]; do - sleep 1 -done From 61ce18152a4398da2289145c4cd915b1a69d0d29 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 19 Feb 2026 22:55:08 +0000 Subject: [PATCH 3/9] config loader for env variables Issue: ZENKO-5182 --- .devcontainer/README.md | 14 +- .github/scripts/end2end/load-config.sh | 240 +++++++ .github/scripts/end2end/run-e2e-ctst.sh | 5 + .github/scripts/end2end/run-e2e-test.sh | 4 + tests/config-loader/index.js | 71 ++ tests/config-loader/k8sClient.js | 22 + tests/config-loader/package.json | 11 + tests/config-loader/yarn.lock | 639 ++++++++++++++++++ .../features/crrReplicationS3utils.feature | 3 +- tests/ctst/run-ctst-locally.sh | 18 +- tests/ctst/run-test-pod.sh | 23 + tests/ctst/world/Zenko.ts | 7 +- tests/ctst/yarn.lock | 13 + .../node_tests/run-node-tests-locally.sh | 4 +- 14 files changed, 1051 insertions(+), 23 deletions(-) create mode 100755 .github/scripts/end2end/load-config.sh create mode 100644 tests/config-loader/index.js create mode 100644 tests/config-loader/k8sClient.js create mode 100644 tests/config-loader/package.json create mode 100644 tests/config-loader/yarn.lock create mode 100755 tests/ctst/run-test-pod.sh diff --git a/.devcontainer/README.md b/.devcontainer/README.md index d49bda6dc5..771b5c12ec 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -69,8 +69,12 @@ Now you can use aws cli to interact with the S3 service ### Inspecting Codespace creation logs -You can inspect the logs of the Codespace creation this way: -1. Press `Ctrl+Shift+P` (or `Cmd+Shift+P` on Mac) -2. Type "Codespaces: Export Logs" and select it -3. A zip file will be downloaded to your local machine -4. In the zip, look at the `creation.log` file \ No newline at end of file +You can inspect the logs of the Codespace creation in 2 ways way: +1. When Codespace creation is still running : +Use Cmd/Ctrl + Shift + P -> View Creation Log to see full logs + +2. When the setup is finished, dump the logs : +a. Press `Ctrl+Shift+P` (or `Cmd+Shift+P` on Mac) +b. Type "Codespaces: Export Logs" and select it +c. A zip file will be downloaded to your local machine +d. In the zip, look at the `creation.log` file diff --git a/.github/scripts/end2end/load-config.sh b/.github/scripts/end2end/load-config.sh new file mode 100755 index 0000000000..130aa9309f --- /dev/null +++ b/.github/scripts/end2end/load-config.sh @@ -0,0 +1,240 @@ +#!/bin/bash +# Unified configuration loader for Zenko end-to-end tests +# +# Usage: +# source load-config.sh ctst # Load config for CTST tests +# source load-config.sh e2e # Load config for zenko_tests (e2e) +# source load-config.sh common # Load only common config +# +# After sourcing, use the helpers: +# kubectl exec pod -- env $(env_for_kubectl_exec) command +# kubectl run pod $(env_for_kubectl_run) -- command + +set -e +x + +SUITE="${1:-common}" + + +# Extract a value from the top-level env block in end2end.yaml. +# Strips ${{ ... }} expressions (secrets/context refs) leaving an empty string. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORKFLOWS_END2END_YAML="${SCRIPT_DIR}/../../workflows/end2end.yaml" +get_env_var() { + local key="$1" + yq eval ".env.${key}" "$WORKFLOWS_END2END_YAML" | sed 's/\${{[^}]*}}//g' | tr -d '"' +} + +# Output helpers – both derived from the same ENV_VARS array. +# Usage: kubectl exec pod -- env $(env_for_kubectl_exec) command +env_for_kubectl_exec() { printf '%s ' "${ENV_VARS[@]}"; } +# Usage: kubectl run pod $(env_for_kubectl_run) -- command +env_for_kubectl_run() { printf -- '--env=%s ' "${ENV_VARS[@]}"; } + +# ============================================================================= +# COMMON - Used by both CTST and zenko_tests +# ============================================================================= +load_common() { + ENV_VARS=() + + # From end2end.yaml + ENV_VARS+=("SUBDOMAIN=$(get_env_var SUBDOMAIN)") + ENV_VARS+=("KEYCLOAK_TEST_REALM_NAME=$(get_env_var OIDC_REALM)") + ENV_VARS+=("KEYCLOAK_TEST_CLIENT_ID=$(get_env_var OIDC_CLIENT_ID)") + ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var OIDC_USERNAME)") + ENV_VARS+=("KEYCLOAK_TEST_PASSWORD=$(get_env_var OIDC_PASSWORD)") + ENV_VARS+=("KEYCLOAK_TEST_HOST=$(get_env_var OIDC_HOST)") + ENV_VARS+=("KEYCLOAK_TEST_PORT=80") + ENV_VARS+=("KEYCLOAK_TEST_GRANT_TYPE=password") + ENV_VARS+=("AZURE_ACCOUNT_NAME=$(get_env_var AZURE_ACCOUNT_NAME)") + ENV_VARS+=("AZURE_SECRET_KEY=$(get_env_var AZURE_SECRET_KEY)") + ENV_VARS+=("CLOUDSERVER_ENDPOINT=http://end2end-connector-s3api.default.svc.cluster.local:80") + ENV_VARS+=("VAULT_ENDPOINT=http://end2end-management-vault-iam-admin-api:80") + + # From k8s: Zenko account credentials + ENV_VARS+=("ZENKO_ACCESS_KEY=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.AccessKeyId}' | base64 -d)") + ENV_VARS+=("ZENKO_SECRET_KEY=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.SecretAccessKey}' | base64 -d)") + + # From k8s: Admin vault credentials + ENV_VARS+=("ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d)") + ENV_VARS+=("ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d)") +} + +# ============================================================================= +# CTST ONLY - Variables specific to cucumber tests +# ============================================================================= +load_ctst() { + load_common + + # Hardcoded CTST values + ENV_VARS+=("ZENKO_ACCOUNT_NAME=zenko-ctst") + ENV_VARS+=("STORAGE_MANAGER_USER_NAME=ctst_storage_manager") + ENV_VARS+=("STORAGE_ACCOUNT_OWNER_USER_NAME=ctst_storage_account_owner") + ENV_VARS+=("DATA_CONSUMER_USER_NAME=ctst_data_consumer") + ENV_VARS+=("DATA_ACCESSOR_USER_NAME=ctst_data_accessor") + ENV_VARS+=("ZENKO_PORT=80") + ENV_VARS+=("UTILIZATION_SERVICE_PORT=80") + ENV_VARS+=("AZURE_ARCHIVE_ACCESS_TIER=Hot") + ENV_VARS+=("AZURE_ARCHIVE_MANIFEST_ACCESS_TIER=Hot") + + # From end2end.yaml + ENV_VARS+=("DR_SUBDOMAIN=$(get_env_var DR_SUBDOMAIN)") + ENV_VARS+=("PROMETHEUS_NAME=$(get_env_var PROMETHEUS_NAME)") + ENV_VARS+=("AZURE_BACKEND_ENDPOINT=$(get_env_var AZURE_BACKEND_ENDPOINT)") + ENV_VARS+=("AZURE_BACKEND_QUEUE_ENDPOINT=$(get_env_var AZURE_BACKEND_QUEUE_ENDPOINT)") + ENV_VARS+=("AZURE_ARCHIVE_BUCKET_NAME=$(get_env_var AZURE_ARCHIVE_BUCKET_NAME)") + ENV_VARS+=("AZURE_ARCHIVE_BUCKET_NAME_2=$(get_env_var AZURE_ARCHIVE_BUCKET_NAME_2)") + ENV_VARS+=("AZURE_ARCHIVE_QUEUE_NAME=$(get_env_var AZURE_ARCHIVE_QUEUE_NAME)") + ENV_VARS+=("NOTIF_DEST_NAME=$(get_env_var NOTIF_DEST_NAME)") + ENV_VARS+=("NOTIF_DEST_TOPIC=$(get_env_var NOTIF_DEST_TOPIC)") + ENV_VARS+=("NOTIF_ALT_DEST_NAME=$(get_env_var NOTIF_ALT_DEST_NAME)") + ENV_VARS+=("NOTIF_ALT_DEST_TOPIC=$(get_env_var NOTIF_ALT_DEST_TOPIC)") + ENV_VARS+=("NOTIF_AUTH_DEST_NAME=$(get_env_var NOTIF_AUTH_DEST_NAME)") + ENV_VARS+=("NOTIF_AUTH_DEST_TOPIC=$(get_env_var NOTIF_AUTH_DEST_TOPIC)") + ENV_VARS+=("NOTIF_AUTH_DEST_USERNAME=$(get_env_var NOTIF_AUTH_DEST_USERNAME)") + ENV_VARS+=("NOTIF_AUTH_DEST_PASSWORD=$(get_env_var NOTIF_AUTH_DEST_PASSWORD)") + + # From k8s: DR admin credentials (only exists if PRA is deployed) + ENV_VARS+=("DR_ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' 2>/dev/null | base64 -d || true)") + ENV_VARS+=("DR_ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' 2>/dev/null | base64 -d || true)") + + # From k8s: Kafka config + local kafka_host_port kafka_port + kafka_host_port=$(kubectl get secret -l app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end \ + -o jsonpath='{.items[0].data.config\.json}' | base64 -d | jq -r '.kafka.hosts') + kafka_port="${kafka_host_port#*:}" + ENV_VARS+=("KAFKA_HOST_PORT=${kafka_host_port}") + ENV_VARS+=("KAFKA_AUTH_HOST_PORT=end2end-base-queue-auth-0:${kafka_port}") + + # From k8s: Sorbet/kafka topics + local sorbet_config + sorbet_config=$(kubectl get secret -l "app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end" \ + -o jsonpath='{.items[0].data.config\.json}' | base64 -d) + ENV_VARS+=("KAFKA_DEAD_LETTER_TOPIC=$(echo "${sorbet_config}" | jq -r '."kafka-dead-letter-topic"')") + ENV_VARS+=("KAFKA_OBJECT_TASK_TOPIC=$(echo "${sorbet_config}" | jq -r '."kafka-object-task-topic"')") + ENV_VARS+=("KAFKA_GC_REQUEST_TOPIC=$(echo "${sorbet_config}" | jq -r '."kafka-gc-request-topic"')") + + # From k8s: Zenko resource values + ENV_VARS+=("TIME_PROGRESSION_FACTOR=$(kubectl get zenko end2end -o jsonpath='{.metadata.annotations.zenko\.io/time-progression-factor}')") + ENV_VARS+=("INSTANCE_ID=$(kubectl get zenko end2end -o jsonpath='{.status.instanceID}')") + ENV_VARS+=("KAFKA_CLEANER_INTERVAL=$(kubectl get zenko end2end -o jsonpath='{.spec.kafkaCleaner.interval}')") + ENV_VARS+=("SORBETD_RESTORE_TIMEOUT=$(kubectl get zenko end2end -o jsonpath='{.spec.sorbet.server.azure.restoreTimeout}')") + ENV_VARS+=("UTILIZATION_SERVICE_HOST=$(kubectl get zenko end2end -o jsonpath='{.spec.scuba.api.ingress.hostname}')") + + # From k8s: Backbeat API config + local cloudserver_config + cloudserver_config=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end \ + -o jsonpath='{.items[0].data.config\.json}' | base64 -d) + ENV_VARS+=("BACKBEAT_API_HOST=$(echo "${cloudserver_config}" | jq -r '.backbeat.host')") + ENV_VARS+=("BACKBEAT_API_PORT=$(echo "${cloudserver_config}" | jq -r '.backbeat.port')") + + # From k8s: Service users credentials (individual components) + ENV_VARS+=("BACKBEAT_LCBP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d)") + ENV_VARS+=("BACKBEAT_LCC_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-conductor-1\.json}' | base64 -d)") + ENV_VARS+=("BACKBEAT_LCOP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-op-1\.json}' | base64 -d)") + ENV_VARS+=("BACKBEAT_QP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d)") + ENV_VARS+=("SORBET_FWD_2_ACCESSKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d)") + ENV_VARS+=("SORBET_FWD_2_SECRETKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d)") +} + +# ============================================================================= +# E2E ONLY - Variables specific to zenko_tests (mocha) +# ============================================================================= +load_e2e() { + load_common + + # From end2end.yaml + ENV_VARS+=("AWS_BACKEND_SOURCE_LOCATION=$(get_env_var AWS_BACKEND_SOURCE_LOCATION)") + ENV_VARS+=("AWS_BACKEND_DESTINATION_LOCATION=$(get_env_var AWS_BACKEND_DESTINATION_LOCATION)") + ENV_VARS+=("AWS_BACKEND_DESTINATION_FAIL_LOCATION=$(get_env_var AWS_BACKEND_DESTINATION_FAIL_LOCATION)") + ENV_VARS+=("GCP_BACKEND_DESTINATION_LOCATION=$(get_env_var GCP_BACKEND_DESTINATION_LOCATION)") + ENV_VARS+=("AZURE_BACKEND_DESTINATION_LOCATION=$(get_env_var AZURE_BACKEND_DESTINATION_LOCATION)") + ENV_VARS+=("COLD_BACKEND_DESTINATION_LOCATION=$(get_env_var COLD_BACKEND_DESTINATION_LOCATION)") + ENV_VARS+=("AZURE_ARCHIVE_BACKEND_DESTINATION_LOCATION=$(get_env_var AZURE_ARCHIVE_BACKEND_DESTINATION_LOCATION)") + ENV_VARS+=("MIRIA_BACKEND_DESTINATION_LOCATION=$(get_env_var MIRIA_BACKEND_DESTINATION_LOCATION)") + ENV_VARS+=("LOCATION_QUOTA_BACKEND=$(get_env_var LOCATION_QUOTA_BACKEND)") + ENV_VARS+=("AWS_BUCKET_NAME=$(get_env_var AWS_BUCKET_NAME)") + ENV_VARS+=("AWS_CRR_BUCKET_NAME=$(get_env_var AWS_CRR_BUCKET_NAME)") + ENV_VARS+=("AWS_FAIL_BUCKET_NAME=$(get_env_var AWS_FAIL_BUCKET_NAME)") + ENV_VARS+=("AZURE_CRR_BUCKET_NAME=$(get_env_var AZURE_CRR_BUCKET_NAME)") + ENV_VARS+=("AZURE_ARCHIVE_BUCKET_NAME=$(get_env_var AZURE_ARCHIVE_BUCKET_NAME)") + ENV_VARS+=("GCP_CRR_BUCKET_NAME=$(get_env_var GCP_CRR_BUCKET_NAME)") + ENV_VARS+=("GCP_CRR_MPU_BUCKET_NAME=$(get_env_var GCP_CRR_MPU_BUCKET_NAME)") + ENV_VARS+=("GCP_ACCESS_KEY=$(get_env_var GCP_ACCESS_KEY)") + ENV_VARS+=("GCP_SECRET_KEY=$(get_env_var GCP_SECRET_KEY)") + ENV_VARS+=("GCP_BACKEND_SERVICE_KEY=$(get_env_var GCP_BACKEND_SERVICE_KEY)") + ENV_VARS+=("GCP_BACKEND_SERVICE_EMAIL=$(get_env_var GCP_BACKEND_SERVICE_EMAIL)") + ENV_VARS+=("AZURE_BACKEND_ENDPOINT=$(get_env_var AZURE_BACKEND_ENDPOINT)") + ENV_VARS+=("AWS_ENDPOINT=$(get_env_var AWS_ENDPOINT)") + ENV_VARS+=("AWS_ACCESS_KEY=$(get_env_var AWS_ACCESS_KEY)") + ENV_VARS+=("AWS_SECRET_KEY=$(get_env_var AWS_SECRET_KEY)") + ENV_VARS+=("VERIFY_CERTIFICATES=$(get_env_var VERIFY_CERTIFICATES)") + ENV_VARS+=("ENABLE_RING_TESTS=$(get_env_var ENABLE_RING_TESTS)") + ENV_VARS+=("RING_S3C_ACCESS_KEY=$(get_env_var RING_S3C_ACCESS_KEY)") + ENV_VARS+=("RING_S3C_SECRET_KEY=$(get_env_var RING_S3C_SECRET_KEY)") + ENV_VARS+=("RING_S3C_ENDPOINT=$(get_env_var RING_S3C_ENDPOINT)") + ENV_VARS+=("RING_S3C_BACKEND_SOURCE_LOCATION=$(get_env_var RING_S3C_BACKEND_SOURCE_LOCATION)") + ENV_VARS+=("RING_S3C_INGESTION_SRC_BUCKET_NAME=$(get_env_var RING_S3C_INGESTION_SRC_BUCKET_NAME)") + ENV_VARS+=("RING_S3C_BACKEND_SOURCE_NON_VERSIONED_LOCATION=$(get_env_var RING_S3C_BACKEND_SOURCE_NON_VERSIONED_LOCATION)") + ENV_VARS+=("RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME=$(get_env_var RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME)") + ENV_VARS+=("RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE=$(get_env_var RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE)") + ENV_VARS+=("CRR_SOURCE_LOCATION_NAME=$(get_env_var CRR_SOURCE_LOCATION_NAME)") + ENV_VARS+=("CRR_DESTINATION_LOCATION_NAME=$(get_env_var CRR_DESTINATION_LOCATION_NAME)") + ENV_VARS+=("CRR_ROLE_NAME=$(get_env_var CRR_ROLE_NAME)") + ENV_VARS+=("BACKBEAT_BUCKET_CHECK_TIMEOUT_S=$(get_env_var BACKBEAT_BUCKET_CHECK_TIMEOUT_S)") + ENV_VARS+=("MOCHA_FILE=$(get_env_var MOCHA_FILE)") + + # Derived endpoints + ENV_VARS+=("CLOUDSERVER_HOST=end2end-connector-s3api.default.svc.cluster.local") + ENV_VARS+=("VAULT_STS_ENDPOINT=http://end2end-connector-vault-sts-api:80") + ENV_VARS+=("BACKBEAT_API_ENDPOINT=http://end2end-management-backbeat-api.default.svc.cluster.local:80") + + # From k8s: MongoDB config + local cloudserver_secret + cloudserver_secret=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end \ + -o jsonpath="{.items[0].data.config\.json}" | base64 -d) + ENV_VARS+=("MONGO_DATABASE=$(echo "${cloudserver_secret}" | jq -r '.mongodb.database')") + ENV_VARS+=("MONGO_READ_PREFERENCE=$(echo "${cloudserver_secret}" | jq -r '.mongodb.readPreference')") + ENV_VARS+=("MONGO_REPLICA_SET_HOSTS=$(echo "${cloudserver_secret}" | jq -r '.mongodb.replicaSetHosts')") + ENV_VARS+=("MONGO_SHARD_COLLECTION=$(echo "${cloudserver_secret}" | jq -r '.mongodb.shardCollections')") + ENV_VARS+=("MONGO_WRITE_CONCERN=$(echo "${cloudserver_secret}" | jq -r '.mongodb.writeConcern')") + ENV_VARS+=("MONGO_AUTH_USERNAME=$(echo "${cloudserver_secret}" | jq -r '.mongodb.authCredentials.username')") + ENV_VARS+=("MONGO_AUTH_PASSWORD=$(echo "${cloudserver_secret}" | jq -r '.mongodb.authCredentials.password')") + + # From k8s: CRR account credentials + local crr_src crr_dst + crr_src=$(get_env_var CRR_SOURCE_ACCOUNT_NAME) + crr_dst=$(get_env_var CRR_DESTINATION_ACCOUNT_NAME) + local src_ak src_sk src_st src_id dst_ak dst_sk dst_st dst_id + src_ak=$(kubectl get secret "end2end-account-${crr_src}" -o jsonpath='{.data.AccessKeyId}' | base64 -d) + src_sk=$(kubectl get secret "end2end-account-${crr_src}" -o jsonpath='{.data.SecretAccessKey}' | base64 -d) + src_st=$(kubectl get secret "end2end-account-${crr_src}" -o jsonpath='{.data.SessionToken}' | base64 -d) + src_id=$(kubectl get secret "end2end-account-${crr_src}" -o jsonpath='{.data.AccountId}' | base64 -d) + dst_ak=$(kubectl get secret "end2end-account-${crr_dst}" -o jsonpath='{.data.AccessKeyId}' | base64 -d) + dst_sk=$(kubectl get secret "end2end-account-${crr_dst}" -o jsonpath='{.data.SecretAccessKey}' | base64 -d) + dst_st=$(kubectl get secret "end2end-account-${crr_dst}" -o jsonpath='{.data.SessionToken}' | base64 -d) + dst_id=$(kubectl get secret "end2end-account-${crr_dst}" -o jsonpath='{.data.AccountId}' | base64 -d) + ENV_VARS+=("CRR_SOURCE_INFO={\"AccessKeyId\":\"${src_ak}\",\"SecretAccessKey\":\"${src_sk}\",\"SessionToken\":\"${src_st}\",\"AccountId\":\"${src_id}\"}") + ENV_VARS+=("CRR_DESTINATION_INFO={\"AccessKeyId\":\"${dst_ak}\",\"SecretAccessKey\":\"${dst_sk}\",\"SessionToken\":\"${dst_st}\",\"AccountId\":\"${dst_id}\"}") + + # From k8s: Zenko account session token + ENV_VARS+=("ZENKO_SESSION_TOKEN=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.SessionToken}' | base64 -d)") +} + +# ============================================================================= +# MAIN +# ============================================================================= +case "$SUITE" in + common) + load_common + ;; + ctst) + load_ctst + ;; + e2e) + load_e2e + ;; + *) + echo "Usage: source load-config.sh [common|ctst|e2e]" >&2 + exit 1 + ;; +esac diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index f69d9f59dc..e905435b32 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -7,6 +7,10 @@ set -exu # run-e2e-ctst.sh "@PreMerge and not @PRA" # run-e2e-ctst.sh "@PRA" +# Load environment configuration +DIR=$(dirname "$0") +source "$DIR/load-config.sh" ctst + TAGS=${1:?'Error: TAGS argument is required (e.g., "@PreMerge", "@PRA")'} ZENKO_NAME="end2end" PARALLEL_RUNS=${PARALLEL_RUNS:-$(( ( $(nproc) + 1 ) / 2 ))} @@ -172,6 +176,7 @@ kubectl run $POD_NAME \ --rm \ --attach=True \ --image-pull-policy=IfNotPresent \ + $(env_for_kubectl_run) \ --env=TARGET_VERSION=$VERSION \ --env=AZURE_BLOB_URL=$AZURE_BACKEND_ENDPOINT \ --env=AZURE_QUEUE_URL=$AZURE_BACKEND_QUEUE_ENDPOINT \ diff --git a/.github/scripts/end2end/run-e2e-test.sh b/.github/scripts/end2end/run-e2e-test.sh index e0f391f368..a99fb840a6 100755 --- a/.github/scripts/end2end/run-e2e-test.sh +++ b/.github/scripts/end2end/run-e2e-test.sh @@ -6,6 +6,9 @@ DIR=$(dirname $0) . "$DIR/common.sh" +# Load environment configuration +source "$DIR/load-config.sh" e2e + ZENKO_NAME=${1:-end2end} E2E_IMAGE=${2:-ghcr.io/scality/zenko/zenko-e2e:latest} STAGE=${3:-end2end} @@ -66,6 +69,7 @@ run_e2e_test() { --attach=True \ --namespace=${NAMESPACE} \ --image-pull-policy=Always \ + $(env_for_kubectl_run) \ --env=CLOUDSERVER_HOST=${CLOUDSERVER_HOST} \ --env=CLOUDSERVER_ENDPOINT=${CLOUDSERVER_ENDPOINT} \ --env=ZENKO_ACCESS_KEY=${ZENKO_ACCESS_KEY} \ diff --git a/tests/config-loader/index.js b/tests/config-loader/index.js new file mode 100644 index 0000000000..f60b1c5bf9 --- /dev/null +++ b/tests/config-loader/index.js @@ -0,0 +1,71 @@ +const { readSecret } = require('./k8sClient'); +const yaml = require('js-yaml'); +const fs = require('fs'); +const path = require('path'); + +// Shared tests config - values needed by both ctst and zenko_tests +const sharedTestsConfig = { + AdminAccessKey: undefined, + AdminSecretKey: undefined, + Subdomain: undefined, +}; + +// Cucumber specific config +const ctstConfig = { + // DRAdminAccessKey: undefined, + // KafkaHosts: undefined, +}; + +// Zenko tests specific config +const zenkoTestsConfig = { + // MongoDatabase: undefined, +}; + +let _loaded = false; + +/** + * Load static config from end2end.yaml workflow file + */ +function loadYamlConfig() { + const configPath = path.join(__dirname, 'end2end.yaml'); + const fileContents = fs.readFileSync(configPath, 'utf8'); + const workflowConfig = yaml.load(fileContents); + return workflowConfig.env || {}; +} + +/** + * Load all configuration from k8s secrets and config files. + * Called once at startup (e.g., in BeforeAll hook). + */ +async function load(zenkoName = 'end2end', namespace = 'default') { + if (_loaded) { + return; + } + + const envConfig = loadYamlConfig(); + sharedTestsConfig.Subdomain = envConfig.SUBDOMAIN; + + const adminCreds = await readSecret( + `${zenkoName}-management-vault-admin-creds.v1`, + namespace + ); + + sharedTestsConfig.AdminAccessKey = adminCreds.accessKey; + sharedTestsConfig.AdminSecretKey = adminCreds.secretKey; + + // TODO: Load CTST-specific secrets + // const drCreds = await k8sClient.readSecret(...); + // ctstConfig.DRAdminAccessKey = drCreds.accessKey; + + // TODO: Load zenko_tests-specific secrets + // zenkoTestsConfig.MongoDatabase = ...; + + _loaded = true; +} + +module.exports = { + load, + sharedTestsConfig: sharedTestsConfig, + ctstConfig: ctstConfig, + zenkoTestsConfig: zenkoTestsConfig, +}; diff --git a/tests/config-loader/k8sClient.js b/tests/config-loader/k8sClient.js new file mode 100644 index 0000000000..f22b7ff747 --- /dev/null +++ b/tests/config-loader/k8sClient.js @@ -0,0 +1,22 @@ +const k8s = require('@kubernetes/client-node'); + +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); + +const coreApi = kc.makeApiClient(k8s.CoreV1Api); + +async function readSecret(secretName, namespace = 'default') { + const response = await coreApi.readNamespacedSecret(secretName, namespace); + const decoded = {}; + const secretData = response.body?.data || response.data; + if (secretData) { + for (const [key, value] of Object.entries(secretData)) { + decoded[key] = Buffer.from(value, 'base64').toString('utf-8'); + } + } + return decoded; +} + +module.exports = { + readSecret, +}; diff --git a/tests/config-loader/package.json b/tests/config-loader/package.json new file mode 100644 index 0000000000..3aff25ede1 --- /dev/null +++ b/tests/config-loader/package.json @@ -0,0 +1,11 @@ +{ + "name": "zenko-config-loader", + "version": "1.0.0", + "description": "K8s configuration loader for Zenko tests", + "main": "index.js", + "private": true, + "dependencies": { + "@kubernetes/client-node": "^0.21.0", + "js-yaml": "^4.1.1" + } +} diff --git a/tests/config-loader/yarn.lock b/tests/config-loader/yarn.lock new file mode 100644 index 0000000000..bde39060a1 --- /dev/null +++ b/tests/config-loader/yarn.lock @@ -0,0 +1,639 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + +"@kubernetes/client-node@^0.21.0": + version "0.21.0" + resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-0.21.0.tgz#c807af50e5d4ecbbaa571087636d79cd71a7d9cc" + integrity sha512-yYRbgMeyQbvZDHt/ZqsW3m4lRefzhbbJEuj8sVXM+bufKrgmzriA2oq7lWPH/k/LQIicAME9ixPUadTrxIF6dQ== + dependencies: + "@types/js-yaml" "^4.0.1" + "@types/node" "^20.1.1" + "@types/request" "^2.47.1" + "@types/ws" "^8.5.3" + byline "^5.0.0" + isomorphic-ws "^5.0.0" + js-yaml "^4.1.0" + jsonpath-plus "^8.0.0" + request "^2.88.0" + rfc4648 "^1.3.0" + stream-buffers "^3.0.2" + tar "^7.0.0" + tslib "^2.4.1" + ws "^8.11.0" + optionalDependencies: + openid-client "^5.3.0" + +"@types/caseless@*": + version "0.12.5" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.5.tgz#db9468cb1b1b5a925b8f34822f1669df0c5472f5" + integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg== + +"@types/js-yaml@^4.0.1": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2" + integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg== + +"@types/node@*": + version "25.2.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.2.3.tgz#9c18245be768bdb4ce631566c7da303a5c99a7f8" + integrity sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ== + dependencies: + undici-types "~7.16.0" + +"@types/node@^20.1.1": + version "20.19.33" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.33.tgz#ac8364c623b72d43125f0e7dd722bbe968f0c65e" + integrity sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw== + dependencies: + undici-types "~6.21.0" + +"@types/request@^2.47.1": + version "2.48.13" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.13.tgz#abdf4256524e801ea8fdda54320f083edb5a6b80" + integrity sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.5" + +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + +"@types/ws@^8.5.3": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== + dependencies: + "@types/node" "*" + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" + integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q== + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@^2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.5.tgz#a5f6364ad7e4e67e95b4a07e2d8c6f711c74f624" + integrity sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.35" + safe-buffer "^5.2.1" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +jose@^4.15.9: + version "4.15.9" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" + integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== + +js-yaml@^4.1.0, js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +jsonpath-plus@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-8.1.0.tgz#68c92281215672d1d6c785b3c1bdc8acc097ba3f" + integrity sha512-qVTiuKztFGw0dGhYi3WNqvddx3/SHtyDT0xJaeyz4uP0d1tkpG+0y5uYQ4OcIo1TLAz3PE/qDOW9F0uDt3+CTw== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.35, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minipass@^7.0.4, minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.1.0.tgz#6ad76c3a8f10227c9b51d1c9ac8e30b27f5a251c" + integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== + dependencies: + minipass "^7.1.2" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-hash@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + +oidc-token-hash@^5.0.3: + version "5.2.0" + resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz#be8a8885c7e2478d21a674e15afa31f1bcc4a61f" + integrity sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw== + +openid-client@^5.3.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-5.7.1.tgz#34cace862a3e6472ed7d0a8616ef73b7fb85a9c3" + integrity sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew== + dependencies: + jose "^4.15.9" + lru-cache "^6.0.0" + object-hash "^2.2.0" + oidc-token-hash "^5.0.3" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +psl@^1.1.28: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@~6.5.2: + version "6.5.4" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.4.tgz#8796b01abc51ebc3e8c9fa870dc1705ee990533b" + integrity sha512-0BeLMIVqP5aQ+8izCO5KjIAuwHx4FwA4MtZzA+Q6TqS4Bu+E/TzHArugK5XqzaFmoBugtLH5S/w7pGPxnJfhtQ== + +request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +rfc4648@^1.3.0: + version "1.5.4" + resolved "https://registry.yarnpkg.com/rfc4648/-/rfc4648-1.5.4.tgz#1174c0afba72423a0b70c386ecfeb80aa61b05ca" + integrity sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg== + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stream-buffers@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-3.0.3.tgz#9fc6ae267d9c4df1190a781e011634cac58af3cd" + integrity sha512-pqMqwQCso0PBJt2PQmDO0cFj0lyqmiwOMiMSkVtRokl7e+ZTRYgDHKnuZNbqjiJXgsg4nuqtD/zxuo9KqTp0Yw== + +tar@^7.0.0: + version "7.5.7" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.7.tgz#adf99774008ba1c89819f15dbd6019c630539405" + integrity sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.1.0" + yallist "^5.0.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tslib@^2.4.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +ws@^8.11.0: + version "8.19.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.19.0.tgz#ddc2bdfa5b9ad860204f5a72a4863a8895fd8c8b" + integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== diff --git a/tests/ctst/features/crrReplicationS3utils.feature b/tests/ctst/features/crrReplicationS3utils.feature index e9d1644068..8580ecb32d 100644 --- a/tests/ctst/features/crrReplicationS3utils.feature +++ b/tests/ctst/features/crrReplicationS3utils.feature @@ -13,6 +13,7 @@ Feature: Replication @2.12.0 @PreMerge + @yoyo @ReplicationTest Scenario Outline: Replicate objects created before creating the replication rule Given an existing bucket "source-bucket-1" "with" versioning, "without" ObjectLock "without" retention mode @@ -35,4 +36,4 @@ Feature: Replication When the destination bucket on the location is created again And the job to replicate existing objects with status "FAILED" is executed Then the object replication should "succeed" within 300 seconds - And the replicated object should be the same as the source object \ No newline at end of file + And the replicated object should be the same as the source object diff --git a/tests/ctst/run-ctst-locally.sh b/tests/ctst/run-ctst-locally.sh index c3b86264b8..105463bc12 100755 --- a/tests/ctst/run-ctst-locally.sh +++ b/tests/ctst/run-ctst-locally.sh @@ -10,21 +10,14 @@ set -exu CUCUMBER_TAGS="$1" IMAGE_NAME="${2:-ghcr.io/scality/zenko/zenko-e2e-ctst:ctst_codespace_setup}" +# Load unified test configuration +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/../../.github/scripts/end2end/load-config.sh" ctst + # Version is used with a Before Hook (in ctst/common/hooks.ts) to skip # certain tests based on their @version tag. VERSION=$(cat ../../VERSION | grep -Po 'VERSION="\K[^"]*') POD_NAME="ctst-end2end" -WORLD_PARAMETERS="$(jq -c < { */ constructor(options: IWorldOptions) { super(options); + Logger.createLogger(this); // store service users credentials from world parameters if (this.parameters.ServiceUsersCredentials) { @@ -174,7 +175,7 @@ export default class Zenko extends World { Identity.addIdentity(IdentityEnum.ADMIN, Zenko.PRIMARY_SITE_NAME, { accessKeyId: this.parameters.AdminAccessKey, secretAccessKey: this.parameters.AdminSecretKey, - }, undefined, undefined, undefined, this.parameters.subdomain); + }, undefined, undefined, undefined, this.parameters.Subdomain); Zenko.sites['source'] = { accountName: Identity.defaultAccountName, @@ -901,7 +902,7 @@ export default class Zenko extends World { const protocol = this.parameters.ssl === false ? 'http://' : 'https://'; const axiosConfig: AxiosRequestConfig = { method, - url: `${protocol}s3.${this.parameters.subdomain + url: `${protocol}s3.${this.parameters.Subdomain || Constants.DEFAULT_SUBDOMAIN}${path}`, headers, data: payload, @@ -956,7 +957,7 @@ export default class Zenko extends World { }; const axiosConfig: AxiosRequestConfig = { method, - url: `${protocol}management.${this.parameters.subdomain || Constants.DEFAULT_SUBDOMAIN}/api/v1${path}`, + url: `${protocol}management.${this.parameters.Subdomain || Constants.DEFAULT_SUBDOMAIN}/api/v1${path}`, headers, data: payload, }; diff --git a/tests/ctst/yarn.lock b/tests/ctst/yarn.lock index 40a3ee3251..9aa758d86d 100644 --- a/tests/ctst/yarn.lock +++ b/tests/ctst/yarn.lock @@ -4398,6 +4398,13 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -5903,3 +5910,9 @@ yup@1.2.0: tiny-case "^1.0.3" toposort "^2.0.2" type-fest "^2.19.0" + +"zenko-config-loader@file:../config-loader": + version "1.0.0" + dependencies: + "@kubernetes/client-node" "^0.21.0" + js-yaml "^4.1.1" diff --git a/tests/zenko_tests/node_tests/run-node-tests-locally.sh b/tests/zenko_tests/node_tests/run-node-tests-locally.sh index b21a25718a..036761ba73 100755 --- a/tests/zenko_tests/node_tests/run-node-tests-locally.sh +++ b/tests/zenko_tests/node_tests/run-node-tests-locally.sh @@ -14,10 +14,10 @@ # If you need to use a different image, delete pod first: # kubectl delete pod node-tests-local -set -e +set -ex ZENKO_NAME=${ZENKO_NAME:-end2end} -IMAGE_NAME="${3:-ghcr.io/scality/zenko/zenko-e2e:latest}" +IMAGE_NAME="${3:-ghcr.io/scality/zenko/zenko-e2e-ctst:ctst_codespace_setup}" POD_NAME="node-tests-local" TEST_GREP="${1:-should list objects in V2 format}" From 1ab3414311eefaa836a8e75c2173bd9e73f78c67 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 19 Feb 2026 23:25:25 +0000 Subject: [PATCH 4/9] replace world parameters with env variables Issue: ZENKO-5182 --- .github/scripts/end2end/common.sh | 2 +- .github/scripts/end2end/keycloak-helper.sh | 2 +- .github/scripts/end2end/load-config.sh | 34 ++++---- .github/scripts/end2end/run-e2e-ctst.sh | 51 +++++------- .github/scripts/end2end/run-e2e-test.sh | 3 +- .github/workflows/end2end.yaml | 2 +- tests/ctst/common/common.ts | 6 +- tests/ctst/common/hooks.ts | 4 +- tests/ctst/steps/cloudserverAuth.ts | 2 +- tests/ctst/steps/iam-policies/common.ts | 4 +- tests/ctst/steps/replication.ts | 2 +- tests/ctst/steps/utils/utils.ts | 2 +- tests/ctst/steps/website/website.ts | 2 +- tests/ctst/world/Zenko.ts | 78 ++++++++++--------- .../node_tests/utils/getWebIdentityToken.js | 3 +- 15 files changed, 100 insertions(+), 97 deletions(-) diff --git a/.github/scripts/end2end/common.sh b/.github/scripts/end2end/common.sh index eb490d7026..32f9e7c77f 100644 --- a/.github/scripts/end2end/common.sh +++ b/.github/scripts/end2end/common.sh @@ -2,7 +2,7 @@ get_token() { curl -k -H "Host: keycloak.zenko.local" \ -d "client_id=${OIDC_CLIENT_ID}" \ -d "username=${OIDC_USERNAME}" \ - -d "password=${OIDC_PASSWORD}" \ + -d "password=${KEYCLOAK_TEST_PASSWORD}" \ -d "grant_type=password" \ -d "scope=openid" \ https://localhost/auth/realms/${OIDC_REALM}/protocol/openid-connect/token | \ diff --git a/.github/scripts/end2end/keycloak-helper.sh b/.github/scripts/end2end/keycloak-helper.sh index ec0cde2f9f..e41fff3af3 100755 --- a/.github/scripts/end2end/keycloak-helper.sh +++ b/.github/scripts/end2end/keycloak-helper.sh @@ -39,7 +39,7 @@ case $COMMAND in ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh set-password \ -r ${OIDC_REALM} \ --username ${OIDC_USERNAME} \ - --new-password ${OIDC_PASSWORD} + --new-password ${KEYCLOAK_TEST_PASSWORD} # attach StorageManager role to user ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh add-roles \ diff --git a/.github/scripts/end2end/load-config.sh b/.github/scripts/end2end/load-config.sh index 130aa9309f..a50368e5e4 100755 --- a/.github/scripts/end2end/load-config.sh +++ b/.github/scripts/end2end/load-config.sh @@ -37,18 +37,16 @@ load_common() { ENV_VARS=() # From end2end.yaml - ENV_VARS+=("SUBDOMAIN=$(get_env_var SUBDOMAIN)") ENV_VARS+=("KEYCLOAK_TEST_REALM_NAME=$(get_env_var OIDC_REALM)") ENV_VARS+=("KEYCLOAK_TEST_CLIENT_ID=$(get_env_var OIDC_CLIENT_ID)") ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var OIDC_USERNAME)") - ENV_VARS+=("KEYCLOAK_TEST_PASSWORD=$(get_env_var OIDC_PASSWORD)") + ENV_VARS+=("KEYCLOAK_TEST_PASSWORD=$(get_env_var KEYCLOAK_TEST_PASSWORD)") ENV_VARS+=("KEYCLOAK_TEST_HOST=$(get_env_var OIDC_HOST)") ENV_VARS+=("KEYCLOAK_TEST_PORT=80") ENV_VARS+=("KEYCLOAK_TEST_GRANT_TYPE=password") ENV_VARS+=("AZURE_ACCOUNT_NAME=$(get_env_var AZURE_ACCOUNT_NAME)") ENV_VARS+=("AZURE_SECRET_KEY=$(get_env_var AZURE_SECRET_KEY)") - ENV_VARS+=("CLOUDSERVER_ENDPOINT=http://end2end-connector-s3api.default.svc.cluster.local:80") - ENV_VARS+=("VAULT_ENDPOINT=http://end2end-management-vault-iam-admin-api:80") + ENV_VARS+=("AZURE_BACKEND_ENDPOINT=$(get_env_var AZURE_BACKEND_ENDPOINT)") # From k8s: Zenko account credentials ENV_VARS+=("ZENKO_ACCESS_KEY=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.AccessKeyId}' | base64 -d)") @@ -65,7 +63,11 @@ load_common() { load_ctst() { load_common + # From end2end.yaml + ENV_VARS+=("SUBDOMAIN=$(get_env_var SUBDOMAIN)") + # Hardcoded CTST values + ENV_VARS+=("SSL=false") ENV_VARS+=("ZENKO_ACCOUNT_NAME=zenko-ctst") ENV_VARS+=("STORAGE_MANAGER_USER_NAME=ctst_storage_manager") ENV_VARS+=("STORAGE_ACCOUNT_OWNER_USER_NAME=ctst_storage_account_owner") @@ -79,7 +81,6 @@ load_ctst() { # From end2end.yaml ENV_VARS+=("DR_SUBDOMAIN=$(get_env_var DR_SUBDOMAIN)") ENV_VARS+=("PROMETHEUS_NAME=$(get_env_var PROMETHEUS_NAME)") - ENV_VARS+=("AZURE_BACKEND_ENDPOINT=$(get_env_var AZURE_BACKEND_ENDPOINT)") ENV_VARS+=("AZURE_BACKEND_QUEUE_ENDPOINT=$(get_env_var AZURE_BACKEND_QUEUE_ENDPOINT)") ENV_VARS+=("AZURE_ARCHIVE_BUCKET_NAME=$(get_env_var AZURE_ARCHIVE_BUCKET_NAME)") ENV_VARS+=("AZURE_ARCHIVE_BUCKET_NAME_2=$(get_env_var AZURE_ARCHIVE_BUCKET_NAME_2)") @@ -127,13 +128,19 @@ load_ctst() { ENV_VARS+=("BACKBEAT_API_HOST=$(echo "${cloudserver_config}" | jq -r '.backbeat.host')") ENV_VARS+=("BACKBEAT_API_PORT=$(echo "${cloudserver_config}" | jq -r '.backbeat.port')") - # From k8s: Service users credentials (individual components) - ENV_VARS+=("BACKBEAT_LCBP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d)") - ENV_VARS+=("BACKBEAT_LCC_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-conductor-1\.json}' | base64 -d)") - ENV_VARS+=("BACKBEAT_LCOP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-op-1\.json}' | base64 -d)") - ENV_VARS+=("BACKBEAT_QP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d)") - ENV_VARS+=("SORBET_FWD_2_ACCESSKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d)") - ENV_VARS+=("SORBET_FWD_2_SECRETKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d)") + # From k8s: Service users credentials + local lcbp_creds lcc_creds lcop_creds qp_creds sorbet_ak sorbet_sk + lcbp_creds=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d) + lcc_creds=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-conductor-1\.json}' | base64 -d) + lcop_creds=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-op-1\.json}' | base64 -d) + qp_creds=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d) + sorbet_ak=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d) + sorbet_sk=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d) + + # Build SERVICE_USERS_CREDENTIALS JSON (same format as run-e2e-ctst.sh) + local service_users_creds + service_users_creds=$(echo '{"backbeat-lifecycle-bp-1":'"${lcbp_creds}"',"backbeat-lifecycle-conductor-1":'"${lcc_creds}"',"backbeat-lifecycle-op-1":'"${lcop_creds}"',"backbeat-qp-1":'"${qp_creds}"',"sorbet-fwd-2":{"accessKey":"'"${sorbet_ak}"'","secretKey":"'"${sorbet_sk}"'"}}') + ENV_VARS+=("SERVICE_USERS_CREDENTIALS=${service_users_creds}") } # ============================================================================= @@ -163,7 +170,6 @@ load_e2e() { ENV_VARS+=("GCP_SECRET_KEY=$(get_env_var GCP_SECRET_KEY)") ENV_VARS+=("GCP_BACKEND_SERVICE_KEY=$(get_env_var GCP_BACKEND_SERVICE_KEY)") ENV_VARS+=("GCP_BACKEND_SERVICE_EMAIL=$(get_env_var GCP_BACKEND_SERVICE_EMAIL)") - ENV_VARS+=("AZURE_BACKEND_ENDPOINT=$(get_env_var AZURE_BACKEND_ENDPOINT)") ENV_VARS+=("AWS_ENDPOINT=$(get_env_var AWS_ENDPOINT)") ENV_VARS+=("AWS_ACCESS_KEY=$(get_env_var AWS_ACCESS_KEY)") ENV_VARS+=("AWS_SECRET_KEY=$(get_env_var AWS_SECRET_KEY)") @@ -185,6 +191,8 @@ load_e2e() { # Derived endpoints ENV_VARS+=("CLOUDSERVER_HOST=end2end-connector-s3api.default.svc.cluster.local") + ENV_VARS+=("CLOUDSERVER_ENDPOINT=http://end2end-connector-s3api.default.svc.cluster.local:80") + ENV_VARS+=("VAULT_ENDPOINT=http://end2end-management-vault-iam-admin-api:80") ENV_VARS+=("VAULT_STS_ENDPOINT=http://end2end-connector-vault-sts-api:80") ENV_VARS+=("BACKBEAT_API_ENDPOINT=http://end2end-management-backbeat-api.default.svc.cluster.local:80") diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index e905435b32..599d9f5268 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -20,18 +20,20 @@ VERSION=$(cat ../../../VERSION | grep -Po 'VERSION="\K[^"]*') # Zenko Environment ZENKO_ACCOUNT_NAME="zenko-ctst" -ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) -ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) +# ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) +# ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) ADMIN_PRA_ACCESS_KEY_ID=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) ADMIN_PRA_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) -STORAGE_MANAGER_USER_NAME="ctst_storage_manager" -STORAGE_ACCOUNT_OWNER_USER_NAME="ctst_storage_account_owner" -DATA_CONSUMER_USER_NAME="ctst_data_consumer" -DATA_ACCESSOR_USER_NAME="ctst_data_accessor" + +# STORAGE_MANAGER_USER_NAME="ctst_storage_manager" +# STORAGE_ACCOUNT_OWNER_USER_NAME="ctst_storage_account_owner" +# DATA_CONSUMER_USER_NAME="ctst_data_consumer" +# DATA_ACCESSOR_USER_NAME="ctst_data_accessor" + VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.local" -ZENKO_PORT="80" +# ZENKO_PORT="80" KEYCLOAK_TEST_USER=${OIDC_USERNAME} -KEYCLOAK_TEST_PASSWORD=${OIDC_PASSWORD} +# KEYCLOAK_TEST_PASSWORD=${OIDC_PASSWORD} KEYCLOAK_TEST_HOST=${OIDC_HOST} KEYCLOAK_TEST_PORT="80" KEYCLOAK_TEST_REALM_NAME=${OIDC_REALM} @@ -45,7 +47,7 @@ BACKBEAT_LCOP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lc BACKBEAT_QP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d) SORBET_FWD_2_ACCESSKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d) SORBET_FWD_2_SECRETKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d) -SERVICE_USERS_CREDENTIALS=$(echo '{"backbeat-lifecycle-bp-1":'${BACKBEAT_LCBP_1_CREDS}',"backbeat-lifecycle-conductor-1":'${BACKBEAT_LCC_1_CREDS}',"backbeat-lifecycle-op-1":'${BACKBEAT_LCOP_1_CREDS}',"backbeat-qp-1":'${BACKBEAT_QP_1_CREDS}',"sorbet-fwd-2":{"accessKey":"'${SORBET_FWD_2_ACCESSKEY}'","secretKey":"'${SORBET_FWD_2_SECRETKEY}'"}}' | jq -R) +# SERVICE_USERS_CREDENTIALS=$(echo '{"backbeat-lifecycle-bp-1":'${BACKBEAT_LCBP_1_CREDS}',"backbeat-lifecycle-conductor-1":'${BACKBEAT_LCC_1_CREDS}',"backbeat-lifecycle-op-1":'${BACKBEAT_LCOP_1_CREDS}',"backbeat-qp-1":'${BACKBEAT_QP_1_CREDS}',"sorbet-fwd-2":{"accessKey":"'${SORBET_FWD_2_ACCESSKEY}'","secretKey":"'${SORBET_FWD_2_SECRETKEY}'"}}' | jq -R) # Get KAFKA topics for sorbet KAFKA_DEAD_LETTER_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ @@ -57,8 +59,8 @@ KAFKA_OBJECT_TASK_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorb KAFKA_GC_REQUEST_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-gc-request-topic"' | cut -d "\"" -f 2) -DR_ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) -DR_ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) +# DR_ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) +# DR_ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) # Extracting kafka host from bacbeat's config KAFKA_HOST_PORT=$(kubectl get secret -l app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end \ @@ -90,13 +92,6 @@ UTILIZATION_SERVICE_PORT="80" # Setting CTST world params WORLD_PARAMETERS="$(jq -c <('accountName') || - world.parameters.AccountName); + process.env.ZENKO_ACCOUNT_NAME); world.resetCommand(); world.addCommandParameter({ bucket: bucketName }); const createdObjects = world.getCreatedObjects(); @@ -125,14 +125,14 @@ async function createBucket(world: Zenko, versioning: string, bucketName: string Given('a {string} bucket with dot', async function (this: Zenko, versioning: string) { const preName = this.getSaved('accountName') || - this.parameters.AccountName || Constants.ACCOUNT_NAME; + process.env.ZENKO_ACCOUNT_NAME || Constants.ACCOUNT_NAME; await createBucket(this, versioning, `${preName}.${Constants.BUCKET_NAME_TEST}${Utils.randomString()}`.toLocaleLowerCase()); }); Given('a {string} bucket', async function (this: Zenko, versioning: string) { const preName = this.getSaved('accountName') || - this.parameters.AccountName || Constants.ACCOUNT_NAME; + process.env.ZENKO_ACCOUNT_NAME || Constants.ACCOUNT_NAME; await createBucket(this, versioning, `${preName}${Constants.BUCKET_NAME_TEST}${Utils.randomString()}`.toLocaleLowerCase()); }); diff --git a/tests/ctst/common/hooks.ts b/tests/ctst/common/hooks.ts index acf621a8a1..feab9f709b 100644 --- a/tests/ctst/common/hooks.ts +++ b/tests/ctst/common/hooks.ts @@ -62,8 +62,8 @@ Before({ tags: '@UtilizationAPI', timeout: 1200000 }, async function (scenarioOp After(async function (this: Zenko, results) { // Reset any configuration set on the endpoint (ssl, port) - CacheHelper.parameters.ssl = this.parameters.ssl; - CacheHelper.parameters.port = this.parameters.port; + CacheHelper.parameters.ssl = process.env.SSL === 'true'; + CacheHelper.parameters.port = process.env.ZENKO_PORT; if (results.result?.status === 'FAILED') { this.logger.warn('bucket was not cleaned for test', { bucket: this.getSaved('bucketName'), diff --git a/tests/ctst/steps/cloudserverAuth.ts b/tests/ctst/steps/cloudserverAuth.ts index a75a104be4..c658fcb989 100644 --- a/tests/ctst/steps/cloudserverAuth.ts +++ b/tests/ctst/steps/cloudserverAuth.ts @@ -36,7 +36,7 @@ When('the user tries to perform CreateBucket', async function (this: Zenko) { this.resetCommand(); this.useSavedIdentity(); const preName = this.getSaved('accountName') || - this.parameters.AccountName || Constants.ACCOUNT_NAME; + process.env.ZENKO_ACCOUNT_NAME || Constants.ACCOUNT_NAME; const usedBucketName = `${preName}${Constants.BUCKET_NAME_TEST}${Utils.randomString()}`.toLocaleLowerCase(); this.addToSaved('bucketName', usedBucketName); this.addCommandParameter({ bucket: usedBucketName }); diff --git a/tests/ctst/steps/iam-policies/common.ts b/tests/ctst/steps/iam-policies/common.ts index 24dc31cfb5..e8bcd0d034 100644 --- a/tests/ctst/steps/iam-policies/common.ts +++ b/tests/ctst/steps/iam-policies/common.ts @@ -29,13 +29,13 @@ When('the user tries to perform vault auth {string}', async function (this: Zenk SecretKey: userCredentials.secretAccessKey, SessionToken: userCredentials.sessionToken, ip: this.parameters.VaultAuthHost, - ssl: CacheHelper.parameters ? CacheHelper.parameters.ssl as boolean : undefined, + ssl: CacheHelper.parameters.ssl, }; switch (action) { case 'GetAccountInfo': this.setResult(await VaultAuth.getAccounts([ - this.getSaved('accountNameForScenario') || this.parameters.AccountName, + this.getSaved('accountNameForScenario') || process.env.ZENKO_ACCOUNT_NAME, ], null, null, { // @ts-expect-error accountNames is not generated by CTST yet accountNames: true, diff --git a/tests/ctst/steps/replication.ts b/tests/ctst/steps/replication.ts index 7e0311355a..56af088d3f 100644 --- a/tests/ctst/steps/replication.ts +++ b/tests/ctst/steps/replication.ts @@ -26,7 +26,7 @@ When('the job to replicate existing objects with status {string} is executed', const s3utilsVersion = zenkoVersion.spec.versions.s3utils; const credentials = Identity.getCredentialsForIdentity( IdentityEnum.ACCOUNT, - this.parameters.AccountName + process.env.ZENKO_ACCOUNT_NAME ); const podManifest = { apiVersion: 'v1', diff --git a/tests/ctst/steps/utils/utils.ts b/tests/ctst/steps/utils/utils.ts index ceef07ece0..053fbf8a89 100644 --- a/tests/ctst/steps/utils/utils.ts +++ b/tests/ctst/steps/utils/utils.ts @@ -170,7 +170,7 @@ async function createBucketWithConfiguration( retentionMode?: string) { world.resetCommand(); const preName = world.getSaved('accountName') || - world.parameters.AccountName || Constants.ACCOUNT_NAME; + process.env.ZENKO_ACCOUNT_NAME || Constants.ACCOUNT_NAME; const usedBucketName = bucketName || `${preName}${Constants.BUCKET_NAME_TEST}${Utils.randomString()}`.toLocaleLowerCase(); world.addToSaved('bucketName', usedBucketName); diff --git a/tests/ctst/steps/website/website.ts b/tests/ctst/steps/website/website.ts index 023ec014d2..9047b20f43 100644 --- a/tests/ctst/steps/website/website.ts +++ b/tests/ctst/steps/website/website.ts @@ -58,7 +58,7 @@ When('the user creates an S3 Bucket policy granting public read access', async f Then('the user should be able to load the index.html file from the {string} endpoint', async function (this: Zenko, endpoint: string) { - const baseUrl = this.parameters.ssl === false ? 'http://' : 'https://'; + const baseUrl = process.env.SSL === 'false' ? 'http://' : 'https://'; // The ingress may take some time to be ready (<60s) const uri = `${baseUrl}${this.getSaved('bucketName')}.${endpoint}`; let response; diff --git a/tests/ctst/world/Zenko.ts b/tests/ctst/world/Zenko.ts index 5e7decbb34..ad31e9806e 100644 --- a/tests/ctst/world/Zenko.ts +++ b/tests/ctst/world/Zenko.ts @@ -44,12 +44,12 @@ export enum EntityType { } export interface ZenkoWorldParameters extends ClientOptions { - AccountName: string; - AccountAccessKey: string; - AccountSecretKey: string; - DRAdminAccessKey?: string; - DRAdminSecretKey?: string; - DRSubdomain?: string; + // AccountName: string; + // AccountAccessKey: string; + // AccountSecretKey: string; + // DRAdminAccessKey?: string; + // DRAdminSecretKey?: string; + // DRSubdomain?: string; VaultAuthHost: string; NotificationDestination: string; NotificationDestinationTopic: string; @@ -70,12 +70,12 @@ export interface ZenkoWorldParameters extends ClientOptions { KeycloakRealm: string; KeycloakClientId: string; KeycloakGrantType: string; + // KeycloakTestPassword: string; StorageManagerUsername: string; StorageAccountOwnerUsername: string; DataConsumerUsername: string; DataAccessorUsername: string; ServiceUsersCredentials: string; - KeycloakTestPassword: string; AzureAccountName: string; AzureAccountKey: string; AzureArchiveContainer: string; @@ -137,45 +137,49 @@ export default class Zenko extends World { Logger.createLogger(this); // store service users credentials from world parameters - if (this.parameters.ServiceUsersCredentials) { + if (process.env.SERVICE_USERS_CREDENTIALS) { const serviceUserCredentials = - JSON.parse(this.parameters.ServiceUsersCredentials) as Record; + JSON.parse(process.env.SERVICE_USERS_CREDENTIALS) as Record; for (const serviceUserName in serviceUserCredentials) { - if (!Identity.hasIdentity(IdentityEnum.SERVICE_USER, serviceUserName, this.parameters.AccountName)) { + if (!Identity.hasIdentity(IdentityEnum.SERVICE_USER, serviceUserName, process.env.ZENKO_ACCOUNT_NAME)) { Identity.addIdentity(IdentityEnum.SERVICE_USER, serviceUserName, { accessKeyId: serviceUserCredentials[serviceUserName].accessKey, secretAccessKey: serviceUserCredentials[serviceUserName].secretKey, - }, this.parameters.AccountName); + }, process.env.ZENKO_ACCOUNT_NAME); } } } // Workaround to be able to access global parameters in BeforeAll/AfterAll hooks + // Only cache specific parameters needed by cli-testing that aren't available as env vars CacheHelper.cacheParameters({ - ...this.parameters, + ssl: process.env.SSL === 'true', + port: process.env.ZENKO_PORT, + subdomain: process.env.SUBDOMAIN, }); CacheHelper.savedAcrossTests[Zenko.PRA_INSTALL_COUNT_KEY] = 0; - if (this.parameters.AccountName && !Identity.hasIdentity(IdentityEnum.ACCOUNT, this.parameters.AccountName)) { - Identity.addIdentity(IdentityEnum.ACCOUNT, this.parameters.AccountName, { - accessKeyId: this.parameters.AccountAccessKey, - secretAccessKey: this.parameters.AccountSecretKey, + if (process.env.ZENKO_ACCOUNT_NAME && + !Identity.hasIdentity(IdentityEnum.ACCOUNT, process.env.ZENKO_ACCOUNT_NAME)) { + Identity.addIdentity(IdentityEnum.ACCOUNT, process.env.ZENKO_ACCOUNT_NAME, { + accessKeyId: process.env.ACCOUNT_ACCESS_KEY, + secretAccessKey: process.env.ACCOUNT_SECRET_KEY, }); } - if (this.parameters.AccountName) { - Identity.useIdentity(IdentityEnum.ACCOUNT, this.parameters.AccountName); - Identity.defaultAccountName = this.parameters.AccountName; + if (process.env.ZENKO_ACCOUNT_NAME) { + Identity.useIdentity(IdentityEnum.ACCOUNT, process.env.ZENKO_ACCOUNT_NAME); + Identity.defaultAccountName = process.env.ZENKO_ACCOUNT_NAME; } - if (this.parameters.AdminAccessKey && this.parameters.AdminSecretKey && + if (process.env.ADMIN_ACCESS_KEY_ID && process.env.ADMIN_SECRET_ACCESS_KEY && !Identity.hasIdentity(IdentityEnum.ADMIN, Zenko.PRIMARY_SITE_NAME)) { Identity.addIdentity(IdentityEnum.ADMIN, Zenko.PRIMARY_SITE_NAME, { - accessKeyId: this.parameters.AdminAccessKey, - secretAccessKey: this.parameters.AdminSecretKey, - }, undefined, undefined, undefined, this.parameters.Subdomain); + accessKeyId: process.env.ADMIN_ACCESS_KEY_ID, + secretAccessKey: process.env.ADMIN_SECRET_ACCESS_KEY, + }, undefined, undefined, undefined, process.env.SUBDOMAIN); Zenko.sites['source'] = { accountName: Identity.defaultAccountName, @@ -186,13 +190,13 @@ export default class Zenko extends World { if (this.needsSecondarySite()) { if (!Identity.hasIdentity(IdentityEnum.ADMIN, Zenko.SECONDARY_SITE_NAME)) { Identity.addIdentity(IdentityEnum.ADMIN, Zenko.SECONDARY_SITE_NAME, { - accessKeyId: this.parameters.DRAdminAccessKey!, - secretAccessKey: this.parameters.DRAdminSecretKey!, - }, undefined, undefined, undefined, this.parameters.DRSubdomain); + accessKeyId: process.env.DR_ADMIN_ACCESS_KEY_ID!, + secretAccessKey: process.env.DR_ADMIN_SECRET_ACCESS_KEY!, + }, undefined, undefined, undefined, process.env.DR_SUBDOMAIN); } Zenko.sites['sink'] = { - accountName: `dr${this.parameters.AccountName}`, + accountName: `dr${process.env.ZENKO_ACCOUNT_NAME}`, adminIdentityName: Zenko.SECONDARY_SITE_NAME, }; } @@ -203,7 +207,9 @@ export default class Zenko extends World { } private needsSecondarySite() { - return this.parameters.DRAdminAccessKey && this.parameters.DRAdminSecretKey && this.parameters.DRSubdomain; + return process.env.DR_ADMIN_ACCESS_KEY_ID && + process.env.DR_ADMIN_SECRET_ACCESS_KEY && + process.env.DR_SUBDOMAIN; } /** @@ -411,7 +417,7 @@ export default class Zenko extends World { clientId: string, grantType: string, ): Promise { - const baseUrl = this.parameters.ssl === false ? 'http://' : 'https://'; + const baseUrl = process.env.SSL === 'false' ? 'http://' : 'https://'; const data = qs.stringify({ username, password, @@ -713,10 +719,10 @@ export default class Zenko extends World { } } - const accountName = this.sites['source']?.accountName || CacheHelper.parameters.AccountName!; + const accountName = this.sites['source']?.accountName || process.env.ZENKO_ACCOUNT_NAME!; const accountAccessKeys = Identity.getCredentialsForIdentity( IdentityEnum.ACCOUNT, this.sites['source']?.accountName - || CacheHelper.parameters.AccountName!) || { + || process.env.ZENKO_ACCOUNT_NAME!) || { accessKeyId: '', secretAccessKey: '', }; @@ -899,10 +905,10 @@ export default class Zenko extends World { const axiosInstance = axios.create(); axiosInstance.interceptors.request.use(interceptor); - const protocol = this.parameters.ssl === false ? 'http://' : 'https://'; + const protocol = process.env.SSL === 'false' ? 'http://' : 'https://'; const axiosConfig: AxiosRequestConfig = { method, - url: `${protocol}s3.${this.parameters.Subdomain + url: `${protocol}s3.${process.env.SUBDOMAIN || Constants.DEFAULT_SUBDOMAIN}${path}`, headers, data: payload, @@ -941,7 +947,7 @@ export default class Zenko extends World { ): Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> { const token = await this.getWebIdentityToken( this.parameters.KeycloakUsername || 'storage_manager', - this.parameters.KeycloakPassword || '123', + process.env.KEYCLOAK_TEST_PASSWORD, this.parameters.KeycloakHost || 'keycloak.zenko.local', this.parameters.KeycloakPort || '80', `/auth/realms/${this.parameters.KeycloakRealm || 'zenko'}/protocol/openid-connect/token`, @@ -949,7 +955,7 @@ export default class Zenko extends World { this.parameters.KeycloakGrantType || 'password', ); const axiosInstance = axios.create(); - const protocol = this.parameters.ssl === false ? 'http://' : 'https://'; + const protocol = process.env.SSL === 'false' ? 'http://' : 'https://'; // eslint-disable-next-line no-param-reassign headers = { ...headers, @@ -957,7 +963,7 @@ export default class Zenko extends World { }; const axiosConfig: AxiosRequestConfig = { method, - url: `${protocol}management.${this.parameters.Subdomain || Constants.DEFAULT_SUBDOMAIN}/api/v1${path}`, + url: `${protocol}management.${process.env.SUBDOMAIN || Constants.DEFAULT_SUBDOMAIN}/api/v1${path}`, headers, data: payload, }; diff --git a/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js b/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js index 8a02914c44..7ae4f695f3 100644 --- a/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js +++ b/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js @@ -2,7 +2,6 @@ const querystring = require('querystring'); const http = require('http'); const assert = require('assert'); -const USER_1_PASSWORD = process.env.KEYCLOAK_TEST_PASSWORD || '123'; const HOST_1_URL = process.env.KEYCLOAK_TEST_HOST || 'http://keycloak.zenko.local'; const HOST_1_PORT = parseInt(process.env.KEYCLOAK_TEST_PORT, 10) || 80; const REALM_NAME = process.env.KEYCLOAK_TEST_REALM_NAME || 'zenko'; @@ -82,7 +81,7 @@ function getWebIdentityToken( function getTokenForIdentity(identity, callback) { getWebIdentityToken( identity, - USER_1_PASSWORD, + process.env.KEYCLOAK_TEST_PASSWORD, HOST_1_URL, HOST_1_PORT, KEYCLOAK_PATH, From cda202330f0477eed0e4eff041e0482b37c6f18c Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 23 Feb 2026 10:02:08 +0000 Subject: [PATCH 5/9] refactor keycload vars --- .github/scripts/end2end/common.sh | 6 +-- .../end2end/configs/keycloak_config.json | 14 +++--- .../end2end/configs/keycloak_user.json | 2 +- .github/scripts/end2end/configs/zenko.yaml | 6 +-- .github/scripts/end2end/enable-https.sh | 4 +- .github/scripts/end2end/keycloak-helper.sh | 14 +++--- .github/scripts/end2end/load-config.sh | 15 ++++--- .github/scripts/end2end/run-e2e-ctst.sh | 20 +++------ .github/scripts/end2end/run-e2e-test.sh | 22 +++++----- .github/workflows/end2end.yaml | 14 +++--- tests/ctst/world/Zenko.ts | 44 +++++++++---------- .../node_tests/utils/getWebIdentityToken.js | 11 ++--- 12 files changed, 82 insertions(+), 90 deletions(-) diff --git a/.github/scripts/end2end/common.sh b/.github/scripts/end2end/common.sh index 32f9e7c77f..5752f84835 100644 --- a/.github/scripts/end2end/common.sh +++ b/.github/scripts/end2end/common.sh @@ -1,11 +1,11 @@ get_token() { curl -k -H "Host: keycloak.zenko.local" \ - -d "client_id=${OIDC_CLIENT_ID}" \ - -d "username=${OIDC_USERNAME}" \ + -d "client_id=${KEYCLOAK_TEST_CLIENT_ID}" \ + -d "username=${KEYCLOAK_TEST_USER}" \ -d "password=${KEYCLOAK_TEST_PASSWORD}" \ -d "grant_type=password" \ -d "scope=openid" \ - https://localhost/auth/realms/${OIDC_REALM}/protocol/openid-connect/token | \ + https://localhost/auth/realms/${KEYCLOAK_TEST_REALM_NAME}/protocol/openid-connect/token | \ jq -cr '.id_token' } diff --git a/.github/scripts/end2end/configs/keycloak_config.json b/.github/scripts/end2end/configs/keycloak_config.json index 2966edcb7f..c6b1042268 100644 --- a/.github/scripts/end2end/configs/keycloak_config.json +++ b/.github/scripts/end2end/configs/keycloak_config.json @@ -1,5 +1,5 @@ { - "realm" : "${OIDC_REALM}", + "realm" : "${KEYCLOAK_TEST_REALM_NAME}", "enabled" : true, "defaultRoles" : [ "uma_authorization", "offline_access" ], "roles": { @@ -9,7 +9,7 @@ "name": "StorageManager", "composite": false, "clientRole": false, - "containerId": "${OIDC_REALM}", + "containerId": "${KEYCLOAK_TEST_REALM_NAME}", "attributes": {} }, { @@ -17,7 +17,7 @@ "name": "AccountTest::DataAccessor", "composite": false, "clientRole": false, - "containerId": "${OIDC_REALM}", + "containerId": "${KEYCLOAK_TEST_REALM_NAME}", "attributes": {} }, { @@ -25,7 +25,7 @@ "name": "AccountTest::DataConsumer", "composite": false, "clientRole": false, - "containerId": "${OIDC_REALM}", + "containerId": "${KEYCLOAK_TEST_REALM_NAME}", "attributes": {} }, { @@ -33,7 +33,7 @@ "name": "AccountTest::StorageAccountOwner", "composite": false, "clientRole": false, - "containerId": "${OIDC_REALM}", + "containerId": "${KEYCLOAK_TEST_REALM_NAME}", "attributes": {} } ] @@ -41,7 +41,7 @@ "requiredCredentials" : [ "password" ], "users" : [ { - "username": "${OIDC_USERNAME}-norights", + "username": "${KEYCLOAK_TEST_USER}-norights", "enabled": true, "totp": false, "emailVerified": false, @@ -193,7 +193,7 @@ } ], "clients" : [ { - "clientId" : "${OIDC_CLIENT_ID}", + "clientId" : "${KEYCLOAK_TEST_CLIENT_ID}", "rootUrl": "http://keycloack.zenko.local", "adminUrl": "/", "surrogateAuthRequired" : false, diff --git a/.github/scripts/end2end/configs/keycloak_user.json b/.github/scripts/end2end/configs/keycloak_user.json index 7dfe2e1126..6866c3a283 100644 --- a/.github/scripts/end2end/configs/keycloak_user.json +++ b/.github/scripts/end2end/configs/keycloak_user.json @@ -1,5 +1,5 @@ { - "username": "${OIDC_USERNAME}", + "username": "${KEYCLOAK_TEST_USER}", "enabled": true, "totp": false, "emailVerified": true, diff --git a/.github/scripts/end2end/configs/zenko.yaml b/.github/scripts/end2end/configs/zenko.yaml index e4a886bed4..808049a1b0 100644 --- a/.github/scripts/end2end/configs/zenko.yaml +++ b/.github/scripts/end2end/configs/zenko.yaml @@ -87,10 +87,10 @@ spec: management: provider: InCluster oidc: - provider: '${OIDC_ENDPOINT}/auth/realms/${OIDC_REALM}' + provider: '${KEYCLOAK_TEST_ENDPOINT}/auth/realms/${KEYCLOAK_TEST_REALM_NAME}' federatedProviders: - - '${OIDC_ENDPOINT}/auth/realms/${OIDC_REALM}' - vaultClientId: ${OIDC_CLIENT_ID} + - '${KEYCLOAK_TEST_ENDPOINT}/auth/realms/${KEYCLOAK_TEST_REALM_NAME}' + vaultClientId: ${KEYCLOAK_TEST_CLIENT_ID} api: ingress: hostname: ${ZENKO_MANAGEMENT_INGRESS} diff --git a/.github/scripts/end2end/enable-https.sh b/.github/scripts/end2end/enable-https.sh index a2dafc2488..3b91dab289 100755 --- a/.github/scripts/end2end/enable-https.sh +++ b/.github/scripts/end2end/enable-https.sh @@ -60,8 +60,8 @@ kubectl patch zenko/${ZENKO_NAME} --type=merge -p '{ kubectl wait --for condition=Available --timeout 5m zenko/${ZENKO_NAME} # Update environment variables to use HTTPS URLs -echo "OIDC_ENDPOINT=https://keycloak.zenko.local" >> $GITHUB_ENV -echo "OIDC_HOST=keycloak.zenko.local" >> $GITHUB_ENV +echo "KEYCLOAK_TEST_ENDPOINT=https://keycloak.zenko.local" >> $GITHUB_ENV +echo "KEYCLOAK_TEST_HOST=keycloak.zenko.local" >> $GITHUB_ENV echo "ENABLE_KEYCLOAK_HTTPS=true" >> $GITHUB_ENV # Set the HTTPS ingress options for Keycloak diff --git a/.github/scripts/end2end/keycloak-helper.sh b/.github/scripts/end2end/keycloak-helper.sh index e41fff3af3..8b0da1183e 100755 --- a/.github/scripts/end2end/keycloak-helper.sh +++ b/.github/scripts/end2end/keycloak-helper.sh @@ -34,17 +34,17 @@ case $COMMAND in export OIDC_EMAIL=${OIDC_EMAIL:-"e2e@zenko.local"} envsubst < $DIR/configs/keycloak_user.json | \ - ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh create users -r ${OIDC_REALM} -f - + ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh create users -r ${KEYCLOAK_TEST_REALM_NAME} -f - ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh set-password \ - -r ${OIDC_REALM} \ - --username ${OIDC_USERNAME} \ + -r ${KEYCLOAK_TEST_REALM_NAME} \ + --username ${KEYCLOAK_TEST_USER} \ --new-password ${KEYCLOAK_TEST_PASSWORD} # attach StorageManager role to user ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh add-roles \ - -r ${OIDC_REALM} \ - --uusername ${OIDC_USERNAME} \ + -r ${KEYCLOAK_TEST_REALM_NAME} \ + --uusername ${KEYCLOAK_TEST_USER} \ --rolename "StorageManager" ;; @@ -54,9 +54,9 @@ case $COMMAND in export INSTANCE_ID=`kubectl -n ${NAMESPACE} get zenko -o jsonpath='{.items[0].status.instanceID}'` # get user id - USER_ID=$(${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh get users -r ${OIDC_REALM} -q "username=${OIDC_USERNAME}" | jq -r '.[0].id') + USER_ID=$(${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh get users -r ${KEYCLOAK_TEST_REALM_NAME} -q "username=${KEYCLOAK_TEST_USER}" | jq -r '.[0].id') # set instanceIds array attribute for user - ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh update users/${USER_ID} -r ${OIDC_REALM} -s 'attributes={"instanceIds":["'"${INSTANCE_ID}"'"],"role":"user"}' + ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh update users/${USER_ID} -r ${KEYCLOAK_TEST_REALM_NAME} -s 'attributes={"instanceIds":["'"${INSTANCE_ID}"'"],"role":"user"}' ;; diff --git a/.github/scripts/end2end/load-config.sh b/.github/scripts/end2end/load-config.sh index a50368e5e4..e9ba422ff6 100755 --- a/.github/scripts/end2end/load-config.sh +++ b/.github/scripts/end2end/load-config.sh @@ -37,13 +37,16 @@ load_common() { ENV_VARS=() # From end2end.yaml - ENV_VARS+=("KEYCLOAK_TEST_REALM_NAME=$(get_env_var OIDC_REALM)") - ENV_VARS+=("KEYCLOAK_TEST_CLIENT_ID=$(get_env_var OIDC_CLIENT_ID)") - ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var OIDC_USERNAME)") + ENV_VARS+=("KEYCLOAK_TEST_REALM_NAME=$(get_env_var KEYCLOAK_TEST_REALM_NAME)") + ENV_VARS+=("KEYCLOAK_TEST_CLIENT_ID=$(get_env_var KEYCLOAK_TEST_CLIENT_ID)") + # CTST uses the base user (storage_manager), E2E uses a restricted user (-norights suffix) + if [[ "$SUITE" == "e2e" ]]; then + ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var KEYCLOAK_TEST_USER)-norights") + else + ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var KEYCLOAK_TEST_USER)") + fi ENV_VARS+=("KEYCLOAK_TEST_PASSWORD=$(get_env_var KEYCLOAK_TEST_PASSWORD)") - ENV_VARS+=("KEYCLOAK_TEST_HOST=$(get_env_var OIDC_HOST)") - ENV_VARS+=("KEYCLOAK_TEST_PORT=80") - ENV_VARS+=("KEYCLOAK_TEST_GRANT_TYPE=password") + ENV_VARS+=("KEYCLOAK_TEST_HOST=$(get_env_var KEYCLOAK_TEST_HOST)") ENV_VARS+=("AZURE_ACCOUNT_NAME=$(get_env_var AZURE_ACCOUNT_NAME)") ENV_VARS+=("AZURE_SECRET_KEY=$(get_env_var AZURE_SECRET_KEY)") ENV_VARS+=("AZURE_BACKEND_ENDPOINT=$(get_env_var AZURE_BACKEND_ENDPOINT)") diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index 599d9f5268..926e34ccb3 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -32,13 +32,13 @@ ADMIN_PRA_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-ad VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.local" # ZENKO_PORT="80" -KEYCLOAK_TEST_USER=${OIDC_USERNAME} +# KEYCLOAK_TEST_USER=${OIDC_USERNAME} # KEYCLOAK_TEST_PASSWORD=${OIDC_PASSWORD} -KEYCLOAK_TEST_HOST=${OIDC_HOST} -KEYCLOAK_TEST_PORT="80" -KEYCLOAK_TEST_REALM_NAME=${OIDC_REALM} -KEYCLOAK_TEST_CLIENT_ID=${OIDC_CLIENT_ID} -KEYCLOAK_TEST_GRANT_TYPE="password" +# KEYCLOAK_TEST_HOST=${OIDC_HOST} +# KEYCLOAK_TEST_PORT="80" +# KEYCLOAK_TEST_REALM_NAME=${OIDC_REALM} +# KEYCLOAK_TEST_CLIENT_ID=${OIDC_CLIENT_ID} +# KEYCLOAK_TEST_GRANT_TYPE="password" # get Zenko service users credentials BACKBEAT_LCBP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d) @@ -105,12 +105,6 @@ WORLD_PARAMETERS="$(jq -c < { break; case EntityType.STORAGE_MANAGER: await this.prepareARWWI(this.parameters.StorageManagerUsername || 'storage_manager', - 'storage-manager-role', this.parameters.KeycloakTestPassword); + 'storage-manager-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.STORAGE_ACCOUNT_OWNER: await this.prepareARWWI(this.parameters.StorageAccountOwnerUsername || 'storage_account_owner', - 'storage-account-owner-role', this.parameters.KeycloakTestPassword); + 'storage-account-owner-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.DATA_CONSUMER: await this.prepareARWWI(this.parameters.DataConsumerUsername || 'data_consumer', - 'data-consumer-role', this.parameters.KeycloakTestPassword); + 'data-consumer-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.DATA_ACCESSOR: await this.prepareARWWI(this.parameters.DataAccessorUsername || 'data_accessor', - 'data-accessor-role', this.parameters.KeycloakTestPassword); + 'data-accessor-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.ASSUME_ROLE_USER: await this.prepareAssumeRole(false); @@ -314,11 +314,11 @@ export default class Zenko extends World { const webIdentityToken = await this.getWebIdentityToken( ARWWIName, ARWWIPassword || '123', - this.parameters.KeycloakHost || 'keycloak.zenko.local', - this.parameters.KeycloakPort || '80', - `/auth/realms/${this.parameters.KeycloakRealm || 'zenko'}/protocol/openid-connect/token`, - this.parameters.KeycloakClientId || Constants.K_CLIENT, - this.parameters.KeycloakGrantType || 'password', + process.env.KEYCLOAK_TEST_HOST, + '80', + `/auth/realms/${process.env.KEYCLOAK_TEST_REALM_NAME}/protocol/openid-connect/token`, + process.env.KEYCLOAK_TEST_CLIENT_ID || Constants.K_CLIENT, + 'password', ); if (!webIdentityToken) { throw new Error('Error when trying to get a WebIdentity token.'); @@ -946,13 +946,13 @@ export default class Zenko extends World { payload: object | string = {}, ): Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> { const token = await this.getWebIdentityToken( - this.parameters.KeycloakUsername || 'storage_manager', + process.env.KEYCLOAK_TEST_USER, process.env.KEYCLOAK_TEST_PASSWORD, - this.parameters.KeycloakHost || 'keycloak.zenko.local', - this.parameters.KeycloakPort || '80', - `/auth/realms/${this.parameters.KeycloakRealm || 'zenko'}/protocol/openid-connect/token`, - this.parameters.KeycloakClientId || Constants.K_CLIENT, - this.parameters.KeycloakGrantType || 'password', + process.env.KEYCLOAK_TEST_HOST, + '80', + `/auth/realms/${process.env.KEYCLOAK_TEST_REALM_NAME || 'zenko'}/protocol/openid-connect/token`, + process.env.KEYCLOAK_TEST_CLIENT_ID || Constants.K_CLIENT, + 'password', ); const axiosInstance = axios.create(); const protocol = process.env.SSL === 'false' ? 'http://' : 'https://'; diff --git a/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js b/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js index 7ae4f695f3..cefba2b323 100644 --- a/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js +++ b/tests/zenko_tests/node_tests/utils/getWebIdentityToken.js @@ -2,12 +2,12 @@ const querystring = require('querystring'); const http = require('http'); const assert = require('assert'); -const HOST_1_URL = process.env.KEYCLOAK_TEST_HOST || 'http://keycloak.zenko.local'; -const HOST_1_PORT = parseInt(process.env.KEYCLOAK_TEST_PORT, 10) || 80; +const HOST_1 = process.env.KEYCLOAK_TEST_HOST; +const HOST_1_PORT = 80; const REALM_NAME = process.env.KEYCLOAK_TEST_REALM_NAME || 'zenko'; const KEYCLOAK_PATH = `/auth/realms/${REALM_NAME}/protocol/openid-connect/token`; const CLIENT_ID = process.env.KEYCLOAK_TEST_CLIENT_ID || 'zenko-ui'; -const GRANT_TYPE = process.env.KEYCLOAK_TEST_GRANT_TYPE || 'password'; +const GRANT_TYPE = 'password'; /** @@ -33,9 +33,6 @@ function getWebIdentityToken( grandType, callback, ) { - // In Zenko, we are using an endpoint as the `KEYCLOAK_TEST_HOST` env variable - // So we should remove any existing http of https prefix in HOST_1_URL. - host = host.replace('https://', '').replace('http://', ''); const userData = querystring.stringify({ username, password, @@ -82,7 +79,7 @@ function getTokenForIdentity(identity, callback) { getWebIdentityToken( identity, process.env.KEYCLOAK_TEST_PASSWORD, - HOST_1_URL, + HOST_1, HOST_1_PORT, KEYCLOAK_PATH, CLIENT_ID, From 09721c880faa3733e8d217deca97962f4fb77135 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 23 Feb 2026 13:37:44 +0000 Subject: [PATCH 6/9] migrate more variables --- .../end2end/configs/keycloak_config.json | 8 +- .../end2end/configs/keycloak_user.json | 2 +- .github/scripts/end2end/keycloak-helper.sh | 4 +- .github/scripts/end2end/load-config.sh | 7 +- .github/scripts/end2end/run-e2e-ctst.sh | 79 +++++++------------ tests/ctst/common/common.ts | 6 +- tests/ctst/steps/azureArchive.ts | 39 ++++----- tests/ctst/steps/iam-policies/common.ts | 6 +- tests/ctst/steps/notifications.ts | 8 +- .../ctst/steps/utilization/utilizationAPI.ts | 4 +- tests/ctst/world/Zenko.ts | 39 ++++----- 11 files changed, 87 insertions(+), 115 deletions(-) diff --git a/.github/scripts/end2end/configs/keycloak_config.json b/.github/scripts/end2end/configs/keycloak_config.json index c6b1042268..0f2c799df9 100644 --- a/.github/scripts/end2end/configs/keycloak_config.json +++ b/.github/scripts/end2end/configs/keycloak_config.json @@ -48,7 +48,7 @@ "email": "e2e-norights@zenko.local", "attributes": { "instanceIds": [ - "${INSTANCE_ID}" + "${ZENKO_INSTANCE_ID}" ], "role": [ "user" @@ -85,7 +85,7 @@ "email": "storage_manager@zenko.local", "attributes": { "instanceIds": [ - "${INSTANCE_ID}" + "${ZENKO_INSTANCE_ID}" ], "role": [ "user" @@ -123,7 +123,7 @@ "email": "data_consumer@zenko.local", "attributes": { "instanceIds": [ - "${INSTANCE_ID}" + "${ZENKO_INSTANCE_ID}" ], "role": [ "user" @@ -161,7 +161,7 @@ "email": "storage_account_owner@zenko.local", "attributes": { "instanceIds": [ - "${INSTANCE_ID}" + "${ZENKO_INSTANCE_ID}" ], "role": [ "user" diff --git a/.github/scripts/end2end/configs/keycloak_user.json b/.github/scripts/end2end/configs/keycloak_user.json index 6866c3a283..a8a69169f9 100644 --- a/.github/scripts/end2end/configs/keycloak_user.json +++ b/.github/scripts/end2end/configs/keycloak_user.json @@ -8,7 +8,7 @@ "email": "${OIDC_EMAIL}", "attributes": { "instanceIds": [ - "${INSTANCE_ID}" + "${ZENKO_INSTANCE_ID}" ], "role": [ "user" diff --git a/.github/scripts/end2end/keycloak-helper.sh b/.github/scripts/end2end/keycloak-helper.sh index 8b0da1183e..84ce7cb583 100755 --- a/.github/scripts/end2end/keycloak-helper.sh +++ b/.github/scripts/end2end/keycloak-helper.sh @@ -51,12 +51,12 @@ case $COMMAND in "set-user-instance-ids") refresh_creds - export INSTANCE_ID=`kubectl -n ${NAMESPACE} get zenko -o jsonpath='{.items[0].status.instanceID}'` + export ZENKO_INSTANCE_ID=`kubectl -n ${NAMESPACE} get zenko -o jsonpath='{.items[0].status.instanceID}'` # get user id USER_ID=$(${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh get users -r ${KEYCLOAK_TEST_REALM_NAME} -q "username=${KEYCLOAK_TEST_USER}" | jq -r '.[0].id') # set instanceIds array attribute for user - ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh update users/${USER_ID} -r ${KEYCLOAK_TEST_REALM_NAME} -s 'attributes={"instanceIds":["'"${INSTANCE_ID}"'"],"role":"user"}' + ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh update users/${USER_ID} -r ${KEYCLOAK_TEST_REALM_NAME} -s 'attributes={"instanceIds":["'"${ZENKO_INSTANCE_ID}"'"],"role":"user"}' ;; diff --git a/.github/scripts/end2end/load-config.sh b/.github/scripts/end2end/load-config.sh index e9ba422ff6..3add5f21e6 100755 --- a/.github/scripts/end2end/load-config.sh +++ b/.github/scripts/end2end/load-config.sh @@ -39,10 +39,9 @@ load_common() { # From end2end.yaml ENV_VARS+=("KEYCLOAK_TEST_REALM_NAME=$(get_env_var KEYCLOAK_TEST_REALM_NAME)") ENV_VARS+=("KEYCLOAK_TEST_CLIENT_ID=$(get_env_var KEYCLOAK_TEST_CLIENT_ID)") - # CTST uses the base user (storage_manager), E2E uses a restricted user (-norights suffix) if [[ "$SUITE" == "e2e" ]]; then ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var KEYCLOAK_TEST_USER)-norights") - else + elif [[ "$SUITE" == "ctst" ]]; then ENV_VARS+=("KEYCLOAK_TEST_USER=$(get_env_var KEYCLOAK_TEST_USER)") fi ENV_VARS+=("KEYCLOAK_TEST_PASSWORD=$(get_env_var KEYCLOAK_TEST_PASSWORD)") @@ -77,7 +76,6 @@ load_ctst() { ENV_VARS+=("DATA_CONSUMER_USER_NAME=ctst_data_consumer") ENV_VARS+=("DATA_ACCESSOR_USER_NAME=ctst_data_accessor") ENV_VARS+=("ZENKO_PORT=80") - ENV_VARS+=("UTILIZATION_SERVICE_PORT=80") ENV_VARS+=("AZURE_ARCHIVE_ACCESS_TIER=Hot") ENV_VARS+=("AZURE_ARCHIVE_MANIFEST_ACCESS_TIER=Hot") @@ -119,7 +117,7 @@ load_ctst() { # From k8s: Zenko resource values ENV_VARS+=("TIME_PROGRESSION_FACTOR=$(kubectl get zenko end2end -o jsonpath='{.metadata.annotations.zenko\.io/time-progression-factor}')") - ENV_VARS+=("INSTANCE_ID=$(kubectl get zenko end2end -o jsonpath='{.status.instanceID}')") + ENV_VARS+=("ZENKO_INSTANCE_ID=$(kubectl get zenko end2end -o jsonpath='{.status.instanceID}')") ENV_VARS+=("KAFKA_CLEANER_INTERVAL=$(kubectl get zenko end2end -o jsonpath='{.spec.kafkaCleaner.interval}')") ENV_VARS+=("SORBETD_RESTORE_TIMEOUT=$(kubectl get zenko end2end -o jsonpath='{.spec.sorbet.server.azure.restoreTimeout}')") ENV_VARS+=("UTILIZATION_SERVICE_HOST=$(kubectl get zenko end2end -o jsonpath='{.spec.scuba.api.ingress.hostname}')") @@ -140,7 +138,6 @@ load_ctst() { sorbet_ak=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d) sorbet_sk=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d) - # Build SERVICE_USERS_CREDENTIALS JSON (same format as run-e2e-ctst.sh) local service_users_creds service_users_creds=$(echo '{"backbeat-lifecycle-bp-1":'"${lcbp_creds}"',"backbeat-lifecycle-conductor-1":'"${lcc_creds}"',"backbeat-lifecycle-op-1":'"${lcop_creds}"',"backbeat-qp-1":'"${qp_creds}"',"sorbet-fwd-2":{"accessKey":"'"${sorbet_ak}"'","secretKey":"'"${sorbet_sk}"'"}}') ENV_VARS+=("SERVICE_USERS_CREDENTIALS=${service_users_creds}") diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index 926e34ccb3..1d8f903675 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -22,15 +22,13 @@ VERSION=$(cat ../../../VERSION | grep -Po 'VERSION="\K[^"]*') ZENKO_ACCOUNT_NAME="zenko-ctst" # ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) # ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) -ADMIN_PRA_ACCESS_KEY_ID=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) -ADMIN_PRA_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) # STORAGE_MANAGER_USER_NAME="ctst_storage_manager" # STORAGE_ACCOUNT_OWNER_USER_NAME="ctst_storage_account_owner" # DATA_CONSUMER_USER_NAME="ctst_data_consumer" # DATA_ACCESSOR_USER_NAME="ctst_data_accessor" -VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.local" +# VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.local" # ZENKO_PORT="80" # KEYCLOAK_TEST_USER=${OIDC_USERNAME} # KEYCLOAK_TEST_PASSWORD=${OIDC_PASSWORD} @@ -41,58 +39,52 @@ VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.loca # KEYCLOAK_TEST_GRANT_TYPE="password" # get Zenko service users credentials -BACKBEAT_LCBP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d) -BACKBEAT_LCC_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-conductor-1\.json}' | base64 -d) -BACKBEAT_LCOP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-op-1\.json}' | base64 -d) -BACKBEAT_QP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d) -SORBET_FWD_2_ACCESSKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d) -SORBET_FWD_2_SECRETKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d) +# BACKBEAT_LCBP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d) +# BACKBEAT_LCC_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-conductor-1\.json}' | base64 -d) +# BACKBEAT_LCOP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-op-1\.json}' | base64 -d) +# BACKBEAT_QP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d) +# SORBET_FWD_2_ACCESSKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d) +# SORBET_FWD_2_SECRETKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d) # SERVICE_USERS_CREDENTIALS=$(echo '{"backbeat-lifecycle-bp-1":'${BACKBEAT_LCBP_1_CREDS}',"backbeat-lifecycle-conductor-1":'${BACKBEAT_LCC_1_CREDS}',"backbeat-lifecycle-op-1":'${BACKBEAT_LCOP_1_CREDS}',"backbeat-qp-1":'${BACKBEAT_QP_1_CREDS}',"sorbet-fwd-2":{"accessKey":"'${SORBET_FWD_2_ACCESSKEY}'","secretKey":"'${SORBET_FWD_2_SECRETKEY}'"}}' | jq -R) # Get KAFKA topics for sorbet -KAFKA_DEAD_LETTER_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ - -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-dead-letter-topic"' | cut -d "\"" -f 2) +# KAFKA_DEAD_LETTER_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ + # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-dead-letter-topic"' | cut -d "\"" -f 2) -KAFKA_OBJECT_TASK_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ - -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-object-task-topic"' | cut -d "\"" -f 2) +# KAFKA_OBJECT_TASK_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ + # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-object-task-topic"' | cut -d "\"" -f 2) -KAFKA_GC_REQUEST_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ - -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-gc-request-topic"' | cut -d "\"" -f 2) - -# DR_ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) -# DR_ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-pra-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) +# KAFKA_GC_REQUEST_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ + # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-gc-request-topic"' | cut -d "\"" -f 2) # Extracting kafka host from bacbeat's config -KAFKA_HOST_PORT=$(kubectl get secret -l app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end \ - -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq .kafka.hosts) -KAFKA_HOST_PORT=${KAFKA_HOST_PORT:1:-1} -KAFKA_PORT=${KAFKA_HOST_PORT#*:} +# KAFKA_HOST_PORT=$(kubectl get secret -l app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end \ + # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq -r .kafka.hosts) +# KAFKA_PORT=${KAFKA_HOST_PORT#*:} -KAFKA_AUTH_HOST="end2end-base-queue-auth-0" -KAFKA_AUTH_HOST_PORT="$KAFKA_AUTH_HOST:$KAFKA_PORT" +# KAFKA_AUTH_HOST="end2end-base-queue-auth-0" +# KAFKA_AUTH_HOST_PORT="$KAFKA_AUTH_HOST:$KAFKA_PORT" -TIME_PROGRESSION_FACTOR=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath="{.metadata.annotations.zenko\.io/time-progression-factor}") -INSTANCE_ID=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.status.instanceID}') +# TIME_PROGRESSION_FACTOR=$(kubectl get zenko end2end -o jsonpath="{.metadata.annotations.zenko\.io/time-progression-factor}") +# ZENKO_INSTANCE_ID=$(kubectl get zenko end2end -o jsonpath='{.status.instanceID}') # Azure archive tests -AZURE_ARCHIVE_ACCESS_TIER="Hot" -AZURE_ARCHIVE_MANIFEST_ACCESS_TIER="Hot" +# AZURE_ARCHIVE_ACCESS_TIER="Hot" +# AZURE_ARCHIVE_MANIFEST_ACCESS_TIER="Hot" -BACKBEAT_API_HOST=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq .backbeat.host) -BACKBEAT_API_HOST=${BACKBEAT_API_HOST:1:-1} -BACKBEAT_API_PORT=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq .backbeat.port) +# BACKBEAT_API_HOST=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq -r .backbeat.host) +# BACKBEAT_API_PORT=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq -r .backbeat.port) KAFKA_CLEANER_INTERVAL=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.kafkaCleaner.interval}') -SORBETD_RESTORE_TIMEOUT=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.sorbet.server.azure.restoreTimeout}') +# SORBETD_RESTORE_TIMEOUT=$(kubectl get zenko end2end -o jsonpath='{.spec.sorbet.server.azure.restoreTimeout}') # Utilization service -UTILIZATION_SERVICE_HOST=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.scuba.api.ingress.hostname}') -UTILIZATION_SERVICE_PORT="80" +# UTILIZATION_SERVICE_HOST=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.scuba.api.ingress.hostname}') +# UTILIZATION_SERVICE_PORT="80" # Setting CTST world params WORLD_PARAMETERS="$(jq -c < { @@ -307,9 +307,9 @@ Then('kafka consumed messages should not take too much place on disk', { timeout try { const ignoredTopics = ['dead-letter']; - const kafkaAdmin = new Kafka({ brokers: [this.parameters.KafkaHosts] }).admin(); + const kafkaAdmin = new Kafka({ brokers: [process.env.KAFKA_HOST_PORT] }).admin(); const topics: string[] = (await kafkaAdmin.listTopics()) - .filter(t => (t.includes(this.parameters.InstanceID) && + .filter(t => (t.includes(process.env.ZENKO_INSTANCE_ID) && !ignoredTopics.some(e => t.includes(e)))); const previousOffsets = await getTopicsOffsets(topics, kafkaAdmin); diff --git a/tests/ctst/steps/azureArchive.ts b/tests/ctst/steps/azureArchive.ts index 983a752e6c..b741795e08 100644 --- a/tests/ctst/steps/azureArchive.ts +++ b/tests/ctst/steps/azureArchive.ts @@ -211,7 +211,7 @@ Then('manifest access tier should be valid for object {string}', async function manifestName, getAzureCreds(this), ); - assert.strictEqual(manifestProperties.accessTier, this.parameters.AzureArchiveManifestTier); + assert.strictEqual(manifestProperties.accessTier, Zenko.AZURE_ARCHIVE_MANIFEST_ACCESS_TIER); }); Then('tar access tier should be valid for object {string}', async function (this: Zenko, objectName: string) { @@ -229,7 +229,7 @@ Then('tar access tier should be valid for object {string}', async function (this tarName, getAzureCreds(this), ); - assert.strictEqual(packProperties.accessTier, this.parameters.AzureArchiveAccessTier); + assert.strictEqual(packProperties.accessTier, Zenko.AZURE_ARCHIVE_ACCESS_TIER); }); Then('manifest and tar containing object {string} should exist', async function (this: Zenko, objectName: string) { @@ -303,7 +303,7 @@ Then('blob for object {string} must be rehydrated', const tarName = await isObjectRehydrated(this, objectName); assert(tarName); await AzureHelper.sendBlobCreatedEventToQueue( - this.parameters.AzureArchiveQueue, + process.env.AZURE_ARCHIVE_QUEUE_NAME, this.parameters.AzureArchiveContainer, `rehydrate/${tarName}`, getAzureCreds(this), @@ -321,7 +321,7 @@ Then('blob for object {string} fails to rehydrate', const tarName = await isObjectRehydrated(this, objectName); // wait for restore to fail and end up in dead letter queue - const restoreTimeoutSeconds = parseInt(this.parameters.SorbetdRestoreTimeout); + const restoreTimeoutSeconds = parseInt(process.env.SORBETD_RESTORE_TIMEOUT); await Utils.sleep(restoreTimeoutSeconds * 1000 + 1000); assert(tarName); // restoreTimeout is set to 30s in the config @@ -361,10 +361,10 @@ Then('the storage class of object {string} must stay {string} for {int} seconds' When('i run sorbetctl to retry failed restore for {string} location', { timeout: 10 * 60 * 1000 }, async function (this: Zenko, location: string) { const command = `/ctst/sorbetctl forward list failed --trigger-retry --skip-invalid \ - --kafka-dead-letter-topic=${this.parameters.KafkaDeadLetterQueueTopic} \ - --kafka-object-task-topic=${this.parameters.KafkaObjectTaskTopic} \ - --kafka-gc-request-topic=${this.parameters.KafkaGCRequestTopic} \ - --kafka-brokers ${this.parameters.KafkaHosts}`; + --kafka-dead-letter-topic=${process.env.KAFKA_DEAD_LETTER_TOPIC} \ + --kafka-object-task-topic=${process.env.KAFKA_OBJECT_TASK_TOPIC} \ + --kafka-gc-request-topic=${process.env.KAFKA_GC_REQUEST_TOPIC} \ + --kafka-brokers ${process.env.KAFKA_HOST_PORT}`; try { this.logger.debug('Running command', { command, location }); const result = await util.promisify(exec)(command); @@ -378,8 +378,8 @@ When('i run sorbetctl to retry failed restore for {string} location', }); When('i wait for {int} days', { timeout: 10 * 60 * 1000 }, async function (this: Zenko, days: number) { - const realTimeDay = days * 24 * 60 * 60 * 1000 / - (this.parameters.TimeProgressionFactor > 1 ? this.parameters.TimeProgressionFactor : 1); + const factor = Math.max(1, Number(process.env.TIME_PROGRESSION_FACTOR) || 1); + const realTimeDay = days * 24 * 60 * 60 * 1000 / factor; await Utils.sleep(realTimeDay); }); @@ -402,9 +402,10 @@ Then('object {string} should expire in {int} days', async function (this: Zenko, const expiryDate = new Date(expireResDate[1]).getTime(); const lastModified = new Date(head.LastModified).getTime(); const diff = (expiryDate - lastModified) / 1000 / 86400; - const realTimeDays = days / (this.parameters.TimeProgressionFactor > 1 ? this.parameters.TimeProgressionFactor : 1); + const factor = Math.max(1, Number(process.env.TIME_PROGRESSION_FACTOR) || 1); + const realTimeDays = days / factor; assert.ok(diff >= realTimeDays && diff < realTimeDays + 0.005, - `Expected ${realTimeDays} but got ${diff} ; ${this.parameters.TimeProgressionFactor}`); + `Expected ${realTimeDays} but got ${diff} ; ${process.env.TIME_PROGRESSION_FACTOR}`); }); Given('that lifecycle is {string} for the {string} location', @@ -416,8 +417,8 @@ Given('that lifecycle is {string} for the {string} location', path = `/_/lifecycle/resume/${location}`; } const options = { - hostname: this.parameters.BackbeatApiHost, - port: this.parameters.BackbeatApiPort, + hostname: process.env.BACKBEAT_API_HOST, + port: process.env.BACKBEAT_API_PORT, method: 'POST', path, }; @@ -434,7 +435,7 @@ Given('an azure archive location {string}', { timeout: 15 * 60 * 1000 }, bucketName: this.parameters.AzureArchiveContainer, queue: { type: 'location-azure-storage-queue-v1', - queueName: this.parameters.AzureArchiveQueue, + queueName: process.env.AZURE_ARCHIVE_QUEUE_NAME, endpoint: AZURE_STORAGE_QUEUE_URL, }, auth: { @@ -444,7 +445,7 @@ Given('an azure archive location {string}', { timeout: 15 * 60 * 1000 }, }, }, }; - const result = await this.managementAPIRequest('POST', `/config/${this.parameters.InstanceID}/location`, {}, + const result = await this.managementAPIRequest('POST', `/config/${process.env.ZENKO_INSTANCE_ID}/location`, {}, locationConfig); assert.strictEqual(result.statusCode, 201); this.addToSaved('locationName', locationName); @@ -454,7 +455,7 @@ Given('an azure archive location {string}', { timeout: 15 * 60 * 1000 }, When('i change azure archive location {string} container target', { timeout: 15 * 60 * 1000 }, async function (this: Zenko, locationName: string) { - const result = await this.managementAPIRequest('GET', `/config/overlay/view/${this.parameters.InstanceID}`); + const result = await this.managementAPIRequest('GET', `/config/overlay/view/${process.env.ZENKO_INSTANCE_ID}`); if ('err' in result) { assert.ifError(result.err); } else { @@ -466,7 +467,7 @@ When('i change azure archive location {string} container target', { timeout: 15 details.bucketName = this.parameters.AzureArchiveContainer2; auth.accountKey = this.parameters.AzureAccountKey; const putResult = await this.managementAPIRequest('PUT', - `/config/${this.parameters.InstanceID}/location/${locationName}`, + `/config/${process.env.ZENKO_INSTANCE_ID}/location/${locationName}`, {}, locationConfig); if ('err' in putResult) { @@ -482,7 +483,7 @@ When('i change azure archive location {string} container target', { timeout: 15 }); Then('i can get the {string} location details', async function (this: Zenko, locationName: string) { - const result = await this.managementAPIRequest('GET', `/config/overlay/view/${this.parameters.InstanceID}`); + const result = await this.managementAPIRequest('GET', `/config/overlay/view/${process.env.ZENKO_INSTANCE_ID}`); if ('err' in result) { assert.ifError(result.err); } diff --git a/tests/ctst/steps/iam-policies/common.ts b/tests/ctst/steps/iam-policies/common.ts index e8bcd0d034..5f4103722b 100644 --- a/tests/ctst/steps/iam-policies/common.ts +++ b/tests/ctst/steps/iam-policies/common.ts @@ -20,15 +20,11 @@ When('the user tries to perform vault auth {string}', async function (this: Zenk + 'Make sure the `IAMSession` and `AssumedSession` world parameter are defined.'); } - if (!this.parameters.VaultAuthHost) { - throw new Error('Vault auth endpoint is not set. Make sure the `VaultAuthHost` world parameter is defined.'); - } - const vaultAuthClientOptions: ClientOptions = { AccessKey: userCredentials.accessKeyId, SecretKey: userCredentials.secretAccessKey, SessionToken: userCredentials.sessionToken, - ip: this.parameters.VaultAuthHost, + ip: "end2end-connector-vault-auth-api.default.svc.cluster.local", ssl: CacheHelper.parameters.ssl, }; diff --git a/tests/ctst/steps/notifications.ts b/tests/ctst/steps/notifications.ts index 69f1176c11..d64b620032 100644 --- a/tests/ctst/steps/notifications.ts +++ b/tests/ctst/steps/notifications.ts @@ -118,7 +118,7 @@ Given('one notification destination', function (this: Zenko) { this, this.parameters.NotificationDestination, this.parameters.NotificationDestinationTopic, - this.parameters.KafkaHosts, + process.env.KAFKA_HOST_PORT, ); }); @@ -127,7 +127,7 @@ Given('one authenticated notification destination', function (this: Zenko) { this, this.parameters.NotificationDestinationAuth, this.parameters.NotificationDestinationTopicAuth, - this.parameters.KafkaAuthHosts, + process.env.KAFKA_AUTH_HOST_PORT, ); }); @@ -136,12 +136,12 @@ Given('two notification destinations', function (this: Zenko) { notificationDestinations.push({ destinationName: this.parameters.NotificationDestination, topic: this.parameters.NotificationDestinationTopic, - hosts: this.parameters.KafkaHosts, + hosts: process.env.KAFKA_HOST_PORT, }); notificationDestinations.push({ destinationName: this.parameters.NotificationDestinationAlt, topic: this.parameters.NotificationDestinationTopicAlt, - hosts: this.parameters.KafkaHosts, + hosts: process.env.KAFKA_HOST_PORT, }); this.addToSaved('notificationDestinations', notificationDestinations); }); diff --git a/tests/ctst/steps/utilization/utilizationAPI.ts b/tests/ctst/steps/utilization/utilizationAPI.ts index f76cef9a72..467a9ba541 100644 --- a/tests/ctst/steps/utilization/utilizationAPI.ts +++ b/tests/ctst/steps/utilization/utilizationAPI.ts @@ -27,8 +27,8 @@ When('the user retrieves utilization metrics using scubaclient for metric type { this.addToSaved('metricType', metricType); const client = new ScubaClient({ - port: parseInt(this.parameters.UtilizationServicePort), - host: this.parameters.UtilizationServiceHost, + port: Zenko.UTILIZATION_SERVICE_PORT, + host: process.env.UTILIZATION_SERVICE_HOST, useHttps: false, auth: { awsV4: { diff --git a/tests/ctst/world/Zenko.ts b/tests/ctst/world/Zenko.ts index 43b46b5e20..5d02d31c03 100644 --- a/tests/ctst/world/Zenko.ts +++ b/tests/ctst/world/Zenko.ts @@ -1,4 +1,4 @@ -import { World, IWorldOptions, setWorldConstructor } from '@cucumber/cucumber'; +// import { World, IWorldOptions, setWorldConstructor } from '@cucumber/cucumber'; import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios'; import { AccessKey } from '@aws-sdk/client-iam'; import { Credentials } from '@aws-sdk/client-sts'; @@ -50,7 +50,7 @@ export interface ZenkoWorldParameters extends ClientOptions { // DRAdminAccessKey?: string; // DRAdminSecretKey?: string; // DRSubdomain?: string; - VaultAuthHost: string; + // VaultAuthHost: string; NotificationDestination: string; NotificationDestinationTopic: string; NotificationDestinationAlt: string; @@ -60,8 +60,8 @@ export interface ZenkoWorldParameters extends ClientOptions { NotificationDestinationAuthUsername: string; NotificationDestinationAuthPassword: string; KafkaExternalIps: string; - KafkaHosts: string; - KafkaAuthHosts: string; + // KafkaHosts: string; + // KafkaAuthHosts: string; PrometheusService: string; // KeycloakUsername: string; // KeycloakPassword: string; @@ -82,18 +82,18 @@ export interface ZenkoWorldParameters extends ClientOptions { AzureArchiveContainer2: string; AzureArchiveAccessTier: string; AzureArchiveManifestTier: string; - AzureArchiveQueue: string; - TimeProgressionFactor: number; - KafkaDeadLetterQueueTopic: string; - KafkaObjectTaskTopic: string; - KafkaGCRequestTopic: string; - InstanceID: string; - BackbeatApiHost: string; - BackbeatApiPort: string; - KafkaCleanerInterval: string; - SorbetdRestoreTimeout: string; - UtilizationServiceHost: string; - UtilizationServicePort: string; + // AzureArchiveQueue: string; + // TimeProgressionFactor: number; + // KafkaDeadLetterQueueTopic: string; + // KafkaObjectTaskTopic: string; + // KafkaGCRequestTopic: string; + // InstanceID: string; + // BackbeatApiHost: string; + // BackbeatApiPort: string; + // KafkaCleanerInterval: string; + // SorbetdRestoreTimeout: string; + // UtilizationServiceHost: string; + // UtilizationServicePort: string; [key: string]: unknown; } @@ -127,6 +127,9 @@ export default class Zenko extends World { static readonly PRIMARY_SITE_NAME = 'admin'; static readonly SECONDARY_SITE_NAME = 'dradmin'; static readonly PRA_INSTALL_COUNT_KEY = 'praInstallCount'; + static readonly AZURE_ARCHIVE_ACCESS_TIER = 'Hot'; + static readonly AZURE_ARCHIVE_MANIFEST_ACCESS_TIER = 'Hot'; + static readonly UTILIZATION_SERVICE_PORT = 80; /** * @constructor @@ -999,7 +1002,7 @@ export default class Zenko extends World { async addWebsiteEndpoint(this: Zenko, endpoint: string): Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> { return await this.managementAPIRequest('POST', - `/config/${this.parameters.InstanceID}/website/endpoint`, + `/config/${process.env.ZENKO_INSTANCE_ID}/website/endpoint`, { 'Content-Type': 'application/json', }, @@ -1009,7 +1012,7 @@ export default class Zenko extends World { async deleteLocation(this: Zenko, locationName: string): Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> { return await this.managementAPIRequest('DELETE', - `/config/${this.parameters.InstanceID}/location/${locationName}`); + `/config/${process.env.ZENKO_INSTANCE_ID}/location/${locationName}`); } saveCreatedObject(objectName: string, versionId: string) { From f5de72ae23acfda19ac81f5bec4567aeda8690e2 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 23 Feb 2026 14:24:11 +0000 Subject: [PATCH 7/9] udate more env, notif destinations --- .devcontainer/devcontainer.json | 1 + .github/scripts/end2end/keycloak-helper.sh | 2 +- .github/scripts/end2end/run-e2e-ctst.sh | 11 ------- tests/ctst/steps/azureArchive.ts | 34 +++++++++++----------- tests/ctst/steps/notifications.ts | 16 +++++----- tests/ctst/steps/pra.ts | 4 +-- tests/ctst/world/Zenko.ts | 25 ++++++++-------- 7 files changed, 42 insertions(+), 51 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 19cf7b1653..0b23ef0ce6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -96,6 +96,7 @@ "vscode": { "extensions": [ "ms-kubernetes-tools.vscode-kubernetes-tools", + "cucumberopen.cucumber-official" ] } }, diff --git a/.github/scripts/end2end/keycloak-helper.sh b/.github/scripts/end2end/keycloak-helper.sh index 84ce7cb583..1ecfee4d74 100755 --- a/.github/scripts/end2end/keycloak-helper.sh +++ b/.github/scripts/end2end/keycloak-helper.sh @@ -29,7 +29,7 @@ case $COMMAND in "add-user") refresh_creds - export INSTANCE_ID=`kubectl -n ${NAMESPACE} get zenko ${ZENKO_NAME} -o jsonpath='{.status.instanceID}'` + export ZENKO_INSTANCE_ID=`kubectl -n ${NAMESPACE} get zenko ${ZENKO_NAME} -o jsonpath='{.status.instanceID}'` export OIDC_EMAIL=${OIDC_EMAIL:-"e2e@zenko.local"} diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index 1d8f903675..daee8b55a1 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -85,24 +85,13 @@ KAFKA_CLEANER_INTERVAL=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.kaf # Setting CTST world params WORLD_PARAMETERS="$(jq -c < { // lisintg all blobs in the container const blobs = await AzureHelper.listBlobs( - world.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, getAzureCreds(world), ); // filtering the list of blobs only leaving the manifests @@ -104,7 +104,7 @@ async function findObjectPackAndManifest( for (let i = 0; i < manifests.length; i++) { // downloading the manifest const manifestBuffer = await AzureHelper.downloadBlob( - world.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, manifests[i].name, getAzureCreds(world), ); @@ -175,19 +175,19 @@ export async function cleanAzureContainer( ); if (tarName) { await AzureHelper.deleteBlob( - world.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, tarName, getAzureCreds(world), ); await AzureHelper.deleteBlob( - world.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, `rehydrate/${tarName}`, getAzureCreds(world), ); } if (manifestName) { await AzureHelper.deleteBlob( - world.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, manifestName, getAzureCreds(world), ); @@ -207,7 +207,7 @@ Then('manifest access tier should be valid for object {string}', async function assert(manifestName); // manifest access tier const manifestProperties = await AzureHelper.getBlobProperties( - this.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, manifestName, getAzureCreds(this), ); @@ -225,7 +225,7 @@ Then('tar access tier should be valid for object {string}', async function (this assert(tarName); // manifest access tier const packProperties = await AzureHelper.getBlobProperties( - this.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, tarName, getAzureCreds(this), ); @@ -304,7 +304,7 @@ Then('blob for object {string} must be rehydrated', assert(tarName); await AzureHelper.sendBlobCreatedEventToQueue( process.env.AZURE_ARCHIVE_QUEUE_NAME, - this.parameters.AzureArchiveContainer, + process.env.AZURE_ARCHIVE_BUCKET_NAME, `rehydrate/${tarName}`, getAzureCreds(this), ); @@ -432,7 +432,7 @@ Given('an azure archive location {string}', { timeout: 15 * 60 * 1000 }, locationType: 'location-azure-archive-v1', details: { endpoint: AZURE_STORAGE_BLOB_URL, - bucketName: this.parameters.AzureArchiveContainer, + bucketName: process.env.AZURE_ARCHIVE_BUCKET_NAME, queue: { type: 'location-azure-storage-queue-v1', queueName: process.env.AZURE_ARCHIVE_QUEUE_NAME, @@ -440,8 +440,8 @@ Given('an azure archive location {string}', { timeout: 15 * 60 * 1000 }, }, auth: { type: 'location-azure-shared-key', - accountName: this.parameters.AzureAccountName, - accountKey: this.parameters.AzureAccountKey, + accountName: process.env.AZURE_ACCOUNT_NAME, + accountKey: process.env.AZURE_SECRET_KEY, }, }, }; @@ -464,8 +464,8 @@ When('i change azure archive location {string} container target', { timeout: 15 const locationConfig = locations[locationName] as Record; const details = locationConfig.details as { bucketName: string, auth: { accountKey: string } }; const auth = details.auth; - details.bucketName = this.parameters.AzureArchiveContainer2; - auth.accountKey = this.parameters.AzureAccountKey; + details.bucketName = process.env.AZURE_ARCHIVE_BUCKET_NAME_2; + auth.accountKey = process.env.AZURE_SECRET_KEY; const putResult = await this.managementAPIRequest('PUT', `/config/${process.env.ZENKO_INSTANCE_ID}/location/${locationName}`, {}, @@ -474,7 +474,7 @@ When('i change azure archive location {string} container target', { timeout: 15 assert.ifError(putResult.err); } else { assert.strictEqual((putResult.data as { details: { bucketName: string } }).details.bucketName, - this.parameters.AzureArchiveContainer2); + process.env.AZURE_ARCHIVE_BUCKET_NAME_2); assert.strictEqual(putResult.statusCode, 200); } } diff --git a/tests/ctst/steps/notifications.ts b/tests/ctst/steps/notifications.ts index d64b620032..6ba77e9457 100644 --- a/tests/ctst/steps/notifications.ts +++ b/tests/ctst/steps/notifications.ts @@ -116,8 +116,8 @@ function setNotificationDestination(world: Zenko, destination: string, topic: st Given('one notification destination', function (this: Zenko) { setNotificationDestination( this, - this.parameters.NotificationDestination, - this.parameters.NotificationDestinationTopic, + process.env.NOTIF_DEST_NAME, + process.env.NOTIF_DEST_TOPIC, process.env.KAFKA_HOST_PORT, ); }); @@ -125,8 +125,8 @@ Given('one notification destination', function (this: Zenko) { Given('one authenticated notification destination', function (this: Zenko) { setNotificationDestination( this, - this.parameters.NotificationDestinationAuth, - this.parameters.NotificationDestinationTopicAuth, + process.env.NOTIF_AUTH_DEST_NAME, + process.env.NOTIF_AUTH_DEST_TOPIC, process.env.KAFKA_AUTH_HOST_PORT, ); }); @@ -134,13 +134,13 @@ Given('one authenticated notification destination', function (this: Zenko) { Given('two notification destinations', function (this: Zenko) { const notificationDestinations = []; notificationDestinations.push({ - destinationName: this.parameters.NotificationDestination, - topic: this.parameters.NotificationDestinationTopic, + destinationName: process.env.NOTIF_DEST_NAME, + topic: process.env.NOTIF_DEST_TOPIC, hosts: process.env.KAFKA_HOST_PORT, }); notificationDestinations.push({ - destinationName: this.parameters.NotificationDestinationAlt, - topic: this.parameters.NotificationDestinationTopicAlt, + destinationName: process.env.NOTIF_ALT_DEST_NAME, + topic: process.env.NOTIF_ALT_DEST_TOPIC, hosts: process.env.KAFKA_HOST_PORT, }); this.addToSaved('notificationDestinations', notificationDestinations); diff --git a/tests/ctst/steps/pra.ts b/tests/ctst/steps/pra.ts index 4542658ce0..7a6d9dd861 100644 --- a/tests/ctst/steps/pra.ts +++ b/tests/ctst/steps/pra.ts @@ -70,7 +70,7 @@ async function installPRA(world: Zenko, sinkS3Endpoint = 'http://s3.zenko.local' sourceZenkoNamespace: 'default', sourceS3Endpoint: 'http://s3.zenko.local', sinkS3Endpoint, - prometheusService: world.parameters.PrometheusService, + prometheusService: Zenko.PROMETHEUS_SERVICE, prometheusHostname: 'prom.dr.zenko.local', prometheusExternalIpsDiscovery: true, forceRotateServiceCredentials: (CacheHelper.savedAcrossTests[Zenko.PRA_INSTALL_COUNT_KEY] as number) > 0, @@ -330,7 +330,7 @@ Then('the kafka DR volume exists', { timeout: volumeTimeout + 2000 }, async func Then('prometheus should scrap federated metrics from DR sink', { timeout: 180000 }, async function (this: Zenko) { const prom = new PrometheusDriver({ - endpoint: `http://${this.parameters.PrometheusService}:9090`, + endpoint: `http://${Zenko.PROMETHEUS_SERVICE}:9090`, baseURL: '/api/v1', }); diff --git a/tests/ctst/world/Zenko.ts b/tests/ctst/world/Zenko.ts index 5d02d31c03..9537b64920 100644 --- a/tests/ctst/world/Zenko.ts +++ b/tests/ctst/world/Zenko.ts @@ -51,18 +51,18 @@ export interface ZenkoWorldParameters extends ClientOptions { // DRAdminSecretKey?: string; // DRSubdomain?: string; // VaultAuthHost: string; - NotificationDestination: string; - NotificationDestinationTopic: string; - NotificationDestinationAlt: string; - NotificationDestinationTopicAlt: string; - NotificationDestinationAuth: string; - NotificationDestinationTopicAuth: string; - NotificationDestinationAuthUsername: string; + // NotificationDestination: string; + // NotificationDestinationTopic: string; + // NotificationDestinationAlt: string; + // NotificationDestinationTopicAlt: string; + // NotificationDestinationAuth: string; + // NotificationDestinationTopicAuth: string; + // NotificationDestinationAuthUsername: string; NotificationDestinationAuthPassword: string; KafkaExternalIps: string; // KafkaHosts: string; // KafkaAuthHosts: string; - PrometheusService: string; + // PrometheusService: string; // KeycloakUsername: string; // KeycloakPassword: string; // KeycloakHost: string; @@ -76,10 +76,10 @@ export interface ZenkoWorldParameters extends ClientOptions { DataConsumerUsername: string; DataAccessorUsername: string; ServiceUsersCredentials: string; - AzureAccountName: string; - AzureAccountKey: string; - AzureArchiveContainer: string; - AzureArchiveContainer2: string; + // AzureAccountName: string; + // AzureAccountKey: string; + // AzureArchiveContainer: string; + // AzureArchiveContainer2: string; AzureArchiveAccessTier: string; AzureArchiveManifestTier: string; // AzureArchiveQueue: string; @@ -130,6 +130,7 @@ export default class Zenko extends World { static readonly AZURE_ARCHIVE_ACCESS_TIER = 'Hot'; static readonly AZURE_ARCHIVE_MANIFEST_ACCESS_TIER = 'Hot'; static readonly UTILIZATION_SERVICE_PORT = 80; + static readonly PROMETHEUS_SERVICE = `${process.env.PROMETHEUS_NAME}-operated.default.svc.cluster.local`; /** * @constructor From 9181d8b3d96735305424b02faaf8260c30b14d89 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 23 Feb 2026 16:04:11 +0000 Subject: [PATCH 8/9] last var --- .github/scripts/end2end/load-config.sh | 10 +- .github/scripts/end2end/run-e2e-ctst.sh | 92 +++---------------- .github/workflows/end2end.yaml | 5 + .../features/crrReplicationS3utils.feature | 2 +- tests/ctst/steps/azureArchive.ts | 34 +++---- tests/ctst/steps/iam-policies/common.ts | 2 +- tests/ctst/steps/pra.ts | 2 +- tests/ctst/world/Zenko.ts | 24 ++--- 8 files changed, 54 insertions(+), 117 deletions(-) diff --git a/.github/scripts/end2end/load-config.sh b/.github/scripts/end2end/load-config.sh index 3add5f21e6..328834fbc6 100755 --- a/.github/scripts/end2end/load-config.sh +++ b/.github/scripts/end2end/load-config.sh @@ -70,16 +70,16 @@ load_ctst() { # Hardcoded CTST values ENV_VARS+=("SSL=false") - ENV_VARS+=("ZENKO_ACCOUNT_NAME=zenko-ctst") - ENV_VARS+=("STORAGE_MANAGER_USER_NAME=ctst_storage_manager") - ENV_VARS+=("STORAGE_ACCOUNT_OWNER_USER_NAME=ctst_storage_account_owner") - ENV_VARS+=("DATA_CONSUMER_USER_NAME=ctst_data_consumer") - ENV_VARS+=("DATA_ACCESSOR_USER_NAME=ctst_data_accessor") ENV_VARS+=("ZENKO_PORT=80") ENV_VARS+=("AZURE_ARCHIVE_ACCESS_TIER=Hot") ENV_VARS+=("AZURE_ARCHIVE_MANIFEST_ACCESS_TIER=Hot") # From end2end.yaml + ENV_VARS+=("ZENKO_ACCOUNT_NAME=$(get_env_var ZENKO_ACCOUNT_NAME)") + ENV_VARS+=("STORAGE_MANAGER_USER_NAME=$(get_env_var STORAGE_MANAGER_USER_NAME)") + ENV_VARS+=("STORAGE_ACCOUNT_OWNER_USER_NAME=$(get_env_var STORAGE_ACCOUNT_OWNER_USER_NAME)") + ENV_VARS+=("DATA_CONSUMER_USER_NAME=$(get_env_var DATA_CONSUMER_USER_NAME)") + ENV_VARS+=("DATA_ACCESSOR_USER_NAME=$(get_env_var DATA_ACCESSOR_USER_NAME)") ENV_VARS+=("DR_SUBDOMAIN=$(get_env_var DR_SUBDOMAIN)") ENV_VARS+=("PROMETHEUS_NAME=$(get_env_var PROMETHEUS_NAME)") ENV_VARS+=("AZURE_BACKEND_QUEUE_ENDPOINT=$(get_env_var AZURE_BACKEND_QUEUE_ENDPOINT)") diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index daee8b55a1..0d7d1e1c6f 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -18,80 +18,12 @@ PARALLEL_RUNS=${PARALLEL_RUNS:-$(( ( $(nproc) + 1 ) / 2 ))} # Zenko Version VERSION=$(cat ../../../VERSION | grep -Po 'VERSION="\K[^"]*') -# Zenko Environment -ZENKO_ACCOUNT_NAME="zenko-ctst" -# ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) -# ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) - -# STORAGE_MANAGER_USER_NAME="ctst_storage_manager" -# STORAGE_ACCOUNT_OWNER_USER_NAME="ctst_storage_account_owner" -# DATA_CONSUMER_USER_NAME="ctst_data_consumer" -# DATA_ACCESSOR_USER_NAME="ctst_data_accessor" - -# VAULT_AUTH_HOST="${ZENKO_NAME}-connector-vault-auth-api.default.svc.cluster.local" -# ZENKO_PORT="80" -# KEYCLOAK_TEST_USER=${OIDC_USERNAME} -# KEYCLOAK_TEST_PASSWORD=${OIDC_PASSWORD} -# KEYCLOAK_TEST_HOST=${OIDC_HOST} -# KEYCLOAK_TEST_PORT="80" -# KEYCLOAK_TEST_REALM_NAME=${OIDC_REALM} -# KEYCLOAK_TEST_CLIENT_ID=${OIDC_CLIENT_ID} -# KEYCLOAK_TEST_GRANT_TYPE="password" - -# get Zenko service users credentials -# BACKBEAT_LCBP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-bp-1\.json}' | base64 -d) -# BACKBEAT_LCC_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-conductor-1\.json}' | base64 -d) -# BACKBEAT_LCOP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-lifecycle-op-1\.json}' | base64 -d) -# BACKBEAT_QP_1_CREDS=$(kubectl get secret -l app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.backbeat-qp-1\.json}' | base64 -d) -# SORBET_FWD_2_ACCESSKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.accessKey}' | base64 -d) -# SORBET_FWD_2_SECRETKEY=$(kubectl get secret -l app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.secretKey}' | base64 -d) -# SERVICE_USERS_CREDENTIALS=$(echo '{"backbeat-lifecycle-bp-1":'${BACKBEAT_LCBP_1_CREDS}',"backbeat-lifecycle-conductor-1":'${BACKBEAT_LCC_1_CREDS}',"backbeat-lifecycle-op-1":'${BACKBEAT_LCOP_1_CREDS}',"backbeat-qp-1":'${BACKBEAT_QP_1_CREDS}',"sorbet-fwd-2":{"accessKey":"'${SORBET_FWD_2_ACCESSKEY}'","secretKey":"'${SORBET_FWD_2_SECRETKEY}'"}}' | jq -R) - -# Get KAFKA topics for sorbet -# KAFKA_DEAD_LETTER_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ - # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-dead-letter-topic"' | cut -d "\"" -f 2) - -# KAFKA_OBJECT_TASK_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ - # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-object-task-topic"' | cut -d "\"" -f 2) - -# KAFKA_GC_REQUEST_TOPIC=$(kubectl get secret -l app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end \ - # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq '."kafka-gc-request-topic"' | cut -d "\"" -f 2) - -# Extracting kafka host from bacbeat's config -# KAFKA_HOST_PORT=$(kubectl get secret -l app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end \ - # -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq -r .kafka.hosts) -# KAFKA_PORT=${KAFKA_HOST_PORT#*:} - -# KAFKA_AUTH_HOST="end2end-base-queue-auth-0" -# KAFKA_AUTH_HOST_PORT="$KAFKA_AUTH_HOST:$KAFKA_PORT" - -# TIME_PROGRESSION_FACTOR=$(kubectl get zenko end2end -o jsonpath="{.metadata.annotations.zenko\.io/time-progression-factor}") -# ZENKO_INSTANCE_ID=$(kubectl get zenko end2end -o jsonpath='{.status.instanceID}') - -# Azure archive tests -# AZURE_ARCHIVE_ACCESS_TIER="Hot" -# AZURE_ARCHIVE_MANIFEST_ACCESS_TIER="Hot" - -# BACKBEAT_API_HOST=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq -r .backbeat.host) -# BACKBEAT_API_PORT=$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq -r .backbeat.port) - -KAFKA_CLEANER_INTERVAL=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.kafkaCleaner.interval}') -# SORBETD_RESTORE_TIMEOUT=$(kubectl get zenko end2end -o jsonpath='{.spec.sorbet.server.azure.restoreTimeout}') - -# Utilization service -# UTILIZATION_SERVICE_HOST=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.scuba.api.ingress.hostname}') -# UTILIZATION_SERVICE_PORT="80" - # Setting CTST world params WORLD_PARAMETERS="$(jq -c < blob.name.includes('.json.')); @@ -106,7 +100,7 @@ async function findObjectPackAndManifest( const manifestBuffer = await AzureHelper.downloadBlob( process.env.AZURE_ARCHIVE_BUCKET_NAME, manifests[i].name, - getAzureCreds(world), + getAzureCreds(), ); const { ok, result } = safeJsonParse(manifestBuffer.toString()); if (!ok) { @@ -177,19 +171,19 @@ export async function cleanAzureContainer( await AzureHelper.deleteBlob( process.env.AZURE_ARCHIVE_BUCKET_NAME, tarName, - getAzureCreds(world), + getAzureCreds(), ); await AzureHelper.deleteBlob( process.env.AZURE_ARCHIVE_BUCKET_NAME, `rehydrate/${tarName}`, - getAzureCreds(world), + getAzureCreds(), ); } if (manifestName) { await AzureHelper.deleteBlob( process.env.AZURE_ARCHIVE_BUCKET_NAME, manifestName, - getAzureCreds(world), + getAzureCreds(), ); } currentKey = iterator.next(); @@ -209,7 +203,7 @@ Then('manifest access tier should be valid for object {string}', async function const manifestProperties = await AzureHelper.getBlobProperties( process.env.AZURE_ARCHIVE_BUCKET_NAME, manifestName, - getAzureCreds(this), + getAzureCreds(), ); assert.strictEqual(manifestProperties.accessTier, Zenko.AZURE_ARCHIVE_MANIFEST_ACCESS_TIER); }); @@ -227,7 +221,7 @@ Then('tar access tier should be valid for object {string}', async function (this const packProperties = await AzureHelper.getBlobProperties( process.env.AZURE_ARCHIVE_BUCKET_NAME, tarName, - getAzureCreds(this), + getAzureCreds(), ); assert.strictEqual(packProperties.accessTier, Zenko.AZURE_ARCHIVE_ACCESS_TIER); }); @@ -306,7 +300,7 @@ Then('blob for object {string} must be rehydrated', process.env.AZURE_ARCHIVE_QUEUE_NAME, process.env.AZURE_ARCHIVE_BUCKET_NAME, `rehydrate/${tarName}`, - getAzureCreds(this), + getAzureCreds(), ); }); @@ -377,7 +371,7 @@ When('i run sorbetctl to retry failed restore for {string} location', } }); -When('i wait for {int} days', { timeout: 10 * 60 * 1000 }, async function (this: Zenko, days: number) { +When('i wait for {int} days', { timeout: 10 * 60 * 1000 }, async (days: number) => { const factor = Math.max(1, Number(process.env.TIME_PROGRESSION_FACTOR) || 1); const realTimeDay = days * 24 * 60 * 60 * 1000 / factor; await Utils.sleep(realTimeDay); @@ -409,7 +403,7 @@ Then('object {string} should expire in {int} days', async function (this: Zenko, }); Given('that lifecycle is {string} for the {string} location', - async function (this: Zenko, status: string, location: string) { + async (_this: Zenko, status: string, location: string) => { let path: string; if (status === 'paused') { path = `/_/lifecycle/pause/${location}`; @@ -431,12 +425,12 @@ Given('an azure archive location {string}', { timeout: 15 * 60 * 1000 }, name: locationName, locationType: 'location-azure-archive-v1', details: { - endpoint: AZURE_STORAGE_BLOB_URL, + endpoint: process.env.AZURE_BACKEND_ENDPOINT || 'http://127.0.0.1:10000/devstoreaccount1', bucketName: process.env.AZURE_ARCHIVE_BUCKET_NAME, queue: { type: 'location-azure-storage-queue-v1', queueName: process.env.AZURE_ARCHIVE_QUEUE_NAME, - endpoint: AZURE_STORAGE_QUEUE_URL, + endpoint: process.env.AZURE_BACKEND_QUEUE_ENDPOINT || 'http://127.0.0.1:10001/devstoreaccount1', }, auth: { type: 'location-azure-shared-key', diff --git a/tests/ctst/steps/iam-policies/common.ts b/tests/ctst/steps/iam-policies/common.ts index 5f4103722b..45a5b9ec7d 100644 --- a/tests/ctst/steps/iam-policies/common.ts +++ b/tests/ctst/steps/iam-policies/common.ts @@ -24,7 +24,7 @@ When('the user tries to perform vault auth {string}', async function (this: Zenk AccessKey: userCredentials.accessKeyId, SecretKey: userCredentials.secretAccessKey, SessionToken: userCredentials.sessionToken, - ip: "end2end-connector-vault-auth-api.default.svc.cluster.local", + ip: 'end2end-connector-vault-auth-api.default.svc.cluster.local', ssl: CacheHelper.parameters.ssl, }; diff --git a/tests/ctst/steps/pra.ts b/tests/ctst/steps/pra.ts index 7a6d9dd861..7a2f846cd0 100644 --- a/tests/ctst/steps/pra.ts +++ b/tests/ctst/steps/pra.ts @@ -328,7 +328,7 @@ Then('the kafka DR volume exists', { timeout: volumeTimeout + 2000 }, async func assert(volumeParsed.result!['volume phase'] === 'Bound'); }); -Then('prometheus should scrap federated metrics from DR sink', { timeout: 180000 }, async function (this: Zenko) { +Then('prometheus should scrap federated metrics from DR sink', { timeout: 180000 }, async () => { const prom = new PrometheusDriver({ endpoint: `http://${Zenko.PROMETHEUS_SERVICE}:9090`, baseURL: '/api/v1', diff --git a/tests/ctst/world/Zenko.ts b/tests/ctst/world/Zenko.ts index 9537b64920..c9085ce628 100644 --- a/tests/ctst/world/Zenko.ts +++ b/tests/ctst/world/Zenko.ts @@ -1,4 +1,4 @@ -// import { World, IWorldOptions, setWorldConstructor } from '@cucumber/cucumber'; +import { World, IWorldOptions, setWorldConstructor } from '@cucumber/cucumber'; import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios'; import { AccessKey } from '@aws-sdk/client-iam'; import { Credentials } from '@aws-sdk/client-sts'; @@ -71,17 +71,17 @@ export interface ZenkoWorldParameters extends ClientOptions { // KeycloakClientId: string; // KeycloakGrantType: string; // KeycloakTestPassword: string; - StorageManagerUsername: string; - StorageAccountOwnerUsername: string; - DataConsumerUsername: string; - DataAccessorUsername: string; - ServiceUsersCredentials: string; + // StorageManagerUsername: string; + // StorageAccountOwnerUsername: string; + // DataConsumerUsername: string; + // DataAccessorUsername: string; + // ServiceUsersCredentials: string; // AzureAccountName: string; // AzureAccountKey: string; // AzureArchiveContainer: string; // AzureArchiveContainer2: string; - AzureArchiveAccessTier: string; - AzureArchiveManifestTier: string; + // AzureArchiveAccessTier: string; + // AzureArchiveManifestTier: string; // AzureArchiveQueue: string; // TimeProgressionFactor: number; // KafkaDeadLetterQueueTopic: string; @@ -268,19 +268,19 @@ export default class Zenko extends World { await this.prepareIamUser(); break; case EntityType.STORAGE_MANAGER: - await this.prepareARWWI(this.parameters.StorageManagerUsername || 'storage_manager', + await this.prepareARWWI(process.env.STORAGE_MANAGER_USER_NAME, 'storage-manager-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.STORAGE_ACCOUNT_OWNER: - await this.prepareARWWI(this.parameters.StorageAccountOwnerUsername || 'storage_account_owner', + await this.prepareARWWI(process.env.STORAGE_ACCOUNT_OWNER_USER_NAME, 'storage-account-owner-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.DATA_CONSUMER: - await this.prepareARWWI(this.parameters.DataConsumerUsername || 'data_consumer', + await this.prepareARWWI(process.env.DATA_CONSUMER_USER_NAME, 'data-consumer-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.DATA_ACCESSOR: - await this.prepareARWWI(this.parameters.DataAccessorUsername || 'data_accessor', + await this.prepareARWWI(process.env.DATA_ACCESSOR_USER_NAME, 'data-accessor-role', process.env.KEYCLOAK_TEST_PASSWORD); break; case EntityType.ASSUME_ROLE_USER: From fc0b18a3c0e42936ef93cbfa201190e66c7bdf83 Mon Sep 17 00:00:00 2001 From: sylvain senechal Date: Mon, 23 Feb 2026 23:35:38 +0100 Subject: [PATCH 9/9] move e2e vars --- .github/scripts/end2end/load-config.sh | 4 +- .github/scripts/end2end/run-e2e-ctst.sh | 1 + .github/scripts/end2end/run-e2e-test.sh | 108 ------------------ .../backbeat/tests/retry/pendingMetrics.js | 2 +- .../node_tests/backbeat/tests/retry/retry.js | 2 +- 5 files changed, 5 insertions(+), 112 deletions(-) diff --git a/.github/scripts/end2end/load-config.sh b/.github/scripts/end2end/load-config.sh index 328834fbc6..fb10319ef5 100755 --- a/.github/scripts/end2end/load-config.sh +++ b/.github/scripts/end2end/load-config.sh @@ -116,7 +116,7 @@ load_ctst() { ENV_VARS+=("KAFKA_GC_REQUEST_TOPIC=$(echo "${sorbet_config}" | jq -r '."kafka-gc-request-topic"')") # From k8s: Zenko resource values - ENV_VARS+=("TIME_PROGRESSION_FACTOR=$(kubectl get zenko end2end -o jsonpath='{.metadata.annotations.zenko\.io/time-progression-factor}')") + # ENV_VARS+=("TIME_PROGRESSION_FACTOR=$(kubectl get zenko end2end -o jsonpath='{.metadata.annotations.zenko\.io/time-progression-factor}')") ENV_VARS+=("ZENKO_INSTANCE_ID=$(kubectl get zenko end2end -o jsonpath='{.status.instanceID}')") ENV_VARS+=("KAFKA_CLEANER_INTERVAL=$(kubectl get zenko end2end -o jsonpath='{.spec.kafkaCleaner.interval}')") ENV_VARS+=("SORBETD_RESTORE_TIMEOUT=$(kubectl get zenko end2end -o jsonpath='{.spec.sorbet.server.azure.restoreTimeout}')") @@ -174,7 +174,7 @@ load_e2e() { ENV_VARS+=("AWS_ACCESS_KEY=$(get_env_var AWS_ACCESS_KEY)") ENV_VARS+=("AWS_SECRET_KEY=$(get_env_var AWS_SECRET_KEY)") ENV_VARS+=("VERIFY_CERTIFICATES=$(get_env_var VERIFY_CERTIFICATES)") - ENV_VARS+=("ENABLE_RING_TESTS=$(get_env_var ENABLE_RING_TESTS)") + # ENV_VARS+=("ENABLE_RING_TESTS=$(get_env_var ENABLE_RING_TESTS)") ENV_VARS+=("RING_S3C_ACCESS_KEY=$(get_env_var RING_S3C_ACCESS_KEY)") ENV_VARS+=("RING_S3C_SECRET_KEY=$(get_env_var RING_S3C_SECRET_KEY)") ENV_VARS+=("RING_S3C_ENDPOINT=$(get_env_var RING_S3C_ENDPOINT)") diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh index 0d7d1e1c6f..f09650e1d8 100755 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ b/.github/scripts/end2end/run-e2e-ctst.sh @@ -67,6 +67,7 @@ kubectl run $POD_NAME \ --image-pull-policy=IfNotPresent \ $(env_for_kubectl_run) \ --env=TARGET_VERSION=$VERSION \ + --env=TIME_PROGRESSION_FACTOR=$TIME_PROGRESSION_FACTOR \ --env=VERBOSE=1 \ --env=SDK=true \ --override-type strategic \ diff --git a/.github/scripts/end2end/run-e2e-test.sh b/.github/scripts/end2end/run-e2e-test.sh index c23f68e0cf..b60476287a 100755 --- a/.github/scripts/end2end/run-e2e-test.sh +++ b/.github/scripts/end2end/run-e2e-test.sh @@ -19,46 +19,6 @@ BACKBEAT_BUCKET_CHECK_TIMEOUT_S=${BACKBEAT_BUCKET_CHECK_TIMEOUT_S:-10} POD_NAME="${ZENKO_NAME}-${STAGE//_/-}-test" TOKEN=$(get_token) -CLOUDSERVER_SECRET="$(kubectl get secret -l app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end \ - -o jsonpath="{.items[0].data.config\.json}" | base64 -di)" - -# set environment vars -MONGO_DATABASE=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.database') -MONGO_READ_PREFERENCE=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.readPreference') -MONGO_REPLICA_SET_HOSTS=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.replicaSetHosts') -MONGO_SHARD_COLLECTION=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.shardCollections') -MONGO_WRITE_CONCERN=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.writeConcern') -MONGO_AUTH_USERNAME=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.authCredentials.username') -MONGO_AUTH_PASSWORD=$(echo "${CLOUDSERVER_SECRET}" | jq -r '.mongodb.authCredentials.password') -CLOUDSERVER_HOST="${ZENKO_NAME}-connector-s3api.default.svc.cluster.local" -CLOUDSERVER_ENDPOINT="http://${CLOUDSERVER_HOST}:80" -BACKBEAT_API_ENDPOINT="http://${ZENKO_NAME}-management-backbeat-api.default.svc.cluster.local:80" -VAULT_ENDPOINT="http://${ZENKO_NAME}-management-vault-iam-admin-api:80" -VAULT_STS_ENDPOINT="http://${ZENKO_NAME}-connector-vault-sts-api:80" -ADMIN_ACCESS_KEY_ID=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.accessKey}' | base64 -d) -ADMIN_SECRET_ACCESS_KEY=$(kubectl get secret end2end-management-vault-admin-creds.v1 -o jsonpath='{.data.secretKey}' | base64 -d) -ZENKO_ACCESS_KEY=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.AccessKeyId}' | base64 -d) -ZENKO_SECRET_KEY=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.SecretAccessKey}' | base64 -d) -ZENKO_SESSION_TOKEN=$(kubectl get secret end2end-account-zenko -o jsonpath='{.data.SessionToken}' | base64 -d) -SOURCE_ACCESS_KEY=$(kubectl get secret "end2end-account-${CRR_SOURCE_ACCOUNT_NAME}" -o jsonpath='{.data.AccessKeyId}' | base64 -d) -SOURCE_SECRET_KEY=$(kubectl get secret "end2end-account-${CRR_SOURCE_ACCOUNT_NAME}" -o jsonpath='{.data.SecretAccessKey}' | base64 -d) -SOURCE_SESSION_TOKEN=$(kubectl get secret "end2end-account-${CRR_SOURCE_ACCOUNT_NAME}" -o jsonpath='{.data.SessionToken}' | base64 -d) -SOURCE_ACCOUNT_ID=$(kubectl get secret "end2end-account-${CRR_SOURCE_ACCOUNT_NAME}" -o jsonpath='{.data.AccountId}' | base64 -d) -CRR_SOURCE_INFO="{\"AccessKeyId\":\"${SOURCE_ACCESS_KEY}\",\"SecretAccessKey\":\"${SOURCE_SECRET_KEY}\",\"SessionToken\":\"${SOURCE_SESSION_TOKEN}\",\"AccountId\":\"${SOURCE_ACCOUNT_ID}\"}" -DESTINATION_ACCESS_KEY=$(kubectl get secret "end2end-account-${CRR_DESTINATION_ACCOUNT_NAME}" -o jsonpath='{.data.AccessKeyId}' | base64 -d) -DESTINATION_SECRET_KEY=$(kubectl get secret "end2end-account-${CRR_DESTINATION_ACCOUNT_NAME}" -o jsonpath='{.data.SecretAccessKey}' | base64 -d) -DESTINATION_SESSION_TOKEN=$(kubectl get secret "end2end-account-${CRR_DESTINATION_ACCOUNT_NAME}" -o jsonpath='{.data.SessionToken}' | base64 -d) -DESTINATION_ACCOUNT_ID=$(kubectl get secret "end2end-account-${CRR_DESTINATION_ACCOUNT_NAME}" -o jsonpath='{.data.AccountId}' | base64 -d) -CRR_DESTINATION_INFO="{\"AccessKeyId\":\"${DESTINATION_ACCESS_KEY}\",\"SecretAccessKey\":\"${DESTINATION_SECRET_KEY}\",\"SessionToken\":\"${DESTINATION_SESSION_TOKEN}\",\"AccountId\":\"${DESTINATION_ACCOUNT_ID}\"}" -OIDC_FULLNAME="${OIDC_FIRST_NAME} ${OIDC_LAST_NAME}" -# NOTE: KEYCLOAK_TEST_USER is already set with -norights suffix by load-config.sh -# KEYCLOAK_TEST_HOST=${OIDC_ENDPOINT} -# KEYCLOAK_TEST_PORT="80" -# KEYCLOAK_TEST_REALM_NAME=${OIDC_REALM} -# KEYCLOAK_TEST_CLIENT_ID=${OIDC_CLIENT_ID} -# KEYCLOAK_TEST_GRANT_TYPE="password" -MOCHA_FILE=${MOCHA_FILE:-} - run_e2e_test() { kubectl run ${1} ${POD_NAME} \ --pod-running-timeout=5m \ @@ -69,78 +29,10 @@ run_e2e_test() { --namespace=${NAMESPACE} \ --image-pull-policy=Always \ $(env_for_kubectl_run) \ - --env=CLOUDSERVER_HOST=${CLOUDSERVER_HOST} \ - --env=CLOUDSERVER_ENDPOINT=${CLOUDSERVER_ENDPOINT} \ - --env=ZENKO_ACCESS_KEY=${ZENKO_ACCESS_KEY} \ - --env=ZENKO_SECRET_KEY=${ZENKO_SECRET_KEY} \ - --env=ZENKO_SESSION_TOKEN=${ZENKO_SESSION_TOKEN} \ - --env=ADMIN_ACCESS_KEY_ID=${ADMIN_ACCESS_KEY_ID} \ - --env=ADMIN_SECRET_ACCESS_KEY=${ADMIN_SECRET_ACCESS_KEY} \ - --env=VAULT_ENDPOINT=${VAULT_ENDPOINT} \ - --env=VAULT_STS_ENDPOINT=${VAULT_STS_ENDPOINT} \ --env=TOKEN=${TOKEN} \ --env=STAGE=${STAGE} \ - --env=CYPRESS_KEYCLOAK_USER_FULLNAME="${OIDC_FULLNAME}" \ - --env=CYPRESS_KEYCLOAK_USERNAME=${KEYCLOAK_TEST_USER} \ - --env=CYPRESS_KEYCLOAK_PASSWORD=${KEYCLOAK_TEST_PASSWORD} \ - --env=CYPRESS_KEYCLOAK_ROOT=${KEYCLOAK_TEST_ENDPOINT} \ - --env=CYPRESS_KEYCLOAK_CLIENT_ID=${KEYCLOAK_TEST_CLIENT_ID} \ - --env=CYPRESS_KEYCLOAK_REALM=${KEYCLOAK_TEST_REALM_NAME} \ - --env=AWS_BACKEND_SOURCE_LOCATION=${AWS_BACKEND_SOURCE_LOCATION} \ - --env=AWS_BACKEND_DESTINATION_LOCATION=${AWS_BACKEND_DESTINATION_LOCATION} \ - --env=AWS_S3_FAIL_BACKEND_DESTINATION_LOCATION=${AWS_BACKEND_DESTINATION_FAIL_LOCATION} \ - --env=GCP_BACKEND_DESTINATION_LOCATION=${GCP_BACKEND_DESTINATION_LOCATION:-} \ - --env=AZURE_BACKEND_DESTINATION_LOCATION=${AZURE_BACKEND_DESTINATION_LOCATION} \ - --env=COLD_BACKEND_DESTINATION_LOCATION=${COLD_BACKEND_DESTINATION_LOCATION} \ - --env=AZURE_ARCHIVE_BACKEND_DESTINATION_LOCATION=${AZURE_ARCHIVE_BACKEND_DESTINATION_LOCATION} \ - --env=MIRIA_BACKEND_DESTINATION_LOCATION=${MIRIA_BACKEND_DESTINATION_LOCATION} \ - --env=LOCATION_QUOTA_BACKEND=${LOCATION_QUOTA_BACKEND} \ - --env=AWS_BUCKET_NAME=${AWS_BUCKET_NAME} \ - --env=AWS_CRR_BUCKET_NAME=${AWS_CRR_BUCKET_NAME} \ - --env=AWS_S3_FAIL_BACKBEAT_BUCKET_NAME=${AWS_FAIL_BUCKET_NAME} \ - --env=AZURE_CRR_BUCKET_NAME=${AZURE_CRR_BUCKET_NAME} \ - --env=AZURE_ARCHIVE_BUCKET_NAME=${AZURE_ARCHIVE_BUCKET_NAME} \ - --env=GCP_CRR_BUCKET_NAME=${GCP_CRR_BUCKET_NAME} \ - --env=GCP_CRR_MPU_BUCKET_NAME=${GCP_CRR_MPU_BUCKET_NAME} \ - --env=GCP_ACCESS_KEY=${GCP_ACCESS_KEY} \ - --env=GCP_SECRET_KEY=${GCP_SECRET_KEY} \ - --env=GCP_BACKEND_SERVICE_KEY="${GCP_BACKEND_SERVICE_KEY}" \ - --env=GCP_BACKEND_SERVICE_EMAIL=${GCP_BACKEND_SERVICE_EMAIL} \ - --env=AZURE_ACCOUNT_NAME=${AZURE_ACCOUNT_NAME} \ - --env=AZURE_BACKEND_ENDPOINT=${AZURE_BACKEND_ENDPOINT} \ - --env=AZURE_SECRET_KEY=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== \ - --env=AWS_ENDPOINT=${AWS_ENDPOINT} \ - --env=AWS_ACCESS_KEY=accessKey1 \ - --env=AWS_SECRET_KEY=verySecretKey1 \ - --env=VERIFY_CERTIFICATES=false \ --env=ENABLE_RING_TESTS=${ENABLE_RING_TESTS} \ - --env=RING_S3C_ACCESS_KEY=${RING_S3C_ACCESS_KEY} \ - --env=RING_S3C_SECRET_KEY=${RING_S3C_SECRET_KEY} \ - --env=RING_S3C_ENDPOINT=${RING_S3C_ENDPOINT} \ - --env=RING_S3C_BACKEND_SOURCE_LOCATION=${RING_S3C_BACKEND_SOURCE_LOCATION} \ - --env=RING_S3C_INGESTION_SRC_BUCKET_NAME=${RING_S3C_INGESTION_SRC_BUCKET_NAME} \ - --env=RING_S3C_BACKEND_SOURCE_NON_VERSIONED_LOCATION=${RING_S3C_BACKEND_SOURCE_NON_VERSIONED_LOCATION} \ - --env=RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME=${RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME} \ - --env=RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE=${RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE} \ --env=KEYCLOAK_TEST_USER=${KEYCLOAK_TEST_USER} \ - --env=KEYCLOAK_TEST_PASSWORD=${KEYCLOAK_TEST_PASSWORD} \ - --env=KEYCLOAK_TEST_HOST=${KEYCLOAK_TEST_HOST} \ - --env=KEYCLOAK_TEST_REALM_NAME=${KEYCLOAK_TEST_REALM_NAME} \ - --env=KEYCLOAK_TEST_CLIENT_ID=${KEYCLOAK_TEST_CLIENT_ID} \ - --env=BACKBEAT_BUCKET_CHECK_TIMEOUT_S=${BACKBEAT_BUCKET_CHECK_TIMEOUT_S} \ - --env=MONGO_DATABASE=${MONGO_DATABASE} \ - --env=MONGO_READ_PREFERENCE=${MONGO_READ_PREFERENCE} \ - --env=MONGO_REPLICA_SET_HOSTS=${MONGO_REPLICA_SET_HOSTS} \ - --env=MONGO_SHARD_COLLECTION=${MONGO_SHARD_COLLECTION} \ - --env=MONGO_WRITE_CONCERN=${MONGO_WRITE_CONCERN} \ - --env=MONGO_AUTH_USERNAME=${MONGO_AUTH_USERNAME} \ - --env=MONGO_AUTH_PASSWORD=${MONGO_AUTH_PASSWORD} \ - --env=CRR_SOURCE_LOCATION_NAME=${CRR_SOURCE_LOCATION_NAME} \ - --env=CRR_SOURCE_INFO=${CRR_SOURCE_INFO} \ - --env=CRR_DESTINATION_LOCATION_NAME=${CRR_DESTINATION_LOCATION_NAME} \ - --env=CRR_DESTINATION_INFO=${CRR_DESTINATION_INFO} \ - --env=CRR_ROLE_NAME=${CRR_ROLE_NAME} \ - --env=MOCHA_FILE=${MOCHA_FILE} \ --override-type strategic \ --overrides=' { diff --git a/tests/zenko_tests/node_tests/backbeat/tests/retry/pendingMetrics.js b/tests/zenko_tests/node_tests/backbeat/tests/retry/pendingMetrics.js index 14295d9738..4822bc4d63 100644 --- a/tests/zenko_tests/node_tests/backbeat/tests/retry/pendingMetrics.js +++ b/tests/zenko_tests/node_tests/backbeat/tests/retry/pendingMetrics.js @@ -15,7 +15,7 @@ const awsUtils = new ReplicationUtility(awsS3Client); const srcBucket = `source-bucket-${Date.now()}`; const awsDestBucket = process.env.AWS_CRR_BUCKET_NAME; const destAWSLocation = process.env.AWS_BACKEND_DESTINATION_LOCATION; -const destFailBucket = process.env.AWS_S3_FAIL_BACKBEAT_BUCKET_NAME; +const destFailBucket = process.env.AWS_FAIL_BUCKET_NAME; const destFailLocation = process.env.AWS_S3_FAIL_BACKEND_DESTINATION_LOCATION; const hex = crypto.createHash('md5') .update(Math.random().toString()) diff --git a/tests/zenko_tests/node_tests/backbeat/tests/retry/retry.js b/tests/zenko_tests/node_tests/backbeat/tests/retry/retry.js index d27c434847..65e96082d4 100644 --- a/tests/zenko_tests/node_tests/backbeat/tests/retry/retry.js +++ b/tests/zenko_tests/node_tests/backbeat/tests/retry/retry.js @@ -11,7 +11,7 @@ const { makeGETRequest, makeUpdateRequest, getResponseBody } = require('../../.. const scalityUtils = new ReplicationUtility(scalityS3Client); const awsUtils = new ReplicationUtility(awsS3Client); const srcBucket = `source-bucket-${Date.now()}`; -const destFailBucket = process.env.AWS_S3_FAIL_BACKBEAT_BUCKET_NAME; +const destFailBucket = process.env.AWS_FAIL_BUCKET_NAME; const destFailLocation = process.env.AWS_S3_FAIL_BACKEND_DESTINATION_LOCATION; const hex = crypto.createHash('md5')