forked from widdix/aws-cf-templates
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cfc0afb
commit fdd1612
Showing
21 changed files
with
1,379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
target/ | ||
.idea/ | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Free Templates for AWS CloudFormation | ||
|
||
Tests for our free Templates for AWS CloudFormation. The goal of this tests is to ensure that our templates are always working. The test are implemented in Java 8 and run in JUnit 4. | ||
|
||
If you run this tests, many AWS CloudFormation tests are created and **charges will apply**! | ||
|
||
[widdix GmbH](https://widdix.net) sponsors the test runs on every push and once per week to ensure that everything is working as expected. | ||
|
||
## Prerequisits | ||
|
||
To run this tests you need: | ||
* A resolvable Route 53 hosted zone where record sets can be added automatically (**NOT** your production environment!) | ||
* A domain suffix that cen be used for subdomains (e.g. `awstest.mydomain.com`) | ||
* A wildcard ACM certificate in `us-east-1` that matches with the domain suffix from above (e.g. `*.awstest.mydomain.com`) | ||
* A wildcard ACM certificate in the region you want to run this tests in like above | ||
|
||
## Supported env variables | ||
|
||
* `HOSTED_ZONE_ID` **required** A hosted zone id of your Route 53 hosted zone where the tests can create record sets | ||
* `DOMAIN_SUFFIX` **required** A domain suffix that is part of your hosted zone | ||
* `CLOUDFRONT_ACM_CERTIFICATE_ARN` **required** A wildcard ACM certificate in `us-east-1` | ||
* `ACM_CERTIFICATE_ARN` **required** A wildcard ACM certificate in the region where the tests run | ||
* `IAM_ROLE_ARN` if the tests should assume an IAM role before they run supply the ARN of the IAM role | ||
* `TEMPLATE_DIR` Load templates from local disk (instead of S3 bucket `widdix-aws-cf-templates`). Must end with an `/`. See `BUCKET` as well. | ||
* `BUCKET` Some templates are to big to be passed as a string from local disk, therefore you need to supply the name of the bucket that is used to upload templates. | ||
|
||
## Usage | ||
|
||
### AWS credentials | ||
|
||
The AWS credentials are passed in as defined by the AWS SDK for Java: http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html | ||
|
||
One addition is, that you can supply the env variable `IAM_ROLE_ARN` which let's the tests assume a role before they start with the default credentials. | ||
|
||
### Region selection | ||
|
||
The region selection works like defined by the AWS SDK for Java: http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-region-selection.html | ||
|
||
### Run all tests | ||
|
||
``` | ||
AWS_REGION="us-east-1" HOSTED_ZONE_ID="..." DOMAIN_SUFFIX="..." CLOUDFRONT_ACM_CERTIFICATE_ARN="..." ACM_CERTIFICATE_ARN="..." mvn test | ||
``` | ||
|
||
### Run a single test suite | ||
|
||
to run the `TestJenkins` tests: | ||
|
||
``` | ||
AWS_REGION="us-east-1" HOSTED_ZONE_ID="..." DOMAIN_SUFFIX="..." CLOUDFRONT_ACM_CERTIFICATE_ARN="..." ACM_CERTIFICATE_ARN="..." mvn -Dtest=TestJenkins test | ||
``` | ||
|
||
### Run a single test | ||
|
||
to run the `TestJenkins.testHA` test: | ||
|
||
``` | ||
AWS_REGION="us-east-1" HOSTED_ZONE_ID="..." DOMAIN_SUFFIX="..." CLOUDFRONT_ACM_CERTIFICATE_ARN="..." ACM_CERTIFICATE_ARN="..." mvn -Dtest=TestJenkins#testHA test | ||
``` | ||
|
||
### Load templates from local file system | ||
|
||
``` | ||
AWS_REGION="us-east-1" HOSTED_ZONE_ID="..." DOMAIN_SUFFIX="..." CLOUDFRONT_ACM_CERTIFICATE_ARN="..." ACM_CERTIFICATE_ARN="..." BUCKET="..." TEMPLATE_DIR="/path/to/widdix-aws-cf-templates/" mvn test | ||
``` | ||
|
||
### Assume role | ||
|
||
This is useful if you run on a integration server like Jenkins and want to assume a different IAM role for this tests. | ||
|
||
``` | ||
IAM_ROLE_ARN="arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME" mvn test | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>de.widdix</groupId> | ||
<artifactId>awscftemplates-tests</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-cloudformation</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-ec2</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-s3</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-route53</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-sts</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-ecs</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>de.taimos</groupId> | ||
<artifactId>httputils</artifactId> | ||
<version>1.10</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.evanlennick</groupId> | ||
<artifactId>retry4j</artifactId> | ||
<version>0.6.2</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.jcraft</groupId> | ||
<artifactId>jsch</artifactId> | ||
<version>0.1.54</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.12</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>com.amazonaws</groupId> | ||
<artifactId>aws-java-sdk-bom</artifactId> | ||
<version>1.11.95</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.5.1</version> | ||
<configuration> | ||
<source>1.8</source> | ||
<target>1.8</target> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
121 changes: 121 additions & 0 deletions
121
test/src/test/java/de/widdix/awscftemplates/AAWSTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package de.widdix.awscftemplates; | ||
|
||
import com.amazonaws.auth.AWSCredentialsProvider; | ||
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; | ||
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; | ||
import com.amazonaws.services.ec2.AmazonEC2; | ||
import com.amazonaws.services.ec2.AmazonEC2AsyncClientBuilder; | ||
import com.amazonaws.services.ec2.model.*; | ||
import com.amazonaws.services.route53.AmazonRoute53AsyncClientBuilder; | ||
import com.amazonaws.services.route53.model.*; | ||
import com.amazonaws.services.securitytoken.AWSSecurityTokenService; | ||
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; | ||
import com.amazonaws.services.route53.AmazonRoute53; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
public abstract class AAWSTest extends ATest { | ||
|
||
public final static String IAM_SESSION_NAME = "aws-cf-templates"; | ||
|
||
protected final AWSCredentialsProvider credentialsProvider; | ||
|
||
private AmazonEC2 ec2; | ||
|
||
private AmazonRoute53 route53; | ||
|
||
public AAWSTest() { | ||
super(); | ||
if (Config.has(Config.Key.IAM_ROLE_ARN)) { | ||
final AWSSecurityTokenService sts = AWSSecurityTokenServiceClientBuilder.standard().build(); | ||
this.credentialsProvider = new STSAssumeRoleSessionCredentialsProvider.Builder(Config.get(Config.Key.IAM_ROLE_ARN), IAM_SESSION_NAME).withStsClient(sts).build(); | ||
} else { | ||
this.credentialsProvider = new DefaultAWSCredentialsProviderChain(); | ||
} | ||
this.ec2 = AmazonEC2AsyncClientBuilder.standard().withCredentials(this.credentialsProvider).build(); | ||
this.route53 = AmazonRoute53AsyncClientBuilder.standard().withCredentials(this.credentialsProvider).build(); | ||
} | ||
|
||
protected final KeyPair createKey(final String keyName) { | ||
final CreateKeyPairResult res = this.ec2.createKeyPair(new CreateKeyPairRequest().withKeyName(keyName)); | ||
return res.getKeyPair(); | ||
} | ||
|
||
protected final void deleteKey(final String keyName) { | ||
this.ec2.deleteKeyPair(new DeleteKeyPairRequest().withKeyName(keyName)); | ||
} | ||
|
||
private void waitForDomain(final String name, final String changeId, final ChangeStatus finalStatus) { | ||
System.out.println("waitForDomain[" + name + "]: to reach status " + finalStatus); | ||
while (true) { | ||
try { | ||
Thread.sleep(5000); | ||
} catch (final InterruptedException e) { | ||
// continue | ||
} | ||
final GetChangeResult res = this.route53.getChange(new GetChangeRequest().withId(changeId)); | ||
final ChangeStatus currentStatus = ChangeStatus.fromValue(res.getChangeInfo().getStatus()); | ||
if (finalStatus == currentStatus) { | ||
System.out.println("waitForDomain[" + name + "]: final status reached."); | ||
return; | ||
} else { | ||
System.out.println("waitForDomain[" + name + "]: continue to wait (still in intermediate status " + currentStatus + ") ..."); | ||
} | ||
} | ||
} | ||
|
||
protected final String generateDomain(final String prefix) { | ||
return prefix + "." + Config.get(Config.Key.DOMAIN_SUFFIX); | ||
} | ||
|
||
protected final String createDomain(final String prefix, final String host) { | ||
final String name = this.generateDomain(prefix); | ||
final ResourceRecord rr = new ResourceRecord(host); | ||
final ResourceRecordSet rrs = new ResourceRecordSet(name, RRType.CNAME).withTTL(60L).withResourceRecords(rr); | ||
final Change create = new Change().withAction(ChangeAction.CREATE).withResourceRecordSet(rrs); | ||
final ChangeBatch changeBatch = new ChangeBatch().withChanges(create); | ||
final ChangeResourceRecordSetsRequest req = new ChangeResourceRecordSetsRequest().withHostedZoneId(Config.get(Config.Key.HOSTED_ZONE_ID)).withChangeBatch(changeBatch); | ||
final ChangeResourceRecordSetsResult res = this.route53.changeResourceRecordSets(req); | ||
this.waitForDomain(name, res.getChangeInfo().getId(), ChangeStatus.INSYNC); | ||
return name; | ||
} | ||
|
||
protected final void deleteDomain(final String prefix) { | ||
final String name = this.generateDomain(prefix); | ||
final ListResourceRecordSetsResult res1 = this.route53.listResourceRecordSets(new ListResourceRecordSetsRequest().withHostedZoneId(Config.get(Config.Key.HOSTED_ZONE_ID)).withStartRecordName(name)); | ||
final ResourceRecordSet rrs = res1.getResourceRecordSets().get(0); | ||
final Change delete = new Change().withAction(ChangeAction.DELETE).withResourceRecordSet(rrs); | ||
final ChangeBatch changeBatch = new ChangeBatch().withChanges(delete); | ||
final ChangeResourceRecordSetsRequest req = new ChangeResourceRecordSetsRequest().withHostedZoneId(Config.get(Config.Key.HOSTED_ZONE_ID)).withChangeBatch(changeBatch); | ||
final ChangeResourceRecordSetsResult res2 = this.route53.changeResourceRecordSets(req); | ||
this.waitForDomain(name, res2.getChangeInfo().getId(), ChangeStatus.INSYNC); | ||
} | ||
|
||
protected final Vpc getDefaultVPC() { | ||
final DescribeVpcsResult res = this.ec2.describeVpcs(new DescribeVpcsRequest().withFilters(new Filter().withName("isDefault").withValues("true"))); | ||
return res.getVpcs().get(0); | ||
} | ||
|
||
protected final List<Subnet> getDefaultSubnets() { | ||
final DescribeSubnetsResult res = this.ec2.describeSubnets(new DescribeSubnetsRequest().withFilters(new Filter().withName("defaultForAz").withValues("true"))); | ||
return res.getSubnets(); | ||
} | ||
|
||
protected final SecurityGroup getDefaultSecurityGroup() { | ||
final Vpc vpc = this.getDefaultVPC(); | ||
final DescribeSecurityGroupsResult res = this.ec2.describeSecurityGroups(new DescribeSecurityGroupsRequest().withFilters( | ||
new Filter().withName("vpc-id").withValues(vpc.getVpcId()), | ||
new Filter().withName("group-name").withValues("default") | ||
)); | ||
return res.getSecurityGroups().get(0); | ||
} | ||
|
||
protected final String random8String() { | ||
final String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase(); | ||
final int beginIndex = (int) (Math.random() * (uuid.length() - 7)); | ||
final int endIndex = beginIndex + 7; | ||
return "r" + uuid.substring(beginIndex, endIndex); // must begin [a-z] | ||
} | ||
|
||
} |
Oops, something went wrong.