Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions build_stream/orchestrator/catalog/use_cases/parse_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,13 @@ def _extract_catalog_metadata(
role_images[role_name] = f"{role_name}.img"
roles.sort()

# Add synthetic service_kube_control_plane_first_x86_64 role if base role exists
# This ensures Image records are created for the _first variant during build-image completion
if "service_kube_control_plane_x86_64" in roles and "service_kube_control_plane_first_x86_64" not in roles:
roles.append("service_kube_control_plane_first_x86_64")
role_images["service_kube_control_plane_first_x86_64"] = "service_kube_control_plane_first_x86_64.img"
roles.sort()

return {
"image_group_id": str(image_group_id),
"roles": roles,
Expand Down
3 changes: 1 addition & 2 deletions build_stream/orchestrator/upload/use_cases/upload_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ def _validate_all_files(self, files: List[tuple]):
"""Validate all files before processing (fail-fast).

Args:
files: List of (filename, content) tuples.

Raises:
InvalidFilenameError: If any filename is invalid.
Expand Down Expand Up @@ -600,7 +599,7 @@ def _copy_software_config_from_artifacts(self, job_id: str) -> None:
try:
config = load_config()
artifacts_base = Path(config.file_store.base_path)
source = artifacts_base / job_id / "software_config.json"
source = artifacts_base / job_id / "input" / "software_config.json"

if not source.exists():
log_secure_info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1190,91 +1190,10 @@
},
"required": [
"url",
"gpgkey",
"name"
],
"allOf": [
{
"if": {
"required": [
"sslcacert"
],
"properties": {
"sslcacert": {
"minLength": 1
}
}
},
"then": {
"required": [
"sslclientkey",
"sslclientcert"
],
"properties": {
"sslclientkey": {
"minLength": 1
},
"sslclientcert": {
"minLength": 1
}
}
}
},
{
"if": {
"required": [
"sslclientkey"
],
"properties": {
"sslclientkey": {
"minLength": 1
}
}
},
"then": {
"required": [
"sslcacert",
"sslclientcert"
],
"properties": {
"sslcacert": {
"minLength": 1
},
"sslclientcert": {
"minLength": 1
}
}
}
},
{
"if": {
"required": [
"sslclientcert"
],
"properties": {
"sslclientcert": {
"minLength": 1
}
}
},
"then": {
"required": [
"sslcacert",
"sslclientkey"
],
"properties": {
"sslcacert": {
"minLength": 1
},
"sslclientkey": {
"minLength": 1
}
}
}
}
]
},
"description": "Optional configuration for overriding policy and caching settings for RHEL subscription-based repositories on x86_64 architecture."
"description": "Optional configuration for overriding policy and caching settings for RHEL subscription-based repositories on x86_64 architecture. Only url and name are required. Certificates are auto-populated from subscription defaults if not provided."
},
"rhel_subscription_repo_config_aarch64": {
"type": [
Expand Down Expand Up @@ -1329,91 +1248,10 @@
},
"required": [
"url",
"gpgkey",
"name"
],
"allOf": [
{
"if": {
"required": [
"sslcacert"
],
"properties": {
"sslcacert": {
"minLength": 1
}
}
},
"then": {
"required": [
"sslclientkey",
"sslclientcert"
],
"properties": {
"sslclientkey": {
"minLength": 1
},
"sslclientcert": {
"minLength": 1
}
}
}
},
{
"if": {
"required": [
"sslclientkey"
],
"properties": {
"sslclientkey": {
"minLength": 1
}
}
},
"then": {
"required": [
"sslcacert",
"sslclientcert"
],
"properties": {
"sslcacert": {
"minLength": 1
},
"sslclientcert": {
"minLength": 1
}
}
}
},
{
"if": {
"required": [
"sslclientcert"
],
"properties": {
"sslclientcert": {
"minLength": 1
}
}
},
"then": {
"required": [
"sslcacert",
"sslclientkey"
],
"properties": {
"sslcacert": {
"minLength": 1
},
"sslclientkey": {
"minLength": 1
}
}
}
}
]
},
"description": "Optional configuration for overriding policy and caching settings for RHEL subscription-based repositories on aarch64 architecture."
"description": "Optional configuration for overriding policy and caching settings for RHEL subscription-based repositories on aarch64 architecture. Only url and name are required. Certificates are auto-populated from subscription defaults if not provided."
}
},
"required": [
Expand Down
32 changes: 18 additions & 14 deletions input/local_repo_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,26 +84,26 @@
#
# 6. rhel_subscription_repo_config_x86_64
#-------------------------------------------
# Optional configuration for overriding policy and caching settings for RHEL
# subscription-based repositories on x86_64 architecture.
# When subscription is enabled, this config takes precedence over dynamically
# generated URLs for matching repositories and adds any additional repositories.
# Optional configuration for overriding RHEL subscription-based repositories
# on x86_64 architecture.
# When subscription is enabled, user-provided repos with names matching base repos
# (baseos, appstream, codeready-builder) will have their URL overridden.
# Non-matching repositories are added as additional repos.
# Fields:
# url : Base URL of the repository (REQUIRED)
# gpgkey : GPG key URL (REQUIRED, can be empty to disable gpgcheck)
# name : Repository name for matching (REQUIRED)
# Use 'baseos', 'appstream', or 'codeready-builder' to override base repo URLs
# gpgkey : GPG key URL (OPTIONAL, defaults to empty to disable gpgcheck)
# policy : Repository sync policy. Allowed values: always, partial (OPTIONAL)
# If not provided, uses repo_config from software_config.json
# caching : Enable or disable local caching. Allowed values: true, false (OPTIONAL)
# If not provided, defaults to true
# sslcacert : Path to SSL CA certificate (optional)
# sslclientkey: Path to SSL client key (optional)
# sslclientcert: Path to SSL client certificate (optional)
# Notes:
# - Do not use Jinja variables in this configuration.
# - Omit SSL fields entirely if SSL is not in use.
# - Matching is done by repository name (e.g., appstream)
# - Non-matching repositories are added as additional repos
# - Only 'url' and 'name' are required fields
# - SSL certificates are ALWAYS auto-populated from RHEL subscription defaults
# - User cannot override SSL certificates (sslcacert, sslclientkey, sslclientcert)
# - Matching is done by repository name (e.g., baseos, appstream, codeready-builder)
# - Non-matching repositories are added as additional repos with subscription certs
#
# 7. rhel_subscription_repo_config_aarch64
#--------------------------------------------
Expand Down Expand Up @@ -176,8 +176,12 @@ rhel_os_url_x86_64:
rhel_os_url_aarch64:
# Example:
# rhel_subscription_repo_config_x86_64:
# - { url: "https://example.com/appstream", gpgkey: "", sslcacert: "", sslclientkey: "", sslclientcert: "", name: "appstream", policy: "always", caching: true }
# - { url: "https://cdn.redhat.com/content/dist/rhel10/10.0/x86_64/supplementary/os/", gpgkey: "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release", sslcacert: "", sslclientkey: "", sslclientcert: "", name: "supplementary", policy: "always", caching: false }
# # Override baseos with standard URL (only url and name required, certs auto-populated)
# - { url: "https://cdn.redhat.com/content/dist/rhel10/10.0/x86_64/baseos/os/", name: "baseos" }
# # Override appstream with custom URL and policy
# - { url: "https://cdn.redhat.com/content/dist/rhel10/10.0/x86_64/appstream/os/", name: "appstream", policy: "always" }
# # Add supplementary repo (non-base repo, certs auto-populated)
# - { url: "https://cdn.redhat.com/content/dist/rhel10/10.0/x86_64/supplementary/os/", name: "supplementary", policy: "always", caching: false }
rhel_subscription_repo_config_x86_64:
rhel_subscription_repo_config_aarch64:
# Making incorrect changes to this variable can cause omnia failure. Please edit cautiously.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,45 @@
changed_when: true
failed_when: false

- name: Extract only RHEL baseurls (appstream, baseos, codeready-builder)
- name: Extract EUS baseurls (appstream, baseos, codeready-builder)
vars:
eus_pattern: "rhel-{{ rhel_version }}-for-x86_64-(appstream|baseos)-eus-rpms|codeready-builder-for-rhel-{{ rhel_version }}-x86_64-eus-rpms"
ansible.builtin.shell: |
set -o pipefail
awk -v ver="{{ rhel_version }}" '
awk '
/^\[/ {section=$0}
/^baseurl/ && section ~ /(rhel-{{ rhel_version }}-for-x86_64-(appstream|baseos)-rpms|codeready-builder-for-rhel-{{ rhel_version }}-x86_64-rpms)/ {
gsub(/\$releasever/, ver, $3)
/^baseurl/ && section ~ /({{ eus_pattern }})/ {
gsub(/\$releasever/, "{{ hostvars['localhost']['cluster_os_version'] }}", $3)
print $3
}
' {{ redhat_repo_file }}
register: repo_baseurls
register: eus_baseurls
changed_when: false
failed_when: false

- name: Extract standard baseurls if EUS not found
vars:
std_pattern: "rhel-{{ rhel_version }}-for-x86_64-(appstream|baseos)-rpms|codeready-builder-for-rhel-{{ rhel_version }}-x86_64-rpms"
ansible.builtin.shell: |
set -o pipefail
awk '
/^\[/ {section=$0}
/^baseurl/ && section ~ /({{ std_pattern }})/ {
gsub(/\$releasever/, "{{ hostvars['localhost']['cluster_os_version'] }}", $3)
print $3
}
' {{ redhat_repo_file }}
register: standard_baseurls
changed_when: false
when: eus_baseurls.stdout_lines | default([]) | length == 0

- name: Set fact repo baseurls with trailing slash
- name: Set fact repo baseurls (EUS preferred, fallback to standard)
ansible.builtin.set_fact:
repo_baseurls: "{{ repo_baseurls.stdout_lines
| map('regex_replace', '([^/])$', '\\1/')
| list }}"
repo_baseurls: >-
{{ (eus_baseurls.stdout_lines if (eus_baseurls.stdout_lines | default([]) | length > 0)
else standard_baseurls.stdout_lines | default([]))
| map('regex_replace', '([^/])$', '\1/')
| list }}

- name: Show extracted baseurls
ansible.builtin.debug:
Expand Down
Loading
Loading