Skip to content

Commit

Permalink
Merge branch 'main' into awsgh-26089
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jul 24, 2023
2 parents 69ecdcc + eea223b commit dfbe8d5
Show file tree
Hide file tree
Showing 17 changed files with 172 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/github-merit-badger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
badges: '[beginning-contributor,repeat-contributor,valued-contributor,admired-contributor,star-contributor,distinguished-contributor]'
thresholds: '[0,3,6,13,25,50]'
badge-type: 'achievement'
ignore-usernames: '[RomainMuller,rix0rrr,MrArnoldPalmer,iliapolo,otaviomacedo,madeline-k,kaizencc,comcalvi,corymhall,peterwoodworth,ryparker,TheRealAmazonKendra,vinayak-kukreja,Naumel,mrgrain,pahud,cgarvis,kellertk,HBobertz,sumupitchayan,pattasai,SankyRed,udaypant,colifran,khushail,aws-cdk-automation,dependabot[bot],mergify[bot]]'
ignore-usernames: '[RomainMuller,rix0rrr,MrArnoldPalmer,iliapolo,otaviomacedo,madeline-k,kaizencc,comcalvi,corymhall,peterwoodworth,ryparker,TheRealAmazonKendra,vinayak-kukreja,Naumel,mrgrain,pahud,cgarvis,kellertk,HBobertz,sumupitchayan,pattasai,SankyRed,udaypant,colifran,khushail,scanlonp,aws-cdk-automation,dependabot[bot],mergify[bot]]'
2 changes: 1 addition & 1 deletion .mergify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pull_request_rules:
label:
add: [ contribution/core ]
conditions:
- author~=^(RomainMuller|rix0rrr|MrArnoldPalmer|iliapolo|uttarasridhar|otaviomacedo|madeline-k|kaizencc|comcalvi|corymhall|peterwoodworth|ryparker|TheRealAmazonKendra|vinayak-kukreja|Naumel|mrgrain|pahud|cgarvis|kellertk|HBobertz|sumupitchayan|pattasai|SankyRed|udaypant|colifran)$
- author~=^(RomainMuller|rix0rrr|MrArnoldPalmer|iliapolo|uttarasridhar|otaviomacedo|madeline-k|kaizencc|comcalvi|corymhall|peterwoodworth|ryparker|TheRealAmazonKendra|vinayak-kukreja|Naumel|mrgrain|pahud|cgarvis|kellertk|HBobertz|sumupitchayan|pattasai|SankyRed|udaypant|colifran|scanlonp)$
- -label~="contribution/core"
- name: automatic merge
actions:
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ Note: `lerna` uses a local cache by default. If your build fails, you can fix
the issue and run the command again and it will not rerun any previously
successful steps.

Note: If you encounter `ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`, please try running the command with increased memory by using `export NODE_OPTIONS="--max-old-space-size=8192"`.

At this point, you can run build and test the `aws-cdk-lib` module by running

```console
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ integTest('can use the custom permissions boundary to bootstrap', withoutBootstr
expect(template).toContain('permission-boundary-name');
}));

integTest('can use the custom permissions boundary (with slashes) to bootstrap', withoutBootstrap(async (fixture) => {
let template = await fixture.cdkBootstrapModern({
// toolkitStackName doesn't matter for this particular invocation
toolkitStackName: fixture.bootstrapStackName,
showTemplate: true,
customPermissionsBoundary: 'permission-boundary-name/with/path',
});

expect(template).toContain('permission-boundary-name/with/path');
}));

integTest('can remove customPermissionsBoundary', withoutBootstrap(async (fixture) => {
const bootstrapStackName = fixture.bootstrapStackName;
const policyName = `${bootstrapStackName}-pb`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ export interface DefaultStagingStackOptions {
* @default true
*/
readonly autoDeleteStagingAssets?: boolean;

/**
* Specify a custom prefix to be used as the staging stack name and
* construct ID. The prefix will be appended before the appId, which
* is required to be part of the stack name and construct ID to
* ensure uniqueness.
*
* @default 'StagingStack'
*/
readonly stagingStackNamePrefix?: string;
}

/**
Expand Down Expand Up @@ -159,12 +169,13 @@ export class DefaultStagingStack extends Stack implements IStagingResources {
new UsingAppStagingSynthesizer(stack, `UsingAppStagingSynthesizer/${stack.stackName}`);
}

const stackId = `StagingStack-${appId}-${context.environmentString}`;
const stackPrefix = options.stagingStackNamePrefix ?? 'StagingStack';
// Stack name does not need to contain environment because appId is unique inside an env
const stackName = `${stackPrefix}-${appId}`;
const stackId = `${stackName}-${context.environmentString}`;
return new DefaultStagingStack(app, stackId, {
...options,

// Does not need to contain environment because stack names are unique inside an env anyway
stackName: `StagingStack-${appId}`,
stackName,
env: {
account: stack.account,
region: stack.region,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,29 @@ describe(AppStagingSynthesizer, () => {
Template.fromJSON(getStagingResourceStack(asm).template).resourceCountIs('Custom::S3AutoDeleteObjects', 0);
});

test('stack prefix can be customized', () => {
// GIVEN
const prefix = 'Prefix';
app = new App({
defaultStackSynthesizer: AppStagingSynthesizer.defaultResources({
appId: APP_ID,
stagingStackNamePrefix: prefix,
}),
});
stack = new Stack(app, 'Stack', {
env: {
account: '000000000000',
region: 'us-east-1',
},
});

// WHEN
const asm = app.synth();

// THEN
expect(getStagingResourceStack(asm, prefix).template).toBeDefined();
});

describe('environment specifics', () => {
test('throws if App includes env-agnostic and specific env stacks', () => {
// GIVEN - App with Stack with specific environment
Expand Down Expand Up @@ -536,7 +559,7 @@ describe(AppStagingSynthesizer, () => {
/**
* Return the staging resource stack that is generated as part of the assembly
*/
function getStagingResourceStack(asm: CloudAssembly) {
return asm.getStackArtifact(`StagingStack-${APP_ID}-000000000000-us-east-1`);
function getStagingResourceStack(asm: CloudAssembly, prefix?: string) {
return asm.getStackArtifact(`${prefix ?? 'StagingStack'}-${APP_ID}-000000000000-us-east-1`);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ describe('lambda api', () => {
// THEN
const template = Template.fromStack(stack);
// Ensure that all methods have "AWS_PROXY" integrations.
const methods = template.findResources('AWS::ApiGateway::Mathod');
const methods = template.findResources('AWS::ApiGateway::Method');
const hasProxyIntegration = Match.objectLike({ Integration: Match.objectLike({ Type: 'AWS_PROXY' }) });
for (const method of Object.values(methods)) {
expect(hasProxyIntegration.test(method)).toBeTruthy();
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk-lib/aws-ecs/lib/base/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1367,7 +1367,7 @@ export abstract class BaseService extends Resource
}

private deploymentAlarmsAvailableInRegion(): boolean {
const unsupportedPartitions = ['aws-cn', 'aws-us-gov', 'aws-us-iso', 'aws-us-iso-b'];
const unsupportedPartitions = ['aws-cn', 'aws-us-gov', 'aws-iso', 'aws-iso-b'];
const currentRegion = RegionInfo.get(this.stack.resolve(this.stack.region));
if (currentRegion.partition) {
return !unsupportedPartitions.includes(currentRegion.partition);
Expand Down
26 changes: 26 additions & 0 deletions packages/aws-cdk-lib/aws-ecs/test/ec2/ec2-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2365,6 +2365,32 @@ describe('ec2 service', () => {
});
});

test('no deployment alarms in isolated partitions', () => {
const app = new cdk.App();
const govCloudStack = new cdk.Stack(app, 'IsoStack', {
env: { region: 'us-isob-east-1' },
});
const vpc = new ec2.Vpc(govCloudStack, 'MyVpc', {});
const gcCluster = new ecs.Cluster(govCloudStack, 'EcsCluster', { vpc });
addDefaultCapacityProvider(gcCluster, govCloudStack, vpc);
const gcTaskDefinition = new ecs.Ec2TaskDefinition(govCloudStack, 'Ec2TaskDef');

gcTaskDefinition.addContainer('web', {
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
memoryLimitMiB: 512,
});
new ecs.Ec2Service(govCloudStack, 'Ec2Service', {
cluster: gcCluster,
taskDefinition: gcTaskDefinition,
});

Template.fromStack(govCloudStack).hasResourceProperties('AWS::ECS::Service', {
DeploymentConfiguration: {
Alarms: Match.absent(),
},
});
});

/**
* This section of tests test all combinations of the following possible
* alarm names and metrics. Most combinations work just fine, some
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-cdk-lib/aws-rds/lib/cluster-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ export class AuroraMysqlEngineVersion {
public static readonly VER_3_02_1 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.1');
/** Version "8.0.mysql_aurora.3.02.2". */
public static readonly VER_3_02_2 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.2');
/** Version "8.0.mysql_aurora.3.02.3". */
public static readonly VER_3_02_3 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.3');
/** Version "8.0.mysql_aurora.3.03.0". */
public static readonly VER_3_03_0 = AuroraMysqlEngineVersion.builtIn_8_0('3.03.0');

Expand Down
41 changes: 28 additions & 13 deletions packages/aws-cdk-lib/core/lib/private/tree-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { ISynthesisSession } from '../stack-synthesizers';
import { IInspectable, TreeInspector } from '../tree';

const FILE_PATH = 'tree.json';

type Mutable<T> = {
-readonly [P in keyof T]: Mutable<T[P]>;
};
/**
* Construct that is automatically attached to the top-level `App`.
* This generates, as part of synthesis, a file containing the construct tree and the metadata for each node in the tree.
Expand Down Expand Up @@ -109,21 +111,34 @@ export class TreeMetadata extends Construct {
* tree that leads to a specific construct so drop any nodes not in that path
*
* @param node Node the current tree node
* @param child Node the previous tree node and the current node's child node
* @returns Node the new tree
* @returns Node the root node of the new tree
*/
private renderTreeWithChildren(node: Node, child?: Node): Node {
if (node.parent) {
return this.renderTreeWithChildren(node.parent, node);
} else if (child) {
return {
...node,
children: {
[child.id]: child,
},
private renderTreeWithChildren(node: Node): Node {
/**
* @param currentNode - The current node being evaluated
* @param currentNodeChild - The previous node which should be the only child of the current node
* @returns The node with all children removed except for the path to the current node
*/
function renderTreeWithSingleChild(currentNode: Mutable<Node>, currentNodeChild: Mutable<Node>) {
currentNode.children = {
[currentNodeChild.id]: currentNodeChild,
};
if (currentNode.parent) {
currentNode.parent = renderTreeWithSingleChild(currentNode.parent, currentNode);
}
return currentNode;
}
return node;

const currentNode = node.parent ? renderTreeWithSingleChild(node.parent, node) : node;
// now that we have the new tree we need to return the root node
let root = currentNode;
do {
if (root.parent) {
root = root.parent;
}
} while (root.parent);

return root;
}

/**
Expand Down
18 changes: 16 additions & 2 deletions packages/aws-cdk-lib/core/lib/validation/private/construct-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,26 @@ export class ConstructTree {
return node;
}

/**
* @param node - the root node of the tree
* @returns the terminal node in the tree
*/
private lastChild(node: Node): Node {
if (node.children) {
return this.lastChild(this.getChild(node.children));
}
return node;
}

/**
* Get a ConstructTrace from the cache for a given construct
*
* Construct the stack trace of constructs. This will start with the
* root of the tree and go down to the construct that has the violation
*/
public getTrace(node: Node, locations?: string[]): ConstructTrace | undefined {
const trace = this._traceCache.get(node.path);
const lastChild = this.lastChild(node);
const trace = this._traceCache.get(lastChild.path);
if (trace) {
return trace;
}
Expand All @@ -177,7 +189,9 @@ export class ConstructTree {
libraryVersion: node.constructInfo?.version,
location: thisLocation ?? "Run with '--debug' to include location info",
};
this._traceCache.set(constructTrace.path, constructTrace);
// set the cache for the last child path. If the last child path is different then
// we have a different tree and need to retrieve the trace again
this._traceCache.set(lastChild.path, constructTrace);
return constructTrace;
}

Expand Down
9 changes: 9 additions & 0 deletions packages/aws-cdk-lib/core/test/validation/trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ class MyL2Resource extends Resource implements IMyL2Resource {
public readonly constructPath: string;
constructor(scope: Construct, id: string) {
super(scope, id);
new core.CfnResource(this, 'Resource1', {
type: 'AWS::CDK::TestResource',
properties: {
testProp1: 'testValue',
},
});
const resource = new core.CfnResource(this, 'Resource', {
type: 'AWS::CDK::TestResource',
properties: {
Expand All @@ -127,6 +133,7 @@ class MyConstruct extends Construct {
public readonly constructPath: string;
constructor(scope: Construct, id: string) {
super(scope, id);
new MyL2Resource(this, 'MyL2Resource1');
const myResource = new MyL2Resource(this, 'MyL2Resource');
this.constructPath = myResource.constructPath;
}
Expand All @@ -136,6 +143,8 @@ class MyStack extends core.Stack {
public readonly constructPath: string;
constructor(scope: Construct, id: string, props?: core.StackProps) {
super(scope, id, props);
new MyConstruct(this, 'MyConstruct2');
new MyConstruct(this, 'MyConstruct3');
const myConstruct = new MyConstruct(this, 'MyConstruct');
this.constructPath = myConstruct.constructPath;
}
Expand Down
4 changes: 3 additions & 1 deletion packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,9 @@ export class Bootstrapper {

private validatePolicyName(permissionsBoundary: string) {
// https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicy.html
const regexp: RegExp = /[\w+=,.@-]+/;
// Added support for policy names with a path
// See https://github.com/aws/aws-cdk/issues/26320
const regexp: RegExp = /[\w+\/=,.@-]+/;
const matches = regexp.exec(permissionsBoundary);
if (!(matches && matches.length === 1 && matches[0] === permissionsBoundary)) {
throw new Error(`The permissions boundary name ${permissionsBoundary} does not match the IAM conventions.`);
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-cdk/lib/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ export class CdkToolkit {
}
}

stream.write(format('\n✨ Number of stacks with differences: %s\n', diffs));

return diffs && options.fail ? 1 : 0;
}

Expand Down
22 changes: 22 additions & 0 deletions packages/aws-cdk/test/api/bootstrap2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,28 @@ describe('Bootstrapping v2', () => {
]));
});

test('adding permission boundary with path in policy name', async () => {
mockTheToolkitInfo({
Parameters: [
{
ParameterKey: 'InputPermissionsBoundary',
ParameterValue: '',
},
],
});
await bootstrapper.bootstrapEnvironment(env, sdk, {
parameters: {
customPermissionsBoundary: 'permissions-boundary-name/with/path',
},
});

expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([
expect.arrayContaining([
expect.stringMatching(/Adding new permissions boundary permissions-boundary-name\/with\/path/),
]),
]));
});

test('passing trusted accounts without CFN managed policies results in an error', async () => {
await expect(bootstrapper.bootstrapEnvironment(env, sdk, {
parameters: {
Expand Down
8 changes: 7 additions & 1 deletion packages/aws-cdk/test/diff.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ describe('non-nested stacks', () => {
expect(plainTextOutput).toContain('Stack A');
expect(plainTextOutput).toContain('Stack B');

expect(buffer.data.trim()).toContain('✨ Number of stacks with differences: 2');
expect(exitCode).toBe(0);
});

Expand All @@ -96,6 +97,7 @@ describe('non-nested stacks', () => {
});

// THEN
expect(buffer.data.trim()).toContain('✨ Number of stacks with differences: 1');
expect(exitCode).toBe(1);
});

Expand All @@ -121,6 +123,7 @@ describe('non-nested stacks', () => {
});

// THEN
expect(buffer.data.trim()).toContain('✨ Number of stacks with differences: 1');
expect(exitCode).toBe(1);
});

Expand Down Expand Up @@ -255,7 +258,10 @@ Resources
└─ [~] .Properties:
└─ [~] .Prop:
├─ [-] old-value
└─ [+] new-value`);
└─ [+] new-value
✨ Number of stacks with differences: 3`);

expect(exitCode).toBe(0);
});
Expand Down

0 comments on commit dfbe8d5

Please sign in to comment.