From 749fd8d9be0c9f810946eef665c2933f3db0140e Mon Sep 17 00:00:00 2001 From: Mostafa Abdelwahab Date: Sun, 3 May 2026 13:10:07 +0300 Subject: [PATCH 1/2] Add unit test to test precedence behavior between user-data.users and default user config Signed-off-by: Mostafa Abdelwahab --- .../distros/test_user_data_normalize.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/unittests/distros/test_user_data_normalize.py b/tests/unittests/distros/test_user_data_normalize.py index a1a77d1a0e9..925a5a93855 100644 --- a/tests/unittests/distros/test_user_data_normalize.py +++ b/tests/unittests/distros/test_user_data_normalize.py @@ -196,6 +196,30 @@ def test_users_dict_default_additional(self): assert users["bob"]["blah"] is True assert users["bob"]["default"] is True + def test_users_dict_override_default_attribute(self): + distro = self._make_distro("ubuntu", bcfg) + ug_cfg = { + "users": ["default", {"name": "bob", "lock_passwd": False}], + } + users, _ = self._norm(ug_cfg, distro) + + assert "bob" in users + assert "name" not in users["bob"] + + for key, val in bcfg.items(): + if key == "lock_passwd": + # Assert that the default user config is True + assert val is True + # Assert that the resolved value + # matches the passed config: False + assert users["bob"][key] is False + elif key == "groups": + assert users["bob"][key] == ",".join(val) + elif key != "name": + assert users["bob"][key] == val + + assert users["bob"]["default"] is True + def test_users_dict_extract(self): distro = self._make_distro("ubuntu", bcfg) ug_cfg = { From 8d31a7e4e48c9ecfe97e47135e446b0b31a0bfc7 Mon Sep 17 00:00:00 2001 From: Mostafa Abdelwahab Date: Sun, 3 May 2026 13:43:31 +0300 Subject: [PATCH 2/2] fix(ug_util): prioritize user-data.users over the default user config Signed-off-by: Mostafa Abdelwahab --- cloudinit/distros/ug_util.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cloudinit/distros/ug_util.py b/cloudinit/distros/ug_util.py index 2d0a887e7c4..53ad0a7d20b 100644 --- a/cloudinit/distros/ug_util.py +++ b/cloudinit/distros/ug_util.py @@ -134,13 +134,14 @@ def _normalize_users(u_cfg, def_user_cfg=None): # Now merge the extracted groups with the default config provided users_groups = util.uniq_merge_sorted(parsed_groups, def_groups) parsed_config["groups"] = ",".join(users_groups) - # The real config for the default user is the combination of the - # default user config provided by the distro, the default user - # config provided by the above merging for the user 'default' and - # then the parsed config from the user's 'real name' which does not - # have to be 'default' (but could be) + # The real config for the default user is the combination of: + # - the parsed config from the user's 'real name' which does + # not have to be 'default' (but could be) + # - then the default user config provided by the above merging + # for the user 'default' + # - then the default user config provided by the distro not users[def_user] = util.mergemanydict( - [def_user_cfg, def_config, parsed_config] + [parsed_config, def_config, def_user_cfg] ) # Ensure that only the default user that we found (if any) is actually