From 89fb8d542b27c42993448716f73d64542df32636 Mon Sep 17 00:00:00 2001 From: Ines Fazlic Date: Tue, 30 Jul 2024 17:36:08 +0100 Subject: [PATCH] test(fargate): test loading ARTILLERY_CLOUD_API_KEY from .env on Fargate (#3265) --- .../cloud-e2e/fargate/cloud-api-key.test.js | 126 ++++++++++++++++++ .../test/cloud-e2e/fargate/cw-adot.test.js | 5 +- .../test/cloud-e2e/fargate/dd-adot.test.js | 5 +- .../fargate/fixtures/adot/helpers.js | 7 - .../fixtures/cloud-api-key-load/scenario.yml | 10 ++ packages/artillery/test/helpers/index.js | 8 +- 6 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 packages/artillery/test/cloud-e2e/fargate/cloud-api-key.test.js create mode 100644 packages/artillery/test/cloud-e2e/fargate/fixtures/cloud-api-key-load/scenario.yml diff --git a/packages/artillery/test/cloud-e2e/fargate/cloud-api-key.test.js b/packages/artillery/test/cloud-e2e/fargate/cloud-api-key.test.js new file mode 100644 index 0000000000..c1e3f13d6c --- /dev/null +++ b/packages/artillery/test/cloud-e2e/fargate/cloud-api-key.test.js @@ -0,0 +1,126 @@ +const { test, before, beforeEach } = require('tap'); +const { $ } = require('zx'); +const fs = require('fs'); +const got = require('got'); +const { + generateTmpReportPath, + getTestTags, + getTestId +} = require('../../helpers'); +const { + checkForNegativeValues, + checkAggregateCounterSums +} = require('../../helpers/expectations'); + +const A9_PATH = process.env.A9_PATH || 'artillery'; + +before(async () => { + await $`${A9_PATH} -V`; +}); + +const baseTags = getTestTags(['type:acceptance']); + +beforeEach(async (t) => { + $.verbose = true; + t.context.reportFilePath = generateTmpReportPath(t.name, 'json'); +}); + +test('Cloud API key gets loaded from dotenv on Fargate runs', async (t) => { + const scenarioPath = `${__dirname}/fixtures/cloud-api-key-load/scenario.yml`; + const dotEnvPath = `${__dirname}/fixtures/cloud-api-key-load/cloud-key-env`; + + // Move the key from process.env to the dotenv file so we can test if it is being properly loaded + fs.writeFileSync( + dotEnvPath, + `ARTILLERY_CLOUD_API_KEY=${process.env.ARTILLERY_CLOUD_API_KEY}` + ); + delete process.env.ARTILLERY_CLOUD_API_KEY; + + // Run the test without it to make sure the key is not available without the dotenv file + try { + await $`${A9_PATH} run-fargate ${scenarioPath} --record --tags ${baseTags}`; + } catch (err) { + console.log('Error in test run without API key: ', err.message); + t.ok( + err.message.includes( + 'Error: API key is required to record test results to Artillery Cloud' + ), + 'Should error if API key is not provided' + ); + } + + // Run the test with the key provided in the dotenv file + let output; + try { + output = + await $`${A9_PATH} run-fargate ${scenarioPath} --output ${t.context.reportFilePath} --record --tags ${baseTags} --dotenv ${dotEnvPath}`; + } catch (err) { + console.log(err); + t.error( + err, + 'Should not have errored when running the test with the API key provided in the dotenv file' + ); + t.ok( + !err.message.includes( + 'Error: API key is required to record test results to Artillery Cloud' + ), + 'The API key should be available when provided in the dotenv file' + ); + } + + // Get the test from the Artillery Cloud API + const testRunId = getTestId(output.stdout); + const testRunCloudEndpoint = `${ + process.env.ARTILLERY_CLOUD_ENDPOINT || 'https://app.artillery.io' + }/api/load-tests/${testRunId}`; + console.log('Test run Cloud API endpoint: ', testRunCloudEndpoint); + + let res; + try { + res = await got(testRunCloudEndpoint, { + headers: { + 'x-auth-token': `${fs + .readFileSync(dotEnvPath, 'utf8') + .split('=')[1] + .trim()}` + }, + throwHttpErrors: false + }); + } catch (err) { + t.error( + err, + 'Should not have errored when getting the test from the Artillery Cloud API' + ); + } + console.log(`Response status: ${res?.statusCode} ${res?.statusMessage}`); + + const testData = JSON.parse(res.body); + const report = JSON.parse(fs.readFileSync(t.context.reportFilePath, 'utf8')); + + // Assertions + t.equal(output.exitCode, 0, 'CLI Exit Code should be 0'); + t.ok( + output.stdout.includes( + 'Artillery Cloud reporting is configured for this test run' + ), + 'Should have configured Artillery Cloud reporting' + ); + t.equal( + res.statusCode, + 200, + 'Should get a 200 response when getting the test by id from the Artillery Cloud API' + ); + t.ok( + t.equal(testData.id, testRunId, 'Correct test should be returned') && + t.match( + testData?.report?.summary, + report.summary, + 'Report data should match the report file' + ), + 'Should have successfully recorded the test to Artillery Cloud' + ); + + fs.unlinkSync(dotEnvPath); + checkForNegativeValues(t, report); + checkAggregateCounterSums(t, report); +}); diff --git a/packages/artillery/test/cloud-e2e/fargate/cw-adot.test.js b/packages/artillery/test/cloud-e2e/fargate/cw-adot.test.js index befb32a087..081d80afbd 100644 --- a/packages/artillery/test/cloud-e2e/fargate/cw-adot.test.js +++ b/packages/artillery/test/cloud-e2e/fargate/cw-adot.test.js @@ -6,9 +6,10 @@ const fs = require('fs'); const { generateTmpReportPath, deleteFile, - getTestTags + getTestTags, + getTestId } = require('../../helpers'); -const { getTestId, getXRayTraces } = require('./fixtures/adot/helpers.js'); +const { getXRayTraces } = require('./fixtures/adot/helpers.js'); const { checkForNegativeValues, checkAggregateCounterSums diff --git a/packages/artillery/test/cloud-e2e/fargate/dd-adot.test.js b/packages/artillery/test/cloud-e2e/fargate/dd-adot.test.js index 760acc4df5..b02692663a 100644 --- a/packages/artillery/test/cloud-e2e/fargate/dd-adot.test.js +++ b/packages/artillery/test/cloud-e2e/fargate/dd-adot.test.js @@ -6,13 +6,14 @@ const fs = require('fs'); const { generateTmpReportPath, deleteFile, - getTestTags + getTestTags, + getTestId } = require('../../helpers'); const { checkForNegativeValues, checkAggregateCounterSums } = require('../../helpers/expectations'); -const { getDatadogSpans, getTestId } = require('./fixtures/adot/helpers.js'); +const { getDatadogSpans } = require('./fixtures/adot/helpers.js'); const A9_PATH = process.env.A9_PATH || 'artillery'; //NOTE: This test reports to Artillery Dashboard to dogfood and improve visibility diff --git a/packages/artillery/test/cloud-e2e/fargate/fixtures/adot/helpers.js b/packages/artillery/test/cloud-e2e/fargate/fixtures/adot/helpers.js index 8c12299ad1..bbbd18d555 100644 --- a/packages/artillery/test/cloud-e2e/fargate/fixtures/adot/helpers.js +++ b/packages/artillery/test/cloud-e2e/fargate/fixtures/adot/helpers.js @@ -6,17 +6,10 @@ const AWS = require('aws-sdk'); const xray = new AWS.XRay({ region: 'us-east-1' }); module.exports = { - getTestId, getDatadogSpans, getXRayTraces }; -function getTestId(outputString) { - const regex = /Test run ID: \S+/; - const match = outputString.match(regex); - return match[0].replace('Test run ID: ', ''); -} - async function getDatadogSpans(apiKey, appKey, testId, expectedTotalSpans) { const url = 'https://api.datadoghq.com/api/v2/spans/events/search'; const headers = { diff --git a/packages/artillery/test/cloud-e2e/fargate/fixtures/cloud-api-key-load/scenario.yml b/packages/artillery/test/cloud-e2e/fargate/fixtures/cloud-api-key-load/scenario.yml new file mode 100644 index 0000000000..674948c3f3 --- /dev/null +++ b/packages/artillery/test/cloud-e2e/fargate/fixtures/cloud-api-key-load/scenario.yml @@ -0,0 +1,10 @@ +config: + target: http://asciiart.artillery.io:8080 + phases: + - duration: 1 + arrivalRate: 1 +scenarios: + - name: load homepage + flow: + - get: + url: "/dino" diff --git a/packages/artillery/test/helpers/index.js b/packages/artillery/test/helpers/index.js index 156796983c..77057a7cc3 100644 --- a/packages/artillery/test/helpers/index.js +++ b/packages/artillery/test/helpers/index.js @@ -59,6 +59,11 @@ const toCorrectPath = (originalPath) => { ? originalPath.split(path.sep).join(path.posix.sep) : originalPath; }; +function getTestId(outputString) { + const regex = /Test run ID: \S+/i; + const match = outputString.match(regex); + return match[0].replace('Test run ID: ', ''); +} module.exports = { execute, @@ -68,5 +73,6 @@ module.exports = { generateTmpReportPath, getTestTags, toCorrectPath, - getImageArchitecture + getImageArchitecture, + getTestId };