#9946 Regression in test_integration/test_pwpolicy.py::TestPWquality::test_graceperiod_not_replicated
Closed: fixed by frenaud. Opened by frenaud.

Issue

The commit https://github.com/freeipa/freeipa/commit/a1e76fa0b18ac0f7648c122645f76c3bd4c66818 introduced a regression in the test test_pwpolicy.py::TestPWquality::test_graceperiod_not_replicated.

Logs in https://$ARTIFACTS_SERVER/idm-ci/freeipa_upstream_nightly/Nightly-rawhide/master/2026-02-16_10-11/rawhide/test_pwpolicy/2/report.html?sort=result

self = <ipatests.test_integration.test_pwpolicy.TestPWquality object at 0x7f58831f9c70>
    def test_graceperiod_not_replicated(self):
        """Test that the grace period is reset on password reset"""
        dn = "uid={user},cn=users,cn=accounts,{base_dn}".format(
             user=USER, base_dn=str(self.master.domain.basedn))
        # Resetting the password will mark it as expired
        self.reset_password(self.master)
        # Generate some logins but don't exceed the limit
        for _i in range(2, -1, -1):
            result = self.master.run_command(
                ["ldapsearch", "-e", "ppolicy", "-D", dn,
                 "-w", PASSWORD, "-b", dn], raiseonerr=False
            )
        # Verify that passwordgraceusertime is not replicated
        result = tasks.ldapsearch_dm(
            self.master, dn, ['passwordgraceusertime',],
        )
        assert 'passwordgraceusertime: 3' in result.stdout_text.lower()
>       result = tasks.ldapsearch_dm(
            self.replicas[0], dn, ['passwordgraceusertime',],
        )
_i         = 0
dn         = 'uid=tuser,cn=users,cn=accounts,dc=ufreeipa,dc=test'
result     = <pytest_multihost.transport.SSHCommand object at 0x7f5883523770>
self       = <ipatests.test_integration.test_pwpolicy.TestPWquality object at 0x7f58831f9c70>
test_integration/test_pwpolicy.py:478: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pytest_ipa/integration/tasks.py:2495: in ldapsearch_dm
    return host.run_command(args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        args       = ['ldapsearch', '-x', '-ZZ', '-H', 'ldap://replica.ufreeipa.test', '-D', ...]
        base       = 'uid=tuser,cn=users,cn=accounts,dc=ufreeipa,dc=test'
        host       = <ipatests.pytest_ipa.integration.host.Host replica.ufreeipa.test (replica)>
        kwargs     = {}
        ldap_args  = ['passwordgraceusertime']
        scope      = 'sub'
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <ipatests.pytest_ipa.integration.host.Host replica.ufreeipa.test (replica)>
argv = ['ldapsearch', '-x', '-ZZ', '-H', 'ldap://replica.ufreeipa.test', '-D', ...]
set_env = True, stdin_text = None, log_stdout = True, raiseonerr = True
cwd = None, bg = False, encoding = 'utf-8', ok_returncode = 0
    def run_command(self, argv, set_env=True, stdin_text=None,
                    log_stdout=True, raiseonerr=True,
                    cwd=None, bg=False, encoding='utf-8', ok_returncode=0):
        """Wrapper around run_command to log stderr on raiseonerr=True
        :param ok_returncode: return code considered to be correct,
                              you can pass an integer or sequence of integers
        """
        result = super().run_command(
            argv, set_env=set_env, stdin_text=stdin_text,
            log_stdout=log_stdout, raiseonerr=False, cwd=cwd, bg=bg,
            encoding=encoding
        )
        # in FIPS mode SSH may print noise to stderr, remove the string
        # "FIPS mode initialized" + optional newline.
        result.stderr_bytes = FIPS_NOISE_RE.sub(b'', result.stderr_bytes)
        try:
            result_ok = result.returncode in ok_returncode
        except TypeError:
            result_ok = result.returncode == ok_returncode
        if not result_ok and raiseonerr:
            result.log.error('stderr: %s', result.stderr_text)
>           raise subprocess.CalledProcessError(
                result.returncode, argv,
                result.stdout_text, result.stderr_text
            )
E           subprocess.CalledProcessError: Command '['ldapsearch', '-x', '-ZZ', '-H', 'ldap://replica.ufreeipa.test', '-D', 'cn=Directory Manager', '-w', 'Secret.123', '-s', 'sub', '-b', 'uid=tuser,cn=users,cn=accounts,dc=ufreeipa,dc=test', '-o', 'ldif-wrap=no', '-LLL', 'passwordgraceusertime']' returned non-zero exit status 1.
__class__  = <class 'ipatests.pytest_ipa.integration.host.Host'>
argv       = ['ldapsearch', '-x', '-ZZ', '-H', 'ldap://replica.ufreeipa.test', '-D', ...]
bg         = False
cwd        = None
encoding   = 'utf-8'
log_stdout = True
ok_returncode = 0
raiseonerr = True
result     = <pytest_multihost.transport.SSHCommand object at 0x7f5883523930>
result_ok  = False
self       = <ipatests.pytest_ipa.integration.host.Host replica.ufreeipa.test (replica)>
set_env    = True
stdin_text = None
pytest_ipa/integration/host.py:202: CalledProcessError
----------------------------- Captured stderr call -----------------------------
ipa: ERROR: stderr: ldap_start_tls: Can't contact LDAP server (-1)

Steps to Reproduce

  1. Run the nightly test test_integration/test_pwpolicy.py::TestPWquality::test_graceperiod_not_replicated on the main branch

Actual behavior

The test does not install the replica any more but tries to read data from it.

Expected behavior

The test should install the replica.

Version/Release/Distribution

freeipa-server-4.14.0.dev202602160814+gita1e76fa0b-0.fc45.x86_64

Additional info:

The commit creates a new test class TestPWquality that inherits from BasePWpolicy.
As BasePWpolicy overrides the install method with task.install_master instead of super(TestPWPolicy, cls).install(mh), only the master gets installed.

The diff can be seen here.

IMO the base class BasePWpolicy should define num_replicas=0 and topology=line, and keep on calling super(TestPWPolicy, cls).install(mh).
This way, if a child class overrides num_replicas, the child class will have master + replicas installed without the need to override install.


Metadata Update from @frenaud:
- Custom field on_review adjusted to https://github.com/freeipa/freeipa/pull/8186
- Issue assigned to frenaud

master:

  • d1f0095a516fed16798bf015960d3ba053454a13 ipatests: fix install method for BasePWpolicy

ipa-4-12:

  • 7bcc67382e3c635b928cf86ec53010ffd4ce27d4 ipatests: fix install method for BasePWpolicy

ipa-4-13:

  • 5cd2639f539ce220c291b00afafa72fd35e1d07e ipatests: fix install method for BasePWpolicy

Metadata Update from @frenaud:
- Issue close_status updated to: fixed
- Issue status updated to: Closed (was: Open)

Metadata