AWS SAM: общие файлы в функциях Lambda

Я работаю с AWS SAM (Serverless Application Model) над созданием лямбда-кода Python 3.6 в настройке шлюза API. Таким образом, у меня есть один template.yaml файл, который создает несколько лямбда-функций. Они организованы с помощью лямбда-функций, каждая из которых находится в своем собственном подкаталоге внутри проекта. Лямбда также разделяет несколько общих файлов, которые я храню в общей папке.

project-home
 -lambda_a_dir
   -lambda_a.py
 -lambda_b_dir
   -lambda_b.py
 -shared_dir
   -shared.py

Проблема в том, что, хотя Pycharm может четко видеть shared.py, SAM не может и отказывается распознавать общие файлы со следующей ошибкой: Unable to import module 'lambdaA': No module named 'shared' Если я перемещаю копию файла shared.py в каждый каталог лямбда, и Pycharm, и SAM счастливы, и я могу построить / развернуть в AWS.
Мой вопрос: как я могу создать шаблон SAM с общими файлами, находящимися в общем каталоге?
До сих пор я пробовал:

  • Символическая ссылка и псевдоним MacOS.
  • Различные комбинации CodeUri альтернатив
  • Локальный пакет с __init__ и setup.py. (Я не могу использовать общедоступный пакет, потому что код является частным и не может быть помещен в общедоступный репозиторий.)

Вот мой файл шаблона:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  lambdaA:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: ./lambda_a_dir/
      Handler: lambda_a.lambda_handler
      Runtime: python3.6
  lambdaB:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: ./lambda_b_dir/
      Handler: lambda_b.lambda_handler
      Runtime: python3.6

person Hephaestus    schedule 08.04.2019    source источник
comment
Вам следует попробовать AWS Lambda Layers. Помещение содержимого shared_dir на отдельный слой должно помочь.   -  person Dunedan    schedule 08.04.2019
comment
FWIW: есть проблема и PR, отправленный команде интерфейса командной строки AWS, что команда aws cloudformation package должна следовать символическим ссылкам.   -  person matsev    schedule 08.04.2019
comment
@Dunedan Ваш ответ был правильным. Если вы напишете свой ответ в качестве ответа, я буду вам благодарен за это.   -  person Hephaestus    schedule 09.04.2019
comment
Поскольку у вас уже есть полный ответ как часть вашего вопроса, я предлагаю вам разделить эту часть, дать фактический ответ и отметить его как принятый.   -  person Dunedan    schedule 10.04.2019


Ответы (3)


Следуя рекомендации @Dunedan, я создал объект Layers для каждой лямбда-функции с общим кодом, это эффективно добавило эти подпрограммы в PythonPath для этих функций. Я также добавил следующее в определение шаблона API с новыми свойствами Layers:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  lambdaA:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: ./lambda_a_dir/
      Handler: lambda_a.lambda_handler
      Runtime: python3.6
      Layers: 
        - arn:aws:lambda:us-west-1:012345678:layer:my_shared_zip:1
  lambdaB:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: ./lambda_b_dir/
      Handler: lambda_b.lambda_handler
      Runtime: python3.6
      Layers: 
        - arn:aws:lambda:us-west-1:012345678:layer:my_shared_zip:1

Обратите внимание, что код должен быть заархивирован перед загрузкой и должен иметь следующую структуру каталогов, с кодом внутри каталога с именем языка. В этом случае, поскольку я использовал Python, код должен был находиться в каталоге python, а затем каталог python был заархивирован:

my_shared_zip.zip
 -python
   -shared.py
   -other_shared.py
   -more_shared.py

Последнее примечание. Хотя в идеале этот общий каталог python должен быть развернут непосредственно командой sam deploy в объектах Layer, я обнаружил, что поддержка Layers в AWS SAM CLI все еще настолько нова и содержит такие ошибки, что на данный момент она не работает. Надеюсь, в ближайшие месяцы это будет исправлено. А пока мне нужно вручную установить новые версии файла shared-zip. Вздох.

person Hephaestus    schedule 10.04.2019

Решение слоев выглядит как взлом. Я попытался создать символическую ссылку на «общую» папку, и это сработало - общая папка была успешно упакована вместе с моей лямбда-функцией.

cd lambda_a_dir
ln -s ../shared
person MrKsn    schedule 21.05.2020
comment
Я думаю, что это вопрос общего кода и дублированного кода. С помощью слоев один и тот же уровень может быть присоединен (совместно использован) к десяткам лямбда-функций, и легко убедиться, что все они используют один и тот же уровень (поскольку у слоев есть управление версиями). В решении с символической ссылкой каждая функция лямбда будет иметь свою собственную частную копию общих файлов, что приводит к вопросу о том, какой код использует каждая лямбда. Тем не менее, я начинаю думать, что контейнерами (с ECR / ECS) может быть проще управлять, но я все еще работаю над этим. - person Hephaestus; 22.05.2020
comment
100% правильно! Лично я бы предпочел, чтобы в функциях был запечен весь требуемый код внутри zip. Небольшой недостаток решения для символических ссылок: chalice deploy не следует за символическими ссылками :( - person MrKsn; 24.05.2020
comment
Это не работает для лямбда-выражения python с использованием CDK: '( - person Natacha; 07.07.2021

Вы пробовали использовать Rocketsam CLI? Он решает именно эту проблему (совместное использование кода лямбдами с использованием символических ссылок, которые автоматически создаются во время сборки). Это также позволяет разделить файл YAML, чтобы каждая лямбда могла иметь отдельный файл YAML.

person Nadav96    schedule 02.10.2020