2

I am trying to fetch the CloudFormation stack details using boto3 as below

import boto3
import json

def lambda_handler(event, context):
    global cnfOutput
    cnfOutput = cfn1.describe_stacks(StackName='cfn-init-stack1')
    cnf2 = json.dumps(cnfOutput)
    return cnf2

Below is the output I get if I print cfnOutput. I tried to do json.dumps and getting the error. Please need help

{u'Stacks': [{u'StackId': 'arn:aws:cloudformation:us-west-2:123456789123:stack/cfn-init-stack1/d209-11e8-b83e-0ad6ed005066', u'Description': 'CloudFormation template for creating an ec2 instance', u'Parameters': [{u'ParameterValue': 'e1', u'ParameterKey': 'KeyName'}, {u'ParameterValue': 'ami-a0cfeed8', u'ParameterKey': 'ImageId'}, {u'ParameterValue': 't2.micro', u'ParameterKey': 'InstanceType'}], u'Tags': [], u'Outputs': [{u'Description': 'The public name of the EC2 instance.', u'OutputKey': 'PublicName', u'OutputValue': 'ec2-51-111-211-211.us-west-2.compute.amazonaws.com'}], u'RoleARN': 'arn:aws:iam::123456789123:role/CFN1-role', u'EnableTerminationProtection': False, u'CreationTime': datetime.datetime(2018, 10, 17, 12, 40, 10, 783000, tzinfo=tzlocal()), u'StackName': 'cfn-init-stack1', u'NotificationARNs': ['arn:aws:sns:us-west-2:123456789123:topic2'], u'StackStatus': 'CREATE_COMPLETE', u'DisableRollback': False, u'RollbackConfiguration': {u'RollbackTriggers': []}}], 'ResponseMetadata': {'RetryAttempts': 0, 'HTTPStatusCode': 200, 'RequestId': 'd20e-11e8-b15b-a11f0bf7ba', 'HTTPHeaders': {'x-amzn-requestid': 'd20e-11e8-b15b-a11f0bf7ba', 'date': 'Wed, 17 Oct 2018 13:13:11 GMT', 'content-length': '2010', 'content-type': 'text/xml'}}}

Getting below error

File "/usr/lib64/python2.7/json/encoder.py", line 184, in default raise TypeError(repr(o) + " is not JSON serializable") TypeError: datetime.datetime(2018, 10, 17, 12, 40, 10, 783000, tzinfo=tzlocal()) is not JSON serializable

1 Answer 1

2

How to convert the original dictionary to JSON

The following ran for me without issues:

j = json.dumps({"key": str(datetime.datetime(2017, 10, 12, 12, 40, 10, 783000))})

However, when I ran it as:

j = json.dumps({"key": datetime.datetime(2017, 10, 12, 12, 40, 10, 783000)})

I got the same error as you.

If you can convert the result of datetime.datetime(2018, 10, 17, 12, 40, 10, 783000, tzinfo=tzlocal()) to a string before calling json.dumps, it should fix your issue.

How to extract OutputValue from original dictionary

# d is your original dictionary
# after you convert the datetime.datetime() result to string
d = {
    u'Stacks': [{
        u'StackId': 'arn:aws:cloudformation:us-west-2:123456789123:stack/cfn-init-stack1/d209-11e8-b83e-0ad6ed005066', 
        u'Description': 'CloudFormation template for creating an ec2 instance', u'Parameters': [{
            u'ParameterValue': 'e1', u'ParameterKey': 'KeyName'
        }, {
            u'ParameterValue': 'ami-a0cfeed8', u'ParameterKey': 'ImageId'
        }, {
            u'ParameterValue': 't2.micro', u'ParameterKey': 'InstanceType'
        }], u'Tags': [], u'Outputs': [{
            u'Description': 'The public name of the EC2 instance.', u'OutputKey': 'PublicName', u'OutputValue': 'ec2-51-111-211-211.us-west-2.compute.amazonaws.com'
        }], u'RoleARN': 'arn:aws:iam::123456789123:role/CFN1-role', u'EnableTerminationProtection': False, u'CreationTime': str(datetime.datetime(2018, 10, 17, 12, 40, 10, 783000)), u'StackName': 'cfn-init-stack1', u'NotificationARNs': ['arn:aws:sns:us-west-2:123456789123:topic2'], u'StackStatus': 'CREATE_COMPLETE', u'DisableRollback': False, u'RollbackConfiguration': {
            u'RollbackTriggers': []
        }
    }], 
    'ResponseMetadata': {
        'RetryAttempts': 0,
        'HTTPStatusCode': 200,
        'RequestId': 'd20e-11e8-b15b-a11f0bf7ba',
        'HTTPHeaders': {
            'x-amzn-requestid': 'd20e-11e8-b15b-a11f0bf7ba',
            'date': 'Wed, 17 Oct 2018 13:13:11 GMT',
            'content-length': '2010',
            'content-type': 'text/xml'
        }
    }
}

stacks = d.get("Stacks")

if stacks == None:
    print("Key not in dictionary")
else:
    for s in stacks:
        outputs = s.get("Outputs")
        if outputs == None:
            continue

        for o in outputs:
            print(o.get("OutputValue"))

Output for me is ec2-51-111-211-211.us-west-2.compute.amazonaws.com when using the dictionary in your question (after converting datetime.datetime() result to a string but before converting the whole dictionary to JSON).

Sign up to request clarification or add additional context in comments.

4 Comments

I want to extract the "OutputValue" from the above after converting the output to json. So please tell me how to do it.
When you convert your dictionary to JSON then it will a string object and therefore it will be better if you extracted the value first and then converted it to JSON.
I'm not sure if the above is what you were looking for but have a look. In your cfn1.describe_stacks method, try to return the results of datetime.datetime() within your dictionary as a string. If you can do that then the above is how you can extract "OutputValue"
I would convert using datetime.strftime(DATETIME_FORMAT). This will allow deconverting use datetime.strptime(DATETIME_FORMAT). docs.python.org/3/library/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.