Skip to content

Conversation

@gracelu0
Copy link
Contributor

@gracelu0 gracelu0 commented Mar 6, 2025

Issue # (if applicable)

Closes #27456

Reason for this change

Currently the module supports all templated targets for EventBridge scheduler except for EcsRunTask.

Description of changes

  • Added new base class EcsRunTask with subclasses EcsRunFargateTask and EcsRunEc2Task depending on where user wants to schedule their ECS task. Decided on this design since some of the parameters in EcsParameters only apply one of Fargate or EC2.

Describe any new or updated permissions being added

  • Grant ecs:RunTask to the schedule execution role for the task definition and iam:passRole using existing grantRun() method (docs)
  this.props.taskDefinition.grantRun(role);

// TaskDefinition grant method 
  public grantRun(grantee: iam.IGrantable) {
    grantee.grantPrincipal.addToPrincipalPolicy(this.passRoleStatement);
    return iam.Grant.addToPrincipal({
      grantee,
      actions: ['ecs:RunTask'],
      resourceArns: [this.taskDefinitionArn],
    });
  }

//   passRoleStatement 
private get passRoleStatement() {
    if (!this._passRoleStatement) {
      this._passRoleStatement = new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: ['iam:PassRole'],
        resources: this.executionRole ? [this.taskRole.roleArn, this.executionRole.roleArn] : [this.taskRole.roleArn],
        conditions: {
          StringLike: { 'iam:PassedToService': 'ecs-tasks.amazonaws.com' },
        },
      });
    }

    return this._passRoleStatement;
  }
  • If tags are defined, grant ecs:TagResourceto the schedule execution tole for tasks in the cluster
    if (this.props.propagateTags === true || this.props.tags) {
      role.addToPrincipalPolicy(new PolicyStatement({
        actions: ['ecs:TagResource'],
        resources: [`arn:${this.cluster.stack.partition}:ecs:${this.cluster.env.region}:${this.props.taskDefinition.env.account}:task/${this.cluster.clusterName}/*`],
      }));
    }

Description of how you validated changes

Added unit tests and integration tests with assertions.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation aws-cdk-automation requested a review from a team March 6, 2025 01:04
@github-actions github-actions bot added effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2 labels Mar 6, 2025
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Mar 6, 2025
@codecov
Copy link

codecov bot commented Mar 6, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.38%. Comparing base (2623e00) to head (08fc170).
Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #33697   +/-   ##
=======================================
  Coverage   82.38%   82.38%           
=======================================
  Files         120      120           
  Lines        6937     6937           
  Branches     1170     1170           
=======================================
  Hits         5715     5715           
  Misses       1119     1119           
  Partials      103      103           
Flag Coverage Δ
suite.unit 82.38% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
packages/aws-cdk ∅ <ø> (∅)
packages/aws-cdk-lib/core 82.38% <ø> (ø)
🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@godwingrs22 godwingrs22 self-assigned this Mar 6, 2025
@gracelu0 gracelu0 force-pushed the ecs-run-task-scheduler-target branch 2 times, most recently from e97c70c to 109b25f Compare March 6, 2025 19:48
@aws-cdk-automation aws-cdk-automation added the pr/needs-maintainer-review This PR needs a review from a Core Team Member label Mar 6, 2025
@gracelu0 gracelu0 changed the title feat(scheduler-targets): ECSRunTask scheduler target feat(scheduler-targets): EcsRunTask scheduler target Mar 6, 2025
Copy link
Member

@godwingrs22 godwingrs22 left a comment

Choose a reason for hiding this comment

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

Thanks @gracelu0 for this great work. LGTM overall. Left few nits and comments for my understanding.

Comment on lines 64 to 90
new scheduler.Schedule(stack, 'Schedule', {
schedule: scheduler.ScheduleExpression.rate(cdk.Duration.minutes(5)),
target: targets.EcsRunTask.onFargate(cluster, {
taskDefinition,
subnetSelection: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
securityGroups: [securityGroup],
}),
});
Copy link
Member

Choose a reason for hiding this comment

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

Can we a unit test for both fargate and ec2 task by calling like below also?

new scheduler.Schedule(stack, 'Schedule', {
        schedule: scheduler.ScheduleExpression.rate(cdk.Duration.minutes(5)),
        target: new targets.FargateTask(...)
      });

new scheduler.Schedule(stack, 'Schedule', {
        schedule: scheduler.ScheduleExpression.rate(cdk.Duration.minutes(5)),
        target: new targets.EC2Task(...)
      });

Copy link
Contributor Author

@gracelu0 gracelu0 Mar 17, 2025

Choose a reason for hiding this comment

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

The API is intentionally designed to only support the static factory methods (EcsRunTask.onFargate() and EcsRunTask.onEc2()). The concrete classes (FargateTask and EC2Task) are implementation details and not part of the public API, so users can't directly instantiate them.

I recognize this isn't consistent with the other scheduler targets though (e.g. new targets.SqsSendMessage()) - so for consistency we could refactor as new targets.EcsRunFargateTask() and new targets.EcsRunEc2Task()

Copy link
Member

Choose a reason for hiding this comment

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

Yes i think we should expose this as public api as well so users can directly instantiate to be consistent with other scheduler targets. I'm good with the naming you suggested.

@aws-cdk-automation aws-cdk-automation removed the pr/needs-maintainer-review This PR needs a review from a Core Team Member label Mar 6, 2025
@gracelu0 gracelu0 force-pushed the ecs-run-task-scheduler-target branch 2 times, most recently from 947c4c6 to b0eb93a Compare March 17, 2025 17:41
@shikha372 shikha372 self-assigned this Mar 17, 2025
Copy link
Member

@godwingrs22 godwingrs22 left a comment

Choose a reason for hiding this comment

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

Thanks @gracelu0 for addressing the earlier comments. Left two comments to clarify on the validation.

Comment on lines 294 to 292
if (this.props.taskDefinition.networkMode !== ecs.NetworkMode.AWS_VPC && (this.props.securityGroups || this.props.vpcSubnets)) {
throw new ValidationError('Security groups and subnets can only be used with awsvpc network mode', _schedule);
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if this check is valid. Based on the CFN doc, it doesn't explicitly state that subnets or security groups should not be provided for other network modes.

I think it says as networkConfiguration is required for task definitions that use the awsvpc network mode. I know AWS_VPC network mode needs subnet and security group. But other network modes such as host or bridge i'm not sure if these subnets or secruity group can be used.

Please correct me if my understanding is wrong.

In that case, may be we should validate to check if the vpcSubnets is provided if aws_vpc network mode is used. since subnet is a required property on conditional basis.

if (this.props.taskDefinition.networkMode === ecs.NetworkMode.AWS_VPC && !this.props.vpcSubnets) {
    throw new ValidationError('Subnets must be specified when using awsvpc network mode', _schedule);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The info seems to be scattered across multiple docs 😅 but here's another doc for AwsvpcConfiguration that says:

Properties

AwsvpcConfiguration
Specifies the Amazon VPC subnets and security groups for the task, and whether a public IP address is to be used. 

**This structure is relevant only for ECS tasks that use the awsvpc network mode.**

Based on that, my understanding is that for other network modes like 'host' or 'bridge', subnets and securityGroups should not be specified. I see in the stepfunctions-tasks module for ecs run-task we have some similar validation logic.

In that case, may be we should validate to check if the vpcSubnets is provided if aws_vpc network mode is used. since subnet is a required property on conditional basis.

We could add the validation or default to using the private subnets if user doesn't pass in any subnets and task definition is using AWS_VPC network mode:

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

Setting a default for subnets is the current behaviour for Fargate, I can update EC2 with the same unless you think we should not set any default and instead enforce the user to provide a value.

Copy link
Collaborator

@aws-cdk-automation aws-cdk-automation left a comment

Choose a reason for hiding this comment

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

(This review is outdated)

@gracelu0 gracelu0 force-pushed the ecs-run-task-scheduler-target branch from 1c9c62c to 08fc170 Compare March 19, 2025 00:51
@aws-cdk-automation aws-cdk-automation dismissed their stale review March 19, 2025 00:52

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

@gracelu0 gracelu0 requested a review from godwingrs22 March 19, 2025 18:39
Copy link
Member

@godwingrs22 godwingrs22 left a comment

Choose a reason for hiding this comment

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

Thanks @gracelu0. LGTM overall. Just one question for my understanding before i approve the PR.

Comment on lines 322 to 328
awsvpcConfiguration: {
subnets: this.cluster.vpc.selectSubnets(this.props.vpcSubnets).subnetIds,
securityGroups: this.props.securityGroups?.map((sg) => sg.securityGroupId),
subnets: this.cluster.vpc.selectSubnets(subnetSelection).subnetIds,
securityGroups: (this.props.securityGroups && this.props.securityGroups.length > 0)
?
this.props.securityGroups.map((sg) => sg.securityGroupId)
: undefined,
},
Copy link
Member

@godwingrs22 godwingrs22 Mar 19, 2025

Choose a reason for hiding this comment

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

qq: For my understanding, is assignPublicIp feature not supported for EC2 based tasks ? I see we have it supported for Fargate based tasks. For ec2 based tasks, if the network mode is aws_vpc and subnet is a public subnet then users can still enable assignPublicIp right if they want to connect via public ip?

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 based the implementation on the CloudFormation docs for AWS::Scheduler::Schedule AwsVpcConfiguration, it says under AssignPublicIp:

You can specify ENABLED only when LaunchType in EcsParameters is set to FARGATE.

Copy link
Member

Choose a reason for hiding this comment

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

Thank you for the clarification.

@godwingrs22 godwingrs22 added pr/do-not-merge This PR should not be merged at this time. and removed pr/do-not-merge This PR should not be merged at this time. labels Mar 19, 2025
@mergify
Copy link
Contributor

mergify bot commented Mar 24, 2025

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify
Copy link
Contributor

mergify bot commented Mar 24, 2025

This pull request has been removed from the queue for the following reason: pull request branch update failed.

The pull request can't be updated

You should update or rebase your pull request manually.

If you want to requeue this pull request, you can post a @mergifyio requeue comment.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: 66721c4
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented Mar 24, 2025

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit 3fe58b5 into aws:main Mar 24, 2025
14 checks passed
@github-actions
Copy link
Contributor

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 24, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

contribution/core This is a PR that came from AWS. effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(aws-scheduler-targets-alpha): Add EcsRunTask Target

4 participants