Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(events-targets): allow all ECS TaskOverrides #32344

Merged
merged 13 commits into from
Feb 12, 2025
Merged

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@
}
},
"Id": "Target0",
"Input": "{\"containerOverrides\":[{\"name\":\"TheContainer\",\"environment\":[{\"name\":\"I_WAS_TRIGGERED\",\"value\":\"From CloudWatch Events\"}]}]}",
"Input": "{\"containerOverrides\":[{\"name\":\"TheContainer\",\"environment\":[{\"name\":\"I_WAS_TRIGGERED\",\"value\":\"From CloudWatch Events\"}]}],\"cpu\":\"512\",\"memory\":\"512\"}",
"RoleArn": {
"Fn::GetAtt": [
"TaskDefEventsRoleFB3B67B8",
Expand Down Expand Up @@ -1078,4 +1078,4 @@
]
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ rule.addTarget(new targets.EcsTask({
cluster,
taskDefinition,
taskCount: 1,
cpu: '512',
memory: '512',
containerOverrides: [{
containerName: 'TheContainer',
environment: [
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@
}
},
"Id": "Target0",
"Input": "{\"containerOverrides\":[{\"name\":\"TheContainer\",\"environment\":[{\"name\":\"I_WAS_TRIGGERED\",\"value\":\"From CloudWatch Events\"}]}]}",
"Input": "{\"containerOverrides\":[{\"name\":\"TheContainer\",\"environment\":[{\"name\":\"I_WAS_TRIGGERED\",\"value\":\"From CloudWatch Events\"}]}],\"cpu\":\"512\",\"memory\":\"512\"}",
"RoleArn": {
"Fn::GetAtt": [
"TaskDefEventsRoleFB3B67B8",
Expand Down Expand Up @@ -959,4 +959,4 @@
]
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ rule.addTarget(new targets.EcsTask({
taskDefinition,
taskCount: 1,
enableExecuteCommand: true,
cpu: '512',
memory: '512',
containerOverrides: [{
containerName: 'TheContainer',
environment: [
Expand Down
27 changes: 27 additions & 0 deletions packages/aws-cdk-lib/aws-events-targets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,33 @@ rule.addTarget(new targets.EcsTask({
}));
```

### Overriding Values in the Task Definition

You can override values in the task definition by setting the corresponding properties in the `EcsTaskProps`. All
values in the [`TaskOverrides` API](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html) are
supported.

```ts
import * as ecs from 'aws-cdk-lib/aws-ecs';

declare const cluster: ecs.ICluster;
declare const taskDefinition: ecs.TaskDefinition;

const rule = new events.Rule(this, 'Rule', {
schedule: events.Schedule.rate(cdk.Duration.hours(1)),
});

rule.addTarget(new targets.EcsTask({
cluster,
taskDefinition,
taskCount: 1,

// Overrides the cpu and memory values in the task definition
cpu: '512',
memory: '512',
}));
```

## Schedule a Redshift query (serverless or cluster)

Use the `RedshiftQuery` target to schedule an Amazon Redshift Query.
Expand Down
28 changes: 28 additions & 0 deletions packages/aws-cdk-lib/aws-events-targets/lib/ecs-task-properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,31 @@ export interface TaskEnvironmentVariable {
*/
readonly value: string;
}

/**
* Override ephemeral storage for the task.
*/
export interface EphemeralStorageOverride {
/**
* The total amount, in GiB, of ephemeral storage to set for the task.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied these docstrings from the Task Override docs: https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html

*
* The minimum supported value is 20 GiB and the maximum supported value is 200 GiB.
*/
readonly sizeInGiB: number;
}

/**
* Override inference accelerators for the task.
*/
export interface InferenceAcceleratorOverride {
/**
* The Elastic Inference accelerator device name to override for the task.
* This parameter must match a `deviceName` specified in the task definition.
*/
readonly deviceName: string;

/**
* The Elastic Inference accelerator type to use.
*/
readonly deviceType: string;
}
79 changes: 75 additions & 4 deletions packages/aws-cdk-lib/aws-events-targets/lib/ecs-task.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Construct } from 'constructs';
import { ContainerOverride } from './ecs-task-properties';
import { ContainerOverride, EphemeralStorageOverride, InferenceAcceleratorOverride } from './ecs-task-properties';
import { addToDeadLetterQueueResourcePolicy, bindBaseTargetConfig, singletonEventRole, TargetBaseProps } from './util';
import * as ec2 from '../../aws-ec2';
import * as ecs from '../../aws-ecs';
Expand Down Expand Up @@ -50,6 +50,54 @@ export interface EcsTaskProps extends TargetBaseProps {
*/
readonly containerOverrides?: ContainerOverride[];

/**
* The CPU override for the task.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*
* @default - The task definition's CPU value
*/
readonly cpu?: string;

/**
* The ephemeral storage setting override for the task.
*
* NOTE: This parameter is only supported for tasks hosted on Fargate that use the following platform versions:
* - Linux platform version 1.4.0 or later.
* - Windows platform version 1.0.0 or later.
*
* @default - The task definition's ephemeral storage value
*/
readonly ephemeralStorage?: EphemeralStorageOverride;

/**
* The execution role for the task.
*
* The Amazon Resource Name (ARN) of the task execution role override for the task.
*
* @default - The task definition's execution role
*/
readonly executionRole?: iam.IRole;

/**
* The Elastic Inference accelerator override for the task.
*
* @default - The task definition's inference accelerator overrides
*/
readonly inferenceAcceleratorOverrides?: InferenceAcceleratorOverride[];

/**
* The memory override for the task.
*
* @default - The task definition's memory value
*/
readonly memory?: string;

/**
* The IAM role for the task.
*
* @default - The task definition's task role
*/
readonly taskRole?: iam.IRole;

/**
* In what subnets to place the task's ENIs
*
Expand Down Expand Up @@ -222,14 +270,12 @@ export class EcsTask implements events.IRuleTarget {
public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig {
const arn = this.cluster.clusterArn;
const role = this.role;
const containerOverrides = this.props.containerOverrides && this.props.containerOverrides
.map(({ containerName, ...overrides }) => ({ name: containerName, ...overrides }));
const input = { containerOverrides };
const taskCount = this.taskCount;
const taskDefinitionArn = this.taskDefinition.taskDefinitionArn;
const propagateTags = this.propagateTags;
const tagList = this.tags;
const enableExecuteCommand = this.enableExecuteCommand;
const input = this.createInput();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this logic is more complex now, I refactored it to a dedicated private method.


const subnetSelection = this.props.subnetSelection || { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS };

Expand Down Expand Up @@ -276,6 +322,31 @@ export class EcsTask implements events.IRuleTarget {
};
}

private createInput(): Record<string, any> {
const containerOverrides = this.props.containerOverrides && this.props.containerOverrides
.map(({ containerName, ...overrides }) => ({ name: containerName, ...overrides }));

if (this.props.ephemeralStorage) {
const ephemeralStorage = this.props.ephemeralStorage;
if (ephemeralStorage.sizeInGiB < 20 || ephemeralStorage.sizeInGiB > 200) {
throw new Error('Ephemeral storage size must be between 20 GiB and 200 GiB.');
}
}

// See https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html
return {
// In prior versions, containerOverrides was passed even when undefined, so we always set it for backward compatibility.
containerOverrides,

...(this.props.cpu && { cpu: this.props.cpu }),
...(this.props.ephemeralStorage && { ephemeralStorage: this.props.ephemeralStorage }),
...(this.props.executionRole?.roleArn && { executionRole: this.props.executionRole.roleArn }),
...(this.props.inferenceAcceleratorOverrides && { inferenceAcceleratorOverrides: this.props.inferenceAcceleratorOverrides }),
...(this.props.memory && { memory: this.props.memory }),
...(this.props.taskRole?.roleArn && { taskRole: this.props.taskRole.roleArn }),
};
}

private createEventRolePolicyStatements(): iam.PolicyStatement[] {
// check if there is a taskdefinition revision (arn will end with : followed by digits) included in the arn already
let needsRevisionWildcard = false;
Expand Down
Loading
Loading