mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2024-09-14 20:13:21 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			257 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
	
		
			7.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| # This file is part of Ansible
 | |
| #
 | |
| # Ansible is free software: you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License as published by
 | |
| # the Free Software Foundation, either version 3 of the License, or
 | |
| # (at your option) any later version.
 | |
| #
 | |
| # Ansible is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| # GNU General Public License for more details.
 | |
| #
 | |
| # You should have received a copy of the GNU General Public License
 | |
| # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| DOCUMENTATION = '''
 | |
| ---
 | |
| module: route53
 | |
| version_added: "1.3"
 | |
| short_description: add or delete entries in Amazons Route53 DNS service
 | |
| description:
 | |
|      - Creates and deletes DNS records in Amazons Route53 service
 | |
| options:
 | |
|   command:
 | |
|     description:
 | |
|       - Specifies the action to take.  
 | |
|     required: true
 | |
|     default: null
 | |
|     aliases: []
 | |
|     choices: [ 'get', 'create', 'delete' ]
 | |
|   zone:
 | |
|     description:
 | |
|       - The DNS zone to modify
 | |
|     required: true
 | |
|     default: null
 | |
|     aliases: []
 | |
|   record:
 | |
|     description:
 | |
|       - The full DNS record to create or delete
 | |
|     required: true
 | |
|     default: null
 | |
|     aliases: []
 | |
|   ttl:
 | |
|     description:
 | |
|       - The TTL to give the new record
 | |
|     required: false
 | |
|     default: 3600 (one hour)
 | |
|     aliases: []
 | |
|   type:
 | |
|     description:
 | |
|       - The type of DNS record to create
 | |
|     required: true
 | |
|     default: null
 | |
|     aliases: []
 | |
|     choices: [ 'A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS' ]
 | |
|   value:
 | |
|     description:
 | |
|       - The new value when creating a DNS record.  Multiple comma-spaced values are allowed.  When deleting a record all values for the record must be specified or Route53 will not delete it.
 | |
|     required: false
 | |
|     default: null
 | |
|     aliases: []
 | |
|   aws_secret_key:
 | |
|     description:
 | |
|       - AWS secret key. 
 | |
|     required: false
 | |
|     default: null
 | |
|     aliases: ['ec2_secret_key', 'secret_key']
 | |
|   aws_access_key:
 | |
|     description:
 | |
|       - AWS access key. 
 | |
|     required: false
 | |
|     default: null
 | |
|     aliases: ['ec2_access_key', 'access_key']
 | |
|   overwrite:
 | |
|     description:
 | |
|       - Whether an existing record should be overwritten on create if values do not match
 | |
|     required: false
 | |
|     default: null
 | |
|     aliases: []
 | |
| requirements: [ "boto" ]
 | |
| author: Bruce Pennypacker
 | |
| '''
 | |
| 
 | |
| EXAMPLES = '''
 | |
| # Add new.foo.com as an A record with 3 IPs
 | |
| - route53: >
 | |
|       command=create
 | |
|       zone=foo.com
 | |
|       record=new.foo.com
 | |
|       type=A
 | |
|       ttl=7200
 | |
|       value=1.1.1.1,2.2.2.2,3.3.3.3
 | |
| 
 | |
| # Retrieve the details for new.foo.com
 | |
| - route53: >
 | |
|       command=get
 | |
|       zone=foo.com
 | |
|       record=new.foo.com
 | |
|       type=A
 | |
|   register: rec
 | |
| 
 | |
| # Delete new.foo.com A record using the results from the get command
 | |
| - route53: >
 | |
|       command=delete
 | |
|       zone=foo.com
 | |
|       record={{ rec.set.record }}
 | |
|       type={{ rec.set.type }}
 | |
|       value={{ rec.set.value }}
 | |
| 
 | |
| # Add an AAAA record.  Note that because there are colons in the value
 | |
| # that the entire parameter list must be quoted:
 | |
| - route53: >
 | |
|       "command=create
 | |
|       zone=foo.com
 | |
|       record=localhost.foo.com
 | |
|       type=AAAA
 | |
|       ttl=7200
 | |
|       value="::1"
 | |
| '''
 | |
| 
 | |
| import sys
 | |
| import time
 | |
| 
 | |
| try:
 | |
|     import boto
 | |
|     from boto import route53
 | |
|     from boto.route53.record import ResourceRecordSets
 | |
| except ImportError:
 | |
|     print "failed=True msg='boto required for this module'"
 | |
|     sys.exit(1)
 | |
| 
 | |
| def commit(changes):
 | |
|     """Commit changes, but retry PriorRequestNotComplete errors."""
 | |
|     retry = 10
 | |
|     while True:
 | |
|         try:
 | |
|             retry -= 1
 | |
|             return changes.commit()
 | |
|         except boto.route53.exception.DNSServerError, e:
 | |
|             code = e.body.split("<Code>")[1]
 | |
|             code = code.split("</Code>")[0]
 | |
|             if code != 'PriorRequestNotComplete' or retry < 0:
 | |
|                 raise e
 | |
|             time.sleep(500)
 | |
| 
 | |
| def main():
 | |
|     module = AnsibleModule(
 | |
|         argument_spec = dict(
 | |
|             command         = dict(choices=['get', 'create', 'delete'], required=True),
 | |
|             zone            = dict(required=True),
 | |
|             record          = dict(required=True),
 | |
|             ttl             = dict(required=False, default=3600),
 | |
|             type            = dict(choices=['A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS'], required=True),
 | |
|             value           = dict(required=False), 
 | |
|             ec2_secret_key  = dict(aliases=['aws_secret_key', 'secret_key'], no_log=True, required=False),
 | |
|             ec2_access_key  = dict(aliases=['aws_access_key', 'access_key'], required=False),
 | |
|             overwrite       = dict(required=False, type='bool')
 | |
|         )
 | |
|     )
 | |
| 
 | |
|     command_in            = module.params.get('command')
 | |
|     zone_in               = module.params.get('zone')
 | |
|     ttl_in                = module.params.get('ttl')
 | |
|     record_in             = module.params.get('record')
 | |
|     type_in               = module.params.get('type')
 | |
|     value_in              = module.params.get('value')
 | |
| 
 | |
|     ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
 | |
| 
 | |
|     value_list = ()
 | |
| 
 | |
|     if type(value_in) is str:
 | |
|         if value_in:
 | |
|             value_list = sorted(value_in.split(','))
 | |
|     elif type(value_in)  is list:
 | |
|         value_list = sorted(value_in)
 | |
| 
 | |
|     if zone_in[-1:] != '.':
 | |
|         zone_in += "."
 | |
| 
 | |
|     if record_in[-1:] != '.':
 | |
|         record_in += "."
 | |
| 
 | |
|     if command_in == 'create' or command_in == 'delete':
 | |
|         if not value_in:
 | |
|             module.fail_json(msg = "parameter 'value' required for create/delete")
 | |
| 
 | |
|     # connect to the route53 endpoint 
 | |
|     try:
 | |
|         conn = boto.route53.connection.Route53Connection(aws_access_key, aws_secret_key)
 | |
|     except boto.exception.BotoServerError, e:
 | |
|         module.fail_json(msg = e.error_message)
 | |
| 
 | |
|     # Get all the existing hosted zones and save their ID's
 | |
|     zones = {}
 | |
|     results = conn.get_all_hosted_zones()
 | |
|     for r53zone in results['ListHostedZonesResponse']['HostedZones']:
 | |
|         zone_id = r53zone['Id'].replace('/hostedzone/', '')
 | |
|         zones[r53zone['Name']] = zone_id
 | |
| 
 | |
|     # Verify that the requested zone is already defined in Route53
 | |
|     if not zone_in in zones:
 | |
|         errmsg = "Zone %s does not exist in Route53" % zone_in
 | |
|         module.fail_json(msg = errmsg)
 | |
| 
 | |
|     record = {}
 | |
|     
 | |
|     found_record = False
 | |
|     sets = conn.get_all_rrsets(zones[zone_in])
 | |
|     for rset in sets:
 | |
|         if rset.type == type_in and rset.name == record_in:
 | |
|             found_record = True
 | |
|             record['zone'] = zone_in
 | |
|             record['type'] = rset.type
 | |
|             record['record'] = rset.name
 | |
|             record['ttl'] = rset.ttl
 | |
|             record['value'] = ','.join(sorted(rset.resource_records))
 | |
|             record['values'] = sorted(rset.resource_records)
 | |
|             if value_list == sorted(rset.resource_records) and record['ttl'] == ttl_in and command_in == 'create':
 | |
|                 module.exit_json(changed=False)
 | |
| 
 | |
|     if command_in == 'get':
 | |
|         module.exit_json(changed=False, set=record)
 | |
| 
 | |
|     if command_in == 'delete' and not found_record:
 | |
|         module.exit_json(changed=False)
 | |
| 
 | |
|     changes = ResourceRecordSets(conn, zones[zone_in])
 | |
| 
 | |
|     if command_in == 'create' and found_record:
 | |
|         if not module.params['overwrite']:
 | |
|             module.fail_json(msg = "Record already exists with different value. Set 'overwrite' to replace it")
 | |
|         else:
 | |
|             change = changes.add_change("DELETE", record_in, type_in, record['ttl'])
 | |
|         for v in record['values']:
 | |
|             change.add_value(v)
 | |
| 
 | |
|     if command_in == 'create' or command_in == 'delete':
 | |
|         change = changes.add_change(command_in.upper(), record_in, type_in, ttl_in)
 | |
|         for v in value_list:
 | |
|             change.add_value(v)
 | |
| 
 | |
|     try:
 | |
|         result = commit(changes)
 | |
|     except boto.route53.exception.DNSServerError, e:
 | |
|         txt = e.body.split("<Message>")[1]
 | |
|         txt = txt.split("</Message>")[0]
 | |
|         module.fail_json(msg = txt)
 | |
| 
 | |
|     module.exit_json(changed=True)
 | |
| 
 | |
| # import module snippets
 | |
| from ansible.module_utils.basic import *
 | |
| from ansible.module_utils.ec2 import *
 | |
| 
 | |
| main()
 |