1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Fixes #1226 - keycloak_client detects changes on check_mode but not in run mode (#7881)

* Fix warning integrated

* Update Keycloak version intergrated test

* Exclude metadata from diff test

* Sanity

* Add fragments

* typo

* Add test

* Update changelogs/fragments/7881-fix-keycloak-client-ckeckmode.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* Remove docker compose

* Update changelogs/fragments/7881-fix-keycloak-client-ckeckmode.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Andre Desrosiers <andre.desrosiers@ssss.gouv.qc.ca>
Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
desand01 2024-02-17 06:31:45 -05:00 committed by GitHub
parent 8ea58618db
commit 001292c780
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 98 additions and 82 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- keycloak_client - fixes issue when metadata is provided in desired state when task is in check mode (https://github.com/ansible-collections/community.general/issues/1226, https://github.com/ansible-collections/community.general/pull/7881).

View file

@ -717,13 +717,14 @@ end_state:
'''
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, camel, \
keycloak_argument_spec, get_token, KeycloakError
keycloak_argument_spec, get_token, KeycloakError, is_struct_included
from ansible.module_utils.basic import AnsibleModule
import copy
PROTOCOL_OPENID_CONNECT = 'openid-connect'
PROTOCOL_SAML = 'saml'
CLIENT_META_DATA = ['authorizationServicesEnabled']
def normalise_cr(clientrep, remove_ids=False):
@ -946,7 +947,7 @@ def main():
if module._diff:
result['diff'] = dict(before=sanitize_cr(before_norm),
after=sanitize_cr(desired_norm))
result['changed'] = (before_norm != desired_norm)
result['changed'] = not is_struct_included(desired_norm, before_norm, CLIENT_META_DATA)
module.exit_json(**result)

View file

@ -4,14 +4,16 @@ GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://w
SPDX-License-Identifier: GPL-3.0-or-later
-->
The integration test can be performed as follows:
# Running keycloak_client module integration test
```
# 1. Start docker-compose:
docker-compose -f tests/integration/targets/keycloak_client/docker-compose.yml stop
docker-compose -f tests/integration/targets/keycloak_client/docker-compose.yml rm -f -v
docker-compose -f tests/integration/targets/keycloak_client/docker-compose.yml up -d
To run Keycloak client module's integration test, start a keycloak server using Docker:
# 2. Run the integration tests:
ansible-test integration keycloak_client --allow-unsupported -v
```
docker run -d --rm --name mykeycloak -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=password quay.io/keycloak/keycloak:latest start-dev --http-relative-path /auth
Run the integration tests:
ansible-test integration -v keycloak_client --allow-unsupported --docker fedora35 --docker-network host
Cleanup:
docker stop mykeycloak

View file

@ -1,31 +0,0 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
version: '3.4'
services:
postgres:
image: postgres:9.6
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_DB: postgres
POSTGRES_PASSWORD: postgres
keycloak:
image: jboss/keycloak:12.0.4
ports:
- 8080:8080
environment:
DB_VENDOR: postgres
DB_ADDR: postgres
DB_DATABASE: postgres
DB_USER: postgres
DB_SCHEMA: public
DB_PASSWORD: postgres
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: password

View file

@ -2,58 +2,78 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Wait for Keycloak
uri:
url: "{{ url }}/admin/"
status_code: 200
validate_certs: no
register: result
until: result.status == 200
retries: 10
delay: 10
- name: Delete realm
community.general.keycloak_realm: "{{ auth_args | combine(call_args) }}"
vars:
call_args:
id: "{{ realm }}"
realm: "{{ realm }}"
state: absent
community.general.keycloak_realm:
auth_keycloak_url: "{{ url }}"
auth_realm: "{{ admin_realm }}"
auth_username: "{{ admin_user }}"
auth_password: "{{ admin_password }}"
id: "{{ realm }}"
realm: "{{ realm }}"
state: absent
- name: Create realm
community.general.keycloak_realm: "{{ auth_args | combine(call_args) }}"
vars:
call_args:
id: "{{ realm }}"
realm: "{{ realm }}"
state: present
community.general.keycloak_realm:
auth_keycloak_url: "{{ url }}"
auth_realm: "{{ admin_realm }}"
auth_username: "{{ admin_user }}"
auth_password: "{{ admin_password }}"
id: "{{ realm }}"
realm: "{{ realm }}"
state: present
- name: Desire client
community.general.keycloak_client: "{{ auth_args | combine(call_args) }}"
vars:
call_args:
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
community.general.keycloak_client:
auth_keycloak_url: "{{ url }}"
auth_realm: "{{ admin_realm }}"
auth_username: "{{ admin_user }}"
auth_password: "{{ admin_password }}"
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
register: desire_client_not_present
- name: Desire client again with same props
community.general.keycloak_client: "{{ auth_args | combine(call_args) }}"
vars:
call_args:
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
community.general.keycloak_client:
auth_keycloak_url: "{{ url }}"
auth_realm: "{{ admin_realm }}"
auth_username: "{{ admin_user }}"
auth_password: "{{ admin_password }}"
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
register: desire_client_when_present_and_same
- name: Check client again with same props
community.general.keycloak_client: "{{ auth_args | combine(call_args) }}"
community.general.keycloak_client:
auth_keycloak_url: "{{ url }}"
auth_realm: "{{ admin_realm }}"
auth_username: "{{ admin_user }}"
auth_password: "{{ admin_password }}"
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
authorization_services_enabled: False
check_mode: true
vars:
call_args:
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
register: check_client_when_present_and_same
- name: Assert changes not detected in last two tasks (desire when same, and check)
@ -61,3 +81,25 @@
that:
- desire_client_when_present_and_same is not changed
- check_client_when_present_and_same is not changed
- name: Check client again with changed props
community.general.keycloak_client:
auth_keycloak_url: "{{ url }}"
auth_realm: "{{ admin_realm }}"
auth_username: "{{ admin_user }}"
auth_password: "{{ admin_password }}"
realm: "{{ realm }}"
client_id: "{{ client_id }}"
state: present
redirect_uris: '{{redirect_uris1}}'
attributes: '{{client_attributes1}}'
protocol_mappers: '{{protocol_mappers1}}'
authorization_services_enabled: False
service_accounts_enabled: True
check_mode: true
register: check_client_when_present_and_changed
- name: Assert changes detected in last tasks
assert:
that:
- check_client_when_present_and_changed is changed

View file

@ -24,7 +24,7 @@ redirect_uris1:
- "http://example.b.com/"
- "http://example.a.com/"
client_attributes1: {"backchannel.logout.session.required": true, "backchannel.logout.revoke.offline.tokens": false}
client_attributes1: {"backchannel.logout.session.required": true, "backchannel.logout.revoke.offline.tokens": false, "client.secret.creation.time": 0}
protocol_mappers1:
- name: 'email'