【问题标题】:How to get selective item when AWS::CustomResource has list type output当 AWS::CustomResource 具有列表类型输出时如何获取选择性项目
【发布时间】:2020-06-26 00:46:22
【问题描述】:

我正在尝试在 Cloudformation 模板中创建 AWS 自定义资源以检索 MSK 代理 DNS 详细信息。

下面是我的示例 lambda 代码:

import json
import logging
import boto3
import subprocess
import shlex
import os
import time
from hashlib import md5
from crhelper import CfnResource
from time import sleep

logger = logging.getLogger(__name__)
helper = CfnResource(json_logging=True, log_level='DEBUG')




@helper.create
@helper.update
def create_handler(event, _):
    print('Received event: %s' % json.dumps(event))
    retry_timeout = 0
    if "Timeout" in event['ResourceProperties']:
        retry_timeout = int(event['ResourceProperties']["Timeout"])
    if retry_timeout > 600:
        retry_timeout = 600
    MskArn = event['ResourceProperties']['MskArn']
    kafkaClient = boto3.client('kafka', region_name=event['ResourceProperties']['aws-region'])
    while True:
        try:
            response = kafkaClient.list_nodes(
                ClusterArn=event['ResourceProperties']['MskArn']
            )
            r1=response['NodeInfoList']
            BrokerCount=len(r1)
            i = 0
            DNS=[]
            name = event['ResourceProperties']['Name']
            while i < BrokerCount:
                broker=response['NodeInfoList'][i]
                brokerDNS=broker['BrokerNodeInfo']['Endpoints'][0]
                DNS.append(brokerDNS)
                print(brokerDNS)
                i = i + 1
            return DNS
            outp = DNS
            break
        except Exception as e:
            if retry_timeout < 1:
                raise
            else:
                logging.error('Exception: %s' % e, exc_info=True)
                print("retrying until timeout...")
                time.sleep(5)
                retry_timeout = retry_timeout - 5
    response_data = {}
    if "ResponseKey" in event['ResourceProperties']:
        response_data[event['ResourceProperties']["ResponseKey"]] = outp
    if len(outp.encode('utf-8')) > 1000:
        outp = 'MD5-' + str(md5(outp.encode('utf-8')).hexdigest())
    helper.Data.update(response_data)
    return outp


def lambda_handler(event, context):
    helper(event, context)
    print(response_data)

以下是我的示例 AWS Cloudformation 模板:

---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'To Get MSK Broker DNS CloudFormation Template'
Resources:
  GetMskBrokersDetails:
    Type: "Custom::GetMskDetails"
    Version: '1.0'
    Properties:
      Name: GetMskBrokerDNS
      ServiceToken: LAMBDA_ARN
      aws-region: !Sub "${AWS::Region}"
      MskArn: MSK_CLUSTER_ARN

Outputs:
  MskBrokerDns1:
    Description: Msk Broker DNS Records
    Value: !Ref GetMskBrokersDetails

以上工作正常。当我执行上述模板时,它会给出以下输出。

MskBrokerDns1   ['b-1.kafka.ap-south-1.amazonaws.com', 'b-2.kafka.ap-south-1.amazonaws.com']

由于上面的输出是列表,我们希望在两个单独的输出变量中获得上面的 DNS 详细信息。如下:

Outputs:
  MskBrokerDns1:
    Description: Msk Broker DNS Records
    Value: !Select [ 0, !Ref GetMskBrokersDetails ]
  MskBrokerDns2:
    Description: Msk Broker DNS Records
    Value: !Select [ 1, !Ref GetMskBrokersDetails ]

当我们尝试执行具有上述更改的模板时,我们得到以下错误:

模板错误:Fn::Select 需要一个包含两个元素的列表参数:一个整数索引和一个列表

所以我们请求社区支持,我们如何解决上述问题。

【问题讨论】:

  • 不明白你的代码是如何工作的。 ResponseKey 是什么?为什么你同时通过return 语句和helper.Data 返回outpreturn 应该用于返回物理资源 id,而不是一些 python 列表?
  • 我的问题。我对python不太感兴趣。在 Google 的帮助下,我能够更新 python 代码,现在它可以工作了。

标签: python amazon-web-services amazon-cloudformation aws-cloudformation-custom-resource


【解决方案1】:

经过一些尝试和尝试,我们能够得到我们想要的响应。这可能不是有效的方法。 Lambda 代码:

import json
import logging
import boto3
import subprocess
import shlex
import os
import time
from hashlib import md5
from crhelper import CfnResource
from time import sleep

logger = logging.getLogger(__name__)
helper = CfnResource(json_logging=True, log_level='DEBUG')




@helper.create
@helper.update
def create_handler(event, _):
    print('Received event: %s' % json.dumps(event))
    retry_timeout = 0
    if "Timeout" in event['ResourceProperties']:
        retry_timeout = int(event['ResourceProperties']["Timeout"])
    if retry_timeout > 600:
        retry_timeout = 600
    MskArn = event['ResourceProperties']['MskArn']
    kafkaClient = boto3.client('kafka', region_name=event['ResourceProperties']['aws-region'])
    while True:
        try:
            response = kafkaClient.list_nodes(
                ClusterArn=event['ResourceProperties']['MskArn']
            )
            r1=response['NodeInfoList']
            BrokerCount=len(r1)
            i = 0
            DNS=[]
            name = event['ResourceProperties']['Name']
            while i < BrokerCount:
                broker=response['NodeInfoList'][i]
                brokerDNS=broker['BrokerNodeInfo']['Endpoints'][0]
                DNS.append(brokerDNS)
                i = i + 1
            outp = DNS
            break
        except Exception as e:
            if retry_timeout < 1:
                raise
            else:
                logging.error('Exception: %s' % e, exc_info=True)
                print("retrying until timeout...")
                time.sleep(5)
                retry_timeout = retry_timeout - 5
    response_data = {}
    response_data['BrokerDNS1'] = DNS[0]
    response_data['BrokerDNS2'] = DNS[1]
    print(response_data)
    helper.Data.update(response_data)

def lambda_handler(event, context):
    helper(event, context)

以下是 AWS Cloudformation 资源定义:

  GetMskBrokersDetails:
    Type: "Custom::GetMskDetails"
    Version: '1.0'
    Properties:
      Name: GetMskBrokerDNS
      ServiceToken: !Ref MskGetBrokerDnsLambdaArn
      aws-region: !Sub "${AWS::Region}"
      MskArn: !Ref MskCluster
Outputs:
  MskBrokerDns1:
    Description: Msk Broker DNS Records
    Value: !GetAtt GetMskBrokersDetails.BrokerDNS1
  MskBrokerDns2:
    Description: Msk Broker DNS Records
    Value: !GetAtt GetMskBrokersDetails.BrokerDNS2

【讨论】:

  • 是的,现在它更有意义了。这就是应该使用response_data 的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-23
  • 2017-08-12
  • 1970-01-01
相关资源
最近更新 更多