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(stepfunctions-tasks): add cpu and memory parameters to EcsRunTask #30140

Merged
merged 17 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

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 @@ -828,7 +828,7 @@
"GroupId"
]
},
"\"]}},\"Overrides\":{\"ContainerOverrides\":[{\"Name\":\"TheContainer\",\"Environment\":[{\"Name\":\"SOME_KEY\",\"Value.$\":\"$.SomeKey\"}]}]},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}},\"FargateTaskSetRevisionNumber\":{\"Next\":\"FargateTaskWithPropagatedTag\",\"Type\":\"Task\",\"Resource\":\"arn:",
"\"]}},\"Overrides\":{\"Cpu\":\"1024\",\"Memory\":\"2048\",\"ContainerOverrides\":[{\"Name\":\"TheContainer\",\"Environment\":[{\"Name\":\"SOME_KEY\",\"Value.$\":\"$.SomeKey\"}]}]},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}},\"FargateTaskSetRevisionNumber\":{\"Next\":\"FargateTaskWithPropagatedTag\",\"Type\":\"Task\",\"Resource\":\"arn:",
{
"Ref": "AWS::Partition"
},
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 @@ -57,6 +57,8 @@ const definition = new sfn.Pass(stack, 'Start', {
platformVersion: ecs.FargatePlatformVersion.VERSION1_4,
}),
taskTimeout: sfn.Timeout.at('$.Timeout'),
cpu: '1024',
memoryMiB: '2048',
}),
).next(
new tasks.EcsRunTask(stack, 'FargateTaskSetRevisionNumber', {
Expand Down
33 changes: 33 additions & 0 deletions packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,39 @@ const runTask = new tasks.EcsRunTask(this, 'RunFargate', {
});
```

#### Override CPU and Memory Parameter

By setting the property cpu or memoryMiB, you can override the Fargate or EC2 task instance size at runtime.

see: https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html

```ts
const vpc = ec2.Vpc.fromLookup(this, 'Vpc', {
isDefault: true,
});
const cluster = new ecs.Cluster(this, 'ECSCluster', { vpc });

const taskDefinition = new ecs.TaskDefinition(this, 'TD', {
compatibility: ecs.Compatibility.FARGATE,
cpu: '256',
memoryMiB: '512'
});

taskDefinition.addContainer('TheContainer', {
image: ecs.ContainerImage.fromRegistry('foo/bar'),
});

const runTask = new tasks.EcsRunTask(this, 'Run', {
integrationPattern: sfn.IntegrationPattern.RUN_JOB,
cluster,
taskDefinition,
launchTarget: new tasks.EcsFargateLaunchTarget(),
cpu: '1024',
memoryMiB: '1048'
});
```


#### ECS enable Exec

By setting the property [`enableExecuteCommand`](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RunTask.html#ECS-RunTask-request-enableExecuteCommand) to `true`, you can enable the [ECS Exec feature](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html) for the task for either Fargate or EC2 launch types.
Expand Down
67 changes: 50 additions & 17 deletions packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/ecs/run-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ export interface EcsRunTaskProps extends sfn.TaskStateBaseProps {
* @default false
*/
readonly enableExecuteCommand?: boolean;

/**
* Cpu setting override
* @see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html
* @default - No override
*/
readonly cpu?: string;
kackyt marked this conversation as resolved.
Show resolved Hide resolved

/**
* Memory setting override
* @see https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html
* @default - No override
*/
readonly memoryMiB?: string;
}

/**
Expand Down Expand Up @@ -310,7 +324,12 @@ export class EcsRunTask extends sfn.TaskStateBase implements ec2.IConnectable {
Cluster: this.props.cluster.clusterArn,
TaskDefinition: this.props.revisionNumber === undefined ? this.props.taskDefinition.family : `${this.props.taskDefinition.family}:${this.props.revisionNumber.toString()}`,
NetworkConfiguration: this.networkConfiguration,
Overrides: renderOverrides(this.props.containerOverrides),
Overrides: renderOverrides(
{
cpu: this.props.cpu,
memoryMiB: this.props.memoryMiB,
containerOverrides: this.props.containerOverrides,
}),
PropagateTags: this.props.propagatedTagSource,
...this.props.launchTarget.bind(this, { taskDefinition: this.props.taskDefinition, cluster: this.props.cluster }).parameters,
EnableExecuteCommand: this.props.enableExecuteCommand,
Expand Down Expand Up @@ -415,26 +434,40 @@ export class EcsRunTask extends sfn.TaskStateBase implements ec2.IConnectable {
}
}

function renderOverrides(containerOverrides?: ContainerOverride[]) {
if (!containerOverrides || containerOverrides.length === 0) {
interface OverrideProps {
cpu?: string;
memoryMiB?: string;
containerOverrides?: ContainerOverride[];
}

function renderOverrides(props: OverrideProps) {
const containerOverrides = props.containerOverrides;
const noContainerOverrides = !containerOverrides || containerOverrides.length === 0;
if (noContainerOverrides && !props.cpu && !props.memoryMiB) {
return undefined;
}

const ret = new Array<any>();
for (const override of containerOverrides) {
ret.push({
Name: override.containerDefinition.containerName,
Command: override.command,
Cpu: override.cpu,
Memory: override.memoryLimit,
MemoryReservation: override.memoryReservation,
Environment:
override.environment?.map((e) => ({
Name: e.name,
Value: e.value,
})),
});
if (!noContainerOverrides) {
shikha372 marked this conversation as resolved.
Show resolved Hide resolved
for (const override of containerOverrides) {
ret.push({
Name: override.containerDefinition.containerName,
Command: override.command,
Cpu: override.cpu,
Memory: override.memoryLimit,
MemoryReservation: override.memoryReservation,
Environment:
override.environment?.map((e) => ({
Name: e.name,
Value: e.value,
})),
});
}
}

return { ContainerOverrides: ret };
return {
Cpu: props.cpu,
Memory: props.memoryMiB,
ContainerOverrides: noContainerOverrides ? undefined : ret,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,60 @@ test('Running a task with NONE as propagated tag source', () => {
}).toStateJson())).toHaveProperty('Parameters.PropagateTags', 'NONE');
});

test('Running a task with cpu parameter', () => {
const taskDefinition = new ecs.TaskDefinition(stack, 'TD', {
memoryMiB: '1024',
cpu: '512',
compatibility: ecs.Compatibility.FARGATE,
});
const containerDefinition = taskDefinition.addContainer('TheContainer', {
containerName: 'ExplicitContainerName',
image: ecs.ContainerImage.fromRegistry('foo/bar'),
memoryLimitMiB: 256,
});

expect(stack.resolve(
new tasks.EcsRunTask(stack, 'task', {
cluster,
taskDefinition,
cpu: '1024',
containerOverrides: [
{
containerDefinition,
environment: [{ name: 'SOME_KEY', value: sfn.JsonPath.stringAt('$.SomeKey') }],
},
],
launchTarget: new tasks.EcsFargateLaunchTarget(),
}).toStateJson())).toHaveProperty('Parameters.Overrides.Cpu', '1024');
});

test('Running a task with memory parameter', () => {
const taskDefinition = new ecs.TaskDefinition(stack, 'TD', {
memoryMiB: '1024',
cpu: '512',
compatibility: ecs.Compatibility.FARGATE,
});
const containerDefinition = taskDefinition.addContainer('TheContainer', {
containerName: 'ExplicitContainerName',
image: ecs.ContainerImage.fromRegistry('foo/bar'),
memoryLimitMiB: 256,
});

expect(stack.resolve(
new tasks.EcsRunTask(stack, 'task', {
cluster,
taskDefinition,
memoryMiB: '2048',
containerOverrides: [
{
containerDefinition,
environment: [{ name: 'SOME_KEY', value: sfn.JsonPath.stringAt('$.SomeKey') }],
},
],
launchTarget: new tasks.EcsFargateLaunchTarget(),
}).toStateJson())).toHaveProperty('Parameters.Overrides.Memory', '2048');
});

test('Running a Fargate Task', () => {
const taskDefinition = new ecs.TaskDefinition(stack, 'TD', {
memoryMiB: '512',
Expand Down