前回、AWS CloudFormation(CFn)のLambda-BackedカスタムリソースでネストされたJSONを返しても!GetAtt
で参照できないことがわかったのですが、よくよく調べてみるとネストで返せそうだったのでさらに調べてみました。
AWS CloudFormationのLambda-BackedカスタムリソースでネストされたJSONを返しても参照できない – Qiita
https://cloudpack.media/48318
結論
import cfnresponse def handler(event, context): data = { "hoge": "hoge", "foo.hoge": "hoge" } cfnresponse.send(event, context, cfnresponse.SUCCESS, data)
ってするとそれっぽくなります。(白目
調べたこと
CFnのGetAtt
関数ドキュメントにあるテンプレート例でSourceSecurityGroupOwnerId: !GetAtt myELB.SourceSecurityGroup.GroupName
とmyELB
リソースに対してネストされてる(っぽい)値SourceSecurityGroup.GroupName
を参照しているのをみつけました。
Fn::GetAtt – AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html
LoadBalancerのドキュメントをみると戻り値として確かにSourceSecurityGroup.GroupName
は定義されています。
AWS::ElasticLoadBalancing::LoadBalancer – AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb.html#aws-properties-ec2-elb-ref
通常のリソースの場合はネストされた情報が取り扱えるのでしょうか?
GetAttドキュメントの属性を確認すると、コンマ区切りで定義されている項目が確認できます。
Fn::GetAtt – AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html#intrinsic-function-reference-getatt-attrib
Lambda-Backedカスタムリソースでネストされてるっぽくしてみる
Lambda-Backedカスタムリソースでも同じように参照できるレスポンスデータの返し方を考えてみました。
テンプレート定義
Lambda関数でフラットなJSONを返しますが、名前をfoo.hoge
とします(安直)。
cfn-template.yaml
Resources: CustomResource: Type: Custom::CustomResource Properties: ServiceToken: !GetAtt CustomResourceFunction.Arn CustomResourceFunction: Type: AWS::Lambda::Function Properties: Handler: index.handler Role: !GetAtt FunctionExecutionRole.Arn Code: ZipFile: !Sub | import cfnresponse def handler(event, context): data = { "hoge": "hoge", "foo.hoge": "hoge" } cfnresponse.send(event, context, cfnresponse.SUCCESS, data) Runtime: python3.7 FunctionExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: root PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "arn:aws:logs:*:*:*" Outputs: hoge: Value: !GetAtt CustomResource.hoge foo: Value: !GetAtt CustomResource.foo.hoge
スタック作成して確認してみる
> aws cloudformation create-stack \ --stack-name cfn-response-test \ --template-body file://cfn-template.yaml \ --capabilities CAPABILITY_IAM { "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/cea96c90-97b7-11e9-b384-0e75601403f8" } > aws cloudformation describe-stacks \ --stack-name cfn-response-test { "Stacks": [ { "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/cea96c90-97b7-11e9-b384-0e75601403f8", "StackName": "cfn-response-test", "CreationTime": "2019-06-26T02:12:11.362Z", "RollbackConfiguration": {}, "StackStatus": "CREATE_COMPLETE", "DisableRollback": false, "NotificationARNs": [], "Capabilities": [ "CAPABILITY_IAM" ], "Outputs": [ { "OutputKey": "hoge", "OutputValue": "hoge" }, { "OutputKey": "foo", "OutputValue": "hoge" } ], "Tags": [], "EnableTerminationProtection": false, "DriftInformation": { "StackDriftStatus": "NOT_CHECKED" } } ] }
無事に!GetAtt CustomResource.foo.hoge
で値が参照できました。
一応関数のログを確認しておきます。
> aws cloudformation list-stack-resources \ --stack-name cfn-response-test { "StackResourceSummaries": [ { "LogicalResourceId": "CustomResource", "PhysicalResourceId": "2019/06/26/[$LATEST]0f6645081f974de7a40c44ac5a6b1493", "ResourceType": "Custom::CustomResource", "LastUpdatedTimestamp": "2019-06-26T02:12:38.029Z", "ResourceStatus": "CREATE_COMPLETE", "DriftInformation": { "StackResourceDriftStatus": "NOT_CHECKED" } }, { "LogicalResourceId": "CustomResourceFunction", "PhysicalResourceId": "cfn-response-test-CustomResourceFunction-RUGERLT0O78L", "ResourceType": "AWS::Lambda::Function", "LastUpdatedTimestamp": "2019-06-26T02:12:33.223Z", "ResourceStatus": "CREATE_COMPLETE", "DriftInformation": { "StackResourceDriftStatus": "NOT_CHECKED" } }, (略) ] } > aws logs get-log-events \ --log-group-name /aws/lambda/cfn-response-test-CustomResourceFunction-RUGERLT0O78L \ --log-stream-name '2019/06/26/[$LATEST]0f6645081f974de7a40c44ac5a6b1493' \ --output=text \ --query "events[*].message" START RequestId: 9fb7a4fa-44b4-49ee-a5b7-bcbc57d40961 Version: $LATEST https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/(略) Response body: {"Status": "SUCCESS", "Reason": "See the details in CloudWatch Log Stream: 2019/06/26/[$LATEST]0f6645081f974de7a40c44ac5a6b1493", "PhysicalResourceId": "2019/06/26/[$LATEST]0f6645081f974de7a40c44ac5a6b1493", "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/cea96c90-97b7-11e9-b384-0e75601403f8", "RequestId": "bc048c80-c2f9-42ab-a596-6e031d8299f3", "LogicalResourceId": "CustomResource", "NoEcho": false, "Data": {"hoge": "hoge", "foo.hoge": "hoge"}} Status code: OK END RequestId: 9fb7a4fa-44b4-49ee-a5b7-bcbc57d40961 REPORT RequestId: 9fb7a4fa-44b4-49ee-a5b7-bcbc57d40961 Duration: 351.55 ms Billed Duration: 400 ms Memory Size: 128 MB Max Memory Used: 24 MB
フラットですがネストされてるっぽく参照できるData
を返していることが確認できます。
まとめ
微妙に納得できない感じですが、テンプレートでどうしてもリソース情報のネスト構造を維持したまま参照したい場合にLambda-Backedカスタムリソース側で吸収するのに使えそうです。
参考
AWS CloudFormationのLambda-BackedカスタムリソースでネストされたJSONを返しても参照できない – Qiita
https://cloudpack.media/48318
Fn::GetAtt – AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html
AWS::ElasticLoadBalancing::LoadBalancer – AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb.html#aws-properties-ec2-elb-ref
元記事はこちら
「AWS CloudFormationのLambda-BackedカスタムリソースでネストされてるっぽいJSONを返す方法」