From fedba4655bb7fdcd8e15928b5adfcf8809103b8c Mon Sep 17 00:00:00 2001 From: Guillaume Dorschner Date: Fri, 19 Dec 2025 11:52:39 +0100 Subject: [PATCH 1/5] fix: idempotence boolean compare --- ...???-keycloak-clientscope-change-problem.yml | 4 ++++ plugins/modules/keycloak_clientscope.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 changelogs/fragments/???-keycloak-clientscope-change-problem.yml diff --git a/changelogs/fragments/???-keycloak-clientscope-change-problem.yml b/changelogs/fragments/???-keycloak-clientscope-change-problem.yml new file mode 100644 index 0000000000..8d1feff08c --- /dev/null +++ b/changelogs/fragments/???-keycloak-clientscope-change-problem.yml @@ -0,0 +1,4 @@ +--- +bugfixes: +- keycloak_clientscope - fixed `normalise_cr()` to properly convert string "true"/"false" values to Python booleans. + Before boolean-like strings caused Ansible to always report `changed=True` even when the configuration hadn't actually changed. \ No newline at end of file diff --git a/plugins/modules/keycloak_clientscope.py b/plugins/modules/keycloak_clientscope.py index 61763886a9..b873f18f75 100644 --- a/plugins/modules/keycloak_clientscope.py +++ b/plugins/modules/keycloak_clientscope.py @@ -298,6 +298,21 @@ from ansible_collections.community.general.plugins.module_utils.identity.keycloa ) from ansible.module_utils.basic import AnsibleModule +def normalise_boolean(obj): + """ + Recursive fonction to traverse the obj and unify the boolean values. + """ + if isinstance(obj, dict): + return {k: normalise_boolean(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [normalise_boolean(v) for v in obj] + elif isinstance(obj, str): + if obj.lower() == "true": + return True + elif obj.lower() == "false": + return False + return obj + def normalise_cr(clientscoperep, remove_ids=False): """Re-sorts any properties where the order so that diff's is minimised, and adds default values where appropriate so that the @@ -319,6 +334,9 @@ def normalise_cr(clientscoperep, remove_ids=False): if remove_ids: mapper.pop("id", None) + for key, value in mapper.items(): + mapper[key] = normalise_boolean(value) + # Set to a default value. mapper["consentRequired"] = mapper.get("consentRequired", False) From f0aa08aca65caf3fc4347df8e53ea7a3dad58740 Mon Sep 17 00:00:00 2001 From: Guillaume Dorschner Date: Fri, 19 Dec 2025 12:00:06 +0100 Subject: [PATCH 2/5] change fragments id with pr id --- ...-problem.yml => 11296-keycloak-clientscope-change-problem.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelogs/fragments/{???-keycloak-clientscope-change-problem.yml => 11296-keycloak-clientscope-change-problem.yml} (100%) diff --git a/changelogs/fragments/???-keycloak-clientscope-change-problem.yml b/changelogs/fragments/11296-keycloak-clientscope-change-problem.yml similarity index 100% rename from changelogs/fragments/???-keycloak-clientscope-change-problem.yml rename to changelogs/fragments/11296-keycloak-clientscope-change-problem.yml From 7928b70c2ae6c87883fb67f5944878d12af7da53 Mon Sep 17 00:00:00 2001 From: Guillaume Dorschner Date: Fri, 19 Dec 2025 12:05:09 +0100 Subject: [PATCH 3/5] fix: indentation --- plugins/modules/keycloak_clientscope.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/modules/keycloak_clientscope.py b/plugins/modules/keycloak_clientscope.py index b873f18f75..eb74294b25 100644 --- a/plugins/modules/keycloak_clientscope.py +++ b/plugins/modules/keycloak_clientscope.py @@ -303,14 +303,14 @@ def normalise_boolean(obj): Recursive fonction to traverse the obj and unify the boolean values. """ if isinstance(obj, dict): - return {k: normalise_boolean(v) for k, v in obj.items()} + return {k: normalise_boolean(v) for k, v in obj.items()} elif isinstance(obj, list): - return [normalise_boolean(v) for v in obj] + return [normalise_boolean(v) for v in obj] elif isinstance(obj, str): - if obj.lower() == "true": - return True - elif obj.lower() == "false": - return False + if obj.lower() == "true": + return True + elif obj.lower() == "false": + return False return obj @@ -335,7 +335,7 @@ def normalise_cr(clientscoperep, remove_ids=False): mapper.pop("id", None) for key, value in mapper.items(): - mapper[key] = normalise_boolean(value) + mapper[key] = normalise_boolean(value) # Set to a default value. mapper["consentRequired"] = mapper.get("consentRequired", False) From b92d94db23da476822af6a82146082e936d7d6ae Mon Sep 17 00:00:00 2001 From: Guillaume Dorschner Date: Fri, 19 Dec 2025 12:27:40 +0100 Subject: [PATCH 4/5] added: blank line --- plugins/modules/keycloak_clientscope.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/keycloak_clientscope.py b/plugins/modules/keycloak_clientscope.py index eb74294b25..a14c2d1bac 100644 --- a/plugins/modules/keycloak_clientscope.py +++ b/plugins/modules/keycloak_clientscope.py @@ -298,6 +298,7 @@ from ansible_collections.community.general.plugins.module_utils.identity.keycloa ) from ansible.module_utils.basic import AnsibleModule + def normalise_boolean(obj): """ Recursive fonction to traverse the obj and unify the boolean values. From 478cd50be16406273051ff796d9e59bacea3ad6e Mon Sep 17 00:00:00 2001 From: Guillaume Dorschner <44686652+GuillaumeDorschner@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:02:01 +0100 Subject: [PATCH 5/5] Update changelogs/fragments/11296-keycloak-clientscope-change-problem.yml Co-authored-by: Felix Fontein --- .../fragments/11296-keycloak-clientscope-change-problem.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/changelogs/fragments/11296-keycloak-clientscope-change-problem.yml b/changelogs/fragments/11296-keycloak-clientscope-change-problem.yml index 8d1feff08c..5f99d2e5c5 100644 --- a/changelogs/fragments/11296-keycloak-clientscope-change-problem.yml +++ b/changelogs/fragments/11296-keycloak-clientscope-change-problem.yml @@ -1,4 +1,5 @@ --- bugfixes: -- keycloak_clientscope - fixed `normalise_cr()` to properly convert string "true"/"false" values to Python booleans. - Before boolean-like strings caused Ansible to always report `changed=True` even when the configuration hadn't actually changed. \ No newline at end of file +- keycloak_clientscope - fixed ``normalise_cr()`` to properly convert string ``"true"`` / ``"false"`` values to Python booleans. + Before boolean-like strings caused Ansible to always report ``changed=true`` even when the configuration had not actually changed + (https://github.com/ansible-collections/community.general/pull/11296). \ No newline at end of file