{"_id":"@aleios-internal-tools/stress-test-toolbox-construct","_rev":"3-de43b8cc149dd1aa741f44f3a3f8cfc2","name":"@aleios-internal-tools/stress-test-toolbox-construct","dist-tags":{"latest":"2.1.0"},"versions":{"2.0.0":{"name":"@aleios-internal-tools/stress-test-toolbox-construct","version":"2.0.0","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","scripts":{"build":"tsup lib/index.ts --format cjs,esm --dts && cp -r ./constructs/stress-test-fargate-task/docker ./dist/ && cp -r ./constructs/stress-test-rest-api/auth/create-api-key ./dist/ && cp -r ./constructs/stress-test-rest-api/auth/remove-api-key ./dist/","watch":"tsc -w","test":"jest","publish-package":"npm run build && changeset && changeset publish"},"devDependencies":{"@types/aws-lambda":"^8.10.136","@types/jest":"^29.5.4","@types/js-yaml":"^4.0.9","@types/node":"20.5.3","@types/ramda":"^0.29.11","aws-cdk-lib":"^2.124.0","constructs":"^10.3.0","jest":"^29.6.3","ts-jest":"^29.1.1","tsup":"^8.0.2","typescript":"~5.1.6"},"peerDependencies":{"aws-cdk-lib":"^2.124.0","constructs":"^10.3.0"},"dependencies":{"@aleios-internal-tools/cdk-helpers":"^0.0.1","@aws-sdk/client-api-gateway":"^3.540.0","@aws-sdk/client-dynamodb":"^3.540.0","@aws-sdk/lib-dynamodb":"^3.540.0","@aws-sdk/lib-storage":"^3.540.0","@changesets/cli":"^2.27.1","aws-lambda":"^1.0.7","dotenv":"^16.4.5","js-yaml":"^4.1.0","path":"^0.12.7","ramda":"^0.29.1"},"gitHead":"b66ac72a6fc02f202dbbd9caa455be4e177382e4","description":"Our in-house load testing tool on AWS Fargate enables developers to effortlessly conduct scalable and comprehensive performance and load tests, ensuring our applications withstand real-world pressures.","_id":"@aleios-internal-tools/stress-test-toolbox-construct@2.0.0","_nodeVersion":"18.13.0","_npmVersion":"9.7.1","dist":{"integrity":"sha512-6AG0Zvz1zqWEnkQEbI0lWuoa8qjhehZkUfeIZm7rbm/KdmAC1khOrRTXWSzHttNf/DGkq8L5FscCV8MSz4mLZw==","shasum":"a9f5912d0ea47939c34c27ce45c6fe6edc7d6ae6","tarball":"https://registry.npmjs.org/@aleios-internal-tools/stress-test-toolbox-construct/-/stress-test-toolbox-construct-2.0.0.tgz","fileCount":19,"unpackedSize":388878,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTeVy2+lHr6lBDlJBEetFwKo9t+9FGdjjtafM+axH6YwIgH/m3XWdkXR54BYfQHJZsuPrxFLVdxQGw7gs3s2VHgzs="}]},"_npmUser":{"name":"lizacullis","email":"lizac@aleios.com"},"directories":{},"maintainers":[{"name":"lizacullis","email":"lizac@aleios.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/stress-test-toolbox-construct_2.0.0_1712649785326_0.04119649210298437"},"_hasShrinkwrap":false},"2.0.1":{"name":"@aleios-internal-tools/stress-test-toolbox-construct","version":"2.0.1","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","repository":{"type":"git","url":"git+https://github.com/aleios-cloud/stress-test-construct.git"},"scripts":{"build":"tsup lib/index.ts --format cjs,esm --dts && cp -r ./constructs/stress-test-fargate-task/docker ./dist/ && cp -r ./constructs/stress-test-rest-api/auth/create-api-key ./dist/ && cp -r ./constructs/stress-test-rest-api/auth/remove-api-key ./dist/","watch":"tsc -w","test":"jest","publish-package":"npm run build && changeset && changeset publish"},"devDependencies":{"@types/aws-lambda":"^8.10.136","@types/jest":"^29.5.4","@types/js-yaml":"^4.0.9","@types/node":"20.5.3","@types/ramda":"^0.29.11","aws-cdk-lib":"^2.124.0","constructs":"^10.3.0","jest":"^29.6.3","ts-jest":"^29.1.1","tsup":"^8.0.2","typescript":"~5.1.6"},"peerDependencies":{"aws-cdk-lib":"^2.124.0","constructs":"^10.3.0"},"dependencies":{"@aleios-internal-tools/cdk-helpers":"^0.0.1","@aws-sdk/client-api-gateway":"^3.540.0","@aws-sdk/client-dynamodb":"^3.540.0","@aws-sdk/lib-dynamodb":"^3.540.0","@aws-sdk/lib-storage":"^3.540.0","@changesets/cli":"^2.27.1","aws-lambda":"^1.0.7","dotenv":"^16.4.5","js-yaml":"^4.1.0","path":"^0.12.7","ramda":"^0.29.1"},"gitHead":"b66ac72a6fc02f202dbbd9caa455be4e177382e4","description":"Our in-house load testing tool on AWS Fargate enables developers to effortlessly conduct scalable and comprehensive performance and load tests, ensuring our applications withstand real-world pressures.","bugs":{"url":"https://github.com/aleios-cloud/stress-test-construct/issues"},"homepage":"https://github.com/aleios-cloud/stress-test-construct#readme","_id":"@aleios-internal-tools/stress-test-toolbox-construct@2.0.1","_nodeVersion":"18.13.0","_npmVersion":"9.7.1","dist":{"integrity":"sha512-+Yq1hq02NS5ERQaK7BUC/tkCb8oNy9CSIZ3uzBLsHXQGCvRmd6fP35EWKCX5Oi14lDHZhjLptkMdrGKhiiIFhA==","shasum":"2f84fbef7137465940ade291df88370b65f28ca3","tarball":"https://registry.npmjs.org/@aleios-internal-tools/stress-test-toolbox-construct/-/stress-test-toolbox-construct-2.0.1.tgz","fileCount":19,"unpackedSize":388995,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE3uMpkJPnxo8yoDFQI38uscgxYX+Eg3IGJ7ATUEdPVvAiEAhAcX35fN6RBd3kx9HGTYidkQ3UN24tI9aGGW5VnjwVs="}]},"_npmUser":{"name":"lizacullis","email":"lizac@aleios.com"},"directories":{},"maintainers":[{"name":"lizacullis","email":"lizac@aleios.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/stress-test-toolbox-construct_2.0.1_1712651616418_0.6683471927876119"},"_hasShrinkwrap":false},"2.1.0":{"name":"@aleios-internal-tools/stress-test-toolbox-construct","version":"2.1.0","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","repository":{"type":"git","url":"git+https://github.com/aleios-cloud/stress-test-construct.git"},"scripts":{"build":"tsup lib/index.ts --format cjs,esm --dts && cp -r ./constructs/stress-test-fargate-task/docker ./dist/ && cp -r ./constructs/stress-test-rest-api/auth/create-api-key ./dist/ && cp -r ./constructs/stress-test-rest-api/auth/remove-api-key ./dist/","watch":"tsc -w","test":"jest","publish-package":"npm run build && changeset && changeset publish"},"devDependencies":{"@types/aws-lambda":"^8.10.136","@types/jest":"^29.5.4","@types/js-yaml":"^4.0.9","@types/node":"20.5.3","@types/ramda":"^0.29.11","aws-cdk-lib":"^2.124.0","constructs":"^10.3.0","jest":"^29.6.3","ts-jest":"^29.1.1","tsup":"^8.0.2","typescript":"~5.1.6"},"peerDependencies":{"aws-cdk-lib":"^2.124.0","constructs":"^10.3.0"},"dependencies":{"@aleios-internal-tools/cdk-helpers":"^1.0.0","@aws-sdk/client-api-gateway":"^3.540.0","@aws-sdk/client-dynamodb":"^3.540.0","@aws-sdk/lib-dynamodb":"^3.540.0","@aws-sdk/lib-storage":"^3.540.0","@changesets/cli":"^2.27.1","aws-lambda":"^1.0.7","dotenv":"^16.4.5","js-yaml":"^4.1.0","path":"^0.12.7","ramda":"^0.29.1"},"gitHead":"b66ac72a6fc02f202dbbd9caa455be4e177382e4","description":"Our in-house load testing tool on AWS Fargate enables developers to effortlessly conduct scalable and comprehensive performance and load tests, ensuring our applications withstand real-world pressures.","bugs":{"url":"https://github.com/aleios-cloud/stress-test-construct/issues"},"homepage":"https://github.com/aleios-cloud/stress-test-construct#readme","_id":"@aleios-internal-tools/stress-test-toolbox-construct@2.1.0","_nodeVersion":"18.13.0","_npmVersion":"9.7.1","dist":{"integrity":"sha512-Vd2FFg2wWdY/DLj5RLGzFtt0HLruFwImEipSDH/5LpbnKu9AXg5KDDy0HQQU1Alprqxu0JK8L9Er3vcrJ5u2NA==","shasum":"422e5ec1d2e3d4f3e350cbf7a86ac71a3bc3e477","tarball":"https://registry.npmjs.org/@aleios-internal-tools/stress-test-toolbox-construct/-/stress-test-toolbox-construct-2.1.0.tgz","fileCount":19,"unpackedSize":388995,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD1wIxoaFRyyA6ciTl2EJ6rfj4Vyugb/JbIb76FXr4vBQIhANzET3/lNEAKtH8NUDn6s8leX5MHhoAxBYYfBNHD8kN3"}]},"_npmUser":{"name":"lizacullis","email":"lizac@aleios.com"},"directories":{},"maintainers":[{"name":"lizacullis","email":"lizac@aleios.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/stress-test-toolbox-construct_2.1.0_1712651698720_0.656446025925733"},"_hasShrinkwrap":false}},"time":{"created":"2024-04-09T08:03:05.241Z","2.0.0":"2024-04-09T08:03:05.483Z","modified":"2024-04-12T12:06:32.257Z","2.0.1":"2024-04-09T08:33:36.701Z","2.1.0":"2024-04-09T08:34:59.006Z"},"maintainers":[{"email":"aidenw@aleios.com","name":"aiden-walton"},{"email":"lizac@aleios.com","name":"lizacullis"}],"description":"Our in-house load testing tool on AWS Fargate enables developers to effortlessly conduct scalable and comprehensive performance and load tests, ensuring our applications withstand real-world pressures.","readme":"# Welcome to Stress Test Toolbox.\n\nOur in-house load testing tool on AWS Fargate enables developers to effortlessly conduct scalable and comprehensive performance and load tests, ensuring our applications withstand real-world pressures.\n\nCombining this tool with our retool front end enables an even better user experience as well as great dashboards to view the results of your tests.\n\n# How to set up the tool\n## The Backend\n\nTo use this construct, first install the npm package.\n\n```bash\nnpm i @stress-test-toolbox/stress-test-construct\n```\n\nImport the construct from the package\n\n```typescript\nimport { StressTestConstruct } from \"@stress-test-toolbox/stress-test-construct\";\n```\n\nThen in your cdk stack create an instance of the construct\n\n```typescript\nnew StressTestConstruct(this, \"stress-test-toolbox\");\n```\n\nExample stack:\n\n```typescript\nimport { Stack } from \"aws-cdk-lib\";\nimport { StressTestConstruct } from \"@stress-test-toolbox/stress-test-construct\";\nimport { Construct } from \"constructs\";\n\nexport class TestingStack extends Stack {\n  constructor(scope: Construct, id: string) {\n    super(scope, id);\n\n    new StressTestConstruct(this, \"stress-test-toolbox\");\n  }\n}\n```\n## The Frontend \nWe have created a retool front end that you can use to run this tool. \n\n***How to deploy your own version coming soon!***\n\n## CI/CD\nAdding the tool via CI/CD, to hit the load testing endpoint from a github workflow file to trigger your tests:\n\n1. Firstly you need to make sure that you have the load testing stack deployed into your project’s AWS account.\n2. You need to get an api key that can be used in the CI/CD to invoke the load testing endpoint. This can be done by hitting the `createApiKey` endpoint.\n3. Next you need to add a config file for the artillery test you want to run, this config file needs to be in json and not yaml.  This config file can be stored anywhere in your repo, but would recommend storing in your ‘.github’ folder for easy access.\n4. Now we can implement a step in a github workflow file as below.\n\n```yaml\n- name: Run load-test\n  run: |\n    curl -X POST \\\n    -H \"x-api-key: xxx\" \\\n    -H \"Content-Type: application/json\" \\\n    -d \"@./.github/config.json\" \\ \n    https://<your-api-gateway-url>/loadTestRequest\n```\n\nThings to note:\n\n- The `x-api-key` will be the api key’s value you get from hitting the `createApiKey` endpoint\n- We are using the `-d` flag to reference our config file. The path specified to your `config.json` which contains your artillery load test config needs to have an `@` at the beginning.\n- The api url is the load testing stack url which should include the ‘/loadTestRequest’ path\n\n# How to use it\n\nNow that you have the tool all set up, you just need to start using it. \nThe whole point of this tool is to make it easy for users to use so this will be relatively simple. \n\n## Via Backend Only\n1. First create a config file for your test. We are using artillery to run these test, so have a look at their [docs](https://www.artillery.io/) on how to write the config. **NOTE: You need to write the config in json not in yml as artillery uses.**\n2. With your config file, you can now hit the `loadTestRequest` endpoint to start your test. Have a look at the [loadTestRequest endpoint](#loadtestrequest) details for the structure of the request body.\n3. Once you have successfully hit the endpoint your load test will start running. \n4. It is recommended to add your email into the body so that you are notified once you test has completed running. \n5. Now that your test is finished the results are stored in S3. You can download a json report as well as a html report that will display the data in graphs etc. \n\n## Via Frontend \n\n1. Open your retool app and go to the run a test page. There is a code block where you can write your config file. We are using artillery to run our tests so have a look at their [docs](https://www.artillery.io/) on how to write the config. **NOTE: You need to write the config in json not in yml as artillery uses.**\n2. On the right there are options that you can fill in, such as testName and email (to receive a notification once your test is complete.) These are optional, but very useful. \n3. Once your test has completed running, go to the Results page. Here you will find a table with all your tests in. Click on a test to view the results via metrics and graphs.\n\n\n# Architecture\n\n![architecture](./assets/architecture.png)\n\n## Flow:\n\n1. Client sends LoadTestRequest to API Gateway with some config.\n   1. API Gateway is protected with IAM Auth. Create and Delete key commands also exist to manage keys easily.\n   2. This is a async request so the user gets an immediate response which contains the `executionId`. This is use to uniquely identify the tests. This is done using response mappings.\n2. LoadTestRequest is forwarded to StepFunction which invokes a StateMachine.\n3. The StateMachine creates a Database entry into DDB using the `execId` as the Primary Key, and status sets the config user as well as sets the test status to `TEST_INITIATED`.\n4. Then the StepFunction runs the RunTask step which creates a Fargate Task from a Task Definition.\n   1. This will update the status of the test in DDB to `TEST_RUNNING`\n   2. This will run the actual load test with the configuration provided by the user.\n5. Once the test has run in the Fargate Task the task will also store the result reports in S3 before terminating.\n6. Once the test is completed the status will once again be updated\n   1. If it was successful the status will be updated to `TEST_COMPLETED`.\n   2. If it was unsuccessful the status will be updated to `TEST_FAILED`.\n7. If a user provided an email, a email notification will be sent to the user to notify them that the test has finished running\n8. The results of the tests are pulled by Retool directly from S3 and DDB.\n\n## Services\n\n### Api Gateway\n\n> Postman Collection:\n> Find the asset for the postman collection in the assets folder, under [load-testing-postman-collection.json](./assets/load-testing-postman-collection.json)\n\n**Endpoints:**\n\n- `LoadTestRequest`(Has request validation)\n- `CreateAPIKey` (For IAM Auth)\n- `DeleteAPIKey` (For IAM Auth)\n\n---\n\n#### /loadTestRequest\n\nHeaders:\n\n```yml\nx-api-key: <IAM Auth API Key>\n```\n\nBody:\n\n```typescript\nconfig: JSON formatted artillery test script (required)\ntestName: String (optional)\nemail: String (optional)\n```\n\nResponse Example:\n\n```json\n{\n  \"executionArn\": \"arn:aws:states:eu-west-2:730335287746:execution:liza-stress-test-RunLoadTestTaskStateMachine:25d70ecb-fad8-47b6-9971-27bf796e75a8\",\n  \"startDate\": 1.710772458892e9\n}\n```\n\n---\n\n#### /createApiKey\n\n> Authorization: You need to create an IAM user for something like postman and then use the `AccessKey` and `SecretKey` to authorise the request.\n\nBody:\n\n```typescript\nkeyName: String(required);\n```\n\nResponse Example:\n\n```json\n{\n  \"apiKey\": {\n    \"id\": \"qg5mwymgg1\",\n    \"value\": \"NxHvgAqVkZafzmfgf2eSY7Upx8XqfBOU7z95ltVu\",\n    \"name\": \"liza-test\"\n  },\n  \"usagePlan\": {\n    \"id\": \"zoufj0\",\n    \"name\": \"liza-test-usage-plan\"\n  }\n}\n```\n\n---\n\n#### deleteApiKey\n\n> Authorization: You need to create an IAM user for something like postman and then use the `AccessKey` and `SecretKey` to authorise the request.\n\nBody:\n\n```typescript\napiKeyId: String(required);\n```\n\nResponse Example:\n\n```json\n200: ok\n```\n---\n### Step Function:\n---\nThe step function has the following steps:\n\n![stepFunctionFlow](./assets/stepFunctionFlow.png)\n\n#### Flow\n\n1. Adds an execution entry into DDB\n   - Status = `TEST_INITIATED`\n   - Config = The config provided by the user in JSON format\n   - Test Name = Name provided by user, if it has been provided\n2. Runs the fargate task with the provided config.\n   - Updates the status to `TEST_RUNNING`.\n   - Starts an artillery load test with the config.\n   - Once the test is complete the results are stored in S3.\n   - If anything in this task fails, it will be caught and the status will be updated to `TEST_FAILED`.\n3. After the fargate task has completed and terminated, we update the status again\n   - Status = `TEST_COMPLETED`\n4. Send an email to notify the user if the test is complete\n   - If the user has provided an email, an email will be sent\n   - Otherwise, this step is skipped\n","readmeFilename":"README.md","homepage":"https://github.com/aleios-cloud/stress-test-construct#readme","repository":{"type":"git","url":"git+https://github.com/aleios-cloud/stress-test-construct.git"},"bugs":{"url":"https://github.com/aleios-cloud/stress-test-construct/issues"}}