From 8010d19be950c1533c5bb47b8004b8f574da6a45 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Mon, 14 Feb 2022 17:57:04 +0100
Subject: [PATCH] servicedelegation: Do not fail for not existing members with
 state absent

Ensuring absence of members (services and targets) that do not exist may
not fail as they are not members for servicedelegationtarget and
servicedelegationrule.

servicedelegation_normalize_principals in ansible_freeipa_module has
been extended with a check_exists argument that defaults to False. state
== "present" is now given as this argument to turn on the element exists
check only if elements should be added.
---
 .../module_utils/ansible_freeipa_module.py    |  8 +++--
 plugins/modules/ipaservicedelegationrule.py   |  6 ++--
 plugins/modules/ipaservicedelegationtarget.py |  4 +--
 .../test_servicedelegationrule.yml            | 30 +++++++++++++++++--
 .../test_servicedelegationtarget.yml          | 12 ++++++++
 5 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index 6485ec8f..aa40810a 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -551,7 +551,8 @@ else:
             return False
         return True
 
-    def servicedelegation_normalize_principals(module, principal):
+    def servicedelegation_normalize_principals(module, principal,
+                                               check_exists=False):
         """
         Normalize servicedelegation principals.
 
@@ -620,12 +621,13 @@ else:
                     _host = _host[:-len(realm) - 1]
 
                 # Seach for host
-                if not _check_exists(module, "host", _host):
+                if check_exists and not _check_exists(module, "host", _host):
                     module.fail_json(msg="Host '%s' does not exist" % _host)
 
             # Check the service principal exists
             else:
-                if not _check_exists(module, "service", princ):
+                if check_exists and \
+                   not _check_exists(module, "service", princ):
                     module.fail_json(msg="Service %s does not exist" % princ)
 
             _principal.append(princ)
diff --git a/plugins/modules/ipaservicedelegationrule.py b/plugins/modules/ipaservicedelegationrule.py
index 93e41b46..aaff1115 100644
--- a/plugins/modules/ipaservicedelegationrule.py
+++ b/plugins/modules/ipaservicedelegationrule.py
@@ -221,9 +221,9 @@ def main():
 
         # Normalize principals
         if principal:
-            principal = servicedelegation_normalize_principals(ansible_module,
-                                                               principal)
-        if target:
+            principal = servicedelegation_normalize_principals(
+                ansible_module, principal, state == "present")
+        if target and state == "present":
             check_targets(ansible_module, target)
 
         commands = []
diff --git a/plugins/modules/ipaservicedelegationtarget.py b/plugins/modules/ipaservicedelegationtarget.py
index a17accae..59b3418c 100644
--- a/plugins/modules/ipaservicedelegationtarget.py
+++ b/plugins/modules/ipaservicedelegationtarget.py
@@ -177,8 +177,8 @@ def main():
 
         # Normalize principals
         if principal:
-            principal = servicedelegation_normalize_principals(ansible_module,
-                                                               principal)
+            principal = servicedelegation_normalize_principals(
+                ansible_module, principal, state == "present")
 
         commands = []
         principal_add = principal_del = []
diff --git a/tests/servicedelegationrule/test_servicedelegationrule.yml b/tests/servicedelegationrule/test_servicedelegationrule.yml
index 0e351e8b..5b847359 100644
--- a/tests/servicedelegationrule/test_servicedelegationrule.yml
+++ b/tests/servicedelegationrule/test_servicedelegationrule.yml
@@ -21,7 +21,9 @@
     ipaservice:
       ipaadmin_password: SomeADMINpassword
       ipaapi_context: "{{ ipa_context | default(omit) }}"
-      name: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
+      name:
+      - "{{ 'test-service/' + ansible_facts['fqdn'] }}"
+      - "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
       state: absent
       continue: yes
 
@@ -29,7 +31,9 @@
     ipaservicedelegationtarget:
       ipaadmin_password: SomeADMINpassword
       ipaapi_context: "{{ ipa_context | default(omit) }}"
-      name: test-delegation-target
+      name:
+      - test-delegation-target
+      - not-existing-test-delegation-target
       state: absent
 
   # CREATE TEST ITEMS
@@ -68,6 +72,28 @@
     register: result
     failed_when: result.changed or result.failed
 
+  - name: Do not fail to ensure absence of not existing servicedelegationrule test-delegation-rule member principal
+    ipaservicedelegationrule:
+      ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
+      name: test-delegation-rule
+      principal: "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
+      action: member
+      state: absent
+    register: result
+    failed_when: result.changed or result.failed
+
+  - name: Do not fail to ensure absence of not existing servicedelegationrule test-delegation-rule member target
+    ipaservicedelegationrule:
+      ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
+      name: test-delegation-rule
+      target: not-existing-test-delegation-target
+      action: member
+      state: absent
+    register: result
+    failed_when: result.changed or result.failed
+
   - name: Ensure servicedelegationrule test-delegation-rule member target test-delegation-target is present
     ipaservicedelegationrule:
       ipaadmin_password: SomeADMINpassword
diff --git a/tests/servicedelegationtarget/test_servicedelegationtarget.yml b/tests/servicedelegationtarget/test_servicedelegationtarget.yml
index aeb1aa4a..acb9e3f1 100644
--- a/tests/servicedelegationtarget/test_servicedelegationtarget.yml
+++ b/tests/servicedelegationtarget/test_servicedelegationtarget.yml
@@ -25,6 +25,7 @@
       - "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
       - "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
       - "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
+      - "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
       state: absent
       continue: yes
 
@@ -72,6 +73,17 @@
     register: result
     failed_when: result.changed or result.failed
 
+  - name: Do not fail to ensure absence of not existing servicedelegationtarget test-delegation-target member principal
+    ipaservicedelegationtarget:
+      ipaadmin_password: SomeADMINpassword
+      ipaapi_context: "{{ ipa_context | default(omit) }}"
+      name: test-delegation-target
+      principal: "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
+      action: member
+      state: absent
+    register: result
+    failed_when: result.changed or result.failed
+
   - name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is present
     ipaservicedelegationtarget:
       ipaadmin_password: SomeADMINpassword
-- 
GitLab