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

feat(lambda-nodejs): use docker instead of npm for parcel-bundler #7169

Merged
merged 32 commits into from May 1, 2020

Conversation

AlexCheema
Copy link
Contributor

Commit Message

feat(lambda-nodejs): use docker instead of npm package for parcel-bundler

End Commit Message

There was a dependency on the parcel-bundler npm package for using the @aws-cdk/aws-lambda-nodejs package. This required installing parcel-bundler in your project. This replaces the npm dependency with a docker image.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: ea0e032
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 3f9db92
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 4490601
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 157281e
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 74383e2
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I would like us to look into extracting this common code into a separate module like @aws-cdk/aws-lambda-bundling. We can do that in a subsequent PR.

packages/@aws-cdk/aws-lambda-nodejs/README.md Show resolved Hide resolved
@@ -67,15 +67,3 @@ test('throws if status is not 0', () => {
});
expect(() => builder.build()).toThrow('status-error');
});

test('throws when parcel-bundler is not 1.x', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test for when docker is not installed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,5 @@
FROM node:13.8.0-alpine3.11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a wee comment explaining what this docker image is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,5 @@
FROM node:13.8.0-alpine3.11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
FROM node:13.8.0-alpine3.11
ARG VERSION=13.8.0-alpine3.11
FROM node:$VERSION

With a prop allowing to customize the version? and the default either in the Dockerfile as above or in the .ts file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we expose this build arg as an optional prop in NodejsFunctionProps and then BuilderOptions? There's a risk of being stucked with a parcel-bundler version that could be incompatible with the fixed node/alpine version of the Dockerfile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expose nodeDockerTag in NodejsFunctionProps and pass it to the Builder and we're done here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@eladb
Copy link
Contributor

eladb commented Apr 6, 2020

@jogold LMK if this looks good.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: e1428ae
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@AlexCheema
Copy link
Contributor Author

Looks good. I would like us to look into extracting this common code into a separate module like @aws-cdk/aws-lambda-bundling. We can do that in a subsequent PR.

I also wrote an implementation for Python that uses Docker. Feel free to use this when you make the separate module:

import * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
import * as path from "path";
import { spawnSync } from "child_process";

export interface PyFunctionProps {
  /**
   * The runtime environment. Only runtimes of the PYTHON family are
   * supported.
   *
   * @default - PYTHON_3_8
   */
  readonly runtime?: lambda.Runtime;
  /**
   * The path to the entry file.
   */
  readonly entry: string;
  /**
   * The name of the exported handler in the entry file.
   *
   * @default handler
   */
  readonly handler?: string;
  /**
   * The layer directory.
   *
   * @default - `.layer` in the entry file directory
   */
  readonly layerDir?: string;
}
export class PyFunction extends lambda.Function {
  constructor(scope: cdk.Construct, id: string, props: PyFunctionProps) {
    if (props.runtime && props.runtime.family !== lambda.RuntimeFamily.PYTHON) {
      throw new Error("Only `PYTHON` runtimes are supported.");
    }

    const runtime = props.runtime || lambda.Runtime.PYTHON_3_8;
    const entry = props.entry;
    const handler = props.handler || "handler";
    const handlerDir = path.dirname(entry);
    const layerDir = props.layerDir || path.join(handlerDir, ".layer");

    super(scope, id, {
      ...props,
      code: lambda.Code.fromAsset(handlerDir),
      runtime,
      handler: `${path.basename(entry).replace(".py", "")}.${handler}`,
    });

    const dependenciesLayer = createDependenciesLayer(this, runtime, `${handlerDir}/requirements.txt`, layerDir);
    this.addLayers(dependenciesLayer);
  }
}

function createDependenciesLayer(
  scope: cdk.Construct,
  runtime: lambda.Runtime,
  requirementsPath: string,
  layerDir: string,
  skipPip: boolean = false
) {
  if (!skipPip) {
    const dockerArgs = [
      "run",
      "--rm",
      "-v",
      `${path.resolve(requirementsPath)}:/requirements.txt`,
      "-v",
      `${path.resolve(layerDir)}/python:/output`,
      pyV(runtime) === 2 ? "2.7.17-slim-stretch" : "python:3.7.7-slim-stretch",
    ];
    const pipArgs = ["pip", "install", "-r", "/requirements.txt", "-t", "/output"];
    const proc = spawnSync("docker", [...dockerArgs, ...pipArgs]);

    if (proc.error) {
      throw proc.error;
    }

    if (proc.status !== 0) {
      throw new Error(`[Status ${proc.status}] stdout: ${proc.stdout.toString().trim()}\n\n\nstderr: ${proc.stderr.toString().trim()}`);
    }
  }

  return new lambda.LayerVersion(scope, "DependenciesLayer", { code: lambda.Code.fromAsset(layerDir) });
}

function pyV(runtime: lambda.Runtime): 2 | 3 {
  if (runtime.name.includes("python2")) return 2;

  return 3;
}

@eladb
Copy link
Contributor

eladb commented Apr 6, 2020

I also wrote an implementation for Python that uses Docker. Feel free to use this when you make the separate module:

Would you like to contribute that?

@jogold
Copy link
Contributor

jogold commented Apr 6, 2020

@eladb looks like Docker (docker-in-docker) is not available in the CodeBuild image that is running for PRs?

@AlexCheema
Copy link
Contributor Author

I also wrote an implementation for Python that uses Docker. Feel free to use this when you make the separate module:

Would you like to contribute that?

I can't commit the time to that unfortunately. Feel free to use the code though!

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 9a5cb5c
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 370778d
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@eladb
Copy link
Contributor

eladb commented Apr 6, 2020

@eladb looks like Docker (docker-in-docker) is not available in the CodeBuild image that is running for PRs?

Damn! @RomainMuller any suggestion?

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 9f85d87
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: c7852e9
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: d3c79d4
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@eladb
Copy link
Contributor

eladb commented Apr 30, 2020

@AlexCheema can you update yarn.lock please?

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: feadb67
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@AlexCheema
Copy link
Contributor Author

@AlexCheema can you update yarn.lock please?

Done

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 711b58e
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented May 1, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 8de8246
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented May 1, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit 55c4d0b into aws:master May 1, 2020
@jogold
Copy link
Contributor

jogold commented May 1, 2020

@AlexCheema have you been able to test this with dependencies/modules? I'm always getting Cannot resolve dependency '...' with this setup. Seems like parcel-bundler in the container cannot find those dependencies.

@jogold
Copy link
Contributor

jogold commented May 1, 2020

I think that this is because the node_modules folder is outside the mounted volume.

@eladb looking into this and waiting for a reply from @AlexCheema but I think that this needs to be reverted/not released...

@AlexCheema
Copy link
Contributor Author

I think that this is because the node_modules folder is outside the mounted volume.

@eladb looking into this and waiting for a reply from @AlexCheema but I think that this needs to be reverted/not released...

I'm not sure I understand the problem. Best if you implement a fix.

jogold added a commit to jogold/aws-cdk that referenced this pull request May 7, 2020
jogold added a commit to jogold/aws-cdk that referenced this pull request May 7, 2020
jogold added a commit to jogold/aws-cdk that referenced this pull request May 7, 2020
mergify bot pushed a commit that referenced this pull request May 7, 2020
@AlexCheema AlexCheema deleted the alexcheema/docker-parcel-bundler branch May 8, 2020 09:14
@iDVB
Copy link

iDVB commented May 29, 2020

@eladb @jogold Does NodeJSFunction yet support handling a hash that we can, or it can use for adding function versions? Sorry, I've been bouncing around 4-5 issues to try and catch up on where you guys are at with this feature.

@jogold
Copy link
Contributor

jogold commented May 29, 2020

@eladb @jogold Does NodeJSFunction yet support handling a hash that we can, or it can use for adding function versions? Sorry, I've been bouncing around 4-5 issues to try and catch up on where you guys are at with this feature.

NodejsFunction extends lambda.Function so everything available on lambda.Function should be available here also, does this answer your question?

@iDVB
Copy link

iDVB commented May 29, 2020

@jogold Sorry, I was not more clear. I'm not aware of any process currently that knows if something in your lambda src files changed.
I saw something like this...
lambda.addVersion(sha256(require('./mymain.ts')))
which only works if that ./mymain.ts is a single file. In our case we use NodeJSFunction and is many files that get bundled with parcel.

So is there currently a way to use the output from parcel as the thing to generate the hash from?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants