-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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(ecs): container port ranges in port mappings #26692
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pull request linter has failed. See the aws-cdk-automation comment below for failure reasons. If you believe this pull request should receive an exemption, please comment and provide a justification.
A comment requesting an exemption should contain the text Exemption Request
. Additionally, if clarification is needed add Clarification Request
to a comment.
✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this. It seems like a rather involved change so I want to make sure I understand the possible implications before we ship it.
packages/aws-cdk-lib/aws-ecs-patterns/lib/ecs/network-multiple-target-groups-ecs-service.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also considering that the breaking change you are making (switching a property from required to optional) is not allowed if the structure you're doing this in is exposed to be read by customer code somewhere.
Someone could have written this code:
const somePort: number = container.portMapping.containerPort;
console.log(somePort);
This code used to be fine, but after your change will fail to compile with number | undefined is not assignable to number
.
That type of change is not allowed.
Unfortunately, I don't think there is any other way to implement this feature within the current code as |
I agree this is not optimal. Something we could consider is passing values through the token system. We could do something like: class PortRange implements cdk.IResolvable {
public readonly creationStack: string[] = [];
public readonly typeHint?: cdk.ResolutionTypeHint;
public readonly isPortRange = true;
public static of(startPort: number, endPort: number): number {
return cdk.Token.asNumber(new PortRange(startPort, endPort));
}
public static tryDetect(port: number): PortRange | undefined {
const x = cdk.Tokenization.reverseNumber(port);
return x && (x as any).isPortRange ? x as PortRange : undefined;
}
private constructor(public readonly startPort: number, public readonly endPort: number) { }
public resolve(_context: cdk.IResolveContext) {
// This should not end up in a CFN template, so does not need to implement
// resolve()
throw new Error('PortRange may only be passed to ECS PortMapping\'s containerPort');
}
public toString(): string {
return cdk.Token.asString(this);
}
} This is using some dark token magic, but it will work. We can use that to smuggle a We would use that instead of adding a new property. Demo: const x = PortRange.of(1000, 2000);
console.log(x);
// -1.8881545897087535e+289
console.log(PortRange.tryDetect(x));
/*
PortRange {
startPort: 1000,
endPort: 2000,
creationStack: [],
typeHint: 'string'
}
*/ |
Or the following, which is not as nice but much more simple: const portMapping: PortMapping = {
containerPort: 0, // Magic value
portRange: '1000-2000',
}; Potentially with a This is probably preferable for understandability and discoverability. |
If I understand correctly, you would leave |
Indeed.
Yes, but it's not all that bad.
As much as the trick feels neat, this is more discoverable than pulling in the magic |
I have to admit that, before opening this PR, I thought a lot about adding a |
I have implemented all the requested changes. There are still some outstanding points above, feel free to mark the conversations as done if you are satisfied with the replies or add more feedback on how I should proceed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll ship it! Thanks for this.
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). |
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). |
It seems that |
Build is now failing because of different NodeJS version used for a resource in the integration test I've added. Do I have to update the snapshot or can you do it for me? |
Thanks for updating the test snapshot. Unfortunately, there is one more problem that makes the build fail, but seems to be unrelated 😭 Maybe another pull of the changes from the |
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). |
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). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
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). |
Amazon ECS supports container port ranges for port mapping since quite a bit, however the
ContainerDefinition
L2 construct does not expose a way to set them. Right now, the only viable solution I found to use the feature is using Escape Hatches. Within this PR, thecontainerPortRange
property is added to thePortMapping
object and mapped back to the underlying L1 construct.The current implementation contains a breaking change: since setting both a port range and a single fixed port doesn't make sense, I had to mark optional all the properties of
PortMapping
, hence thecontainerPort
property changed its type fromnon-nullable
tonullable
. The downside of the proposed solution is that now all the properties are optional and the compiler doesn't complain if an empty object is passed as port mapping. I added some runtime checks to ensure that a valid object is created, but I didn't find a better way to do it at compile time that is also compatible with the transformation done byjsii
.Closes #23509.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license