Skip to content

Commit

Permalink
Merge branch 'master' into feature-lb-access-log
Browse files Browse the repository at this point in the history
  • Loading branch information
ramancloudsmartz authored Jun 7, 2021
2 parents e31ac0a + 6c7c7b5 commit 90fd0cd
Show file tree
Hide file tree
Showing 7 changed files with 403 additions and 392 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/yarn-upgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,7 @@ jobs:
run: yarn install

- name: Run "yarn upgrade"
# jsdom breaks us starting from 16.5.1. Caused by https://github.com/feross/queue-microtask/issues/17
# in combination with https://github.com/jsdom/jsdom/commit/31eb938fdaa5d446e194c9ec4f0d6b46b4354954
# pinning this for now since its only used in tests (by jest-enviroment-jsdom).
# we are not even using this because our environment is 'node' - just the mere fact this module is loaded is what breaks.
# also - jest-enviroment-jsdom doesnt actually require 16.5.1 (https://github.com/facebook/jest/blob/master/packages/jest-environment-jsdom/package.json#L23)
run: yarn upgrade --pattern '!(jsdom)'
run: yarn upgrade

# Next, create and upload the changes as a patch file. This will later be downloaded to create a pull request
# Creating a pull request requires write permissions and it's best to keep write privileges isolated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ export interface DefaultStackSynthesizerProps {
* @default - DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX
*/
readonly bucketPrefix?: string;

/**
* Bootstrap stack version SSM parameter.
*
* The placeholder `${Qualifier}` will be replaced with the value of qualifier.
*
* @default DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER
*/
readonly bootstrapStackVersionSsmParameter?: string;
}

/**
Expand Down Expand Up @@ -227,6 +236,11 @@ export class DefaultStackSynthesizer extends StackSynthesizer {
*/
public static readonly DEFAULT_FILE_ASSET_PREFIX = '';

/**
* Default bootstrap stack version SSM parameter.
*/
public static readonly DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER = '/cdk-bootstrap/${Qualifier}/version';

private _stack?: Stack;
private bucketName?: string;
private repositoryName?: string;
Expand All @@ -237,6 +251,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer {
private lookupRoleArn?: string;
private qualifier?: string;
private bucketPrefix?: string;
private bootstrapStackVersionSsmParameter?: string;

private readonly files: NonNullable<cxschema.AssetManifest['files']> = {};
private readonly dockerImages: NonNullable<cxschema.AssetManifest['dockerImages']> = {};
Expand Down Expand Up @@ -297,6 +312,11 @@ export class DefaultStackSynthesizer extends StackSynthesizer {
this.imageAssetPublishingRoleArn = specialize(this.props.imageAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSET_PUBLISHING_ROLE_ARN);
this.lookupRoleArn = specialize(this.props.lookupRoleArn ?? DefaultStackSynthesizer.DEFAULT_LOOKUP_ROLE_ARN);
this.bucketPrefix = specialize(this.props.bucketPrefix ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX);
this.bootstrapStackVersionSsmParameter = replaceAll(
this.props.bootstrapStackVersionSsmParameter ?? DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER,
'${Qualifier}',
qualifier,
);
/* eslint-enable max-len */
}

Expand Down Expand Up @@ -393,7 +413,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer {
// If it's done AFTER _synthesizeTemplate(), then the template won't contain the
// right constructs.
if (this.props.generateBootstrapVersionRule ?? true) {
addBootstrapVersionRule(this.stack, MIN_BOOTSTRAP_STACK_VERSION, this.qualifier);
addBootstrapVersionRule(this.stack, MIN_BOOTSTRAP_STACK_VERSION, <string> this.bootstrapStackVersionSsmParameter);
}

this.synthesizeStackTemplate(this.stack, session);
Expand All @@ -408,7 +428,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer {
cloudFormationExecutionRoleArn: this._cloudFormationExecutionRoleArn,
stackTemplateAssetObjectUrl: templateManifestUrl,
requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION,
bootstrapStackVersionSsmParameter: `/cdk-bootstrap/${this.qualifier}/version`,
bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter,
additionalDependencies: [artifactId],
});
}
Expand Down Expand Up @@ -497,7 +517,7 @@ export class DefaultStackSynthesizer extends StackSynthesizer {
properties: {
file: manifestFile,
requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION,
bootstrapStackVersionSsmParameter: `/cdk-bootstrap/${this.qualifier}/version`,
bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter,
},
});

Expand Down Expand Up @@ -564,7 +584,7 @@ function stackLocationOrInstrinsics(stack: Stack) {
* The CLI normally checks this, but in a pipeline the CLI is not involved
* so we encode this rule into the template in a way that CloudFormation will check it.
*/
function addBootstrapVersionRule(stack: Stack, requiredVersion: number, qualifier: string) {
function addBootstrapVersionRule(stack: Stack, requiredVersion: number, bootstrapStackVersionSsmParameter: string) {
// Because of https://github.com/aws/aws-cdk/blob/master/packages/assert-internal/lib/synth-utils.ts#L74
// synthesize() may be called more than once on a stack in unit tests, and the below would break
// if we execute it a second time. Guard against the constructs already existing.
Expand All @@ -573,7 +593,7 @@ function addBootstrapVersionRule(stack: Stack, requiredVersion: number, qualifie
const param = new CfnParameter(stack, 'BootstrapVersion', {
type: 'AWS::SSM::Parameter::Value<String>',
description: 'Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store.',
default: `/cdk-bootstrap/${qualifier}/version`,
default: bootstrapStackVersionSsmParameter,
});

// There is no >= check in CloudFormation, so we have to check the number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ nodeunitShim({
test.done();
},

'customize version parameter'(test: Test) {
// GIVEN
const myapp = new App();

// WHEN
const mystack = new Stack(myapp, 'mystack', {
synthesizer: new DefaultStackSynthesizer({
bootstrapStackVersionSsmParameter: 'stack-version-parameter',
}),
});

mystack.synthesizer.addFileAsset({
fileName: __filename,
packaging: FileAssetPackaging.FILE,
sourceHash: 'file-asset-hash',
});

// THEN
const asm = myapp.synth();
const manifestArtifact = getAssetManifest(asm);

// THEN - the asset manifest has an SSM parameter entry
expect(manifestArtifact.bootstrapStackVersionSsmParameter).toEqual('stack-version-parameter');

test.done();
},

'generates missing context with the lookup role ARN as one of the missing context properties'(test: Test) {
// GIVEN
stack = new Stack(app, 'Stack2', {
Expand Down Expand Up @@ -246,7 +273,6 @@ nodeunitShim({
test.done();
},


'synthesis with bucketPrefix'(test: Test) {
// GIVEN
const myapp = new App();
Expand Down
6 changes: 5 additions & 1 deletion packages/@aws-cdk/custom-resources/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,18 @@ the actual handler.
```ts
import { CustomResource } from '@aws-cdk/core';
import * as logs from '@aws-cdk/aws-logs';
import * as iam from '@aws-cdk/aws-iam';
import * as cr from '@aws-cdk/custom-resources';

const onEvent = new lambda.Function(this, 'MyHandler', { /* ... */ });

const myRole = new iam.Role(this, 'MyRole', { /* ... */ });

const myProvider = new cr.Provider(this, 'MyProvider', {
onEventHandler: onEvent,
isCompleteHandler: isComplete, // optional async "waiter"
logRetention: logs.RetentionDays.ONE_DAY // default is INFINITE
logRetention: logs.RetentionDays.ONE_DAY, // default is INFINITE
role: myRole, // must be assumable by the `lambda.amazonaws.com` service principal
});

new CustomResource(this, 'Resource1', { serviceToken: myProvider.serviceToken });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as path from 'path';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda';
import * as logs from '@aws-cdk/aws-logs';
import { Duration } from '@aws-cdk/core';
Expand Down Expand Up @@ -105,6 +106,15 @@ export interface ProviderProps {
*/
readonly securityGroups?: ec2.ISecurityGroup[];

/**
* AWS Lambda execution role.
*
* The role that will be assumed by the AWS Lambda.
* Must be assumable by the 'lambda.amazonaws.com' service principal.
*
* @default - A default role will be created.
*/
readonly role?: iam.IRole;
}

/**
Expand Down Expand Up @@ -135,6 +145,7 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
private readonly vpc?: ec2.IVpc;
private readonly vpcSubnets?: ec2.SubnetSelection;
private readonly securityGroups?: ec2.ISecurityGroup[];
private readonly role?: iam.IRole;

constructor(scope: Construct, id: string, props: ProviderProps) {
super(scope, id);
Expand All @@ -152,6 +163,8 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
this.vpcSubnets = props.vpcSubnets;
this.securityGroups = props.securityGroups;

this.role = props.role;

const onEventFunction = this.createFunction(consts.FRAMEWORK_ON_EVENT_HANDLER_NAME);

if (this.isCompleteHandler) {
Expand All @@ -166,7 +179,6 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
interval: retry.interval,
maxAttempts: retry.maxAttempts,
});

// the on-event entrypoint is going to start the execution of the waiter
onEventFunction.addEnvironment(consts.WAITER_STATE_MACHINE_ARN_ENV, waiterStateMachine.stateMachineArn);
waiterStateMachine.grantStartExecution(onEventFunction);
Expand Down Expand Up @@ -197,6 +209,7 @@ export class Provider extends CoreConstruct implements ICustomResourceProvider {
vpc: this.vpc,
vpcSubnets: this.vpcSubnets,
securityGroups: this.securityGroups,
role: this.role,
});

fn.addEnvironment(consts.USER_ON_EVENT_FUNCTION_ARN_ENV, this.onEventHandler.functionArn);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as path from 'path';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda';
import * as logs from '@aws-cdk/aws-logs';
import { Duration, Stack } from '@aws-cdk/core';
Expand Down Expand Up @@ -342,3 +343,57 @@ describe('log retention', () => {
expect(stack).not.toHaveResource('Custom::LogRetention');
});
});

describe('role', () => {
it('uses custom role when present', () => {
// GIVEN
const stack = new Stack();

// WHEN
new cr.Provider(stack, 'MyProvider', {
onEventHandler: new lambda.Function(stack, 'MyHandler', {
code: lambda.Code.fromAsset(path.join(__dirname, './integration-test-fixtures/s3-file-handler')),
handler: 'index.onEvent',
runtime: lambda.Runtime.NODEJS_10_X,
}),
role: new iam.Role(stack, 'MyRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],
}),
});

// THEN
expect(stack).toHaveResourceLike('AWS::Lambda::Function', {
Role: {
'Fn::GetAtt': [
'MyRoleF48FFE04',
'Arn',
],
},
});
});

it('uses default role otherwise', () => {
// GIVEN
const stack = new Stack();

// WHEN
new cr.Provider(stack, 'MyProvider', {
onEventHandler: new lambda.Function(stack, 'MyHandler', {
code: lambda.Code.fromAsset(path.join(__dirname, './integration-test-fixtures/s3-file-handler')),
handler: 'index.onEvent',
runtime: lambda.Runtime.NODEJS_10_X,
}),
});

// THEN
expect(stack).toHaveResourceLike('AWS::Lambda::Function', {
Role: {
'Fn::GetAtt': [
'MyProviderframeworkonEventServiceRole8761E48D',
'Arn',
],
},
});
});
});
Loading

0 comments on commit 90fd0cd

Please sign in to comment.