Skip to content

Commit

Permalink
Merge branch 'master' into bug-6723-kubepatch_type2
Browse files Browse the repository at this point in the history
  • Loading branch information
mattchrist committed Mar 17, 2020
2 parents fca12c5 + d10fe67 commit d87eafa
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 12 deletions.
26 changes: 24 additions & 2 deletions packages/@aws-cdk/aws-ec2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ new ec2.FlowLog(this, 'FlowLog', {
## User Data
User data enables you to run a script when your instances start up. In order to configure these scripts you can add commands directly to the script
or you can use the UserData's convenience functions to aid in the creation of your script.

A user data could be configured to run a script found in an asset through the following:
```ts
const asset = new Asset(this, 'Asset', {path: path.join(__dirname, 'configure.sh')});
Expand All @@ -576,4 +576,26 @@ instance.userData.addExecuteFileCommand({
arguments: '--verbose -y'
});
asset.grantRead( instance.role );
```
```

## Importing existing subnet

To import an existing Subnet, call `Subnet.fromSubnetAttributes()` or
`Subnet.fromSubnetId()`. Only if you supply the subnet's Availability Zone
and Route Table Ids when calling `Subnet.fromSubnetAttributes()` will you be
able to use the CDK features that use these values (such as selecting one
subnet per AZ).

Importing an existing subnet looks like this:

```ts
// Supply all properties
const subnet = Subnet.fromSubnetAttributes(this, 'SubnetFromAttributes', {
subnetId: 's-1234',
availabilityZone: 'pub-az-4465',
routeTableId: 'rt-145'
});

// Supply only subnet id
const subnet = Subnet.fromSubnetId(this, 'SubnetFromId', 's-1234');
```
27 changes: 24 additions & 3 deletions packages/@aws-cdk/aws-ec2/lib/vpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,10 @@ export interface VpcAttributes {
export interface SubnetAttributes {
/**
* The Availability Zone the subnet is located in
*
* @default - No AZ information, cannot use AZ selection features
*/
readonly availabilityZone: string;
readonly availabilityZone?: string;

/**
* The subnetId for this particular subnet
Expand All @@ -573,6 +575,8 @@ export interface SubnetAttributes {

/**
* The ID of the route table for this particular subnet
*
* @default - No route table information, cannot create VPC endpoints
*/
readonly routeTableId?: string;
}
Expand Down Expand Up @@ -1316,6 +1320,15 @@ export class Subnet extends Resource implements ISubnet {
return new ImportedSubnet(scope, id, attrs);
}

/**
* Import existing subnet from id.
*/
// tslint:disable:no-shadowed-variable
public static fromSubnetId(scope: Construct, id: string, subnetId: string): ISubnet {
return this.fromSubnetAttributes(scope, id, { subnetId });
}
// tslint:enable:no-shadowed-variable

/**
* The Availability Zone the subnet is located in
*/
Expand Down Expand Up @@ -1770,9 +1783,9 @@ function tap<T>(x: T, fn: (x: T) => void): T {

class ImportedSubnet extends Resource implements ISubnet, IPublicSubnet, IPrivateSubnet {
public readonly internetConnectivityEstablished: IDependable = new ConcreteDependable();
public readonly availabilityZone: string;
public readonly subnetId: string;
public readonly routeTable: IRouteTable;
private readonly _availabilityZone?: string;

constructor(scope: Construct, id: string, attrs: SubnetAttributes) {
super(scope, id);
Expand All @@ -1785,14 +1798,22 @@ class ImportedSubnet extends Resource implements ISubnet, IPublicSubnet, IPrivat
scope.node.addWarning(`No routeTableId was provided to the subnet ${ref}. Attempting to read its .routeTable.routeTableId will return null/undefined. (More info: https://github.com/aws/aws-cdk/pull/3171)`);
}

this.availabilityZone = attrs.availabilityZone;
this._availabilityZone = attrs.availabilityZone;
this.subnetId = attrs.subnetId;
this.routeTable = {
// Forcing routeTableId to pretend non-null to maintain backwards-compatibility. See https://github.com/aws/aws-cdk/pull/3171
routeTableId: attrs.routeTableId!
};
}

public get availabilityZone(): string {
if (!this._availabilityZone) {
// tslint:disable-next-line: max-line-length
throw new Error("You cannot reference a Subnet's availability zone if it was not supplied. Add the availabilityZone when importing using Subnet.fromSubnetAttributes()");
}
return this._availabilityZone;
}

public associateNetworkAcl(id: string, networkAcl: INetworkAcl): void {
const scope = Construct.isConstruct(networkAcl) ? networkAcl : this;
const other = Construct.isConstruct(networkAcl) ? this : networkAcl;
Expand Down
52 changes: 52 additions & 0 deletions packages/@aws-cdk/aws-ec2/test/test.vpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,58 @@ export = {
test.deepEqual(subnetIds.length, 1);
test.deepEqual(subnetIds[0], subnet.subnetId);
test.done();
},

'subnet created from subnetId'(test: Test) {
// GIVEN
const stack = getTestStack();

// WHEN
const subnet = Subnet.fromSubnetId(stack, 'subnet1', 'pub-1');

// THEN
test.deepEqual(subnet.subnetId, 'pub-1');
test.done();
},

'Referencing AZ throws error when subnet created from subnetId'(test: Test) {
// GIVEN
const stack = getTestStack();

// WHEN
const subnet = Subnet.fromSubnetId(stack, 'subnet1', 'pub-1');

// THEN
// tslint:disable-next-line: max-line-length
test.throws(() => subnet.availabilityZone, "You cannot reference a Subnet's availability zone if it was not supplied. Add the availabilityZone when importing using Subnet.fromSubnetAttributes()");
test.done();
},

'Referencing AZ throws error when subnet created from attributes without az'(test: Test) {
// GIVEN
const stack = getTestStack();

// WHEN
const subnet = Subnet.fromSubnetAttributes(stack, 'subnet1', { subnetId : 'pub-1', availabilityZone: '' });

// THEN
test.deepEqual(subnet.subnetId, 'pub-1');
// tslint:disable-next-line: max-line-length
test.throws(() => subnet.availabilityZone, "You cannot reference a Subnet's availability zone if it was not supplied. Add the availabilityZone when importing using Subnet.fromSubnetAttributes()");
test.done();
},

'AZ have value when subnet created from attributes with az'(test: Test) {
// GIVEN
const stack = getTestStack();

// WHEN
const subnet = Subnet.fromSubnetAttributes(stack, 'subnet1', { subnetId : 'pub-1', availabilityZone: 'az-1234' });

// THEN
test.deepEqual(subnet.subnetId, 'pub-1');
test.deepEqual(subnet.availabilityZone, 'az-1234');
test.done();
}

},
Expand Down
15 changes: 15 additions & 0 deletions packages/@aws-cdk/aws-kinesis/lib/stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import * as kms from '@aws-cdk/aws-kms';
import { Construct, IResource, Resource, Stack } from '@aws-cdk/core';
import { CfnStream } from './kinesis.generated';

/**
* A Kinesis Stream
*/
export interface IStream extends IResource {
/**
* The ARN of the stream.
Expand Down Expand Up @@ -64,6 +67,8 @@ export interface StreamAttributes {

/**
* The KMS key securing the contents of the stream if encryption is enabled.
*
* @default - No encryption
*/
readonly encryptionKey?: kms.IKey;
}
Expand Down Expand Up @@ -168,6 +173,9 @@ abstract class StreamBase extends Resource implements IStream {
}
}

/**
* Properties for a Kinesis Stream
*/
export interface StreamProps {
/**
* Enforces a particular physical stream name.
Expand Down Expand Up @@ -213,6 +221,13 @@ export interface StreamProps {
*/
export class Stream extends StreamBase {

/**
* Import an existing Kinesis Stream provided an ARN
*
* @param scope The parent creating construct (usually `this`).
* @param id The construct's name
* @param streamArn Stream ARN (i.e. arn:aws:kinesis:<region>:<account-id>:stream/Foo)
*/
public static fromStreamArn(scope: Construct, id: string, streamArn: string): IStream {
return Stream.fromStreamAttributes(scope, id, { streamArn });
}
Expand Down
4 changes: 0 additions & 4 deletions packages/@aws-cdk/aws-kinesis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@
"stability": "experimental",
"awslint": {
"exclude": [
"docs-public-apis:@aws-cdk/aws-kinesis.Stream.fromStreamArn",
"docs-public-apis:@aws-cdk/aws-kinesis.IStream",
"props-default-doc:@aws-cdk/aws-kinesis.StreamAttributes.encryptionKey",
"docs-public-apis:@aws-cdk/aws-kinesis.StreamProps"
]
}
}
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-logs/lib/log-group.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import * as iam from '@aws-cdk/aws-iam';
import { Construct, IResource, RemovalPolicy, Resource, Stack } from '@aws-cdk/core';
import { Construct, IResource, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core';
import { LogStream } from './log-stream';
import { CfnLogGroup } from './logs.generated';
import { MetricFilter } from './metric-filter';
Expand Down Expand Up @@ -352,7 +352,7 @@ export class LogGroup extends LogGroupBase {
if (retentionInDays === undefined) { retentionInDays = RetentionDays.TWO_YEARS; }
if (retentionInDays === Infinity || retentionInDays === RetentionDays.INFINITE) { retentionInDays = undefined; }

if (retentionInDays !== undefined && retentionInDays <= 0) {
if (retentionInDays !== undefined && !Token.isUnresolved(retentionInDays) && retentionInDays <= 0) {
throw new Error(`retentionInDays must be positive, got ${retentionInDays}`);
}

Expand Down
22 changes: 21 additions & 1 deletion packages/@aws-cdk/aws-logs/test/test.loggroup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, haveResource, matchTemplate } from '@aws-cdk/assert';
import * as iam from '@aws-cdk/aws-iam';
import { RemovalPolicy, Stack } from '@aws-cdk/core';
import { CfnParameter, RemovalPolicy, Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import { LogGroup, RetentionDays } from '../lib';

Expand Down Expand Up @@ -86,6 +86,26 @@ export = {
test.done();
},

'unresolved retention'(test: Test) {
// GIVEN
const stack = new Stack();
const parameter = new CfnParameter(stack, "RetentionInDays", { default: 30, type: "Number" });

// WHEN
new LogGroup(stack, 'LogGroup', {
retention: parameter.valueAsNumber
});

// THEN
expect(stack).to(haveResource('AWS::Logs::LogGroup', {
RetentionInDays: {
Ref: "RetentionInDays"
}
}));

test.done();
},

'will delete log group if asked to'(test: Test) {
// GIVEN
const stack = new Stack();
Expand Down
4 changes: 4 additions & 0 deletions packages/@aws-cdk/core/lib/secret-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export class SecretValue extends Intrinsic {
throw new Error(`secretId cannot be empty`);
}

if (!secretId.startsWith('arn:') && secretId.includes(':')) {
throw new Error(`secret id "${secretId}" is not an ARN but contains ":"`);
}

const parts = [
secretId,
'SecretString',
Expand Down
5 changes: 5 additions & 0 deletions packages/@aws-cdk/core/test/test.secret-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export = {
test.done();
},

'secretsManager with a non-ARN ID that has colon'(test: Test) {
test.throws(() => SecretValue.secretsManager('not:an:arn'), /is not an ARN but contains ":"/);
test.done();
},

'ssmSecure'(test: Test) {
// GIVEN
const stack = new Stack();
Expand Down

0 comments on commit d87eafa

Please sign in to comment.