Я пытаюсь расширить это руководство , создавая CodePipeline для сбора изменений в GitHub, их сборки и развертывания изменений в моей Lambda.sam build --use-container; sam local start-api
позволяет мне успешно вызывать функцию локально, но при развертывании функции в AWS код не может импортировать зависимость.
Мой код зависит от requests
.Я должным образом включил это в мой requirements.txt
файл:
requests==2.20.0
Мой buildspec.yml содержит инструкции по установке зависимостей
version: 0.1
phases:
install:
commands:
- pip install -r hello_world/requirements.txt -t .
- pip install -U pytest
pre_build:
commands:
- python -m pytest tests/
build:
commands:
- aws cloudformation package --template-file template.yaml --s3-bucket <my_bucket>
--output-template-file outputTemplate.yml
artifacts:
type: zip
files:
- '**/*'
Когда мой пакет собирается в CodeBuild, это подтверждается:
[Container] 2018/12/27 23:16:44 Waiting for agent ping
[Container] 2018/12/27 23:16:46 Waiting for DOWNLOAD_SOURCE
[Container] 2018/12/27 23:16:46 Phase is DOWNLOAD_SOURCE
[Container] 2018/12/27 23:16:46 CODEBUILD_SRC_DIR=/codebuild/output/src775882062/src
[Container] 2018/12/27 23:16:46 YAML location is /codebuild/output/src775882062/src/buildspec.yml
[Container] 2018/12/27 23:16:46 Processing environment variables
[Container] 2018/12/27 23:16:46 Moving to directory /codebuild/output/src775882062/src
[Container] 2018/12/27 23:16:46 Registering with agent
[Container] 2018/12/27 23:16:46 Phases found in YAML: 3
[Container] 2018/12/27 23:16:46 PRE_BUILD: 1 commands
[Container] 2018/12/27 23:16:46 BUILD: 1 commands
[Container] 2018/12/27 23:16:46 INSTALL: 2 commands
[Container] 2018/12/27 23:16:46 Phase complete: DOWNLOAD_SOURCE Success: true
[Container] 2018/12/27 23:16:46 Phase context status code: Message:
[Container] 2018/12/27 23:16:46 Entering phase INSTALL
[Container] 2018/12/27 23:16:46 Running command pip install -r hello_world/requirements.txt -t .
Collecting requests==2.20.0 (from -r hello_world/requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/f1/ca/10332a30cb25b627192b4ea272c351bce3ca1091e541245cccbace6051d8/requests-2.20.0-py2.py3-none-any.whl (60kB)
...
Но когда я вызываю развернутую функцию, я получаю сообщение об ошибке:
Unable to import module 'app': No module named 'requests'
Это похоже на этот вопрос , но яя не использую PYTHONPATH
в моем здании Lambda.
РЕДАКТИРОВАТЬ: я добавил код отладки к файлам в этом пакете, чтобы попытаться понять их среду выполнения.Я также добавил подобную отладку в другой пакет , который я развернул в Lambda через CodePipeline (хотя этот не использует SAM).Код отладки приведен ниже:
import os, sys
print('Inside ' + __file__)
for path in sys.path:
print(path)
if (os.path.exists(path)):
print(os.listdir(path))
for f in os.listdir(path):
if f.startswith('requests'):
print('Found requests!')
print()
Этот код пытается определить, присутствует ли модуль requests
в sys.path
среды выполнения Lambda - и, если да, где.
Для этого (с поддержкой SAM) пакета requests
нигде не найдено.В пакете без поддержки SAM requests
(а также все другие объявленные requirements.txt
зависимости пакета) были обнаружены в /var/task
.
Похоже, что CodeBuild не являетсясвязывание зависимостей функции вместе с источником, или CloudFormation не развертывает эти зависимости.Я подозреваю, что это как-то связано с тем фактом, что это определенная SAM функция, а не «ванильная» функция Cloudformation.
На этой странице говорится, что «Вы также можете использоватьдругие сервисы AWS, которые интегрируются с AWS SAM для автоматизации ваших развертываний », но я не понимаю, как заставить CodePipeline запускать sam deploy
вместо aws cloudformation deploy
(хотя эта страница утверждает, что они являются синонимами).
EDIT2 - Я считаю, что я нашел проблему.Для контекста, вспомните, что у меня есть два пакета, которые развертывают Lambdas через CodePipeline (или пытаются) - один, упомянутый в этом вопросе, который ссылается на Lambda как AWS::Serverless::Function
, и второй, который использует AWS::Lambda::Function
.Код первой функции был определен как относительное местоположение (т. Е. Ссылка на каталог в моем пакете: CodeUri: main/
), тогда как код второй функции * второй функции был ссылкой на местоположение S3 (извлечено в CodePipeline), с Fn::GetArtifactAtt": ["built", "ObjectKey"]}
или ...BucketName"]}
)
Ниже приведен пример вывода CodeBuild первого пакета:
[Container] 2018/12/30 19:19:48 Running command aws cloudformation package --template-file template.yaml --s3-bucket pop-culture-serverless-bucket --output-template-file outputTemplate.yml
Uploading to 669099ba3d2258eeb7391ad772bf870d 4222 / 4222.0 (100.00%)
Successfully packaged artifacts and wrote output template to file outputTemplate.yml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /codebuild/output/src110881899/src/outputTemplate.yml --stack-name <YOUR STACK NAME>
Сравните с тем же выводом из вывода CodeBuild второго пакета:
....
[Container] 2018/12/30 16:42:27 Running command aws cloudformation package --template-file template.json --s3-bucket {BUCKET_NAME} --output-template-file outputTemplate.yml
Successfully packaged artifacts and wrote output template to file outputTemplate.yml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /codebuild/output/src282566886/src/outputTemplate.yml --stack-name <YOUR STACK NAME>
Это говорит о том, что вызов aws cloudformation package
первого пакета приводит к загрузке файла (669099ba3d2258eeb7391ad772bf870d
) на S3, который основан на только на содержимом template.yaml
тогда как «выходные данные» этапа сборки CodePipeline второго пакета представляют собой zip
каталога, в котором CodeBuild выполнял в - который включает в себя зависимости (из-за вызовов pip install
).
Я мог бы обойти это, просто изменив template.yaml
моей функции SAM-шаблона для ссылки на местоположение S3 - но это означало бы, что я не смогутестируйте обновления функции локально (например, sam local start-api
) без редактирования шаблона, поскольку он будет ссылаться на местоположение S3 и поэтому не будет зависеть от локальных изменений.
В идеале я хочу найтиспособ включить зависимости кода в упакованный и загруженный файл S3.При локальном тестировании выясняется, что запуск sam package
/ aws cloudformation package
без первого запуска sam build
приводит к включению только исходного кода (без зависимостей).Однако я не могу запустить sam build
в CodeBuild, поскольку SAM там не установлен.
(Это также говорит о том, что я непреднамеренно развертывал тестовые зависимости моего второго пакета - поскольку требовалось установить их в CodeBuild (для запуска тестов))