Skip to content

Commit

Permalink
Merge branch 'master' into add-ingress-protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] committed Mar 9, 2021
2 parents eb560ca + abfc0ea commit 7ae6aea
Show file tree
Hide file tree
Showing 20 changed files with 548 additions and 158 deletions.
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/cache-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ export class CacheHeaderBehavior {
if (headers.length === 0) {
throw new Error('At least one header to allow must be provided');
}
if (headers.length > 10) {
throw new Error(`Maximum allowed headers in Cache Policy is 10; got ${headers.length}.`);
}
return new CacheHeaderBehavior('whitelist', headers);
}

Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/test/cache-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ describe('CachePolicy', () => {
expect(() => new CachePolicy(stack, 'CachePolicy6', { cachePolicyName: 'My_Policy' })).not.toThrow();
});

test('throws if more than 10 CacheHeaderBehavior headers are being passed', () => {
const errorMessage = /Maximum allowed headers in Cache Policy is 10; got (.*?)/;
expect(() => new CachePolicy(stack, 'CachePolicy1', {
headerBehavior: CacheHeaderBehavior.allowList('Lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'sed', 'do', 'eiusmod'),
})).toThrow(errorMessage);

expect(() => new CachePolicy(stack, 'CachePolicy2', {
headerBehavior: CacheHeaderBehavior.allowList('Lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'sed', 'do'),
})).not.toThrow();
});

test('does not throw if cachePolicyName is a token', () => {
expect(() => new CachePolicy(stack, 'CachePolicy', {
cachePolicyName: Aws.STACK_NAME,
Expand Down
28 changes: 28 additions & 0 deletions packages/@aws-cdk/aws-codebuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,31 @@ if (project.enableBatchBuilds()) {
console.log('Batch builds were enabled');
}
```

## Timeouts

There are two types of timeouts that can be set when creating your Project.
The `timeout` property can be used to set an upper limit on how long your Project is able to run without being marked as completed.
The default is 60 minutes.
An example of overriding the default follows.

```ts
import * as codebuild from '@aws-cdk/aws-codebuild';

new codebuild.Project(stack, 'MyProject', {
timeout: Duration.minutes(90)
});
```

The `queuedTimeout` property can be used to set an upper limit on how your Project remains queued to run.
There is no default value for this property.
As an example, to allow your Project to queue for up to thirty (30) minutes before the build fails,
use the following code.

```ts
import * as codebuild from '@aws-cdk/aws-codebuild';

new codebuild.Project(stack, 'MyProject', {
queuedTimeout: Duration.minutes(30)
});
```
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-codebuild/lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,15 @@ export interface CommonProjectProps {
* @default - no log configuration is set
*/
readonly logging?: LoggingOptions;

/**
* The number of minutes after which AWS CodeBuild stops the build if it's
* still in queue. For valid values, see the timeoutInMinutes field in the AWS
* CodeBuild User Guide.
*
* @default - no queue timeout is set
*/
readonly queuedTimeout?: Duration
}

export interface ProjectProps extends CommonProjectProps {
Expand Down Expand Up @@ -869,6 +878,7 @@ export class Project extends ProjectBase {
cache: cache._toCloudFormation(),
name: this.physicalName,
timeoutInMinutes: props.timeout && props.timeout.toMinutes(),
queuedTimeoutInMinutes: props.queuedTimeout && props.queuedTimeout.toMinutes(),
secondarySources: Lazy.any({ produce: () => this.renderSecondarySources() }),
secondarySourceVersions: Lazy.any({ produce: () => this.renderSecondarySourceVersions() }),
secondaryArtifacts: Lazy.any({ produce: () => this.renderSecondaryArtifacts() }),
Expand Down
43 changes: 43 additions & 0 deletions packages/@aws-cdk/aws-codebuild/test/test.project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -960,4 +960,47 @@ export = {
test.done();
},
},

'Timeouts': {
'can add queued timeout'(test: Test) {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new codebuild.Project(stack, 'Project', {
source: codebuild.Source.s3({
bucket: new s3.Bucket(stack, 'Bucket'),
path: 'path',
}),
queuedTimeout: cdk.Duration.minutes(30),
});

// THEN
expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', {
QueuedTimeoutInMinutes: 30,
}));

test.done();
},
'can override build timeout'(test: Test) {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new codebuild.Project(stack, 'Project', {
source: codebuild.Source.s3({
bucket: new s3.Bucket(stack, 'Bucket'),
path: 'path',
}),
timeout: cdk.Duration.minutes(30),
});

// THEN
expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', {
TimeoutInMinutes: 30,
}));

test.done();
},
},
};
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-ecr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const user = new iam.User(this, 'User', { ... });
ecr.AuthorizationToken.grantRead(user);
```

If you access images in the [Public ECR Gallery](https://gallery.ecr.aws/) as well, it is recommended you authenticate to the regsitry to benefit from
If you access images in the [Public ECR Gallery](https://gallery.ecr.aws/) as well, it is recommended you authenticate to the registry to benefit from
higher rate and bandwidth limits.

> See `Pricing` in https://aws.amazon.com/blogs/aws/amazon-ecr-public-a-new-public-container-registry/ and [Service quotas](https://docs.aws.amazon.com/AmazonECR/latest/public/public-service-quotas.html).
Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ obtained from either DockerHub or from ECR repositories, or built directly from
image directly from a `Dockerfile` in your source directory.
- `ecs.ContainerImage.fromDockerImageAsset(asset)`: uses an existing
`@aws-cdk/aws-ecr-assets.DockerImageAsset` as a container image.
- `new ecs.TagParameterContainerImage(repository)`: use the given ECR repository as the image
but a CloudFormation parameter as the tag.

### Environment variables

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,20 @@ export class TagParameterContainerImage extends ContainerImage {
},
});
}

/**
* Returns the value of the CloudFormation Parameter that represents the tag of the image
* in the ECR repository.
*/
public get tagParameterValue(): string {
return cdk.Lazy.string({
produce: () => {
if (this.imageTagParameter) {
return this.imageTagParameter.valueAsString;
} else {
throw new Error('TagParameterContainerImage must be used in a container definition when using tagParameterValue');
}
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,21 @@ nodeunitShim({

test.done();
},

'throws an error when tagParameterValue() is used without binding the image'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const repository = new ecr.Repository(stack, 'Repository');
const tagParameterContainerImage = new ecs.TagParameterContainerImage(repository);
new cdk.CfnOutput(stack, 'Output', {
value: tagParameterContainerImage.tagParameterValue,
});

test.throws(() => {
SynthUtils.synthesize(stack);
}, /TagParameterContainerImage must be used in a container definition when using tagParameterValue/);

test.done();
},
},
});
33 changes: 33 additions & 0 deletions packages/@aws-cdk/aws-events-targets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,39 @@ const rule = new events.Rule(this, 'rule', {
rule.addTarget(new targets.CloudWatchLogGroup(logGroup));
```

## Trigger a CodeBuild project

Use the `CodeBuildProject` target to trigger a CodeBuild project.

The code snippet below creates a CodeCommit repository that triggers a CodeBuild project
on commit to the master branch. You can optionally attach a
[dead letter queue](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html).

```ts
import * as codebuild from '@aws-sdk/aws-codebuild';
import * as codecommit from '@aws-sdk/aws-codecommit';
import * as sqs from '@aws-sdk/aws-sqs';
import * as targets from "@aws-cdk/aws-events-targets";

const repo = new codecommit.Repository(this, 'MyRepo', {
repositoryName: 'aws-cdk-codebuild-events',
});

const project = new codebuild.Project(this, 'MyProject', {
source: codebuild.Source.codeCommit({ repository: repo }),
});

const deadLetterQueue = new sqs.Queue(this, 'DeadLetterQueue');

// trigger a build when a commit is pushed to the repo
const onCommitRule = repo.onCommit('OnCommit', {
target: new targets.CodeBuildProject(project, {
deadLetterQueue: deadLetterQueue,
}),
branches: ['master'],
});
```

## Trigger a State Machine

Use the `SfnStateMachine` target to trigger a State Machine.
Expand Down
21 changes: 20 additions & 1 deletion packages/@aws-cdk/aws-events-targets/lib/codebuild.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as codebuild from '@aws-cdk/aws-codebuild';
import * as events from '@aws-cdk/aws-events';
import * as iam from '@aws-cdk/aws-iam';
import { singletonEventRole } from './util';
import * as sqs from '@aws-cdk/aws-sqs';
import { addToDeadLetterQueueResourcePolicy, singletonEventRole } from './util';

/**
* Customize the CodeBuild Event Target
Expand All @@ -24,6 +25,18 @@ export interface CodeBuildProjectProps {
* @default - the entire EventBridge event
*/
readonly event?: events.RuleTargetInput;

/**
* The SQS queue to be used as deadLetterQueue.
* Check out the [considerations for using a dead-letter queue](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html#dlq-considerations).
*
* The events not successfully delivered are automatically retried for a specified period of time,
* depending on the retry policy of the target.
* If an event is not delivered before all retry attempts are exhausted, it will be sent to the dead letter queue.
*
* @default - no dead-letter queue
*/
readonly deadLetterQueue?: sqs.IQueue;
}

/**
Expand All @@ -39,9 +52,15 @@ export class CodeBuildProject implements events.IRuleTarget {
* Allows using build projects as event rule targets.
*/
public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig {

if (this.props.deadLetterQueue) {
addToDeadLetterQueueResourcePolicy(_rule, this.props.deadLetterQueue);
}

return {
id: '',
arn: this.project.projectArn,
deadLetterConfig: this.props.deadLetterQueue ? { arn: this.props.deadLetterQueue?.queueArn } : undefined,
role: this.props.eventRole || singletonEventRole(this.project, [
new iam.PolicyStatement({
actions: ['codebuild:StartBuild'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect, haveResource } from '@aws-cdk/assert';
import * as codebuild from '@aws-cdk/aws-codebuild';
import * as events from '@aws-cdk/aws-events';
import * as iam from '@aws-cdk/aws-iam';
import * as sqs from '@aws-cdk/aws-sqs';
import { CfnElement, Stack } from '@aws-cdk/core';
import * as targets from '../../lib';

Expand Down Expand Up @@ -120,4 +121,84 @@ describe('CodeBuild event target', () => {
],
}));
});

test('use a Dead Letter Queue for the rule target', () => {
// GIVEN
const rule = new events.Rule(stack, 'Rule', {
schedule: events.Schedule.expression('rate(1 hour)'),
});

const queue = new sqs.Queue(stack, 'Queue');

// WHEN
const eventInput = {
buildspecOverride: 'buildspecs/hourly.yml',
};

rule.addTarget(
new targets.CodeBuildProject(project, {
event: events.RuleTargetInput.fromObject(eventInput),
deadLetterQueue: queue,
}),
);

// THEN
expect(stack).to(haveResource('AWS::Events::Rule', {
Targets: [
{
Arn: projectArn,
Id: 'Target0',
DeadLetterConfig: {
Arn: {
'Fn::GetAtt': [
'Queue4A7E3555',
'Arn',
],
},
},
Input: JSON.stringify(eventInput),
RoleArn: {
'Fn::GetAtt': ['MyProjectEventsRole5B7D93F5', 'Arn'],
},
},
],
}));

expect(stack).to(haveResource('AWS::SQS::QueuePolicy', {
PolicyDocument: {
Statement: [
{
Action: 'sqs:SendMessage',
Condition: {
ArnEquals: {
'aws:SourceArn': {
'Fn::GetAtt': [
'Rule4C995B7F',
'Arn',
],
},
},
},
Effect: 'Allow',
Principal: {
Service: 'events.amazonaws.com',
},
Resource: {
'Fn::GetAtt': [
'Queue4A7E3555',
'Arn',
],
},
Sid: 'AllowEventRuleRule',
},
],
Version: '2012-10-17',
},
Queues: [
{
Ref: 'Queue4A7E3555',
},
],
}));
});
});
Loading

0 comments on commit 7ae6aea

Please sign in to comment.