├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── THIRD-PARTY ├── bin ├── requirements.txt └── runner.py ├── cloudformation ├── additional-region.yaml ├── fargate-cluster.yaml ├── fargate-vpc.yaml ├── master.yaml └── pipeline.yaml ├── docs ├── add-region-params.png ├── add-region.gif ├── arch.png ├── cfn-outputs.png ├── cloudwatch.jpg ├── dashboard.png ├── elasticsearch.png ├── fargate.png ├── master-outputs.png └── pipeline.png └── examples ├── elasticsearch ├── README.md ├── consumer.test.js ├── es-client.js ├── package-lock.json ├── package.json ├── producer.test.js └── taurus.yml └── http └── taurus.yml /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | bin/env 3 | node_modules -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/issues), or [recently closed](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM blazemeter/taurus 2 | ADD examples/http /bzt-configs/ 3 | # ADD examples/elasticsearch /bzt-configs/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT No Attribution 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## [NEW] We launched as an official AWS Solution! 2 | 3 | The last few months we have been working hard on making this project better and we are happy to announce that v1.0 is now available to be deployed as an official AWS Solution: [https://aws.amazon.com/solutions/distributed-load-testing-on-aws](https://aws.amazon.com/solutions/distributed-load-testing-on-aws). 4 | 5 | The solution offers a polished version of this project with proper documentation and a User Interface (Console) where you can run and manage your load test scenarios. The solution is also open source, so you can fork it, customize it or even contribute back if you are interested! GitHub repository: [https://github.com/awslabs/distributed-load-testing-on-aws](https://github.com/awslabs/distributed-load-testing-on-aws). 6 | 7 | The instructions below will continue to work but our development efforts will be focused on the new release. 8 | 9 | ## [OLD] Distributed Load Testing Using Fargate [![](https://img.shields.io/badge/CFN-deploy-green.svg?style=flat-square&logo=amazon)](#getting-started) [![](https://img.shields.io/github/stars/aws-samples/distributed-load-testing-using-aws-fargate.svg?logo=github&style=flat-square)](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate) 10 | 11 | This project launches a solution that runs Distributed Load Tests using 12 | [AWS Fargate](https://aws.amazon.com/fargate) and [Taurus](https://gettaurus.org). You can use it to test your 13 | services under high stress scenarios and understand it's behavior and scalability. 14 | 15 | ![Architecture](docs/arch.png) 16 | 17 | Taurus acts as a wrapper around JMeter and allows you to generate HTTP requests in parallel simulating a 18 | real-world scenario. This solution shows how to run Taurus on Docker containers and deploy them to Fargate clusters 19 | running in different AWS regions, so that you can simulate requests coming from different geographic locations into 20 | your service. 21 | 22 | **Note**: Your service (system under test) does not have to be running on AWS. You can configure this solution to hit 23 | any HTTP endpoint as long as it's accessible through the internet. However, this solution is meant to be deployed 24 | on an AWS account. 25 | 26 | ## License Summary 27 | 28 | This sample code is made available under a modified MIT license. See the LICENSE file. 29 | 30 | ## Requirements 31 | 32 | - An AWS Account 33 | - [Git Credentials for AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-gc.html) 34 | 35 | ## Getting Started 36 | 37 | ### Step 1. Launch Solution 38 | 39 | In this step you will launch the `master` CloudFormation stack that will create a Fargate Cluster, an ECR Docker registry, an IAM 40 | Execution Role, a Task Definition, a CloudWatch Log Group, a Security Group, a new VPC, a CodeCommit repository, a CodePipeline 41 | and 2 CodeBuild projects with their associated IAM Roles. 42 | 43 | Region Name | Region Code | Launch 44 | ------|-----|----- 45 | US East (N. Virginia) | us-east-1 | [![Launch in us-east-1](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/master.yaml) 46 | US East (Ohio) | us-east-2 | [![Launch in us-east-2](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/master.yaml) 47 | US West (Oregon) | us-west-2 | [![Launch in us-west-2](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/master.yaml) 48 | EU West (Ireland) | eu-west-1 | [![Launch in eu-west-1](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/master.yaml) 49 | 50 | You will notice that the CloudFormation `master` stack expands itself into 4 stacks: The master one, which takes care of 51 | creating resources that will be shared across regions like the ECR Registry and the CodePipeline; The VPC nested stack, 52 | which creates the network configuration and subnets; The Fargate nested stack which creates the cluster and task definition 53 | and the Pipeline nested stack that creates the CodeCommit repository and the CodeBuild projects to build and run the 54 | load tests in Fargate. 55 | 56 | ### Step 2. Clone this repository 57 | 58 | ```bash 59 | git clone https://github.com/aws-samples/distributed-load-testing-using-aws-fargate.git 60 | ``` 61 | 62 | ### Step 3. Modify the load test scenario 63 | 64 | Configure your test scenario by editing the `examples/http/taurus.yml` file. The default example shown below runs a load test 65 | for 5 minutes with 5 concurrent requests per second against https://aws.amazon.com with a ramp-up time of 1 minute. 66 | 67 | ```yaml 68 | execution: 69 | - concurrency: 5 70 | ramp-up: 1m 71 | hold-for: 5m 72 | scenario: aws-website-test 73 | 74 | scenarios: 75 | aws-website-test: 76 | requests: 77 | - https://aws.amazon.com 78 | ``` 79 | 80 | To learn more about the syntax of this file, check the Taurus docs: https://gettaurus.org/kb/Index. 81 | 82 | ### Step 4. Push to CodeCommit 83 | 84 | One of the resources that gets created when deploying this solution is a CodeCommit repository and a CodePipeline connected 85 | to it. On every commit the pipeline will run automatically, build the load test scenarios into a Docker image and push 86 | the image to the ECR registry and finally run the load tests into the Fargate clusters. 87 | 88 | Now, remove the current Git origin of the project because you just cloned it from Github and you want your remote origin 89 | to be the CodeCommit repository instead. 90 | 91 | ```bash 92 | git remote rm origin 93 | ``` 94 | 95 | Now, set the origin to be your new CodeCommit repository. An easy way to find the repository URL is in the `Outputs` section 96 | of the CloudFormation stack you launched on Step 1. [See the following screenshot](docs/cfn-outputs.png). The URL 97 | should look something like this: `https://git-codecommit.us-west-2.amazonaws.com/v1/repos/distributed-load-testing-using-aws-fargate`. 98 | 99 | ```bash 100 | git remote add origin {code_commit_repository_url} 101 | ``` 102 | 103 | Finally, push the code. 104 | 105 | ```bash 106 | git push -u origin master 107 | ``` 108 | 109 | **Note** If you get a permission denied error when pushing, you may not have configured CodeCommit credentials. Follow this 110 | steps to get your authentication setup: [Git Credentials for AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/setting-up-gc.html). 111 | 112 | If the push was successful, go to CodePipeline and check how the build progresses all the way to the last step, which will 113 | run the tests in the Fargate cluster. The pipeline should look like this: 114 | 115 | ![Pipeline](docs/pipeline.png) 116 | 117 | ### Step 5. Monitor the test execution 118 | 119 | When the last step of the pipeline has finished successfully, it means that your load tests are now running on Fargate. 120 | Go to the ECS Console to find your Fargate cluster, click on it and you should see 3 tasks running: 121 | 122 | ![FargateTasks](docs/fargate.png) 123 | 124 | Finally, this solution also created a [CloudWatch Metric Filter](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html) 125 | that will capture the average response times for each HTTP request that is issued to your system under test by the 126 | Docker tasks running on Fargate. 127 | 128 | What this filter is doing, is parsing the Taurus logs and assigning a variable name to each value in the log. It ignores 129 | all values in the log except for `avgRt` which is captured as a new metric and stored in your CloudWatch Metrics. To learn 130 | more about how this metric filter was created, check the CloudFormation template `cloudformation/fargate-cluster.yaml`. 131 | 132 | Go to CloudWatch and you should see a Dashboard that was created automatically for you under the Dashboards section. It 133 | will display the metrics captured by the filter described above and display it in a nice graph: 134 | 135 | ![Dashboard](docs/dashboard.png) 136 | 137 | ## Launch Additional Regions (Optional) 138 | 139 | It may be likely that running this solution from a single AWS region is enough to load test your service. However, 140 | if you want to take it a step further, you can deploy Fargate clusters in multiple regions and make it a 141 | multi-region load test simulation. In order to do this, I created a separate CloudFormation template that launches this 142 | solution in additional regions. The difference between this template and the Master one is that this one does not 143 | create the ECR Docker Registry, the CodePipeline and IAM Roles, as those resources will be shared across all your regions. 144 | 145 | Use the following links to launch the solution in the desired additional regions: 146 | 147 | Additional Region | Region Code | Launch 148 | ------|-----|----- 149 | US East (N. Virginia) | us-east-1 | [![Launch in us-east-1](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/additional-region.yaml) 150 | US East (Ohio) | us-east-2 | [![Launch in us-east-2](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/additional-region.yaml) 151 | US West (Oregon) | us-west-2 | [![Launch in us-west-2](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/additional-region.yaml) 152 | EU West (Ireland) | eu-west-1 | [![Launch in eu-west-1](https://camo.githubusercontent.com/210bb3bfeebe0dd2b4db57ef83837273e1a51891/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f636c6f7564666f726d6174696f6e2d6578616d706c65732f636c6f7564666f726d6174696f6e2d6c61756e63682d737461636b2e706e67)](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=DistributedLoadTesting&templateURL=https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/additional-region.yaml) 153 | 154 | This stack will ask for 2 parameters: The `DockerRegistryURL` and `TaskExecutionRoleArn`. You can find the values for those 155 | parameters in the `Outputs` section of the `Master` CloudFormation stack launched in **Step 1**. 156 | 157 | ![MasterOutputs](docs/master-outputs.png) 158 | 159 | ![AdditionalRegionParams](docs/add-region-params.png) 160 | 161 | Finally, Once the stack has been completed, you need to tell CodePipeline that a new region has been configured so that 162 | it also launches the Load Tests scenarios in this region. To do this, go back to the region where you launched the `Master` 163 | stack and follow these steps: 164 | 165 | 1. Go to CodePipeline, then select the pipeline created by the master stack 166 | 2. Click on the `LoadTest` step to edit it. 167 | 3. Go to Edit > Environment 168 | 4. Expand the `Additional Configuration` section 169 | 5. Add 2 new environment variables to have your additional region added. 170 | 171 | Name | Value 172 | ---------------------|--------------------- 173 | REGION_2 | Additional region (i.e. us-east-1) 174 | REGION_2_STACK_NAME | CloudFormation stack name (i.e. DistributedLoadTesting) 175 | 176 | *Gif to help demonstrate the steps mentioned above: 177 | 178 | ![AddRegion](docs/add-region.gif) 179 | 180 | Save the changes, run the pipeline and you are done! Repeat those steps for every additional region. 181 | 182 | ### Monitor All Regions 183 | 184 | When you launch this solution in multiple regions, I recommend you centralize the monitoring into the same CloudWatch 185 | Dashboard for easier visibility. In order to do this, you need to pull metrics from different regions into the Dashboard 186 | by [follow this steps](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cross_region_dashboard.html). Once 187 | configured, the multi-region Dashboard will look something like this: 188 | 189 | ![CloudWatch](docs/cloudwatch.jpg) 190 | 191 | ## How to Run Locally 192 | 193 | It's a good practice to run your tests locally before pushing them to CodeCommit to make sure they run correctly in a 194 | Docker container. To do this, build the image by issuing the following command in the root directory of this project. 195 | 196 | ```bash 197 | docker build -t load-tests-using-fargate . 198 | ``` 199 | 200 | Then run the container locally. 201 | 202 | ```bash 203 | docker run -it load-tests-using-fargate taurus.yml 204 | ``` 205 | 206 | If you are happy with the result, you can push the changes to the CodeCommit repository and let the pipeline 207 | do the rest. -------------------------------------------------------------------------------- /THIRD-PARTY: -------------------------------------------------------------------------------- 1 | ** Boto3; version 1.9.4 -- https://github.com/boto/boto3/ 2 | ** Taurus; version 1.13.0 -- https://github.com/Blazemeter/taurus 3 | 4 | Apache License 5 | Version 2.0, January 2004 6 | http://www.apache.org/licenses/ 7 | 8 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 9 | 10 | 1. Definitions. 11 | 12 | "License" shall mean the terms and conditions for use, reproduction, and 13 | distribution as defined by Sections 1 through 9 of this document. 14 | 15 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 16 | owner that is granting the License. 17 | 18 | "Legal Entity" shall mean the union of the acting entity and all other entities 19 | that control, are controlled by, or are under common control with that entity. 20 | For the purposes of this definition, "control" means (i) the power, direct or 21 | indirect, to cause the direction or management of such entity, whether by 22 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity exercising 26 | permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, including 29 | but not limited to software source code, documentation source, and 30 | configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical transformation or 33 | translation of a Source form, including but not limited to compiled object 34 | code, generated documentation, and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or Object form, 37 | made available under the License, as indicated by a copyright notice that is 38 | included in or attached to the work (an example is provided in the Appendix 39 | below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object form, that 42 | is based on (or derived from) the Work and for which the editorial revisions, 43 | annotations, elaborations, or other modifications represent, as a whole, an 44 | original work of authorship. For the purposes of this License, Derivative Works 45 | shall not include works that remain separable from, or merely link (or bind by 46 | name) to the interfaces of, the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including the original 49 | version of the Work and any modifications or additions to that Work or 50 | Derivative Works thereof, that is intentionally submitted to Licensor for 51 | inclusion in the Work by the copyright owner or by an individual or Legal 52 | Entity authorized to submit on behalf of the copyright owner. For the purposes 53 | of this definition, "submitted" means any form of electronic, verbal, or 54 | written communication sent to the Licensor or its representatives, including 55 | but not limited to communication on electronic mailing lists, source code 56 | control systems, and issue tracking systems that are managed by, or on behalf 57 | of, the Licensor for the purpose of discussing and improving the Work, but 58 | excluding communication that is conspicuously marked or otherwise designated in 59 | writing by the copyright owner as "Not a Contribution." 60 | 61 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 62 | of whom a Contribution has been received by Licensor and subsequently 63 | incorporated within the Work. 64 | 65 | 2. Grant of Copyright License. Subject to the terms and conditions of this 66 | License, each Contributor hereby grants to You a perpetual, worldwide, 67 | non-exclusive, no-charge, royalty-free, irrevocable copyright license to 68 | reproduce, prepare Derivative Works of, publicly display, publicly perform, 69 | sublicense, and distribute the Work and such Derivative Works in Source or 70 | Object form. 71 | 72 | 3. Grant of Patent License. Subject to the terms and conditions of this 73 | License, each Contributor hereby grants to You a perpetual, worldwide, 74 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this 75 | section) patent license to make, have made, use, offer to sell, sell, import, 76 | and otherwise transfer the Work, where such license applies only to those 77 | patent claims licensable by such Contributor that are necessarily infringed by 78 | their Contribution(s) alone or by combination of their Contribution(s) with the 79 | Work to which such Contribution(s) was submitted. If You institute patent 80 | litigation against any entity (including a cross-claim or counterclaim in a 81 | lawsuit) alleging that the Work or a Contribution incorporated within the Work 82 | constitutes direct or contributory patent infringement, then any patent 83 | licenses granted to You under this License for that Work shall terminate as of 84 | the date such litigation is filed. 85 | 86 | 4. Redistribution. You may reproduce and distribute copies of the Work or 87 | Derivative Works thereof in any medium, with or without modifications, and in 88 | Source or Object form, provided that You meet the following conditions: 89 | 90 | (a) You must give any other recipients of the Work or Derivative Works a copy 91 | of this License; and 92 | 93 | (b) You must cause any modified files to carry prominent notices stating that 94 | You changed the files; and 95 | 96 | (c) You must retain, in the Source form of any Derivative Works that You 97 | distribute, all copyright, patent, trademark, and attribution notices from the 98 | Source form of the Work, excluding those notices that do not pertain to any 99 | part of the Derivative Works; and 100 | 101 | (d) If the Work includes a "NOTICE" text file as part of its distribution, then 102 | any Derivative Works that You distribute must include a readable copy of the 103 | attribution notices contained within such NOTICE file, excluding those notices 104 | that do not pertain to any part of the Derivative Works, in at least one of the 105 | following places: within a NOTICE text file distributed as part of the 106 | Derivative Works; within the Source form or documentation, if provided along 107 | with the Derivative Works; or, within a display generated by the Derivative 108 | Works, if and wherever such third-party notices normally appear. The contents 109 | of the NOTICE file are for informational purposes only and do not modify the 110 | License. You may add Your own attribution notices within Derivative Works that 111 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 112 | provided that such additional attribution notices cannot be construed as 113 | modifying the License. 114 | 115 | You may add Your own copyright statement to Your modifications and may provide 116 | additional or different license terms and conditions for use, reproduction, or 117 | distribution of Your modifications, or for any such Derivative Works as a 118 | whole, provided Your use, reproduction, and distribution of the Work otherwise 119 | complies with the conditions stated in this License. 120 | 121 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 122 | Contribution intentionally submitted for inclusion in the Work by You to the 123 | Licensor shall be under the terms and conditions of this License, without any 124 | additional terms or conditions. Notwithstanding the above, nothing herein shall 125 | supersede or modify the terms of any separate license agreement you may have 126 | executed with Licensor regarding such Contributions. 127 | 128 | 6. Trademarks. This License does not grant permission to use the trade names, 129 | trademarks, service marks, or product names of the Licensor, except as required 130 | for reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in 134 | writing, Licensor provides the Work (and each Contributor provides its 135 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 136 | KIND, either express or implied, including, without limitation, any warranties 137 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 138 | PARTICULAR PURPOSE. You are solely responsible for determining the 139 | appropriateness of using or redistributing the Work and assume any risks 140 | associated with Your exercise of permissions under this License. 141 | 142 | 8. Limitation of Liability. In no event and under no legal theory, whether in 143 | tort (including negligence), contract, or otherwise, unless required by 144 | applicable law (such as deliberate and grossly negligent acts) or agreed to in 145 | writing, shall any Contributor be liable to You for damages, including any 146 | direct, indirect, special, incidental, or consequential damages of any 147 | character arising as a result of this License or out of the use or inability to 148 | use the Work (including but not limited to damages for loss of goodwill, work 149 | stoppage, computer failure or malfunction, or any and all other commercial 150 | damages or losses), even if such Contributor has been advised of the 151 | possibility of such damages. 152 | 153 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or 154 | Derivative Works thereof, You may choose to offer, and charge a fee for, 155 | acceptance of support, warranty, indemnity, or other liability obligations 156 | and/or rights consistent with this License. However, in accepting such 157 | obligations, You may act only on Your own behalf and on Your sole 158 | responsibility, not on behalf of any other Contributor, and only if You agree 159 | to indemnify, defend, and hold each Contributor harmless for any liability 160 | incurred by, or claims asserted against, such Contributor by reason of your 161 | accepting any such warranty or additional liability. 162 | 163 | END OF TERMS AND CONDITIONS 164 | 165 | APPENDIX: How to apply the Apache License to your work. 166 | 167 | To apply the Apache License to your work, attach the following boilerplate 168 | notice, with the fields enclosed by brackets "[]" replaced with your own 169 | identifying information. (Don't include the brackets!) The text should be 170 | enclosed in the appropriate comment syntax for the file format. We also 171 | recommend that a file or class name and description of purpose be included on 172 | the same "printed page" as the copyright notice for easier identification 173 | within third-party archives. 174 | 175 | Copyright [yyyy] [name of copyright owner] 176 | 177 | Licensed under the Apache License, Version 2.0 (the "License"); 178 | you may not use this file except in compliance with the License. 179 | You may obtain a copy of the License at 180 | 181 | http://www.apache.org/licenses/LICENSE-2.0 182 | 183 | Unless required by applicable law or agreed to in writing, software 184 | distributed under the License is distributed on an "AS IS" BASIS, 185 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 186 | See the License for the specific language governing permissions and 187 | limitations under the License. 188 | 189 | * For Boto3 see also this required NOTICE: 190 | Copyright 2013-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 191 | * For Taurus see also this required NOTICE: 192 | Copyright 2015 BlazeMeter Inc. -------------------------------------------------------------------------------- /bin/requirements.txt: -------------------------------------------------------------------------------- 1 | boto3==1.9.4 -------------------------------------------------------------------------------- /bin/runner.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | import boto3 16 | import uuid 17 | import os 18 | 19 | 20 | # Will be passed as environment variable to the Fargate docker containers. 21 | # Useful with the Elasticsearch example as the test suite will read the cluster URL from this variable. 22 | ENDPOINT_UNDER_TEST = os.getenv('ENDPOINT_UNDER_TEST', 'http://strawberry.banana.com') 23 | TASK_COUNT = int(os.getenv('TASK_COUNT', 3)) 24 | 25 | def get_regions_from_environment_variables(): 26 | regions = [] 27 | region_count = 1 28 | next_region = os.environ.get('REGION_' + str(region_count)) 29 | while next_region: 30 | regions.append({ 31 | 'name': next_region, 32 | 'stackName': os.environ.get('REGION_' + str(region_count) + '_STACK_NAME') 33 | }) 34 | region_count += 1 35 | next_region = os.environ.get('REGION_' + str(region_count)) 36 | 37 | return regions 38 | 39 | 40 | def start_distributed_load_test(): 41 | run_id = str(uuid.uuid4()) 42 | print('Started new load test with runId = {}'.format(run_id)) 43 | 44 | print('Getting list of regions from environment variables') 45 | regions = get_regions_from_environment_variables() 46 | 47 | for region in regions: 48 | 49 | if not region['stackName']: 50 | continue 51 | 52 | cloud_formation = boto3.client('cloudformation', region_name=region['name']) 53 | ecs = boto3.client('ecs', region_name=region['name']) 54 | 55 | print('Describing CloudFormation stack {} in region {}'.format(region['stackName'], region['name'])) 56 | stacks = cloud_formation.describe_stacks( 57 | StackName=region['stackName'] 58 | ) 59 | 60 | if not stacks['Stacks']: 61 | print("CloudFormation stack {} not found in region {}".format(region['stackName'], region['name'])) 62 | exit(0) 63 | 64 | stack = stacks['Stacks'][0] 65 | outputs = stack['Outputs'] 66 | stack_outputs = {} 67 | 68 | print('Extracting cluster values from CloudFormation stack') 69 | for output in outputs: 70 | stack_outputs[output['OutputKey']] = output['OutputValue'] 71 | 72 | print('Scheduling tasks in region {}'.format(region['name'])) 73 | response = ecs.run_task( 74 | cluster=stack_outputs['FargateClusterName'], 75 | taskDefinition=stack_outputs['TaskDefinitionArn'], 76 | count=TASK_COUNT, 77 | startedBy=run_id, 78 | group=run_id, 79 | launchType='FARGATE', 80 | overrides={ 81 | 'containerOverrides': [ 82 | { 83 | 'name': 'dlt-fargate-task', 84 | 'environment': [ 85 | { 86 | 'name': 'ENDPOINT_UNDER_TEST', 87 | 'value': ENDPOINT_UNDER_TEST 88 | }, 89 | ], 90 | }, 91 | ] 92 | }, 93 | networkConfiguration={ 94 | 'awsvpcConfiguration': { 95 | 'assignPublicIp': 'ENABLED', 96 | 'securityGroups': [stack_outputs['TaskSecurityGroup']], 97 | 'subnets': [ 98 | stack_outputs['SubnetA'], 99 | stack_outputs['SubnetB'], 100 | stack_outputs['SubnetC'] 101 | ] 102 | } 103 | } 104 | ) 105 | 106 | if not response or response['failures']: 107 | print('Failed to schedule tasks') 108 | exit(0) 109 | 110 | for task in response['tasks']: 111 | print('Task scheduled {}', task['taskArn']) 112 | 113 | 114 | if __name__ == '__main__': 115 | start_distributed_load_test() 116 | -------------------------------------------------------------------------------- /cloudformation/additional-region.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | AWSTemplateFormatVersion: 2010-09-09 16 | Description: > 17 | Additional Region for Distributed Load Test Using AWS Fargate. 18 | It deploys a Fargate Cluster, a VPC and a CloudWatch Log group. 19 | 20 | Parameters: 21 | DockerRegistryURL: 22 | Type: String 23 | Description: > 24 | URL of the ECR repository created in the master CloudFormation template. It should be in the form of 25 | account_id.dkr.ecr.region.amazonaws.com/registry_name 26 | TaskExecutionRoleArn: 27 | Type: String 28 | Description: > 29 | IAM Execution Role ARN for the Fargate tasks, it should have been created by the master 30 | CloudFormation template and available in the Outputs section. 31 | 32 | Resources: 33 | Vpc: 34 | Type: AWS::CloudFormation::Stack 35 | Properties: 36 | TemplateURL: "https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/fargate-vpc.yaml" 37 | 38 | FargateCluster: 39 | Type: AWS::CloudFormation::Stack 40 | DependsOn: Vpc 41 | Properties: 42 | TemplateURL: "https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/fargate-cluster.yaml" 43 | Parameters: 44 | VpcId: !GetAtt Vpc.Outputs.VpcId 45 | TaskExecutionRoleArn: !Ref TaskExecutionRoleArn 46 | DockerImage: !Join 47 | - '' 48 | - - !Ref DockerRegistryURL 49 | - ':latest' 50 | Outputs: 51 | FargateClusterName: 52 | Value: !GetAtt FargateCluster.Outputs.FargateClusterName 53 | TaskSecurityGroup: 54 | Value: !GetAtt FargateCluster.Outputs.TaskSecurityGroup 55 | TaskDefinitionArn: 56 | Value: !GetAtt FargateCluster.Outputs.TaskDefinitionArn 57 | VpcId: 58 | Value: !GetAtt Vpc.Outputs.VpcId 59 | SubnetA: 60 | Value: !GetAtt Vpc.Outputs.SubnetA 61 | SubnetB: 62 | Value: !GetAtt Vpc.Outputs.SubnetB 63 | SubnetC: 64 | Value: !GetAtt Vpc.Outputs.SubnetC -------------------------------------------------------------------------------- /cloudformation/fargate-cluster.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | AWSTemplateFormatVersion: 2010-09-09 16 | Description: > 17 | Distributed load testing (DLT) using AWS Fargate. 18 | Creates a Fargate Cluster, a Task Definition, IAM Role and a CloudWatch Log Group 19 | 20 | Parameters: 21 | VpcId: 22 | Type: String 23 | DockerImage: 24 | Type: String 25 | TaskExecutionRoleArn: 26 | Type: String 27 | DockerTaskMemory: 28 | Type: Number 29 | Default: 2048 30 | DockerTaskCpu: 31 | Type: Number 32 | Default: 512 33 | 34 | Resources: 35 | Cluster: 36 | Type: AWS::ECS::Cluster 37 | 38 | FargateTaskSecurityGroup: 39 | Type: AWS::EC2::SecurityGroup 40 | Properties: 41 | GroupDescription: 'DLT Fargate tasks security group' 42 | VpcId: !Ref VpcId 43 | SecurityGroupEgress: 44 | IpProtocol: '-1' 45 | CidrIp: 0.0.0.0/0 46 | 47 | FargateTaskCloudWatchLogGroup: 48 | Type: AWS::Logs::LogGroup 49 | Properties: 50 | RetentionInDays: 365 51 | 52 | TaurusLogFilterAvgResponseTime: 53 | Type: AWS::Logs::MetricFilter 54 | Properties: 55 | FilterPattern: "[time, logType=INFO*, logTitle=Current*, numVu, vu, numSucc, succ, numFail, fail, avgRt, x]" 56 | LogGroupName: !Ref FargateTaskCloudWatchLogGroup 57 | MetricTransformations: 58 | - 59 | MetricValue: "$avgRt" 60 | MetricNamespace: "dlt-fargate/taurus" 61 | MetricName: "avgResponseTime" 62 | 63 | FargateTaskDefinition: 64 | Type: AWS::ECS::TaskDefinition 65 | Properties: 66 | Cpu: !Ref DockerTaskCpu 67 | ExecutionRoleArn: !Ref TaskExecutionRoleArn 68 | Memory: !Ref DockerTaskMemory 69 | NetworkMode: awsvpc 70 | RequiresCompatibilities: 71 | - FARGATE 72 | TaskRoleArn: !Ref TaskExecutionRoleArn 73 | ContainerDefinitions: 74 | - 75 | Name: "dlt-fargate-task" 76 | Essential: true 77 | Image: !Ref DockerImage 78 | Memory: !Ref DockerTaskMemory 79 | LogConfiguration: 80 | LogDriver: awslogs 81 | Options: 82 | awslogs-group: !Ref FargateTaskCloudWatchLogGroup 83 | awslogs-region: !Ref "AWS::Region" 84 | awslogs-stream-prefix: "dlt-fargate" 85 | Command: 86 | - "taurus.yml" 87 | 88 | 89 | Outputs: 90 | FargateClusterName: 91 | Value: !Ref Cluster 92 | TaskSecurityGroup: 93 | Value: !Ref FargateTaskSecurityGroup 94 | TaskDefinitionArn: 95 | Value: !Ref FargateTaskDefinition -------------------------------------------------------------------------------- /cloudformation/fargate-vpc.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | AWSTemplateFormatVersion: 2010-09-09 16 | Description: > 17 | Distributed Load Testing using AWS Fargate. 18 | Dedicated VPC where the ECS Fargate tasks will be placed 19 | 20 | Parameters: 21 | VpcCidrBlock: 22 | Type: String 23 | Default: 192.168.0.0/16 24 | Description: CIDR block of the new VPC where Fargate will be placed 25 | SubnetACidrBlock: 26 | Type: String 27 | Default: 192.168.0.0/20 28 | Description: CIDR block of subnet A 29 | SubnetBCidrBlock: 30 | Type: String 31 | Default: 192.168.16.0/20 32 | Description: CIDR block of subnet B 33 | SubnetCCidrBlock: 34 | Type: String 35 | Default: 192.168.32.0/20 36 | Description: CIDR block of subnet C 37 | 38 | Mappings: 39 | RegionMap: 40 | us-east-1: 41 | az1: us-east-1a 42 | az2: us-east-1b 43 | az3: us-east-1c 44 | us-east-2: 45 | az1: us-east-2a 46 | az2: us-east-2b 47 | az3: us-east-2c 48 | us-west-2: 49 | az1: us-west-2a 50 | az2: us-west-2b 51 | az3: us-west-2c 52 | eu-west-1: 53 | az1: eu-west-1a 54 | az2: eu-west-1b 55 | az3: eu-west-1c 56 | 57 | Resources: 58 | DLTVpc: 59 | Type: AWS::EC2::VPC 60 | Properties: 61 | CidrBlock: !Ref VpcCidrBlock 62 | InstanceTenancy: default 63 | EnableDnsSupport: true 64 | EnableDnsHostnames: true 65 | Tags: 66 | - Key: Name 67 | Value: dlt-fargate 68 | 69 | PublicSubnetA: 70 | Type: AWS::EC2::Subnet 71 | Properties: 72 | CidrBlock: !Ref SubnetACidrBlock 73 | AvailabilityZone: !FindInMap [RegionMap, !Ref "AWS::Region", "az1"] 74 | VpcId: !Ref DLTVpc 75 | 76 | PublicSubnetB: 77 | Type: AWS::EC2::Subnet 78 | Properties: 79 | CidrBlock: !Ref SubnetBCidrBlock 80 | AvailabilityZone: !FindInMap [RegionMap, !Ref "AWS::Region", "az2"] 81 | VpcId: !Ref DLTVpc 82 | 83 | PublicSubnetC: 84 | Type: AWS::EC2::Subnet 85 | Properties: 86 | CidrBlock: !Ref SubnetCCidrBlock 87 | AvailabilityZone: !FindInMap [RegionMap, !Ref "AWS::Region", "az3"] 88 | VpcId: !Ref DLTVpc 89 | 90 | InternetGateway: 91 | Type: AWS::EC2::InternetGateway 92 | Properties: {} 93 | 94 | MainRouteTable: 95 | Type: AWS::EC2::RouteTable 96 | Properties: 97 | VpcId: !Ref DLTVpc 98 | 99 | GatewayAttachment: 100 | Type: AWS::EC2::VPCGatewayAttachment 101 | Properties: 102 | VpcId: !Ref DLTVpc 103 | InternetGatewayId: !Ref InternetGateway 104 | 105 | RouteToInternet: 106 | Type: AWS::EC2::Route 107 | DependsOn: GatewayAttachment 108 | Properties: 109 | DestinationCidrBlock: 0.0.0.0/0 110 | RouteTableId: !Ref MainRouteTable 111 | GatewayId: !Ref InternetGateway 112 | 113 | RouteTableAssociationA: 114 | Type: AWS::EC2::SubnetRouteTableAssociation 115 | Properties: 116 | RouteTableId: !Ref MainRouteTable 117 | SubnetId: !Ref PublicSubnetA 118 | 119 | RouteTableAssociationB: 120 | Type: AWS::EC2::SubnetRouteTableAssociation 121 | Properties: 122 | RouteTableId: !Ref MainRouteTable 123 | SubnetId: !Ref PublicSubnetB 124 | 125 | RouteTableAssociationC: 126 | Type: AWS::EC2::SubnetRouteTableAssociation 127 | Properties: 128 | RouteTableId: !Ref MainRouteTable 129 | SubnetId: !Ref PublicSubnetC 130 | 131 | 132 | Outputs: 133 | VpcId: 134 | Value: !Ref DLTVpc 135 | SubnetA: 136 | Value: !Ref PublicSubnetA 137 | SubnetB: 138 | Value: !Ref PublicSubnetB 139 | SubnetC: 140 | Value: !Ref PublicSubnetC -------------------------------------------------------------------------------- /cloudformation/master.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | AWSTemplateFormatVersion: 2010-09-09 16 | Description: > 17 | Master Template for Distributed Load Test Using AWS Fargate. 18 | It deploys an ECR Repository, a Fargate Cluster, a VPC, 19 | a CloudWatch Log Group and an IAM Execution Role. 20 | 21 | Parameters: 22 | GitRepositoryName: 23 | Type: String 24 | Default: "distributed-load-testing-using-aws-fargate" 25 | 26 | Resources: 27 | DockerRegistry: 28 | Type: AWS::ECR::Repository 29 | 30 | CloudWatchDashboard: 31 | Type: AWS::CloudWatch::Dashboard 32 | Properties: 33 | DashboardBody: !Sub '{"widgets":[{"type":"metric","x":0,"y":0,"width":8,"height":8,"properties":{"metrics":[["dlt-fargate/taurus","avgResponseTime"]],"view":"timeSeries","stacked":true,"region":"${AWS::Region}","stat":"Average"}}]}' 34 | 35 | TaskExecutionRole: 36 | Type: AWS::IAM::Role 37 | Properties: 38 | AssumeRolePolicyDocument: 39 | Version: "2012-10-17" 40 | Statement: 41 | - Effect: Allow 42 | Action: "sts:AssumeRole" 43 | Principal: 44 | Service: "ecs-tasks.amazonaws.com" 45 | ManagedPolicyArns: 46 | - "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" 47 | 48 | Vpc: 49 | Type: AWS::CloudFormation::Stack 50 | Properties: 51 | TemplateURL: "https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/fargate-vpc.yaml" 52 | 53 | FargateCluster: 54 | Type: AWS::CloudFormation::Stack 55 | DependsOn: Vpc 56 | Properties: 57 | TemplateURL: "https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/fargate-cluster.yaml" 58 | Parameters: 59 | VpcId: !GetAtt Vpc.Outputs.VpcId 60 | TaskExecutionRoleArn: !GetAtt TaskExecutionRole.Arn 61 | DockerImage: !Join 62 | - '' 63 | - - !Ref 'AWS::AccountId' 64 | - '.dkr.ecr.' 65 | - !Ref 'AWS::Region' 66 | - '.amazonaws.com/' 67 | - !Ref DockerRegistry 68 | - ':latest' 69 | 70 | Pipeline: 71 | Type: AWS::CloudFormation::Stack 72 | DependsOn: Vpc 73 | Properties: 74 | TemplateURL: "https://s3.amazonaws.com/distributed-load-testing-using-aws-fargate/templates/pipeline.yaml" 75 | Parameters: 76 | DockerRegistryArn: !GetAtt DockerRegistry.Arn 77 | MasterStackId: !Ref 'AWS::StackName' 78 | GitRepositoryName: !Ref GitRepositoryName 79 | DockerRegistryURL: !Join 80 | - '' 81 | - - !Ref 'AWS::AccountId' 82 | - '.dkr.ecr.' 83 | - !Ref 'AWS::Region' 84 | - '.amazonaws.com/' 85 | - !Ref DockerRegistry 86 | 87 | Outputs: 88 | GitRepoHttpUrl: 89 | Value: !GetAtt Pipeline.Outputs.GitRepoHttpUrl 90 | DockerRegistryName: 91 | Value: !Ref DockerRegistry 92 | DockerRegistryURL: 93 | Value: !Join 94 | - '' 95 | - - !Ref 'AWS::AccountId' 96 | - '.dkr.ecr.' 97 | - !Ref 'AWS::Region' 98 | - '.amazonaws.com/' 99 | - !Ref DockerRegistry 100 | TaskExecutionRoleArn: 101 | Value: !GetAtt TaskExecutionRole.Arn 102 | FargateClusterName: 103 | Value: !GetAtt FargateCluster.Outputs.FargateClusterName 104 | TaskSecurityGroup: 105 | Value: !GetAtt FargateCluster.Outputs.TaskSecurityGroup 106 | TaskDefinitionArn: 107 | Value: !GetAtt FargateCluster.Outputs.TaskDefinitionArn 108 | VpcId: 109 | Value: !GetAtt Vpc.Outputs.VpcId 110 | SubnetA: 111 | Value: !GetAtt Vpc.Outputs.SubnetA 112 | SubnetB: 113 | Value: !GetAtt Vpc.Outputs.SubnetB 114 | SubnetC: 115 | Value: !GetAtt Vpc.Outputs.SubnetC 116 | -------------------------------------------------------------------------------- /cloudformation/pipeline.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | AWSTemplateFormatVersion: 2010-09-09 16 | Description: > 17 | Deployment pipeline for Distributed Load Test Using AWS Fargate. 18 | It creates a CodeBuild project used to configure and run a load test. 19 | 20 | Parameters: 21 | GitRepositoryName: 22 | Type: String 23 | DockerRegistryURL: 24 | Type: String 25 | DockerRegistryArn: 26 | Type: String 27 | ContainersPerRegion: 28 | Type: Number 29 | Default: 3 30 | MasterStackId: 31 | Type: String 32 | 33 | Resources: 34 | CodeRepository: 35 | Type: AWS::CodeCommit::Repository 36 | Properties: 37 | RepositoryDescription: "Distributed load testing using AWS Fargate" 38 | RepositoryName: !Ref GitRepositoryName 39 | 40 | ArtifactStoreBucket: 41 | Type: AWS::S3::Bucket 42 | Properties: 43 | VersioningConfiguration: 44 | Status: Enabled 45 | 46 | # Builds, tags and pushes the docker image 47 | # into the ECR Registry. 48 | CodeBuild: 49 | Type: AWS::CodeBuild::Project 50 | Properties: 51 | Description: Builds distributed load testing suite 52 | TimeoutInMinutes: 20 53 | ServiceRole: !GetAtt CodeBuildRole.Arn 54 | Artifacts: 55 | Type: CODEPIPELINE 56 | Environment: 57 | Type: LINUX_CONTAINER 58 | ComputeType: BUILD_GENERAL1_MEDIUM 59 | Image: "aws/codebuild/docker:18.09.0" 60 | EnvironmentVariables: 61 | - 62 | Name: DOCKER_REGISTRY_URL 63 | Value: !Ref DockerRegistryURL 64 | Source: 65 | Type: CODEPIPELINE 66 | BuildSpec: !Sub | 67 | version: 0.2 68 | phases: 69 | pre_build: 70 | commands: 71 | - echo $DOCKER_REGISTRY_URL 72 | - echo $CODEBUILD_RESOLVED_SOURCE_VERSION 73 | - aws --version 74 | - $(aws ecr get-login --region ${AWS::Region} --no-include-email) 75 | build: 76 | commands: 77 | - docker build -t $DOCKER_REGISTRY_URL:latest . 78 | - docker tag $DOCKER_REGISTRY_URL:latest $DOCKER_REGISTRY_URL:$CODEBUILD_RESOLVED_SOURCE_VERSION 79 | post_build: 80 | commands: 81 | - docker push $DOCKER_REGISTRY_URL:latest 82 | - docker push $DOCKER_REGISTRY_URL:$CODEBUILD_RESOLVED_SOURCE_VERSION 83 | 84 | # CodeBuild project that runs the runner.py python script 85 | # to start the load tests. The script will schedule the 86 | # execution of Fargate tasks into the different regions. 87 | LoadTestRunner: 88 | Type: AWS::CodeBuild::Project 89 | Properties: 90 | Description: Runs the load tests in Fargate 91 | ServiceRole: !GetAtt CodeBuildRole.Arn 92 | Artifacts: 93 | Type: CODEPIPELINE 94 | Environment: 95 | Type: LINUX_CONTAINER 96 | ComputeType: BUILD_GENERAL1_SMALL 97 | Image: "aws/codebuild/python:3.6.5" 98 | EnvironmentVariables: 99 | - 100 | Name: "TASK_COUNT" 101 | Value: !Ref ContainersPerRegion 102 | - 103 | Name: "REGION_1" 104 | Value: !Ref 'AWS::Region' 105 | - 106 | Name: "REGION_1_STACK_NAME" 107 | Value: !Ref MasterStackId 108 | Source: 109 | Type: CODEPIPELINE 110 | BuildSpec: !Sub | 111 | version: 0.2 112 | phases: 113 | build: 114 | commands: 115 | - cd bin 116 | - python runner.py 117 | 118 | CodePipeline: 119 | Type: AWS::CodePipeline::Pipeline 120 | DependsOn: BuildAndPipelinePolicy 121 | Properties: 122 | RoleArn: !GetAtt CodePipelineRole.Arn 123 | ArtifactStore: 124 | Type: S3 125 | Location: !Ref ArtifactStoreBucket 126 | Stages: 127 | - 128 | Name: Source 129 | Actions: 130 | - 131 | Name: Source 132 | ActionTypeId: 133 | Category: Source 134 | Provider: CodeCommit 135 | Owner: AWS 136 | Version: 1 137 | OutputArtifacts: 138 | - Name: SourceOutput 139 | Configuration: 140 | RepositoryName: !GetAtt CodeRepository.Name 141 | BranchName: 'master' 142 | 143 | - 144 | Name: Build 145 | Actions: 146 | - 147 | Name: Build 148 | ActionTypeId: 149 | Category: Build 150 | Owner: AWS 151 | Version: 1 152 | Provider: CodeBuild 153 | InputArtifacts: 154 | - Name: SourceOutput 155 | OutputArtifacts: 156 | - Name: BuildOutput 157 | Configuration: 158 | ProjectName: 159 | Ref: CodeBuild 160 | 161 | - 162 | Name: LoadTest 163 | Actions: 164 | - Name: Runner 165 | ActionTypeId: 166 | Category: Build 167 | Owner: AWS 168 | Version: 1 169 | Provider: CodeBuild 170 | InputArtifacts: 171 | - Name: SourceOutput 172 | Configuration: 173 | ProjectName: 174 | Ref: LoadTestRunner 175 | 176 | # Shared IAM policy for CodePipeline and CodeBuild projects for simplicity. 177 | # We could be more strict and create a separate role for each build 178 | # project and another one for the pipeline. 179 | BuildAndPipelinePolicy: 180 | Type: AWS::IAM::Policy 181 | Properties: 182 | PolicyName: "distributed-load-testing-using-aws-fargate" 183 | Roles: 184 | - !Ref CodeBuildRole 185 | - !Ref CodePipelineRole 186 | PolicyDocument: 187 | Version: 2012-10-17 188 | Statement: 189 | - Effect: Allow 190 | Resource: 191 | - !GetAtt ArtifactStoreBucket.Arn 192 | - !Join 193 | - '' 194 | - - !GetAtt ArtifactStoreBucket.Arn 195 | - '/*' 196 | Action: 197 | - "s3:*" 198 | - Effect: Allow 199 | Resource: !GetAtt CodeRepository.Arn 200 | Action: 201 | - "codecommit:GetBranch" 202 | - "codecommit:GetCommit" 203 | - "codecommit:UploadArchive" 204 | - "codecommit:GetUploadArchiveStatus" 205 | - "codecommit:CancelUploadArchive" 206 | - Effect: Allow 207 | Resource: !Ref DockerRegistryArn 208 | Action: 209 | - "ecr:DescribeImages" 210 | - "ecr:PutImage" 211 | - "ecr:UploadLayerPart" 212 | - "ecr:CompleteLayerUpload" 213 | - "ecr:InitiateLayerUpload" 214 | - "ecr:GetDownloadUrlForLayer" 215 | - "ecr:ListImages" 216 | - "ecr:BatchCheckLayerAvailability" 217 | - "ecr:GetRepositoryPolicy" 218 | - Effect: Allow 219 | Resource: "*" 220 | Action: 221 | - "codebuild:StartBuild" 222 | - "codebuild:StopBuild" 223 | - "codebuild:BatchGetBuilds" 224 | - "logs:CreateLogStream" 225 | - "logs:CreateLogGroup" 226 | - "logs:PutLogEvents" 227 | - "ecr:GetAuthorizationToken" 228 | - "cloudformation:DescribeStacks" 229 | - "ecs:RunTask" 230 | - "iam:PassRole" 231 | 232 | CodeBuildRole: 233 | Type: AWS::IAM::Role 234 | Properties: 235 | AssumeRolePolicyDocument: 236 | Version: 2012-10-17 237 | Statement: 238 | - 239 | Effect: Allow 240 | Principal: 241 | Service: 242 | - codebuild.amazonaws.com 243 | Action: 244 | - sts:AssumeRole 245 | Path: "/" 246 | 247 | CodePipelineRole: 248 | Type: AWS::IAM::Role 249 | Properties: 250 | AssumeRolePolicyDocument: 251 | Version: 2012-10-17 252 | Statement: 253 | - Effect: Allow 254 | Principal: 255 | Service: 256 | - codepipeline.amazonaws.com 257 | Action: 258 | - sts:AssumeRole 259 | Path: "/" 260 | 261 | Outputs: 262 | GitRepoHttpUrl: 263 | Value: !GetAtt CodeRepository.CloneUrlHttp 264 | GitRepoSshUrl: 265 | Value: !GetAtt CodeRepository.CloneUrlSsh 266 | -------------------------------------------------------------------------------- /docs/add-region-params.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/add-region-params.png -------------------------------------------------------------------------------- /docs/add-region.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/add-region.gif -------------------------------------------------------------------------------- /docs/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/arch.png -------------------------------------------------------------------------------- /docs/cfn-outputs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/cfn-outputs.png -------------------------------------------------------------------------------- /docs/cloudwatch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/cloudwatch.jpg -------------------------------------------------------------------------------- /docs/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/dashboard.png -------------------------------------------------------------------------------- /docs/elasticsearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/elasticsearch.png -------------------------------------------------------------------------------- /docs/fargate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/fargate.png -------------------------------------------------------------------------------- /docs/master-outputs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/master-outputs.png -------------------------------------------------------------------------------- /docs/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/distributed-load-testing-using-aws-fargate/b4a7032d59ac15e123567565d896e2373f45dce9/docs/pipeline.png -------------------------------------------------------------------------------- /examples/elasticsearch/README.md: -------------------------------------------------------------------------------- 1 | ## Load Testing an Amazon Elasticsearch Cluster 2 | 3 | To start, follow the instructions in the main [README](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/blob/master/README.md) 4 | and do the following changes: 5 | 6 | ### Modify the Dockerfile 7 | Open the [Dockerfile](https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/blob/master/Dockerfile) 8 | in the root directory of the project and uncomment the elasticsearch instruction and comment out the http one. It should 9 | look like this: 10 | 11 | ```Dockerfile 12 | # ADD examples/http /bzt-configs/ 13 | ADD examples/elasticsearch /bzt-configs/ 14 | ``` 15 | 16 | Then add an environment variable to the TestRunner step in the CodePipeline to specify your Elasticsearch cluster URL. 17 | The environment variable name should be `ENDPOINT_UNDER_TEST` and it's value should be the http endpoint of the cluster. 18 | If you open the runner.py script under the `bin` folder. You will see how the script is using the environment variable. 19 | 20 | ### Modify Test Scenarios 21 | 22 | I have written a `consumer.test.js` and a `producer.test.js` scenarios for demonstration 23 | purposes under the `examples/elasticsearch` folder, but you can edit them to fit your needs. In this example, 24 | the producer will create random JSON documents to be indexed in the cluster, while the consumer will issue *search* 25 | requests of randomly generated words. If you look at the `taurus.yml` file, you can see both scenarios specified, 26 | which means that Taurus will execute both scripts in parallel. 27 | 28 | ### Testing a Private Elasticsearch Cluster 29 | 30 | If the Elasticsearch is private, meaning that it's endpoint is not accessible from the internet. Then head to the 31 | `v2.0-beta` version of this project: https://github.com/aws-samples/distributed-load-testing-using-aws-fargate/releases/tag/v0.2-beta 32 | and use that code base. The current one is no longer compatible for private connectivity as the Fargate clusters 33 | get created in it's own VPC. 34 | -------------------------------------------------------------------------------- /examples/elasticsearch/consumer.test.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | * software and associated documentation files (the "Software"), to deal in the Software 5 | * without restriction, including without limitation the rights to use, copy, modify, 6 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | * permit persons to whom the Software is furnished to do so. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | const elasticsearch = require('./es-client'); 17 | const ChanceJs = require('chance'); 18 | const chance = new ChanceJs(); 19 | 20 | describe('Elasticsearch Document Consumer', () => { 21 | it('searches documents based on random text', () => { 22 | return elasticsearch.client.search({ 23 | index: elasticsearch.index, 24 | q: 'description:'.concat(chance.word()), 25 | }); 26 | }); 27 | }); -------------------------------------------------------------------------------- /examples/elasticsearch/es-client.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | * software and associated documentation files (the "Software"), to deal in the Software 5 | * without restriction, including without limitation the rights to use, copy, modify, 6 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | * permit persons to whom the Software is furnished to do so. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | const elasticsearch = require('elasticsearch'); 17 | const awsElasticSearch = require('http-aws-es'); 18 | 19 | const elasticSearchUrl = process.env.ENDPOINT_UNDER_TEST; 20 | const index = 'performance-testing'; 21 | const client = new elasticsearch.Client({ 22 | hosts: [elasticSearchUrl], 23 | connectionClass: awsElasticSearch, 24 | apiVersion: "6.3", 25 | }); 26 | 27 | module.exports.index = index; 28 | module.exports.client = client; -------------------------------------------------------------------------------- /examples/elasticsearch/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elasticsearch-test-suite", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "agentkeepalive": { 8 | "version": "3.5.2", 9 | "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", 10 | "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", 11 | "requires": { 12 | "humanize-ms": "^1.2.1" 13 | } 14 | }, 15 | "ansi-colors": { 16 | "version": "3.2.3", 17 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", 18 | "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" 19 | }, 20 | "ansi-regex": { 21 | "version": "2.1.1", 22 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 23 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 24 | }, 25 | "ansi-styles": { 26 | "version": "2.2.1", 27 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 28 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 29 | }, 30 | "argparse": { 31 | "version": "1.0.10", 32 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 33 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 34 | "requires": { 35 | "sprintf-js": "~1.0.2" 36 | } 37 | }, 38 | "aws-sdk": { 39 | "version": "2.348.0", 40 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.348.0.tgz", 41 | "integrity": "sha512-TfguapuOAwk7EG8zhYJPjkCaF4tyGjfgcXLkYbWbuS4O6E8pn0x2K5Yt1KXwLiWxG0fzKCLiiaNA5H7bKAP4YQ==", 42 | "requires": { 43 | "buffer": "4.9.1", 44 | "events": "1.1.1", 45 | "ieee754": "1.1.8", 46 | "jmespath": "0.15.0", 47 | "querystring": "0.2.0", 48 | "sax": "1.2.1", 49 | "url": "0.10.3", 50 | "uuid": "3.1.0", 51 | "xml2js": "0.4.19" 52 | } 53 | }, 54 | "balanced-match": { 55 | "version": "1.0.0", 56 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 57 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 58 | }, 59 | "base64-js": { 60 | "version": "1.3.0", 61 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", 62 | "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" 63 | }, 64 | "brace-expansion": { 65 | "version": "1.1.11", 66 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 67 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 68 | "requires": { 69 | "balanced-match": "^1.0.0", 70 | "concat-map": "0.0.1" 71 | } 72 | }, 73 | "browser-stdout": { 74 | "version": "1.3.1", 75 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 76 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" 77 | }, 78 | "buffer": { 79 | "version": "4.9.1", 80 | "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", 81 | "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", 82 | "requires": { 83 | "base64-js": "^1.0.2", 84 | "ieee754": "^1.1.4", 85 | "isarray": "^1.0.0" 86 | } 87 | }, 88 | "camelcase": { 89 | "version": "5.3.1", 90 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 91 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 92 | }, 93 | "chalk": { 94 | "version": "1.1.3", 95 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 96 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 97 | "requires": { 98 | "ansi-styles": "^2.2.1", 99 | "escape-string-regexp": "^1.0.2", 100 | "has-ansi": "^2.0.0", 101 | "strip-ansi": "^3.0.0", 102 | "supports-color": "^2.0.0" 103 | } 104 | }, 105 | "chance": { 106 | "version": "1.0.16", 107 | "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.16.tgz", 108 | "integrity": "sha512-2bgDHH5bVfAXH05SPtjqrsASzZ7h90yCuYT2z4mkYpxxYvJXiIydBFzVieVHZx7wLH1Ag2Azaaej2/zA1XUrNQ==" 109 | }, 110 | "cliui": { 111 | "version": "5.0.0", 112 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 113 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 114 | "requires": { 115 | "string-width": "^3.1.0", 116 | "strip-ansi": "^5.2.0", 117 | "wrap-ansi": "^5.1.0" 118 | }, 119 | "dependencies": { 120 | "ansi-regex": { 121 | "version": "4.1.0", 122 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 123 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 124 | }, 125 | "string-width": { 126 | "version": "3.1.0", 127 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 128 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 129 | "requires": { 130 | "emoji-regex": "^7.0.1", 131 | "is-fullwidth-code-point": "^2.0.0", 132 | "strip-ansi": "^5.1.0" 133 | } 134 | }, 135 | "strip-ansi": { 136 | "version": "5.2.0", 137 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 138 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 139 | "requires": { 140 | "ansi-regex": "^4.1.0" 141 | } 142 | } 143 | } 144 | }, 145 | "color-convert": { 146 | "version": "1.9.3", 147 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 148 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 149 | "requires": { 150 | "color-name": "1.1.3" 151 | } 152 | }, 153 | "color-name": { 154 | "version": "1.1.3", 155 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 156 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 157 | }, 158 | "concat-map": { 159 | "version": "0.0.1", 160 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 161 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 162 | }, 163 | "debug": { 164 | "version": "3.2.6", 165 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 166 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 167 | "requires": { 168 | "ms": "^2.1.1" 169 | } 170 | }, 171 | "decamelize": { 172 | "version": "1.2.0", 173 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 174 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 175 | }, 176 | "define-properties": { 177 | "version": "1.1.3", 178 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 179 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 180 | "requires": { 181 | "object-keys": "^1.0.12" 182 | } 183 | }, 184 | "diff": { 185 | "version": "3.5.0", 186 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 187 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" 188 | }, 189 | "elasticsearch": { 190 | "version": "15.2.0", 191 | "resolved": "https://registry.npmjs.org/elasticsearch/-/elasticsearch-15.2.0.tgz", 192 | "integrity": "sha512-jOFcBoEh3Sn3gjUTozInODZTLriJtfppAUC7jnQCUE+OUj8o7GoAyC+L4h/L3ZxmXNFbQCunqVR+nmSofHdo9A==", 193 | "requires": { 194 | "agentkeepalive": "^3.4.1", 195 | "chalk": "^1.0.0", 196 | "lodash": "^4.17.10" 197 | } 198 | }, 199 | "emoji-regex": { 200 | "version": "7.0.3", 201 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 202 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" 203 | }, 204 | "es-abstract": { 205 | "version": "1.17.6", 206 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", 207 | "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", 208 | "requires": { 209 | "es-to-primitive": "^1.2.1", 210 | "function-bind": "^1.1.1", 211 | "has": "^1.0.3", 212 | "has-symbols": "^1.0.1", 213 | "is-callable": "^1.2.0", 214 | "is-regex": "^1.1.0", 215 | "object-inspect": "^1.7.0", 216 | "object-keys": "^1.1.1", 217 | "object.assign": "^4.1.0", 218 | "string.prototype.trimend": "^1.0.1", 219 | "string.prototype.trimstart": "^1.0.1" 220 | } 221 | }, 222 | "es-to-primitive": { 223 | "version": "1.2.1", 224 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 225 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 226 | "requires": { 227 | "is-callable": "^1.1.4", 228 | "is-date-object": "^1.0.1", 229 | "is-symbol": "^1.0.2" 230 | } 231 | }, 232 | "escape-string-regexp": { 233 | "version": "1.0.5", 234 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 235 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 236 | }, 237 | "esprima": { 238 | "version": "4.0.1", 239 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 240 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 241 | }, 242 | "events": { 243 | "version": "1.1.1", 244 | "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", 245 | "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" 246 | }, 247 | "find-up": { 248 | "version": "3.0.0", 249 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 250 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 251 | "requires": { 252 | "locate-path": "^3.0.0" 253 | } 254 | }, 255 | "flat": { 256 | "version": "4.1.0", 257 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 258 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 259 | "requires": { 260 | "is-buffer": "~2.0.3" 261 | } 262 | }, 263 | "fs.realpath": { 264 | "version": "1.0.0", 265 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 266 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 267 | }, 268 | "function-bind": { 269 | "version": "1.1.1", 270 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 271 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 272 | }, 273 | "get-caller-file": { 274 | "version": "2.0.5", 275 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 276 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 277 | }, 278 | "glob": { 279 | "version": "7.1.3", 280 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 281 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 282 | "requires": { 283 | "fs.realpath": "^1.0.0", 284 | "inflight": "^1.0.4", 285 | "inherits": "2", 286 | "minimatch": "^3.0.4", 287 | "once": "^1.3.0", 288 | "path-is-absolute": "^1.0.0" 289 | } 290 | }, 291 | "growl": { 292 | "version": "1.10.5", 293 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 294 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" 295 | }, 296 | "has": { 297 | "version": "1.0.3", 298 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 299 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 300 | "requires": { 301 | "function-bind": "^1.1.1" 302 | } 303 | }, 304 | "has-ansi": { 305 | "version": "2.0.0", 306 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 307 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 308 | "requires": { 309 | "ansi-regex": "^2.0.0" 310 | } 311 | }, 312 | "has-flag": { 313 | "version": "3.0.0", 314 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 315 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 316 | }, 317 | "has-symbols": { 318 | "version": "1.0.1", 319 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 320 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" 321 | }, 322 | "he": { 323 | "version": "1.2.0", 324 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 325 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" 326 | }, 327 | "http-aws-es": { 328 | "version": "6.0.0", 329 | "resolved": "https://registry.npmjs.org/http-aws-es/-/http-aws-es-6.0.0.tgz", 330 | "integrity": "sha512-g+qp7J110/m4aHrR3iit4akAlnW0UljZ6oTq/rCcbsI8KP9x+95vqUtx49M2XQ2JMpwJio3B6gDYx+E8WDxqiA==" 331 | }, 332 | "humanize-ms": { 333 | "version": "1.2.1", 334 | "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", 335 | "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", 336 | "requires": { 337 | "ms": "^2.0.0" 338 | } 339 | }, 340 | "ieee754": { 341 | "version": "1.1.8", 342 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", 343 | "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" 344 | }, 345 | "inflight": { 346 | "version": "1.0.6", 347 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 348 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 349 | "requires": { 350 | "once": "^1.3.0", 351 | "wrappy": "1" 352 | } 353 | }, 354 | "inherits": { 355 | "version": "2.0.4", 356 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 357 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 358 | }, 359 | "is-buffer": { 360 | "version": "2.0.4", 361 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 362 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" 363 | }, 364 | "is-callable": { 365 | "version": "1.2.0", 366 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", 367 | "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" 368 | }, 369 | "is-date-object": { 370 | "version": "1.0.2", 371 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 372 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" 373 | }, 374 | "is-fullwidth-code-point": { 375 | "version": "2.0.0", 376 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 377 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 378 | }, 379 | "is-regex": { 380 | "version": "1.1.0", 381 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", 382 | "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", 383 | "requires": { 384 | "has-symbols": "^1.0.1" 385 | } 386 | }, 387 | "is-symbol": { 388 | "version": "1.0.3", 389 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 390 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 391 | "requires": { 392 | "has-symbols": "^1.0.1" 393 | } 394 | }, 395 | "isarray": { 396 | "version": "1.0.0", 397 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 398 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 399 | }, 400 | "isexe": { 401 | "version": "2.0.0", 402 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 403 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 404 | }, 405 | "jmespath": { 406 | "version": "0.15.0", 407 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", 408 | "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" 409 | }, 410 | "js-yaml": { 411 | "version": "3.13.1", 412 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 413 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 414 | "requires": { 415 | "argparse": "^1.0.7", 416 | "esprima": "^4.0.0" 417 | } 418 | }, 419 | "locate-path": { 420 | "version": "3.0.0", 421 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 422 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 423 | "requires": { 424 | "p-locate": "^3.0.0", 425 | "path-exists": "^3.0.0" 426 | } 427 | }, 428 | "lodash": { 429 | "version": "4.17.21", 430 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 431 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 432 | }, 433 | "log-symbols": { 434 | "version": "2.2.0", 435 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", 436 | "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", 437 | "requires": { 438 | "chalk": "^2.0.1" 439 | }, 440 | "dependencies": { 441 | "ansi-styles": { 442 | "version": "3.2.1", 443 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 444 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 445 | "requires": { 446 | "color-convert": "^1.9.0" 447 | } 448 | }, 449 | "chalk": { 450 | "version": "2.4.2", 451 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 452 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 453 | "requires": { 454 | "ansi-styles": "^3.2.1", 455 | "escape-string-regexp": "^1.0.5", 456 | "supports-color": "^5.3.0" 457 | } 458 | }, 459 | "supports-color": { 460 | "version": "5.5.0", 461 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 462 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 463 | "requires": { 464 | "has-flag": "^3.0.0" 465 | } 466 | } 467 | } 468 | }, 469 | "minimatch": { 470 | "version": "3.0.4", 471 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 472 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 473 | "requires": { 474 | "brace-expansion": "^1.1.7" 475 | } 476 | }, 477 | "minimist": { 478 | "version": "1.2.5", 479 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 480 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 481 | }, 482 | "mkdirp": { 483 | "version": "0.5.4", 484 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", 485 | "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", 486 | "requires": { 487 | "minimist": "^1.2.5" 488 | } 489 | }, 490 | "mocha": { 491 | "version": "6.2.3", 492 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", 493 | "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", 494 | "requires": { 495 | "ansi-colors": "3.2.3", 496 | "browser-stdout": "1.3.1", 497 | "debug": "3.2.6", 498 | "diff": "3.5.0", 499 | "escape-string-regexp": "1.0.5", 500 | "find-up": "3.0.0", 501 | "glob": "7.1.3", 502 | "growl": "1.10.5", 503 | "he": "1.2.0", 504 | "js-yaml": "3.13.1", 505 | "log-symbols": "2.2.0", 506 | "minimatch": "3.0.4", 507 | "mkdirp": "0.5.4", 508 | "ms": "2.1.1", 509 | "node-environment-flags": "1.0.5", 510 | "object.assign": "4.1.0", 511 | "strip-json-comments": "2.0.1", 512 | "supports-color": "6.0.0", 513 | "which": "1.3.1", 514 | "wide-align": "1.1.3", 515 | "yargs": "13.3.2", 516 | "yargs-parser": "13.1.2", 517 | "yargs-unparser": "1.6.0" 518 | }, 519 | "dependencies": { 520 | "supports-color": { 521 | "version": "6.0.0", 522 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", 523 | "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", 524 | "requires": { 525 | "has-flag": "^3.0.0" 526 | } 527 | } 528 | } 529 | }, 530 | "ms": { 531 | "version": "2.1.1", 532 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 533 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 534 | }, 535 | "node-environment-flags": { 536 | "version": "1.0.5", 537 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", 538 | "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", 539 | "requires": { 540 | "object.getownpropertydescriptors": "^2.0.3", 541 | "semver": "^5.7.0" 542 | } 543 | }, 544 | "object-inspect": { 545 | "version": "1.7.0", 546 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 547 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" 548 | }, 549 | "object-keys": { 550 | "version": "1.1.1", 551 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 552 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 553 | }, 554 | "object.assign": { 555 | "version": "4.1.0", 556 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 557 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 558 | "requires": { 559 | "define-properties": "^1.1.2", 560 | "function-bind": "^1.1.1", 561 | "has-symbols": "^1.0.0", 562 | "object-keys": "^1.0.11" 563 | } 564 | }, 565 | "object.getownpropertydescriptors": { 566 | "version": "2.1.0", 567 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", 568 | "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", 569 | "requires": { 570 | "define-properties": "^1.1.3", 571 | "es-abstract": "^1.17.0-next.1" 572 | } 573 | }, 574 | "once": { 575 | "version": "1.4.0", 576 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 577 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 578 | "requires": { 579 | "wrappy": "1" 580 | } 581 | }, 582 | "p-limit": { 583 | "version": "2.3.0", 584 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 585 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 586 | "requires": { 587 | "p-try": "^2.0.0" 588 | } 589 | }, 590 | "p-locate": { 591 | "version": "3.0.0", 592 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 593 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 594 | "requires": { 595 | "p-limit": "^2.0.0" 596 | } 597 | }, 598 | "p-try": { 599 | "version": "2.2.0", 600 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 601 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 602 | }, 603 | "path-exists": { 604 | "version": "3.0.0", 605 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 606 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" 607 | }, 608 | "path-is-absolute": { 609 | "version": "1.0.1", 610 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 611 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 612 | }, 613 | "punycode": { 614 | "version": "1.3.2", 615 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 616 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 617 | }, 618 | "querystring": { 619 | "version": "0.2.0", 620 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 621 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 622 | }, 623 | "require-directory": { 624 | "version": "2.1.1", 625 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 626 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 627 | }, 628 | "require-main-filename": { 629 | "version": "2.0.0", 630 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 631 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" 632 | }, 633 | "sax": { 634 | "version": "1.2.1", 635 | "resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 636 | "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" 637 | }, 638 | "semver": { 639 | "version": "5.7.1", 640 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 641 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 642 | }, 643 | "set-blocking": { 644 | "version": "2.0.0", 645 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 646 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 647 | }, 648 | "sprintf-js": { 649 | "version": "1.0.3", 650 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 651 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 652 | }, 653 | "string-width": { 654 | "version": "2.1.1", 655 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 656 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 657 | "requires": { 658 | "is-fullwidth-code-point": "^2.0.0", 659 | "strip-ansi": "^4.0.0" 660 | }, 661 | "dependencies": { 662 | "ansi-regex": { 663 | "version": "3.0.0", 664 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 665 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 666 | }, 667 | "strip-ansi": { 668 | "version": "4.0.0", 669 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 670 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 671 | "requires": { 672 | "ansi-regex": "^3.0.0" 673 | } 674 | } 675 | } 676 | }, 677 | "string.prototype.trimend": { 678 | "version": "1.0.1", 679 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", 680 | "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", 681 | "requires": { 682 | "define-properties": "^1.1.3", 683 | "es-abstract": "^1.17.5" 684 | } 685 | }, 686 | "string.prototype.trimstart": { 687 | "version": "1.0.1", 688 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", 689 | "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", 690 | "requires": { 691 | "define-properties": "^1.1.3", 692 | "es-abstract": "^1.17.5" 693 | } 694 | }, 695 | "strip-ansi": { 696 | "version": "3.0.1", 697 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 698 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 699 | "requires": { 700 | "ansi-regex": "^2.0.0" 701 | } 702 | }, 703 | "strip-json-comments": { 704 | "version": "2.0.1", 705 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 706 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" 707 | }, 708 | "supports-color": { 709 | "version": "2.0.0", 710 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 711 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 712 | }, 713 | "url": { 714 | "version": "0.10.3", 715 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 716 | "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", 717 | "requires": { 718 | "punycode": "1.3.2", 719 | "querystring": "0.2.0" 720 | } 721 | }, 722 | "uuid": { 723 | "version": "3.1.0", 724 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 725 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" 726 | }, 727 | "which": { 728 | "version": "1.3.1", 729 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 730 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 731 | "requires": { 732 | "isexe": "^2.0.0" 733 | } 734 | }, 735 | "which-module": { 736 | "version": "2.0.0", 737 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 738 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" 739 | }, 740 | "wide-align": { 741 | "version": "1.1.3", 742 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 743 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 744 | "requires": { 745 | "string-width": "^1.0.2 || 2" 746 | } 747 | }, 748 | "wrap-ansi": { 749 | "version": "5.1.0", 750 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 751 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 752 | "requires": { 753 | "ansi-styles": "^3.2.0", 754 | "string-width": "^3.0.0", 755 | "strip-ansi": "^5.0.0" 756 | }, 757 | "dependencies": { 758 | "ansi-regex": { 759 | "version": "4.1.0", 760 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 761 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 762 | }, 763 | "ansi-styles": { 764 | "version": "3.2.1", 765 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 766 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 767 | "requires": { 768 | "color-convert": "^1.9.0" 769 | } 770 | }, 771 | "string-width": { 772 | "version": "3.1.0", 773 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 774 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 775 | "requires": { 776 | "emoji-regex": "^7.0.1", 777 | "is-fullwidth-code-point": "^2.0.0", 778 | "strip-ansi": "^5.1.0" 779 | } 780 | }, 781 | "strip-ansi": { 782 | "version": "5.2.0", 783 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 784 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 785 | "requires": { 786 | "ansi-regex": "^4.1.0" 787 | } 788 | } 789 | } 790 | }, 791 | "wrappy": { 792 | "version": "1.0.2", 793 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 794 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 795 | }, 796 | "xml2js": { 797 | "version": "0.4.19", 798 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 799 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 800 | "requires": { 801 | "sax": ">=0.6.0", 802 | "xmlbuilder": "~9.0.1" 803 | } 804 | }, 805 | "xmlbuilder": { 806 | "version": "9.0.7", 807 | "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 808 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 809 | }, 810 | "y18n": { 811 | "version": "4.0.1", 812 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 813 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" 814 | }, 815 | "yargs": { 816 | "version": "13.3.2", 817 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 818 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 819 | "requires": { 820 | "cliui": "^5.0.0", 821 | "find-up": "^3.0.0", 822 | "get-caller-file": "^2.0.1", 823 | "require-directory": "^2.1.1", 824 | "require-main-filename": "^2.0.0", 825 | "set-blocking": "^2.0.0", 826 | "string-width": "^3.0.0", 827 | "which-module": "^2.0.0", 828 | "y18n": "^4.0.0", 829 | "yargs-parser": "^13.1.2" 830 | }, 831 | "dependencies": { 832 | "ansi-regex": { 833 | "version": "4.1.0", 834 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 835 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" 836 | }, 837 | "string-width": { 838 | "version": "3.1.0", 839 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 840 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 841 | "requires": { 842 | "emoji-regex": "^7.0.1", 843 | "is-fullwidth-code-point": "^2.0.0", 844 | "strip-ansi": "^5.1.0" 845 | } 846 | }, 847 | "strip-ansi": { 848 | "version": "5.2.0", 849 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 850 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 851 | "requires": { 852 | "ansi-regex": "^4.1.0" 853 | } 854 | } 855 | } 856 | }, 857 | "yargs-parser": { 858 | "version": "13.1.2", 859 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 860 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 861 | "requires": { 862 | "camelcase": "^5.0.0", 863 | "decamelize": "^1.2.0" 864 | } 865 | }, 866 | "yargs-unparser": { 867 | "version": "1.6.0", 868 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", 869 | "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", 870 | "requires": { 871 | "flat": "^4.1.0", 872 | "lodash": "^4.17.15", 873 | "yargs": "^13.3.0" 874 | } 875 | } 876 | } 877 | } 878 | -------------------------------------------------------------------------------- /examples/elasticsearch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elasticsearch-test-suite", 3 | "version": "1.0.0", 4 | "description": "Example of load testing an Amazon Elasticsearch cluster", 5 | "main": "producer.test.js", 6 | "dependencies": { 7 | "aws-sdk": "^2.348.0", 8 | "chance": "^1.0.16", 9 | "elasticsearch": "^15.2.0", 10 | "http-aws-es": "^6.0.0", 11 | "mocha": "^6.0.0" 12 | }, 13 | "devDependencies": {}, 14 | "scripts": { 15 | "test": "mocha ." 16 | }, 17 | "author": "Fernando Dingler", 18 | "license": "MIT-0", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/aws-samples/distributed-load-testing-using-aws-fargate" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/elasticsearch/producer.test.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | * software and associated documentation files (the "Software"), to deal in the Software 5 | * without restriction, including without limitation the rights to use, copy, modify, 6 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | * permit persons to whom the Software is furnished to do so. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | const ChanceJs = require('chance'); 17 | const elasticsearch = require('./es-client'); 18 | const chance = new ChanceJs(); 19 | 20 | describe('Elasticsearch Document Producer', () => { 21 | it('stores a JSON document', () => { 22 | return elasticsearch.client.index({ 23 | index: elasticsearch.index, 24 | type: 'dummyType', 25 | id: chance.hash(), 26 | body: { 27 | name: chance.first(), 28 | created: new Date().getTime(), 29 | description: chance.paragraph(), 30 | }, 31 | }); 32 | }); 33 | }); -------------------------------------------------------------------------------- /examples/elasticsearch/taurus.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | execution: 16 | - executor: mocha 17 | hold-for: 10m 18 | scenario: 19 | script: producer.test.js 20 | - executor: mocha 21 | hold-for: 10m 22 | scenario: 23 | script: consumer.test.js 24 | 25 | services: 26 | - module: shellexec 27 | prepare: 28 | - npm install -------------------------------------------------------------------------------- /examples/http/taurus.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | # software and associated documentation files (the "Software"), to deal in the Software 5 | # without restriction, including without limitation the rights to use, copy, modify, 6 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | # permit persons to whom the Software is furnished to do so. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 10 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 11 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 12 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 13 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 14 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | execution: 16 | - concurrency: 10 17 | ramp-up: 5m 18 | hold-for: 25m 19 | scenario: aws-website-test 20 | 21 | scenarios: 22 | aws-website-test: 23 | requests: 24 | - https://aws.amazon.com 25 | --------------------------------------------------------------------------------