From 7218b36d3e1e0f9fac465993f0168c03c221ef0d Mon Sep 17 00:00:00 2001 From: prakhar Date: Tue, 23 Jun 2026 17:54:36 +1000 Subject: [PATCH 1/2] fix: GPTEINFRA-16720 scope provision-user-data.yaml to fix showroom multi-user mode trigger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The agnosticd.core.agnosticd_user_data lookup in the showroom role's prepare_variables.yaml reads provision-user-data.yaml, not user-info.yaml. If user1's Phase 1 writes users.user1 into that file, user2's showroom role sees _showroom_user_data.users defined and enters multi-user mode, creating namespace user2-showroom-user1 instead of user2-showroom. Two-part fix: 1. Strip the users key from provision-user-data.yaml before each user's Phase 1 — preserves global keys (cluster credentials) but removes per-user entries so the showroom lookup stays in single-user mode. 2. Reset _showroom_user_data: {} fact before Phase 1 — set_fact persists across include_role calls in the same play, so combine() in prepare_variables.yaml merges onto dirty in-memory data even if the file is clean. The fact reset ensures a clean slate per iteration. Also scopes user-info.yaml (display messages) and strips Phase 1 msgs from merge-back to prevent duplicate portal messages. Validated in LB2863 combined CI test order. Jira: GPTEINFRA-16720 --- roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml b/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml index a08f357..e661c48 100644 --- a/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml +++ b/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml @@ -1,5 +1,4 @@ --- -# ========================================================================= # Run all tenant workloads for a single user (Phase 1). # # VARIABLE SCOPING: @@ -17,7 +16,6 @@ # # No agnosticd_user_info calls here — registration is in Phase 2. # See workload.yml header for why two-phase is necessary. -# ========================================================================= - name: "Set identity: {{ tenant_user_prefix ~ _tenant_user_num }}" ansible.builtin.set_fact: From 554675956221deaf61f521727ee9d3dddbab1e49 Mon Sep 17 00:00:00 2001 From: prakhar Date: Wed, 24 Jun 2026 10:29:56 +1000 Subject: [PATCH 2/2] fix: GPTEINFRA-16720 strip only users key from _showroom_user_data, not full reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resetting _showroom_user_data to {} wiped the showroom role vars/main.yml default (bastion_public_hostname: 'test_hostname'), breaking labs with no bastion (LB2236 Ansible Dev Tools DevSpaces, LB2391 Modernize OCP Virt). Labs WITH a bastion still work because provision-user-data.yaml has the value. Labs WITHOUT a bastion depended on the role default — wiped by our {} reset. Strip only the users key instead using dict2items|rejectattr|items2dict. Guards: - _showroom_user_data is defined (skip on first user iteration) - _showroom_user_data is mapping (guard against non-dict type edge case) - _showroom_user_data.users is defined (only strip when actually dirty) This preserves bastion_public_hostname and all other role defaults while still preventing multi-user mode trigger on subsequent user iterations. --- .../tasks/provision_user.yml | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml b/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml index e661c48..205d61c 100644 --- a/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml +++ b/roles/ocp4_workload_multi_tenant_loop/tasks/provision_user.yml @@ -92,9 +92,25 @@ dest: "{{ output_dir }}/provision-user-data.yaml" mode: '0644' -- name: "Reset _showroom_user_data fact to prevent dirty in-memory combine: {{ _tenant_username }}" +- name: "Strip users key from _showroom_user_data fact to prevent dirty in-memory combine: {{ _tenant_username }}" + # Remove ONLY the users key — resetting to {} would wipe role defaults such as + # bastion_public_hostname: 'test_hostname' (from showroom vars/main.yml), breaking + # labs without a bastion (e.g. DevSpaces-only labs). Stripping just the users key + # is sufficient: combine() in prepare_variables.yaml then merges from a clean slate + # that still carries role-level defaults. + when: + - _showroom_user_data is defined + - _showroom_user_data is mapping + - _showroom_user_data.users is defined ansible.builtin.set_fact: - _showroom_user_data: {} + _showroom_user_data: >- + {{ + _showroom_user_data + | dict2items + | rejectattr('key', 'equalto', 'users') + | list + | items2dict + }} # ───────────────────────────────────────────────────────────────────────────── - name: "Provision workloads: {{ _tenant_username }}"