Skip to content

Commit

Permalink
fix(cloudfront): EdgeFunction fails with newStyleStackSynthesis (#12356)
Browse files Browse the repository at this point in the history
The `EdgeFunction` construct copied some patterns from CodePipelines to enable
cross-environment interaction. One key difference is that for Lambda@Edge,
CDK assets are created in the cross-environment support stack. This isn't
supported by the BootstraplessSynthesizer, so this custom logic (copied from
CodePipelines) needs to be removed.

The EdgeFunction support stack will now use whatever synthesizer is default for
the current stack.

fixes #12172


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
njlynch authored Jan 5, 2021
1 parent 36b081e commit fb02736
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 18 deletions.
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ new cloudfront.Distribution(this, 'myDist', {
> To make it easier to request functions for Lambda@Edge, the `EdgeFunction` construct can be used.
> The `EdgeFunction` construct will automatically request a function in `us-east-1`, regardless of the region of the current stack.
> `EdgeFunction` has the same interface as `Function` and can be created and used interchangably.
> Please note that using `EdgeFunction` requires that the `us-east-1` region has been bootstrapped.
> See https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html for more about bootstrapping regions.
If the stack is in `us-east-1`, a "normal" `lambda.Function` can be used instead of an `EdgeFunction`.

Expand Down
23 changes: 5 additions & 18 deletions packages/@aws-cdk/aws-cloudfront/lib/experimental/edge-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda';
import * as ssm from '@aws-cdk/aws-ssm';
import {
BootstraplessSynthesizer, CfnResource, ConstructNode,
CfnResource, ConstructNode,
CustomResource, CustomResourceProvider, CustomResourceProviderRuntime,
DefaultStackSynthesizer, IStackSynthesizer, Resource, Stack, Stage, Token,
Resource, Stack, Stage, Token,
} from '@aws-cdk/core';
import { Construct } from 'constructs';

Expand All @@ -31,6 +31,9 @@ export interface EdgeFunctionProps extends lambda.FunctionProps {
* Convenience resource for requesting a Lambda function in the 'us-east-1' region for use with Lambda@Edge.
* Implements several restrictions enforced by Lambda@Edge.
*
* Note that this construct requires that the 'us-east-1' region has been bootstrapped.
* See https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html or 'cdk bootstrap --help' for options.
*
* @resource AWS::Lambda::Function
* @experimental
*/
Expand Down Expand Up @@ -214,7 +217,6 @@ export class EdgeFunction extends Resource implements lambda.IVersion {
let edgeStack = stage.node.tryFindChild(edgeStackId) as Stack;
if (!edgeStack) {
edgeStack = new Stack(stage, edgeStackId, {
synthesizer: crossRegionSupportSynthesizer(this.stack),
env: { region: EdgeFunction.EDGE_REGION },
});
}
Expand All @@ -230,21 +232,6 @@ interface FunctionConfig {
readonly functionStack: Stack;
}

// Stolen (and modified) from `@aws-cdk/aws-codepipeline`'s `Pipeline`.
function crossRegionSupportSynthesizer(stack: Stack): IStackSynthesizer | undefined {
// If we have the new synthesizer we need a bootstrapless copy of it,
// because we don't want to require bootstrapping the environment
// of the account in this replication region.
// Otherwise, return undefined to use the default.
const scopeStackSynthesizer = stack.synthesizer;
return (scopeStackSynthesizer instanceof DefaultStackSynthesizer)
? new BootstraplessSynthesizer({
deployRoleArn: scopeStackSynthesizer.deployRoleArn,
cloudFormationExecutionRoleArn: scopeStackSynthesizer.cloudFormationExecutionRoleArn,
})
: undefined;
}

function addEdgeLambdaToRoleTrustStatement(role: iam.IRole) {
if (role instanceof iam.Role && role.assumeRolePolicy) {
const statement = new iam.PolicyStatement();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as path from 'path';
import '@aws-cdk/assert/jest';
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import * as iam from '@aws-cdk/aws-iam';
Expand Down Expand Up @@ -227,6 +228,23 @@ test('metric methods', () => {
}
});

test('cross-region stack supports new-style synthesis with assets', () => {
app = new cdk.App({
context: { '@aws-cdk/core:newStyleStackSynthesis': true },
});
stack = new cdk.Stack(app, 'Stack', {
env: { account: '111111111111', region: 'testregion' },
});

new cloudfront.experimental.EdgeFunction(stack, 'MyFn', {
code: lambda.Code.fromAsset(path.join(__dirname, 'my-lambda-handler')),
handler: 'index.handler',
runtime: lambda.Runtime.PYTHON_3_8,
});

expect(() => app.synth()).not.toThrow();
});

function defaultEdgeFunctionProps(stackId?: string) {
return {
code: lambda.Code.fromInline('foo'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main(event, context):
return {
'message': 'Hello, world!'
}

0 comments on commit fb02736

Please sign in to comment.