#aws-sam-cli
#aws-sam-cli
Вопрос:
Я нахожусь в процессе переноса целых стеков CloudFormation в Troposphere, включая пользовательские ресурсы CFN, основанные на Lambda и Lambda.
Одна из моих целей — полностью отказаться от создания файлов шаблонов, сделав код Python единственным «источником истины» (т.Е. Без файлов шаблонов, которые создаются и, следовательно, могут редактироваться, вызывая смещение конфигурации).
Для этого требуется возможность:
- Передайте файлоподобный объект в SAM builder (вместо имени файла)
- Вызов 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
Смотрите также 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()
вызовы вместе с оценкой возвращаемых значений и того, что нет. Это не идеальная ситуация.