Skip to content

Commit 2cf666e

Browse files
authored
Merge branch 'master' into pr/cloudfront-response
2 parents 036ae27 + 0138292 commit 2cf666e

File tree

12 files changed

+271
-17
lines changed

12 files changed

+271
-17
lines changed

packages/@aws-cdk/aws-ec2/lib/instance-types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ export enum InstanceClass {
118118
*/
119119
R5 = 'r5',
120120

121+
/**
122+
* Memory optimized instances, 6th generation with Intel Xeon Scalable processors (3rd generation processors code named Ice Lake)
123+
*/
124+
MEMORY6_INTEL = 'r6i',
125+
126+
/**
127+
* Memory optimized instances, 6th generation with Intel Xeon Scalable processors (3rd generation processors code named Ice Lake)
128+
*/
129+
R6I = 'r6i',
130+
121131
/**
122132
* Memory optimized instances for high performance computing, 5th generation
123133
*/

packages/@aws-cdk/aws-ec2/test/instance.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ describe('instance', () => {
138138
});
139139
test('instance architecture is correctly discerned for x86-64 instance', () => {
140140
// GIVEN
141-
const sampleInstanceClasses = ['c5', 'm5ad', 'r5n', 'm6', 't3a']; // A sample of x86-64 instance classes
141+
const sampleInstanceClasses = ['c5', 'm5ad', 'r5n', 'm6', 't3a', 'r6i']; // A sample of x86-64 instance classes
142142

143143
for (const instanceClass of sampleInstanceClasses) {
144144
// WHEN

packages/@aws-cdk/aws-iam/README.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ Identity Pools Developer Guide].
329329

330330
The following examples defines an OpenID Connect provider. Two client IDs
331331
(audiences) are will be able to send authentication requests to
332-
https://openid/connect.
332+
<https://openid/connect>.
333333

334334
```ts
335335
const provider = new iam.OpenIdConnectProvider(this, 'MyProvider', {
@@ -439,6 +439,26 @@ const user = iam.User.fromUserAttributes(this, 'MyImportedUserByAttributes', {
439439
});
440440
```
441441

442+
## Groups
443+
444+
An IAM user group is a collection of IAM users. User groups let you specify permissions for multiple users.
445+
446+
```ts
447+
const group = new iam.Group(this, 'MyGroup');
448+
```
449+
450+
To import an existing group by ARN:
451+
452+
```ts
453+
const group = iam.Group.fromGroupArn(this, 'MyImportedGroupByArn', 'arn:aws:iam::account-id:group/group-name');
454+
```
455+
456+
To import an existing group by name [with path](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-friendly-names):
457+
458+
```ts
459+
const group = iam.Group.fromGroupName(this, 'MyImportedGroupByName', 'group-name');
460+
```
461+
442462
To add a user to a group (both for a new and imported user/group):
443463

444464
```ts
@@ -450,12 +470,11 @@ user.addToGroup(group);
450470
group.addUser(user);
451471
```
452472

453-
454473
## Features
455474

456-
* Policy name uniqueness is enforced. If two policies by the same name are attached to the same
475+
* Policy name uniqueness is enforced. If two policies by the same name are attached to the same
457476
principal, the attachment will fail.
458-
* Policy names are not required - the CDK logical ID will be used and ensured to be unique.
459-
* Policies are validated during synthesis to ensure that they have actions, and that policies
477+
* Policy names are not required - the CDK logical ID will be used and ensured to be unique.
478+
* Policies are validated during synthesis to ensure that they have actions, and that policies
460479
attached to IAM principals specify relevant resources, while policies attached to resources
461480
specify which IAM principals they apply to.

packages/@aws-cdk/aws-iam/lib/group.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,24 @@ export class Group extends GroupBase {
156156
return new Import(scope, id);
157157
}
158158

159+
/**
160+
* Import an existing group by given name (with path).
161+
* This method has same caveats of `fromGroupArn`
162+
*
163+
* @param scope construct scope
164+
* @param id construct id
165+
* @param groupName the groupName (path included) of the existing group to import
166+
*/
167+
static fromGroupName(scope: Construct, id: string, groupName: string) {
168+
const groupArn = Stack.of(scope).formatArn({
169+
service: 'iam',
170+
region: '',
171+
resource: 'group',
172+
resourceName: groupName,
173+
});
174+
return Group.fromGroupArn(scope, id, groupArn);
175+
}
176+
159177
public readonly groupName: string;
160178
public readonly groupArn: string;
161179

packages/@aws-cdk/aws-iam/test/group.test.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ describe('IAM groups', () => {
2727
{
2828
MyGroupCBA54B1B: { Type: 'AWS::IAM::Group' },
2929
User1E278A736:
30-
{
31-
Type: 'AWS::IAM::User',
32-
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
33-
},
30+
{
31+
Type: 'AWS::IAM::User',
32+
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
33+
},
3434
User21F1486D1:
35-
{
36-
Type: 'AWS::IAM::User',
37-
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
38-
},
35+
{
36+
Type: 'AWS::IAM::User',
37+
Properties: { Groups: [{ Ref: 'MyGroupCBA54B1B' }] },
38+
},
3939
},
4040
});
4141
});
@@ -56,4 +56,21 @@ describe('IAM groups', () => {
5656
],
5757
});
5858
});
59+
60+
test('groups imported by group name have valid arn', () => {
61+
// GIVEN
62+
const stack = new Stack();
63+
64+
// WHEN
65+
const group1 = Group.fromGroupName(stack, 'imported-group1', 'MyGroupName1');
66+
const group2 = Group.fromGroupName(stack, 'imported-group2', 'division/MyGroupName2');
67+
68+
// THEN
69+
expect(stack.resolve(group1.groupArn)).toStrictEqual({
70+
'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::', { Ref: 'AWS::AccountId' }, ':group/MyGroupName1']],
71+
});
72+
expect(stack.resolve(group2.groupArn)).toStrictEqual({
73+
'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::', { Ref: 'AWS::AccountId' }, ':group/division/MyGroupName2']],
74+
});
75+
});
5976
});

packages/@aws-cdk/core/lib/asset-staging.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ export class AssetStaging extends CoreConstruct {
189189
if (props.bundling) {
190190
// Check if we actually have to bundle for this stack
191191
const bundlingStacks: string[] = this.node.tryGetContext(cxapi.BUNDLING_STACKS) ?? ['*'];
192-
skip = !bundlingStacks.find(pattern => minimatch(Stack.of(this).stackName, pattern));
192+
// bundlingStacks is of the form `Stage/Stack`, convert it to `Stage-Stack` before comparing to stack name
193+
skip = !bundlingStacks.find(pattern => minimatch(Stack.of(this).stackName, pattern.replace('/', '-')));
193194
const bundling = props.bundling;
194195
stageThisAsset = () => this.stageByBundling(bundling, skip);
195196
} else {

packages/@aws-cdk/core/test/staging.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,8 +859,42 @@ describe('staging', () => {
859859
expect(asset.stagedPath).toEqual(directory);
860860
expect(asset.relativeStagedPath(stack)).toEqual(directory);
861861
expect(asset.assetHash).toEqual('f66d7421aa2d044a6c1f60ddfc76dc78571fcd8bd228eb48eb394e2dbad94a5c');
862+
});
863+
864+
test('correctly skips bundling with stack under stage', () => {
865+
// GIVEN
866+
const app = new App();
867+
868+
const stage = new Stage(app, 'Stage');
869+
stage.node.setContext(cxapi.BUNDLING_STACKS, ['Stage/Stack1']);
870+
871+
const stack1 = new Stack(stage, 'Stack1');
872+
const stack2 = new Stack(stage, 'Stack2');
873+
const directory = path.join(__dirname, 'fs', 'fixtures', 'test1');
862874

875+
new AssetStaging(stack1, 'Asset', {
876+
sourcePath: directory,
877+
assetHashType: AssetHashType.OUTPUT,
878+
bundling: {
879+
image: DockerImage.fromRegistry('alpine'),
880+
command: [DockerStubCommand.SUCCESS],
881+
},
882+
});
883+
884+
new AssetStaging(stack2, 'Asset', {
885+
sourcePath: directory,
886+
assetHashType: AssetHashType.OUTPUT,
887+
bundling: {
888+
image: DockerImage.fromRegistry('alpine'),
889+
command: [DockerStubCommand.MULTIPLE_FILES],
890+
},
891+
});
863892

893+
const dockerStubInput = readDockerStubInputConcat();
894+
// Docker ran for the asset in Stack1
895+
expect(dockerStubInput).toMatch(DockerStubCommand.SUCCESS);
896+
// DOcker did not run for the asset in Stack2
897+
expect(dockerStubInput).not.toMatch(DockerStubCommand.MULTIPLE_FILES);
864898
});
865899

866900
test('bundling still occurs with partial wildcard', () => {

packages/@aws-cdk/custom-resources/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,25 @@ This sample demonstrates the following concepts:
347347
* Non-intrinsic physical IDs
348348
* Implemented in Python
349349

350+
351+
### Customizing Provider Function name
352+
353+
In multi-account environments or when the custom resource may be re-utilized across several
354+
stacks it may be useful to manually set a name for the Provider Function Lambda and therefore
355+
have a predefined service token ARN.
356+
357+
```ts
358+
359+
const myProvider = new cr.Provider(this, 'MyProvider', {
360+
onEventHandler: onEvent,
361+
isCompleteHandler: isComplete,
362+
logRetention: logs.RetentionDays.ONE_DAY,
363+
role: myRole,
364+
providerFunctionName: 'the-lambda-name', // Optional
365+
});
366+
367+
```
368+
350369
## Custom Resources for AWS APIs
351370

352371
Sometimes a single API call can fill the gap in the CloudFormation coverage. In

packages/@aws-cdk/custom-resources/lib/provider-framework/provider.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ export interface ProviderProps {
115115
* @default - A default role will be created.
116116
*/
117117
readonly role?: iam.IRole;
118+
119+
/**
120+
* Provider Lambda name.
121+
*
122+
* The provider lambda function name.
123+
*
124+
* @default - CloudFormation default name from unique physical ID
125+
*/
126+
readonly providerFunctionName?: string;
118127
}
119128

120129
/**
@@ -165,7 +174,7 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
165174

166175
this.role = props.role;
167176

168-
const onEventFunction = this.createFunction(consts.FRAMEWORK_ON_EVENT_HANDLER_NAME);
177+
const onEventFunction = this.createFunction(consts.FRAMEWORK_ON_EVENT_HANDLER_NAME, props.providerFunctionName);
169178

170179
if (this.isCompleteHandler) {
171180
const isCompleteFunction = this.createFunction(consts.FRAMEWORK_IS_COMPLETE_HANDLER_NAME);
@@ -198,7 +207,7 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
198207
};
199208
}
200209

201-
private createFunction(entrypoint: string) {
210+
private createFunction(entrypoint: string, name?: string) {
202211
const fn = new lambda.Function(this, `framework-${entrypoint}`, {
203212
code: lambda.Code.fromAsset(RUNTIME_HANDLER_PATH),
204213
description: `AWS CDK resource provider framework - ${entrypoint} (${this.node.path})`.slice(0, 256),
@@ -210,6 +219,7 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
210219
vpcSubnets: this.vpcSubnets,
211220
securityGroups: this.securityGroups,
212221
role: this.role,
222+
functionName: name,
213223
});
214224

215225
fn.addEnvironment(consts.USER_ON_EVENT_FUNCTION_ARN_ENV, this.onEventHandler.functionArn);

packages/@aws-cdk/custom-resources/test/provider-framework/provider.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,27 @@ describe('role', () => {
397397
});
398398
});
399399
});
400+
401+
describe('name', () => {
402+
it('uses custom name when present', () => {
403+
// GIVEN
404+
const stack = new Stack();
405+
const providerFunctionName = 'test-name';
406+
407+
// WHEN
408+
new cr.Provider(stack, 'MyProvider', {
409+
onEventHandler: new lambda.Function(stack, 'MyHandler', {
410+
code: lambda.Code.fromAsset(path.join(__dirname, './integration-test-fixtures/s3-file-handler')),
411+
handler: 'index.onEvent',
412+
runtime: lambda.Runtime.NODEJS_10_X,
413+
}),
414+
providerFunctionName,
415+
});
416+
417+
// THEN
418+
expect(stack).toHaveResourceLike('AWS::Lambda::Function', {
419+
FunctionName: providerFunctionName,
420+
});
421+
});
422+
});
423+

0 commit comments

Comments
 (0)