From ccf61224f17e91fda49b1b126f8aea18d42a1bd2 Mon Sep 17 00:00:00 2001 From: thomasbargetz Date: Mon, 26 Jan 2026 17:16:33 +0100 Subject: [PATCH] keycloak_client: 11443: Fix false change detection for null client attributes (#11444) * 11443: fix diff for keycloak_client module for non existing client attributes * 11443: code cleanup * 11443: add changelog fragment * Adjust changelog fragment. --------- Co-authored-by: Thomas Bargetz Co-authored-by: Felix Fontein --- .../11443-fix-keycloak-client-diff-for-null-attributes.yml | 2 ++ plugins/modules/keycloak_client.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/11443-fix-keycloak-client-diff-for-null-attributes.yml diff --git a/changelogs/fragments/11443-fix-keycloak-client-diff-for-null-attributes.yml b/changelogs/fragments/11443-fix-keycloak-client-diff-for-null-attributes.yml new file mode 100644 index 0000000000..a28a98e3f1 --- /dev/null +++ b/changelogs/fragments/11443-fix-keycloak-client-diff-for-null-attributes.yml @@ -0,0 +1,2 @@ +bugfixes: + - keycloak_client - fix idempotency bug caused by ``null`` client attribute value differences for non-existing client attributes (https://github.com/ansible-collections/community.general/issues/11443, https://github.com/ansible-collections/community.general/pull/11444). \ No newline at end of file diff --git a/plugins/modules/keycloak_client.py b/plugins/modules/keycloak_client.py index 0bdf3d853b..c05a595ac5 100644 --- a/plugins/modules/keycloak_client.py +++ b/plugins/modules/keycloak_client.py @@ -1319,7 +1319,11 @@ def main(): new_param_value = flow_binding_from_dict_to_model(new_param_value, realm, kc) elif client_param == "attributes" and "attributes" in before_client: attributes_copy = copy.deepcopy(before_client["attributes"]) - attributes_copy.update(new_param_value) + # Merge client attributes while excluding null-valued attributes that are not present in Keycloak's response. + # This ensures idempotency by treating absent attributes and null attributes as equivalent. + attributes_copy.update( + {key: value for key, value in new_param_value.items() if value is not None or key in attributes_copy} + ) new_param_value = attributes_copy elif client_param in ["clientScopesBehavior", "client_scopes_behavior"]: continue