Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated source code for LambdaFunction where edgeLambda: true is incorrect #3577

Open
toxygene opened this issue May 14, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@toxygene
Copy link

toxygene commented May 14, 2024

The code, handler, and runtime properties created by the LambdaFunction component for an Edge function, are required (via the cloudfront.experimental.EdgeFunctionProps interface [1][2][3]). None of these values are used and the source code generated by the component overwrites the values [4].

Contrast this with the properties interface created by the LambdaFunction component for a Lambda (non-Edge) function. The code, handler, and runtime properties are not present because the property class extends lambda.FunctionOptions [5][6].

Since aws_cloudfront.experimental.EdgeFunction doesn't provide a properties interface that doesn't include code, handler, and runtime, the Projen LambdaFunction component should be modified to create a properly constructed one in the source code.

[1] https://github.com/projen/projen/blob/main/src/awscdk/lambda-function.ts#L224-L226
[2] https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-cloudfront/lib/experimental/edge-function.ts#L21
[3] https://github.com/aws/aws-cdk/blob/b0975e410a404d07952e01303af01224ccfad864/packages/aws-cdk-lib/aws-lambda/lib/function.ts#L550
[4] https://github.com/projen/projen/blob/main/src/awscdk/lambda-function.ts#L254-L261
[5] https://github.com/projen/projen/blob/main/src/awscdk/lambda-function.ts#L229
[6] https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-lambda/lib/function.ts#L146

@toxygene
Copy link
Author

Here's my "quick stab at the solution".

if (options.edgeLambda) {
    scr.open(
        `export interface ${propsType} extends lambda.FunctionOptions {`
    );
    src.line("  /**");
    src.line("    * The stack ID of Lambda@Edge function.");
    src.line("    *");
    scr.line("    * @default - `edge-lambda-stack-${region}`");
    src.line("    */");
    src.line("   readonly stackId?: string;");
}

@mrgrain
Copy link
Contributor

mrgrain commented May 15, 2024

Thanks for the report. Your description sounds accurate, I'm just having a bit of hard time following it. Would you mind adding the code that is currently produced and what it should look like for an EdgeFunction?

@toxygene
Copy link
Author

toxygene commented May 15, 2024

Here's the generated construct code.

// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
import * as path from 'path';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

/**
 * Props for OAuthDefaultBehaviorFunction
 */
export interface OAuthDefaultBehaviorFunctionProps extends cloudfront.experimental.EdgeFunctionProps {
}

/**
 * An AWS Lambda function which executes lambdas/oauth-cloudfront-behaviors/DefaultBehavior.
 */
export class OAuthDefaultBehaviorFunction extends cloudfront.experimental.EdgeFunction {
  constructor(scope: Construct, id: string, props?: OAuthDefaultBehaviorFunctionProps) {
    super(scope, id, {
      description: './lambdas/oauth-cloudfront-behaviors/DefaultBehavior.edge-lambda.ts',
      ...props,
      runtime: new lambda.Runtime('nodejs20.x', lambda.RuntimeFamily.NODEJS),
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, '../../assets/lambdas/oauth-cloudfront-behaviors/DefaultBehavior.edge-lambda')),
    });
  }
}

While the Lambda module provides the FunctionOptions interface for use cases like this, the EdgeFunction module does not, so we have to reproduce the functionality ourselves (by extending FunctionOptions and copying all the properties from EdgeFunctionProps).

// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
import * as path from 'path';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

/**
 * Props for OAuthDefaultBehaviorFunction
 */
export interface OAuthDefaultBehaviorFunctionProps extends FunctionOptions {
  /**
   * The stack ID of Lambda@Edge function.
   *
   * @default - `edge-lambda-stack-${region}`
   */
  readonly stackId?: string;
}

/**
 * An AWS Lambda function which executes lambdas/oauth-cloudfront-behaviors/DefaultBehavior.
 */
export class OAuthDefaultBehaviorFunction extends cloudfront.experimental.EdgeFunction {
  constructor(scope: Construct, id: string, props?: OAuthDefaultBehaviorFunctionProps) {
    super(scope, id, {
      description: './lambdas/oauth-cloudfront-behaviors/DefaultBehavior.edge-lambda.ts',
      ...props,
      runtime: new lambda.Runtime('nodejs20.x', lambda.RuntimeFamily.NODEJS),
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, '../../assets/lambdas/oauth-cloudfront-behaviors/DefaultBehavior.edge-lambda')),
    });
  }
}

Admittedly, manually copying over the EdgeFunctionProps is not great -- changes will have to be kept in sync. A better long term solution would be getting the EdgeFunction module to provide the interface.

@mrgrain mrgrain added the enhancement New feature or request label May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants