Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to specify prefix directly #8

Merged
merged 2 commits into from
Apr 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/8-hosttech-prefix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- "hosttech_dns_record* modules - allow to specify ``prefix`` instead of ``record`` (https://github.com/ansible-collections/community.dns/pull/8)."
- "hosttech_dns_record_info - also return ``prefix`` for a record set (https://github.com/ansible-collections/community.dns/pull/8)."
11 changes: 10 additions & 1 deletion plugins/doc_fragments/module_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,17 @@ class ModuleDocFragment(object):
record:
description:
- The full DNS record to create or delete.
required: true
- Exactly one of I(record) and I(prefix) must be specified.
type: str
prefix:
description:
- The prefix of the DNS record.
- This is the part of I(record) before I(zone). For example, if the record to be modified is C(www.example.com)
for the zone C(example.com), the prefix is C(www). If the record in this example would be C(example.com), the
prefix would be C('') (empty string).
- Exactly one of I(record) and I(prefix) must be specified.
type: str
version_added: 0.2.0
ttl:
description:
- The TTL to give the new record, in seconds.
Expand Down
11 changes: 10 additions & 1 deletion plugins/doc_fragments/module_record_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,17 @@ class ModuleDocFragment(object):
record:
description:
- The full DNS record to retrieve.
- Required if I(what) is C(single_record) or C(all_types_for_record).
- If I(what) is C(single_record) or C(all_types_for_record), exactly one of I(record) and I(prefix) is required.
type: str
prefix:
description:
- The prefix of the DNS record.
- This is the part of I(record) before I(zone). For example, if the record to be modified is C(www.example.com)
for the zone C(example.com), the prefix is C(www). If the record in this example would be C(example.com), the
prefix would be C('') (empty string).
- If I(what) is C(single_record) or C(all_types_for_record), exactly one of I(record) and I(prefix) is required.
type: str
version_added: 0.2.0
type:
description:
- The type of DNS record to retrieve.
Expand Down
19 changes: 15 additions & 4 deletions plugins/module_utils/module/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,29 @@


def normalize_dns_name(name):
if name is None:
return name
# Get zone and record.
name = name.lower()
if name[-1:] == '.':
if name.endswith('.'):
name = name[:-1]
return name


def get_prefix(normalized_record, normalized_zone):
def get_prefix(normalized_zone, normalized_record=None, prefix=None):
# If normalized_record is not specified, use prefix
if normalized_record is None:
if prefix is not None:
if prefix.endswith('.'):
prefix = prefix[:-1]
prefix = prefix.lower()
if prefix == '':
prefix = None
return (prefix + '.' + normalized_zone) if prefix else normalized_zone, prefix
# Convert record to prefix
if not normalized_record.endswith('.' + normalized_zone) and normalized_record != normalized_zone:
raise DNSAPIError('Record must be in zone')
if normalized_record == normalized_zone:
return None
return normalized_record, None
else:
return normalized_record[:len(normalized_record) - len(normalized_zone) - 1]
return normalized_record, normalized_record[:len(normalized_record) - len(normalized_zone) - 1]
14 changes: 9 additions & 5 deletions plugins/module_utils/module/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,35 @@ def create_module_argument_spec(zone_id_type='str'):
state=dict(type='str', choices=['present', 'absent'], required=True),
zone=dict(type='str'),
zone_id=dict(type=zone_id_type),
record=dict(type='str', required=True),
record=dict(type='str'),
prefix=dict(type='str'),
ttl=dict(type='int', default=3600),
type=dict(choices=['A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS', 'CAA'], required=True),
value=dict(required=True, type='list', elements='str'),
overwrite=dict(default=False, type='bool'),
),
required_one_of=[
('zone', 'zone_id'),
('record', 'prefix'),
],
mutually_exclusive=[
('zone', 'zone_id'),
('record', 'prefix'),
],
)


def run_module(module, create_api):
record_in = normalize_dns_name(module.params.get('record'))
prefix_in = module.params.get('prefix')
try:
# Create API
api = create_api()

# Get zone information
if module.params.get('zone') is not None:
zone_in = normalize_dns_name(module.params.get('zone'))
prefix = get_prefix(record_in, zone_in)
record_in, prefix = get_prefix(normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in)
zone = api.get_zone_with_records_by_name(zone_in)
if zone is None:
module.fail_json(msg='Zone not found')
Expand All @@ -70,7 +74,7 @@ def run_module(module, create_api):
if zone is None:
module.fail_json(msg='Zone not found')
zone_in = normalize_dns_name(zone.zone.name)
prefix = get_prefix(record_in, zone_in)
record_in, prefix = get_prefix(normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in)

# Find matching records
type_in = module.params.get('type')
Expand Down Expand Up @@ -160,8 +164,8 @@ def run_module(module, create_api):
)
if module._diff:
result['diff'] = dict(
before=format_records_for_output(sorted(before, key=lambda record: record.target), record_in) if before else dict(),
after=format_records_for_output(sorted(after, key=lambda record: record.target), record_in) if after else dict(),
before=format_records_for_output(sorted(before, key=lambda record: record.target), record_in, prefix) if before else [],
after=format_records_for_output(sorted(after, key=lambda record: record.target), record_in, prefix) if after else [],
)

module.exit_json(**result)
Expand Down
23 changes: 16 additions & 7 deletions plugins/module_utils/module/record_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,21 @@ def create_module_argument_spec(zone_id_type='str'):
what=dict(type='str', choices=['single_record', 'all_types_for_record', 'all_records'], default='single_record'),
zone=dict(type='str'),
zone_id=dict(type=zone_id_type),
record=dict(type='str', default=None),
record=dict(type='str'),
prefix=dict(type='str'),
type=dict(type='str', choices=['A', 'CNAME', 'MX', 'AAAA', 'TXT', 'PTR', 'SRV', 'SPF', 'NS', 'CAA'], default=None),
),
required_if=[
('what', 'single_record', ['record', 'type']),
('what', 'all_types_for_record', ['record']),
('what', 'single_record', ['type']),
('what', 'single_record', ['record', 'prefix'], True),
('what', 'all_types_for_record', ['record', 'prefix'], True),
],
required_one_of=[
('zone', 'zone_id'),
],
mutually_exclusive=[
('zone', 'zone_id'),
('record', 'prefix'),
],
)

Expand All @@ -73,7 +76,8 @@ def run_module(module, create_api):
if module.params.get('what') == 'single_record':
# Extract prefix
record_in = normalize_dns_name(module.params.get('record'))
prefix = get_prefix(record_in, zone_in)
prefix_in = module.params.get('prefix')
record_in, prefix = get_prefix(normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in)

# Find matching records
type_in = module.params.get('type')
Expand All @@ -83,7 +87,7 @@ def run_module(module, create_api):
records.append(record)

# Format output
data = format_records_for_output(records, record_in) if records else {}
data = format_records_for_output(records, record_in, prefix) if records else {}
module.exit_json(
changed=False,
set=data,
Expand All @@ -93,7 +97,9 @@ def run_module(module, create_api):
# Extract prefix if necessary
if module.params.get('what') == 'all_types_for_record':
check_prefix = True
prefix = get_prefix(normalize_dns_name(module.params.get('record')), zone_in)
record_in = normalize_dns_name(module.params.get('record'))
prefix_in = module.params.get('prefix')
record_in, prefix = get_prefix(normalized_zone=zone_in, normalized_record=record_in, prefix=prefix_in)
else:
check_prefix = False
prefix = None
Expand All @@ -111,7 +117,10 @@ def run_module(module, create_api):
record_list.append(record)

# Format output
data = [format_records_for_output(record_list, record_name) for (record_name, dummy), record_list in sorted(records.items())]
data = [
format_records_for_output(record_list, record_name, record_list[0].prefix)
for (record_name, dummy), record_list in sorted(records.items())
]
module.exit_json(
changed=False,
sets=data,
Expand Down
3 changes: 2 additions & 1 deletion plugins/module_utils/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ def __repr__(self):
return self.__str__()


def format_records_for_output(records, record_name):
def format_records_for_output(records, record_name, prefix=None):
ttls = sorted(set([record.ttl for record in records]))
entry = {
'record': record_name,
'prefix': prefix or '',
'type': min([record.type for record in records]) if records else None,
'ttl': ttls[0] if len(ttls) > 0 else None,
'value': [record.target for record in records],
Expand Down
10 changes: 10 additions & 0 deletions plugins/modules/hosttech_dns_record_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
description: The record name.
type: str
sample: sample.example.com
prefix:
description: The record prefix.
type: str
sample: sample
version_added: 0.2.0
type:
description: The DNS record type.
type: str
Expand Down Expand Up @@ -96,6 +101,11 @@
description: The record name.
type: str
sample: sample.example.com
prefix:
description: The record prefix.
type: str
sample: sample
version_added: 0.2.0
type:
description: The DNS record type.
type: str
Expand Down
15 changes: 11 additions & 4 deletions tests/unit/plugins/module_utils/module/test__utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ def test_normalize_dns_name():
assert normalize_dns_name('EXAMpLE.CoM') == 'example.com'
assert normalize_dns_name('Example.com') == 'example.com'
assert normalize_dns_name('.') == ''
assert normalize_dns_name(None) is None


def test_get_prefix():
assert get_prefix('example.com', 'example.com') is None
assert get_prefix('www.example.com', 'example.com') == 'www'
assert get_prefix(normalized_zone='example.com', normalized_record='example.com') == ('example.com', None)
assert get_prefix(normalized_zone='example.com', normalized_record='www.example.com') == ('www.example.com', 'www')
assert get_prefix(normalized_zone='example.com') == ('example.com', None)
assert get_prefix(normalized_zone='example.com', prefix='') == ('example.com', None)
assert get_prefix(normalized_zone='example.com', prefix='.') == ('example.com', None)
assert get_prefix(normalized_zone='example.com', prefix='www') == ('www.example.com', 'www')
assert get_prefix(normalized_zone='example.com', prefix='www.') == ('www.example.com', 'www')
assert get_prefix(normalized_zone='example.com', prefix='wWw.') == ('www.example.com', 'www')
with pytest.raises(DNSAPIError):
get_prefix('example.org', 'example.com')
get_prefix(normalized_zone='example.com', normalized_record='example.org')
with pytest.raises(DNSAPIError):
get_prefix('wwwexample.com', 'example.com')
get_prefix(normalized_zone='example.com', normalized_record='wwwexample.com')
21 changes: 14 additions & 7 deletions tests/unit/plugins/module_utils/test_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,46 +48,53 @@ def test_format_records_for_output():
AAAA.type = 'AAAA'
AAAA.ttl = 600
AAAA.target = '::1'
assert format_records_for_output([], 'foo') == {
assert format_records_for_output([], 'foo', '') == {
'record': 'foo',
'prefix': '',
'type': None,
'ttl': None,
'value': [],
}
assert format_records_for_output([A1, A2], 'foo') == {
assert format_records_for_output([A1, A2], 'foo', 'bar') == {
'record': 'foo',
'prefix': 'bar',
'type': 'A',
'ttl': 300,
'value': ['1.2.3.4', '1.2.3.5'],
}
assert format_records_for_output([A3, A1], 'foo') == {
assert format_records_for_output([A3, A1], 'foo', None) == {
'record': 'foo',
'prefix': '',
'type': 'A',
'ttl': 300,
'ttls': [300, 3600],
'value': ['1.2.3.6', '1.2.3.4'],
}
assert format_records_for_output([A3], 'foo') == {
assert format_records_for_output([A3], 'foo', None) == {
'record': 'foo',
'prefix': '',
'type': 'A',
'ttl': 3600,
'value': ['1.2.3.6'],
}
assert format_records_for_output([AAAA], 'foo') == {
assert format_records_for_output([AAAA], 'foo', None) == {
'record': 'foo',
'prefix': '',
'type': 'AAAA',
'ttl': 600,
'value': ['::1'],
}
assert format_records_for_output([A3, AAAA], 'foo') == {
assert format_records_for_output([A3, AAAA], 'foo', None) == {
'record': 'foo',
'prefix': '',
'type': 'A',
'ttl': 600,
'ttls': [600, 3600],
'value': ['1.2.3.6', '::1'],
}
assert format_records_for_output([AAAA, A3], 'foo') == {
assert format_records_for_output([AAAA, A3], 'foo', None) == {
'record': 'foo',
'prefix': '',
'type': 'A',
'ttl': 600,
'ttls': [600, 3600],
Expand Down
Loading