From 5b26d91f83fe003659eb4a8888199b9ca7585094 Mon Sep 17 00:00:00 2001 From: Sayuri Date: Sat, 6 Jun 2026 13:37:35 +0530 Subject: [PATCH 1/4] fix: replace ipcalc with ansible.utils.ipaddr filter --- .../tasks/validate_network_spec.yml | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/prepare_oim/roles/prepare_oim_validation/tasks/validate_network_spec.yml b/prepare_oim/roles/prepare_oim_validation/tasks/validate_network_spec.yml index 622f633d61..3779f7767f 100644 --- a/prepare_oim/roles/prepare_oim_validation/tasks/validate_network_spec.yml +++ b/prepare_oim/roles/prepare_oim_validation/tasks/validate_network_spec.yml @@ -79,14 +79,22 @@ success_msg: "{{ admin_nic_ip_success_msg }}" when: fetch_oim_hostname.stdout in oim_hostname -- name: Compute network address using ipcalc - ansible.builtin.command: "/usr/bin/ipcalc -n {{ admin_nic_ip }}/{{ admin_netmask_bits }}" - register: network_address_output - changed_when: false +# - name: Compute network address using ipcalc +# ansible.builtin.command: "/usr/bin/ipcalc -n {{ admin_nic_ip }}/{{ admin_netmask_bits }}" +# register: network_address_output +# changed_when: false + +# - name: Extract network address +# ansible.builtin.set_fact: +# admin_net_addr: "{{ network_address_output.stdout.split('=')[1] }}" + +- name: Compute network address + ansible.builtin.set_fact: + network_address: "{{ (admin_nic_ip + '/' + (admin_netmask_bits | string)) | ansible.utils.ipaddr('network') }}" -- name: Extract network address +- name: Set admin_net_addr from computed network address ansible.builtin.set_fact: - admin_net_addr: "{{ network_address_output.stdout.split('=')[1] }}" + admin_net_addr: "{{ network_address }}" - name: Initialize network_interface_type ansible.builtin.set_fact: From b7352c2b11d5d70f91058a278717e4d51aff6e7c Mon Sep 17 00:00:00 2001 From: Sayuri Date: Sun, 7 Jun 2026 11:59:25 +0530 Subject: [PATCH 2/4] fix: make update-ca-trust and CA trust paths OS-aware for Wolfi compatibility --- .../library/module_utils/local_repo/config.py | 13 ++++++++++- .../pulp/tasks/create_pulp_config_https.yml | 23 ++++++++++++++++++- .../deploy_containers/pulp/vars/main.yml | 1 - .../tasks/create_k8s_config_nfs.yml | 23 ++++++++++++++++++- provision/roles/k8s_config/vars/main.yml | 1 - 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/common/library/module_utils/local_repo/config.py b/common/library/module_utils/local_repo/config.py index 5a8d4a63f5..9d6a407fcc 100644 --- a/common/library/module_utils/local_repo/config.py +++ b/common/library/module_utils/local_repo/config.py @@ -134,7 +134,18 @@ ISO_TIMEOUT_MIN = 45 # minutes TASK_POLL_INTERVAL = 10 # seconds FILE_URI = "/pulp/api/v3/content/file/files/" -PULP_SSL_CA_CERT = "/etc/pki/ca-trust/source/anchors/pulp_webserver.crt" + +import os + +def _get_ca_cert_path(): + """Return CA cert path based on OS. Fedora/RHEL vs Wolfi/Debian.""" + rhel_path = "/etc/pki/ca-trust/source/anchors/pulp_webserver.crt" + wolfi_path = "/usr/local/share/ca-certificates/pulp_webserver.crt" + if os.path.exists("/etc/pki/ca-trust/source/anchors"): + return rhel_path + return wolfi_path + +PULP_SSL_CA_CERT = _get_ca_cert_path() # ---------------------------- # Used by download_image.py # ---------------------------- diff --git a/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml b/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml index f015f6ce74..0127f8e905 100644 --- a/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml +++ b/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml @@ -108,15 +108,36 @@ state: file loop: "{{ cert_items.values() }}" + - name: Detect CA trust anchors directory + ansible.builtin.set_fact: + ca_trust_anchors_dir: >- + {{ '/etc/pki/ca-trust/source/anchors' + if ansible_facts['os_family'] | default('') in ['RedHat', 'Fedora'] + else '/usr/local/share/ca-certificates' }} + when: ca_trust_anchors_dir is not defined + + - name: Set anchors path + ansible.builtin.set_fact: + ca_trust_path: "{{ ca_trust_anchors_dir }}/pulp_webserver.crt" + when: ca_trust_path is not defined + - name: Copy Pulp crt to container trust ansible.builtin.copy: src: "{{ pulp_cert_src }}" dest: "{{ ca_trust_path }}" mode: "{{ logs_dir_permission }}" + - name: Detect CA trust update command + ansible.builtin.set_fact: + ca_trust_cmd: >- + {{ 'update-ca-trust extract' + if ansible_facts['os_family'] | default('') in ['RedHat', 'Fedora'] + else 'update-ca-certificates' }} + when: ca_trust_cmd is not defined + - name: Add Pulp Certificate to TrustStore ansible.builtin.command: - cmd: update-ca-trust extract + cmd: "{{ ca_trust_cmd }}" changed_when: false - name: Create a track file diff --git a/prepare_oim/roles/deploy_containers/pulp/vars/main.yml b/prepare_oim/roles/deploy_containers/pulp/vars/main.yml index da17b168d3..d352bfc2e0 100644 --- a/prepare_oim/roles/deploy_containers/pulp/vars/main.yml +++ b/prepare_oim/roles/deploy_containers/pulp/vars/main.yml @@ -138,7 +138,6 @@ generate_cert_cmd: > -addext {{ cert_san }} pulp_cert_src: "/opt/omnia/pulp/settings/certs/pulp_webserver.crt" -ca_trust_path: "/etc/pki/ca-trust/source/anchors/" # Usage: reload_pulp_nginx.yml nginx_reload_cmd: "nginx -s reload" diff --git a/provision/roles/k8s_config/tasks/create_k8s_config_nfs.yml b/provision/roles/k8s_config/tasks/create_k8s_config_nfs.yml index 47a48f976d..624417ff36 100644 --- a/provision/roles/k8s_config/tasks/create_k8s_config_nfs.yml +++ b/provision/roles/k8s_config/tasks/create_k8s_config_nfs.yml @@ -200,6 +200,19 @@ nfs_subdir_external_provisioner_pkg: "{{ k8s_packages_json['service_kube_control_plane_first']['cluster'] | selectattr('type', 'equalto', 'tarball') | selectattr('package', 'search', 'nfs-subdir-external-provisioner') | map(attribute='package') | join }}" # noqa: yaml[line-length] whereabouts_pkg: "{{ k8s_packages_json['service_kube_control_plane_first']['cluster'] | selectattr('type', 'equalto', 'git') | selectattr('package', 'search', 'whereabouts') | map(attribute='package') | join }}" # noqa: yaml[line-length] +- name: Detect CA trust anchors directory + ansible.builtin.set_fact: + ca_trust_anchors_dir: >- + {{ '/etc/pki/ca-trust/source/anchors' + if ansible_facts['os_family'] | default('') in ['RedHat', 'Fedora'] + else '/usr/local/share/ca-certificates' }} + when: ca_trust_anchors_dir is not defined + +- name: Set anchors path + ansible.builtin.set_fact: + anchors_path: "{{ ca_trust_anchors_dir }}/pulp_webserver.crt" + when: anchors_path is not defined + - name: Copy pulp webserver certificate to target host ansible.builtin.copy: src: "{{ pulp_webserver_cert_path }}" @@ -207,8 +220,16 @@ mode: "{{ file_mode }}" become: true +- name: Detect CA trust update command + ansible.builtin.set_fact: + ca_trust_cmd: >- + {{ 'update-ca-trust' + if ansible_facts['os_family'] | default('') in ['RedHat', 'Fedora'] + else 'update-ca-certificates' }} + when: ca_trust_cmd is not defined + - name: Update CA trust on target host - ansible.builtin.command: update-ca-trust + ansible.builtin.command: "{{ ca_trust_cmd }}" register: update_ca changed_when: false diff --git a/provision/roles/k8s_config/vars/main.yml b/provision/roles/k8s_config/vars/main.yml index c949564d70..baa9583d29 100644 --- a/provision/roles/k8s_config/vars/main.yml +++ b/provision/roles/k8s_config/vars/main.yml @@ -27,7 +27,6 @@ whereabouts_git_url: "{{ offline_git_path }}/{{ whereabouts_pkg }}/{{ whereabout file_mode: "0644" ha_config_file: "{{ input_project_dir }}/high_availability_config.yml" pulp_webserver_cert_path: "/opt/omnia/pulp/settings/certs/pulp_webserver.crt" -anchors_path: "/etc/pki/ca-trust/source/anchors/pulp_webserver.crt" # Usage: create_node_dir.yml nodes_yaml: "{{ hostvars['localhost']['oim_shared_path'] }}/omnia/openchami/workdir/nodes/nodes.yaml" From 6529f1ae7b7c5d7b544a2f8d0d668dc24455cba5 Mon Sep 17 00:00:00 2001 From: Sayuri Date: Sun, 7 Jun 2026 13:05:29 +0530 Subject: [PATCH 3/4] fix: ca directory issue --- .../pulp/tasks/create_pulp_config_https.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml b/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml index 0127f8e905..d057d6e346 100644 --- a/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml +++ b/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml @@ -121,6 +121,12 @@ ca_trust_path: "{{ ca_trust_anchors_dir }}/pulp_webserver.crt" when: ca_trust_path is not defined + - name: Ensure CA trust directory exists + ansible.builtin.file: + path: "{{ ca_trust_anchors_dir }}" + state: directory + mode: '0755' + - name: Copy Pulp crt to container trust ansible.builtin.copy: src: "{{ pulp_cert_src }}" From 6e7e4a2b6f3d4a05e0e2899806d74e008b3145e8 Mon Sep 17 00:00:00 2001 From: Sayuri Date: Tue, 9 Jun 2026 11:47:00 +0530 Subject: [PATCH 4/4] Configured pulp as fallback to download RHEL packages --- .../library/module_utils/local_repo/config.py | 1 + .../module_utils/local_repo/download_rpm.py | 277 ++++++++++++------ .../tasks/create_metadata.yml | 14 + .../tasks/process_rpm_repo.yml | 7 + .../roles/validation/tasks/prerequisites.yml | 7 + .../pulp/tasks/create_pulp_config_https.yml | 63 +++- 6 files changed, 277 insertions(+), 92 deletions(-) diff --git a/common/library/module_utils/local_repo/config.py b/common/library/module_utils/local_repo/config.py index 9d6a407fcc..3ac531779e 100644 --- a/common/library/module_utils/local_repo/config.py +++ b/common/library/module_utils/local_repo/config.py @@ -86,6 +86,7 @@ "x86_64": ["dnf", "info", "--quiet"], "aarch64": ["dnf", "info", "--quiet", "--forcearch=aarch64"] } +PULP_RPM_PACKAGES_API = "/pulp/api/v3/content/rpm/packages/" # ---------------------------- # Cleanup File Types diff --git a/common/library/module_utils/local_repo/download_rpm.py b/common/library/module_utils/local_repo/download_rpm.py index e6fe9603a2..1af2c4ea9d 100644 --- a/common/library/module_utils/local_repo/download_rpm.py +++ b/common/library/module_utils/local_repo/download_rpm.py @@ -18,17 +18,91 @@ import subprocess import os import glob +import json import shutil from pathlib import Path from ansible.module_utils.local_repo.config import ( DNF_COMMANDS, - DNF_INFO_COMMANDS + DNF_INFO_COMMANDS, + PULP_RPM_PACKAGES_API ) from multiprocessing import Lock from ansible.module_utils.local_repo.parse_and_download import write_status_to_file, _prefix_repo_name_with_arch file_lock = Lock() + +def _is_dnf_available(): + """Check if dnf binary is available on the system.""" + return shutil.which('dnf') is not None + + +def _pulp_cmd(cmd_string, logger=None): + """Run a pulp CLI command and return parsed JSON output, or None on failure.""" + result = subprocess.run(cmd_string, shell=True, check=False, capture_output=True, text=True) + if result.returncode != 0: + if logger: + logger.debug(f"Pulp command failed: {cmd_string}, stderr: {result.stderr}") + return None + try: + return json.loads(result.stdout) + except (json.JSONDecodeError, ValueError): + return None + + +def _pulp_get_repo_version(repo_name, logger): + """Get latest_version_href for a Pulp RPM repository.""" + data = _pulp_cmd(f"pulp rpm repository show --name {repo_name}", logger) + if isinstance(data, dict): + return data.get("latest_version_href", "") + return "" + + +def _pulp_find_package(pkg_name, repo_name, logger): + """Find RPM package in a Pulp repository. Returns package info dict or None.""" + version_href = _pulp_get_repo_version(repo_name, logger) + if not version_href: + return None + api_url = f"{PULP_RPM_PACKAGES_API}?name={pkg_name}&repository_version={version_href}&limit=1" + data = _pulp_cmd(f"pulp show --href '{api_url}'", logger) + if isinstance(data, dict) and data.get("count", 0) > 0: + return data.get("results", [None])[0] + if isinstance(data, list) and len(data) > 0: + return data[0] + return None + + +def _pulp_validate_package(pkg_name, repo_name, logger): + """Check if package exists in Pulp repo (replaces dnf info).""" + return _pulp_find_package(pkg_name, repo_name, logger) is not None + + +def _pulp_download_rpm(pkg_name, repo_name, rpm_directory, logger): + """Download a single RPM from Pulp distribution (replaces dnf download).""" + pkg_info = _pulp_find_package(pkg_name, repo_name, logger) + if not pkg_info: + logger.error(f"Package '{pkg_name}' not found in Pulp repo '{repo_name}'") + return False + location_href = pkg_info.get("location_href", "") + if not location_href: + logger.error(f"No location_href for package '{pkg_name}'") + return False + dist_data = _pulp_cmd(f"pulp rpm distribution show --name {repo_name}", logger) + if not isinstance(dist_data, dict) or not dist_data.get("base_url"): + logger.error(f"Could not get distribution URL for '{repo_name}'") + return False + base_url = dist_data["base_url"].rstrip("/") + download_url = f"{base_url}/{location_href}" + logger.info(f"Downloading '{pkg_name}' from {download_url}") + dl_result = subprocess.run( + ["wget", "-c", "-q", "--no-check-certificate", "-P", rpm_directory, download_url], + check=False, capture_output=True, text=True + ) + if dl_result.returncode == 0 or _check_rpm_downloaded(rpm_directory, pkg_name): + return True + logger.error(f"wget failed for '{pkg_name}': {dl_result.stderr}") + return False + def _check_rpm_downloaded(rpm_directory, pkg_name): """ Check if an RPM file for the given package exists in the directory. @@ -100,86 +174,107 @@ def process_rpm(package, repo_store_path, status_file_path, cluster_os_type, arch_key = "x86_64" if arc.lower() in ("x86_64") else "aarch64" - # First try to download all at once - dnf_download_command = ( - DNF_COMMANDS[arch_key] - + [f"--destdir={rpm_directory}"] - + rpm_list - ) - - result = subprocess.run( - dnf_download_command, - check=False, - capture_output=True, - text=True - ) - logger.info(f"Return code {result.returncode}") - logger.debug(f"STDOUT:\n{result.stdout}") - logger.debug(f"STDERR:\n{result.stderr}") - - stdout_lines = result.stdout.splitlines() - stderr_lines = result.stderr.splitlines() - downloaded = [] failed = [] - # Detect successes/failures from combined run - # Use filesystem check instead of parsing output (works with both DNF4 and DNF5) - for pkg in rpm_list: - # Get repo_name for this specific RPM from mapping - pkg_repo_name = repo_mapping.get(pkg, "") + if _is_dnf_available(): + # First try to download all at once + dnf_download_command = ( + DNF_COMMANDS[arch_key] + + [f"--destdir={rpm_directory}"] + + rpm_list + ) - # Check if package was downloaded by looking for the RPM file - pkg_downloaded = _check_rpm_downloaded(rpm_directory, pkg) - - # Also check for "No match for argument" or "No package" errors in stderr - pkg_not_found = False - for line in stderr_lines: - if pkg in line and ("No match for argument" in line or - "No package" in line or - "not found" in line.lower()): - pkg_not_found = True - break - - if pkg_downloaded and not pkg_not_found: - downloaded.append(pkg) - write_status_to_file(status_file_path, pkg, "rpm", "Success", logger, file_lock, pkg_repo_name) - logger.info(f"Package '{pkg}' downloaded successfully.") - else: - failed.append(pkg) - if pkg_not_found: - logger.warning(f"Package '{pkg}' not found in configured repositories") - - # Retry failed ones individually - if failed: - logger.warning(f"Retrying failed packages individually: {failed}") - for pkg in failed[:]: - cmd = DNF_COMMANDS[arch_key] + [f'--destdir={rpm_directory}', pkg] - retry_res = subprocess.run(cmd, check=False, capture_output=True, text=True) + result = subprocess.run( + dnf_download_command, + check=False, + capture_output=True, + text=True + ) + logger.info(f"Return code {result.returncode}") + logger.debug(f"STDOUT:\n{result.stdout}") + logger.debug(f"STDERR:\n{result.stderr}") + + stdout_lines = result.stdout.splitlines() + stderr_lines = result.stderr.splitlines() + + # Detect successes/failures from combined run + # Use filesystem check instead of parsing output (works with both DNF4 and DNF5) + for pkg in rpm_list: # Get repo_name for this specific RPM from mapping pkg_repo_name = repo_mapping.get(pkg, "") - # Check for package not found errors - retry_stderr = retry_res.stderr.lower() - pkg_invalid = any(err in retry_stderr for err in [ - "no match for argument", - "no package", - "not found", - "unable to find a match" - ]) - - # Check if RPM file exists after retry (works with both DNF4 and DNF5) - if retry_res.returncode == 0 and _check_rpm_downloaded(rpm_directory, pkg): + # Check if package was downloaded by looking for the RPM file + pkg_downloaded = _check_rpm_downloaded(rpm_directory, pkg) + + # Also check for "No match for argument" or "No package" errors in stderr + pkg_not_found = False + for line in stderr_lines: + if pkg in line and ("No match for argument" in line or + "No package" in line or + "not found" in line.lower()): + pkg_not_found = True + break + + if pkg_downloaded and not pkg_not_found: downloaded.append(pkg) - failed.remove(pkg) write_status_to_file(status_file_path, pkg, "rpm", "Success", logger, file_lock, pkg_repo_name) - logger.info(f"Package '{pkg}' downloaded successfully on retry.") + logger.info(f"Package '{pkg}' downloaded successfully.") else: - write_status_to_file(status_file_path, pkg, "rpm", "Failed", logger, file_lock, pkg_repo_name) - if pkg_invalid: - logger.error(f"Package '{pkg}' does not exist in configured repositories.") + failed.append(pkg) + if pkg_not_found: + logger.warning(f"Package '{pkg}' not found in configured repositories") + + # Retry failed ones individually + if failed: + logger.warning(f"Retrying failed packages individually: {failed}") + for pkg in failed[:]: + cmd = DNF_COMMANDS[arch_key] + [f'--destdir={rpm_directory}', pkg] + retry_res = subprocess.run(cmd, check=False, capture_output=True, text=True) + # Get repo_name for this specific RPM from mapping + pkg_repo_name = repo_mapping.get(pkg, "") + + # Check for package not found errors + retry_stderr = retry_res.stderr.lower() + pkg_invalid = any(err in retry_stderr for err in [ + "no match for argument", + "no package", + "not found", + "unable to find a match" + ]) + + # Check if RPM file exists after retry (works with both DNF4 and DNF5) + if retry_res.returncode == 0 and _check_rpm_downloaded(rpm_directory, pkg): + downloaded.append(pkg) + failed.remove(pkg) + write_status_to_file(status_file_path, pkg, "rpm", "Success", logger, file_lock, pkg_repo_name) + logger.info(f"Package '{pkg}' downloaded successfully on retry.") + else: + write_status_to_file(status_file_path, pkg, "rpm", "Failed", logger, file_lock, pkg_repo_name) + if pkg_invalid: + logger.error(f"Package '{pkg}' does not exist in configured repositories.") + else: + logger.error(f"Package '{pkg}' still failed after retry.") + + else: + # Pulp-based download (dnf not available, e.g. Wolfi container) + logger.info("dnf not available, using Pulp CLI for RPM download") + for pkg in rpm_list: + pkg_repo_name = repo_mapping.get(pkg, "") + if pkg_repo_name: + prefixed_repo_name = _prefix_repo_name_with_arch(pkg_repo_name, status_file_path, logger) + if _pulp_download_rpm(pkg, prefixed_repo_name, rpm_directory, logger): + downloaded.append(pkg) + write_status_to_file(status_file_path, pkg, "rpm", "Success", logger, file_lock, pkg_repo_name) + logger.info(f"Package '{pkg}' downloaded successfully via Pulp.") else: - logger.error(f"Package '{pkg}' still failed after retry.") + failed.append(pkg) + write_status_to_file(status_file_path, pkg, "rpm", "Failed", logger, file_lock, pkg_repo_name) + logger.error(f"Package '{pkg}' download failed via Pulp.") + else: + failed.append(pkg) + logger.warning(f"No repo_name mapping for package '{pkg}', cannot download via Pulp") + write_status_to_file(status_file_path, pkg, "rpm", "Failed", logger, file_lock, "") # Determine final status if not failed: @@ -191,35 +286,47 @@ def process_rpm(package, repo_store_path, status_file_path, cluster_os_type, else: logger.info("RPM won't be downloaded when repo_config is partial or never") - logger.info("Validating package availability using dnf info...") arch_key = "x86_64" if arc.lower() in ("x86_64") else "aarch64" valid_packages = [] invalid_packages = [] + use_dnf = _is_dnf_available() + + if use_dnf: + logger.info("Validating package availability using dnf info...") + else: + logger.info("dnf not available, validating package availability using Pulp CLI...") for pkg in package["rpm_list"]: # Get repo_name for this specific RPM from mapping pkg_repo_name = repo_mapping.get(pkg, "") - # Validate package using dnf info with specific repo only - if pkg_repo_name: - # Apply architecture prefixing if needed - prefixed_repo_name = _prefix_repo_name_with_arch(pkg_repo_name, status_file_path, logger) + if not pkg_repo_name: + # Skip validation if no specific repo is defined + logger.warning(f"No repo_name defined for package '{pkg}', skipping validation") + continue + + # Apply architecture prefixing if needed + prefixed_repo_name = _prefix_repo_name_with_arch(pkg_repo_name, status_file_path, logger) + + if use_dnf: + # Validate package using dnf info with specific repo dnf_info_command = DNF_INFO_COMMANDS[arch_key] + [ f"--repo={prefixed_repo_name}", # Search specific repo from JSON pkg ] + result = subprocess.run( + dnf_info_command, + check=False, + capture_output=True, + text=True + ) + pkg_exists = result.returncode == 0 else: - # Skip validation if no specific repo is defined - logger.warning(f"No repo_name defined for package '{pkg}', skipping validation") - continue - result = subprocess.run( - dnf_info_command, - check=False, - capture_output=True, - text=True - ) - if result.returncode == 0: + # Validate package using Pulp CLI + pkg_exists = _pulp_validate_package(pkg, prefixed_repo_name, logger) + + if pkg_exists: # Package exists and is available valid_packages.append(pkg) write_status_to_file( diff --git a/local_repo/roles/parse_and_download/tasks/create_metadata.yml b/local_repo/roles/parse_and_download/tasks/create_metadata.yml index c994f225dc..54eaea6cc9 100644 --- a/local_repo/roles/parse_and_download/tasks/create_metadata.yml +++ b/local_repo/roles/parse_and_download/tasks/create_metadata.yml @@ -15,6 +15,13 @@ - name: Clean DNF cache ansible.builtin.command: dnf clean all changed_when: false + when: ansible_facts['pkg_mgr'] | default('') in ['dnf', 'dnf4', 'dnf5', 'yum'] + +- name: Clean apk cache + ansible.builtin.command: apk cache clean + changed_when: false + failed_when: false + when: ansible_facts['pkg_mgr'] | default('') == 'apk' - name: Remove pulp.repo if exists ansible.builtin.file: @@ -25,6 +32,13 @@ ansible.builtin.dnf: update_cache: true changed_when: false + when: ansible_facts['pkg_mgr'] | default('') in ['dnf', 'dnf4', 'dnf5', 'yum'] + +- name: Regenerate apk package index + community.general.apk: + update_cache: true + changed_when: false + when: ansible_facts['pkg_mgr'] | default('') == 'apk' - name: Check for data folder existence ansible.builtin.stat: diff --git a/local_repo/roles/parse_and_download/tasks/process_rpm_repo.yml b/local_repo/roles/parse_and_download/tasks/process_rpm_repo.yml index 166e6f8784..78de31f50e 100644 --- a/local_repo/roles/parse_and_download/tasks/process_rpm_repo.yml +++ b/local_repo/roles/parse_and_download/tasks/process_rpm_repo.yml @@ -43,3 +43,10 @@ ansible.builtin.dnf: update_cache: true changed_when: false + when: ansible_facts['pkg_mgr'] | default('') in ['dnf', 'dnf4', 'dnf5', 'yum'] + +- name: Regenerate apk package index + community.general.apk: + update_cache: true + changed_when: false + when: ansible_facts['pkg_mgr'] | default('') == 'apk' diff --git a/local_repo/roles/validation/tasks/prerequisites.yml b/local_repo/roles/validation/tasks/prerequisites.yml index a969bce84e..de6c5ffac8 100644 --- a/local_repo/roles/validation/tasks/prerequisites.yml +++ b/local_repo/roles/validation/tasks/prerequisites.yml @@ -25,3 +25,10 @@ loop: - "{{ ['max_parallel_downloads', dnf_max_parallel] }}" - "{{ ['strict', 'False'] }}" + when: ansible_facts['pkg_mgr'] | default('') in ['dnf', 'dnf4', 'dnf5', 'yum'] + +- name: Refresh apk package index + community.general.apk: + update_cache: true + changed_when: false + when: ansible_facts['pkg_mgr'] | default('') == 'apk' diff --git a/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml b/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml index d057d6e346..8b228e8860 100644 --- a/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml +++ b/prepare_oim/roles/deploy_containers/pulp/tasks/create_pulp_config_https.yml @@ -133,18 +133,67 @@ dest: "{{ ca_trust_path }}" mode: "{{ logs_dir_permission }}" - - name: Detect CA trust update command + - name: Change group ownership of SSL certificate and key + ansible.builtin.file: + path: "{{ item }}" + group: pulp + state: file + loop: "{{ cert_items.values() }}" + + # ── CA Trust: OS-aware cert installation ──────────────────────────────── + # Fedora/RHEL: use update-ca-trust (native command exists) + # Wolfi/Other: directly append cert to system CA bundle (no command exists) + + - name: Detect CA trust anchors directory ansible.builtin.set_fact: - ca_trust_cmd: >- - {{ 'update-ca-trust extract' + ca_trust_anchors_dir: >- + {{ '/etc/pki/ca-trust/source/anchors' if ansible_facts['os_family'] | default('') in ['RedHat', 'Fedora'] - else 'update-ca-certificates' }} - when: ca_trust_cmd is not defined + else '/usr/local/share/ca-certificates' }} + when: ca_trust_anchors_dir is not defined + + - name: Set anchors path + ansible.builtin.set_fact: + ca_trust_path: "{{ ca_trust_anchors_dir }}/pulp_webserver.crt" + when: ca_trust_path is not defined - - name: Add Pulp Certificate to TrustStore + - name: Ensure CA trust directory exists + ansible.builtin.file: + path: "{{ ca_trust_anchors_dir }}" + state: directory + mode: '0755' + + - name: Copy Pulp crt to container trust + ansible.builtin.copy: + src: "{{ pulp_cert_src }}" + dest: "{{ ca_trust_path }}" + mode: "{{ logs_dir_permission }}" + + - name: Add Pulp Certificate to TrustStore (RHEL/Fedora) ansible.builtin.command: - cmd: "{{ ca_trust_cmd }}" + cmd: update-ca-trust extract + changed_when: false + when: ansible_facts['os_family'] | default('') in ['RedHat', 'Fedora'] + + - name: Add Pulp Certificate to TrustStore (Wolfi/Other) + ansible.builtin.shell: | + cat "{{ ca_trust_path }}" >> /etc/ssl/certs/ca-certificates.crt changed_when: false + when: ansible_facts['os_family'] | default('') not in ['RedHat', 'Fedora'] + + # ── End CA Trust ──────────────────────────────────────────────────────── + + - name: Create a track file + ansible.builtin.file: + path: "{{ track_file_path }}" + state: touch + mode: "{{ logs_dir_permission }}" + + - name: Record current timestamp in track file + ansible.builtin.copy: + dest: "{{ track_file_path }}" + content: "Timestamp: {{ ansible_date_time.iso8601 }}" + mode: "{{ logs_dir_permission }}" - name: Create a track file ansible.builtin.file: