From 94205328839b3afa37d92defeb9bab2c9fb10aa4 Mon Sep 17 00:00:00 2001 From: Daniel Pawlik Date: Tue, 24 Mar 2026 13:29:10 +0100 Subject: [PATCH 1/6] [reproducer] Replace all reproducer vars with zuul vars Some variables are missing, especially related to the registry credentials. That complicate the situation, where some keys might not exists in reproducer file. Some of the variables are jinja2 template, which are "translated" by Ansible. Alternative way was to use yq command like: yq eval-all -P 'select(fileIndex == 0) * select(fileIndex == 1)' \ /tmp/reproducer-variables.yml \ /home/zuul/configs/zuul_vars.yaml > merged.yaml The yq is available in latest version available for current python3 version installed on hypervisor. In that case, we can not use the yq tool, but use a python script. Co-authored-by: Claude (AI Assistant) claude@anthropic.com Signed-off-by: Daniel Pawlik --- roles/reproducer/files/merge_yaml_override.py | 118 ++++++++++++++++++ .../reproducer/tasks/overwrite_zuul_vars.yml | 50 ++++---- 2 files changed, 145 insertions(+), 23 deletions(-) create mode 100644 roles/reproducer/files/merge_yaml_override.py diff --git a/roles/reproducer/files/merge_yaml_override.py b/roles/reproducer/files/merge_yaml_override.py new file mode 100644 index 0000000000..ab4b140fc8 --- /dev/null +++ b/roles/reproducer/files/merge_yaml_override.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Copyright Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# Merge two YAML files whose root is a mapping: keys from OVERRIDE replace BASE +# recursively for nested mappings; non-dict values (scalars, lists) are +# replaced entirely by OVERRIDE. Requires PyYAML (python3-pyyaml / python3-yaml +# on RPM systems). + +from __future__ import annotations + +import sys + +try: + import yaml +except ImportError: + sys.stderr.write( + "merge_yaml_override.py: PyYAML is required " + "(e.g. dnf install python3-pyyaml or pip install pyyaml)\n" + ) + sys.exit(1) + + +class DoubleQuoteDumper(yaml.SafeDumper): + """SafeDumper that uses double quotes instead of single quotes.""" + + pass + + +def _str_representer(dumper, data): + if "\n" in data: + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") + if any(c in data for c in "{}[]%*&!@#"): + return dumper.represent_scalar("tag:yaml.org,2002:str", data, style='"') + return dumper.represent_scalar("tag:yaml.org,2002:str", data) + + +DoubleQuoteDumper.add_representer(str, _str_representer) + + +def deep_merge(base: object, override: object) -> object: + if base is None: + return override + if override is None: + return base + if isinstance(base, dict) and isinstance(override, dict): + out = dict(base) + for key, val in override.items(): + if key in out: + out[key] = deep_merge(out[key], val) + else: + out[key] = val + return out + return override + + +def main() -> None: + argc = len(sys.argv) + if argc not in (3, 4): + sys.stderr.write( + f"usage: {sys.argv[0]} FILE1_BASE.yml FILE2_OVERRIDE.yml [MERGED_OUT.yml]\n" + " Deep-merge two YAML mappings: FILE2 wins on duplicate keys (nested dicts merged).\n" + " Scalars and lists from FILE2 replace FILE1. If MERGED_OUT is omitted, print to stdout.\n" + ) + sys.exit(2) + + base_path, override_path = sys.argv[1], sys.argv[2] + out_path = sys.argv[3] if argc == 4 else None + + with open(base_path, encoding="utf-8") as f: + base = yaml.safe_load(f) + with open(override_path, encoding="utf-8") as f: + override = yaml.safe_load(f) + + if base is None: + base = {} + if override is None: + override = {} + + if not isinstance(base, dict): + sys.stderr.write( + f"{base_path}: root must be a mapping, got {type(base).__name__}\n" + ) + sys.exit(3) + if not isinstance(override, dict): + sys.stderr.write( + f"{override_path}: root must be a mapping, got {type(override).__name__}\n" + ) + sys.exit(3) + + merged = deep_merge(base, override) + dump_kw = dict( + default_flow_style=False, + sort_keys=False, + allow_unicode=True, + ) + if out_path is None: + yaml.dump(merged, sys.stdout, Dumper=DoubleQuoteDumper, **dump_kw) + else: + with open(out_path, "w", encoding="utf-8") as out_f: + yaml.dump(merged, out_f, Dumper=DoubleQuoteDumper, **dump_kw) + + +if __name__ == "__main__": + main() diff --git a/roles/reproducer/tasks/overwrite_zuul_vars.yml b/roles/reproducer/tasks/overwrite_zuul_vars.yml index 8cf458ce29..24b7a5b105 100644 --- a/roles/reproducer/tasks/overwrite_zuul_vars.yml +++ b/roles/reproducer/tasks/overwrite_zuul_vars.yml @@ -15,46 +15,50 @@ - name: Overwrite reproducer-variables.yml when ZIronic used when: _current_zuul_vars.stat.exists + vars: + temp_reproducer_var_path: /tmp/reproducer-variables.yml + temp_merged_reproducer_var_path: /tmp/merged-reproducer-variables.yml block: - - name: Dump reproducer-variables.yml to var + - name: Slurp reproducer-variables.yml to hypervisor ansible.builtin.slurp: src: "{{ cifmw_basedir }}/parameters/reproducer-variables.yml" register: reproducer_original delegate_to: controller-0 no_log: "{{ cifmw_nolog | default(true) | bool }}" - - name: Dump zuul_vars.yaml to var - ansible.builtin.slurp: - src: "{{ ansible_user_dir }}/configs/zuul_vars.yaml" - register: zuul_job_vars + - name: Create temp file reproducer-variables.yml on hypervisor + ansible.builtin.copy: + content: "{{ reproducer_original.content | b64decode }}" + dest: "{{ temp_reproducer_var_path }}" + mode: "0664" no_log: "{{ cifmw_nolog | default(true) | bool }}" - - name: Load current job zuul_vars.yaml - ansible.builtin.include_vars: - file: "{{ ansible_user_dir }}/configs/zuul_vars.yaml" - name: _current_zuul_vars_include + - name: Copy merge yamls script + become: true + ansible.builtin.copy: + src: merge_yaml_override.py + dest: /usr/local/bin/merge_yaml_override + mode: "0755" - - name: Decode reproducer-variables.yml content - ansible.builtin.set_fact: - reproducer_vars_content: "{{ reproducer_original.content | b64decode | from_yaml }}" + - name: Execute merge script + ansible.builtin.shell: > + python3 /usr/local/bin/merge_yaml_override + {{ temp_reproducer_var_path }} + {{ ansible_user_dir }}/configs/zuul_vars.yaml > + {{ temp_merged_reproducer_var_path }} no_log: "{{ cifmw_nolog | default(true) | bool }}" - - name: Filter zuul vars to only keys present in reproducer-variables - ansible.builtin.set_fact: - _zuul_vars_filtered: >- - {{ - _current_zuul_vars_include | dict2items - | selectattr('key', 'in', reproducer_vars_content.keys()) - | items2dict - }} + - name: Slurp merged reproducer-variables.yml from hypervisor + ansible.builtin.slurp: + src: "{{ temp_merged_reproducer_var_path }}" + register: merged_reproducer_slurp no_log: "{{ cifmw_nolog | default(true) | bool }}" - name: Write back merged reproducer-variables.yml ansible.builtin.copy: - content: >- - {{ reproducer_vars_content | combine(_zuul_vars_filtered, recursive=true) | to_nice_yaml }} + content: "{{ merged_reproducer_slurp.content | b64decode }}" dest: "{{ cifmw_basedir }}/parameters/reproducer-variables.yml" - mode: '0664' + mode: "0664" backup: true no_log: "{{ cifmw_nolog | default(true) | bool }}" delegate_to: controller-0 From c971b37f223b21138a7f11e96b982c937f8e3cb6 Mon Sep 17 00:00:00 2001 From: Daniel Pawlik Date: Wed, 25 Mar 2026 11:32:41 +0100 Subject: [PATCH 2/6] [reproducer] Sync src dir when controller available and using ZIronic Keep support for legacy workflow where controller host is created and actions are done not on hypervisor directly, but on controller. Signed-off-by: Daniel Pawlik --- reproducer.yml | 21 +++--- roles/cifmw_setup/tasks/bootstrap.yml | 2 + .../reproducer/tasks/overwrite_zuul_vars.yml | 8 +++ roles/reproducer/tasks/sync_src_dir.yml | 64 +++++++++++++++++++ 4 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 roles/reproducer/tasks/sync_src_dir.yml diff --git a/reproducer.yml b/reproducer.yml index f5433b3544..3d6b246a4a 100644 --- a/reproducer.yml +++ b/reproducer.yml @@ -108,18 +108,22 @@ name: firewalld state: restarted + # NOTE(dpawlik): Keep support for legacy workflow where + # controller host is created and actions are done not on + # hypervisor directly, but on controller. # NOTE(dpawlik): Synchronize current Zuul repositories stored in $HOME/src # to controller-0 to make sure all projects are in state as they should. - - name: Synchronize src dir with controller-0 + - name: Set hypervisor name if not defined + when: hypervisor is not defined + ansible.builtin.set_fact: + hypervisor: "{{ ansible_fqdn }}" + + - name: Synchronize src dir when: - not cifmw_deploy_reproducer_env | default(true) | bool - vars: - sync_dir: "{{ ansible_user_dir }}/src" - ansible.posix.synchronize: - src: "{{ sync_dir }}/" - dest: "zuul@controller-0:{{ sync_dir }}" - archive: true - recursive: true + ansible.builtin.include_role: + name: reproducer + tasks_from: sync_src_dir.yml # NOTE(dpawlik): After calling reproducer role using ZIronic tool, # when the bootstrap phase has been completed, it generates a file @@ -133,6 +137,7 @@ ansible.builtin.include_role: name: reproducer tasks_from: overwrite_zuul_vars.yml + - name: Run deployment if instructed to when: - cifmw_deploy_architecture | default(false) | bool diff --git a/roles/cifmw_setup/tasks/bootstrap.yml b/roles/cifmw_setup/tasks/bootstrap.yml index 87ac0cd4b7..81ce905430 100644 --- a/roles/cifmw_setup/tasks/bootstrap.yml +++ b/roles/cifmw_setup/tasks/bootstrap.yml @@ -59,6 +59,8 @@ role: discover_latest_image - name: Create artifacts with custom params + when: + - cifmw_deploy_reproducer_env | default(true) | bool tags: - always ansible.builtin.copy: diff --git a/roles/reproducer/tasks/overwrite_zuul_vars.yml b/roles/reproducer/tasks/overwrite_zuul_vars.yml index 24b7a5b105..e9158489a6 100644 --- a/roles/reproducer/tasks/overwrite_zuul_vars.yml +++ b/roles/reproducer/tasks/overwrite_zuul_vars.yml @@ -62,3 +62,11 @@ backup: true no_log: "{{ cifmw_nolog | default(true) | bool }}" delegate_to: controller-0 + + - name: Overwrite custom-params.yml + ansible.builtin.copy: + content: "{{ merged_reproducer_slurp.content | b64decode }}" + dest: "{{ cifmw_basedir }}/artifacts/parameters/custom-params.yml" + mode: "0664" + no_log: "{{ cifmw_nolog | default(true) | bool }}" + delegate_to: controller-0 diff --git a/roles/reproducer/tasks/sync_src_dir.yml b/roles/reproducer/tasks/sync_src_dir.yml new file mode 100644 index 0000000000..6790407152 --- /dev/null +++ b/roles/reproducer/tasks/sync_src_dir.yml @@ -0,0 +1,64 @@ +--- +# NOTE(dpawlik): Synchronize data when ZIronic provision+bootstrap the +# hypervisor AND Zuul job uses ZIronic flavor which is executing +# job directly on hypervisor. When job starts, src and secrets dir are "recreated" +# by zuul-executor with current job data. Sync the data with +# controller-0 which is executing nested Ansible. +- name: Synchronize hypervisor secrets dir with controller-0 + vars: + sync_dir: "{{ ansible_user_dir }}/secrets" + ansible.posix.synchronize: + src: "{{ sync_dir }}/" + dest: "zuul@controller-0:{{ sync_dir }}" + archive: true + recursive: true + no_log: "{{ cifmw_nolog | default(true) | bool }}" + +- name: Synchronize hypervisor src dir with controller-0 + vars: + sync_dir: "{{ ansible_user_dir }}/src" + ansible.posix.synchronize: + src: "{{ sync_dir }}/" + dest: "zuul@controller-0:{{ sync_dir }}" + archive: true + recursive: true + no_log: "{{ cifmw_nolog | default(true) | bool }}" + +# NOTE(dpawlik): Synchronize data when ZIronic provision+bootstrap the +# hypervisor BUT legacy workflow is used (spawning controller VM +# which is executing all other playbooks). When job starts, all +# data like secrets, src dir etc. is stored on controller VM, but because +# later tasks are using nested ansible execution, then all playbooks needs +# to be up-to-date. +# That case would be mostly used by developers. Synchronize module +# would ignore if sync would happen to the same host. No need to synchronize +# with controller-0 again, due tasks above would do that. +- name: Synchronize controller VM configs dir with hypervisor + vars: + sync_dir: "{{ ansible_user_dir }}/configs" + ansible.posix.synchronize: + src: "{{ sync_dir }}/" + dest: "zuul@{{ hypervisor }}:{{ sync_dir }}" + archive: true + recursive: true + no_log: "{{ cifmw_nolog | default(true) | bool }}" + +- name: Synchronize controller secrets dir with hypervisor + vars: + sync_dir: "{{ ansible_user_dir }}/secrets" + ansible.posix.synchronize: + src: "{{ sync_dir }}/" + dest: "zuul@{{ hypervisor }}:{{ sync_dir }}" + archive: true + recursive: true + no_log: "{{ cifmw_nolog | default(true) | bool }}" + +- name: Synchronize src dir with hypervisor + vars: + sync_dir: "{{ ansible_user_dir }}/src" + ansible.posix.synchronize: + src: "{{ sync_dir }}/" + dest: "zuul@{{ hypervisor }}:{{ sync_dir }}" + archive: true + recursive: true + no_log: "{{ cifmw_nolog | default(true) | bool }}" From b988e14926ed808fad1868898b3a204ccfa0bc30 Mon Sep 17 00:00:00 2001 From: Daniel Pawlik Date: Fri, 27 Mar 2026 10:43:30 +0100 Subject: [PATCH 3/6] [reproducer] Add secret files as argument for deploy architecture On executing nested Ansible, some variables like: 'cifmw_registry_token' are not redirected, which is causing an issue in later tasks, which are operating on those variables and if it is undefine, it raise an issue. To satisfy nested Ansible execution, provide necessary variables. Also include hypervisor name as it can be a missing variable, due jobs already bootstrapped by ZIronic does not require to have that variable, which in some tasks is necessary. Signed-off-by: Daniel Pawlik --- reproducer.yml | 26 ++++++++++++++++++- roles/cifmw_setup/tasks/bootstrap.yml | 2 -- .../tasks/compute_additional_args.yml | 12 +++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 roles/reproducer/tasks/compute_additional_args.yml diff --git a/reproducer.yml b/reproducer.yml index 3d6b246a4a..240d2e1347 100644 --- a/reproducer.yml +++ b/reproducer.yml @@ -138,6 +138,27 @@ name: reproducer tasks_from: overwrite_zuul_vars.yml + # NOTE(dpawlik): Since we use ZIronic, some variables are not + # redirected to nested ansible execution - they needs to be + # included on executing host - controller-0. + - name: Compute additional deploy_architecture_args with secrets + when: + - not cifmw_deploy_reproducer_env | default(true) | bool + vars: + basic_secret_files: + - "{{ ansible_user_dir }}/secrets/registry_token_creds.yaml" + ansible.builtin.include_role: + name: reproducer + tasks_from: compute_additional_args.yml + loop: "{{ cifmw_deploy_architecture_secret_files | default(basic_secret_files) }}" + loop_control: + loop_var: secret_file + + - name: Print final cifmw_deploy_architecture_args + ansible.builtin.debug: + msg: > + Current cifmw_deploy_architecture_args {{ cifmw_deploy_architecture_args | default('') }} + - name: Run deployment if instructed to when: - cifmw_deploy_architecture | default(false) | bool @@ -146,7 +167,10 @@ poll: 20 delegate_to: controller-0 ansible.builtin.command: - cmd: "$HOME/deploy-architecture.sh {{ cifmw_deploy_architecture_args | default('') }}" + cmd: > + $HOME/deploy-architecture.sh + -e hypervisor="{{ hypervisor }}" + {{ cifmw_deploy_architecture_args | default('') }} - name: Run post deployment if instructed to when: diff --git a/roles/cifmw_setup/tasks/bootstrap.yml b/roles/cifmw_setup/tasks/bootstrap.yml index 81ce905430..87ac0cd4b7 100644 --- a/roles/cifmw_setup/tasks/bootstrap.yml +++ b/roles/cifmw_setup/tasks/bootstrap.yml @@ -59,8 +59,6 @@ role: discover_latest_image - name: Create artifacts with custom params - when: - - cifmw_deploy_reproducer_env | default(true) | bool tags: - always ansible.builtin.copy: diff --git a/roles/reproducer/tasks/compute_additional_args.yml b/roles/reproducer/tasks/compute_additional_args.yml new file mode 100644 index 0000000000..bcae05d166 --- /dev/null +++ b/roles/reproducer/tasks/compute_additional_args.yml @@ -0,0 +1,12 @@ +--- +- name: "Checking if file exists {{ secret_file }}" + ansible.builtin.stat: + path: "{{ secret_file }}" + register: _current_file + +- name: Add secret file into cifmw_deploy_architecture_args when exists + when: _current_file.stat.exists + ansible.builtin.set_fact: + cifmw_deploy_architecture_args: > + {{ cifmw_deploy_architecture_args | default('') }} + -e @{{ secret_file }} From e0338d325159c1b0ba4b921b761944fe6722c50a Mon Sep 17 00:00:00 2001 From: Daniel Pawlik Date: Wed, 1 Apr 2026 12:47:25 +0200 Subject: [PATCH 4/6] [reproducer] Add task for overwriting pull secret The pull_secret.json might contain authentication to necessary registries for CI job, that are not available during the bootstrap process using PreMetal (earlier ZIronic). --- reproducer.yml | 7 ++++ .../tasks/overwrite_pull_secret.yml | 36 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 roles/reproducer/tasks/overwrite_pull_secret.yml diff --git a/reproducer.yml b/reproducer.yml index 240d2e1347..82bcd860e6 100644 --- a/reproducer.yml +++ b/reproducer.yml @@ -138,6 +138,13 @@ name: reproducer tasks_from: overwrite_zuul_vars.yml + - name: Overwrite pull-secret.json and add missing registries + when: + - not cifmw_deploy_reproducer_env | default(true) | bool + ansible.builtin.include_role: + name: reproducer + tasks_from: overwrite_pull_secret.yml + # NOTE(dpawlik): Since we use ZIronic, some variables are not # redirected to nested ansible execution - they needs to be # included on executing host - controller-0. diff --git a/roles/reproducer/tasks/overwrite_pull_secret.yml b/roles/reproducer/tasks/overwrite_pull_secret.yml new file mode 100644 index 0000000000..530d6f9eb2 --- /dev/null +++ b/roles/reproducer/tasks/overwrite_pull_secret.yml @@ -0,0 +1,36 @@ +--- +# No log in that file are necessary and it should not use: cifmw_nolog var. +- name: Slurp full pull-secret from secrets dir + ansible.builtin.slurp: + src: "{{ ansible_user_dir }}/secrets/pull_secret.json" + register: _full_pull_secret + no_log: true + +- name: Get current cluster pull-secret + kubernetes.core.k8s_info: + kubeconfig: "{{ cifmw_openshift_kubeconfig | default(ansible_user_dir ~ '/.kube/config') }}" + kind: Secret + name: pull-secret + namespace: openshift-config + register: _cluster_pull_secret + no_log: true + +- name: Merge and update cluster pull-secret + vars: + _full_auths: "{{ (_full_pull_secret.content | b64decode | from_json).auths }}" + _cluster_auths: "{{ (_cluster_pull_secret.resources[0].data['.dockerconfigjson'] | b64decode | from_json).auths }}" + _merged: + auths: "{{ _cluster_auths | combine(_full_auths, recursive=true) }}" + kubernetes.core.k8s: + kubeconfig: "{{ cifmw_openshift_kubeconfig | default(ansible_user_dir ~ '/.kube/config') }}" + state: present + definition: + apiVersion: v1 + kind: Secret + metadata: + name: pull-secret + namespace: openshift-config + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: "{{ _merged | to_json | b64encode }}" + no_log: true From 454ab8ec9eb7946f1989d48b089f134e6b7b779b Mon Sep 17 00:00:00 2001 From: Daniel Pawlik Date: Wed, 1 Apr 2026 12:52:02 +0200 Subject: [PATCH 5/6] [reproducer] Move tasks related to pre action after PreMetal bootstrap Let's move all the tasks for pre job execution after PreMetal bootstrap. That would make reproducer playbook easier to read. Signed-off-by: Daniel Pawlik --- reproducer.yml | 45 ++--------------------------- roles/reproducer/tasks/premetal.yml | 36 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 43 deletions(-) create mode 100644 roles/reproducer/tasks/premetal.yml diff --git a/reproducer.yml b/reproducer.yml index 82bcd860e6..84fab83a4e 100644 --- a/reproducer.yml +++ b/reproducer.yml @@ -118,53 +118,12 @@ ansible.builtin.set_fact: hypervisor: "{{ ansible_fqdn }}" - - name: Synchronize src dir + - name: Prepare job after earlier bootstrap by PreMetal when: - not cifmw_deploy_reproducer_env | default(true) | bool ansible.builtin.include_role: name: reproducer - tasks_from: sync_src_dir.yml - - # NOTE(dpawlik): After calling reproducer role using ZIronic tool, - # when the bootstrap phase has been completed, it generates a file - # "reproducer-variables.yml" that contains all variables done in the - # CI job. The problem here is, that "testing" phase might have other - # variables than what was in the bootstrap phase. It means, that - # we need to overwrite the variables with current CI job vars. - - name: Overwrite reproducer-variables.yml when ZIronic bootstrap - when: - - not cifmw_deploy_reproducer_env | default(true) | bool - ansible.builtin.include_role: - name: reproducer - tasks_from: overwrite_zuul_vars.yml - - - name: Overwrite pull-secret.json and add missing registries - when: - - not cifmw_deploy_reproducer_env | default(true) | bool - ansible.builtin.include_role: - name: reproducer - tasks_from: overwrite_pull_secret.yml - - # NOTE(dpawlik): Since we use ZIronic, some variables are not - # redirected to nested ansible execution - they needs to be - # included on executing host - controller-0. - - name: Compute additional deploy_architecture_args with secrets - when: - - not cifmw_deploy_reproducer_env | default(true) | bool - vars: - basic_secret_files: - - "{{ ansible_user_dir }}/secrets/registry_token_creds.yaml" - ansible.builtin.include_role: - name: reproducer - tasks_from: compute_additional_args.yml - loop: "{{ cifmw_deploy_architecture_secret_files | default(basic_secret_files) }}" - loop_control: - loop_var: secret_file - - - name: Print final cifmw_deploy_architecture_args - ansible.builtin.debug: - msg: > - Current cifmw_deploy_architecture_args {{ cifmw_deploy_architecture_args | default('') }} + tasks_from: premetal.yml - name: Run deployment if instructed to when: diff --git a/roles/reproducer/tasks/premetal.yml b/roles/reproducer/tasks/premetal.yml new file mode 100644 index 0000000000..6350bb7e5c --- /dev/null +++ b/roles/reproducer/tasks/premetal.yml @@ -0,0 +1,36 @@ +--- +- name: Synchronize src dir + ansible.builtin.include_tasks: + file: sync_src_dir.yml + +# NOTE(dpawlik): After calling reproducer role using PreMetal tool, +# when the bootstrap phase has been completed, it generates a file +# "reproducer-variables.yml" that contains all variables done in the +# CI job. The problem here is, that "testing" phase might have other +# variables than what was in the bootstrap phase. It means, that +# we need to overwrite the variables with current CI job vars. +- name: Overwrite reproducer-variables.yml when PreMetal bootstrap + ansible.builtin.include_tasks: + file: overwrite_zuul_vars.yml + +- name: Overwrite pull-secret.json and add missing registries + ansible.builtin.include_tasks: + file: overwrite_pull_secret.yml + +# NOTE(dpawlik): Since we use PreMetal, some variables are not +# redirected to nested ansible execution - they needs to be +# included on executing host - controller-0. +- name: Compute additional deploy_architecture_args with secrets + vars: + basic_secret_files: + - "{{ ansible_user_dir }}/secrets/registry_token_creds.yaml" + ansible.builtin.include_tasks: + file: compute_additional_args.yml + loop: "{{ cifmw_deploy_architecture_secret_files | default(basic_secret_files) }}" + loop_control: + loop_var: secret_file + +- name: Print final cifmw_deploy_architecture_args + ansible.builtin.debug: + msg: > + Current cifmw_deploy_architecture_args {{ cifmw_deploy_architecture_args | default('') }} From c175436c102ca96f929f3a3466632d49a5f7a67f Mon Sep 17 00:00:00 2001 From: Daniel Pawlik Date: Wed, 1 Apr 2026 17:12:17 +0200 Subject: [PATCH 6/6] [reproducer] DNM Checking if secret can be dropped Worth to try, if we can skip sync secrets with controller-0 to avoid potential leak. Signed-off-by: Daniel Pawlik --- .../tasks/compute_additional_args.yml | 12 ------------ .../reproducer/tasks/overwrite_pull_secret.yml | 3 +++ roles/reproducer/tasks/overwrite_zuul_vars.yml | 8 -------- roles/reproducer/tasks/premetal.yml | 18 ------------------ roles/reproducer/tasks/sync_src_dir.yml | 10 ---------- 5 files changed, 3 insertions(+), 48 deletions(-) delete mode 100644 roles/reproducer/tasks/compute_additional_args.yml diff --git a/roles/reproducer/tasks/compute_additional_args.yml b/roles/reproducer/tasks/compute_additional_args.yml deleted file mode 100644 index bcae05d166..0000000000 --- a/roles/reproducer/tasks/compute_additional_args.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: "Checking if file exists {{ secret_file }}" - ansible.builtin.stat: - path: "{{ secret_file }}" - register: _current_file - -- name: Add secret file into cifmw_deploy_architecture_args when exists - when: _current_file.stat.exists - ansible.builtin.set_fact: - cifmw_deploy_architecture_args: > - {{ cifmw_deploy_architecture_args | default('') }} - -e @{{ secret_file }} diff --git a/roles/reproducer/tasks/overwrite_pull_secret.yml b/roles/reproducer/tasks/overwrite_pull_secret.yml index 530d6f9eb2..545e393c39 100644 --- a/roles/reproducer/tasks/overwrite_pull_secret.yml +++ b/roles/reproducer/tasks/overwrite_pull_secret.yml @@ -4,6 +4,7 @@ ansible.builtin.slurp: src: "{{ ansible_user_dir }}/secrets/pull_secret.json" register: _full_pull_secret + delegate_to: hypervisor no_log: true - name: Get current cluster pull-secret @@ -13,6 +14,7 @@ name: pull-secret namespace: openshift-config register: _cluster_pull_secret + delegate_to: controller-0 no_log: true - name: Merge and update cluster pull-secret @@ -33,4 +35,5 @@ type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: "{{ _merged | to_json | b64encode }}" + delegate_to: controller-0 no_log: true diff --git a/roles/reproducer/tasks/overwrite_zuul_vars.yml b/roles/reproducer/tasks/overwrite_zuul_vars.yml index e9158489a6..24b7a5b105 100644 --- a/roles/reproducer/tasks/overwrite_zuul_vars.yml +++ b/roles/reproducer/tasks/overwrite_zuul_vars.yml @@ -62,11 +62,3 @@ backup: true no_log: "{{ cifmw_nolog | default(true) | bool }}" delegate_to: controller-0 - - - name: Overwrite custom-params.yml - ansible.builtin.copy: - content: "{{ merged_reproducer_slurp.content | b64decode }}" - dest: "{{ cifmw_basedir }}/artifacts/parameters/custom-params.yml" - mode: "0664" - no_log: "{{ cifmw_nolog | default(true) | bool }}" - delegate_to: controller-0 diff --git a/roles/reproducer/tasks/premetal.yml b/roles/reproducer/tasks/premetal.yml index 6350bb7e5c..d3bd1d90e6 100644 --- a/roles/reproducer/tasks/premetal.yml +++ b/roles/reproducer/tasks/premetal.yml @@ -16,21 +16,3 @@ - name: Overwrite pull-secret.json and add missing registries ansible.builtin.include_tasks: file: overwrite_pull_secret.yml - -# NOTE(dpawlik): Since we use PreMetal, some variables are not -# redirected to nested ansible execution - they needs to be -# included on executing host - controller-0. -- name: Compute additional deploy_architecture_args with secrets - vars: - basic_secret_files: - - "{{ ansible_user_dir }}/secrets/registry_token_creds.yaml" - ansible.builtin.include_tasks: - file: compute_additional_args.yml - loop: "{{ cifmw_deploy_architecture_secret_files | default(basic_secret_files) }}" - loop_control: - loop_var: secret_file - -- name: Print final cifmw_deploy_architecture_args - ansible.builtin.debug: - msg: > - Current cifmw_deploy_architecture_args {{ cifmw_deploy_architecture_args | default('') }} diff --git a/roles/reproducer/tasks/sync_src_dir.yml b/roles/reproducer/tasks/sync_src_dir.yml index 6790407152..29514eb7fc 100644 --- a/roles/reproducer/tasks/sync_src_dir.yml +++ b/roles/reproducer/tasks/sync_src_dir.yml @@ -4,16 +4,6 @@ # job directly on hypervisor. When job starts, src and secrets dir are "recreated" # by zuul-executor with current job data. Sync the data with # controller-0 which is executing nested Ansible. -- name: Synchronize hypervisor secrets dir with controller-0 - vars: - sync_dir: "{{ ansible_user_dir }}/secrets" - ansible.posix.synchronize: - src: "{{ sync_dir }}/" - dest: "zuul@controller-0:{{ sync_dir }}" - archive: true - recursive: true - no_log: "{{ cifmw_nolog | default(true) | bool }}" - - name: Synchronize hypervisor src dir with controller-0 vars: sync_dir: "{{ ansible_user_dir }}/src"