Запуск сборки AWS SAM из скрипта Python

#aws-sam-cli

#aws-sam-cli

Вопрос:

Я нахожусь в процессе переноса целых стеков CloudFormation в Troposphere, включая пользовательские ресурсы CFN, основанные на Lambda и Lambda.

Одна из моих целей — полностью отказаться от создания файлов шаблонов, сделав код Python единственным «источником истины» (т.Е. Без файлов шаблонов, которые создаются и, следовательно, могут редактироваться, вызывая смещение конфигурации).

Для этого требуется возможность:

  1. Передайте файлоподобный объект в SAM builder (вместо имени файла)
  2. Вызов AWS SAM builder из Python, а не из CLI

Моя первая наивная идея заключалась в том, что я мог бы импортировать несколько модулей из aws-sam-cli put a wrapper для io.StringIO него (чтобы сохранить шаблон как файлоподобный объект) и вуаля! Затем я посмотрел на исходный код sam build , и вся надежда покинула меня:

  • Возможно, я не смогу использовать Docker / containers для сборки, поскольку он будет отображать среду сборки, включая файлы шаблонов.
  • Интерфейс командной строки AWS SAM не предназначен для использования чисто вызываемого набора библиотечных функций, подобных boto3. Близко, но не совсем.

Вот ядро исходного кода Python

 with BuildContext(template,
                  base_dir,
                  build_dir,
                  clean=clean,
                  manifest_path=manifest_path,
                  use_container=use_container,
                  parameter_overrides=parameter_overrides,
                  docker_network=docker_network,
                  skip_pull_image=skip_pull_image,
                  mode=mode) as ctx:

    builder = ApplicationBuilder(ctx.function_provider,
                                 ctx.build_dir,
                                 ctx.base_dir,
                                 manifest_path_override=ctx.manifest_path_override,
                                 container_manager=ctx.container_manager,
                                 mode=ctx.mode
                                 )
    try:
        artifacts = builder.build()
        modified_template = builder.update_template(ctx.template_dict,
                                                    ctx.original_template_path,
                                                    artifacts)

        move_template(ctx.original_template_path,
                      ctx.output_template_path,
                      modified_template)

        click.secho("nBuild Succeeded", fg="green")

        msg = gen_success_msg(os.path.relpath(ctx.build_dir),
                              os.path.relpath(ctx.output_template_path),
                              os.path.abspath(ctx.build_dir) == os.path.abspath(DEFAULT_BUILD_DIR))

        click.secho(msg, fg="yellow")
 

Это зависит от ряда импортируемых файлов из внутренней библиотеки aws-sam-cli, при этом сборка ориентирована на

 from samcli.commands.build.build_context import BuildContext
from samcli.lib.build.app_builder import ApplicationBuilder, BuildError, UnsupportedBuilderLibraryVersionError, ContainerBuildNotSupported
from samcli.lib.build.workflow_config import UnsupportedRuntimeException
 

Понятно, что это означает, что это не так просто, как создать что-то вроде клиента boto3, и я пошел! Больше похоже, что мне пришлось бы разветвлять все и выбрасывать почти все, чтобы оставить команду сборки, контекст и среду.

Достаточно интересно, sam package что sam deploy , согласно документам, это просто псевдонимы для aws cloudformation package and aws cloudformation deploy , что означает, что их можно использовать в boto3!

Возможно, кто-нибудь уже решил эту проблему? Я искал и искал здесь, но ничего не нашел.

Я использую PyCharm и инструментарий AWS, которые отлично подходят для разработки и отладки, и оттуда я могу запускать сборки SAM, но они «скрыты» в плагинах PyCharm, которые написаны на Kotlin!

Мой текущий обходной путь заключается в создании шаблонов CFN в виде временных файлов и передаче их командам CLI, которые вызываются из Python — подход, который мне всегда не нравился.

Я могу отправить запрос функции команде aws-sam-cli и посмотреть, что они скажут, если только один из них не прочитает это.

Ответ №1:

Мне удалось запустить sam local start-api скрипт на python3.

Во-первых, pip3 install aws-sam-cli

Затем отдельная команда может быть импортирована и запущена.

 import sys
from samcli.commands.local.start_api.cli import cli
sys.exit(cli())
 

… при условии наличия шаблона.yaml в текущем каталоге.

Чего мне (пока) не удалось сделать, так это повлиять на аргументы командной строки, которые cli() будут получены, чтобы я мог указать, какие -t template из них использовать.

Редактировать

Глядя на то, как работают интеграционные тесты aws-sam-cli, кажется, что они фактически запускают процесс запуска CLI. Таким образом, они на самом деле вообще не передают параметр cli() вызову:-(

Например:

 class TestSamPython36HelloWorldIntegration(InvokeIntegBase):
    template = Path("template.yml")

    def test_invoke_returncode_is_zero(self):
        command_list = self.get_command_list(
            "HelloWorldServerlessFunction", template_path=self.template_path, event_path=self.event_path
        )

        process = Popen(command_list, stdout=PIPE)
        return_code = process.wait()

        self.assertEquals(return_code, 0)

   .... etc
 

из https://github.com/awslabs/aws-sam-cli/blob/a83aa9e620ff679ca740496a3f1ff4872b88894a/tests/integration/local/invoke/test_integrations_cli.py

Смотрите также start_api_integ_base.py в том же репозитории.

Я думаю, что в целом этого следовало ожидать, потому что все это реализовано в терминах click платформы приложений командной строки. К сожалению.

Смотрите, например http://click.palletsprojects.com/en/7.x/testing / в котором говорится: «Метод CliRunner.invoke() запускает сценарий командной строки изолированно …» — мой акцент.

Комментарии:

1. Вау! Сколько времени вам потребовалось, чтобы определить путь? : D Это именно то, что я ищу. Если вам удастся узнать, как передать шаблон, он получит галочку. 😉 Я посмотрю, смогу ли я попробовать это сам, а затем сделать один шаг в IDE / debugger, возможно, выяснить, где хранятся параметры.

2. Я просмотрел исходный код aws-sam-cli на GitHub и разобрался … возможно, модульные тесты объясняют, как задавать аргументы командной строки, но не заглядывали так далеко. github.com/awslabs/aws-sam-cli

Ответ №2:

Я использую следующий скрипт python для запуска команд sam cli. Это должно сработать и для вас.

 import json
import sys
import os

try:
    LAMBDA_S3_BUCKET="s3-bucket-name-in-same-region"
    AWS_REGION="us-east-1"      
    API_NAME = "YourAPIName"
    BASE_PATH="/path/to/your/project/code/dir"
    STACK_NAME="YourCloudFormationStackName"
    BUILD_DIR="%s/%s" % (BASE_PATH, "build_artifact")

    if not os.path.exists(BUILD_DIR):
        os.mkdir(BUILD_DIR)

    os.system("cd %s amp;amp; sam build --template template.yaml --build-dir %s" % (BASE_PATH, BUILD_DIR))
    os.system("cd %s amp;amp; sam package --template-file %s/template.yaml --output-template-file packaged.yaml --s3-bucket %s" %(BASE_PATH, BUILD_DIR,  LAMBDA_S3_BUCKET))
    os.system("cd %s amp;amp; sam deploy  --template-file packaged.yaml --stack-name %s --capabilities CAPABILITY_IAM --region %s" %(BASE_PATH, STACK_NAME, AWS_REGION))  

except Exception as e:
    print(e.message)
    exit(1)
 

Комментарии:

1. Да, мой текущий обходной путь использует os.system() вызовы вместе с оценкой возвращаемых значений и того, что нет. Это не идеальная ситуация.