diff --git a/changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml b/changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml new file mode 100644 index 00000000000..2424b3397e4 --- /dev/null +++ b/changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml @@ -0,0 +1,2 @@ +bugfixes: + - Lookup user by UID in password database if login name is not found (https://github.com/ansible/ansible/issues/17029) diff --git a/lib/ansible/module_utils/facts/system/user.py b/lib/ansible/module_utils/facts/system/user.py index 745b5db3f6f..35a07759950 100644 --- a/lib/ansible/module_utils/facts/system/user.py +++ b/lib/ansible/module_utils/facts/system/user.py @@ -35,7 +35,10 @@ class UserFactCollector(BaseFactCollector): user_facts['user_id'] = getpass.getuser() - pwent = pwd.getpwnam(getpass.getuser()) + try: + pwent = pwd.getpwnam(getpass.getuser()) + except KeyError: + pwent = pwd.getpwuid(os.getuid()) user_facts['user_uid'] = pwent.pw_uid user_facts['user_gid'] = pwent.pw_gid diff --git a/test/units/module_utils/facts/system/test_user.py b/test/units/module_utils/facts/system/test_user.py new file mode 100644 index 00000000000..5edfe146bc4 --- /dev/null +++ b/test/units/module_utils/facts/system/test_user.py @@ -0,0 +1,40 @@ +# unit tests for ansible system lsb fact collectors +# -*- coding: utf-8 -*- +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.module_utils.facts.system.user import UserFactCollector + +import os + + +def test_logname(): + """ Test if ``UserFactCollector`` still works with LOGNAME set """ + collector = UserFactCollector() + + unmodified_facts = collector.collect() + # Change logname env var and check if the collector still finds + # the pw entry. + os.environ["LOGNAME"] = "NONEXISTINGUSERDONTEXISTPLEASE" + modified_facts = collector.collect() + + # Set logname should be different to the real name. + assert unmodified_facts['user_id'] != modified_facts['user_id'] + # Actual UID is the same. + assert unmodified_facts['user_uid'] == modified_facts['user_uid']