Skip to content

Commit

Permalink
feat(core): environment-agnostic cloud assemblies
Browse files Browse the repository at this point in the history
Formalize the simple use case for synthesizing cloudformation templates that
are not pre-associated with a specific AWS account/region.

When a CDK stack is defined without an explicit `env` configuration, or if `env.account`
and/or `env.region` are set to `Aws.accountId`/`Aws.region`, the stack is said to be
"environment-agnostic". This means that when a template is synthesized, we will use
the CloudFormation intrinsics `AWS::AccountId` and `AWS::Region` instead of concrete
account/region.

The cloud assembly manifest for such stacks will indicate `aws://unknown-account/unknown-region`
to represent that this stack is environment-agnostic, and tooling should rely on external
configuration to determine the deployment environment.

Environment-agnostic stacks have limitations. For example, their resources cannot be referenced
across accounts or regions, and context providers such as SSM, AZs, VPC and Route53 lookup
cannot be used since they won't know which environment to query.

To faciliate the env-agnostic use case at the AWS Construct Library level,
this change removes any dependency on concrete environment specification. Namely:

- The AZ provider, which is now accessible through `stack.availabilityZones` will fall
  back to use `[ Fn::GetAZs[0], Fn::GetAZs[1] ]` in case the stack is env-agnostic. This is
  a safe fallback since all AWS regions have at least two AZs.
- The use of the SSM context provider by the EC2 and ECS libraries to retrieve AMIs was
  replaced by deploy-time resolution of SSM parameters, so no fallback is required.

See list of breaking API changes below.

Added a few static methods to `ssm.StringParameter` to make it easier to reference values directly:
* `valueFromLookup` will read a value during synthesis using the SSM context provider.
* `valueForStringParameter` will return a deploy-time resolved value.
* `valueForSecureStringParameter` will return a deploy-time resolved secure string value.

Fixes #2866

BREAKING CHANGE: `ContextProvider` is no longer designed to be extended. Use `ContextProvider.getValue` and `ContextProvider.getKey` as utilities.
* **core:** `Context.getSsmParameter` has been removed. Use `ssm.StringParameter.valueFromLookup`
* **core:** `Context.getAvailabilityZones` has been removed. Use `stack.availabilityZones`
* **core:** `Context.getDefaultAccount` and `getDefaultRegion` have been removed an no longer available.
* **route52:** `HostedZoneProvider` has been removed. Use `HostedZone.fromLookup`.
* **ec2:** `VpcNetworkProvider` has been removed. Use `Vpc.fromLookup`.
* **ec2:** `ec2.MachineImage` will now resolve AMIs from SSM during deployment.
* **ecs:** `ecs.EcsOptimizedAmi` will now resolve AMis from SSM during deployment.
  • Loading branch information
Elad Ben-Israel committed Jun 19, 2019
1 parent 83eee09 commit aae14b7
Show file tree
Hide file tree
Showing 28 changed files with 645 additions and 649 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Test extends cdk.Stack {
name: 'Basic',
apiKey: key,
description: 'Free tier monthly usage plan',
throttle: { rateLimit: 5 },
quota: {
limit: 10000,
period: apigateway.Period.Month
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-ec2/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export * from './machine-image';
export * from './security-group';
export * from './security-group-rule';
export * from './vpc';
export * from './vpc-network-provider';
export * from './vpc-lookup';
export * from './vpn';
export * from './vpc-endpoint';

Expand Down
12 changes: 7 additions & 5 deletions packages/@aws-cdk/aws-ec2/lib/machine-image.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Construct, Context, Stack, Token } from '@aws-cdk/cdk';
import ssm = require('@aws-cdk/aws-ssm');
import { Construct, Stack, Token } from '@aws-cdk/cdk';

/**
* Interface for classes that can select an appropriate machine image to use
Expand All @@ -25,7 +26,8 @@ export class WindowsImage implements IMachineImageSource {
* Return the image to use in the given context
*/
public getImage(scope: Construct): MachineImage {
const ami = Context.getSsmParameter(scope, this.imageParameterName(this.version));
const parameterName = this.imageParameterName(this.version);
const ami = ssm.StringParameter.valueForStringParameter(scope, parameterName);
return new MachineImage(ami, new WindowsOS());
}

Expand Down Expand Up @@ -102,7 +104,7 @@ export class AmazonLinuxImage implements IMachineImageSource {
].filter(x => x !== undefined); // Get rid of undefineds

const parameterName = '/aws/service/ami-amazon-linux-latest/' + parts.join('-');
const ami = Context.getSsmParameter(scope, parameterName);
const ami = ssm.StringParameter.valueForStringParameter(scope, parameterName);
return new MachineImage(ami, new LinuxOS());
}
}
Expand Down Expand Up @@ -180,9 +182,9 @@ export class GenericLinuxImage implements IMachineImageSource {
}

public getImage(scope: Construct): MachineImage {
let region = Stack.of(scope).region;
const region = Stack.of(scope).region;
if (Token.isUnresolved(region)) {
region = Context.getDefaultRegion(scope);
throw new Error(`Unable to determine AMI from AMI map since stack is region-agnostic`);
}

const ami = region !== 'test-region' ? this.amiMap[region] : 'ami-12345';
Expand Down
41 changes: 41 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/vpc-lookup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* 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 VpcLookupOptions {
/**
* The ID of the VPC
*
* If given, will import exactly this VPC.
*
* @default Don't filter on vpcId
*/
readonly vpcId?: string;

/**
* The name of the VPC
*
* If given, will import the VPC with this name.
*
* @default Don't filter on vpcName
*/
readonly vpcName?: string;

/**
* Tags on the VPC
*
* The VPC must have all of these tags
*
* @default Don't filter on tags
*/
readonly tags?: {[key: string]: string};

/**
* Whether to match the default VPC
*
* @default Don't care whether we return the default VPC
*/
readonly isDefault?: boolean;
}
85 changes: 0 additions & 85 deletions packages/@aws-cdk/aws-ec2/lib/vpc-network-provider.ts

This file was deleted.

Loading

0 comments on commit aae14b7

Please sign in to comment.