URL: https://github.com/freeipa/freeipa/pull/3251
Author: rcritten
 Title: #3251: [Backport][ipa-4-7] Work around autoremember-build timing issue 
test failures
Action: opened

PR body:
"""
This PR was opened automatically because PR #3242 was pushed to master and 
backport to ipa-4-7 is required.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/3251/head:pr3251
git checkout pr3251
From 8559064f2bf3f8450d80b4e1b70bcaf24c48dddc Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Mon, 10 Jun 2019 13:52:08 -0400
Subject: [PATCH] tests: Wait for automember rebuild --no-wait tasks to finish

The behavior of automember changed with the design
https://www.port389.org/docs/389ds/design/automember-postop-modify-design.html
such that members are "cleaned up" first then re-added. This has
the effect of removing members that no longer apply to a rule.

This was breaking the automember rebuild tests because sometimes
the tests were faster than 389-ds causing memberships to be missed.

This does a client-side wait for the task to finish up so still
exercises the rebuild code.

https://pagure.io/freeipa/issue/7972

Signed-off-by: Rob Crittenden <rcrit...@redhat.com>
---
 .../test_xmlrpc/test_automember_plugin.py     | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/ipatests/test_xmlrpc/test_automember_plugin.py b/ipatests/test_xmlrpc/test_automember_plugin.py
index 7f61929b56..344d682c24 100644
--- a/ipatests/test_xmlrpc/test_automember_plugin.py
+++ b/ipatests/test_xmlrpc/test_automember_plugin.py
@@ -31,7 +31,9 @@
 from ipapython.ipautil import run
 from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test, raises_exact
 from ipatests.util import assert_deepequal
+from ipaserver.plugins.automember import REBUILD_TASK_CONTAINER
 
+import time
 import pytest
 import unittest
 
@@ -275,6 +277,52 @@ def set_automember_process_modify_ops(value):
     run(cmd)
 
 
+def wait_automember_rebuild():
+    """Wait for an asynchronous automember rebuild to finish
+
+    Lookup the rebuild taskid and then loop until it is finished.
+
+    If no task is found assume that the task is already finished.
+    """
+    if not have_ldap2:
+        raise unittest.SkipTest('server plugin not available')
+    ldap = ldap2(api)
+    ldap.connect()
+
+    # give the task a chance to start
+    time.sleep(1)
+
+    try:
+        task_entries, unused = ldap.find_entries(
+            base_dn=REBUILD_TASK_CONTAINER,
+            filter='(&(!(nstaskexitcode=0))(scope=*))')
+    except errors.NotFound:
+        # either it's done already or it never started
+        return
+
+    # we run these serially so there should be only one at a time
+    assert len(task_entries) == 1
+
+    task_dn = task_entries[0].dn
+
+    start_time = time.time()
+    while True:
+        try:
+            task = ldap.get_entry(task_dn)
+        except errors.NotFound:
+            # not likely but let's hope the task disappered because it's
+            # finished
+            break
+
+        if 'nstaskexitcode' in task:
+            # a non-zero exit code means something broke
+            assert task.single_value['nstaskexitcode'] == '0'
+            break
+        time.sleep(1)
+        # same arbitrary wait time as hardcoded in automember plugin
+        assert time.time() < (start_time + 60)
+
+
 @pytest.mark.tier1
 class TestAutomemberRebuildHostMembership(XMLRPC_test):
     def test_create_deps_for_rebuilding_hostgroups(self, hostgroup1, host1,
@@ -302,6 +350,7 @@ def test_rebuild_membership_hostgroups(self, automember_hostgroup,
             set_automember_process_modify_ops(value=b'off')
             automember_hostgroup.rebuild()
             automember_hostgroup.rebuild(no_wait=True)
+            wait_automember_rebuild()
             # After rebuild, the member is added, and we need to update
             # the tracker obj
             hostgroup1.attrs.update(member_host=[host1.fqdn])
@@ -315,6 +364,7 @@ def test_rebuild_membership_hostgroups(self, automember_hostgroup,
         # Rebuild membership to re-add the member
         automember_hostgroup.rebuild()
         automember_hostgroup.rebuild(no_wait=True)
+        wait_automember_rebuild()
         # After rebuild, the member is added, and we need to update
         # the tracker obj
         hostgroup1.attrs.update(member_host=[host1.fqdn])
@@ -342,6 +392,7 @@ def test_rebuild_membership_for_host(self, host1, automember_hostgroup,
                                                             no_wait=True)
         result = command()
         automember_hostgroup.check_rebuild(result, no_wait=True)
+        wait_automember_rebuild()
 
         hostgroup1.attrs.update(member_host=[host1.fqdn])
         hostgroup1.retrieve()
@@ -380,6 +431,7 @@ def test_rebuild_membership_groups(self, automember_group, group1, user1):
             set_automember_process_modify_ops(value=b'off')
             automember_group.rebuild()
             automember_group.rebuild(no_wait=True)
+            wait_automember_rebuild()
             # After rebuild, the member is added, and we need to update
             # the tracker obj
             group1.attrs.update(member_user=[user1.name])
@@ -393,6 +445,7 @@ def test_rebuild_membership_groups(self, automember_group, group1, user1):
         # Rebuild membership to re-add the member
         automember_group.rebuild()
         automember_group.rebuild(no_wait=True)
+        wait_automember_rebuild()
         # After rebuild, the member is added, and we need to update
         # the tracker obj
         group1.attrs.update(member_user=[user1.name])
@@ -419,6 +472,7 @@ def test_rebuild_membership_for_user(self, user1, automember_group,
                                                         no_wait=True)
         result = command()
         automember_group.check_rebuild(result, no_wait=True)
+        wait_automember_rebuild()
         group1.attrs.update(member_user=[user1.name])
         group1.retrieve()
 
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to