Skip to content
Snippets Groups Projects
Unverified Commit 75d16c2d authored by Sergio Oliveira Campos's avatar Sergio Oliveira Campos
Browse files

Allow multiple dns zones to be absent.

This PR allow ipadnszone module to ensure that multiple dns zones
are absent at once, to be consistent with other ansible-freeipa
modules.

To fix this issue, it was required that custom arguents must be
passed using keyword arguments so that `get_ipa_command_args()`
is kept generic.
parent da5dc0c4
No related branches found
No related tags found
No related merge requests found
...@@ -163,7 +163,7 @@ Variable | Description | Required ...@@ -163,7 +163,7 @@ Variable | Description | Required
-------- | ----------- | -------- -------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no `ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`name` \| `zone_name` | The zone name string. | yes `name` \| `zone_name` | The zone name string or list of strings. | yes
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no `forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
  | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes   | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
  | `port` - The custom port that should be used on this server. | no   | `port` - The custom port that should be used on this server. | no
......
...@@ -506,7 +506,7 @@ class FreeIPABaseModule(AnsibleModule): ...@@ -506,7 +506,7 @@ class FreeIPABaseModule(AnsibleModule):
# when needed. # when needed.
self.ipa_params = AnsibleFreeIPAParams(self) self.ipa_params = AnsibleFreeIPAParams(self)
def get_ipa_command_args(self): def get_ipa_command_args(self, **kwargs):
""" """
Return a dict to be passed to an IPA command. Return a dict to be passed to an IPA command.
...@@ -538,7 +538,7 @@ class FreeIPABaseModule(AnsibleModule): ...@@ -538,7 +538,7 @@ class FreeIPABaseModule(AnsibleModule):
elif hasattr(self, param_name): elif hasattr(self, param_name):
method = getattr(self, param_name) method = getattr(self, param_name)
if callable(method): if callable(method):
value = method() value = method(**kwargs)
# We don't have a way to guess the value so fail. # We don't have a way to guess the value so fail.
else: else:
......
...@@ -41,7 +41,7 @@ options: ...@@ -41,7 +41,7 @@ options:
name: name:
description: The zone name string. description: The zone name string.
required: true required: true
type: str type: list
alises: ["zone_name"] alises: ["zone_name"]
forwarders: forwarders:
description: The list of global DNS forwarders. description: The list of global DNS forwarders.
...@@ -268,7 +268,7 @@ class DNSZoneModule(FreeIPABaseModule): ...@@ -268,7 +268,7 @@ class DNSZoneModule(FreeIPABaseModule):
return True return True
def get_ipa_nsec3paramrecord(self): def get_ipa_nsec3paramrecord(self, **kwargs):
nsec3param_rec = self.ipa_params.nsec3param_rec nsec3param_rec = self.ipa_params.nsec3param_rec
if nsec3param_rec is not None: if nsec3param_rec is not None:
error_msg = ( error_msg = (
...@@ -280,7 +280,7 @@ class DNSZoneModule(FreeIPABaseModule): ...@@ -280,7 +280,7 @@ class DNSZoneModule(FreeIPABaseModule):
self.fail_json(msg=error_msg) self.fail_json(msg=error_msg)
return nsec3param_rec return nsec3param_rec
def get_ipa_idnsforwarders(self): def get_ipa_idnsforwarders(self, **kwargs):
if self.ipa_params.forwarders is not None: if self.ipa_params.forwarders is not None:
forwarders = [] forwarders = []
for forwarder in self.ipa_params.forwarders: for forwarder in self.ipa_params.forwarders:
...@@ -304,14 +304,14 @@ class DNSZoneModule(FreeIPABaseModule): ...@@ -304,14 +304,14 @@ class DNSZoneModule(FreeIPABaseModule):
return forwarders return forwarders
def get_ipa_idnsallowtransfer(self): def get_ipa_idnsallowtransfer(self, **kwargs):
if self.ipa_params.allow_transfer is not None: if self.ipa_params.allow_transfer is not None:
error_msg = "Invalid ip_address for DNS allow_transfer: %s" error_msg = "Invalid ip_address for DNS allow_transfer: %s"
self.validate_ips(self.ipa_params.allow_transfer, error_msg) self.validate_ips(self.ipa_params.allow_transfer, error_msg)
return (";".join(self.ipa_params.allow_transfer) or "none") + ";" return (";".join(self.ipa_params.allow_transfer) or "none") + ";"
def get_ipa_idnsallowquery(self): def get_ipa_idnsallowquery(self, **kwargs):
if self.ipa_params.allow_query is not None: if self.ipa_params.allow_query is not None:
error_msg = "Invalid ip_address for DNS allow_query: %s" error_msg = "Invalid ip_address for DNS allow_query: %s"
self.validate_ips(self.ipa_params.allow_query, error_msg) self.validate_ips(self.ipa_params.allow_query, error_msg)
...@@ -334,70 +334,78 @@ class DNSZoneModule(FreeIPABaseModule): ...@@ -334,70 +334,78 @@ class DNSZoneModule(FreeIPABaseModule):
return ".".join((name, domain)) return ".".join((name, domain))
def get_ipa_idnssoarname(self): def get_ipa_idnssoarname(self, **kwargs):
if self.ipa_params.admin_email is not None: if self.ipa_params.admin_email is not None:
return DNSName( return DNSName(
self._replace_at_symbol_in_rname(self.ipa_params.admin_email) self._replace_at_symbol_in_rname(self.ipa_params.admin_email)
) )
def get_ipa_idnssoamname(self): def get_ipa_idnssoamname(self, **kwargs):
if self.ipa_params.name_server is not None: if self.ipa_params.name_server is not None:
return DNSName(self.ipa_params.name_server) return DNSName(self.ipa_params.name_server)
def get_ipa_skip_overlap_check(self): def get_ipa_skip_overlap_check(self, **kwargs):
if not self.zone and self.ipa_params.skip_overlap_check is not None: zone = kwargs.get('zone')
if not zone and self.ipa_params.skip_overlap_check is not None:
return self.ipa_params.skip_overlap_check return self.ipa_params.skip_overlap_check
def get_ipa_skip_nameserver_check(self): def get_ipa_skip_nameserver_check(self, **kwargs):
if not self.zone and self.ipa_params.skip_nameserver_check is not None: zone = kwargs.get('zone')
if not zone and self.ipa_params.skip_nameserver_check is not None:
return self.ipa_params.skip_nameserver_check return self.ipa_params.skip_nameserver_check
def get_zone(self, zone_name): def get_zone(self, zone_name):
get_zone_args = {"idnsname": zone_name, "all": True} get_zone_args = {"idnsname": zone_name, "all": True}
response = self.api_command("dnszone_find", args=get_zone_args) response = self.api_command("dnszone_find", args=get_zone_args)
zone = None
is_zone_active = False
if response["count"] == 1: if response["count"] == 1:
self.zone = response["result"][0] zone = response["result"][0]
self.is_zone_active = self.zone.get("idnszoneactive") == ["TRUE"] is_zone_active = zone.get("idnszoneactive") == ["TRUE"]
return self.zone
return zone, is_zone_active
# Zone doesn't exist yet def get_zone_names(self):
self.zone = None if len(self.ipa_params.name) > 1 and self.ipa_params.state != "absent":
self.is_zone_active = False self.fail_json(
msg=("Please provide a single name. Multiple values for 'name'"
"can only be supplied for state 'absent'.")
)
@property
def zone_name(self):
return self.ipa_params.name return self.ipa_params.name
def define_ipa_commands(self): def define_ipa_commands(self):
for zone_name in self.get_zone_names():
# Look for existing zone in IPA # Look for existing zone in IPA
self.get_zone(self.zone_name) zone, is_zone_active = self.get_zone(zone_name)
args = self.get_ipa_command_args() args = self.get_ipa_command_args(zone=zone)
just_added = False just_added = False
if self.ipa_params.state in ["present", "enabled", "disabled"]: if self.ipa_params.state in ["present", "enabled", "disabled"]:
if not self.zone: if not zone:
# Since the zone doesn't exist we just create it # Since the zone doesn't exist we just create it
# with given args # with given args
self.add_ipa_command("dnszone_add", self.zone_name, args) self.add_ipa_command("dnszone_add", zone_name, args)
self.is_zone_active = True is_zone_active = True
just_added = True just_added = True
else: else:
# Zone already exist so we need to verify if given args # Zone already exist so we need to verify if given args
# matches the current config. If not we updated it. # matches the current config. If not we updated it.
if self.require_ipa_attrs_change(args, self.zone): if self.require_ipa_attrs_change(args, zone):
self.add_ipa_command("dnszone_mod", self.zone_name, args) self.add_ipa_command("dnszone_mod", zone_name, args)
if self.ipa_params.state == "enabled" and not self.is_zone_active: if self.ipa_params.state == "enabled" and not is_zone_active:
self.add_ipa_command("dnszone_enable", self.zone_name) self.add_ipa_command("dnszone_enable", zone_name)
if self.ipa_params.state == "disabled" and self.is_zone_active: if self.ipa_params.state == "disabled" and is_zone_active:
self.add_ipa_command("dnszone_disable", self.zone_name) self.add_ipa_command("dnszone_disable", zone_name)
if self.ipa_params.state == "absent": if self.ipa_params.state == "absent":
if self.zone: if zone:
self.add_ipa_command("dnszone_del", self.zone_name) self.add_ipa_command("dnszone_del", zone_name)
# Due to a bug in FreeIPA dnszone-add won't set # Due to a bug in FreeIPA dnszone-add won't set
# SOA Serial. The good news is that dnszone-mod does the job. # SOA Serial. The good news is that dnszone-mod does the job.
...@@ -408,7 +416,7 @@ class DNSZoneModule(FreeIPABaseModule): ...@@ -408,7 +416,7 @@ class DNSZoneModule(FreeIPABaseModule):
args = { args = {
"idnssoaserial": self.ipa_params.serial, "idnssoaserial": self.ipa_params.serial,
} }
self.add_ipa_command("dnszone_mod", self.zone_name, args) self.add_ipa_command("dnszone_mod", zone_name, args)
def get_argument_spec(): def get_argument_spec():
...@@ -426,7 +434,7 @@ def get_argument_spec(): ...@@ -426,7 +434,7 @@ def get_argument_spec():
ipaadmin_principal=dict(type="str", default="admin"), ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True), ipaadmin_password=dict(type="str", required=False, no_log=True),
name=dict( name=dict(
type="str", default=None, required=True, aliases=["zone_name"] type="list", default=None, required=True, aliases=["zone_name"]
), ),
forwarders=dict( forwarders=dict(
type="list", type="list",
......
...@@ -149,3 +149,40 @@ ...@@ -149,3 +149,40 @@
forwarders: [] forwarders: []
register: result register: result
failed_when: not result.changed failed_when: not result.changed
- name: Create zones test1
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: test1.testzone.local
- name: Create zones test2
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: test2.testzone.local
- name: Create zones test3
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: test3.testzone.local
- name: Ensure multiple zones are absent
ipadnszone:
ipaadmin_password: SomeADMINpassword
name:
- test1.testzone.local
- test2.testzone.local
- test3.testzone.local
state: absent
register: result
failed_when: not result.changed
- name: Ensure multiple zones are absent, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
name:
- test1.testzone.local
- test2.testzone.local
- test3.testzone.local
state: absent
register: result
failed_when: result.changed
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment