From 90b110794f8ee9905c48ce7c524bcbb46e53ec74 Mon Sep 17 00:00:00 2001 From: Jakob Meng Date: Mon, 22 Aug 2022 14:09:39 +0200 Subject: [PATCH] Refactored federation_idp{,_info} modules Change-Id: Icbff6c799a9c33f1104633f7d9521f02228217a5 --- ci/roles/keystone_idp/defaults/main.yml | 37 +- ci/roles/keystone_idp/tasks/main.yml | 708 ++++++++++++------------ ci/run-collection.yml | 4 +- plugins/modules/federation_idp.py | 242 +++----- plugins/modules/federation_idp_info.py | 93 ++-- 5 files changed, 493 insertions(+), 591 deletions(-) diff --git a/ci/roles/keystone_idp/defaults/main.yml b/ci/roles/keystone_idp/defaults/main.yml index 7c9b5acf..2c9ce7e8 100644 --- a/ci/roles/keystone_idp/defaults/main.yml +++ b/ci/roles/keystone_idp/defaults/main.yml @@ -1,29 +1,14 @@ -idp_name: 'test-idp' -idp_name_2: 'test-idp-2' -idp_description: 'My example IDP' -idp_description_2: 'My example Identity Provider' - -domain_name: 'test-domain' +expected_fields: + - description + - domain_id + - id + - is_enabled + - name + - remote_ids remote_ids_1: -- 'https://auth.example.com/auth/realms/ExampleRealm' -- 'https://auth.stage.example.com/auth/realms/ExampleRealm' + - 'https://auth.example.com/auth/realms/ExampleRealm' + - 'https://auth.stage.example.com/auth/realms/ExampleRealm' remote_ids_2: -- 'https://auth.example.com/auth/realms/ExampleRealm' + - 'https://auth.example.com/auth/realms/ExampleRealm' remote_ids_3: -- 'https://auth.stage.example.com/auth/realms/ExampleRealm' - -idp_info_expected_fields: - - description - - domain_id - - id - - is_enabled - - name - - remote_ids - -idp_expected_fields: - - description - - domain_id - - id - - is_enabled - - name - - remote_ids + - 'https://auth.stage.example.com/auth/realms/ExampleRealm' diff --git a/ci/roles/keystone_idp/tasks/main.yml b/ci/roles/keystone_idp/tasks/main.yml index 5486c5e3..2434c4ad 100644 --- a/ci/roles/keystone_idp/tasks/main.yml +++ b/ci/roles/keystone_idp/tasks/main.yml @@ -18,136 +18,133 @@ block: # ======================================================================== # Initial setup + - name: 'Create test domain' openstack.cloud.identity_domain: - name: '{{ domain_name }}' - register: create_domain - - name: 'Store domain ID as fact' - set_fact: - domain_id: '{{ create_domain.domain.id }}' + name: ansible_domain + register: domain - # We *should* have a blank slate to start with, but we also shouldn't - # explode if I(state=absent) and the IDP doesn't exist + # We *should* have a blank slate to start with, but we also should not + # explode if state is absent and the identity provider does not exist - name: "Ensure IDP doesn't exist to start" openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name }}' - register: delete_idp - - assert: - that: - - delete_idp is successful + state: absent + name: 'ansible_identity_provider' # ======================================================================== # Creation (simple case) - name: 'Create IDP - CHECK_MODE' - check_mode: yes + check_mode: true openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - domain_id: '{{ domain_id }}' - register: create_idp + state: present + id: 'ansible_identity_provider' + domain_id: '{{ domain.domain.id }}' + register: idp + - assert: that: - - create_idp is successful - - create_idp is changed + - idp is changed - name: 'Fetch identity_provider info (provider should be absent)' openstack.cloud.federation_idp_info: - name: '{{ idp_name }}' - register: identity_provider_info + name: 'ansible_identity_provider' + register: idps + - assert: that: - - identity_provider_info.identity_providers | length == 0 + - idps.identity_providers | length == 0 - name: 'Create IDP' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - domain_id: '{{ domain_id }}' - register: create_identity_provider + state: present + name: 'ansible_identity_provider' + domain_id: '{{ domain.domain.id }}' + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - not idp.description - - idp.is_enabled == True - - idp.remote_ids == [] + - idp is changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - not _idp.description + - _idp.is_enabled == False + - _idp.remote_ids == [] vars: - idp: '{{ create_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - - name: Verify returned values + - name: Assert return values of federation_idp module assert: - that: item in create_identity_provider.identity_provider - loop: "{{ idp_expected_fields }}" + that: + # allow new fields to be introduced but prevent fields from being removed + - expected_fields|difference(idp.identity_provider.keys())|length == 0 - name: 'Fetch IDP info - with name' openstack.cloud.federation_idp_info: - name: '{{ idp_name }}' - register: identity_provider_info + name: 'ansible_identity_provider' + register: idps - assert: that: - - idps | length == 1 - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - not idp.description - - idp.is_enabled == True - - idp.remote_ids == [] + - _idps | length == 1 + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - not _idp.description + - _idp.is_enabled == False + - _idp.remote_ids == [] vars: - idps: '{{ identity_provider_info.identity_providers }}' - idp: '{{ identity_provider_info.identity_providers[0] }}' + _idps: '{{ idps.identity_providers }}' + _idp: '{{ idps.identity_providers[0] }}' - - name: Verify returned values + - name: Assert return values of federation_idp_info module assert: - that: item in identity_provider_info.identity_providers[0] - loop: "{{ idp_info_expected_fields }}" + that: + # allow new fields to be introduced but prevent fields from being removed + - expected_fields|difference(idps.identity_providers.0.keys())|length == 0 - name: 'Fetch identity_provider info - without name' openstack.cloud.federation_idp_info: {} - register: identity_provider_info + register: idps + - assert: that: - - '"identity_providers" in identity_provider_info' # In CI we generally have a clean slate, but this might # not be true for everyone... - - idps | length >= 1 + - _idps | length >= 1 vars: - idps: '{{ identity_provider_info.identity_providers }}' + _idps: '{{ idps.identity_providers }}' - name: 'Create identity_provider (retry - no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - domain_id: '{{ domain_id }}' - register: create_identity_provider + state: present + name: 'ansible_identity_provider' + domain_id: '{{ domain.domain.id }}' + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is not changed + - idp is not changed - name: 'Create identity_provider (retry - no change)' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - domain_id: '{{ domain_id }}' - register: create_identity_provider + state: present + name: 'ansible_identity_provider' + domain_id: '{{ domain.domain.id }}' + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is not changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - not idp.description - - idp.is_enabled == True - - idp.remote_ids == [] + - idp is not changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - not _idp.description + - _idp.is_enabled == False + - _idp.remote_ids == [] vars: - idp: '{{ create_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' # ======================================================================== # Update (simple cases) @@ -155,219 +152,220 @@ - name: 'Update IDP set description - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description }}' - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 1' + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed + - idp is changed - name: 'Update IDP set description' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description }}' - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 1' + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == True - - idp.remote_ids == [] + - idp is changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == [] vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - name: 'Update IDP set description (retry - no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description }}' - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 1' + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed + - idp is not changed - name: 'Update IDP set description (retry - no change)' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description }}' - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 1' + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == True - - idp.remote_ids == [] + - idp is not changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == [] vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - name: 'Update IDP set Remote IDs - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' + state: present + name: 'ansible_identity_provider' remote_ids: '{{ remote_ids_1 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed + - idp is changed - name: 'Update IDP set Remote IDs' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' + state: present + name: 'ansible_identity_provider' remote_ids: '{{ remote_ids_1 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == True - - idp.remote_ids == remote_ids_1 + - idp is changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == remote_ids_1 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - name: 'Update IDP set Remote IDs (retry - no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' + state: present + name: 'ansible_identity_provider' remote_ids: '{{ remote_ids_1 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed + - idp is not changed - name: 'Update IDP set Remote IDs (retry - no change)' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' + state: present + name: 'ansible_identity_provider' remote_ids: '{{ remote_ids_1 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == True - - idp.remote_ids == remote_ids_1 + - idp is not changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == remote_ids_1 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - - name: 'Update IDP set Disabled - CHECK_MODE' + - name: 'Update IDP set Enabled - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - enabled: False - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + is_enabled: True + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed + - idp is changed - name: 'Update IDP set Disabled' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - enabled: False - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + is_enabled: True + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == False - - idp.remote_ids == remote_ids_1 + - idp is changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == True + - _idp.remote_ids == remote_ids_1 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - - name: 'Update IDP set Disabled (retry - no change) - CHECK_MODE' + - name: 'Update IDP set Enabled (retry - no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - enabled: False - register: update_identity_provider - - assert: - that: - - update_identity_provider is successful - - update_identity_provider is not changed + state: present + name: 'ansible_identity_provider' + is_enabled: True + register: idp - - name: 'Update IDP set Disabled (retry - no change)' - openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - enabled: False - register: update_identity_provider - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == False - - idp.remote_ids == remote_ids_1 + - idp is not changed + + - name: 'Update IDP set Enabled (retry - no change)' + openstack.cloud.federation_idp: + state: present + name: 'ansible_identity_provider' + is_enabled: True + register: idp + + - assert: + that: + - idp is not changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == True + - _idp.remote_ids == remote_ids_1 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' # If we don't specify anything to change, then nothing should change... - name: 'Minimal call to IDP (no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed + - idp is not changed - name: 'Minimal call to IDP (no change)' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - register: update_identity_provider + state: present + name: 'ansible_identity_provider' + is_enabled: True + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == False - - idp.remote_ids == remote_ids_1 + - idp is not changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == True + - _idp.remote_ids == remote_ids_1 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' # ======================================================================== # Update (mass-update) @@ -375,72 +373,72 @@ - name: 'Update all updatable IDP parameters - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description_2 }}' - enabled: True + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 2' + is_enabled: True remote_ids: '{{ remote_ids_2 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed + - idp is changed - name: 'Update all updatable IDP parameters' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description_2 }}' - enabled: True + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 2' + is_enabled: True remote_ids: '{{ remote_ids_2 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description_2 - - idp.is_enabled == True - - idp.remote_ids == remote_ids_2 + - idp is changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 2' + - _idp.is_enabled == True + - _idp.remote_ids == remote_ids_2 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - name: 'Update all updatable IDP parameters (no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description_2 }}' - enabled: True + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 2' + is_enabled: True remote_ids: '{{ remote_ids_2 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed + - idp is not changed - name: 'Update all updatable IDP parameters (no change)' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name }}' - description: '{{ idp_description_2 }}' - enabled: True + state: present + name: 'ansible_identity_provider' + description: 'ansible idp 2' + is_enabled: True remote_ids: '{{ remote_ids_2 }}' - register: update_identity_provider + register: idp + - assert: that: - - update_identity_provider is successful - - update_identity_provider is not changed - - idp.id == idp_name - - idp.name == idp_name - - idp.domain_id == domain_id - - idp.description == idp_description_2 - - idp.is_enabled == True - - idp.remote_ids == remote_ids_2 + - idp is not changed + - _idp.id == 'ansible_identity_provider' + - _idp.name == 'ansible_identity_provider' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 2' + - _idp.is_enabled == True + - _idp.remote_ids == remote_ids_2 vars: - idp: '{{ update_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' # ======================================================================== # Create complex IDP @@ -448,190 +446,190 @@ - name: 'Create complex IDP - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name_2 }}' - domain_id: '{{ domain_id }}' - description: '{{ idp_description }}' - enabled: False + state: present + name: 'ansible_identity_provider2' + domain_id: '{{ domain.domain.id }}' + description: 'ansible idp 1' + is_enabled: False remote_ids: '{{ remote_ids_3 }}' - register: create_identity_provider + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is changed + - idp is changed - name: 'Create complex IDP' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name_2 }}' - domain_id: '{{ domain_id }}' - description: '{{ idp_description }}' - enabled: False + state: present + name: 'ansible_identity_provider2' + domain_id: '{{ domain.domain.id }}' + description: 'ansible idp 1' + is_enabled: False remote_ids: '{{ remote_ids_3 }}' - register: create_identity_provider + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is changed - - idp.id == idp_name_2 - - idp.name == idp_name_2 - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == False - - idp.remote_ids == remote_ids_3 + - idp is changed + - _idp.id == 'ansible_identity_provider2' + - _idp.name == 'ansible_identity_provider2' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == remote_ids_3 vars: - idp: '{{ create_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' - name: 'Create complex IDP (retry - no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name_2 }}' - domain_id: '{{ domain_id }}' - description: '{{ idp_description }}' - enabled: False + state: present + name: 'ansible_identity_provider2' + domain_id: '{{ domain.domain.id }}' + description: 'ansible idp 1' + is_enabled: False remote_ids: '{{ remote_ids_3 }}' - register: create_identity_provider + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is not changed + - idp is not changed - name: 'Create complex IDP' openstack.cloud.federation_idp: - state: 'present' - name: '{{ idp_name_2 }}' - domain_id: '{{ domain_id }}' - description: '{{ idp_description }}' - enabled: False + state: present + name: 'ansible_identity_provider2' + domain_id: '{{ domain.domain.id }}' + description: 'ansible idp 1' + is_enabled: False remote_ids: '{{ remote_ids_3 }}' - register: create_identity_provider + register: idp + - assert: that: - - create_identity_provider is successful - - create_identity_provider is not changed - - idp.id == idp_name_2 - - idp.name == idp_name_2 - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == False - - idp.remote_ids == remote_ids_3 + - idp is not changed + - _idp.id == 'ansible_identity_provider2' + - _idp.name == 'ansible_identity_provider2' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == remote_ids_3 vars: - idp: '{{ create_identity_provider.identity_provider }}' + _idp: '{{ idp.identity_provider }}' # Attempt to ensure that if we search we only get the one we expect - name: 'Fetch Complex IDP info - with name' openstack.cloud.federation_idp_info: - name: '{{ idp_name_2 }}' - register: identity_provider_info + name: 'ansible_identity_provider2' + register: idps + - assert: that: - - identity_provider_info.identity_providers | length == 1 - - idp.id == idp_name_2 - - idp.name == idp_name_2 - - idp.domain_id == domain_id - - idp.description == idp_description - - idp.is_enabled == False - - idp.remote_ids == remote_ids_3 + - idps.identity_providers | length == 1 + - _idp.id == 'ansible_identity_provider2' + - _idp.name == 'ansible_identity_provider2' + - _idp.domain_id == domain.domain.id + - _idp.description == 'ansible idp 1' + - _idp.is_enabled == False + - _idp.remote_ids == remote_ids_3 vars: - idp: '{{ identity_provider_info.identity_providers[0] }}' + _idp: '{{ idps.identity_providers[0] }}' # Ensure that if we do search we get both of the results we expect - name: 'Fetch multiple IDP info - without name' openstack.cloud.federation_idp_info: {} - register: identity_provider_info + register: idps + - assert: that: # In CI we generally have a clean slate, but this might # not be true for everyone... - - identity_provider_info.identity_providers | length >= 2 + - idps.identity_providers | length >= 2 # In theory these could be attached to different IDPs but let's keep # things simple - - idp_name in (identity_provider_info.identity_providers | map(attribute='id')) - - idp_name in (identity_provider_info.identity_providers | map(attribute='name')) - - idp_name_2 in (identity_provider_info.identity_providers | map(attribute='id')) - - idp_name_2 in (identity_provider_info.identity_providers | map(attribute='name')) - - domain_id in (identity_provider_info.identity_providers | map(attribute='domain_id')) - - idp_description in (identity_provider_info.identity_providers | map(attribute='description')) - - idp_description_2 in (identity_provider_info.identity_providers | map(attribute='description')) - - True in (identity_provider_info.identity_providers | map(attribute='is_enabled')) - - False in (identity_provider_info.identity_providers | map(attribute='is_enabled')) + - "'ansible_identity_provider' in (idps.identity_providers | map(attribute='id'))" + - "'ansible_identity_provider' in (idps.identity_providers | map(attribute='name'))" + - "'ansible_identity_provider2' in (idps.identity_providers | map(attribute='id'))" + - "'ansible_identity_provider2' in (idps.identity_providers | map(attribute='name'))" + - domain.domain.id in (idps.identity_providers | map(attribute='domain_id')) + - "'ansible idp 1' in (idps.identity_providers | map(attribute='description'))" + - "'ansible idp 2' in (idps.identity_providers | map(attribute='description'))" + - True in (idps.identity_providers | map(attribute='is_enabled')) + - False in (idps.identity_providers | map(attribute='is_enabled')) - name: 'Delete identity_provider - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name }}' - register: delete_identity_provider + state: absent + name: 'ansible_identity_provider' + register: idp + - assert: that: - - delete_identity_provider is successful - - delete_identity_provider is changed + - idp is changed - name: 'Delete identity_provider' openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name }}' - register: delete_identity_provider + state: absent + name: 'ansible_identity_provider' + register: idp + - assert: that: - - delete_identity_provider is successful - - delete_identity_provider is changed + - idp is changed - name: 'Delete identity_provider (retry - no change) - CHECK_MODE' check_mode: yes openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name }}' - register: delete_identity_provider + state: absent + name: 'ansible_identity_provider' + register: idp + - assert: that: - - delete_identity_provider is successful - - delete_identity_provider is not changed + - idp is not changed - name: 'Delete identity_provider (retry - no change) ' openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name }}' - register: delete_identity_provider + state: absent + name: 'ansible_identity_provider' + register: idp + - assert: that: - - delete_identity_provider is successful - - delete_identity_provider is not changed + - idp is not changed - name: 'Fetch identity_provider info after deletion' openstack.cloud.federation_idp_info: - name: '{{ idp_name }}' - register: identity_provider_info + name: 'ansible_identity_provider' + register: idps + - assert: that: - - identity_provider_info.identity_providers | length == 0 + - idps.identity_providers | length == 0 - name: 'Delete second identity_provider' openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name_2 }}' - register: delete_identity_provider + state: absent + name: 'ansible_identity_provider2' + register: idp + - assert: that: - - delete_identity_provider is successful - - delete_identity_provider is changed + - idp is changed always: - name: 'Delete idp' openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name }}' - ignore_errors: yes + state: absent + name: 'ansible_identity_provider' - name: 'Delete second identity_provider' openstack.cloud.federation_idp: - state: 'absent' - name: '{{ idp_name_2 }}' - ignore_errors: yes + state: absent + name: 'ansible_identity_provider2' - name: 'Delete domain' openstack.cloud.identity_domain: - state: 'absent' - name: '{{ domain_name }}' - ignore_errors: yes + state: absent + name: ansible_domain diff --git a/ci/run-collection.yml b/ci/run-collection.yml index 338f1182..6ff50356 100644 --- a/ci/run-collection.yml +++ b/ci/run-collection.yml @@ -24,9 +24,7 @@ - { role: identity_role, tags: identity_role } - { role: image, tags: image } - { role: keypair, tags: keypair } - - role: keystone_idp - tags: keystone_idp - when: sdk_version is version(0.44, '>=') + - { role: keystone_idp, tags: keystone_idp } - role: keystone_federation_protocol tags: keystone_federation_protocol when: sdk_version is version(0.44, '>=') diff --git a/plugins/modules/federation_idp.py b/plugins/modules/federation_idp.py index b6b94a65..6c567479 100644 --- a/plugins/modules/federation_idp.py +++ b/plugins/modules/federation_idp.py @@ -4,54 +4,54 @@ # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -DOCUMENTATION = ''' ---- +DOCUMENTATION = r''' module: federation_idp -short_description: manage a federation Identity Provider +short_description: Manage an identity provider in a OpenStack cloud author: OpenStack Ansible SIG description: - - Manage a federation Identity Provider. + - Create, update or delete an identity provider of the OpenStack + identity (Keystone) service. options: - name: - description: - - The name of the Identity Provider. - type: str - required: true - aliases: ['id'] - state: - description: - - Whether the Identity Provider should be C(present) or C(absent). - choices: ['present', 'absent'] - default: present - type: str description: description: - - The description of the Identity Provider. + - The description of the identity provider. type: str domain_id: description: - - The ID of a domain that is associated with the Identity Provider. - Federated users that authenticate with the Identity Provider will be + - The ID of a domain that is associated with the identity provider. + - Federated users that authenticate with the identity provider will be created under the domain specified. - - Required when creating a new Identity Provider. + - Required when creating a new identity provider. type: str - enabled: + id: description: - - Whether the Identity Provider is enabled or not. - - Will default to C(true) when creating a new Identity Provider. + - The ID (and name) of the identity provider. + type: str + required: true + aliases: ['name'] + is_enabled: + description: + - Whether the identity provider is enabled or not. + - Will default to C(false) when creating a new identity provider. type: bool - aliases: ['is_enabled'] + aliases: ['enabled'] remote_ids: description: - - "List of the unique Identity Provider's remote IDs." - - Will default to an empty list when creating a new Identity Provider. + - "List of the unique identity provider's remote IDs." + - Will default to an empty list when creating a new identity provider. type: list elements: str + state: + description: + - Whether the identity provider should be C(present) or C(absent). + choices: ['present', 'absent'] + default: present + type: str extends_documentation_fragment: - openstack.cloud.openstack ''' -EXAMPLES = ''' +EXAMPLES = r''' - name: Create an identity provider openstack.cloud.federation_idp: cloud: example_cloud @@ -59,7 +59,7 @@ EXAMPLES = ''' domain_id: 0123456789abcdef0123456789abcdef description: 'My example IDP' remote_ids: - - 'https://auth.example.com/auth/realms/ExampleRealm' + - 'https://auth.example.com/auth/realms/ExampleRealm' - name: Delete an identity provider openstack.cloud.federation_idp: @@ -68,160 +68,86 @@ EXAMPLES = ''' state: absent ''' -RETURN = ''' +RETURN = r''' identity_provider: - description: Dictionary describing the identity providers - returned: On success when I(state) is 'present' - type: dict - elements: dict - contains: - description: - description: Identity provider description - type: str - sample: "demodescription" - domain_id: - description: Domain to which the identity provider belongs - type: str - sample: "default" - id: - description: Identity provider ID - type: str - sample: "test-idp" - is_enabled: - description: Indicates whether the identity provider is enabled - type: bool - name: - description: Name of the identity provider, equals its ID. - type: str - sample: "test-idp" - remote_ids: - description: Remote IDs associated with the identity provider - type: list + description: Dictionary describing the identity providers + returned: On success when I(state) is C(present). + type: dict + contains: + description: + description: Identity provider description + type: str + sample: "demodescription" + domain_id: + description: Domain to which the identity provider belongs + type: str + sample: "default" + id: + description: Identity provider ID + type: str + sample: "test-idp" + is_enabled: + description: Indicates whether the identity provider is enabled + type: bool + name: + description: Name of the identity provider, equals its ID. + type: str + sample: "test-idp" + remote_ids: + description: Remote IDs associated with the identity provider + type: list ''' from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule +from ansible_collections.openstack.cloud.plugins.module_utils.resource import StateMachine -class IdentityFederationIdpModule(OpenStackModule): +class IdentityProviderModule(OpenStackModule): argument_spec = dict( - name=dict(required=True, aliases=['id']), - state=dict(default='present', choices=['absent', 'present']), description=dict(), domain_id=dict(), - enabled=dict(type='bool', aliases=['is_enabled']), + id=dict(required=True, aliases=['name']), + is_enabled=dict(type='bool', aliases=['enabled']), remote_ids=dict(type='list', elements='str'), + state=dict(default='present', choices=['absent', 'present']), ) module_kwargs = dict( supports_check_mode=True, ) - def delete_identity_provider(self, idp): - """ - Delete an existing Identity Provider - - returns: the "Changed" state - """ - if idp is None: - return False - - if self.ansible.check_mode: - return True - - self.conn.identity.delete_identity_provider(idp) - return True - - def create_identity_provider(self, name): - """ - Create a new Identity Provider - - returns: the "Changed" state and the new identity provider - """ - - if self.ansible.check_mode: - return True, None - - description = self.params.get('description') - enabled = self.params.get('enabled') - domain_id = self.params.get('domain_id') - remote_ids = self.params.get('remote_ids') - - if enabled is None: - enabled = True - if remote_ids is None: - remote_ids = [] - - attributes = { - 'domain_id': domain_id, - 'enabled': enabled, - 'remote_ids': remote_ids, - } - if description is not None: - attributes['description'] = description - - idp = self.conn.identity.create_identity_provider(id=name, **attributes) - return (True, idp.to_dict(computed=False)) - - def update_identity_provider(self, idp): - """ - Update an existing Identity Provider - - returns: the "Changed" state and the new identity provider - """ - - description = self.params.get('description') - enabled = self.params.get('enabled') - domain_id = self.params.get('domain_id') - remote_ids = self.params.get('remote_ids') - - attributes = {} - - if (description is not None) and (description != idp.description): - attributes['description'] = description - if (enabled is not None) and (enabled != idp.is_enabled): - attributes['enabled'] = enabled - if (domain_id is not None) and (domain_id != idp.domain_id): - attributes['domain_id'] = domain_id - if (remote_ids is not None) and (remote_ids != idp.remote_ids): - attributes['remote_ids'] = remote_ids - - if not attributes: - return False, idp.to_dict(computed=False) - - if self.ansible.check_mode: - return True, None - - new_idp = self.conn.identity.update_identity_provider(idp, **attributes) - return (True, new_idp.to_dict(computed=False)) - def run(self): - """ Module entry point """ + sm = StateMachine(connection=self.conn, + service_name='identity', + type_name='identity_provider', + sdk=self.sdk) - name = self.params.get('name') - state = self.params.get('state') - changed = False + kwargs = dict((k, self.params[k]) + for k in ['state', 'timeout'] + if self.params[k] is not None) - idp = self.conn.identity.find_identity_provider(name) + kwargs['attributes'] = \ + dict((k, self.params[k]) + for k in ['description', 'domain_id', 'id', 'is_enabled', + 'remote_ids'] + if self.params[k] is not None) - if state == 'absent': - if idp is not None: - changed = self.delete_identity_provider(idp) - self.exit_json(changed=changed) + identity_provider, is_changed = \ + sm(check_mode=self.ansible.check_mode, + updateable_attributes=None, + non_updateable_attributes=['domain_id'], + wait=False, + **kwargs) - # state == 'present' + if identity_provider is None: + self.exit_json(changed=is_changed) else: - if idp is None: - if self.params.get('domain_id') is None: - self.fail_json(msg='A domain_id must be passed when creating' - ' an identity provider') - (changed, idp) = self.create_identity_provider(name) - self.exit_json(changed=changed, identity_provider=idp) - - (changed, new_idp) = self.update_identity_provider(idp) - self.exit_json(changed=changed, identity_provider=new_idp) + self.exit_json( + changed=is_changed, + identity_provider=identity_provider.to_dict(computed=False)) def main(): - module = IdentityFederationIdpModule() + module = IdentityProviderModule() module() diff --git a/plugins/modules/federation_idp_info.py b/plugins/modules/federation_idp_info.py index 92e251c0..af4c2ff8 100644 --- a/plugins/modules/federation_idp_info.py +++ b/plugins/modules/federation_idp_info.py @@ -4,25 +4,23 @@ # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -DOCUMENTATION = ''' ---- +DOCUMENTATION = r''' module: federation_idp_info -short_description: Get the information about the available federation identity - providers +short_description: Fetch OpenStack federation identity providers author: OpenStack Ansible SIG description: - - Fetch available federation identity providers. + - Fetch OpenStack federation identity providers. options: - name: + id: description: - - The name of the identity provider to fetch. + - The ID (and name) of the identity provider to fetch. type: str - aliases: ['id'] + aliases: ['name'] extends_documentation_fragment: - openstack.cloud.openstack ''' -EXAMPLES = ''' +EXAMPLES = r''' - name: Fetch a specific identity provider openstack.cloud.federation_idp_info: cloud: example_cloud @@ -33,35 +31,35 @@ EXAMPLES = ''' cloud: example_cloud ''' -RETURN = ''' +RETURN = r''' identity_providers: - description: Dictionary describing the identity providers - returned: success - type: list - elements: dict - contains: - description: - description: Identity provider description - type: str - sample: "demodescription" - domain_id: - description: Domain to which the identity provider belongs - type: str - sample: "default" - id: - description: Identity provider ID - type: str - sample: "test-idp" - is_enabled: - description: Indicates wether the identity provider is enabled - type: bool - name: - description: Name of the identity provider, equals its ID. - type: str - sample: "test-idp" - remote_ids: - description: Remote IDs associated with the identity provider - type: list + description: Dictionary describing the identity providers + returned: always + type: list + elements: dict + contains: + description: + description: Identity provider description + type: str + sample: "demodescription" + domain_id: + description: Domain to which the identity provider belongs + type: str + sample: "default" + id: + description: Identity provider ID + type: str + sample: "test-idp" + is_enabled: + description: Indicates whether the identity provider is enabled + type: bool + name: + description: Name of the identity provider, equals its ID. + type: str + sample: "test-idp" + remote_ids: + description: Remote IDs associated with the identity provider + type: list ''' from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule @@ -69,24 +67,21 @@ from ansible_collections.openstack.cloud.plugins.module_utils.openstack import O class IdentityFederationIdpInfoModule(OpenStackModule): argument_spec = dict( - name=dict(aliases=['id']), + id=dict(aliases=['name']), ) module_kwargs = dict( supports_check_mode=True ) def run(self): - """ Module entry point """ - - name = self.params['name'] - - query = {} - if name: - query["id"] = name - - idps = self.conn.identity.identity_providers(**query) - idps = [idp.to_dict(computed=False) for idp in idps] - self.exit_json(changed=False, identity_providers=idps) + kwargs = dict((k, self.params[k]) + for k in ['id'] + if self.params[k] is not None) + identity_providers = self.conn.identity.identity_providers(**kwargs) + self.exit_json( + changed=False, + identity_providers=[i.to_dict(computed=False) + for i in identity_providers]) def main():