Я шукав однакового функціоналу. Використовуючи вкладений стек, як запропонував SpoonMeiser, прийшло в голову, але потім я зрозумів, що те, що мені насправді потрібно, - це власні функції. На щастя CloudFormation дозволяє використовувати AWS :: CloudFormation :: CustomResource, який, трохи працюючи, дозволяє зробити саме це. Це здається, що надмірна кількість лише змінних (я б заперечував, що це повинно було бути в CloudFormation в першу чергу), але це виконує роботу, і, крім того, дозволяє забезпечити всю гнучкість (виберіть пітон / вузол / java). Слід зазначити, що функції лямбда коштують грошей, але ми говоримо тут про копійки, якщо ви не створюєте / видаляєте свої стеки кілька разів на годину.
Перший крок - зробити на цій сторінці лямбда-функцію, яка не робить нічого, окрім як взяти вхідне значення та скопіювати його на вихід. Ми могли б змусити лямбда-функцію робити всілякі божевільні речі, але як тільки ми отримаємо функцію ідентичності, все інше легко. Крім того, ми могли б створити лямбда-функцію, що створюється в самій стеці. Оскільки я використовую багато стеків в одному обліковому записі, у мене буде ціла купа залишків лямбда-функцій та ролей (і всі стеки потрібно створювати за допомогою --capabilities=CAPABILITY_IAM
, оскільки вона також потребує ролі.
Створіть лямбда-функцію
- Перейдіть на домашню сторінку лямбда та виберіть улюблений регіон
- Виберіть "Пусту функцію" як шаблон
- Натисніть "Далі" (не налаштовуйте жодних тригерів)
- Заповнити:
- Назва: CloudFormationIdentity
- Опис: Повертає отриману змінну підтримку у формуванні хмар
- Час виконання: python2.7
- Тип введення коду: редагування вбудованого коду
- Код: див. Нижче
- Обробник:
index.handler
- Роль: Створіть власну роль. У цей момент відкривається спливаюче вікно, що дозволяє створити нову роль. Прийміть усе на цій сторінці та натисніть «Дозволити». Це створить роль з дозволами на публікацію журналів хмарного перегляду.
- Пам'ять: 128 (це мінімум)
- Час очікування: 3 секунди (має бути багато)
- VPC: немає VPC
Потім скопіюйте і вставте код нижче в поле коду. Вгорі функції - код з модуля python-відповіді cfn , який автоматично встановлюється лише в тому випадку, якщо лямбда-функція створена через CloudFormation з якихось дивних причин. handler
Функція досить очевидна.
from __future__ import print_function
import json
try:
from urllib2 import HTTPError, build_opener, HTTPHandler, Request
except ImportError:
from urllib.error import HTTPError
from urllib.request import build_opener, HTTPHandler, Request
SUCCESS = "SUCCESS"
FAILED = "FAILED"
def send(event, context, response_status, reason=None, response_data=None, physical_resource_id=None):
response_data = response_data or {}
response_body = json.dumps(
{
'Status': response_status,
'Reason': reason or "See the details in CloudWatch Log Stream: " + context.log_stream_name,
'PhysicalResourceId': physical_resource_id or context.log_stream_name,
'StackId': event['StackId'],
'RequestId': event['RequestId'],
'LogicalResourceId': event['LogicalResourceId'],
'Data': response_data
}
)
if event["ResponseURL"] == "http://pre-signed-S3-url-for-response":
print("Would send back the following values to Cloud Formation:")
print(response_data)
return
opener = build_opener(HTTPHandler)
request = Request(event['ResponseURL'], data=response_body)
request.add_header('Content-Type', '')
request.add_header('Content-Length', len(response_body))
request.get_method = lambda: 'PUT'
try:
response = opener.open(request)
print("Status code: {}".format(response.getcode()))
print("Status message: {}".format(response.msg))
return True
except HTTPError as exc:
print("Failed executing HTTP request: {}".format(exc.code))
return False
def handler(event, context):
responseData = event['ResourceProperties']
send(event, context, SUCCESS, None, responseData, "CustomResourcePhysicalID")
- Натисніть "Далі"
- Натисніть "Створити функцію"
Тепер ви можете протестувати функцію лямбда, вибравши кнопку «Тест» та вибравши «Шаблон зразка CloudFormation» як зразок шаблону. Ви повинні побачити у своєму журналі, що змінні, подані до нього, повертаються.
Використовуйте змінну у вашому шаблоні CloudFormation
Тепер, коли у нас є ця лямбда-функція, ми можемо використовувати її у шаблонах CloudFormation. Спочатку зверніть увагу на функцію лямбда Arn (перейдіть на домашню сторінку лямбда , натисніть щойно створену функцію, Arn має бути вгорі праворуч, щось на зразок arn:aws:lambda:region:12345:function:CloudFormationIdentity
).
Тепер у своєму шаблоні, у розділі ресурсів, вкажіть ваші змінні:
Identity:
Type: "Custom::Variable"
Properties:
ServiceToken: "arn:aws:lambda:region:12345:function:CloudFormationIdentity"
Arn: "arn:aws:lambda:region:12345:function:CloudFormationIdentity"
ClientBucketVar:
Type: "Custom::Variable"
Properties:
ServiceToken: !GetAtt [Identity, Arn]
Name: !Join ["-", [my-client-bucket, !Ref ClientName]]
Arn: !Join [":", [arn, aws, s3, "", "", !Join ["-", [my-client-bucket, !Ref ClientName]]]]
ClientBackupBucketVar:
Type: "Custom::Variable"
Properties:
ServiceToken: !GetAtt [Identity, Arn]
Name: !Join ["-", [my-client-bucket, !Ref ClientName, backup]]
Arn: !Join [":", [arn, aws, s3, "", "", !Join ["-", [my-client-bucket, !Ref ClientName, backup]]]]
Спочатку я вказую Identity
змінну, яка містить арн для функції лямбда. Якщо помістити цю змінну тут, це означає, що я повинен лише вказати її один раз. Я роблю всі свої змінні типу Custom::Variable
. CloudFormation дозволяє використовувати будь-яке ім’я типу, починаючи з Custom::
користувацьких ресурсів.
Зауважте, що Identity
змінна містить Arn для лямбда-функції двічі. Один раз, щоб вказати функцію лямбда, яку потрібно використовувати. Другий раз як значення змінної.
Тепер, коли у мене є Identity
змінна, я можу визначити нові змінні за допомогою ServiceToken: !GetAtt [Identity, Arn]
(я думаю, що код JSON повинен бути чимось на зразок "ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]}
). Я створюю 2 нові змінні, кожна з яких має 2 поля: Ім'я та Арн. У решті мого шаблону я можу використовувати !GetAtt [ClientBucketVar, Name]
або !GetAtt [ClientBucketVar, Arn]
коли мені це потрібно.
Слово обережності
Під час роботи з користувацькими ресурсами, якщо функція лямбда виходить з ладу, ви затримуєтесь від 1 до 2 годин, тому що CloudFormation чекає відповіді від (розбитої) функції протягом години, перш ніж відмовитися. Тому може бути корисним вказати короткий час очікування для стека під час розробки вашої лямбда-функції.