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

[@aws-cdk/aws-lambda-nodejs] Unable to run lambda locally with sam local after updating to [email protected] #10367

Closed
priceld opened this issue Sep 15, 2020 · 10 comments · Fixed by #10507
Assignees
Labels
@aws-cdk/aws-lambda-nodejs bug This issue is a bug. effort/small Small work item – less than a day of effort p1

Comments

@priceld
Copy link

priceld commented Sep 15, 2020

I'm using @aws-cdk/aws-lambda-nodejs to bundle JS lambda code. However, after updating aws-cdk to v1.61.0 (or higher) I can no longer run sam local with the template that cdk synth --no-staging generates. I believe this is because f5c9124 changed asset-staging.ts and now the template uses a different aws:asset:path for nodejs lambdas.

This is the Metadata of a working template:

Metadata:
  aws:cdk:path: TestStack/func/Resource
  aws:asset:path: /Users/lprice/work/playground/demo-aws-cdk-asset-path-bug/.cdk.staging/asset-bundle-IF4IYG
  aws:asset:property: Code

Versus that of a failing template:

Metadata:
  aws:cdk:path: TestStack/func/Resource
  aws:asset:path: asset.eaa6b4d3a12be11c844440afe5ee48ce3999505afaa441be0292009b5f7f2766
  aws:asset:property: Code

As you can see the path is different. When SAM tries to mount the lambda code to the docker image, this new relative path causes it to use a folder that does not contain the lambda code. The result is that when the lambda invoked, the code cannot be found and I get this error:

2020-09-15T14:52:59.899Z	undefined	ERROR	Uncaught Exception 	{"errorType":"Runtime.HandlerNotFound","errorMessage":"index.handler is undefined or not exported","stack":["Runtime.HandlerNotFound: index.handler is undefined or not exported","    at Object.module.exports.load (/var/runtime/UserFunction.js:144:11)","    at Object.<anonymous> (/var/runtime/index.js:43:30)","    at Module._compile (internal/modules/cjs/loader.js:1138:30)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)","    at Module.load (internal/modules/cjs/loader.js:986:32)","    at Function.Module._load (internal/modules/cjs/loader.js:879:14)","    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)","    at internal/main/run_main_module.js:17:47"]}
START RequestId: f0477efb-b72d-158b-0cdc-cc3d07557371 Version: $LATEST
END RequestId: f0477efb-b72d-158b-0cdc-cc3d07557371
REPORT RequestId: f0477efb-b72d-158b-0cdc-cc3d07557371	Init Duration: 131.03 ms	Duration: 1.06 ms	Billed Duration: 100 ms	Memory Size: 128 MB	Max Memory Used: 40 MB	

{"errorType":"Runtime.HandlerNotFound","errorMessage":"index.handler is undefined or not exported"}

Reproduction Steps

I created this repo to demonstrate this bug and provide steps to reproduce.

What did you expect to happen?

I expected the lambda to run successfully.

What actually happened?

I see an error when trying to invoke the lambda:

{"errorType":"Runtime.HandlerNotFound","errorMessage":"index.handler is undefined or not exported"}

Environment

  • CLI Version : 1.61.0 (build 72e6727)
  • Framework Version: 1.61.0 (build 72e6727)
  • Node.js Version: v12.18.3
  • OS : Mac OS X 10.14.6 (Build: 18G6020)
  • Language (Version): Javascript

Edit: Remove --no-staging flag from cdk synth
Edit: Undo previous edit.


This is 🐛 Bug Report

@priceld priceld added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Sep 15, 2020
@dave-graham
Copy link

Think this maybe linked to an issue I have at #9189 too. Local dev through "cdk synth --no-staging > template.yaml" then "echo '{}' | sam local invoke LambdaName --env-vars environment.json" isn't possible at the moment.

@priceld
Copy link
Author

priceld commented Sep 17, 2020

Good point @dave-graham. I think I am using --no-staging incorrectly in this scenario, but this is still not working even when not using --no-staging. I would like to see both of these issues resolved: it would be great to be able to run the dev version for debugging, but also to be able to run the bundled code locally.

@priceld
Copy link
Author

priceld commented Sep 17, 2020

I stand corrected, it looks like sam local only works prior to v1.61.0 when using --no-staging because it creates a template where the lambda's code path is an absolute, staging path (that actually exists). But according to #9189, this behavior is wrong to begin with.

@eladb
Copy link
Contributor

eladb commented Sep 21, 2020

@jogold thoughts?

@eladb eladb added effort/small Small work item – less than a day of effort p1 labels Sep 21, 2020
@ryan-mars
Copy link

@priceld Do you have a workaround at the moment?

@SomayaB SomayaB removed the needs-triage This issue or PR still needs to be triaged. label Sep 21, 2020
@priceld
Copy link
Author

priceld commented Sep 22, 2020

@ryan-mars, no workaround at the moment. We are just pinned to v1.60.0 for now.

@jogold
Copy link
Contributor

jogold commented Sep 22, 2020

@priceld can you summarize exactly what you expect for aws:asset:path both with and without --no-staging?

@ryan-mars
Copy link

Is the issue that aws:asset:path is a relative path, or that sam local invoke can't be told where to begin a search for assets (i.e. cwd or something)?

Making aws:asset:path an absolute path makes the cloud artifacts less portable. Is portability of generated artifacts a goal of CDK?

@priceld
Copy link
Author

priceld commented Sep 23, 2020

@jogold I guess it depends on the the purpose of the --no-staging flag. Based on the help documentation, it seems like output shouldn't be copied at all when using --no-staging but this doesn't seem to be happening (per #9189).

But @ryan-mars is getting at my point - what I would really like to do (and what I've lost the ability to do after v1.61.0) is be able to run sam local with my CDK template and test lambdas locally. I'm not sure if the answer is doing something with aws:asset:path or figuring out how to tell sam local where to search for assets.

jogold added a commit to jogold/aws-cdk that referenced this issue Sep 24, 2020
The change introduced in aws#9576 did not handle the "staging disabled"
case. As a consequence, when bundling the staged path was always
relative.

Revert to the behavior that was present before this change: when staging
is disabled the staged path is absolute (whether bundling or not).

Closes aws#10367
jogold added a commit to jogold/aws-cdk that referenced this issue Sep 24, 2020
The change introduced in aws#9576 did not handle the "staging disabled"
case. As a consequence, when bundling the staged path was always
relative.

Revert to the behavior that was present before this change: when staging
is disabled the staged path is absolute (whether bundling or not).

Closes aws#10367
@mergify mergify bot closed this as completed in #10507 Sep 24, 2020
mergify bot pushed a commit that referenced this issue Sep 24, 2020
…0507)

The change introduced in #9576 did not handle the "staging disabled"
case. As a consequence, when bundling the staged path was always
relative.

Revert to the behavior that was present before this change: when staging
is disabled the staged path is absolute (whether bundling or not).

Closes #10367


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@ryan-mars
Copy link

@priceld If for any reason in the future you need to patch relative paths to assets in a yaml file generated by CDK I'm using this.

I know it's a little late and the issue is already closed.

const yaml = require('js-yaml')
const fs = require('fs')
const path = require('path')
const { CLOUDFORMATION_SCHEMA } = require('cloudformation-js-yaml-schema')

const yamlPath = path.resolve('template.yaml')
if (!fs.existsSync(yamlPath)) throw `Your YAML isn't there: ${yamlPath}`

const template = yaml.safeLoad(fs.readFileSync(yamlPath, 'utf8'), {
  schema: CLOUDFORMATION_SCHEMA
})

const countPatched = Object.keys(template.Resources)
  .filter((resource) => template.Resources[resource].Type === 'AWS::Lambda::Function')
  .reduce((count, resource) => {
    const oldAssetPath = template.Resources[resource].Metadata['aws:asset:path']
    if (fs.existsSync(path.resolve(oldAssetPath))) {
      console.log(`Skipping ${resource} already a valid path\n${oldAssetPath}`)
      return count
    }
    const newAssetPath = path.resolve('cdk.out', oldAssetPath)
    if (!fs.existsSync(newAssetPath)) throw `There's no there, there: ${newAssetPath}`
    console.log(`Fixing path for ${resource}`)
    console.log(`${oldAssetPath} --> ${newAssetPath}`)
    template.Resources[resource].Metadata['aws:asset:path'] = newAssetPath
    return (count += 1)
  }, 0)

console.log(`Fixed ${countPatched} resources.`)

if (countPatched > 0) {
  console.log(`Writing ${yamlPath}`)
  fs.writeFileSync(yamlPath, yaml.dump(template, { schema: CLOUDFORMATION_SCHEMA }))
} else {
  console.log('Nothing to do, not touching the file.')
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-lambda-nodejs bug This issue is a bug. effort/small Small work item – less than a day of effort p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants