Каков правильный синтаксис команды для проверки того, приведет ли конкретный вызов aws cloudformation update-stack
к каким-либо изменениям?
Проблема заключается в том, что программа автоматизации, которая запускает команду aws cloudformation update-stack --stack-name ourstackname --template-body file://c:\path\to\ourtemplate.json --parameters ParameterKey=someKey,ParameterValue=someValue ...
, дает следующую ошибку:
An error occurred (ValidationError) when calling the UpdateStack operation: No updates are to be performed.
Результатом является код ответа 254
http, который, как мы можем судить по эта ссылка на документацию, означает, что могло возникнуть множество возможных проблем. Таким образом, это НЕ поможет нам обработать этот код ответа 254.
Какой синтаксис команды aws cloudformation
cli мы можем ввести вместо этого, чтобы процесс автоматизации получал код ответа 0
в тех случаях, когда не будут внесены изменения? Например, к команде aws cloudformation update-stack ...
добавлен флаг --flag, чтобы возвращать 0
, когда не вносятся изменения.
В качестве альтернативы, если бы какая-то команда предварительного просмотра возвращала 0
, указывающую, что НИКАКИХ ИЗМЕНЕНИЙ НЕ БУДЕТ, тогда наша автоматизация могла бы просто воздержаться от вызова aws cloudformation update-stack ...
в этой ситуации.
Terraform, например, по умолчанию просто завершается успешно, сообщая, что после запуска не было внесено никаких изменений, когда представлен этот вариант использования.
@CodeMed, можете ли вы просмотреть, поможет ли вам какой-либо из ответов?
Пожалуйста, воздержитесь от использования блока цитат (>
), если материал внутри него не является цитатой. «Цитата» — это высказывание другого человека или материал, содержащийся в книге, фильме, аудиозаписи, сценарии, периодическом издании и т. д. Цитаты, используемые просто в качестве выделения, затрудняют чтение сообщений, поскольку читатели должны вносить мысленные поправки в обычное значение. этого форматирования.
Поскольку вы просите создать «предварительный просмотр», я предлагаю вам попробовать создать Изменить набор, просмотреть его вывод, а затем решить, хотите ли вы выполнить его, если будут перечислены некоторые изменения.
Приведенные ниже команды были протестированы в bash/zsh, вам может потребоваться немного настроить их в среде Windows (к сожалению, прямо сейчас у меня нет возможности протестировать их на компьютере с Windows).
# start the change-set and get its ID (note the extra change-set-name, output and query params)
myid=$(aws cloudformation create-change-set --change-set-name my-change --stack-name ourstackname --template-body file://ourtemplate.json --parameters ParameterKey=someKey,ParameterValue=someValue --output text --query Id)
# wait for your change-set to finish execution
aws cloudformation wait change-set-create-complete --change-set-name $myid 2> /dev/null
# get the result status in a variable
result_status=$(aws cloudformation describe-change-set --change-set-name $myid --output text --query Status)
# only executes the change-set if there were changes, aka Status is complete (if no changes, this will be FAILED)
[[ "$result_status" == "CREATE_COMPLETE" ]] && aws cloudformation execute-change-set --change-set-name $myid
# cleanup change-set afterwards if you want to re-use the name "my-change" from the 1st command, otherwise just leave it
aws cloudformation delete-change-set --change-set-name $myid
Обновлять: автор попросил Python, более отказоустойчивую версию реализации:
from typing import Dict, Tuple
import boto3
from botocore.exceptions import ClientError, WaiterError
def main():
template_file = "../s3-bucket.yaml"
with open(template_file) as template_fileobj:
template_data = template_fileobj.read()
client = boto3.client('cloudformation')
changeset_applied = _create_and_execute_changeset(
client, 'my-stack', 'my-changeset', template_data)
print(changeset_applied)
def _create_and_execute_changeset(client: boto3.client, stack_name: str, changeset_name: str, template_body: str) -> bool:
client.validate_template(TemplateBody=template_body)
response_create_changeset = client.create_change_set(
StackName=stack_name,
ChangeSetName=changeset_name,
TemplateBody=template_body,
)
changeset_id = response_create_changeset['Id']
apply_changeset = True
waiter = client.get_waiter('change_set_create_complete')
try:
waiter.wait(ChangeSetName=changeset_id)
except WaiterError as ex:
if ex.last_response['Status'] == 'FAILED' and ex.last_response['StatusReason'].startswith('The submitted information didn\'t contain changes'):
apply_changeset = False
else:
raise
if apply_changeset:
client.execute_change_set(ChangeSetName=changeset_id)
# executed changesets cleanup automatically
else:
# cleanup changeset not executed
client.delete_change_set(ChangeSetName=changeset_id)
return apply_changeset
if __name__ == '__main__':
main()
@CodeMed ха, отличный вопрос! Если вы спрашиваете об этом, возможно, вы не знаете о несколько скрытой функции boto3: waiters
. Я посмотрю, смогу ли я работать с версией этого кода, работающей на Python, но пока я собираюсь добавить хотя бы эту часть в свой ответ выше.
Я не уверен, понимаю ли я ваш запрос сейчас... Когда вы говорите «простой питон», вы используете Python для вызова AWS cli вместо использования библиотек? Может быть, вы можете предоставить образцы того, что у вас есть, чтобы мы могли лучше понять...
забыл отметить @CodeMed в своем комментарии
@CodeMed Я говорю, что в настоящее время мне трудно понять, что вы ищете. В вашем вопросе есть команды CLI. CLI предназначен для запуска на терминале: bash, PowerShell, каком-то типе, но все же на терминале. Вы только что упомянули Python в комментарии здесь. Вызов API AWS из «python без библиотек» очень сложен, так как вам нужно обрабатывать аутентификацию. Поэтому я считаю, что в вашем рабочем процессе есть что-то, чем вы не делитесь. Вот почему я попросил вас предоставить пример кода того, что/как вы работаете, иначе вам будет сложно помочь.
«Пожалуйста, покажите более устойчивый способ дождаться завершения создания набора изменений», что не так с текущим подходом в ответе?
любая из этих команд вызовет ошибки в python. ваш код (aws cloudformation update-stack
) выдаст ошибку, так как aws не определен. вы скрываете некоторые важные детали от вашей установки
Давайте продолжить обсуждение в чате.
@CodeMed Я снова обновил свой ответ. Мне придется не согласиться с вызовом subprocess
в Python как «выполнение этого кода в python» (из вашего 1-го комментария здесь). Как вы сказали, на самом деле вы просто вызываете команды оболочки из Python, но это может быть любой язык. Если вам нужна отказоустойчивая реализация, я настоятельно рекомендую вам использовать собственные библиотеки (boto) и собственный код Python, чтобы вы могли анализировать и обрабатывать исключения. Я добавил полный рабочий (и отказоустойчивый) пример этого кода на Python. Если это не то, что вы ищете, я рекомендую вам просмотреть свой вопрос и быть более конкретным
Мы не воспользовались вашим предложением boto, потому что нашли очень устойчивый подход с использованием простого Python, который использует меньше кода и не требует от наших пользователей добавления boto. Но мы помечаем ваш ответ как принятый, потому что вы потратили на него много времени, и потому что мы использовали ваши команды cli в качестве отправной точки для создания того, что мы фактически использовали.
@CodeMed спасибо за признание, и я рад, что это помогло вам. Если вы можете, добавьте свое собственное решение в качестве ответа здесь, чтобы другие могли получить пользу, если им это нужно.
Вместо aws cloudformation update-stack
вы можете использовать команду aws cloudformation deploy
.
Документация по развертыванию aws cloudformation
В зависимости от ваших конкретных требований можно использовать следующие два флага, описанные в связанной документации:
--no-execute-changeset
(boolean) Indicates whether to execute the change set. Specify this flag if you want to view your stack changes before executing the change set. The command creates an AWS CloudFormation change set and then exits without executing the change set. After you view the change set, execute it to implement your changes.
--fail-on-empty-changeset
|--no-fail-on-empty-changeset
(boolean) Specify if the CLI should return a non-zero exit code if there are no changes to be made to the stack. The default behavior is to return a zero exit code.
Еще одно преимущество использования команды deploy
заключается в том, что ее можно использовать для создания стека, а также для обновления стека, если он уже существует. Если вас конкретно интересуют различия между deploy
и update-stack
или create-stack
, этот ответ к предыдущему вопросу содержит более подробную информацию.
Я думаю, что с deploy
, если вы пройдете --no-execute-changeset --no-fail-on-empty-changeset
, вы не будете знать, не было ли изменений или было бы успешно завершено даже с изменениями. И передача --no-execute-changeset --fail-on-empty-changeset
приведет к той же проблеме, что и сегодня, код ошибки без особой информации. И вы все еще можете выполнить набор изменений позже. По моему опыту, deploy
действительно полезен только в том случае, если вы хотите закрыть глаза и выполнять его всегда, иначе у вас будет более детальный контроль над другими командами.
Можете ли вы привести какой-либо пример шаблона, который вы используете?
ValidationError
предполагают, что проблема в самом шаблоне, возможно, в его синтаксисе.