mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
exo_dns_record: remove limitation for multiple records only for A type (#35173)
This commit is contained in:
parent
57d5b8642a
commit
24b8f36f1e
3 changed files with 37 additions and 100 deletions
|
@ -1,31 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# (c) 2016, René Moser <mail@renemoser.net>
|
||||
#
|
||||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# Copyright (c) 2016, René Moser <mail@renemoser.net>
|
||||
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||
|
||||
import os
|
||||
|
||||
|
@ -43,7 +18,7 @@ def exo_dns_argument_spec():
|
|||
api_secret=dict(default=os.environ.get('CLOUDSTACK_SECRET'), no_log=True),
|
||||
api_timeout=dict(type='int', default=os.environ.get('CLOUDSTACK_TIMEOUT') or 10),
|
||||
api_region=dict(default=os.environ.get('CLOUDSTACK_REGION') or 'cloudstack'),
|
||||
validate_certs=dict(default='yes', type='bool'),
|
||||
validate_certs=dict(default=True, type='bool'),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -34,12 +34,12 @@ options:
|
|||
description:
|
||||
- Type of the record.
|
||||
default: A
|
||||
choices: ['A', 'ALIAS', 'CNAME', 'MX', 'SPF', 'URL', 'TXT', 'NS', 'SRV', 'NAPTR', 'PTR', 'AAAA', 'SSHFP', 'HINFO', 'POOL']
|
||||
aliases: ['rtype', 'type']
|
||||
choices: [ A, ALIAS, CNAME, MX, SPF, URL, TXT, NS, SRV, NAPTR, PTR, AAAA, SSHFP, HINFO, POOL ]
|
||||
aliases: [ rtype, type ]
|
||||
content:
|
||||
description:
|
||||
- Content of the record.
|
||||
- Required if C(state=present) or C(name="")
|
||||
- Required if C(state=present) or C(multiple=yes).
|
||||
aliases: ['value', 'address']
|
||||
ttl:
|
||||
description:
|
||||
|
@ -48,19 +48,19 @@ options:
|
|||
prio:
|
||||
description:
|
||||
- Priority of the record.
|
||||
aliases: ['priority']
|
||||
aliases: [ priority ]
|
||||
multiple:
|
||||
description:
|
||||
- Whether there are more than one records with similar C(name).
|
||||
- Only allowed with C(record_type=A).
|
||||
- C(content) will not be updated as it is used as key to find the record.
|
||||
aliases: ['priority']
|
||||
- Whether there are more than one records with similar C(name) and C(record_type).
|
||||
- Only allowed for a few record types, e.g. C(record_type=A), C(record_type=NS) or C(record_type=MX).
|
||||
- C(content) will not be updated, instead it is used as a key to find existing records.
|
||||
type: bool
|
||||
default: no
|
||||
state:
|
||||
description:
|
||||
- State of the record.
|
||||
required: false
|
||||
default: 'present'
|
||||
choices: [ 'present', 'absent' ]
|
||||
default: present
|
||||
choices: [ present, absent ]
|
||||
extends_documentation_fragment: exoscale
|
||||
'''
|
||||
|
||||
|
@ -95,23 +95,25 @@ EXAMPLES = '''
|
|||
record_type: CNAME
|
||||
content: web-vm-1
|
||||
|
||||
- name: Create or update a MX record
|
||||
- name: Create another MX record
|
||||
local_action:
|
||||
module: exo_dns_record
|
||||
domain: example.com
|
||||
record_type: MX
|
||||
content: mx1.example.com
|
||||
prio: 10
|
||||
multiple: yes
|
||||
|
||||
- name: Delete a MX record
|
||||
- name: Delete one MX record out of multiple
|
||||
local_action:
|
||||
module: exo_dns_record
|
||||
domain: example.com
|
||||
record_type: MX
|
||||
content: mx1.example.com
|
||||
multiple: yes
|
||||
state: absent
|
||||
|
||||
- name: Remove a record
|
||||
- name: Remove a single A record
|
||||
local_action:
|
||||
module: exo_dns_record
|
||||
name: www
|
||||
|
@ -223,12 +225,7 @@ class ExoDnsRecord(ExoDns):
|
|||
|
||||
self.multiple = self.module.params.get('multiple')
|
||||
self.record_type = self.module.params.get('record_type')
|
||||
if self.multiple and self.record_type != 'A':
|
||||
self.module.fail_json(msg="Multiple is only usable with record_type A")
|
||||
|
||||
self.content = self.module.params.get('content')
|
||||
if self.content and self.record_type != 'TXT':
|
||||
self.content = self.content.lower()
|
||||
|
||||
def _create_record(self, record):
|
||||
self.result['changed'] = True
|
||||
|
@ -265,31 +262,26 @@ class ExoDnsRecord(ExoDns):
|
|||
domain = self.module.params.get('domain')
|
||||
records = self.api_query("/domains/%s/records" % domain, "GET")
|
||||
|
||||
record = None
|
||||
result = {}
|
||||
for r in records:
|
||||
found_record = None
|
||||
if r['record']['record_type'] == self.record_type:
|
||||
|
||||
if r['record']['record_type'] != self.record_type:
|
||||
continue
|
||||
|
||||
r_name = r['record']['name'].lower()
|
||||
r_content = r['record']['content'].lower()
|
||||
r_content = r['record']['content']
|
||||
|
||||
# there are multiple A records but we found an exact match
|
||||
if self.multiple and self.name == r_name and self.content == r_content:
|
||||
record = r
|
||||
break
|
||||
if r_name == self.name:
|
||||
if not self.multiple:
|
||||
if result:
|
||||
self.module.fail_json(msg="More than one record with record_type=%s and name=%s params. "
|
||||
"Use multiple=yes for more than one record." % (self.record_type, self.name))
|
||||
else:
|
||||
result = r
|
||||
elif r_content == self.content:
|
||||
return r
|
||||
|
||||
# We do not expect to found more then one record with that content
|
||||
if not self.multiple and not self.name and self.content == r_content:
|
||||
found_record = r
|
||||
|
||||
# We do not expect to found more then one record with that name
|
||||
elif not self.multiple and self.name and self.name == r_name:
|
||||
found_record = r
|
||||
|
||||
if record and found_record:
|
||||
self.module.fail_json(msg="More than one record with your params. Use multiple=yes for more than one A record.")
|
||||
if found_record:
|
||||
record = found_record
|
||||
return record
|
||||
return result
|
||||
|
||||
def present_record(self):
|
||||
record = self.get_record()
|
||||
|
@ -332,11 +324,8 @@ def main():
|
|||
argument_spec=argument_spec,
|
||||
required_together=exo_dns_required_together(),
|
||||
required_if=[
|
||||
['state', 'present', ['content']],
|
||||
['name', '', ['content']],
|
||||
],
|
||||
required_one_of=[
|
||||
['content', 'name'],
|
||||
('state', 'present', ['content']),
|
||||
('multiple', True, ['content']),
|
||||
],
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
|
|
@ -54,19 +54,6 @@
|
|||
- result is failed
|
||||
- 'result.msg == "missing required arguments: domain"'
|
||||
|
||||
- name: test fail if missing required params
|
||||
local_action:
|
||||
module: exo_dns_record
|
||||
domain: "{{ exo_dns_domain_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
ignore_errors: true
|
||||
- name: verify results of test fail if missing required params
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "name is but the following are missing: content"'
|
||||
|
||||
- name: test fail if missing required params state=present
|
||||
local_action:
|
||||
module: exo_dns_record
|
||||
|
@ -78,21 +65,7 @@
|
|||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "state is present but the following are missing: content"'
|
||||
|
||||
- name: test fail if missing required params state=absent
|
||||
local_action:
|
||||
module: exo_dns_record
|
||||
domain: "{{ exo_dns_domain_name }}"
|
||||
name: ""
|
||||
state: absent
|
||||
register: result
|
||||
ignore_errors: true
|
||||
- name: verify results of test fail if missing required params state=absent
|
||||
assert:
|
||||
that:
|
||||
- result is failed
|
||||
- 'result.msg == "name is but the following are missing: content"'
|
||||
- 'result.msg == "state is present but all of the following are missing: content"'
|
||||
|
||||
- name: test create a record
|
||||
local_action:
|
||||
|
|
Loading…
Reference in a new issue