å°è¥¿ç§åã§ãã
ä»åã¯AWS Cloudformationãã³ãã¬ã¼ãããå¼ã³åºããã¨ã§ãå¥ãªã¼ã¸ã§ã³ã«AWS Cloudformationã¹ã¿ãã¯ããããã¤ããAWS Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã«ã¤ãã¦æ¸ãããã¨æãã¾ãã
ãã®è¨äºãæ¸ããã¨æã£ãçç±ã¯Amazon CloudFrontã®AWS Certificate Managerã®è¨¼ææ¸ãLambda@Edgeããã¼ã¸ãã¢ãªã¼ã¸ã§ã³(us-east-1)ã§ã®ã¿ä½¿ç¨ã§ããã¨ããå¶éãããããã§ãã
ä¾ãã°ãæ±äº¬ãªã¼ã¸ã§ã³(ap-northeast-1)ã§Amazon S3ã¨Amazon CloudFrontã®éçãã¹ãã£ã³ã°ç°å¢ã使ããã¹ã¿ãã¯ããããã¤ããå ´åãAWS Certificate Managerè¨¼ææ¸ã¨Lambda@Edgeã追å ããã«ã¯ãã¼ã¸ãã¢ãªã¼ã¸ã§ã³(us-east-1)ã«ãªã½ã¼ã¹ã使ããå¿
è¦ãããã¾ãã
ãã®ããããã®ãããªã±ã¼ã¹ã®å ´åã¯AWS Cloudformationãã³ãã¬ã¼ãã§ãããã®ãªã½ã¼ã¹ããããã¤ãã鏿è¢ã¨ãã¦ã¯æ¬¡ã®ãããªæ¹æ³ãèãããã¾ãã
- ãã¹ã¦ã®ãªã½ã¼ã¹ãus-east-1ã®AWS Cloudformationã¹ã¿ãã¯ã§ä½æãã
- ap-northeast-1ã§ãããã¤ããAWS Cloudformationã¹ã¿ãã¯ããLambdaã«ã¹ã¿ã ãªã½ã¼ã¹ãå¼ã³åºãã¦ãå¿ è¦ãªãªã½ã¼ã¹ã®ã¿us-east-1ã«ä½æãã
- AWS Cloudformation StackSetsã§å¿ è¦ãªãªã½ã¼ã¹ã®ã¿us-east-1ã«ä½æãã
- 該å½é¨åã®èªååãããã«AWSããã¸ã¡ã³ãã³ã³ã½ã¼ã«ãªã©ã§æå使ãã
1.ã§ããã°us-east-1ãªã¼ã¸ã§ã³ã§å®çµãã¾ãããä»ã®ãªã¼ã¸ã§ã³ã§ãªã½ã¼ã¹ã使ãããå ´åã«ã¯é¸æã§ãã¾ããã
2.ã¨3.ã¯ç©æ¥µçã«èªååãããã¢ããã¼ãã§ãããus-east-1ã§ä½æãããªã½ã¼ã¹ã®ARNãªã©ãap-northeast-1ã§ãããã¤ããAWS Cloudformationã¹ã¿ãã¯ã«æ¸¡ãã¦ãAmazon CloudFrontã¨AWS Certificate Managerè¨¼ææ¸ãLambda@Edgeãé¢é£ä»ããå¿
è¦ãããã¾ãã
4.åæ§ã®ç°å¢ãä½åº¦ã使ããå¿
è¦ããªãããã©ã¡ã¼ã¿å
¥å以éã®ããã»ã¹ãå®å
¨ã«èªååããå¿
è¦ããªãã¨ãã£ãå ´åã«ã¯éçºæéãç¯ç´ããããã®ç¾å®çãªæ¹æ³ã§ãã
ä»åã¯ãããã®ãã¡2.ã使ç¨ããå ã®AWS Cloudformationã¹ã¿ãã¯ã§Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ãå¼ã³åºããus-east-1ã§AWS Cloudformationã¹ã¿ãã¯ã«ãããªã½ã¼ã¹ã使ãã¦è¿ãå¤ãå ã®AWS Cloudformationã¹ã¿ãã¯ã§åãåã£ã¦å¦çãç¶ããæ¹æ³ã試ãã¾ãã
â»æ¬è¨äºããã³å½å·çè ã®ãã®ä»ã®è¨äºã§æ²è¼ããã¦ããã½ã¼ã¹ã³ã¼ãã¯èªä¸»ç ç©¶æ´»åã®ä¸è²«ã¨ãã¦ä½æãããã®ã§ãããåä½ãä¿è¨¼ãããã®ã§ã¯ããã¾ããã使ç¨ããå ´åã¯èªå·±è²¬ä»»ã§ãé¡ãè´ãã¾ããã¾ããäºåãªãä¿®æ£ãããã¨ãããã¾ãã®ã§ãäºæ¿ãã ããã
AWS Cloudformationã®ã«ã¹ã¿ã ãªã½ã¼ã¹ã¨ã¯
AWS Cloudformationã§ãªãã·ã§ã³ã¨ãã¦ä½¿ç¨ã§ããã«ã¹ã¿ã ãªã½ã¼ã¹ã¨ã¯ãAWS CloudFormationã®ãªã½ã¼ã¹ã¿ã¤ãã¨ãã¦ä½¿ç¨ã§ããªããªã½ã¼ã¹ãAWS Lambda颿°ã§å®è¡ããããAmazon SNSãããã¯ã§ããªã¬ã¼ããããã¦ä½¿ç¨ããããã®ãã®ã§ãã
ä¾ãã°ãå¤é¨ãµã¼ãã¹ããªã³ãã¬ãã¹ã·ã¹ãã ã使ç¨ããå ´åãªã©ãæãããã¾ãããä»åã®ããã«AWSãµã¼ãã¹å
é¨ã§ããªã¼ã¸ã§ã³ãã¾ããå¦çãAWSå
ã§æ§ç¯ãããã¤ã¯ããµã¼ãã¹ãå¼ã³åºããªã©ä½¿ãæ¹ã¯æ§ã
ã§ãã
ãã ãAWS Lambdaã§ã«ã¹ã¿ã ãªã½ã¼ã¹ãå®è£
ããå ´åã¯å®è¡æéãæå¤§15å以å
åããå¿
è¦ããããªã©ãAWS Lambdaã®ä»æ§ã«ããå¶éãçºçãããã¨ã«æ³¨æãå¿
è¦ã¨ãªãã¾ãã
ã¾ããAWS Lambdaã§ã«ã¹ã¿ã ãªã½ã¼ã¹ãå®è£
ããå ´åã¯å®è¡å
ã®AWS Cloudformationã¹ã¿ãã¯ã«ç¹æã®å½¢å¼ã§ã¬ã¹ãã³ã¹ãè¿å´ããå¿
è¦ãããã¾ãã
ãã®ã¬ã¹ãã³ã¹ãè¿å´ããæ©è½ã¯ç¨æããã¦ããCloudformationå°ç¨ã¡ã½ããã使ç¨ããããç¬èªã«ã¬ã¹ãã³ã¹ã¡ã½ããã使ããå¿
è¦ãããã¾ãã
詳細ã«ã¤ãã¦ã¯å¾è¿°ãã¾ãã
å¥ãªã¼ã¸ã§ã³ã«AWS Cloudformationã¹ã¿ãã¯ããããã¤ããAWS Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹
ã¾ããä»åã®AWS Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã®ä½¿ç¨ãã¿ã¼ã³ãæ§æå³ã§ç¤ºãã¾ãã

ãã®ããã«ä¸»ã«å¼åºå
ã®AWS Cloudformationã¹ã¿ãã¯ããæä¾ããããã©ã¡ã¼ã¿ã§å¥ãªã¼ã¸ã§ã³ã«å¥ã®AWS Cloudformationã¹ã¿ãã¯ããããã¤ãã¦çµæãå¼åºå
ã«è¿ãã¦ãå¼åºå
ã®å¦çã§çµæãã©ã¡ã¼ã¿ã使ç¨ãã¦ãªã½ã¼ã¹ãé¢é£ä»ããã¨ãããã¨ã主ãªç®çã¨ãã¦ãã¾ãã
ãã®å¥ãªã¼ã¸ã§ã³ã«ãããã¤ããAWS Cloudformationã¹ã¿ãã¯ã¯AWS Lambdaã®å®è¡æéã§ããæå¤§15å以å
ã«çµäºããããã«ããå¿
è¦ãããã¾ãããããã«ã¹ã¿ã ãªã½ã¼ã¹ã使ç¨ãã¦15å以ä¸ãããCloudformationã¹ã¿ãã¯ããããã¤ãããããªå ´åã¯Cloudformationãã³ãã¬ã¼ããè¤æ°ã«åãã¦å®è¡ããããå¶éæéã®ç¡ãå¥ã®æ¹æ³ã§å®è¡ããã®ãããã§ãããã
ã¾ãããã®Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã«ã¢ã¿ããããIAMãã¼ã«ã®IAMããªã·ã¼æ¨©éã¯Lambda颿°ãã¢ã¯ã»ã¹ãããªã½ã¼ã¹ãCloudformationã®å®è¡ãCloudformationã¹ã¿ãã¯ã§ãããã¤ãããªã½ã¼ã¹ãªã©å¿
è¦ãªæ¨©éãä»ä¸ããå¿
è¦ãããã¾ãã
å¥ãªã¼ã¸ã§ã³ã«AWS Cloudformationã¹ã¿ãã¯ããããã¤ããAWS Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã¯æ¬¡ã®ããã«Pythonã§å®è£
ãã¾ããã使ç¨ããã©ã³ã¿ã¤ã ã¯Python 3.9ã§ãã
工夫ãããã¤ã³ããããã¤ãããã®ã§ç¹å¾´ãæãã¦ã¿ã¾ãã
- ã«ã¹ã¿ã ãªã½ã¼ã¹ä»æ§ã®ã¬ã¹ãã³ã¹ãè¿ãã¡ã½ãããèªåã§ä½æãã
CloudFormationã¹ã¿ãã¯ããå¼ã³åºãå ´åã¯cfnresponse.sendã使ç¨ã§ãã¾ãããLambdaåä½ã§ã®å®è¡ããã¹ãã«ã¯ä½¿ç¨ã§ããªãããcfn_response_sendã¨ããèªåã®ã¡ã½ããã使ãã¾ããã
åèï¼cfn-response ã¢ã¸ã¥ã¼ã« - AWS CloudFormation - ãããã¤ãããã³ãã¬ã¼ããS3ã¾ãã¯ãã¼ãã³ã¼ãã£ã³ã°ãã鏿ã§ããããã«ãã
S3ãããã³ãã¬ã¼ããåå¾ããæ¹æ³ã§ã¯æ§ã ãªãã³ãã¬ã¼ããå®è¡ã§ãã¾ãã䏿¹ã§ç¹å®ã®ãã³ãã¬ã¼ãå®è¡ã«ç¹åããããå ´åã¯ãã¼ãã³ã¼ãã£ã³ã°ã鏿ãããã¨ã§ä»ã®ãã³ãã¬ã¼ããå®è¡ãããªãããã«ã§ãã¾ãã - ã«ã¹ã¿ã ãªã½ã¼ã¹ãããããã¤ããCloudFormationãã³ãã¬ã¼ãã®å¼æ°ã®æå®ãç°¡ç´ åãã
ãããã¤ããCloudformationãã³ãã¬ã¼ãã®å¼æ°ã¨ãã¦ä½¿ç¨ããªããã¼ãæå®ãã¦ããã以å¤ã渡ããã¨ã§å¼æ°ã®åãæ¸¡ããæ±ç¨çã«ãã¾ããã - è¦æ±ãããå¦çã¨ç°ãªãç¶æ³ã®å ´åã§ããªã½ã¼ã¹ã使ãããæ¹éã«å¯ãã
è¦æ±ãããCreateãUpdateå¦çããã®ã¾ã¾CloudFormationã®ãããã¤ã«ä½¿ç¨ããã®ã§ã¯ãªããUpdateå¦çã§ã¹ã¿ãã¯ãåå¨ããªãå ´åã«ã¯Createå¦çã«åãæ¿ãããªã©ããªãã¹ããªã½ã¼ã¹ã使ãããæ¹éã«å¯ãã¾ããã - å¦çã®ã¹ãããã鏿ã§ããããã«ãã
å¼åºå ã§ä¾åé¢ä¿ãç¶æããªããCreateå¦çã§ã¯ä½¿ç¨ãããUpdateå¦çãã使ç¨ããã¨ãã£ããã¨ãã§ããããã«ã¹ãããå¦çã鏿ã§ããããã«ãã¾ããã
ãã®ããã«ããªãçãå¼·ãAWS Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã«ãªã£ã¦ãã¾ãã®ã§ãåèã«ããå ´åã¯ãã®ç¹ã«ã¤ãã¦ç¹ã«ã注æãã ããã
# ## ãã®ã«ã¹ã¿ã ãªã½ã¼ã¹ã®ç¹å¾´ # * ã«ã¹ã¿ã ãªã½ã¼ã¹ä»æ§ã®ã¬ã¹ãã³ã¹ãè¿ãã¡ã½ãããèªåã§ä½æãã # CloudFormationã¹ã¿ãã¯ããå¼ã³åºãå ´åã¯cfnresponse.sendã使ç¨ã§ãã¾ãããLambdaåä½ã§ã®å®è¡ããã¹ãã«ã¯ä½¿ç¨ã§ããªãããcfn_response_sendã¨ããèªåã®ã¡ã½ããã使ãã¾ããã # åèï¼https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html # * ãããã¤ãããã³ãã¬ã¼ããS3ã¾ãã¯ãã¼ãã³ã¼ãã£ã³ã°ãã鏿ã§ããããã«ãã # S3ãããã³ãã¬ã¼ããåå¾ããæ¹æ³ã§ã¯æ§ã ãªãã³ãã¬ã¼ããå®è¡ã§ãã¾ãã䏿¹ã§ç¹å®ã®ãã³ãã¬ã¼ãå®è¡ã«ç¹åããããå ´åã¯ãã¼ãã³ã¼ãã£ã³ã°ã鏿ãããã¨ã§ä»ã®ãã³ãã¬ã¼ããå®è¡ãããªãããã«ã§ãã¾ãã # * ã«ã¹ã¿ã ãªã½ã¼ã¹ãããããã¤ããCloudFormationãã³ãã¬ã¼ãã®å¼æ°ã®æå®ãç°¡ç´ åãã # ãããã¤ããCloudformationãã³ãã¬ã¼ãã®å¼æ°ã¨ãã¦ä½¿ç¨ããªããã¼ãæå®ãã¦ããã以å¤ã渡ããã¨ã§å¼æ°ã®åãæ¸¡ããæ±ç¨çã«ãã¾ããã # * è¦æ±ãããå¦çã¨ç°ãªãç¶æ³ã®å ´åã§ããªã½ã¼ã¹ã使ãããæ¹éã«å¯ãã # è¦æ±ãããCreateãUpdateå¦çããã®ã¾ã¾CloudFormationã®ãããã¤ã«ä½¿ç¨ããã®ã§ã¯ãªããUpdateå¦çã§ã¹ã¿ãã¯ãåå¨ããªãå ´åã«ã¯Createå¦çã«åãæ¿ãããªã©ããªãã¹ããªã½ã¼ã¹ã使ãããæ¹éã«å¯ãã¾ããã # * å¦çã®ã¹ãããã鏿ã§ããããã«ãã # å¼åºå ã§ä¾åé¢ä¿ãç¶æããªããCreateå¦çã§ã¯ä½¿ç¨ãããUpdateå¦çãã使ç¨ããã¨ãã£ããã¨ãã§ããããã«ã¹ãããå¦çã鏿ã§ããããã«ãã¾ããã import urllib3 import json import boto3 import botocore import datetime # import cfnresponse SUCCESS = 'SUCCESS' FAILED = 'FAILED' http = urllib3.PoolManager() # å¼åºå ã®Cloudformationã¹ã¿ãã¯ããåãã弿°ã®ãã¡ããããã¤ããCloudformationã¹ã¿ãã¯ã®å¼æ°ã¨ãã¦ä½¿ç¨ããªããã¼ config = { "ExcludeKeys": ["ServiceToken", "StackName", "CfnTplS3Bucket", "CfnTplS3Key", "IsSkip"] } # ãããã¤ããCloudformationãã³ãã¬ã¼ããç´æ¥ã³ã¼ãã«è¨è¿°ãããå ´åã¯ããã«è¨è¿° fixed_cfn_template = ''' ''' # us-east-1ãªã¼ã¸ã§ã³ã«Cloudformationã¹ã¿ãã¯ããããã¤ããã¯ã©ã¤ã¢ã³ã cfn_client = boto3.client('cloudformation', region_name='us-east-1') # Cloudformationãã³ãã¬ã¼ããåå¾ããS3ãªã½ã¼ã¹ s3_resource = boto3.resource('s3') # ã«ã¹ã¿ã ãªã½ã¼ã¹ã®ä»æ§ã§CloudFormationã«ã¬ã¹ãã³ã¹ãè¿ãç¬èªã¡ã½ãã # CloudFormationã¹ã¿ãã¯ããå¼ã³åºãå ´åã¯cfnresponse.sendã使ç¨ã§ããããLambdaåä½ã§ã®å®è¡ã«ã¯ä½¿ç¨ã§ããªãããç¬èªã¡ã½ããã使ç¨ãã def cfn_response_send(event, context, response_status, response_data, physical_resource_id=None, no_echo=False, reason=None): response_url = event['ResponseURL'] print(response_url) response_body = { 'Status': response_status, 'Reason': reason or 'See the details in CloudWatch Log Stream: {}'.format(context.log_stream_name), 'PhysicalResourceId': physical_resource_id or context.log_stream_name, 'StackId': event['StackId'], 'RequestId': event['RequestId'], 'LogicalResourceId': event['LogicalResourceId'], 'NoEcho': no_echo, 'Data': response_data } json_response_body = json.dumps(response_body) print('Response body:') print(json_response_body) headers = { 'content-type': '', 'content-length': str(len(json_response_body)) } try: response = http.request('PUT', response_url, headers=headers, body=json_response_body) print('Status code:', response.status) except Exception as e: print('cfn_response_send(..) failed executing http.request(..):', e) def lambda_handler(event, context): response_data = {} try: print(('event:' + json.dumps(event, indent=2))) resource_properties = event['ResourceProperties'] is_skip = resource_properties.get('IsSkip') # IsSkipã«trueãå ¥ã£ã¦ããå ´åã¯ä½ãå¦çãã空ã®ã¬ã¹ãã³ã¹ãè¿ã # å¼åºå ã§ã«ã¹ã¿ã ãªã½ã¼ã¹å¦çãã¹ãããããå ´åã«ä½¿ç¨ãã if is_skip is not None and is_skip.strip().lower() == 'true': print('Skip All Process.') cfn_response_send(event, context, SUCCESS, response_data) # cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) return stack_name = resource_properties.get('StackName') exclude_keys = config['ExcludeKeys'] cfn_params = [] for key, val in resource_properties.items(): if key not in exclude_keys: cfn_params.append({ 'ParameterKey': key, 'ParameterValue': val }) print('----------[Start]cfn_params:----------') print(cfn_params) print('----------[End]cfn_params:------------') cfn_template = fixed_cfn_template try: # fixed_cfn_template夿°ã«ç´æ¥ãã³ãã¬ã¼ããè¨è¿°ãã¦ããªãå ´åã¯æå®ãããS3ãã±ããã®ãªãã¸ã§ã¯ããããã³ãã¬ã¼ããåå¾ãã if cfn_template.strip() == '': cfn_tpl_s3_bucket = resource_properties['CfnTplS3Bucket'] cfn_tpl_s3_key = resource_properties['CfnTplS3Key'] bucket = s3_resource.Bucket(cfn_tpl_s3_bucket) obj = bucket.Object(cfn_tpl_s3_key).get() cfn_template = obj['Body'].read().decode('utf-8') print('----------[Start]cfn_template:----------') print(cfn_template) print('----------[End]cfn_template:------------') except Exception as e: print('lambda_handler(..) failed executing read s3 obj(..):', e) raise if event['RequestType'] == 'Delete': try: print('Delete Stacks') # Deleteå¦çã®å ´åã¯åç´ã«åé¤ãã print('Run cfn_client.delete_stack.') response = cfn_client.delete_stack( StackName=stack_name ) print('cfn_client.delete_stack response:') print(response) # ã¹ã¿ãã¯ã®Deleteå¦çãå®äºããã¾ã§å¾ 㤠waiter = cfn_client.get_waiter('stack_delete_complete') waiter.wait(StackName=stack_name) except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as err: err_msg = str(err) print('err_msg:') print(err_msg) #ç¸äºã«é¢é£ä»ããããªã½ã¼ã¹å士ã§åé¤ã¨ã©ã¼ã®ã«ã¼ããçºçãããããä¾å¤ã¯ä¸ããªãã if event['RequestType'] == 'Create' or event['RequestType'] == 'Update': # Createå¦çã¨Updateå¦çã®å®è¡æ¹é # Createå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ããªã â Createå¦ç # Createå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ãã â ä½ãããªã # Updateå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ããªã â Createå¦ç # Updateå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ãããã¤å¤æ´ç¹ãåå¨ãã â Updateå¦ç # Updateå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ãããã¤å¤æ´ç¹ãåå¨ããªã â ä½ãããªã # ååã®ã¹ã¿ãã¯ãåå¨ãããã示ããã©ã° exist_stack = False try: print('Run cfn_client.describe_stacks.') existing_stacks = cfn_client.describe_stacks(StackName=stack_name) print('Existing Stacks:') print(existing_stacks) # ã¹ã¿ãã¯ãåå¨ããdescribe_stacksãæ£å¸¸ã«å¦çãããã°exist_stackã¯True exist_stack = True except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as err: err_msg = str(err) print('err_msg:') print(err_msg) # ã¹ã¿ãã¯ãåå¨ãããdescribe_stacksãã¨ã©ã¼ã«ãªãã°exist_stackã¯False if 'DescribeStack' in err_msg and 'does not exist' in err_msg: print(('describe_stacks error: ' + err_msg)) exist_stack = False else: raise # Createå¦çãå¿ è¦ãã示ããã©ã° need_create = True if event['RequestType'] == 'Update': print('Update Stacks') if exist_stack == False: # Updateå¦çãã¤ã¹ã¿ãã¯ãåå¨ããªãå ´åã¯Createå¦çã§ã¹ã¿ãã¯ã使ãã need_create = True else: # Createå¦çãå¿ è¦ãã©ããã示ããã©ã° need_create = False # ãã§ã«ã¹ã¿ãã¯åã«ä¸è´ããã¹ã¿ãã¯ãåå¨ããã°Updateã§å¦çãã try: print('Run cfn_client.update_stack.') response = cfn_client.update_stack( StackName=stack_name, TemplateBody=cfn_template, Parameters=cfn_params, Capabilities=[ 'CAPABILITY_NAMED_IAM' ] ) print('cfn_client.update_stack response:') print(response) # ã¹ã¿ãã¯ã®Updateå¦çãå®äºããã¾ã§å¾ 㤠waiter = cfn_client.get_waiter('stack_update_complete') waiter.wait(StackName=stack_name) except (botocore.exceptions.ValidationError, botocore.exceptions.ClientError) as err: err_msg = str(err) print('err_msg:') print(err_msg) # Updateå¦çãè¦æ±ããããã夿´ç¹ããªãå ´åã¯ä½ãããªã if 'UpdateStack' in err_msg and 'No updates are to be performed' in err_msg: print(('update_stacks error: ' + err_msg)) else: raise if event['RequestType'] == 'Create' or need_create == True: print('Create Stacks') # Createå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ããªãå ´åãã¾ãã¯Updateå¦çè¦æ±ãã¤ã¹ã¿ãã¯ãåå¨ããªãå ´åã«ã¹ã¿ãã¯ãCreateå¦çãã if exist_stack == False: print('Run cfn_client.create_stack.') response = cfn_client.create_stack( StackName=stack_name, TemplateBody=cfn_template, Parameters=cfn_params, Capabilities=[ 'CAPABILITY_NAMED_IAM' ] ) print('cfn_client.create_stack response:') print(response) # ã¹ã¿ãã¯ã®Createå¦çãå®äºããã¾ã§å¾ 㤠waiter = cfn_client.get_waiter('stack_create_complete') waiter.wait(StackName=stack_name) # Createã¾ãã¯Updateãããã¹ã¿ãã¯ãåå¾ãã stacks = cfn_client.describe_stacks(StackName=stack_name) # Outputsã®å 容ãåå¾ããè¿å´å¤ã¨ãã¦æ´å½¢ãã outputs = stacks['Stacks'][0]['Outputs'] print(('Outputs:' + json.dumps(outputs, indent=2))) for output in outputs: response_data[output['OutputKey']] = output['OutputValue'] print(('Outputs:' + json.dumps(response_data, indent=2))) # CloudFormationã«ã¹ã¿ã ãªã½ã¼ã¹ä»æ§ã§å¼åºå ã®ã¹ã¿ãã¯ã«ã¬ã¹ãã³ã¹ãè¿ã cfn_response_send(event, context, SUCCESS, response_data) # cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) return except Exception as e: print('Exception:') print(e) # CloudFormationã«ã¹ã¿ã ãªã½ã¼ã¹ä»æ§ã§å¼åºå ã®ã¹ã¿ãã¯ã«ã¬ã¹ãã³ã¹ãè¿ã cfn_response_send(event, context, FAILED, response_data) # cfnresponse.send(event, context, cfnresponse.FAILED, response_data) return
AWS Lambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã«æ¸¡ãããå¼åºå Cloudformationã¹ã¿ãã¯ããã®å¼æ°ã«ã¤ãã¦
ä¸è¨ã®ã«ã¹ã¿ã ãªã½ã¼ã¹ã«æ¸¡ãããå¼åºå Cloudformationã¹ã¿ãã¯ããã®å¼æ°ã¯æ¬¡ã®ãããªãã©ã¼ããããæ³å®ãã¦ãã¾ãã
{ "RequestType": "Create", "ResponseURL": "http://pre-signed-S3-url-for-response", "StackId": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/stack-name/guid", "RequestId": "unique id for this create request", "ResourceType": "Custom::TestResource", "LogicalResourceId": "MyTestResource", "ResourceProperties": { "ServiceToken": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:CustomResourceToDeployCloudformationStack", "StackName": "CustomResourceToDeployCloudformationStackDemo", "CfnTplS3Bucket": "ï¼ãããã¤ããCloudformationãã³ãã¬ã¼ããæ ¼ç´ããS3ãã±ããåï¼", "CfnTplS3Key": "ï¼ãããã¤ããCloudformationãã³ãã¬ã¼ãã®S3ãã±ããå以éã®ãªãã¸ã§ã¯ããã¼ï¼", "IsSkip": "ï¼Cloudformationãã³ãã¬ã¼ãã®ãããã¤å¦çãã¹ããããããã©ããã示ããã©ã°ï¼", "ï¼ãããã¤ããã¹ã¿ãã¯ã¸æ¸¡ããã¼1ï¼": "ï¼ãããã¤ããã¹ã¿ãã¯ã¸æ¸¡ãå¤1ï¼", "ï¼ãããã¤ããã¹ã¿ãã¯ã¸æ¸¡ããã¼2ï¼": "ï¼ãããã¤ããã¹ã¿ãã¯ã¸æ¸¡ãå¤2ï¼", ï½çç¥ï½ } }
ãã®ãã©ã¼ãããã®ãã¡ã«ã¹ã¿ã ãªã½ã¼ã¹ã使ç¨ããããã«å¼åºå ã¹ã¿ãã¯ã§è¨å®ããå¿ è¦ãããã®ã¯æ¬¡ã®å¼æ°ã§ãã
- StackName
ã«ã¹ã¿ã ãªã½ã¼ã¹ããå¥ãªã¼ã¸ã§ã³ã«ãããã¤ããCloudformationã¹ã¿ãã¯ã®åç§°ã§ãã - CfnTplS3Bucket
ã«ã¹ã¿ã ãªã½ã¼ã¹ããå¥ãªã¼ã¸ã§ã³ã«ãããã¤ããCloudformationãã³ãã¬ã¼ããS3ã«æ ¼ç´ããå ´åã®ãã±ããåã§ãã - CfnTplS3Key
ã«ã¹ã¿ã ãªã½ã¼ã¹ããå¥ãªã¼ã¸ã§ã³ã«ãããã¤ããCloudformationãã³ãã¬ã¼ããS3ã«æ ¼ç´ããå ´åã®ãã±ããå以éã®ãã¼ã§ãã - IsSkip
ã«ã¹ã¿ã ãªã½ã¼ã¹ããå¥ãªã¼ã¸ã§ã³ã¸ã®Cloudformationãã³ãã¬ã¼ããããã¤å¦çãã¹ãããããå ´åã«ä½¿ç¨ãã¾ããtrueã®å ´åã¯å¦çãå®è¡ããã¹ããããã¾ãã - ï¼ãããã¤ããã¹ã¿ãã¯ã¸æ¸¡ããã¼Xï¼
ã«ã¹ã¿ã ãªã½ã¼ã¹ããå¥ãªã¼ã¸ã§ã³ã«ãããã¤ããCloudformationãã³ãã¬ã¼ãã«ããã弿°ã§ããä»åå®è£ ããã«ã¹ã¿ã ãªã½ã¼ã¹ã§ã¯
"ServiceToken","StackName","CfnTplS3Bucket","CfnTplS3Key","IsSkip"
以å¤ã«æ¸¡ããã¦ãã弿°ã¯ãã¹ã¦ãããã¤ããCloudformationãã³ãã¬ã¼ãã«å¼æ°ã¨ãã¦æ¸¡ãã¾ãããã®ãããå¼åºå ã§ã¯ä½è¨ãªå¼æ°ã渡ããªãããã«æ³¨æãå¿ è¦ã§ãã
åèï¼
ã«ã¹ã¿ã ãªã½ã¼ã¹ - AWS CloudFormation
What is AWS CloudFormation? - AWS CloudFormation
Tech Blog with related articles referenced
AWS CloudFormation Templates and AWS Lambda Custom Resources for Associating AWS Certificate Manager, Lambda@Edge, and AWS WAF with a Website on Amazon S3 and Amazon CloudFront Cross-Region
Deploy AWS Cloudformation Stack Cross-Region with AWS Lambda Custom Resources
ã¾ã¨ã
ä»åã¯ä¸»ã«us-east-1以å¤ã®ãªã¼ã¸ã§ã³ã®CloudFormationã¹ã¿ãã¯ããå¼ã³åºãã¦ãus-east-1ã«CloudFormationã¹ã¿ãã¯ããããã¤ããLambdaã«ã¹ã¿ã ãªã½ã¼ã¹ã使ãã¦ã¿ã¾ããã
次åã¯ãã®ã«ã¹ã¿ã ãªã½ã¼ã¹ã使ç¨ãã¦å®éã«ãªã½ã¼ã¹ããããã¤ããä¾ãç´¹ä»ãããã¨æãã¾ãã
