From f0940d82dc53f843e598d073a7ed102f8e50e628 Mon Sep 17 00:00:00 2001
From: Felix Fontein <felix@fontein.de>
Date: Thu, 13 Jun 2024 21:54:42 +0200
Subject: [PATCH] homectl, udm_user: guard crypt imports (#8497)

Guard crypt import.
---
 changelogs/fragments/8497-crypt.yml |  3 +++
 plugins/modules/homectl.py          | 25 +++++++++++++++++++++++--
 plugins/modules/udm_user.py         | 26 ++++++++++++++++++++++++--
 3 files changed, 50 insertions(+), 4 deletions(-)
 create mode 100644 changelogs/fragments/8497-crypt.yml

diff --git a/changelogs/fragments/8497-crypt.yml b/changelogs/fragments/8497-crypt.yml
new file mode 100644
index 0000000000..f77f6c20f9
--- /dev/null
+++ b/changelogs/fragments/8497-crypt.yml
@@ -0,0 +1,3 @@
+known_issues:
+  - "homectl - the module does not work under Python 3.13 or newer, since it relies on the removed ``crypt`` standard library module (https://github.com/ansible-collections/community.general/issues/4691, https://github.com/ansible-collections/community.general/pull/8497)."
+  - "udm_user - the module does not work under Python 3.13 or newer, since it relies on the removed ``crypt`` standard library module (https://github.com/ansible-collections/community.general/issues/4690, https://github.com/ansible-collections/community.general/pull/8497)."
diff --git a/plugins/modules/homectl.py b/plugins/modules/homectl.py
index ca4c19a875..7751651c85 100644
--- a/plugins/modules/homectl.py
+++ b/plugins/modules/homectl.py
@@ -17,6 +17,12 @@ short_description: Manage user accounts with systemd-homed
 version_added: 4.4.0
 description:
     - Manages a user's home directory managed by systemd-homed.
+notes:
+    - This module does B(not) work with Python 3.13 or newer. It uses the deprecated L(crypt Python module,
+      https://docs.python.org/3.12/library/crypt.html) from the Python standard library, which was removed
+      from Python 3.13.
+requirements:
+    - Python 3.12 or earlier
 extends_documentation_fragment:
     - community.general.attributes
 attributes:
@@ -263,12 +269,21 @@ data:
     }
 '''
 
-import crypt
 import json
-from ansible.module_utils.basic import AnsibleModule
+import traceback
+from ansible.module_utils.basic import AnsibleModule, missing_required_lib
 from ansible.module_utils.basic import jsonify
 from ansible.module_utils.common.text.formatters import human_to_bytes
 
+try:
+    import crypt
+except ImportError:
+    HAS_CRYPT = False
+    CRYPT_IMPORT_ERROR = traceback.format_exc()
+else:
+    HAS_CRYPT = True
+    CRYPT_IMPORT_ERROR = None
+
 
 class Homectl(object):
     '''#TODO DOC STRINGS'''
@@ -591,6 +606,12 @@ def main():
         ]
     )
 
+    if not HAS_CRYPT:
+        module.fail_json(
+            msg=missing_required_lib('crypt (part of Python 3.13 standard library)'),
+            exception=CRYPT_IMPORT_ERROR,
+        )
+
     homectl = Homectl(module)
     homectl.result['state'] = homectl.state
 
diff --git a/plugins/modules/udm_user.py b/plugins/modules/udm_user.py
index dcbf0ec85e..5a2e090497 100644
--- a/plugins/modules/udm_user.py
+++ b/plugins/modules/udm_user.py
@@ -20,6 +20,12 @@ description:
     - "This module allows to manage posix users on a univention corporate
        server (UCS).
        It uses the python API of the UCS to create a new object or edit it."
+notes:
+    - This module does B(not) work with Python 3.13 or newer. It uses the deprecated L(crypt Python module,
+      https://docs.python.org/3.12/library/crypt.html) from the Python standard library, which was removed
+      from Python 3.13.
+requirements:
+    - Python 3.12 or earlier
 extends_documentation_fragment:
     - community.general.attributes
 attributes:
@@ -324,10 +330,10 @@ EXAMPLES = '''
 
 RETURN = '''# '''
 
-import crypt
 from datetime import date, timedelta
+import traceback
 
-from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.basic import AnsibleModule, missing_required_lib
 from ansible_collections.community.general.plugins.module_utils.univention_umc import (
     umc_module_for_add,
     umc_module_for_edit,
@@ -335,6 +341,15 @@ from ansible_collections.community.general.plugins.module_utils.univention_umc i
     base_dn,
 )
 
+try:
+    import crypt
+except ImportError:
+    HAS_CRYPT = False
+    CRYPT_IMPORT_ERROR = traceback.format_exc()
+else:
+    HAS_CRYPT = True
+    CRYPT_IMPORT_ERROR = None
+
 
 def main():
     expiry = date.strftime(date.today() + timedelta(days=365), "%Y-%m-%d")
@@ -451,6 +466,13 @@ def main():
             ('state', 'present', ['firstname', 'lastname', 'password'])
         ])
     )
+
+    if not HAS_CRYPT:
+        module.fail_json(
+            msg=missing_required_lib('crypt (part of Python 3.13 standard library)'),
+            exception=CRYPT_IMPORT_ERROR,
+        )
+
     username = module.params['username']
     position = module.params['position']
     ou = module.params['ou']