From ea204ef62c6a9d9cfc232c88b70d94d018df631a Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Wed, 30 Oct 2024 15:31:27 +0100 Subject: [PATCH] chore(e2e): adjust the scripts to make it easier to run atlas cloud e2e tests locally (#6425) * chore(e2e): adjust the scripts to make it easier to run atlas cloud e2e tests locally * chore(ci): remove COMPASS_E2E_ATLAS_CLOUD_SANDBOX_CLOUD_CONFIG env var from test-sanbox-with-atlas function --- .evergreen/functions.yml | 1 - .evergreen/start-atlas-cloud-cluster.sh | 87 +++++++++++++++++-- .../helpers/test-runner-context.ts | 57 ++++-------- 3 files changed, 97 insertions(+), 48 deletions(-) diff --git a/.evergreen/functions.yml b/.evergreen/functions.yml index b4dc14846d3..3fc873e4cb9 100644 --- a/.evergreen/functions.yml +++ b/.evergreen/functions.yml @@ -683,7 +683,6 @@ functions: env: <<: *compass-env DEBUG: ${debug|} - COMPASS_E2E_ATLAS_CLOUD_SANDBOX_CLOUD_CONFIG: 'qa' COMPASS_E2E_ATLAS_CLOUD_SANDBOX_USERNAME: ${e2e_tests_compass_web_atlas_username} COMPASS_E2E_ATLAS_CLOUD_SANDBOX_PASSWORD: ${e2e_tests_compass_web_atlas_password} COMPASS_E2E_ATLAS_CLOUD_SANDBOX_DBUSER_USERNAME: ${e2e_tests_compass_web_atlas_db_username} diff --git a/.evergreen/start-atlas-cloud-cluster.sh b/.evergreen/start-atlas-cloud-cluster.sh index 63e87471639..0b1b48bd540 100644 --- a/.evergreen/start-atlas-cloud-cluster.sh +++ b/.evergreen/start-atlas-cloud-cluster.sh @@ -1,10 +1,61 @@ #!/bin/bash +# This script helps to automatically provision Atlas cluster for running the e2e +# tests against. In CI this will always create a new cluster and delete it when +# the test run is finished. You can also use this script locally to run e2e +# tests against a "logged in" Atlas Cloud experience in compass-web sandbox. +# +# While the provisioning of clusters is automated, you should be aware that it +# requires some extra environmental variables to be available when you are +# running it. If you want to be able to run these e2e tests locally, following +# steps are required: +# +# - Create a test Atlas user on one of the testing environments (-dev / -qa). +# You can only use your work emails with a subaddress to create those (e.g, +# jane.doe+for-testing@mongodb.com). +# +# - Setup a new org and project. Save the org id and project id for later. +# +# - Create new db user with username / password auth and admin role. This user +# will be used to prepopulate dbs with data in tests. Save the credentials. +# +# - Create a new API key (Access Manager > Project Access > Create Application > +# API Key) for the project you created and save the public and private keys. +# +# - (Optional) Deploy a cluster with a required configuration through Atlas +# Cloud UI. If you skip the step, the script will deploy a default cluster for +# you. +# +# - Make sure that you have the following environmental variables provided to +# the script below: +# +# MCLI_OPS_MANAGER_URL API base url matching the environment you used to +# create your user (https://cloud{-dev,-qa}.mongodb.com/) +# MCLI_PUBLIC_API_KEY Public API key +# MCLI_PRIVATE_API_KEY Private API key +# MCLI_ORG_ID Org ID +# MCLI_PROJECT_ID Project ID +# +# COMPASS_E2E_ATLAS_CLOUD_SANDBOX_USERNAME Cloud user you created +# COMPASS_E2E_ATLAS_CLOUD_SANDBOX_PASSWORD Cloud user password +# COMPASS_E2E_ATLAS_CLOUD_SANDBOX_DBUSER_USERNAME Db user for the project +# COMPASS_E2E_ATLAS_CLOUD_SANDBOX_DBUSER_PASSWORD Db user password +# +# - Source the script followed by running the tests to make sure that some +# variables exported from this script are available for the test env: +# +# (ATLAS_CLOUD_TEST_CLUSTER_NAME="TestCluster" source .evergreen/start-atlas-cloud-cluster.sh \ +# && npm run -w compass-e2e-tests test web -- --test-atlas-cloud-sandbox --test-filter="atlas-cloud/**/*") + +_ATLAS_CLOUD_TEST_CLUSTER_NAME=${ATLAS_CLOUD_TEST_CLUSTER_NAME:-""} + # Atlas limits the naming to something like /^[\w\d-]{,23}$/ (and will auto # truncate if it's too long) so we're very limited in terms of how unique this # name can be. Hopefully the epoch + part of git hash is enough for these to not # overlap when tests are running -ATLAS_CLOUD_TEST_CLUSTER_NAME="e2e-$(date +"%s")-$(git rev-parse HEAD)" +DEFAULT_ATLAS_CLOUD_TEST_CLUSTER_NAME="e2e-$(date +"%s")-$(git rev-parse HEAD)" + +ATLAS_CLUSTER_NAME="${_ATLAS_CLOUD_TEST_CLUSTER_NAME:-$DEFAULT_ATLAS_CLOUD_TEST_CLUSTER_NAME}" function atlascli() { docker run \ @@ -17,23 +68,43 @@ function atlascli() { } cleanup() { - echo "Scheduling Atlas deployment \`$ATLAS_CLOUD_TEST_CLUSTER_NAME\` for deletion..." - atlascli clusters delete $ATLAS_CLOUD_TEST_CLUSTER_NAME --force + # Assuming that we want to preserve the cluster if the name was provided + # outside of script. Helpful when trying to run the tests locally, you can + # automatically create a cluster with a custom name for the first time, but + # then re-use it when running the tests again. Don't forget to clean it up + # after you're done! + if [ -z "$_ATLAS_CLOUD_TEST_CLUSTER_NAME" ]; then + echo "Scheduling Atlas deployment \`$ATLAS_CLUSTER_NAME\` for deletion..." + atlascli clusters delete $ATLAS_CLUSTER_NAME --force + else + echo "Custom cluster name provided ($_ATLAS_CLOUD_TEST_CLUSTER_NAME), skipping cluster cleanup" + fi } trap cleanup EXIT -echo "Creating Atlas deployment \`$ATLAS_CLOUD_TEST_CLUSTER_NAME\` to test against..." -atlascli clusters create $ATLAS_CLOUD_TEST_CLUSTER_NAME \ +echo "Creating Atlas deployment \`$ATLAS_CLUSTER_NAME\` to test against..." +atlascli clusters create $ATLAS_CLUSTER_NAME \ --provider AWS \ --region US_EAST_1 \ --tier M10 echo "Waiting for the deployment to be provisioned..." -atlascli clusters watch "$ATLAS_CLOUD_TEST_CLUSTER_NAME" +atlascli clusters watch $ATLAS_CLUSTER_NAME echo "Getting connection string for provisioned cluster..." -ATLAS_CLOUD_TEST_CLUSTER_CONNECTION_STRING_JSON="$(atlascli clusters connectionStrings describe $ATLAS_CLOUD_TEST_CLUSTER_NAME -o json)" +CONNECTION_STRINGS_JSON="$(atlascli clusters connectionStrings describe $ATLAS_CLUSTER_NAME -o json)" + +export COMPASS_E2E_ATLAS_CLOUD_SANDBOX_CLOUD_CONFIG=$( + if [[ "$MCLI_OPS_MANAGER_URL" =~ "-dev" ]]; then + echo "dev" + elif [[ "$MCLI_OPS_MANAGER_URL" =~ "-qa" ]]; then + echo "qa" + else + echo "prod" + fi +) +echo "Cloud config: $COMPASS_E2E_ATLAS_CLOUD_SANDBOX_CLOUD_CONFIG" -export COMPASS_E2E_ATLAS_CLOUD_SANDBOX_DEFAULT_CONNECTIONS="{\"$ATLAS_CLOUD_TEST_CLUSTER_NAME\": $ATLAS_CLOUD_TEST_CLUSTER_CONNECTION_STRING_JSON}" +export COMPASS_E2E_ATLAS_CLOUD_SANDBOX_DEFAULT_CONNECTIONS="{\"$ATLAS_CLUSTER_NAME\": $CONNECTION_STRINGS_JSON}" echo "Cluster connections: $COMPASS_E2E_ATLAS_CLOUD_SANDBOX_DEFAULT_CONNECTIONS" diff --git a/packages/compass-e2e-tests/helpers/test-runner-context.ts b/packages/compass-e2e-tests/helpers/test-runner-context.ts index 4ad3fe13892..e9ed908a4e4 100644 --- a/packages/compass-e2e-tests/helpers/test-runner-context.ts +++ b/packages/compass-e2e-tests/helpers/test-runner-context.ts @@ -4,7 +4,7 @@ import { } from '@mongodb-js/connection-info'; import type { MongoClusterOptions } from 'mongodb-runner'; import yargs from 'yargs'; -import type { Argv } from 'yargs'; +import type { Argv, CamelCase } from 'yargs'; import { hideBin } from 'yargs/helpers'; import Debug from 'debug'; import fs from 'fs'; @@ -106,15 +106,17 @@ function buildDesktopArgs(yargs: Argv) { * make sure that the tests in mms are also updated to account for that */ const atlasCloudExternalArgs = [ - 'test-atlas-cloud-external', 'atlas-cloud-external-url', 'atlas-cloud-external-project-id', 'atlas-cloud-external-cookies-file', 'atlas-cloud-external-default-connections-file', ] as const; +type AtlasCloudExternalArgs = + | typeof atlasCloudExternalArgs[number] + | CamelCase; + const atlasCloudSandboxArgs = [ - 'test-atlas-cloud-sandbox', 'atlas-cloud-sandbox-cloud-config', 'atlas-cloud-sandbox-username', 'atlas-cloud-sandbox-password', @@ -123,6 +125,10 @@ const atlasCloudSandboxArgs = [ 'atlas-cloud-sandbox-default-connections', ] as const; +type AtlasCloudSandboxArgs = + | typeof atlasCloudSandboxArgs[number] + | CamelCase; + let testEnv: 'desktop' | 'web' | undefined; function buildWebArgs(yargs: Argv) { @@ -191,13 +197,9 @@ function buildWebArgs(yargs: Argv) { description: 'Stringified JSON with connections that are expected to be available in the Atlas project', }) - .implies( - Object.fromEntries( - atlasCloudSandboxArgs.map((arg) => { - return [arg, atlasCloudSandboxArgs]; - }) - ) - ) + .implies({ + 'test-atlas-cloud-sandbox': atlasCloudSandboxArgs, + }) .option('test-atlas-cloud-external', { type: 'boolean', description: @@ -221,13 +223,9 @@ function buildWebArgs(yargs: Argv) { description: 'File with JSON array of connections (following ConnectionInfo schema) that are expected to be available in the Atlas project', }) - .implies( - Object.fromEntries( - atlasCloudExternalArgs.map((arg) => { - return [arg, atlasCloudExternalArgs]; - }) - ) - ) + .implies({ + 'test-atlas-cloud-external': atlasCloudExternalArgs, + }) .conflicts({ 'test-atlas-cloud-external': 'test-atlas-cloud-sandbox', 'test-atlas-cloud-sandbox': 'test-atlas-cloud-external', @@ -310,14 +308,7 @@ export function assertTestingWeb(ctx = context): asserts ctx is WebParsedArgs { export function isTestingAtlasCloudExternal( ctx = context ): ctx is WebParsedArgs & { - [K in - | 'testAtlasCloudExternal' - | 'atlasCloudExternalUrl' - | 'atlasCloudExternalProjectId' - | 'atlasCloudExternalCookiesFile' - | 'atlasCloudExternalDefaultConnectionsFile']: NonNullable< - WebParsedArgs[K] - >; + [K in AtlasCloudExternalArgs]: NonNullable; } { return isTestingWeb(ctx) && !!ctx.testAtlasCloudExternal; } @@ -325,13 +316,7 @@ export function isTestingAtlasCloudExternal( export function isTestingAtlasCloudSandbox( ctx = context ): ctx is WebParsedArgs & { - [K in - | 'testAtlasCloudSandbox' - | 'atlasCloudSandboxUsername' - | 'atlasCloudSandboxPassword' - | 'atlasCloudSandboxDbuserUsername' - | 'atlasCloudSandboxDbuserPassword' - | 'atlasCloudSandboxDefaultConnections']: NonNullable; + [K in AtlasCloudSandboxArgs]: NonNullable; } { return isTestingWeb(ctx) && !!ctx.testAtlasCloudSandbox; } @@ -339,13 +324,7 @@ export function isTestingAtlasCloudSandbox( export function assertTestingAtlasCloudSandbox( ctx = context ): asserts ctx is WebParsedArgs & { - [K in - | 'testAtlasCloudSandbox' - | 'atlasCloudSandboxUsername' - | 'atlasCloudSandboxPassword' - | 'atlasCloudSandboxDbuserUsername' - | 'atlasCloudSandboxDbuserPassword' - | 'atlasCloudSandboxDefaultConnections']: NonNullable; + [K in AtlasCloudSandboxArgs]: NonNullable; } { if (!isTestingAtlasCloudSandbox(ctx)) { throw new Error(`Expected tested runtime to be web w/ Atlas Cloud account`);