From 631eeb14792bb9e1ea9ad5732d239db4f1d01f37 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Tue, 13 Nov 2018 16:15:14 +0100 Subject: [PATCH 1/8] feat(aws-ec2): add VPC context provider 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. --- docs/src/context.rst | 13 ++ packages/@aws-cdk/aws-ec2/README.md | 12 ++ packages/@aws-cdk/aws-ec2/lib/index.ts | 1 + .../aws-ec2/lib/vpc-network-provider.ts | 76 +++++++ packages/@aws-cdk/aws-ec2/lib/vpc-ref.ts | 8 + packages/@aws-cdk/aws-ec2/lib/vpc.ts | 22 ++ packages/@aws-cdk/aws-ec2/package.json | 2 + .../aws-ec2/test/example.share-vpcs.lit.ts | 40 ++++ ...integ.import-default-vpc.lit.expected.json | 33 +++ .../test/integ.import-default-vpc.lit.ts | 24 +++ packages/@aws-cdk/cx-api/lib/context/vpc.ts | 21 ++ packages/@aws-cdk/cx-api/lib/index.ts | 1 + packages/aws-cdk/bin/cdk.ts | 10 +- .../context-providers/availability-zones.ts | 22 ++ .../hosted-zones.ts} | 81 +------- .../aws-cdk/lib/context-providers/index.ts | 43 ++++ .../aws-cdk/lib/context-providers/provider.ts | 3 + .../lib/context-providers/ssm-parameters.ts | 28 +++ .../aws-cdk/lib/context-providers/vpcs.ts | 193 ++++++++++++++++++ tools/cdk-integ-tools/lib/integ-helpers.ts | 20 ++ 20 files changed, 569 insertions(+), 84 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts create mode 100644 packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts create mode 100644 packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.expected.json create mode 100644 packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.ts create mode 100644 packages/@aws-cdk/cx-api/lib/context/vpc.ts create mode 100644 packages/aws-cdk/lib/context-providers/availability-zones.ts rename packages/aws-cdk/lib/{contextplugins.ts => context-providers/hosted-zones.ts} (52%) create mode 100644 packages/aws-cdk/lib/context-providers/index.ts create mode 100644 packages/aws-cdk/lib/context-providers/provider.ts create mode 100644 packages/aws-cdk/lib/context-providers/ssm-parameters.ts create mode 100644 packages/aws-cdk/lib/context-providers/vpcs.ts diff --git a/docs/src/context.rst b/docs/src/context.rst index 1ea6441a77dca..f35ac42f16d15 100644 --- a/docs/src/context.rst +++ b/docs/src/context.rst @@ -42,3 +42,16 @@ The |cdk| currently supports the following context providers. .. code:: js const ami: string = new SSMParameterProvider(this).getString('my-awesome-value'); + +:py:class:`VpcNetworkProvider <@aws-cdk/aws-ec2.VpcNetworkProvider>` + Use this provider to look up and reference existing VPC in your accounts. + For example, the follow code imports a VPC by tag name: + +.. code:: js + + const provider = new VpcNetworkProvider(this, { + tags: { + Purpose: 'WebServices' + } + }); + const vpc = VpcNetworkRef.import(this, 'VPC', provider.vpcProps); diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index bbb3b6fd7a59e..4cc2a36b0c183 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -172,6 +172,18 @@ The `VpcNetwork` above will have the exact same subnet definitions as listed above. However, this time the VPC will have only 1 NAT Gateway and all Application subnets will route to the NAT Gateway. +#### 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 +`import()`: + +[sharing VPCs between stacks](test/example.share-vpcs.lit.ts) + +If your VPC is created outside your CDK app, you can use `importFromContext()`: + +[importing existing VPCs](test/integ.import-default-vpc.lit.ts) + ### Allowing Connections In AWS, all network traffic in and out of **Elastic Network Interfaces** (ENIs) diff --git a/packages/@aws-cdk/aws-ec2/lib/index.ts b/packages/@aws-cdk/aws-ec2/lib/index.ts index 9e6e38d27bba0..bade088217cae 100644 --- a/packages/@aws-cdk/aws-ec2/lib/index.ts +++ b/packages/@aws-cdk/aws-ec2/lib/index.ts @@ -5,6 +5,7 @@ export * from './security-group'; export * from './security-group-rule'; export * from './vpc'; export * from './vpc-ref'; +export * from './vpc-network-provider'; // AWS::EC2 CloudFormation Resources: export * from './ec2.generated'; diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts new file mode 100644 index 0000000000000..3268e9a90d0ce --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts @@ -0,0 +1,76 @@ +import cdk = require('@aws-cdk/cdk'); +import cxapi = require('@aws-cdk/cx-api'); +import { VpcNetworkRefProps } from './vpc-ref'; + +/** + * Properties for looking up an existing VPC. + * + * The combination of properties must specify filter down to exactly one + * non-default VPC, otherwise an error is raised. + */ +export interface VpcNetworkProviderProps { + /** + * The ID of the VPC + * + * If given, will import exactly this VPC. + * + * @default Don't filter on vpcId + */ + vpcId?: string; + + /** + * The name of the VPC + * + * If given, will import the VPC with this name. + * + * @default Don't filter on vpcName + */ + vpcName?: string; + + /** + * Tags on the VPC + * + * The VPC must have all of these tags + * + * @default Don't filter on tags + */ + tags?: {[key: string]: string}; + + /** + * Whether to match the default VPC + * + * @default Don't care whether we return the default VPC + */ + isDefault?: boolean; +} + +/** + * Context provider to discover and import existing VPCs + */ +export class VpcNetworkProvider { + private provider: cdk.ContextProvider; + + constructor(context: cdk.Construct, props: VpcNetworkProviderProps) { + this.provider = new cdk.ContextProvider(context, cxapi.VPC_PROVIDER, props as cxapi.VpcContextQuery); + } + + /** + * Return the VPC import props matching the filter + */ + public get vpcProps(): VpcNetworkRefProps { + const ret: cxapi.VpcContextResponse = this.provider.getValue(DUMMY_VPC_PROPS); + return ret; + } +} + +/** + * There are returned when the provider has not supplied props yet + * + * It's only used for testing and on the first run-through. + */ +const DUMMY_VPC_PROPS: cxapi.VpcContextResponse = { + availabilityZones: ['dummy-1a', 'dummy-1b'], + vpcId: 'vpc-12345', + publicSubnetIds: ['s-12345', 's-67890'], + privateSubnetIds: ['p-12345', 'p-67890'], +}; diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-ref.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-ref.ts index 59d0381c92f39..9833283d2c7a4 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-ref.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-ref.ts @@ -1,5 +1,6 @@ import { Construct, IDependable, Output } from "@aws-cdk/cdk"; import { ExportSubnetGroup, ImportSubnetGroup, subnetName } from './util'; +import { VpcNetworkProvider, VpcNetworkProviderProps } from './vpc-network-provider'; /** * The type of Subnet @@ -81,6 +82,13 @@ export abstract class VpcNetworkRef extends Construct implements IDependable { return new ImportedVpcNetwork(parent, name, props); } + /** + * Import an existing VPC from context + */ + public static importFromContext(parent: Construct, name: string, props: VpcNetworkProviderProps): VpcNetworkRef { + return VpcNetworkRef.import(parent, name, new VpcNetworkProvider(parent, props).vpcProps); + } + /** * Identifier for this VPC */ diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index 41bc9b97bcfdc..8483fc47e4c7c 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -407,24 +407,46 @@ export class VpcNetwork extends VpcNetworkRef implements cdk.ITaggable { tags: subnetConfig.tags, }; + let subnet: VpcSubnet; switch (subnetConfig.subnetType) { case SubnetType.Public: const publicSubnet = new VpcPublicSubnet(this, name, subnetProps); this.publicSubnets.push(publicSubnet); + subnet = publicSubnet; break; case SubnetType.Private: const privateSubnet = new VpcPrivateSubnet(this, name, subnetProps); this.privateSubnets.push(privateSubnet); + subnet = privateSubnet; break; case SubnetType.Isolated: const isolatedSubnet = new VpcPrivateSubnet(this, name, subnetProps); + isolatedSubnet.tags.setTag(SUBNETTYPE_TAG, subnetTypeTagValue(subnetConfig.subnetType)); this.isolatedSubnets.push(isolatedSubnet); + subnet = isolatedSubnet; break; + default: + throw new Error(`Unrecognized subnet type: ${subnetConfig.subnetType}`); } + + // These values will be used to recover the config upon provider import + subnet.tags.setTag(SUBNETNAME_TAG, subnetConfig.name); + subnet.tags.setTag(SUBNETTYPE_TAG, subnetTypeTagValue(subnetConfig.subnetType)); }); } } +const SUBNETTYPE_TAG = 'aws-cdk:SubnetType'; +const SUBNETNAME_TAG = 'aws-cdk:SubnetName'; + +function subnetTypeTagValue(type: SubnetType) { + switch (type) { + case SubnetType.Public: return 'Public'; + case SubnetType.Private: return 'Private'; + case SubnetType.Isolated: return 'Isolated'; + } +} + /** * Specify configuration parameters for a VPC subnet */ diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index 47a6af8b806a9..cd37a9628d679 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -60,10 +60,12 @@ }, "dependencies": { "@aws-cdk/aws-iam": "^0.16.0", + "@aws-cdk/cx-api": "^0.16.0", "@aws-cdk/cdk": "^0.16.0" }, "homepage": "https://github.com/awslabs/aws-cdk", "peerDependencies": { + "@aws-cdk/cx-api": "^0.16.0", "@aws-cdk/cdk": "^0.16.0" } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts b/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts new file mode 100644 index 0000000000000..7cdc7fdced354 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts @@ -0,0 +1,40 @@ +import cdk = require('@aws-cdk/cdk'); +import ec2 = require("../lib"); + +const app = new cdk.App(); + +/// !show +class Stack1 extends cdk.Stack { + public readonly vpcProps: ec2.VpcNetworkRefProps; + + constructor(parent: cdk.App, id: string, props?: cdk.StackProps) { + super(parent, id, props); + + const vpc = new ec2.VpcNetwork(this, 'VPC'); + + // Export the VPC to a set of properties + this.vpcProps = vpc.export(); + } +} + +interface Stack2Props extends cdk.StackProps { + vpcProps: ec2.VpcNetworkRefProps; +} + +class Stack2 extends cdk.Stack { + constructor(parent: cdk.App, id: string, props: Stack2Props) { + super(parent, id, props); + + // Import the VPC from a set of properties + const vpc = ec2.VpcNetworkRef.import(this, 'VPC', props.vpcProps); + } +} + +const stack1 = new Stack1(app, 'Stack1'); +const stack2 = new Stack2(app, 'Stack2', { + vpcProps: stack1.vpcProps +}); +/// !hide + +app.run(); + diff --git a/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.expected.json b/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.expected.json new file mode 100644 index 0000000000000..37edfef83075b --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.expected.json @@ -0,0 +1,33 @@ +{ + "Resources": { + "SecurityGroupDD263621": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-ec2-import/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [], + "VpcId": "vpc-60900905" + } + } + }, + "Outputs": { + "PublicSubnets": { + "Value": "ids:subnet-e19455ca,subnet-e0c24797,subnet-ccd77395", + "Export": { + "Name": "aws-cdk-ec2-import:PublicSubnets" + } + }, + "PrivateSubnets": { + "Value": "ids:", + "Export": { + "Name": "aws-cdk-ec2-import:PrivateSubnets" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.ts b/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.ts new file mode 100644 index 0000000000000..2a9fb8921c65f --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.lit.ts @@ -0,0 +1,24 @@ +import cdk = require('@aws-cdk/cdk'); +import ec2 = require("../lib"); + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-ec2-import'); + +/// !show +const vpc = ec2.VpcNetworkRef.importFromContext(stack, 'VPC', { + // This imports the default VPC but you can also + // specify a 'vpcName' or 'tags'. + isDefault: true +}); +/// !hide + +// The only thing in this library that takes a VPC as an argument :) +new ec2.SecurityGroup(stack, 'SecurityGroup', { + vpc +}); + +// Try subnet selection +new cdk.Output(stack, 'PublicSubnets', { value: 'ids:' + vpc.subnets({ subnetsToUse: ec2.SubnetType.Public }).map(s => s.subnetId).join(',') }); +new cdk.Output(stack, 'PrivateSubnets', { value: 'ids:' + vpc.subnets({ subnetsToUse: ec2.SubnetType.Private }).map(s => s.subnetId).join(',') }); + +app.run(); diff --git a/packages/@aws-cdk/cx-api/lib/context/vpc.ts b/packages/@aws-cdk/cx-api/lib/context/vpc.ts new file mode 100644 index 0000000000000..7eb832a77a461 --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/context/vpc.ts @@ -0,0 +1,21 @@ +export const VPC_PROVIDER = 'vpc-provider'; + +export interface VpcContextQuery { + region: string; + account: string; + vpcId?: string; + vpcName?: string; + tags?: {[key: string]: string}; + isDefault?: boolean; +} + +export interface VpcContextResponse { + vpcId: string; + availabilityZones: string[]; + publicSubnetIds?: string[]; + publicSubnetNames?: string[]; + privateSubnetIds?: string[]; + privateSubnetNames?: string[]; + isolatedSubnetIds?: string[]; + isolatedSubnetNames?: string[]; +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index 6077a01aa9581..e788c1b1ba995 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -1,2 +1,3 @@ export * from './cxapi'; export * from './environment'; +export * from './context/vpc'; diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index 3e36a8a4ed68a..3ea0c910d38ef 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -10,7 +10,7 @@ import yargs = require('yargs'); import cdkUtil = require('../lib/util'); import { bootstrapEnvironment, deployStack, destroyStack, loadToolkitInfo, Mode, SDK } from '../lib'; -import contextplugins = require('../lib/contextplugins'); +import contextproviders = require('../lib/context-providers/index'); import { printStackDiff } from '../lib/diff'; import { execProgram } from '../lib/exec'; import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init'; @@ -115,12 +115,6 @@ async function initCommandLine() { ec2creds: argv.ec2creds, }); - const availableContextProviders: contextplugins.ProviderMap = { - 'availability-zones': new contextplugins.AZContextProviderPlugin(aws), - 'ssm': new contextplugins.SSMContextProviderPlugin(aws), - 'hosted-zone': new contextplugins.HostedZoneContextProviderPlugin(aws), - }; - const defaultConfig = new Settings({ versionReporting: true }); const userConfig = await new Settings().load(PER_USER_DEFAULTS); const projectConfig = await new Settings().load(DEFAULTS); @@ -384,7 +378,7 @@ async function initCommandLine() { if (!cdkUtil.isEmpty(allMissing)) { debug(`Some context information is missing. Fetching...`); - await contextplugins.provideContextValues(allMissing, projectConfig, availableContextProviders); + await contextproviders.provideContextValues(allMissing, projectConfig, aws); // Cache the new context to disk await projectConfig.save(DEFAULTS); diff --git a/packages/aws-cdk/lib/context-providers/availability-zones.ts b/packages/aws-cdk/lib/context-providers/availability-zones.ts new file mode 100644 index 0000000000000..f6f80c60150c3 --- /dev/null +++ b/packages/aws-cdk/lib/context-providers/availability-zones.ts @@ -0,0 +1,22 @@ +import { Mode, SDK } from '../api'; +import { debug } from '../logging'; +import { ContextProviderPlugin } from './provider'; + +/** + * Plugin to retrieve the Availability Zones for the current account + */ +export class AZContextProviderPlugin implements ContextProviderPlugin { + constructor(private readonly aws: SDK) { + } + + public async getValue(args: {[key: string]: any}) { + const region = args.region; + const account = args.account; + debug(`Reading AZs for ${account}:${region}`); + const ec2 = await this.aws.ec2(account, region, Mode.ForReading); + const response = await ec2.describeAvailabilityZones().promise(); + if (!response.AvailabilityZones) { return []; } + const azs = response.AvailabilityZones.filter(zone => zone.State === 'available').map(zone => zone.ZoneName); + return azs; + } +} \ No newline at end of file diff --git a/packages/aws-cdk/lib/contextplugins.ts b/packages/aws-cdk/lib/context-providers/hosted-zones.ts similarity index 52% rename from packages/aws-cdk/lib/contextplugins.ts rename to packages/aws-cdk/lib/context-providers/hosted-zones.ts index 8af2987a3d214..6ae4c7f7c537d 100644 --- a/packages/aws-cdk/lib/contextplugins.ts +++ b/packages/aws-cdk/lib/context-providers/hosted-zones.ts @@ -1,57 +1,6 @@ -import cxapi = require('@aws-cdk/cx-api'); -import { Mode, SDK } from './api'; -import { debug } from './logging'; -import { Settings } from './settings'; - -export interface ContextProviderPlugin { - getValue(args: {[key: string]: any}): Promise; -} - -export type ProviderMap = {[name: string]: ContextProviderPlugin}; - -/** - * Plugin to retrieve the Availability Zones for the current account - */ -export class AZContextProviderPlugin implements ContextProviderPlugin { - constructor(private readonly aws: SDK) { - } - - public async getValue(args: {[key: string]: any}) { - const region = args.region; - const account = args.account; - debug(`Reading AZs for ${account}:${region}`); - const ec2 = await this.aws.ec2(account, region, Mode.ForReading); - const response = await ec2.describeAvailabilityZones().promise(); - if (!response.AvailabilityZones) { return []; } - const azs = response.AvailabilityZones.filter(zone => zone.State === 'available').map(zone => zone.ZoneName); - return azs; - } -} - -/** - * Plugin to read arbitrary SSM parameter names - */ -export class SSMContextProviderPlugin implements ContextProviderPlugin { - constructor(private readonly aws: SDK) { - } - - public async getValue(args: {[key: string]: any}) { - const region = args.region; - const account = args.account; - if (!('parameterName' in args)) { - throw new Error('parameterName must be provided in props for SSMContextProviderPlugin'); - } - const parameterName = args.parameterName; - debug(`Reading SSM parameter ${account}:${region}:${parameterName}`); - - const ssm = await this.aws.ssm(account, region, Mode.ForReading); - const response = await ssm.getParameter({ Name: parameterName }).promise(); - if (!response.Parameter || response.Parameter.Value === undefined) { - throw new Error(`SSM parameter not available in account ${account}, region ${region}: ${parameterName}`); - } - return response.Parameter.Value; - } -} +import { Mode, SDK } from '../api'; +import { debug } from '../logging'; +import { ContextProviderPlugin } from './provider'; export interface HostedZoneProviderProps { /** @@ -82,7 +31,7 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { const account = args.account; const region = args.region; if (!this.isHostedZoneProps(args)) { - throw new Error(`HostedZoneProvider requires domainName property to be set in ${args.props}`); + throw new Error(`HostedZoneProvider requires domainName property to be set in ${args}`); } const domainName = args.domainName; debug(`Reading hosted zone ${account}:${region}:${domainName}`); @@ -133,24 +82,4 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { private isHostedZoneProps(props: HostedZoneProviderProps | any): props is HostedZoneProviderProps { return (props as HostedZoneProviderProps).domainName !== undefined; } -} -/** - * Iterate over the list of missing context values and invoke the appropriate providers from the map to retrieve them - */ -export async function provideContextValues( - missingValues: { [key: string]: cxapi.MissingContext }, - projectConfig: Settings, - availableContextProviders: ProviderMap) { - for (const key of Object.keys(missingValues)) { - const missingContext = missingValues[key]; - - const provider = availableContextProviders[missingContext.provider]; - if (!provider) { - throw new Error(`Unrecognized context provider name: ${missingContext.provider}`); - } - - const value = await provider.getValue(missingContext.props); - projectConfig.set(['context', key], value); - debug(`Setting "${key}" context to ${JSON.stringify(value)}`); - } -} +} \ No newline at end of file diff --git a/packages/aws-cdk/lib/context-providers/index.ts b/packages/aws-cdk/lib/context-providers/index.ts new file mode 100644 index 0000000000000..84b842f268090 --- /dev/null +++ b/packages/aws-cdk/lib/context-providers/index.ts @@ -0,0 +1,43 @@ +import cxapi = require('@aws-cdk/cx-api'); +import { SDK } from '../api/util/sdk'; +import { debug } from '../logging'; +import { Settings } from '../settings'; +import { AZContextProviderPlugin } from './availability-zones'; +import { HostedZoneContextProviderPlugin } from './hosted-zones'; +import { ContextProviderPlugin } from './provider'; +import { SSMContextProviderPlugin } from './ssm-parameters'; +import { VpcNetworkContextProviderPlugin } from './vpcs'; + +type ProviderConstructor = (new (sdk: SDK) => ContextProviderPlugin); +export type ProviderMap = {[name: string]: ProviderConstructor}; + +/** + * Iterate over the list of missing context values and invoke the appropriate providers from the map to retrieve them + */ +export async function provideContextValues( + missingValues: { [key: string]: cxapi.MissingContext }, + projectConfig: Settings, + sdk: SDK) { + for (const key of Object.keys(missingValues)) { + const missingContext = missingValues[key]; + + const constructor = availableContextProviders[missingContext.provider]; + if (!constructor) { + // tslint:disable-next-line:max-line-length + throw new Error(`Unrecognized context provider name: ${missingContext.provider}. You might need to update the toolkit to match the version of the construct library.`); + } + + const provider = new constructor(sdk); + + const value = await provider.getValue(missingContext.props); + projectConfig.set(['context', key], value); + debug(`Setting "${key}" context to ${JSON.stringify(value)}`); + } +} + +const availableContextProviders: ProviderMap = { + 'availability-zones': AZContextProviderPlugin, + 'ssm': SSMContextProviderPlugin, + 'hosted-zone': HostedZoneContextProviderPlugin, + [cxapi.VPC_PROVIDER]: VpcNetworkContextProviderPlugin, +}; diff --git a/packages/aws-cdk/lib/context-providers/provider.ts b/packages/aws-cdk/lib/context-providers/provider.ts new file mode 100644 index 0000000000000..3d8a59938e9ef --- /dev/null +++ b/packages/aws-cdk/lib/context-providers/provider.ts @@ -0,0 +1,3 @@ +export interface ContextProviderPlugin { + getValue(args: {[key: string]: any}): Promise; +} diff --git a/packages/aws-cdk/lib/context-providers/ssm-parameters.ts b/packages/aws-cdk/lib/context-providers/ssm-parameters.ts new file mode 100644 index 0000000000000..be561fcef3415 --- /dev/null +++ b/packages/aws-cdk/lib/context-providers/ssm-parameters.ts @@ -0,0 +1,28 @@ +import { Mode, SDK } from '../api'; +import { debug } from '../logging'; +import { ContextProviderPlugin } from './provider'; + +/** + * Plugin to read arbitrary SSM parameter names + */ +export class SSMContextProviderPlugin implements ContextProviderPlugin { + constructor(private readonly aws: SDK) { + } + + public async getValue(args: {[key: string]: any}) { + const region = args.region; + const account = args.account; + if (!('parameterName' in args)) { + throw new Error('parameterName must be provided in props for SSMContextProviderPlugin'); + } + const parameterName = args.parameterName; + debug(`Reading SSM parameter ${account}:${region}:${parameterName}`); + + const ssm = await this.aws.ssm(account, region, Mode.ForReading); + const response = await ssm.getParameter({ Name: parameterName }).promise(); + if (!response.Parameter || response.Parameter.Value === undefined) { + throw new Error(`SSM parameter not available in account ${account}, region ${region}: ${parameterName}`); + } + return response.Parameter.Value; + } +} diff --git a/packages/aws-cdk/lib/context-providers/vpcs.ts b/packages/aws-cdk/lib/context-providers/vpcs.ts new file mode 100644 index 0000000000000..daaa5b0ba7662 --- /dev/null +++ b/packages/aws-cdk/lib/context-providers/vpcs.ts @@ -0,0 +1,193 @@ +import cxapi = require('@aws-cdk/cx-api'); +import AWS = require('aws-sdk'); +import { Mode, SDK } from '../api'; +import { debug } from '../logging'; +import { ContextProviderPlugin } from './provider'; + +export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { + + constructor(private readonly aws: SDK) { + } + + public async getValue(args: cxapi.VpcContextQuery) { + const account: string = args.account; + const region: string = args.region; + + const ec2 = await this.aws.ec2(account, region, Mode.ForReading); + + const vpcId = await this.findVpc(ec2, args); + + return await this.readVpcProps(ec2, vpcId); + } + + private async findVpc(ec2: AWS.EC2, args: {[key: string]: any}): Promise { + const vpcId: string | undefined = args.vpcId; + const vpcName: string | undefined = args.vpcName; + const tags: {[key: string]: string} | undefined = args.tags; + const isDefault: boolean | undefined = args.isDefault; + + // Builter request filter + const filters: AWS.EC2.Filter[] = []; + if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); } + if (vpcName) { filters.push({ Name: 'tag:Name', Values: [vpcName] }); } + if (tags) { + for (const [tag, value] of Object.entries(tags)) { + filters.push({ Name: `tag:${tag}`, Values: [value] }); + } + } + if (isDefault !== undefined) { + filters.push({ Name: 'isDefault', Values: [isDefault ? 'true' : 'false'] }); + } + + debug(`Listing VPCs in ${args.account}:${args.region}`); + const response = await ec2.describeVpcs({ Filters: filters }).promise(); + + const vpcs = response.Vpcs || []; + if (vpcs.length === 0) { + throw new Error(`Could not find any VPCs matching ${JSON.stringify(args)}`); + } + if (vpcs.length > 1) { + throw new Error(`Found ${vpcs.length} VPCs matching ${JSON.stringify(args)}; please narrow the search criteria`); + } + + return vpcs[0].VpcId!; + } + + private async readVpcProps(ec2: AWS.EC2, vpcId: string): Promise { + debug(`Describing VPC ${vpcId}`); + + const response = await ec2.describeSubnets({ Filters: [{ Name: 'vpc-id', Values: [vpcId] }] }).promise(); + const listedSubnets = response.Subnets || []; + + // Now comes our job to separate these subnets out into AZs and subnet groups (Public, Private, Isolated) + // We have the following attributes to go on: + // - 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 + + const azs = Array.from(new Set(listedSubnets.map(s => s.AvailabilityZone!))); + azs.sort(); + + const subnets: Subnet[] = listedSubnets.map(subnet => { + let type = getTag('aws-cdk:SubnetType', subnet.Tags); + if (type === undefined) { + type = subnet.MapPublicIpOnLaunch ? 'Public' : 'Private'; + } + + const name = getTag('aws-cdk:SubnetName', subnet.Tags) || type; + + return { az: subnet.AvailabilityZone!, type: type as SubnetType, name, subnetId: subnet.SubnetId! }; + }); + + const grouped = groupSubnets(subnets); + + return { + vpcId, + availabilityZones: grouped.azs, + isolatedSubnetIds: collapse(flatMap(findGroups(SubnetType.Isolated, grouped), group => group.subnets.map(s => s.subnetId))), + isolatedSubnetNames: collapse(flatMap(findGroups(SubnetType.Isolated, grouped), group => group.name ? [group.name] : [])), + privateSubnetIds: collapse(flatMap(findGroups(SubnetType.Private, grouped), group => group.subnets.map(s => s.subnetId))), + privateSubnetNames: collapse(flatMap(findGroups(SubnetType.Private, grouped), group => group.name ? [group.name] : [])), + publicSubnetIds: collapse(flatMap(findGroups(SubnetType.Public, grouped), group => group.subnets.map(s => s.subnetId))), + publicSubnetNames: collapse(flatMap(findGroups(SubnetType.Public, grouped), group => group.name ? [group.name] : [])), + }; + } +} + +/** + * Return the value of a tag from a set of tags + */ +function getTag(name: string, tags?: AWS.EC2.Tag[]): string | undefined { + for (const tag of tags || []) { + if (tag.Key === name) { + return tag.Value; + } + } + return undefined; +} + +/** + * Group subnets of the same type together, and order by AZ + */ +function groupSubnets(subnets: Subnet[]): SubnetGroups { + const grouping: {[key: string]: Subnet[]} = {}; + for (const subnet of subnets) { + const key = [subnet.type, subnet.name].toString(); + if (!(key in grouping)) { grouping[key] = []; } + grouping[key].push(subnet); + } + + const groups = Object.values(grouping).map(sns => { + sns.sort((a: Subnet, b: Subnet) => a.az.localeCompare(b.az)); + return { + type: sns[0].type, + name: sns[0].name, + subnets: sns, + }; + }); + + const azs = groups[0].subnets.map(s => s.az); + + for (const group of groups) { + const groupAZs = group.subnets.map(s => s.az); + if (!arraysEqual(groupAZs, azs)) { + throw new Error(`Not all subnets in VPC have the same AZs: ${groupAZs} vs ${azs}`); + } + } + + return { azs, groups }; +} + +enum SubnetType { + Public = 'Public', + Private = 'Private', + Isolated = 'Isolated' +} + +interface Subnet { + az: string; + type: SubnetType; + name?: string; + subnetId: string; +} + +interface SubnetGroup { + type: SubnetType; + name?: string; + subnets: Subnet[]; +} + +interface SubnetGroups { + azs: string[]; + groups: SubnetGroup[]; +} + +function arraysEqual(as: string[], bs: string[]): boolean { + if (as.length !== bs.length) { return false; } + + for (let i = 0; i < as.length; i++) { + if (as[i] !== bs[i]) { + return false; + } + } + + return true; +} + +function findGroups(type: SubnetType, groups: SubnetGroups): SubnetGroup[] { + return groups.groups.filter(g => g.type === type); +} + +function flatMap(xs: T[], fn: (x: T) => U[]): U[] { + const ret = new Array(); + for (const x of xs) { + ret.push(...fn(x)); + } + return ret; +} + +function collapse(xs: T[]): T[] | undefined { + if (xs.length > 0) { return xs; } + return undefined; + +} \ No newline at end of file diff --git a/tools/cdk-integ-tools/lib/integ-helpers.ts b/tools/cdk-integ-tools/lib/integ-helpers.ts index 60936c394a5c6..e0a40d3ca9ab3 100644 --- a/tools/cdk-integ-tools/lib/integ-helpers.ts +++ b/tools/cdk-integ-tools/lib/integ-helpers.ts @@ -115,6 +115,26 @@ export const STATIC_TEST_CONTEXT = { "ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2:region=test-region": "ami-1234", "ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2:region=test-region": "ami-1234", "ssm:account=12345678:parameterName=/aws/service/ecs/optimized-ami/amazon-linux/recommended:region=test-region": "{\"image_id\": \"ami-1234\"}", + "vpc-provider:account=12345678:isDefault=true:region=test-region": { + "vpcId": "vpc-60900905", + "availabilityZones": [ + "us-east-1a", + "us-east-1b", + "us-east-1c" + ], + "isolatedSubnetIds": [], + "isolatedSubnetNames": [], + "privateSubnetIds": [], + "privateSubnetNames": [], + "publicSubnetIds": [ + "subnet-e19455ca", + "subnet-e0c24797", + "subnet-ccd77395", + ], + "publicSubnetNames": [ + "Public" + ] + } }; /** From 7586b917a7d101ff47bb3906d3cbc221be3ad84d Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 14 Nov 2018 13:08:29 +0100 Subject: [PATCH 2/8] Fix test runs --- .../aws-ec2/test/example.share-vpcs.lit.ts | 17 +++++++++++++- tools/cdk-integ-tools/lib/integ-helpers.ts | 22 ++++--------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts b/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts index 7cdc7fdced354..6a6f4e997193c 100644 --- a/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts +++ b/packages/@aws-cdk/aws-ec2/test/example.share-vpcs.lit.ts @@ -3,6 +3,16 @@ import ec2 = require("../lib"); const app = new cdk.App(); +interface ConstructThatTakesAVpcProps { + vpc: ec2.VpcNetworkRef; +} + +class ConstructThatTakesAVpc extends cdk.Construct { + constructor(parent: cdk.Construct, id: string, _props: ConstructThatTakesAVpcProps) { + super(parent, id); + } +} + /// !show class Stack1 extends cdk.Stack { public readonly vpcProps: ec2.VpcNetworkRefProps; @@ -27,6 +37,10 @@ class Stack2 extends cdk.Stack { // Import the VPC from a set of properties const vpc = ec2.VpcNetworkRef.import(this, 'VPC', props.vpcProps); + + new ConstructThatTakesAVpc(this, 'Construct', { + vpc + }); } } @@ -36,5 +50,6 @@ const stack2 = new Stack2(app, 'Stack2', { }); /// !hide -app.run(); +Array.isArray(stack2); +app.run(); \ No newline at end of file diff --git a/tools/cdk-integ-tools/lib/integ-helpers.ts b/tools/cdk-integ-tools/lib/integ-helpers.ts index e0a40d3ca9ab3..1bdb3f2ed910f 100644 --- a/tools/cdk-integ-tools/lib/integ-helpers.ts +++ b/tools/cdk-integ-tools/lib/integ-helpers.ts @@ -116,24 +116,10 @@ export const STATIC_TEST_CONTEXT = { "ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2:region=test-region": "ami-1234", "ssm:account=12345678:parameterName=/aws/service/ecs/optimized-ami/amazon-linux/recommended:region=test-region": "{\"image_id\": \"ami-1234\"}", "vpc-provider:account=12345678:isDefault=true:region=test-region": { - "vpcId": "vpc-60900905", - "availabilityZones": [ - "us-east-1a", - "us-east-1b", - "us-east-1c" - ], - "isolatedSubnetIds": [], - "isolatedSubnetNames": [], - "privateSubnetIds": [], - "privateSubnetNames": [], - "publicSubnetIds": [ - "subnet-e19455ca", - "subnet-e0c24797", - "subnet-ccd77395", - ], - "publicSubnetNames": [ - "Public" - ] + vpcId: "vpc-60900905", + availabilityZones: [ "us-east-1a", "us-east-1b", "us-east-1c" ], + publicSubnetIds: [ "subnet-e19455ca", "subnet-e0c24797", "subnet-ccd77395", ], + publicSubnetNames: [ "Public" ] } }; From 396866bd490cbc0668b463fc80b61e590067d6ac Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 14 Nov 2018 13:34:39 +0100 Subject: [PATCH 3/8] Fix tests --- packages/@aws-cdk/aws-ec2/lib/vpc.ts | 4 +-- .../integ.import-default-vpc.expected.json | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.expected.json diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index 8483fc47e4c7c..d59a24f53ed71 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -430,8 +430,8 @@ export class VpcNetwork extends VpcNetworkRef implements cdk.ITaggable { } // These values will be used to recover the config upon provider import - subnet.tags.setTag(SUBNETNAME_TAG, subnetConfig.name); - subnet.tags.setTag(SUBNETTYPE_TAG, subnetTypeTagValue(subnetConfig.subnetType)); + subnet.tags.setTag(SUBNETNAME_TAG, subnetConfig.name, { propagate: false }); + subnet.tags.setTag(SUBNETTYPE_TAG, subnetTypeTagValue(subnetConfig.subnetType), { propagate: false }); }); } } diff --git a/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.expected.json b/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.expected.json new file mode 100644 index 0000000000000..37edfef83075b --- /dev/null +++ b/packages/@aws-cdk/aws-ec2/test/integ.import-default-vpc.expected.json @@ -0,0 +1,33 @@ +{ + "Resources": { + "SecurityGroupDD263621": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-ec2-import/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "SecurityGroupIngress": [], + "VpcId": "vpc-60900905" + } + } + }, + "Outputs": { + "PublicSubnets": { + "Value": "ids:subnet-e19455ca,subnet-e0c24797,subnet-ccd77395", + "Export": { + "Name": "aws-cdk-ec2-import:PublicSubnets" + } + }, + "PrivateSubnets": { + "Value": "ids:", + "Export": { + "Name": "aws-cdk-ec2-import:PrivateSubnets" + } + } + } +} \ No newline at end of file From e1b2ea6e4bf97e1b299d7c3904a85b844bd1f639 Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 14 Nov 2018 16:37:58 +0100 Subject: [PATCH 4/8] Schematize Hosted Zone provider into CXAPI library as well --- packages/@aws-cdk/aws-ec2/README.md | 4 +- packages/@aws-cdk/aws-ec2/lib/vpc.ts | 4 +- .../aws-route53/lib/hosted-zone-provider.ts | 47 +++++----------- packages/@aws-cdk/aws-route53/package.json | 3 +- .../cx-api/lib/context/hosted-zone.ts | 53 +++++++++++++++++++ packages/@aws-cdk/cx-api/lib/context/vpc.ts | 12 ++++- packages/@aws-cdk/cx-api/lib/index.ts | 1 + .../lib/context-providers/hosted-zones.ts | 37 ++++--------- .../aws-cdk/lib/context-providers/vpcs.ts | 14 ++--- 9 files changed, 103 insertions(+), 72 deletions(-) create mode 100644 packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index 4cc2a36b0c183..7633dd72d859c 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -174,8 +174,8 @@ Application subnets will route to the NAT Gateway. #### 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 +If you are creating multiple `Stack`s inside the same CDK application, you +can reuse a VPC defined in one Stack in another by using `export()` and `import()`: [sharing VPCs between stacks](test/example.share-vpcs.lit.ts) diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index d59a24f53ed71..9984f05e5ade9 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -436,8 +436,8 @@ export class VpcNetwork extends VpcNetworkRef implements cdk.ITaggable { } } -const SUBNETTYPE_TAG = 'aws-cdk:SubnetType'; -const SUBNETNAME_TAG = 'aws-cdk:SubnetName'; +const SUBNETTYPE_TAG = 'aws-cdk:subnet-type'; +const SUBNETNAME_TAG = 'aws-cdk:subnet-name'; function subnetTypeTagValue(type: SubnetType) { switch (type) { diff --git a/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts b/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts index f1bf7205a9d9b..c65307e0fa986 100644 --- a/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts +++ b/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts @@ -1,4 +1,5 @@ import cdk = require('@aws-cdk/cdk'); +import cxapi = require('@aws-cdk/cx-api'); import { HostedZoneRef, HostedZoneRefProps } from './hosted-zone-ref'; /** @@ -21,25 +22,18 @@ export interface HostedZoneProviderProps { vpcId?: string; } -const HOSTED_ZONE_PROVIDER = 'hosted-zone'; - -const DEFAULT_HOSTED_ZONE: HostedZoneRefProps = { - hostedZoneId: '/hostedzone/DUMMY', - zoneName: 'example.com', +const DEFAULT_HOSTED_ZONE: cxapi.HostedZoneContextResponse = { + Id: '/hostedzone/DUMMY', + Name: 'example.com', }; -interface AwsHostedZone { - Id: string; - Name: string; -} - /** * Context provider that will lookup the Hosted Zone ID for the given arguments */ export class HostedZoneProvider { private provider: cdk.ContextProvider; constructor(context: cdk.Construct, props: HostedZoneProviderProps) { - this.provider = new cdk.ContextProvider(context, HOSTED_ZONE_PROVIDER, props); + this.provider = new cdk.ContextProvider(context, cxapi.HOSTED_ZONE_PROVIDER, props); } /** @@ -52,27 +46,14 @@ export class HostedZoneProvider { * Return the hosted zone meeting the filter */ public findHostedZone(): HostedZoneRefProps { - const zone = this.provider.getValue(DEFAULT_HOSTED_ZONE); - if (zone === DEFAULT_HOSTED_ZONE) { - return zone; - } - if (!this.isAwsHostedZone(zone)) { - throw new Error(`Expected an AWS Hosted Zone received ${JSON.stringify(zone)}`); - } else { - const actualZone = zone as AwsHostedZone; - // CDK handles the '.' at the end, so remove it here - if (actualZone.Name.endsWith('.')) { - actualZone.Name = actualZone.Name.substring(0, actualZone.Name.length - 1); - } - return { - hostedZoneId: actualZone.Id, - zoneName: actualZone.Name, - }; + const zone = this.provider.getValue(DEFAULT_HOSTED_ZONE) as cxapi.HostedZoneContextResponse; + // CDK handles the '.' at the end, so remove it here + if (zone.Name.endsWith('.')) { + zone.Name = zone.Name.substring(0, zone.Name.length - 1); } + return { + hostedZoneId: zone.Id, + zoneName: zone.Name, + }; } - - private isAwsHostedZone(zone: AwsHostedZone | any): zone is AwsHostedZone { - const candidateZone = zone as AwsHostedZone; - return candidateZone.Name !== undefined && candidateZone.Id !== undefined; - } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-route53/package.json b/packages/@aws-cdk/aws-route53/package.json index 6a3f6c81251e8..b8db850f94b87 100644 --- a/packages/@aws-cdk/aws-route53/package.json +++ b/packages/@aws-cdk/aws-route53/package.json @@ -62,7 +62,8 @@ "dependencies": { "@aws-cdk/aws-ec2": "^0.16.0", "@aws-cdk/aws-logs": "^0.16.0", - "@aws-cdk/cdk": "^0.16.0" + "@aws-cdk/cdk": "^0.16.0", + "@aws-cdk/cx-api": "^0.16.0" }, "homepage": "https://github.com/awslabs/aws-cdk", "peerDependencies": { diff --git a/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts b/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts new file mode 100644 index 0000000000000..ee247a8de887a --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts @@ -0,0 +1,53 @@ +export const HOSTED_ZONE_PROVIDER = 'hosted-zone'; + +/** + * Query to hosted zone context provider + */ +export interface HostedZoneContextQuery { + /** + * Query account + */ + account?: string; + + /** + * Query region + */ + region?: string; + + /** + * The domain name e.g. example.com to lookup + */ + domainName: string; + + /** + * True if the zone you want to find is a private hosted zone + */ + privateZone?: boolean; + + /** + * The VPC ID to that the private zone must be associated with + * + * If you provide VPC ID and privateZone is false, this will return no results + * and raise an error. + */ + vpcId?: string; +} + +/** + * Hosted zone context + */ +export interface HostedZoneContextResponse { + /** + * The ID that Amazon Route 53 assigned to the hosted zone when you created + * it. + */ + Id: string; + + /** + * The name of the domain. For public hosted zones, this is the name that you + * have registered with your DNS registrar. For information about how to + * specify characters other than a-z, 0-9, and - (hyphen) and how to specify + * internationalized domain names, see CreateHostedZone. + */ + Name: string; +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/context/vpc.ts b/packages/@aws-cdk/cx-api/lib/context/vpc.ts index 7eb832a77a461..a7214968870b0 100644 --- a/packages/@aws-cdk/cx-api/lib/context/vpc.ts +++ b/packages/@aws-cdk/cx-api/lib/context/vpc.ts @@ -1,8 +1,16 @@ export const VPC_PROVIDER = 'vpc-provider'; export interface VpcContextQuery { - region: string; - account: string; + /** + * Query account + */ + account?: string; + + /** + * Query region + */ + region?: string; + vpcId?: string; vpcName?: string; tags?: {[key: string]: string}; diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index e788c1b1ba995..b4fb19539fa10 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -1,3 +1,4 @@ export * from './cxapi'; export * from './environment'; +export * from './context/hosted-zone'; export * from './context/vpc'; diff --git a/packages/aws-cdk/lib/context-providers/hosted-zones.ts b/packages/aws-cdk/lib/context-providers/hosted-zones.ts index 6ae4c7f7c537d..d13146505342a 100644 --- a/packages/aws-cdk/lib/context-providers/hosted-zones.ts +++ b/packages/aws-cdk/lib/context-providers/hosted-zones.ts @@ -1,36 +1,17 @@ +import cxapi = require('@aws-cdk/cx-api'); import { Mode, SDK } from '../api'; import { debug } from '../logging'; import { ContextProviderPlugin } from './provider'; -export interface HostedZoneProviderProps { - /** - * The domain name e.g. example.com to lookup - */ - domainName: string; - - /** - * True if the zone you want to find is a private hosted zone - */ - privateZone?: boolean; - - /** - * The VPC ID to that the private zone must be associated with - * - * If you provide VPC ID and privateZone is false, this will return no results - * and raise an error. - */ - vpcId?: string; -} - export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { constructor(private readonly aws: SDK) { } - public async getValue(args: {[key: string]: any}) { + public async getValue(args: {[key: string]: any}): Promise { const account = args.account; const region = args.region; - if (!this.isHostedZoneProps(args)) { + if (!this.isHostedZoneQuery(args)) { throw new Error(`HostedZoneProvider requires domainName property to be set in ${args}`); } const domainName = args.domainName; @@ -45,12 +26,16 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { const filteProps = `dns:${domainName}, privateZone:${args.privateZone}, vpcId:${args.vpcId}`; throw new Error(`Found zones: ${JSON.stringify(candidateZones)} for ${filteProps}, but wanted exactly 1 zone`); } - return candidateZones[0]; + + return { + Id: candidateZones[0].Id, + Name: candidateZones[0].Name, + }; } private async filterZones( r53: AWS.Route53, zones: AWS.Route53.HostedZone[], - props: HostedZoneProviderProps): Promise { + props: cxapi.HostedZoneContextQuery): Promise { let candidates: AWS.Route53.HostedZone[] = []; const domainName = props.domainName.endsWith('.') ? props.domainName : `${props.domainName}.`; @@ -79,7 +64,7 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { return candidates; } - private isHostedZoneProps(props: HostedZoneProviderProps | any): props is HostedZoneProviderProps { - return (props as HostedZoneProviderProps).domainName !== undefined; + private isHostedZoneQuery(props: cxapi.HostedZoneContextQuery | any): props is cxapi.HostedZoneContextQuery { + return (props as cxapi.HostedZoneContextQuery).domainName !== undefined; } } \ No newline at end of file diff --git a/packages/aws-cdk/lib/context-providers/vpcs.ts b/packages/aws-cdk/lib/context-providers/vpcs.ts index daaa5b0ba7662..ddfa84714b416 100644 --- a/packages/aws-cdk/lib/context-providers/vpcs.ts +++ b/packages/aws-cdk/lib/context-providers/vpcs.ts @@ -26,7 +26,7 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { const tags: {[key: string]: string} | undefined = args.tags; const isDefault: boolean | undefined = args.isDefault; - // Builter request filter + // Build request filter const filters: AWS.EC2.Filter[] = []; if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); } if (vpcName) { filters.push({ Name: 'tag:Name', Values: [vpcName] }); } @@ -61,20 +61,22 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { // Now comes our job to separate these subnets out into AZs and subnet groups (Public, Private, Isolated) // We have the following attributes to go on: - // - 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 + // - Type tag, we tag subnets with their type. In absence of this tag, we + // fall back to MapPublicIpOnLaunch => must be a Public subnet, anything + // else is considered Priate. + // - Name tag, we tag subnets with their subnet group name. In absence of this tag, + // we use the type as the name. const azs = Array.from(new Set(listedSubnets.map(s => s.AvailabilityZone!))); azs.sort(); const subnets: Subnet[] = listedSubnets.map(subnet => { - let type = getTag('aws-cdk:SubnetType', subnet.Tags); + let type = getTag('aws-cdk:subnet-type', subnet.Tags); if (type === undefined) { type = subnet.MapPublicIpOnLaunch ? 'Public' : 'Private'; } - const name = getTag('aws-cdk:SubnetName', subnet.Tags) || type; + const name = getTag('aws-cdk:subnet-name', subnet.Tags) || type; return { az: subnet.AvailabilityZone!, type: type as SubnetType, name, subnetId: subnet.SubnetId! }; }); From 42357d76e79aa046fff5fa2ba71b26b6c58eeffc Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 14 Nov 2018 16:43:26 +0100 Subject: [PATCH 5/8] Schematize other context providers as well --- packages/@aws-cdk/cdk/lib/context.ts | 8 +++---- .../cx-api/lib/context/availability-zones.ts | 22 ++++++++++++++++++ .../cx-api/lib/context/ssm-parameter.ts | 23 +++++++++++++++++++ packages/@aws-cdk/cx-api/lib/index.ts | 2 ++ .../aws-cdk/lib/context-providers/index.ts | 6 ++--- 5 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 packages/@aws-cdk/cx-api/lib/context/availability-zones.ts create mode 100644 packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts diff --git a/packages/@aws-cdk/cdk/lib/context.ts b/packages/@aws-cdk/cdk/lib/context.ts index 49fef72abbd72..bf89fa96cd124 100644 --- a/packages/@aws-cdk/cdk/lib/context.ts +++ b/packages/@aws-cdk/cdk/lib/context.ts @@ -1,9 +1,7 @@ +import cxapi = require('@aws-cdk/cx-api'); import { Stack } from './cloudformation/stack'; import { Construct } from './core/construct'; -const AVAILABILITY_ZONES_PROVIDER = 'availability-zones'; -const SSM_PARAMETER_PROVIDER = 'ssm'; - type ContextProviderProps = {[key: string]: any}; /** * Base class for the model side of context providers @@ -136,7 +134,7 @@ export class AvailabilityZoneProvider { private provider: ContextProvider; constructor(context: Construct) { - this.provider = new ContextProvider(context, AVAILABILITY_ZONES_PROVIDER); + this.provider = new ContextProvider(context, cxapi.AVAILABILITY_ZONE_PROVIDER); } /** @@ -161,7 +159,7 @@ export class SSMParameterProvider { private provider: ContextProvider; constructor(context: Construct, props: SSMParameterProviderProps) { - this.provider = new ContextProvider(context, SSM_PARAMETER_PROVIDER, props); + this.provider = new ContextProvider(context, cxapi.SSM_PARAMETER_PROVIDER, props); } /** diff --git a/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts b/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts new file mode 100644 index 0000000000000..6850c2e593fc1 --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/context/availability-zones.ts @@ -0,0 +1,22 @@ +export const AVAILABILITY_ZONE_PROVIDER = 'availability-zones'; + +/** + * Query to hosted zone context provider + */ +export interface AvailabilityZonesContextQuery { + /** + * Query account + */ + account?: string; + + /** + * Query region + */ + region?: string; + +} + +/** + * Response of the AZ provider looks like this + */ +export type AvailabilityZonesContextResponse = string[]; \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts b/packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts new file mode 100644 index 0000000000000..caf807aca1ceb --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/context/ssm-parameter.ts @@ -0,0 +1,23 @@ +export const SSM_PARAMETER_PROVIDER = 'ssm'; + +/** + * Query to hosted zone context provider + */ +export interface SSMParameterContextQuery { + /** + * Query account + */ + account?: string; + + /** + * Query region + */ + region?: string; + + /** + * Parameter name to query + */ + parameterName?: string; +} + +// Response is a string \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index b4fb19539fa10..7856e10f5b787 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -2,3 +2,5 @@ export * from './cxapi'; export * from './environment'; export * from './context/hosted-zone'; export * from './context/vpc'; +export * from './context/ssm-parameter'; +export * from './context/availability-zones'; diff --git a/packages/aws-cdk/lib/context-providers/index.ts b/packages/aws-cdk/lib/context-providers/index.ts index 84b842f268090..7d73feddb88fe 100644 --- a/packages/aws-cdk/lib/context-providers/index.ts +++ b/packages/aws-cdk/lib/context-providers/index.ts @@ -36,8 +36,8 @@ export async function provideContextValues( } const availableContextProviders: ProviderMap = { - 'availability-zones': AZContextProviderPlugin, - 'ssm': SSMContextProviderPlugin, - 'hosted-zone': HostedZoneContextProviderPlugin, + [cxapi.AVAILABILITY_ZONE_PROVIDER]: AZContextProviderPlugin, + [cxapi.SSM_PARAMETER_PROVIDER]: SSMContextProviderPlugin, + [cxapi.HOSTED_ZONE_PROVIDER]: HostedZoneContextProviderPlugin, [cxapi.VPC_PROVIDER]: VpcNetworkContextProviderPlugin, }; From b0dc9c612eaad8d460d0f8bf77f38be92c17d21e Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 15 Nov 2018 09:35:31 +0100 Subject: [PATCH 6/8] Update integ test expectations with new tags, CXAPI now contains filter --- .../test/integ.amazonlinux2.expected.json | 32 +++++ ...g.asg-w-classic-loadbalancer.expected.json | 122 ++++++++++++------ .../test/integ.asg-w-elbv2.expected.json | 86 ++++++++---- .../test/integ.deployment-group.expected.json | 27 ++-- .../aws-ec2/lib/vpc-network-provider.ts | 11 +- .../aws-ec2/test/integ.vpc.expected.json | 120 +++++++++++------ .../test/ec2/integ.lb-awsvpc-nw.expected.json | 32 +++++ .../test/ec2/integ.lb-bridge-nw.expected.json | 32 +++++ .../fargate/integ.asset-image.expected.json | 32 +++++ .../fargate/integ.lb-awsvpc-nw.expected.json | 32 +++++ .../test/integ.elb.expected.json | 52 +++++--- .../test/integ.alb-alias-target.expected.json | 34 ++++- .../test/integ.alb.expected.json | 92 ++++++++----- .../test/integ.nlb.expected.json | 80 ++++++++---- .../test/integ.vpc-lambda.expected.json | 34 ++++- .../aws-rds/test/integ.cluster.expected.json | 88 +++++++++---- .../test/integ.route53.expected.json | 120 +++++++++++------ packages/@aws-cdk/cdk/lib/context.ts | 21 ++- packages/@aws-cdk/cdk/test/test.context.ts | 19 +++ packages/@aws-cdk/cx-api/lib/context/vpc.ts | 62 ++++++++- .../aws-cdk/lib/context-providers/vpcs.ts | 27 +--- tools/cdk-integ-tools/lib/integ-helpers.ts | 2 +- 22 files changed, 872 insertions(+), 285 deletions(-) diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.amazonlinux2.expected.json b/packages/@aws-cdk/aws-autoscaling/test/integ.amazonlinux2.expected.json index 2cea5b897dfec..e90f3f4c3b698 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.amazonlinux2.expected.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.amazonlinux2.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-autoscaling-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-autoscaling-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-autoscaling-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-autoscaling-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-classic-loadbalancer.expected.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-classic-loadbalancer.expected.json index 0ca90cc9a329f..86f5430438bdf 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-classic-loadbalancer.expected.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-classic-loadbalancer.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet2Subnet74179F39": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "VPCPublicSubnet2DefaultRouteB7481BBA": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet3Subnet631C5E25": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PublicSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -217,6 +241,18 @@ } } }, + "VPCPublicSubnet3DefaultRouteA0D29D46": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet3RouteTable98AE0E14" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet3EIPAD4BC883": { "Type": "AWS::EC2::EIP", "Properties": { @@ -243,18 +279,6 @@ ] } }, - "VPCPublicSubnet3DefaultRouteA0D29D46": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet3RouteTable98AE0E14" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -268,6 +292,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -322,6 +354,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -376,6 +416,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PrivateSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -654,4 +702,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json index 167f41eed8cac..1b4796c2a30d1 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-w-elbv2.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet2Subnet74179F39": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "VPCPublicSubnet2DefaultRouteB7481BBA": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -524,13 +556,13 @@ "Properties": { "Port": 80, "Protocol": "HTTP", - "TargetType": "instance", "VpcId": { "Ref": "VPCB9E5F0B4" }, "TargetGroupAttributes": [], - "Targets": [] + "Targets": [], + "TargetType": "instance" } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json b/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json index 3cb6c923102c3..94c87c92a37c0 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json +++ b/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json @@ -67,7 +67,10 @@ "GatewayId": { "Ref": "VPCIGWB7E252D3" } - } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", @@ -147,7 +150,10 @@ "GatewayId": { "Ref": "VPCIGWB7E252D3" } - } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", @@ -227,7 +233,10 @@ "GatewayId": { "Ref": "VPCIGWB7E252D3" } - } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] }, "VPCPublicSubnet3EIPAD4BC883": { "Type": "AWS::EC2::EIP", @@ -626,11 +635,11 @@ "GroupDescription": "aws-cdk-codedeploy-server-dg/ELB/SecurityGroup", "SecurityGroupEgress": [ { - "CidrIp":"255.255.255.255/32", - "Description":"Disallow all traffic", - "FromPort":252, - "IpProtocol":"icmp", - "ToPort":86 + "CidrIp": "255.255.255.255/32", + "Description": "Disallow all traffic", + "FromPort": 252, + "IpProtocol": "icmp", + "ToPort": 86 } ], "SecurityGroupIngress": [ @@ -761,4 +770,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts index 3268e9a90d0ce..4312daa66bebb 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts @@ -51,7 +51,16 @@ export class VpcNetworkProvider { private provider: cdk.ContextProvider; constructor(context: cdk.Construct, props: VpcNetworkProviderProps) { - this.provider = new cdk.ContextProvider(context, cxapi.VPC_PROVIDER, props as cxapi.VpcContextQuery); + const filter: {[key: string]: string} = props.tags || {}; + + // We give special treatment to some tags + if (props.vpcId) { filter['vpc-id'] = props.vpcId; } + if (props.vpcName) { filter['tag:Name'] = props.vpcName; } + if (props.isDefault !== undefined) { + filter.isDefault = props.isDefault ? 'true' : 'false'; + } + + this.provider = new cdk.ContextProvider(context, cxapi.VPC_PROVIDER, { filter } as cxapi.VpcContextQuery); } /** diff --git a/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json b/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json index 3df9527a9028f..d4e099ef34f39 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.vpc.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-vpc/MyVpc/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "MyVpcPublicSubnet1DefaultRoute95FDF9EB": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + } + } + }, "MyVpcPublicSubnet1EIP096967CB": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "MyVpcPublicSubnet1DefaultRoute95FDF9EB": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "MyVpcPublicSubnet1RouteTableC46AB2F4" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "MyVpcIGW5C4A4F63" - } - } - }, "MyVpcPublicSubnet2Subnet492B6BFB": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-vpc/MyVpc/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "MyVpcPublicSubnet2DefaultRoute052936F6": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + } + } + }, "MyVpcPublicSubnet2EIP8CCBA239": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "MyVpcPublicSubnet2DefaultRoute052936F6": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "MyVpcPublicSubnet2RouteTable1DF17386" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "MyVpcIGW5C4A4F63" - } - } - }, "MyVpcPublicSubnet3Subnet57EEE236": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-vpc/MyVpc/PublicSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -217,6 +241,18 @@ } } }, + "MyVpcPublicSubnet3DefaultRoute3A83AB36": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "MyVpcPublicSubnet3RouteTable15028F08" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "MyVpcIGW5C4A4F63" + } + } + }, "MyVpcPublicSubnet3EIPC5ACADAB": { "Type": "AWS::EC2::EIP", "Properties": { @@ -243,18 +279,6 @@ ] } }, - "MyVpcPublicSubnet3DefaultRoute3A83AB36": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "MyVpcPublicSubnet3RouteTable15028F08" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "MyVpcIGW5C4A4F63" - } - } - }, "MyVpcPrivateSubnet1Subnet5057CF7E": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -268,6 +292,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-vpc/MyVpc/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -322,6 +354,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-vpc/MyVpc/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -376,6 +416,14 @@ { "Key": "Name", "Value": "aws-cdk-ec2-vpc/MyVpc/PrivateSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json index c655174233d6e..99d4b337318d6 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json index 7e26702951204..064277c3d33f6 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-ecs-integ-ecs/Vpc/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-ecs-integ-ecs/Vpc/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-ecs-integ-ecs/Vpc/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-ecs-integ-ecs/Vpc/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json index 083b5b9ba3d22..4c6a74ad8703f 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json index d4f7ba85f8c29..f70793b7c3462 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-ecs-integ/Vpc/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.elb.expected.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.elb.expected.json index 50513f3f5ba0f..82a1af386684f 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.elb.expected.json +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.elb.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-elb-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-elb-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -177,11 +193,11 @@ "GroupDescription": "aws-cdk-elb-integ/LB/SecurityGroup", "SecurityGroupEgress": [ { - "CidrIp":"255.255.255.255/32", - "Description":"Disallow all traffic", - "FromPort":252, - "IpProtocol":"icmp", - "ToPort":86 + "CidrIp": "255.255.255.255/32", + "Description": "Disallow all traffic", + "FromPort": 252, + "IpProtocol": "icmp", + "ToPort": 86 } ], "SecurityGroupIngress": [ @@ -233,4 +249,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb-alias-target.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb-alias-target.expected.json index 689e2b1378871..9913cccc6bd68 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb-alias-target.expected.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb-alias-target.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -379,4 +411,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.expected.json index 6e2cd595b15b8..e263b5def9466 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.expected.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.alb.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet2Subnet74179F39": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "VPCPublicSubnet2DefaultRouteB7481BBA": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -335,11 +367,11 @@ "GroupDescription": "Automatically created Security Group for ELB awscdkelbv2integLB9950B1E4", "SecurityGroupEgress": [ { - "CidrIp":"255.255.255.255/32", - "Description":"Disallow all traffic", - "FromPort":252, - "IpProtocol":"icmp", - "ToPort":86 + "CidrIp": "255.255.255.255/32", + "Description": "Disallow all traffic", + "FromPort": 252, + "IpProtocol": "icmp", + "ToPort": 86 } ], "SecurityGroupIngress": [ @@ -435,4 +467,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.nlb.expected.json b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.nlb.expected.json index a27c8b8c2db10..bef1975c48a56 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.nlb.expected.json +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/integ.nlb.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet2Subnet74179F39": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "VPCPublicSubnet2DefaultRouteB7481BBA": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-elbv2-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/aws-lambda/test/integ.vpc-lambda.expected.json b/packages/@aws-cdk/aws-lambda/test/integ.vpc-lambda.expected.json index 386f53a95073c..48abde9d34525 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.vpc-lambda.expected.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.vpc-lambda.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-vpc-lambda/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-vpc-lambda/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-vpc-lambda/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-vpc-lambda/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -403,4 +435,4 @@ ] } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster.expected.json b/packages/@aws-cdk/aws-rds/test/integ.cluster.expected.json index 35e7814dcf7eb..56fabe9401c93 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster.expected.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-rds-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet2Subnet74179F39": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-rds-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "VPCPublicSubnet2DefaultRouteB7481BBA": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-rds-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -242,6 +266,14 @@ { "Key": "Name", "Value": "aws-cdk-rds-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -382,9 +414,9 @@ "GroupDescription": "RDS security group", "SecurityGroupEgress": [ { - "CidrIp":"0.0.0.0/0", - "Description":"Allow all outbound traffic by default", - "IpProtocol":"-1" + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" } ], "SecurityGroupIngress": [], @@ -487,4 +519,4 @@ ] } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-route53/test/integ.route53.expected.json b/packages/@aws-cdk/aws-route53/test/integ.route53.expected.json index 363df70cd4d99..a8083a5765731 100644 --- a/packages/@aws-cdk/aws-route53/test/integ.route53.expected.json +++ b/packages/@aws-cdk/aws-route53/test/integ.route53.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-route53-integ/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -57,6 +65,18 @@ } } }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet1EIP6AD938E8": { "Type": "AWS::EC2::EIP", "Properties": { @@ -83,18 +103,6 @@ ] } }, - "VPCPublicSubnet1DefaultRoute91CEF279": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet1RouteTableFEE4B781" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet2Subnet74179F39": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -108,6 +116,14 @@ { "Key": "Name", "Value": "aws-cdk-route53-integ/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -137,6 +153,18 @@ } } }, + "VPCPublicSubnet2DefaultRouteB7481BBA": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet2EIP4947BC00": { "Type": "AWS::EC2::EIP", "Properties": { @@ -163,18 +191,6 @@ ] } }, - "VPCPublicSubnet2DefaultRouteB7481BBA": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPublicSubnet3Subnet631C5E25": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -188,6 +204,14 @@ { "Key": "Name", "Value": "aws-cdk-route53-integ/VPC/PublicSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -217,6 +241,18 @@ } } }, + "VPCPublicSubnet3DefaultRouteA0D29D46": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet3RouteTable98AE0E14" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, "VPCPublicSubnet3EIPAD4BC883": { "Type": "AWS::EC2::EIP", "Properties": { @@ -243,18 +279,6 @@ ] } }, - "VPCPublicSubnet3DefaultRouteA0D29D46": { - "Type": "AWS::EC2::Route", - "Properties": { - "RouteTableId": { - "Ref": "VPCPublicSubnet3RouteTable98AE0E14" - }, - "DestinationCidrBlock": "0.0.0.0/0", - "GatewayId": { - "Ref": "VPCIGWB7E252D3" - } - } - }, "VPCPrivateSubnet1Subnet8BCA10E0": { "Type": "AWS::EC2::Subnet", "Properties": { @@ -268,6 +292,14 @@ { "Key": "Name", "Value": "aws-cdk-route53-integ/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -322,6 +354,14 @@ { "Key": "Name", "Value": "aws-cdk-route53-integ/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -376,6 +416,14 @@ { "Key": "Name", "Value": "aws-cdk-route53-integ/VPC/PrivateSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } diff --git a/packages/@aws-cdk/cdk/lib/context.ts b/packages/@aws-cdk/cdk/lib/context.ts index bf89fa96cd124..b215e20193ee2 100644 --- a/packages/@aws-cdk/cdk/lib/context.ts +++ b/packages/@aws-cdk/cdk/lib/context.ts @@ -179,27 +179,26 @@ function formatMissingScopeError(provider: string, props: {[key: string]: string return s; } -function propsToArray(props: {[key: string]: any}): string[] { - const propArray: string[] = []; - const keys = Object.keys(props); - keys.sort(); - for (const key of keys) { +function propsToArray(props: {[key: string]: any}, keyPrefix = ''): string[] { + const ret: string[] = []; + + for (const key of Object.keys(props)) { switch (typeof props[key]) { case 'object': { - const childObjStrs = propsToArray(props[key]); - const qualifiedChildStr = childObjStrs.map( child => (`${key}.${child}`)).join(':'); - propArray.push(qualifiedChildStr); + ret.push(...propsToArray(props[key], `${keyPrefix}${key}.`)); break; } case 'string': { - propArray.push(`${key}=${colonQuote(props[key])}`); + ret.push(`${keyPrefix}${key}=${colonQuote(props[key])}`); break; } default: { - propArray.push(`${key}=${JSON.stringify(props[key])}`); + ret.push(`${keyPrefix}${key}=${JSON.stringify(props[key])}`); break; } } } - return propArray; + + ret.sort(); + return ret; } diff --git a/packages/@aws-cdk/cdk/test/test.context.ts b/packages/@aws-cdk/cdk/test/test.context.ts index 4a9b67b559abb..f061a16c4b443 100644 --- a/packages/@aws-cdk/cdk/test/test.context.ts +++ b/packages/@aws-cdk/cdk/test/test.context.ts @@ -59,6 +59,25 @@ export = { 'vpc:account=12345:cidrBlock=192.168.0.16:igw=false:region=us-east-1:tags.Env=Preprod:tags.Name=MyVPC'); test.done(); }, + + 'Key generation can contain arbitrarily deep structures'(test: Test) { + // GIVEN + const stack = new Stack(undefined, 'TestStack', { env: { account: '12345', region: 'us-east-1' } }); + + // WHEN + const provider = new ContextProvider(stack, 'provider', { + list: [ + { key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value2' }, + ], + }); + + // THEN + test.equals(provider.key, 'provider:account=12345:list.0.key=key1:list.0.value=value1:list.1.key=key2:list.1.value=value2:region=us-east-1'); + + test.done(); + }, + 'SSM parameter provider will return context values if available'(test: Test) { const stack = new Stack(undefined, 'TestStack', { env: { account: '12345', region: 'us-east-1' } }); new SSMParameterProvider(stack, {parameterName: 'test'}).parameterValue(); diff --git a/packages/@aws-cdk/cx-api/lib/context/vpc.ts b/packages/@aws-cdk/cx-api/lib/context/vpc.ts index a7214968870b0..a4513b2567a99 100644 --- a/packages/@aws-cdk/cx-api/lib/context/vpc.ts +++ b/packages/@aws-cdk/cx-api/lib/context/vpc.ts @@ -1,5 +1,8 @@ export const VPC_PROVIDER = 'vpc-provider'; +/** + * Query input for looking up a VPC + */ export interface VpcContextQuery { /** * Query account @@ -11,19 +14,70 @@ export interface VpcContextQuery { */ region?: string; - vpcId?: string; - vpcName?: string; - tags?: {[key: string]: string}; - isDefault?: boolean; + /** + * Filters to apply to the VPC + * + * Filter parameters are the same as passed to DescribeVpcs. + * + * @see https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html + */ + filter: {[key: string]: string}; } +/** + * Properties of a discovered VPC + */ export interface VpcContextResponse { + + /** + * VPC id + */ vpcId: string; + + /** + * AZs + */ availabilityZones: string[]; + + /** + * IDs of all public subnets + * + * Element count: #(availabilityZones) · #(publicGroups) + */ publicSubnetIds?: string[]; + + /** + * Name of public subnet groups + * + * Element count: #(publicGroups) + */ publicSubnetNames?: string[]; + + /** + * IDs of all private subnets + * + * Element count: #(availabilityZones) · #(privateGroups) + */ privateSubnetIds?: string[]; + + /** + * Name of private subnet groups + * + * Element count: #(privateGroups) + */ privateSubnetNames?: string[]; + + /** + * IDs of all isolated subnets + * + * Element count: #(availabilityZones) · #(isolatedGroups) + */ isolatedSubnetIds?: string[]; + + /** + * Name of isolated subnet groups + * + * Element count: #(isolatedGroups) + */ isolatedSubnetNames?: string[]; } \ No newline at end of file diff --git a/packages/aws-cdk/lib/context-providers/vpcs.ts b/packages/aws-cdk/lib/context-providers/vpcs.ts index ddfa84714b416..442b55d577a7e 100644 --- a/packages/aws-cdk/lib/context-providers/vpcs.ts +++ b/packages/aws-cdk/lib/context-providers/vpcs.ts @@ -10,8 +10,8 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { } public async getValue(args: cxapi.VpcContextQuery) { - const account: string = args.account; - const region: string = args.region; + const account: string = args.account!; + const region: string = args.region!; const ec2 = await this.aws.ec2(account, region, Mode.ForReading); @@ -20,24 +20,9 @@ export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { return await this.readVpcProps(ec2, vpcId); } - private async findVpc(ec2: AWS.EC2, args: {[key: string]: any}): Promise { - const vpcId: string | undefined = args.vpcId; - const vpcName: string | undefined = args.vpcName; - const tags: {[key: string]: string} | undefined = args.tags; - const isDefault: boolean | undefined = args.isDefault; - - // Build request filter - const filters: AWS.EC2.Filter[] = []; - if (vpcId) { filters.push({ Name: 'vpc-id', Values: [vpcId] }); } - if (vpcName) { filters.push({ Name: 'tag:Name', Values: [vpcName] }); } - if (tags) { - for (const [tag, value] of Object.entries(tags)) { - filters.push({ Name: `tag:${tag}`, Values: [value] }); - } - } - if (isDefault !== undefined) { - filters.push({ Name: 'isDefault', Values: [isDefault ? 'true' : 'false'] }); - } + private async findVpc(ec2: AWS.EC2, args: cxapi.VpcContextQuery): Promise { + // Build request filter (map { Name -> Value } to list of [{ Name, Values }]) + const filters: AWS.EC2.Filter[] = Object.entries(args.filter).map(x => ({ Name: x[0], Values: [x[1]] })); debug(`Listing VPCs in ${args.account}:${args.region}`); const response = await ec2.describeVpcs({ Filters: filters }).promise(); @@ -192,4 +177,4 @@ function collapse(xs: T[]): T[] | undefined { if (xs.length > 0) { return xs; } return undefined; -} \ No newline at end of file +} diff --git a/tools/cdk-integ-tools/lib/integ-helpers.ts b/tools/cdk-integ-tools/lib/integ-helpers.ts index 1bdb3f2ed910f..cb20c87655d0d 100644 --- a/tools/cdk-integ-tools/lib/integ-helpers.ts +++ b/tools/cdk-integ-tools/lib/integ-helpers.ts @@ -115,7 +115,7 @@ export const STATIC_TEST_CONTEXT = { "ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2:region=test-region": "ami-1234", "ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2:region=test-region": "ami-1234", "ssm:account=12345678:parameterName=/aws/service/ecs/optimized-ami/amazon-linux/recommended:region=test-region": "{\"image_id\": \"ami-1234\"}", - "vpc-provider:account=12345678:isDefault=true:region=test-region": { + "vpc-provider:account=12345678:filter.isDefault=true:region=test-region": { vpcId: "vpc-60900905", availabilityZones: [ "us-east-1a", "us-east-1b", "us-east-1c" ], publicSubnetIds: [ "subnet-e19455ca", "subnet-e0c24797", "subnet-ccd77395", ], From b92e20ee3171be4c7f5b0518122f3954de09cc7b Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 15 Nov 2018 14:29:33 +0100 Subject: [PATCH 7/8] Don't really export HostedZoneContextResponse since the names aren't JSII-compliant --- .../aws-route53/lib/hosted-zone-provider.ts | 13 ++++++-- .../cx-api/lib/context/hosted-zone.ts | 32 +++++++++++-------- .../lib/context-providers/hosted-zones.ts | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts b/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts index c65307e0fa986..fc3d01bf88e2f 100644 --- a/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts +++ b/packages/@aws-cdk/aws-route53/lib/hosted-zone-provider.ts @@ -22,7 +22,7 @@ export interface HostedZoneProviderProps { vpcId?: string; } -const DEFAULT_HOSTED_ZONE: cxapi.HostedZoneContextResponse = { +const DEFAULT_HOSTED_ZONE: HostedZoneContextResponse = { Id: '/hostedzone/DUMMY', Name: 'example.com', }; @@ -46,7 +46,7 @@ export class HostedZoneProvider { * Return the hosted zone meeting the filter */ public findHostedZone(): HostedZoneRefProps { - const zone = this.provider.getValue(DEFAULT_HOSTED_ZONE) as cxapi.HostedZoneContextResponse; + const zone = this.provider.getValue(DEFAULT_HOSTED_ZONE) as HostedZoneContextResponse; // CDK handles the '.' at the end, so remove it here if (zone.Name.endsWith('.')) { zone.Name = zone.Name.substring(0, zone.Name.length - 1); @@ -56,4 +56,13 @@ export class HostedZoneProvider { zoneName: zone.Name, }; } +} + +/** + * A mirror of the definition in cxapi, but can use the capital letters + * since it doesn't need to be published via JSII. + */ +interface HostedZoneContextResponse { + Id: string; + Name: string; } \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts b/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts index ee247a8de887a..7862b0affac82 100644 --- a/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts +++ b/packages/@aws-cdk/cx-api/lib/context/hosted-zone.ts @@ -35,19 +35,23 @@ export interface HostedZoneContextQuery { /** * Hosted zone context + * + * This definition is for human reference. It is not machine-checked as the + * naming conventions used in it are not JSII compatible, and changing those + * introduces a backwards incompatibility. */ -export interface HostedZoneContextResponse { - /** - * The ID that Amazon Route 53 assigned to the hosted zone when you created - * it. - */ - Id: string; +// export interface HostedZoneContextResponse { +// /** +// * The ID that Amazon Route 53 assigned to the hosted zone when you created +// * it. +// */ +// Id: string; - /** - * The name of the domain. For public hosted zones, this is the name that you - * have registered with your DNS registrar. For information about how to - * specify characters other than a-z, 0-9, and - (hyphen) and how to specify - * internationalized domain names, see CreateHostedZone. - */ - Name: string; -} \ No newline at end of file +// /** +// * The name of the domain. For public hosted zones, this is the name that you +// * have registered with your DNS registrar. For information about how to +// * specify characters other than a-z, 0-9, and - (hyphen) and how to specify +// * internationalized domain names, see CreateHostedZone. +// */ +// Name: string; +// } \ No newline at end of file diff --git a/packages/aws-cdk/lib/context-providers/hosted-zones.ts b/packages/aws-cdk/lib/context-providers/hosted-zones.ts index d13146505342a..28773aefbd3a6 100644 --- a/packages/aws-cdk/lib/context-providers/hosted-zones.ts +++ b/packages/aws-cdk/lib/context-providers/hosted-zones.ts @@ -8,7 +8,7 @@ export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { constructor(private readonly aws: SDK) { } - public async getValue(args: {[key: string]: any}): Promise { + public async getValue(args: {[key: string]: any}): Promise { const account = args.account; const region = args.region; if (!this.isHostedZoneQuery(args)) { From 838999cffdb2d480e94a1bab055a79295e8627ca Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Thu, 15 Nov 2018 15:06:51 +0100 Subject: [PATCH 8/8] More expectation updates --- .../test/integ.deployment-group.expected.json | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json b/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json index b4c78fa815e6c..d8f996ed7cfe8 100644 --- a/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json +++ b/packages/@aws-cdk/aws-codedeploy/test/integ.deployment-group.expected.json @@ -28,6 +28,14 @@ { "Key": "Name", "Value": "aws-cdk-codedeploy-server-dg/VPC/PublicSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -59,9 +67,6 @@ }, "VPCPublicSubnet1DefaultRoute91CEF279": { "Type": "AWS::EC2::Route", - "DependsOn": [ - "VPCVPCGW99B986DC" - ], "Properties": { "RouteTableId": { "Ref": "VPCPublicSubnet1RouteTableFEE4B781" @@ -114,6 +119,14 @@ { "Key": "Name", "Value": "aws-cdk-codedeploy-server-dg/VPC/PublicSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -145,9 +158,6 @@ }, "VPCPublicSubnet2DefaultRouteB7481BBA": { "Type": "AWS::EC2::Route", - "DependsOn": [ - "VPCVPCGW99B986DC" - ], "Properties": { "RouteTableId": { "Ref": "VPCPublicSubnet2RouteTable6F1A15F1" @@ -200,6 +210,14 @@ { "Key": "Name", "Value": "aws-cdk-codedeploy-server-dg/VPC/PublicSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" } ] } @@ -231,9 +249,6 @@ }, "VPCPublicSubnet3DefaultRouteA0D29D46": { "Type": "AWS::EC2::Route", - "DependsOn": [ - "VPCVPCGW99B986DC" - ], "Properties": { "RouteTableId": { "Ref": "VPCPublicSubnet3RouteTable98AE0E14" @@ -286,6 +301,14 @@ { "Key": "Name", "Value": "aws-cdk-codedeploy-server-dg/VPC/PrivateSubnet1" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -340,6 +363,14 @@ { "Key": "Name", "Value": "aws-cdk-codedeploy-server-dg/VPC/PrivateSubnet2" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] } @@ -394,6 +425,14 @@ { "Key": "Name", "Value": "aws-cdk-codedeploy-server-dg/VPC/PrivateSubnet3" + }, + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" } ] }