Skip to content

Commit

Permalink
Merge branch 'master' into fix-15709
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] committed Sep 10, 2021
2 parents adb5e13 + deaac4a commit 64d2bb7
Show file tree
Hide file tree
Showing 516 changed files with 26,447 additions and 11,346 deletions.
128 changes: 64 additions & 64 deletions .github/workflows/issue-label-assign.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .mergify.yml
Expand Up @@ -6,7 +6,7 @@ pull_request_rules:
label:
add: [ contribution/core ]
conditions:
- author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593)$
- author~=^(eladb|RomainMuller|garnaat|nija-at|skinny85|rix0rrr|NGL321|Jerry-AWS|MrArnoldPalmer|NetaNir|iliapolo|njlynch|ericzbeard|ccfife|fulghum|pkandasamy91|SoManyHs|uttarasridhar|otaviomacedo|BenChaimberg|madeline-k|BryanPan342|kaizen3031593|comcalvi)$
- -label~="contribution/core"
- name: automatic merge
actions:
Expand Down
117 changes: 117 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions allowed-breaking-changes.txt
Expand Up @@ -74,3 +74,7 @@ removed:@aws-cdk/aws-stepfunctions-tasks.BatchSubmitJobProps.jobDefinition
strengthened:@aws-cdk/aws-stepfunctions-tasks.BatchSubmitJobProps
removed:@aws-cdk/aws-lambda-event-sources.ManagedKafkaEventSourceProps.cluster
strengthened:@aws-cdk/aws-lambda-event-sources.ManagedKafkaEventSourceProps

# Remove IO2 from autoscaling EbsDeviceVolumeType. This value is not supported
# at the moment and was not supported in the past.
removed:@aws-cdk/aws-autoscaling.EbsDeviceVolumeType.IO2
4 changes: 3 additions & 1 deletion buildspec-pr.yaml
Expand Up @@ -14,4 +14,6 @@ phases:
- yarn --version || npm -g install yarn
build:
commands:
- /bin/bash ./build.sh --extract && git diff-index --exit-code --ignore-space-at-eol --stat HEAD
- /bin/bash ./build.sh --extract
- /bin/bash ./scripts/transform.sh --extract
- git diff-index --exit-code --ignore-space-at-eol --stat HEAD
1 change: 1 addition & 0 deletions buildspec.yaml
Expand Up @@ -17,6 +17,7 @@ phases:
- 'if ${BUMP_CANDIDATE:-false}; then /bin/bash ./scripts/bump-candidate.sh; fi'
- /bin/bash ./scripts/align-version.sh
- /bin/bash ./build.sh
- /bin/bash ./scripts/transform.sh
post_build:
commands:
- "[ -f .BUILD_COMPLETED ] && /bin/bash ./pack.sh"
Expand Down
18 changes: 14 additions & 4 deletions package.json
Expand Up @@ -20,10 +20,10 @@
"fs-extra": "^9.1.0",
"graceful-fs": "^4.2.6",
"jest-junit": "^12.2.0",
"jsii-diff": "^1.31.0",
"jsii-pacmak": "^1.31.0",
"jsii-reflect": "^1.31.0",
"jsii-rosetta": "^1.31.0",
"jsii-diff": "^1.34.0",
"jsii-pacmak": "^1.34.0",
"jsii-reflect": "^1.34.0",
"jsii-rosetta": "^1.34.0",
"lerna": "^4.0.0",
"patch-package": "^6.4.7",
"standard-version": "^9.3.1",
Expand Down Expand Up @@ -71,6 +71,16 @@
"nohoist": [
"**/jszip",
"**/jszip/**",
"@aws-cdk/assertions-alpha/colors",
"@aws-cdk/assertions-alpha/colors/**",
"@aws-cdk/assertions-alpha/diff",
"@aws-cdk/assertions-alpha/diff/**",
"@aws-cdk/assertions-alpha/fast-deep-equal",
"@aws-cdk/assertions-alpha/fast-deep-equal/**",
"@aws-cdk/assertions-alpha/string-width",
"@aws-cdk/assertions-alpha/string-width/**",
"@aws-cdk/assertions-alpha/table",
"@aws-cdk/assertions-alpha/table/**",
"@aws-cdk/assertions/colors",
"@aws-cdk/assertions/colors/**",
"@aws-cdk/assertions/diff",
Expand Down
35 changes: 35 additions & 0 deletions packages/@aws-cdk-containers/ecs-service-extensions/README.md
Expand Up @@ -19,6 +19,7 @@ The `Service` construct provided by this module can be extended with optional `S
- [AWS AppMesh](https://aws.amazon.com/app-mesh/) for adding your application to a service mesh
- [Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html), for exposing your service to the public
- [AWS FireLens](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_firelens.html), for filtering and routing application logs
- Queue to allow your service to consume messages from an SQS Queue which is populated by one or more SNS Topics that it is subscribed to
- [Community Extensions](#community-extensions), providing support for advanced use cases

The `ServiceExtension` class is an abstract class which you can also implement in
Expand Down Expand Up @@ -321,6 +322,40 @@ const environment = Environment.fromEnvironmentAttributes(stack, 'Environment',

```

## Queue Extension

This service extension creates a default SQS Queue `eventsQueue` for the service (if not provided) and accepts a list of `ISubscribable` objects that the `eventsQueue` can subscribe to. The service extension creates the subscriptions and sets up permissions for the service to consume messages from the SQS Queue.

### Setting up SNS Topic Subscriptions for SQS Queues

You can use this extension to set up SNS Topic subscriptions for the `eventsQueue`. To do this, create a new object of type `TopicSubscription` for every SNS Topic you want the `eventsQueue` to subscribe to and provide it as input to the service extension.

```ts
const myServiceDescription = nameDescription.add(new QueueExtension({
// Provide list of topic subscriptions that you want the `eventsQueue` to subscribe to
subscriptions: [new TopicSubscription({
topic: new sns.Topic(stack, 'my-topic'),
}],
}));

// To access the `eventsQueue` for the service, use the `eventsQueue` getter for the extension
const myQueueExtension = myServiceDescription.extensions.queue as QueueExtension;
const myEventsQueue = myQueueExtension.eventsQueue;
```
For setting up a topic-specific queue subscription, you can provide a custom queue in the `TopicSubscription` object along with the SNS Topic. The extension will set up a topic subscription for the provided queue instead of the default `eventsQueue` of the service.
```ts
nameDescription.add(new QueueExtension({
queue: myEventsQueue,
subscriptions: [new TopicSubscription({
topic: new sns.Topic(stack, 'my-topic'),
// `myTopicQueue` will subscribe to the `my-topic` instead of `eventsQueue`
queue: myTopicQueue,
}],
}));
```
## Community Extensions
We encourage the development of Community Service Extensions that support
Expand Down
Expand Up @@ -6,3 +6,4 @@ export * from './cloudwatch-agent';
export * from './scale-on-cpu-utilization';
export * from './xray';
export * from './assign-public-ip';
export * from './queue';
@@ -0,0 +1,212 @@
import * as ecs from '@aws-cdk/aws-ecs';
import * as sns from '@aws-cdk/aws-sns';
import * as subscription from '@aws-cdk/aws-sns-subscriptions';
import * as sqs from '@aws-cdk/aws-sqs';
import * as cdk from '@aws-cdk/core';
import { Service } from '../service';
import { Container } from './container';
import { ContainerMutatingHook, ServiceExtension } from './extension-interfaces';

// Keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import { Construct } from '@aws-cdk/core';

/**
* An interface that will be implemented by all the resources that can be subscribed to.
*/
export interface ISubscribable {
/**
* All classes implementing this interface must also implement the `subscribe()` method
*/
subscribe(extension: QueueExtension): sqs.IQueue;
}

/**
* The settings for the Queue extension.
*/
export interface QueueExtensionProps {
/**
* The list of subscriptions for this service.
*
* @default none
*/
readonly subscriptions?: ISubscribable[];

/**
* The user-provided default queue for this service.
*
* @default If the `eventsQueue` is not provided, a default SQS Queue is created for the service.
*/
readonly eventsQueue?: sqs.IQueue;
}

/**
* The topic-specific settings for creating the queue subscriptions.
*/
export interface TopicSubscriptionProps {
/**
* The SNS Topic to subscribe to.
*/
readonly topic: sns.ITopic;

/**
* The user-provided queue to subscribe to the given topic.
* If the `queue` is not provided, the default `eventsQueue` will subscribe to the given topic.
*
* @default none
*/
readonly queue?: sqs.IQueue;
}

/**
* The `TopicSubscription` class represents an SNS Topic resource that can be subscribed to by the service queues.
*/
export class TopicSubscription implements ISubscribable {
public readonly topic: sns.ITopic;

public readonly queue?: sqs.IQueue;

constructor(props: TopicSubscriptionProps) {
this.topic = props.topic;
this.queue = props.queue;
}

/**
* This method sets up SNS Topic subscriptions for the SQS queue provided by the user. If a `queue` is not provided,
* the default `eventsQueue` subscribes to the given topic.
*
* @param extension `QueueExtension` added to the service
* @returns the queue subscribed to the given topic
*/
public subscribe(extension: QueueExtension) : sqs.IQueue {
let queue = extension.eventsQueue;
if (this.queue) {
queue = this.queue;
}
this.topic.addSubscription(new subscription.SqsSubscription(queue));
return queue;
}
}

/**
* Settings for the hook which mutates the application container
* to add the events queue URI to its environment.
*/
interface ContainerMutatingProps {
/**
* The events queue name and URI to be added to the container environment.
*/
readonly environment: { [key: string]: string };
}

/**
* This hook modifies the application container's environment to
* add the queue URL for the events queue of the service.
*/
class QueueExtensionMutatingHook extends ContainerMutatingHook {
private environment: { [key: string]: string };

constructor(props: ContainerMutatingProps) {
super();
this.environment = props.environment;
}

public mutateContainerDefinition(props: ecs.ContainerDefinitionOptions): ecs.ContainerDefinitionOptions {
return {
...props,

environment: { ...(props.environment || {}), ...this.environment },
} as ecs.ContainerDefinitionOptions;
}
}

/**
* This extension creates a default `eventsQueue` for the service (if not provided) and accepts a list of objects of
* type `ISubscribable` that the `eventsQueue` subscribes to. It creates the subscriptions and sets up permissions
* for the service to consume messages from the SQS Queues.
*
* The default queue for this service can be accessed using the getter `<extension>.eventsQueue`.
*/
export class QueueExtension extends ServiceExtension {
private _eventsQueue!: sqs.IQueue;

private subscriptionQueues = new Set<sqs.IQueue>();

private environment: { [key: string]: string } = {};

private props?: QueueExtensionProps;

constructor(props?: QueueExtensionProps) {
super('queue');

this.props = props;
}

/**
* This hook creates (if required) and sets the default queue `eventsQueue`. It also sets up the subscriptions for
* the provided `ISubscribable` objects.
*
* @param service The parent service which this extension has been added to
* @param scope The scope that this extension should create resources in
*/
public prehook(service: Service, scope: Construct) {
this.parentService = service;
this.scope = scope;

let eventsQueue = this.props?.eventsQueue;
if (!eventsQueue) {
const deadLetterQueue = new sqs.Queue(this.scope, 'EventsDeadLetterQueue', {
retentionPeriod: cdk.Duration.days(14),
});

eventsQueue = new sqs.Queue(this.scope, 'EventsQueue', {
deadLetterQueue: {
queue: deadLetterQueue,
maxReceiveCount: 3,
},
});
}
this._eventsQueue = eventsQueue;

this.environment[`${this.parentService.id.toUpperCase()}_QUEUE_URI`] = this._eventsQueue.queueUrl;

if (this.props?.subscriptions) {
for (const subs of this.props.subscriptions) {
const subsQueue = subs.subscribe(this);
this.subscriptionQueues.add(subsQueue);
}
}
}

/**
* Add hooks to the main application extension so that it is modified to
* add the events queue URL to the container environment.
*/
public addHooks() {
const container = this.parentService.serviceDescription.get('service-container') as Container;

if (!container) {
throw new Error('Queue Extension requires an application extension');
}

container.addContainerMutatingHook(new QueueExtensionMutatingHook({
environment: this.environment,
}));
}

/**
* After the task definition has been created, this hook grants SQS permissions to the task role.
*
* @param taskDefinition The created task definition
*/
public useTaskDefinition(taskDefinition: ecs.TaskDefinition) {
this._eventsQueue.grantConsumeMessages(taskDefinition.taskRole);
for (const queue of this.subscriptionQueues) {
queue.grantConsumeMessages(taskDefinition.taskRole);
}
}

public get eventsQueue() : sqs.IQueue {
return this._eventsQueue;
}
}
Expand Up @@ -64,6 +64,8 @@
"@aws-cdk/aws-route53": "0.0.0",
"@aws-cdk/aws-route53-targets": "0.0.0",
"@aws-cdk/aws-servicediscovery": "0.0.0",
"@aws-cdk/aws-sns": "0.0.0",
"@aws-cdk/aws-sns-subscriptions": "0.0.0",
"@aws-cdk/aws-sqs": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/custom-resources": "0.0.0",
Expand All @@ -89,6 +91,8 @@
"@aws-cdk/aws-route53": "0.0.0",
"@aws-cdk/aws-route53-targets": "0.0.0",
"@aws-cdk/aws-servicediscovery": "0.0.0",
"@aws-cdk/aws-sns": "0.0.0",
"@aws-cdk/aws-sns-subscriptions": "0.0.0",
"@aws-cdk/aws-sqs": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/custom-resources": "0.0.0",
Expand Down

0 comments on commit 64d2bb7

Please sign in to comment.