使用“ sam invoke local”时,为什么调试会中断对AWS :: Lamba :: LayerVersion的访问?

时间:2019-12-18 16:31:12

标签: typescript amazon-web-services visual-studio-code aws-lambda vscode-debugger

这有效:

sam local invoke -t template.local.yaml -e events/event-timezone.json GetTimezoneFunction

当尝试使用Visual Studio代码进行调试时,此方法不起作用:

sam local invoke -t template.local.yaml -e events/event-timezone.json -d 5858 GetTimezoneFunction

区别在于,第二个错误是找不到在lambda函数使用的单独层中定义的npm'axios'模块。

Error: Cannot find module 'axios'
Require stack:
 - /var/task/get-timezone.js
 - /var/runtime/UserFunction.js
 - /var/runtime/index.js

我能想到的是,可能是通过尝试使用调试器,或者该层的资源未复制到Docker运行时环境,或者某些文件搜索路径被破坏了。

我还有另一个lambda函数,该函数不需要该层的任何内容,无论是否装有调试器,它都能正常工作。

具有getTimeZone功能的文件以以下开头:

import axios from 'axios';

这是template.local.yaml的相关部分:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS Sample

Globals:
  Function:
    Timeout: 30

Resources:
  SampleCommonLayer:
    Type: AWS::Lambda::LayerVersion
    Properties:
      CompatibleRuntimes:
        - nodejs12.x
      Content: dependencies
      Description: Sample Common LayerVersion
      LayerName: SampleCommonLayer

  GetTimezoneFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dist/get-timezone
      Handler: get-timezone.getTimezone
      Runtime: nodejs12.x
      Layers:
        - !Ref SampleCommonLayer
      Events:
        GetTimezone:
          Type: Api
          Properties:
            Path: /get-timezone
            Method: get

Outputs:
  GetTimezoneApi:
    Description: "API Gateway endpoint URL for Prod stage for getTimezone function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/get-timezone/"
  GetTimezoneFunction:
    Description: "getTimezone Lambda Function ARN"
    Value: !GetAtt GetTimezoneFunction.Arn
  GetTimezoneFunctionIamRole:
    Description: "Implicit IAM Role created for getTimezone function"
    Value: !GetAtt GetTimezoneFunctionRole.Arn

这是我的launch.json

{
  "version": "0.2.0",
  "configurations": [{
      "name": "Debug get-timezone",
      "type": "node",
      "request": "attach",
      "address": "localhost",
      "port": 5858,
      "localRoot": "${workspaceRoot}/dist",
      "remoteRoot": "/var/task",
      "protocol": "inspector",
      "stopOnEntry": false,
      "preLaunchTask": "local-tz-debug"
    },
    ...
  ]
}

到目前为止,在寻找该问题的答案时,我只发现了很多未解决的问题和一些不尽相同的问题。

1 个答案:

答案 0 :(得分:0)

我使我的lambda函数之一转储了process.env中的所有环境变量,发现启用调试(通过-d 5858)与未启用调试之间存在一些差异,最明显的是启用调试时未定义NODE_PATH

基于我在其他地方读过的类似问题,我认为我曾经尝试过修复NODE_PATH一次,但这似乎无济于事。

现在我正在转储环境变量,但是,我可以看到尝试在NODE_PATH文件中定义env.json的尝试没有任何效果。从那时起,我发现SAM忽略了未在模板中明确定义的任何环境变量(无论是全局变量还是每个lambda变量)。

此问题已解决:

Globals:
  Function:
    Timeout: 30
    Environment:
      Variables:
        NODE_PATH: /opt/nodejs/node12/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules

解决了这个问题后,它发现我需要调整launch.json才能使调试器断点适用于TypeScript:

{
  "version": "0.2.0",
  "configurations": [{
      "name": "Debug get-timezone",
      "type": "node",
      "request": "attach",
      "address": "localhost",
      "port": 5858,
      "localRoot": "${workspaceRoot}/dist/get-timezone", // <- More specific path needed
      "remoteRoot": "/var/task",
      "protocol": "inspector",
      "stopOnEntry": false,
      "preLaunchTask": "local-tz-debug",
      "outFiles": [ // <- Added this
        "${workspaceRoot}/dist/get-timezone/**/*.js"
      ],
      "sourceMaps": true // <- Added this
    },
    ...
  ]
}

我只希望为本地测试而不是部署定义NODE_PATH变量,因此我有一个单独的template.yaml文件,没有用于部署的定义。 template.yaml还将Content的{​​{1}}定义为LayerVersion,而不是nodejs.zip。我从dependencies自动生成了template.local.yaml,因此我不必维护两个单独的几乎完全相同的模板。

我希望将来有更好的方法可以完成此任务,但现在它可以完成工作。