diff --git a/pkg/distro/defs/distros.yaml b/pkg/distro/defs/distros.yaml index cfed85c415..a6106f754f 100644 --- a/pkg/distro/defs/distros.yaml +++ b/pkg/distro/defs/distros.yaml @@ -148,6 +148,73 @@ distros: vendor: "almalinux" ostree_ref_tmpl: "almalinux/10/%s/edge" + - &rhel9 + name: "rhel-{{.MajorVersion}}.{{.MinorVersion}}" + match: "rhel-9.[0-9]{,[0-9]}" + # rhel9 support being named "rhel-91" for "rhel-9.1" or "rhel-910" for "rhel-9.10" etc + transform_re: "^(?Prhel)-(?P9)(?P[0-9]{1,2})$" + distro_like: rhel-9 + product: "Red Hat Enterprise Linux" + os_version: "9.{{.MinorVersion}}" + release_version: 9 + module_platform_id: "platform:el9" + vendor: "redhat" + ostree_ref_tmpl: "rhel/9/%s/edge" + default_fs_type: "xfs" + defs_path: rhel-9 + iso_label_tmpl: "RHEL-{{.Distro.MajorVersion}}-{{.Distro.MinorVersion}}-0-BaseOS-{{.Arch}}" + conditions: + "some image types are rhel-only": + when: + not_distro_name: "rhel" + ignore_image_types: + - azure-cvm + - azure-rhui + - azure-sap-rhui + - azure-sapapps-rhui + - ec2 + - ec2-sap + - ec2-ha + "CVM is only available starting from 9.6": + when: + version_less_than: "9.6" + ignore_image_types: + - "azure-cvm" + runner: + name: "org.osbuild.rhel{{.MajorVersion}}{{.MinorVersion}}" + build_packages: &rhel9_runner_build_packages + - "glibc" # ldconfig + - "systemd" # systemd-tmpfiles and systemd-sysusers + - "platform-python" # osbuild + - "python3" + # rhel9 allow all + oscap_profiles_allowlist: *oscap_profile_allowlist_rhel + bootstrap_containers: + x86_64: "registry.access.redhat.com/ubi{{.MajorVersion}}/ubi:latest" + aarch64: "registry.access.redhat.com/ubi{{.MajorVersion}}/ubi:latest" + ppc64le: "registry.access.redhat.com/ubi{{.MajorVersion}}/ubi:latest" + s390x: "registry.access.redhat.com/ubi{{.MajorVersion}}/ubi:latest" + + - ¢os9 + <<: *rhel9 + name: centos-9 + distro_like: rhel-9 + product: "CentOS Stream" + os_version: "9-stream" + vendor: "centos" + ostree_ref_tmpl: "centos/9/%s/edge" + default_fs_type: "xfs" + defs_path: rhel-9 + iso_label_tmpl: "CentOS-Stream-{{.Distro.MajorVersion}}-BaseOS-{{.Arch}}" + runner: + name: org.osbuild.centos9 + build_packages: *rhel9_runner_build_packages + bootstrap_containers: + # we need the toolbox container because stock centos has e.g. no + # mount util + x86_64: "quay.io/toolbx-images/centos-toolbox:stream{{.MajorVersion}}" + aarch64: "quay.io/toolbx-images/centos-toolbox:stream{{.MajorVersion}}" + - &rhel8 name: "rhel-{{.MajorVersion}}.{{.MinorVersion}}" match: "rhel-8.[0-9]{,[0-9]}" diff --git a/pkg/distro/defs/rhel-9/distro.yaml b/pkg/distro/defs/rhel-9/distro.yaml index 38ba0c5ef0..1eadb2e1b9 100644 --- a/pkg/distro/defs/rhel-9/distro.yaml +++ b/pkg/distro/defs/rhel-9/distro.yaml @@ -32,6 +32,108 @@ - "grub2-ppc64le" - "grub2-ppc64le-modules" + disk_sizes: + default_required_partition_sizes: &default_required_dir_sizes + "/": 1_073_741_824 # 1 * datasizes.GiB + "/usr": 2_147_483_648 # 2 * datasizes.GiB + + platforms: + x86_64_uefi_platform: &x86_64_uefi_platform + arch: "x86_64" + bootloader: "grub2" + uefi_vendor: "{{.DistroVendor}}" + qcow2_compat: "1.1" + packages: &x86_64_uefi_platform_packages + uefi: + - "dracut-config-generic" + - "efibootmgr" + - "grub2-efi-x64" + - "shim-x64" + x86_64_bios_platform: &x86_64_bios_platform + <<: *x86_64_uefi_platform + bios_platform: "i386-pc" + uefi_vendor: "{{.DistroVendor}}" + packages: &x86_64_bios_platform_packages + <<: *x86_64_uefi_platform_packages + bios: + - "dracut-config-generic" + - "grub2-pc" + build_packages: + bios: + - "grub2-pc" + x86_64_bios_only_platform: &x86_64_bios_only_platform + arch: "x86_64" + bios_platform: "i386-pc" + bootloader: "grub2" + image_format: "raw" + packages: + bios: + - "grub2-pc" + build_packages: + bios: + - "grub2-pc" + x86_64_installer_platform: &x86_64_installer_platform + <<: *x86_64_bios_platform + image_format: "raw" + packages: + <<: *x86_64_bios_platform_packages + firmware: + - "microcode_ctl" # ?? + - "iwl1000-firmware" + - "iwl100-firmware" + - "iwl105-firmware" + - "iwl135-firmware" + - "iwl2000-firmware" + - "iwl2030-firmware" + - "iwl3160-firmware" + - "iwl5000-firmware" + - "iwl5150-firmware" + - "iwl6050-firmware" + aarch64_platform: &aarch64_platform + arch: "aarch64" + bootloader: "grub2" + uefi_vendor: "{{.DistroVendor}}" + image_format: "qcow2" + qcow2_compat: "1.1" + packages: &aarch64_uefi_platform_packages + uefi: + - "dracut-config-generic" + - "efibootmgr" + - "grub2-efi-aa64" + - "grub2-tools" + - "shim-aa64" + ppc64le_bios_platform: &ppc64le_bios_platform + arch: "ppc64le" + bootloader: "grub2" + bios_platform: "powerpc-ieee1275" + image_format: "qcow2" + qcow2_compat: "1.1" + packages: + bios: + - "dracut-config-generic" + - "powerpc-utils" + - "grub2-ppc64le" + - "grub2-ppc64le-modules" + build_packages: + bios: + - "grub2-ppc64le" + - "grub2-ppc64le-modules" + s390x_zipl_platform: &s390x_zipl_platform + arch: "s390x" + # XXX: merge zipl_support/bootloader + bootloader: "zipl" + zipl_support: true + image_format: "qcow2" + qcow2_compat: "1.1" + packages: + zipl: + - "dracut-config-generic" + - "s390utils-base" + - "s390utils-core" + build_packages: + zipl: + - "s390utils-base" + common_conditions: conditions: &conditions_pkgsets_insights_client_on_rhel "add insights client on rhel": @@ -938,6 +1040,16 @@ <<: *azure_common_grub2_config terminal: ["console"] + default_installer_config: &default_installer_config + # see commit c6bfb22f54, controls the kickstart location + iso_root_kickstart: true + additional_dracut_modules: + - "nvdimm" # non-volatile DIMM firmware (provides nfit, cuse, and nd_e820) + - "ifcfg" + additional_drivers: + - "cuse" + - "ipmi_devintf" + - "ipmi_msghandler" image_config: default: @@ -1013,6 +1125,26 @@ image_types: - "subscription-manager-cockpit" qcow2: &qcow2 + filename: "disk.qcow2" + mime_type: "application/x-qemu-disk" + # note that unlike fedora rhel does not use the environment.KVM + # for unknown reasons + bootable: true + default_size: 10_737_418_240 # 10 * datasizes.GibiByte + image_func: "disk" + build_pipelines: ["build"] + payload_pipelines: ["os", "image", "qcow2"] + exports: ["qcow2"] + required_partition_sizes: *default_required_dir_sizes + platforms: + - <<: *x86_64_bios_platform + image_format: "qcow2" + - <<: *aarch64_platform + image_format: "qcow2" + - <<: *ppc64le_bios_platform + image_format: "qcow2" + - <<: *s390x_zipl_platform + image_format: "qcow2" image_config: default_target: "multi-user.target" kernel_options: @@ -1105,8 +1237,22 @@ image_types: oci: <<: *qcow2 + platforms: + - <<: *x86_64_bios_platform + image_format: "qcow2" vhd: &vhd + <<: *qcow2 + filename: "disk.vhd" + mime_type: "application/x-vhd" + default_size: 4_294_967_296 # 4 * datasizes.GibiByte + payload_pipelines: ["os", "image", "vpc"] + exports: ["vpc"] + platforms: + - <<: *x86_64_bios_platform + image_format: "vhd" + - <<: *aarch64_platform + image_format: "vhd" # based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure image_config: &image_config_vhd <<: *azure_image_config_base @@ -1227,6 +1373,11 @@ image_types: "azure-rhui": &azure_rhui <<: *vhd + mime_type: "application/xz" + payload_pipelines: ["os", "image", "vpc", "xz"] + exports: ["xz"] + compression: "xz" + filename: "disk.vhd.xz" partition_table: &partition_table_azure_internal x86_64: &azure_rhui_partition_table_x86_64 uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" @@ -1378,6 +1529,9 @@ image_types: "azure-sap-rhui": <<: *azure_rhui + platforms: + - <<: *x86_64_bios_platform + image_format: "vhd" image_config: <<: [*image_config_vhd, *sap_image_config] package_sets: @@ -1388,6 +1542,9 @@ image_types: azure-sapapps-rhui: <<: *azure_rhui + platforms: + - <<: *x86_64_bios_platform + image_format: "vhd" image_config: <<: [*image_config_vhd, *sapapps_image_config] package_sets: @@ -1396,6 +1553,17 @@ image_types: - *sap_base_pkgset tar: + filename: "root.tar.xz" + mime_type: "application/x-tar" + image_func: "tar" + build_pipelines: ["build"] + payload_pipelines: ["os", "archive"] + exports: ["archive"] + platforms: + - arch: "x86_64" + - arch: "aarch64" + - arch: "ppc64le" + - arch: "s390x" package_sets: os: - include: @@ -1405,6 +1573,18 @@ image_types: - "rng-tools" vmdk: &vmdk + filename: "disk.vmdk" + mime_type: "application/x-vmdk" + bootable: true + default_size: 4_294_967_296 # 4 * datasizes.GibiByte + image_func: "disk" + build_pipelines: ["build"] + payload_pipelines: ["os", "image", "vmdk"] + exports: ["vmdk"] + required_partition_sizes: *default_required_dir_sizes + platforms: + - <<: *x86_64_bios_platform + image_format: "vmdk" image_config: locale: "en_US.UTF-8" kernel_options: ["ro", "net.ifnames=0"] @@ -1424,9 +1604,42 @@ image_types: - "dracut-config-rescue" - "rng-tools" - ova: *vmdk + ova: + <<: *vmdk + filename: "image.ova" + mime_type: "application/ovf" + payload_pipelines: ["os", "image", "vmdk", "ovf", "archive"] + exports: ["archive"] + platforms: + - <<: *x86_64_bios_platform + image_format: "ova" ec2: &ec2 + filename: "image.raw.xz" + mime_type: "application/xz" + build_pipelines: ["build"] + payload_pipelines: ["os", "image", "xz"] + exports: ["xz"] + compression: "xz" + image_func: "disk" + bootable: true + default_size: 10_737_418_240 # 10 * datasizes.GibiByte + required_partition_sizes: *default_required_dir_sizes + platforms: + - <<: *x86_64_bios_platform + image_format: "raw" + - <<: *aarch64_platform + image_format: "raw" + platforms_override: + conditions: &platform_override_conditions_ami + "Keep the RHEL EC2 x86_64 images before 9.3 BIOS-only": + when: + distro_name: "rhel" + version_less_than: "9.3" + override: + - *x86_64_bios_only_platform + - <<: *aarch64_platform + image_format: "raw" image_config: &ec2_image_config locale: "en_US.UTF-8" timezone: "UTC" @@ -1550,9 +1763,27 @@ image_types: ami: <<: *ec2 + mime_type: "application/octet-stream" + filename: "image.raw" + payload_pipelines: ["os", "image"] + exports: ["image"] + compression: "" "ec2-ha": <<: *ec2 + platforms: + - <<: *x86_64_bios_platform + image_format: "raw" + platforms_override: + conditions: &platform_override_conditions_ami + # XXX: duplicated with "ec2" but drops "aarch64", I cannot + # find a better way to express this complex condition in YAML + "Keep the RHEL EC2 x86_64 images before 9.3 BIOS-only": + when: + distro_name: "rhel" + version_less_than: "9.3" + override: + - *x86_64_bios_only_platform package_sets: os: - *ec2_base_pkgset @@ -1565,6 +1796,19 @@ image_types: "ec2-sap": <<: *ec2 + platforms: + - <<: *x86_64_bios_platform + image_format: "raw" + platforms_override: + conditions: &platform_override_conditions_ami + # XXX: duplicated with "ec2" but drops "aarch64", I cannot + # find a better way to express this complex condition in YAML + "Keep the RHEL EC2 x86_64 images before 9.3 BIOS-only": + when: + distro_name: "rhel" + version_less_than: "9.3" + override: + - *x86_64_bios_only_platform image_config: <<: [*ec2_image_config, *sap_image_config] conditions: @@ -1597,6 +1841,16 @@ image_types: - "firewalld" wsl: &wsl + filename: "image.wsl" + mime_type: "application/x-tar" + image_func: "tar" + build_pipelines: ["build"] + payload_pipelines: ["os", "archive"] + exports: ["xz"] + compression: "xz" + platforms: + - arch: "x86_64" + - arch: "aarch64" image_config: cloud_init: - filename: "99_wsl.cfg" @@ -1669,6 +1923,28 @@ image_types: - "rpm-plugin-systemd-inhibit" "image-installer": + filename: "installer.iso" + mime_type: "application/x-iso9660-image" + bootable: true + boot_iso: true + # XXX: merge with boot_iso above + use_syslinux: true + image_func: "image_installer" + # We don't know the variant of the OS pipeline being installed + iso_label: "Unknown" + build_pipelines: ["build"] + payload_pipelines: + - "anaconda-tree" + - "efiboot-tree" + - "os" + - "bootiso-tree" + - "bootiso" + exports: ["bootiso"] + required_partition_sizes: *default_required_dir_sizes + platforms: + - *x86_64_installer_platform + - *aarch64_platform + installer_config: *default_installer_config image_config: locale: "C.UTF-8" conditions: @@ -1684,6 +1960,19 @@ image_types: - *anaconda_pkgset gce: + name_aliases: ["gce-rhui"] + filename: "image.tar.gz" + mime_type: "application/gzip" + image_func: "disk" + build_pipelines: ["build"] + payload_pipelines: ["os", "image", "archive"] + exports: ["archive"] + bootable: true + default_size: 21_474_836_480 # 20 * datasizes.GibiByte + required_partition_sizes: *default_required_dir_sizes + platforms: + - <<: *x86_64_uefi_platform + image_format: "gce" image_config: timezone: "UTC" time_synchronization: @@ -1829,6 +2118,21 @@ image_types: <<: *conditions_pkgsets_insights_client_on_rhel "minimal-raw": + filename: "disk.raw.xz" + mime_type: "application/xz" + compression: "xz" + bootable: true + default_size: 2_147_483_648 # 2 * datasizes.GibiByte + image_func: "disk" + build_pipelines: ["build"] + payload_pipelines: ["os", "image", "xz"] + exports: ["xz"] + required_partition_sizes: *default_required_dir_sizes + platforms: + - <<: *x86_64_uefi_platform + image_format: "raw" + - <<: *aarch64_platform + image_format: "raw" partition_table: x86_64: &partition_table_minimal_raw_x86_64 uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" @@ -1930,6 +2234,15 @@ image_types: - "iwl3160-firmware" openstack: + <<: *qcow2 + default_size: 4_294_967_296 # 4 * datasizes.GibiByte + platforms: + - <<: *x86_64_bios_platform + image_format: "qcow2" + qcow2_compat: "" + - <<: *aarch64_platform + image_format: "qcow2" + qcow2_compat: "" image_config: locale: "en_US.UTF-8" kernel_options: ["ro", "net.ifnames=0"] @@ -1950,6 +2263,17 @@ image_types: - "rng-tools" "edge-commit": &edge_commit + name_aliases: ["rhel-edge-commit"] + filename: "commit.tar" + mime_type: "application/x-tar" + rpm_ostree: true + image_func: "iot_commit" + build_pipelines: ["build"] + payload_pipelines: ["os", "ostree-commit", "commit-archive"] + exports: ["commit-archive"] + platforms: + - *x86_64_bios_platform + - *aarch64_platform partition_table: *edge_base_partition_tables image_config: &edge_commit_image_config @@ -2112,9 +2436,37 @@ image_types: - "dnsmasq" "edge-container": + name_aliases: ["rhel-edge-container"] + filename: "container.tar" + mime_type: "application/x-tar" + rpm_ostree: true + image_func: "iot_container" + build_pipelines: ["build"] + payload_pipelines: ["os", "ostree-commit", "container-tree", "container"] + exports: ["container"] <<: *edge_commit "edge-raw-image": + name_aliases: ["rhel-edge-raw-image"] + filename: "image.raw.xz" + compression: "xz" + mime_type: "application/xz" + build_pipelines: ["build"] + payload_pipelines: ["ostree-deployment", "image", "xz"] + exports: ["xz"] + default_size: 10_737_418_240 # 10 * datasizes.GibiByte + rpm_ostree: true + bootable: true + image_func: "iot" + ostree: + name: "rhel-edge" + remote_name: "rhel-edge" + use_ostree_remotes: true + platforms: + - <<: *x86_64_installer_platform + image_format: "raw" + - <<: *aarch64_platform + image_format: "raw" partition_table: *edge_base_partition_tables image_config: @@ -2147,6 +2499,30 @@ image_types: - "nginx" "edge-installer": + name_aliases: ["rhel-edge-installer"] + filename: "installer.iso" + mime_type: "application/x-iso9660-image" + rpm_ostree: true + boot_iso: true + # XXX: merge with boot_iso above + use_syslinux: true + image_func: "iot_installer" + iso_label: "edge" + variant: "edge" + ostree: + name: "rhel-edge" + build_pipelines: ["build"] + payload_pipelines: + - "anaconda-tree" + - "efiboot-tree" + - "bootiso-tree" + - "bootiso" + exports: ["bootiso"] + required_partition_sizes: *default_required_dir_sizes + platforms: + - *x86_64_uefi_platform + - *aarch64_platform + installer_config: *default_installer_config image_config: enabled_services: *enabled_services_edge locale: "en_US.UTF-8" @@ -2162,6 +2538,43 @@ image_types: - *anaconda_pkgset "edge-simplified-installer": + name_aliases: ["rhel-edge-simplified-installer"] + filename: "simplified-installer.iso" + mime_type: "application/x-iso9660-image" + rpm_ostree: true + bootable: true + boot_iso: true + # XXX: merge with boot_iso above + use_syslinux: true + # NOTE: RHEL 8 only supports the older Anaconda configs + use_legacy_anaconda_config: true + default_size: 10_737_418_240 # 10 * datasizes.GibiByte + image_func: "iot_simplified_installer" + iso_label: "edge" + variant: "edge" + ostree: + name: "rhel-edge" + remote_name: "rhel-edge" + # XXX: find better name + use_ostree_remotes: true + build_pipelines: ["build"] + payload_pipelines: + - "ostree-deployment" + - "image" + - "xz" + - "coi-tree" + - "efiboot-tree" + - "bootiso-tree" + - "bootiso" + exports: ["bootiso"] + required_partition_sizes: *default_required_dir_sizes + installer_config: + additional_dracut_modules: + - "prefixdevname" + - "prefixdevname-tools" + platforms: + - <<: *x86_64_uefi_platform + - <<: *aarch64_platform partition_table: *edge_base_partition_tables image_config: @@ -2241,6 +2654,24 @@ image_types: <<: *edge_commit_aarch64_pkgset "edge-ami": &edge_ami + filename: "image.raw" + mime_type: "application/octet-stream" + default_size: 10_737_418_240 # 10 * datasizes.GibiByte + build_pipelines: ["build"] + payload_pipelines: ["ostree-deployment", "image"] + exports: ["image"] + rpm_ostree: true + bootable: true + image_func: "iot" + ostree: + name: "rhel-edge" + remote_name: "rhel-edge" + use_ostree_remotes: true + platforms: + - <<: *x86_64_installer_platform + image_format: "raw" + - <<: *aarch64_platform + image_format: "raw" partition_table: *edge_base_partition_tables image_config: &image_config_edge_ami @@ -2280,6 +2711,15 @@ image_types: "edge-vsphere": <<: *edge_ami + filename: "image.vmdk" + mime_type: "application/x-vmdk" + payload_pipelines: ["ostree-deployment", "image", "vmdk"] + exports: ["vmdk"] + platforms: + - <<: *x86_64_bios_platform + image_format: "vmdk" + - <<: *aarch64_platform + image_format: "vmdk" image_config: <<: *image_config_edge_ami kernel_options: @@ -2297,6 +2737,24 @@ image_types: - "modprobe.blacklist=vc4" "azure-cvm": + <<: *vhd + filename: "disk.vhd.xz" + mime_type: "application/xz" + payload_pipelines: ["os", "image", "vpc", "xz"] + exports: ["xz"] + compression: "xz" + default_size: 34_359_738_368 # 32 * datasizes.GibiByte + platforms: + - arch: "x86_64" + bootloader: "uki" + image_format: "vhd" + uefi_vendor: "{{.DistroVendor}}" + packages: + uki: + - "efibootmgr" + - "kernel-uki-virt-addons" # provides useful cmdline utilities for the UKI + - "shim-x64" + - "uki-direct" partition_table: x86_64: uuid: "D209C89E-EA5E-4FBD-B161-B461CCE297E0" diff --git a/pkg/distro/generic/imagetype.go b/pkg/distro/generic/imagetype.go index 087ee03cbf..a3b1a2ca22 100644 --- a/pkg/distro/generic/imagetype.go +++ b/pkg/distro/generic/imagetype.go @@ -321,8 +321,8 @@ func (t *imageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp return checkOptionsRhel7(t, bp, options) case manifest.DISTRO_EL8: return checkOptionsRhel8(t, bp, options) - // TODO: add checkOptionsRhel9 once we move them to - // generic distros + case manifest.DISTRO_EL9: + return checkOptionsRhel9(t, bp, options) case manifest.DISTRO_EL10: return checkOptionsRhel10(t, bp, options) default: diff --git a/pkg/distro/generic/options.go b/pkg/distro/generic/options.go index a16f2a5efb..2b9c0c99ac 100644 --- a/pkg/distro/generic/options.go +++ b/pkg/distro/generic/options.go @@ -94,6 +94,206 @@ func checkOptionsRhel10(t *imageType, bp *blueprint.Blueprint, options distro.Im } return warnings, nil } +func checkOptionsRhel9(t *imageType, bp *blueprint.Blueprint, options distro.ImageOptions) ([]string, error) { + + customizations := bp.Customizations + + // holds warnings (e.g. deprecation notices) + var warnings []string + + // we do not support embedding containers on ostree-derived images, only on commits themselves + if len(bp.Containers) > 0 && t.RPMOSTree && (t.Name() != "edge-commit" && t.Name() != "edge-container") { + return warnings, fmt.Errorf("embedding containers is not supported for %s on %s", t.Name(), t.Arch().Distro().Name()) + } + + if options.OSTree != nil { + if err := options.OSTree.Validate(); err != nil { + return warnings, err + } + } + + if t.BootISO && t.RPMOSTree { + // ostree-based ISOs require a URL from which to pull a payload commit + if options.OSTree == nil || options.OSTree.URL == "" { + return warnings, fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.Name()) + } + + if t.Name() == "edge-simplified-installer" { + allowed := []string{"InstallationDevice", "FDO", "Ignition", "Kernel", "User", "Group", "FIPS", "Filesystem"} + if err := customizations.CheckAllowed(allowed...); err != nil { + return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) + } + if customizations.GetInstallationDevice() == "" { + return warnings, fmt.Errorf("boot ISO image type %q requires specifying an installation device to install to", t.Name()) + } + + // FDO is optional, but when specified has some restrictions + if customizations.GetFDO() != nil { + if customizations.GetFDO().ManufacturingServerURL == "" { + return warnings, fmt.Errorf("boot ISO image type %q requires specifying FDO.ManufacturingServerURL configuration to install to when using FDO", t.Name()) + } + var diunSet int + if customizations.GetFDO().DiunPubKeyHash != "" { + diunSet++ + } + if customizations.GetFDO().DiunPubKeyInsecure != "" { + diunSet++ + } + if customizations.GetFDO().DiunPubKeyRootCerts != "" { + diunSet++ + } + if diunSet != 1 { + return warnings, fmt.Errorf("boot ISO image type %q requires specifying one of [FDO.DiunPubKeyHash,FDO.DiunPubKeyInsecure,FDO.DiunPubKeyRootCerts] configuration to install to when using FDO", t.Name()) + } + } + + // ignition is optional, we might be using FDO + if customizations.GetIgnition() != nil { + if customizations.GetIgnition().Embedded != nil && customizations.GetIgnition().FirstBoot != nil { + return warnings, fmt.Errorf("both ignition embedded and firstboot configurations found") + } + if customizations.GetIgnition().FirstBoot != nil && customizations.GetIgnition().FirstBoot.ProvisioningURL == "" { + return warnings, fmt.Errorf("ignition.firstboot requires a provisioning url") + } + } + } else if t.Name() == "edge-installer" { + allowed := []string{"User", "Group", "FIPS", "Installer", "Timezone", "Locale"} + if err := customizations.CheckAllowed(allowed...); err != nil { + return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) + } + } + } + + if t.Name() == "edge-raw-image" || t.Name() == "edge-ami" || t.Name() == "edge-vsphere" { + // ostree-based bootable images require a URL from which to pull a payload commit + if options.OSTree == nil || options.OSTree.URL == "" { + return warnings, fmt.Errorf("%q images require specifying a URL from which to retrieve the OSTree commit", t.Name()) + } + + allowed := []string{"Ignition", "Kernel", "User", "Group", "FIPS", "Filesystem"} + if err := customizations.CheckAllowed(allowed...); err != nil { + return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) + } + // TODO: consider additional checks, such as those in "edge-simplified-installer" + } + + if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.RPMOSTree && t.Name() != "edge-raw-image" && t.Name() != "edge-simplified-installer" { + return warnings, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types") + } + + mountpoints := customizations.GetFilesystems() + partitioning, err := customizations.GetPartitioning() + if err != nil { + return nil, err + } + if (mountpoints != nil || partitioning != nil) && t.RPMOSTree && (t.Name() == "edge-container" || t.Name() == "edge-commit") { + return warnings, fmt.Errorf("custom mountpoints and partitioning are not supported for ostree types") + } else if (mountpoints != nil || partitioning != nil) && t.RPMOSTree && !(t.Name() == "edge-container" || t.Name() == "edge-commit") { + //customization allowed for edge-raw-image,edge-ami,edge-vsphere,edge-simplified-installer + err := blueprint.CheckMountpointsPolicy(mountpoints, policies.OstreeMountpointPolicies) + if err != nil { + return warnings, err + } + } + + if len(mountpoints) > 0 && partitioning != nil { + return nil, fmt.Errorf("partitioning customizations cannot be used with custom filesystems (mountpoints)") + } + + if err := blueprint.CheckMountpointsPolicy(mountpoints, policies.MountpointPolicies); err != nil { + return warnings, err + } + + if err := blueprint.CheckDiskMountpointsPolicy(partitioning, policies.MountpointPolicies); err != nil { + return warnings, err + } + + if err := partitioning.ValidateLayoutConstraints(); err != nil { + return warnings, err + } + + if osc := customizations.GetOpenSCAP(); osc != nil { + if t.Arch().Distro().OsVersion() == "9.0" { + return warnings, fmt.Errorf("OpenSCAP unsupported os version: %s", t.Arch().Distro().OsVersion()) + } + if !oscap.IsProfileAllowed(osc.ProfileID, t.arch.distro.DistroYAML.OscapProfilesAllowList) { + return warnings, fmt.Errorf("OpenSCAP unsupported profile: %s", osc.ProfileID) + } + if t.RPMOSTree { + return warnings, fmt.Errorf("OpenSCAP customizations are not supported for ostree types") + } + if osc.ProfileID == "" { + return warnings, fmt.Errorf("OpenSCAP profile cannot be empty") + } + } + + // Check Directory/File Customizations are valid + dc := customizations.GetDirectories() + fc := customizations.GetFiles() + + err = blueprint.ValidateDirFileCustomizations(dc, fc) + if err != nil { + return warnings, err + } + + dcp := policies.CustomDirectoriesPolicies + fcp := policies.CustomFilesPolicies + + if t.RPMOSTree { + dcp = policies.OstreeCustomDirectoriesPolicies + fcp = policies.OstreeCustomFilesPolicies + } + + err = blueprint.CheckDirectoryCustomizationsPolicy(dc, dcp) + if err != nil { + return warnings, err + } + + err = blueprint.CheckFileCustomizationsPolicy(fc, fcp) + if err != nil { + return warnings, err + } + + // check if repository customizations are valid + _, err = customizations.GetRepositories() + if err != nil { + return warnings, err + } + + if customizations.GetFIPS() && !common.IsBuildHostFIPSEnabled() { + warnings = append(warnings, fmt.Sprintln(common.FIPSEnabledImageWarning)) + } + + instCust, err := customizations.GetInstaller() + if err != nil { + return warnings, err + } + if instCust != nil { + // only supported by the Anaconda installer + if slices.Index([]string{"image-installer", "edge-installer", "live-installer"}, t.Name()) == -1 { + return warnings, fmt.Errorf("installer customizations are not supported for %q", t.Name()) + } + + if t.Name() == "edge-installer" && + instCust.Kickstart != nil && + len(instCust.Kickstart.Contents) > 0 && + (customizations.GetUsers() != nil || customizations.GetGroups() != nil) { + return warnings, fmt.Errorf("edge-installer installer.kickstart.contents are not supported in combination with users or groups") + } + } + + // don't support setting any kernel customizations for image types with + // UKIs + // NOTE: this is very ugly and stupid, it should not be based on the image + // type name, but we want to redo this whole function anyway + // NOTE: we can't use customizations.GetKernel() because it returns + // 'Name: "kernel"' when unset. + if t.Name() == "azure-cvm" && customizations != nil && customizations.Kernel != nil { + return warnings, fmt.Errorf("kernel customizations are not supported for %q", t.Name()) + } + + return warnings, nil +} func checkOptionsRhel8(t *imageType, bp *blueprint.Blueprint, options distro.ImageOptions) ([]string, error) { customizations := bp.Customizations diff --git a/pkg/distro/rhel/rhel9/distro_internal_test.go b/pkg/distro/generic/rhel9_internal_test.go similarity index 59% rename from pkg/distro/rhel/rhel9/distro_internal_test.go rename to pkg/distro/generic/rhel9_internal_test.go index c61b62873c..0245edee46 100644 --- a/pkg/distro/rhel/rhel9/distro_internal_test.go +++ b/pkg/distro/generic/rhel9_internal_test.go @@ -1,25 +1,20 @@ -package rhel9 +package generic import ( "fmt" - "math/rand" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/osbuild/images/internal/common" "github.com/osbuild/images/pkg/blueprint" "github.com/osbuild/images/pkg/datasizes" "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/rhel" ) -// math/rand is good enough in this case -/* #nosec G404 */ -var rng = rand.New(rand.NewSource(0)) - -func TestEC2Partitioning(t *testing.T) { +func TestRhel9_EC2Partitioning(t *testing.T) { testCases := []struct { distro string bootSizeMiB uint64 @@ -59,8 +54,8 @@ func TestEC2Partitioning(t *testing.T) { i, err := a.GetImageType(it) require.NoError(t, err) - it := i.(*rhel.ImageType) - pt, err := it.GetPartitionTable(&blueprint.Customizations{}, distro.ImageOptions{}, rng) + it := i.(*imageType) + pt, err := it.getPartitionTable(&blueprint.Customizations{}, distro.ImageOptions{}, rng) require.NoError(t, err) bootSize, err := pt.GetMountpointSize("/boot") @@ -74,7 +69,7 @@ func TestEC2Partitioning(t *testing.T) { } } -func TestDistroFactory(t *testing.T) { +func TestRhel9_DistroFactory(t *testing.T) { type testCase struct { strID string expected distro.Distro @@ -83,31 +78,31 @@ func TestDistroFactory(t *testing.T) { testCases := []testCase{ { strID: "rhel-90", - expected: newDistro("rhel", 9, 0), + expected: common.Must(newDistro("rhel-9.0")), }, { strID: "rhel-9.0", - expected: newDistro("rhel", 9, 0), + expected: common.Must(newDistro("rhel-9.0")), }, { strID: "rhel-93", - expected: newDistro("rhel", 9, 3), + expected: common.Must(newDistro("rhel-9.3")), }, { strID: "rhel-9.3", - expected: newDistro("rhel", 9, 3), + expected: common.Must(newDistro("rhel-9.3")), }, { strID: "rhel-910", - expected: newDistro("rhel", 9, 10), + expected: common.Must(newDistro("rhel-9.10")), }, { strID: "rhel-9.10", - expected: newDistro("rhel", 9, 10), + expected: common.Must(newDistro("rhel-9.10")), }, { strID: "centos-9", - expected: newDistro("centos", 9, -1), + expected: common.Must(newDistro("centos-9")), }, { strID: "centos-9.0", @@ -117,66 +112,6 @@ func TestDistroFactory(t *testing.T) { strID: "rhel-9", expected: nil, }, - { - strID: "rhel-8.0", - expected: nil, - }, - { - strID: "rhel-80", - expected: nil, - }, - { - strID: "rhel-8.4", - expected: nil, - }, - { - strID: "rhel-84", - expected: nil, - }, - { - strID: "rhel-8.10", - expected: nil, - }, - { - strID: "rhel-810", - expected: nil, - }, - { - strID: "rhel-8", - expected: nil, - }, - { - strID: "rhel-8.4.1", - expected: nil, - }, - { - strID: "rhel-7", - expected: nil, - }, - { - strID: "rhel-79", - expected: nil, - }, - { - strID: "rhel-7.9", - expected: nil, - }, - { - strID: "fedora-9", - expected: nil, - }, - { - strID: "fedora-38", - expected: nil, - }, - { - strID: "fedora-38.1", - expected: nil, - }, - { - strID: "fedora", - expected: nil, - }, } for _, tc := range testCases { diff --git a/pkg/distro/rhel/rhel9/distro_test.go b/pkg/distro/generic/rhel9_test.go similarity index 89% rename from pkg/distro/rhel/rhel9/distro_test.go rename to pkg/distro/generic/rhel9_test.go index 993a41cf2c..d5e1080432 100644 --- a/pkg/distro/rhel/rhel9/distro_test.go +++ b/pkg/distro/generic/rhel9_test.go @@ -1,4 +1,4 @@ -package rhel9_test +package generic_test import ( "fmt" @@ -12,22 +12,17 @@ import ( "github.com/osbuild/images/pkg/blueprint" "github.com/osbuild/images/pkg/distro" "github.com/osbuild/images/pkg/distro/distro_test_common" - "github.com/osbuild/images/pkg/distro/rhel/rhel9" + "github.com/osbuild/images/pkg/distro/generic" ) -type rhelFamilyDistro struct { - name string - distro distro.Distro -} - -var rhelFamilyDistros = []rhelFamilyDistro{ +var rhel9_FamilyDistros = []rhelFamilyDistro{ { name: "rhel-94", - distro: rhel9.DistroFactory("rhel-94"), + distro: generic.DistroFactory("rhel-94"), }, } -func TestFilenameFromType(t *testing.T) { +func TestRhel9_FilenameFromType(t *testing.T) { type args struct { outputFormat string } @@ -226,7 +221,7 @@ func TestFilenameFromType(t *testing.T) { }, }, } - for _, dist := range rhelFamilyDistros { + for _, dist := range rhel9_FamilyDistros { t.Run(dist.name, func(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -253,7 +248,7 @@ func TestFilenameFromType(t *testing.T) { } } -func TestImageType_BuildPackages(t *testing.T) { +func TestRhel9_ImageType_BuildPackages(t *testing.T) { x8664BuildPackages := []string{ "dnf", "dosfstools", @@ -281,7 +276,7 @@ func TestImageType_BuildPackages(t *testing.T) { "x86_64": x8664BuildPackages, "aarch64": aarch64BuildPackages, } - for _, dist := range rhelFamilyDistros { + for _, dist := range rhel9_FamilyDistros { t.Run(dist.name, func(t *testing.T) { d := dist.distro for _, archLabel := range d.ListArches() { @@ -306,7 +301,7 @@ func TestImageType_BuildPackages(t *testing.T) { } } -func TestImageType_Name(t *testing.T) { +func TestRhel9_ImageType_Name(t *testing.T) { imgMap := []struct { arch string imgNames []string @@ -365,7 +360,7 @@ func TestImageType_Name(t *testing.T) { }, } - for _, dist := range rhelFamilyDistros { + for _, dist := range rhel9_FamilyDistros { t.Run(dist.name, func(t *testing.T) { for _, mapping := range imgMap { if mapping.arch == arch.ARCH_S390X.String() && dist.name == "centos" { @@ -388,7 +383,7 @@ func TestImageType_Name(t *testing.T) { } } -func TestImageTypeAliases(t *testing.T) { +func TestRhel9_ImageTypeAliases(t *testing.T) { type args struct { imageTypeAliases []string } @@ -428,7 +423,7 @@ func TestImageTypeAliases(t *testing.T) { }, }, } - for _, dist := range rhelFamilyDistros { + for _, dist := range rhel9_FamilyDistros { t.Run(dist.name, func(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -465,10 +460,10 @@ func TestImageTypeAliases(t *testing.T) { // Check that Manifest() function returns an error for unsupported // configurations. -func TestDistro_ManifestError(t *testing.T) { +func TestRhel9_Distro_ManifestError(t *testing.T) { // Currently, the only unsupported configuration is OSTree commit types // with Kernel boot options - r9distro := rhelFamilyDistros[0].distro + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Kernel: &blueprint.KernelCustomization{ @@ -500,7 +495,7 @@ func TestDistro_ManifestError(t *testing.T) { } } -func TestArchitecture_ListImageTypes(t *testing.T) { +func TestRhel9_Architecture_ListImageTypes(t *testing.T) { imgMap := []struct { arch string imgNames []string @@ -579,7 +574,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) { }, } - for _, dist := range rhelFamilyDistros { + for _, dist := range rhel9_FamilyDistros { t.Run(dist.name, func(t *testing.T) { for _, mapping := range imgMap { arch, err := dist.distro.GetArch(mapping.arch) @@ -598,12 +593,12 @@ func TestArchitecture_ListImageTypes(t *testing.T) { } } -func TestRhel9_ListArches(t *testing.T) { - arches := rhelFamilyDistros[0].distro.ListArches() +func TestRhel9_Rhel9_ListArches(t *testing.T) { + arches := rhel9_FamilyDistros[0].distro.ListArches() assert.Equal(t, []string{"aarch64", "ppc64le", "s390x", "x86_64"}, arches) } -func TestRhel9_GetArch(t *testing.T) { +func TestRhel9_Rhel9_GetArch(t *testing.T) { arches := []struct { name string errorExpected bool @@ -627,7 +622,7 @@ func TestRhel9_GetArch(t *testing.T) { }, } - for _, dist := range rhelFamilyDistros { + for _, dist := range rhel9_FamilyDistros { t.Run(dist.name, func(t *testing.T) { for _, a := range arches { actualArch, err := dist.distro.GetArch(a.name) @@ -643,26 +638,26 @@ func TestRhel9_GetArch(t *testing.T) { } } -func TestRhel9_Name(t *testing.T) { - distro := rhelFamilyDistros[0].distro +func TestRhel9_Rhel9_Name(t *testing.T) { + distro := rhel9_FamilyDistros[0].distro assert.Equal(t, "rhel-9.4", distro.Name()) } -func TestRhel9_ModulePlatformID(t *testing.T) { - distro := rhelFamilyDistros[0].distro +func TestRhel9_Rhel9_ModulePlatformID(t *testing.T) { + distro := rhel9_FamilyDistros[0].distro assert.Equal(t, "platform:el9", distro.ModulePlatformID()) } -func TestRhel9_KernelOption(t *testing.T) { - distro_test_common.TestDistro_KernelOption(t, rhelFamilyDistros[0].distro) +func TestRhel9_Rhel9_KernelOption(t *testing.T) { + distro_test_common.TestDistro_KernelOption(t, rhel9_FamilyDistros[0].distro) } -func TestRhel9_OSTreeOptions(t *testing.T) { - distro_test_common.TestDistro_OSTreeOptions(t, rhelFamilyDistros[0].distro) +func TestRhel9_Rhel9_OSTreeOptions(t *testing.T) { + distro_test_common.TestDistro_OSTreeOptions(t, rhel9_FamilyDistros[0].distro) } -func TestDistro_CustomFileSystemManifestError(t *testing.T) { - r9distro := rhelFamilyDistros[0].distro +func TestRhel9_Distro_CustomFileSystemManifestError(t *testing.T) { + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -689,8 +684,8 @@ func TestDistro_CustomFileSystemManifestError(t *testing.T) { } } -func TestDistro_TestRootMountPoint(t *testing.T) { - r9distro := rhelFamilyDistros[0].distro +func TestRhel9_Distro_TestRootMountPoint(t *testing.T) { + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -717,8 +712,8 @@ func TestDistro_TestRootMountPoint(t *testing.T) { } } -func TestDistro_CustomFileSystemSubDirectories(t *testing.T) { - r9distro := rhelFamilyDistros[0].distro +func TestRhel9_Distro_CustomFileSystemSubDirectories(t *testing.T) { + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -747,8 +742,8 @@ func TestDistro_CustomFileSystemSubDirectories(t *testing.T) { } } -func TestDistro_MountpointsWithArbitraryDepthAllowed(t *testing.T) { - r9distro := rhelFamilyDistros[0].distro +func TestRhel9_Distro_MountpointsWithArbitraryDepthAllowed(t *testing.T) { + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -785,8 +780,8 @@ func TestDistro_MountpointsWithArbitraryDepthAllowed(t *testing.T) { } } -func TestDistro_DirtyMountpointsNotAllowed(t *testing.T) { - r9distro := rhelFamilyDistros[0].distro +func TestRhel9_Distro_DirtyMountpointsNotAllowed(t *testing.T) { + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -819,8 +814,8 @@ func TestDistro_DirtyMountpointsNotAllowed(t *testing.T) { } } -func TestDistro_CustomUsrPartitionNotLargeEnough(t *testing.T) { - r9distro := rhelFamilyDistros[0].distro +func TestRhel9_Distro_CustomUsrPartitionNotLargeEnough(t *testing.T) { + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -847,9 +842,9 @@ func TestDistro_CustomUsrPartitionNotLargeEnough(t *testing.T) { } } -func TestDiskAndFilesystemCustomizationsError(t *testing.T) { +func TestRhel9_DiskAndFilesystemCustomizationsError(t *testing.T) { // simple test that checks that disk customizations are allowed - r8distro := rhelFamilyDistros[0].distro + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Filesystem: []blueprint.FilesystemCustomization{ @@ -885,8 +880,8 @@ func TestDiskAndFilesystemCustomizationsError(t *testing.T) { "edge-ami": true, } - for _, archName := range r8distro.ListArches() { - arch, _ := r8distro.GetArch(archName) + for _, archName := range r9distro.ListArches() { + arch, _ := r9distro.GetArch(archName) for _, imgTypeName := range arch.ListImageTypes() { imgType, _ := arch.GetImageType(imgTypeName) options := distro.ImageOptions{} @@ -899,9 +894,9 @@ func TestDiskAndFilesystemCustomizationsError(t *testing.T) { } } -func TestNoDiskCustomizationsNoError(t *testing.T) { +func TestRhel9_NoDiskCustomizationsNoError(t *testing.T) { // simple test that checks that disk customizations are allowed - r8distro := rhelFamilyDistros[0].distro + r9distro := rhel9_FamilyDistros[0].distro bp := blueprint.Blueprint{ Customizations: &blueprint.Customizations{ Disk: &blueprint.DiskCustomization{ @@ -931,8 +926,8 @@ func TestNoDiskCustomizationsNoError(t *testing.T) { "edge-ami": true, } - for _, archName := range r8distro.ListArches() { - arch, _ := r8distro.GetArch(archName) + for _, archName := range r9distro.ListArches() { + arch, _ := r9distro.GetArch(archName) for _, imgTypeName := range arch.ListImageTypes() { imgType, _ := arch.GetImageType(imgTypeName) options := distro.ImageOptions{} diff --git a/pkg/distro/rhel/arch.go b/pkg/distro/rhel/arch.go deleted file mode 100644 index 4afd68b6cf..0000000000 --- a/pkg/distro/rhel/arch.go +++ /dev/null @@ -1,78 +0,0 @@ -package rhel - -import ( - "errors" - "fmt" - "sort" - - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/platform" -) - -type Architecture struct { - distro *Distribution - arch arch.Arch - imageTypes map[string]distro.ImageType - imageTypeAliases map[string]string -} - -func (a *Architecture) Name() string { - return a.arch.String() -} - -func (a *Architecture) Distro() distro.Distro { - return a.distro -} - -func (a *Architecture) ListImageTypes() []string { - itNames := make([]string, 0, len(a.imageTypes)) - for name := range a.imageTypes { - itNames = append(itNames, name) - } - sort.Strings(itNames) - return itNames -} - -func (a *Architecture) GetImageType(name string) (distro.ImageType, error) { - t, exists := a.imageTypes[name] - if !exists { - aliasForName, exists := a.imageTypeAliases[name] - if !exists { - return nil, errors.New("invalid image type: " + name) - } - t, exists = a.imageTypes[aliasForName] - if !exists { - panic(fmt.Sprintf("image type '%s' is an alias to a non-existing image type '%s'", name, aliasForName)) - } - } - return t, nil -} - -func (a *Architecture) AddImageTypes(platform platform.Platform, imageTypes ...*ImageType) { - if a.imageTypes == nil { - a.imageTypes = map[string]distro.ImageType{} - } - for idx := range imageTypes { - it := imageTypes[idx] - it.arch = a - it.platform = platform - a.imageTypes[it.name] = it - for _, alias := range it.NameAliases { - if a.imageTypeAliases == nil { - a.imageTypeAliases = map[string]string{} - } - if existingAliasFor, exists := a.imageTypeAliases[alias]; exists { - panic(fmt.Sprintf("image type alias '%s' for '%s' is already defined for another image type '%s'", alias, it.name, existingAliasFor)) - } - a.imageTypeAliases[alias] = it.name - } - } -} - -func NewArchitecture(distro *Distribution, arch arch.Arch) *Architecture { - return &Architecture{ - distro: distro, - arch: arch, - } -} diff --git a/pkg/distro/rhel/azure.go b/pkg/distro/rhel/azure.go deleted file mode 100644 index 3c8938815b..0000000000 --- a/pkg/distro/rhel/azure.go +++ /dev/null @@ -1,52 +0,0 @@ -package rhel - -import ( - _ "embed" - "fmt" - "os" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/customizations/fsnode" - "github.com/osbuild/images/pkg/osbuild" -) - -// Dataloss warning script for Azure images. -// -//go:embed temp-disk-dataloss-warning.sh -var azureDatalossWarningScriptContent string - -// Returns a filenode that embeds a script and a systemd unit to run it on -// every boot. -// The script writes a file named DATALOSS_WARNING_README.txt to the root of an -// Azure ephemeral resource disk, if one is mounted, as a warning against using -// the disk for data storage. -// https://docs.microsoft.com/en-us/azure/virtual-machines/linux/managed-disks-overview#temporary-disk -func CreateAzureDatalossWarningScriptAndUnit() (*fsnode.File, *osbuild.SystemdUnitCreateStageOptions, error) { - datalossWarningScriptPath := "/usr/local/sbin/temp-disk-dataloss-warning" - datalossWarningScript, err := fsnode.NewFile(datalossWarningScriptPath, common.ToPtr(os.FileMode(0755)), nil, nil, []byte(azureDatalossWarningScriptContent)) - if err != nil { - return nil, nil, fmt.Errorf("rhel/azure: error creating file node for dataloss warning script: %w", err) - } - - systemdUnit := &osbuild.SystemdUnitCreateStageOptions{ - Filename: "temp-disk-dataloss-warning.service", - UnitType: osbuild.SystemUnitType, - UnitPath: osbuild.EtcUnitPath, - Config: osbuild.SystemdUnit{ - Unit: &osbuild.UnitSection{ - Description: "Azure temporary resource disk dataloss warning file creation", - After: []string{"multi-user.target", "cloud-final.service"}, - }, - Service: &osbuild.ServiceSection{ - Type: osbuild.OneshotServiceType, - ExecStart: []string{datalossWarningScriptPath}, - StandardOutput: "journal+console", - }, - Install: &osbuild.InstallSection{ - WantedBy: []string{"default.target"}, - }, - }, - } - - return datalossWarningScript, systemdUnit, nil -} diff --git a/pkg/distro/rhel/defaults.go b/pkg/distro/rhel/defaults.go deleted file mode 100644 index 5a79776513..0000000000 --- a/pkg/distro/rhel/defaults.go +++ /dev/null @@ -1,5 +0,0 @@ -package rhel - -const ( - UEFIVendor = "redhat" -) diff --git a/pkg/distro/rhel/distribution.go b/pkg/distro/rhel/distribution.go deleted file mode 100644 index 9a0dd8b5e8..0000000000 --- a/pkg/distro/rhel/distribution.go +++ /dev/null @@ -1,192 +0,0 @@ -package rhel - -import ( - "errors" - "fmt" - "sort" - "strings" - - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/runner" -) - -// DefaultDistroImageConfigFunc is a function that returns the default image -// configuration for a distribution. -type DefaultDistroImageConfigFunc func(d *Distribution) *distro.ImageConfig - -type Distribution struct { - name string - DistCodename string - product string - osVersion string - releaseVersion string - modulePlatformID string - vendor string - ostreeRefTmpl string - runner runner.Runner - arches map[string]distro.Arch - DefaultImageConfig DefaultDistroImageConfigFunc - - // distro specific function to check options per image type - CheckOptions CheckOptionsFunc -} - -func (d *Distribution) Name() string { - return d.name -} - -func (d *Distribution) Codename() string { - return d.DistCodename -} - -func (d *Distribution) Releasever() string { - return d.releaseVersion -} - -func (d *Distribution) OsVersion() string { - return d.osVersion -} - -func (d *Distribution) Product() string { - return d.product -} - -func (d *Distribution) ModulePlatformID() string { - return d.modulePlatformID -} - -func (d *Distribution) OSTreeRef() string { - return d.ostreeRefTmpl -} - -func (d *Distribution) Vendor() string { - return d.vendor -} - -func (d *Distribution) ListArches() []string { - archNames := make([]string, 0, len(d.arches)) - for name := range d.arches { - archNames = append(archNames, name) - } - sort.Strings(archNames) - return archNames -} - -func (d *Distribution) GetArch(name string) (distro.Arch, error) { - arch, exists := d.arches[name] - if !exists { - return nil, errors.New("invalid architecture: " + name) - } - return arch, nil -} - -func (d *Distribution) AddArches(arches ...*Architecture) { - if d.arches == nil { - d.arches = map[string]distro.Arch{} - } - - // Do not make copies of architectures, as opposed to image types, - // because architecture definitions are not used by more than a single - // distro definition. - for idx := range arches { - d.arches[arches[idx].Name()] = arches[idx] - } -} - -func (d *Distribution) IsRHEL() bool { - return strings.HasPrefix(d.name, "rhel") -} - -func (d *Distribution) IsAlmaLinux() bool { - return strings.HasPrefix(d.name, "almalinux") -} - -func (d *Distribution) IsAlmaLinuxKitten() bool { - return strings.HasPrefix(d.name, "almalinux_kitten") -} - -func (d *Distribution) GetDefaultImageConfig() *distro.ImageConfig { - if d.DefaultImageConfig == nil { - return nil - } - - return d.DefaultImageConfig(d) -} - -func NewDistribution(name string, major, minor int) (*Distribution, error) { - var rd *Distribution - switch name { - case "rhel": - if major < 0 { - return nil, errors.New("Invalid RHEL major version (must be positive)") - } - - if minor < 0 { - return nil, errors.New("RHEL requires a minor version") - } - - rd = &Distribution{ - name: fmt.Sprintf("rhel-%d.%d", major, minor), - product: "Red Hat Enterprise Linux", - osVersion: fmt.Sprintf("%d.%d", major, minor), - releaseVersion: fmt.Sprintf("%d", major), - modulePlatformID: fmt.Sprintf("platform:el%d", major), - vendor: "redhat", - ostreeRefTmpl: fmt.Sprintf("rhel/%d/%%s/edge", major), - runner: &runner.RHEL{Major: uint64(major), Minor: uint64(minor)}, - } - case "centos": - if minor != -1 { - return nil, fmt.Errorf("CentOS does not have minor versions, but got %d", minor) - } - - rd = &Distribution{ - name: fmt.Sprintf("centos-%d", major), - product: "CentOS Stream", - osVersion: fmt.Sprintf("%d-stream", major), - releaseVersion: fmt.Sprintf("%d", major), - modulePlatformID: fmt.Sprintf("platform:el%d", major), - vendor: "centos", - ostreeRefTmpl: fmt.Sprintf("centos/%d/%%s/edge", major), - runner: &runner.CentOS{Version: uint64(major)}, - } - case "almalinux": - if major < 0 { - return nil, errors.New("Invalid AlmaLinux major version (must be positive)") - } - - if minor < 0 { - return nil, errors.New("AlmaLinux requires a minor version") - } - - rd = &Distribution{ - name: fmt.Sprintf("almalinux-%d.%d", major, minor), - product: "AlmaLinux", - osVersion: fmt.Sprintf("%d.%d", major, minor), - releaseVersion: fmt.Sprintf("%d", major), - modulePlatformID: fmt.Sprintf("platform:el%d", major), - vendor: "almalinux", - ostreeRefTmpl: fmt.Sprintf("almalinux/%d/%%s/edge", major), - runner: &runner.RHEL{Major: uint64(major), Minor: uint64(minor)}, - } - case "almalinux_kitten": - if minor != -1 { - return nil, fmt.Errorf("AlmaLinux Kitten does not have minor versions, but got %d", minor) - } - - rd = &Distribution{ - name: fmt.Sprintf("almalinux_kitten-%d", major), - product: "AlmaLinux Kitten", - osVersion: fmt.Sprintf("%d-kitten", major), - releaseVersion: fmt.Sprintf("%d", major), - modulePlatformID: fmt.Sprintf("platform:el%d", major), - vendor: "almalinux", - ostreeRefTmpl: fmt.Sprintf("almalinux/%d/%%s/edge", major), - runner: &runner.CentOS{Version: uint64(major)}, - } - default: - return nil, fmt.Errorf("unknown distro name: %s", name) - } - - return rd, nil -} diff --git a/pkg/distro/rhel/distro_test.go b/pkg/distro/rhel/distro_test.go deleted file mode 100644 index 843e744cad..0000000000 --- a/pkg/distro/rhel/distro_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package rhel_test - -import ( - "fmt" - "math/rand" - "strings" - "testing" - - "github.com/osbuild/images/pkg/blueprint" - "github.com/osbuild/images/pkg/disk" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/distro_test_common" - "github.com/osbuild/images/pkg/distro/rhel" - "github.com/osbuild/images/pkg/distrofactory" - "github.com/osbuild/images/pkg/platform" - "github.com/stretchr/testify/require" -) - -// math/rand is good enough in this case -/* #nosec G404 */ -var rng = rand.New(rand.NewSource(0)) - -func TestESP(t *testing.T) { - var distros []distro.Distro - distroFactory := distrofactory.NewDefault() - for _, distroName := range []string{"rhel-9.0", "rhel-9.2", "rhel-9.4", "centos-9"} { - distros = append(distros, distroFactory.GetDistro(distroName)) - } - - distro_test_common.TestESP(t, distros, func(i distro.ImageType) (*disk.PartitionTable, error) { - it := i.(*rhel.ImageType) - return it.GetPartitionTable(&blueprint.Customizations{}, distro.ImageOptions{}, rng) - }) -} - -// TestAMIHybridBoot verifies that rhel 8.9 and 9.3 are the first RHEL versions -// that implemented hybrid boot for the ami and ec2* image types -func TestAMIHybridBoot(t *testing.T) { - testCases := []struct { - distro string - bootMode platform.BootMode - }{ - {"rhel-8.8", platform.BOOT_LEGACY}, - {"rhel-8.9", platform.BOOT_HYBRID}, - {"rhel-8.10", platform.BOOT_HYBRID}, - {"centos-8", platform.BOOT_HYBRID}, - {"rhel-9.0", platform.BOOT_LEGACY}, - {"rhel-9.2", platform.BOOT_LEGACY}, - {"rhel-9.3", platform.BOOT_HYBRID}, - {"rhel-9.4", platform.BOOT_HYBRID}, - {"centos-9", platform.BOOT_HYBRID}, - {"rhel-10.0", platform.BOOT_HYBRID}, - {"centos-10", platform.BOOT_HYBRID}, - } - - distroFactory := distrofactory.NewDefault() - - for _, tc := range testCases { - // test only x86_64. ami for aarch64 has always UEFI, other arches are not defined. - a, err := distroFactory.GetDistro(tc.distro).GetArch("x86_64") - require.NoError(t, err) - - for _, it := range a.ListImageTypes() { - // test only ami and ec2* image types - if it != "ami" && !strings.HasPrefix(it, "ec2") { - continue - } - t.Run(fmt.Sprintf("%s/%s", tc.distro, it), func(t *testing.T) { - it, err := a.GetImageType(it) - require.NoError(t, err) - - require.Equal(t, tc.bootMode, it.BootMode()) - }) - } - } - -} diff --git a/pkg/distro/rhel/images.go b/pkg/distro/rhel/images.go deleted file mode 100644 index c9d5a030e8..0000000000 --- a/pkg/distro/rhel/images.go +++ /dev/null @@ -1,874 +0,0 @@ -package rhel - -import ( - "fmt" - "math/rand" - - "github.com/osbuild/images/internal/workload" - "github.com/osbuild/images/pkg/blueprint" - "github.com/osbuild/images/pkg/container" - "github.com/osbuild/images/pkg/customizations/anaconda" - "github.com/osbuild/images/pkg/customizations/fdo" - "github.com/osbuild/images/pkg/customizations/fsnode" - "github.com/osbuild/images/pkg/customizations/ignition" - "github.com/osbuild/images/pkg/customizations/kickstart" - "github.com/osbuild/images/pkg/customizations/oscap" - "github.com/osbuild/images/pkg/customizations/subscription" - "github.com/osbuild/images/pkg/customizations/users" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/image" - "github.com/osbuild/images/pkg/manifest" - "github.com/osbuild/images/pkg/osbuild" - "github.com/osbuild/images/pkg/ostree" - "github.com/osbuild/images/pkg/rpmmd" -) - -func osCustomizations( - t *ImageType, - osPackageSet rpmmd.PackageSet, - options distro.ImageOptions, - containers []container.SourceSpec, - c *blueprint.Customizations, -) (manifest.OSCustomizations, error) { - - imageConfig := t.getDefaultImageConfig() - - osc := manifest.OSCustomizations{} - - if t.Bootable || t.RPMOSTree { - // TODO: for now the only image types that define a default kernel are - // ones that use UKIs and don't allow overriding, so this works. - // However, if we ever need to specify default kernels for image types - // that allow overriding, we will need to change c.GetKernel() to take - // an argument as fallback or make it not return the standard "kernel" - // when it's unset. - osc.KernelName = c.GetKernel().Name - if imageConfig.DefaultKernelName != nil { - osc.KernelName = *imageConfig.DefaultKernelName - } - - var kernelOptions []string - // XXX: keep in sync with the identical copy in fedora/images.go - if t.DefaultImageConfig != nil && len(t.DefaultImageConfig.KernelOptions) > 0 { - kernelOptions = append(kernelOptions, t.DefaultImageConfig.KernelOptions...) - } - if bpKernel := c.GetKernel(); bpKernel.Append != "" { - kernelOptions = append(kernelOptions, bpKernel.Append) - } - osc.KernelOptionsAppend = kernelOptions - if imageConfig.KernelOptionsBootloader != nil { - osc.KernelOptionsBootloader = *imageConfig.KernelOptionsBootloader - } - } - - osc.FIPS = c.GetFIPS() - - osc.BasePackages = osPackageSet.Include - osc.ExcludeBasePackages = osPackageSet.Exclude - osc.ExtraBaseRepos = osPackageSet.Repositories - - osc.Containers = containers - - osc.GPGKeyFiles = imageConfig.GPGKeyFiles - if rpm := c.GetRPM(); rpm != nil && rpm.ImportKeys != nil { - osc.GPGKeyFiles = append(osc.GPGKeyFiles, rpm.ImportKeys.Files...) - } - - if imageConfig.ExcludeDocs != nil { - osc.ExcludeDocs = *imageConfig.ExcludeDocs - } - - if !t.BootISO { - // don't put users and groups in the payload of an installer - // add them via kickstart instead - osc.Groups = users.GroupsFromBP(c.GetGroups()) - - osc.Users = users.UsersFromBP(c.GetUsers()) - osc.Users = append(osc.Users, imageConfig.Users...) - } - - osc.EnabledServices = imageConfig.EnabledServices - osc.DisabledServices = imageConfig.DisabledServices - osc.MaskedServices = imageConfig.MaskedServices - if imageConfig.DefaultTarget != nil { - osc.DefaultTarget = *imageConfig.DefaultTarget - } - - osc.Firewall = imageConfig.Firewall - if fw := c.GetFirewall(); fw != nil { - options := osbuild.FirewallStageOptions{ - Ports: fw.Ports, - } - - if fw.Services != nil { - options.EnabledServices = fw.Services.Enabled - options.DisabledServices = fw.Services.Disabled - } - if fw.Zones != nil { - for _, z := range fw.Zones { - options.Zones = append(options.Zones, osbuild.FirewallZone{ - Name: *z.Name, - Sources: z.Sources, - }) - } - } - osc.Firewall = &options - } - - language, keyboard := c.GetPrimaryLocale() - if language != nil { - osc.Language = *language - } else if imageConfig.Locale != nil { - osc.Language = *imageConfig.Locale - } - if keyboard != nil { - osc.Keyboard = keyboard - } else if imageConfig.Keyboard != nil { - osc.Keyboard = &imageConfig.Keyboard.Keymap - if imageConfig.Keyboard.X11Keymap != nil { - osc.X11KeymapLayouts = imageConfig.Keyboard.X11Keymap.Layouts - } - } - - if hostname := c.GetHostname(); hostname != nil { - osc.Hostname = *hostname - } - - timezone, ntpServers := c.GetTimezoneSettings() - if timezone != nil { - osc.Timezone = *timezone - } else if imageConfig.Timezone != nil { - osc.Timezone = *imageConfig.Timezone - } - - if len(ntpServers) > 0 { - chronyServers := make([]osbuild.ChronyConfigServer, 0, len(ntpServers)) - for _, server := range ntpServers { - chronyServers = append(chronyServers, osbuild.ChronyConfigServer{Hostname: server}) - } - osc.ChronyConfig = &osbuild.ChronyStageOptions{ - Servers: chronyServers, - } - } else if imageConfig.TimeSynchronization != nil { - osc.ChronyConfig = imageConfig.TimeSynchronization - } - - // Relabel the tree, unless the `NoSELinux` flag is explicitly set to `true` - if imageConfig.NoSELinux == nil || imageConfig.NoSELinux != nil && !*imageConfig.NoSELinux { - osc.SELinux = "targeted" - osc.SELinuxForceRelabel = imageConfig.SELinuxForceRelabel - } - - if t.IsRHEL() && options.Facts != nil { - osc.RHSMFacts = options.Facts - } - - var err error - osc.Directories, err = blueprint.DirectoryCustomizationsToFsNodeDirectories(c.GetDirectories()) - if err != nil { - // In theory this should never happen, because the blueprint directory customizations - // should have been validated before this point. - panic(fmt.Sprintf("failed to convert directory customizations to fs node directories: %v", err)) - } - - osc.Files, err = blueprint.FileCustomizationsToFsNodeFiles(c.GetFiles()) - if err != nil { - // In theory this should never happen, because the blueprint file customizations - // should have been validated before this point. - panic(fmt.Sprintf("failed to convert file customizations to fs node files: %v", err)) - } - - // OSTree commits do not include data in `/var` since that is tied to the - // deployment, rather than the commit. Therefore the containers need to be - // stored in a different location, like `/usr/share`, and the container - // storage engine configured accordingly. - if t.RPMOSTree && len(containers) > 0 { - storagePath := "/usr/share/containers/storage" - osc.ContainersStorage = &storagePath - } - - if containerStorage := c.GetContainerStorage(); containerStorage != nil { - osc.ContainersStorage = containerStorage.StoragePath - } - - // set yum repos first, so it doesn't get overridden by - // imageConfig.YUMRepos - osc.YUMRepos = imageConfig.YUMRepos - - customRepos, err := c.GetRepositories() - if err != nil { - // This shouldn't happen and since the repos - // should have already been validated - panic(fmt.Sprintf("failed to get custom repos: %v", err)) - } - - // This function returns a map of filename and corresponding yum repos - // and a list of fs node files for the inline gpg keys so we can save - // them to disk. This step also swaps the inline gpg key with the path - // to the file in the os file tree - yumRepos, gpgKeyFiles, err := blueprint.RepoCustomizationsToRepoConfigAndGPGKeyFiles(customRepos) - if err != nil { - panic(fmt.Sprintf("failed to convert inline gpgkeys to fs node files: %v", err)) - } - - // add the gpg key files to the list of files to be added to the tree - if len(gpgKeyFiles) > 0 { - osc.Files = append(osc.Files, gpgKeyFiles...) - } - - for filename, repos := range yumRepos { - osc.YUMRepos = append(osc.YUMRepos, osbuild.NewYumReposStageOptions(filename, repos)) - } - - if oscapConfig := c.GetOpenSCAP(); oscapConfig != nil { - if t.RPMOSTree { - panic("unexpected oscap options for ostree image type") - } - - oscapDataNode, err := fsnode.NewDirectory(oscap.DataDir, nil, nil, nil, true) - if err != nil { - panic(fmt.Sprintf("unexpected error creating required OpenSCAP directory: %s", oscap.DataDir)) - } - osc.Directories = append(osc.Directories, oscapDataNode) - - remediationConfig, err := oscap.NewConfigs(*oscapConfig, imageConfig.DefaultOSCAPDatastream) - if err != nil { - panic(fmt.Errorf("error creating OpenSCAP configs: %w", err)) - } - - osc.OpenSCAPRemediationConfig = remediationConfig - } - - var subscriptionStatus subscription.RHSMStatus - if options.Subscription != nil { - subscriptionStatus = subscription.RHSMConfigWithSubscription - if options.Subscription.Proxy != "" { - osc.InsightsClientConfig = &osbuild.InsightsClientConfigStageOptions{Config: osbuild.InsightsClientConfig{Proxy: options.Subscription.Proxy}} - } - } else { - subscriptionStatus = subscription.RHSMConfigNoSubscription - } - if rhsmConfig, exists := imageConfig.RHSMConfig[subscriptionStatus]; exists { - osc.RHSMConfig = rhsmConfig - } - - if bpRhsmConfig := subscription.RHSMConfigFromBP(c.GetRHSM()); bpRhsmConfig != nil { - osc.RHSMConfig = osc.RHSMConfig.Update(bpRhsmConfig) - } - - osc.ShellInit = imageConfig.ShellInit - osc.Grub2Config = imageConfig.Grub2Config - osc.Sysconfig = imageConfig.SysconfigStageOptions() - osc.SystemdLogind = imageConfig.SystemdLogind - osc.CloudInit = imageConfig.CloudInit - osc.Modprobe = imageConfig.Modprobe - osc.DracutConf = imageConfig.DracutConf - osc.SystemdDropin = imageConfig.SystemdDropin - osc.SystemdUnit = imageConfig.SystemdUnit - osc.Authselect = imageConfig.Authselect - osc.SELinuxConfig = imageConfig.SELinuxConfig - osc.Tuned = imageConfig.Tuned - osc.Tmpfilesd = imageConfig.Tmpfilesd - osc.PamLimitsConf = imageConfig.PamLimitsConf - osc.Sysctld = imageConfig.Sysctld - osc.DNFConfig = imageConfig.DNFConfigOptions(t.arch.distro.osVersion) - osc.DNFAutomaticConfig = imageConfig.DNFAutomaticConfig - osc.YUMConfig = imageConfig.YumConfig - osc.SshdConfig = imageConfig.SshdConfig - osc.AuthConfig = imageConfig.Authconfig - osc.PwQuality = imageConfig.PwQuality - osc.Subscription = options.Subscription - osc.WAAgentConfig = imageConfig.WAAgentConfig - osc.UdevRules = imageConfig.UdevRules - osc.GCPGuestAgentConfig = imageConfig.GCPGuestAgentConfig - osc.NetworkManager = imageConfig.NetworkManager - - if imageConfig.WSL != nil { - osc.WSLConfig = osbuild.NewWSLConfStageOptions(imageConfig.WSL.Config) - osc.WSLDistributionConfig = osbuild.NewWSLDistributionConfStageOptions(imageConfig.WSL.DistributionConfig) - } - - osc.Files = append(osc.Files, imageConfig.Files...) - osc.Directories = append(osc.Directories, imageConfig.Directories...) - - if imageConfig.NoBLS != nil { - osc.NoBLS = *imageConfig.NoBLS - } - - ca, err := c.GetCACerts() - if err != nil { - panic(fmt.Sprintf("unexpected error checking CA certs: %v", err)) - } - if ca != nil { - osc.CACerts = ca.PEMCerts - } - - if imageConfig.InstallWeakDeps != nil { - osc.InstallWeakDeps = *imageConfig.InstallWeakDeps - } - - if imageConfig.MountUnits != nil { - osc.MountUnits = *imageConfig.MountUnits - } - - osc.VersionlockPackages = imageConfig.VersionlockPackages - - return osc, nil -} - -func ostreeDeploymentCustomizations( - t *ImageType, - c *blueprint.Customizations) (manifest.OSTreeDeploymentCustomizations, error) { - - if !t.RPMOSTree || !t.Bootable { - return manifest.OSTreeDeploymentCustomizations{}, fmt.Errorf("ostree deployment customizations are only supported for bootable rpm-ostree images") - } - - imageConfig := t.getDefaultImageConfig() - deploymentConf := manifest.OSTreeDeploymentCustomizations{} - - var kernelOptions []string - if len(t.DefaultImageConfig.KernelOptions) > 0 { - kernelOptions = append(kernelOptions, t.DefaultImageConfig.KernelOptions...) - } - if bpKernel := c.GetKernel(); bpKernel != nil && bpKernel.Append != "" { - kernelOptions = append(kernelOptions, bpKernel.Append) - } - - if imageConfig.IgnitionPlatform != nil { - deploymentConf.IgnitionPlatform = *imageConfig.IgnitionPlatform - } - - switch deploymentConf.IgnitionPlatform { - case "metal": - if bpIgnition := c.GetIgnition(); bpIgnition != nil && bpIgnition.FirstBoot != nil && bpIgnition.FirstBoot.ProvisioningURL != "" { - kernelOptions = append(kernelOptions, "ignition.config.url="+bpIgnition.FirstBoot.ProvisioningURL) - } - } - - deploymentConf.KernelOptionsAppend = kernelOptions - - deploymentConf.FIPS = c.GetFIPS() - - deploymentConf.Users = users.UsersFromBP(c.GetUsers()) - deploymentConf.Groups = users.GroupsFromBP(c.GetGroups()) - - var err error - deploymentConf.Directories, err = blueprint.DirectoryCustomizationsToFsNodeDirectories(c.GetDirectories()) - if err != nil { - return manifest.OSTreeDeploymentCustomizations{}, err - } - deploymentConf.Files, err = blueprint.FileCustomizationsToFsNodeFiles(c.GetFiles()) - if err != nil { - return manifest.OSTreeDeploymentCustomizations{}, err - } - - language, keyboard := c.GetPrimaryLocale() - if language != nil { - deploymentConf.Locale = *language - } else if imageConfig.Locale != nil { - deploymentConf.Locale = *imageConfig.Locale - } - if keyboard != nil { - deploymentConf.Keyboard = *keyboard - } else if imageConfig.Keyboard != nil { - deploymentConf.Keyboard = imageConfig.Keyboard.Keymap - } - - if imageConfig.OSTreeConfSysrootReadOnly != nil { - deploymentConf.SysrootReadOnly = *imageConfig.OSTreeConfSysrootReadOnly - } - - if imageConfig.LockRootUser != nil { - deploymentConf.LockRoot = *imageConfig.LockRootUser - } - - for _, fs := range c.GetFilesystems() { - deploymentConf.CustomFileSystems = append(deploymentConf.CustomFileSystems, fs.Mountpoint) - } - - if imageConfig.MountUnits != nil { - deploymentConf.MountUnits = *imageConfig.MountUnits - } - - return deploymentConf, nil -} - -func DiskImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - img := image.NewDiskImage() - img.Platform = t.platform - - var err error - img.OSCustomizations, err = osCustomizations(t, packageSets[OSPkgsKey], options, containers, customizations) - if err != nil { - return nil, err - } - - img.Environment = t.Environment - img.Workload = workload - img.Compression = t.Compression - // TODO: move generation into LiveImage - pt, err := t.GetPartitionTable(customizations, options, rng) - if err != nil { - return nil, err - } - img.PartitionTable = pt - - img.Filename = t.Filename() - - img.VPCForceSize = t.DiskImageVPCForceSize - - if img.OSCustomizations.NoBLS { - img.OSProduct = t.Arch().Distro().Product() - img.OSVersion = t.Arch().Distro().OsVersion() - img.OSNick = t.Arch().Distro().Codename() - } - - if t.DiskImagePartTool != nil { - img.PartTool = *t.DiskImagePartTool - } - - return img, nil -} - -func EdgeCommitImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - parentCommit, commitRef := makeOSTreeParentCommit(options.OSTree, t.OSTreeRef()) - img := image.NewOSTreeArchive(commitRef) - - img.Platform = t.platform - - var err error - img.OSCustomizations, err = osCustomizations(t, packageSets[OSPkgsKey], options, containers, customizations) - if err != nil { - return nil, err - } - - img.Environment = t.Environment - img.Workload = workload - img.OSTreeParent = parentCommit - img.OSVersion = t.Arch().Distro().OsVersion() - img.Filename = t.Filename() - - return img, nil -} - -func EdgeContainerImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - parentCommit, commitRef := makeOSTreeParentCommit(options.OSTree, t.OSTreeRef()) - img := image.NewOSTreeContainer(commitRef) - - img.Platform = t.platform - - var err error - img.OSCustomizations, err = osCustomizations(t, packageSets[OSPkgsKey], options, containers, customizations) - if err != nil { - return nil, err - } - - img.ContainerLanguage = img.OSCustomizations.Language - img.Environment = t.Environment - img.Workload = workload - img.OSTreeParent = parentCommit - img.OSVersion = t.Arch().Distro().OsVersion() - img.ExtraContainerPackages = packageSets[ContainerPkgsKey] - img.Filename = t.Filename() - - return img, nil -} - -func EdgeInstallerImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - commit, err := makeOSTreePayloadCommit(options.OSTree, t.OSTreeRef()) - if err != nil { - return nil, fmt.Errorf("%s: %s", t.Name(), err.Error()) - } - - img := image.NewAnacondaOSTreeInstaller(commit) - - img.Platform = t.platform - img.ExtraBasePackages = packageSets[InstallerPkgsKey] - img.Subscription = options.Subscription - - if t.Arch().Distro().Releasever() == "8" { - // NOTE: RHEL 8 only supports the older Anaconda configs - img.UseLegacyAnacondaConfig = true - } - - img.Kickstart, err = kickstart.New(customizations) - if err != nil { - return nil, err - } - img.Kickstart.OSTree = &kickstart.OSTree{ - OSName: "rhel-edge", - } - img.Kickstart.Path = osbuild.KickstartPathOSBuild - img.Kickstart.Language, img.Kickstart.Keyboard = customizations.GetPrimaryLocale() - // ignore ntp servers - we don't currently support setting these in the - // kickstart though kickstart does support setting them - img.Kickstart.Timezone, _ = customizations.GetTimezoneSettings() - - img.RootfsCompression = "xz" - if t.Arch().Distro().Releasever() == "10" { - img.RootfsType = manifest.SquashfsRootfs - } - - if locale := t.getDefaultImageConfig().Locale; locale != nil { - img.Locale = *locale - } - if isoboot := t.getDefaultImageConfig().ISOBootType; isoboot != nil { - img.ISOBoot = *isoboot - } - - installerConfig, err := t.getDefaultInstallerConfig() - if err != nil { - return nil, err - } - - if installerConfig != nil { - img.AdditionalDracutModules = append(img.AdditionalDracutModules, installerConfig.AdditionalDracutModules...) - img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...) - } - - instCust, err := customizations.GetInstaller() - if err != nil { - return nil, err - } - if instCust != nil && instCust.Modules != nil { - img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, instCust.Modules.Enable...) - img.DisabledAnacondaModules = append(img.DisabledAnacondaModules, instCust.Modules.Disable...) - } - - if len(img.Kickstart.Users)+len(img.Kickstart.Groups) > 0 { - // only enable the users module if needed - img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers) - } - - img.ISOLabel, err = t.ISOLabel() - if err != nil { - return nil, err - } - - img.Product = t.Arch().Distro().Product() - img.Variant = "edge" - img.OSVersion = t.Arch().Distro().OsVersion() - img.Release = fmt.Sprintf("%s %s", t.Arch().Distro().Product(), t.Arch().Distro().OsVersion()) - img.FIPS = customizations.GetFIPS() - - img.Filename = t.Filename() - - return img, nil -} - -func EdgeRawImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - commit, err := makeOSTreePayloadCommit(options.OSTree, t.OSTreeRef()) - if err != nil { - return nil, fmt.Errorf("%s: %s", t.Name(), err.Error()) - } - img := image.NewOSTreeDiskImageFromCommit(commit) - - deploymentConfig, err := ostreeDeploymentCustomizations(t, customizations) - if err != nil { - return nil, err - } - img.OSTreeDeploymentCustomizations = deploymentConfig - - img.Platform = t.platform - img.Workload = workload - img.Remote = ostree.Remote{ - Name: "rhel-edge", - URL: options.OSTree.URL, - ContentURL: options.OSTree.ContentURL, - } - img.OSName = "rhel-edge" - - // TODO: move generation into LiveImage - pt, err := t.GetPartitionTable(customizations, options, rng) - if err != nil { - return nil, err - } - img.PartitionTable = pt - - img.Filename = t.Filename() - img.Compression = t.Compression - - return img, nil -} - -func EdgeSimplifiedInstallerImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - commit, err := makeOSTreePayloadCommit(options.OSTree, t.OSTreeRef()) - if err != nil { - return nil, fmt.Errorf("%s: %s", t.Name(), err.Error()) - } - rawImg := image.NewOSTreeDiskImageFromCommit(commit) - - deploymentConfig, err := ostreeDeploymentCustomizations(t, customizations) - if err != nil { - return nil, err - } - rawImg.OSTreeDeploymentCustomizations = deploymentConfig - - rawImg.Platform = t.platform - rawImg.Workload = workload - rawImg.Remote = ostree.Remote{ - Name: "rhel-edge", - URL: options.OSTree.URL, - ContentURL: options.OSTree.ContentURL, - } - rawImg.OSName = "rhel-edge" - - // TODO: move generation into LiveImage - pt, err := t.GetPartitionTable(customizations, options, rng) - if err != nil { - return nil, err - } - rawImg.PartitionTable = pt - - rawImg.Filename = t.Filename() - - img := image.NewOSTreeSimplifiedInstaller(rawImg, customizations.InstallationDevice) - img.ExtraBasePackages = packageSets[InstallerPkgsKey] - // img.Workload = workload - img.Platform = t.platform - img.Filename = t.Filename() - if bpFDO := customizations.GetFDO(); bpFDO != nil { - img.FDO = fdo.FromBP(*bpFDO) - } - // ignition configs from blueprint - if bpIgnition := customizations.GetIgnition(); bpIgnition != nil { - if bpIgnition.Embedded != nil { - var err error - img.IgnitionEmbedded, err = ignition.EmbeddedOptionsFromBP(*bpIgnition.Embedded) - if err != nil { - return nil, err - } - } - } - - img.ISOLabel, err = t.ISOLabel() - if err != nil { - return nil, err - } - - d := t.arch.distro - img.Product = d.product - img.Variant = "edge" - img.OSName = "rhel-edge" - img.OSVersion = d.osVersion - - installerConfig, err := t.getDefaultInstallerConfig() - if err != nil { - return nil, err - } - - if installerConfig != nil { - img.AdditionalDracutModules = append(img.AdditionalDracutModules, installerConfig.AdditionalDracutModules...) - img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...) - } - - return img, nil -} - -func ImageInstallerImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - img := image.NewAnacondaTarInstaller() - - img.Platform = t.platform - img.Workload = workload - - var err error - img.OSCustomizations, err = osCustomizations(t, packageSets[OSPkgsKey], options, containers, customizations) - if err != nil { - return nil, err - } - - img.ExtraBasePackages = packageSets[InstallerPkgsKey] - - if t.Arch().Distro().Releasever() == "8" { - // NOTE: RHEL 8 only supports the older Anaconda configs - img.UseLegacyAnacondaConfig = true - } - - img.Kickstart, err = kickstart.New(customizations) - if err != nil { - return nil, err - } - img.Kickstart.Language = &img.OSCustomizations.Language - img.Kickstart.Keyboard = img.OSCustomizations.Keyboard - img.Kickstart.Timezone = &img.OSCustomizations.Timezone - - installerConfig, err := t.getDefaultInstallerConfig() - if err != nil { - return nil, err - } - - if installerConfig != nil { - img.AdditionalDracutModules = append(img.AdditionalDracutModules, installerConfig.AdditionalDracutModules...) - img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...) - } - - instCust, err := customizations.GetInstaller() - if err != nil { - return nil, err - } - if instCust != nil && instCust.Modules != nil { - img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, instCust.Modules.Enable...) - img.DisabledAnacondaModules = append(img.DisabledAnacondaModules, instCust.Modules.Disable...) - } - img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers) - - img.RootfsCompression = "xz" - if t.Arch().Distro().Releasever() == "10" { - img.RootfsType = manifest.SquashfsRootfs - } - - if isoboot := t.getDefaultImageConfig().ISOBootType; isoboot != nil { - img.ISOBoot = *isoboot - } - - // put the kickstart file in the root of the iso - img.ISORootKickstart = true - - img.ISOLabel, err = t.ISOLabel() - if err != nil { - return nil, err - } - - d := t.arch.distro - img.Product = d.product - img.OSVersion = d.osVersion - img.Release = fmt.Sprintf("%s %s", d.product, d.osVersion) - - img.Filename = t.Filename() - - return img, nil -} - -func TarImage(workload workload.Workload, - t *ImageType, - customizations *blueprint.Customizations, - options distro.ImageOptions, - packageSets map[string]rpmmd.PackageSet, - containers []container.SourceSpec, - rng *rand.Rand) (image.ImageKind, error) { - - img := image.NewArchive() - img.Platform = t.platform - - var err error - img.OSCustomizations, err = osCustomizations(t, packageSets[OSPkgsKey], options, containers, customizations) - if err != nil { - return nil, err - } - - img.Environment = t.Environment - img.Workload = workload - img.Compression = t.Compression - img.OSVersion = t.Arch().Distro().OsVersion() - - img.Filename = t.Filename() - - return img, nil - -} - -// Create an ostree SourceSpec to define an ostree parent commit using the user -// options and the default ref for the image type. Additionally returns the -// ref to be used for the new commit to be created. -func makeOSTreeParentCommit(options *ostree.ImageOptions, defaultRef string) (*ostree.SourceSpec, string) { - commitRef := defaultRef - if options == nil { - // nothing to do - return nil, commitRef - } - if options.ImageRef != "" { - // user option overrides default commit ref - commitRef = options.ImageRef - } - - var parentCommit *ostree.SourceSpec - if options.URL == "" { - // no parent - return nil, commitRef - } - - // ostree URL specified: set source spec for parent commit - parentRef := options.ParentRef - if parentRef == "" { - // parent ref not set: use image ref - parentRef = commitRef - - } - parentCommit = &ostree.SourceSpec{ - URL: options.URL, - Ref: parentRef, - RHSM: options.RHSM, - } - return parentCommit, commitRef -} - -// Create an ostree SourceSpec to define an ostree payload using the user options and the default ref for the image type. -func makeOSTreePayloadCommit(options *ostree.ImageOptions, defaultRef string) (ostree.SourceSpec, error) { - if options == nil || options.URL == "" { - // this should be caught by checkOptions() in distro, but it's good - // to guard against it here as well - return ostree.SourceSpec{}, fmt.Errorf("ostree commit URL required") - } - - commitRef := defaultRef - if options.ImageRef != "" { - // user option overrides default commit ref - commitRef = options.ImageRef - } - - return ostree.SourceSpec{ - URL: options.URL, - Ref: commitRef, - RHSM: options.RHSM, - }, nil -} diff --git a/pkg/distro/rhel/images_test.go b/pkg/distro/rhel/images_test.go deleted file mode 100644 index 7259809fee..0000000000 --- a/pkg/distro/rhel/images_test.go +++ /dev/null @@ -1,447 +0,0 @@ -package rhel - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/blueprint" - "github.com/osbuild/images/pkg/customizations/subscription" - "github.com/osbuild/images/pkg/disk" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/manifest" - "github.com/osbuild/images/pkg/platform" - "github.com/osbuild/images/pkg/rpmmd" -) - -func TestOsCustomizationsRHSM(t *testing.T) { - type testCase struct { - name string - ic *distro.ImageConfig - io *distro.ImageOptions - bpc *blueprint.Customizations - expectedOsc *manifest.OSCustomizations - } - - testCases := []testCase{ - { - name: "no rhsm config at all; subscription in the image options", - ic: &distro.ImageConfig{}, - io: &distro.ImageOptions{Subscription: &subscription.ImageOptions{}}, - bpc: &blueprint.Customizations{}, - expectedOsc: &manifest.OSCustomizations{}, - }, - { - name: "no rhsm config at all; no subscription in the image options", - ic: &distro.ImageConfig{}, - io: &distro.ImageOptions{}, - bpc: &blueprint.Customizations{}, - expectedOsc: &manifest.OSCustomizations{}, - }, - { - name: "rhsm config in the image config, no subscription in the image options", - ic: &distro.ImageConfig{ - RHSMConfig: map[subscription.RHSMStatus]*subscription.RHSMConfig{ - subscription.RHSMConfigNoSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(false), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - subscription.RHSMConfigWithSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - io: &distro.ImageOptions{}, - bpc: &blueprint.Customizations{}, - expectedOsc: &manifest.OSCustomizations{ - RHSMConfig: &subscription.RHSMConfig{ - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(false), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - }, - }, - { - name: "rhsm config in the image config, subscription in the image options", - ic: &distro.ImageConfig{ - RHSMConfig: map[subscription.RHSMStatus]*subscription.RHSMConfig{ - subscription.RHSMConfigNoSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(false), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - subscription.RHSMConfigWithSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - io: &distro.ImageOptions{Subscription: &subscription.ImageOptions{}}, - bpc: &blueprint.Customizations{}, - expectedOsc: &manifest.OSCustomizations{ - RHSMConfig: &subscription.RHSMConfig{ - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - { - name: "no rhsm config in the image config, rhsm config in the BP, subscription in the image options", - ic: &distro.ImageConfig{}, - io: &distro.ImageOptions{Subscription: &subscription.ImageOptions{}}, - bpc: &blueprint.Customizations{ - RHSM: &blueprint.RHSMCustomization{ - Config: &blueprint.RHSMConfig{ - DNFPlugins: &blueprint.SubManDNFPluginsConfig{ - ProductID: &blueprint.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: &blueprint.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubscriptionManager: &blueprint.SubManConfig{ - RHSMConfig: &blueprint.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - RHSMCertdConfig: &blueprint.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - expectedOsc: &manifest.OSCustomizations{ - RHSMConfig: &subscription.RHSMConfig{ - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - { - name: "no rhsm config in the image config, rhsm config in the BP, no subscription in the image options", - ic: &distro.ImageConfig{}, - io: &distro.ImageOptions{}, - bpc: &blueprint.Customizations{ - RHSM: &blueprint.RHSMCustomization{ - Config: &blueprint.RHSMConfig{ - DNFPlugins: &blueprint.SubManDNFPluginsConfig{ - ProductID: &blueprint.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: &blueprint.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubscriptionManager: &blueprint.SubManConfig{ - RHSMConfig: &blueprint.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - RHSMCertdConfig: &blueprint.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - expectedOsc: &manifest.OSCustomizations{ - RHSMConfig: &subscription.RHSMConfig{ - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - { - name: "rhsm config in the image config, rhsm config in the BP, no subscription in the image options", - ic: &distro.ImageConfig{ - RHSMConfig: map[subscription.RHSMStatus]*subscription.RHSMConfig{ - subscription.RHSMConfigNoSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(false), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - subscription.RHSMConfigWithSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - io: &distro.ImageOptions{}, - bpc: &blueprint.Customizations{ - RHSM: &blueprint.RHSMCustomization{ - Config: &blueprint.RHSMConfig{ - DNFPlugins: &blueprint.SubManDNFPluginsConfig{ - SubscriptionManager: &blueprint.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubscriptionManager: &blueprint.SubManConfig{ - RHSMConfig: &blueprint.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - }, - }, - }, - }, - expectedOsc: &manifest.OSCustomizations{ - RHSMConfig: &subscription.RHSMConfig{ - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - }, - }, - { - name: "rhsm config in the image config, rhsm config in the BP, subscription in the image options", - ic: &distro.ImageConfig{ - RHSMConfig: map[subscription.RHSMStatus]*subscription.RHSMConfig{ - subscription.RHSMConfigNoSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(false), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - subscription.RHSMConfigWithSubscription: { - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(false), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(false), - }, - }, - }, - }, - }, - io: &distro.ImageOptions{Subscription: &subscription.ImageOptions{}}, - bpc: &blueprint.Customizations{ - RHSM: &blueprint.RHSMCustomization{ - Config: &blueprint.RHSMConfig{ - DNFPlugins: &blueprint.SubManDNFPluginsConfig{ - ProductID: &blueprint.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubscriptionManager: &blueprint.SubManConfig{ - RHSMCertdConfig: &blueprint.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - }, - }, - expectedOsc: &manifest.OSCustomizations{ - RHSMConfig: &subscription.RHSMConfig{ - DnfPlugins: subscription.SubManDNFPluginsConfig{ - ProductID: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - SubscriptionManager: subscription.DNFPluginConfig{ - Enabled: common.ToPtr(true), - }, - }, - SubMan: subscription.SubManConfig{ - Rhsm: subscription.SubManRHSMConfig{ - ManageRepos: common.ToPtr(true), - }, - Rhsmcertd: subscription.SubManRHSMCertdConfig{ - AutoRegistration: common.ToPtr(true), - }, - }, - }, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - testDistro, err := NewDistribution("rhel", 9, 0) - assert.NoError(t, err) - testArch := NewArchitecture(testDistro, arch.ARCH_X86_64) - it := &ImageType{DefaultImageConfig: tc.ic} - testArch.AddImageTypes(&platform.X86{}, it) - - osc, err := osCustomizations(it, rpmmd.PackageSet{}, *tc.io, nil, tc.bpc) - assert.NoError(t, err) - assert.EqualValues(t, tc.expectedOsc.RHSMConfig, osc.RHSMConfig) - }) - } -} - -func TestPartitionTypeNotCrashing(t *testing.T) { - it := &ImageType{} - assert.Equal(t, it.PartitionType(), disk.PT_NONE) -} diff --git a/pkg/distro/rhel/imagetype.go b/pkg/distro/rhel/imagetype.go deleted file mode 100644 index 15a6a1bda9..0000000000 --- a/pkg/distro/rhel/imagetype.go +++ /dev/null @@ -1,461 +0,0 @@ -package rhel - -import ( - "fmt" - "math/rand" - - "slices" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/internal/environment" - "github.com/osbuild/images/internal/workload" - "github.com/osbuild/images/pkg/blueprint" - "github.com/osbuild/images/pkg/container" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/disk" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/experimentalflags" - "github.com/osbuild/images/pkg/image" - "github.com/osbuild/images/pkg/manifest" - "github.com/osbuild/images/pkg/osbuild" - "github.com/osbuild/images/pkg/platform" - "github.com/osbuild/images/pkg/rpmmd" -) - -const ( - // package set names - - // build package set name - BuildPkgsKey = "build" - - // main/common os image package set name - OSPkgsKey = "os" - - // container package set name - ContainerPkgsKey = "container" - - // installer package set name - InstallerPkgsKey = "installer" - - // blueprint package set name - BlueprintPkgsKey = "blueprint" -) - -// Default directory size minimums for all image types. -var requiredDirectorySizes = map[string]uint64{ - "/": 1 * datasizes.GiB, - "/usr": 2 * datasizes.GiB, -} - -type ImageFunc func(workload workload.Workload, t *ImageType, customizations *blueprint.Customizations, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error) - -type PackageSetFunc func(t *ImageType) (map[string]rpmmd.PackageSet, error) - -type BasePartitionTableFunc func(t *ImageType) (disk.PartitionTable, bool) - -type ISOLabelFunc func(t *ImageType) string - -type CheckOptionsFunc func(t *ImageType, bp *blueprint.Blueprint, options distro.ImageOptions) ([]string, error) - -type ImageType struct { - // properties, which are part of the distro.ImageType interface or are used by all images - name string - filename string - mimeType string - packageSets PackageSetFunc - buildPipelines []string - payloadPipelines []string - exports []string - image ImageFunc - - // properties which can't be set when defining the image type - arch *Architecture - platform platform.Platform - - Environment environment.Environment - Workload workload.Workload - NameAliases []string - Compression string // TODO: remove from image definition and make it a transport option - DefaultImageConfig *distro.ImageConfig - DefaultInstallerConfig *distro.InstallerConfig - DefaultSize uint64 - - // bootISO: installable ISO - BootISO bool - // rpmOstree: edge/ostree - RPMOSTree bool - // bootable image - Bootable bool - // List of valid arches for the image type - BasePartitionTables BasePartitionTableFunc - // Optional list of unsupported partitioning modes - UnsupportedPartitioningModes []disk.PartitioningMode - - ISOLabelFn ISOLabelFunc - - // TODO: determine a better place for these options, but for now they are here - DiskImagePartTool *osbuild.PartTool - DiskImageVPCForceSize *bool -} - -func (t *ImageType) Name() string { - return t.name -} - -func (t *ImageType) Arch() distro.Arch { - return t.arch -} - -func (t *ImageType) Filename() string { - return t.filename -} - -func (t *ImageType) MIMEType() string { - return t.mimeType -} - -func (t *ImageType) OSTreeRef() string { - d := t.arch.distro - if t.RPMOSTree { - return fmt.Sprintf(d.ostreeRefTmpl, t.Arch().Name()) - } - return "" -} - -// IsRHEL returns true if the image type is part of a RHEL distribution -// -// This is a convenience method, because external packages can't get the -// information from t.Arch().Distro(), since the distro.Distro interface -// does not have this method. And since the distro.Distro interface is -// distro-agnostic, it does not make much sense to have a method like this -// in the interface. -func (t *ImageType) IsRHEL() bool { - return t.arch.distro.IsRHEL() -} - -func (t *ImageType) IsAlmaLinux() bool { - return t.arch.distro.IsAlmaLinux() -} - -func (t *ImageType) IsAlmaLinuxKitten() bool { - return t.arch.distro.IsAlmaLinuxKitten() -} - -func (t *ImageType) ISOLabel() (string, error) { - if !t.BootISO { - return "", fmt.Errorf("image type %q is not an ISO", t.name) - } - - if t.ISOLabelFn != nil { - return t.ISOLabelFn(t), nil - } - - return "", nil -} - -func (t *ImageType) Size(size uint64) uint64 { - // Microsoft Azure requires vhd images to be rounded up to the nearest MB - if t.name == "vhd" && size%datasizes.MebiByte != 0 { - size = (size/datasizes.MebiByte + 1) * datasizes.MebiByte - } - if size == 0 { - size = t.DefaultSize - } - return size -} - -func (t *ImageType) BuildPipelines() []string { - return t.buildPipelines -} - -func (t *ImageType) PayloadPipelines() []string { - return t.payloadPipelines -} - -func (t *ImageType) PayloadPackageSets() []string { - return []string{BlueprintPkgsKey} -} - -func (t *ImageType) Exports() []string { - if len(t.exports) > 0 { - return t.exports - } - return []string{"assembler"} -} - -func (t *ImageType) BootMode() platform.BootMode { - if t.platform.GetUEFIVendor() != "" && t.platform.GetBIOSPlatform() != "" { - return platform.BOOT_HYBRID - } else if t.platform.GetUEFIVendor() != "" { - return platform.BOOT_UEFI - } else if t.platform.GetBIOSPlatform() != "" || t.platform.GetZiplSupport() { - return platform.BOOT_LEGACY - } - return platform.BOOT_NONE -} - -func (t *ImageType) BasePartitionTable() (*disk.PartitionTable, error) { - // XXX: simplify once https://github.com/osbuild/images/pull/1372 - // (or something similar) went in, see pkg/distro/fedora, once - // the yaml based loading is in we can drop from ImageType - // "BasePartitionTables BasePartitionTableFunc" - if t.BasePartitionTables == nil { - return nil, nil - } - basePartitionTable, exists := t.BasePartitionTables(t) - if !exists { - return nil, nil - } - return &basePartitionTable, nil -} - -func (t *ImageType) GetPartitionTable( - customizations *blueprint.Customizations, - options distro.ImageOptions, - rng *rand.Rand, -) (*disk.PartitionTable, error) { - archName := t.arch.Name() - - basePartitionTable, exists := t.BasePartitionTables(t) - - if !exists { - return nil, fmt.Errorf("no partition table defined for architecture %q for image type %q", archName, t.Name()) - } - - imageSize := t.Size(options.Size) - partitioning, err := customizations.GetPartitioning() - if err != nil { - return nil, err - } - if partitioning != nil { - // Use the new custom partition table to create a PT fully based on the user's customizations. - // This overrides FilesystemCustomizations, but we should never have both defined. - if options.Size > 0 { - // user specified a size on the command line, so let's override the - // customization with the calculated/rounded imageSize - partitioning.MinSize = imageSize - } - - partOptions := &disk.CustomPartitionTableOptions{ - PartitionTableType: basePartitionTable.Type, // PT type is not customizable, it is determined by the base PT for an image type or architecture - BootMode: t.BootMode(), - DefaultFSType: disk.FS_XFS, // default fs type for RHEL - RequiredMinSizes: requiredDirectorySizes, - Architecture: t.platform.GetArch(), - } - return disk.NewCustomPartitionTable(partitioning, partOptions, rng) - } - - return disk.NewPartitionTable(&basePartitionTable, customizations.GetFilesystems(), imageSize, options.PartitioningMode, t.platform.GetArch(), nil, rng) -} - -func (t *ImageType) getDefaultImageConfig() *distro.ImageConfig { - // ensure that image always returns non-nil default config - imageConfig := t.DefaultImageConfig - if imageConfig == nil { - imageConfig = &distro.ImageConfig{} - } - return imageConfig.InheritFrom(t.arch.distro.GetDefaultImageConfig()) - -} - -func (t *ImageType) getDefaultInstallerConfig() (*distro.InstallerConfig, error) { - if !t.BootISO { - return nil, fmt.Errorf("image type %q is not an ISO", t.name) - } - - return t.DefaultInstallerConfig, nil -} - -func (t *ImageType) PartitionType() disk.PartitionTableType { - if t.BasePartitionTables == nil { - return disk.PT_NONE - } - - basePartitionTable, exists := t.BasePartitionTables(t) - if !exists { - return disk.PT_NONE - } - - return basePartitionTable.Type -} - -func (t *ImageType) Manifest(bp *blueprint.Blueprint, - options distro.ImageOptions, - repos []rpmmd.RepoConfig, - seedp *int64) (*manifest.Manifest, []string, error) { - seed := distro.SeedFrom(seedp) - - if t.Workload != nil { - // For now, if an image type defines its own workload, don't allow any - // user customizations. - // Soon we will have more workflows and each will define its allowed - // set of customizations. The current set of customizations defined in - // the blueprint spec corresponds to the Custom workflow. - if bp.Customizations != nil { - return nil, nil, fmt.Errorf(distro.NoCustomizationsAllowedError, t.Name()) - } - } - - warnings, err := t.checkOptions(bp, options) - if err != nil { - return nil, nil, err - } - - // merge package sets that appear in the image type with the package sets - // of the same name from the distro and arch - staticPackageSets := make(map[string]rpmmd.PackageSet) - - if t.packageSets != nil { - pkgSets, err := t.packageSets(t) - if err != nil { - return nil, nil, err - } - for name, pkgSet := range pkgSets { - staticPackageSets[name] = pkgSet - } - } - - // amend with repository information and collect payload repos - payloadRepos := make([]rpmmd.RepoConfig, 0) - for _, repo := range repos { - if len(repo.PackageSets) > 0 { - // only apply the repo to the listed package sets - for _, psName := range repo.PackageSets { - if slices.Contains(t.PayloadPackageSets(), psName) { - payloadRepos = append(payloadRepos, repo) - } - ps := staticPackageSets[psName] - ps.Repositories = append(ps.Repositories, repo) - staticPackageSets[psName] = ps - } - } - } - - w := t.Workload - if w == nil { - // XXX: this needs to get duplicaed in exactly the same - // way in fedora/imagetype.go - workloadRepos := payloadRepos - customRepos, err := bp.Customizations.GetRepositories() - if err != nil { - return nil, nil, err - } - installFromRepos := blueprint.RepoCustomizationsInstallFromOnly(customRepos) - workloadRepos = append(workloadRepos, installFromRepos...) - - cw := &workload.Custom{ - BaseWorkload: workload.BaseWorkload{ - Repos: workloadRepos, - }, - Packages: bp.GetPackagesEx(false), - EnabledModules: bp.GetEnabledModules(), - } - if services := bp.Customizations.GetServices(); services != nil { - cw.Services = services.Enabled - cw.DisabledServices = services.Disabled - cw.MaskedServices = services.Masked - } - w = cw - } - - containerSources := make([]container.SourceSpec, len(bp.Containers)) - for idx, cont := range bp.Containers { - containerSources[idx] = container.SourceSpec{ - Source: cont.Source, - Name: cont.Name, - TLSVerify: cont.TLSVerify, - Local: cont.LocalStorage, - } - } - - if experimentalflags.Bool("no-fstab") { - if t.DefaultImageConfig == nil { - t.DefaultImageConfig = &distro.ImageConfig{ - MountUnits: common.ToPtr(true), - } - } else { - t.DefaultImageConfig.MountUnits = common.ToPtr(true) - } - } - - source := rand.NewSource(seed) - // math/rand is good enough in this case - /* #nosec G404 */ - rng := rand.New(source) - - img, err := t.image(w, t, bp.Customizations, options, staticPackageSets, containerSources, rng) - if err != nil { - return nil, nil, err - } - mf := manifest.New() - - switch t.Arch().Distro().Releasever() { - case "7": - mf.Distro = manifest.DISTRO_EL7 - case "8": - mf.Distro = manifest.DISTRO_EL8 - case "9": - mf.Distro = manifest.DISTRO_EL9 - case "10": - mf.Distro = manifest.DISTRO_EL10 - default: - return nil, nil, fmt.Errorf("unsupported distro release version: %s", t.Arch().Distro().Releasever()) - } - if options.UseBootstrapContainer { - mf.DistroBootstrapRef = bootstrapContainerFor(t) - } - - _, err = img.InstantiateManifest(&mf, repos, t.arch.distro.runner, rng) - if err != nil { - return nil, nil, err - } - - return &mf, warnings, err -} - -// checkOptions checks the validity and compatibility of options and customizations for the image type. -// Returns ([]string, error) where []string, if non-nil, will hold any generated warnings (e.g. deprecation notices). -func (t *ImageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOptions) ([]string, error) { - if !t.RPMOSTree && options.OSTree != nil { - return nil, fmt.Errorf("OSTree is not supported for %q", t.Name()) - } - - if t.arch.distro.CheckOptions != nil { - return t.arch.distro.CheckOptions(t, bp, options) - } - - return nil, nil -} - -func NewImageType( - name, filename, mimeType string, - pkgSets PackageSetFunc, - imgFunc ImageFunc, - buildPipelines, payloadPipelines, exports []string, -) *ImageType { - return &ImageType{ - name: name, - filename: filename, - mimeType: mimeType, - packageSets: pkgSets, - image: imgFunc, - buildPipelines: buildPipelines, - payloadPipelines: payloadPipelines, - exports: exports, - } -} - -// XXX: this will become part of the yaml distro definitions, i.e. -// the yaml will have a "bootstrap_ref" key for each distro/arch -func bootstrapContainerFor(t *ImageType) string { - distro := t.arch.distro - - if distro.IsRHEL() { - return fmt.Sprintf("registry.access.redhat.com/ubi%s/ubi:latest", distro.Releasever()) - } else { - // we need the toolbox container because stock centos has - // e.g. no mount util - return "quay.io/toolbx-images/centos-toolbox:stream" + distro.Releasever() - } -} diff --git a/pkg/distro/rhel/rhel9/ami.go b/pkg/distro/rhel/rhel9/ami.go deleted file mode 100644 index 8c858c9b32..0000000000 --- a/pkg/distro/rhel/rhel9/ami.go +++ /dev/null @@ -1,130 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkEc2ImgTypeX86_64(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ec2", - "image.raw.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 10 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(d, a.String(), "ec2") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkAMIImgTypeX86_64(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ami", - "image.raw", - "application/octet-stream", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image"}, - []string{"image"}, - ) - - it.Bootable = true - it.DefaultSize = 10 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(d, a.String(), "ami") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} -func mkEC2SapImgTypeX86_64(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ec2-sap", - "image.raw.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 10 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(d, a.String(), "ec2-sap") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkEc2HaImgTypeX86_64(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ec2-ha", - "image.raw.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 10 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(d, a.String(), "ec2-ha") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkAMIImgTypeAarch64(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ami", - "image.raw", - "application/octet-stream", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image"}, - []string{"image"}, - ) - - it.Bootable = true - it.DefaultSize = 10 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(d, a.String(), "ami") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkEC2ImgTypeAarch64(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ec2", - "image.raw.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 10 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(d, a.String(), "ec2") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} diff --git a/pkg/distro/rhel/rhel9/azure.go b/pkg/distro/rhel/rhel9/azure.go deleted file mode 100644 index 6231289be5..0000000000 --- a/pkg/distro/rhel/rhel9/azure.go +++ /dev/null @@ -1,115 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/distro/rhel" -) - -// Azure image type -func mkAzureImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "vhd", - "disk.vhd", - "application/x-vhd", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vpc"}, - []string{"vpc"}, - ) - - it.Bootable = true - it.DefaultSize = 4 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(rd, a.String(), "vhd") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -// Azure RHEL-internal image type -func mkAzureInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "azure-rhui", - "disk.vhd.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vpc", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 64 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(rd, a.String(), "azure-rhui") - - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkAzureSapInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "azure-sap-rhui", - "disk.vhd.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vpc", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 64 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(rd, a.String(), "azure-sap-rhui") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkAzureSapAppsImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "azure-sapapps-rhui", - "disk.vhd.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vpc", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 64 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(rd, a.String(), "azure-sapapps-rhui") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -// Azure Confidential VM -func mkAzureCVMImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "azure-cvm", - "disk.vhd.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vpc", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.Bootable = true - it.DefaultSize = 32 * datasizes.GibiByte - it.DefaultImageConfig = imageConfig(rd, a.String(), "azure-cvm") - it.BasePartitionTables = defaultBasePartitionTables - - return it -} diff --git a/pkg/distro/rhel/rhel9/bare_metal.go b/pkg/distro/rhel/rhel9/bare_metal.go deleted file mode 100644 index 138563570d..0000000000 --- a/pkg/distro/rhel/rhel9/bare_metal.go +++ /dev/null @@ -1,52 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkTarImgType() *rhel.ImageType { - return rhel.NewImageType( - "tar", - "root.tar.xz", - "application/x-tar", - packageSetLoader, - rhel.TarImage, - []string{"build"}, - []string{"os", "archive"}, - []string{"archive"}, - ) -} - -func mkImageInstallerImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "image-installer", - "installer.iso", - "application/x-iso9660-image", - packageSetLoader, - rhel.ImageInstallerImage, - []string{"build"}, - []string{"anaconda-tree", "rootfs-image", "efiboot-tree", "os", "bootiso-tree", "bootiso"}, - []string{"bootiso"}, - ) - - it.BootISO = true - it.Bootable = true - it.ISOLabelFn = distroISOLabelFunc - - it.DefaultInstallerConfig = &distro.InstallerConfig{ - AdditionalDracutModules: []string{ - "nvdimm", // non-volatile DIMM firmware (provides nfit, cuse, and nd_e820) - "ifcfg", - }, - AdditionalDrivers: []string{ - "cuse", - "ipmi_devintf", - "ipmi_msghandler", - }, - } - it.DefaultImageConfig = imageConfig(d, a.String(), "image-installer") - - return it -} diff --git a/pkg/distro/rhel/rhel9/distro.go b/pkg/distro/rhel/rhel9/distro.go deleted file mode 100644 index a62c75b765..0000000000 --- a/pkg/distro/rhel/rhel9/distro.go +++ /dev/null @@ -1,427 +0,0 @@ -package rhel9 - -import ( - "fmt" - "strings" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/customizations/oscap" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/defs" - "github.com/osbuild/images/pkg/distro/rhel" - "github.com/osbuild/images/pkg/platform" -) - -var ( - // rhel9 & cs9 share the same list - // of allowed profiles so a single - // allow list can be used - oscapProfileAllowList = []oscap.Profile{ - oscap.AnssiBp28Enhanced, - oscap.AnssiBp28High, - oscap.AnssiBp28Intermediary, - oscap.AnssiBp28Minimal, - oscap.CcnAdvanced, - oscap.CcnBasic, - oscap.CcnIntermediate, - oscap.Cis, - oscap.CisServerL1, - oscap.CisWorkstationL1, - oscap.CisWorkstationL2, - oscap.Cui, - oscap.E8, - oscap.Hippa, - oscap.IsmO, - oscap.Ospp, - oscap.PciDss, - oscap.Stig, - oscap.StigGui, - } -) - -func distroISOLabelFunc(t *rhel.ImageType) string { - const RHEL_ISO_LABEL = "RHEL-%s-%s-0-BaseOS-%s" - const CS_ISO_LABEL = "CentOS-Stream-%s-BaseOS-%s" - const ALMALINUX_ISO_LABEL = "AlmaLinux-%s-%s-%s-dvd" - - if t.IsRHEL() { - osVer := strings.Split(t.Arch().Distro().OsVersion(), ".") - return fmt.Sprintf(RHEL_ISO_LABEL, osVer[0], osVer[1], t.Arch().Name()) - } else if t.IsAlmaLinux() { - osVer := strings.Split(t.Arch().Distro().OsVersion(), ".") - return fmt.Sprintf(ALMALINUX_ISO_LABEL, osVer[0], osVer[1], t.Arch().Name()) - } else { - return fmt.Sprintf(CS_ISO_LABEL, t.Arch().Distro().Releasever(), t.Arch().Name()) - } -} - -func defaultDistroImageConfig(d *rhel.Distribution) *distro.ImageConfig { - return common.Must(defs.DistroImageConfig(d.Name())) -} - -func newDistro(name string, major, minor int) *rhel.Distribution { - rd, err := rhel.NewDistribution(name, major, minor) - if err != nil { - panic(err) - } - rd.CheckOptions = checkOptions - rd.DefaultImageConfig = defaultDistroImageConfig - - // Architecture definitions - x86_64 := rhel.NewArchitecture(rd, arch.ARCH_X86_64) - aarch64 := rhel.NewArchitecture(rd, arch.ARCH_AARCH64) - ppc64le := rhel.NewArchitecture(rd, arch.ARCH_PPC64LE) - s390x := rhel.NewArchitecture(rd, arch.ARCH_S390X) - - x86_64.AddImageTypes( - &platform.X86{ - BIOS: true, - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_QCOW2, - QCOW2Compat: "1.1", - }, - }, - mkQcow2ImgType(rd, arch.ARCH_X86_64), - mkOCIImgType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{ - BIOS: true, - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_QCOW2, - }, - }, - mkOpenstackImgType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{ - BIOS: true, - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_VMDK, - }, - }, - mkVMDKImgType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{ - BIOS: true, - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_OVA, - }, - }, - mkOVAImgType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{}, - mkTarImgType(), - mkWSLImgType(rd, arch.ARCH_X86_64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_QCOW2, - }, - }, - mkOpenstackImgType(rd, arch.ARCH_AARCH64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{}, - mkTarImgType(), - mkWSLImgType(rd, arch.ARCH_AARCH64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_QCOW2, - QCOW2Compat: "1.1", - }, - }, - mkQcow2ImgType(rd, arch.ARCH_AARCH64), - ) - - ppc64le.AddImageTypes( - &platform.PPC64LE{ - BIOS: true, - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_QCOW2, - QCOW2Compat: "1.1", - }, - }, - mkQcow2ImgType(rd, arch.ARCH_PPC64LE), - ) - ppc64le.AddImageTypes( - &platform.PPC64LE{}, - mkTarImgType(), - ) - - s390x.AddImageTypes( - &platform.S390X{ - Zipl: true, - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_QCOW2, - QCOW2Compat: "1.1", - }, - }, - mkQcow2ImgType(rd, arch.ARCH_S390X), - ) - s390x.AddImageTypes( - &platform.S390X{}, - mkTarImgType(), - ) - - ec2X86Platform := &platform.X86{ - BIOS: true, - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_RAW, - }, - } - - // Keep the RHEL EC2 x86_64 images before 9.3 BIOS-only for backward compatibility. - // RHEL-internal EC2 images and RHEL AMI images are kept intentionally in sync - // with regard to not supporting hybrid boot mode before RHEL version 9.3. - // The partitioning table for these reflects that and is also intentionally in sync. - if rd.IsRHEL() && common.VersionLessThan(rd.OsVersion(), "9.3") { - ec2X86Platform.UEFIVendor = "" - } - - x86_64.AddImageTypes( - ec2X86Platform, - mkAMIImgTypeX86_64(rd, arch.ARCH_X86_64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_RAW, - }, - }, - mkAMIImgTypeAarch64(rd, arch.ARCH_AARCH64), - ) - - azureX64Platform := &platform.X86{ - BIOS: true, - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_VHD, - }, - } - - azureAarch64Platform := &platform.Aarch64{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_VHD, - }, - } - - x86_64.AddImageTypes(azureX64Platform, mkAzureImgType(rd, azureX64Platform.GetArch())) - aarch64.AddImageTypes(azureAarch64Platform, mkAzureImgType(rd, azureAarch64Platform.GetArch())) - - gceX86Platform := &platform.X86{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_GCE, - }, - } - x86_64.AddImageTypes( - gceX86Platform, - mkGCEImageType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{ - BasePlatform: platform.BasePlatform{ - FirmwarePackages: []string{ - "microcode_ctl", // ?? - "iwl1000-firmware", - "iwl100-firmware", - "iwl105-firmware", - "iwl135-firmware", - "iwl2000-firmware", - "iwl2030-firmware", - "iwl3160-firmware", - "iwl5000-firmware", - "iwl5150-firmware", - "iwl6050-firmware", - }, - }, - BIOS: true, - UEFIVendor: rd.Vendor(), - }, - mkEdgeOCIImgType(rd, arch.ARCH_X86_64), - mkEdgeCommitImgType(rd, arch.ARCH_X86_64), - mkEdgeInstallerImgType(rd, arch.ARCH_X86_64), - mkEdgeRawImgType(rd, arch.ARCH_X86_64), - mkImageInstallerImgType(rd, arch.ARCH_X86_64), - mkEdgeAMIImgType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{ - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_VMDK, - }, - BIOS: true, - UEFIVendor: rd.Vendor(), - }, - mkEdgeVsphereImgType(rd, arch.ARCH_X86_64), - ) - - x86_64.AddImageTypes( - &platform.X86{ - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_RAW, - }, - BIOS: false, - UEFIVendor: rd.Vendor(), - }, - mkEdgeSimplifiedInstallerImgType(rd, arch.ARCH_X86_64), - mkMinimalrawImgType(rd, arch.ARCH_X86_64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - BasePlatform: platform.BasePlatform{}, - UEFIVendor: rd.Vendor(), - }, - mkEdgeOCIImgType(rd, arch.ARCH_AARCH64), - mkEdgeCommitImgType(rd, arch.ARCH_AARCH64), - mkEdgeInstallerImgType(rd, arch.ARCH_AARCH64), - mkEdgeSimplifiedInstallerImgType(rd, arch.ARCH_AARCH64), - mkImageInstallerImgType(rd, arch.ARCH_AARCH64), - mkEdgeAMIImgType(rd, arch.ARCH_AARCH64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_VMDK, - }, - UEFIVendor: rd.Vendor(), - }, - mkEdgeVsphereImgType(rd, arch.ARCH_X86_64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_RAW, - }, - UEFIVendor: rd.Vendor(), - }, - mkEdgeRawImgType(rd, arch.ARCH_AARCH64), - mkMinimalrawImgType(rd, arch.ARCH_AARCH64), - ) - - if rd.IsRHEL() { // RHEL-only (non-CentOS) image types - x86_64.AddImageTypes(azureX64Platform, mkAzureInternalImgType(rd, azureX64Platform.GetArch())) - aarch64.AddImageTypes(azureAarch64Platform, mkAzureInternalImgType(rd, azureAarch64Platform.GetArch())) - - x86_64.AddImageTypes(azureX64Platform, mkAzureSapInternalImgType(rd, azureX64Platform.GetArch()), mkAzureSapAppsImgType(rd, azureX64Platform.GetArch())) - - // add ec2 image types to RHEL distro only - x86_64.AddImageTypes(ec2X86Platform, - mkEc2ImgTypeX86_64(rd, arch.ARCH_X86_64), - mkEc2HaImgTypeX86_64(rd, arch.ARCH_X86_64), - mkEC2SapImgTypeX86_64(rd, arch.ARCH_X86_64), - ) - - aarch64.AddImageTypes( - &platform.Aarch64{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_RAW, - }, - }, - mkEC2ImgTypeAarch64(rd, arch.ARCH_AARCH64), - ) - - // CVM is only available starting from 9.6 - if common.VersionGreaterThanOrEqual(rd.OsVersion(), "9.6") { - azureX64CVMPlatform := &platform.X86{ - UEFIVendor: rd.Vendor(), - BasePlatform: platform.BasePlatform{ - ImageFormat: platform.FORMAT_VHD, - }, - Bootloader: platform.BOOTLOADER_UKI, - } - x86_64.AddImageTypes( - azureX64CVMPlatform, - mkAzureCVMImgType(rd, arch.ARCH_X86_64), - ) - - } - } - - rd.AddArches(x86_64, aarch64, ppc64le, s390x) - return rd -} - -func ParseID(idStr string) (*distro.ID, error) { - id, err := distro.ParseID(idStr) - if err != nil { - return nil, err - } - - if id.Name != "rhel" && id.Name != "centos" && id.Name != "almalinux" { - return nil, fmt.Errorf("invalid distro name: %s", id.Name) - } - - // Backward compatibility layer for "rhel-93" or "rhel-910" - if id.Name == "rhel" && id.MinorVersion == -1 { - if id.MajorVersion/10 == 9 { - // handle single digit minor version - id.MinorVersion = id.MajorVersion % 10 - id.MajorVersion = 9 - } else if id.MajorVersion/100 == 9 { - // handle two digit minor version - id.MinorVersion = id.MajorVersion % 100 - id.MajorVersion = 9 - } - } - - if id.MajorVersion != 9 { - return nil, fmt.Errorf("invalid distro major version: %d", id.MajorVersion) - } - - // CentOS does not use minor version - if id.Name == "centos" && id.MinorVersion != -1 { - return nil, fmt.Errorf("centos does not use minor version, but got: %d", id.MinorVersion) - } - - // RHEL uses minor version - if id.Name == "rhel" && id.MinorVersion == -1 { - return nil, fmt.Errorf("rhel requires minor version, but got: %d", id.MinorVersion) - } - - // So does AlmaLinux - if id.Name == "almalinux" && id.MinorVersion == -1 { - return nil, fmt.Errorf("almalinux requires minor version, but got: %d", id.MinorVersion) - } - - return id, nil -} - -func DistroFactory(idStr string) distro.Distro { - id, err := ParseID(idStr) - if err != nil { - return nil - } - - return newDistro(id.Name, 9, id.MinorVersion) -} diff --git a/pkg/distro/rhel/rhel9/edge.go b/pkg/distro/rhel/rhel9/edge.go deleted file mode 100644 index aa92f72f24..0000000000 --- a/pkg/distro/rhel/rhel9/edge.go +++ /dev/null @@ -1,212 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/internal/environment" - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/disk" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkEdgeCommitImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-commit", - "commit.tar", - "application/x-tar", - packageSetLoader, - rhel.EdgeCommitImage, - []string{"build"}, - []string{"os", "ostree-commit", "commit-archive"}, - []string{"commit-archive"}, - ) - - it.NameAliases = []string{"rhel-edge-commit"} - it.RPMOSTree = true - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-commit") - - return it -} - -func mkEdgeOCIImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-container", - "container.tar", - "application/x-tar", - packageSetLoader, - rhel.EdgeContainerImage, - []string{"build"}, - []string{"os", "ostree-commit", "container-tree", "container"}, - []string{"container"}, - ) - - it.NameAliases = []string{"rhel-edge-container"} - it.RPMOSTree = true - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-container") - - return it -} - -func mkEdgeRawImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-raw-image", - "image.raw.xz", - "application/xz", - nil, - rhel.EdgeRawImage, - []string{"build"}, - []string{"ostree-deployment", "image", "xz"}, - []string{"xz"}, - ) - - it.NameAliases = []string{"rhel-edge-raw-image"} - it.Compression = "xz" - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-raw-image") - - it.DefaultSize = 10 * datasizes.GibiByte - it.RPMOSTree = true - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - it.UnsupportedPartitioningModes = []disk.PartitioningMode{disk.RawPartitioningMode} - - return it -} - -func mkEdgeInstallerImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-installer", - "installer.iso", - "application/x-iso9660-image", - packageSetLoader, - rhel.EdgeInstallerImage, - []string{"build"}, - []string{"anaconda-tree", "rootfs-image", "efiboot-tree", "bootiso-tree", "bootiso"}, - []string{"bootiso"}, - ) - - it.NameAliases = []string{"rhel-edge-installer"} - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-installer") - it.DefaultInstallerConfig = &distro.InstallerConfig{ - AdditionalDracutModules: []string{ - "nvdimm", // non-volatile DIMM firmware (provides nfit, cuse, and nd_e820) - "ifcfg", - }, - AdditionalDrivers: []string{ - "cuse", - "ipmi_devintf", - "ipmi_msghandler", - }, - } - it.RPMOSTree = true - it.BootISO = true - it.ISOLabelFn = distroISOLabelFunc - - return it -} - -func mkEdgeSimplifiedInstallerImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-simplified-installer", - "simplified-installer.iso", - "application/x-iso9660-image", - // TODO: non-arch-specific package set handling for installers - // This image type requires build packages for installers and - // ostree/edge. For now we only have x86-64 installer build - // package sets defined. When we add installer build package sets - // for other architectures, this will need to be moved to the - // architecture and the merging will happen in the PackageSets() - // method like the other sets. - packageSetLoader, - rhel.EdgeSimplifiedInstallerImage, - []string{"build"}, - []string{"ostree-deployment", "image", "xz", "coi-tree", "efiboot-tree", "bootiso-tree", "bootiso"}, - []string{"bootiso"}, - ) - - it.NameAliases = []string{"rhel-edge-simplified-installer"} - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-simplified-installer") - - it.DefaultInstallerConfig = &distro.InstallerConfig{ - AdditionalDracutModules: []string{ - "prefixdevname", - "prefixdevname-tools", - }, - } - - it.DefaultSize = 10 * datasizes.GibiByte - it.RPMOSTree = true - it.BootISO = true - it.Bootable = true - it.ISOLabelFn = distroISOLabelFunc - it.BasePartitionTables = defaultBasePartitionTables - it.UnsupportedPartitioningModes = []disk.PartitioningMode{disk.RawPartitioningMode} - - return it -} - -func mkEdgeAMIImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-ami", - "image.raw", - "application/octet-stream", - nil, - rhel.EdgeRawImage, - []string{"build"}, - []string{"ostree-deployment", "image"}, - []string{"image"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-ami") - - it.DefaultSize = 10 * datasizes.GibiByte - it.RPMOSTree = true - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - it.UnsupportedPartitioningModes = []disk.PartitioningMode{disk.RawPartitioningMode} - it.Environment = &environment.EC2{} - - return it -} - -func mkEdgeVsphereImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "edge-vsphere", - "image.vmdk", - "application/x-vmdk", - nil, - rhel.EdgeRawImage, - []string{"build"}, - []string{"ostree-deployment", "image", "vmdk"}, - []string{"vmdk"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "edge-vsphere") - it.DefaultSize = 10 * datasizes.GibiByte - it.RPMOSTree = true - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - it.UnsupportedPartitioningModes = []disk.PartitioningMode{disk.RawPartitioningMode} - - return it -} - -func mkMinimalrawImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "minimal-raw", - "disk.raw.xz", - "application/xz", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.DefaultImageConfig = imageConfig(d, a.String(), "minimal-raw") - it.DefaultSize = 2 * datasizes.GibiByte - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - - return it -} diff --git a/pkg/distro/rhel/rhel9/gce.go b/pkg/distro/rhel/rhel9/gce.go deleted file mode 100644 index 971e43bd10..0000000000 --- a/pkg/distro/rhel/rhel9/gce.go +++ /dev/null @@ -1,31 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkGCEImageType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "gce", - "image.tar.gz", - "application/gzip", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "archive"}, - []string{"archive"}, - ) - - it.NameAliases = []string{"gce-rhui"} - // The configuration for non-RHUI images does not touch the RHSM configuration at all. - // https://issues.redhat.com/browse/COMPOSER-2157 - it.DefaultImageConfig = imageConfig(rd, a.String(), "gce") - it.DefaultSize = 20 * datasizes.GibiByte - it.Bootable = true - // TODO: the base partition table still contains the BIOS boot partition, but the image is UEFI-only - it.BasePartitionTables = defaultBasePartitionTables - - return it -} diff --git a/pkg/distro/rhel/rhel9/options.go b/pkg/distro/rhel/rhel9/options.go deleted file mode 100644 index 3935f87d44..0000000000 --- a/pkg/distro/rhel/rhel9/options.go +++ /dev/null @@ -1,222 +0,0 @@ -package rhel9 - -import ( - "fmt" - "strings" - - "slices" - - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/blueprint" - "github.com/osbuild/images/pkg/customizations/oscap" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/rhel" - "github.com/osbuild/images/pkg/policies" -) - -// checkOptions checks the validity and compatibility of options and customizations for the image type. -// Returns ([]string, error) where []string, if non-nil, will hold any generated warnings (e.g. deprecation notices). -func checkOptions(t *rhel.ImageType, bp *blueprint.Blueprint, options distro.ImageOptions) ([]string, error) { - - customizations := bp.Customizations - - // holds warnings (e.g. deprecation notices) - var warnings []string - - // we do not support embedding containers on ostree-derived images, only on commits themselves - if len(bp.Containers) > 0 && t.RPMOSTree && (t.Name() != "edge-commit" && t.Name() != "edge-container") { - return warnings, fmt.Errorf("embedding containers is not supported for %s on %s", t.Name(), t.Arch().Distro().Name()) - } - - if options.OSTree != nil { - if err := options.OSTree.Validate(); err != nil { - return warnings, err - } - } - - if t.BootISO && t.RPMOSTree { - // ostree-based ISOs require a URL from which to pull a payload commit - if options.OSTree == nil || options.OSTree.URL == "" { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.Name()) - } - - if t.Name() == "edge-simplified-installer" { - allowed := []string{"InstallationDevice", "FDO", "Ignition", "Kernel", "User", "Group", "FIPS", "Filesystem"} - if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) - } - if customizations.GetInstallationDevice() == "" { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying an installation device to install to", t.Name()) - } - - // FDO is optional, but when specified has some restrictions - if customizations.GetFDO() != nil { - if customizations.GetFDO().ManufacturingServerURL == "" { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying FDO.ManufacturingServerURL configuration to install to when using FDO", t.Name()) - } - var diunSet int - if customizations.GetFDO().DiunPubKeyHash != "" { - diunSet++ - } - if customizations.GetFDO().DiunPubKeyInsecure != "" { - diunSet++ - } - if customizations.GetFDO().DiunPubKeyRootCerts != "" { - diunSet++ - } - if diunSet != 1 { - return warnings, fmt.Errorf("boot ISO image type %q requires specifying one of [FDO.DiunPubKeyHash,FDO.DiunPubKeyInsecure,FDO.DiunPubKeyRootCerts] configuration to install to when using FDO", t.Name()) - } - } - - // ignition is optional, we might be using FDO - if customizations.GetIgnition() != nil { - if customizations.GetIgnition().Embedded != nil && customizations.GetIgnition().FirstBoot != nil { - return warnings, fmt.Errorf("both ignition embedded and firstboot configurations found") - } - if customizations.GetIgnition().FirstBoot != nil && customizations.GetIgnition().FirstBoot.ProvisioningURL == "" { - return warnings, fmt.Errorf("ignition.firstboot requires a provisioning url") - } - } - } else if t.Name() == "edge-installer" { - allowed := []string{"User", "Group", "FIPS", "Installer", "Timezone", "Locale"} - if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) - } - } - } - - if t.Name() == "edge-raw-image" || t.Name() == "edge-ami" || t.Name() == "edge-vsphere" { - // ostree-based bootable images require a URL from which to pull a payload commit - if options.OSTree == nil || options.OSTree.URL == "" { - return warnings, fmt.Errorf("%q images require specifying a URL from which to retrieve the OSTree commit", t.Name()) - } - - allowed := []string{"Ignition", "Kernel", "User", "Group", "FIPS", "Filesystem"} - if err := customizations.CheckAllowed(allowed...); err != nil { - return warnings, fmt.Errorf(distro.UnsupportedCustomizationError, t.Name(), strings.Join(allowed, ", ")) - } - // TODO: consider additional checks, such as those in "edge-simplified-installer" - } - - if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.RPMOSTree && t.Name() != "edge-raw-image" && t.Name() != "edge-simplified-installer" { - return warnings, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types") - } - - if slices.Contains(t.UnsupportedPartitioningModes, options.PartitioningMode) { - return warnings, fmt.Errorf("partitioning mode %q is not supported for %q", options.PartitioningMode, t.Name()) - } - - mountpoints := customizations.GetFilesystems() - partitioning, err := customizations.GetPartitioning() - if err != nil { - return nil, err - } - if (mountpoints != nil || partitioning != nil) && t.RPMOSTree && (t.Name() == "edge-container" || t.Name() == "edge-commit") { - return warnings, fmt.Errorf("custom mountpoints and partitioning are not supported for ostree types") - } else if (mountpoints != nil || partitioning != nil) && t.RPMOSTree && !(t.Name() == "edge-container" || t.Name() == "edge-commit") { - //customization allowed for edge-raw-image,edge-ami,edge-vsphere,edge-simplified-installer - err := blueprint.CheckMountpointsPolicy(mountpoints, policies.OstreeMountpointPolicies) - if err != nil { - return warnings, err - } - } - - if len(mountpoints) > 0 && partitioning != nil { - return nil, fmt.Errorf("partitioning customizations cannot be used with custom filesystems (mountpoints)") - } - - if err := blueprint.CheckMountpointsPolicy(mountpoints, policies.MountpointPolicies); err != nil { - return warnings, err - } - - if err := blueprint.CheckDiskMountpointsPolicy(partitioning, policies.MountpointPolicies); err != nil { - return warnings, err - } - - if err := partitioning.ValidateLayoutConstraints(); err != nil { - return warnings, err - } - - if osc := customizations.GetOpenSCAP(); osc != nil { - if t.Arch().Distro().OsVersion() == "9.0" { - return warnings, fmt.Errorf("OpenSCAP unsupported os version: %s", t.Arch().Distro().OsVersion()) - } - if !oscap.IsProfileAllowed(osc.ProfileID, oscapProfileAllowList) { - return warnings, fmt.Errorf("OpenSCAP unsupported profile: %s", osc.ProfileID) - } - if t.RPMOSTree { - return warnings, fmt.Errorf("OpenSCAP customizations are not supported for ostree types") - } - if osc.ProfileID == "" { - return warnings, fmt.Errorf("OpenSCAP profile cannot be empty") - } - } - - // Check Directory/File Customizations are valid - dc := customizations.GetDirectories() - fc := customizations.GetFiles() - - err = blueprint.ValidateDirFileCustomizations(dc, fc) - if err != nil { - return warnings, err - } - - dcp := policies.CustomDirectoriesPolicies - fcp := policies.CustomFilesPolicies - - if t.RPMOSTree { - dcp = policies.OstreeCustomDirectoriesPolicies - fcp = policies.OstreeCustomFilesPolicies - } - - err = blueprint.CheckDirectoryCustomizationsPolicy(dc, dcp) - if err != nil { - return warnings, err - } - - err = blueprint.CheckFileCustomizationsPolicy(fc, fcp) - if err != nil { - return warnings, err - } - - // check if repository customizations are valid - _, err = customizations.GetRepositories() - if err != nil { - return warnings, err - } - - if customizations.GetFIPS() && !common.IsBuildHostFIPSEnabled() { - warnings = append(warnings, fmt.Sprintln(common.FIPSEnabledImageWarning)) - } - - instCust, err := customizations.GetInstaller() - if err != nil { - return warnings, err - } - if instCust != nil { - // only supported by the Anaconda installer - if slices.Index([]string{"image-installer", "edge-installer", "live-installer"}, t.Name()) == -1 { - return warnings, fmt.Errorf("installer customizations are not supported for %q", t.Name()) - } - - if t.Name() == "edge-installer" && - instCust.Kickstart != nil && - len(instCust.Kickstart.Contents) > 0 && - (customizations.GetUsers() != nil || customizations.GetGroups() != nil) { - return warnings, fmt.Errorf("edge-installer installer.kickstart.contents are not supported in combination with users or groups") - } - } - - // don't support setting any kernel customizations for image types with - // UKIs - // NOTE: this is very ugly and stupid, it should not be based on the image - // type name, but we want to redo this whole function anyway - // NOTE: we can't use customizations.GetKernel() because it returns - // 'Name: "kernel"' when unset. - if t.Name() == "azure-cvm" && customizations != nil && customizations.Kernel != nil { - return warnings, fmt.Errorf("kernel customizations are not supported for %q", t.Name()) - } - - return warnings, nil -} diff --git a/pkg/distro/rhel/rhel9/package_sets.go b/pkg/distro/rhel/rhel9/package_sets.go deleted file mode 100644 index 00a3730a54..0000000000 --- a/pkg/distro/rhel/rhel9/package_sets.go +++ /dev/null @@ -1,17 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/internal/common" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/defs" - "github.com/osbuild/images/pkg/distro/rhel" - "github.com/osbuild/images/pkg/rpmmd" -) - -func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) { - return defs.PackageSets(t) -} - -func imageConfig(d *rhel.Distribution, archName, imageType string) *distro.ImageConfig { - return common.Must(defs.ImageConfig(d.Name(), archName, imageType)) -} diff --git a/pkg/distro/rhel/rhel9/partition_tables.go b/pkg/distro/rhel/rhel9/partition_tables.go deleted file mode 100644 index 299ffe3761..0000000000 --- a/pkg/distro/rhel/rhel9/partition_tables.go +++ /dev/null @@ -1,19 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/disk" - "github.com/osbuild/images/pkg/distro/defs" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func defaultBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) { - partitionTable, err := defs.PartitionTable(t) - if err != nil { - // XXX: have a check to differenciate ErrNoEnt and else - return disk.PartitionTable{}, false - } - if partitionTable == nil { - return disk.PartitionTable{}, false - } - return *partitionTable, true -} diff --git a/pkg/distro/rhel/rhel9/qcow2.go b/pkg/distro/rhel/rhel9/qcow2.go deleted file mode 100644 index b0f4d11f19..0000000000 --- a/pkg/distro/rhel/rhel9/qcow2.go +++ /dev/null @@ -1,67 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkQcow2ImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "qcow2", - "disk.qcow2", - "application/x-qemu-disk", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "qcow2"}, - []string{"qcow2"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "qcow2") - it.DefaultSize = 10 * datasizes.GibiByte - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkOCIImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "oci", - "disk.qcow2", - "application/x-qemu-disk", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "qcow2"}, - []string{"qcow2"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "oci") - it.DefaultSize = 10 * datasizes.GibiByte - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkOpenstackImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "openstack", - "disk.qcow2", - "application/x-qemu-disk", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "qcow2"}, - []string{"qcow2"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "openstack") - it.DefaultSize = 4 * datasizes.GibiByte - it.Bootable = true - it.BasePartitionTables = defaultBasePartitionTables - - return it -} diff --git a/pkg/distro/rhel/rhel9/vmdk.go b/pkg/distro/rhel/rhel9/vmdk.go deleted file mode 100644 index b4fe219aeb..0000000000 --- a/pkg/distro/rhel/rhel9/vmdk.go +++ /dev/null @@ -1,47 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/datasizes" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkVMDKImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "vmdk", - "disk.vmdk", - "application/x-vmdk", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vmdk"}, - []string{"vmdk"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "vmdk") - it.Bootable = true - it.DefaultSize = 4 * datasizes.GibiByte - it.BasePartitionTables = defaultBasePartitionTables - - return it -} - -func mkOVAImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "ova", - "image.ova", - "application/ovf", - packageSetLoader, - rhel.DiskImage, - []string{"build"}, - []string{"os", "image", "vmdk", "ovf", "archive"}, - []string{"archive"}, - ) - - it.DefaultImageConfig = imageConfig(d, a.String(), "ova") - it.Bootable = true - it.DefaultSize = 4 * datasizes.GibiByte - it.BasePartitionTables = defaultBasePartitionTables - - return it -} diff --git a/pkg/distro/rhel/rhel9/wsl.go b/pkg/distro/rhel/rhel9/wsl.go deleted file mode 100644 index 9819475d65..0000000000 --- a/pkg/distro/rhel/rhel9/wsl.go +++ /dev/null @@ -1,24 +0,0 @@ -package rhel9 - -import ( - "github.com/osbuild/images/pkg/arch" - "github.com/osbuild/images/pkg/distro/rhel" -) - -func mkWSLImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType { - it := rhel.NewImageType( - "wsl", - "image.wsl", - "application/x-tar", - packageSetLoader, - rhel.TarImage, - []string{"build"}, - []string{"os", "archive", "xz"}, - []string{"xz"}, - ) - - it.Compression = "xz" - it.DefaultImageConfig = imageConfig(d, a.String(), "wsl") - - return it -} diff --git a/pkg/distro/rhel/temp-disk-dataloss-warning.sh b/pkg/distro/rhel/temp-disk-dataloss-warning.sh deleted file mode 100644 index a1482861bf..0000000000 --- a/pkg/distro/rhel/temp-disk-dataloss-warning.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# /usr/local/sbin/temp-disk-dataloss-warning -# Write dataloss warning file on mounted Azure resource disk - -AZURE_RESOURCE_DISK_PART1="/dev/disk/cloud/azure_resource-part1" - -MOUNTPATH=$(grep "$AZURE_RESOURCE_DISK_PART1" /etc/fstab | tr '\t' ' ' | cut -d' ' -f2) -if [ -z "$MOUNTPATH" ]; then - echo "There is no mountpoint of $AZURE_RESOURCE_DISK_PART1 in /etc/fstab" - exit 0 -fi - -if [ "$MOUNTPATH" = "none" ]; then - echo "Mountpoint of $AZURE_RESOURCE_DISK_PART1 is not a path" - exit 1 -fi - -if ! mountpoint -q "$MOUNTPATH"; then - echo "$AZURE_RESOURCE_DISK_PART1 is not mounted at $MOUNTPATH" - exit 1 -fi - -echo "Creating a dataloss warning file at ${MOUNTPATH}/DATALOSS_WARNING_README.txt" - -cat <<'EOF' > "${MOUNTPATH}/DATALOSS_WARNING_README.txt" -WARNING: THIS IS A TEMPORARY DISK. - -Any data stored on this drive is SUBJECT TO LOSS and THERE IS NO WAY TO RECOVER IT. - -Please do not use this disk for storing any personal or application data. - -EOF diff --git a/pkg/distrofactory/distrofactory.go b/pkg/distrofactory/distrofactory.go index dd8f768a42..693989b5fb 100644 --- a/pkg/distrofactory/distrofactory.go +++ b/pkg/distrofactory/distrofactory.go @@ -6,7 +6,6 @@ import ( "github.com/osbuild/images/pkg/distro" "github.com/osbuild/images/pkg/distro/generic" - "github.com/osbuild/images/pkg/distro/rhel/rhel9" "github.com/osbuild/images/pkg/distro/test_distro" ) @@ -107,7 +106,6 @@ func New(factories ...FactoryFunc) *Factory { func NewDefault() *Factory { return New( generic.DistroFactory, - rhel9.DistroFactory, ) } diff --git a/pkg/distroidparser/idparser.go b/pkg/distroidparser/idparser.go index 8b63309877..388c9859c5 100644 --- a/pkg/distroidparser/idparser.go +++ b/pkg/distroidparser/idparser.go @@ -3,7 +3,6 @@ package distroidparser import ( "github.com/osbuild/images/pkg/distro" "github.com/osbuild/images/pkg/distro/defs" - "github.com/osbuild/images/pkg/distro/rhel/rhel9" ) var DefaultParser = NewDefaultParser() @@ -61,6 +60,5 @@ func (p *Parser) Standardize(idStr string) (string, error) { func NewDefaultParser() *Parser { return New( defs.ParseID, - rhel9.ParseID, ) } diff --git a/pkg/distroidparser/idparser_test.go b/pkg/distroidparser/idparser_test.go index f75a59782e..0f7082c1cd 100644 --- a/pkg/distroidparser/idparser_test.go +++ b/pkg/distroidparser/idparser_test.go @@ -3,9 +3,10 @@ package distroidparser import ( "testing" - "github.com/osbuild/images/pkg/distro" - "github.com/osbuild/images/pkg/distro/rhel/rhel9" "github.com/stretchr/testify/require" + + "github.com/osbuild/images/pkg/distro" + "github.com/osbuild/images/pkg/distro/defs" ) func TestDefaltParser(t *testing.T) { @@ -193,9 +194,9 @@ func TestDefaltParser(t *testing.T) { } func TestParserDoubleMatch(t *testing.T) { - Parser := New(rhel9.ParseID, rhel9.ParseID) + Parser := New(defs.ParseID, defs.ParseID) require.Panics(t, func() { - _, _ = Parser.Parse("rhel-9.0") + _, _ = Parser.Parse("rhel-90") }, "Parser should panic when rhel-9.0 is matched by multiple parsers") }