mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2025-10-26 05:50:36 -07:00 
			
		
		
		
	Add attributes to oneandone, ovh, and rackspace modules (#5948)
Add attributes to oneandone, ovh, and rackspace modules.
(cherry picked from commit 6bd131f2fb)
		
	
			
		
			
				
	
	
		
			362 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			362 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| # -*- coding: utf-8 -*-
 | |
| # Copyright Ansible Project
 | |
| # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| from __future__ import absolute_import, division, print_function
 | |
| __metaclass__ = type
 | |
| 
 | |
| 
 | |
| DOCUMENTATION = '''
 | |
| ---
 | |
| module: rax_dns_record
 | |
| short_description: Manage DNS records on Rackspace Cloud DNS
 | |
| description:
 | |
|   - Manage DNS records on Rackspace Cloud DNS.
 | |
|   - This module relies on the C(pyrax) package which is deprecated in favour of using Openstack API.
 | |
|   - Unless maintainers step up to work on the module, it will be marked as deprecated in community.general 7.0.0 and removed in version 9.0.0.
 | |
| attributes:
 | |
|   check_mode:
 | |
|     support: none
 | |
|   diff_mode:
 | |
|     support: none
 | |
| options:
 | |
|   comment:
 | |
|     type: str
 | |
|     description:
 | |
|       - Brief description of the domain. Maximum length of 160 characters
 | |
|   data:
 | |
|     type: str
 | |
|     description:
 | |
|       - IP address for A/AAAA record, FQDN for CNAME/MX/NS, or text data for
 | |
|         SRV/TXT
 | |
|     required: true
 | |
|   domain:
 | |
|     type: str
 | |
|     description:
 | |
|       - Domain name to create the record in. This is an invalid option when
 | |
|         type=PTR
 | |
|   loadbalancer:
 | |
|     type: str
 | |
|     description:
 | |
|       - Load Balancer ID to create a PTR record for. Only used with type=PTR
 | |
|   name:
 | |
|     type: str
 | |
|     description:
 | |
|       - FQDN record name to create
 | |
|     required: true
 | |
|   overwrite:
 | |
|     description:
 | |
|       - Add new records if data doesn't match, instead of updating existing
 | |
|         record with matching name. If there are already multiple records with
 | |
|         matching name and overwrite=true, this module will fail.
 | |
|     default: true
 | |
|     type: bool
 | |
|   priority:
 | |
|     type: int
 | |
|     description:
 | |
|       - Required for MX and SRV records, but forbidden for other record types.
 | |
|         If specified, must be an integer from 0 to 65535.
 | |
|   server:
 | |
|     type: str
 | |
|     description:
 | |
|       - Server ID to create a PTR record for. Only used with type=PTR
 | |
|   state:
 | |
|     type: str
 | |
|     description:
 | |
|       - Indicate desired state of the resource
 | |
|     choices:
 | |
|       - present
 | |
|       - absent
 | |
|     default: present
 | |
|   ttl:
 | |
|     type: int
 | |
|     description:
 | |
|       - Time to live of record in seconds
 | |
|     default: 3600
 | |
|   type:
 | |
|     type: str
 | |
|     description:
 | |
|       - DNS record type
 | |
|     choices:
 | |
|       - A
 | |
|       - AAAA
 | |
|       - CNAME
 | |
|       - MX
 | |
|       - NS
 | |
|       - SRV
 | |
|       - TXT
 | |
|       - PTR
 | |
|     required: true
 | |
| notes:
 | |
|   - "It is recommended that plays utilizing this module be run with
 | |
|     C(serial: 1) to avoid exceeding the API request limit imposed by
 | |
|     the Rackspace CloudDNS API"
 | |
|   - To manipulate a C(PTR) record either C(loadbalancer) or C(server) must be
 | |
|     supplied
 | |
|   - As of version 1.7, the C(type) field is required and no longer defaults to an C(A) record.
 | |
|   - C(PTR) record support was added in version 1.7
 | |
| author: "Matt Martz (@sivel)"
 | |
| extends_documentation_fragment:
 | |
|   - community.general.rackspace
 | |
|   - community.general.rackspace.openstack
 | |
|   - community.general.attributes
 | |
| 
 | |
| '''
 | |
| 
 | |
| EXAMPLES = '''
 | |
| - name: Create DNS Records
 | |
|   hosts: all
 | |
|   gather_facts: false
 | |
|   tasks:
 | |
|     - name: Create A record
 | |
|       local_action:
 | |
|         module: rax_dns_record
 | |
|         credentials: ~/.raxpub
 | |
|         domain: example.org
 | |
|         name: www.example.org
 | |
|         data: "{{ rax_accessipv4 }}"
 | |
|         type: A
 | |
|       register: a_record
 | |
| 
 | |
|     - name: Create PTR record
 | |
|       local_action:
 | |
|         module: rax_dns_record
 | |
|         credentials: ~/.raxpub
 | |
|         server: "{{ rax_id }}"
 | |
|         name: "{{ inventory_hostname }}"
 | |
|         region: DFW
 | |
|       register: ptr_record
 | |
| '''
 | |
| 
 | |
| try:
 | |
|     import pyrax
 | |
|     HAS_PYRAX = True
 | |
| except ImportError:
 | |
|     HAS_PYRAX = False
 | |
| 
 | |
| from ansible.module_utils.basic import AnsibleModule
 | |
| from ansible_collections.community.general.plugins.module_utils.rax import (rax_argument_spec,
 | |
|                                                                             rax_find_loadbalancer,
 | |
|                                                                             rax_find_server,
 | |
|                                                                             rax_required_together,
 | |
|                                                                             rax_to_dict,
 | |
|                                                                             setup_rax_module,
 | |
|                                                                             )
 | |
| 
 | |
| 
 | |
| def rax_dns_record_ptr(module, data=None, comment=None, loadbalancer=None,
 | |
|                        name=None, server=None, state='present', ttl=7200):
 | |
|     changed = False
 | |
|     results = []
 | |
| 
 | |
|     dns = pyrax.cloud_dns
 | |
| 
 | |
|     if not dns:
 | |
|         module.fail_json(msg='Failed to instantiate client. This '
 | |
|                              'typically indicates an invalid region or an '
 | |
|                              'incorrectly capitalized region name.')
 | |
| 
 | |
|     if loadbalancer:
 | |
|         item = rax_find_loadbalancer(module, pyrax, loadbalancer)
 | |
|     elif server:
 | |
|         item = rax_find_server(module, pyrax, server)
 | |
| 
 | |
|     if state == 'present':
 | |
|         current = dns.list_ptr_records(item)
 | |
|         for record in current:
 | |
|             if record.data == data:
 | |
|                 if record.ttl != ttl or record.name != name:
 | |
|                     try:
 | |
|                         dns.update_ptr_record(item, record, name, data, ttl)
 | |
|                         changed = True
 | |
|                     except Exception as e:
 | |
|                         module.fail_json(msg='%s' % e.message)
 | |
|                     record.ttl = ttl
 | |
|                     record.name = name
 | |
|                     results.append(rax_to_dict(record))
 | |
|                     break
 | |
|                 else:
 | |
|                     results.append(rax_to_dict(record))
 | |
|                     break
 | |
| 
 | |
|         if not results:
 | |
|             record = dict(name=name, type='PTR', data=data, ttl=ttl,
 | |
|                           comment=comment)
 | |
|             try:
 | |
|                 results = dns.add_ptr_records(item, [record])
 | |
|                 changed = True
 | |
|             except Exception as e:
 | |
|                 module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|         module.exit_json(changed=changed, records=results)
 | |
| 
 | |
|     elif state == 'absent':
 | |
|         current = dns.list_ptr_records(item)
 | |
|         for record in current:
 | |
|             if record.data == data:
 | |
|                 results.append(rax_to_dict(record))
 | |
|                 break
 | |
| 
 | |
|         if results:
 | |
|             try:
 | |
|                 dns.delete_ptr_records(item, data)
 | |
|                 changed = True
 | |
|             except Exception as e:
 | |
|                 module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|         module.exit_json(changed=changed, records=results)
 | |
| 
 | |
| 
 | |
| def rax_dns_record(module, comment=None, data=None, domain=None, name=None,
 | |
|                    overwrite=True, priority=None, record_type='A',
 | |
|                    state='present', ttl=7200):
 | |
|     """Function for manipulating record types other than PTR"""
 | |
| 
 | |
|     changed = False
 | |
| 
 | |
|     dns = pyrax.cloud_dns
 | |
|     if not dns:
 | |
|         module.fail_json(msg='Failed to instantiate client. This '
 | |
|                              'typically indicates an invalid region or an '
 | |
|                              'incorrectly capitalized region name.')
 | |
| 
 | |
|     if state == 'present':
 | |
|         if not priority and record_type in ['MX', 'SRV']:
 | |
|             module.fail_json(msg='A "priority" attribute is required for '
 | |
|                                  'creating a MX or SRV record')
 | |
| 
 | |
|         try:
 | |
|             domain = dns.find(name=domain)
 | |
|         except Exception as e:
 | |
|             module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|         try:
 | |
|             if overwrite:
 | |
|                 record = domain.find_record(record_type, name=name)
 | |
|             else:
 | |
|                 record = domain.find_record(record_type, name=name, data=data)
 | |
|         except pyrax.exceptions.DomainRecordNotUnique as e:
 | |
|             module.fail_json(msg='overwrite=true and there are multiple matching records')
 | |
|         except pyrax.exceptions.DomainRecordNotFound as e:
 | |
|             try:
 | |
|                 record_data = {
 | |
|                     'type': record_type,
 | |
|                     'name': name,
 | |
|                     'data': data,
 | |
|                     'ttl': ttl
 | |
|                 }
 | |
|                 if comment:
 | |
|                     record_data.update(dict(comment=comment))
 | |
|                 if priority and record_type.upper() in ['MX', 'SRV']:
 | |
|                     record_data.update(dict(priority=priority))
 | |
| 
 | |
|                 record = domain.add_records([record_data])[0]
 | |
|                 changed = True
 | |
|             except Exception as e:
 | |
|                 module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|         update = {}
 | |
|         if comment != getattr(record, 'comment', None):
 | |
|             update['comment'] = comment
 | |
|         if ttl != getattr(record, 'ttl', None):
 | |
|             update['ttl'] = ttl
 | |
|         if priority != getattr(record, 'priority', None):
 | |
|             update['priority'] = priority
 | |
|         if data != getattr(record, 'data', None):
 | |
|             update['data'] = data
 | |
| 
 | |
|         if update:
 | |
|             try:
 | |
|                 record.update(**update)
 | |
|                 changed = True
 | |
|                 record.get()
 | |
|             except Exception as e:
 | |
|                 module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|     elif state == 'absent':
 | |
|         try:
 | |
|             domain = dns.find(name=domain)
 | |
|         except Exception as e:
 | |
|             module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|         try:
 | |
|             record = domain.find_record(record_type, name=name, data=data)
 | |
|         except pyrax.exceptions.DomainRecordNotFound as e:
 | |
|             record = {}
 | |
|         except pyrax.exceptions.DomainRecordNotUnique as e:
 | |
|             module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|         if record:
 | |
|             try:
 | |
|                 record.delete()
 | |
|                 changed = True
 | |
|             except Exception as e:
 | |
|                 module.fail_json(msg='%s' % e.message)
 | |
| 
 | |
|     module.exit_json(changed=changed, record=rax_to_dict(record))
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     argument_spec = rax_argument_spec()
 | |
|     argument_spec.update(
 | |
|         dict(
 | |
|             comment=dict(),
 | |
|             data=dict(required=True),
 | |
|             domain=dict(),
 | |
|             loadbalancer=dict(),
 | |
|             name=dict(required=True),
 | |
|             overwrite=dict(type='bool', default=True),
 | |
|             priority=dict(type='int'),
 | |
|             server=dict(),
 | |
|             state=dict(default='present', choices=['present', 'absent']),
 | |
|             ttl=dict(type='int', default=3600),
 | |
|             type=dict(required=True, choices=['A', 'AAAA', 'CNAME', 'MX', 'NS',
 | |
|                                               'SRV', 'TXT', 'PTR'])
 | |
|         )
 | |
|     )
 | |
| 
 | |
|     module = AnsibleModule(
 | |
|         argument_spec=argument_spec,
 | |
|         required_together=rax_required_together(),
 | |
|         mutually_exclusive=[
 | |
|             ['server', 'loadbalancer', 'domain'],
 | |
|         ],
 | |
|         required_one_of=[
 | |
|             ['server', 'loadbalancer', 'domain'],
 | |
|         ],
 | |
|     )
 | |
| 
 | |
|     if not HAS_PYRAX:
 | |
|         module.fail_json(msg='pyrax is required for this module')
 | |
| 
 | |
|     comment = module.params.get('comment')
 | |
|     data = module.params.get('data')
 | |
|     domain = module.params.get('domain')
 | |
|     loadbalancer = module.params.get('loadbalancer')
 | |
|     name = module.params.get('name')
 | |
|     overwrite = module.params.get('overwrite')
 | |
|     priority = module.params.get('priority')
 | |
|     server = module.params.get('server')
 | |
|     state = module.params.get('state')
 | |
|     ttl = module.params.get('ttl')
 | |
|     record_type = module.params.get('type')
 | |
| 
 | |
|     setup_rax_module(module, pyrax, False)
 | |
| 
 | |
|     if record_type.upper() == 'PTR':
 | |
|         if not server and not loadbalancer:
 | |
|             module.fail_json(msg='one of the following is required: '
 | |
|                                  'server,loadbalancer')
 | |
|         rax_dns_record_ptr(module, data=data, comment=comment,
 | |
|                            loadbalancer=loadbalancer, name=name, server=server,
 | |
|                            state=state, ttl=ttl)
 | |
|     else:
 | |
|         rax_dns_record(module, comment=comment, data=data, domain=domain,
 | |
|                        name=name, overwrite=overwrite, priority=priority,
 | |
|                        record_type=record_type, state=state, ttl=ttl)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |