Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Wonqa makes it easy to create disposable SSL-enabled staging environments using AWS Fargate and accessible through custom DNS: https://your-branch-name.your-domain
.
These environments are useful for any type of QA, from manual testing to functional tests.
Read the release announcement here.
Wonqa runs in node and is available through npm
npm i --save-dev wonqa
Wonqa relies on software not included in the npm package:
docker login
once docker is installed on your machine.Wonqa provides a init()
method which will configure all required AWS resources for you. If you use init, simply call it once to setup the required AWS resources. If you prefer configuring AWS resources by yourself, see the list of required resources below.
wonqa.init()
You'll need an AWS account, an IAM user with basic permissions and to save your AWS credentials to your local aws credentials file:
Programmatic access
access type. When prompted to give the user permissions, click on Attach existing policies directly
and select the IAMFullAccess
policy. This will allow wonqa to make a set of API calls to setup AWS resources on your behalf. You can remove this permission after calling init()
.Access key ID
and Secret access key
which you'll need to save to the default profile of your ~/.aws/credentials
file (see here for more). Do not delete this file or wonqa won't be able to function: wonqa uses the NodeJS aws-sdk which, in turn, uses this file to make API calls to AWS services.[default]
aws_access_key_id = <ACCESS_KEY_ID>
aws_secret_access_key = <SECRET_ACCESS_KEY>
init()
onceconst { init } = require('wonqa');
// !! You only need to run this once.
init({
iamUsername: 'string', // the username of your IAM user
awsRegion: 'string', // the awsRegion where your services will be created and run
});
Init()
will do the following:
WonqaAccess
to the provided IAM userecsExecutionRole
and attach the following policies to that role: AmazonECSTaskExecutionRolePolicy
and CloudWatchLogsFullAccess
wonqa-cluster
wonqa-nginx
and add a lifecycle policy that repositoryAfter running init()
you should see a console log with the IDs of the created resources which you can then use to call wonqa.create()
wonqa.init()
Wonqa relies on several AWS resources which you'll need to create.
AmazonECSTaskExecutionRolePolicy
and CloudWatchLogsFullAccess
policies attached.awsRegion
you provide to the wonqa constructor, as well as one or more subnets pointing to a route table which includes at least a route with destination 0.0.0.0/0
pointing to a target internet gateway (this will give internet access to your VPC and therefore the resources running your environment)TCP 443 0.0.0.0/0
and TCP 443 ::/0
) or you will not be able to access your containerconst { Wonqa } = require('wonqa');
// initialize the client
const wonqa = new Wonqa({
...options // see below for more details and examples
});
// create your environment (this generally takes 1-3 mins as AWS provisions the resources)
wonqa.create();
Once a task is running, you can get logs for a container by calling:
// tail the logs of the container named api
wonqa.logs('api');
To clean up resources created when running .create()
, use:
// delete resources created by the last .create() call
wonqa.prune();
This is an example config
const wonqa = new Wonqa({
https: {
dnsimpleToken: '8ftZw6dk19fzaDJdkdl2929QIqbjoiLL', // optional
email: 'bob@domain.com', // required
cachePath: '/Users/bob/Desktop/myApp', // required
nginx: {
configurationPath: '/Users/bob/nginx.conf', // optional
servers: [ // at least 1 is required
{ default: true, port: 8000, }, // default application port
{ serverName: 'api', port: 3000 } // additional server definitions are optional
],
imageRepositoryPath: '012012012.dkr.ecr.us-east-1.amazonaws.com/wonqa-nginx', // optional
},
},
dns: {
rootDomain: 'myDomain.com', // required
subDomain: 'feature-cats', // required
dnsProvider: 'DNSIMPLE || ROUTE_53' // required
dnsimpleToken: '8ftZw6dk19fzaDJdkdl2929QIqbjoiLL', // required if dnsProvider is dnsimple
dnsimpleAccountID: '19291291', // required if dnsProvider is dnsimple
hostedZoneId: 'ZDJDJJO12345S', // required if dnsProvider is route53
createDNSRecords: () => Promise, // optional
},
aws: {
awsAccountID: '012012012', // required
awsRegion: 'us-east-1', // required
iamUsername: 'bob', // required
clusterName: 'wonqa-cluster', // required
subnets: ['subnet-7c629102'], // required
securityGroups: ['sg-f2o903cd3'], // required
cpu: '256', // required
memory: '512', // required
containerDefinitions: [ // at least 1 container definition is required
{
name: 'frontend', // required
image: '012012012.dkr.ecr.us-east-1.amazonaws.com/frontend:feature-cats', // required
portMappings: [ // optional
{ containerPort: 8000, hostPort: 8000, protocol: 'tcp' },
],
command: ['npm', 'run', 'start'], // optional
// for all possible container parameters, see:
// https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions
},
{
name: 'api',
image: '012012012.dkr.ecr.us-east-1.amazonaws.com/api:feature-cats',
portMappings: [
{ containerPort: 3000, hostPort: 3000, protocol: 'tcp' },
],
command: ['npm', 'run', 'start:server'],
},
],
},
preCreate: [ () => Promise, () => Promise ], // optional
postCreate: [ () => Promise, () => Promise ], // optional
onSuccess: () => Promise, // optional
onError: () => Promise, // optional
});
By default, wonqa adds HTTPS to your environment.
https.dnsimpleToken
, https.email
?Wonqa uses the certbot/dns-dnsimple and certbot/dns-route53 Docker image to generate LetsEncrypt SSL certificates using certbot's plugins. Wonqa currently only supports certbot's DNSimple and Route53 plugins and so you'll need a DNSimple or AWS account, but we welcome PRs to support additional DNS providers through Certbot's plugins.
https.nginx
?To enable Internet traffic to hit your SSL-enabled QA environment living inside AWS Fargate, wonqa will configure a nginx container to proxy HTTPs traffic from the Internet to the containers running your app code.
https.cachePath
?To avoid hitting LetsEncrypt's rate limits you'll need to provide the wonqa constructor with an absolute path to a local directory that wonqa can use to cache certificates in between builds. For eg: /Users/bob/Desktop/myApp
where myApp is a directory. Wonqa create a directory named etc
at this path to store SSL certificates. For example, if you provide the path /Users/bob/Desktop/myApp
, wonqa will create /Users/bob/Desktop/myApp/etc
where etc
is a directory.
Tips:
/Users/bob/Desktop/myApp/etc
to your .gitignore
file if you don't want your SSL certificates to be checked-inOnce your environment is up and running, DNS records can be created to point a user-friendly URL to the environment's AWS IP.
By default, wonqa will use DNSimple to create or edit DNS records. If you use DNSimple, simply pass your DNSimple creds to the wonqa constructor.
wonqa will also create DNS records for Route53.
If you prefer a custom implementation, you can pass a createDNSRecords
function to the wonqa constructor. This function will be called with the publicIP as its only argument and should return a Promise which resolves when the records are created. Wonqa will call this function as soon as the environment is running inside AWS and will poll the given https://subDomain.rootDomain
URL for a 200 OK once the promise has resolved.
dnsimpleAccountID
[string] required: The ID of your DNSimple account required to generate SSL certificates.
dnsimpleToken
[string] required: Your DNSimple API token required to generate SSL certificates.
dnsProvider
[string] required: The DNS provider of choice (currently only DNSIMPLE or ROUTE_53).
imageRepositoryPath
[string]: The path of an AWS ECR image repository used by wonqa to store the SSL-enabled nginx image for each QA environment. If this is undefined, Wonqa will look for an ECR repository in your account with the name "wonqa-nginx" or create it.
email
[string] required: the email used to register SSL certs using certbot
cachePath
[string] required: The path to a local directory wonqa will use to cache your SSL certificates.
configurationPath
[string]: The path to a local file containing your nginx configuration. For a sample configuration, see this example
servers
[array] required: an array of objects defining the server names and ports used by wonqa to generate the nginx config used to build the nginx image. This image will be used by a container which will proxy SSL traffic to the containers with your app code living inside the AWS Fargate network. This array should contain at least one object defining the base port that your app listens on, for eg: [{ default: true, port: 8000 }]
. If your app uses multiple domains and ports (one for a client bundle and one for a backend bundle, for example), wonqa will need to generate SSL certificates for each additional domain as well as configure nginx to proxy traffic to each domain/port. In this case, provide additional objects in this array to define the subdomains and ports used. For eg: [{ default: true, port: 8000 }, { serverName: 'api', port: 3000 }]
will allow your environment to be accessible at <subDomain>.<rootDomain>
(traffic will be proxied to this URL on port 8000) and api.<subDomain>.<rootDomain>
(traffic will be proxied to this URL on port 3000). !! The serverName
values should be in lowercase.
awsLogsGroup
[string]: the log group used by the nginx container. Defaults to: "wonqa-log-group"
awsLogsRegion
[string]: the log region used by the nginx container. Defaults to the provided awsRegion.
awsLogsStreamPrefix
[string]: the log stream prefix used by the nginx container. Defaults to the provided "wonqa".
dnsimpleAccountID
[string] required if createDNSRecords is undefined: The ID of your DNSimple account.
dnsimpleToken
[string] required if createDNSRecords is undefined: Your DNSimple API token.
dnsProvider
[string] required: The DNS provider of choice (currently only DNSIMPLE or ROUTE_53).
hostZoneId
[string] The host zone id of rootDomain in AWS.
rootDomain
[string] required: The domain used for your QA environment. For eg: google.com
. This is also the domain used to create DNS records if you use DNSimple.
subDomain
[string] required: The sub-domain where your QA environment will be located. We recommend using your current branch name re-formatted to be in lowercase and with only alphanumerical characters and dash characters (to be URL safe!). You can easily get this by running:
BRANCH=`git rev-parse --abbrev-ref HEAD` # get git branch name
echo ${BRANCH//[^A-Za-z0-9]/-} # strip out everything but alphanumerical and dash characters
createDNSRecords
[function]: By default Wonqa will create DNS records using DNSimple. You can override this behavior by providing this callback. This function will accept 1 argument, the AWS PublicIP used to run your task, and should return a Promise which resolves when the DNS records have been created.awsAccountID
[string] required: The ID for your AWS account
awsRegion
[string] required: The AWS region where your resources are located
iamUsername
[string] required: The IAM user with all the required permissions to run AWS commands
clusterName
[string] required: The name of the ECS cluster where your environment will live
subnets
[array] required: The AWS VPC subnets used to run your tasks. You can use any public subnet linked to the VPC which runs the Fargate cluster.
securityGroups
[array] required: The AWS security groups used to access your VPC. Make sure to add ingress rules for all ports/protocols required by your app.
cpu
[string] required: the CPU value required for your task to run. More info here.
memory
[string] required: the memory value required for your task to run. More info here.
containerDefinitions
[array] required: An array of container definition objects that Wonqa uses to create your AWS containers. Each object must include the following basic parameters
name
[string] required: the name of the container.image
[string] required: the path of the Docker image for this container. Checkout ./utils/images.sh and ./utils/Dockerfile for examples on how to create Docker images and push them to an ECR repo
You can also define optional parameters such as:portMappings
[array]: An array of objects defining port mappings between the host (the AWS agent) and your container. For eg: [{ containerPort: 3000, hostPort: 3000, protocol: 'tcp' }]
cpu
[number]: the CPU amount to be reserved for this containermemoryReservation
[number]: the memory allocated for this containercommand
[array]: The commands to be passed to the container at run-time. For eg: ['npm', 'run', 'start']
environment
[array]: environment variables to be passed to the container. For eg: [{ name: 'NODE_ENV', value: 'test' }]
logConfiguration
[object]: AWS log configs. This defaults to: { logDriver: 'awslogs', options: { 'awslogs-group': 'wonqa-log-group', 'awslogs-region': <awsRegion>, 'awslogs-stream-prefix': 'wonqa' }}
preCreate
[array]: This should be an array of functions which return Promises. Wonqa waits for every promise to resolve before creating your QA environment. This can be useful to perform some custom cleanup of resources, or push notifications to Github.
postCreate
[array]: This should be an array of functions which return Promises. Wonqa waits for every promise to resolve before finishing its process. This is useful to perform additional custom cleanup, or push notifications to Github.
onSuccess
[function]: A function which will be called once the QA environment is running and returns a 200 OK. It is called with 1 argument, the URL of the environment, and should return a Promise.
onError
[function]: A function which will be called if an error is encountered. It is called with 1 argument, the error object, and should return a Promise.
Wonqa helps you keep your costs low by pruning stale resources each time you create a new QA environment.
Each time you call wonqa.create()
, wonqa will first create a QA environment and use your provided subDomain and an incremental revision ID to tag the created AWS resources. At the end of this process, wonqa will look for any AWS resource which match the provided subDomain and a previous revision ID and delete those.
You can also use wonqa.prune()
to delete any resources created by the last create()
call. prune()
will find the ECS task linked to the given subDomain
and stop it, then deregister the related task definition, then delete the images stored in the wonqa-nginx
ECR repo (or the ECR repo at imageRepositoryPath
) also tagged with the provided subDomain
. By default, this call will also delete DNS records created by default, unless you overrode this behavior by providing a createDNSRecords
callback. For eg., you can call prune()
whenever a PR is merged using GitHub webhooks.
If you use AWS's ECR service to host your images, you may want to consider adding lifecycle policies on each repo to automatically delete images after a given time period.
If you run init()
more than once, you'll see errors as wonqa tries to create resources that have already been created by a previous call. You'll need to log into the AWS console to delete these resources and try again.
If the wonqa.create()
runs but you are unable to accessing your environment causes a timeout (for eg., if it hangs on Waiting for your QA env to return a 200 OK
), this probably means that the security group that you are using does not have ingress rules for HTTP and HTTPS as well as the rules required by your app to work.
FAQs
On-demand test environments
The npm package wonqa receives a total of 5 weekly downloads. As such, wonqa popularity was classified as not popular.
We found that wonqa demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.