diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 871a4fad22..2a4c498765 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -3,11 +3,11 @@ ## Running CTST tests in the codespace -To run the CTST tests in the codespace, simply head to `.github/script/end2end/` and run `run-e2e-ctst.sh` script. +To run the CTST tests in the codespace, simply head to `tests/@setup/` and run the `run-tests.sh` script. ```bash - cd .github/scripts/end2end/ - bash run-e2e-ctst.sh + cd tests/@setup/ + ./run-tests.sh ~/.kube/config ctst ``` ## Accessing s3 service diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh index 3421b3f37c..c8023e2a2d 100755 --- a/.devcontainer/setup.sh +++ b/.devcontainer/setup.sh @@ -53,7 +53,7 @@ done ( cd .github/scripts/end2end - bash configure-e2e-ctst.sh + bash configure-hosts.sh ) docker image prune -af diff --git a/.github/actions/build-setup-image/action.yaml b/.github/actions/build-setup-image/action.yaml new file mode 100644 index 0000000000..3bd7532dbe --- /dev/null +++ b/.github/actions/build-setup-image/action.yaml @@ -0,0 +1,66 @@ +name: Build Setup Image +description: Build the Zenko setup Docker image for use in Kubernetes Jobs + +inputs: + registry: + description: 'Container registry to push to' + required: false + default: 'ghcr.io' + image-name: + description: 'Image name' + required: false + default: 'zenko-setup' + tag: + description: 'Image tag' + required: false + default: 'latest' + push: + description: 'Push image to registry' + required: false + default: 'true' + +outputs: + image: + description: 'Full image name with tag' + value: ${{ inputs.registry }}/${{ github.repository_owner }}/${{ inputs.image-name }}:${{ inputs.tag }} + digest: + description: 'Image digest' + value: ${{ steps.build.outputs.digest }} + +runs: + using: composite + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Container Registry + if: ${{ inputs.push == 'true' }} + uses: docker/login-action@v3 + with: + registry: ${{ inputs.registry }} + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.registry }}/${{ github.repository_owner }}/${{ inputs.image-name }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=sha,prefix={{branch}}- + type=raw,value=${{ inputs.tag }} + + - name: Build and push + id: build + uses: docker/build-push-action@v5 + with: + context: tests/@setup + file: tests/@setup/Dockerfile + push: ${{ inputs.push }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64 \ No newline at end of file diff --git a/.github/actions/deploy/action.yaml b/.github/actions/deploy/action.yaml index a3b013d212..6db94c9717 100644 --- a/.github/actions/deploy/action.yaml +++ b/.github/actions/deploy/action.yaml @@ -7,10 +7,6 @@ inputs: description: "The tag of the Zenko Operator image to use" required: false default: "" - deploy_metadata: - description: "Deploy a metadata cluster alongside Zenko" - required: false - default: "false" runs: using: composite steps: @@ -62,14 +58,6 @@ runs: shell: bash run: bash deploy-zenko.sh end2end default working-directory: ./.github/scripts/end2end - - name: Add Keycloak user and assign StorageManager role - shell: bash - run: bash keycloak-helper.sh set-user-instance-ids default - working-directory: ./.github/scripts/end2end - - name: Start external service mocks - shell: bash - run: bash install-mocks.sh "default" - working-directory: ./.github/scripts/end2end - name: Start mock sorbet service shell: bash run: sh tests/smoke/deploy-sorbet-resources.sh end2end @@ -84,14 +72,9 @@ runs: env: SORBETD_NAME: mock-miria working-directory: ./.github/scripts/end2end/operator - - name: Deploy metadata - shell: bash - run: ./deploy-metadata.sh - working-directory: ./.github/scripts/end2end - if: ${{ inputs.deploy_metadata == 'true' }} - - name: End-to-end configuration + - name: Configure DNS for CTST shell: bash - run: bash configure-e2e.sh "end2end" ${E2E_IMAGE_NAME}:${E2E_IMAGE_TAG} "default" + run: bash configure-hosts.sh working-directory: ./.github/scripts/end2end - name: Linting shell: bash diff --git a/.github/scripts/end2end/configure-e2e-ctst.sh b/.github/scripts/end2end/configure-e2e-ctst.sh deleted file mode 100755 index e1439867ee..0000000000 --- a/.github/scripts/end2end/configure-e2e-ctst.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -set -exu - -# Setup test environment variables -export ZENKO_NAME=${1:-"end2end"} -# Getting kafka host from backbeat'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} -# Removing the port -export NOTIF_KAFKA_HOST=${KAFKA_HOST_PORT%:*} -export NOTIF_KAFKA_PORT=${KAFKA_HOST_PORT#*:} - -UUID=$(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 .extensions.replication.topic) -UUID=${UUID%.*} -UUID=${UUID:1} - -echo "127.0.0.1 iam.zenko.local ui.zenko.local s3-local-file.zenko.local keycloak.zenko.local \ - sts.zenko.local management.zenko.local s3.zenko.local website.mywebsite.com utilization.zenko.local" | sudo tee -a /etc/hosts - -# Add bucket notification target -envsubst < ./configs/notification_destinations.yaml | kubectl apply -f - -# Wait for service stabilization -kubectl wait --for condition=DeploymentInProgress=true --timeout 10m zenko/${ZENKO_NAME} -kubectl wait --for condition=DeploymentFailure=false --timeout 10m zenko/${ZENKO_NAME} -kubectl wait --for condition=DeploymentInProgress=false --timeout 10m zenko/${ZENKO_NAME} - -# Get kafka image name and tag -KAFKA_REGISTRY_NAME=$(yq eval ".kafka.sourceRegistry" ../../../solution/deps.yaml) -KAFKA_IMAGE_NAME=$(yq eval ".kafka.image" ../../../solution/deps.yaml) -KAFKA_IMAGE_TAG=$(yq eval ".kafka.tag" ../../../solution/deps.yaml) -KAFKA_IMAGE=$KAFKA_REGISTRY_NAME/$KAFKA_IMAGE_NAME:$KAFKA_IMAGE_TAG - -# Cold location topic -AZURE_ARCHIVE_STATUS_TOPIC="${UUID}.cold-status-e2e-azure-archive" -AZURE_ARCHIVE_STATUS_TOPIC_2_NV="${UUID}.cold-status-e2e-azure-archive-2-non-versioned" -AZURE_ARCHIVE_STATUS_TOPIC_2_V="${UUID}.cold-status-e2e-azure-archive-2-versioned" -AZURE_ARCHIVE_STATUS_TOPIC_2_S="${UUID}.cold-status-e2e-azure-archive-2-suspended" - -# Creating bucket notification topic in kafka -kubectl run kafka-topics \ - --image=$KAFKA_IMAGE \ - --pod-running-timeout=5m \ - --rm \ - --restart=Never \ - --attach=True \ - --command -- bash -c \ - "kafka-topics.sh --create --topic $NOTIF_DEST_TOPIC --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ - kafka-topics.sh --create --topic $NOTIF_ALT_DEST_TOPIC --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ - kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ - kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC_2_NV --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ - kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC_2_V --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ - kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC_2_S --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists" diff --git a/.github/scripts/end2end/configure-e2e.sh b/.github/scripts/end2end/configure-e2e.sh deleted file mode 100755 index 7a41195494..0000000000 --- a/.github/scripts/end2end/configure-e2e.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/sh - -set -exu - -. "$(dirname $0)/common.sh" - -ZENKO_NAME=${1:-end2end} -E2E_IMAGE=${2:-ghcr.io/scality/zenko/zenko-e2e:latest} -NAMESPACE=${3:-default} - -SERVICE_ACCOUNT="${ZENKO_NAME}-config" -POD_NAME="${ZENKO_NAME}-config" -MANAGEMENT_ENDPOINT="http://${ZENKO_NAME}-management-orbit-api:5001" -VAULT_ENDPOINT="http://${ZENKO_NAME}-connector-vault-sts-api" -UUID=$(kubectl get zenko ${ZENKO_NAME} --namespace ${NAMESPACE} -o jsonpath='{.status.instanceID}') -TOKEN=$(get_token) - -cat <> $GITHUB_ENV -echo "OIDC_ENDPOINT=https://keycloak.zenko.local" >> $GITHUB_ENV -echo "NAVBAR_ENDPOINT=https://shell-ui.zenko.local" >> $GITHUB_ENV -echo "OIDC_HOST=keycloak.zenko.local" >> $GITHUB_ENV -echo "ENABLE_KEYCLOAK_HTTPS=true" >> $GITHUB_ENV - -# Set the HTTPS ingress options for Keycloak -KEYCLOAK_INGRESS_OPTIONS="$DIR/configs/keycloak_ingress_https.yaml" -KEYCLOAK_OPTIONS="$DIR/configs/keycloak_options.yaml" -helm upgrade --install keycloak codecentric/keycloak -f "${KEYCLOAK_OPTIONS}" -f "${KEYCLOAK_INGRESS_OPTIONS}" --version ${KEYCLOAK_VERSION} -kubectl rollout status sts/keycloak --timeout=5m - -echo "HTTPS successfully enabled for Zenko deployment" diff --git a/.github/scripts/end2end/install-kind-dependencies.sh b/.github/scripts/end2end/install-kind-dependencies.sh index 1d3df78e6c..17f43d6d20 100755 --- a/.github/scripts/end2end/install-kind-dependencies.sh +++ b/.github/scripts/end2end/install-kind-dependencies.sh @@ -124,6 +124,9 @@ prom_url=https://raw.githubusercontent.com/coreos/prometheus-operator/${PROMETHE kubectl create -f $prom_url || kubectl replace -f $prom_url --wait # wait for the resource to exist kubectl wait --for=condition=established --timeout=10m crd/alertmanagers.monitoring.coreos.com + +# Set PROMETHEUS_NAME for envsubst +export PROMETHEUS_NAME="prometheus-test" envsubst < configs/prometheus.yaml | kubectl apply -f - # zookeeper diff --git a/.github/scripts/end2end/install-mocks.sh b/.github/scripts/end2end/install-mocks.sh deleted file mode 100644 index 12321cc14f..0000000000 --- a/.github/scripts/end2end/install-mocks.sh +++ /dev/null @@ -1,25 +0,0 @@ -#! /bin/sh - -set -exu - -NAMESPACE=${1:-default} - -kubectl create \ - configmap aws-mock \ - --from-file=../mocks/aws/mock-metadata.tar.gz \ - --namespace ${NAMESPACE} - -kubectl create \ - -f ../mocks/azure-mock.yaml \ - -f ../mocks/aws-mock.yaml \ - --namespace ${NAMESPACE} && \ - -kubectl wait \ - --for=condition=Ready \ - --timeout=10m \ - pod -l component=mock \ - --namespace ${NAMESPACE} - -kubectl get \ - pod -l component=mock \ - --namespace ${NAMESPACE} diff --git a/.github/scripts/end2end/keycloak-helper.sh b/.github/scripts/end2end/keycloak-helper.sh deleted file mode 100755 index ec0cde2f9f..0000000000 --- a/.github/scripts/end2end/keycloak-helper.sh +++ /dev/null @@ -1,67 +0,0 @@ -#! /bin/sh - -set -exu - -DIR=$(dirname "$0") - -COMMAND=${1:-''} -NAMESPACE=${2:-default} -ZENKO_NAME=${3:-end2end} - -KEYCLOAK_EXEC="kubectl -n ${NAMESPACE} exec -i keycloak-0 --" - -refresh_creds() { - ${KEYCLOAK_EXEC} \ - /opt/jboss/keycloak/bin/kcadm.sh config credentials \ - --server http://localhost:8080/auth \ - --realm master \ - --user admin \ - --password password -} - -case $COMMAND in - "setup-realm") - refresh_creds - envsubst < $DIR/configs/keycloak_config.json | \ - ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh create realms -f - - ;; - - "add-user") - refresh_creds - - export INSTANCE_ID=`kubectl -n ${NAMESPACE} get zenko ${ZENKO_NAME} -o jsonpath='{.status.instanceID}'` - - 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 set-password \ - -r ${OIDC_REALM} \ - --username ${OIDC_USERNAME} \ - --new-password ${OIDC_PASSWORD} - - # attach StorageManager role to user - ${KEYCLOAK_EXEC} /opt/jboss/keycloak/bin/kcadm.sh add-roles \ - -r ${OIDC_REALM} \ - --uusername ${OIDC_USERNAME} \ - --rolename "StorageManager" - ;; - - "set-user-instance-ids") - refresh_creds - - 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') - # 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"}' - - - ;; - *) - echo "Invalid action. Available actions are [setup, add-user]" - exit 1 - ;; -esac diff --git a/.github/scripts/end2end/run-e2e-ctst.sh b/.github/scripts/end2end/run-e2e-ctst.sh deleted file mode 100755 index 195f3241c0..0000000000 --- a/.github/scripts/end2end/run-e2e-ctst.sh +++ /dev/null @@ -1,206 +0,0 @@ -#!/bin/bash -set -exu - -ZENKO_NAME=${1:-end2end} -COMMAND=${2:-"premerge"} -PARALLEL_RUNS=${PARALLEL_RUNS:-$(( ( $(nproc) + 1 ) / 2 ))} -RETRIES=${4:-3} - -shift 4 - -JUNIT_REPORT_PATH=${JUNIT_REPORT_PATH:-"ctst-junit.xml"} - -# 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) -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" -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) - -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 \ - -o jsonpath='{.items[0].data.config\.json}' | base64 -di | jq .kafka.hosts) -KAFKA_HOST_PORT=${KAFKA_HOST_PORT:1:-1} - -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}') - -# 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 .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) - -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}') - -# 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 < 'e2e-config.yaml' - cat e2e-config.yaml - echo 'Generated e2e-config.yaml file' - name: Build and push CI image uses: docker/build-push-action@v5 with: @@ -393,12 +423,12 @@ jobs: GIT_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: yarn cache-dependency-path: tests/ctst/yarn.lock - name: Install ctst test dependencies working-directory: tests/ctst - run: yarn install + run: yarn install --network-concurrency=1 - name: Lint ctst tests working-directory: tests/ctst run: yarn lint @@ -421,6 +451,9 @@ jobs: SORBET_TAG=$(yq eval '.sorbet.tag' deps.yaml) DRCTL_TAG=$(yq eval .drctl.tag deps.yaml) EOF + - name: Prepare build context + run: cp .github/scripts/mocks/aws/mock-metadata.tar.gz tests/ctst/mock-metadata.tar.gz + - name: Build and push CI image uses: docker/build-push-action@v5 with: @@ -430,12 +463,13 @@ jobs: CTST_TAG=${{ env.CTST_TAG }} SORBET_TAG=${{ env.SORBET_TAG }} DRCTL_TAG=${{ env.DRCTL_TAG}} + GIT_ACCESS_TOKEN=${{ steps.app-token.outputs.token }} tags: "${{ env.E2E_CTST_IMAGE_NAME }}:${{ env.E2E_IMAGE_TAG }}" cache-from: type=gha,scope=end2end-ctst cache-to: type=gha,mode=max,scope=end2end-ctst end2end-pra: - needs: [build-kafka, lint-and-build-ctst] + needs: [build-kafka, lint-and-build-ctst, build-setup-image] runs-on: ubuntu-24.04-16core steps: - name: Checkout @@ -471,24 +505,19 @@ jobs: env: ZENKO_MONGODB_DATABASE: pradb working-directory: ./.github/scripts/end2end - - name: Add Keycloak pra user and assign StorageManager role - shell: bash - run: bash keycloak-helper.sh add-user default end2end-pra + - name: Setup PRA test environment env: - OIDC_USERNAME: 'zenko-end2end-pra' - OIDC_EMAIL: 'e2e-pra@zenko.local' - working-directory: ./.github/scripts/end2end - - name: Configure E2E PRA test environment - run: bash configure-e2e.sh end2end-pra ${E2E_IMAGE_NAME}:${E2E_IMAGE_TAG} default - working-directory: ./.github/scripts/end2end - env: - OIDC_USERNAME: 'zenko-end2end-pra' - - name: Configure E2E CTST test environment - run: bash configure-e2e-ctst.sh + INSTANCE_ID: "end2end-pra" + SETUP_IMAGE: ${{ needs.build-setup-image.outputs.image }} + GIT_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} + run: ./setup-tests.sh --kubeconfig ~/.kube/config + working-directory: ./tests/@setup + - name: Configure hosts file + run: bash configure-hosts.sh working-directory: ./.github/scripts/end2end - name: Run CTST end to end tests - run: bash run-e2e-ctst.sh "" "" "" "" --tags @PRA - working-directory: ./.github/scripts/end2end + run: ./run-tests.sh --kubeconfig ~/.kube/config --type ctst -- --tags @PRA + working-directory: ./tests/@setup - name: Debug wait uses: ./.github/actions/debug-wait timeout-minutes: 60 @@ -504,7 +533,7 @@ jobs: run: kind delete cluster end2end-2-shards-http: - needs: [build-kafka, build-test-image] + needs: [build-kafka, build-test-image, build-setup-image] runs-on: - ubuntu-24.04-8core env: @@ -535,6 +564,12 @@ jobs: uses: ./.github/actions/deploy env: GIT_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} + - name: Setup test environment + env: + SETUP_IMAGE: ${{ needs.build-setup-image.outputs.image }} + GIT_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} + run: ./setup-tests.sh --kubeconfig ~/.kube/config + working-directory: ./tests/@setup - name: Run init CI test run: bash run-e2e-test.sh "end2end" ${E2E_IMAGE_NAME}:${E2E_IMAGE_TAG} "end2end" "default" working-directory: ./.github/scripts/end2end @@ -547,9 +582,6 @@ jobs: - name: Run smoke tests run: bash run-e2e-test.sh "end2end" ${E2E_IMAGE_NAME}:${E2E_IMAGE_TAG} "smoke" "default" working-directory: ./.github/scripts/end2end - - name: Enable HTTPS - run: bash enable-https.sh - working-directory: ./.github/scripts/end2end - name: Run smoke tests run: bash run-e2e-test.sh "end2end" ${E2E_IMAGE_NAME}:${E2E_IMAGE_TAG} "smoke" "default" working-directory: ./.github/scripts/end2end @@ -568,7 +600,7 @@ jobs: run: kind delete cluster end2end-sharded: - needs: [build-kafka, build-test-image] + needs: [build-kafka, build-test-image, build-setup-image] runs-on: - ubuntu-24.04-8core env: @@ -598,10 +630,17 @@ jobs: zenko-operator - name: Deploy Zenko uses: ./.github/actions/deploy + - name: Setup test environment env: + SETUP_IMAGE: ${{ needs.build-setup-image.outputs.image }} GIT_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} - with: - deploy_metadata: ${{ env.ENABLE_RING_TESTS }} + run: | + if [[ "${{ env.ENABLE_RING_TESTS }}" == "true" ]]; then + ./setup-tests.sh --kubeconfig ~/.kube/config -- setup --metadata + else + ./setup-tests.sh --kubeconfig ~/.kube/config -- setup --rbac --dns --buckets --locations --accounts --endpoints --workflows --tls + fi + working-directory: ./tests/@setup - name: Run backbeat end to end tests run: bash run-e2e-test.sh "end2end" ${E2E_IMAGE_NAME}:${E2E_IMAGE_TAG} "backbeat" "default" working-directory: ./.github/scripts/end2end @@ -620,7 +659,7 @@ jobs: run: kind delete cluster ctst-end2end-sharded: - needs: [build-kafka, lint-and-build-ctst] + needs: [build-kafka, lint-and-build-ctst, build-setup-image] runs-on: - ubuntu-24.04-8core steps: @@ -655,12 +694,18 @@ jobs: TIME_PROGRESSION_FACTOR: 86400 TRANSITION_ONE_DAY_EARLIER: false EXPIRE_ONE_DAY_EARLIER: false - - name: Configure E2E test environment - run: bash configure-e2e-ctst.sh + - name: Setup test environment + env: + SETUP_IMAGE: ${{ needs.build-setup-image.outputs.image }} + GIT_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }} + run: ./setup-tests.sh --kubeconfig ~/.kube/config + working-directory: ./tests/@setup + - name: Configure hosts file + run: bash configure-hosts.sh working-directory: ./.github/scripts/end2end - name: Run CTST end to end tests - run: bash run-e2e-ctst.sh "" "" "" "" --tags 'not @PRA' - working-directory: ./.github/scripts/end2end + run: ./run-tests.sh --kubeconfig ~/.kube/config --type ctst -- --tags 'not @PRA' + working-directory: ./tests/@setup - name: Debug wait uses: ./.github/actions/debug-wait timeout-minutes: 60 diff --git a/solution/deps.yaml b/solution/deps.yaml index d0a83f3192..64d4788588 100644 --- a/solution/deps.yaml +++ b/solution/deps.yaml @@ -113,7 +113,7 @@ sorbet: policy: sorbet/sorbet-policies dashboard: sorbet/sorbet-dashboards image: sorbet - tag: v1.2.0-preview.1 + tag: 931169543e23666c99a20e1c679e7661ec1c50eb envsubst: SORBET_TAG stern: # tail any pod logs with pattern matchin tag: 1.30.0 diff --git a/tests/@setup/.dockerignore b/tests/@setup/.dockerignore new file mode 100644 index 0000000000..e5d1c8cb13 --- /dev/null +++ b/tests/@setup/.dockerignore @@ -0,0 +1,14 @@ +node_modules +npm-debug.log +.git +.gitignore +README.md +.env +.nyc_output +coverage +.nyc_output +.vscode +.idea +dist +*.log +.DS_Store \ No newline at end of file diff --git a/tests/@setup/.gitignore b/tests/@setup/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/@setup/Dockerfile b/tests/@setup/Dockerfile new file mode 100644 index 0000000000..1554085313 --- /dev/null +++ b/tests/@setup/Dockerfile @@ -0,0 +1,50 @@ +FROM node:22-alpine + +# Install system dependencies +RUN apk add --no-cache \ + curl \ + git \ + bash \ + jq \ + openssl \ + ca-certificates + +# Install TypeScript globally +RUN yarn global add typescript@5.9.2 + +# Install kubectl +RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \ + chmod +x kubectl && \ + mv kubectl /usr/local/bin/ + +# Install helm +RUN curl -fsSL https://get.helm.sh/helm-v3.12.0-linux-amd64.tar.gz | tar -xzC /tmp && \ + mv /tmp/linux-amd64/helm /usr/local/bin/helm && \ + chmod +x /usr/local/bin/helm + +# Set working directory +WORKDIR /app + +# Copy package files +COPY package.json yarn.lock ./ + +# Install dependencies +RUN yarn install --prod --network-concurrency=1 + +# Copy source code +COPY . . + +# Build TypeScript +RUN yarn build + +# Create non-root user for security +RUN addgroup -g 1001 -S nodejs && \ + adduser -S nextjs -u 1001 + +# Set proper permissions +RUN chown -R nextjs:nodejs /app +USER nextjs + +# Default command +ENTRYPOINT ["node", "dist/cli.js"] +CMD ["--help"] \ No newline at end of file diff --git a/tests/@setup/README.md b/tests/@setup/README.md new file mode 100644 index 0000000000..c0aaa8021c --- /dev/null +++ b/tests/@setup/README.md @@ -0,0 +1,69 @@ +# Zenko Test Environment Setup + +Simple scripts to setup and run tests against any Zenko cluster using Kubernetes Jobs. + +## Quick Start + +### 1. Setup Test Environment +```bash +# Using default kubeconfig +./setup-tests.sh + +# Using specific kubeconfig +./setup-tests.sh /path/to/kubeconfig + +# With custom options +./setup-tests.sh ~/.kube/config --no-metadata --no-tls +``` + +### 2. Run Tests +```bash +# Run CTST tests +./run-tests.sh ctst + +# Run CTST with specific tags +./run-tests.sh ~/.kube/config ctst --tags @PRA +./run-tests.sh ~/.kube/config ctst --tags 'not @PRA' +``` + +## Environment Variables + +Set these before running the scripts to customize behavior: + +### Setup Configuration +```bash +export NAMESPACE="default" +export INSTANCE_ID="end2end" +export SUBDOMAIN="zenko.local" +export GIT_ACCESS_TOKEN="your-token" +export METADATA_NAMESPACE="metadata" +export SETUP_IMAGE="ghcr.io/scality/zenko-setup:latest" +export LOG_LEVEL="debug" +export JOB_TIMEOUT="1800" +``` + +### Test Configuration +```bash +# CTST and test images +export E2E_IMAGE="ghcr.io/scality/zenko/zenko-e2e:latest" +export E2E_CTST_IMAGE="ghcr.io/scality/zenko/zenko-e2e-ctst:latest" + +# Keycloak configuration +export OIDC_REALM="zenko" +export OIDC_USERNAME="storage_manager" +export OIDC_PASSWORD="123" +export OIDC_HOST="keycloak.zenko.local" + +# CTST specific configuration +export PARALLEL_RUNS="4" +export RETRIES="3" +export JUNIT_REPORT_PATH="ctst-junit.xml" + +# Azure storage configuration +export AZURE_ACCOUNT_NAME="devstoreaccount1" +export AZURE_SECRET_KEY="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" +``` + +## Requirements + +- `kubectl` configured to access your cluster diff --git a/tests/@setup/configs/accounts.json b/tests/@setup/configs/accounts.json new file mode 100644 index 0000000000..90db9111d5 --- /dev/null +++ b/tests/@setup/configs/accounts.json @@ -0,0 +1,24 @@ +{ + "accounts": [ + { + "name": "account-test-1", + "email": "account-test-1@zenko.local", + "description": "Primary test account for integration testing" + }, + { + "name": "account-test-2", + "email": "account-test-2@zenko.local", + "description": "Secondary test account for multi-account scenarios" + }, + { + "name": "replication-source", + "email": "replication-source@zenko.local", + "description": "Source account for replication workflows" + }, + { + "name": "replication-target", + "email": "replication-target@zenko.local", + "description": "Target account for replication workflows" + } + ] +} \ No newline at end of file diff --git a/tests/@setup/configs/buckets.json b/tests/@setup/configs/buckets.json new file mode 100644 index 0000000000..e37c9f6b42 --- /dev/null +++ b/tests/@setup/configs/buckets.json @@ -0,0 +1,122 @@ +{ + "aws": { + "buckets": [ + { + "name": "ci-zenko-aws-source-bucket", + "versioning": false, + "objects": [ + { "key": "test-object-1.txt", "body": "Test content 1" }, + { "key": "test-object-2.txt", "body": "Test content 2" }, + { "key": "folder/nested-object.txt", "body": "Nested content" } + ] + }, + { + "name": "ci-zenko-aws-target-bucket", + "versioning": false, + "objects": [] + }, + { + "name": "ci-zenko-aws-crr-target-bucket", + "versioning": false, + "objects": [] + }, + { + "name": "ci-zenko-aws-fail-target-bucket", + "versioning": false, + "objects": [] + }, + { + "name": "ci-zenko-aws-versioned-bucket", + "versioning": true, + "objects": [] + }, + { + "name": "ci-zenko-aws-lifecycle-bucket", + "versioning": false, + "objects": [] + }, + { + "name": "ci-zenko-aws-replication-bucket", + "versioning": true, + "objects": [] + }, + { + "name": "ci-zenko-aws-notification-bucket", + "versioning": false, + "objects": [] + } + ] + }, + "azure": { + "containers": [ + { + "name": "ci-zenko-azure-source-container", + "blobs": [ + { "name": "test-blob-1.txt", "content": "Azure test content 1" }, + { "name": "test-blob-2.txt", "content": "Azure test content 2" }, + { "name": "folder/nested-blob.txt", "content": "Azure nested content" } + ] + }, + { + "name": "ci-zenko-azure-target-container", + "blobs": [] + }, + { + "name": "ci-zenko-azure-archive-container", + "blobs": [] + }, + { + "name": "ci-zenko-azure-lifecycle-container", + "blobs": [] + }, + { + "name": "ci-zenko-azure-crr-target-bucket", + "blobs": [] + }, + { + "name": "ci-zenko-azure-archive-target-bucket", + "blobs": [] + } + ], + "queues": [ + { "name": "ci-zenko-azure-notifications-queue" }, + { "name": "ci-zenko-azure-status-queue" } + ] + }, + "ring": { + "buckets": [ + { + "name": "ci-zenko-ring-source-bucket", + "objects": [] + }, + { + "name": "ci-zenko-ring-target-bucket", + "objects": [] + }, + { + "name": "ci-zenko-ring-archive-bucket", + "objects": [] + }, + { + "name": "ingestion-test-src-bucket", + "objects": [] + }, + { + "name": "ingestion-test-src-non-versioned-bucket", + "objects": [] + }, + { + "name": "ci-zenko-quota-test-bucket", + "objects": [] + }, + { + "name": "ci-zenko-gcp-crr-target-bucket", + "objects": [] + }, + { + "name": "ci-zenko-gcp-crr-mpu-bucket", + "objects": [] + } + ] + } +} \ No newline at end of file diff --git a/tests/@setup/configs/dns.conf b/tests/@setup/configs/dns.conf new file mode 100644 index 0000000000..0355557df5 --- /dev/null +++ b/tests/@setup/configs/dns.conf @@ -0,0 +1,20 @@ +.:53 { + errors + health + ready + # Zenko test rewrite rules for {{subdomain}} + rewrite name regex (.+\.)?aws-mock\.{{subdomain}} cloudserver-mock.{{namespace}}.svc.cluster.local + rewrite name regex (.+\.)?azure-mock\.{{subdomain}} azurite-mock.{{namespace}}.svc.cluster.local + rewrite name regex iam\.{{subdomain}} zenko-iam.{{namespace}}.svc.cluster.local + rewrite name regex ui\.{{subdomain}} zenko-ui.{{namespace}}.svc.cluster.local + rewrite name regex s3\.{{subdomain}} zenko-s3.{{namespace}}.svc.cluster.local + rewrite name regex management\.{{subdomain}} zenko-management.{{namespace}}.svc.cluster.local + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + fallthrough in-addr.arpa ip6.arpa + } + prometheus :9153 + forward . /etc/resolv.conf + cache 30 + log +} diff --git a/tests/@setup/configs/endpoints.json b/tests/@setup/configs/endpoints.json new file mode 100644 index 0000000000..cc2d99b1af --- /dev/null +++ b/tests/@setup/configs/endpoints.json @@ -0,0 +1,19 @@ +{ + "endpoints": [ + { + "hostname": "s3.test-location-1.zenko.local", + "locationName": "aws-test-location", + "description": "S3 endpoint for AWS test location" + }, + { + "hostname": "s3.test-location-2.zenko.local", + "locationName": "azure-test-location", + "description": "S3 endpoint for Azure test location" + }, + { + "hostname": "s3.ring-test.zenko.local", + "locationName": "ring-test-location", + "description": "S3 endpoint for Ring test location" + } + ] +} \ No newline at end of file diff --git a/tests/@setup/configs/locations.json b/tests/@setup/configs/locations.json new file mode 100644 index 0000000000..cabf42cc22 --- /dev/null +++ b/tests/@setup/configs/locations.json @@ -0,0 +1,129 @@ +{ + "locations": [ + { + "name": "awsbackend", + "locationType": "location-s3-v1", + "details": { + "endpoint": "http://cloudserver-mock.{namespace}.svc.cluster.local:8000", + "bucketName": "ci-zenko-aws-target-bucket", + "accessKey": "accessKey1", + "secretKey": "verySecretKey1", + "bucketMatch": true, + "pathStyle": true + } + }, + { + "name": "awsbackendmismatch", + "locationType": "location-s3-v1", + "details": { + "endpoint": "http://cloudserver-mock.{namespace}.svc.cluster.local:8000", + "bucketName": "ci-zenko-aws-crr-target-bucket", + "accessKey": "accessKey1", + "secretKey": "verySecretKey1", + "bucketMatch": false, + "pathStyle": true + } + }, + { + "name": "awsbackendfail", + "locationType": "location-s3-v1", + "details": { + "endpoint": "http://cloudserver-mock.{namespace}.svc.cluster.local:8000", + "bucketName": "ci-zenko-aws-fail-target-bucket", + "accessKey": "accessKey1", + "secretKey": "verySecretKey1", + "bucketMatch": false, + "pathStyle": true + } + }, + { + "name": "azurebackendmismatch", + "locationType": "location-azure-v1", + "details": { + "endpoint": "http://azurite-mock.{namespace}.svc.cluster.local:10000/devstoreaccount1", + "containerName": "ci-zenko-azure-crr-target-bucket", + "accountName": "devstoreaccount1", + "accountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + } + }, + { + "name": "e2e-azure-archive", + "locationType": "location-azure-v1", + "details": { + "endpoint": "http://azurite-mock.{namespace}.svc.cluster.local:10000/devstoreaccount1", + "containerName": "ci-zenko-azure-archive-target-bucket", + "accountName": "devstoreaccount1", + "accountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + } + }, + { + "name": "gcpbackendmismatch", + "locationType": "location-gcp-v1", + "details": { + "endpoint": "https://storage.googleapis.com", + "bucketName": "ci-zenko-gcp-crr-target-bucket", + "accessKey": "gcp-access-key", + "secretKey": "gcp-secret-key", + "bucketMatch": false + } + }, + { + "name": "e2e-cold", + "locationType": "location-dmf-v1", + "details": { + "endpoint": "http://dmf-service:7778", + "repoId": ["repoId"], + "nsId": "nsId", + "username": "username", + "password": "password" + } + }, + { + "name": "e2e-miria-archive", + "locationType": "location-dmf-v1", + "details": { + "endpoint": "http://mock-miria:7778", + "repoId": ["repoId"], + "nsId": "nsId", + "username": "username", + "password": "password" + } + }, + { + "name": "quotabackend", + "locationType": "location-s3-v1", + "details": { + "endpoint": "http://cloudserver-mock.{namespace}.svc.cluster.local:8000", + "bucketName": "ci-zenko-quota-test-bucket", + "accessKey": "accessKey1", + "secretKey": "verySecretKey1", + "bucketMatch": true, + "pathStyle": true + } + }, + { + "name": "rings3cbackendingestion", + "locationType": "location-s3-v1", + "details": { + "endpoint": "http://s3c.local:8000", + "bucketName": "ingestion-test-src-bucket", + "accessKey": "accessKey1", + "secretKey": "verySecretKey1", + "bucketMatch": false, + "pathStyle": true + } + }, + { + "name": "rings3cbackendingestionnonversioned", + "locationType": "location-s3-v1", + "details": { + "endpoint": "http://s3c.local:8000", + "bucketName": "ingestion-test-src-non-versioned-bucket", + "accessKey": "accessKey1", + "secretKey": "verySecretKey1", + "bucketMatch": false, + "pathStyle": true + } + } + ] +} \ No newline at end of file diff --git a/tests/@setup/configs/setup.json b/tests/@setup/configs/setup.json new file mode 100644 index 0000000000..78860e7860 --- /dev/null +++ b/tests/@setup/configs/setup.json @@ -0,0 +1,46 @@ +{ + "setup": { + "description": "Default Zenko test environment setup configuration", + "version": "1.0.0", + "tasks": { + "rbac": { + "enabled": true, + "description": "Setup RBAC permissions for service accounts" + }, + "dns": { + "enabled": true, + "description": "Configure CoreDNS for test domains" + }, + "mocks": { + "enabled": true, + "aws": true, + "azure": true, + "description": "Deploy AWS and Azure mock services" + }, + "locations": { + "enabled": true, + "description": "Create storage locations via Management API" + }, + "buckets": { + "enabled": true, + "configFile": "configs/buckets.json", + "description": "Create test buckets across all providers" + }, + "accounts": { + "enabled": true, + "configFile": "configs/accounts.json", + "description": "Create test accounts via Management API" + }, + "endpoints": { + "enabled": true, + "configFile": "configs/endpoints.json", + "description": "Create S3 endpoints via Management API" + }, + "workflows": { + "enabled": false, + "configFile": "configs/workflows.json", + "description": "Create replication/lifecycle/ingestion workflows" + } + } + } +} \ No newline at end of file diff --git a/tests/@setup/configs/workflows.json b/tests/@setup/configs/workflows.json new file mode 100644 index 0000000000..ef9300afbe --- /dev/null +++ b/tests/@setup/configs/workflows.json @@ -0,0 +1,71 @@ +{ + "replication": [ + { + "name": "aws-to-azure-replication", + "sourceBucket": "ci-zenko-aws-source-bucket", + "sourceLocation": "aws-test-location", + "targetBucket": "ci-zenko-azure-target-container", + "targetLocation": "azure-test-location", + "enabled": true, + "description": "Replicate from AWS mock to Azure mock" + }, + { + "name": "versioned-replication", + "sourceBucket": "ci-zenko-aws-versioned-bucket", + "sourceLocation": "aws-test-location", + "targetBucket": "ci-zenko-aws-replication-bucket", + "targetLocation": "aws-test-location", + "enabled": true, + "description": "Versioned bucket replication within AWS" + } + ], + "lifecycle": [ + { + "name": "aws-lifecycle-transition", + "bucketName": "ci-zenko-aws-lifecycle-bucket", + "rules": [ + { + "id": "transition-to-azure", + "status": "Enabled", + "filter": { "prefix": "archive/" }, + "transitions": [ + { + "days": 30, + "storageClass": "azure-test-location" + } + ] + }, + { + "id": "expire-old-objects", + "status": "Enabled", + "filter": { "prefix": "temp/" }, + "expiration": { "days": 90 } + } + ] + }, + { + "name": "azure-lifecycle-cleanup", + "bucketName": "ci-zenko-azure-lifecycle-container", + "rules": [ + { + "id": "cleanup-logs", + "status": "Enabled", + "filter": { "prefix": "logs/" }, + "expiration": { "days": 7 } + } + ] + } + ], + "ingestion": [ + { + "name": "ring-to-aws-ingestion", + "sourceBucket": "ci-zenko-ring-source-bucket", + "sourceLocation": "ring-test-location", + "targetBucket": "ci-zenko-aws-target-bucket", + "targetLocation": "aws-test-location", + "schedule": "0 2 * * *", + "enabled": true, + "description": "Daily ingestion from Ring to AWS at 2 AM" + } + ] +} \ No newline at end of file diff --git a/tests/@setup/eslint.config.mjs b/tests/@setup/eslint.config.mjs new file mode 100644 index 0000000000..566d8ae19d --- /dev/null +++ b/tests/@setup/eslint.config.mjs @@ -0,0 +1,26 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; +import tseslint from 'typescript-eslint'; +import { includeIgnoreFile } from '@eslint/compat'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const gitignorePath = path.resolve(__dirname, '.gitignore'); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default tseslint.config( + ...compat.extends('scality'), + ...tseslint.configs.recommended, + includeIgnoreFile(gitignorePath), + { + rules: { + '@typescript-eslint/no-explicit-any': 'off', + }, + }, +); diff --git a/tests/@setup/package.json b/tests/@setup/package.json new file mode 100644 index 0000000000..4d9227827c --- /dev/null +++ b/tests/@setup/package.json @@ -0,0 +1,51 @@ +{ + "name": "zenko-test-setup", + "version": "1.0.0", + "description": "Unified CLI tool for Zenko test environment setup", + "main": "dist/cli.js", + "bin": { + "zenko-setup": "dist/cli.js" + }, + "scripts": { + "build": "tsc", + "dev": "ts-node src/cli.ts", + "start": "node dist/cli.js", + "lint": "eslint src/**/*.ts", + "clean": "rm -rf dist" + }, + "keywords": [ + "zenko", + "setup", + "testing", + "kubernetes", + "cli" + ], + "author": "Scality", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-iam": "^3.888.0", + "@aws-sdk/client-s3": "^3.888.0", + "@azure/storage-blob": "^12.28.0", + "@azure/storage-queue": "^12.27.0", + "@kubernetes/client-node": "^1.3.0", + "axios": "^1.12.2", + "commander": "^14.0.1", + "dotenv": "^17.2.2", + "werelogs": "scality/werelogs#8.2.2", + "yaml": "^2.8.1" + }, + "devDependencies": { + "@eslint/compat": "^1.3.2", + "@types/node": "^20.5.0", + "@typescript-eslint/eslint-plugin": "^6.4.1", + "@typescript-eslint/parser": "^6.4.1", + "eslint": "^9.35.0", + "eslint-config-scality": "scality/Guidelines#8.3.0", + "ts-node": "^10.9.1", + "typescript": "^5.2.2", + "typescript-eslint": "^8.43.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/tests/@setup/run-tests.sh b/tests/@setup/run-tests.sh new file mode 100755 index 0000000000..43bdbfb40f --- /dev/null +++ b/tests/@setup/run-tests.sh @@ -0,0 +1,289 @@ +#!/bin/bash +set -euo pipefail + +NAMESPACE="${NAMESPACE:-default}" +INSTANCE_ID="${INSTANCE_ID:-end2end}" +SUBDOMAIN="${SUBDOMAIN:-zenko.local}" +E2E_IMAGE="${E2E_IMAGE:-ghcr.io/scality/zenko/zenko-e2e:latest}" +E2E_CTST_IMAGE="${E2E_CTST_IMAGE:-ghcr.io/scality/zenko/zenko-e2e-ctst:latest}" +JOB_TIMEOUT="${JOB_TIMEOUT:-3600}" + +PARALLEL_RUNS="${PARALLEL_RUNS:-$(( ( $(nproc || echo 2) + 1 ) / 2 ))}" +JUNIT_REPORT_PATH="${JUNIT_REPORT_PATH:-/reports/ctst-junit.xml}" + +MANAGED_BY_LABEL="zenko-run-tests-script" +CLUSTER_ROLE_BINDING_NAME="ctst-cluster-admin-for-${NAMESPACE}" + +usage() { + cat < Required. The type of test to run (e2e, smoke, ctst). + --kubeconfig Path to the kubeconfig file. Defaults to ~/.kube/config. + --cleanup Remove all resources created by this script and exit. + --help Display this help message and exit. + +ADDITIONAL_TEST_ARGS: + Any arguments placed after '--' will be passed directly to the test command. + Example for ctst: -- --tags @PRA --tags ~@Flaky +EOF + exit 1 +} + +check_deps() { + echo "Checking for required dependencies..." + command -v kubectl >/dev/null || { echo "Error: kubectl is not installed. Please install it to continue." >&2; exit 1; } + command -v jq >/dev/null || { echo "Error: jq is not installed. Please install it to continue." >&2; exit 1; } + echo "All dependencies are satisfied." +} + +cleanup() { + echo "Starting cleanup of script-managed resources..." + echo "Deleting ClusterRoleBinding '${CLUSTER_ROLE_BINDING_NAME}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" delete clusterrolebinding "${CLUSTER_ROLE_BINDING_NAME}" --ignore-not-found=true + + echo "Deleting test Jobs in namespace '${NAMESPACE}' with label 'managed-by=${MANAGED_BY_LABEL}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" delete job -n "${NAMESPACE}" -l "managed-by=${MANAGED_BY_LABEL}" --ignore-not-found=true + echo "Cleanup complete." +} + +run_checks() { + echo "Performing prerequisite checks..." + [[ -f "${KUBECONFIG_FILE}" ]] || { echo "Error: Kubeconfig file not found: ${KUBECONFIG_FILE}" >&2; exit 1; } + + echo "Testing cluster connectivity..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" cluster-info >/dev/null || { echo "Error: Cannot connect to Kubernetes cluster." >&2; exit 1; } + + echo "Checking for Zenko instance '${INSTANCE_ID}' in namespace '${NAMESPACE}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" get zenko "${INSTANCE_ID}" -n "${NAMESPACE}" >/dev/null || \ + { echo "Error: Zenko instance not found. Please ensure Zenko is deployed." >&2; exit 1; } + echo "All checks passed." +} + +setup_ctst_permissions() { + echo "Applying CTST cluster-admin permissions for ServiceAccount 'default' in namespace '${NAMESPACE}'..." + cat </dev/null || echo "unknown") + + test_image="${E2E_CTST_IMAGE}" + + local world_parameters + world_parameters=$(jq -cn \ + --arg namespace "${NAMESPACE}" \ + --arg subdomain "${SUBDOMAIN}" \ + --arg dr_subdomain "${DR_SUBDOMAIN:-dr.zenko.local}" \ + --arg keycloak_username "${OIDC_USERNAME:-storage_manager}" \ + --arg keycloak_password "${OIDC_PASSWORD:-123}" \ + --arg keycloak_host "${OIDC_HOST:-keycloak.zenko.local}" \ + --arg keycloak_realm "${OIDC_REALM:-zenko}" \ + --arg keycloak_client_id "${OIDC_CLIENT_ID:-zenko-ui}" \ + '{ "Namespace": $namespace, "subdomain": $subdomain, "DRSubdomain": $dr_subdomain, "KeycloakUsername": $keycloak_username, "KeycloakPassword": $keycloak_password, "KeycloakHost": $keycloak_host, "KeycloakRealm": $keycloak_realm, "KeycloakClientId": $keycloak_client_id }') + + test_command=( + "./run" "premerge" "${world_parameters}" + "--parallel" "${PARALLEL_RUNS}" + "--retry" "${RETRIES:-3}" + "--retry-tag-filter" "@Flaky" + "--format" "junit:${JUNIT_REPORT_PATH}" + ) + test_command+=("${ADDITIONAL_ARGS[@]}") + + env_vars_yaml=$(cat <&2 + exit 1 + ;; + esac + + local command_yaml + command_yaml=$(array_to_yaml_list test_command) + + echo "Creating test job: ${job_name}" + echo "Test Image: ${test_image}" + echo "Test Command: ${test_command[*]}" + + cat <&2 + exit 1 + fi +} + +main() { + KUBECONFIG_FILE="${HOME}/.kube/config" + TEST_TYPE="" + ACTION="run" + ADDITIONAL_ARGS=() + + while [[ $# -gt 0 ]]; do + case $1 in + --type) + TEST_TYPE="$2" + shift 2 + ;; + --kubeconfig) + KUBECONFIG_FILE="$2" + shift 2 + ;; + --cleanup) + ACTION="cleanup" + shift 1 + ;; + --help) + usage + ;; + --) + shift + ADDITIONAL_ARGS=("$@") + break + ;; + *) + echo "Error: Unknown option: $1" >&2 + exit 1 + ;; + esac + done + + if [[ "${ACTION}" == "cleanup" ]]; then + cleanup + exit 0 + fi + + if [[ -z "${TEST_TYPE}" ]]; then + echo "Error: Test type is required. Use --type ." >&2 + exit 1 + fi + + check_deps + run_checks + + if [[ "${TEST_TYPE}" == "ctst" ]]; then + setup_ctst_permissions + fi + + create_job "${TEST_TYPE}" +} + +main "$@" diff --git a/tests/@setup/setup-tests.sh b/tests/@setup/setup-tests.sh new file mode 100755 index 0000000000..d5e928130b --- /dev/null +++ b/tests/@setup/setup-tests.sh @@ -0,0 +1,228 @@ +#!/bin/bash +set -euo pipefail + +NAMESPACE="${NAMESPACE:-default}" +INSTANCE_ID="${INSTANCE_ID:-end2end}" +SUBDOMAIN="${SUBDOMAIN:-zenko.local}" +SETUP_IMAGE="${SETUP_IMAGE:-ghcr.io/scality/zenko-setup:latest}" +LOG_LEVEL="${LOG_LEVEL:-info}" +METADATA_NAMESPACE="${METADATA_NAMESPACE:-metadata}" +JOB_TIMEOUT="${JOB_TIMEOUT:-1800}" +KUBECONFIG_FILE="${KUBECONFIG_FILE:-${HOME}/.kube/config}" + +SERVICE_ACCOUNT_NAME="zenko-setup" +CLUSTER_ROLE_NAME="zenko-setup-role" +CLUSTER_ROLE_BINDING_NAME="zenko-setup-binding" +MANAGED_BY_LABEL="zenko-setup-script" + +usage() { + cat < Path to the kubeconfig file. Defaults to ~/.kube/config. + --cleanup Remove all resources created by this script and exit. + --help Display this help message and exit. + +ADDITIONAL_SETUP_ARGS: + Any arguments placed after '--' will be passed directly to the setup container. +EOF + exit 1 +} + +check_deps() { + command -v kubectl >/dev/null || { echo "Error: kubectl is not installed. Please install it to continue." >&2; exit 1; } +} + +array_to_yaml_list() { + local -n arr=$1 + for item in "${arr[@]}"; do + echo " - \"${item}\"" + done +} + +cleanup() { + echo "Starting cleanup of all resources managed by this script..." + + echo "Deleting ClusterRoleBinding '${CLUSTER_ROLE_BINDING_NAME}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" delete clusterrolebinding "${CLUSTER_ROLE_BINDING_NAME}" --ignore-not-found=true + + echo "Deleting ClusterRole '${CLUSTER_ROLE_NAME}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" delete clusterrole "${CLUSTER_ROLE_NAME}" --ignore-not-found=true + + echo "Deleting ServiceAccount '${SERVICE_ACCOUNT_NAME}' in namespace '${NAMESPACE}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" delete serviceaccount "${SERVICE_ACCOUNT_NAME}" -n "${NAMESPACE}" --ignore-not-found=true + + echo "Deleting setup Jobs in namespace '${NAMESPACE}'..." + kubectl --kubeconfig="${KUBECONFIG_FILE}" delete job -n "${NAMESPACE}" -l "managed-by=${MANAGED_BY_LABEL}" --ignore-not-found=true + + echo "Cleanup complete." +} + +apply_rbac() { + echo "Applying RBAC permissions..." + cat < rbac.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ${SERVICE_ACCOUNT_NAME} + namespace: ${NAMESPACE} + labels: + managed-by: ${MANAGED_BY_LABEL} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ${CLUSTER_ROLE_NAME} + labels: + managed-by: ${MANAGED_BY_LABEL} +rules: +- apiGroups: ["", "apps", "batch", "rbac.authorization.k8s.io", "zenko.io", "networking.k8s.io"] + resources: ["*"] + verbs: ["*"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ${CLUSTER_ROLE_BINDING_NAME} + labels: + managed-by: ${MANAGED_BY_LABEL} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ${CLUSTER_ROLE_NAME} +subjects: +- kind: ServiceAccount + name: ${SERVICE_ACCOUNT_NAME} + namespace: ${NAMESPACE} +EOF + cat rbac.yaml + kubectl --kubeconfig="${KUBECONFIG_FILE}" apply -f rbac.yaml +} + +create_job() { + local -n additional_args_ref=$1 + local job_name="zenko-setup-$(date +%s)" + + local -a setup_args + setup_args=( + "all" + "--namespace" "${NAMESPACE}" + "--subdomain" "${SUBDOMAIN}" + "--instance-id" "${INSTANCE_ID}" + "--metadata-namespace" "${METADATA_NAMESPACE}" + ) + if [[ -n "${GIT_ACCESS_TOKEN:-}" ]]; then + setup_args+=("--git-access-token" "${GIT_ACCESS_TOKEN}") + fi + setup_args+=("${additional_args_ref[@]}") + + local setup_args_yaml + setup_args_yaml=$(array_to_yaml_list setup_args) + + echo "Creating setup job: ${job_name}..." + echo "Setup container args: ${setup_args[*]}" + + cat < job.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: ${job_name} + namespace: ${NAMESPACE} + labels: + app: zenko-setup + managed-by: ${MANAGED_BY_LABEL} +spec: + ttlSecondsAfterFinished: 300 + backoffLimit: 1 + activeDeadlineSeconds: ${JOB_TIMEOUT} + template: + spec: + serviceAccountName: ${SERVICE_ACCOUNT_NAME} + restartPolicy: Never + containers: + - name: setup + image: ${SETUP_IMAGE} + args: +${setup_args_yaml} + env: + - name: LOG_LEVEL + value: "${LOG_LEVEL}" + - name: GIT_ACCESS_TOKEN + value: "${GIT_ACCESS_TOKEN:-}" + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "500m" +EOF + cat job.yaml + kubectl --kubeconfig="${KUBECONFIG_FILE}" apply -f job.yaml + + echo "Waiting for job '${job_name}' to complete (timeout: ${JOB_TIMEOUT}s)..." + if kubectl --kubeconfig="${KUBECONFIG_FILE}" wait --for=condition=complete "job/${job_name}" -n "${NAMESPACE}" --timeout="${JOB_TIMEOUT}s"; then + echo "Setup completed successfully." + echo "Setup job logs (last 50 lines):" + kubectl --kubeconfig="${KUBECONFIG_FILE}" logs "job/${job_name}" -n "${NAMESPACE}" --tail=50 || true + else + echo "Error: Setup job failed or timed out." >&2 + echo "--- Job Description ---" + kubectl --kubeconfig="${KUBECONFIG_FILE}" describe "job/${job_name}" -n "${NAMESPACE}" || true + echo "--- Pod Status ---" + kubectl --kubeconfig="${KUBECONFIG_FILE}" get pods -l job-name="${job_name}" -n "${NAMESPACE}" -o wide || true + echo "--- Full Job Logs ---" + kubectl --kubeconfig="${KUBECONFIG_FILE}" logs "job/${job_name}" -n "${NAMESPACE}" || true + exit 1 + fi +} + +main() { + ACTION="run" + ADDITIONAL_ARGS=() + + while [[ $# -gt 0 ]]; do + case $1 in + --kubeconfig) + KUBECONFIG_FILE="$2" + shift 2 + ;; + --cleanup) + ACTION="cleanup" + shift 1 + ;; + --help) + usage + ;; + --) + shift + ADDITIONAL_ARGS=("$@") + break + ;; + *) + echo "Error: Unknown option: $1" >&2 + usage + ;; + esac + done + + check_deps + + if [[ "${ACTION}" == "cleanup" ]]; then + cleanup + exit 0 + fi + + echo "Starting Zenko test environment setup..." + echo "Using kubeconfig: ${KUBECONFIG_FILE}" + + cleanup + + apply_rbac + create_job ADDITIONAL_ARGS + + echo "Zenko test environment is ready." +} + +main "$@" diff --git a/tests/@setup/src/accounts.ts b/tests/@setup/src/accounts.ts new file mode 100644 index 0000000000..c3ebe421db --- /dev/null +++ b/tests/@setup/src/accounts.ts @@ -0,0 +1,176 @@ +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; +import * as fs from 'fs'; +import * as path from 'path'; +import axios from 'axios'; + +export interface AccountConfig { + name: string; + email: string; + description?: string; +} + +export interface AccountsConfig { + accounts: AccountConfig[]; +} + +export interface AccountsOptions { + namespace: string; + instanceId?: string; + configFile?: string; +} + +function loadAccountsConfig(configFile?: string): AccountsConfig { + const defaultConfigPath = path.join(__dirname, '..', 'configs', 'accounts.json'); + const configPath = configFile ? path.resolve(configFile) : defaultConfigPath; + + if (!fs.existsSync(configPath)) { + throw new Error(`Accounts configuration file not found: ${configPath}`); + } + + try { + const configData = fs.readFileSync(configPath, 'utf-8'); + return JSON.parse(configData) as AccountsConfig; + } catch (error) { + throw new Error(`Failed to parse accounts configuration: ${error instanceof Error ? error.message : String(error)}`); + } +} + +export async function setupAccounts(options: AccountsOptions): Promise { + const k8s = new KubernetesClient(); + const config = loadAccountsConfig(options.configFile); + + logger.info('Setting up test accounts via Management API'); + + // Get management API endpoint and credentials + const { managementEndpoint, authToken } = await getManagementCredentials(k8s, options); + + // Get instance ID from Zenko CR if not provided + const instanceId = options.instanceId || await getInstanceId(k8s, options); + + if (!instanceId) { + throw new Error('Instance ID is required for account creation. Either provide --instance-id or ensure Zenko CR exists'); + } + + for (const account of config.accounts) { + try { + await createAccount(managementEndpoint, authToken, instanceId, account, options); + logger.info(`Created account: ${account.name}`); + } catch (error) { + logger.error(`Failed to create account ${account.name}: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } + } + + logger.info(`Successfully created ${config.accounts.length} test accounts`); +} + +async function getManagementCredentials(k8s: KubernetesClient, options: AccountsOptions): Promise<{ managementEndpoint: string; authToken: string }> { + // Get management API endpoint from service + const managementService = await k8s.coreApi.readNamespacedService({ + name: 'zenko-management', + namespace: options.namespace, + }); + + const managementPort = managementService.spec?.ports?.find(p => p.name === 'http')?.port || 8080; + const managementEndpoint = `http://zenko-management.${options.namespace}.svc.cluster.local:${managementPort}`; + + // Get admin credentials for authentication + const adminSecret = await k8s.coreApi.readNamespacedSecret({ + name: 'zenko-admin', + namespace: options.namespace, + }); + + if (!adminSecret.data) { + throw new Error('Failed to retrieve admin credentials from zenko-admin secret'); + } + + const accessKey = Buffer.from(adminSecret.data['access-key'], 'base64').toString(); + const secretKey = Buffer.from(adminSecret.data['secret-key'], 'base64').toString(); + + // Create admin auth token (basic auth for management API) + const authToken = Buffer.from(`${accessKey}:${secretKey}`).toString('base64'); + + return { managementEndpoint, authToken }; +} + +async function getInstanceId(k8s: KubernetesClient, options: AccountsOptions): Promise { + try { + // Try to get instance ID from Zenko CR + const customObjects = k8s.customObjectsApi; + const zenkoList = await customObjects.listNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha1', + namespace: options.namespace, + plural: 'zenkos', + }); + + const zenkos = zenkoList.body as any; + if (zenkos.items && zenkos.items.length > 0) { + return zenkos.items[0].spec?.instanceId || zenkos.items[0].metadata?.name; + } + + return null; + } catch (error) { + logger.debug(`Failed to retrieve instance ID from Zenko CR: ${error instanceof Error ? error.message : String(error)}`); + return null; + } +} + +async function createAccount( + managementEndpoint: string, + authToken: string, + instanceId: string, + account: AccountConfig, + options: AccountsOptions +): Promise { + + const accountPayload = { + userName: account.name, + email: account.email, + }; + + const response = await axios.post( + `${managementEndpoint}/api/v1/config/${instanceId}/user`, + accountPayload, + { + headers: { + 'Authorization': `Basic ${authToken}`, + 'Content-Type': 'application/json', + }, + timeout: 30000, + } + ); + + if (response.status !== 201 && response.status !== 200) { + throw new Error(`Management API returned status ${response.status}: ${JSON.stringify(response.data)}`); + } + + // Store account credentials in a Kubernetes secret for later use in tests + const accountData = response.data; + const k8s = new KubernetesClient(); + + const secret = { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: `end2end-account-${account.name}`, + namespace: options.namespace, + labels: { + 'app.kubernetes.io/name': 'zenko-test-setup', + 'app.kubernetes.io/component': 'account-credentials', + 'test.zenko.io/account-name': account.name, + }, + }, + data: { + 'account-id': Buffer.from(accountData.id || '').toString('base64'), + 'account-name': Buffer.from(account.name).toString('base64'), + 'account-email': Buffer.from(account.email).toString('base64'), + 'access-key': Buffer.from(accountData.accessKey || '').toString('base64'), + 'secret-key': Buffer.from(accountData.secretKey || '').toString('base64'), + }, + }; + + await k8s.applyManifest(secret, options.namespace); + logger.debug(`Created secret end2end-account-${account.name} with account credentials`); +} \ No newline at end of file diff --git a/tests/@setup/src/buckets.ts b/tests/@setup/src/buckets.ts new file mode 100644 index 0000000000..0b7b77513a --- /dev/null +++ b/tests/@setup/src/buckets.ts @@ -0,0 +1,244 @@ +import { S3Client, CreateBucketCommand, PutBucketVersioningCommand, PutObjectCommand } from '@aws-sdk/client-s3'; +import { BlobServiceClient, StorageSharedKeyCredential as BlobStorageSharedKeyCredential } from '@azure/storage-blob'; +import { QueueServiceClient, StorageSharedKeyCredential } from '@azure/storage-queue'; +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; +import * as fs from 'fs'; +import * as path from 'path'; + +export interface BucketObject { + key: string; + body: string; +} + +export interface AWSBucket { + name: string; + versioning: boolean; + objects: BucketObject[]; +} + +export interface AzureBlob { + name: string; + content: string; +} + +export interface AzureContainer { + name: string; + blobs: AzureBlob[]; +} + +export interface AzureQueue { + name: string; +} + +export interface RingBucket { + name: string; + objects: BucketObject[]; +} + +export interface BucketsConfig { + aws: { + buckets: AWSBucket[]; + }; + azure: { + containers: AzureContainer[]; + queues: AzureQueue[]; + }; + ring: { + buckets: RingBucket[]; + }; +} + +export interface BucketsOptions { + namespace: string; + provider?: 'aws' | 'azure' | 'ring'; + configFile?: string; +} + +function loadBucketsConfig(configFile?: string): BucketsConfig { + const defaultConfigPath = path.join(__dirname, '..', 'configs', 'buckets.json'); + const configPath = configFile ? path.resolve(configFile) : defaultConfigPath; + + if (!fs.existsSync(configPath)) { + throw new Error(`Buckets configuration file not found: ${configPath}`); + } + + try { + const configData = fs.readFileSync(configPath, 'utf-8'); + return JSON.parse(configData) as BucketsConfig; + } catch (error) { + throw new Error(`Failed to parse buckets configuration: ${error instanceof Error ? error.message : String(error)}`); + } +} + +export async function setupBuckets(options: BucketsOptions): Promise { + const k8s = new KubernetesClient(); + const config = loadBucketsConfig(options.configFile); + + if (!options.provider || options.provider === 'aws') { + await setupAWSBuckets(k8s, options, config.aws.buckets); + } + + if (!options.provider || options.provider === 'azure') { + await setupAzureBuckets(k8s, options, config.azure); + } + + if (!options.provider || options.provider === 'ring') { + await setupRingBuckets(k8s, options, config.ring.buckets); + } +} + +async function setupAWSBuckets(k8s: KubernetesClient, options: BucketsOptions, buckets: AWSBucket[]): Promise { + logger.info('Creating AWS test buckets'); + + // Get AWS credentials from mock service + const awsSecret = await k8s.coreApi.readNamespacedSecret({ + name: 'aws-mock-credentials', + namespace: options.namespace, + }); + const awsConfig = { + credentials: { + accessKeyId: Buffer.from(awsSecret.data!['aws-access-key-id'], 'base64').toString(), + secretAccessKey: Buffer.from(awsSecret.data!['aws-secret-access-key'], 'base64').toString() + }, + region: Buffer.from(awsSecret.data!['aws-region'], 'base64').toString(), + endpoint: Buffer.from(awsSecret.data!['aws-endpoint'], 'base64').toString(), + forcePathStyle: true + }; + + const s3Client = new S3Client(awsConfig); + + for (const bucket of buckets) { + try { + await s3Client.send(new CreateBucketCommand({ Bucket: bucket.name })); + logger.debug(`Created bucket: ${bucket.name}`); + + // Enable versioning if specified + if (bucket.versioning) { + await s3Client.send(new PutBucketVersioningCommand({ + Bucket: bucket.name, + VersioningConfiguration: { + Status: 'Enabled' + } + })); + logger.debug(`Enabled versioning on: ${bucket.name}`); + } + + // Add test objects from configuration + for (const obj of bucket.objects) { + await s3Client.send(new PutObjectCommand({ + Bucket: bucket.name, + Key: obj.key, + Body: obj.body + })); + } + + if (bucket.objects.length > 0) { + logger.debug(`Added ${bucket.objects.length} test objects to: ${bucket.name}`); + } + + } catch (error: any) { + if (error.name === 'BucketAlreadyOwnedByYou' || error.name === 'BucketAlreadyExists') { + logger.debug(`Bucket ${bucket.name} already exists`); + } else { + logger.error(`Failed to create bucket ${bucket.name}: ${error.message}`); + throw error; + } + } + } + + logger.info(`Created ${buckets.length} AWS test buckets`); +} + +async function setupAzureBuckets(k8s: KubernetesClient, options: BucketsOptions, azureConfig: { containers: AzureContainer[]; queues: AzureQueue[] }): Promise { + logger.info('Creating Azure test containers and queues'); + + // Get Azure credentials from mock service + const azureSecret = await k8s.coreApi.readNamespacedSecret({ + name: 'azure-mock-credentials', + namespace: options.namespace, + }); + const accountName = Buffer.from(azureSecret.data!['account-name'], 'base64').toString(); + const accountKey = Buffer.from(azureSecret.data!['account-key'], 'base64').toString(); + const blobEndpoint = Buffer.from(azureSecret.data!['blob-endpoint'], 'base64').toString(); + const queueEndpoint = Buffer.from(azureSecret.data!['queue-endpoint'], 'base64').toString(); + + const blobSharedKeyCredential = new BlobStorageSharedKeyCredential(accountName, accountKey); + const queueSharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey); + + // Setup blob containers + const blobServiceClient = new BlobServiceClient(blobEndpoint, blobSharedKeyCredential); + + for (const container of azureConfig.containers) { + try { + const containerClient = blobServiceClient.getContainerClient(container.name); + await containerClient.create(); + logger.debug(`Created container: ${container.name}`); + + // Add blobs from configuration + for (const blob of container.blobs) { + const blockBlobClient = containerClient.getBlockBlobClient(blob.name); + await blockBlobClient.upload(blob.content, blob.content.length); + } + + if (container.blobs.length > 0) { + logger.debug(`Added ${container.blobs.length} test blobs to: ${container.name}`); + } + + } catch (error: any) { + if (error.statusCode === 409) { + logger.debug(`Container ${container.name} already exists`); + } else { + logger.error(`Failed to create container ${container.name}: ${error.message}`); + throw error; + } + } + } + + // Setup queues from configuration + const queueServiceClient = new QueueServiceClient(queueEndpoint, queueSharedKeyCredential); + + for (const queue of azureConfig.queues) { + try { + const queueClient = queueServiceClient.getQueueClient(queue.name); + await queueClient.create(); + logger.debug(`Created queue: ${queue.name}`); + } catch (error: any) { + if (error.statusCode === 409) { + logger.debug(`Queue ${queue.name} already exists`); + } else { + logger.error(`Failed to create queue ${queue.name}: ${error.message}`); + throw error; + } + } + } + + logger.info(`Created ${azureConfig.containers.length} Azure containers and ${azureConfig.queues.length} queues`); +} + +async function setupRingBuckets(k8s: KubernetesClient, options: BucketsOptions, buckets: RingBucket[]): Promise { + logger.info('Creating Ring/S3C test buckets'); + + // Ring buckets are typically created through S3 API against Ring storage + // This would require Ring/S3C credentials and endpoint configuration + // For now, create a configuration based on the input buckets + + const ringConfig = { + apiVersion: 'v1', + kind: 'ConfigMap', + metadata: { + name: 'ring-test-buckets', + namespace: options.namespace + }, + data: { + 'buckets.json': JSON.stringify(buckets.map(bucket => ({ + name: bucket.name, + objects: bucket.objects + })), null, 2) + } + }; + + await k8s.applyManifest(ringConfig, options.namespace); + + logger.info(`Ring bucket configuration created for ${buckets.length} buckets (actual buckets require Ring/S3C setup)`); +} \ No newline at end of file diff --git a/tests/@setup/src/cli.ts b/tests/@setup/src/cli.ts new file mode 100644 index 0000000000..ee847ecd65 --- /dev/null +++ b/tests/@setup/src/cli.ts @@ -0,0 +1,422 @@ +#!/usr/bin/env node + +import { Command } from 'commander'; +import { setupMocks } from './mocks'; +import { setupBuckets } from './buckets'; +import { setupLocations } from './locations'; +import { setupAccounts } from './accounts'; +import { setupEndpoints } from './endpoints'; +import { setupWorkflows } from './workflows'; +import { setupTLSWithOpenSSL } from './tls'; +import { setupDNS } from './dns'; +import { setupRBAC } from './rbac'; +import { setupMetadata } from './metadata'; +import { setupCTSTLocal } from './ctst-local'; +import { waitForZenkoToStabilize } from './utils/zenko-status'; +import { logger } from './utils/logger'; + +const program = new Command(); + +program + .name('zenko-setup') + .description('Unified CLI tool for Zenko test environment setup') + .version('1.0.0'); + +program + .option('-n, --namespace ', 'Kubernetes namespace', 'default') + .option('-d, --subdomain ', 'DNS subdomain', 'zenko.local') + .option('-i, --instance-id ', 'Zenko instance ID') + .option('-k, --kubeconfig ', 'Path to kubeconfig file') + .option('-v, --verbose', 'Enable verbose logging'); + +program + .command('all') + .description('Run complete setup (all tasks, use --no- to exclude specific tasks)') + .option('--config ', 'Path to setup configuration file') + .option('--buckets-config ', 'Path to buckets configuration file') + .option('--accounts-config ', 'Path to accounts configuration file') + .option('--endpoints-config ', 'Path to endpoints configuration file') + .option('--workflows-config ', 'Path to workflows configuration file') + .option('--locations-config ', 'Path to locations configuration file') + .option('--git-access-token ', 'Git access token for metadata repository') + .option('--metadata-namespace ', 'Metadata service namespace', 'metadata') + .option('--no-rbac', 'Skip RBAC setup') + .option('--no-dns', 'Skip DNS setup') + .option('--no-mocks', 'Skip mock services setup') + .option('--no-locations', 'Skip storage locations setup') + .option('--no-accounts', 'Skip test accounts setup') + .option('--no-endpoints', 'Skip S3 endpoints setup') + .option('--no-workflows', 'Skip workflows setup') + .option('--no-buckets', 'Skip test buckets setup') + .option('--no-metadata', 'Skip metadata service setup') + .option('--no-ctst-local', 'Skip CTST local environment setup') + .option('--no-tls', 'Skip TLS certificates setup') + .action(async (options) => { + const globalOptions = program.opts(); + await runSetup({ + ...globalOptions, + // Run everything for 'all' command, unless specifically excluded + rbac: !options.noRbac, + dns: !options.noDns, + mocks: !options.noMocks, + locations: !options.noLocations, + accounts: !options.noAccounts, + endpoints: !options.noEndpoints, + workflows: !options.noWorkflows, + buckets: !options.noBuckets, + metadata: !options.noMetadata, + ctstLocal: !options.noCtstLocal, + tls: !options.noTls, + configFile: options.config, + bucketsConfig: options.bucketsConfig, + accountsConfig: options.accountsConfig, + endpointsConfig: options.endpointsConfig, + workflowsConfig: options.workflowsConfig, + locationsConfig: options.locationsConfig, + gitAccessToken: options.gitAccessToken, + metadataNamespace: options.metadataNamespace, + }); + }); + +program + .command('setup') + .description('Run selective setup tasks') + .option('--rbac', 'Setup RBAC permissions') + .option('--dns', 'Configure DNS') + .option('--mocks', 'Setup mock services') + .option('--locations', 'Setup storage locations') + .option('--accounts', 'Create test accounts') + .option('--endpoints', 'Create S3 endpoints') + .option('--workflows', 'Create workflows') + .option('--buckets', 'Create test buckets') + .option('--metadata', 'Deploy metadata service') + .option('--ctst-local', 'Setup CTST local development environment') + .option('--tls', 'Setup TLS certificates') + .option('--config ', 'Path to setup configuration file') + .option('--buckets-config ', 'Path to buckets configuration file') + .option('--accounts-config ', 'Path to accounts configuration file') + .option('--endpoints-config ', 'Path to endpoints configuration file') + .option('--workflows-config ', 'Path to workflows configuration file') + .option('--locations-config ', 'Path to locations configuration file') + .option('--git-access-token ', 'Git access token for metadata repository') + .option('--metadata-namespace ', 'Metadata service namespace', 'metadata') + .action(async (options) => { + const globalOptions = program.opts(); + await runSetup({ + ...globalOptions, + // Only run tasks that are explicitly specified + rbac: options.rbac || false, + dns: options.dns || false, + mocks: options.mocks || false, + locations: options.locations || false, + accounts: options.accounts || false, + endpoints: options.endpoints || false, + workflows: options.workflows || false, + buckets: options.buckets || false, + metadata: options.metadata || false, + ctstLocal: options['ctst-local'] || false, + tls: options.tls || false, + configFile: options.config, + bucketsConfig: options.bucketsConfig, + accountsConfig: options.accountsConfig, + endpointsConfig: options.endpointsConfig, + workflowsConfig: options.workflowsConfig, + locationsConfig: options.locationsConfig, + gitAccessToken: options.gitAccessToken, + metadataNamespace: options.metadataNamespace, + }); + }); + +program + .command('mocks') + .description('Setup AWS and Azure mock services') + .option('--aws-only', 'Setup only AWS mocks') + .option('--azure-only', 'Setup only Azure mocks') + .action(async (options) => { + const globalOptions = program.opts(); + await setupMocks({ + namespace: globalOptions.namespace || 'default', + subdomain: globalOptions.subdomain || 'zenko.local', + instanceId: globalOptions.instanceId, + awsOnly: options.awsOnly, + azureOnly: options.azureOnly, + }); + }); + +program + .command('buckets') + .description('Create test buckets across all providers') + .option('--provider ', 'Specific provider (aws|azure|ring)') + .option('--config ', 'Path to buckets configuration file') + .action(async (options) => { + const globalOptions = program.opts(); + await setupBuckets({ + namespace: globalOptions.namespace || 'default', + provider: options.provider, + configFile: options.config, + }); + }); + +program + .command('locations') + .description('Setup storage locations via Management API') + .option('--config ', 'Path to locations configuration file') + .action(async (options) => { + const globalOptions = program.opts(); + await setupLocations({ + namespace: globalOptions.namespace || 'default', + instanceId: globalOptions.instanceId, + configFile: options.config, + }); + }); + +program + .command('accounts') + .description('Create test accounts via Management API') + .option('--config ', 'Path to accounts configuration file') + .action(async (options) => { + const globalOptions = program.opts(); + await setupAccounts({ + namespace: globalOptions.namespace || 'default', + instanceId: globalOptions.instanceId, + configFile: options.config, + }); + }); + +program + .command('endpoints') + .description('Create S3 endpoints via Management API') + .option('--config ', 'Path to endpoints configuration file') + .action(async (options) => { + const globalOptions = program.opts(); + await setupEndpoints({ + namespace: globalOptions.namespace || 'default', + instanceId: globalOptions.instanceId, + configFile: options.config, + }); + }); + +program + .command('workflows') + .description('Create replication/lifecycle/ingestion workflows') + .option('--config ', 'Path to workflows configuration file') + .option('--type ', 'Specific workflow type (replication|lifecycle|ingestion)') + .action(async (options) => { + const globalOptions = program.opts(); + await setupWorkflows({ + namespace: globalOptions.namespace || 'default', + instanceId: globalOptions.instanceId, + configFile: options.config, + workflowType: options.type, + }); + }); + + +program + .command('tls') + .description('Setup TLS certificates for HTTPS testing') + .option('--domains ', 'Comma-separated list of domains to include in certificate') + .action(async (options) => { + const globalOptions = program.opts(); + await setupTLSWithOpenSSL({ + namespace: globalOptions.namespace || 'default', + domains: options.domains ? options.domains.split(',') : undefined, + }); + }); + +program + .command('dns') + .description('Configure CoreDNS for test domains') + .action(async () => { + const globalOptions = program.opts(); + await setupDNS({ + namespace: globalOptions.namespace || 'default', + subdomain: globalOptions.subdomain || 'zenko.local', + }); + }); + +program + .command('rbac') + .description('Setup RBAC permissions for service accounts') + .action(async () => { + const globalOptions = program.opts(); + await setupRBAC({ + namespace: globalOptions.namespace || 'default', + }); + }); + +program + .command('metadata') + .description('Deploy metadata service (S3C)') + .option('--git-access-token ', 'Git access token for metadata repository') + .option('--metadata-namespace ', 'Metadata service namespace', 'metadata') + .option('--timeout ', 'Timeout in seconds for deployment', '300') + .action(async (options) => { + const globalOptions = program.opts(); + await setupMetadata({ + gitAccessToken: options.gitAccessToken || process.env.GIT_ACCESS_TOKEN, + namespace: options.metadataNamespace || 'metadata', + timeout: parseInt(options.timeout || '300'), + }); + }); + +program + .command('ctst-local') + .description('Setup CTST local development environment') + .option('--skip-hosts-file', 'Skip /etc/hosts file setup') + .option('--skip-rbac', 'Skip RBAC permissions setup') + .option('--skip-dns', 'Skip DNS configuration') + .option('--skip-zenko-wait', 'Skip waiting for Zenko to be ready') + .action(async (options) => { + const globalOptions = program.opts(); + await setupCTSTLocal({ + namespace: globalOptions.namespace || 'default', + instanceId: globalOptions.instanceId, + subdomain: globalOptions.subdomain || 'zenko.local', + skipHostsFile: options.skipHostsFile, + skipRBAC: options.skipRbac, + skipDNS: options.skipDns, + skipZenkoWait: options.skipZenkoWait, + }); + }); + +async function runSetup(options: any) { + try { + logger.info('Starting Zenko test environment setup'); + + // First, wait for Zenko to be ready + logger.info('Checking Zenko readiness...'); + await waitForZenkoToStabilize({ + namespace: options.namespace || 'default', + instanceId: options.instanceId || 'end2end', + timeout: 10 * 60 * 1000, // 10 minutes + }); + + const tasks = []; + + if (options.rbac) { + tasks.push({ + name: 'RBAC', fn: () => setupRBAC({ + namespace: options.namespace || 'default', + }) + }); + } + + if (options.dns) { + tasks.push({ + name: 'DNS', fn: () => setupDNS({ + namespace: options.namespace || 'default', + subdomain: options.subdomain || 'zenko.local', + }) + }); + } + + if (options.mocks) { + tasks.push({ + name: 'Mock Services', fn: () => setupMocks({ + namespace: options.namespace || 'default', + subdomain: options.subdomain || 'zenko.local', + instanceId: options.instanceId, + }) + }); + } + + if (options.locations) { + tasks.push({ + name: 'Storage Locations', fn: () => setupLocations({ + namespace: options.namespace || 'default', + instanceId: options.instanceId, + configFile: options.locationsConfig, + }) + }); + } + + if (options.accounts) { + tasks.push({ + name: 'Test Accounts', fn: () => setupAccounts({ + namespace: options.namespace || 'default', + instanceId: options.instanceId, + configFile: options.accountsConfig, + }) + }); + } + + if (options.endpoints) { + tasks.push({ + name: 'S3 Endpoints', fn: () => setupEndpoints({ + namespace: options.namespace || 'default', + instanceId: options.instanceId, + configFile: options.endpointsConfig, + }) + }); + } + + if (options.workflows) { + tasks.push({ + name: 'Workflows', fn: () => setupWorkflows({ + namespace: options.namespace || 'default', + instanceId: options.instanceId, + configFile: options.workflowsConfig, + }) + }); + } + + if (options.buckets) { + tasks.push({ + name: 'Test Buckets', fn: () => setupBuckets({ + namespace: options.namespace || 'default', + configFile: options.bucketsConfig, + }) + }); + } + + if (options.metadata) { + tasks.push({ + name: 'Metadata Service', fn: () => setupMetadata({ + gitAccessToken: options.gitAccessToken || process.env.GIT_ACCESS_TOKEN, + namespace: options.metadataNamespace || 'metadata', + timeout: 300, + }) + }); + } + + if (options.ctstLocal) { + tasks.push({ + name: 'CTST Local Environment', fn: () => setupCTSTLocal({ + namespace: options.namespace || 'default', + instanceId: options.instanceId, + subdomain: options.subdomain || 'zenko.local', + }) + }); + } + + if (options.tls) { + tasks.push({ + name: 'TLS Certificates', fn: () => setupTLSWithOpenSSL({ + namespace: options.namespace || 'default', + domains: ['*.zenko.local'], + }) + }); + } + + for (const task of tasks) { + logger.info(`Setting up ${task.name}...`); + + try { + await task.fn(); + logger.info(`${task.name} setup completed`); + } catch (error) { + logger.error(`${task.name} setup failed`, { error: error instanceof Error ? error.message : String(error) }); + throw error; + } + } + + logger.info('Zenko test environment setup completed successfully!'); + + } catch (error) { + logger.error('Setup failed', { error: error instanceof Error ? error.message : String(error) }); + process.exit(1); + } +} + +program.parse(); \ No newline at end of file diff --git a/tests/@setup/src/ctst-local.ts b/tests/@setup/src/ctst-local.ts new file mode 100644 index 0000000000..c64b7324f9 --- /dev/null +++ b/tests/@setup/src/ctst-local.ts @@ -0,0 +1,131 @@ +import { execSync } from 'child_process'; +import { readFileSync } from 'fs'; +import { logger } from './utils/logger'; +import { setupRBAC } from './rbac'; +import { setupDNS } from './dns'; +import { waitForZenkoToStabilize } from './utils/zenko-status'; + +export interface CTSTLocalOptions { + namespace: string; + instanceId?: string; + subdomain?: string; + skipHostsFile?: boolean; + skipRBAC?: boolean; + skipDNS?: boolean; + skipZenkoWait?: boolean; +} + +export async function setupCTSTLocal(options: CTSTLocalOptions): Promise { + logger.info('Setting up CTST local development environment...'); + + try { + // 1. Setup RBAC permissions for CTST + if (!options.skipRBAC) { + logger.info('Setting up CTST permissions...'); + await setupCTSTPermissions(options.namespace); + } + + // 2. Setup DNS/CoreDNS configuration + if (!options.skipDNS) { + logger.info('Checking CoreDNS configuration...'); + await setupDNS({ + namespace: options.namespace, + subdomain: options.subdomain || 'zenko.local', + }); + } + + // 3. Setup /etc/hosts for local development + if (!options.skipHostsFile) { + logger.info('Checking /etc/hosts configuration...'); + await setupHostsFile(options.subdomain || 'zenko.local'); + } + + // 4. Wait for Zenko to be ready + if (!options.skipZenkoWait) { + logger.info('Waiting for Zenko deployment to be ready...'); + await waitForZenkoToStabilize({ + namespace: options.namespace, + instanceId: options.instanceId || 'end2end', + timeout: 10 * 60 * 1000, // 10 minutes + }); + } + + logger.info('CTST local environment ready!'); + logger.info('Usage:'); + logger.info(' cd tests/ctst'); + logger.info(' npm test # Run all CTST tests'); + logger.info(' npm run test -- --tags @PRA # Run specific test tags'); + logger.info(''); + logger.info('Note: CTST will handle all Kubernetes setup (mocks, topics, deployments, etc.) automatically'); + + } catch (error) { + logger.error('Failed to setup CTST local environment:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function setupCTSTPermissions(namespace: string): Promise { + try { + logger.info('Creating cluster-admin permissions for CTST...'); + + // Create clusterrolebinding for CTST with cluster-admin permissions + const clusterRoleBindingYaml = ` +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ctst-cluster-admin +subjects: +- kind: ServiceAccount + name: default + namespace: ${namespace} +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +`; + + // Apply the configuration using kubectl + execSync('kubectl apply -f -', { + input: clusterRoleBindingYaml, + stdio: ['pipe', 'inherit', 'inherit'], + }); + + logger.info('CTST cluster-admin permissions configured successfully'); + } catch (error) { + logger.error('Failed to setup CTST permissions:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function setupHostsFile(subdomain: string): Promise { + try { + // Check if /etc/hosts already contains our entries + let hostsContent = ''; + try { + hostsContent = readFileSync('/etc/hosts', 'utf8'); + } catch (error) { + logger.debug('Could not read /etc/hosts file, skipping hosts file setup'); + return; + } + + if (hostsContent.includes(subdomain)) { + logger.info('/etc/hosts already configured'); + return; + } + + logger.info('Setting up /etc/hosts (requires sudo)...'); + + const hostsEntry = `127.0.0.1 iam.${subdomain} ui.${subdomain} s3-local-file.${subdomain} keycloak.${subdomain} sts.${subdomain} management.${subdomain} s3.${subdomain} website.mywebsite.com utilization.${subdomain}`; + + // Use sudo to append to /etc/hosts + execSync(`echo "${hostsEntry}" | sudo tee -a /etc/hosts`, { + stdio: 'inherit', + }); + + logger.info('/etc/hosts configured successfully'); + } catch (error) { + logger.warn('Failed to setup /etc/hosts (this may require manual setup):', { error: error instanceof Error ? error.message : String(error) }); + logger.info(`Manual setup: Add this line to /etc/hosts:`); + logger.info(`127.0.0.1 iam.${subdomain} ui.${subdomain} s3-local-file.${subdomain} keycloak.${subdomain} sts.${subdomain} management.${subdomain} s3.${subdomain} website.mywebsite.com utilization.${subdomain}`); + } +} \ No newline at end of file diff --git a/tests/@setup/src/dns.ts b/tests/@setup/src/dns.ts new file mode 100644 index 0000000000..db34137ac6 --- /dev/null +++ b/tests/@setup/src/dns.ts @@ -0,0 +1,155 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; + +export interface DNSOptions { + namespace: string; + subdomain?: string; +} + +// Define interfaces for our JSON configuration files for type safety +interface Location { + details: { + endpoint: string; + bucketName?: string; + }; +} +interface Endpoint { + hostname: string; +} + +/** + * Generates rewrite rules from the provided JSON config files. + * @returns A string containing all the dynamic rewrite rules. + */ +function generateDynamicRules(): string { + const configDir = path.join(__dirname, '..', 'config'); + const locations: { locations: Location[] } = JSON.parse(fs.readFileSync(path.join(configDir, 'locations.json'), 'utf8')); + const endpoints: { endpoints: Endpoint[] } = JSON.parse(fs.readFileSync(path.join(configDir, 'endpoints.json'), 'utf8')); + + const rules: string[] = []; + const destination = 'ingress-nginx-controller.ingress-nginx.svc.cluster.local'; + + // This mapping helps create bucket-specific hostnames based on the endpoint. + const mockServiceMap: { [key: string]: string } = { + 'cloudserver-mock': 'aws-mock.zenko.local', + 'azurite-mock': 'azure-mock.zenko.local', + }; + + // 1. Generate rules from locations.json for bucket-specific hostnames + for (const loc of locations.locations) { + if (!loc.details.bucketName) continue; + + for (const serviceKey in mockServiceMap) { + if (loc.details.endpoint.includes(serviceKey)) { + const publicDomain = mockServiceMap[serviceKey]; + const source = `${loc.details.bucketName}.${publicDomain}`; + rules.push(` rewrite name exact ${source} ${destination}`); + break; // Move to the next location once a match is found + } + } + } + + // 2. Generate rules from endpoints.json + for (const ep of endpoints.endpoints) { + rules.push(` rewrite name exact ${ep.hostname} ${destination}`); + } + + if (rules.length > 0) { + return `# Dynamically generated rules\n` + rules.join('\n'); + } + return '# No dynamic rules generated'; +} + +/** + * Reads the template and injects dynamic rules to create the final Corefile. + * @param options - Contains the namespace for placeholder replacement. + * @returns The complete and final Corefile content as a string. + */ +function generateCorefile(options: DNSOptions): string { + const templatePath = path.join(__dirname, '..', 'config', 'dns.conf'); + const corefileTemplate = fs.readFileSync(templatePath, 'utf8'); + + const dynamicRules = generateDynamicRules(); + + // Replace placeholders in the template + const finalCorefile = corefileTemplate + .replace('{{dynamic_rules}}', dynamicRules) + .replace(/{namespace}/g, options.namespace); // Replace any namespace placeholders if they exist + + return finalCorefile; +} + +/** + * Restarts the CoreDNS deployment to apply configuration changes. + */ +async function restartCoreDNS(k8s: KubernetesClient): Promise { + try { + logger.debug('Attempting to restart CoreDNS deployment...'); + const patch = [ + { + op: 'add', + path: '/spec/template/metadata/annotations/kubectl.kubernetes.io~1restartedAt', + value: new Date().toISOString(), + }, + ]; + + await k8s.appsApi.patchNamespacedDeployment({ + name: 'coredns', + namespace: 'kube-system', + body: patch, + }); + + logger.info('CoreDNS deployment restart triggered.'); + await k8s.waitForDeployment('coredns', 'kube-system', 60000); + logger.info('CoreDNS deployment is ready.'); + } catch (error: any) { + const errorBody = error.response ? JSON.stringify(error.response.body) : error.message; + logger.warn(`Could not restart CoreDNS deployment: ${errorBody}. A manual restart may be needed.`); + } +} + +/** + * Main function to set up DNS by overwriting the CoreDNS ConfigMap. + */ +export async function setupDNS(options: DNSOptions): Promise { + const k8s = new KubernetesClient(); + const configMapName = 'coredns'; + const configMapNamespace = 'kube-system'; + + logger.info('Generating CoreDNS configuration...'); + const newCorefile = generateCorefile(options); + + const configMapBody = { + apiVersion: 'v1', + kind: 'ConfigMap', + metadata: { name: configMapName, namespace: configMapNamespace }, + data: { 'Corefile': newCorefile }, + }; + + logger.info(`Applying CoreDNS ConfigMap to ${configMapNamespace}/${configMapName}...`); + try { + // This is the "create or replace" logic, equivalent to `kubectl apply` + await k8s.coreApi.replaceNamespacedConfigMap({ + name: configMapName, + namespace: configMapNamespace, + body: configMapBody, + }); + logger.info('CoreDNS ConfigMap successfully replaced.'); + } catch (error: any) { + if (error.response?.statusCode === 404) { + await k8s.coreApi.createNamespacedConfigMap({ + namespace: configMapNamespace, + body: configMapBody, + }); + logger.info('CoreDNS ConfigMap successfully created.'); + } else { + logger.error('Failed to apply CoreDNS ConfigMap:', error); + throw error; + } + } + + await restartCoreDNS(k8s); + logger.info('CoreDNS setup completed successfully.'); +} diff --git a/tests/@setup/src/endpoints.ts b/tests/@setup/src/endpoints.ts new file mode 100644 index 0000000000..bb75ca96a8 --- /dev/null +++ b/tests/@setup/src/endpoints.ts @@ -0,0 +1,150 @@ +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; +import * as fs from 'fs'; +import * as path from 'path'; +import axios from 'axios'; + +export interface EndpointConfig { + hostname: string; + locationName: string; + description?: string; +} + +export interface EndpointsConfig { + endpoints: EndpointConfig[]; +} + +export interface EndpointsOptions { + namespace: string; + instanceId?: string; + configFile?: string; +} + +function loadEndpointsConfig(configFile?: string): EndpointsConfig { + const defaultConfigPath = path.join(__dirname, '..', 'configs', 'endpoints.json'); + const configPath = configFile ? path.resolve(configFile) : defaultConfigPath; + + if (!fs.existsSync(configPath)) { + throw new Error(`Endpoints configuration file not found: ${configPath}`); + } + + try { + const configData = fs.readFileSync(configPath, 'utf-8'); + return JSON.parse(configData) as EndpointsConfig; + } catch (error) { + throw new Error(`Failed to parse endpoints configuration: ${error instanceof Error ? error.message : String(error)}`); + } +} + +export async function setupEndpoints(options: EndpointsOptions): Promise { + const k8s = new KubernetesClient(); + const config = loadEndpointsConfig(options.configFile); + + logger.info('Setting up S3 endpoints via Management API'); + + // Get management API endpoint and credentials + const { managementEndpoint, authToken } = await getManagementCredentials(k8s, options); + + // Get instance ID from Zenko CR if not provided + const instanceId = options.instanceId || await getInstanceId(k8s, options); + + if (!instanceId) { + throw new Error('Instance ID is required for endpoint creation. Either provide --instance-id or ensure Zenko CR exists'); + } + + for (const endpoint of config.endpoints) { + try { + await createEndpoint(managementEndpoint, authToken, instanceId, endpoint, options); + logger.info(`Created endpoint: ${endpoint.hostname} -> ${endpoint.locationName}`); + } catch (error) { + logger.error(`Failed to create endpoint ${endpoint.hostname}: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } + } + + logger.info(`Successfully created ${config.endpoints.length} S3 endpoints`); +} + +async function getManagementCredentials(k8s: KubernetesClient, options: EndpointsOptions): Promise<{ managementEndpoint: string; authToken: string }> { + // Get management API endpoint from service + const managementService = await k8s.coreApi.readNamespacedService({ + name: 'zenko-management', + namespace: options.namespace, + }); + + const managementPort = managementService.spec?.ports?.find(p => p.name === 'http')?.port || 8080; + const managementEndpoint = `http://zenko-management.${options.namespace}.svc.cluster.local:${managementPort}`; + + // Get admin credentials for authentication + const adminSecret = await k8s.coreApi.readNamespacedSecret({ + name: 'zenko-admin', + namespace: options.namespace, + }); + + if (!adminSecret.data) { + throw new Error('Failed to retrieve admin credentials from zenko-admin secret'); + } + + const accessKey = Buffer.from(adminSecret.data['access-key'], 'base64').toString(); + const secretKey = Buffer.from(adminSecret.data['secret-key'], 'base64').toString(); + + // Create admin auth token (basic auth for management API) + const authToken = Buffer.from(`${accessKey}:${secretKey}`).toString('base64'); + + return { managementEndpoint, authToken }; +} + +async function getInstanceId(k8s: KubernetesClient, options: EndpointsOptions): Promise { + try { + // Try to get instance ID from Zenko CR + const customObjects = k8s.customObjectsApi; + const zenkoList = await customObjects.listNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha1', + namespace: options.namespace, + plural: 'zenkos', + }); + + const zenkos = zenkoList.body as any; + if (zenkos.items && zenkos.items.length > 0) { + return zenkos.items[0].spec?.instanceId || zenkos.items[0].metadata?.name; + } + + return null; + } catch (error) { + logger.debug(`Failed to retrieve instance ID from Zenko CR: ${error instanceof Error ? error.message : String(error)}`); + return null; + } +} + +async function createEndpoint( + managementEndpoint: string, + authToken: string, + instanceId: string, + endpoint: EndpointConfig, + options: EndpointsOptions +): Promise { + + const endpointPayload = { + hostname: endpoint.hostname, + locationName: endpoint.locationName, + }; + + const response = await axios.post( + `${managementEndpoint}/api/v1/config/${instanceId}/endpoint`, + endpointPayload, + { + headers: { + 'Authorization': `Basic ${authToken}`, + 'Content-Type': 'application/json', + }, + timeout: 30000, + } + ); + + if (response.status !== 201 && response.status !== 200) { + throw new Error(`Management API returned status ${response.status}: ${JSON.stringify(response.data)}`); + } + + logger.debug(`Created S3 endpoint ${endpoint.hostname} pointing to location ${endpoint.locationName}`); +} \ No newline at end of file diff --git a/tests/@setup/src/locations.ts b/tests/@setup/src/locations.ts new file mode 100644 index 0000000000..c043fd032f --- /dev/null +++ b/tests/@setup/src/locations.ts @@ -0,0 +1,160 @@ +import axios from 'axios'; +import * as fs from 'fs'; +import * as path from 'path'; +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; + +export interface LocationsOptions { + namespace: string; + instanceId?: string; + configFile?: string; +} + +interface StorageLocation { + name: string; + locationType: string; + details: any; +} + +interface LocationsConfig { + locations: StorageLocation[]; +} + +function loadLocationsConfig(configFile?: string): LocationsConfig { + const defaultConfigPath = path.join(__dirname, '..', 'configs', 'locations.json'); + const configPath = configFile ? path.resolve(configFile) : defaultConfigPath; + + if (!fs.existsSync(configPath)) { + throw new Error(`Locations configuration file not found: ${configPath}`); + } + + try { + const configData = fs.readFileSync(configPath, 'utf-8'); + return JSON.parse(configData) as LocationsConfig; + } catch (error) { + throw new Error(`Failed to parse locations configuration: ${error instanceof Error ? error.message : String(error)}`); + } +} + +export async function setupLocations(options: LocationsOptions): Promise { + const k8s = new KubernetesClient(); + + logger.info('Setting up storage locations via Management API'); + + // Load locations configuration + const config = loadLocationsConfig(options.configFile); + + // Get Management API endpoint and credentials + const managementEndpoint = await getManagementEndpoint(k8s, options.namespace); + const credentials = await getManagementCredentials(k8s, options.namespace); + + // Process locations and replace namespace placeholders + const locations: StorageLocation[] = config.locations.map(location => ({ + ...location, + details: { + ...location.details, + endpoint: location.details.endpoint?.replace('{namespace}', options.namespace) + } + })); + + + // Create locations via Management API + + for (const location of locations) { + await createStorageLocation(managementEndpoint, credentials, location); + } + + logger.info(`Created ${locations.length} storage locations`); +} + +async function getManagementEndpoint(k8s: KubernetesClient, namespace: string): Promise { + try { + // Try to find Management API service + const services = await k8s.coreApi.listNamespacedService({ namespace }); + const mgmtService = services.items.find(svc => + svc.metadata?.name?.includes('management') || + svc.metadata?.name?.includes('api') || + svc.metadata?.name?.includes('zenko-management') + ); + + if (mgmtService) { + const serviceName = mgmtService.metadata!.name; + const port = mgmtService.spec?.ports?.[0]?.port || 8443; + return `http://${serviceName}.${namespace}.svc.cluster.local:${port}`; + } + + // Fallback to common endpoint + return `http://zenko-management.${namespace}.svc.cluster.local:8443`; + } catch (error) { + logger.warn('Could not determine Management API endpoint, using default'); + return `http://zenko-management.${namespace}.svc.cluster.local:8443`; + } +} + +async function getManagementCredentials(k8s: KubernetesClient, namespace: string): Promise<{ accessKey: string; secretKey: string }> { + try { + // Look for admin credentials in secrets + const secrets = await k8s.coreApi.listNamespacedSecret({ namespace }); + const adminSecret = secrets.items.find(secret => + secret.metadata?.name?.includes('admin') || + secret.metadata?.name?.includes('management') || + secret.metadata?.name?.includes('credentials') + ); + + if (adminSecret?.data) { + const accessKey = adminSecret.data['access-key'] || adminSecret.data['accessKey'] || adminSecret.data['AWS_ACCESS_KEY_ID']; + const secretKey = adminSecret.data['secret-key'] || adminSecret.data['secretKey'] || adminSecret.data['AWS_SECRET_ACCESS_KEY']; + + if (accessKey && secretKey) { + return { + accessKey: Buffer.from(accessKey, 'base64').toString(), + secretKey: Buffer.from(secretKey, 'base64').toString() + }; + } + } + } catch (error) { + logger.debug('Could not find admin credentials in secrets'); + } + + // Return default test credentials + logger.warn('Using default test credentials for Management API'); + return { + accessKey: 'accessKey1', + secretKey: 'verySecretKey1' + }; +} + +async function createStorageLocation(endpoint: string, credentials: { accessKey: string; secretKey: string }, location: StorageLocation): Promise { + try { + const response = await axios.post( + `${endpoint}/api/v1/config/${location.name}/location`, + { + locationType: location.locationType, + locationDetails: location.details + }, + { + headers: { + 'Authorization': `AWS ${credentials.accessKey}:${credentials.secretKey}`, + 'Content-Type': 'application/json' + }, + timeout: 30000 + } + ); + + if (response.status === 200 || response.status === 201) { + logger.debug(`Created storage location: ${location.name}`); + } else { + logger.warn(`Unexpected response creating location ${location.name}: ${response.status}`); + } + + } catch (error: any) { + if (error.response?.status === 409) { + logger.debug(`Storage location ${location.name} already exists`); + } else if (error.code === 'ECONNREFUSED') { + logger.warn(`Management API not available at ${endpoint}, skipping location ${location.name}`); + } else { + logger.error(`Failed to create storage location ${location.name}: ${error.message}`); + // Don't throw - continue with other locations + } + } +} \ No newline at end of file diff --git a/tests/@setup/src/metadata.ts b/tests/@setup/src/metadata.ts new file mode 100644 index 0000000000..70dbe8dcc0 --- /dev/null +++ b/tests/@setup/src/metadata.ts @@ -0,0 +1,293 @@ +import { execSync } from 'child_process'; +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; +import { V1Job, V1ObjectMeta, V1JobSpec, V1PodTemplateSpec, V1PodSpec, V1Container, V1EnvVar } from '@kubernetes/client-node'; + +export interface MetadataOptions { + gitAccessToken: string; + namespace?: string; + timeout?: number; +} + +export async function setupMetadata(options: MetadataOptions): Promise { + const namespace = options.namespace || 'metadata'; + const timeout = options.timeout || 300; + + logger.info('Setting up metadata service...'); + + try { + await createNamespace(namespace); + await deployMetadataViaJob(options.gitAccessToken, namespace); + await waitForRepdReady(namespace, timeout); + await restartAndWaitForBucketd(namespace, timeout); + await patchCloudserverConfig(namespace); + await restartAndWaitForCloudserver(namespace, timeout); + + logger.info('Metadata service setup completed successfully'); + } catch (error) { + logger.error('Failed to setup metadata service:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function createNamespace(namespace: string): Promise { + logger.info(`Creating namespace: ${namespace}`); + + const k8s = new KubernetesClient(); + try { + await k8s.coreApi.createNamespace({ + body: { + metadata: { name: namespace } + } + }); + logger.info(`Namespace ${namespace} created`); + } catch (error: any) { + if (error.response?.statusCode === 409) { + logger.info(`Namespace ${namespace} already exists`); + } else { + throw error; + } + } +} + +async function deployMetadataViaJob(gitAccessToken: string, namespace: string): Promise { + logger.info('Deploying metadata service via Kubernetes Job...'); + + const k8s = new KubernetesClient(); + + try { + const jobName = `metadata-deploy-${Date.now()}`; + const job = createMetadataDeploymentJob(jobName, namespace, gitAccessToken); + + await k8s.createJobAndWaitForCompletion(job, 'default'); + + logger.info('Metadata deployment job completed successfully'); + + } catch (error) { + logger.error('Failed to deploy metadata via job:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +function createMetadataDeploymentJob(jobName: string, targetNamespace: string, gitAccessToken: string): V1Job { + const job = new V1Job(); + const metadata = new V1ObjectMeta(); + const jobSpec = new V1JobSpec(); + const podTemplate = new V1PodTemplateSpec(); + const podSpec = new V1PodSpec(); + const container = new V1Container(); + + // Job metadata + metadata.name = jobName; + metadata.labels = { + 'app': 'metadata-deploy', + 'managed-by': 'zenko-setup' + }; + + // Container specification + container.name = 'metadata-deploy'; + container.image = 'alpine/helm:3.12.0'; // Image with both git and helm + container.command = ['/bin/sh']; + container.args = ['-c', ` + set -ex + + # Install git and other dependencies + apk add --no-cache git jq + + # Clone metadata repository + git clone --depth 1 https://git:${gitAccessToken}@github.com/scality/metadata.git /workspace/metadata + cd /workspace/metadata/helm + + # Update helm dependencies + helm dependency update cloudserver/ + + # Install the chart + helm install -n ${targetNamespace} \\ + --create-namespace \\ + --set metadata.persistentVolume.storageClass='' \\ + --set metadata.sproxyd.persistentVolume.storageClass='' \\ + s3c cloudserver/ + + echo "Metadata chart installed successfully" + `]; + + // Environment variables + container.env = [ + { name: 'HELM_CACHE_HOME', value: '/tmp/.helm' } as V1EnvVar, + { name: 'HELM_CONFIG_HOME', value: '/tmp/.helm' } as V1EnvVar, + { name: 'HELM_DATA_HOME', value: '/tmp/.helm' } as V1EnvVar, + ]; + + // Pod specification + podSpec.containers = [container]; + podSpec.restartPolicy = 'Never'; + + // Pod template + podTemplate.spec = podSpec; + + // Job specification + jobSpec.template = podTemplate; + jobSpec.backoffLimit = 2; // Retry up to 2 times + jobSpec.activeDeadlineSeconds = 600; // 10 minute timeout + + // Job + job.apiVersion = 'batch/v1'; + job.kind = 'Job'; + job.metadata = metadata; + job.spec = jobSpec; + + return job; +} + +async function waitForRepdReady(namespace: string, timeout: number): Promise { + logger.info('Waiting for repd to be ready...'); + + try { + execSync(`kubectl -n ${namespace} rollout status --watch --timeout=${timeout}s statefulset/s3c-metadata-repd`, { + stdio: 'inherit' + }); + + await waitForAllPodsInService('metadata-repd', namespace, '91*', 60); + logger.info('Repd is ready'); + } catch (error) { + logger.error('Failed to wait for repd:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function restartAndWaitForBucketd(namespace: string, timeout: number): Promise { + logger.info('Restarting bucketd to fix reconnection issues...'); + + try { + execSync(`kubectl -n ${namespace} rollout restart deployment/s3c-metadata-bucketd`, { + stdio: 'inherit' + }); + + execSync(`kubectl -n ${namespace} rollout status --watch --timeout=${timeout}s deploy/s3c-metadata-bucketd`, { + stdio: 'inherit' + }); + + await waitForAllPodsInService('metadata-bucketd', namespace, '9000', 60); + logger.info('Bucketd is ready'); + } catch (error) { + logger.error('Failed to restart/wait for bucketd:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function patchCloudserverConfig(namespace: string): Promise { + logger.info('Patching cloudserver config to add s3c.local endpoint...'); + + try { + // Get current config + const getCurrentConfigCmd = `kubectl get configmap/s3c-cloudserver-config-json -n ${namespace} -o jsonpath='{.data.config\\.json}'`; + const currentConfig = execSync(getCurrentConfigCmd, { encoding: 'utf8' }); + + // Update config with jq + const updateConfigCmd = `echo '${currentConfig}' | jq '.restEndpoints["s3c.local"] = "us-east-1"'`; + const updatedConfig = execSync(updateConfigCmd, { encoding: 'utf8' }); + + // Patch configmap + const patchData = JSON.stringify({ + data: { + 'config.json': updatedConfig.trim() + } + }); + + execSync(`kubectl patch configmap/s3c-cloudserver-config-json -n ${namespace} --type='merge' -p='${patchData}'`, { + stdio: 'inherit' + }); + + logger.info('Cloudserver config patched successfully'); + } catch (error) { + logger.error('Failed to patch cloudserver config:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function restartAndWaitForCloudserver(namespace: string, timeout: number): Promise { + logger.info('Restarting cloudserver to apply new config...'); + + try { + execSync(`kubectl -n ${namespace} rollout restart deployment/s3c-cloudserver`, { + stdio: 'inherit' + }); + + execSync(`kubectl -n ${namespace} rollout status --watch --timeout=${timeout}s deployment/s3c-cloudserver`, { + stdio: 'inherit' + }); + + await waitForAllPodsInService('cloudserver', namespace, '8000', 60); + logger.info('Cloudserver is ready'); + } catch (error) { + logger.error('Failed to restart/wait for cloudserver:', { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function waitForAllPodsInService( + service: string, + namespace: string, + portRegex: string, + timeoutSeconds: number +): Promise { + logger.info(`Waiting for all pods behind service ${service} to be ready on port ${portRegex}...`); + + try { + // Get pods for the service + const getPodsCmd = `kubectl get pods -n ${namespace} -l app=${service} -o jsonpath='{range .items[*]}{.metadata.deletionTimestamp}:{.status.podIP}:{.spec.containers[*].ports[*].containerPort}{"\\n"}{end}'`; + const podsOutput = execSync(getPodsCmd, { encoding: 'utf8' }); + + const pods = podsOutput.trim().split('\n').filter(line => line); + + for (const podInfo of pods) { + const [deletionTimestamp, ip, ports] = podInfo.split(':'); + + // Skip pods that are terminating or don't have IP/ports + if (deletionTimestamp !== '' || !ip || !ports) { + continue; + } + + // Check each port that matches the regex + const portList = ports.split(' '); + for (const port of portList) { + if (port.match(new RegExp(portRegex.replace('*', '.*')))) { + await waitForEndpoint(ip, port, timeoutSeconds); + } + } + } + } catch (error) { + logger.error(`Failed to wait for pods in service ${service}:`, { error: error instanceof Error ? error.message : String(error) }); + throw error; + } +} + +async function waitForEndpoint(host: string, port: string, timeoutSeconds: number): Promise { + logger.debug(`Waiting for ${host}:${port} to be available...`); + + const startTime = Date.now(); + const timeoutMs = timeoutSeconds * 1000; + + return new Promise((resolve, reject) => { + const checkEndpoint = () => { + const elapsed = Date.now() - startTime; + if (elapsed > timeoutMs) { + reject(new Error(`Timeout waiting for ${host}:${port} after ${timeoutSeconds} seconds`)); + return; + } + + try { + execSync(`kubectl run wait-for-port-${Date.now()} --image=busybox --attach=True --rm --restart=Never --pod-running-timeout=5m --image-pull-policy=IfNotPresent -- sh -c 'nc -z -w 1 ${host} ${port}'`, { + stdio: 'pipe' + }); + logger.debug(`${host}:${port} is now available`); + resolve(); + } catch { + // Still not ready, try again + setTimeout(checkEndpoint, 1000); + } + }; + + checkEndpoint(); + }); +} \ No newline at end of file diff --git a/tests/@setup/src/mocks.ts b/tests/@setup/src/mocks.ts new file mode 100644 index 0000000000..4a9044a9b0 --- /dev/null +++ b/tests/@setup/src/mocks.ts @@ -0,0 +1,236 @@ +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; + +export interface MocksOptions { + namespace: string; + subdomain: string; + instanceId?: string; + awsOnly?: boolean; + azureOnly?: boolean; +} + +export async function setupMocks(options: MocksOptions): Promise { + const k8s = new KubernetesClient(); + await k8s.ensureNamespace(options.namespace); + + if (!options.azureOnly) { + await setupAwsMocks(k8s, options); + } + + if (!options.awsOnly) { + await setupAzureMocks(k8s, options); + } +} + +async function setupAwsMocks(k8s: KubernetesClient, options: MocksOptions): Promise { + logger.info('Setting up AWS S3 mock (CloudServer)'); + + // CloudServer deployment for S3 API mocking + const cloudServerDeployment = { + apiVersion: 'apps/v1', + kind: 'Deployment', + metadata: { + name: 'cloudserver-mock', + namespace: options.namespace, + labels: { + app: 'cloudserver-mock', + component: 'aws-mock' + } + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: 'cloudserver-mock' + } + }, + template: { + metadata: { + labels: { + app: 'cloudserver-mock' + } + }, + spec: { + containers: [{ + name: 'cloudserver', + image: 'ghcr.io/scality/cloudserver:latest', + ports: [{ containerPort: 8000 }], + env: [ + { name: 'SCALITY_ACCESS_KEY_ID', value: 'accessKey1' }, + { name: 'SCALITY_SECRET_ACCESS_KEY', value: 'verySecretKey1' }, + { name: 'S3BACKEND', value: 'mem' }, + { name: 'LOG_LEVEL', value: 'info' }, + { name: 'REMOTE_MANAGEMENT_DISABLE', value: '1' } + ], + readinessProbe: { + httpGet: { + path: '/', + port: 8000 + }, + initialDelaySeconds: 10, + periodSeconds: 5 + } + }] + } + } + } + }; + + // CloudServer service + const cloudServerService = { + apiVersion: 'v1', + kind: 'Service', + metadata: { + name: 'cloudserver-mock', + namespace: options.namespace, + labels: { + app: 'cloudserver-mock' + } + }, + spec: { + selector: { + app: 'cloudserver-mock' + }, + ports: [{ + port: 8000, + targetPort: 8000, + name: 's3' + }] + } + }; + + // AWS credentials secret for testing + const awsCredsSecret = { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: 'aws-mock-credentials', + namespace: options.namespace + }, + type: 'Opaque', + stringData: { + 'aws-access-key-id': 'accessKey1', + 'aws-secret-access-key': 'verySecretKey1', + 'aws-region': 'us-east-1', + 'aws-endpoint': `http://cloudserver-mock.${options.namespace}.svc.cluster.local:8000` + } + }; + + await k8s.applyManifest(cloudServerDeployment, options.namespace); + await k8s.applyManifest(cloudServerService, options.namespace); + await k8s.applyManifest(awsCredsSecret, options.namespace); + + // Wait for deployment to be ready + await k8s.waitForDeployment('cloudserver-mock', options.namespace); + + logger.info('AWS S3 mock setup completed'); +} + +async function setupAzureMocks(k8s: KubernetesClient, options: MocksOptions): Promise { + logger.info('Setting up Azure Blob/Queue mock (Azurite)'); + + // Azurite deployment for Azure Storage API mocking + const azuriteDeployment = { + apiVersion: 'apps/v1', + kind: 'Deployment', + metadata: { + name: 'azurite-mock', + namespace: options.namespace, + labels: { + app: 'azurite-mock', + component: 'azure-mock' + } + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: 'azurite-mock' + } + }, + template: { + metadata: { + labels: { + app: 'azurite-mock' + } + }, + spec: { + containers: [{ + name: 'azurite', + image: 'mcr.microsoft.com/azure-storage/azurite:latest', + ports: [ + { containerPort: 10000, name: 'blob' }, + { containerPort: 10001, name: 'queue' }, + { containerPort: 10002, name: 'table' } + ], + command: [ + 'azurite', + '--blobHost', '0.0.0.0', + '--queueHost', '0.0.0.0', + '--tableHost', '0.0.0.0', + '--location', '/workspace', + '--debug', '/workspace/debug.log' + ], + readinessProbe: { + httpGet: { + path: '/', + port: 10000 + }, + initialDelaySeconds: 10, + periodSeconds: 5 + } + }] + } + } + } + }; + + // Azurite service + const azuriteService = { + apiVersion: 'v1', + kind: 'Service', + metadata: { + name: 'azurite-mock', + namespace: options.namespace, + labels: { + app: 'azurite-mock' + } + }, + spec: { + selector: { + app: 'azurite-mock' + }, + ports: [ + { port: 10000, targetPort: 10000, name: 'blob' }, + { port: 10001, targetPort: 10001, name: 'queue' }, + { port: 10002, targetPort: 10002, name: 'table' } + ] + } + }; + + // Azure credentials secret for testing + const azureCredsSecret = { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: 'azure-mock-credentials', + namespace: options.namespace + }, + type: 'Opaque', + stringData: { + 'account-name': 'devstoreaccount1', + 'account-key': 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==', + 'blob-endpoint': `http://azurite-mock.${options.namespace}.svc.cluster.local:10000/devstoreaccount1`, + 'queue-endpoint': `http://azurite-mock.${options.namespace}.svc.cluster.local:10001/devstoreaccount1` + } + }; + + await k8s.applyManifest(azuriteDeployment, options.namespace); + await k8s.applyManifest(azuriteService, options.namespace); + await k8s.applyManifest(azureCredsSecret, options.namespace); + + // Wait for deployment to be ready + await k8s.waitForDeployment('azurite-mock', options.namespace); + + logger.info('Azure Storage mock setup completed'); +} \ No newline at end of file diff --git a/tests/@setup/src/rbac.ts b/tests/@setup/src/rbac.ts new file mode 100644 index 0000000000..915054374c --- /dev/null +++ b/tests/@setup/src/rbac.ts @@ -0,0 +1,135 @@ +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; + +export interface RBACOptions { + namespace: string; +} + +export async function setupRBAC(options: RBACOptions): Promise { + const k8s = new KubernetesClient(); + await k8s.ensureNamespace(options.namespace); + + logger.info('Setting up RBAC permissions for service accounts'); + + // Create cluster role for test service accounts + const clusterRole = { + apiVersion: 'rbac.authorization.k8s.io/v1', + kind: 'ClusterRole', + metadata: { + name: 'zenko-test-admin' + }, + rules: [ + { + apiGroups: ['*'], + resources: ['*'], + verbs: ['*'] + } + ] + }; + + // Get all service accounts in the namespace + const serviceAccounts = await k8s.coreApi.listNamespacedServiceAccount({ + namespace: options.namespace, + }); + const zenkoServiceAccounts = serviceAccounts.items.filter(sa => + sa.metadata?.name?.includes('zenko') || + sa.metadata?.name?.includes('cloudserver') || + sa.metadata?.name?.includes('backbeat') || + sa.metadata?.name?.includes('operator') + ); + + // Apply cluster role + try { + await k8s.rbacApi.createClusterRole({ + body: clusterRole, + }); + } catch (error: any) { + if (error.response?.statusCode === 409) { + logger.debug('ClusterRole zenko-test-admin already exists'); + await k8s.rbacApi.replaceClusterRole({ + name: 'zenko-test-admin', + body: clusterRole, + }); + } else { + throw error; + } + } + + // Create cluster role bindings for each service account + for (const sa of zenkoServiceAccounts) { + const saName = sa.metadata?.name; + if (!saName) continue; + + const clusterRoleBinding = { + apiVersion: 'rbac.authorization.k8s.io/v1', + kind: 'ClusterRoleBinding', + metadata: { + name: `zenko-test-admin-${saName}` + }, + subjects: [{ + kind: 'ServiceAccount', + name: saName, + namespace: options.namespace + }], + roleRef: { + kind: 'ClusterRole', + name: 'zenko-test-admin', + apiGroup: 'rbac.authorization.k8s.io' + } + }; + + try { + await k8s.rbacApi.createClusterRoleBinding({ + body: clusterRoleBinding, + }); + logger.debug(`Created ClusterRoleBinding for ${saName}`); + } catch (error: any) { + if (error.response?.statusCode === 409) { + logger.debug(`ClusterRoleBinding for ${saName} already exists`); + await k8s.rbacApi.replaceClusterRoleBinding({ + name: `zenko-test-admin-${saName}`, + body: clusterRoleBinding, + }); + } else { + throw error; + } + } + } + + // Create role binding for default service account in namespace + const defaultRoleBinding = { + apiVersion: 'rbac.authorization.k8s.io/v1', + kind: 'ClusterRoleBinding', + metadata: { + name: `zenko-test-admin-default-${options.namespace}` + }, + subjects: [{ + kind: 'ServiceAccount', + name: 'default', + namespace: options.namespace + }], + roleRef: { + kind: 'ClusterRole', + name: 'zenko-test-admin', + apiGroup: 'rbac.authorization.k8s.io' + } + }; + + try { + await k8s.rbacApi.createClusterRoleBinding({ + body: defaultRoleBinding, + }); + } catch (error: any) { + if (error.response?.statusCode === 409) { + logger.debug(`Default ClusterRoleBinding already exists`); + await k8s.rbacApi.replaceClusterRoleBinding({ + name: `zenko-test-admin-default-${options.namespace}`, + body: defaultRoleBinding, + }); + } else { + throw error; + } + } + + logger.info(`RBAC setup completed for ${zenkoServiceAccounts.length + 1} service accounts`); +} \ No newline at end of file diff --git a/tests/@setup/src/tls.ts b/tests/@setup/src/tls.ts new file mode 100644 index 0000000000..153f4019dd --- /dev/null +++ b/tests/@setup/src/tls.ts @@ -0,0 +1,85 @@ +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; +import { execSync } from 'child_process'; +import { mkdtempSync, readFileSync, rmSync } from 'fs'; +import { join } from 'path'; +import { tmpdir } from 'os'; + +export interface TLSOptions { + namespace: string; + domains?: string[]; +} + +export async function setupTLSWithOpenSSL(options: TLSOptions): Promise { + const k8s = new KubernetesClient(); + const domains = options.domains || ['zenko.local']; + const mainDomain = domains[0] || 'zenko.local'; + + logger.info('Setting up TLS certificates for HTTPS testing'); + + // Create temporary directory + const tempDir = mkdtempSync(join(tmpdir(), 'zenko-tls-')); + + try { + // Generate self-signed certificate (simple approach like the original) + // Use wildcard domain if specified, otherwise use main domain + const certDomain = mainDomain.startsWith('*.') ? mainDomain : `*.${mainDomain.replace('*.', '')}`; + const opensslCmd = `openssl req -x509 -nodes -days 365 -newkey rsa:2048 ` + + `-keyout tls.key -out tls.crt -subj "/CN=${certDomain}"`; + + logger.info(`Generating self-signed certificate for ${mainDomain}...`); + execSync(opensslCmd, { cwd: tempDir, stdio: 'pipe' }); + + // Read generated files + const tlsKey = readFileSync(join(tempDir, 'tls.key'), 'utf8'); + const tlsCert = readFileSync(join(tempDir, 'tls.crt'), 'utf8'); + + // Create TLS secret using kubectl equivalent + await createTLSSecret(k8s, options.namespace, 'zenko-tls', tlsCert, tlsKey); + + logger.info(`Successfully created TLS secret 'zenko-tls' for domain: ${mainDomain}`); + + } catch (error) { + logger.error(`Failed to setup TLS certificates: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } finally { + // Clean up temporary directory + rmSync(tempDir, { recursive: true, force: true }); + } +} + +async function createTLSSecret(k8s: KubernetesClient, namespace: string, secretName: string, cert: string, key: string): Promise { + try { + // Check if secret already exists + try { + await k8s.coreApi.readNamespacedSecret({ name: secretName, namespace }); + logger.info(`TLS secret ${secretName} already exists, replacing...`); + await k8s.coreApi.deleteNamespacedSecret({ name: secretName, namespace }); + } catch (error) { + // Secret doesn't exist, which is fine + } + + // Create new TLS secret + await k8s.coreApi.createNamespacedSecret({ + namespace, + body: { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: secretName, + namespace: namespace, + }, + type: 'kubernetes.io/tls', + data: { + 'tls.crt': Buffer.from(cert).toString('base64'), + 'tls.key': Buffer.from(key).toString('base64'), + }, + }, + }); + + logger.info(`Created TLS secret: ${secretName}`); + } catch (error) { + logger.error(`Failed to create TLS secret: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } +} \ No newline at end of file diff --git a/tests/@setup/src/utils/k8s.ts b/tests/@setup/src/utils/k8s.ts new file mode 100644 index 0000000000..0ed733e692 --- /dev/null +++ b/tests/@setup/src/utils/k8s.ts @@ -0,0 +1,307 @@ +import * as k8s from '@kubernetes/client-node'; +import { logger } from './logger'; + +export class KubernetesClient { + private kc: k8s.KubeConfig; + public coreApi: k8s.CoreV1Api; + public appsApi: k8s.AppsV1Api; + public customObjectsApi: k8s.CustomObjectsApi; + public rbacApi: k8s.RbacAuthorizationV1Api; + public batchApi: k8s.BatchV1Api; + + constructor(kubeconfig?: string) { + this.kc = new k8s.KubeConfig(); + + if (kubeconfig) { + this.kc.loadFromFile(kubeconfig); + } else if (process.env.KUBECONFIG) { + this.kc.loadFromFile(process.env.KUBECONFIG); + } else { + try { + // Try in-cluster config first (when running as a Pod) + this.kc.loadFromCluster(); + logger.debug('Using in-cluster Kubernetes configuration'); + } catch { + try { + // Fallback to default (local kubeconfig) + this.kc.loadFromDefault(); + logger.debug('Using default Kubernetes configuration'); + } catch (defaultError) { + logger.error('Failed to load Kubernetes configuration.'); + throw defaultError; + } + } + } + + this.coreApi = this.kc.makeApiClient(k8s.CoreV1Api); + this.appsApi = this.kc.makeApiClient(k8s.AppsV1Api); + this.customObjectsApi = this.kc.makeApiClient(k8s.CustomObjectsApi); + this.rbacApi = this.kc.makeApiClient(k8s.RbacAuthorizationV1Api); + this.batchApi = this.kc.makeApiClient(k8s.BatchV1Api); + } + + async ensureNamespace(namespace: string): Promise { + try { + await this.coreApi.readNamespace({ name: namespace }); + logger.debug(`Namespace ${namespace} exists`); + } catch (error: any) { + if (error.response?.statusCode === 404) { + logger.info(`Creating namespace ${namespace}`); + await this.coreApi.createNamespace({ + body: { + apiVersion: 'v1', + kind: 'Namespace', + metadata: { name: namespace } + } + }); + } else { + throw error; + } + } + } + + async applyManifest(manifest: any, namespace?: string): Promise { + const { kind, apiVersion, metadata } = manifest; + + if (namespace && !metadata.namespace) { + metadata.namespace = namespace; + } + + logger.debug(`Applying ${kind}/${metadata.name} in namespace ${metadata.namespace || 'default'}`); + + try { + switch (kind) { + case 'Deployment': + try { + await this.appsApi.readNamespacedDeployment( + { name: metadata.name, namespace: metadata.namespace || 'default' } + ); + await this.appsApi.replaceNamespacedDeployment( + { + name: metadata.name, + namespace: metadata.namespace || 'default', + body: manifest, + }, + ); + } catch (error: any) { + if (error.response?.statusCode === 404) { + await this.appsApi.createNamespacedDeployment( + metadata.namespace || 'default', + manifest, + ); + } else { + throw error; + } + } + break; + + case 'Service': + try { + await this.coreApi.readNamespacedService( + { name: metadata.name, namespace: metadata.namespace || 'default' } + ); + await this.coreApi.replaceNamespacedService( + { + name: metadata.name, + namespace: metadata.namespace || 'default', + body: manifest, + }, + ); + } catch (error: any) { + if (error.response?.statusCode === 404) { + await this.coreApi.createNamespacedService(metadata.namespace || 'default', manifest); + } else { + throw error; + } + } + break; + + case 'ConfigMap': + try { + await this.coreApi.readNamespacedConfigMap( + { name: metadata.name, namespace: metadata.namespace || 'default' } + ); + await this.coreApi.replaceNamespacedConfigMap( + { + name: metadata.name, + namespace: metadata.namespace || 'default', + body: manifest, + }, + ); + } catch (error: any) { + if (error.response?.statusCode === 404) { + await this.coreApi.createNamespacedConfigMap(metadata.namespace || 'default', manifest); + } else { + throw error; + } + } + break; + + case 'Secret': + try { + await this.coreApi.readNamespacedSecret( + { name: metadata.name, namespace: metadata.namespace || 'default' } + ); + await this.coreApi.replaceNamespacedSecret( + { + name: metadata.name, + namespace: metadata.namespace || 'default', + body: manifest, + }, + ); + } catch (error: any) { + if (error.response?.statusCode === 404) { + await this.coreApi.createNamespacedSecret( + metadata.namespace || 'default', + manifest, + ); + } else { + throw error; + } + } + break; + + default: + // Handle custom resources + // eslint-disable-next-line no-case-declarations + const [group, version] = apiVersion.split('/'); + await this.customObjectsApi.createNamespacedCustomObject( + { + group, + version, + plural: `${kind.toLowerCase()}s`, + body: manifest, + namespace: metadata.namespace || 'default', + }, + ); + } + } catch (error: any) { + if (error.response?.statusCode === 409) { + logger.debug(`Resource ${kind}/${metadata.name} already exists`); + } else { + throw error; + } + } + } + + async waitForDeployment(name: string, namespace: string, timeoutMs: number = 300000): Promise { + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutMs) { + try { + const deployment = await this.appsApi.readNamespacedDeployment({ name, namespace }); + const status = deployment.status; + + if (status?.readyReplicas === status?.replicas && status?.replicas && status.replicas > 0) { + logger.debug(`Deployment ${name} is ready`); + return; + } + + logger.debug(`Waiting for deployment ${name} (${status?.readyReplicas || 0}/${status?.replicas || 0})`); + await new Promise(resolve => setTimeout(resolve, 5000)); + } catch (error) { + logger.debug(`Error checking deployment ${name}: ${error}`); + await new Promise(resolve => setTimeout(resolve, 5000)); + } + } + + throw new Error(`Deployment ${name} did not become ready within ${timeoutMs}ms`); + } + + /** + * Wait for a Kubernetes Job to complete (succeed or fail) + */ + async waitForJobCompletion(jobName: string, namespace: string, timeoutMs: number = 10 * 60 * 1000): Promise { + logger.info(`Waiting for job ${jobName} to complete...`); + + const pollInterval = 5000; // 5 seconds + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutMs) { + try { + const jobResponse = await this.batchApi.readNamespacedJob({ + name: jobName, + namespace, + }); + + const job = jobResponse; + const status = job?.status; + + if (status?.succeeded && status.succeeded > 0) { + logger.info(`Job ${jobName} completed successfully`); + return; + } + + if (status?.failed && status.failed > 0) { + // Get job logs for debugging + const podsResponse = await this.coreApi.listNamespacedPod({ + namespace, + labelSelector: `job-name=${jobName}` + }); + + if (podsResponse?.items.length > 0) { + const podName = podsResponse.items[0].metadata?.name; + if (podName) { + try { + const logsResponse = await this.coreApi.readNamespacedPodLog({ + name: podName, + namespace + }); + logger.error(`Job ${jobName} failed. Pod logs:`, { logs: logsResponse }); + } catch (logError) { + logger.debug('Could not retrieve pod logs', { error: logError }); + } + } + } + throw new Error(`Job ${jobName} failed`); + } + + logger.debug(`Job ${jobName} still running...`, { status }); + await new Promise(resolve => setTimeout(resolve, pollInterval)); + } catch (error) { + if ((error as any)?.response?.statusCode === 404) { + throw new Error(`Job ${jobName} not found`); + } + throw error; + } + } + + throw new Error(`Timeout waiting for job ${jobName} to complete after ${timeoutMs}ms`); + } + + /** + * Create a Job and wait for its completion + */ + async createJobAndWaitForCompletion( + job: k8s.V1Job, + namespace: string, + timeoutMs: number = 10 * 60 * 1000 + ): Promise { + const jobResponse = await this.batchApi.createNamespacedJob({ + namespace, + body: job + }); + + const jobName = jobResponse?.metadata?.name; + if (!jobName) { + throw new Error('Failed to create job - no name returned'); + } + + logger.info(`Created job: ${jobName}`); + + try { + await this.waitForJobCompletion(jobName, namespace, timeoutMs); + } finally { + // Clean up the job + try { + await this.batchApi.deleteNamespacedJob({ + name: jobName, + namespace + }); + logger.debug(`Cleaned up job: ${jobName}`); + } catch (cleanupError) { + logger.debug(`Failed to cleanup job ${jobName}:`, { error: cleanupError }); + } + } + } +} diff --git a/tests/@setup/src/utils/logger.ts b/tests/@setup/src/utils/logger.ts new file mode 100644 index 0000000000..01e895a971 --- /dev/null +++ b/tests/@setup/src/utils/logger.ts @@ -0,0 +1,9 @@ +import Werelogs from 'werelogs'; + +// Configure werelogs +Werelogs.configure({ + level: (process.env.LOG_LEVEL as any) || 'info', + dump: (process.env.LOG_DUMP_LEVEL as any) || 'error', +}); + +export const logger = new Werelogs.Logger('ZenkoSetup').newRequestLogger(); diff --git a/tests/@setup/src/utils/zenko-status.ts b/tests/@setup/src/utils/zenko-status.ts new file mode 100644 index 0000000000..771d47a488 --- /dev/null +++ b/tests/@setup/src/utils/zenko-status.ts @@ -0,0 +1,108 @@ +import { KubernetesClient } from './k8s'; +import { logger } from './logger'; + +interface ZenkoStatusValue { + lastTransitionTime: string; + message: string; + status: 'True' | 'False'; + reason?: string; + type: 'DeploymentFailure' | 'DeploymentInProgress' | 'Available'; +} + +type ZenkoStatus = ZenkoStatusValue[]; + +interface ZenkoStatusOptions { + namespace: string; + instanceId?: string; + timeout?: number; +} + +function sleep(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export async function waitForZenkoToStabilize(options: ZenkoStatusOptions): Promise { + const { namespace, instanceId = 'end2end', timeout = 15 * 60 * 1000 } = options; + const k8s = new KubernetesClient(); + + const startTime = Date.now(); + let status = false; + let deploymentFailure: ZenkoStatusValue = { + lastTransitionTime: '', + message: '', + status: 'False', + type: 'DeploymentFailure', + }; + let deploymentInProgress: ZenkoStatusValue = { + lastTransitionTime: '', + message: '', + status: 'False', + type: 'DeploymentInProgress', + }; + let available: ZenkoStatusValue = { + lastTransitionTime: '', + message: '', + status: 'False', + type: 'Available', + }; + + logger.info(`Waiting for Zenko instance '${instanceId}' to stabilize...`); + + while (!status && Date.now() - startTime < timeout) { + const zenkoCR = await k8s.customObjectsApi.getNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha2', + namespace, + plural: 'zenkos', + name: instanceId + }).catch(err => { + logger.debug('Error getting Zenko CR', { + error: err instanceof Error ? err.message : String(err), + }); + return null; + }); + + if (!zenkoCR) { + await sleep(5000); + continue; + } + + const conditions: ZenkoStatus = (zenkoCR as any)?.status?.conditions || []; + + conditions.forEach(condition => { + if (condition.type === 'DeploymentFailure') { + deploymentFailure = condition; + } else if (condition.type === 'DeploymentInProgress') { + deploymentInProgress = condition; + } else if (condition.type === 'Available') { + available = condition; + } + }); + + logger.debug('Checking Zenko CR status', { + deploymentFailure: `${deploymentFailure.type}=${deploymentFailure.status}`, + deploymentInProgress: `${deploymentInProgress.type}=${deploymentInProgress.status}`, + available: `${available.type}=${available.status}`, + }); + + if (deploymentFailure.status === 'False' && + deploymentInProgress.status === 'False' && + available.status === 'True' + ) { + status = true; + break; + } + + if (deploymentFailure.status === 'True') { + throw new Error(`Zenko deployment failed: ${deploymentFailure.message}`); + } + + await sleep(5000); + } + + if (!status) { + throw new Error(`Zenko instance '${instanceId}' did not stabilize within ${timeout / 1000} seconds`); + } + + logger.info(`Zenko instance '${instanceId}' is ready and stable`); +} diff --git a/tests/@setup/src/workflows.ts b/tests/@setup/src/workflows.ts new file mode 100644 index 0000000000..be921dd490 --- /dev/null +++ b/tests/@setup/src/workflows.ts @@ -0,0 +1,303 @@ +import { KubernetesClient } from './utils/k8s'; +import { logger } from './utils/logger'; +import * as fs from 'fs'; +import * as path from 'path'; +import axios from 'axios'; + +export interface ReplicationWorkflow { + name: string; + sourceBucket: string; + sourceLocation: string; + targetBucket: string; + targetLocation: string; + enabled: boolean; + description?: string; +} + +export interface LifecycleRule { + id: string; + status: 'Enabled' | 'Disabled'; + filter: { + prefix?: string; + tags?: { [key: string]: string }; + }; + transitions?: Array<{ + days: number; + storageClass: string; + }>; + expiration?: { + days: number; + }; +} + +export interface LifecycleWorkflow { + name: string; + bucketName: string; + rules: LifecycleRule[]; +} + +export interface IngestionWorkflow { + name: string; + sourceBucket: string; + sourceLocation: string; + targetBucket: string; + targetLocation: string; + schedule: string; + enabled: boolean; + description?: string; +} + +export interface WorkflowsConfig { + replication: ReplicationWorkflow[]; + lifecycle: LifecycleWorkflow[]; + ingestion: IngestionWorkflow[]; +} + +export interface WorkflowsOptions { + namespace: string; + instanceId?: string; + configFile?: string; + workflowType?: 'replication' | 'lifecycle' | 'ingestion'; +} + +function loadWorkflowsConfig(configFile?: string): WorkflowsConfig { + const defaultConfigPath = path.join(__dirname, '..', 'configs', 'workflows.json'); + const configPath = configFile ? path.resolve(configFile) : defaultConfigPath; + + if (!fs.existsSync(configPath)) { + throw new Error(`Workflows configuration file not found: ${configPath}`); + } + + try { + const configData = fs.readFileSync(configPath, 'utf-8'); + return JSON.parse(configData) as WorkflowsConfig; + } catch (error) { + throw new Error(`Failed to parse workflows configuration: ${error instanceof Error ? error.message : String(error)}`); + } +} + +export async function setupWorkflows(options: WorkflowsOptions): Promise { + const k8s = new KubernetesClient(); + const config = loadWorkflowsConfig(options.configFile); + + logger.info('Setting up workflows via Management API'); + + // Get management API endpoint and credentials + const { managementEndpoint, authToken } = await getManagementCredentials(k8s, options); + + // Get instance ID from Zenko CR if not provided + const instanceId = options.instanceId || await getInstanceId(k8s, options); + + if (!instanceId) { + throw new Error('Instance ID is required for workflow creation. Either provide --instance-id or ensure Zenko CR exists'); + } + + let totalCreated = 0; + + // Create replication workflows + if (!options.workflowType || options.workflowType === 'replication') { + for (const workflow of config.replication) { + try { + await createReplicationWorkflow(managementEndpoint, authToken, instanceId, workflow, options); + logger.info(`Created replication workflow: ${workflow.name}`); + totalCreated++; + } catch (error) { + logger.error(`Failed to create replication workflow ${workflow.name}: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } + } + } + + // Create lifecycle workflows + if (!options.workflowType || options.workflowType === 'lifecycle') { + for (const workflow of config.lifecycle) { + try { + await createLifecycleWorkflow(managementEndpoint, authToken, instanceId, workflow, options); + logger.info(`Created lifecycle workflow: ${workflow.name}`); + totalCreated++; + } catch (error) { + logger.error(`Failed to create lifecycle workflow ${workflow.name}: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } + } + } + + // Create ingestion workflows + if (!options.workflowType || options.workflowType === 'ingestion') { + for (const workflow of config.ingestion) { + try { + await createIngestionWorkflow(managementEndpoint, authToken, instanceId, workflow, options); + logger.info(`Created ingestion workflow: ${workflow.name}`); + totalCreated++; + } catch (error) { + logger.error(`Failed to create ingestion workflow ${workflow.name}: ${error instanceof Error ? error.message : String(error)}`); + throw error; + } + } + } + + logger.info(`Successfully created ${totalCreated} workflows`); +} + +async function getManagementCredentials(k8s: KubernetesClient, options: WorkflowsOptions): Promise<{ managementEndpoint: string; authToken: string }> { + // Get management API endpoint from service + const managementService = await k8s.coreApi.readNamespacedService({ + name: 'zenko-management', + namespace: options.namespace, + }); + + const managementPort = managementService.spec?.ports?.find(p => p.name === 'http')?.port || 8080; + const managementEndpoint = `http://zenko-management.${options.namespace}.svc.cluster.local:${managementPort}`; + + // Get admin credentials for authentication + const adminSecret = await k8s.coreApi.readNamespacedSecret({ + name: 'zenko-admin', + namespace: options.namespace, + }); + + if (!adminSecret.data) { + throw new Error('Failed to retrieve admin credentials from zenko-admin secret'); + } + + const accessKey = Buffer.from(adminSecret.data['access-key'], 'base64').toString(); + const secretKey = Buffer.from(adminSecret.data['secret-key'], 'base64').toString(); + + // Create admin auth token (basic auth for management API) + const authToken = Buffer.from(`${accessKey}:${secretKey}`).toString('base64'); + + return { managementEndpoint, authToken }; +} + +async function getInstanceId(k8s: KubernetesClient, options: WorkflowsOptions): Promise { + try { + // Try to get instance ID from Zenko CR + const customObjects = k8s.customObjectsApi; + const zenkoList = await customObjects.listNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha1', + namespace: options.namespace, + plural: 'zenkos', + }); + + const zenkos = zenkoList.body as any; + if (zenkos.items && zenkos.items.length > 0) { + return zenkos.items[0].spec?.instanceId || zenkos.items[0].metadata?.name; + } + + return null; + } catch (error) { + logger.debug(`Failed to retrieve instance ID from Zenko CR: ${error instanceof Error ? error.message : String(error)}`); + return null; + } +} + +async function createReplicationWorkflow( + managementEndpoint: string, + authToken: string, + instanceId: string, + workflow: ReplicationWorkflow, + options: WorkflowsOptions +): Promise { + + const workflowPayload = { + workflowId: workflow.name, + type: 'replication', + enabled: workflow.enabled, + source: { + bucket: workflow.sourceBucket, + location: workflow.sourceLocation, + }, + destination: { + bucket: workflow.targetBucket, + location: workflow.targetLocation, + }, + }; + + const response = await axios.post( + `${managementEndpoint}/api/v1/config/${instanceId}/workflow`, + workflowPayload, + { + headers: { + 'Authorization': `Basic ${authToken}`, + 'Content-Type': 'application/json', + }, + timeout: 30000, + } + ); + + if (response.status !== 201 && response.status !== 200) { + throw new Error(`Management API returned status ${response.status}: ${JSON.stringify(response.data)}`); + } +} + +async function createLifecycleWorkflow( + managementEndpoint: string, + authToken: string, + instanceId: string, + workflow: LifecycleWorkflow, + options: WorkflowsOptions +): Promise { + + const workflowPayload = { + workflowId: workflow.name, + type: 'lifecycle', + bucketName: workflow.bucketName, + rules: workflow.rules, + }; + + const response = await axios.post( + `${managementEndpoint}/api/v1/config/${instanceId}/lifecycle`, + workflowPayload, + { + headers: { + 'Authorization': `Basic ${authToken}`, + 'Content-Type': 'application/json', + }, + timeout: 30000, + } + ); + + if (response.status !== 201 && response.status !== 200) { + throw new Error(`Management API returned status ${response.status}: ${JSON.stringify(response.data)}`); + } +} + +async function createIngestionWorkflow( + managementEndpoint: string, + authToken: string, + instanceId: string, + workflow: IngestionWorkflow, + options: WorkflowsOptions +): Promise { + + const workflowPayload = { + workflowId: workflow.name, + type: 'ingestion', + enabled: workflow.enabled, + schedule: workflow.schedule, + source: { + bucket: workflow.sourceBucket, + location: workflow.sourceLocation, + }, + destination: { + bucket: workflow.targetBucket, + location: workflow.targetLocation, + }, + }; + + const response = await axios.post( + `${managementEndpoint}/api/v1/config/${instanceId}/workflow`, + workflowPayload, + { + headers: { + 'Authorization': `Basic ${authToken}`, + 'Content-Type': 'application/json', + }, + timeout: 30000, + } + ); + + if (response.status !== 201 && response.status !== 200) { + throw new Error(`Management API returned status ${response.status}: ${JSON.stringify(response.data)}`); + } +} \ No newline at end of file diff --git a/tests/@setup/tsconfig.json b/tests/@setup/tsconfig.json new file mode 100644 index 0000000000..ebbbe2b307 --- /dev/null +++ b/tests/@setup/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts" + ] +} \ No newline at end of file diff --git a/tests/@setup/yarn.lock b/tests/@setup/yarn.lock new file mode 100644 index 0000000000..b12b6f446d --- /dev/null +++ b/tests/@setup/yarn.lock @@ -0,0 +1,2956 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@5.2.0", "@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-iam@^3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.888.0.tgz#7736c8c988a015e8c6be324a9b59292ce7c90445" + integrity sha512-BYJVOji9jrYcOiUsWspS94viNK0XCGb7QyLcHc4cyq2BXqTy3HXINnPtk+xHvep1LqRaIuyfIOGlmIKKsJ1tGA== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.888.0" + "@aws-sdk/credential-provider-node" "3.888.0" + "@aws-sdk/middleware-host-header" "3.887.0" + "@aws-sdk/middleware-logger" "3.887.0" + "@aws-sdk/middleware-recursion-detection" "3.887.0" + "@aws-sdk/middleware-user-agent" "3.888.0" + "@aws-sdk/region-config-resolver" "3.887.0" + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-endpoints" "3.887.0" + "@aws-sdk/util-user-agent-browser" "3.887.0" + "@aws-sdk/util-user-agent-node" "3.888.0" + "@smithy/config-resolver" "^4.2.1" + "@smithy/core" "^3.11.0" + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/hash-node" "^4.1.1" + "@smithy/invalid-dependency" "^4.1.1" + "@smithy/middleware-content-length" "^4.1.1" + "@smithy/middleware-endpoint" "^4.2.1" + "@smithy/middleware-retry" "^4.2.1" + "@smithy/middleware-serde" "^4.1.1" + "@smithy/middleware-stack" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-body-length-node" "^4.1.0" + "@smithy/util-defaults-mode-browser" "^4.1.1" + "@smithy/util-defaults-mode-node" "^4.1.1" + "@smithy/util-endpoints" "^3.1.1" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-retry" "^4.1.1" + "@smithy/util-utf8" "^4.1.0" + "@smithy/util-waiter" "^4.1.1" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.888.0.tgz#6a030cc4cc98974062862bd6d490e1b72478057c" + integrity sha512-MgYyF/qpvCMYVSiOpRJ5C/EtdFxuYAeF5SprtMsbf71xBiiCH5GurB616i+ZxJqHlfhBQTTvR0qugnWvk1Wqvw== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.888.0" + "@aws-sdk/credential-provider-node" "3.888.0" + "@aws-sdk/middleware-bucket-endpoint" "3.887.0" + "@aws-sdk/middleware-expect-continue" "3.887.0" + "@aws-sdk/middleware-flexible-checksums" "3.888.0" + "@aws-sdk/middleware-host-header" "3.887.0" + "@aws-sdk/middleware-location-constraint" "3.887.0" + "@aws-sdk/middleware-logger" "3.887.0" + "@aws-sdk/middleware-recursion-detection" "3.887.0" + "@aws-sdk/middleware-sdk-s3" "3.888.0" + "@aws-sdk/middleware-ssec" "3.887.0" + "@aws-sdk/middleware-user-agent" "3.888.0" + "@aws-sdk/region-config-resolver" "3.887.0" + "@aws-sdk/signature-v4-multi-region" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-endpoints" "3.887.0" + "@aws-sdk/util-user-agent-browser" "3.887.0" + "@aws-sdk/util-user-agent-node" "3.888.0" + "@aws-sdk/xml-builder" "3.887.0" + "@smithy/config-resolver" "^4.2.1" + "@smithy/core" "^3.11.0" + "@smithy/eventstream-serde-browser" "^4.1.1" + "@smithy/eventstream-serde-config-resolver" "^4.2.1" + "@smithy/eventstream-serde-node" "^4.1.1" + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/hash-blob-browser" "^4.1.1" + "@smithy/hash-node" "^4.1.1" + "@smithy/hash-stream-node" "^4.1.1" + "@smithy/invalid-dependency" "^4.1.1" + "@smithy/md5-js" "^4.1.1" + "@smithy/middleware-content-length" "^4.1.1" + "@smithy/middleware-endpoint" "^4.2.1" + "@smithy/middleware-retry" "^4.2.1" + "@smithy/middleware-serde" "^4.1.1" + "@smithy/middleware-stack" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-body-length-node" "^4.1.0" + "@smithy/util-defaults-mode-browser" "^4.1.1" + "@smithy/util-defaults-mode-node" "^4.1.1" + "@smithy/util-endpoints" "^3.1.1" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-retry" "^4.1.1" + "@smithy/util-stream" "^4.3.1" + "@smithy/util-utf8" "^4.1.0" + "@smithy/util-waiter" "^4.1.1" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + +"@aws-sdk/client-sso@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.888.0.tgz#ab161ff13de9bf43b641df9d04172150761f8418" + integrity sha512-8CLy/ehGKUmekjH+VtZJ4w40PqDg3u0K7uPziq/4P8Q7LLgsy8YQoHNbuY4am7JU3HWrqLXJI9aaz1+vPGPoWA== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.888.0" + "@aws-sdk/middleware-host-header" "3.887.0" + "@aws-sdk/middleware-logger" "3.887.0" + "@aws-sdk/middleware-recursion-detection" "3.887.0" + "@aws-sdk/middleware-user-agent" "3.888.0" + "@aws-sdk/region-config-resolver" "3.887.0" + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-endpoints" "3.887.0" + "@aws-sdk/util-user-agent-browser" "3.887.0" + "@aws-sdk/util-user-agent-node" "3.888.0" + "@smithy/config-resolver" "^4.2.1" + "@smithy/core" "^3.11.0" + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/hash-node" "^4.1.1" + "@smithy/invalid-dependency" "^4.1.1" + "@smithy/middleware-content-length" "^4.1.1" + "@smithy/middleware-endpoint" "^4.2.1" + "@smithy/middleware-retry" "^4.2.1" + "@smithy/middleware-serde" "^4.1.1" + "@smithy/middleware-stack" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-body-length-node" "^4.1.0" + "@smithy/util-defaults-mode-browser" "^4.1.1" + "@smithy/util-defaults-mode-node" "^4.1.1" + "@smithy/util-endpoints" "^3.1.1" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-retry" "^4.1.1" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.888.0.tgz#d0b9115d5b79b515a0435ff59ad721195bcb55a8" + integrity sha512-L3S2FZywACo4lmWv37Y4TbefuPJ1fXWyWwIJ3J4wkPYFJ47mmtUPqThlVrSbdTHkEjnZgJe5cRfxk0qCLsFh1w== + dependencies: + "@aws-sdk/types" "3.887.0" + "@aws-sdk/xml-builder" "3.887.0" + "@smithy/core" "^3.11.0" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/property-provider" "^4.0.5" + "@smithy/protocol-http" "^5.2.1" + "@smithy/signature-v4" "^5.1.3" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-utf8" "^4.1.0" + fast-xml-parser "5.2.5" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.888.0.tgz#20bd28d5ea79d5254829700d9230e0d1a360fdbd" + integrity sha512-shPi4AhUKbIk7LugJWvNpeZA8va7e5bOHAEKo89S0Ac8WDZt2OaNzbh/b9l0iSL2eEyte8UgIsYGcFxOwIF1VA== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.888.0.tgz#e32ff8223dbe090bcf004bcc58ec1b676043ccac" + integrity sha512-Jvuk6nul0lE7o5qlQutcqlySBHLXOyoPtiwE6zyKbGc7RVl0//h39Lab7zMeY2drMn8xAnIopL4606Fd8JI/Hw== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/property-provider" "^4.0.5" + "@smithy/protocol-http" "^5.2.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/util-stream" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.888.0.tgz#4a97261b8593c3c8c8e5bac974ba0e5e0a40d89f" + integrity sha512-M82ItvS5yq+tO6ZOV1ruaVs2xOne+v8HW85GFCXnz8pecrzYdgxh6IsVqEbbWruryG/mUGkWMbkBZoEsy4MgyA== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/credential-provider-env" "3.888.0" + "@aws-sdk/credential-provider-http" "3.888.0" + "@aws-sdk/credential-provider-process" "3.888.0" + "@aws-sdk/credential-provider-sso" "3.888.0" + "@aws-sdk/credential-provider-web-identity" "3.888.0" + "@aws-sdk/nested-clients" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/credential-provider-imds" "^4.0.7" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.888.0.tgz#48f769d52d999088d4437dc1bc76af55afecad9b" + integrity sha512-KCrQh1dCDC8Y+Ap3SZa6S81kHk+p+yAaOQ5jC3dak4zhHW3RCrsGR/jYdemTOgbEGcA6ye51UbhWfrrlMmeJSA== + dependencies: + "@aws-sdk/credential-provider-env" "3.888.0" + "@aws-sdk/credential-provider-http" "3.888.0" + "@aws-sdk/credential-provider-ini" "3.888.0" + "@aws-sdk/credential-provider-process" "3.888.0" + "@aws-sdk/credential-provider-sso" "3.888.0" + "@aws-sdk/credential-provider-web-identity" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/credential-provider-imds" "^4.0.7" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.888.0.tgz#34842315e44b4882c63eb92fa2151c2efaf5401f" + integrity sha512-+aX6piSukPQ8DUS4JAH344GePg8/+Q1t0+kvSHAZHhYvtQ/1Zek3ySOJWH2TuzTPCafY4nmWLcQcqvU1w9+4Lw== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.888.0.tgz#85956b3bcebbcb1aee096d07b4365e524dc1b985" + integrity sha512-b1ZJji7LJ6E/j1PhFTyvp51in2iCOQ3VP6mj5H6f5OUnqn7efm41iNMoinKr87n0IKZw7qput5ggXVxEdPhouA== + dependencies: + "@aws-sdk/client-sso" "3.888.0" + "@aws-sdk/core" "3.888.0" + "@aws-sdk/token-providers" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.888.0.tgz#03de49dca86649ae2061247ee4d2831642a4767f" + integrity sha512-7P0QNtsDzMZdmBAaY/vY1BsZHwTGvEz3bsn2bm5VSKFAeMmZqsHK1QeYdNsFjLtegnVh+wodxMq50jqLv3LFlA== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/nested-clients" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.887.0.tgz#a89331e130effd1ee35dec309b8163fb4a9d4920" + integrity sha512-qRCte/3MtNiMhPh4ZEGk9cHfAXq6IDTflvi2t1tkOIVZFyshkSCvNQNJrrE2D/ljVbOK1f3XbBDaF43EoQzIRQ== + dependencies: + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-arn-parser" "3.873.0" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-config-provider" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.887.0.tgz#cc52bc31752875a8d3dfa84a5705e2b563ffc39f" + integrity sha512-AlrTZZScDTG9SYeT82BC5cK/6Q4N0miN5xqMW/pbBqP3fNXlsdJOWKB+EKD3V6DV41EV5GVKHKe/1065xKSQ4w== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.888.0.tgz#b66da7fe00fe980a9274bc36bd56190a218a4314" + integrity sha512-vdwd4wMAlXSg1bldhXyTsDSnyPP+bbEVihapejGKNd4gLfyyHwjTfbli+B/hEONGttQs5Dp54UMn8yW/UA189g== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-crypto/util" "5.2.0" + "@aws-sdk/core" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/is-array-buffer" "^4.0.0" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-stream" "^4.3.1" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.887.0.tgz#765305b5a2c412e6bf53eb6d557f2ab831ff50a7" + integrity sha512-ulzqXv6NNqdu/kr0sgBYupWmahISHY+azpJidtK6ZwQIC+vBUk9NdZeqQpy7KVhIk2xd4+5Oq9rxapPwPI21CA== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.887.0.tgz#fdf76f587c04cc8d755f05e41d4df65a78b34127" + integrity sha512-eU/9Cq4gg2sS32bOomxdx2YF43kb+o70pMhnEBBnVVeqzE8co78SO5FQdWfRTfhNJgTyQ6Vgosx//CNMPIfZPg== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.887.0.tgz#fec1c731d158306425897b371cfabdf188d07f12" + integrity sha512-YbbgLI6jKp2qSoAcHnXrQ5jcuc5EYAmGLVFgMVdk8dfCfJLfGGSaOLxF4CXC7QYhO50s+mPPkhBYejCik02Kug== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.887.0.tgz#4fdb1039042565a4ba0ff506584a99f3c7c3fd23" + integrity sha512-tjrUXFtQnFLo+qwMveq5faxP5MQakoLArXtqieHphSqZTXm21wDJM73hgT4/PQQGTwgYjDKqnqsE1hvk0hcfDw== + dependencies: + "@aws-sdk/types" "3.887.0" + "@aws/lambda-invoke-store" "^0.0.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.888.0.tgz#9e561338d9d036a5bf8252b578222b351b635ea1" + integrity sha512-rKOFNfqgqOfrdcLGF8fcO75azWS2aq2ksRHFoIEFru5FJxzu/yDAhY4C2FKiP/X34xeIUS2SbE/gQgrgWHSN2g== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-arn-parser" "3.873.0" + "@smithy/core" "^3.11.0" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/signature-v4" "^5.1.3" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-stream" "^4.3.1" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.887.0.tgz#861a3bdb2e0565d492a0869651a348ff36ac5faf" + integrity sha512-1ixZks0IDkdac1hjPe4vdLSuD9HznkhblCEb4T0wNyw3Ee1fdXg+MlcPWywzG5zkPXLcIrULUzJg/OSYfaDXcQ== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.888.0.tgz#8b7f8ed11120fd1b931b09de12f7846f72bfe538" + integrity sha512-ZkcUkoys8AdrNNG7ATjqw2WiXqrhTvT+r4CIK3KhOqIGPHX0p0DQWzqjaIl7ZhSUToKoZ4Ud7MjF795yUr73oA== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-endpoints" "3.887.0" + "@smithy/core" "^3.11.0" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/nested-clients@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.888.0.tgz#5c3ea2517bf05caf4bd699e731f97bf5e565f397" + integrity sha512-py4o4RPSGt+uwGvSBzR6S6cCBjS4oTX5F8hrHFHfPCdIOMVjyOBejn820jXkCrcdpSj3Qg1yUZXxsByvxc9Lyg== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.888.0" + "@aws-sdk/middleware-host-header" "3.887.0" + "@aws-sdk/middleware-logger" "3.887.0" + "@aws-sdk/middleware-recursion-detection" "3.887.0" + "@aws-sdk/middleware-user-agent" "3.888.0" + "@aws-sdk/region-config-resolver" "3.887.0" + "@aws-sdk/types" "3.887.0" + "@aws-sdk/util-endpoints" "3.887.0" + "@aws-sdk/util-user-agent-browser" "3.887.0" + "@aws-sdk/util-user-agent-node" "3.888.0" + "@smithy/config-resolver" "^4.2.1" + "@smithy/core" "^3.11.0" + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/hash-node" "^4.1.1" + "@smithy/invalid-dependency" "^4.1.1" + "@smithy/middleware-content-length" "^4.1.1" + "@smithy/middleware-endpoint" "^4.2.1" + "@smithy/middleware-retry" "^4.2.1" + "@smithy/middleware-serde" "^4.1.1" + "@smithy/middleware-stack" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-body-length-node" "^4.1.0" + "@smithy/util-defaults-mode-browser" "^4.1.1" + "@smithy/util-defaults-mode-node" "^4.1.1" + "@smithy/util-endpoints" "^3.1.1" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-retry" "^4.1.1" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.887.0.tgz#5e89768b44cd5e5c624852ade958579144ac2eb5" + integrity sha512-VdSMrIqJ3yjJb/fY+YAxrH/lCVv0iL8uA+lbMNfQGtO5tB3Zx6SU9LEpUwBNX8fPK1tUpI65CNE4w42+MY/7Mg== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.1.1" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.888.0.tgz#27336bd763746daa3513a8a72436754a370fccce" + integrity sha512-FmOHUaJzEhqfcpyh0L7HLwYcYopK13Dbmuf+oUyu56/RoeB1nLnltH1VMQVj8v3Am2IwlGR+/JpFyrdkErN+cA== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/protocol-http" "^5.2.1" + "@smithy/signature-v4" "^5.1.3" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.888.0.tgz#db79f49c8999c93abab321fbab4e2e6920738b93" + integrity sha512-WA3NF+3W8GEuCMG1WvkDYbB4z10G3O8xuhT7QSjhvLYWQ9CPt3w4VpVIfdqmUn131TCIbhCzD0KN/1VJTjAjyw== + dependencies: + "@aws-sdk/core" "3.888.0" + "@aws-sdk/nested-clients" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/types@3.887.0", "@aws-sdk/types@^3.222.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.887.0.tgz#989f3b67d7ddb97443e4bdb80ad2313c604b240d" + integrity sha512-fmTEJpUhsPsovQ12vZSpVTEP/IaRoJAMBGQXlQNjtCpkBp6Iq3KQDa/HDaPINE+3xxo6XvTdtibsNOd5zJLV9A== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.873.0.tgz#12c5ea852574dfb6fe78eaac1666433dff1acffa" + integrity sha512-qag+VTqnJWDn8zTAXX4wiVioa0hZDQMtbZcGRERVnLar4/3/VIKBhxX2XibNQXFu1ufgcRn4YntT/XEPecFWcg== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.887.0.tgz#e4f2dfb608360b6d8b4e3793492d4625dba00275" + integrity sha512-kpegvT53KT33BMeIcGLPA65CQVxLUL/C3gTz9AzlU/SDmeusBHX4nRApAicNzI/ltQ5lxZXbQn18UczzBuwF1w== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-endpoints" "^3.1.1" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.873.0.tgz#cc10edef3b7aecf365943ec657116d6eb470d9cb" + integrity sha512-xcVhZF6svjM5Rj89T1WzkjQmrTF6dpR2UvIHPMTnSZoNe6CixejPZ6f0JJ2kAhO8H+dUHwNBlsUgOTIKiK/Syg== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.887.0.tgz#1c5ccc82a0b31a4b159ad98cb12abda1e6c422c8" + integrity sha512-X71UmVsYc6ZTH4KU6hA5urOzYowSXc3qvroagJNLJYU1ilgZ529lP4J9XOYfEvTXkLR1hPFSRxa43SrwgelMjA== + dependencies: + "@aws-sdk/types" "3.887.0" + "@smithy/types" "^4.5.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.888.0": + version "3.888.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.888.0.tgz#45c871429c7742cf73f570fbc39ef17f4d12e8de" + integrity sha512-rSB3OHyuKXotIGfYEo//9sU0lXAUrTY28SUUnxzOGYuQsAt0XR5iYwBAp+RjV6x8f+Hmtbg0PdCsy1iNAXa0UQ== + dependencies: + "@aws-sdk/middleware-user-agent" "3.888.0" + "@aws-sdk/types" "3.887.0" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@3.887.0": + version "3.887.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.887.0.tgz#376754d19384bbe5b8139c0a0e6521a4a6500c67" + integrity sha512-lMwgWK1kNgUhHGfBvO/5uLe7TKhycwOn3eRCqsKPT9aPCx/HWuTlpcQp8oW2pCRGLS7qzcxqpQulcD+bbUL7XQ== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@aws/lambda-invoke-store@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@aws/lambda-invoke-store/-/lambda-invoke-store-0.0.1.tgz#92d792a7dda250dfcb902e13228f37a81be57c8f" + integrity sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw== + +"@azure/abort-controller@^2.0.0", "@azure/abort-controller@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz#42fe0ccab23841d9905812c58f1082d27784566d" + integrity sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA== + dependencies: + tslib "^2.6.2" + +"@azure/core-auth@^1.10.0", "@azure/core-auth@^1.9.0": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.10.1.tgz#68a17fa861ebd14f6fd314055798355ef6bedf1b" + integrity sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-util" "^1.13.0" + tslib "^2.6.2" + +"@azure/core-client@^1.10.0", "@azure/core-client@^1.9.3": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@azure/core-client/-/core-client-1.10.1.tgz#83d78f97d647ab22e6811a7a68bb4223e7a1d019" + integrity sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-auth" "^1.10.0" + "@azure/core-rest-pipeline" "^1.22.0" + "@azure/core-tracing" "^1.3.0" + "@azure/core-util" "^1.13.0" + "@azure/logger" "^1.3.0" + tslib "^2.6.2" + +"@azure/core-http-compat@^2.0.0", "@azure/core-http-compat@^2.2.0": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@azure/core-http-compat/-/core-http-compat-2.3.1.tgz#2182e39a31c062800d4e3ad69bcf0109d87713dc" + integrity sha512-az9BkXND3/d5VgdRRQVkiJb2gOmDU8Qcq4GvjtBmDICNiQ9udFmDk4ZpSB5Qq1OmtDJGlQAfBaS4palFsazQ5g== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-client" "^1.10.0" + "@azure/core-rest-pipeline" "^1.22.0" + +"@azure/core-lro@^2.2.0": + version "2.7.2" + resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.7.2.tgz#787105027a20e45c77651a98b01a4d3b01b75a08" + integrity sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw== + dependencies: + "@azure/abort-controller" "^2.0.0" + "@azure/core-util" "^1.2.0" + "@azure/logger" "^1.0.0" + tslib "^2.6.2" + +"@azure/core-paging@^1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.6.2.tgz#40d3860dc2df7f291d66350b2cfd9171526433e7" + integrity sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA== + dependencies: + tslib "^2.6.2" + +"@azure/core-rest-pipeline@^1.19.1", "@azure/core-rest-pipeline@^1.22.0": + version "1.22.1" + resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.1.tgz#f47bc02ff9a79f62e6a32aa375420b1b86dcbccd" + integrity sha512-UVZlVLfLyz6g3Hy7GNDpooMQonUygH7ghdiSASOOHy97fKj/mPLqgDX7aidOijn+sCMU+WU8NjlPlNTgnvbcGA== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-auth" "^1.10.0" + "@azure/core-tracing" "^1.3.0" + "@azure/core-util" "^1.13.0" + "@azure/logger" "^1.3.0" + "@typespec/ts-http-runtime" "^0.3.0" + tslib "^2.6.2" + +"@azure/core-tracing@^1.2.0", "@azure/core-tracing@^1.3.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.3.1.tgz#e971045c901ea9c110616b0e1db272507781d5f6" + integrity sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ== + dependencies: + tslib "^2.6.2" + +"@azure/core-util@^1.11.0", "@azure/core-util@^1.13.0", "@azure/core-util@^1.2.0": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.13.1.tgz#6dff2ff6d3c9c6430c6f4d3b3e65de531f10bafe" + integrity sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@typespec/ts-http-runtime" "^0.3.0" + tslib "^2.6.2" + +"@azure/core-xml@^1.4.3", "@azure/core-xml@^1.4.5": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-xml/-/core-xml-1.5.0.tgz#cd82d511d7bcc548d206f5627c39724c5d5a4434" + integrity sha512-D/sdlJBMJfx7gqoj66PKVmhDDaU6TKA49ptcolxdas29X7AfvLTmfAGLjAcIMBK7UZ2o4lygHIqVckOlQU3xWw== + dependencies: + fast-xml-parser "^5.0.7" + tslib "^2.8.1" + +"@azure/logger@^1.0.0", "@azure/logger@^1.1.4", "@azure/logger@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.3.0.tgz#5501cf85d4f52630602a8cc75df76568c969a827" + integrity sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA== + dependencies: + "@typespec/ts-http-runtime" "^0.3.0" + tslib "^2.6.2" + +"@azure/storage-blob@^12.28.0": + version "12.28.0" + resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.28.0.tgz#a64ce49f0fe9fe08f1f7c1b36164033678d38cf6" + integrity sha512-VhQHITXXO03SURhDiGuHhvc/k/sD2WvJUS7hqhiVNbErVCuQoLtWql7r97fleBlIRKHJaa9R7DpBjfE0pfLYcA== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-auth" "^1.9.0" + "@azure/core-client" "^1.9.3" + "@azure/core-http-compat" "^2.2.0" + "@azure/core-lro" "^2.2.0" + "@azure/core-paging" "^1.6.2" + "@azure/core-rest-pipeline" "^1.19.1" + "@azure/core-tracing" "^1.2.0" + "@azure/core-util" "^1.11.0" + "@azure/core-xml" "^1.4.5" + "@azure/logger" "^1.1.4" + "@azure/storage-common" "^12.0.0-beta.2" + events "^3.0.0" + tslib "^2.8.1" + +"@azure/storage-common@^12.0.0", "@azure/storage-common@^12.0.0-beta.2": + version "12.0.0" + resolved "https://registry.yarnpkg.com/@azure/storage-common/-/storage-common-12.0.0.tgz#a652d7daeb252b7827362b4e818f52fee15a1264" + integrity sha512-QyEWXgi4kdRo0wc1rHum9/KnaWZKCdQGZK1BjU4fFL6Jtedp7KLbQihgTTVxldFy1z1ZPtuDPx8mQ5l3huPPbA== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-auth" "^1.9.0" + "@azure/core-http-compat" "^2.2.0" + "@azure/core-rest-pipeline" "^1.19.1" + "@azure/core-tracing" "^1.2.0" + "@azure/core-util" "^1.11.0" + "@azure/logger" "^1.1.4" + events "^3.3.0" + tslib "^2.8.1" + +"@azure/storage-queue@^12.27.0": + version "12.27.0" + resolved "https://registry.yarnpkg.com/@azure/storage-queue/-/storage-queue-12.27.0.tgz#cde0c3560b08320ed61e813132d27de716c45973" + integrity sha512-GoviVZrJ1BkYCmsam0gOZFqAjH7bKbnbBIEVPkgzCz3RzsB/C05jumQep+3GavZoWw7Yw4iaCNPSyyS1lbN1Gg== + dependencies: + "@azure/abort-controller" "^2.1.2" + "@azure/core-auth" "^1.9.0" + "@azure/core-client" "^1.9.3" + "@azure/core-http-compat" "^2.0.0" + "@azure/core-paging" "^1.6.2" + "@azure/core-rest-pipeline" "^1.19.1" + "@azure/core-tracing" "^1.2.0" + "@azure/core-util" "^1.11.0" + "@azure/core-xml" "^1.4.3" + "@azure/logger" "^1.1.4" + "@azure/storage-common" "^12.0.0" + tslib "^2.8.1" + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.8.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.5.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/compat@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@eslint/compat/-/compat-1.3.2.tgz#1a8766e447fad3d091b1a88b9f78f867832285b7" + integrity sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA== + +"@eslint/config-array@^0.21.0": + version "0.21.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.0.tgz#abdbcbd16b124c638081766392a4d6b509f72636" + integrity sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.3.1.tgz#d316e47905bd0a1a931fa50e669b9af4104d1617" + integrity sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA== + +"@eslint/core@^0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.15.2.tgz#59386327d7862cc3603ebc7c78159d2dcc4a868f" + integrity sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.35.0": + version "9.35.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.35.0.tgz#ffbc7e13cf1204db18552e9cd9d4a8e17c692d07" + integrity sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw== + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz#fd8764f0ee79c8ddab4da65460c641cefee017c5" + integrity sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w== + dependencies: + "@eslint/core" "^0.15.2" + levn "^0.4.1" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jsep-plugin/assignment@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" + integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== + +"@jsep-plugin/regex@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" + integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== + +"@kubernetes/client-node@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-1.3.0.tgz#6088bc1c4f6bb01f52e6e933f35008feb39fe909" + integrity sha512-IE0yrIpOT97YS5fg2QpzmPzm8Wmcdf4ueWMn+FiJSI3jgTTQT1u+LUhoYpdfhdHAVxdrNsaBg2C0UXSnOgMoCQ== + dependencies: + "@types/js-yaml" "^4.0.1" + "@types/node" "^22.0.0" + "@types/node-fetch" "^2.6.9" + "@types/stream-buffers" "^3.0.3" + form-data "^4.0.0" + hpagent "^1.2.0" + isomorphic-ws "^5.0.0" + js-yaml "^4.1.0" + jsonpath-plus "^10.3.0" + node-fetch "^2.6.9" + openid-client "^6.1.3" + rfc4648 "^1.3.0" + socks-proxy-agent "^8.0.4" + stream-buffers "^3.0.2" + tar-fs "^3.0.8" + ws "^8.18.2" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@smithy/abort-controller@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-4.1.1.tgz#9b3872ab6b2c061486175c281dadc0a853260533" + integrity sha512-vkzula+IwRvPR6oKQhMYioM3A/oX/lFCZiwuxkQbRhqJS2S4YRY2k7k/SyR2jMf3607HLtbEwlRxi0ndXHMjRg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.1.0.tgz#4d814dd07ebb1f579daf51671945389f9772400f" + integrity sha512-Bnv0B3nSlfB2mPO0WgM49I/prl7+kamF042rrf3ezJ3Z4C7csPYvyYgZfXTGXwXfj1mAwDWjE/ybIf49PzFzvA== + dependencies: + "@smithy/util-base64" "^4.1.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.1.0.tgz#48fa62c85b146be2a06525f0457ce58a46d69ab0" + integrity sha512-a36AtR7Q7XOhRPt6F/7HENmTWcB8kN7mDJcOFM/+FuKO6x88w8MQJfYCufMWh4fGyVkPjUh3Rrz/dnqFQdo6OQ== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-4.2.1.tgz#12c24e550e2675e03a78bec64a652ed129bce718" + integrity sha512-FXil8q4QN7mgKwU2hCLm0ltab8NyY/1RiqEf25Jnf6WLS3wmb11zGAoLETqg1nur2Aoibun4w4MjeN9CMJ4G6A== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-config-provider" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + tslib "^2.6.2" + +"@smithy/core@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.11.0.tgz#18ee04696ca35889046169e422a894bea1bec59d" + integrity sha512-Abs5rdP1o8/OINtE49wwNeWuynCu0kme1r4RI3VXVrHr4odVDG7h7mTnw1WXXfN5Il+c25QOnrdL2y56USfxkA== + dependencies: + "@smithy/middleware-serde" "^4.1.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-stream" "^4.3.1" + "@smithy/util-utf8" "^4.1.0" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/credential-provider-imds@^4.0.7", "@smithy/credential-provider-imds@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-4.1.1.tgz#e1535a0121a98a2d872eaffc2470eccc057cebd5" + integrity sha512-1WdBfM9DwA59pnpIizxnUvBf/de18p4GP+6zP2AqrlFzoW3ERpZaT4QueBR0nS9deDMaQRkBlngpVlnkuuTisQ== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/property-provider" "^4.1.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-4.1.1.tgz#637eb4bceecc3ef588b86c28506439a9cdd7a41f" + integrity sha512-PwkQw1hZwHTQB6X5hSUWz2OSeuj5Z6enWuAqke7DgWoP3t6vg3ktPpqPz3Erkn6w+tmsl8Oss6nrgyezoea2Iw== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^4.5.0" + "@smithy/util-hex-encoding" "^4.1.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.1.1.tgz#f7df13ebd5a6028b12b496f12eecdd08c4c9b792" + integrity sha512-Q9QWdAzRaIuVkefupRPRFAasaG/droBqn1feiMnmLa+LLEUG45pqX1+FurHFmlqiCfobB3nUlgoJfeXZsr7MPA== + dependencies: + "@smithy/eventstream-serde-universal" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.2.1.tgz#77333a110361bfe2749b685d31e01299ede87c40" + integrity sha512-oSUkF9zDN9zcOUBMtxp8RewJlh71E9NoHWU8jE3hU9JMYCsmW4assVTpgic/iS3/dM317j6hO5x18cc3XrfvEw== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.1.1.tgz#635819a756cb8a69a7e3eb91ca9076284ea00939" + integrity sha512-tn6vulwf/ScY0vjhzptSJuDJJqlhNtUjkxJ4wiv9E3SPoEqTEKbaq6bfqRO7nvhTG29ALICRcvfFheOUPl8KNA== + dependencies: + "@smithy/eventstream-serde-universal" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.1.1.tgz#803cdde6a17ac501cc700ce38400caf70715ecb1" + integrity sha512-uLOAiM/Dmgh2CbEXQx+6/ssK7fbzFhd+LjdyFxXid5ZBCbLHTFHLdD/QbXw5aEDsLxQhgzDxLLsZhsftAYwHJA== + dependencies: + "@smithy/eventstream-codec" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.2.1.tgz#fe284a00f1b3a35edf9fba454d287b7f74ef20af" + integrity sha512-5/3wxKNtV3wO/hk1is+CZUhL8a1yy/U+9u9LKQ9kZTkMsHaQjJhc3stFfiujtMnkITjzWfndGA2f7g9Uh9vKng== + dependencies: + "@smithy/protocol-http" "^5.2.1" + "@smithy/querystring-builder" "^4.1.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-4.1.1.tgz#fbcab0008b973ccf370c698cd11ec8d9584607c8" + integrity sha512-avAtk++s1e/1VODf+rg7c9R2pB5G9y8yaJaGY4lPZI2+UIqVyuSDMikWjeWfBVmFZ3O7NpDxBbUCyGhThVUKWQ== + dependencies: + "@smithy/chunked-blob-reader" "^5.1.0" + "@smithy/chunked-blob-reader-native" "^4.1.0" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/hash-node@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-4.1.1.tgz#86ceca92487492267e944e4f4507106b731e7971" + integrity sha512-H9DIU9WBLhYrvPs9v4sYvnZ1PiAI0oc8CgNQUJ1rpN3pP7QADbTOUjchI2FB764Ub0DstH5xbTqcMJu1pnVqxA== + dependencies: + "@smithy/types" "^4.5.0" + "@smithy/util-buffer-from" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-4.1.1.tgz#1d8e4485fa15c458d7a8248a50d0f5f91705cced" + integrity sha512-3ztT4pV0Moazs3JAYFdfKk11kYFDo4b/3R3+xVjIm6wY9YpJf+xfz+ocEnNKcWAdcmSMqi168i2EMaKmJHbJMA== + dependencies: + "@smithy/types" "^4.5.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-4.1.1.tgz#2511335ff889944701c7d2a3b1e4a4d6fe9ddfab" + integrity sha512-1AqLyFlfrrDkyES8uhINRlJXmHA2FkG+3DY8X+rmLSqmFwk3DJnvhyGzyByPyewh2jbmV+TYQBEfngQax8IFGg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^4.0.0", "@smithy/is-array-buffer@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-4.1.0.tgz#d18a2f22280e7173633cb91a9bdb6f3d8a6560b8" + integrity sha512-ePTYUOV54wMogio+he4pBybe8fwg4sDvEVDBU8ZlHOZXbXK3/C0XfJgUCu6qAZcawv05ZhZzODGUerFBPsPUDQ== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-4.1.1.tgz#df81396bef83eb17bce531c871af935df986bdfc" + integrity sha512-MvWXKK743BuHjr/hnWuT6uStdKEaoqxHAQUvbKJPPZM5ZojTNFI5D+47BoQfBE5RgGlRRty05EbWA+NXDv+hIA== + dependencies: + "@smithy/types" "^4.5.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-4.1.1.tgz#eaea7bd14c7a0b64aef87b8c372c2a04d7b9cb72" + integrity sha512-9wlfBBgTsRvC2JxLJxv4xDGNBrZuio3AgSl0lSFX7fneW2cGskXTYpFxCdRYD2+5yzmsiTuaAJD1Wp7gWt9y9w== + dependencies: + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.2.1.tgz#54c61a113e6da7b615724d03517879d377d3888d" + integrity sha512-fUTMmQvQQZakXOuKizfu7fBLDpwvWZjfH6zUK2OLsoNZRZGbNUdNSdLJHpwk1vS208jtDjpUIskh+JoA8zMzZg== + dependencies: + "@smithy/core" "^3.11.0" + "@smithy/middleware-serde" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/shared-ini-file-loader" "^4.1.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-middleware" "^4.1.1" + tslib "^2.6.2" + +"@smithy/middleware-retry@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.2.1.tgz#61be10c06e183c392a3769cb8b03c7846b37bee7" + integrity sha512-JzfvjwSJXWRl7LkLgIRTUTd2Wj639yr3sQGpViGNEOjtb0AkAuYqRAHs+jSOI/LPC0ZTjmFVVtfrCICMuebexw== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/service-error-classification" "^4.1.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-retry" "^4.1.1" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-4.1.1.tgz#cfb99f53c744d7730928235cbe66cc7ff8a8a9b2" + integrity sha512-lh48uQdbCoj619kRouev5XbWhCwRKLmphAif16c4J6JgJ4uXjub1PI6RL38d3BLliUvSso6klyB/LTNpWSNIyg== + dependencies: + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-4.1.1.tgz#1d533fde4ccbb62d7fc0f0b8ac518b7e4791e311" + integrity sha512-ygRnniqNcDhHzs6QAPIdia26M7e7z9gpkIMUe/pK0RsrQ7i5MblwxY8078/QCnGq6AmlUUWgljK2HlelsKIb/A== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-4.2.1.tgz#31be8865dbea9a9f23aee278a6728317d0ed0250" + integrity sha512-AIA0BJZq2h295J5NeCTKhg1WwtdTA/GqBCaVjk30bDgMHwniUETyh5cP9IiE9VrId7Kt8hS7zvREVMTv1VfA6g== + dependencies: + "@smithy/property-provider" "^4.1.1" + "@smithy/shared-ini-file-loader" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.2.1.tgz#d7ab8e31659030d3d5a68f0982f15c00b1e67a0c" + integrity sha512-REyybygHlxo3TJICPF89N2pMQSf+p+tBJqpVe1+77Cfi9HBPReNjTgtZ1Vg73exq24vkqJskKDpfF74reXjxfw== + dependencies: + "@smithy/abort-controller" "^4.1.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/querystring-builder" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/property-provider@^4.0.5", "@smithy/property-provider@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-4.1.1.tgz#6e11ae6729840314afed05fd6ab48f62c654116b" + integrity sha512-gm3ZS7DHxUbzC2wr8MUCsAabyiXY0gaj3ROWnhSx/9sPMc6eYLMM4rX81w1zsMaObj2Lq3PZtNCC1J6lpEY7zg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-5.2.1.tgz#33f2b8e4e1082c3ae0372d1322577e6fa71d7824" + integrity sha512-T8SlkLYCwfT/6m33SIU/JOVGNwoelkrvGjFKDSDtVvAXj/9gOT78JVJEas5a+ETjOu4SVvpCstKgd0PxSu/aHw== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-4.1.1.tgz#4d35c1735de8214055424045a117fa5d1d5cdec1" + integrity sha512-J9b55bfimP4z/Jg1gNo+AT84hr90p716/nvxDkPGCD4W70MPms0h8KF50RDRgBGZeL83/u59DWNqJv6tEP/DHA== + dependencies: + "@smithy/types" "^4.5.0" + "@smithy/util-uri-escape" "^4.1.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-4.1.1.tgz#21b861439b2db16abeb0a6789b126705fa25eea1" + integrity sha512-63TEp92YFz0oQ7Pj9IuI3IgnprP92LrZtRAkE3c6wLWJxfy/yOPRt39IOKerVr0JS770olzl0kGafXlAXZ1vng== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-4.1.1.tgz#86a615298ae406c3b6c7dc63c1c1738c54cfdfc6" + integrity sha512-Iam75b/JNXyDE41UvrlM6n8DNOa/r1ylFyvgruTUx7h2Uk7vDNV9AAwP1vfL1fOL8ls0xArwEGVcGZVd7IO/Cw== + dependencies: + "@smithy/types" "^4.5.0" + +"@smithy/shared-ini-file-loader@^4.0.5", "@smithy/shared-ini-file-loader@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.1.1.tgz#d4a748bb8027e1111635464c9b1e546d608fc089" + integrity sha512-YkpikhIqGc4sfXeIbzSj10t2bJI/sSoP5qxLue6zG+tEE3ngOBSm8sO3+djacYvS/R5DfpxN/L9CyZsvwjWOAQ== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^5.1.3": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-5.2.1.tgz#0048489d2f1b3c888382595a085edd31967498f8" + integrity sha512-M9rZhWQLjlQVCCR37cSjHfhriGRN+FQ8UfgrYNufv66TJgk+acaggShl3KS5U/ssxivvZLlnj7QH2CUOKlxPyA== + dependencies: + "@smithy/is-array-buffer" "^4.1.0" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-hex-encoding" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-uri-escape" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.6.1.tgz#4bebcf313431bd274da0b28c7ddc4ba335f9994b" + integrity sha512-WolVLDb9UTPMEPPOncrCt6JmAMCSC/V2y5gst2STWJ5r7+8iNac+EFYQnmvDCYMfOLcilOSEpm5yXZXwbLak1Q== + dependencies: + "@smithy/core" "^3.11.0" + "@smithy/middleware-endpoint" "^4.2.1" + "@smithy/middleware-stack" "^4.1.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-stream" "^4.3.1" + tslib "^2.6.2" + +"@smithy/types@^4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.5.0.tgz#850e334662a1ef1286c35814940c80880400a370" + integrity sha512-RkUpIOsVlAwUIZXO1dsz8Zm+N72LClFfsNqf173catVlvRZiwPy0x2u0JLEA4byreOPKDZPGjmPDylMoP8ZJRg== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-4.1.1.tgz#0e9a5e72b3cf9d7ab7305f9093af5528d9debaf6" + integrity sha512-bx32FUpkhcaKlEoOMbScvc93isaSiRM75pQ5IgIBaMkT7qMlIibpPRONyx/0CvrXHzJLpOn/u6YiDX2hcvs7Dg== + dependencies: + "@smithy/querystring-parser" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/util-base64@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-4.1.0.tgz#5965026081d9aef4a8246f5702807570abe538b2" + integrity sha512-RUGd4wNb8GeW7xk+AY5ghGnIwM96V0l2uzvs/uVHf+tIuVX2WSvynk5CxNoBCsM2rQRSZElAo9rt3G5mJ/gktQ== + dependencies: + "@smithy/util-buffer-from" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-4.1.0.tgz#636bdf4bc878c546627dab4b9b0e4db31b475be7" + integrity sha512-V2E2Iez+bo6bUMOTENPr6eEmepdY8Hbs+Uc1vkDKgKNA/brTJqOW/ai3JO1BGj9GbCeLqw90pbbH7HFQyFotGQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-4.1.0.tgz#646750e4af58f97254a5d5cfeaba7d992f0152ec" + integrity sha512-BOI5dYjheZdgR9XiEM3HJcEMCXSoqbzu7CzIgYrx0UtmvtC3tC2iDGpJLsSRFffUpy8ymsg2ARMP5fR8mtuUQQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-4.1.0.tgz#21f9e644a0eb41226d92e4eff763f76a7db7e9cc" + integrity sha512-N6yXcjfe/E+xKEccWEKzK6M+crMrlwaCepKja0pNnlSkm6SjAeLKKA++er5Ba0I17gvKfN/ThV+ZOx/CntKTVw== + dependencies: + "@smithy/is-array-buffer" "^4.1.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^4.0.0", "@smithy/util-config-provider@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-4.1.0.tgz#6a07d73446c1e9a46d7a3c125f2a9301060bc957" + integrity sha512-swXz2vMjrP1ZusZWVTB/ai5gK+J8U0BWvP10v9fpcFvg+Xi/87LHvHfst2IgCs1i0v4qFZfGwCmeD/KNCdJZbQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.1.1.tgz#40b9659d6fc15aa1101e440d1a92579cb66ebfa3" + integrity sha512-hA1AKIHFUMa9Tl6q6y8p0pJ9aWHCCG8s57flmIyLE0W7HcJeYrYtnqXDcGnftvXEhdQnSexyegXnzzTGk8bKLA== + dependencies: + "@smithy/property-provider" "^4.1.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.1.1.tgz#bca834c5ee16949bf8d0db9ac7bf988ad0d3ce10" + integrity sha512-RGSpmoBrA+5D2WjwtK7tto6Pc2wO9KSXKLpLONhFZ8VyuCbqlLdiDAfuDTNY9AJe4JoE+Cx806cpTQQoQ71zPQ== + dependencies: + "@smithy/config-resolver" "^4.2.1" + "@smithy/credential-provider-imds" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/property-provider" "^4.1.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-3.1.1.tgz#62c7e10e3a685c9cbb4080220d9e819ee79be8ff" + integrity sha512-qB4R9kO0SetA11Rzu6MVGFIaGYX3p6SGGGfWwsKnC6nXIf0n/0AKVwRTsYsz9ToN8CeNNtNgQRwKFBndGJZdyw== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-4.1.0.tgz#9b27cf0c25d0de2c8ebfe75cc20df84e5014ccc9" + integrity sha512-1LcueNN5GYC4tr8mo14yVYbh/Ur8jHhWOxniZXii+1+ePiIbsLZ5fEI0QQGtbRRP5mOhmooos+rLmVASGGoq5w== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-4.1.1.tgz#e19749a127499c9bdada713a8afd807d92d846e2" + integrity sha512-CGmZ72mL29VMfESz7S6dekqzCh8ZISj3B+w0g1hZFXaOjGTVaSqfAEFAq8EGp8fUL+Q2l8aqNmt8U1tglTikeg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/util-retry@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-4.1.1.tgz#f4a99d9b0ffb9e4bb119ac5a24e54e54d891e22c" + integrity sha512-jGeybqEZ/LIordPLMh5bnmnoIgsqnp4IEimmUp5c5voZ8yx+5kAlN5+juyr7p+f7AtZTgvhmInQk4Q0UVbrZ0Q== + dependencies: + "@smithy/service-error-classification" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@smithy/util-stream@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.3.1.tgz#63cce0f09d99d75142c6dc8fe03e55ac0171de47" + integrity sha512-khKkW/Jqkgh6caxMWbMuox9+YfGlsk9OnHOYCGVEdYQb/XVzcORXHLYUubHmmda0pubEDncofUrPNniS9d+uAA== + dependencies: + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-buffer-from" "^4.1.0" + "@smithy/util-hex-encoding" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-4.1.0.tgz#ed4a5c498f1da07122ca1e3df4ca3e2c67c6c18a" + integrity sha512-b0EFQkq35K5NHUYxU72JuoheM6+pytEVUGlTwiFxWFpmddA+Bpz3LgsPRIpBk8lnPE47yT7AF2Egc3jVnKLuPg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-4.1.0.tgz#912c33c1a06913f39daa53da79cb8f7ab740d97b" + integrity sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ== + dependencies: + "@smithy/util-buffer-from" "^4.1.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-4.1.1.tgz#5b74429ca9e37f61838800b919d0063b1a865bef" + integrity sha512-PJBmyayrlfxM7nbqjomF4YcT1sApQwZio0NHSsT0EzhJqljRmvhzqZua43TyEs80nJk2Cn2FGPg/N8phH6KeCQ== + dependencies: + "@smithy/abort-controller" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@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/json-schema@^7.0.12", "@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node-fetch@^2.6.9": + version "2.6.13" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.13.tgz#e0c9b7b5edbdb1b50ce32c127e85e880872d56ee" + integrity sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw== + dependencies: + "@types/node" "*" + form-data "^4.0.4" + +"@types/node@*": + version "24.3.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.3.1.tgz#b0a3fb2afed0ef98e8d7f06d46ef6349047709f3" + integrity sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g== + dependencies: + undici-types "~7.10.0" + +"@types/node@^20.5.0": + version "20.19.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.13.tgz#b79004a05068e28fb2de281b3a44c5c993650e59" + integrity sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g== + dependencies: + undici-types "~6.21.0" + +"@types/node@^22.0.0": + version "22.18.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.3.tgz#e1a4eb680a688141cdd369c5a035f48cf8ece9e3" + integrity sha512-gTVM8js2twdtqM+AE2PdGEe9zGQY4UvmFjan9rZcVb6FGdStfjWoWejdmy4CfWVO9rh5MiYQGZloKAGkJt8lMw== + dependencies: + undici-types "~6.21.0" + +"@types/semver@^7.5.0": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.1.tgz#3ce3af1a5524ef327d2da9e4fd8b6d95c8d70528" + integrity sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA== + +"@types/stream-buffers@^3.0.3": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/stream-buffers/-/stream-buffers-3.0.7.tgz#0b719fa1bd2ca2cc0908205a440e5e569e1aa21e" + integrity sha512-azOCy05sXVXrO+qklf0c/B07H/oHaIuDDAiHPVwlk3A9Ek+ksHyTeMajLZl3r76FxpPpxem//4Te61G1iW3Giw== + dependencies: + "@types/node" "*" + +"@types/uuid@^9.0.1": + version "9.0.8" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" + integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== + +"@typescript-eslint/eslint-plugin@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz#4d730c2becd8e47ef76e59f68aee0fb560927cfc" + integrity sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.43.0" + "@typescript-eslint/type-utils" "8.43.0" + "@typescript-eslint/utils" "8.43.0" + "@typescript-eslint/visitor-keys" "8.43.0" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/eslint-plugin@^6.4.1": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" + integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/type-utils" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.43.0.tgz#4024159925e7671f1782bdd3498bdcfbd48f9137" + integrity sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw== + dependencies: + "@typescript-eslint/scope-manager" "8.43.0" + "@typescript-eslint/types" "8.43.0" + "@typescript-eslint/typescript-estree" "8.43.0" + "@typescript-eslint/visitor-keys" "8.43.0" + debug "^4.3.4" + +"@typescript-eslint/parser@^6.4.1": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== + dependencies: + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.43.0.tgz#958dbaa16fbd1e81d46ab86e139f6276757140f8" + integrity sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.43.0" + "@typescript-eslint/types" "^8.43.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + +"@typescript-eslint/scope-manager@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.43.0.tgz#009ebc09cc6e7e0dd67898a0e9a70d295361c6b9" + integrity sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg== + dependencies: + "@typescript-eslint/types" "8.43.0" + "@typescript-eslint/visitor-keys" "8.43.0" + +"@typescript-eslint/tsconfig-utils@8.43.0", "@typescript-eslint/tsconfig-utils@^8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.43.0.tgz#e6721dba183d61769a90ffdad202aebc383b18c8" + integrity sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA== + +"@typescript-eslint/type-utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" + integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== + dependencies: + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/type-utils@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.43.0.tgz#29ea2e34eeae5b8e9fe4f4730c5659fa330aa04e" + integrity sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg== + dependencies: + "@typescript-eslint/types" "8.43.0" + "@typescript-eslint/typescript-estree" "8.43.0" + "@typescript-eslint/utils" "8.43.0" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== + +"@typescript-eslint/types@8.43.0", "@typescript-eslint/types@^8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.43.0.tgz#00d34a5099504eb1b263e022cc17c4243ff2302e" + integrity sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw== + +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== + dependencies: + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/typescript-estree@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.43.0.tgz#39e5d431239b4d90787072ae0c2290cbd3e0a562" + integrity sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw== + dependencies: + "@typescript-eslint/project-service" "8.43.0" + "@typescript-eslint/tsconfig-utils" "8.43.0" + "@typescript-eslint/types" "8.43.0" + "@typescript-eslint/visitor-keys" "8.43.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + semver "^7.5.4" + +"@typescript-eslint/utils@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.43.0.tgz#5c391133a52f8500dfdabd7026be72a537d7b59e" + integrity sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.43.0" + "@typescript-eslint/types" "8.43.0" + "@typescript-eslint/typescript-estree" "8.43.0" + +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== + dependencies: + "@typescript-eslint/types" "6.21.0" + eslint-visitor-keys "^3.4.1" + +"@typescript-eslint/visitor-keys@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.43.0.tgz#633d3414afec3cf0a0e4583e1575f4101ef51d30" + integrity sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw== + dependencies: + "@typescript-eslint/types" "8.43.0" + eslint-visitor-keys "^4.2.1" + +"@typespec/ts-http-runtime@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.1.tgz#2fa94050f25b4d85d0bc8b9d97874b8d347a9173" + integrity sha512-SnbaqayTVFEA6/tYumdF0UmybY0KHyKwGPBXnyckFlrrKdhWFrL3a2HIPXHjht5ZOElKGcXfD2D63P36btb+ww== + dependencies: + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + tslib "^2.6.2" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.15.0, acorn@^8.4.1: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + +ajv@^6.12.4: + 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" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +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== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +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== + +axios@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7" + integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + +b4a@^1.6.4: + version "1.7.1" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.7.1.tgz#6fd4ec2fb33ba7a4ff341a2869bbfc88a6e57850" + integrity sha512-ZovbrBV0g6JxK5cGUF1Suby1vLfKjv4RWi8IxoaO/Mon8BDD9I21RxjHFtgQ+kskJqLAVyQZly3uMBui+vhc8Q== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bare-events@^2.2.0, bare-events@^2.5.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.6.1.tgz#f793b28bdc3dcf147d7cf01f882a6f0b12ccc4a2" + integrity sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g== + +bare-fs@^4.0.1: + version "4.4.4" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.4.4.tgz#69e7da11d4d7d4a77e1dc9454e11f7ac13a93462" + integrity sha512-Q8yxM1eLhJfuM7KXVP3zjhBvtMJCYRByoTT+wHXjpdMELv0xICFJX+1w4c7csa+WZEOsq4ItJ4RGwvzid6m/dw== + dependencies: + bare-events "^2.5.4" + bare-path "^3.0.0" + bare-stream "^2.6.4" + bare-url "^2.2.2" + fast-fifo "^1.3.2" + +bare-os@^3.0.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.2.tgz#b3c4f5ad5e322c0fd0f3c29fc97d19009e2796e5" + integrity sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A== + +bare-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" + integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== + dependencies: + bare-os "^3.0.1" + +bare-stream@^2.6.4: + version "2.7.0" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.7.0.tgz#5b9e7dd0a354d06e82d6460c426728536c35d789" + integrity sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A== + dependencies: + streamx "^2.21.0" + +bare-url@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.2.2.tgz#1369d1972bbd7d9b358d0214d3f12abe2328d3e9" + integrity sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA== + dependencies: + bare-path "^3.0.0" + +bowser@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.12.1.tgz#f9ad78d7aebc472feb63dd9635e3ce2337e0e2c1" + integrity sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +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" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + 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" + +commander@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" + integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== + +commander@^14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.1.tgz#2f9225c19e6ebd0dc4404dd45821b2caa17ea09b" + integrity sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +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== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dotenv@^17.2.2: + version "17.2.2" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.2.tgz#4010cfe1c2be4fc0f46fd3d951afb424bc067ac6" + integrity sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q== + +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" + +end-of-stream@^1.1.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + +entities@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" + integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== + +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" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-scality@scality/Guidelines#8.3.0: + version "8.3.0" + resolved "https://codeload.github.com/scality/Guidelines/tar.gz/666b90495dc7e9a401a37ba4d58c7eba89db90ac" + dependencies: + commander "11.1.0" + markdownlint "0.31.1" + +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.35.0: + version "9.35.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.35.0.tgz#7a89054b7b9ee1dfd1b62035d8ce75547773f47e" + integrity sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.0" + "@eslint/config-helpers" "^0.3.1" + "@eslint/core" "^0.15.2" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.35.0" + "@eslint/plugin-kit" "^0.3.5" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +events@^3.0.0, events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + 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-fifo@^1.2.0, fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + +fast-glob@^3.2.9, fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +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== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fast-xml-parser@5.2.5, fast-xml-parser@^5.0.7: + version "5.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz#4809fdfb1310494e341098c25cb1341a01a9144a" + integrity sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ== + dependencies: + strnum "^2.1.0" + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + +follow-redirects@^1.15.6: + version "1.15.11" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" + integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + +form-data@^4.0.0, form-data@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" + integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + 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" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.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== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +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" + +hpagent@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-1.2.0.tgz#0ae417895430eb3770c03443456b8d90ca464903" + integrity sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA== + +http-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.0: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +ignore@^7.0.0: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +ip-address@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.0.1.tgz#a8180b783ce7788777d796286d61bce4276818ed" + integrity sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +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== + +jose@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.0.tgz#96285365689d16f2845a353964d2284bf19f464c" + integrity sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsep@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" + integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +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-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +jsonpath-plus@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz#59e22e4fa2298c68dfcd70659bb47f0cad525238" + integrity sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA== + dependencies: + "@jsep-plugin/assignment" "^1.3.0" + "@jsep-plugin/regex" "^1.0.4" + jsep "^1.4.0" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +linkify-it@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec" + integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw== + dependencies: + uc.micro "^1.0.1" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +markdown-it@13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430" + integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q== + dependencies: + argparse "^2.0.1" + entities "~3.0.1" + linkify-it "^4.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +markdownlint-micromark@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/markdownlint-micromark/-/markdownlint-micromark-0.1.7.tgz#c465091b30d61a56027ccbfb981c80c96448c165" + integrity sha512-BbRPTC72fl5vlSKv37v/xIENSRDYL/7X/XoFzZ740FGEbs9vZerLrIkFRY0rv7slQKxDczToYuMmqQFN61fi4Q== + +markdownlint@0.31.1: + version "0.31.1" + resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.31.1.tgz#f014ed2d3614c5dbc351b7f65641ccc0a5facdb7" + integrity sha512-CKMR2hgcIBrYlIUccDCOvi966PZ0kJExDrUi1R+oF9PvqQmCrTqjOsgIvf2403OmJ+CWomuzDoylr6KbuMyvHA== + dependencies: + markdown-it "13.0.1" + markdownlint-micromark "0.1.7" + +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== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +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: + 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" + +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +oauth4webapi@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-3.8.1.tgz#a6e205570c09e33aa656982c85e78841a57a6fec" + integrity sha512-olkZDELNycOWQf9LrsELFq8n05LwJgV8UkrS0cburk6FOwf8GvLam+YB+Uj5Qvryee+vwWOfQVeI5Vm0MVg7SA== + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +openid-client@^6.1.3: + version "6.8.0" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-6.8.0.tgz#ae60540fc1aaf595ee9100004ebda722e1d80e60" + integrity sha512-oG1d1nAVhIIE+JSjLS+7E9wY1QOJpZltkzlJdbZ7kEn7Hp3hqur2TEeQ8gLOHoHkhbRAGZJKoOnEQcLOQJuIyg== + dependencies: + jose "^6.1.0" + oauth4webapi "^3.8.1" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +pump@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" + integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +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== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-json-stringify@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" + integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== + +semver@^7.5.4, semver@^7.6.0: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^8.0.4: + version "8.0.5" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" + integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== + dependencies: + agent-base "^7.1.2" + debug "^4.3.4" + socks "^2.8.3" + +socks@^2.8.3: + version "2.8.7" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea" + integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A== + dependencies: + ip-address "^10.0.1" + smart-buffer "^4.2.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== + +streamx@^2.15.0, streamx@^2.21.0: + version "2.22.1" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.1.tgz#c97cbb0ce18da4f4db5a971dc9ab68ff5dc7f5a5" + integrity sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA== + dependencies: + fast-fifo "^1.3.2" + text-decoder "^1.1.0" + optionalDependencies: + bare-events "^2.2.0" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strnum@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.1.1.tgz#cf2a6e0cf903728b8b2c4b971b7e36b4e82d46ab" + integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tar-fs@^3.0.8: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.1.0.tgz#4675e2254d81410e609d91581a762608de999d25" + integrity sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w== + dependencies: + pump "^3.0.0" + tar-stream "^3.1.5" + optionalDependencies: + bare-fs "^4.0.1" + bare-path "^3.0.0" + +tar-stream@^3.1.5: + version "3.1.7" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== + dependencies: + b4a "^1.6.4" + fast-fifo "^1.2.0" + streamx "^2.15.0" + +text-decoder@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" + integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== + dependencies: + b4a "^1.6.4" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-api-utils@^1.0.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" + integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== + +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + +ts-node@^10.9.1: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^2.6.2, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +typescript-eslint@^8.43.0: + version "8.43.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.43.0.tgz#335ac16a859f385dfb23022e0d8298962364d099" + integrity sha512-FyRGJKUGvcFekRRcBKFBlAhnp4Ng8rhe8tuvvkR9OiU0gfd4vyvTRQHEckO6VDlH57jbeUQem2IpqPq9kLJH+w== + dependencies: + "@typescript-eslint/eslint-plugin" "8.43.0" + "@typescript-eslint/parser" "8.43.0" + "@typescript-eslint/typescript-estree" "8.43.0" + "@typescript-eslint/utils" "8.43.0" + +typescript@^5.2.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" + integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +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.10.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" + integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== + +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@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +werelogs@scality/werelogs#8.2.2: + version "8.2.2" + resolved "https://codeload.github.com/scality/werelogs/tar.gz/e53bef5145697bf8af940dcbe59408988d64854f" + dependencies: + fast-safe-stringify "^2.1.1" + safe-json-stringify "^1.2.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^8.18.2: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +yaml@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.1.tgz#1870aa02b631f7e8328b93f8bc574fac5d6c4d79" + integrity sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/tests/ZENKO_SETUP_INVENTORY.md b/tests/ZENKO_SETUP_INVENTORY.md new file mode 100644 index 0000000000..13e4f24f06 --- /dev/null +++ b/tests/ZENKO_SETUP_INVENTORY.md @@ -0,0 +1,143 @@ +# Zenko Test Setup Inventory + +Complete inventory of ALL non-standard Zenko setup tasks across the entire codebase. + +## Setup Tasks Inventory + +| Task | Current Implementation | Used By | What It Does | +|------|----------------------|---------|--------------| +| **Mock Services - AWS** | `.github/scripts/end2end/install-mocks.sh` + `tests/ctst/steps/setup/setup.ts` | CTST, Node Tests, Backbeat Tests | Creates AWS S3 mock (CloudServer) with pre-configured metadata | +| **Mock Services - Azure** | `.github/scripts/end2end/install-mocks.sh` + `tests/ctst/steps/setup/setup.ts` | CTST, Azure Archive Tests | Creates Azurite mock for blob/queue storage | +| **Buckets - AWS** | `tests/zenko_tests/create_buckets.py` | Node Tests, Backbeat Tests | Creates `ci-zenko-aws-*-bucket` buckets with versioning | +| **Buckets - Azure** | `tests/zenko_tests/create_buckets.py` | Node Tests, Azure Tests | Creates Azure containers and queues | +| **Buckets - Ring** | `tests/zenko_tests/create_buckets.py` | Ring/S3C Tests | Creates Ring buckets with pre-populated objects | +| **Storage Locations** | `tests/zenko_tests/configuration.py` + `tests/ctst/steps/setup/setup.ts` | All Tests | Creates AWS/Azure/DMF/Ring storage locations via Management API | +| **Accounts** | `tests/zenko_tests/configuration.py` | Node Tests, UI Tests | Creates test accounts via Management API | +| **Endpoints** | `tests/zenko_tests/configuration.py` | Node Tests | Creates S3 endpoints via Management API | +| **Workflows - Replication** | `tests/zenko_tests/configuration.py` | Replication Tests | Creates replication workflows via Management API | +| **Workflows - Lifecycle** | `tests/zenko_tests/configuration.py` | Lifecycle Tests | Creates lifecycle workflows via Management API | +| **Workflows - Ingestion** | `tests/zenko_tests/configuration.py` | Ingestion Tests | Creates ingestion workflows via Management API | +| **Keycloak Realm** | `.github/scripts/end2end/keycloak-helper.sh` | Auth Tests, UI Tests | Creates realm with roles: StorageManager, AccountTest::*, etc. | +| **Keycloak Users** | `.github/scripts/end2end/keycloak-helper.sh` | Auth Tests, UI Tests | Creates users with instance IDs and role assignments | +| **DNS - CoreDNS** | `.github/scripts/end2end/patch-coredns.sh` | All Tests | Adds rewrite rules for `*.aws-mock.zenko.local` → ingress | +| **DNS - /etc/hosts** | `.github/scripts/end2end/setup-ctst-local.sh` | Local Development | Adds `127.0.0.1 iam.zenko.local ui.zenko.local s3.zenko.local...` | +| **RBAC - Cluster Admin** | `.github/scripts/end2end/setup-ctst-local.sh` + `tests/ctst/steps/setup/setup.ts` | CTST, Node Tests | Grants cluster-admin to all service accounts | +| **Kafka Topics** | `tests/ctst/steps/setup/setup.ts` | CTST, Notification Tests | Creates notification and cold storage status topics | +| **Notification Targets** | `tests/ctst/steps/setup/setup.ts` | CTST, Notification Tests | Creates ZenkoNotificationTarget CRDs for Kafka | +| **Deployment Patches** | `tests/ctst/steps/setup/setup.ts` | CTST, Quota Tests | Sets `SCUBA_HEALTHCHECK_FREQUENCY=100` on cloudserver | +| **TLS Certificates** | `.github/scripts/end2end/enable-https.sh` | HTTPS Tests | Creates CA certificates and TLS secrets | +| **Metadata Service** | `.github/scripts/end2end/deploy-metadata.sh` | S3C/Ring Tests | Deploys separate metadata service (bucketd/repd) | +| **PRA Setup** | `.github/scripts/end2end/prepare-pra.sh` | PRA/DR Tests | Configures Point-in-time Recovery and Archive | +| **Shell UI** | `.github/scripts/end2end/deploy-shell-ui.sh` | UI Tests | Deploys shell-ui for navigation | +| **Admin Credentials** | `tests/ctst/steps/setup/setup.ts` | CTST | Extracts admin access/secret keys from secrets | +| **Service User Credentials** | `tests/ctst/steps/setup/setup.ts` | CTST | Extracts backbeat service user credentials | +| **PRA Credentials** | `tests/ctst/steps/setup/setup.ts` | CTST | Extracts DR/PRA admin credentials | +| **Kafka Configuration** | `tests/ctst/steps/setup/setup.ts` | CTST | Extracts Kafka hosts and topics from secrets | +| **Instance Information** | `tests/ctst/steps/setup/setup.ts` | CTST | Extracts InstanceID, time progression factor from Zenko CR | + +## Setup Script Locations + +### Shell Scripts (19 files) +``` +.github/scripts/end2end/ +├── install-mocks.sh # Mock services +├── keycloak-helper.sh # Keycloak realm/users +├── patch-coredns.sh # DNS configuration +├── setup-ctst-local.sh # Local dev setup +├── enable-https.sh # TLS certificates +├── deploy-metadata.sh # Metadata service +├── prepare-pra.sh # PRA configuration +├── deploy-shell-ui.sh # Shell UI +├── run-e2e-test.sh # Test runner (with setup) +├── run-e2e-ctst.sh # CTST runner (DEPRECATED - replaced by tests/@setup/run-tests.sh) +├── deploy-zenko.sh # Zenko deployment +├── deploy-zkop.sh # Zenko operator +├── bootstrap-kind.sh # Kind cluster setup +├── install-kind-dependencies.sh # Kind dependencies +├── common.sh # Shared utilities +├── requirements.sh # Prerequisite checks +└── create-pull-image-secret.sh # Image pull secrets +``` + +**Note:** The following files have been removed/migrated to tests/@setup/: +- configure-e2e.sh and configure-hosts.sh (migrated to TypeScript setup) + +### Python Scripts +``` +tests/zenko_tests/ +├── cleans3c.py # S3C cleanup utility +└── docker-entrypoint.sh # Test container entrypoint + +Note: configuration.py and create_buckets.py have been migrated to TypeScript in tests/@setup/src/ +``` + +### TypeScript/CTST Setup +``` +tests/ctst/steps/setup/setup.ts # CTST-specific setup (overlaps with shell scripts) +``` + +## Analysis + +**Total Setup Implementations:** 22+ files +**Duplicated Logic:** Mock services, RBAC, storage locations, credentials extraction +**Languages:** Bash (19 files), Python (2 files), TypeScript (1 file) +**Scope:** Some global (RBAC, DNS), some test-suite specific (credentials, buckets) + +**Key Insight:** Setup is scattered across 3 different languages and 22+ files, with significant duplication between CTST (TypeScript) and shell scripts (Bash) for the same functionality. + +--- + +# Centralization Strategy + +## Solution + +Create single TypeScript setup container that replaces all 22+ setup scripts. + +``` +tests/@setup/ +├── src/ +│ ├── mocks.ts # AWS/Azure mock deployment +│ ├── buckets.ts # Bucket creation (all providers) +│ ├── locations.ts # Storage locations via Management API +│ ├── keycloak.ts # Realm/users/roles +│ ├── dns.ts # CoreDNS configuration +│ ├── rbac.ts # Service account permissions +│ └── cli.ts # CLI interface +├── package.json # Dependencies +└── Dockerfile # Self-contained image +``` + +## Usage + +Single command replaces all setup scripts: + +```bash +docker run --rm -v ~/.kube:/root/.kube \ + -e NAMESPACE=default \ + -e SUBDOMAIN=zenko.local \ + -e INSTANCE_ID=xyz123 \ + ghcr.io/scality/zenko-test-setup:latest \ + --mocks --buckets --locations --keycloak +``` + +## Why Container Approach + +**Problem:** Setup logic scattered across 22+ files in 3 languages (Bash, Python, TypeScript) with no shared dependencies or runtime. + +**Container Solution:** +- Packages all setup logic in single consistent environment +- Provides TypeScript runtime with all dependencies (@kubernetes/client-node, @aws-sdk/*, @azure/*) +- Eliminates language/dependency conflicts between test suites +- Can be called identically from any test suite or CI/CD pipeline +- Kubernetes API access via mounted kubeconfig + +**Alternative approaches failed:** +- Shell scripts: Limited, hard to maintain, no type safety +- Python integration: Would require Python runtime in TypeScript test suites +- Direct TypeScript import: Would force all test suites to adopt TypeScript dependencies + +## Integration + +**CTST:** Call container in BeforeAll, keep only info retrieval functions +**Node tests:** Replace create_buckets.py + configuration.py with container call +**GitHub workflows:** Replace install-mocks.sh + keycloak-helper.sh + other scripts with container call diff --git a/tests/ctst/CTST_MANUAL_SETUP_ANALYSIS.md b/tests/ctst/CTST_MANUAL_SETUP_ANALYSIS.md new file mode 100644 index 0000000000..312a4921af --- /dev/null +++ b/tests/ctst/CTST_MANUAL_SETUP_ANALYSIS.md @@ -0,0 +1,218 @@ +# CTST Manual Setup Requirements Analysis + +This document contains a comprehensive analysis of all manual setup requirements for CTST tests, excluding Zenko deployment itself. + +## **COMPLETE LIST OF MANUAL CTST SETUP REQUIREMENTS** + +### **1. ENVIRONMENT VARIABLES SETUP** +These are currently set via shell scripts and need to be extracted from Kubernetes secrets: + +#### **Admin Credentials** +```bash +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) +``` + +#### **Service User Credentials** +```bash +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) +``` + +#### **Kafka Topics and Configuration** +```bash +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) +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) +``` + +#### **Backbeat API Configuration** +```bash +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_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) +``` + +#### **Zenko Instance Configuration** +```bash +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}') +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}') +UTILIZATION_SERVICE_HOST=$(kubectl get zenko ${ZENKO_NAME} -o jsonpath='{.spec.scuba.api.ingress.hostname}') +``` + +### **2. KUBERNETES RBAC SETUP** +**Critical Security Risk - Currently Grants Cluster Admin to ALL Service Accounts:** +```bash +kubectl create clusterrolebinding serviceaccounts-cluster-admin \ + --clusterrole=cluster-admin \ + --group=system:serviceaccounts +``` + +### **3. DEPLOYMENT ENVIRONMENT MODIFICATIONS** +```bash +kubectl set env deployment end2end-connector-cloudserver SCUBA_HEALTHCHECK_FREQUENCY=100 +kubectl rollout status deployment end2end-connector-cloudserver +``` + +### **4. HOST NETWORK CONFIGURATION** +**Requires sudo access to modify /etc/hosts:** +```bash +echo "127.0.0.1 iam.zenko.local ui.zenko.local s3-local-file.zenko.local keycloak.zenko.local \ + sts.zenko.local management.zenko.local s3.zenko.local website.mywebsite.com utilization.zenko.local" | sudo tee -a /etc/hosts +``` + +### **5. KEYCLOAK SETUP AND CONFIGURATION** +#### **Keycloak Realm and User Creation via Docker Container:** +```bash +docker run \ + --rm \ + --network=host \ + "${E2E_IMAGE}" /bin/bash \ + -c "SUBDOMAIN=${SUBDOMAIN} CONTROL_PLANE_INGRESS_ENDPOINT=${OIDC_ENDPOINT} ACCOUNT=${ZENKO_ACCOUNT_NAME} KEYCLOAK_REALM=${KEYCLOAK_TEST_REALM_NAME} STORAGE_MANAGER=${STORAGE_MANAGER_USER_NAME} STORAGE_ACCOUNT_OWNER=${STORAGE_ACCOUNT_OWNER_USER_NAME} DATA_CONSUMER=${DATA_CONSUMER_USER_NAME} DATA_ACCESSOR=${DATA_ACCESSOR_USER_NAME} /ctst/bin/seedKeycloak.sh" +``` + +#### **Keycloak Configuration Requirements:** +- **Realm creation** with specific roles: `StorageManager`, `AccountTest::DataAccessor`, `AccountTest::DataConsumer`, `AccountTest::StorageAccountOwner` +- **User creation** with instance IDs and roles +- **Client configuration** for OIDC integration + +### **6. KAFKA TOPIC CREATION** +**Multiple Kafka topics need to be created:** +```bash +kubectl run kafka-topics \ + --image=$KAFKA_IMAGE \ + --pod-running-timeout=5m \ + --rm \ + --restart=Never \ + --attach=True \ + --command -- bash -c \ + "kafka-topics.sh --create --topic $NOTIF_DEST_TOPIC --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ + kafka-topics.sh --create --topic $NOTIF_ALT_DEST_TOPIC --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ + kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ + kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC_2_NV --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ + kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC_2_V --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists ; \ + kafka-topics.sh --create --topic $AZURE_ARCHIVE_STATUS_TOPIC_2_S --partitions 10 --bootstrap-server $KAFKA_HOST_PORT --if-not-exists" +``` + +### **7. KUBERNETES CUSTOM RESOURCES** +#### **ZenkoNotificationTarget Resources:** +```yaml +apiVersion: zenko.io/v1alpha2 +kind: ZenkoNotificationTarget +metadata: + name: ${NOTIF_DEST_NAME} + labels: + app.kubernetes.io/instance: ${ZENKO_NAME} +spec: + type: kafka + host: ${NOTIF_KAFKA_HOST} + port: ${NOTIF_KAFKA_PORT} + destinationTopic: ${NOTIF_DEST_TOPIC} +``` + +### **8. MOCK SERVICES DEPLOYMENT** +#### **Azure Mock Service:** +- **Azurite container** for Azure Blob/Queue simulation +- **Ingress configuration** for multiple Azure endpoints +- **TLS certificates** for secure communication + +#### **AWS Mock Service:** +- **CloudServer container** with pre-configured metadata +- **ConfigMap** with mock metadata tar.gz +- **Ingress configuration** for AWS endpoints + +### **9. EXTERNAL DEPENDENCIES** +#### **Required Environment Variables from External Systems:** +- `SUBDOMAIN`, `DR_SUBDOMAIN` +- `NOTIF_DEST_NAME`, `NOTIF_DEST_TOPIC`, `NOTIF_ALT_DEST_NAME`, `NOTIF_ALT_DEST_TOPIC` +- `KAFKA_EXTERNAL_IP` +- `PROMETHEUS_NAME` +- `OIDC_USERNAME`, `OIDC_PASSWORD`, `OIDC_HOST`, `OIDC_REALM`, `OIDC_CLIENT_ID`, `OIDC_ENDPOINT` +- `AZURE_ACCOUNT_NAME`, `AZURE_SECRET_KEY`, `AZURE_BACKEND_ENDPOINT`, `AZURE_BACKEND_QUEUE_ENDPOINT` +- `AZURE_ARCHIVE_BUCKET_NAME`, `AZURE_ARCHIVE_BUCKET_NAME_2`, `AZURE_ARCHIVE_QUEUE_NAME` + +### **10. VOLUME AND STORAGE REQUIREMENTS** +#### **Pod Volume Mounts:** +```yaml +volumeMounts: + - name: "cold-data" + mountPath: "/cold-data" + - name: "reports" + mountPath: "/reports" +volumes: + - name: "cold-data" + persistentVolumeClaim: + claimName: "sorbet-data" + - name: "reports" + hostPath: + path: "/data/reports" + type: "DirectoryOrCreate" +``` + +### **11. SERVICE ACCOUNT AND RBAC FOR CONFIGURATION** +```yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ${SERVICE_ACCOUNT} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ${SERVICE_ACCOUNT} +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["*"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: ${SERVICE_ACCOUNT} +subjects: +- kind: ServiceAccount + name: ${SERVICE_ACCOUNT} +roleRef: + kind: Role + name: ${SERVICE_ACCOUNT} + apiGroup: rbac.authorization.k8s.io +``` + +### **12. ZENKO STATUS WAITING** +**Wait for Zenko deployment stabilization:** +```bash +kubectl wait --for condition=DeploymentInProgress=true --timeout 10m zenko/${ZENKO_NAME} +kubectl wait --for condition=DeploymentFailure=false --timeout 10m zenko/${ZENKO_NAME} +kubectl wait --for condition=DeploymentInProgress=false --timeout 10m zenko/${ZENKO_NAME} +``` + +--- + +## **SUMMARY** + +This comprehensive analysis reveals **12 major categories** of manual setup requirements that need to be automated in BeforeAll hooks: + +1. **Environment Variables Extraction** (from ~30+ kubectl secret/configmap queries) +2. **Kubernetes RBAC Setup** (security-critical cluster-admin binding) +3. **Deployment Modifications** (environment variable injection) +4. **Host Network Configuration** (requires sudo access) +5. **Keycloak Setup** (Docker container execution + realm/user creation) +6. **Kafka Topic Creation** (6+ topics with specific configurations) +7. **Custom Resource Creation** (ZenkoNotificationTarget resources) +8. **Mock Services Deployment** (Azure + AWS mock services) +9. **External Dependencies** (20+ environment variables from CI/external systems) +10. **Volume/Storage Setup** (PVC and hostPath configurations) +11. **Service Account/RBAC** (for configuration pods) +12. **Status Synchronization** (waiting for Zenko stabilization) + +**Key Challenge:** The current setup has significant **security implications** (cluster-admin to all service accounts) and **external dependencies** (Docker execution, sudo access, external environment variables) that will need careful handling in the BeforeAll automation. + +The goal of moving everything to BeforeAll hooks using the Kubernetes client is achievable, but will require handling these external dependencies and security considerations properly. \ No newline at end of file diff --git a/tests/ctst/Dockerfile b/tests/ctst/Dockerfile index 93bda2472e..19ebf06222 100644 --- a/tests/ctst/Dockerfile +++ b/tests/ctst/Dockerfile @@ -1,27 +1,44 @@ ARG SORBET_TAG=latest ARG CTST_TAG=latest ARG DRCTL_TAG=latest +ARG GIT_ACCESS_TOKEN= FROM ghcr.io/scality/sorbet:$SORBET_TAG AS sorbet FROM ghcr.io/scality/zenko-drctl:$DRCTL_TAG AS drctl FROM ghcr.io/scality/cli-testing:$CTST_TAG COPY package.json /tmp/package.json + +USER root +RUN npm install typescript@5.9.2 -g + +# Configure git to use the access token for private repositories +RUN git config --global url.https://x-access-token:${GIT_ACCESS_TOKEN}@github.com/.insteadOf https://github.com/ && \ + git config --global url.https://x-access-token:${GIT_ACCESS_TOKEN}@github.com/.insteadOf github.com: && \ + git config --global url.https://x-access-token:${GIT_ACCESS_TOKEN}@github.com/.insteadOf ssh://git@github.com/ + +# CTST does it if needed, but better to merge dependencies +# here so we benefit from Docker layer caching +WORKDIR /ctst +RUN merge-packages /tmp/package.json package.json --output package.json && \ + jq 'del(.devDependencies)' package.json > package.json.tmp && \ + mv package.json.tmp package.json && \ + echo "Merged package.json:" && cat package.json && \ + yarn install --prod --network-concurrency=1 && \ + yarn cache clean && \ + echo "Dependencies pre-installed at build time - runtime will skip installation" && \ + touch .init + COPY ./features /ctst/features COPY ./common /ctst/common COPY ./steps /ctst/steps COPY ./world /ctst/world -USER root -RUN npm install typescript@5.8.3 -g - RUN chmod 0777 -R /tmp/ RUN chmod 0777 -R /ctst/ ENV SDK=true -WORKDIR /ctst - COPY --from=sorbet /sorbetctl . COPY --from=drctl /zenko-drctl . diff --git a/tests/ctst/HOW_TO_WRITE_TESTS.md b/tests/ctst/HOW_TO_WRITE_TESTS.md index 4f5bbe74d6..13f9ae830f 100644 --- a/tests/ctst/HOW_TO_WRITE_TESTS.md +++ b/tests/ctst/HOW_TO_WRITE_TESTS.md @@ -59,6 +59,23 @@ possible. Solutions exist: relative checks. - As a last resort, we might have a dedicated test suite. +### Cold Storage Tests and Parallel Execution + +Previously, `@ColdStorage` tests were forced to run sequentially due to shared +DMF volume access. This has been resolved with the following improvements: + +- **Bucket-specific file isolation**: The sorbet mock backend now uses S3 alias + naming (`/cold-data/data/s3-aliases/{bucket}-{key}-{versionId}/`) which provides + perfect isolation between parallel test runs. +- **Intelligent file counting**: DMF volume checks now scan only for files + belonging to the specific test's bucket name. +- **Per-test cleanup**: Each test cleans up only its own files, preventing + interference with parallel tests. + +This means `@ColdStorage` tests can now run with full parallelization, +significantly reducing test execution time. Please follow the rules for parallel +execution, if you are using `@ColdStorage` tests. + ## 5. Focus on validating features. We only want to assert against externally visible state, as given in the diff --git a/tests/ctst/MIGRATION_TO_CTST_ONLY.md b/tests/ctst/MIGRATION_TO_CTST_ONLY.md new file mode 100644 index 0000000000..9e39061062 --- /dev/null +++ b/tests/ctst/MIGRATION_TO_CTST_ONLY.md @@ -0,0 +1,142 @@ +# Migration to CTST-Only Test Suite + +This document outlines the plan to migrate all E2E tests to CTST and remove legacy test suites. + +## **Current State Analysis** + +### **Existing Test Suites:** +1. **Python E2E Tests** (`tests/zenko_tests/`) + - Configuration-based tests using `configuration.py` + - Account, location, workflow setup via Management API + - Bucket creation and management + +2. **Node.js Tests** (`tests/zenko_tests/node_tests/`) + - Backbeat tests + - CloudServer tests + - IAM policy tests + - Smoke tests + - UI tests + +3. **CTST Tests** (`tests/ctst/`) + - Feature-based Gherkin tests + - TypeScript step definitions + - Modern Cucumber.js framework + +### **Current Workflow Steps:** +```yaml +- Configure E2E test environment (Python) +- Run Python E2E tests (end2end, iam-policies, object-api, smoke, backbeat) +- Configure E2E CTST test environment +- Run CTST tests +``` + +## **Migration Strategy** + +### **Phase 1: CTST Infrastructure Simplification** ✅ (COMPLETED) +- [x] Simplified CTST setup to minimal parameter extraction +- [x] Moved static values to Zenko class +- [x] Removed complex Kubernetes setup from CTST (now handled internally) +- [x] Created comprehensive ZenkoCR TypeScript types + +### **Phase 2: Feature Migration** (IN PROGRESS) +Migrate existing test functionality to CTST: + +#### **Already in CTST:** +- [x] Azure Archive tests (`azureArchive.feature`) +- [x] PRA tests (`pra.feature`) +- [x] CloudServer Auth (`cloudserverAuth.feature`) +- [x] Bucket Website (`bucketWebsite.feature`) +- [x] IAM Policies (`iam-policies/`) +- [x] Quotas (`quotas/`) +- [x] Resource Policies (`resource-policies/`) +- [x] Utilization (`utilization/`) +- [x] Bucket Notifications (`bucket-notifications/`) + +#### **Need Migration to CTST:** +- [ ] **Backbeat tests** → Convert to CTST features +- [ ] **Object API tests** → Convert to CTST features +- [ ] **Smoke tests** → Convert to CTST features +- [ ] **UI tests** → Convert to CTST features +- [ ] **Configuration management** → Convert to CTST Background steps + +### **Phase 3: Infrastructure Consolidation** (FUTURE) +Replace shared infrastructure with CTST-native approach: + +#### **Current Shared Infrastructure:** +- `install-mocks.sh` → CTST built-in mock management +- `patch-coredns.sh` → CTST built-in DNS configuration +- `keycloak-helper.sh` → CTST built-in Keycloak setup +- `configuration.py` → CTST Background steps + +#### **CTST-Native Replacements:** +```typescript +// Replace install-mocks.sh +@Before +async function setupMockServices() { + // CTST handles mock services internally +} + +// Replace configuration.py +@Background +async function setupTestConfiguration() { + // CTST handles accounts, locations, workflows +} +``` + +### **Phase 4: Workflow Simplification** (FUTURE) +Final simplified workflow: + +```yaml +steps: + - name: Deploy Zenko + uses: ./.github/actions/deploy + - name: Setup CTST Prerequisites + run: bash setup-ctst-local.sh + - name: Run All E2E Tests via CTST + run: ./run-tests.sh ~/.kube/config ctst +``` + +## **Local Development Support** + +### **Current Approach:** +```bash +# Setup prerequisites (DNS, /etc/hosts) +.github/scripts/end2end/setup-ctst-local.sh + +# Run CTST tests +cd tests/ctst +npm test +``` + +### **Future CTST-Only Approach:** +```bash +# CTST handles everything +cd tests/ctst +npm test # CTST auto-detects environment and sets up everything needed +``` + +## **Benefits of CTST-Only Architecture** + +1. **Unified Framework**: Single test framework for all E2E testing +2. **Better Maintainability**: No duplicate test logic across frameworks +3. **Modern Tooling**: TypeScript, Gherkin, modern Cucumber.js +4. **Self-Contained**: CTST handles all infrastructure setup internally +5. **Developer Experience**: Simple `npm test` for all E2E testing + +## **Migration Checklist** + +- [x] Simplify CTST parameter extraction +- [x] Remove complex Kubernetes setup from CTST +- [x] Create CTST-native local development script +- [ ] Migrate remaining Python tests to CTST features +- [ ] Migrate Node.js tests to CTST steps +- [ ] Remove legacy test suites +- [ ] Simplify GitHub Actions workflow +- [ ] Update documentation + +## **Timeline** + +1. **Immediate**: CTST infrastructure simplified (DONE) +2. **Short-term**: Migrate critical test features to CTST +3. **Medium-term**: Deprecate Python/Node.js test suites +4. **Long-term**: CTST becomes the only E2E test suite \ No newline at end of file diff --git a/tests/ctst/README.md b/tests/ctst/README.md index c8fed82e24..a1d5c2b136 100644 --- a/tests/ctst/README.md +++ b/tests/ctst/README.md @@ -59,5 +59,5 @@ this can be used to check if CTST is working properly > > Some tests may require some additional configuration before running the tests. > -> Please refer to `.github/scripts/end2end/configure-e2e-ctst.sh` to see the configuration applied +> Please refer to `.github/scripts/end2end/configure-hosts.sh` to see the configuration applied in the CI for CTST tests. diff --git a/tests/ctst/common/common.ts b/tests/ctst/common/common.ts index 07a4c3eb0f..1da90a1ce2 100644 --- a/tests/ctst/common/common.ts +++ b/tests/ctst/common/common.ts @@ -124,15 +124,13 @@ 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; + const preName = this.getSaved('accountName') || Zenko.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; + const preName = this.getSaved('accountName') || Zenko.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..158715e56d 100644 --- a/tests/ctst/common/hooks.ts +++ b/tests/ctst/common/hooks.ts @@ -27,7 +27,6 @@ export const replicationLockTags = [ const noParallelRun = atMostOnePicklePerTag([ '@AfterAll', '@PRA', - '@ColdStorage', ...replicationLockTags ]); diff --git a/tests/ctst/common/utils.ts b/tests/ctst/common/utils.ts index dd1fbb917c..8659c8ebc6 100644 --- a/tests/ctst/common/utils.ts +++ b/tests/ctst/common/utils.ts @@ -1,7 +1,7 @@ import { exec } from 'child_process'; import http from 'http'; import { createHash } from 'crypto'; -import { Command, IAM, Identity, IdentityEnum } from 'cli-testing'; +import { Command, coordinate, IAM, Identity, IdentityEnum } from 'cli-testing'; import { AttachedPolicy, Group, @@ -12,7 +12,6 @@ import { import { AWSCliOptions } from 'cli-testing'; import Zenko from 'world/Zenko'; import fs from 'fs'; -import lockFile from 'proper-lockfile'; import { ITestCaseHookParameter } from '@cucumber/cucumber'; import { AWSCredentials, Constants, Utils } from 'cli-testing'; import { createBucketWithConfiguration, putObject } from '../steps/utils/utils'; @@ -323,9 +322,6 @@ export async function prepareMetricsScenarios( const { gherkinDocument, pickle } = scenarioConfiguration; const featureName = gherkinDocument.feature?.name?.replace(/ /g, '-').toLowerCase() || 'metrics'; const filePath = `/tmp/${featureName}`; - let initiated = false; - let releaseLock: (() => Promise) | false = false; - const output: Record = {}; const { versioning = '', @@ -333,73 +329,57 @@ export async function prepareMetricsScenarios( jobNamespace = `${featureName}-setup` } = options; - if (!fs.existsSync(filePath)) { - fs.writeFileSync(filePath, JSON.stringify({ - ready: false, - })); - } else { - initiated = true; - } - - if (!initiated) { - try { - releaseLock = await lockFile.lock(filePath, { stale: Constants.DEFAULT_TIMEOUT / 2 }); - } catch (err) { - world.logger.error('Unable to acquire lock', { err }); - releaseLock = false; - } - } - - if (releaseLock) { - const scenarioIds = new Set(); - - for (const scenario of gherkinDocument.feature?.children || []) { - for (const example of scenario.scenario?.examples || []) { - for (const values of example.tableBody || []) { - const scenarioWithExampleID = hashStringAndKeepFirst20Characters(`${values.id}`); - scenarioIds.add(scenarioWithExampleID); + await coordinate( + { + lockName: featureName, + timeout: Constants.DEFAULT_TIMEOUT, + logger: world.logger, + }, + // Work function: executed exactly once + async () => { + const output: Record = {}; + const scenarioIds = new Set(); + + for (const scenario of gherkinDocument.feature?.children || []) { + for (const example of scenario.scenario?.examples || []) { + for (const values of example.tableBody || []) { + const scenarioWithExampleID = hashStringAndKeepFirst20Characters(`${values.id}`); + scenarioIds.add(scenarioWithExampleID); + } } } - } - - for (const scenarioId of scenarioIds) { - await world.createAccount(scenarioId, true); - await createBucketWithConfiguration(world, scenarioId, versioning); - await putObject(world); - output[scenarioId] = Identity.getCurrentCredentials()!; - } - - await createJobAndWaitForCompletion(world, jobName, jobNamespace); - - await Utils.sleep(2000); - fs.writeFileSync(filePath, JSON.stringify({ - ready: true, - ...output, - })); - - await releaseLock(); - } else { - while (!fs.existsSync(filePath)) { - await Utils.sleep(100); - } + + for (const scenarioId of scenarioIds) { + await world.createAccount(scenarioId, true); + await createBucketWithConfiguration(world, scenarioId, versioning); + await putObject(world); + output[scenarioId] = Identity.getCurrentCredentials()!; + } - let configuration: { ready: boolean } = JSON.parse(fs.readFileSync(filePath, 'utf8')) as { ready: boolean }; - while (!configuration.ready) { - await Utils.sleep(100); - configuration = JSON.parse(fs.readFileSync(filePath, 'utf8')) as { ready: boolean }; + await createJobAndWaitForCompletion(world, jobName, jobNamespace); + + await Utils.sleep(2000); + + // Store output in a temporary file for other workers to read + fs.writeFileSync(filePath, JSON.stringify({ + ready: true, + ...output, + })); + }, + // Post-processing: all workers read the configuration + async () => { + const configuration: Record = JSON.parse(fs.readFileSync(filePath, 'utf8')); + const key = hashStringAndKeepFirst20Characters(`${pickle.astNodeIds[1]}`); + world.logger.debug('Scenario key', { key, from: `${pickle.astNodeIds[1]}`, configuration }); + + world.addToSaved('bucketName', key); + world.addToSaved('accountName', key); + world.addToSaved('accountNameForScenario', key); + world.addToSaved('metricsEnvironmentSetup', true); + + if (configuration[key]) { + Identity.addIdentity(IdentityEnum.ACCOUNT, key, configuration[key], undefined, true, true); + } } - } - - const configuration: typeof output = JSON.parse(fs.readFileSync(filePath, 'utf8')) as typeof output; - const key = hashStringAndKeepFirst20Characters(`${pickle.astNodeIds[1]}`); - world.logger.debug('Scenario key', { key, from: `${pickle.astNodeIds[1]}`, configuration }); - - world.addToSaved('bucketName', key); - world.addToSaved('accountName', key); - world.addToSaved('accountNameForScenario', key); - world.addToSaved('metricsEnvironmentSetup', true); - - if (configuration[key]) { - Identity.addIdentity(IdentityEnum.ACCOUNT, key, configuration[key], undefined, true, true); - } + ); } diff --git a/tests/ctst/package.json b/tests/ctst/package.json index 631c9a7601..e21c522268 100644 --- a/tests/ctst/package.json +++ b/tests/ctst/package.json @@ -8,7 +8,8 @@ "license": "ISC", "private": true, "dependencies": { - "@kubernetes/client-node": "^0.21.0", + "@kubernetes/client-node": "^1.3.0", + "@types/node": "^18.19.121", "@types/proper-lockfile": "^4.1.4", "@types/qs": "^6.9.15", "assert": "^2.1.0", @@ -16,16 +17,16 @@ "kafkajs": "^2.2.4", "node-gyp": "^10.2.0", "prometheus-query": "^3.4.0", - "proper-lockfile": "^4.1.2", "qs": "^6.13.0", - "scubaclient": "git+https://github.com/scality/scubaclient#^1.1.2" + "scubaclient": "git+https://github.com/scality/scubaclient#^1.1.3", + "werelogs": "scality/werelogs#8.2.2" }, "devDependencies": { "@aws-sdk/client-iam": "^3.582.0", "@aws-sdk/client-s3": "^3.583.0", "@aws-sdk/client-sts": "^3.583.0", "@eslint/compat": "^1.1.1", - "cli-testing": "github:scality/cli-testing.git#1.2.4", + "cli-testing": "github:scality/cli-testing.git#bc237af6354d5d6e64606d61ea464356f68bad98", "eslint": "^9.9.1", "eslint-config-scality": "scality/Guidelines#8.3.0", "typescript-eslint": "^8.4.0" diff --git a/tests/ctst/steps/cloudserverAuth.ts b/tests/ctst/steps/cloudserverAuth.ts index a75a104be4..db724170ef 100644 --- a/tests/ctst/steps/cloudserverAuth.ts +++ b/tests/ctst/steps/cloudserverAuth.ts @@ -35,8 +35,7 @@ When('the user tries to perform DeleteObjects', async function (this: Zenko) { 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; + const preName = this.getSaved('accountName') || Zenko.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/dmf.ts b/tests/ctst/steps/dmf.ts index 1f4acdd269..f09b4527ed 100644 --- a/tests/ctst/steps/dmf.ts +++ b/tests/ctst/steps/dmf.ts @@ -1,23 +1,110 @@ import { Then, Given, After } from '@cucumber/cucumber'; import assert from 'assert'; -import { execShellCommand } from 'common/utils'; import Zenko from 'world/Zenko'; +import { execInCluster } from './utils/kubernetes'; +import { Utils } from 'cli-testing'; -async function cleanDmfVolume() { - await execShellCommand('rm -rf /cold-data/*'); +/** + * Clean up S3 alias files for this specific bucket + * @param world - The Zenko world object + * @param bucketName - The name of the bucket to clean up + * @returns void + */ +async function cleanDmfVolumeForBucket(world: Zenko, bucketName: string) { + if (!bucketName) { + return; + } + + const commands = [ + `find /cold-data/data/s3-aliases -name "${bucketName}-*" -type f -delete 2>/dev/null || true`, + `find /cold-data/data/s3-aliases -name "${bucketName}-*" -type d -empty -delete 2>/dev/null || true` + ]; + + for (const command of commands) { + await execInCluster(world, command); + } } +/** + * Check if the DMF volume contains the expected number of objects. + * This requires sorbet mock backend with UseS3Naming=true. + * Files are stored as: /cold-data/data/s3-aliases/{bucket}-{key}-{versionId}/content + * This enables parallel test execution by providing bucket-level isolation + * @param this - The Zenko world object + * @param objectCount - The expected number of objects + * @returns void + */ Then('dmf volume should contain {int} objects', - { timeout: 2 * 60 * 1000 }, async (objectCount: number) => { + { timeout: 2 * 60 * 1000 }, async function (this: Zenko, objectCount: number) { + const bucketName = this.getSaved('bucketName'); + if (!bucketName) { + throw new Error('bucketName not found in test context. Ensure bucket is created before this step.'); + } + let conditionOk = false; - while (!conditionOk) { - // Getting the number of objects inside the volume used - // by the mock dmf to store transitioned objects - const outStr = await execShellCommand('find /cold-data -type f | wc -l'); - // we store two files per object (content and manifest.json) - conditionOk = Number(outStr) === objectCount * 2; + let attempts = 0; + const maxAttempts = 60; + + while (!conditionOk && attempts < maxAttempts) { + try { + const outStr = await execInCluster( + this, + `find /cold-data/data/s3-aliases -name "${bucketName}-*" -type f | wc -l` + ); + const fileCount = Number(outStr.trim()); + + // We expect 2 files per object (content + manifest.json) + const expectedFileCount = objectCount * 2; + conditionOk = fileCount === expectedFileCount; + + if (!conditionOk) { + this.logger.debug(`DMF volume check for bucket ${bucketName}`, { + expected: expectedFileCount, + found: fileCount, + attempt: attempts + 1, + maxAttempts + }); + + if (attempts % 10 === 0) { + const filesFound = await execInCluster( + this, + `find /cold-data/data/s3-aliases -name "${bucketName}-*" -type f 2>/dev/null` + ); + this.logger.debug(`Files found for bucket ${bucketName}:`, { files: filesFound }); + } + + await Utils.sleep(2000); + attempts++; + } + } catch (error) { + this.logger.error('Error checking DMF volume', { error, bucket: bucketName }); + throw error; + } + } + + if (!conditionOk) { + const finalCount = await execInCluster( + this, + `find /cold-data/data/s3-aliases -name "${bucketName}-*" -type f | wc -l` + ); + const actualFiles = await execInCluster( + this, + `find /cold-data/data/s3-aliases -name "${bucketName}-*" -type f 2>/dev/null` + ); + + assert.fail( + `DMF volume should contain ${objectCount * 2} files for bucket ${bucketName}, ` + + `but found ${finalCount.trim()} after ${attempts} attempts. ` + + `Files found: ${actualFiles}` + ); } - assert(conditionOk); + + this.logger.debug(`DMF volume check passed for bucket ${bucketName}`, { + expectedObjects: objectCount, + foundFiles: objectCount * 2, + attempts, + maxAttempts, + }); }); Given('a flaky backend that will require {int} retries for {string}', @@ -29,6 +116,17 @@ Given('a flaky backend that will require {int} retries for {string}', this.addToSaved('backendFlakiness', op); }); -After({ tags: '@Dmf' }, async () => { - await cleanDmfVolume(); +After({ tags: '@Dmf' }, async function (this: Zenko, results) { + const bucketName = this.getSaved('bucketName'); + + if (results.result?.status === 'FAILED') { + this.logger.warn('DMF volume was not cleaned for failed test', { + bucket: bucketName, + reason: 'test failed - keeping files for debugging' + }); + return; + } + + await cleanDmfVolumeForBucket(this, bucketName); + this.logger.debug(`Cleaned DMF volume for bucket: ${bucketName}`); }); diff --git a/tests/ctst/steps/pra.ts b/tests/ctst/steps/pra.ts index 4542658ce0..1f0c343993 100644 --- a/tests/ctst/steps/pra.ts +++ b/tests/ctst/steps/pra.ts @@ -3,7 +3,6 @@ import Zenko from 'world/Zenko'; import ZenkoDrctl from './dr/drctl'; import { createSecret, - displayCRStatus, getDRSink, getDRSource, getPVCFromLabel, @@ -85,7 +84,6 @@ export function preparePRA(world: Zenko) { } export async function displayDebuggingInformation(world: Zenko) { - await displayCRStatus(world); const drSource = await getDRSource(world); const drSink = await getDRSink(world); diff --git a/tests/ctst/steps/setup/setup.ts b/tests/ctst/steps/setup/setup.ts new file mode 100644 index 0000000000..e7f099cf01 --- /dev/null +++ b/tests/ctst/steps/setup/setup.ts @@ -0,0 +1,1051 @@ +import Werelogs from 'werelogs'; +import { BeforeAll } from '@cucumber/cucumber'; +import { CacheHelper, coordinate } from 'cli-testing'; +import fs from 'fs'; +import path from 'path'; +import { + KubeConfig, + CoreV1Api, + CustomObjectsApi, + AppsV1Api, + RbacAuthorizationV1Api, + V1Pod, + V1Service, + V1ClusterRoleBinding, + V1ConfigMap, +} from '@kubernetes/client-node'; +import Zenko, { ZenkoWorldParameters } from 'world/Zenko'; +import { getZenkoCR, waitForDeploymentRollout, waitForZenkoToStabilize } from 'steps/utils/kubernetes'; + +type AdminCredentials = { + AdminAccessKey: string; + AdminSecretKey: string; + AccountAccessKey: string; + AccountSecretKey: string; +}; + +type PRACredentials = { + DRAdminAccessKey?: string; + DRAdminSecretKey?: string; + DRSubdomain?: string; +}; + +type ServiceUserCredentials = { + accessKey: string; + secretKey: string; +}; + +type ZenkoInstanceInfo = { + TimeProgressionFactor: number; + InstanceID?: string; + KafkaCleanerInterval?: string; + SorbetdRestoreTimeout?: string; + UtilizationServiceHost?: string; +}; + +const logger = new Werelogs.Logger('CTST').newRequestLogger(); + +function initializeKubernetesClients() { + const kc = new KubeConfig(); + kc.loadFromDefault(); + + return { + coreClient: kc.makeApiClient(CoreV1Api), + customObjectClient: kc.makeApiClient(CustomObjectsApi), + appsClient: kc.makeApiClient(AppsV1Api), + rbacClient: kc.makeApiClient(RbacAuthorizationV1Api), + }; +} + +/** + * Extract admin credentials from environment or Kubernetes + */ +async function extractAdminCredentials(coreClient: CoreV1Api, parameters: ZenkoWorldParameters): + Promise { + let adminAccessKey = parameters.AdminAccessKey; + let adminSecretKey = parameters.AdminSecretKey; + + if (!adminAccessKey || !adminSecretKey) { + const adminSecret = await coreClient + .readNamespacedSecret({ + name: 'end2end-management-vault-admin-creds.v1', + namespace: parameters.Namespace + }); + adminAccessKey = Buffer.from(adminSecret.data?.accessKey || '', 'base64').toString(); + adminSecretKey = Buffer.from(adminSecret.data?.secretKey || '', 'base64').toString(); + } + + const finalAdminAccessKey = adminAccessKey || parameters.AdminAccessKey || 'admin'; + const finalAdminSecretKey = adminSecretKey || parameters.AdminSecretKey || 'password'; + + logger.info('Extracted admin credentials', { + finalAdminAccessKey, + finalAdminSecretKey, + }); + return { + AdminAccessKey: finalAdminAccessKey, + AdminSecretKey: finalAdminSecretKey, + AccountAccessKey: parameters.AccountAccessKey || finalAdminAccessKey, + AccountSecretKey: parameters.AccountSecretKey || finalAdminSecretKey, + }; +} + +/** + * Extract PRA admin credentials from environment or Kubernetes + * Only attempts to fetch PRA credentials if DR subdomain is configured and PRA secret exists + */ +async function extractPRACredentials(coreClient: CoreV1Api, parameters: ZenkoWorldParameters): Promise { + let praAdminAccessKey = parameters.DRAdminAccessKey; + let praAdminSecretKey = parameters.DRAdminSecretKey; + + if (parameters.DRSubdomain) { + try { + const praAdminSecret = await coreClient + .readNamespacedSecret({ + name: 'end2end-pra-management-vault-admin-creds.v1', + namespace: parameters.Namespace + }); + + praAdminAccessKey = Buffer.from(praAdminSecret.data?.accessKey || '', 'base64').toString(); + praAdminSecretKey = Buffer.from(praAdminSecret.data?.secretKey || '', 'base64').toString(); + logger.info('PRA credentials extracted from Kubernetes secret'); + } catch (error) { + if ((error as { response?: { statusCode?: number } }).response?.statusCode === 404) { + logger.info('PRA secret not found, no PRA setup detected - skipping PRA credential extraction'); + } else { + logger.warn('Error reading PRA secret, skipping PRA credential extraction', { + error: (error as { message?: string }).message, + }); + } + } + } else { + logger.info('DRSubdomain not configured, skipping PRA credential extraction'); + } + + logger.info('Extracted PRA credentials', { + praAdminAccessKey, + praAdminSecretKey, + }); + + return { + DRAdminAccessKey: praAdminAccessKey || parameters.DRAdminAccessKey, + DRAdminSecretKey: praAdminSecretKey || parameters.DRAdminSecretKey, + DRSubdomain: parameters.DRSubdomain, + }; +} + +/** + * Extract service user credentials from Kubernetes + */ +async function extractServiceCredentials(coreClient: CoreV1Api, parameters: ZenkoWorldParameters) { + if (parameters.ServiceUsersCredentials) { + return { accessKey: parameters.ServiceUsersCredentials, secretKey: parameters.ServiceUsersCredentials }; + } + + const serviceUserSecrets = await Promise.allSettled([ + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=backbeat-lcbp-user-creds,app.kubernetes.io/instance=end2end' + }), + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=backbeat-lcc-user-creds,app.kubernetes.io/instance=end2end' + }), + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=backbeat-lcop-user-creds,app.kubernetes.io/instance=end2end' + }), + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=backbeat-qp-user-creds,app.kubernetes.io/instance=end2end' + }), + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=sorbet-fwd-creds,app.kubernetes.io/instance=end2end' + }), + ]); + + const credentials: Record = {}; + + const serviceCredentialHandlers = [ + { index: 0, key: 'backbeat-lifecycle-bp-1.json', name: 'backbeat-lifecycle-bp-1' }, + { index: 1, key: 'backbeat-lifecycle-conductor-1.json', name: 'backbeat-lifecycle-conductor-1' }, + { index: 2, key: 'backbeat-lifecycle-op-1.json', name: 'backbeat-lifecycle-op-1' }, + { index: 3, key: 'backbeat-qp-1.json', name: 'backbeat-qp-1' }, + ]; + + serviceCredentialHandlers.forEach(({ index, key, name }) => { + if (serviceUserSecrets[index].status === 'fulfilled' && serviceUserSecrets[index].value.items.length > 0) { + const data = + Buffer.from(serviceUserSecrets[index].value.items[0].data?.[key] || '', 'base64').toString(); + credentials[name] = JSON.parse(data) as ServiceUserCredentials; + } + }); + + if (serviceUserSecrets[4].status === 'fulfilled' && serviceUserSecrets[4].value.items.length > 0) { + const sorbetAccessKey = + Buffer.from(serviceUserSecrets[4].value.items[0].data?.accessKey || '', 'base64').toString(); + const sorbetSecretKey = + Buffer.from(serviceUserSecrets[4].value.items[0].data?.secretKey || '', 'base64').toString(); + credentials['sorbet-fwd-2'] = { + accessKey: sorbetAccessKey, + secretKey: sorbetSecretKey, + }; + } + + logger.info('Extracted service user credentials', { + credentials, + }); + + return credentials; +} + +/** + * Extract Kafka configuration from Kubernetes secrets + */ +async function extractKafkaConfiguration(coreClient: CoreV1Api, parameters: ZenkoWorldParameters) { + let kafkaHosts = parameters.KafkaHosts; + let kafkaDeadLetterTopic = parameters.KafkaDeadLetterQueueTopic; + let kafkaObjectTaskTopic = parameters.KafkaObjectTaskTopic; + let kafkaGCRequestTopic = parameters.KafkaGCRequestTopic; + let backbeatApiHost = parameters.BackbeatApiHost; + let backbeatApiPort = parameters.BackbeatApiPort; + + const configExtractionTasks = []; + + if (!kafkaHosts || !backbeatApiHost) { + configExtractionTasks.push( + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end' + }).then(backbeatConfigSecrets => { + if (backbeatConfigSecrets.items.length > 0) { + const configData = Buffer.from( + backbeatConfigSecrets.items[0].data?.['config.json'] || '', + 'base64', + ).toString(); + const config = JSON.parse(configData); + kafkaHosts = kafkaHosts || config.kafka?.hosts || ''; + } + }) + ); + + configExtractionTasks.push( + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=connector-cloudserver-config,app.kubernetes.io/instance=end2end' + }).then(cloudserverConfigSecrets => { + if (cloudserverConfigSecrets.items.length > 0) { + const cloudserverConfigData = Buffer.from( + cloudserverConfigSecrets.items[0].data?.['config.json'] || '', + 'base64', + ).toString(); + const cloudserverConfig = JSON.parse(cloudserverConfigData); + backbeatApiHost = backbeatApiHost || cloudserverConfig.backbeat?.host?.replace(/"/g, '') || ''; + backbeatApiPort = backbeatApiPort || cloudserverConfig.backbeat?.port || ''; + } + }) + ); + } + + if (!kafkaDeadLetterTopic || !kafkaObjectTaskTopic || !kafkaGCRequestTopic) { + configExtractionTasks.push( + coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + // eslint-disable-next-line max-len + labelSelector: 'app.kubernetes.io/name=cold-sorbet-config-e2e-azure-archive,app.kubernetes.io/instance=end2end' + }).then(sorbetConfigSecrets => { + if (sorbetConfigSecrets.items.length > 0) { + const sorbetConfigData = + Buffer.from(sorbetConfigSecrets.items[0].data?.['config.json'] || '', 'base64').toString(); + const sorbetConfig = JSON.parse(sorbetConfigData); + kafkaDeadLetterTopic = kafkaDeadLetterTopic || sorbetConfig['kafka-dead-letter-topic'] || ''; + kafkaObjectTaskTopic = kafkaObjectTaskTopic || sorbetConfig['kafka-object-task-topic'] || ''; + kafkaGCRequestTopic = kafkaGCRequestTopic || sorbetConfig['kafka-gc-request-topic'] || ''; + } + }) + ); + } + + await Promise.allSettled(configExtractionTasks); + + logger.info('Extracted Kafka configuration', { + kafkaHosts, + kafkaDeadLetterTopic, + kafkaObjectTaskTopic, + kafkaGCRequestTopic, + backbeatApiHost, + backbeatApiPort, + }); + + return { + KafkaHosts: kafkaHosts || 'kafka.default.svc.cluster.local:9092', + KafkaDeadLetterQueueTopic: kafkaDeadLetterTopic, + KafkaObjectTaskTopic: kafkaObjectTaskTopic, + KafkaGCRequestTopic: kafkaGCRequestTopic, + BackbeatApiHost: backbeatApiHost, + BackbeatApiPort: backbeatApiPort, + }; +} + +/** + * Extract Zenko Custom Resource information + */ +async function extractZenkoCRInfo(parameters: ZenkoWorldParameters): Promise { + let timeProgressionFactor = parameters.TimeProgressionFactor; + let instanceId = parameters.InstanceID; + let kafkaCleanerInterval = parameters.KafkaCleanerInterval; + let sorbetdRestoreTimeout = parameters.SorbetdRestoreTimeout; + let utilizationServiceHost = parameters.UtilizationServiceHost; + + if (!instanceId || !timeProgressionFactor) { + const zenkoBody = await getZenkoCR({ + parameters, + logger, + } as Zenko, parameters.Namespace, 'end2end'); + + if (zenkoBody) { + timeProgressionFactor = timeProgressionFactor || + parseInt(zenkoBody.metadata?.annotations?.['zenko.io/time-progression-factor'] || '1', 10); + instanceId = instanceId || zenkoBody.status?.instanceID || ''; + kafkaCleanerInterval = kafkaCleanerInterval || zenkoBody.spec?.kafkaCleaner?.interval || ''; + sorbetdRestoreTimeout = sorbetdRestoreTimeout || + zenkoBody.spec?.sorbet?.server?.azure?.restoreTimeout || ''; + utilizationServiceHost = utilizationServiceHost || zenkoBody.spec?.scuba?.api?.ingress?.hostname || ''; + } + } + + logger.info('Extracted Zenko Custom Resource information', { + timeProgressionFactor, + instanceId, + kafkaCleanerInterval, + sorbetdRestoreTimeout, + utilizationServiceHost, + }); + + return { + TimeProgressionFactor: timeProgressionFactor || 1, + InstanceID: instanceId, + KafkaCleanerInterval: kafkaCleanerInterval, + SorbetdRestoreTimeout: sorbetdRestoreTimeout, + UtilizationServiceHost: utilizationServiceHost, + }; +} + +/** + * Setup cluster configuration (done only by first worker who gets the lock) + */ +async function setupClusterConfiguration(parameters: ZenkoWorldParameters): Promise { + logger.info('Configuring Kubernetes cluster for CTST...'); + + const { coreClient, customObjectClient, appsClient, rbacClient } = initializeKubernetesClients(); + + const setupTasks = [ + setupClusterRBAC(rbacClient), + setupKafkaTopics(coreClient, parameters), + setupMockServices(coreClient, parameters), + setupNotificationTargets(customObjectClient, parameters), + applyDeploymentModifications(appsClient, parameters), + setupStorageLocations(parameters), + ]; + + await Promise.allSettled(setupTasks); + + logger.info('Setup tasks completed, waiting for Zenko to stabilize (up to 10 minutes)...'); + + await waitForZenkoToStabilize({ parameters, logger } as Zenko, true, 10 * 60 * 1000, parameters.Namespace); + + logger.info('Zenko stabilization completed successfully'); +} + +/** + * Extract and cache parameters from the configured cluster (done by all workers) + */ +async function extractAndCacheParameters(parameters: ZenkoWorldParameters): Promise { + const { coreClient } = initializeKubernetesClients(); + + const [adminCreds, praCreds, serviceCredentials, kafkaConfig, zenkoInfo] = await Promise.all([ + extractAdminCredentials(coreClient, parameters), + extractPRACredentials(coreClient, parameters), + extractServiceCredentials(coreClient, parameters), + extractKafkaConfiguration(coreClient, parameters), + extractZenkoCRInfo(parameters), + ]); + + const setupParameters = { + ...parameters, + ...adminCreds, + ...praCreds, + ...serviceCredentials, + ...kafkaConfig, + ...zenkoInfo, + AccountName: Zenko.ACCOUNT_NAME, + ssl: Zenko.SSL_ENABLED, + port: Zenko.PORT, + VaultAuthHost: parameters.VaultAuthHost || 'end2end-connector-vault-auth-api.default.svc.cluster.local', + UtilizationServicePort: parameters.UtilizationServicePort || '80', + NotificationDestination: parameters.NotificationDestination || 'ctst-notif-dest', + NotificationDestinationTopic: parameters.NotificationDestinationTopic || 'ctst-notif-topic', + NotificationDestinationAlt: parameters.NotificationDestinationAlt || 'ctst-notif-dest-alt', + NotificationDestinationTopicAlt: parameters.NotificationDestinationTopicAlt || 'ctst-notif-topic-alt', + KafkaExternalIps: parameters.KafkaExternalIps || '', + PrometheusService: parameters.PrometheusService || 'prometheus-operated.default.svc.cluster.local', + StorageManagerUsername: parameters.StorageManagerUsername || 'ctst_storage_manager', + StorageAccountOwnerUsername: parameters.StorageAccountOwnerUsername || 'ctst_storage_account_owner', + DataConsumerUsername: parameters.DataConsumerUsername || 'ctst_data_consumer', + DataAccessorUsername: parameters.DataAccessorUsername || 'ctst_data_accessor', + AzureArchiveAccessTier: parameters.AzureArchiveAccessTier || 'Hot', + AzureArchiveManifestTier: parameters.AzureArchiveManifestTier || 'Hot', + + KeycloakUsername: parameters.KeycloakUsername || 'testuser', + KeycloakPassword: parameters.KeycloakPassword || 'testpass', + KeycloakPort: parameters.KeycloakPort || '80', + KeycloakGrantType: parameters.KeycloakGrantType || 'password', + KeycloakHost: parameters.KeycloakHost || 'keycloak.zenko.local', + KeycloakRealm: parameters.KeycloakRealm || 'zenko', + KeycloakClientId: parameters.KeycloakClientId || 'zenko-ui', + + AzureAccountName: parameters.AzureAccountName || 'devstoreaccount1', + AzureAccountKey: parameters.AzureAccountKey || + 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==', + AzureArchiveContainer: parameters.AzureArchiveContainer || 'archive-container', + AzureArchiveContainer2: parameters.AzureArchiveContainer2 || 'archive-container-2', + AzureArchiveQueue: parameters.AzureArchiveQueue || 'archive-queue', + + subdomain: parameters.subdomain || 'zenko.local', + }; + + CacheHelper.cacheParameters(setupParameters); + + logger.info('CTST parameters extracted and cached'); +} + +/** + * Setup Kafka topics + */ +async function setupKafkaTopics(coreClient: CoreV1Api, parameters: ZenkoWorldParameters): Promise { + const kafkaConfig = await extractKafkaConfiguration(coreClient, parameters); + if (!kafkaConfig.KafkaHosts) { + logger.info('Kafka hosts not found, skipping Kafka topics setup'); + return; + } + + // Extract UUID from backbeat config like the old script + let uuid = parameters.Namespace; + try { + const backbeatConfigSecrets = await coreClient.listNamespacedSecret({ + namespace: parameters.Namespace, + labelSelector: 'app.kubernetes.io/name=backbeat-config,app.kubernetes.io/instance=end2end' + }); + if (backbeatConfigSecrets.items.length > 0) { + const configData = Buffer.from( + backbeatConfigSecrets.items[0].data?.['config.json'] || '', + 'base64', + ).toString(); + const config = JSON.parse(configData); + const replicationTopic = config.extensions?.replication?.topic; + if (replicationTopic) { + // Extract UUID from topic like "uuid.backbeat-replication" + uuid = replicationTopic.split('.')[0]; + } + } + } catch (error) { + logger.info('Failed to extract UUID from backbeat config, using namespace', { error }); + } + + const topics = [ + parameters.NotificationDestinationTopic || 'ctst-notif-topic', + parameters.NotificationDestinationTopicAlt || 'ctst-notif-topic-alt', + `${uuid}.cold-status-e2e-azure-archive`, + `${uuid}.cold-status-e2e-azure-archive-2-non-versioned`, + `${uuid}.cold-status-e2e-azure-archive-2-versioned`, + `${uuid}.cold-status-e2e-azure-archive-2-suspended`, + ]; + + const topicCommands = topics.map(topic => + // eslint-disable-next-line max-len + `kafka-topics.sh --create --topic ${topic} --partitions 10 --bootstrap-server ${kafkaConfig.KafkaHosts} --if-not-exists` + ).join(' ; '); + + const kafkaTopicsPod: V1Pod = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { + name: `kafka-topics-setup-${Date.now()}`, + namespace: parameters.Namespace, + }, + spec: { + restartPolicy: 'Never', + containers: [ + { + name: 'kafka-topics', + image: 'confluentinc/cp-kafka:latest', + command: ['bash'], + args: ['-c', topicCommands], + }, + ], + }, + }; + + await coreClient.createNamespacedPod({ namespace: parameters.Namespace, body: kafkaTopicsPod }); + logger.info('Kafka topics setup initiated', { + kafkaTopicsPod, + }); +} + +/** + * Create AWS mock configmap with metadata + */ +async function createAwsMockConfigMap(coreClient: CoreV1Api, parameters: ZenkoWorldParameters): Promise { + try { + // Try to find the tar.gz file in possible locations: + // Docker container path (from GitHub workflow copy) is prioritized + const possiblePaths = [ + '/ctst/mock-metadata.tar.gz', // Docker container location + path.join(__dirname, '../../../..', '.github/scripts/mocks/aws/mock-metadata.tar.gz'), + path.join(process.cwd(), '.github/scripts/mocks/aws/mock-metadata.tar.gz'), + ]; + + let tarGzPath: string | null = null; + for (const tarPath of possiblePaths) { + if (fs.existsSync(tarPath)) { + tarGzPath = tarPath; + break; + } + } + + if (!tarGzPath) { + throw new Error(`AWS mock metadata file not found. Searched paths: ${possiblePaths.join(', ')}`); + } + + // Read the tar.gz file and create configmap with it + const tarGzContent = fs.readFileSync(tarGzPath); + const configMapData = { + 'mock-metadata.tar.gz': tarGzContent.toString('base64'), + }; + logger.info('Using mock-metadata.tar.gz file', { tarGzPath }); + + const awsMockConfigMap: V1ConfigMap = { + apiVersion: 'v1', + kind: 'ConfigMap', + metadata: { + name: 'aws-mock', + namespace: parameters.Namespace, + }, + binaryData: configMapData, + }; + + await coreClient.createNamespacedConfigMap({ namespace: parameters.Namespace, body: awsMockConfigMap }); + logger.info('AWS mock configmap created successfully'); + } catch (error) { + if ((error as { response?: { statusCode: number } }).response?.statusCode === 409) { + logger.info('AWS mock configmap already exists'); + } else { + logger.error('Failed to create AWS mock configmap', { error }); + throw error; + } + } +} + +/** + * Setup mock services + */ +async function setupMockServices(coreClient: CoreV1Api, parameters: ZenkoWorldParameters): Promise { + const existingPods = await coreClient.listNamespacedPod({ + namespace: parameters.Namespace, + labelSelector: 'component=mock' + }); + + if (existingPods.items.length > 0) { + logger.info('Mock services already deployed', { + existingPods, + }); + return; + } + + await createAwsMockConfigMap(coreClient, parameters); + + const azureMockService: V1Service = { + apiVersion: 'v1', + kind: 'Service', + metadata: { + name: 'azure-mock', + namespace: parameters.Namespace, + }, + spec: { + selector: { name: 'azure-mock' }, + type: 'ClusterIP', + ports: [ + { name: 'blob', port: 80, targetPort: 'blob' }, + { name: 'queue', port: 81, targetPort: 'queue' }, + ], + }, + }; + + const azureMockPod: V1Pod = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { + name: 'azure-mock-pod', + namespace: parameters.Namespace, + labels: { name: 'azure-mock', component: 'mock' }, + }, + spec: { + hostname: 'devstoreaccount1', + subdomain: 'azure-mock', + containers: [ + { + name: 'azurite', + image: 'mcr.microsoft.com/azure-storage/azurite:3.35.0', + command: [ + 'azurite', '-l', '/data', + '--blobHost', '0.0.0.0', '--blobPort', '80', + '--queueHost', '0.0.0.0', '--queuePort', '81', + ], + ports: [ + { name: 'blob', containerPort: 80 }, + { name: 'queue', containerPort: 81 }, + ], + }, + ], + }, + }; + + const awsMockService: V1Service = { + apiVersion: 'v1', + kind: 'Service', + metadata: { + name: 'aws-mock', + namespace: parameters.Namespace, + }, + spec: { + selector: { name: 'aws-mock' }, + type: 'ClusterIP', + ports: [ + { name: 'http', port: 80, targetPort: 'http' }, + ], + }, + }; + + const awsMockPod: V1Pod = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { + name: 'aws-mock-pod', + namespace: parameters.Namespace, + labels: { name: 'aws-mock', component: 'mock' }, + }, + spec: { + initContainers: [ + { + name: 'setup', + image: 'zenko/cloudserver:latest', + imagePullPolicy: 'Always', + command: ['tar', '-xvf', '/static-config/mock-metadata.tar.gz', '-C', '/usr/src/app'], + volumeMounts: [ + { + name: 'configmap', + mountPath: '/static-config', + }, + { + name: 'metadata', + mountPath: '/usr/src/app/localMetadata', + }, + ], + }, + ], + containers: [ + { + name: 'aws-mock', + image: 'zenko/cloudserver:latest', + ports: [ + { name: 'http', containerPort: 8000 }, + ], + env: [ + { name: 'LOG_LEVEL', value: 'trace' }, + { name: 'REMOTE_MANAGEMENT_DISABLE', value: '1' }, + { name: 'ENDPOINT', value: 'aws-mock.zenko.local' }, + { name: 'S3BACKEND', value: 'file' }, + ], + volumeMounts: [ + { + name: 'metadata', + mountPath: '/usr/src/app/localMetadata', + }, + ], + resources: { + limits: { cpu: '1', memory: '2Gi' }, + requests: { cpu: '1', memory: '2Gi' }, + }, + }, + ], + volumes: [ + { + name: 'metadata', + emptyDir: {}, + }, + { + name: 'configmap', + configMap: { + name: 'aws-mock', + }, + }, + ], + }, + }; + + await Promise.allSettled([ + coreClient.createNamespacedService({ namespace: parameters.Namespace, body: azureMockService }), + coreClient.createNamespacedPod({ namespace: parameters.Namespace, body: azureMockPod }), + coreClient.createNamespacedService({ namespace: parameters.Namespace, body: awsMockService }), + coreClient.createNamespacedPod({ namespace: parameters.Namespace, body: awsMockPod }), + ]); + + logger.info('Mock services deployment initiated', { + azureMockService, + azureMockPod, + awsMockService, + awsMockPod, + }); +} + +/** + * Setup notification targets + */ +async function setupNotificationTargets(customObjectClient: CustomObjectsApi, parameters: ZenkoWorldParameters) { + const { coreClient } = initializeKubernetesClients(); + const kafkaConfig = await extractKafkaConfiguration(coreClient, parameters); + if (!kafkaConfig.KafkaHosts) { + return; + } + + const [kafkaHost, kafkaPort] = kafkaConfig.KafkaHosts.split(':'); + + const targets = [ + { + name: parameters.NotificationDestination || 'ctst-notif-dest', + topic: parameters.NotificationDestinationTopic || 'ctst-notif-topic' + }, + { + name: parameters.NotificationDestinationAlt || 'ctst-notif-dest-alt', + topic: parameters.NotificationDestinationTopicAlt || 'ctst-notif-topic-alt' + }, + ]; + + for (const target of targets) { + const notificationTarget = { + apiVersion: 'zenko.io/v1alpha2', + kind: 'ZenkoNotificationTarget', + metadata: { + name: target.name, + namespace: parameters.Namespace, + labels: { 'app.kubernetes.io/instance': 'end2end' }, + }, + spec: { + type: 'kafka', + host: kafkaHost, + port: parseInt(kafkaPort || '9092', 10), + destinationTopic: target.topic, + }, + }; + + await customObjectClient.createNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha2', + namespace: parameters.Namespace, + plural: 'zenkonotificationtargets', + body: notificationTarget + }).catch(err => { + if (err.response?.statusCode !== 409) { + throw err; + } + }); + } + + logger.info('Notification targets configured', { + targets, + }); +} + +/** + * Apply deployment modifications + */ +async function applyDeploymentModifications(appsClient: AppsV1Api, parameters: ZenkoWorldParameters): Promise { + const deploymentName = 'end2end-connector-cloudserver'; + + // eslint-disable-next-line max-len + const deployment = await appsClient.readNamespacedDeployment({ name: deploymentName, namespace: parameters.Namespace }); + + const containers = deployment.spec?.template?.spec?.containers || []; + const cloudserverContainer = containers.find(c => c.name === 'cloudserver'); + + if (!cloudserverContainer) { + throw new Error(`CloudServer container not found in deployment ${deploymentName}`); + } + + if (!cloudserverContainer.env) { + cloudserverContainer.env = []; + } + + // We need to set the healthcheck frequency to 100 to speed up the testing of quota-related features. + const existingEnvIndex = cloudserverContainer.env.findIndex(e => e.name === 'SCUBA_HEALTHCHECK_FREQUENCY'); + if (existingEnvIndex >= 0) { + cloudserverContainer.env[existingEnvIndex].value = '100'; + } else { + cloudserverContainer.env.push({ + name: 'SCUBA_HEALTHCHECK_FREQUENCY', + value: '100', + }); + } + + await appsClient.patchNamespacedDeployment({ + name: deploymentName, + namespace: parameters.Namespace, + body: deployment + }); + + await waitForDeploymentRollout(appsClient, deploymentName, parameters.Namespace); + + logger.info('Deployment modifications applied', { + deploymentName, + parameters, + }); +} + +/** + * Setup storage locations via Management API + */ +async function setupStorageLocations(parameters: ZenkoWorldParameters): Promise { + if (!parameters.InstanceID) { + logger.info('InstanceID not available, skipping storage location setup'); + return; + } + + logger.info('Setting up storage locations...'); + + // Create a minimal Zenko instance for Management API calls + const zenkoInstance = { + parameters, + managementAPIRequest: async ( + method: string, + path: string, + headers: Record = {}, + body?: unknown, + ) => { + const axios = (await import('axios')).default; + const baseURL = `http://management.${parameters.subdomain}`; + + try { + const response = await axios({ + method, + url: `${baseURL}${path}`, + headers: { + 'Content-Type': 'application/json', + ...headers, + }, + data: body, + }); + return { statusCode: response.status, data: response.data }; + } catch (error: any) { // eslint-disable-line @typescript-eslint/no-explicit-any + if (error.response) { + return { statusCode: error.response.status, err: error.response.data }; + } + return { statusCode: 500, err: error.message }; + } + }, + logger, + }; + + const locations = [ + // AWS Backend Source Location + { + name: 'awsbackend', + locationType: 'location-aws-s3-v1', + details: { + bucketName: 'ci-zenko-aws-target-bucket', + endpoint: `aws-mock.${parameters.Namespace}.svc.cluster.local`, + accessKey: 'accessKey1', + secretKey: 'verySecretKey1', + bucketMatch: true, + repoId: [], + }, + }, + // AWS Backend Destination Location (for replication) + { + name: 'awsbackendmismatch', + locationType: 'location-aws-s3-v1', + legacyAwsBehavior: true, + details: { + bucketName: 'ci-zenko-aws-crr-target-bucket', + endpoint: `aws-mock.${parameters.Namespace}.svc.cluster.local`, + accessKey: 'accessKey1', + secretKey: 'verySecretKey1', + bucketMatch: false, + repoId: [], + }, + }, + // AWS Backend Fail Location (for failure testing) + { + name: 'awsbackendfail', + locationType: 'location-aws-s3-v1', + details: { + bucketName: 'ci-zenko-aws-fail-target-bucket', + endpoint: `aws-mock.${parameters.Namespace}.svc.cluster.local`, + accessKey: 'accessKey1', + secretKey: 'verySecretKey1', + bucketMatch: true, + repoId: [], + }, + }, + // AWS Backend Replication Fail CTST Location + { + name: 'awsbackendreplicationctstfail', + locationType: 'location-aws-s3-v1', + details: { + bucketName: 'ci-zenko-aws-replication-fail-ctst-bucket', + endpoint: `aws-mock.${parameters.Namespace}.svc.cluster.local`, + accessKey: 'accessKey1', + secretKey: 'verySecretKey1', + bucketMatch: false, + repoId: [], + }, + }, + // Cold Storage Location (used in dmf.feature, quotas.feature, pra.feature) + { + name: 'e2e-cold', + locationType: 'location-dmf-v1', + isCold: true, + details: { + endpoint: 'ws://mock-sorbet:5001/session', + username: 'user1', + password: 'pass1', + repoId: [ + '233aead6-1d7b-4647-a7cf-0d3280b5d1d7', + '81e78de8-df11-4acd-8ad1-577ff05a68db', + ], + nsId: '65f9fd61-42fe-4a68-9ac0-6ba25311cc85', + }, + }, + // Azure Archive Location (used extensively in azureArchive.feature with hardcoded name) + { + name: 'e2e-azure-archive', + locationType: 'location-azure-archive-v1', + isCold: true, + details: { + // eslint-disable-next-line max-len + endpoint: `https://${parameters.AzureAccountName}.blob.azure-mock.${parameters.Namespace}.svc.cluster.local`, + bucketName: parameters.AzureArchiveContainer, + queue: { + type: 'location-azure-storage-queue-v1', + queueName: parameters.AzureArchiveQueue, + // eslint-disable-next-line max-len + endpoint: `https://${parameters.AzureAccountName}.queue.azure-mock.${parameters.Namespace}.svc.cluster.local`, + }, + auth: { + type: 'location-azure-shared-key', + accountName: parameters.AzureAccountName, + accountKey: parameters.AzureAccountKey, + }, + repoId: ['233aead6-1d7b-4647-a7cf-0d3280b5d1d7'], + }, + }, + ]; + + const creationResults = await Promise.allSettled( + locations.map(async location => { + try { + const result = await zenkoInstance.managementAPIRequest( + 'POST', + `/config/${parameters.InstanceID}/location`, + {}, + location + ); + + if (result.statusCode === 201) { + logger.info(`Successfully created location: ${location.name}`); + return { location: location.name, success: true }; + } else if (result.statusCode === 409) { + logger.info(`Location already exists: ${location.name}`); + return { location: location.name, success: true, existed: true }; + } else { + logger.error(`Failed to create location ${location.name}`, { + statusCode: result.statusCode, + error: result.err || result.data, + }); + return { location: location.name, success: false, error: result.err || result.data }; + } + } catch (error) { + logger.error(`Exception creating location ${location.name}`, { error }); + return { location: location.name, success: false, error }; + } + }) + ); + + // Log results + const successful = creationResults.filter(r => r.status === 'fulfilled' && r.value.success); + const failed = creationResults.filter(r => r.status === 'rejected' || !r.value?.success); + + logger.info(`Storage location setup completed: ${successful.length} successful, ${failed.length} failed`); + + if (failed.length > 0) { + const failedNames = failed.map(r => + r.status === 'fulfilled' ? r.value.location : 'unknown' + ); + logger.warn(`Failed to create locations: ${failedNames.join(', ')}`); + } +} + +/** + * Setup cluster RBAC (cluster-admin binding for service accounts) + */ +async function setupClusterRBAC(rbacClient: RbacAuthorizationV1Api): Promise { + const clusterRoleBinding: V1ClusterRoleBinding = { + apiVersion: 'rbac.authorization.k8s.io/v1', + kind: 'ClusterRoleBinding', + metadata: { + name: 'serviceaccounts-cluster-admin', + }, + roleRef: { + apiGroup: 'rbac.authorization.k8s.io', + kind: 'ClusterRole', + name: 'cluster-admin', + }, + subjects: [ + { + apiGroup: 'rbac.authorization.k8s.io', + kind: 'Group', + name: 'system:serviceaccounts', + }, + ], + }; + + try { + await rbacClient.createClusterRoleBinding({ body: clusterRoleBinding }); + logger.info('Cluster RBAC binding created successfully'); + } catch (error) { + if ((error as { response?: { statusCode: number } }).response?.statusCode === 409) { + logger.info('Cluster RBAC binding already exists'); + } else { + logger.error('Failed to create cluster RBAC binding', { error }); + throw error; + } + } +} + +BeforeAll({ timeout: 15 * 60 * 1000 }, async function () { + await coordinate( + { + lockName: 'ctst-setup', + timeout: 15 * 60 * 1000, + logger, + }, + async () => { + logger.info('Performing CTST cluster setup...'); + await setupClusterConfiguration(this.parameters as ZenkoWorldParameters); + }, + async () => { + await extractAndCacheParameters(this.parameters as ZenkoWorldParameters); + } + ); + logger.info('Final parameters:', { parameters: this.parameters, cachedParameters: CacheHelper.parameters }); +}); diff --git a/tests/ctst/steps/utils/kubernetes.ts b/tests/ctst/steps/utils/kubernetes.ts index 4650fa14b5..981958682c 100644 --- a/tests/ctst/steps/utils/kubernetes.ts +++ b/tests/ctst/steps/utils/kubernetes.ts @@ -15,6 +15,7 @@ import { BatchV1Api, V1Pod, } from '@kubernetes/client-node'; +import { ZenkoCR } from 'world/ZenkoCR'; type ZenkoStatusValue = { lastTransitionTime: string, @@ -125,8 +126,8 @@ export async function createJobAndWaitForCompletion( world.logger.debug(`Acquired lock for job: ${jobName}`); // Read the cron job and prepare the job spec - const cronJob = await batchClient.readNamespacedCronJob(jobName, 'default'); - const cronJobSpec = cronJob.body.spec?.jobTemplate.spec; + const cronJob = await batchClient.readNamespacedCronJob({ name: jobName, namespace: 'default' }); + const cronJobSpec = cronJob.spec?.jobTemplate.spec; const job = new V1Job(); const metadata = new V1ObjectMeta(); @@ -143,10 +144,10 @@ export async function createJobAndWaitForCompletion( job.metadata = metadata; // Create the job - const response = await batchClient.createNamespacedJob('default', job); - world.logger.debug('Job created', { job: response.body.metadata }); + const response = await batchClient.createNamespacedJob({ namespace: 'default', body: job }); + world.logger.debug('Job created', { job: response.metadata }); - const expectedJobName = response.body.metadata?.name; + const expectedJobName = response.metadata?.name; // Watch for job completion await new Promise((resolve, reject) => { @@ -174,7 +175,7 @@ export async function createJobAndWaitForCompletion( ); }); } catch (err: unknown) { - world.logger.error('Error creating or waiting for job completion', { + world.logger.debug('Error creating or waiting for job completion', { jobName, err, }); @@ -195,8 +196,8 @@ export async function createAndRunPod( const watchClient = createKubeWatchClient(world); try { - const response = await clientCore.createNamespacedPod('default', podManifest); - const podName = response.body.metadata?.name; + const response = await clientCore.createNamespacedPod({ namespace: 'default', body: podManifest }); + const podName = response.metadata?.name; if (waitForCompletion && podName) { world.logger.debug('Waiting for pod completion', { podName }); @@ -219,7 +220,7 @@ export async function createAndRunPod( resolve(); } else if (phase === 'Failed') { clearTimeout(timeoutId); - world.logger.error('Pod failed', { + world.logger.debug('Pod failed', { podName, status: watchObj.object?.status }); @@ -240,15 +241,15 @@ export async function createAndRunPod( if (cleanup && podName) { world.logger.debug('Cleaning up pod', { podName }); try { - await clientCore.deleteNamespacedPod(podName, 'default'); + await clientCore.deleteNamespacedPod({ name: podName, namespace: 'default' }); } catch (cleanupErr) { world.logger.warn('Failed to cleanup pod', { podName, err: cleanupErr }); } } - return response.body; + return response; } catch (err: unknown) { - world.logger.error('Failed to create and run pod:', { err }); + world.logger.debug('Failed to create and run pod:', { err }); throw new Error(`Failed to create and run pod: ${err}`); } } @@ -284,18 +285,18 @@ export async function waitForZenkoToStabilize( // zenko status. let reconciliationDetected = !needsReconciliation; - world.logger.debug('Waiting for Zenko to stabilize'); + world.logger.info('Waiting for Zenko to stabilize'); const zenkoClient = createKubeCustomObjectClient(world); while (!status && Date.now() - startTime < timeout) { - const zenkoCR = await zenkoClient.getNamespacedCustomObject( - 'zenko.io', - 'v1alpha2', + const zenkoCR = await zenkoClient.getNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha2', namespace, - 'zenkos', - 'end2end', - ).catch(err => { - world.logger.error('Error getting Zenko CR', { + plural: 'zenkos', + name: 'end2end' + }).catch(err => { + world.logger.info('Error getting Zenko CR', { err: err as unknown, }); return null; @@ -306,7 +307,7 @@ export async function waitForZenkoToStabilize( continue; } - const conditions: ZenkoStatus = (zenkoCR.body as { + const conditions: ZenkoStatus = (zenkoCR as { status: { conditions: ZenkoStatus, }, @@ -322,7 +323,7 @@ export async function waitForZenkoToStabilize( } }); - world.logger.debug('Checking Zenko CR status', { + world.logger.info('Checking Zenko CR status', { conditions, deploymentFailure, deploymentInProgress, @@ -367,8 +368,8 @@ export async function waitForDataServicesToStabilize(world: Zenko, timeout = 15 // First list all deployments, and then filter the ones with an annotation that matches the data services const deployments: V1Deployment[] = []; - const serviceDeployments = await appsClient.listNamespacedDeployment(namespace); - for (const deployment of serviceDeployments.body.items) { + const serviceDeployments = await appsClient.listNamespacedDeployment({ namespace }); + for (const deployment of serviceDeployments.items) { const annotations = deployment.metadata?.annotations; if (annotations && dataServices.some(service => annotations[annotationKey]?.includes(service))) { deployments.push(deployment); @@ -389,11 +390,12 @@ export async function waitForDataServicesToStabilize(world: Zenko, timeout = 15 throw new Error('Deployment name not found'); } - const deploymentStatus = await appsClient.readNamespacedDeploymentStatus(deploymentName, namespace); - const replicas = deploymentStatus.body.status?.replicas; - const readyReplicas = deploymentStatus.body.status?.readyReplicas; - const updatedReplicas = deploymentStatus.body.status?.updatedReplicas; - const availableReplicas = deploymentStatus.body.status?.availableReplicas; + // eslint-disable-next-line max-len + const deploymentStatus = await appsClient.readNamespacedDeploymentStatus({ name: deploymentName, namespace }); + const replicas = deploymentStatus.status?.replicas; + const readyReplicas = deploymentStatus.status?.readyReplicas; + const updatedReplicas = deploymentStatus.status?.updatedReplicas; + const availableReplicas = deploymentStatus.status?.availableReplicas; world.logger.debug('Checking deployment status', { deployment: deploymentName, @@ -423,72 +425,47 @@ export async function waitForDataServicesToStabilize(world: Zenko, timeout = 15 return allRunning; } -export async function displayCRStatus(world: Zenko, namespace = 'default') { - const zenkoClient = createKubeCustomObjectClient(world); - - const zenkoCR = await zenkoClient.getNamespacedCustomObject( - 'zenko.io', - 'v1alpha2', - namespace, - 'zenkos', - 'end2end', - ).catch(err => { - world.logger.error('Error getting Zenko CR', { - err: err as unknown, - }); - return null; - }); - - if (!zenkoCR) { - return; - } - - world.logger.debug('Checking Zenko CR status', { - zenkoCR, - }); -} - export async function getDRSource(world: Zenko, namespace = 'default') { const zenkoClient = createKubeCustomObjectClient(world); - const zenkoCR = await zenkoClient.getNamespacedCustomObject( - 'zenko.io', - 'v1alpha1', + const zenkoCR = await zenkoClient.getNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha1', namespace, - 'zenkodrsources', - 'end2end-source', - ).catch(err => { + plural: 'zenkodrsources', + name: 'end2end-source' + }).catch(err => { world.logger.debug('Error getting Zenko CR', { err: err as unknown, }); }); - return zenkoCR?.body; + return zenkoCR; } export async function getDRSink(world: Zenko, namespace = 'default') { const zenkoClient = createKubeCustomObjectClient(world); - const zenkoCR = await zenkoClient.getNamespacedCustomObject( - 'zenko.io', - 'v1alpha1', + const zenkoCR = await zenkoClient.getNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha1', namespace, - 'zenkodrsinks', - 'end2end-pra-sink', - ).catch(err => { + plural: 'zenkodrsinks', + name: 'end2end-pra-sink' + }).catch(err => { world.logger.debug('Error getting Zenko CR', { err: err as unknown, }); }); - return zenkoCR?.body; + return zenkoCR; } export async function getPVCFromLabel(world: Zenko, label: string, value: string, namespace = 'default') { const coreClient = createKubeCoreClient(world); - const pvcList = await coreClient.listNamespacedPersistentVolumeClaim(namespace); - const pvc = pvcList.body.items.find((pvc: V1PersistentVolumeClaim) => pvc.metadata?.labels?.[label] === value); + const pvcList = await coreClient.listNamespacedPersistentVolumeClaim({ namespace }); + const pvc = pvcList.items.find((pvc: V1PersistentVolumeClaim) => pvc.metadata?.labels?.[label] === value); return pvc; } @@ -511,7 +488,7 @@ export async function createSecret( }; try { - await coreClient.deleteNamespacedSecret(secretName, namespace); + await coreClient.deleteNamespacedSecret({ name: secretName, namespace }); } catch (err) { world.logger.debug('Secret does not exist, creating new', { secretName, @@ -521,10 +498,10 @@ export async function createSecret( } try { - const response = await coreClient.createNamespacedSecret(namespace, secret); + const response = await coreClient.createNamespacedSecret({ namespace, body: secret }); return response; } catch (err) { - world.logger.error('Error creating secret', { + world.logger.debug('Error creating secret', { namespace, secret, err, @@ -540,15 +517,15 @@ export async function getMongoDBConfig( const customObjectClient = createKubeCustomObjectClient(world); try { // Get replicaSetHosts from Zenko CR - const zenkoCR = await customObjectClient.getNamespacedCustomObject( - 'zenko.io', - 'v1alpha2', + const zenkoCR = await customObjectClient.getNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha2', namespace, - 'zenkos', - 'end2end' - ); + plural: 'zenkos', + name: 'end2end' + }); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mongodbSpec = (zenkoCR.body as any)?.spec?.mongodb; + const mongodbSpec = (zenkoCR as any)?.spec?.mongodb; const mongodbConfig = { replicaSetHosts: mongodbSpec?.endpoints || [], }; @@ -568,16 +545,12 @@ export async function getLocationConfigs( const coreClient = createKubeCoreClient(world); try { // Get location configurations from connector-cloudserver-config secret - const secretList = await coreClient.listNamespacedSecret( + const secretList = await coreClient.listNamespacedSecret({ namespace, - undefined, - undefined, - undefined, - undefined, - 'app.kubernetes.io/name=connector-cloudserver-config' - ); - - const secret = secretList.body.items[0]; + labelSelector: 'app.kubernetes.io/name=connector-cloudserver-config' + }); + + const secret = secretList.items[0]; const locationConfigData = secret.data?.['locationConfig.json']; if (!locationConfigData) { throw new Error('locationConfig.json not found in secret'); @@ -597,13 +570,13 @@ export async function getZenkoVersion( ): Promise { const customObjectClient = createKubeCustomObjectClient(world); try { - const zenkoVersionList = await customObjectClient.listNamespacedCustomObject( - 'zenko.io', - 'v1alpha1', + const zenkoVersionList = await customObjectClient.listNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha1', namespace, - 'zenkoversions' - ); - const zenkoVersionItems = (zenkoVersionList.body as { items: ZenkoVersion[] })?.items; + plural: 'zenkoversions' + }); + const zenkoVersionItems = (zenkoVersionList as { items: ZenkoVersion[] })?.items; if (!zenkoVersionItems || zenkoVersionItems.length === 0) { throw new Error('No ZenkoVersion resources found'); } @@ -615,3 +588,187 @@ export async function getZenkoVersion( } } +/** + * Execute a shell command in a pod with host volume access + * Simplified to only support host path mounting for system volumes + * @param world - The Zenko world object + * @param command - The command to execute + * @param options - The options for the command execution + * @returns The output of the command + */ +export async function execCommandWithVolumeAccess( + world: Zenko, + command: string, + options: { + volumeMountPath?: string; + hostPath?: string; + image?: string; + namespace?: string; + timeout?: number; + cleanup?: boolean; + } = {} +): Promise { + const { + volumeMountPath = '/cold-data', + hostPath = '/cold-data', + image = 'alpine:3.22', + namespace = 'default', + timeout = 30000, + cleanup = true, + } = options; + + // Generate unique pod name to prevent conflicts between concurrent tests + const timestamp = Date.now(); + const randomId = Math.random().toString(36).substring(2, 8); + const testContext = world.getSaved?.('bucketName') || 'test'; + const podName = `ctst-exec-${testContext}-${timestamp}-${randomId}`.toLowerCase(); + + const podManifest: V1Pod = { + apiVersion: 'v1', + kind: 'Pod', + metadata: { + name: podName, + namespace, + labels: { + 'app.kubernetes.io/name': 'ctst-command-executor', + 'app.kubernetes.io/component': 'test-utility', + 'ctst.test/execution-id': `${timestamp}-${randomId}` + } + }, + spec: { + restartPolicy: 'Never', + securityContext: { + runAsNonRoot: false, + fsGroup: 0 + }, + containers: [{ + name: 'executor', + image, + command: ['/bin/sh', '-c', command], + securityContext: { + runAsUser: 0, + allowPrivilegeEscalation: false, + readOnlyRootFilesystem: false, + capabilities: { + drop: ['ALL'] + } + }, + volumeMounts: [{ + name: 'host-volume', + mountPath: volumeMountPath + }] + }], + volumes: [{ + name: 'host-volume', + hostPath: { + path: hostPath, + type: 'DirectoryOrCreate' + } + }] + } + }; + + try { + await createAndRunPod(world, podManifest, true, false, timeout); + + const coreClient = createKubeCoreClient(world); + const logs = await coreClient.readNamespacedPodLog({ name: podName, namespace }); + + if (cleanup) { + try { + await coreClient.deleteNamespacedPod({ name: podName, namespace }); + world.logger.debug('Pod cleaned up after log retrieval', { podName }); + } catch (cleanupErr) { + world.logger.warn('Failed to cleanup pod after log retrieval', { podName, err: cleanupErr }); + } + } + + return logs.trim(); + } catch (error) { + world.logger.debug('Command execution failed', { + command, + podName, + error: error instanceof Error ? error.message : String(error) + }); + + if (cleanup) { + const coreClient = createKubeCoreClient(world); + await coreClient.deleteNamespacedPod({ name: podName, namespace }); + } + + throw error; + } +} + +/** + * Execute command in Kubernetes cluster with host volume access + * Designed for concurrent test execution without conflicts + * Uses unique pod names and labels for isolation + */ +export async function execInCluster( + world: Zenko, + command: string, + volumeOptions?: Parameters[2] +): Promise { + world.logger.debug('Executing command in cluster', { command }); + + try { + return await execCommandWithVolumeAccess(world, command, volumeOptions); + } catch (error) { + world.logger.debug('Kubernetes command execution failed', { + command, + error, + }); + throw error; + } +} + +/** + * Wait for deployment rollout to complete + */ +export async function waitForDeploymentRollout( + appsClient: AppsV1Api, + deploymentName: string, + namespace: string, + timeoutMs = 120000, +) { + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutMs) { + const deployment = await appsClient.readNamespacedDeployment({ name: deploymentName, namespace }); + const status = deployment.status; + + if (status?.readyReplicas === status?.replicas && + status?.updatedReplicas === status?.replicas && + status?.replicas && status.replicas > 0) { + return; + } + + await new Promise(resolve => setTimeout(resolve, 2000)); + } + + throw new Error(`Deployment ${deploymentName} rollout timed out after ${timeoutMs}ms`); +} + +/** + * Get Zenko Custom Resource + */ +export async function getZenkoCR(world: Zenko, namespace = 'default', name = 'end2end'): Promise { + const zenkoClient = createKubeCustomObjectClient(world); + + const zenkoCR = await zenkoClient.getNamespacedCustomObject({ + group: 'zenko.io', + version: 'v1alpha2', + namespace, + plural: 'zenkos', + name + }).catch(err => { + world.logger.debug('Error getting Zenko CR', { + err: err as unknown, + }); + return; + }); + + return zenkoCR as ZenkoCR; +} + diff --git a/tests/ctst/steps/utils/utils.ts b/tests/ctst/steps/utils/utils.ts index ceef07ece0..2220696b46 100644 --- a/tests/ctst/steps/utils/utils.ts +++ b/tests/ctst/steps/utils/utils.ts @@ -169,8 +169,7 @@ async function createBucketWithConfiguration( withObjectLock?: string, retentionMode?: string) { world.resetCommand(); - const preName = world.getSaved('accountName') || - world.parameters.AccountName || Constants.ACCOUNT_NAME; + const preName = world.getSaved('accountName') || Zenko.ACCOUNT_NAME; const usedBucketName = bucketName || `${preName}${Constants.BUCKET_NAME_TEST}${Utils.randomString()}`.toLocaleLowerCase(); world.addToSaved('bucketName', usedBucketName); diff --git a/tests/ctst/world/Zenko.ts b/tests/ctst/world/Zenko.ts index ef94be2d6c..bb3fff2a32 100644 --- a/tests/ctst/world/Zenko.ts +++ b/tests/ctst/world/Zenko.ts @@ -4,8 +4,6 @@ import { AccessKey } from '@aws-sdk/client-iam'; import { Credentials } from '@aws-sdk/client-sts'; import { aws4Interceptor } from 'aws4-axios'; import qs from 'qs'; -import fs from 'fs'; -import lockFile from 'proper-lockfile'; import Werelogs from 'werelogs'; import { CacheHelper, @@ -20,6 +18,7 @@ import { Utils, AWSCredentials, Logger, + coordinate, } from 'cli-testing'; import { extractPropertyFromResults } from '../common/utils'; @@ -89,6 +88,7 @@ export interface ZenkoWorldParameters extends ClientOptions { SorbetdRestoreTimeout: string; UtilizationServiceHost: string; UtilizationServicePort: string; + Namespace: string; [key: string]: unknown; } @@ -122,6 +122,11 @@ 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 CTST configuration values + static readonly ACCOUNT_NAME = 'zenko-ctst'; + static readonly SSL_ENABLED = false; + static readonly PORT = '80'; /** * @constructor @@ -638,72 +643,68 @@ export default class Zenko extends World { if (!Identity.hasIdentity(IdentityEnum.ACCOUNT, accountName)) { Identity.useIdentity(IdentityEnum.ADMIN, site.adminIdentityName); - const filePath = `/tmp/account-init-${accountName}.json`; - if (!fs.existsSync(filePath)) { - fs.writeFileSync(filePath, JSON.stringify({ - ready: false, - })); - } - let account = null; - let releaseLock: (() => Promise) | null = null; - try { - releaseLock = await lockFile.lock(filePath, { - stale: Constants.DEFAULT_TIMEOUT / 2, - retries: { - retries: 5, - factor: 3, - minTimeout: 1000, - maxTimeout: 5000, + + await coordinate( + { + lockName: `account-init-${accountName}`, + timeout: Constants.DEFAULT_TIMEOUT / 2, + logger: CacheHelper.logger, + }, + // Work function: executed exactly once + async () => { + try { + await SuperAdmin.createAccount({ accountName }); + } catch (err) { + if (!(err as { EntityAlreadyExists: boolean }).EntityAlreadyExists && + (err as { code: string }).code !== 'EntityAlreadyExists') { + throw err; + } } - }); - - try { - await SuperAdmin.createAccount({ accountName }); - /* eslint-disable */ - } catch (err: any) { - if (!err.EntityAlreadyExists && err.code !== 'EntityAlreadyExists') { - throw err; + }, + // Post-processing function: executed by all workers + async () => { + // Waiting until the account exists, in case of parallel mode. + let remaining = Constants.MAX_ACCOUNT_CHECK_RETRIES; + let account = await SuperAdmin.getAccount({ accountName }); + while (!account && remaining > 0) { + await Utils.sleep(500); + account = await SuperAdmin.getAccount({ accountName }); + remaining--; + } + if (!account) { + throw new Error(`Account ${accountName} not found in site ${siteKey}.`); } - } - } finally { - if (releaseLock) { - await releaseLock(); - } - } - /* eslint-enable */ - // Waiting until the account exists, in case of parallel mode. - let remaining = Constants.MAX_ACCOUNT_CHECK_RETRIES; - account = await SuperAdmin.getAccount({ accountName }); - while (!account && remaining > 0) { - await Utils.sleep(500); - account = await SuperAdmin.getAccount({ accountName }); - remaining--; - } - if (!account) { - throw new Error(`Account ${accountName} not found in site ${siteKey}.`); - } - // Account was found, generate access keys if not provided - const accountAccessKeys = Identity.getCredentialsForIdentity( - IdentityEnum.ACCOUNT, accountName) || { - accessKeyId: '', - secretAccessKey: '', - }; - - if (!accountAccessKeys.accessKeyId || !accountAccessKeys.secretAccessKey) { - const accessKeys = await SuperAdmin.generateAccountAccessKey({ accountName }); - if (!Utils.isAccessKeys(accessKeys)) { - throw new Error('Failed to generate account access keys for site ${siteKey}'); - } - accountAccessKeys.accessKeyId = accessKeys.accessKeyId; - accountAccessKeys.secretAccessKey = accessKeys.secretAccessKey; - } + // Account was found, generate access keys if not provided + const accountAccessKeys = Identity.getCredentialsForIdentity( + IdentityEnum.ACCOUNT, accountName) || { + accessKeyId: '', + secretAccessKey: '', + }; + + if (!accountAccessKeys.accessKeyId || !accountAccessKeys.secretAccessKey) { + const accessKeys = await SuperAdmin.generateAccountAccessKey({ accountName }); + if (!Utils.isAccessKeys(accessKeys)) { + throw new Error(`Failed to generate account access keys for site ${siteKey}`); + } + accountAccessKeys.accessKeyId = accessKeys.accessKeyId; + accountAccessKeys.secretAccessKey = accessKeys.secretAccessKey; + } - CacheHelper.logger.debug('Adding account identity', { - accountName, - accountAccessKeys, - }); - Identity.addIdentity(IdentityEnum.ACCOUNT, accountName, accountAccessKeys, undefined, true, true); + CacheHelper.logger.debug('Adding account identity', { + accountName, + accountAccessKeys, + }); + Identity.addIdentity( + IdentityEnum.ACCOUNT, + accountName, + accountAccessKeys, + undefined, + true, + true, + ); + } + ); } } diff --git a/tests/ctst/world/ZenkoCR.ts b/tests/ctst/world/ZenkoCR.ts new file mode 100644 index 0000000000..18956205f3 --- /dev/null +++ b/tests/ctst/world/ZenkoCR.ts @@ -0,0 +1,494 @@ +export type ZenkoConditionType = 'Available' | 'DeploymentInProgress' | 'DeploymentFailure'; + +export type ZenkoCondition = { + type: ZenkoConditionType; + status: 'True' | 'False' | 'Unknown'; + lastTransitionTime?: string; + reason?: string; + message?: string; +}; + +export type ZenkoComponentIngress = { + hostname?: string; + annotations?: Record; +}; + +export type ZenkoSpecKafkaCleaner = { + logLevel?: string; + interval?: string; + kafkaErrorsWarningThreshold?: number; +}; + +export type ZenkoSpecSorbetServerAzureConfig = { + archiveTier?: string; + rehydrationTier?: string; + rehydrationPrefix?: string; + restoreTimeout?: string; + blockSize?: string; + pollingDelay?: string; +}; + +export type ZenkoSpecSorbetServerConfig = { + jobTimeout?: string; + azure?: ZenkoSpecSorbetServerAzureConfig; +}; + +export type ZenkoSpecSorbet = { + enable?: boolean; + jobStoreCollection?: string; + expirationJobStoreCollection?: string; + server?: ZenkoSpecSorbetServerConfig; +}; + +export type ZenkoSpecScubaExternalAPI = { + replicas?: number; + ingress?: ZenkoComponentIngress; +}; + +export type ZenkoSpecScuba = { + replicas?: number; + api?: ZenkoSpecScubaExternalAPI; +}; + +export type ZenkoSpecManagementOIDC = { + provider?: string; + federatedProviders?: string[]; + uiClientId?: string; + uiControlPlaneClientId?: string; + uiWorkloadPlaneProviderUrl?: string; + uiControlPlaneProviderUrl?: string; + vaultClientId?: string; + ingress?: ZenkoComponentIngress; +}; + +export type ZenkoSpecManagement = { + provider?: 'InCluster' | 'Orbit'; + endpoint?: string; + pushEndpoint?: string; + oidc?: ZenkoSpecManagementOIDC; +}; + +export type ZenkoSpecPersistence = { + resources?: ZenkoSpecResourcesSpec; +}; + +// v1alpha1 types that are extended in v1alpha2 +export type ZenkoSpecResourcesSpec = { + requestCPU?: string; + requestMemory?: string; + limitCPU?: string; + limitMemory?: string; +}; + +export type ZenkoSpecAffinity = { + nodeAffinity?: Record; + podAffinity?: Record; + podAntiAffinity?: Record; +}; + +export type ZenkoSpecComponentSpec = { + replicas?: number; + resources?: ZenkoSpecResourcesSpec; +}; + +export type ZenkoSpecMongoDB = { + provider?: 'External'; + persistence?: ZenkoSpecPersistence; + endpoints?: string[]; + userSecretName?: string; + usernameKey?: string; + passwordKey?: string; + replicaSetName?: string; + writeConcern?: string; + readPreference?: 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest'; + databaseName?: string; + enableSharding?: boolean; + metricsJobName?: string; + metricsShardJobName?: string; +}; + +export type ZenkoSpecZookeeperProvider = 'Managed' | 'External'; + +export type ZenkoSpecZookeeper = { + provider?: ZenkoSpecZookeeperProvider; + persistence?: ZenkoSpecPersistence; + endpoints?: string[]; +}; + +export type ZenkoSpecKafkaProvider = 'Managed' | 'External'; + +// v1alpha2 enhanced Kafka types +export type ZenkoSpecKafkaManagedClusterUser = { + name?: string; + secretName?: string; +}; + +export type ZenkoSpecKafkaManagedClusterExternalListener = { + type?: 'haproxy'; + tls?: boolean; + port?: number; + brokerIpAddresses?: Record; +}; + +export type ZenkoSpecKafkaManagedCluster = { + persistence?: ZenkoSpecPersistence; + zkAddresses?: string[]; + jmxJarPath?: string; + kafkaConfigFilesCM?: string; + resources?: ZenkoSpecResourcesSpec; + externalListener?: ZenkoSpecKafkaManagedClusterExternalListener; + users?: ZenkoSpecKafkaManagedClusterUser[]; + defaultBrokerAffinity?: ZenkoSpecAffinity; +}; + +export type ZenkoSpecKafkaExternalClusterTLSCA = { + secretName?: string; +}; + +export type ZenkoSpecKafkaExternalClusterTLSAuth = { + secretName?: string; +}; + +export type ZenkoSpecKafkaExternalClusterTLS = { + enable?: boolean; + auth?: ZenkoSpecKafkaExternalClusterTLSAuth; + ca?: ZenkoSpecKafkaExternalClusterTLSCA; + hostAliases?: Record[]; +}; + +export type ZenkoSpecKafkaExternalCluster = { + brokers?: string[]; + tls?: ZenkoSpecKafkaExternalClusterTLS; +}; + +export type ZenkoSpecKafkaCluster = { + replicas?: number; + managed?: ZenkoSpecKafkaManagedCluster; + external?: ZenkoSpecKafkaExternalCluster; + connect?: ZenkoSpecKafkaConnect; + maxMessageBytes?: string; + versions?: Record; + remainingDiskSpaceWarningThreshold?: number; + maxConsumerLagMessagesWarningThreshold?: number; + maxConsumerLagSecondsWarningThreshold?: number; +}; + +// v1alpha1 Kafka (simpler version) +export type ZenkoSpecKafka = { + provider?: ZenkoSpecKafkaProvider; + persistence?: ZenkoSpecPersistence; + brokers?: string[]; + jmxJarPath?: string; + kafkaConfigFiles?: string; + + // v1alpha2 extensions + cluster?: ZenkoSpecKafkaCluster; +}; + +export type ZenkoSpecRedisProvider = 'Zenko'; + +export type ZenkoSpecRedis = { + provider?: ZenkoSpecRedisProvider; + persistence?: ZenkoSpecPersistence; +}; + +export type ZenkoSpecLocalData = { + persistence?: ZenkoSpecPersistence; +}; + +export type ZenkoSpecBlobserver = { + replicas?: number; + enable?: boolean; +}; + +export type ZenkoSpecJabba = { + replicas?: number; + ingress?: ZenkoComponentIngress; +}; + +// v1alpha2 enhanced component types +export type ZenkoSpecMetrics = { + scrapePath?: string; + scrapePort?: string; + scrapeInterval?: string; +}; + +export type ZenkoSpecLogging = { + logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error'; + dumpLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error'; +}; + +export type ZenkoSpecComponentSpecV2 = { + replicas?: number; + metrics?: ZenkoSpecMetrics; + logging?: ZenkoSpecLogging; + // resources.SchedulingSpec inline + nodeSelector?: Record; + tolerations?: Record[]; + affinity?: ZenkoSpecAffinity; +}; + +export type ZenkoSpecCloudserver = { + replicas?: number; + ingress?: ZenkoComponentIngress; + + // v1alpha2 enhancements + metrics?: ZenkoSpecMetrics; + logging?: ZenkoSpecLogging; + systemErrorsWarningThreshold?: number; + systemErrorsCriticalThreshold?: number; + listingLatencyWarningThreshold?: number; + listingLatencyCriticalThreshold?: number; + deleteLatencyWarningThreshold?: number; + deleteLatencyCriticalThreshold?: number; + quotaUnavailabilityThreshold?: number; +}; + +export type ZenkoSpecInternalCloudserver = { + enable?: boolean; + replicas?: number; + ingress?: ZenkoComponentIngress; + metrics?: ZenkoSpecMetrics; + logging?: ZenkoSpecLogging; +}; + +// v1alpha2 enhanced Backbeat types +export type ZenkoSpecBackbeatRetryBackoff = { + minMs?: number; + maxMs?: number; + jitterPercent?: number; + factorPercent?: number; +}; + +export type ZenkoSpecBackbeatRetry = { + maxRetries?: number; + timeoutSeconds?: number; + backoff?: ZenkoSpecBackbeatRetryBackoff; +}; + +export type ZenkoSpecBackbeatConcurrency = { + concurrency?: number; +}; + +export type ZenkoSpecCircuitBreakerProbe = { + noop?: boolean; + kafkaLag?: boolean; + prometheus?: boolean; +}; + +export type ZenkoSpecCircuitBreaker = { + probes?: ZenkoSpecCircuitBreakerProbe[]; + nominalEvaluateInterval?: string; + trippedEvaluateInterval?: string; + stabilizingEvaluateInterval?: string; + stabilizeAfterNSuccesses?: number; +}; + +export type ZenkoSpecBackbeatComponentSpec = { + replicas?: number; + concurrency?: number; + retry?: ZenkoSpecBackbeatRetry; + circuitBreaker?: ZenkoSpecCircuitBreaker; +}; + +export type ZenkoSpecBackbeatLifecycleConductor = { + concurrency?: number; + cronRule?: string; + circuitBreaker?: ZenkoSpecCircuitBreaker; + concurrentIndexBuildLimit?: number; +}; + +export type ZenkoSpecBackbeatLifecycleBucketProcessor = { + replicas?: number; + concurrency?: number; + triggerTransitionsOneDayEarlierForTesting?: boolean; +}; + +export type ZenkoSpecBackbeatReplicationRetry = { + aws?: ZenkoSpecBackbeatRetry; + azure?: ZenkoSpecBackbeatRetry; + gcp?: ZenkoSpecBackbeatRetry; + scality?: ZenkoSpecBackbeatRetry; +}; + +export type ZenkoSpecBackbeatReplicationDataProcessor = { + replicas?: number; + concurrency?: number; + mpuPartsConcurrency?: number; + retry?: ZenkoSpecBackbeatReplicationRetry; + circuitBreaker?: ZenkoSpecCircuitBreaker; +}; + +export type ZenkoSpecBackbeatBucketNotification = { + replicas?: number; + concurrency?: number; + backbeatTopic?: string; + useDedicatedTopicsByDefault?: boolean; + enable?: boolean; + failedNotificationWarningThreshold?: number; + failedNotificationCriticalThreshold?: number; +}; + +export type ZenkoSpecBackbeat = { + replicas?: number; + triggerExpirationsOneDayEarlierForTesting?: boolean; + replicationErrorsWarningThreshold?: number; + replicationErrorsCriticalThreshold?: number; + rpoWarningThreshold?: string; + rpoCriticalThreshold?: string; + latencyWarningThreshold?: string; + latencyCriticalThreshold?: string; + lifecycleLatencyWarningThreshold?: string; + lifecycleLatencyCriticalThreshold?: string; + + // v1alpha2 component specifications + lifecyclePopulator?: ZenkoSpecBackbeatComponentSpec; + lifecycleConductor?: ZenkoSpecBackbeatLifecycleConductor; + lifecycleBucketProcessor?: ZenkoSpecBackbeatLifecycleBucketProcessor; + lifecycleObjectProcessor?: ZenkoSpecBackbeatComponentSpec; + lifecycleTransitionProcessor?: ZenkoSpecBackbeatComponentSpec; + replicationProducer?: ZenkoSpecBackbeatComponentSpec; + replicationDataProcessor?: ZenkoSpecBackbeatReplicationDataProcessor; + replicationStatusProcessor?: ZenkoSpecBackbeatComponentSpec; + garbageCollector?: ZenkoSpecBackbeatComponentSpec; + ingestionProducer?: ZenkoSpecBackbeatComponentSpec; + ingestionProcessor?: ZenkoSpecBackbeatComponentSpec; + oplogPopulator?: ZenkoSpecBackbeatComponentSpec; + notificationProducer?: ZenkoSpecBackbeatComponentSpec; + bucketNotification?: ZenkoSpecBackbeatBucketNotification; +}; + +export type ZenkoSpecUtapi = { + replicas?: number; + enable?: boolean; + controlPlaneIngress?: ZenkoComponentIngress; + workloadPlaneIngress?: ZenkoComponentIngress; +}; + +export type ZenkoSpecVault = { + replicas?: number; + enable?: boolean; + iamIngress?: ZenkoComponentIngress; + stsIngress?: ZenkoComponentIngress; + noImplicitDeny?: boolean; + + // v1alpha2 enhancements + metrics?: ZenkoSpecMetrics; + logging?: ZenkoSpecLogging; + systemErrorsWarningThreshold?: number; + systemErrorsCriticalThreshold?: number; + authenticationLatencyWarningThreshold?: number; + authenticationLatencyCriticalThreshold?: number; + authorizationLatencyWarningThreshold?: number; + authorizationLatencyCriticalThreshold?: number; +}; + +// v1alpha2 additional component types +export type ZenkoSpecVeeamSOSApi = { + enable?: boolean; + cronRule?: string; +}; + +export type ZenkoSpecS3utils = { + metrics?: ZenkoSpecMetrics; + countItemsJobDurationThreshold?: string; + updateBucketCapacityInfoJobDurationThreshold?: string; + updateBucketCapacityInfoSuccessJobExistenceDurationThreshold?: string; + cronRule?: string; +}; + +export type ZenkoSpecKafkaConnect = { + replicas?: number; + clusterGroupId?: string; + configStorageTopic?: string; + offsetStorageTopic?: string; + statusStorageTopic?: string; +}; + +export type ZenkoSpecRegistry = { + imagePullSecretNames?: string[]; +}; + +export type ZenkoSpecIngress = { + controlPlaneClass?: string; + workloadPlaneClass?: string; + certificates?: Record[]; + annotations?: Record; +}; + +export type ZenkoSpecEgressProxyCA = { + 'ca.crt'?: string; + secretName?: string; + secretAttributeName?: string; +}; + +export type ZenkoSpecEgressProxy = { + https?: string; + http?: string; + ca?: ZenkoSpecEgressProxyCA; + exclude?: string[]; +}; + +export type ZenkoSpecEgress = { + proxy?: ZenkoSpecEgressProxy; + skipTLSVerify?: boolean; +}; + +export type ZenkoSpec = { + version?: string; + replicas?: number; + management?: ZenkoSpecManagement; + registry?: ZenkoSpecRegistry; + ingress?: ZenkoSpecIngress; + egress?: ZenkoSpecEgress; + initialConfiguration?: Record; + + // v1alpha1 components + mongodb?: ZenkoSpecMongoDB; + zookeeper?: ZenkoSpecZookeeper; + kafka?: ZenkoSpecKafka; + redis?: ZenkoSpecRedis; + localData?: ZenkoSpecLocalData; + blobserver?: ZenkoSpecBlobserver; + jabba?: ZenkoSpecJabba; + cloudserver?: ZenkoSpecCloudserver; + backbeat?: ZenkoSpecBackbeat; + utapi?: ZenkoSpecUtapi; + vault?: ZenkoSpecVault; + + // v1alpha2 additions and enhancements + kafkaCleaner?: ZenkoSpecKafkaCleaner; + kafkaConnect?: ZenkoSpecKafkaConnect; + sorbet?: ZenkoSpecSorbet; + scuba?: ZenkoSpecScuba; + internalCloudserver?: ZenkoSpecInternalCloudserver; + + // Additional v1alpha2 fields + dashboardFolder?: string; + veeamSosApi?: ZenkoSpecVeeamSOSApi; + s3utils?: ZenkoSpecS3utils; +}; + +export type ZenkoStatus = { + instanceID?: string; + readyReplicas?: number; + conditions?: ZenkoCondition[]; + observedGeneration?: number; +}; + +export type ZenkoCR = { + apiVersion?: string; + kind?: string; + metadata?: { + name?: string; + namespace?: string; + annotations?: { + 'zenko.io/time-progression-factor'?: string; + 'zenko.io/service-users-seq'?: string; + [key: string]: string | undefined; + }; + labels?: Record; + }; + spec?: ZenkoSpec; + status?: ZenkoStatus; +}; diff --git a/tests/ctst/yarn.lock b/tests/ctst/yarn.lock index b87653453a..3343dd8544 100644 --- a/tests/ctst/yarn.lock +++ b/tests/ctst/yarn.lock @@ -80,7 +80,7 @@ "@smithy/util-utf8" "^2.0.0" tslib "^2.6.2" -"@aws-sdk/client-iam@^3.582.0", "@aws-sdk/client-iam@^3.637.0": +"@aws-sdk/client-iam@^3.582.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.864.0.tgz#8d250deb90f2f6e628c2bfc4d2da8520b2246fc8" integrity sha512-uTlSDLJntfHSC4LZVfuf8xhPx907cPlLYf00Wsz4gEPPLFkKNOPCbxzRqEsFG4haGkBENMc3U1cMt3iE/BGnSg== @@ -126,7 +126,53 @@ "@smithy/util-waiter" "^4.0.7" tslib "^2.6.2" -"@aws-sdk/client-s3@^3.583.0", "@aws-sdk/client-s3@^3.637.0": +"@aws-sdk/client-iam@^3.879.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-iam/-/client-iam-3.886.0.tgz#ab7c458ce6a304a482630e93295decbf6f885092" + integrity sha512-w/DJIoG2nOlSyuGKTl7d4AWs7hJ3+J612jLYJujqne0H6LlkPUZTW9IBNmzMXWuF3JYM8rVOMTfRpocKkcWS6A== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/credential-provider-node" "3.886.0" + "@aws-sdk/middleware-host-header" "3.873.0" + "@aws-sdk/middleware-logger" "3.876.0" + "@aws-sdk/middleware-recursion-detection" "3.886.0" + "@aws-sdk/middleware-user-agent" "3.883.0" + "@aws-sdk/region-config-resolver" "3.873.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-endpoints" "3.879.0" + "@aws-sdk/util-user-agent-browser" "3.873.0" + "@aws-sdk/util-user-agent-node" "3.883.0" + "@smithy/config-resolver" "^4.1.5" + "@smithy/core" "^3.9.2" + "@smithy/fetch-http-handler" "^5.1.1" + "@smithy/hash-node" "^4.0.5" + "@smithy/invalid-dependency" "^4.0.5" + "@smithy/middleware-content-length" "^4.0.5" + "@smithy/middleware-endpoint" "^4.1.21" + "@smithy/middleware-retry" "^4.1.22" + "@smithy/middleware-serde" "^4.0.9" + "@smithy/middleware-stack" "^4.0.5" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/node-http-handler" "^4.1.1" + "@smithy/protocol-http" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/url-parser" "^4.0.5" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.29" + "@smithy/util-defaults-mode-node" "^4.0.29" + "@smithy/util-endpoints" "^3.0.7" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-retry" "^4.0.7" + "@smithy/util-utf8" "^4.0.0" + "@smithy/util-waiter" "^4.0.7" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.583.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.864.0.tgz#ffbcbf0ba861fad711261b4174da3be19b1c7d5f" integrity sha512-QGYi9bWliewxumsvbJLLyx9WC0a4DP4F+utygBcq0zwPxaM0xDfBspQvP1dsepi7mW5aAjZmJ2+Xb7X0EhzJ/g== @@ -190,6 +236,70 @@ tslib "^2.6.2" uuid "^9.0.1" +"@aws-sdk/client-s3@^3.879.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.886.0.tgz#5ee89042c0b7cc492549233af2c1802611369cf3" + integrity sha512-IuZ2EHiSMkEqjOJk/QMQG55zGpj/iDkKNS1V3oKV6ClstmErySBfW0Ri8GuW7WJ1k1pkFO+hvgL6yn1yO+Y6XQ== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/credential-provider-node" "3.886.0" + "@aws-sdk/middleware-bucket-endpoint" "3.873.0" + "@aws-sdk/middleware-expect-continue" "3.873.0" + "@aws-sdk/middleware-flexible-checksums" "3.883.0" + "@aws-sdk/middleware-host-header" "3.873.0" + "@aws-sdk/middleware-location-constraint" "3.873.0" + "@aws-sdk/middleware-logger" "3.876.0" + "@aws-sdk/middleware-recursion-detection" "3.886.0" + "@aws-sdk/middleware-sdk-s3" "3.883.0" + "@aws-sdk/middleware-ssec" "3.873.0" + "@aws-sdk/middleware-user-agent" "3.883.0" + "@aws-sdk/region-config-resolver" "3.873.0" + "@aws-sdk/signature-v4-multi-region" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-endpoints" "3.879.0" + "@aws-sdk/util-user-agent-browser" "3.873.0" + "@aws-sdk/util-user-agent-node" "3.883.0" + "@aws-sdk/xml-builder" "3.873.0" + "@smithy/config-resolver" "^4.1.5" + "@smithy/core" "^3.9.2" + "@smithy/eventstream-serde-browser" "^4.0.5" + "@smithy/eventstream-serde-config-resolver" "^4.1.3" + "@smithy/eventstream-serde-node" "^4.0.5" + "@smithy/fetch-http-handler" "^5.1.1" + "@smithy/hash-blob-browser" "^4.0.5" + "@smithy/hash-node" "^4.0.5" + "@smithy/hash-stream-node" "^4.0.5" + "@smithy/invalid-dependency" "^4.0.5" + "@smithy/md5-js" "^4.0.5" + "@smithy/middleware-content-length" "^4.0.5" + "@smithy/middleware-endpoint" "^4.1.21" + "@smithy/middleware-retry" "^4.1.22" + "@smithy/middleware-serde" "^4.0.9" + "@smithy/middleware-stack" "^4.0.5" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/node-http-handler" "^4.1.1" + "@smithy/protocol-http" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/url-parser" "^4.0.5" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.29" + "@smithy/util-defaults-mode-node" "^4.0.29" + "@smithy/util-endpoints" "^3.0.7" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-retry" "^4.0.7" + "@smithy/util-stream" "^4.2.4" + "@smithy/util-utf8" "^4.0.0" + "@smithy/util-waiter" "^4.0.7" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + "@aws-sdk/client-sso@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.864.0.tgz#4099313516d61ed61791551c6f0683259b9cbf5e" @@ -234,7 +344,51 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" -"@aws-sdk/client-sts@^3.4.1", "@aws-sdk/client-sts@^3.583.0", "@aws-sdk/client-sts@^3.637.0": +"@aws-sdk/client-sso@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.886.0.tgz#127dbe0651f90ac39e71b08001c673507dac80be" + integrity sha512-CwpPZBlONsUO6OvMzNNP9PETZ3dPCQum3nUisk5VuzLTvNd80w2aWeSN/TpcAAbNvcRYbM+FsC4gBm4Q4VWn0g== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/middleware-host-header" "3.873.0" + "@aws-sdk/middleware-logger" "3.876.0" + "@aws-sdk/middleware-recursion-detection" "3.886.0" + "@aws-sdk/middleware-user-agent" "3.883.0" + "@aws-sdk/region-config-resolver" "3.873.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-endpoints" "3.879.0" + "@aws-sdk/util-user-agent-browser" "3.873.0" + "@aws-sdk/util-user-agent-node" "3.883.0" + "@smithy/config-resolver" "^4.1.5" + "@smithy/core" "^3.9.2" + "@smithy/fetch-http-handler" "^5.1.1" + "@smithy/hash-node" "^4.0.5" + "@smithy/invalid-dependency" "^4.0.5" + "@smithy/middleware-content-length" "^4.0.5" + "@smithy/middleware-endpoint" "^4.1.21" + "@smithy/middleware-retry" "^4.1.22" + "@smithy/middleware-serde" "^4.0.9" + "@smithy/middleware-stack" "^4.0.5" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/node-http-handler" "^4.1.1" + "@smithy/protocol-http" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/url-parser" "^4.0.5" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.29" + "@smithy/util-defaults-mode-node" "^4.0.29" + "@smithy/util-endpoints" "^3.0.7" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-retry" "^4.0.7" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@^3.4.1", "@aws-sdk/client-sts@^3.583.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.864.0.tgz#67eb3e35953a552331d999ed8f26ec458bdf6d15" integrity sha512-g3To8L5T9rRoF1Nsx7Bf7VxBd/6fYu/YdSnLmjAW7QJ4yGvP4l4gTY//jFksapniD/kLVJXyNuS5PJBwGzvw5Q== @@ -279,6 +433,51 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/client-sts@^3.879.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.886.0.tgz#4b1e5664f3ca26d8136a7b77933448483ab408b9" + integrity sha512-7ucGZylYyxtaTSJSOWLzsWdQ9bQoH8Yt+IPznTRCauX3oXPHKxBUCeikWwkcVzYCrjLHvGpej9fxWCxH67jqrQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/credential-provider-node" "3.886.0" + "@aws-sdk/middleware-host-header" "3.873.0" + "@aws-sdk/middleware-logger" "3.876.0" + "@aws-sdk/middleware-recursion-detection" "3.886.0" + "@aws-sdk/middleware-user-agent" "3.883.0" + "@aws-sdk/region-config-resolver" "3.873.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-endpoints" "3.879.0" + "@aws-sdk/util-user-agent-browser" "3.873.0" + "@aws-sdk/util-user-agent-node" "3.883.0" + "@smithy/config-resolver" "^4.1.5" + "@smithy/core" "^3.9.2" + "@smithy/fetch-http-handler" "^5.1.1" + "@smithy/hash-node" "^4.0.5" + "@smithy/invalid-dependency" "^4.0.5" + "@smithy/middleware-content-length" "^4.0.5" + "@smithy/middleware-endpoint" "^4.1.21" + "@smithy/middleware-retry" "^4.1.22" + "@smithy/middleware-serde" "^4.0.9" + "@smithy/middleware-stack" "^4.0.5" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/node-http-handler" "^4.1.1" + "@smithy/protocol-http" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/url-parser" "^4.0.5" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.29" + "@smithy/util-defaults-mode-node" "^4.0.29" + "@smithy/util-endpoints" "^3.0.7" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-retry" "^4.0.7" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/core@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.864.0.tgz#5ea4e400bb479faf4e0aa71a32ec89e8a3f2ceaf" @@ -300,6 +499,27 @@ fast-xml-parser "5.2.5" tslib "^2.6.2" +"@aws-sdk/core@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.883.0.tgz#1674b371784188f26fd39ad6ea9edafd8c385e20" + integrity sha512-FmkqnqBLkXi4YsBPbF6vzPa0m4XKUuvgKDbamfw4DZX2CzfBZH6UU4IwmjNV3ZM38m0xraHarK8KIbGSadN3wg== + dependencies: + "@aws-sdk/types" "3.862.0" + "@aws-sdk/xml-builder" "3.873.0" + "@smithy/core" "^3.9.2" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/property-provider" "^4.0.5" + "@smithy/protocol-http" "^5.1.3" + "@smithy/signature-v4" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-utf8" "^4.0.0" + fast-xml-parser "5.2.5" + tslib "^2.6.2" + "@aws-sdk/credential-provider-env@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.864.0.tgz#32e048eafaad51e3c67ef34d1310cc19f2f67c38" @@ -311,6 +531,17 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/credential-provider-env@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.883.0.tgz#834f1e92eca815fe2005d2ae3ec021153e863788" + integrity sha512-Z6tPBXPCodfhIF1rvQKoeRGMkwL6TK0xdl1UoMIA1x4AfBpPICAF77JkFBExk/pdiFYq1d04Qzddd/IiujSlLg== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-http@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.864.0.tgz#e312b137c1fdce87adb5140b039516c077726f5c" @@ -327,6 +558,22 @@ "@smithy/util-stream" "^4.2.4" tslib "^2.6.2" +"@aws-sdk/credential-provider-http@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.883.0.tgz#91e9d15631cc83df068f7ce91a645938d142edcb" + integrity sha512-P589ug1lMOOEYLTaQJjSP+Gee34za8Kk2LfteNQfO9SpByHFgGj++Sg8VyIe30eZL8Q+i4qTt24WDCz1c+dgYg== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@smithy/fetch-http-handler" "^5.1.1" + "@smithy/node-http-handler" "^4.1.1" + "@smithy/property-provider" "^4.0.5" + "@smithy/protocol-http" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/util-stream" "^4.2.4" + tslib "^2.6.2" + "@aws-sdk/credential-provider-ini@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.864.0.tgz#3149745e91d030f191ad618e7ee15c92101ad24e" @@ -346,6 +593,25 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/credential-provider-ini@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.886.0.tgz#6f5bb13252b065477daebd7bb618b5eb3e6b3527" + integrity sha512-86ZuuUGLzzYqxkglFBUMCsvb7vSr+IeIPkXD/ERuX9wX0xPxBK961UG7pygO7yaAVzcHSWbWArAXOcEWVlk+7Q== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/credential-provider-env" "3.883.0" + "@aws-sdk/credential-provider-http" "3.883.0" + "@aws-sdk/credential-provider-process" "3.883.0" + "@aws-sdk/credential-provider-sso" "3.886.0" + "@aws-sdk/credential-provider-web-identity" "3.886.0" + "@aws-sdk/nested-clients" "3.886.0" + "@aws-sdk/types" "3.862.0" + "@smithy/credential-provider-imds" "^4.0.7" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-node@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.864.0.tgz#d01277b53ac179d2ea97ba16147ba0cb3f710aae" @@ -364,6 +630,24 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/credential-provider-node@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.886.0.tgz#89073d8a27689c56174fcf8215e248818b70916c" + integrity sha512-hyXQrUW6bXkSWOZlNWnNcbXsjM0CBIOfutDFd3tS7Ilhqkx8P3eptT0fVR8GFxNg/ruq5PvnybGK83brUmD7tw== + dependencies: + "@aws-sdk/credential-provider-env" "3.883.0" + "@aws-sdk/credential-provider-http" "3.883.0" + "@aws-sdk/credential-provider-ini" "3.886.0" + "@aws-sdk/credential-provider-process" "3.883.0" + "@aws-sdk/credential-provider-sso" "3.886.0" + "@aws-sdk/credential-provider-web-identity" "3.886.0" + "@aws-sdk/types" "3.862.0" + "@smithy/credential-provider-imds" "^4.0.7" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-process@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.864.0.tgz#5f39e34a084cfa07966874955fa3aa0f966bcf15" @@ -376,6 +660,18 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/credential-provider-process@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.883.0.tgz#00938bd9257a7affb041386d92b708dbdee8dc58" + integrity sha512-m1shbHY/Vppy4EdddG9r8x64TO/9FsCjokp5HbKcZvVoTOTgUJrdT8q2TAQJ89+zYIJDqsKbqfrmfwJ1zOdnGQ== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-sso@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.864.0.tgz#1556640016f9bd3dd1c2e140270098a75c922ca3" @@ -390,6 +686,20 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/credential-provider-sso@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.886.0.tgz#87899424255801ce85b0d711708b61d21e69b839" + integrity sha512-KxNgGcT/2ec7XBhiYGBYlk+UyiMqosi5LzLjq2qR4nYf8Deo/lCtbqXSQplwSQ0JIV2kNDcnMQiSafSS9TrL/A== + dependencies: + "@aws-sdk/client-sso" "3.886.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/token-providers" "3.886.0" + "@aws-sdk/types" "3.862.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/credential-provider-web-identity@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.864.0.tgz#5cf54ec064957552e4c8c9070fd2b313f152a776" @@ -402,6 +712,18 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/credential-provider-web-identity@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.886.0.tgz#9f234d8624447e498a901acb1840cb0ebe19a985" + integrity sha512-pilcy1GUOr4lIWApTcgJLGL+t79SOoe66pzmranQhbn+HGAp2VgiZizeID9P3HLmZObStVal4yTaJur0hWb5ZQ== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/nested-clients" "3.886.0" + "@aws-sdk/types" "3.862.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/hash-node@^3.110.0": version "3.374.0" resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.374.0.tgz#fad2ddb51ae7091b91ed1308836fe3385d128f9e" @@ -423,6 +745,19 @@ "@smithy/util-config-provider" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-bucket-endpoint@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.873.0.tgz#cfc2d87328e3d9fecd165e4f5caa4cf1a22b220d" + integrity sha512-b4bvr0QdADeTUs+lPc9Z48kXzbKHXQKgTvxx/jXDgSW9tv4KmYPO1gIj6Z9dcrBkRWQuUtSW3Tu2S5n6pe+zeg== + dependencies: + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-arn-parser" "3.873.0" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/protocol-http" "^5.1.3" + "@smithy/types" "^4.3.2" + "@smithy/util-config-provider" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-expect-continue@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.862.0.tgz#f53c28c41f63859362797fd76e993365b598d0ba" @@ -433,6 +768,16 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-expect-continue@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.873.0.tgz#2d4fea9104070d06c26f6f978eb038e807f3ca34" + integrity sha512-GIqoc8WgRcf/opBOZXFLmplJQKwOMjiOMmDz9gQkaJ8FiVJoAp8EGVmK2TOWZMQUYsavvHYsHaor5R2xwPoGVg== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/protocol-http" "^5.1.3" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/middleware-flexible-checksums@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.864.0.tgz#fcbb40ae1513f96185ec961693c0f55ec1f4da18" @@ -452,6 +797,25 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-flexible-checksums@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.883.0.tgz#b15629c1737e7bd52a7a7ee1a62149dd23b54681" + integrity sha512-EloU4ZjkH+CXCHJcYElXo5nZ1vK6Miam/S02YSHk5JTrJkm4RV478KXXO29TIIAwZXcLT/FEQOZ9ZH/JHFFCFQ== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-crypto/util" "5.2.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@smithy/is-array-buffer" "^4.0.0" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/protocol-http" "^5.1.3" + "@smithy/types" "^4.3.2" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-stream" "^4.2.4" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-host-header@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.862.0.tgz#9b5fa0ad4c17a84816b4bfde7cda949116374042" @@ -462,6 +826,16 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-host-header@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.873.0.tgz#81e9c2f61674b96337472bcaefd85ce3b7a24f7b" + integrity sha512-KZ/W1uruWtMOs7D5j3KquOxzCnV79KQW9MjJFZM/M0l6KI8J6V3718MXxFHsTjUE4fpdV6SeCNLV1lwGygsjJA== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/protocol-http" "^5.1.3" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/middleware-location-constraint@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.862.0.tgz#d55babadc9f9b7150c56b028fc6953021a5a565a" @@ -471,6 +845,15 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-location-constraint@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.873.0.tgz#aab9e90d0545087102709b68ca1a1c816e3c58cf" + integrity sha512-r+hIaORsW/8rq6wieDordXnA/eAu7xAPLue2InhoEX6ML7irP52BgiibHLpt9R0psiCzIHhju8qqKa4pJOrmiw== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/middleware-logger@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.862.0.tgz#fba26924421135c824dec7e1cd0f75990a588fdb" @@ -480,6 +863,15 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-logger@3.876.0": + version "3.876.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.876.0.tgz#16ee45f7bcd887badc8f12d80eef9ba18a0ac97c" + integrity sha512-cpWJhOuMSyz9oV25Z/CMHCBTgafDCbv7fHR80nlRrPdPZ8ETNsahwRgltXP1QJJ8r3X/c1kwpOR7tc+RabVzNA== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/middleware-recursion-detection@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.862.0.tgz#d83433251e550b7ed9cd731a447c92aaec378f01" @@ -490,6 +882,17 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-recursion-detection@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.886.0.tgz#2ba280503609b63fbe28bc92ca37ad51a048b06f" + integrity sha512-yMMlPqiX1SXFwQ0L1a/U19rdXx7eYseHsJEC9F9M5LUUPBI7k117nA0vXxvsvODVQ6JKtY7nTiPrc98GcVKgnw== + dependencies: + "@aws-sdk/types" "3.862.0" + "@aws/lambda-invoke-store" "^0.0.1" + "@smithy/protocol-http" "^5.1.3" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/middleware-sdk-s3@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.864.0.tgz#5142210471ed702452277ad653af483147c42598" @@ -510,6 +913,26 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/middleware-sdk-s3@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.883.0.tgz#419019a4c301427d9941e7577cefbe4a6242692f" + integrity sha512-i4sGOj9xhSN6/LkYj3AJ2SRWENnpN9JySwNqIoRqO1Uon8gfyNLJd1yV+s43vXQsU5wbKWVXK8l9SRo+vNTQwg== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-arn-parser" "3.873.0" + "@smithy/core" "^3.9.2" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/protocol-http" "^5.1.3" + "@smithy/signature-v4" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-stream" "^4.2.4" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/middleware-ssec@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.862.0.tgz#d6c7d03c966cb6642acec8c7f046afd3a72c0f7c" @@ -519,6 +942,15 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-ssec@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.873.0.tgz#e7dd0d5184f536197c14a9e256e74e1354d74168" + integrity sha512-AF55J94BoiuzN7g3hahy0dXTVZahVi8XxRBLgzNp6yQf0KTng+hb/V9UQZVYY1GZaDczvvvnqC54RGe9OZZ9zQ== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/middleware-user-agent@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.864.0.tgz#7c8a5e7f09eb2855f9a045cdfeee56e099e15552" @@ -532,6 +964,19 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/middleware-user-agent@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.883.0.tgz#6b48003f6c047d8755ad85329bab192557f935b3" + integrity sha512-q58uLYnGLg7hsnWpdj7Cd1Ulsq1/PUJOHvAfgcBuiDE/+Fwh0DZxZZyjrU+Cr+dbeowIdUaOO8BEDDJ0CUenJw== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-endpoints" "3.879.0" + "@smithy/core" "^3.9.2" + "@smithy/protocol-http" "^5.1.3" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/nested-clients@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.864.0.tgz#8d8b7e8e481649ae0f6ef37339b07cd8f6405e74" @@ -576,6 +1021,50 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@aws-sdk/nested-clients@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.886.0.tgz#bc9a8227c63fc7917d7e9f7a69e33b4dda5c42ee" + integrity sha512-CqeRdkNyJ7LlKLQtMTzK11WIiryEK8JbSL5LCia0B1Lp22OByDUiUSFZZ3FZq9poD5qHQI63pHkzAr5WkLGS5A== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.883.0" + "@aws-sdk/middleware-host-header" "3.873.0" + "@aws-sdk/middleware-logger" "3.876.0" + "@aws-sdk/middleware-recursion-detection" "3.886.0" + "@aws-sdk/middleware-user-agent" "3.883.0" + "@aws-sdk/region-config-resolver" "3.873.0" + "@aws-sdk/types" "3.862.0" + "@aws-sdk/util-endpoints" "3.879.0" + "@aws-sdk/util-user-agent-browser" "3.873.0" + "@aws-sdk/util-user-agent-node" "3.883.0" + "@smithy/config-resolver" "^4.1.5" + "@smithy/core" "^3.9.2" + "@smithy/fetch-http-handler" "^5.1.1" + "@smithy/hash-node" "^4.0.5" + "@smithy/invalid-dependency" "^4.0.5" + "@smithy/middleware-content-length" "^4.0.5" + "@smithy/middleware-endpoint" "^4.1.21" + "@smithy/middleware-retry" "^4.1.22" + "@smithy/middleware-serde" "^4.0.9" + "@smithy/middleware-stack" "^4.0.5" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/node-http-handler" "^4.1.1" + "@smithy/protocol-http" "^5.1.3" + "@smithy/smithy-client" "^4.5.2" + "@smithy/types" "^4.3.2" + "@smithy/url-parser" "^4.0.5" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.29" + "@smithy/util-defaults-mode-node" "^4.0.29" + "@smithy/util-endpoints" "^3.0.7" + "@smithy/util-middleware" "^4.0.5" + "@smithy/util-retry" "^4.0.7" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + "@aws-sdk/region-config-resolver@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.862.0.tgz#99e7942be513abacb715d06781e6f4d62b3e9cf2" @@ -588,6 +1077,18 @@ "@smithy/util-middleware" "^4.0.5" tslib "^2.6.2" +"@aws-sdk/region-config-resolver@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.873.0.tgz#9a5ddf8aa5a068d1c728dda3ef7e5b31561f7419" + integrity sha512-q9sPoef+BBG6PJnc4x60vK/bfVwvRWsPgcoQyIra057S/QGjq5VkjvNk6H8xedf6vnKlXNBwq9BaANBXnldUJg== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/types" "^4.3.2" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.0.5" + tslib "^2.6.2" + "@aws-sdk/signature-v4-multi-region@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.864.0.tgz#75e24f5382aa77b7e629f8feb366bcf2a358ffb8" @@ -600,6 +1101,18 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/signature-v4-multi-region@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.883.0.tgz#127440b9a2a0242e3e0d25338c3d0f1f7244283c" + integrity sha512-86PO7+xhuQ48cD3xlZgEpRxVP1lBarWAJy23sB6zZLHgZSbnYXYjRFuyxX4PlFzqllM3PDKJvq3WnXeqSXeNsg== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@smithy/protocol-http" "^5.1.3" + "@smithy/signature-v4" "^5.1.3" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/token-providers@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.864.0.tgz#c5f88c34bf268435a5b64b7814193c63ae330a68" @@ -613,6 +1126,19 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/token-providers@3.886.0": + version "3.886.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.886.0.tgz#9829095ea3b510cddf3e3c3c8cabab0584e10e1c" + integrity sha512-dYS3apmGcldFglpAiAajcdDKtKjBw/NkG6nRYIC2q7+OZsxeyzunT1EUSxV4xphLoqiuhuCg/fTnBI3WVtb3IQ== + dependencies: + "@aws-sdk/core" "3.883.0" + "@aws-sdk/nested-clients" "3.886.0" + "@aws-sdk/types" "3.862.0" + "@smithy/property-provider" "^4.0.5" + "@smithy/shared-ini-file-loader" "^4.0.5" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/types@3.862.0", "@aws-sdk/types@^3.222.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.862.0.tgz#2f5622e1aa3a5281d4f419f5d2c90f87dd5ff0cf" @@ -628,6 +1154,13 @@ dependencies: tslib "^2.6.2" +"@aws-sdk/util-arn-parser@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.873.0.tgz#12c5ea852574dfb6fe78eaac1666433dff1acffa" + integrity sha512-qag+VTqnJWDn8zTAXX4wiVioa0hZDQMtbZcGRERVnLar4/3/VIKBhxX2XibNQXFu1ufgcRn4YntT/XEPecFWcg== + dependencies: + tslib "^2.6.2" + "@aws-sdk/util-endpoints@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.862.0.tgz#d66975bbedc1899721e3bf2a548fadfaee2ba2ee" @@ -639,6 +1172,17 @@ "@smithy/util-endpoints" "^3.0.7" tslib "^2.6.2" +"@aws-sdk/util-endpoints@3.879.0": + version "3.879.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.879.0.tgz#e30c15beede883d327dbd290c47512d6d700a2e9" + integrity sha512-aVAJwGecYoEmbEFju3127TyJDF9qJsKDUUTRMDuS8tGn+QiWQFnfInmbt+el9GU1gEJupNTXV+E3e74y51fb7A== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/types" "^4.3.2" + "@smithy/url-parser" "^4.0.5" + "@smithy/util-endpoints" "^3.0.7" + tslib "^2.6.2" + "@aws-sdk/util-locate-window@^3.0.0": version "3.804.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz#a2ee8dc5d9c98276986e8e1ba03c0c84d9afb0f5" @@ -656,6 +1200,16 @@ bowser "^2.11.0" tslib "^2.6.2" +"@aws-sdk/util-user-agent-browser@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.873.0.tgz#0fcc3c1877ae74aa692cc0b4ad874bc9a6ee1ad6" + integrity sha512-AcRdbK6o19yehEcywI43blIBhOCSo6UgyWcuOJX5CFF8k39xm1ILCjQlRRjchLAxWrm0lU0Q7XV90RiMMFMZtA== + dependencies: + "@aws-sdk/types" "3.862.0" + "@smithy/types" "^4.3.2" + bowser "^2.11.0" + tslib "^2.6.2" + "@aws-sdk/util-user-agent-node@3.864.0": version "3.864.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.864.0.tgz#2fd8276a6d7d0ee3d6fe75421c5565e63ae6a0d5" @@ -667,6 +1221,17 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/util-user-agent-node@3.883.0": + version "3.883.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.883.0.tgz#584fed4347a9a4434a98026bf3e201f236bd132a" + integrity sha512-28cQZqC+wsKUHGpTBr+afoIdjS6IoEJkMqcZsmo2Ag8LzmTa6BUWQenFYB0/9BmDy4PZFPUn+uX+rJgWKB+jzA== + dependencies: + "@aws-sdk/middleware-user-agent" "3.883.0" + "@aws-sdk/types" "3.862.0" + "@smithy/node-config-provider" "^4.1.4" + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + "@aws-sdk/xml-builder@3.862.0": version "3.862.0" resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.862.0.tgz#d368c76f0f129d43b3ffbc2dc18f53ddd64ec328" @@ -675,6 +1240,19 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@aws-sdk/xml-builder@3.873.0": + version "3.873.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.873.0.tgz#b5a3acfdeecfc1b7fee8a7773cb2a45590eb5701" + integrity sha512-kLO7k7cGJ6KaHiExSJWojZurF7SnGMDHXRuQunFnEoD0n1yB6Lqy/S/zHiQ7oJnBhPr9q0TW9qFkrsZb1Uc54w== + dependencies: + "@smithy/types" "^4.3.2" + tslib "^2.6.2" + +"@aws/lambda-invoke-store@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@aws/lambda-invoke-store/-/lambda-invoke-store-0.0.1.tgz#92d792a7dda250dfcb902e13228f37a81be57c8f" + integrity sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw== + "@azure/abort-controller@^2.0.0", "@azure/abort-controller@^2.1.2": version "2.1.2" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz#42fe0ccab23841d9905812c58f1082d27784566d" @@ -775,7 +1353,7 @@ "@typespec/ts-http-runtime" "^0.3.0" tslib "^2.6.2" -"@azure/storage-blob@^12.24.0": +"@azure/storage-blob@^12.28.0": version "12.28.0" resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.28.0.tgz#a64ce49f0fe9fe08f1f7c1b36164033678d38cf6" integrity sha512-VhQHITXXO03SURhDiGuHhvc/k/sD2WvJUS7hqhiVNbErVCuQoLtWql7r97fleBlIRKHJaa9R7DpBjfE0pfLYcA== @@ -810,7 +1388,7 @@ events "^3.3.0" tslib "^2.8.1" -"@azure/storage-queue@^12.23.0": +"@azure/storage-queue@^12.27.0": version "12.27.0" resolved "https://registry.yarnpkg.com/@azure/storage-queue/-/storage-queue-12.27.0.tgz#cde0c3560b08320ed61e813132d27de716c45973" integrity sha512-GoviVZrJ1BkYCmsam0gOZFqAjH7bKbnbBIEVPkgzCz3RzsB/C05jumQep+3GavZoWw7Yw4iaCNPSyyS1lbN1Gg== @@ -828,7 +1406,7 @@ "@azure/storage-common" "^12.0.0" tslib "^2.8.1" -"@babel/code-frame@^7.0.0": +"@babel/code-frame@^7.26.2": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== @@ -859,36 +1437,38 @@ resolved "https://registry.yarnpkg.com/@cucumber/ci-environment/-/ci-environment-10.0.1.tgz#c8584f1d4a619e4318cf60c01b838db096d72ccd" integrity sha512-/+ooDMPtKSmvcPMDYnMZt4LuoipfFfHaYspStI4shqw8FyKcfQAmekz6G+QKWjQQrvM+7Hkljwx58MEwPCwwzg== -"@cucumber/cucumber-expressions@17.1.0": - version "17.1.0" - resolved "https://registry.yarnpkg.com/@cucumber/cucumber-expressions/-/cucumber-expressions-17.1.0.tgz#1a428548a2c98ef3224bd484fc5666b4f7153a72" - integrity sha512-PCv/ppsPynniKPWJr5v566daCVe+pbxQpHGrIu/Ev57cCH9Rv+X0F6lio4Id3Z64TaG7btCRLUGewIgLwmrwOA== +"@cucumber/cucumber-expressions@18.0.1": + version "18.0.1" + resolved "https://registry.yarnpkg.com/@cucumber/cucumber-expressions/-/cucumber-expressions-18.0.1.tgz#0899cbda2ed5546dbaa0e40f0c754b6e3bd1bb69" + integrity sha512-NSid6bI+7UlgMywl5octojY5NXnxR9uq+JisjOrO52VbFsQM6gTWuQFE8syI10KnIBEdPzuEUSVEeZ0VFzRnZA== dependencies: regexp-match-indices "1.0.2" -"@cucumber/cucumber@^10.9.0": - version "10.9.0" - resolved "https://registry.yarnpkg.com/@cucumber/cucumber/-/cucumber-10.9.0.tgz#1ee505b3fc513367d2ddc651ad71059c3fd544c8" - integrity sha512-7XHJ6nmr9IkIag0nv6or82HfelbSInrEe3H4aT6dMHyTehwFLUifG6eQQ+uE4LZIOXAnzLPH37YmqygEO67vCA== +"@cucumber/cucumber@^12.2.0": + version "12.2.0" + resolved "https://registry.yarnpkg.com/@cucumber/cucumber/-/cucumber-12.2.0.tgz#4243aeddf390a1514c28ed2afd7830c4f0966d3d" + integrity sha512-b7W4snvXYi1T2puUjxamASCCNhNzVSzb/fQUuGSkdjm/AFfJ24jo8kOHQyOcaoArCG71sVQci4vkZaITzl/V1w== dependencies: "@cucumber/ci-environment" "10.0.1" - "@cucumber/cucumber-expressions" "17.1.0" - "@cucumber/gherkin" "28.0.0" + "@cucumber/cucumber-expressions" "18.0.1" + "@cucumber/gherkin" "34.0.0" "@cucumber/gherkin-streams" "5.0.1" - "@cucumber/gherkin-utils" "9.0.0" - "@cucumber/html-formatter" "21.6.0" + "@cucumber/gherkin-utils" "9.2.0" + "@cucumber/html-formatter" "21.14.0" + "@cucumber/junit-xml-formatter" "0.8.1" "@cucumber/message-streams" "4.0.1" - "@cucumber/messages" "24.1.0" - "@cucumber/tag-expressions" "6.1.0" + "@cucumber/messages" "28.1.0" + "@cucumber/pretty-formatter" "1.0.1" + "@cucumber/tag-expressions" "6.2.0" assertion-error-formatter "^3.0.0" capital-case "^1.0.4" chalk "^4.1.2" - cli-table3 "0.6.3" - commander "^10.0.0" + cli-table3 "0.6.5" + commander "^14.0.0" debug "^4.3.4" error-stack-parser "^2.1.4" figures "^3.2.0" - glob "^10.3.10" + glob "^11.0.0" has-ansi "^4.0.1" indent-string "^4.0.0" is-installed-globally "^0.4.0" @@ -896,23 +1476,19 @@ knuth-shuffle-seeded "^1.0.6" lodash.merge "^4.6.2" lodash.mergewith "^4.6.2" - luxon "3.2.1" + luxon "3.7.1" mime "^3.0.0" - mkdirp "^2.1.5" + mkdirp "^3.0.0" mz "^2.7.0" progress "^2.0.3" - read-pkg-up "^7.0.1" - resolve-pkg "^2.0.0" - semver "7.5.3" + read-package-up "^11.0.0" + semver "7.7.2" string-argv "0.3.1" - strip-ansi "6.0.1" supports-color "^8.1.1" - tmp "0.2.3" - type-fest "^4.8.3" + type-fest "^4.41.0" util-arity "^1.1.0" - xmlbuilder "^15.1.1" yaml "^2.2.2" - yup "1.2.0" + yup "1.7.0" "@cucumber/gherkin-streams@5.0.1": version "5.0.1" @@ -922,45 +1498,82 @@ commander "9.1.0" source-map-support "0.5.21" -"@cucumber/gherkin-utils@9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@cucumber/gherkin-utils/-/gherkin-utils-9.0.0.tgz#944c64c458742d8e73b750e5dde2cf56b161d674" - integrity sha512-clk4q39uj7pztZuZtyI54V8lRsCUz0Y/p8XRjIeHh7ExeEztpWkp4ca9q1FjUOPfQQ8E7OgqFbqoQQXZ1Bx7fw== +"@cucumber/gherkin-utils@9.2.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@cucumber/gherkin-utils/-/gherkin-utils-9.2.0.tgz#42c50a6232022f5a17ca677a734daa4a15d0b6e1" + integrity sha512-3nmRbG1bUAZP3fAaUBNmqWO0z0OSkykZZotfLjyhc8KWwDSOrOmMJlBTd474lpA8EWh4JFLAX3iXgynBqBvKzw== dependencies: - "@cucumber/gherkin" "^28.0.0" - "@cucumber/messages" "^24.0.0" + "@cucumber/gherkin" "^31.0.0" + "@cucumber/messages" "^27.0.0" "@teppeis/multimaps" "3.0.0" - commander "12.0.0" + commander "13.1.0" source-map-support "^0.5.21" -"@cucumber/gherkin@28.0.0", "@cucumber/gherkin@^28.0.0": - version "28.0.0" - resolved "https://registry.yarnpkg.com/@cucumber/gherkin/-/gherkin-28.0.0.tgz#91246da622524807b21430c1692bedd319d3d4bb" - integrity sha512-Ee6zJQq0OmIUPdW0mSnsCsrWA2PZAELNDPICD2pLfs0Oz7RAPgj80UsD2UCtqyAhw2qAR62aqlktKUlai5zl/A== +"@cucumber/gherkin@34.0.0": + version "34.0.0" + resolved "https://registry.yarnpkg.com/@cucumber/gherkin/-/gherkin-34.0.0.tgz#891ec27a7c09a9fc3695aaf3c3a3c8a1c594102f" + integrity sha512-659CCFsrsyvuBi/Eix1fnhSheMnojSfnBcqJ3IMPNawx7JlrNJDcXYSSdxcUw3n/nG05P+ptCjmiZY3i14p+tA== + dependencies: + "@cucumber/messages" ">=19.1.4 <29" + +"@cucumber/gherkin@^31.0.0": + version "31.0.0" + resolved "https://registry.yarnpkg.com/@cucumber/gherkin/-/gherkin-31.0.0.tgz#12cff1a6e92b7d30cc5e374e91fbdd2135064aad" + integrity sha512-wlZfdPif7JpBWJdqvHk1Mkr21L5vl4EfxVUOS4JinWGf3FLRV6IKUekBv5bb5VX79fkDcfDvESzcQ8WQc07Wgw== dependencies: - "@cucumber/messages" ">=19.1.4 <=24" + "@cucumber/messages" ">=19.1.4 <=26" -"@cucumber/html-formatter@21.6.0": - version "21.6.0" - resolved "https://registry.yarnpkg.com/@cucumber/html-formatter/-/html-formatter-21.6.0.tgz#bfd8c4db31c6c96a8520332efba2ea9838ca36f0" - integrity sha512-Qw1tdObBJrgXgXwVjKVjB3hFhFPI8WhIFb+ULy8g5lDl5AdnKDiyDXAMvAWRX+pphnRMMNdkPCt6ZXEfWvUuAA== +"@cucumber/html-formatter@21.14.0": + version "21.14.0" + resolved "https://registry.yarnpkg.com/@cucumber/html-formatter/-/html-formatter-21.14.0.tgz#beb29b66892189f8e242243aa8b807f7b9dc1c6c" + integrity sha512-vQqbmQZc0QiN4c+cMCffCItpODJlOlYtPG7pH6We096dBOa7u0ttDMjT6KrMAnQlcln54rHL46r408IFpuznAw== + +"@cucumber/junit-xml-formatter@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cucumber/junit-xml-formatter/-/junit-xml-formatter-0.8.1.tgz#f27e52054d6934326c3961c683fc7f5b4d827a89" + integrity sha512-FT1Y96pyd9/ifbE9I7dbkTCjkwEdW9C0MBobUZoKD13c8EnWAt0xl1Yy/v/WZLTk4XfCLte1DATtLx01jt+YiA== + dependencies: + "@cucumber/query" "^13.0.2" + "@teppeis/multimaps" "^3.0.0" + luxon "^3.5.0" + xmlbuilder "^15.1.1" "@cucumber/message-streams@4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@cucumber/message-streams/-/message-streams-4.0.1.tgz#a5339d3504594bb2edb5732aaae94dddb24d0970" integrity sha512-Kxap9uP5jD8tHUZVjTWgzxemi/0uOsbGjd4LBOSxcJoOCRbESFwemUzilJuzNTB8pcTQUh8D5oudUyxfkJOKmA== -"@cucumber/messages@24.1.0", "@cucumber/messages@>=19.1.4 <=24", "@cucumber/messages@^24.0.0": - version "24.1.0" - resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-24.1.0.tgz#a212c97b0548144c3ccfae021a96d6c56d3841d3" - integrity sha512-hxVHiBurORcobhVk80I9+JkaKaNXkW6YwGOEFIh/2aO+apAN+5XJgUUWjng9NwqaQrW1sCFuawLB1AuzmBaNdQ== +"@cucumber/messages@28.1.0", "@cucumber/messages@>=19.1.4 <29": + version "28.1.0" + resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-28.1.0.tgz#5fdcfc3f9b30103cb45c69044ebe9a892bec38ce" + integrity sha512-2LzZtOwYKNlCuNf31ajkrekoy2M4z0Z1QGiPH40n4gf5t8VOUFb7m1ojtR4LmGvZxBGvJZP8voOmRqDWzBzYKA== dependencies: - "@types/uuid" "9.0.8" + "@types/uuid" "10.0.0" class-transformer "0.5.1" - reflect-metadata "0.2.1" - uuid "9.0.1" + reflect-metadata "0.2.2" + uuid "11.1.0" -"@cucumber/pretty-formatter@^1.0.1": +"@cucumber/messages@>=19.1.4 <=26": + version "26.0.1" + resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-26.0.1.tgz#18765481cf2580066977cbe26af111458e05c424" + integrity sha512-DIxSg+ZGariumO+Lq6bn4kOUIUET83A4umrnWmidjGFl8XxkBieUZtsmNbLYgH/gnsmP07EfxxdTr0hOchV1Sg== + dependencies: + "@types/uuid" "10.0.0" + class-transformer "0.5.1" + reflect-metadata "0.2.2" + uuid "10.0.0" + +"@cucumber/messages@^27.0.0": + version "27.2.0" + resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-27.2.0.tgz#ee0cc006a391568fb668d47a23ac2e5bf901ff3a" + integrity sha512-f2o/HqKHgsqzFLdq6fAhfG1FNOQPdBdyMGpKwhb7hZqg0yZtx9BVqkTyuoNk83Fcvk3wjMVfouFXXHNEk4nddA== + dependencies: + "@types/uuid" "10.0.0" + class-transformer "0.5.1" + reflect-metadata "0.2.2" + uuid "11.0.5" + +"@cucumber/pretty-formatter@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@cucumber/pretty-formatter/-/pretty-formatter-1.0.1.tgz#65d6c1df436920036a7bd02d08cb44d20e7af0ab" integrity sha512-A1lU4VVP0aUWdOTmpdzvXOyEYuPtBDI0xYwYJnmoMDplzxMdhcHk86lyyvYDoMoPzzq6OkOE3isuosvUU4X7IQ== @@ -970,10 +1583,25 @@ figures "^3.2.0" ts-dedent "^2.0.0" -"@cucumber/tag-expressions@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@cucumber/tag-expressions/-/tag-expressions-6.1.0.tgz#cb7af908bdb43669b7574c606f71fa707196e962" - integrity sha512-+3DwRumrCJG27AtzCIL37A/X+A/gSfxOPLg8pZaruh5SLumsTmpvilwroVWBT2fPzmno/tGXypeK5a7NHU4RzA== +"@cucumber/pretty-formatter@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@cucumber/pretty-formatter/-/pretty-formatter-2.1.0.tgz#78fc53d2d44b2ff3dcbbfb7d309b1e0a808b4a02" + integrity sha512-VufasjEZLPDzhGmikvjp8BeV/p3d7N2nArqplWn3LMqu+SddmicCS0tHk59GduQxi5SYr8ldfFe5mBDgJpUWbQ== + dependencies: + "@cucumber/query" "^13.5.0" + +"@cucumber/query@^13.0.2", "@cucumber/query@^13.5.0": + version "13.6.0" + resolved "https://registry.yarnpkg.com/@cucumber/query/-/query-13.6.0.tgz#56858d6db13c0f623f0dc18bc4114a3f03dce130" + integrity sha512-tiDneuD5MoWsJ9VKPBmQok31mSX9Ybl+U4wqDoXeZgsXHDURqzM3rnpWVV3bC34y9W6vuFxrlwF/m7HdOxwqRw== + dependencies: + "@teppeis/multimaps" "3.0.0" + lodash.sortby "^4.7.0" + +"@cucumber/tag-expressions@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@cucumber/tag-expressions/-/tag-expressions-6.2.0.tgz#9cd13c242b01b98a08142ed4987860b0b7e1d893" + integrity sha512-KIF0eLcafHbWOuSDWFw0lMmgJOLdDRWjEL1kfXEWrqHmx2119HxVAr35WuEd9z542d3Yyg+XNqSr+81rIKqEdg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": version "4.7.0" @@ -1074,6 +1702,18 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== +"@isaacs/balanced-match@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29" + integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ== + +"@isaacs/brace-expansion@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz#4b3dabab7d8e75a429414a96bd67bf4c1d13e0f3" + integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA== + dependencies: + "@isaacs/balanced-match" "^4.0.1" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -1111,27 +1751,46 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@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== +"@jsep-plugin/assignment@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" + integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== + +"@jsep-plugin/regex@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" + integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== + +"@keycloak/keycloak-admin-client@^26.3.3": + version "26.3.3" + resolved "https://registry.yarnpkg.com/@keycloak/keycloak-admin-client/-/keycloak-admin-client-26.3.3.tgz#d84d0f13ca96d7370d47b4be5a26c8b9577bf49d" + integrity sha512-gDwiB0o9N09f/OZY2dTMIuoiu99Rs/aFscN3yEfGbVfV6/DtaLxtLqfcD5G5C7/Sq+yNpqh1tMa4Ezfislcgkg== + dependencies: + camelize-ts "^3.0.0" + url-join "^5.0.0" + url-template "^3.1.1" + +"@kubernetes/client-node@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@kubernetes/client-node/-/client-node-1.3.0.tgz#6088bc1c4f6bb01f52e6e933f35008feb39fe909" + integrity sha512-IE0yrIpOT97YS5fg2QpzmPzm8Wmcdf4ueWMn+FiJSI3jgTTQT1u+LUhoYpdfhdHAVxdrNsaBg2C0UXSnOgMoCQ== 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" + "@types/node" "^22.0.0" + "@types/node-fetch" "^2.6.9" + "@types/stream-buffers" "^3.0.3" + form-data "^4.0.0" + hpagent "^1.2.0" isomorphic-ws "^5.0.0" js-yaml "^4.1.0" - jsonpath-plus "^8.0.0" - request "^2.88.0" + jsonpath-plus "^10.3.0" + node-fetch "^2.6.9" + openid-client "^6.1.3" rfc4648 "^1.3.0" + socks-proxy-agent "^8.0.4" stream-buffers "^3.0.2" - tar "^7.0.0" - tslib "^2.4.1" - ws "^8.11.0" - optionalDependencies: - openid-client "^5.3.0" + tar-fs "^3.0.8" + ws "^8.18.2" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -1185,6 +1844,14 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/abort-controller@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-4.1.1.tgz#9b3872ab6b2c061486175c281dadc0a853260533" + integrity sha512-vkzula+IwRvPR6oKQhMYioM3A/oX/lFCZiwuxkQbRhqJS2S4YRY2k7k/SyR2jMf3607HLtbEwlRxi0ndXHMjRg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/chunked-blob-reader-native@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz#33cbba6deb8a3c516f98444f65061784f7cd7f8c" @@ -1211,6 +1878,34 @@ "@smithy/util-middleware" "^4.0.5" tslib "^2.6.2" +"@smithy/config-resolver@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-4.2.1.tgz#12c24e550e2675e03a78bec64a652ed129bce718" + integrity sha512-FXil8q4QN7mgKwU2hCLm0ltab8NyY/1RiqEf25Jnf6WLS3wmb11zGAoLETqg1nur2Aoibun4w4MjeN9CMJ4G6A== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-config-provider" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + tslib "^2.6.2" + +"@smithy/core@^3.11.0", "@smithy/core@^3.9.2": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.11.0.tgz#18ee04696ca35889046169e422a894bea1bec59d" + integrity sha512-Abs5rdP1o8/OINtE49wwNeWuynCu0kme1r4RI3VXVrHr4odVDG7h7mTnw1WXXfN5Il+c25QOnrdL2y56USfxkA== + dependencies: + "@smithy/middleware-serde" "^4.1.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-body-length-browser" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-stream" "^4.3.1" + "@smithy/util-utf8" "^4.1.0" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + "@smithy/core@^3.8.0": version "3.8.0" resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.8.0.tgz#321d03564b753025b92e4476579efcd5c505ab1f" @@ -1239,6 +1934,17 @@ "@smithy/url-parser" "^4.0.5" tslib "^2.6.2" +"@smithy/credential-provider-imds@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-4.1.1.tgz#e1535a0121a98a2d872eaffc2470eccc057cebd5" + integrity sha512-1WdBfM9DwA59pnpIizxnUvBf/de18p4GP+6zP2AqrlFzoW3ERpZaT4QueBR0nS9deDMaQRkBlngpVlnkuuTisQ== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/property-provider" "^4.1.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + tslib "^2.6.2" + "@smithy/eventstream-codec@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-4.0.5.tgz#e742a4badaaf985ac9abcf4283ff4c39d7e48438" @@ -1295,6 +2001,17 @@ "@smithy/util-base64" "^4.0.0" tslib "^2.6.2" +"@smithy/fetch-http-handler@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-5.2.1.tgz#fe284a00f1b3a35edf9fba454d287b7f74ef20af" + integrity sha512-5/3wxKNtV3wO/hk1is+CZUhL8a1yy/U+9u9LKQ9kZTkMsHaQjJhc3stFfiujtMnkITjzWfndGA2f7g9Uh9vKng== + dependencies: + "@smithy/protocol-http" "^5.2.1" + "@smithy/querystring-builder" "^4.1.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + tslib "^2.6.2" + "@smithy/hash-blob-browser@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.5.tgz#f8f2857e59907c3359dc451a22c1623373115aea" @@ -1370,6 +2087,13 @@ dependencies: tslib "^2.6.2" +"@smithy/is-array-buffer@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-4.1.0.tgz#d18a2f22280e7173633cb91a9bdb6f3d8a6560b8" + integrity sha512-ePTYUOV54wMogio+he4pBybe8fwg4sDvEVDBU8ZlHOZXbXK3/C0XfJgUCu6qAZcawv05ZhZzODGUerFBPsPUDQ== + dependencies: + tslib "^2.6.2" + "@smithy/md5-js@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-4.0.5.tgz#77216159386050dbcf6b58f16f4ac14ac5183474" @@ -1402,6 +2126,20 @@ "@smithy/util-middleware" "^4.0.5" tslib "^2.6.2" +"@smithy/middleware-endpoint@^4.1.21", "@smithy/middleware-endpoint@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.2.1.tgz#54c61a113e6da7b615724d03517879d377d3888d" + integrity sha512-fUTMmQvQQZakXOuKizfu7fBLDpwvWZjfH6zUK2OLsoNZRZGbNUdNSdLJHpwk1vS208jtDjpUIskh+JoA8zMzZg== + dependencies: + "@smithy/core" "^3.11.0" + "@smithy/middleware-serde" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/shared-ini-file-loader" "^4.1.1" + "@smithy/types" "^4.5.0" + "@smithy/url-parser" "^4.1.1" + "@smithy/util-middleware" "^4.1.1" + tslib "^2.6.2" + "@smithy/middleware-retry@^4.1.19": version "4.1.19" resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.1.19.tgz#19c013c1a548e1185cc1bfabfab3f498667c9e89" @@ -1418,6 +2156,22 @@ tslib "^2.6.2" uuid "^9.0.1" +"@smithy/middleware-retry@^4.1.22": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.2.1.tgz#61be10c06e183c392a3769cb8b03c7846b37bee7" + integrity sha512-JzfvjwSJXWRl7LkLgIRTUTd2Wj639yr3sQGpViGNEOjtb0AkAuYqRAHs+jSOI/LPC0ZTjmFVVtfrCICMuebexw== + dependencies: + "@smithy/node-config-provider" "^4.2.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/service-error-classification" "^4.1.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-retry" "^4.1.1" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + "@smithy/middleware-serde@^4.0.9": version "4.0.9" resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-4.0.9.tgz#71213158bb11c1d632829001ca3f233323fb2a7c" @@ -1427,6 +2181,15 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/middleware-serde@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-4.1.1.tgz#cfb99f53c744d7730928235cbe66cc7ff8a8a9b2" + integrity sha512-lh48uQdbCoj619kRouev5XbWhCwRKLmphAif16c4J6JgJ4uXjub1PI6RL38d3BLliUvSso6klyB/LTNpWSNIyg== + dependencies: + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/middleware-stack@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-4.0.5.tgz#577050d4c0afe816f1ea85f335b2ef64f73e4328" @@ -1435,6 +2198,14 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/middleware-stack@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-4.1.1.tgz#1d533fde4ccbb62d7fc0f0b8ac518b7e4791e311" + integrity sha512-ygRnniqNcDhHzs6QAPIdia26M7e7z9gpkIMUe/pK0RsrQ7i5MblwxY8078/QCnGq6AmlUUWgljK2HlelsKIb/A== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/node-config-provider@^4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-4.1.4.tgz#42f231b7027e5a7ce003fd80180e586fe814944a" @@ -1445,6 +2216,16 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/node-config-provider@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-4.2.1.tgz#31be8865dbea9a9f23aee278a6728317d0ed0250" + integrity sha512-AIA0BJZq2h295J5NeCTKhg1WwtdTA/GqBCaVjk30bDgMHwniUETyh5cP9IiE9VrId7Kt8hS7zvREVMTv1VfA6g== + dependencies: + "@smithy/property-provider" "^4.1.1" + "@smithy/shared-ini-file-loader" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/node-http-handler@^4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.1.1.tgz#dd806d9e08b6e73125040dd0808ab56d16a178e9" @@ -1456,6 +2237,17 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/node-http-handler@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.2.1.tgz#d7ab8e31659030d3d5a68f0982f15c00b1e67a0c" + integrity sha512-REyybygHlxo3TJICPF89N2pMQSf+p+tBJqpVe1+77Cfi9HBPReNjTgtZ1Vg73exq24vkqJskKDpfF74reXjxfw== + dependencies: + "@smithy/abort-controller" "^4.1.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/querystring-builder" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/property-provider@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-4.0.5.tgz#d3b368b31d5b130f4c30cc0c91f9ebb28d9685fc" @@ -1464,6 +2256,14 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/property-provider@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-4.1.1.tgz#6e11ae6729840314afed05fd6ab48f62c654116b" + integrity sha512-gm3ZS7DHxUbzC2wr8MUCsAabyiXY0gaj3ROWnhSx/9sPMc6eYLMM4rX81w1zsMaObj2Lq3PZtNCC1J6lpEY7zg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/protocol-http@^4.1.8": version "4.1.8" resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.8.tgz#0461758671335f65e8ff3fc0885ab7ed253819c9" @@ -1480,6 +2280,14 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/protocol-http@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-5.2.1.tgz#33f2b8e4e1082c3ae0372d1322577e6fa71d7824" + integrity sha512-T8SlkLYCwfT/6m33SIU/JOVGNwoelkrvGjFKDSDtVvAXj/9gOT78JVJEas5a+ETjOu4SVvpCstKgd0PxSu/aHw== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/querystring-builder@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-4.0.5.tgz#158ae170f8ec2d8af6b84cdaf774205a7dfacf68" @@ -1489,6 +2297,15 @@ "@smithy/util-uri-escape" "^4.0.0" tslib "^2.6.2" +"@smithy/querystring-builder@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-4.1.1.tgz#4d35c1735de8214055424045a117fa5d1d5cdec1" + integrity sha512-J9b55bfimP4z/Jg1gNo+AT84hr90p716/nvxDkPGCD4W70MPms0h8KF50RDRgBGZeL83/u59DWNqJv6tEP/DHA== + dependencies: + "@smithy/types" "^4.5.0" + "@smithy/util-uri-escape" "^4.1.0" + tslib "^2.6.2" + "@smithy/querystring-parser@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-4.0.5.tgz#95706e56aa769f09dc8922d1b19ffaa06946e252" @@ -1497,6 +2314,14 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/querystring-parser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-4.1.1.tgz#21b861439b2db16abeb0a6789b126705fa25eea1" + integrity sha512-63TEp92YFz0oQ7Pj9IuI3IgnprP92LrZtRAkE3c6wLWJxfy/yOPRt39IOKerVr0JS770olzl0kGafXlAXZ1vng== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/service-error-classification@^4.0.7": version "4.0.7" resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-4.0.7.tgz#24072198a8c110d29677762162a5096e29eb4862" @@ -1504,6 +2329,13 @@ dependencies: "@smithy/types" "^4.3.2" +"@smithy/service-error-classification@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-4.1.1.tgz#86a615298ae406c3b6c7dc63c1c1738c54cfdfc6" + integrity sha512-Iam75b/JNXyDE41UvrlM6n8DNOa/r1ylFyvgruTUx7h2Uk7vDNV9AAwP1vfL1fOL8ls0xArwEGVcGZVd7IO/Cw== + dependencies: + "@smithy/types" "^4.5.0" + "@smithy/shared-ini-file-loader@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.5.tgz#8d8a493276cd82a7229c755bef8d375256c5ebb9" @@ -1512,17 +2344,12 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" -"@smithy/signature-v4@^2.1.1": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.3.0.tgz#c30dd4028ae50c607db99459981cce8cdab7a3fd" - integrity sha512-ui/NlpILU+6HAQBfJX8BBsDXuKSNrjTSuOYArRblcrErwKFutjrCNb/OExfVRyj9+26F9J+ZmfWT+fKWuDrH3Q== +"@smithy/shared-ini-file-loader@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.1.1.tgz#d4a748bb8027e1111635464c9b1e546d608fc089" + integrity sha512-YkpikhIqGc4sfXeIbzSj10t2bJI/sSoP5qxLue6zG+tEE3ngOBSm8sO3+djacYvS/R5DfpxN/L9CyZsvwjWOAQ== dependencies: - "@smithy/is-array-buffer" "^2.2.0" - "@smithy/types" "^2.12.0" - "@smithy/util-hex-encoding" "^2.2.0" - "@smithy/util-middleware" "^2.2.0" - "@smithy/util-uri-escape" "^2.2.0" - "@smithy/util-utf8" "^2.3.0" + "@smithy/types" "^4.5.0" tslib "^2.6.2" "@smithy/signature-v4@^4.1.0": @@ -1553,6 +2380,20 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@smithy/signature-v4@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-5.2.1.tgz#0048489d2f1b3c888382595a085edd31967498f8" + integrity sha512-M9rZhWQLjlQVCCR37cSjHfhriGRN+FQ8UfgrYNufv66TJgk+acaggShl3KS5U/ssxivvZLlnj7QH2CUOKlxPyA== + dependencies: + "@smithy/is-array-buffer" "^4.1.0" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-hex-encoding" "^4.1.0" + "@smithy/util-middleware" "^4.1.1" + "@smithy/util-uri-escape" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + "@smithy/smithy-client@^4.4.10": version "4.4.10" resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.4.10.tgz#c4b49c1d1ff9eb813f88f1e425a5dfac25a03180" @@ -1566,6 +2407,19 @@ "@smithy/util-stream" "^4.2.4" tslib "^2.6.2" +"@smithy/smithy-client@^4.5.2", "@smithy/smithy-client@^4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.6.1.tgz#4bebcf313431bd274da0b28c7ddc4ba335f9994b" + integrity sha512-WolVLDb9UTPMEPPOncrCt6JmAMCSC/V2y5gst2STWJ5r7+8iNac+EFYQnmvDCYMfOLcilOSEpm5yXZXwbLak1Q== + dependencies: + "@smithy/core" "^3.11.0" + "@smithy/middleware-endpoint" "^4.2.1" + "@smithy/middleware-stack" "^4.1.1" + "@smithy/protocol-http" "^5.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-stream" "^4.3.1" + tslib "^2.6.2" + "@smithy/types@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.2.0.tgz#9dc65767b0ee3d6681704fcc67665d6fc9b6a34e" @@ -1573,13 +2427,6 @@ dependencies: tslib "^2.5.0" -"@smithy/types@^2.12.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.12.0.tgz#c44845f8ba07e5e8c88eda5aed7e6a0c462da041" - integrity sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw== - dependencies: - tslib "^2.6.2" - "@smithy/types@^3.7.2": version "3.7.2" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.2.tgz#05cb14840ada6f966de1bf9a9c7dd86027343e10" @@ -1594,6 +2441,13 @@ dependencies: tslib "^2.6.2" +"@smithy/types@^4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.5.0.tgz#850e334662a1ef1286c35814940c80880400a370" + integrity sha512-RkUpIOsVlAwUIZXO1dsz8Zm+N72LClFfsNqf173catVlvRZiwPy0x2u0JLEA4byreOPKDZPGjmPDylMoP8ZJRg== + dependencies: + tslib "^2.6.2" + "@smithy/url-parser@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-4.0.5.tgz#1824a9c108b85322c5a31f345f608d47d06f073a" @@ -1603,6 +2457,15 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/url-parser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-4.1.1.tgz#0e9a5e72b3cf9d7ab7305f9093af5528d9debaf6" + integrity sha512-bx32FUpkhcaKlEoOMbScvc93isaSiRM75pQ5IgIBaMkT7qMlIibpPRONyx/0CvrXHzJLpOn/u6YiDX2hcvs7Dg== + dependencies: + "@smithy/querystring-parser" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/util-base64@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-4.0.0.tgz#8345f1b837e5f636e5f8470c4d1706ae0c6d0358" @@ -1612,6 +2475,15 @@ "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" +"@smithy/util-base64@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-4.1.0.tgz#5965026081d9aef4a8246f5702807570abe538b2" + integrity sha512-RUGd4wNb8GeW7xk+AY5ghGnIwM96V0l2uzvs/uVHf+tIuVX2WSvynk5CxNoBCsM2rQRSZElAo9rt3G5mJ/gktQ== + dependencies: + "@smithy/util-buffer-from" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" + tslib "^2.6.2" + "@smithy/util-body-length-browser@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz#965d19109a4b1e5fe7a43f813522cce718036ded" @@ -1619,6 +2491,13 @@ dependencies: tslib "^2.6.2" +"@smithy/util-body-length-browser@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-4.1.0.tgz#636bdf4bc878c546627dab4b9b0e4db31b475be7" + integrity sha512-V2E2Iez+bo6bUMOTENPr6eEmepdY8Hbs+Uc1vkDKgKNA/brTJqOW/ai3JO1BGj9GbCeLqw90pbbH7HFQyFotGQ== + dependencies: + tslib "^2.6.2" + "@smithy/util-body-length-node@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz#3db245f6844a9b1e218e30c93305bfe2ffa473b3" @@ -1658,6 +2537,14 @@ "@smithy/is-array-buffer" "^4.0.0" tslib "^2.6.2" +"@smithy/util-buffer-from@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-4.1.0.tgz#21f9e644a0eb41226d92e4eff763f76a7db7e9cc" + integrity sha512-N6yXcjfe/E+xKEccWEKzK6M+crMrlwaCepKja0pNnlSkm6SjAeLKKA++er5Ba0I17gvKfN/ThV+ZOx/CntKTVw== + dependencies: + "@smithy/is-array-buffer" "^4.1.0" + tslib "^2.6.2" + "@smithy/util-config-provider@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz#e0c7c8124c7fba0b696f78f0bd0ccb060997d45e" @@ -1665,6 +2552,13 @@ dependencies: tslib "^2.6.2" +"@smithy/util-config-provider@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-4.1.0.tgz#6a07d73446c1e9a46d7a3c125f2a9301060bc957" + integrity sha512-swXz2vMjrP1ZusZWVTB/ai5gK+J8U0BWvP10v9fpcFvg+Xi/87LHvHfst2IgCs1i0v4qFZfGwCmeD/KNCdJZbQ== + dependencies: + tslib "^2.6.2" + "@smithy/util-defaults-mode-browser@^4.0.26": version "4.0.26" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.26.tgz#fc04cd466bbb0d80e41930af8d6a8c33c48490f2" @@ -1676,6 +2570,17 @@ bowser "^2.11.0" tslib "^2.6.2" +"@smithy/util-defaults-mode-browser@^4.0.29": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.1.1.tgz#40b9659d6fc15aa1101e440d1a92579cb66ebfa3" + integrity sha512-hA1AKIHFUMa9Tl6q6y8p0pJ9aWHCCG8s57flmIyLE0W7HcJeYrYtnqXDcGnftvXEhdQnSexyegXnzzTGk8bKLA== + dependencies: + "@smithy/property-provider" "^4.1.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + bowser "^2.11.0" + tslib "^2.6.2" + "@smithy/util-defaults-mode-node@^4.0.26": version "4.0.26" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.26.tgz#adfee8c54301ec4cbabed58cd604995a81b4a8dc" @@ -1689,6 +2594,19 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/util-defaults-mode-node@^4.0.29": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.1.1.tgz#bca834c5ee16949bf8d0db9ac7bf988ad0d3ce10" + integrity sha512-RGSpmoBrA+5D2WjwtK7tto6Pc2wO9KSXKLpLONhFZ8VyuCbqlLdiDAfuDTNY9AJe4JoE+Cx806cpTQQoQ71zPQ== + dependencies: + "@smithy/config-resolver" "^4.2.1" + "@smithy/credential-provider-imds" "^4.1.1" + "@smithy/node-config-provider" "^4.2.1" + "@smithy/property-provider" "^4.1.1" + "@smithy/smithy-client" "^4.6.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/util-endpoints@^3.0.7": version "3.0.7" resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-3.0.7.tgz#9d52f2e7e7a1ea4814ae284270a5f1d3930b3773" @@ -1698,13 +2616,6 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" -"@smithy/util-hex-encoding@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.2.0.tgz#87edb7c88c2f422cfca4bb21f1394ae9602c5085" - integrity sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ== - dependencies: - tslib "^2.6.2" - "@smithy/util-hex-encoding@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" @@ -1719,12 +2630,11 @@ dependencies: tslib "^2.6.2" -"@smithy/util-middleware@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.2.0.tgz#80cfad40f6cca9ffe42a5899b5cb6abd53a50006" - integrity sha512-L1qpleXf9QD6LwLCJ5jddGkgWyuSvWBkJwWAZ6kFkdifdso+sk3L3O1HdmPvCdnCK3IS4qWyPxev01QMnfHSBw== +"@smithy/util-hex-encoding@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-4.1.0.tgz#9b27cf0c25d0de2c8ebfe75cc20df84e5014ccc9" + integrity sha512-1LcueNN5GYC4tr8mo14yVYbh/Ur8jHhWOxniZXii+1+ePiIbsLZ5fEI0QQGtbRRP5mOhmooos+rLmVASGGoq5w== dependencies: - "@smithy/types" "^2.12.0" tslib "^2.6.2" "@smithy/util-middleware@^3.0.11": @@ -1743,6 +2653,14 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/util-middleware@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-4.1.1.tgz#e19749a127499c9bdada713a8afd807d92d846e2" + integrity sha512-CGmZ72mL29VMfESz7S6dekqzCh8ZISj3B+w0g1hZFXaOjGTVaSqfAEFAq8EGp8fUL+Q2l8aqNmt8U1tglTikeg== + dependencies: + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/util-retry@^4.0.7": version "4.0.7" resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-4.0.7.tgz#3169450193e917da170a87557fcbdfe0faa86779" @@ -1752,6 +2670,15 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" +"@smithy/util-retry@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-4.1.1.tgz#f4a99d9b0ffb9e4bb119ac5a24e54e54d891e22c" + integrity sha512-jGeybqEZ/LIordPLMh5bnmnoIgsqnp4IEimmUp5c5voZ8yx+5kAlN5+juyr7p+f7AtZTgvhmInQk4Q0UVbrZ0Q== + dependencies: + "@smithy/service-error-classification" "^4.1.1" + "@smithy/types" "^4.5.0" + tslib "^2.6.2" + "@smithy/util-stream@^4.2.4": version "4.2.4" resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.2.4.tgz#fa9f0e2fd5a8a5adbd013066b475ea8f9d4f900f" @@ -1765,12 +2692,19 @@ "@smithy/util-hex-encoding" "^4.0.0" "@smithy/util-utf8" "^4.0.0" tslib "^2.6.2" - -"@smithy/util-uri-escape@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.2.0.tgz#56f5764051a33b67bc93fdd2a869f971b0635406" - integrity sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA== - dependencies: + +"@smithy/util-stream@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.3.1.tgz#63cce0f09d99d75142c6dc8fe03e55ac0171de47" + integrity sha512-khKkW/Jqkgh6caxMWbMuox9+YfGlsk9OnHOYCGVEdYQb/XVzcORXHLYUubHmmda0pubEDncofUrPNniS9d+uAA== + dependencies: + "@smithy/fetch-http-handler" "^5.2.1" + "@smithy/node-http-handler" "^4.2.1" + "@smithy/types" "^4.5.0" + "@smithy/util-base64" "^4.1.0" + "@smithy/util-buffer-from" "^4.1.0" + "@smithy/util-hex-encoding" "^4.1.0" + "@smithy/util-utf8" "^4.1.0" tslib "^2.6.2" "@smithy/util-uri-escape@^3.0.0": @@ -1787,6 +2721,13 @@ dependencies: tslib "^2.6.2" +"@smithy/util-uri-escape@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-4.1.0.tgz#ed4a5c498f1da07122ca1e3df4ca3e2c67c6c18a" + integrity sha512-b0EFQkq35K5NHUYxU72JuoheM6+pytEVUGlTwiFxWFpmddA+Bpz3LgsPRIpBk8lnPE47yT7AF2Egc3jVnKLuPg== + dependencies: + tslib "^2.6.2" + "@smithy/util-utf8@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-1.1.0.tgz#b791ab1e3f694374edfe22811e39dd8424a1be69" @@ -1795,7 +2736,7 @@ "@smithy/util-buffer-from" "^1.1.0" tslib "^2.5.0" -"@smithy/util-utf8@^2.0.0", "@smithy/util-utf8@^2.3.0": +"@smithy/util-utf8@^2.0.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== @@ -1819,6 +2760,14 @@ "@smithy/util-buffer-from" "^4.0.0" tslib "^2.6.2" +"@smithy/util-utf8@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-4.1.0.tgz#912c33c1a06913f39daa53da79cb8f7ab740d97b" + integrity sha512-mEu1/UIXAdNYuBcyEPbjScKi/+MQVXNIuY/7Cm5XLIWe319kDrT5SizBE95jqtmEXoDbGoZxKLCMttdZdqTZKQ== + dependencies: + "@smithy/util-buffer-from" "^4.1.0" + tslib "^2.6.2" + "@smithy/util-waiter@^4.0.7": version "4.0.7" resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-4.0.7.tgz#c013cf6a5918c21f8b430b4a825dbac132163f4a" @@ -1828,7 +2777,7 @@ "@smithy/types" "^4.3.2" tslib "^2.6.2" -"@teppeis/multimaps@3.0.0": +"@teppeis/multimaps@3.0.0", "@teppeis/multimaps@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@teppeis/multimaps/-/multimaps-3.0.0.tgz#bb9c3f8d569f589e548586fa0bbf423010ddfdc5" integrity sha512-ID7fosbc50TbT0MK0EG12O+gAP3W3Aa/Pz4DaTtQtEvlc9Odaqi0de+xuZ7Li2GtK4HzEX7IuRWS/JmZLksR3Q== @@ -1853,11 +2802,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@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/estree@^1.0.6": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" @@ -1873,6 +2817,14 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/node-fetch@^2.6.9": + version "2.6.13" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.13.tgz#e0c9b7b5edbdb1b50ce32c127e85e880872d56ee" + integrity sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw== + dependencies: + "@types/node" "*" + form-data "^4.0.4" + "@types/node@*": version "24.3.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-24.3.0.tgz#89b09f45cb9a8ee69466f18ee5864e4c3eb84dec" @@ -1880,14 +2832,21 @@ dependencies: undici-types "~7.10.0" -"@types/node@^20.1.1": - version "20.19.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" - integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow== +"@types/node@^18.19.121": + version "18.19.124" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.124.tgz#6f49e4fab8274910691a900e8a14316cbf3c7a31" + integrity sha512-hY4YWZFLs3ku6D2Gqo3RchTd9VRCcrjqp/I0mmohYeUVA5Y8eCXKJEasHxLAJVZRJuQogfd1GiJ9lgogBgKeuQ== + dependencies: + undici-types "~5.26.4" + +"@types/node@^22.0.0": + version "22.18.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.18.1.tgz#cc85ee6999b2a2928739281d2f56ff410a140c52" + integrity sha512-rzSDyhn4cYznVG+PCzGe1lwuMYJrcBS1fc3JqSa2PvtABwWo+dZ1ij5OVok3tqfpEBCBoaR4d7upFJk73HRJDw== dependencies: undici-types "~6.21.0" -"@types/normalize-package-data@^2.4.0": +"@types/normalize-package-data@^2.4.3": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== @@ -1904,51 +2863,33 @@ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== -"@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/retry@*": version "0.12.5" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.5.tgz#f090ff4bd8d2e5b940ff270ab39fd5ca1834a07e" integrity sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw== -"@types/semver@^7.5.8": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.0.tgz#64c441bdae033b378b6eef7d0c3d77c329b9378e" - integrity sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA== +"@types/semver@^7.7.1": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.1.tgz#3ce3af1a5524ef327d2da9e4fd8b6d95c8d70528" + integrity sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA== -"@types/tar@^6.1.13": - version "6.1.13" - resolved "https://registry.yarnpkg.com/@types/tar/-/tar-6.1.13.tgz#9b5801c02175344101b4b91086ab2bbc8e93a9b6" - integrity sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw== +"@types/stream-buffers@^3.0.3": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/stream-buffers/-/stream-buffers-3.0.7.tgz#0b719fa1bd2ca2cc0908205a440e5e569e1aa21e" + integrity sha512-azOCy05sXVXrO+qklf0c/B07H/oHaIuDDAiHPVwlk3A9Ek+ksHyTeMajLZl3r76FxpPpxem//4Te61G1iW3Giw== dependencies: "@types/node" "*" - minipass "^4.0.0" -"@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/uuid@10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d" + integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== -"@types/uuid@9.0.8", "@types/uuid@^9.0.1": +"@types/uuid@^9.0.1": version "9.0.8" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== -"@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" "*" - "@typescript-eslint/eslint-plugin@8.40.0": version "8.40.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz#19f959f273b32f5082c891903645e6a85328db4e" @@ -2098,7 +3039,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2155,18 +3096,6 @@ argparse@^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== - assert@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" @@ -2199,11 +3128,6 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -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-axios@^3.3.8: version "3.4.0" resolved "https://registry.yarnpkg.com/aws4-axios/-/aws4-axios-3.4.0.tgz#a0b4c029bcec57579fdda0649aa09075767466b0" @@ -2212,12 +3136,21 @@ aws4-axios@^3.3.8: "@aws-sdk/client-sts" "^3.4.1" aws4 "^1.12.0" -aws4@^1.12.0, aws4@^1.8.0: +aws4@^1.12.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== -axios@^1.7.4, axios@^1.8.4: +axios@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.0.tgz#11248459be05a5ee493485628fa0e4323d0abfc3" + integrity sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + +axios@^1.8.4: version "1.11.0" resolved "https://registry.yarnpkg.com/axios/-/axios-1.11.0.tgz#c2ec219e35e414c025b2095e8b8280278478fdb6" integrity sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA== @@ -2226,17 +3159,57 @@ axios@^1.7.4, axios@^1.8.4: form-data "^4.0.4" proxy-from-env "^1.1.0" +b4a@^1.6.4: + version "1.7.1" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.7.1.tgz#6fd4ec2fb33ba7a4ff341a2869bbfc88a6e57850" + integrity sha512-ZovbrBV0g6JxK5cGUF1Suby1vLfKjv4RWi8IxoaO/Mon8BDD9I21RxjHFtgQ+kskJqLAVyQZly3uMBui+vhc8Q== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -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== +bare-events@^2.2.0, bare-events@^2.5.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.6.1.tgz#f793b28bdc3dcf147d7cf01f882a6f0b12ccc4a2" + integrity sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g== + +bare-fs@^4.0.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.4.0.tgz#61cd6cbfdc7760731da5a14a87ba23f93b87be7f" + integrity sha512-DfdhZD+8fPM80vB28NMIlQIW4FBdkRMNLIa8o5HPSfGlxXek1C34qd98YItQzSl86Kt2IGom9+izFCrNuR7BXw== + dependencies: + bare-events "^2.5.4" + bare-path "^3.0.0" + bare-stream "^2.6.4" + bare-url "^2.2.2" + fast-fifo "^1.3.2" + +bare-os@^3.0.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.2.tgz#b3c4f5ad5e322c0fd0f3c29fc97d19009e2796e5" + integrity sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A== + +bare-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" + integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== + dependencies: + bare-os "^3.0.1" + +bare-stream@^2.6.4: + version "2.7.0" + resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.7.0.tgz#5b9e7dd0a354d06e82d6460c426728536c35d789" + integrity sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A== + dependencies: + streamx "^2.21.0" + +bare-url@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.2.2.tgz#1369d1972bbd7d9b358d0214d3f12abe2328d3e9" + integrity sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA== dependencies: - tweetnacl "^0.14.3" + bare-path "^3.0.0" bindings@^1.3.1: version "1.5.0" @@ -2277,11 +3250,6 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -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== - cacache@^18.0.0: version "18.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.4.tgz#4601d7578dadb59c66044e157d02a3314682d6a5" @@ -2331,6 +3299,11 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelize-ts@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelize-ts/-/camelize-ts-3.0.0.tgz#b9a7b4ff802464dc3d6475637a64a9742ad3db09" + integrity sha512-cgRwKKavoDKLTjO4FQTs3dRBePZp/2Y9Xpud0FhuCOTE86M2cniKN4CCXgRnsyXNMmQMifVHcv6SPaMtTx6ofQ== + capital-case@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" @@ -2340,11 +3313,6 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.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== - chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2373,16 +3341,7 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-table3@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" - -cli-table3@^0.6.0: +cli-table3@0.6.5, cli-table3@^0.6.0: version "0.6.5" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== @@ -2391,31 +3350,33 @@ cli-table3@^0.6.0: optionalDependencies: "@colors/colors" "1.5.0" -"cli-testing@github:scality/cli-testing.git#1.2.4": - version "1.2.4" - resolved "git+ssh://git@github.com/scality/cli-testing.git#687c3bdb5d684c5de4082a5dd9f9c00e94ec104c" +"cli-testing@github:scality/cli-testing.git#bc237af6354d5d6e64606d61ea464356f68bad98": + version "1.3.0" + resolved "git+ssh://git@github.com/scality/cli-testing.git#bc237af6354d5d6e64606d61ea464356f68bad98" dependencies: "@aws-crypto/sha256-universal" "^5.2.0" - "@aws-sdk/client-iam" "^3.637.0" - "@aws-sdk/client-s3" "^3.637.0" - "@aws-sdk/client-sts" "^3.637.0" - "@azure/storage-blob" "^12.24.0" - "@azure/storage-queue" "^12.23.0" - "@cucumber/cucumber" "^10.9.0" - "@cucumber/pretty-formatter" "^1.0.1" - "@kubernetes/client-node" "^0.21.0" - "@smithy/signature-v4" "^4.1.0" - "@types/semver" "^7.5.8" - "@types/tar" "^6.1.13" + "@aws-sdk/client-iam" "^3.879.0" + "@aws-sdk/client-s3" "^3.879.0" + "@aws-sdk/client-sts" "^3.879.0" + "@azure/storage-blob" "^12.28.0" + "@azure/storage-queue" "^12.27.0" + "@cucumber/cucumber" "^12.2.0" + "@cucumber/pretty-formatter" "^2.1.0" + "@keycloak/keycloak-admin-client" "^26.3.3" + "@kubernetes/client-node" "^1.3.0" + "@smithy/signature-v4" "^5.1.3" + "@types/proper-lockfile" "^4.1.4" + "@types/semver" "^7.7.1" junit-xml "^1.2.0" - node-rdkafka "^3.1.0" - semver "^7.6.3" + node-rdkafka "^3.5.0" + proper-lockfile "^4.1.2" + semver "^7.7.2" tar "^7.4.3" ts-node "^10.9.2" tsconfig-paths "^4.2.0" - typescript "^5.5.4" - vaultclient "git+https://github.com/scality/vaultclient#8.5.0" - werelogs scality/werelogs#8.2.0 + typescript "^5.9.2" + vaultclient "git+https://github.com/scality/vaultclient#8.5.3" + werelogs scality/werelogs#8.2.2 color-convert@^2.0.1: version "2.0.1" @@ -2429,7 +3390,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: +combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -2441,31 +3402,26 @@ commander@11.1.0, commander@^11.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== -commander@12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.0.0.tgz#b929db6df8546080adfd004ab215ed48cf6f2592" - integrity sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA== +commander@13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== commander@9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.1.0.tgz#a6b263b2327f2e188c6402c42623327909f2dbec" integrity sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w== -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.0.tgz#f244fc74a92343514e56229f16ef5c5e22ced5e9" + integrity sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -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== - create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -2480,13 +3436,6 @@ cross-spawn@^7.0.6: shebang-command "^2.0.0" which "^2.0.1" -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" - debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.4.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" @@ -2541,14 +3490,6 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -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" - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2566,6 +3507,13 @@ encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" +end-of-stream@^1.1.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + entities@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" @@ -2581,13 +3529,6 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - error-stack-parser@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" @@ -2741,26 +3682,16 @@ exponential-backoff@^3.1.1: resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.2.tgz#a8f26adb96bf78e8cd8ad1037928d5e5c0679d91" integrity sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA== -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, fast-deep-equal@^3.1.3: 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-fifo@^1.2.0, fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + fast-glob@^3.3.2: version "3.3.3" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" @@ -2827,13 +3758,10 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" +find-up-simple@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/find-up-simple/-/find-up-simple-1.0.1.tgz#18fb90ad49e45252c4d7fca56baade04fa3fca1e" + integrity sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ== find-up@^5.0.0: version "5.0.0" @@ -2868,7 +3796,7 @@ for-each@^0.3.5: dependencies: is-callable "^1.2.7" -foreground-child@^3.1.0: +foreground-child@^3.1.0, foreground-child@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== @@ -2876,24 +3804,7 @@ foreground-child@^3.1.0: cross-spawn "^7.0.6" signal-exit "^4.0.1" -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@^4.0.4: +form-data@^4.0.0, form-data@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== @@ -2904,15 +3815,6 @@ form-data@^4.0.4: hasown "^2.0.2" mime-types "^2.1.12" -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" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -2956,13 +3858,6 @@ get-proto@^1.0.0, get-proto@^1.0.1: 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" - glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -2989,6 +3884,18 @@ glob@^10.2.2, glob@^10.3.10: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^11.0.0: + version "11.0.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.3.tgz#9d8087e6d72ddb3c4707b1d2778f80ea3eaefcd6" + integrity sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA== + dependencies: + foreground-child "^3.3.1" + jackspeak "^4.1.1" + minimatch "^10.0.3" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^2.0.0" + global-dirs@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" @@ -3016,19 +3923,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -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-ansi@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-4.0.1.tgz#f216a8c8d7b129e490dc15f4a62cc1cdb9603ce8" @@ -3067,10 +3961,17 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +hosted-git-info@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17" + integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w== + dependencies: + lru-cache "^10.0.1" + +hpagent@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-1.2.0.tgz#0ae417895430eb3770c03443456b8d90ca464903" + integrity sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA== http-cache-semantics@^4.1.1: version "4.2.0" @@ -3085,15 +3986,6 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" -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" - "httpagent@git+https://github.com/scality/httpagent#1.1.0": version "1.1.0" resolved "git+https://github.com/scality/httpagent#8f9958eb9cde086db7819a86582fba640a5f8876" @@ -3150,6 +4042,11 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== +index-to-position@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/index-to-position/-/index-to-position-1.1.0.tgz#2e50bd54c8040bdd6d9b3d95ec2a8fedf86b4d44" + integrity sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg== + inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" @@ -3173,23 +4070,11 @@ is-arguments@^1.0.4: call-bound "^1.0.2" has-tostringtag "^1.0.2" -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.16.0: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" - integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== - dependencies: - hasown "^2.0.2" - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -3270,11 +4155,6 @@ is-typed-array@^1.1.3: dependencies: which-typed-array "^1.1.16" -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== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -3290,11 +4170,6 @@ isomorphic-ws@^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== - jackspeak@^3.1.2: version "3.4.3" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" @@ -3304,10 +4179,17 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -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== +jackspeak@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.1.tgz#96876030f450502047fc7e8c7fcf8ce8124e43ae" + integrity sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + +jose@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.0.tgz#96285365689d16f2845a353964d2284bf19f464c" + integrity sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA== js-tokens@^4.0.0: version "4.0.0" @@ -3321,60 +4203,39 @@ js-yaml@^4.1.0: 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== +jsep@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" + integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - 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-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -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== - json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -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== +jsonpath-plus@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz#59e22e4fa2298c68dfcd70659bb47f0cad525238" + integrity sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA== dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" + "@jsep-plugin/assignment" "^1.3.0" + "@jsep-plugin/regex" "^1.0.4" + jsep "^1.4.0" junit-xml@^1.2.0: version "1.2.0" @@ -3410,11 +4271,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - linkify-it@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec" @@ -3422,13 +4278,6 @@ linkify-it@^4.0.1: dependencies: uc.micro "^1.0.1" -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -3446,6 +4295,11 @@ lodash.mergewith@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== + lower-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" @@ -3458,17 +4312,20 @@ lru-cache@^10.0.1, lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== -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" +lru-cache@^11.0.0: + version "11.2.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.1.tgz#d426ac471521729c6c1acda5f7a633eadaa28db2" + integrity sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ== + +luxon@3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.7.1.tgz#9bd09aa84a56afb00c57ea78a8ec5bd16eb24ec0" + integrity sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg== -luxon@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.2.1.tgz#14f1af209188ad61212578ea7e3d518d18cee45f" - integrity sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg== +luxon@^3.5.0: + version "3.7.2" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.7.2.tgz#d697e48f478553cca187a0f8436aff468e3ba0ba" + integrity sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew== make-error@^1.1.1: version "1.3.6" @@ -3545,7 +4402,7 @@ mime-db@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: +mime-types@^2.1.12: 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== @@ -3557,6 +4414,13 @@ mime@^3.0.0: resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== +minimatch@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.3.tgz#cf7a0314a16c4d9ab73a7730a0e8e3c3502d47aa" + integrity sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw== + dependencies: + "@isaacs/brace-expansion" "^5.0.0" + minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -3622,11 +4486,6 @@ minipass@^3.0.0: dependencies: yallist "^4.0.0" -minipass@^4.0.0: - version "4.2.8" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" - integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== - minipass@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" @@ -3657,12 +4516,7 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^2.1.5: - version "2.1.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" - integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== - -mkdirp@^3.0.1: +mkdirp@^3.0.0, mkdirp@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== @@ -3704,6 +4558,13 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp@^10.2.0: version "10.3.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.3.1.tgz#1dd1a1a1c6c5c59da1a76aea06a062786b2c8a1a" @@ -3720,7 +4581,7 @@ node-gyp@^10.2.0: tar "^6.2.1" which "^4.0.0" -node-rdkafka@^3.1.0: +node-rdkafka@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/node-rdkafka/-/node-rdkafka-3.5.0.tgz#ace9b750036ae8bdc2fc191b746edbb72a2f4232" integrity sha512-KaMJ4lEMJJWrVKKGW1WvWmXbiALJHvTLLBjjJsjWbF7vJyaNDuJW4aPmkbO1yJxS4uKwV40aWTyFEj8iC7vJ0Q== @@ -3735,31 +4596,25 @@ nopt@^7.0.0: dependencies: abbrev "^2.0.0" -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== +normalize-package-data@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.2.tgz#a7bc22167fe24025412bcff0a9651eb768b03506" + integrity sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g== dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" + hosted-git-info "^7.0.0" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" -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== +oauth4webapi@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-3.8.1.tgz#a6e205570c09e33aa656982c85e78841a57a6fec" + integrity sha512-olkZDELNycOWQf9LrsELFq8n05LwJgV8UkrS0cburk6FOwf8GvLam+YB+Uj5Qvryee+vwWOfQVeI5Vm0MVg7SA== object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -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== - object-inspect@^1.13.3: version "1.13.4" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" @@ -3790,20 +4645,20 @@ object.assign@^4.1.4: has-symbols "^1.1.0" object-keys "^1.1.1" -oidc-token-hash@^5.0.3: - version "5.1.1" - resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.1.1.tgz#d35e31ca26d3a26678f5e9bda100b095ab58011f" - integrity sha512-D7EmwxJV6DsEB6vOFLrBM2OzsVgQzgPWyHlV2OOAVj772n+WTXpudC9e9u5BVKQnYwaD30Ivhi9b+4UeBcGu9g== +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" -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== +openid-client@^6.1.3: + version "6.8.0" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-6.8.0.tgz#ae60540fc1aaf595ee9100004ebda722e1d80e60" + integrity sha512-oG1d1nAVhIIE+JSjLS+7E9wY1QOJpZltkzlJdbZ7kEn7Hp3hqur2TEeQ8gLOHoHkhbRAGZJKoOnEQcLOQJuIyg== dependencies: - jose "^4.15.9" - lru-cache "^6.0.0" - object-hash "^2.2.0" - oidc-token-hash "^5.0.3" + jose "^6.1.0" + oauth4webapi "^3.8.1" optionator@^0.9.3: version "0.9.4" @@ -3817,13 +4672,6 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -3831,13 +4679,6 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -3852,11 +4693,6 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - package-json-from-dist@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" @@ -3876,15 +4712,14 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== +parse-json@^8.0.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-8.3.0.tgz#88a195a2157025139a2317a4f2f9252b61304ed5" + integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" + "@babel/code-frame" "^7.26.2" + index-to-position "^1.1.0" + type-fest "^4.39.1" path-exists@^4.0.0: version "4.0.0" @@ -3896,11 +4731,6 @@ path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - path-scurry@^1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" @@ -3909,10 +4739,13 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -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== +path-scurry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" + integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== + dependencies: + lru-cache "^11.0.0" + minipass "^7.1.2" picocolors@^1.1.1: version "1.1.1" @@ -3978,14 +4811,15 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -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== +pump@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" + integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== dependencies: - punycode "^2.3.1" + end-of-stream "^1.1.0" + once "^1.3.1" -punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: +punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -3997,39 +4831,35 @@ qs@^6.13.0: dependencies: side-channel "^1.1.0" -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== +read-package-up@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/read-package-up/-/read-package-up-11.0.0.tgz#71fb879fdaac0e16891e6e666df22de24a48d5ba" + integrity sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ== dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" + find-up-simple "^1.0.0" + read-pkg "^9.0.0" + type-fest "^4.6.0" -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== +read-pkg@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-9.0.1.tgz#b1b81fb15104f5dbb121b6bbdee9bbc9739f569b" + integrity sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA== dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" + "@types/normalize-package-data" "^2.4.3" + normalize-package-data "^6.0.0" + parse-json "^8.0.0" + type-fest "^4.6.0" + unicorn-magic "^0.1.0" -reflect-metadata@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.1.tgz#8d5513c0f5ef2b4b9c3865287f3c0940c1f67f74" - integrity sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw== +reflect-metadata@0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" + integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== regexp-match-indices@1.0.2: version "1.0.2" @@ -4048,58 +4878,11 @@ repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== -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" - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg/-/resolve-pkg-2.0.0.tgz#ac06991418a7623edc119084edc98b0e6bf05a41" - integrity sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ== - dependencies: - resolve-from "^5.0.0" - -resolve@^1.10.0: - version "1.22.10" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" - integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== - dependencies: - is-core-module "^2.16.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -4122,11 +4905,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -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== - safe-json-stringify@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" @@ -4141,7 +4919,7 @@ safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" -"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -4151,32 +4929,20 @@ sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== -"scubaclient@git+https://github.com/scality/scubaclient#^1.1.2": - version "1.1.2" - resolved "git+https://github.com/scality/scubaclient#8a5738b474495aa00fc0fd9a5e9278054c5dc83c" +"scubaclient@git+https://github.com/scality/scubaclient#^1.1.3": + version "1.1.3" + resolved "git+https://github.com/scality/scubaclient#0263d4f38b66bf47ed76044b79785b87d9227b99" dependencies: "@aws-crypto/sha256-js" "^5.2.0" - "@smithy/signature-v4" "^2.1.1" - axios "^1.7.4" + "@smithy/signature-v4" "^5.2.1" + axios "^1.12.0" seed-random@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54" integrity sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ== -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3: - version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" - integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== - dependencies: - lru-cache "^6.0.0" - -semver@^7.3.5, semver@^7.6.0, semver@^7.6.3: +semver@7.7.2, semver@^7.3.5, semver@^7.6.0, semver@^7.7.2: version "7.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== @@ -4260,7 +5026,7 @@ smart-buffer@^4.2.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -socks-proxy-agent@^8.0.3: +socks-proxy-agent@^8.0.3, socks-proxy-agent@^8.0.4: version "8.0.5" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== @@ -4316,21 +5082,6 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== -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" - ssri@^10.0.0: version "10.0.6" resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.6.tgz#a8aade2de60ba2bce8688e3fa349bad05c7dc1e5" @@ -4348,6 +5099,16 @@ stream-buffers@^3.0.2: resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-3.0.3.tgz#9fc6ae267d9c4df1190a781e011634cac58af3cd" integrity sha512-pqMqwQCso0PBJt2PQmDO0cFj0lyqmiwOMiMSkVtRokl7e+ZTRYgDHKnuZNbqjiJXgsg4nuqtD/zxuo9KqTp0Yw== +streamx@^2.15.0, streamx@^2.21.0: + version "2.22.1" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.1.tgz#c97cbb0ce18da4f4db5a971dc9ab68ff5dc7f5a5" + integrity sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA== + dependencies: + fast-fifo "^1.3.2" + text-decoder "^1.1.0" + optionalDependencies: + bare-events "^2.2.0" + string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -4387,7 +5148,7 @@ string-width@^5.0.1, string-width@^5.1.2: dependencies: ansi-regex "^5.0.1" -strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4430,10 +5191,25 @@ supports-color@^8.1.1: dependencies: has-flag "^4.0.0" -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +tar-fs@^3.0.8: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.1.0.tgz#4675e2254d81410e609d91581a762608de999d25" + integrity sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w== + dependencies: + pump "^3.0.0" + tar-stream "^3.1.5" + optionalDependencies: + bare-fs "^4.0.1" + bare-path "^3.0.0" + +tar-stream@^3.1.5: + version "3.1.7" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== + dependencies: + b4a "^1.6.4" + fast-fifo "^1.2.0" + streamx "^2.15.0" tar@^6.1.11, tar@^6.2.1: version "6.2.1" @@ -4447,7 +5223,7 @@ tar@^6.1.11, tar@^6.2.1: mkdirp "^1.0.3" yallist "^4.0.0" -tar@^7.0.0, tar@^7.4.3: +tar@^7.4.3: version "7.4.3" resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw== @@ -4459,6 +5235,13 @@ tar@^7.0.0, tar@^7.4.3: mkdirp "^3.0.1" yallist "^5.0.0" +text-decoder@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" + integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== + dependencies: + b4a "^1.6.4" + thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" @@ -4478,11 +5261,6 @@ tiny-case@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q== -tmp@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" - integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -4495,13 +5273,10 @@ toposort@^2.0.2: resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg== -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" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-api-utils@^2.1.0: version "2.1.0" @@ -4541,23 +5316,11 @@ tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.0.3, tslib@^2.4.1, tslib@^2.5.0, tslib@^2.6.2, tslib@^2.8.1: +tslib@^2.0.3, tslib@^2.5.0, tslib@^2.6.2, tslib@^2.8.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== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -4565,22 +5328,12 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - type-fest@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== -type-fest@^4.8.3: +type-fest@^4.39.1, type-fest@^4.41.0, type-fest@^4.6.0: version "4.41.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== @@ -4595,7 +5348,7 @@ typescript-eslint@^8.4.0: "@typescript-eslint/typescript-estree" "8.40.0" "@typescript-eslint/utils" "8.40.0" -typescript@^5.5.4: +typescript@^5.9.2: version "5.9.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== @@ -4605,6 +5358,11 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + undici-types@~6.21.0: version "6.21.0" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" @@ -4615,6 +5373,11 @@ undici-types@~7.10.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== +unicorn-magic@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4" + integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== + unique-filename@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" @@ -4643,6 +5406,16 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-join@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-5.0.0.tgz#c2f1e5cbd95fa91082a93b58a1f42fecb4bdbcf1" + integrity sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA== + +url-template@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/url-template/-/url-template-3.1.1.tgz#c220d5f3f793d28b0de341002112879cc8a43905" + integrity sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA== + util-arity@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/util-arity/-/util-arity-1.1.0.tgz#59d01af1fdb3fede0ac4e632b0ab5f6ce97c9330" @@ -4659,22 +5432,32 @@ util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" -uuid@9.0.1, uuid@^9.0.1: +uuid@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" + integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== + +uuid@11.0.5: + version "11.0.5" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.0.5.tgz#07b46bdfa6310c92c3fb3953a8720f170427fc62" + integrity sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA== + +uuid@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" + integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== + +uuid@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== -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== - v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -validate-npm-package-license@^3.0.1: +validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== @@ -4682,9 +5465,9 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -"vaultclient@git+https://github.com/scality/vaultclient#8.5.0": - version "8.5.0" - resolved "git+https://github.com/scality/vaultclient#c20d56eaed2cef9579768389f7e2f2d4ec8b6f85" +"vaultclient@git+https://github.com/scality/vaultclient#8.5.3": + version "8.5.3" + resolved "git+https://github.com/scality/vaultclient#24e33cfe2a98cc4545ddc615371bfd8d2f2e98d1" dependencies: "@aws-crypto/sha256-universal" "^5.2.0" "@smithy/signature-v4" "^4.1.0" @@ -4693,14 +5476,10 @@ validate-npm-package-license@^3.0.1: werelogs scality/werelogs#8.2.0 xml2js "^0.6.2" -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" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== werelogs@scality/werelogs#8.2.0: version "8.2.0" @@ -4709,6 +5488,21 @@ werelogs@scality/werelogs#8.2.0: fast-safe-stringify "^2.1.1" safe-json-stringify "^1.2.0" +werelogs@scality/werelogs#8.2.2: + version "8.2.2" + resolved "https://codeload.github.com/scality/werelogs/tar.gz/e53bef5145697bf8af940dcbe59408988d64854f" + dependencies: + fast-safe-stringify "^2.1.1" + safe-json-stringify "^1.2.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-typed-array@^1.1.16, which-typed-array@^1.1.2: version "1.1.19" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" @@ -4759,7 +5553,12 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" -ws@^8.11.0: +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^8.18.2: version "8.18.3" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== @@ -4812,10 +5611,10 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yup@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/yup/-/yup-1.2.0.tgz#9e51af0c63bdfc9be0fdc6c10aa0710899d8aff6" - integrity sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ== +yup@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/yup/-/yup-1.7.0.tgz#5d2feeccc1725c39bfed6ec677cc0622527dafaf" + integrity sha512-VJce62dBd+JQvoc+fCVq+KZfPHr+hXaxCcVgotfwWvlR0Ja3ffYKaJBT8rptPOSKOGJDCUnW2C2JWpud7aRP6Q== dependencies: property-expr "^2.0.5" tiny-case "^1.0.3" diff --git a/tests/zenko_tests/configuration.py b/tests/zenko_tests/configuration.py deleted file mode 100644 index 6dd94dcfaa..0000000000 --- a/tests/zenko_tests/configuration.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python - -import logging -import os -import sys -import time - -import yaml -import jwt -from bravado.client import SwaggerClient -from bravado.requests_client import RequestsClient -from bravado_core.spec import Spec -from kubernetes import client, config -from kubernetes.config.config_exception import ConfigException -from jsonschema import validate - -from e2e_config import accounts, endpoints, locations, workflows, schema -import create_buckets - -logging.basicConfig(level=logging.INFO) -_log = logging.getLogger("end2end configuration") - - -def load_k8s_config(config_file): - """ - Loads K8S config. - - :param config_file: Name of the kube-config file. - """ - try: - config.load_incluster_config() - return - except: - _log.info("unable to load incluster config") - - try: - config.load_kube_config(config_file=config_file) - return - except: - _log.info("unable to load k8s config file") - - raise Exception("Failed to load k8s config") - - -def load_end2end_config(config_file): - """ - Loads end-to-end test setup file - - :param config_file: Name of the end-to-end config file. - """ - with open(config_file) as file: - return yaml.full_load(file) - - -def create_swagger_client(swagger_conf_url, api_url, token=""): - """ - Create swagger client - - :param swagger_conf_url: url to swagger.conf - :param api_url: - :param token: jwt string - """ - # to view available clients - # print(dir(client)) - - # to use a client - # ui_client = client.ui_facing - - # to list methods available - # print(dir(client.ui_facing)) - - # describe method - # print(client.ui_facing.createConfigurationOverlayUser.__doc__) - - # to view list of models for request/response - # for model in client.swagger_spec.definitions: - # print(model) - - # retrieve model for request/response - # client.get_model('user-v1') - - # print the properties of the model - # print(client.get_model('user-v1').__doc__) - - if api_url.startswith("http://"): - api_url = api_url.lstrip("http://") - elif api_url.startswith("https://"): - api_url = api_url.lstrip("https://") - - http_client = RequestsClient() - http_client.set_api_key(api_url, - token, - param_name="X-Authentication-Token", - param_in="header") - client = SwaggerClient.from_url(swagger_conf_url, http_client=http_client, config={ - 'validate_swagger_spec': False, - }) - - return client - - -def main(): - TOKEN = os.getenv("TOKEN") - UUID = os.getenv("UUID") - KUBECONFIG = os.getenv("KUBECONFIG") - CONFIG_FILE = os.getenv("CONFIG_FILE", "./e2e-config.yaml") - MANAGEMENT_ENDPOINT = os.getenv("MANAGEMENT_ENDPOINT", - "http://managementapi.zenko.local") - MANAGEMENT_ENDPOINT = MANAGEMENT_ENDPOINT.rstrip('/') - NAMESPACE = os.getenv("NAMESPACE", "default") - - try: - load_k8s_config(config_file=KUBECONFIG) - e2e_config = load_end2end_config(config_file=CONFIG_FILE) - - validate(e2e_config, yaml.full_load(schema.e2e_config_schema)) - - client = create_swagger_client(MANAGEMENT_ENDPOINT + "/swagger.json", - MANAGEMENT_ENDPOINT, - token=TOKEN) - - # create buckets - create_buckets.create_aws_buckets() - create_buckets.create_ring_buckets() - create_buckets.create_azure_containers() - create_buckets.create_azure_queues() - - # create zenko resources - for account in e2e_config["accounts"]: - accounts.create_account(client, - TOKEN, - UUID, - account, - namespace=NAMESPACE) - - for endpoint in e2e_config["endpoints"]: - endpoints.create_endpoint(client, UUID, endpoint["hostname"], - endpoint["locationName"]) - - for location in e2e_config["locations"]: - locations.create_location(client, UUID, location) - - for wf in e2e_config["workflows"]["replication"]: - workflows.create_replication_workflow(client, UUID, wf) - - for wf in e2e_config["workflows"]["lifecycle"]: - workflows.create_lifecycle_workflow(client, UUID, wf) - - for wf in e2e_config["workflows"]["ingestion"]: - workflows.create_ingestion_workflow(client, UUID, wf) - - except Exception as e: - _log.error("Unable to run set up: %s", e) - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/tests/zenko_tests/create_buckets.py b/tests/zenko_tests/create_buckets.py deleted file mode 100644 index 5c12b27022..0000000000 --- a/tests/zenko_tests/create_buckets.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python -from boto3 import Session -from azure.storage.blob import BlobServiceClient -from azure.core.credentials import AzureNamedKeyCredential -from azure.core.exceptions import ResourceExistsError -from azure.storage.queue import QueueServiceClient -import os -import logging - -logging.basicConfig(level=logging.INFO) -_log = logging.getLogger('create_buckets') - -VERIFY_CERTIFICATES = os.environ.get('VERIFY_CERTIFICATES', 'false').lower() == 'true' - -def get_env(key, default=None, error=False): - if not error: - return os.environ.get(key, default) - return os.environ[key] - -def bucket_safe_create(bucket): - try: - _log.info('Creating bucket %s' % bucket.name) - bucket.create() - except bucket.meta.client.exceptions.BucketAlreadyOwnedByYou: - _log.info('Bucket %s already exists!' % bucket.name) - except Exception as exp: # pylint: disable=broad-except - _log.info('Error creating bucket %s - %s' % (bucket.name, str(exp))) - raise exp - -def put_file(bucket, object_name, body): - """ - Put an object in a bucket - """ - try: - _log.info('Putting object %s' % object_name) - obj = bucket.Object(object_name) - obj.put(Body=body) - except Exception as exp: - _log.info('Error putting object %s - %s' % (bucket.name, object_name, str(exp))) - raise exp - -def put_singlepart_mpu(bucket, object_name, body): - """ - Put an object in a bucket using a single part multipart upload - """ - try: - _log.info('Putting object %s using multipart upload' % object_name) - mpu = bucket.meta.client.create_multipart_upload( - Bucket=bucket.name, - Key=object_name - ) - response = bucket.meta.client.upload_part( - Body=body, - Bucket=bucket.name, - Key=object_name, - PartNumber=1, - UploadId=mpu['UploadId'] - ) - bucket.meta.client.complete_multipart_upload( - Bucket=bucket.name, - Key=object_name, - UploadId=mpu['UploadId'], - MultipartUpload={ - 'Parts': [{ - 'PartNumber': 1, - 'ETag': response['ETag'] - }] - } - ) - except Exception as exp: - _log.error('Error in multipart upload for object %s - %s' % (object_name, str(exp))) - raise exp - -def create_ring_buckets(): - RING_S3C_ACCESS_KEY = get_env('RING_S3C_ACCESS_KEY') - RING_S3C_SECRET_KEY = get_env('RING_S3C_SECRET_KEY') - RING_S3C_ENDPOINT = get_env('RING_S3C_ENDPOINT') - ENABLE_RING_TESTS = get_env('ENABLE_RING_TESTS') - ## test bucket names - RING_S3C_INGESTION_SRC_BUCKET_NAME = get_env('RING_S3C_INGESTION_SRC_BUCKET_NAME') - RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME = get_env('RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME') - RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE = get_env('RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE') - - # Disable if Ring is not enabled - if ENABLE_RING_TESTS == "false": - return - - s3c = Session(aws_access_key_id=RING_S3C_ACCESS_KEY, - aws_secret_access_key=RING_S3C_SECRET_KEY) - ring_s3c_client = s3c.resource('s3', endpoint_url=RING_S3C_ENDPOINT, - verify=VERIFY_CERTIFICATES) - - versioned_bucket = ring_s3c_client.Bucket(RING_S3C_INGESTION_SRC_BUCKET_NAME) - non_versioned_bucket = ring_s3c_client.Bucket(RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME) - - ## Creating S3C buckets - _log.info('Creating S3C buckets...') - bucket_safe_create(versioned_bucket) - bucket_safe_create(non_versioned_bucket) - - ## Adding non versioned objects before test execution to avoid - ## having to create the location mid tests which might cause flakiness. - ## A RING location can only be created if the bucket is versioned, and - ## once versioning is enabled it cannot be disabled. - _log.info('Putting non versioned objects...') - for i in range(int(RING_S3C_INGESTION_NON_VERSIONED_OBJECT_COUNT_PER_TYPE)): - put_file(non_versioned_bucket, 'simple-%d' % i, b'data') - put_file(non_versioned_bucket, 'zerobyte-%d' % i, b'') - put_singlepart_mpu(non_versioned_bucket, 'mpu-singlepart-%d' % i, b'mpudata') - - ## Enabling versioning - _log.info('Enabling versioning on buckets...') - versioned_bucket.Versioning().enable() - non_versioned_bucket.Versioning().enable() - -def create_aws_buckets(): - AWS_ACCESS_KEY = get_env('AWS_ACCESS_KEY') - AWS_SECRET_KEY = get_env('AWS_SECRET_KEY') - AWS_ENDPOINT = get_env('AWS_ENDPOINT') - AWS_FAIL_BUCKET_NAME = get_env('AWS_FAIL_BUCKET_NAME') - AWS_REPLICATION_FAIL_CTST_BUCKET_NAME = get_env('AWS_REPLICATION_FAIL_CTST_BUCKET_NAME') - - s3c = Session(aws_access_key_id=AWS_ACCESS_KEY, - aws_secret_access_key=AWS_SECRET_KEY) - aws_s3c_client = s3c.resource('s3', endpoint_url=AWS_ENDPOINT, - verify=VERIFY_CERTIFICATES) - - ## Creating AWS buckets - _log.info('Creating AWS buckets...') - bucket_safe_create(aws_s3c_client.Bucket(AWS_FAIL_BUCKET_NAME)) - bucket_safe_create(aws_s3c_client.Bucket(AWS_REPLICATION_FAIL_CTST_BUCKET_NAME)) - aws_s3c_client.Bucket(AWS_FAIL_BUCKET_NAME).Versioning().enable() - aws_s3c_client.Bucket(AWS_REPLICATION_FAIL_CTST_BUCKET_NAME).Versioning().enable() - -def create_azure_containers(): - AZURE_BACKEND_ENDPOINT = get_env("AZURE_BACKEND_ENDPOINT") - AZURE_ACCOUNT_NAME = get_env("AZURE_ACCOUNT_NAME") - AZURE_SECRET_KEY = get_env("AZURE_SECRET_KEY") - AZURE_CRR_BUCKET_NAME = get_env("AZURE_CRR_BUCKET_NAME") - AZURE_ARCHIVE_BUCKET_NAME = get_env("AZURE_ARCHIVE_BUCKET_NAME") - AZURE_ARCHIVE_BUCKET_NAME_2 = get_env("AZURE_ARCHIVE_BUCKET_NAME_2") - - credential = AzureNamedKeyCredential(name=AZURE_ACCOUNT_NAME, - key=AZURE_SECRET_KEY) - blob_service_client = BlobServiceClient(account_url=AZURE_BACKEND_ENDPOINT, - credential=credential, - connection_verify=VERIFY_CERTIFICATES) - ## Creating Azure buckets - _log.info('Creating Azure buckets...') - for bucket_name in [AZURE_CRR_BUCKET_NAME, AZURE_ARCHIVE_BUCKET_NAME, AZURE_ARCHIVE_BUCKET_NAME_2]: - try: - _log.info('Creating bucket %s' % bucket_name) - blob_service_client.create_container(name=bucket_name) - except ResourceExistsError: - _log.info('Container %s already exists!' % bucket_name) - -def create_azure_queues(): - AZURE_BACKEND_QUEUE_ENDPOINT = get_env("AZURE_BACKEND_QUEUE_ENDPOINT") - AZURE_ACCOUNT_NAME = get_env("AZURE_ACCOUNT_NAME") - AZURE_SECRET_KEY = get_env("AZURE_SECRET_KEY") - AZURE_ARCHIVE_QUEUE_NAME = get_env("AZURE_ARCHIVE_QUEUE_NAME") - - credential = AzureNamedKeyCredential(name=AZURE_ACCOUNT_NAME, - key=AZURE_SECRET_KEY) - - queue_client = QueueServiceClient(account_url=AZURE_BACKEND_QUEUE_ENDPOINT, - credential=credential, - connection_verify=VERIFY_CERTIFICATES) - - ## Creating Azure queue - _log.info('Creating Azure queues...') - try: - _log.info('Creating queue %s' % AZURE_ARCHIVE_QUEUE_NAME) - queue_client.create_queue(name=AZURE_ARCHIVE_QUEUE_NAME) - except ResourceExistsError: - _log.info('Queue %s already exists!' % AZURE_ARCHIVE_QUEUE_NAME) diff --git a/tests/zenko_tests/e2e-config.yaml.template b/tests/zenko_tests/e2e-config.yaml.template deleted file mode 100644 index ded5c90396..0000000000 --- a/tests/zenko_tests/e2e-config.yaml.template +++ /dev/null @@ -1,119 +0,0 @@ -accounts: - - "zenko" -endpoints: [] -locations: - - name: "${AWS_BACKEND_DESTINATION_LOCATION}" - locationType: "location-aws-s3-v1" - legacyAwsBehavior: yes - details: - bucketName: "${AWS_CRR_BUCKET_NAME}" - endpoint: "${AWS_ENDPOINT}" - accessKey: "${AWS_ACCESS_KEY}" - secretKey: "${AWS_SECRET_KEY}" - bucketMatch: no - repoId: [] - - name: "${AWS_BACKEND_DESTINATION_FAIL_LOCATION}" - locationType: "location-aws-s3-v1" - details: - bucketName: "${AWS_FAIL_BUCKET_NAME}" - endpoint: "${AWS_ENDPOINT}" - accessKey: "${AWS_ACCESS_KEY}" - secretKey: "${AWS_SECRET_KEY}" - bucketMatch: yes - repoId: [] - - name: "${AWS_BACKEND_SOURCE_LOCATION}" - locationType: "location-aws-s3-v1" - details: - bucketName: "${AWS_BUCKET_NAME}" - endpoint: "${AWS_ENDPOINT}" - accessKey: "${AWS_ACCESS_KEY}" - secretKey: "${AWS_SECRET_KEY}" - bucketMatch: yes - repoId: [] - - name: "${AWS_BACKEND_DESTINATION_REPLICATION_FAIL_CTST_LOCATION}" - # This location is used for a specific test that temporarily removes its bucket - # Consider using other locations first - locationType: "location-aws-s3-v1" - details: - bucketName: "${AWS_REPLICATION_FAIL_CTST_BUCKET_NAME}" - endpoint: "${AWS_ENDPOINT}" - accessKey: "${AWS_ACCESS_KEY}" - secretKey: "${AWS_SECRET_KEY}" - bucketMatch: no - repoId: [] - - name: ${AZURE_BACKEND_DESTINATION_LOCATION} - locationType: location-azure-v1 - details: - bucketName: ${AZURE_CRR_BUCKET_NAME} - endpoint: ${AZURE_BACKEND_ENDPOINT} - accessKey: ${AZURE_ACCOUNT_NAME} - secretKey: ${AZURE_SECRET_KEY} - bucketMatch: no - repoId: [] - - name: "${RING_S3C_BACKEND_SOURCE_LOCATION}" - locationType: "location-scality-ring-s3-v1" - details: - bucketName: "${RING_S3C_INGESTION_SRC_BUCKET_NAME}" - endpoint: "${RING_S3C_ENDPOINT}" - accessKey: "${RING_S3C_ACCESS_KEY}" - secretKey: "${RING_S3C_SECRET_KEY}" - bucketMatch: yes - repoId: [] - - name: "${RING_S3C_BACKEND_SOURCE_NON_VERSIONED_LOCATION}" - locationType: "location-scality-ring-s3-v1" - details: - bucketName: "${RING_S3C_INGESTION_SRC_NON_VERSIONED_BUCKET_NAME}" - endpoint: "${RING_S3C_ENDPOINT}" - accessKey: "${RING_S3C_ACCESS_KEY}" - secretKey: "${RING_S3C_SECRET_KEY}" - bucketMatch: yes - repoId: [] - - name: "${GCP_BACKEND_DESTINATION_LOCATION}" - locationType: "location-gcp-v1" - details: - bucketName: "${GCP_CRR_BUCKET_NAME}" - mpuBucketName: "${GCP_CRR_MPU_BUCKET_NAME}" - accessKey: "${GCP_ACCESS_KEY}" - secretKey: "${GCP_SECRET_KEY}" - bucketMatch: no - repoId: [] - - name: "${COLD_BACKEND_DESTINATION_LOCATION}" - locationType: "location-dmf-v1" - isCold: true - details: - endpoint: "ws://mock-sorbet:5001/session" - username: "user1" - password: "pass1" - repoId: - - 233aead6-1d7b-4647-a7cf-0d3280b5d1d7 - - 81e78de8-df11-4acd-8ad1-577ff05a68db - nsId: 65f9fd61-42fe-4a68-9ac0-6ba25311cc85 - - name: "${AZURE_ARCHIVE_BACKEND_DESTINATION_LOCATION}" - locationType: "location-azure-archive-v1" - isCold: true - details: - endpoint: "${AZURE_BACKEND_ENDPOINT}" - bucketName: "${AZURE_ARCHIVE_BUCKET_NAME}" - queue: - type: "location-azure-storage-queue-v1" - queueName: "${AZURE_ARCHIVE_QUEUE_NAME}" - endpoint: "${AZURE_BACKEND_QUEUE_ENDPOINT}" - auth: - type: "location-azure-shared-key" - accountName: "${AZURE_ACCOUNT_NAME}" - accountKey: "${AZURE_SECRET_KEY}" - repoId: - - 233aead6-1d7b-4647-a7cf-0d3280b5d1d7 - - name: "${MIRIA_BACKEND_DESTINATION_LOCATION}" - locationType: "location-miria-v1" - isCold: true - details: - endpoint: "ws://mock-miria:5001/session" - username: "user1" - password: "pass1" - repoId: - - 65f9fd61-42fe-4a68-9ac0-6ba25311cc85 -workflows: - replication: [] - lifecycle: [] - ingestion: [] diff --git a/tests/zenko_tests/e2e_config/accounts.py b/tests/zenko_tests/e2e_config/accounts.py deleted file mode 100644 index b484a16b0b..0000000000 --- a/tests/zenko_tests/e2e_config/accounts.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -import logging - -from kubernetes import client, config -from kubernetes.client.rest import ApiException - -from e2e_config import clients - -_log = logging.getLogger("end2end configuration") - -def get_credentials(token, account_id): - """ - Retrieve credentials from sts service - - :param token: oidc id token - :param account_id: account id - """ - _log.info("getting account credentials") - - # TODO: either use account credentials by generating it using pensieve-api - # or create a role and then use assume role to generate credential/token - # do not use hard coded role, this will be removed in the future versions! - res = clients.stsclient.assume_role_with_web_identity( - RoleArn="arn:aws:iam::%s:role/scality-internal/storage-manager-role" % (account_id), - RoleSessionName='end2end', - WebIdentityToken=token, - DurationSeconds=60 * 60 * 12, # 12 hrs - ) - - return res - - -def create_account_secret(name, credentials, namespace="default"): - """ - Create a k8s secret resource for account - - :param name: secret name - :param credentials: sts assume role credentials - :param namespace: k8s namespace - """ - _log.info("creating account secret") - - core = client.CoreV1Api() - secret = client.V1Secret( - api_version="v1", - metadata=client.V1ObjectMeta( - name=name, - labels={ - "type": "end2end", - }, - ), - string_data=credentials, - ) - - try: - res = core.create_namespaced_secret(namespace, body=secret) - except ApiException as e: - if e.status == 409: - _log.warning("secret already exists") - else: - raise e - - _log.info("created account secret") - - -def create_account(client, token, uuid, account_name, namespace="default"): - """ - Creates a user account and save its accessKey and secretKey as k8s secret - - :param client: swagger client - :param uuid: zenko instance uuid - :param account_name: account_name - :param namespace: k8s namespace - """ - try: - User_V1 = client.get_model('user-v1') - u = User_V1(userName=account_name, - email="%s@zenko.local" % (account_name)) - - res = ( - client.ui_facing - .createConfigurationOverlayUser(user=u, uuid=uuid) - .response() - .result - ) - - creds = get_credentials(token, res.id) - create_account_secret(name="end2end-account-%s" % (res.userName), - credentials=creds["Credentials"], - namespace=namespace) - - _log.info("created account") - except Exception as e: - raise Exception( - "Failed to create account '%s': %s" % (account_name, e)) diff --git a/tests/zenko_tests/e2e_config/clients.py b/tests/zenko_tests/e2e_config/clients.py deleted file mode 100644 index 17b6152e39..0000000000 --- a/tests/zenko_tests/e2e_config/clients.py +++ /dev/null @@ -1,10 +0,0 @@ -import os -import boto3 - -VAULT_ENDPOINT = os.getenv("VAULT_ENDPOINT") -session = boto3.session.Session() - -stsclient = session.client( - service_name='sts', - endpoint_url=VAULT_ENDPOINT, -) diff --git a/tests/zenko_tests/e2e_config/endpoints.py b/tests/zenko_tests/e2e_config/endpoints.py deleted file mode 100644 index 4775c0d107..0000000000 --- a/tests/zenko_tests/e2e_config/endpoints.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python - -import logging - -_log = logging.getLogger("end2end configuration") - -def create_endpoint(client, uuid, host, location): - """ - Creates an endpoint for a location - :param client: swagger client - :param uuid: zenko instance uuid - :param host: hostname - :param location: location name - """ - try: - Endpoint_V1 = client.get_model('endpoint-v1') - ep = Endpoint_V1(hostname=host, locationName=location) - - res = ( - client.ui_facing - .createConfigurationOverlayEndpoint(endpoint=ep, uuid=uuid) - .response() - .result - ) - - _log.info(res) - _log.info("endpoint created") - except Exception as e: - raise Exception( - "Failed to create endpoint for location '%s': %s" % (location, e)) diff --git a/tests/zenko_tests/e2e_config/locations.py b/tests/zenko_tests/e2e_config/locations.py deleted file mode 100644 index 578f4e5057..0000000000 --- a/tests/zenko_tests/e2e_config/locations.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -import logging -import os - -_log = logging.getLogger("end2end configuration") - -def create_location(client, uuid, location): - """ - Creates a location - :param client: swagger client - :param uuid: zenko instance uuid - :param location: location details - """ - - ENABLE_RING_TESTS = os.environ['ENABLE_RING_TESTS'] - if ENABLE_RING_TESTS == "false" and location["locationType"] == "location-scality-ring-s3-v1": - return - - try: - Location_V1 = client.get_model('location-v1') - if "bootstrapList" not in location["details"]: - location["details"]["bootstrapList"] = [] - loc = Location_V1(name=location["name"], - locationType=location["locationType"], - details=location["details"]) - - res = ( - client.ui_facing - .createConfigurationOverlayLocation(location=loc, uuid=uuid) - .response() - .result - ) - - _log.info("location created") - except Exception as e: - raise Exception( - "Failed to create location '%s': %s" % (location["name"], e)) diff --git a/tests/zenko_tests/e2e_config/schema.py b/tests/zenko_tests/e2e_config/schema.py deleted file mode 100644 index 4b518b9b2a..0000000000 --- a/tests/zenko_tests/e2e_config/schema.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python - -e2e_config_schema = """ -type: object -properties: - accounts: - type: array - items: - type: string - endpoints: - type: array - items: - type: object - properties: - hostname: - type: string - locationName: - type: string - locations: - type: array - items: - type: object - properties: - name: - type: string - locationType: - type: string - details: - type: object - properties: - bucketName: - type: string - endpoint: - type: string - accessKey: - type: string - secretKey: - type: string - workflows: - type: object - properties: - replication: - type: array - items: - type: object - lifecycle: - type: array - items: - type: object - ingestion: - type: array - items: - type: object -""" diff --git a/tests/zenko_tests/e2e_config/workflows.py b/tests/zenko_tests/e2e_config/workflows.py deleted file mode 100644 index 8dea787396..0000000000 --- a/tests/zenko_tests/e2e_config/workflows.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python - -import logging - -_log = logging.getLogger("end2end configuration") - -def create_replication_workflow(client, UUID, workflow): - pass - -def create_lifecycle_workflow(client, UUID, workflow): - pass - -def create_ingestion_workflow(client, UUID, workflow): - pass