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

Set subnets used by ECS task rather than relying on cdk context #2477

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

philmcmahon
Copy link
Contributor

@philmcmahon philmcmahon commented Oct 15, 2024

What does this change?

I ran into an issue when working with the ecs-task role where I found it only worked if you provided a cdk context file. This was because, by default an EcsRunTask will try to assign itself to the 'PRIVATE' subnets identified by the cdk context file. This works for lurch (which was the project the Ecs task role was created for) because that project is a private repo, with a checked in context file.

Relying on a context file isn't ideal. This PR removes the need for a context file by requiring consumers to either specify which subnets to use directly, or falling back to using GuVpc.subnetsFromParameterFixedNumber

But what is GuVpc.subnetsFromParameterFixedNumber?

Unfortunately, when I tried to use just the normal GuVpc.subnetsFromParameter it resulted in CDK creating a custom resource, presumably to deal with some assumed circular dependency. You can see an example of the custom resource mess here.

The issue is caused by this line in GuVpc:

Subnet.fromSubnetAttributes(scope, `subnet-${subnetId}`, { subnetId, routeTableId: " " }),

With some experimentation, I discovered that if you specify the subnets using .bySubnetId, and use a standard cloudformation list operation (Fn.select), then this custom resource is avoided. The thing is, I was a bit reluctant (scared) to change the existing approach to subnets, as it would affect all GuEc2Apps. The alternative approach of using Fn.select also makes for slightly messier cloudformation output - instead of looking like this:

    "Subnets": {
      "Ref": "testguec2appPublicSubnets",
    },

the subnets definition ends up looking like this:

{"Subnets":["",
              {
                "Fn::Select": [
                  0,
                  {
                    "Ref": "ecstestPrivateSubnets",
                  },
                ],
              },
              "","",
              {
                "Fn::Select": [
                  1,
                  {
                    "Ref": "ecstestPrivateSubnets",
                  },
                ],
              },
              "","",
              {
                "Fn::Select": [
                  2,
                  {
                    "Ref": "ecstestPrivateSubnets",
                  },
                ],
              },
              ""]

The new approach also assumes knowledge of how many subnets there are - whilst we usually have 3, in the tests we sometimes just have one, so more effort would be needed there.

I think this approach is a reasonable compromise, but very happy to talk it through/try to pair on a better solution.

Whilst I try and resolve that, this is a placeholder PR so I can share the work with others

How to test

Copy link

changeset-bot bot commented Oct 15, 2024

🦋 Changeset detected

Latest commit: 284f7d2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@guardian/cdk Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@philmcmahon philmcmahon changed the title [WIP not ready for review] Set subnets used by ECS task using GuVpc.subnetsFromParameter Set subnets used by ECS task rather than relying on cdk context Oct 16, 2024
@philmcmahon philmcmahon marked this pull request as ready for review October 16, 2024 11:54
@philmcmahon philmcmahon requested a review from a team October 16, 2024 12:15
Comment on lines +200 to +205
const taskSubnets = subnets
? subnets
: assignPublicIp
? GuVpc.subnetsFromParameterFixedNumber(scope, { type: SubnetType.PUBLIC, app }, 3)
: GuVpc.subnetsFromParameterFixedNumber(scope, { type: SubnetType.PRIVATE, app }, 3);

Copy link
Member

Choose a reason for hiding this comment

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

I think this nested ternary is unnecessary complexity; could we remove the assignPublicIp prop and pass in the correct subnets when instantiating this construct? The consequence is the subnets prop becomes mandatory, but I think it'll result in a simpler interface. For example:

new GuEcsTask(scope, "my-task", {
  subnets: GuVpc.subnetsFromParameterFixedNumber(scope, { type: SubnetType.PUBLIC, app }
});

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants