-
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(aws-ec2): add VPC context provider #1168
Conversation
Add a context provider for looking up existing VPCs in an account. This is useful if the VPC is defined outside of your CDK app, such as in a different CDK app, by hand or in a CloudFormation template. Addresses some need of #1095.
89d5266
to
631eeb1
Compare
packages/@aws-cdk/aws-ec2/README.md
Outdated
#### Sharing VPCs across stacks | ||
|
||
If you are creating multiple `Stack`s inside the same CDK application, | ||
you can reuse a VPC from one Stack in another by using `export()` and |
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.
"to another"
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.
No, I don't think that's correct.
@@ -0,0 +1,21 @@ | |||
export const VPC_PROVIDER = 'vpc-provider'; | |||
|
|||
export interface VpcContextQuery { |
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.
Doc?
const tags: {[key: string]: string} | undefined = args.tags; | ||
const isDefault: boolean | undefined = args.isDefault; | ||
|
||
// Builter request filter |
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.
Build
|
||
// Builter request filter | ||
const filters: AWS.EC2.Filter[] = []; | ||
if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); } |
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.
Why not just expose the filters API in the context provider API and move the logic of building the filters to the construct library?
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.
@rix0rrr might still be recovering from when I used the word filter
and he really didn't like it, but this context is different and I won't give him too hard a time if filter
comes back.
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 guess I wanted as narrow an API as possible. But yeah, I suppose it makes it easier to add features in the future.
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.
Just feels like we can expose this to the user and give them more power without sacrificing too much usability (maybe we can add a bunch of sugar methods for the common use cases)
azs.sort(); | ||
|
||
const subnets: Subnet[] = listedSubnets.map(subnet => { | ||
let type = getTag('aws-cdk:SubnetType', subnet.Tags); |
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 think we try to standardize around something like aws:cdk:subnet-type
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.
can we set an aws:
tag? or does it have to be aws-cdk
?
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.
Don't believe we can set the aws:
tag.
// - Type tag, we tag subnets with their type | ||
// - Name tag, we tag subnets with their subnet group name | ||
// - MapPublicIpOnLaunch in absence of tags => must be a Public subnet, anything else is either Isolated or Private | ||
|
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.
Also mention that"type" is used as a name if we don't have a name tag
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 actual source of truth for this is the route table. I was thinking the logic would be check for our Type
tag and trust that CDK is the source of truth if it exists. If that is not there pull the route tables. If a route exists to an IGW (public), only NAT (private), neither (isolated). Yes there are egress only gateways and I'm not sure if those are public or private, my vote is private.
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 know, but that seemed like overcomplicating.
So for non-CDK-exported VPCs we only support public/private nets, for CDK-exported VPCs we support isolated subnets as well. Seems like a fair compromise.
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 happen to know my legacy VPCs do not set MapPublicIpOnLaunch
to true for public subnets. I'm not positive if it was a secure by default argument or a non-repudiation (the non EIP public IPs are never in Cloud Trail). I do agree this is more complicated, and if we launch without it and let the community drive the request I'm probably ok.
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 would argue in those cases you can always add the tags manually.
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.
Small comments, but my big question is should route table be the subnet type source of truth.
const SUBNETTYPE_TAG = 'aws-cdk:SubnetType'; | ||
const SUBNETNAME_TAG = 'aws-cdk:SubnetName'; | ||
|
||
function subnetTypeTagValue(type: SubnetType) { |
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.
This makes me think we should have used String enums for this type.
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.
Maybe so. It's not too onerous to have this function I think.
|
||
// Builter request filter | ||
const filters: AWS.EC2.Filter[] = []; | ||
if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); } |
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.
@rix0rrr might still be recovering from when I used the word filter
and he really didn't like it, but this context is different and I won't give him too hard a time if filter
comes back.
// - Type tag, we tag subnets with their type | ||
// - Name tag, we tag subnets with their subnet group name | ||
// - MapPublicIpOnLaunch in absence of tags => must be a Public subnet, anything else is either Isolated or Private | ||
|
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 actual source of truth for this is the route table. I was thinking the logic would be check for our Type
tag and trust that CDK is the source of truth if it exists. If that is not there pull the route tables. If a route exists to an IGW (public), only NAT (private), neither (isolated). Yes there are egress only gateways and I'm not sure if those are public or private, my vote is private.
azs.sort(); | ||
|
||
const subnets: Subnet[] = listedSubnets.map(subnet => { | ||
let type = getTag('aws-cdk:SubnetType', subnet.Tags); |
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.
can we set an aws:
tag? or does it have to be aws-cdk
?
/** | ||
* Group subnets of the same type together, and order by AZ | ||
*/ | ||
function groupSubnets(subnets: Subnet[]): SubnetGroups { |
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.
+1 have to sort these
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.
It's not even optional :)
Purpose: 'WebServices' | ||
} | ||
}); | ||
const vpc = VpcNetworkRef.import(this, 'VPC', provider.vpcProps); |
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.
Should we also include the VpcNetwork.importFromContext
usage in this example?
|
||
/** | ||
* Properties for looking up an existing VPC. | ||
* |
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.
Reference AWS docs page that describes the query API
} | ||
|
||
// These values will be used to recover the config upon provider import |
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.
Mention the name of the context provider class here
* Query region | ||
*/ | ||
region?: string; | ||
|
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.
Redundant
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.
It's not, though I suppose I could model it differently.
* Query region | ||
*/ | ||
region?: string; | ||
|
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 would put this under filters: any[]
to avoid the need to define this in 100% places.
|
||
// Builter request filter | ||
const filters: AWS.EC2.Filter[] = []; | ||
if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); } |
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.
Just feels like we can expose this to the user and give them more power without sacrificing too much usability (maybe we can add a bunch of sugar methods for the common use cases)
Add a context provider for looking up existing VPCs in an account. This
is useful if the VPC is defined outside of your CDK app, such as in a
different CDK app, by hand or in a CloudFormation template.
Addresses some need of #1095.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.