如何让我的AWS Lambda访问存储在供应商/bundle中的宝石



我正在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

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

Gemfile
Gemfile.lock
lambda_function.rb
vendor/
bundle/
ruby
2.3.0
gems/webhook

2.3.0槽下还有其他几个文件夹,包括build_infocachedoc等。为了将这些代码放到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'"
]
}

不应该有更多的内容,因为下面的教程确切地展示了如何设置我所拥有的,但不起作用。有人成功地从AWS Lambda的宝石文件中提取宝石吗?

我在用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'

在您的情况下,将"/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,我们需要自己做一些"魔术"。

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

您的zip似乎在2.3.0中安装了gems,但堆栈跟踪列表为2.5.0。这种不匹配意味着lambda运行程序找不到您的宝石。

我认为您不应该更改GEM_PATH,也不应该在每个lambda函数中设置$LOAD_PATH。"最好"的方法是在创建层档案时进行这个小破解:

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/

最新更新