ฉันกำลังมองหาฟังก์ชั่นเดียวกัน การใช้ซ้อนกันซ้อนตามที่ SpoonMeiser แนะนำมาถึงใจ แต่แล้วฉันก็ตระหนักว่าสิ่งที่ฉันต้องการจริง ๆ คือฟังก์ชั่นที่กำหนดเอง โชคดีที่ CloudFormation อนุญาตให้ใช้AWS :: CloudFormation :: CustomResourceที่มีบิตของงานอนุญาตให้ทำอย่างนั้น รู้สึกเหมือน overkill สำหรับตัวแปรเพียงอย่างเดียว (สิ่งที่ฉันจะโต้แย้งว่าควรจะอยู่ใน CloudFormation ในตอนแรก) แต่มันทำให้งานเสร็จและนอกจากนี้ยังช่วยให้ทุกอย่างยืดหยุ่น (เลือก python / node / java) ควรสังเกตว่าฟังก์ชั่นแลมบ์ดามีค่าใช้จ่าย แต่เรากำลังพูดถึงเพนนีที่นี่เว้นแต่คุณจะสร้าง / ลบสแต็คของคุณหลายครั้งต่อชั่วโมง
ขั้นแรกคือการสร้างฟังก์ชั่นแลมบ์ดาในหน้านี้ที่ไม่ทำอะไรเลยนอกจากรับค่าอินพุตและคัดลอกไปยังเอาต์พุต เราสามารถให้ฟังก์ชั่นแลมบ์ดาทำทุกสิ่งที่บ้าได้ แต่เมื่อเรามีฟังก์ชั่นเอกลักษณ์แล้วสิ่งอื่น ๆ ก็ง่าย อีกทางหนึ่งเราอาจมีฟังก์ชั่นแลมบ์ดาที่ถูกสร้างขึ้นในสแต็กเอง เนื่องจากฉันใช้สแต็คจำนวนมากใน 1 บัญชีฉันจะมีฟังก์ชั่นแลมบ์ดาและบทบาทที่เหลือทั้งหมด (และต้องสร้างสแต็กทั้งหมดด้วย--capabilities=CAPABILITY_IAM
เนื่องจากมันต้องการบทบาทด้วย
สร้างฟังก์ชั่นแลมบ์ดา
- ไปที่แลมบ์ดาหน้าแรกและเลือกภูมิภาคที่คุณชื่นชอบ
- เลือก "ฟังก์ชั่นที่ว่างเปล่า" เป็นแม่แบบ
- คลิก "ถัดไป" (ไม่ได้กำหนดค่าทริกเกอร์ใด ๆ )
- กรอก:
- ชื่อ: CloudFormationIdentity
- คำอธิบาย: ส่งคืนสิ่งที่ได้รับการสนับสนุนผันแปรใน Cloud Formation
- รันไทม์: python2.7
- ประเภทรายการรหัส: แก้ไขรหัสอินไลน์
- รหัส: ดูด้านล่าง
- handler:
index.handler
- บทบาท: สร้างบทบาทที่กำหนดเอง ณ จุดนี้ป๊อปอัปจะเปิดขึ้นเพื่อให้คุณสร้างบทบาทใหม่ ยอมรับทุกอย่างในหน้านี้และคลิก "อนุญาต" มันจะสร้างบทบาทที่มีสิทธิ์ในการโพสต์ลงในบันทึกของ cloudwatch
- หน่วยความจำ: 128 (นี่คือขั้นต่ำ)
- หมดเวลา: 3 วินาที (ควรมีมากมาย)
- VPC: ไม่มี VPC
จากนั้นคัดลอกโค้ดด้านล่างในฟิลด์รหัส ด้านบนของฟังก์ชั่นเป็นรหัสจากโมดูล cfn-responseที่จะได้รับการติดตั้งอัตโนมัติหากฟังก์ชั่นแลมบ์ดาถูกสร้างขึ้นผ่าน 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
ตัวแปรที่มี Arn สำหรับฟังก์ชัน lambda การใส่ตัวแปรนี้ไว้ที่นี่หมายความว่าฉันต้องระบุเพียงครั้งเดียว Custom::Variable
ฉันจะทำให้ตัวแปรของฉันทุกประเภท CloudFormation ช่วยให้คุณใช้ชื่อประเภทเริ่มต้นด้วยCustom::
สำหรับทรัพยากรที่กำหนดเอง
โปรดทราบว่าIdentity
ตัวแปรมี Arn สำหรับฟังก์ชั่นแลมบ์ดาสองครั้ง หนึ่งครั้งเพื่อระบุฟังก์ชั่นแลมบ์ดาที่จะใช้ ครั้งที่สองเป็นค่าของตัวแปร
ตอนนี้ฉันมีIdentity
ตัวแปรแล้วฉันสามารถกำหนดตัวแปรใหม่โดยใช้ServiceToken: !GetAtt [Identity, Arn]
(ฉันคิดว่ารหัส JSON ควรเป็นอย่างนั้น"ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]}
) ฉันสร้างตัวแปรใหม่ 2 ตัวแต่ละตัวมี 2 ฟิลด์: ชื่อและ Arn ในส่วนที่เหลือของแม่แบบของฉันฉันสามารถใช้!GetAtt [ClientBucketVar, Name]
หรือ!GetAtt [ClientBucketVar, Arn]
เมื่อใดก็ตามที่ฉันต้องการมัน
คำเตือน
เมื่อทำงานกับทรัพยากรที่กำหนดเองหากฟังก์ชัน lambda ขัดข้องคุณติดอยู่ระหว่าง 1 ถึง 2 ชั่วโมงเนื่องจาก CloudFormation รอการตอบกลับจากฟังก์ชัน (หยุดทำงาน) เป็นเวลาหนึ่งชั่วโมงก่อนที่จะยอมแพ้ ดังนั้นจึงเป็นการดีที่จะระบุการหมดเวลาสั้น ๆ สำหรับสแต็กขณะที่พัฒนาฟังก์ชันแลมบ์ดา