如何让我的AWS Lambda访问存储在vendor/bundle中的gem?

Cst*_*le5 10 ruby amazon-web-services bundler aws-lambda

我正在Ruby中编写Lambda函数,最终将通过Webhook向Slack发送一些通知.所以我的lambda_function文件就是

require 'json'
require 'webhook'

def lambda_handler(event:, context:)
    # TODO implement
    { statusCode: 200, body: JSON.generate('Hello from Lambda!') }
    Webhook.post('https://mywebhookurl', {message: 'test'})
end
Run Code Online (Sandbox Code Playgroud)

我的内联代码编辑器中的目录结构如下所示:

Gemfile
Gemfile.lock
lambda_function.rb
vendor/
  bundle/
    ruby
      2.3.0
        gems/webhook
Run Code Online (Sandbox Code Playgroud)

也是在2.3.0洗澡其他几个文件夹,包括build_info, cache,doc等.为了得到这个代码到AWS LAMBDA,我跑

zip -r myLambda.zip * 将所有内容放入zip文件并上传到Lambda.

但是,当我最终对lambda运行基本测试时,我收到以下错误:

{
  "errorMessage": "cannot load such file -- webhook",
  "errorType": "Init<LoadError>",
  "stackTrace": [
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
    "/var/task/lambda_function.rb:2:in `<top (required)>'",
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'"
  ]
}
Run Code Online (Sandbox Code Playgroud)

由于下面的教程确切地说明了如何设置我所拥有但不起作用,因此不应再有这个了.有没有人成功从AWS Lambda的gemfile中提取宝石?

rya*_*nes 13

在使用Ruby构建AWS Lambda Layers时遇到了同样的问题.一种快速简便的方法是将所有gem路径添加到AWS Lambda中的Ruby的$ LOAD_PATH中.IE:

load_paths = Dir["/opt/ruby/gems/2.5.0/**/lib"]
$LOAD_PATH.unshift(*load_paths)

require 'webhook'
Run Code Online (Sandbox Code Playgroud)

更换"/opt/ruby/gems/2.5.0/**/lib""./vendor/bundle/ruby/2.3.0/gems/**/lib"你的情况.

当你这样做时,require 'webhook'它会查看所有路径"./vendor/bundle/ruby/2.3.0/gems/webhook-1.0.0/lib/webhook.rb",并将其添加到您的AWS Lambda中.require不需要文件扩展名.

当我们通过bundler运行rails时,它为我们做了一堆"魔术",包括确保我们的$ LOAD_PATH指向宝石.由于AWS Lambdas不使用bundler,我们需要自己做一些"魔术".

  • 尝试使用GitHub(`master`分支)中的gem时遇到了类似的问题。看来通往我的宝石的路径并不相同,它位于“ ./vendor/bundle/ruby/2.5.0/bundler/gems/”下。这意味着我必须调整这两行,使其看起来像这样:`load_paths = Dir [“ ./ vendor / bundle / ruby​​ / 2.5.0 / bundler / gems / ** / lib”]。我不知道这是否有所不同:我使用的是2.0.1版的Bundle。 (2认同)
  • 对于那些寻找简单示例的人,您可以在这里找到一个:https://github.com/ryanjones/ruby_lambda_layers (2认同)

小智 9

您需要确保本地使用的Ruby版本与Lambda使用的版本匹配.

您的zip似乎在2.3.0中安装了gem,但您的堆栈跟踪列出了2.5.0.这种不匹配意味着lambda跑者无法找到你的宝石.


Jon*_*ret 5

我认为您不应该更改 GEM_PATH 或必须$LOAD_PATH在每个 lambda 函数中进行设置。“最好”的方法是在创建图层存档时执行以下小技巧:

bundle install --path vendor/bundle
cd vendor/bundle
mkdir ruby/gems
mv ruby/2.5.0 ruby/gems/
zip -r layer.zip ruby/gems/2.5.0/
Run Code Online (Sandbox Code Playgroud)