darthguinea
darthguinea

Reputation: 115

boto3 python change_resource_record_sets

I am trying to use boto3 to create a new DNS record, however I seem to be getting back a pretty ambiguous error back. I have played around with some of the parameters from:

https://boto3.readthedocs.io/en/develop/reference/services/route53.html#Route53.Client.change_resource_record_sets

I have searched for examples of this but have not been able to find any.

    [12/01/2017 09:57:12] [INFO]: get_zone_data found zone [{u'ResourceRecordSetCount': 11, u'CallerReference': 
    '6A78SD-88E9-11F7-B1C6-A8S7DAS8D7',
     u'Config': {u'PrivateZone': False}, u'Id': '/hostedzone/ASD678ASD78', u'Name': 'test.mydomain.com.'}]
    Traceback (most recent call last):
      File "example.py", line 6, in <module>
        dns.add(name='hurried.me')
      File "scale/scale/net/dns.py", line 99, in add
client.change_resource_record_sets(**params)
      File "/usr/local/lib/python2.7/site-packages/botocore/client.py", line 251, in _api_call
        return self._make_api_call(operation_name, kwargs)
      File "/usr/local/lib/python2.7/site-packages/botocore/client.py", line 537, in _make_api_call
        raise ClientError(parsed_response, operation_name)
    botocore.exceptions.ClientError: An error occurred (InvalidInput) when calling the ChangeResourceRecordSets operation: Invalid request

My code:

    def add(self, name=None,
            type='A',
            location='172.32.0.1',
            weight=10,
            ttl=10,
            private=False,
            ):

    zone = self.get_zone_data(name, private)
                        #'Weight': weight,

    params = {
        'HostedZoneId': 'C0P6YPA54A',
        'ChangeBatch': {
            'Changes': [{
                'Action': 'CREATE',
                    'ResourceRecordSet': {
                        'Name': 'test.mydomain.com',
                        'Type': 'A',
                        'TTL': 300,
                    }
                },]
        }
    }

    client = self.session.client('route53')
    client.change_resource_record_sets(**params)

Upvotes: 4

Views: 8119

Answers (2)

user3389126
user3389126

Reputation: 11

Add search for hosted zone

#!/usr/bin/python3
#
import boto3
import argparse


client = boto3.client('route53')

TYPE = ['CNAME',
        'TXT',
        'MX',
        'A']

ACTION = ['CREATE',
          'DELETE',
          'UPSERT']

def add_cname_record(Domain, Name, value, action, type, ttl):
    try:
        zones = client.list_hosted_zones_by_name(DNSName=Domain)
        if not zones or len(zones['HostedZones']) == 0:
            raise Exception("Could not find DNS zone to update")
        zone_id = zones['HostedZones'][0]['Id']
        response = client.change_resource_record_sets(
        HostedZoneId=zone_id,
        ChangeBatch= {
                        'Comment': 'add %s -> %s' % (Name, value),
                        'Changes': [
                            {
                             'Action': action,
                             'ResourceRecordSet': {
                                 'Name': Name + "." + Domain,
                                 'Type': type,
                                 'TTL': ttl,
                                 'ResourceRecords': [{'Value': value}]
                            }
                        }]
        })
    except Exception as e:
        print(e)

def main():
    parser = argparse.ArgumentParser(description='Create DNS records on R53')

    parser.add_argument('-d', '--Domain', required=True, type=str)
    parser.add_argument('-n', '--Name', required=True, type=str)
    parser.add_argument('-t', '--Type', choices=TYPE, required=True, type=str)
    parser.add_argument('-v', '--value', required=True)
    parser.add_argument('-a', '--action', choices=ACTION, required=True)
    parser.add_argument('--ttl', default=300, type=int)

    args = parser.parse_args()

    add_cname_record(args.Domain, args.Name, args.value, args.action, args.Type, args.ttl)

if __name__ == "__main__":
    main()
#
}

Upvotes: -1

RubenVS
RubenVS

Reputation: 81

the ResourceRecordset is incomplete, you will also need to specify:

'ResourceRecords': [{'Value': value}] 

(add it after the ttl)

If you don'y do this you're basically trying to create a record without a destination. I would also suggest you work with variables in the ResourceRecordset to make it easier to use it for a variety of actions!

I currently do it like this:

import boto3
import argparse


client = boto3.client('route53')

TYPE = ['CNAME',
        'A']

ACTION = ['CREATE',
          'DELETE',
          'UPSERT']

def add_cname_record(Name, value, action, type, ttl):
    try:
        response = client.change_resource_record_sets(
        HostedZoneId='<HOSTEDZONE>',
        ChangeBatch= {
                        'Comment': 'add %s -> %s' % (Name, value),
                        'Changes': [
                            {
                             'Action': action,
                             'ResourceRecordSet': {
                                 'Name': Name,
                                 'Type': type,
                                 'TTL': ttl,
                                 'ResourceRecords': [{'Value': value}]
                            }
                        }]
        })
    except Exception as e:
        print(e)

def main():
    parser = argparse.ArgumentParser(description='Create DNS records on R53')

    parser.add_argument('-N', '--Name', required=True, type=str)
    parser.add_argument('-T', '--Type', choices=TYPE, required=True, type=str)
    parser.add_argument('-v', '--value', required=True)
    parser.add_argument('-a', '--action', choices=ACTION, required=True)
    parser.add_argument('-t', '--ttl', default=300, type=int)

    args = parser.parse_args()

    add_cname_record(args.Name, args.value, args.action, args.Type, args.ttl)

if __name__ == "__main__":
    main()

Upvotes: 8

Related Questions