Search code examples
amazon-web-servicesaws-lambdaaws-cloudformationaws-cloudformation-custom-resource

exporting outputs in cloudformation using custom resources with lambda


I ran a CFN template using custom resources to export route53 private hosted zone name. I was able to export the hostedzonename as I wanted but I can not import this hostedzonename into another stack. I get this error:

Value of property HostedZoneName must be of type String

Any help is appreciated. thank you. here is my code.

AWSTemplateFormatVersion: 2010-09-09
Description: CloudFormation exports


Resources:
  LambdaExecutionRole:
    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"
            - "route53:Get*"
            - "route53:List*"
            - "route53:TestDNSAnswer"
            Resource: "*"
  GetCertARN: 
    Type: "AWS::Lambda::Function"
    DeletionPolicy: Delete
    DependsOn:
      - LambdaExecutionRole
    Properties: 
      Handler: "index.handler"
      Role: 
        Fn::GetAtt: 
          - "LambdaExecutionRole"
          - "Arn"
      Runtime: "python3.7"
      MemorySize: 128
      Timeout: 100
      Code: 
        ZipFile: |
          import boto3
          import botocore
          import cfnresponse
          route53 = boto3.client('route53')
          def handler(event, context):
            hostedZoneName=''
            response2 = route53.list_hosted_zones()
            f=response2['HostedZones']
            for zone in f:
                config=zone["Config"]
                name=zone["Name"]
                e=config["PrivateZone"]
                if ('abcxyz.cloud' in name) and e:
                    hostedZoneName=name
            responseData = {}
            responseData['hostedzonename'] = hostedZoneName
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
  CertArnInvocation:
    Type: Custom::CertArn
    Properties:
      ServiceToken: !GetAtt GetCertARN.Arn
      Region: !Ref "AWS::Region"

Outputs:
  ExportsStackName:
    Value: !Ref 'AWS::StackName'
    Export:
      Name: !Sub '${AWS::StackName}'

  HostedZoneNameOutput: 
    Value: !GetAtt CertArnInvocation.hostedzonename
    Description: Return Value of private hosted zone name
    Export: 
      Name: !Sub 'nonProdHostedZoneName'

Solution

  • You are exporting HostedZoneNameOutput under name of nonProdHostedZoneName:

        Export: 
          Name: !Sub 'nonProdHostedZoneName'
    

    But it seams that you are importing (not-shown) value called HostedZoneName.

    Update based on comments (HostedZoneName was list, not string). Corrected version:

    HostedZoneName: !ImportValue nonProdHostedZoneName