Skip to content

Commit

Permalink
Merge branch 'master' into instance-type-hpc6a
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jan 19, 2022
2 parents bc333a6 + a5ff631 commit a0da564
Show file tree
Hide file tree
Showing 66 changed files with 1,169 additions and 1,250 deletions.
24 changes: 3 additions & 21 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -803,35 +803,17 @@ The pattern is simple:
with the name of the context key that **enables** this new feature (for
example, `ENABLE_STACK_NAME_DUPLICATES`). The context key should be in the
form `module.Type:feature` (e.g. `@aws-cdk/core:enableStackNameDuplicates`).
2. Use `node.tryGetContext(cxapi.ENABLE_XXX)` to check if this feature is enabled
2. Use `FeatureFlags.of(construct).isEnabled(cxapi.ENABLE_XXX)` to check if this feature is enabled
in your code. If it is not defined, revert to the legacy behavior.
3. Add your feature flag to the `FUTURE_FLAGS` map in
[cx-api/lib/features.ts](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/cx-api/lib/features.ts).
This map is inserted to generated `cdk.json` files for new projects created
through `cdk init`.
4. In your PR title (which goes into CHANGELOG), add a `(under feature flag)` suffix. e.g:
4. In your tests, use the `testFutureBehavior` and `testLegacyBehavior` [jest helper methods] to test the enabled and disabled behavior.
5. In your PR title (which goes into CHANGELOG), add a `(under feature flag)` suffix. e.g:

`fix(core): impossible to use the same physical stack name for two stacks (under feature flag)`

In the [next major version of the
CDK](https://github.com/aws/aws-cdk/issues/3398) we will either remove the
legacy behavior or flip the logic for all these features and then
reset the `FEATURE_FLAGS` map for the next cycle.

### Feature Flags - CDKv2

We have started working on the next version of the CDK, specifically CDKv2. This is currently being maintained
on a separate branch `v2-main` whereas `master` continues to track versions `1.x`.

Feature flags introduced in the CDK 1.x and removed in 2.x, must be added to the `FUTURE_FLAGS_EXPIRED` list in
[cx-api/lib/features.ts](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/cx-api/lib/features.ts)
on the `v2-main` branch.
This will make the default behaviour in CDKv2 as if the flag is enabled and also prevents users from disabling
the feature flag.

A couple of [jest helper methods] are available for use with unit tests. These help run unit tests that test
behaviour when flags are enabled or disabled in the two major versions.

[jest helper methods]: https://github.com/aws/aws-cdk/blob/master/tools/@aws-cdk/cdk-build-tools/lib/feature-flag.ts

## Versioning and Release
Expand Down
5 changes: 5 additions & 0 deletions allowed-breaking-changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,8 @@ base-types:@aws-cdk/aws-lambda-event-sources.SelfManagedKafkaEventSourceProps
changed-type:@aws-cdk/aws-elasticloadbalancingv2.ApplicationLoadBalancer.vpc
changed-type:@aws-cdk/aws-elasticloadbalancingv2.BaseLoadBalancer.vpc
changed-type:@aws-cdk/aws-elasticloadbalancingv2.NetworkLoadBalancer.vpc

# removed methods and properties related to event bridge notifications for S3 buckets as they are not yet supported (19 Jan 2022)
removed:@aws-cdk/aws-s3.Bucket.enableEventBridgeNotification
removed:@aws-cdk/aws-s3.BucketBase.enableEventBridgeNotification
removed:@aws-cdk/aws-s3.BucketProps.eventBridgeEnabled
16 changes: 14 additions & 2 deletions packages/@aws-cdk/assertions/lib/match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class LiteralMatch extends Matcher {

public test(actual: any): MatchResult {
if (Array.isArray(this.pattern)) {
return new ArrayMatch(this.name, this.pattern, { subsequence: false }).test(actual);
return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual);
}

if (typeof this.pattern === 'object') {
Expand Down Expand Up @@ -155,13 +155,21 @@ interface ArrayMatchOptions {
* @default true
*/
readonly subsequence?: boolean;

/**
* Whether to continue matching objects inside the array partially
*
* @default false
*/
readonly partialObjects?: boolean;
}

/**
* Match class that matches arrays.
*/
class ArrayMatch extends Matcher {
private readonly subsequence: boolean;
private readonly partialObjects: boolean;

constructor(
public readonly name: string,
Expand All @@ -170,6 +178,7 @@ class ArrayMatch extends Matcher {

super();
this.subsequence = options.subsequence ?? true;
this.partialObjects = options.partialObjects ?? false;
}

public test(actual: any): MatchResult {
Expand All @@ -195,7 +204,10 @@ class ArrayMatch extends Matcher {
while (patternIdx < this.pattern.length && actualIdx < actual.length) {
const patternElement = this.pattern[patternIdx];

const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement);
const matcher = Matcher.isMatcher(patternElement)
? patternElement
: new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects });

const matcherName = matcher.name;
if (this.subsequence && (matcherName == 'absent' || matcherName == 'anyValue')) {
// array subsequence matcher is not compatible with anyValue() or absent() matcher. They don't make sense to be used together.
Expand Down
21 changes: 19 additions & 2 deletions packages/@aws-cdk/assertions/test/match.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,31 @@ describe('Matchers', () => {
expectPass(matcher, { foo: 'bar', baz: { fred: 'waldo', wobble: 'flob' } });
});

test('nested with ArrayMatch', () => {
test('ArrayMatch nested inside ObjectMatch', () => {
matcher = Match.objectLike({
foo: Match.arrayWith(['bar']),
});
expectPass(matcher, { foo: ['bar', 'baz'], fred: 'waldo' });
expectFailure(matcher, { foo: ['baz'], fred: 'waldo' }, [/Missing element \[bar\] at pattern index 0 at \/foo/]);
});

test('Partiality is maintained throughout arrays', () => {
// Before this fix:
//
// - objectLike({ x: { LITERAL }) ==> LITERAL would be matched partially as well
// - objectLike({ xs: [ { LITERAL } ] }) ==> but here LITERAL would be matched fully
//
// That passing through an array resets the partial matching to full is a
// surprising inconsistency.
//
matcher = Match.objectLike({
foo: [{ bar: 'bar' }],
});
expectPass(matcher, { foo: [{ bar: 'bar' }] }); // Trivially true
expectPass(matcher, { boo: 'boo', foo: [{ bar: 'bar' }] }); // Additional members at top level okay
expectPass(matcher, { foo: [{ bar: 'bar', boo: 'boo' }] }); // Additional members at inner level okay
});

test('absent', () => {
matcher = Match.objectLike({ foo: Match.absent() });
expectPass(matcher, { bar: 'baz' });
Expand Down Expand Up @@ -389,7 +406,7 @@ describe('Matchers', () => {
function expectPass(matcher: Matcher, target: any): void {
const result = matcher.test(target);
if (result.hasFailed()) {
fail(result.toHumanStrings()); // eslint-disable-line jest/no-jasmine-globals
throw new Error(result.toHumanStrings().join('\n')); // eslint-disable-line jest/no-jasmine-globals
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-acmpca/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@aws-cdk/assert-internal": "0.0.0",
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/cfn2ts": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
Expand Down
1 change: 0 additions & 1 deletion packages/@aws-cdk/aws-acmpca/test/acmpca.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import '@aws-cdk/assert-internal/jest';
import {} from '../lib';

test('No tests are specified for this package', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-dynamodb-global/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"constructs": "^3.3.69"
},
"devDependencies": {
"@aws-cdk/assert-internal": "0.0.0",
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/cdk-integ-tools": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import '@aws-cdk/assert-internal/jest';
import { Template } from '@aws-cdk/assertions';
import { Attribute, AttributeType, StreamViewType, Table } from '@aws-cdk/aws-dynamodb';
import { describeDeprecated, testDeprecated } from '@aws-cdk/cdk-build-tools';
import { App, CfnOutput, Stack } from '@aws-cdk/core';
Expand Down Expand Up @@ -26,7 +26,7 @@ describeDeprecated('Default Global DynamoDB stack', () => {
const topStack = stack.node.findChild(CONSTRUCT_NAME) as Stack;
for ( const reg of STACK_PROPS.regions ) {
const tableStack = topStack.node.findChild(CONSTRUCT_NAME + '-' + reg) as Stack;
expect(tableStack).toHaveResource('AWS::DynamoDB::Table', {
Template.fromStack(tableStack).hasResourceProperties('AWS::DynamoDB::Table', {
'KeySchema': [
{
'AttributeName': 'hashKey',
Expand All @@ -46,12 +46,12 @@ describeDeprecated('Default Global DynamoDB stack', () => {
});
}
const customResourceStack = stack.node.findChild(CONSTRUCT_NAME + '-CustomResource') as Stack;
expect(customResourceStack).toHaveResource('AWS::Lambda::Function', {
Template.fromStack(customResourceStack).hasResourceProperties('AWS::Lambda::Function', {
Description: 'Lambda to make DynamoDB a global table',
Handler: 'index.handler',
Timeout: 300,
});
expect(customResourceStack).toHaveResource('AWS::CloudFormation::CustomResource', {
Template.fromStack(customResourceStack).hasResourceProperties('AWS::CloudFormation::CustomResource', {
Regions: STACK_PROPS.regions,
ResourceType: 'Custom::DynamoGlobalTableCoordinator',
TableName: TABLE_NAME,
Expand All @@ -75,7 +75,7 @@ testDeprecated('GlobalTable generated stacks inherit their account from the pare
value: globalTable.regionalTables[0].tableStreamArn!,
});

expect(stack).toMatchTemplate({
Template.fromStack(stack).templateMatches({
'Outputs': {
'DynamoDbOutput': {
'Value': {
Expand Down
56 changes: 56 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/peer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ export class Peer {
return new PrefixList(prefixListId);
}

/**
* A security group ID
*/
public static securityGroupId(securityGroupId: string, sourceSecurityGroupOwnerId?: string): IPeer {
return new SecurityGroupId(securityGroupId, sourceSecurityGroupOwnerId);
}

protected constructor() {
}
}
Expand Down Expand Up @@ -199,3 +206,52 @@ class PrefixList implements IPeer {
return { destinationPrefixListId: this.prefixListId };
}
}

/**
* A connection to or from a given security group ID
*
* For ingress rules, a sourceSecurityGroupOwnerId parameter can be specified if
* the security group exists in another account.
* This parameter will be ignored for egress rules.
*/
class SecurityGroupId implements IPeer {
public readonly canInlineRule = true;
public readonly connections: Connections = new Connections({ peer: this });
public readonly uniqueId: string;

constructor(private readonly securityGroupId: string, private readonly sourceSecurityGroupOwnerId?: string) {
if (!Token.isUnresolved(securityGroupId)) {
const securityGroupMatch = securityGroupId.match(/^sg-[a-z0-9]{8,17}$/);

if (!securityGroupMatch) {
throw new Error(`Invalid security group ID: "${securityGroupId}"`);
}
}

if (sourceSecurityGroupOwnerId && !Token.isUnresolved(sourceSecurityGroupOwnerId)) {
const accountNumberMatch = sourceSecurityGroupOwnerId.match(/^[0-9]{12}$/);

if (!accountNumberMatch) {
throw new Error(`Invalid security group owner ID: "${sourceSecurityGroupOwnerId}"`);
}
}
this.uniqueId = securityGroupId;
}

/**
* Produce the ingress rule JSON for the given connection
*/
public toIngressRuleConfig(): any {
return {
sourceSecurityGroupId: this.securityGroupId,
...(this.sourceSecurityGroupOwnerId && { sourceSecurityGroupOwnerId: this.sourceSecurityGroupOwnerId }),
};
}

/**
* Produce the egress rule JSON for the given connection
*/
public toEgressRuleConfig(): any {
return { destinationSecurityGroupId: this.securityGroupId };
}
}
Loading

0 comments on commit a0da564

Please sign in to comment.