Skip to content

Commit

Permalink
Merge branch 'master' into njlynch/duration-plus
Browse files Browse the repository at this point in the history
  • Loading branch information
njlynch authored Jul 14, 2020
2 parents a127048 + 767da12 commit 6c2e689
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 16 deletions.
30 changes: 28 additions & 2 deletions packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// !cdk-integ pragma:ignore-assets
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import { App, CfnOutput, Duration } from '@aws-cdk/core';
import { App, CfnOutput, Duration, Token } from '@aws-cdk/core';
import * as eks from '../lib';
import * as hello from './hello-k8s';
import { TestStack } from './util';
Expand Down Expand Up @@ -113,10 +113,36 @@ class EksClusterStack extends TestStack {
}
}

// this test uses the bottlerocket image, which is only supported in these
// regions. see https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-eks#bottlerocket
const supportedRegions = [
'ap-northeast-1',
'ap-south-1',
'eu-central-1',
'us-east-1',
'us-west-2',
];

const app = new App();

// since the EKS optimized AMI is hard-coded here based on the region,
// we need to actually pass in a specific region.
new EksClusterStack(app, 'aws-cdk-eks-cluster-test');
const stack = new EksClusterStack(app, 'aws-cdk-eks-cluster-test');

if (process.env.CDK_INTEG_ACCOUNT !== '12345678') {

// only validate if we are about to actually deploy.
// TODO: better way to determine this, right now the 'CDK_INTEG_ACCOUNT' seems like the only way.

if (Token.isUnresolved(stack.region)) {
throw new Error(`region (${stack.region}) cannot be a token and must be configured to one of: ${supportedRegions}`);
}

if (!supportedRegions.includes(stack.region)) {
throw new Error(`region (${stack.region}) must be configured to one of: ${supportedRegions}`);
}

}


app.synth();
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,22 @@ const fn = new lambda.Function(this, 'MyFunction', {
See [the AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html)
to learn more about AWS Lambda's X-Ray support.

### Lambda with Profiling

```ts
import * as lambda from '@aws-cdk/aws-lambda';

const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_10_X,
handler: 'index.handler',
code: lambda.Code.fromInline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
profiling: true
});
```

See [the AWS documentation](https://docs.aws.amazon.com/codeguru/latest/profiler-ug/setting-up-lambda.html)
to learn more about AWS Lambda's Profiling support.

### Lambda with Reserved Concurrent Executions

```ts
Expand Down
49 changes: 47 additions & 2 deletions packages/@aws-cdk/aws-lambda/lib/function.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import { IProfilingGroup, ProfilingGroup } from '@aws-cdk/aws-codeguruprofiler';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as iam from '@aws-cdk/aws-iam';
import * as logs from '@aws-cdk/aws-logs';
Expand Down Expand Up @@ -190,6 +191,22 @@ export interface FunctionOptions extends EventInvokeConfigOptions {
*/
readonly tracing?: Tracing;

/**
* Enable profiling.
* @see https://docs.aws.amazon.com/codeguru/latest/profiler-ug/setting-up-lambda.html
*
* @default - No profiling.
*/
readonly profiling?: boolean;

/**
* Profiling Group.
* @see https://docs.aws.amazon.com/codeguru/latest/profiler-ug/setting-up-lambda.html
*
* @default - A new profiling group will be created if `profiling` is set.
*/
readonly profilingGroup?: IProfilingGroup;

/**
* A list of layers to add to the function's execution environment. You can configure your Lambda function to pull in
* additional code during initialization in the form of layers. Layers are packages of libraries or other dependencies
Expand Down Expand Up @@ -485,8 +502,6 @@ export class Function extends FunctionBase {
physicalName: props.functionName,
});

this.environment = props.environment || {};

const managedPolicies = new Array<iam.IManagedPolicy>();

// the arn is in the form of - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Expand Down Expand Up @@ -520,6 +535,30 @@ export class Function extends FunctionBase {
const code = props.code.bind(this);
verifyCodeConfig(code, props.runtime);

let profilingGroupEnvironmentVariables = {};
if (props.profilingGroup && props.profiling !== false) {
this.validateProfilingEnvironmentVariables(props);
props.profilingGroup.grantPublish(this.role);
profilingGroupEnvironmentVariables = {
AWS_CODEGURU_PROFILER_GROUP_ARN: Stack.of(scope).formatArn({
service: 'codeguru-profiler',
resource: 'profilingGroup',
resourceName: props.profilingGroup.profilingGroupName,
}),
AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
};
} else if (props.profiling) {
this.validateProfilingEnvironmentVariables(props);
const profilingGroup = new ProfilingGroup(this, 'ProfilingGroup');
profilingGroup.grantPublish(this.role);
profilingGroupEnvironmentVariables = {
AWS_CODEGURU_PROFILER_GROUP_ARN: profilingGroup.profilingGroupArn,
AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
};
}

this.environment = { ...profilingGroupEnvironmentVariables, ...(props.environment || {}) };

this.deadLetterQueue = this.buildDeadLetterQueue(props);

const resource: CfnFunction = new CfnFunction(this, 'Resource', {
Expand Down Expand Up @@ -852,6 +891,12 @@ export class Function extends FunctionBase {
mode: props.tracing,
};
}

private validateProfilingEnvironmentVariables(props: FunctionProps) {
if (props.environment && (props.environment.AWS_CODEGURU_PROFILER_GROUP_ARN || props.environment.AWS_CODEGURU_PROFILER_ENABLED)) {
throw new Error('AWS_CODEGURU_PROFILER_GROUP_ARN and AWS_CODEGURU_PROFILER_ENABLED must not be set when profiling options enabled');
}
}
}

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-lambda/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
},
"dependencies": {
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-codeguruprofiler": "0.0.0",
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-efs": "0.0.0",
"@aws-cdk/aws-events": "0.0.0",
Expand All @@ -99,6 +100,7 @@
"homepage": "https://github.com/aws/aws-cdk",
"peerDependencies": {
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-codeguruprofiler": "0.0.0",
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-efs": "0.0.0",
"@aws-cdk/aws-events": "0.0.0",
Expand Down
174 changes: 174 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/test.function.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as path from 'path';
import { expect, haveOutput, haveResource } from '@aws-cdk/assert';
import { ProfilingGroup } from '@aws-cdk/aws-codeguruprofiler';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as efs from '@aws-cdk/aws-efs';
import * as logs from '@aws-cdk/aws-logs';
Expand Down Expand Up @@ -184,6 +185,179 @@ export = testCase({
test.done();
},

'default function with CDK created Profiling Group'(test: Test) {
const stack = new cdk.Stack();

new lambda.Function(stack, 'MyLambda', {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_10_X,
profiling: true,
});

expect(stack).to(haveResource('AWS::CodeGuruProfiler::ProfilingGroup', {
ProfilingGroupName: 'MyLambdaProfilingGroupC5B6CCD8',
}));

expect(stack).to(haveResource('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [
{
Action: [
'codeguru-profiler:ConfigureAgent',
'codeguru-profiler:PostAgentProfile',
],
Effect: 'Allow',
Resource: {
'Fn::GetAtt': ['MyLambdaProfilingGroupEC6DE32F', 'Arn'],
},
},
],
Version: '2012-10-17',
},
PolicyName: 'MyLambdaServiceRoleDefaultPolicy5BBC6F68',
Roles: [
{
Ref: 'MyLambdaServiceRole4539ECB6',
},
],
}));

expect(stack).to(haveResource('AWS::Lambda::Function', {
Environment: {
Variables: {
AWS_CODEGURU_PROFILER_GROUP_ARN: { 'Fn::GetAtt': ['MyLambdaProfilingGroupEC6DE32F', 'Arn'] },
AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
},
},
}));

test.done();
},

'default function with client provided Profiling Group'(test: Test) {
const stack = new cdk.Stack();

new lambda.Function(stack, 'MyLambda', {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_10_X,
profilingGroup: new ProfilingGroup(stack, 'ProfilingGroup'),
});

expect(stack).to(haveResource('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [
{
Action: [
'codeguru-profiler:ConfigureAgent',
'codeguru-profiler:PostAgentProfile',
],
Effect: 'Allow',
Resource: {
'Fn::GetAtt': ['ProfilingGroup26979FD7', 'Arn'],
},
},
],
Version: '2012-10-17',
},
PolicyName: 'MyLambdaServiceRoleDefaultPolicy5BBC6F68',
Roles: [
{
Ref: 'MyLambdaServiceRole4539ECB6',
},
],
}));

expect(stack).to(haveResource('AWS::Lambda::Function', {
Environment: {
Variables: {
AWS_CODEGURU_PROFILER_GROUP_ARN: {
'Fn::Join': [
'',
[
'arn:', { Ref: 'AWS::Partition' }, ':codeguru-profiler:', { Ref: 'AWS::Region' },
':', { Ref: 'AWS::AccountId' }, ':profilingGroup/', { Ref: 'ProfilingGroup26979FD7' },
],
],
},
AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
},
},
}));

test.done();
},

'default function with client provided Profiling Group but profiling set to false'(test: Test) {
const stack = new cdk.Stack();

new lambda.Function(stack, 'MyLambda', {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_10_X,
profiling: false,
profilingGroup: new ProfilingGroup(stack, 'ProfilingGroup'),
});

expect(stack).notTo(haveResource('AWS::IAM::Policy'));

expect(stack).notTo(haveResource('AWS::Lambda::Function', {
Environment: {
Variables: {
AWS_CODEGURU_PROFILER_GROUP_ARN: {
'Fn::Join': [
'',
[
'arn:', { Ref: 'AWS::Partition' }, ':codeguru-profiler:', { Ref: 'AWS::Region' },
':', { Ref: 'AWS::AccountId' }, ':profilingGroup/', { Ref: 'ProfilingGroup26979FD7' },
],
],
},
AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
},
},
}));

test.done();
},

'default function with profiling enabled and client provided env vars'(test: Test) {
const stack = new cdk.Stack();

test.throws(() => new lambda.Function(stack, 'MyLambda', {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_10_X,
profiling: true,
environment: {
AWS_CODEGURU_PROFILER_GROUP_ARN: 'profiler_group_arn',
AWS_CODEGURU_PROFILER_ENABLED: 'yes',
},
}),
/AWS_CODEGURU_PROFILER_GROUP_ARN and AWS_CODEGURU_PROFILER_ENABLED must not be set when profiling options enabled/);

test.done();
},

'default function with client provided Profiling Group and client provided env vars'(test: Test) {
const stack = new cdk.Stack();

test.throws(() => new lambda.Function(stack, 'MyLambda', {
code: new lambda.InlineCode('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_10_X,
profilingGroup: new ProfilingGroup(stack, 'ProfilingGroup'),
environment: {
AWS_CODEGURU_PROFILER_GROUP_ARN: 'profiler_group_arn',
AWS_CODEGURU_PROFILER_ENABLED: 'yes',
},
}),
/AWS_CODEGURU_PROFILER_GROUP_ARN and AWS_CODEGURU_PROFILER_ENABLED must not be set when profiling options enabled/);

test.done();
},

'currentVersion': {
// see test.function-hash.ts for more coverage for this
'logical id of version is based on the function hash'(test: Test) {
Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions/lib/states/map.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as cdk from '@aws-cdk/core';
import { Chain } from '../chain';
import { FieldUtils } from '../fields';
import { StateGraph } from '../state-graph';
import { CatchProps, IChainable, INextable, RetryProps } from '../types';
import { StateType } from './private/state-type';
Expand Down Expand Up @@ -156,6 +157,7 @@ export class Map extends State implements INextable {
ResultPath: renderJsonPath(this.resultPath),
...this.renderNextEnd(),
...this.renderInputOutput(),
...this.renderParameters(),
...this.renderRetryCatch(),
...this.renderIterator(),
...this.renderItemsPath(),
Expand Down Expand Up @@ -185,4 +187,13 @@ export class Map extends State implements INextable {
ItemsPath: renderJsonPath(this.itemsPath),
};
}

/**
* Render Parameters in ASL JSON format
*/
private renderParameters(): any {
return FieldUtils.renderObject({
Parameters: this.parameters,
});
}
}
5 changes: 4 additions & 1 deletion packages/@aws-cdk/aws-stepfunctions/test/map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ describe('Map State', () => {
'Map State': {
Type: 'Map',
End: true,
Parameters: { foo: 'foo', bar: '$.bar' },
Parameters: {
'foo': 'foo',
'bar.$': '$.bar',
},
Iterator: {
StartAt: 'Pass State',
States: {
Expand Down
Loading

0 comments on commit 6c2e689

Please sign in to comment.