Blame SOURCES/ansible-freeipa-0.1.12-Allow-multiple-dns-zones-to-be-absent_rhbz#1845058.patch

01db47
From 75d16c2da4a5621943873a26343eb0f2acc2a925 Mon Sep 17 00:00:00 2001
01db47
From: Sergio Oliveira Campos <seocam@seocam.com>
01db47
Date: Mon, 3 Aug 2020 11:54:44 -0300
01db47
Subject: [PATCH] Allow multiple dns zones to be absent.
01db47
01db47
This PR allow ipadnszone module to ensure that multiple dns zones
01db47
are absent at once, to be consistent with other ansible-freeipa
01db47
modules.
01db47
01db47
To fix this issue, it was required that custom arguents must be
01db47
passed using keyword arguments so that `get_ipa_command_args()`
01db47
is kept generic.
01db47
---
01db47
 README-dnszone.md                             |   2 +-
01db47
 .../module_utils/ansible_freeipa_module.py    |   4 +-
01db47
 plugins/modules/ipadnszone.py                 | 126 ++++++++++--------
01db47
 tests/dnszone/test_dnszone.yml                |  37 +++++
01db47
 4 files changed, 107 insertions(+), 62 deletions(-)
01db47
01db47
diff --git a/README-dnszone.md b/README-dnszone.md
01db47
index 766efe5..9c9b12c 100644
01db47
--- a/README-dnszone.md
01db47
+++ b/README-dnszone.md
01db47
@@ -163,7 +163,7 @@ Variable | Description | Required
01db47
 -------- | ----------- | --------
01db47
 `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
01db47
 `ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
01db47
-`name` \| `zone_name` | The zone name string. | yes
01db47
+`name` \| `zone_name` | The zone name string or list of strings. | yes
01db47
 `forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
01db47
   | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
01db47
   | `port` - The custom port that should be used on this server. | no
01db47
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
01db47
index 122ea2e..1e55693 100644
01db47
--- a/plugins/module_utils/ansible_freeipa_module.py
01db47
+++ b/plugins/module_utils/ansible_freeipa_module.py
01db47
@@ -506,7 +506,7 @@ class FreeIPABaseModule(AnsibleModule):
01db47
         #   when needed.
01db47
         self.ipa_params = AnsibleFreeIPAParams(self)
01db47
 
01db47
-    def get_ipa_command_args(self):
01db47
+    def get_ipa_command_args(self, **kwargs):
01db47
         """
01db47
         Return a dict to be passed to an IPA command.
01db47
 
01db47
@@ -538,7 +538,7 @@ class FreeIPABaseModule(AnsibleModule):
01db47
             elif hasattr(self, param_name):
01db47
                 method = getattr(self, param_name)
01db47
                 if callable(method):
01db47
-                    value = method()
01db47
+                    value = method(**kwargs)
01db47
 
01db47
             # We don't have a way to guess the value so fail.
01db47
             else:
01db47
diff --git a/plugins/modules/ipadnszone.py b/plugins/modules/ipadnszone.py
01db47
index 717978e..c5e812a 100644
01db47
--- a/plugins/modules/ipadnszone.py
01db47
+++ b/plugins/modules/ipadnszone.py
01db47
@@ -41,7 +41,7 @@ options:
01db47
   name:
01db47
     description: The zone name string.
01db47
     required: true
01db47
-    type: str
01db47
+    type: list
01db47
     alises: ["zone_name"]
01db47
   forwarders:
01db47
     description: The list of global DNS forwarders.
01db47
@@ -268,7 +268,7 @@ class DNSZoneModule(FreeIPABaseModule):
01db47
 
01db47
         return True
01db47
 
01db47
-    def get_ipa_nsec3paramrecord(self):
01db47
+    def get_ipa_nsec3paramrecord(self, **kwargs):
01db47
         nsec3param_rec = self.ipa_params.nsec3param_rec
01db47
         if nsec3param_rec is not None:
01db47
             error_msg = (
01db47
@@ -280,7 +280,7 @@ class DNSZoneModule(FreeIPABaseModule):
01db47
                 self.fail_json(msg=error_msg)
01db47
             return nsec3param_rec
01db47
 
01db47
-    def get_ipa_idnsforwarders(self):
01db47
+    def get_ipa_idnsforwarders(self, **kwargs):
01db47
         if self.ipa_params.forwarders is not None:
01db47
             forwarders = []
01db47
             for forwarder in self.ipa_params.forwarders:
01db47
@@ -304,14 +304,14 @@ class DNSZoneModule(FreeIPABaseModule):
01db47
 
01db47
             return forwarders
01db47
 
01db47
-    def get_ipa_idnsallowtransfer(self):
01db47
+    def get_ipa_idnsallowtransfer(self, **kwargs):
01db47
         if self.ipa_params.allow_transfer is not None:
01db47
             error_msg = "Invalid ip_address for DNS allow_transfer: %s"
01db47
             self.validate_ips(self.ipa_params.allow_transfer, error_msg)
01db47
 
01db47
             return (";".join(self.ipa_params.allow_transfer) or "none") + ";"
01db47
 
01db47
-    def get_ipa_idnsallowquery(self):
01db47
+    def get_ipa_idnsallowquery(self, **kwargs):
01db47
         if self.ipa_params.allow_query is not None:
01db47
             error_msg = "Invalid ip_address for DNS allow_query: %s"
01db47
             self.validate_ips(self.ipa_params.allow_query, error_msg)
01db47
@@ -334,81 +334,89 @@ class DNSZoneModule(FreeIPABaseModule):
01db47
 
01db47
         return ".".join((name, domain))
01db47
 
01db47
-    def get_ipa_idnssoarname(self):
01db47
+    def get_ipa_idnssoarname(self, **kwargs):
01db47
         if self.ipa_params.admin_email is not None:
01db47
             return DNSName(
01db47
                 self._replace_at_symbol_in_rname(self.ipa_params.admin_email)
01db47
             )
01db47
 
01db47
-    def get_ipa_idnssoamname(self):
01db47
+    def get_ipa_idnssoamname(self, **kwargs):
01db47
         if self.ipa_params.name_server is not None:
01db47
             return DNSName(self.ipa_params.name_server)
01db47
 
01db47
-    def get_ipa_skip_overlap_check(self):
01db47
-        if not self.zone and self.ipa_params.skip_overlap_check is not None:
01db47
+    def get_ipa_skip_overlap_check(self, **kwargs):
01db47
+        zone = kwargs.get('zone')
01db47
+        if not zone and self.ipa_params.skip_overlap_check is not None:
01db47
             return self.ipa_params.skip_overlap_check
01db47
 
01db47
-    def get_ipa_skip_nameserver_check(self):
01db47
-        if not self.zone and self.ipa_params.skip_nameserver_check is not None:
01db47
+    def get_ipa_skip_nameserver_check(self, **kwargs):
01db47
+        zone = kwargs.get('zone')
01db47
+        if not zone and self.ipa_params.skip_nameserver_check is not None:
01db47
             return self.ipa_params.skip_nameserver_check
01db47
 
01db47
     def get_zone(self, zone_name):
01db47
         get_zone_args = {"idnsname": zone_name, "all": True}
01db47
         response = self.api_command("dnszone_find", args=get_zone_args)
01db47
 
01db47
+        zone = None
01db47
+        is_zone_active = False
01db47
+
01db47
         if response["count"] == 1:
01db47
-            self.zone = response["result"][0]
01db47
-            self.is_zone_active = self.zone.get("idnszoneactive") == ["TRUE"]
01db47
-            return self.zone
01db47
+            zone = response["result"][0]
01db47
+            is_zone_active = zone.get("idnszoneactive") == ["TRUE"]
01db47
 
01db47
-        # Zone doesn't exist yet
01db47
-        self.zone = None
01db47
-        self.is_zone_active = False
01db47
+        return zone, is_zone_active
01db47
+
01db47
+    def get_zone_names(self):
01db47
+        if len(self.ipa_params.name) > 1 and self.ipa_params.state != "absent":
01db47
+            self.fail_json(
01db47
+                msg=("Please provide a single name. Multiple values for 'name'"
01db47
+                     "can only be supplied for state 'absent'.")
01db47
+            )
01db47
 
01db47
-    @property
01db47
-    def zone_name(self):
01db47
         return self.ipa_params.name
01db47
 
01db47
     def define_ipa_commands(self):
01db47
-        # Look for existing zone in IPA
01db47
-        self.get_zone(self.zone_name)
01db47
-        args = self.get_ipa_command_args()
01db47
-        just_added = False
01db47
-
01db47
-        if self.ipa_params.state in ["present", "enabled", "disabled"]:
01db47
-            if not self.zone:
01db47
-                # Since the zone doesn't exist we just create it
01db47
-                #   with given args
01db47
-                self.add_ipa_command("dnszone_add", self.zone_name, args)
01db47
-                self.is_zone_active = True
01db47
-                just_added = True
01db47
-
01db47
-            else:
01db47
-                # Zone already exist so we need to verify if given args
01db47
-                #   matches the current config. If not we updated it.
01db47
-                if self.require_ipa_attrs_change(args, self.zone):
01db47
-                    self.add_ipa_command("dnszone_mod", self.zone_name, args)
01db47
-
01db47
-            if self.ipa_params.state == "enabled" and not self.is_zone_active:
01db47
-                self.add_ipa_command("dnszone_enable", self.zone_name)
01db47
-
01db47
-            if self.ipa_params.state == "disabled" and self.is_zone_active:
01db47
-                self.add_ipa_command("dnszone_disable", self.zone_name)
01db47
-
01db47
-        if self.ipa_params.state == "absent":
01db47
-            if self.zone:
01db47
-                self.add_ipa_command("dnszone_del", self.zone_name)
01db47
-
01db47
-        # Due to a bug in FreeIPA dnszone-add won't set
01db47
-        #   SOA Serial. The good news is that dnszone-mod does the job.
01db47
-        # See: https://pagure.io/freeipa/issue/8227
01db47
-        # Because of that, if the zone was just added with a given serial
01db47
-        #   we run mod just after to workaround the bug
01db47
-        if just_added and self.ipa_params.serial is not None:
01db47
-            args = {
01db47
-                "idnssoaserial": self.ipa_params.serial,
01db47
-            }
01db47
-            self.add_ipa_command("dnszone_mod", self.zone_name, args)
01db47
+        for zone_name in self.get_zone_names():
01db47
+            # Look for existing zone in IPA
01db47
+            zone, is_zone_active = self.get_zone(zone_name)
01db47
+            args = self.get_ipa_command_args(zone=zone)
01db47
+            just_added = False
01db47
+
01db47
+            if self.ipa_params.state in ["present", "enabled", "disabled"]:
01db47
+                if not zone:
01db47
+                    # Since the zone doesn't exist we just create it
01db47
+                    #   with given args
01db47
+                    self.add_ipa_command("dnszone_add", zone_name, args)
01db47
+                    is_zone_active = True
01db47
+                    just_added = True
01db47
+
01db47
+                else:
01db47
+                    # Zone already exist so we need to verify if given args
01db47
+                    #   matches the current config. If not we updated it.
01db47
+                    if self.require_ipa_attrs_change(args, zone):
01db47
+                        self.add_ipa_command("dnszone_mod", zone_name, args)
01db47
+
01db47
+                if self.ipa_params.state == "enabled" and not is_zone_active:
01db47
+                    self.add_ipa_command("dnszone_enable", zone_name)
01db47
+
01db47
+                if self.ipa_params.state == "disabled" and is_zone_active:
01db47
+                    self.add_ipa_command("dnszone_disable", zone_name)
01db47
+
01db47
+            if self.ipa_params.state == "absent":
01db47
+                if zone:
01db47
+                    self.add_ipa_command("dnszone_del", zone_name)
01db47
+
01db47
+            # Due to a bug in FreeIPA dnszone-add won't set
01db47
+            #   SOA Serial. The good news is that dnszone-mod does the job.
01db47
+            # See: https://pagure.io/freeipa/issue/8227
01db47
+            # Because of that, if the zone was just added with a given serial
01db47
+            #   we run mod just after to workaround the bug
01db47
+            if just_added and self.ipa_params.serial is not None:
01db47
+                args = {
01db47
+                    "idnssoaserial": self.ipa_params.serial,
01db47
+                }
01db47
+                self.add_ipa_command("dnszone_mod", zone_name, args)
01db47
 
01db47
 
01db47
 def get_argument_spec():
01db47
@@ -426,7 +434,7 @@ def get_argument_spec():
01db47
         ipaadmin_principal=dict(type="str", default="admin"),
01db47
         ipaadmin_password=dict(type="str", required=False, no_log=True),
01db47
         name=dict(
01db47
-            type="str", default=None, required=True, aliases=["zone_name"]
01db47
+            type="list", default=None, required=True, aliases=["zone_name"]
01db47
         ),
01db47
         forwarders=dict(
01db47
             type="list",
01db47
diff --git a/tests/dnszone/test_dnszone.yml b/tests/dnszone/test_dnszone.yml
01db47
index f7bd1f0..bd820df 100644
01db47
--- a/tests/dnszone/test_dnszone.yml
01db47
+++ b/tests/dnszone/test_dnszone.yml
01db47
@@ -149,3 +149,40 @@
01db47
       forwarders: []
01db47
     register: result
01db47
     failed_when: not result.changed
01db47
+
01db47
+  - name: Create zones test1
01db47
+    ipadnszone:
01db47
+      ipaadmin_password: SomeADMINpassword
01db47
+      name: test1.testzone.local
01db47
+
01db47
+  - name: Create zones test2
01db47
+    ipadnszone:
01db47
+      ipaadmin_password: SomeADMINpassword
01db47
+      name: test2.testzone.local
01db47
+
01db47
+  - name: Create zones test3
01db47
+    ipadnszone:
01db47
+      ipaadmin_password: SomeADMINpassword
01db47
+      name: test3.testzone.local
01db47
+
01db47
+  - name: Ensure multiple zones are absent
01db47
+    ipadnszone:
01db47
+      ipaadmin_password: SomeADMINpassword
01db47
+      name:
01db47
+        - test1.testzone.local
01db47
+        - test2.testzone.local
01db47
+        - test3.testzone.local
01db47
+      state: absent
01db47
+    register: result
01db47
+    failed_when: not result.changed
01db47
+
01db47
+  - name: Ensure multiple zones are absent, again
01db47
+    ipadnszone:
01db47
+      ipaadmin_password: SomeADMINpassword
01db47
+      name:
01db47
+        - test1.testzone.local
01db47
+        - test2.testzone.local
01db47
+        - test3.testzone.local
01db47
+      state: absent
01db47
+    register: result
01db47
+    failed_when: result.changed
01db47
-- 
01db47
2.26.2
01db47