distro/rhel-8: merge all the RHEL-8 minor releases into one

As it turns out, the default expectation is not to distinguish between
these. We will now produce whatever is the most recent minor release by
default, and image tests will still be pinned at a given snapshot to be
reproducible.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2020-05-20 17:26:26 +02:00
parent 1e29ab291e
commit cc231e0ed1
30 changed files with 63835 additions and 66140 deletions

View file

@ -144,7 +144,9 @@ func GetHostDistroName() (string, error) {
return "", err
}
name := osrelease["ID"] + "-" + osrelease["VERSION_ID"]
// NOTE: We only consider major releases
version := strings.Split(osrelease["VERSION_ID"], ".")
name := osrelease["ID"] + "-" + version[0]
return name, nil
}

View file

@ -10,9 +10,7 @@ import (
"github.com/osbuild/osbuild-composer/internal/distro/fedora30"
"github.com/osbuild/osbuild-composer/internal/distro/fedora31"
"github.com/osbuild/osbuild-composer/internal/distro/fedora32"
"github.com/osbuild/osbuild-composer/internal/distro/rhel81"
"github.com/osbuild/osbuild-composer/internal/distro/rhel82"
"github.com/osbuild/osbuild-composer/internal/distro/rhel83"
"github.com/osbuild/osbuild-composer/internal/distro/rhel8"
)
func TestDistro_Manifest(t *testing.T) {
@ -20,7 +18,7 @@ func TestDistro_Manifest(t *testing.T) {
t,
"../../test/cases/",
"*",
fedora30.New(), fedora31.New(), fedora32.New(), rhel81.New(), rhel82.New(), rhel83.New(),
fedora30.New(), fedora31.New(), fedora32.New(), rhel8.New(),
)
}
@ -30,12 +28,10 @@ func TestDistro_RegistryList(t *testing.T) {
"fedora-30",
"fedora-31",
"fedora-32",
"rhel-8.1",
"rhel-8.2",
"rhel-8.3",
"rhel-8",
}
distros, err := distro.NewRegistry(fedora30.New(), fedora31.New(), fedora32.New(), rhel81.New(), rhel82.New(), rhel83.New())
distros, err := distro.NewRegistry(fedora30.New(), fedora31.New(), fedora32.New(), rhel8.New())
require.NoError(t, err)
require.Equalf(t, expected, distros.List(), "unexpected list of distros")

View file

@ -1,4 +1,4 @@
package rhel82
package rhel8
import (
"errors"
@ -15,17 +15,16 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
const name = "rhel-8.2"
const name = "rhel-8"
const modulePlatformID = "platform:el8"
type RHEL82 struct {
type RHEL8 struct {
arches map[string]arch
imageTypes map[string]imageType
buildPackages []string
}
type arch struct {
name string
bootloaderPackages []string
buildPackages []string
uefi bool
@ -45,27 +44,27 @@ type imageType struct {
assembler func(uefi bool, size uint64) *osbuild.Assembler
}
type rhel82Arch struct {
type rhel8Arch struct {
name string
distro *RHEL82
distro *RHEL8
arch *arch
}
type rhel82ImageType struct {
type rhel8ImageType struct {
name string
arch *rhel82Arch
arch *rhel8Arch
imageType *imageType
}
func (a *rhel82Arch) Distro() distro.Distro {
func (a *rhel8Arch) Distro() distro.Distro {
return a.distro
}
func (t *rhel82ImageType) Arch() distro.Arch {
func (t *rhel8ImageType) Arch() distro.Arch {
return t.arch
}
func (d *RHEL82) ListArches() []string {
func (d *RHEL8) ListArches() []string {
archs := make([]string, 0, len(d.arches))
for name := range d.arches {
archs = append(archs, name)
@ -74,24 +73,24 @@ func (d *RHEL82) ListArches() []string {
return archs
}
func (d *RHEL82) GetArch(arch string) (distro.Arch, error) {
func (d *RHEL8) GetArch(arch string) (distro.Arch, error) {
a, exists := d.arches[arch]
if !exists {
return nil, errors.New("invalid architecture: " + arch)
}
return &rhel82Arch{
return &rhel8Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *rhel82Arch) Name() string {
func (a *rhel8Arch) Name() string {
return a.name
}
func (a *rhel82Arch) ListImageTypes() []string {
func (a *rhel8Arch) ListImageTypes() []string {
formats := make([]string, 0, len(a.distro.imageTypes))
for name := range a.distro.imageTypes {
formats = append(formats, name)
@ -100,32 +99,32 @@ func (a *rhel82Arch) ListImageTypes() []string {
return formats
}
func (a *rhel82Arch) GetImageType(imageType string) (distro.ImageType, error) {
func (a *rhel8Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &rhel82ImageType{
return &rhel8ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *rhel82ImageType) Name() string {
func (t *rhel8ImageType) Name() string {
return t.name
}
func (t *rhel82ImageType) Filename() string {
func (t *rhel8ImageType) Filename() string {
return t.imageType.name
}
func (t *rhel82ImageType) MIMEType() string {
func (t *rhel8ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *rhel82ImageType) Size(size uint64) uint64 {
func (t *rhel8ImageType) Size(size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if t.name == "vhd" && size%MegaByte != 0 {
@ -137,7 +136,7 @@ func (t *rhel82ImageType) Size(size uint64) uint64 {
return size
}
func (t *rhel82ImageType) BasePackages() ([]string, []string) {
func (t *rhel8ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
@ -146,11 +145,11 @@ func (t *rhel82ImageType) BasePackages() ([]string, []string) {
return packages, t.imageType.excludedPackages
}
func (t *rhel82ImageType) BuildPackages() []string {
func (t *rhel8ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *rhel82ImageType) Manifest(c *blueprint.Customizations,
func (t *rhel8ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
@ -166,10 +165,10 @@ func (t *rhel82ImageType) Manifest(c *blueprint.Customizations,
}, nil
}
func New() *RHEL82 {
func New() *RHEL8 {
const GigaByte = 1024 * 1024 * 1024
r := RHEL82{
r := RHEL8{
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
@ -185,8 +184,7 @@ func New() *RHEL82 {
"xz",
},
arches: map[string]arch{
"x86_64": arch{
name: "x86_64",
"x86_64": {
bootloaderPackages: []string{
"dracut-config-generic",
"grub2-pc",
@ -195,8 +193,7 @@ func New() *RHEL82 {
"grub2-pc",
},
},
"aarch64": arch{
name: "aarch64",
"aarch64": {
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
@ -536,15 +533,15 @@ func New() *RHEL82 {
return &r
}
func (r *RHEL82) Name() string {
func (r *RHEL8) Name() string {
return name
}
func (r *RHEL82) ModulePlatformID() string {
func (r *RHEL8) ModulePlatformID() string {
return modulePlatformID
}
func (r *RHEL82) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
func (r *RHEL8) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.imageTypes[outputFormat]
if !exists {
return nil, nil, errors.New("invalid output format: " + outputFormat)
@ -563,7 +560,7 @@ func (r *RHEL82) BasePackages(outputFormat string, outputArchitecture string) ([
return packages, output.excludedPackages, nil
}
func (r *RHEL82) BuildPackages(outputArchitecture string) ([]string, error) {
func (r *RHEL8) BuildPackages(outputArchitecture string) ([]string, error) {
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
@ -584,7 +581,7 @@ func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
}
}
func (t *rhel82ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
func (t *rhel8ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.rhel82")
@ -656,13 +653,13 @@ func (t *rhel82ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.Re
return p, nil
}
func (r *rhel82ImageType) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
func (r *rhel8ImageType) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
p := &osbuild.Pipeline{}
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, buildPackageSpecs)))
return p
}
func (r *rhel82ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
func (r *rhel8ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
@ -681,7 +678,7 @@ func (r *rhel82ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, s
Packages: packages,
}
}
func (r *rhel82ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
func (r *rhel8ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
@ -721,7 +718,7 @@ func (r *rhel82ImageType) userStageOptions(users []blueprint.UserCustomization)
return &options, nil
}
func (r *rhel82ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
func (r *rhel8ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
@ -741,7 +738,7 @@ func (r *rhel82ImageType) groupStageOptions(groups []blueprint.GroupCustomizatio
return &options
}
func (r *rhel82ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
func (r *rhel8ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
@ -754,7 +751,7 @@ func (r *rhel82ImageType) firewallStageOptions(firewall *blueprint.FirewallCusto
return &options
}
func (r *rhel82ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
func (r *rhel8ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
@ -766,7 +763,7 @@ func (r *rhel82ImageType) systemdStageOptions(enabledServices, disabledServices
}
}
func (r *rhel82ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
func (r *rhel8ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("0bd700f8-090f-4556-b797-b340297ea1bd", "xfs", "/", "defaults", 0, 0)
if uefi {
@ -775,7 +772,7 @@ func (r *rhel82ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOption
return &options
}
func (r *rhel82ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
func (r *rhel8ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
var uefiOptions *osbuild.GRUB2UEFI
@ -793,13 +790,13 @@ func (r *rhel82ImageType) grub2StageOptions(kernelOptions string, uefi bool) *os
}
}
func (r *rhel82ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
func (r *rhel8ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}
}
func (r *RHEL82) qemuAssembler(format string, filename string, uefi bool, size uint64) *osbuild.Assembler {
func (r *RHEL8) qemuAssembler(format string, filename string, uefi bool, size uint64) *osbuild.Assembler {
var options osbuild.QEMUAssemblerOptions
if uefi {
fstype := uuid.MustParse("C12A7328-F81F-11D2-BA4B-00A0C93EC93B")
@ -854,7 +851,7 @@ func (r *RHEL82) qemuAssembler(format string, filename string, uefi bool, size u
return osbuild.NewQEMUAssembler(&options)
}
func (r *RHEL82) tarAssembler(filename, compression string) *osbuild.Assembler {
func (r *RHEL8) tarAssembler(filename, compression string) *osbuild.Assembler {
return osbuild.NewTarAssembler(
&osbuild.TarAssemblerOptions{
Filename: filename,
@ -862,7 +859,7 @@ func (r *RHEL82) tarAssembler(filename, compression string) *osbuild.Assembler {
})
}
func (r *RHEL82) rawFSAssembler(filename string, size uint64) *osbuild.Assembler {
func (r *RHEL8) rawFSAssembler(filename string, size uint64) *osbuild.Assembler {
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
return osbuild.NewRawFSAssembler(
&osbuild.RawFSAssemblerOptions{

View file

@ -1,10 +1,10 @@
package rhel82_test
package rhel8_test
import (
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/distro_test_common"
"github.com/osbuild/osbuild-composer/internal/distro/rhel82"
"github.com/osbuild/osbuild-composer/internal/distro/rhel8"
"github.com/stretchr/testify/assert"
)
@ -75,7 +75,7 @@ func TestFilenameFromType(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dist := rhel82.New()
dist := rhel8.New()
arch, _ := dist.GetArch("x86_64")
imgType, err := arch.GetImageType(tt.args.outputFormat)
if (err != nil) != tt.wantErr {
@ -122,7 +122,7 @@ func TestImageType_BuildPackages(t *testing.T) {
"x86_64": x8664BuildPackages,
"aarch64": aarch64BuildPackages,
}
d := rhel82.New()
d := rhel8.New()
for _, archLabel := range d.ListArches() {
archStruct, err := d.GetArch(archLabel)
if assert.NoErrorf(t, err, "d.GetArch(%v) returned err = %v; expected nil", archLabel, err) {
@ -139,7 +139,7 @@ func TestImageType_BuildPackages(t *testing.T) {
}
func TestImageType_Name(t *testing.T) {
distro := rhel82.New()
distro := rhel8.New()
imgMap := []struct {
arch string
imgNames []string
@ -211,7 +211,7 @@ func TestImageType_Size(t *testing.T) {
},
}
distro := rhel82.New()
distro := rhel8.New()
arch, err := distro.GetArch("x86_64")
if assert.NoError(t, err) {
for _, mapping := range sizeMap {
@ -345,7 +345,7 @@ func TestImageType_BasePackages(t *testing.T) {
bootable: true,
},
}
distro := rhel82.New()
distro := rhel8.New()
arch, err := distro.GetArch("x86_64")
assert.NoError(t, err)
@ -365,17 +365,17 @@ func TestImageType_BasePackages(t *testing.T) {
}
func TestDistro_Manifest(t *testing.T) {
distro_test_common.TestDistro_Manifest(t, "../../../test/cases/", "rhel_8.2*", rhel82.New())
distro_test_common.TestDistro_Manifest(t, "../../../test/cases/", "rhel_8*", rhel8.New())
}
func TestRhel82_ListArches(t *testing.T) {
distro := rhel82.New()
func TestRhel8_ListArches(t *testing.T) {
distro := rhel8.New()
arches := distro.ListArches()
assert.Equal(t, []string{"aarch64", "x86_64"}, arches)
}
func TestRhel82_GetArch(t *testing.T) {
distro := rhel82.New()
func TestRhel8_GetArch(t *testing.T) {
distro := rhel8.New()
arches := []struct {
name string
errorExpected bool
@ -404,12 +404,12 @@ func TestRhel82_GetArch(t *testing.T) {
}
}
func TestRhel82_Name(t *testing.T) {
distro := rhel82.New()
assert.Equal(t, "rhel-8.2", distro.Name())
func TestRhel8_Name(t *testing.T) {
distro := rhel8.New()
assert.Equal(t, "rhel-8", distro.Name())
}
func TestRhel82_ModulePlatformID(t *testing.T) {
distro := rhel82.New()
func TestRhel8_ModulePlatformID(t *testing.T) {
distro := rhel8.New()
assert.Equal(t, "platform:el8", distro.ModulePlatformID())
}

View file

@ -1,847 +0,0 @@
package rhel81
import (
"errors"
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/crypt"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
const name = "rhel-8.1"
const modulePlatformID = "platform:el8"
type RHEL81 struct {
arches map[string]arch
imageTypes map[string]imageType
buildPackages []string
}
type arch struct {
name string
bootloaderPackages []string
buildPackages []string
uefi bool
}
type imageType struct {
name string
mimeType string
packages []string
excludedPackages []string
enabledServices []string
disabledServices []string
bootable bool
defaultTarget string
kernelOptions string
defaultSize uint64
assembler func(uefi bool, size uint64) *osbuild.Assembler
}
type rhel81Arch struct {
name string
distro *RHEL81
arch *arch
}
type rhel81ImageType struct {
name string
arch *rhel81Arch
imageType *imageType
}
func (a *rhel81Arch) Distro() distro.Distro {
return a.distro
}
func (t *rhel81ImageType) Arch() distro.Arch {
return t.arch
}
func (d *RHEL81) ListArches() []string {
archs := make([]string, 0, len(d.arches))
for name := range d.arches {
archs = append(archs, name)
}
sort.Strings(archs)
return archs
}
func (d *RHEL81) GetArch(name string) (distro.Arch, error) {
a, exists := d.arches[name]
if !exists {
return nil, errors.New("invalid architecture: " + name)
}
return &rhel81Arch{
name: name,
distro: d,
arch: &a,
}, nil
}
func (a *rhel81Arch) Name() string {
return a.name
}
func (a *rhel81Arch) ListImageTypes() []string {
formats := make([]string, 0, len(a.distro.imageTypes))
for name := range a.distro.imageTypes {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
}
func (a *rhel81Arch) GetImageType(name string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[name]
if !exists {
return nil, errors.New("invalid image type: " + name)
}
return &rhel81ImageType{
name: name,
arch: a,
imageType: &t,
}, nil
}
func (t *rhel81ImageType) Name() string {
return t.name
}
func (t *rhel81ImageType) Filename() string {
return t.imageType.name
}
func (t *rhel81ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *rhel81ImageType) Size(size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if t.name == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
}
if size == 0 {
size = t.imageType.defaultSize
}
return size
}
func (t *rhel81ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.imageType.excludedPackages
}
func (t *rhel81ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *rhel81ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func New() *RHEL81 {
const GigaByte = 1024 * 1024 * 1024
r := RHEL81{
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
"e2fsprogs",
"glibc",
"policycoreutils",
"python36",
"qemu-img",
"systemd",
"tar",
"xfsprogs",
"xz",
},
arches: map[string]arch{
"x86_64": arch{
name: "x86_64",
bootloaderPackages: []string{
"dracut-config-generic",
"grub2-pc",
},
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
uefi: true,
},
},
}
r.imageTypes["ami"] = imageType{
name: "image.vhdx",
mimeType: "application/octet-stream",
packages: []string{
"checkpolicy",
"chrony",
"cloud-init",
"cloud-init",
"cloud-utils-growpart",
"@core",
"dhcp-client",
"gdisk",
"insights-client",
"kernel",
"langpacks-en",
"net-tools",
"NetworkManager",
"redhat-release",
"redhat-release-eula",
"rng-tools",
"rsync",
"selinux-policy-targeted",
"tar",
"yum-utils",
// TODO this doesn't exist in BaseOS or AppStream
// "rh-amazon-rhui-client",
},
excludedPackages: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-tools-firmware",
"biosdevname",
"dracut-config-rescue",
"firewalld",
"iprutils",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"plymouth",
// TODO this cannot be removed, because the kernel (?)
// depends on it. The ec2 kickstart force-removes it.
// "linux-firmware",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
defaultTarget: "multi-user.target",
bootable: true,
kernelOptions: "ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
defaultSize: 6 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vhdx", "image.vhdx", uefi, size)
},
}
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
"firewalld",
"chrony",
"langpacks-en",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: false,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
}
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"firewalld",
"kernel",
"langpacks-en",
"selinux-policy-targeted",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw", "disk.img", uefi, size)
},
}
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@core",
"chrony",
"dnf",
"kernel",
"yum",
"nfs-utils",
"dnf-utils",
"cloud-init",
"python3-jsonschema",
"qemu-guest-agent",
"cloud-utils-growpart",
"dracut-norescue",
"tar",
"tcpdump",
"rsync",
"dnf-plugin-spacewalk",
"rhn-client-tools",
"rhnlib",
"rhnsd",
"rhn-setup",
"NetworkManager",
"dhcp-client",
"cockpit-ws",
"cockpit-system",
"subscription-manager-cockpit",
"redhat-release",
"redhat-release-eula",
"rng-tools",
"insights-client",
// TODO: rh-amazon-rhui-client
},
excludedPackages: []string{
"dracut-config-rescue",
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-tools-firmware",
"firewalld",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"langpacks-*",
"langpacks-en",
"biosdevname",
"plymouth",
"iprutils",
"langpacks-en",
"fedora-release",
"fedora-repos",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
kernelOptions: "console=ttyS0 console=ttyS0,115200n8 no_timer_check crashkernel=auto net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
// From the lorax kickstart
"kernel",
"selinux-policy-targeted",
"cloud-init",
"qemu-guest-agent",
"spice-vdagent",
},
excludedPackages: []string{
"dracut-config-rescue",
},
bootable: true,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
"firewalld",
"chrony",
"langpacks-en",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: false,
kernelOptions: "ro net.ifnames=0",
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
// From the lorax kickstart
"kernel",
"selinux-policy-targeted",
"chrony",
"WALinuxAgent",
"python3",
"net-tools",
"cloud-init",
"cloud-utils-growpart",
"gdisk",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
enabledServices: []string{
"sshd",
"waagent",
},
defaultTarget: "multi-user.target",
bootable: true,
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vpc", "disk.vhd", uefi, size)
},
}
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"firewalld",
"kernel",
"langpacks-en",
"open-vm-tools",
"selinux-policy-targeted",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vmdk", "disk.vmdk", uefi, size)
},
}
return &r
}
func (r *RHEL81) Name() string {
return name
}
func (r *RHEL81) ModulePlatformID() string {
return modulePlatformID
}
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
}
func (t *rhel81ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.rhel81")
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
kernelOptions := t.imageType.kernelOptions
if kernel := c.GetKernel(); kernel != nil {
kernelOptions += " " + kernel.Append
}
p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(kernelOptions, t.arch.arch.uefi)))
// TODO support setting all languages and install corresponding langpack-* package
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{*language}))
} else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{"en_US"}))
}
if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{*keyboard}))
}
if hostname := c.GetHostname(); hostname != nil {
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{*hostname}))
}
timezone, ntpServers := c.GetTimezoneSettings()
// TODO install chrony when this is set?
if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{*timezone}))
}
if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{ntpServers}))
}
if users := c.GetUsers(); len(users) > 0 {
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
p.AddStage(osbuild.NewUsersStage(options))
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if services := c.GetServices(); services != nil || t.imageType.enabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.imageType.enabledServices, t.imageType.disabledServices, services, t.imageType.defaultTarget)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *rhel81ImageType) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
p := &osbuild.Pipeline{}
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, buildPackageSpecs)))
return p
}
func (r *rhel81ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
continue
}
gpgKeys = append(gpgKeys, repo.GPGKey)
}
var packages []string
for _, spec := range specs {
packages = append(packages, spec.Checksum)
}
return &osbuild.RPMStageOptions{
GPGKeys: gpgKeys,
Packages: packages,
}
}
func (r *rhel81ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
for _, c := range users {
if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) {
cryptedPassword, err := crypt.CryptSHA512(*c.Password)
if err != nil {
return nil, err
}
c.Password = &cryptedPassword
}
user := osbuild.UsersStageOptionsUser{
Groups: c.Groups,
Description: c.Description,
Home: c.Home,
Shell: c.Shell,
Password: c.Password,
Key: c.Key,
}
if c.UID != nil {
uid := strconv.Itoa(*c.UID)
user.UID = &uid
}
if c.GID != nil {
gid := strconv.Itoa(*c.GID)
user.GID = &gid
}
options.Users[c.Name] = user
}
return &options, nil
}
func (r *rhel81ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
for _, group := range groups {
groupData := osbuild.GroupsStageOptionsGroup{
Name: group.Name,
}
if group.GID != nil {
gid := strconv.Itoa(*group.GID)
groupData.GID = &gid
}
options.Groups[group.Name] = groupData
}
return &options
}
func (r *rhel81ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
if firewall.Services != nil {
options.EnabledServices = firewall.Services.Enabled
options.DisabledServices = firewall.Services.Disabled
}
return &options
}
func (r *rhel81ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
}
return &osbuild.SystemdStageOptions{
EnabledServices: enabledServices,
DisabledServices: disabledServices,
DefaultTarget: target,
}
}
func (r *rhel81ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("0bd700f8-090f-4556-b797-b340297ea1bd", "xfs", "/", "defaults", 0, 0)
if uefi {
options.AddFilesystem("46BB-8120", "vfat", "/boot/efi", "umask=0077,shortname=winnt", 0, 2)
}
return &options
}
func (r *rhel81ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
var uefiOptions *osbuild.GRUB2UEFI
if uefi {
uefiOptions = &osbuild.GRUB2UEFI{
Vendor: "redhat",
}
}
return &osbuild.GRUB2StageOptions{
RootFilesystemUUID: id,
KernelOptions: kernelOptions,
Legacy: !uefi,
UEFI: uefiOptions,
}
}
func (r *rhel81ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}
}
func (r *RHEL81) qemuAssembler(format string, filename string, uefi bool, size uint64) *osbuild.Assembler {
var options osbuild.QEMUAssemblerOptions
if uefi {
fstype := uuid.MustParse("C12A7328-F81F-11D2-BA4B-00A0C93EC93B")
options = osbuild.QEMUAssemblerOptions{
Format: format,
Filename: filename,
Size: size,
PTUUID: "8DFDFF87-C96E-EA48-A3A6-9408F1F6B1EF",
PTType: "gpt",
Partitions: []osbuild.QEMUPartition{
{
Start: 2048,
Size: 972800,
Type: &fstype,
Filesystem: osbuild.QEMUFilesystem{
Type: "vfat",
UUID: "46BB-8120",
Label: "EFI System Partition",
Mountpoint: "/boot/efi",
},
},
{
Start: 976896,
Filesystem: osbuild.QEMUFilesystem{
Type: "xfs",
UUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
Mountpoint: "/",
},
},
},
}
} else {
options = osbuild.QEMUAssemblerOptions{
Format: format,
Filename: filename,
Size: size,
PTUUID: "0x14fc63d2",
PTType: "mbr",
Partitions: []osbuild.QEMUPartition{
{
Start: 2048,
Bootable: true,
Filesystem: osbuild.QEMUFilesystem{
Type: "xfs",
UUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
Mountpoint: "/",
},
},
},
}
}
return osbuild.NewQEMUAssembler(&options)
}
func (r *RHEL81) tarAssembler(filename, compression string) *osbuild.Assembler {
return osbuild.NewTarAssembler(
&osbuild.TarAssemblerOptions{
Filename: filename,
Compression: compression,
})
}
func (r *RHEL81) rawFSAssembler(filename string, size uint64) *osbuild.Assembler {
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
return osbuild.NewRawFSAssembler(
&osbuild.RawFSAssemblerOptions{
Filename: filename,
RootFilesystemUUID: id,
Size: size,
FilesystemType: "xfs",
})
}

View file

@ -1,94 +0,0 @@
package rhel81_test
import (
"github.com/osbuild/osbuild-composer/internal/distro/rhel81"
"testing"
)
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string
}
tests := []struct {
name string
args args
want string
want1 string
wantErr bool
}{
{
name: "ami",
args: args{"ami"},
want: "image.vhdx",
want1: "application/octet-stream",
},
{
name: "ext4",
args: args{"ext4-filesystem"},
want: "filesystem.img",
want1: "application/octet-stream",
},
{
name: "openstack",
args: args{"openstack"},
want: "disk.qcow2",
want1: "application/x-qemu-disk",
},
{
name: "partitioned-disk",
args: args{"partitioned-disk"},
want: "disk.img",
want1: "application/octet-stream",
},
{
name: "qcow2",
args: args{"qcow2"},
want: "disk.qcow2",
want1: "application/x-qemu-disk",
},
{
name: "tar",
args: args{"tar"},
want: "root.tar.xz",
want1: "application/x-tar",
},
{
name: "vhd",
args: args{"vhd"},
want: "disk.vhd",
want1: "application/x-vhd",
},
{
name: "vmdk",
args: args{"vmdk"},
want: "disk.vmdk",
want1: "application/x-vmdk",
},
{
name: "invalid-output-type",
args: args{"foobar"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dist := rhel81.New()
arch, _ := dist.GetArch("x86_64")
imgType, err := arch.GetImageType(tt.args.outputFormat)
if (err != nil) != tt.wantErr {
t.Errorf("Arch.GetImageType() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
got := imgType.Filename()
got1 := imgType.MIMEType()
if got != tt.want {
t.Errorf("ImageType.Filename() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("ImageType.MIMEType() got1 = %v, want %v", got1, tt.want1)
}
}
})
}
}

View file

@ -1,874 +0,0 @@
package rhel83
import (
"errors"
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
"github.com/google/uuid"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/crypt"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
const name = "rhel-8.3"
const modulePlatformID = "platform:el8"
type RHEL83 struct {
arches map[string]arch
imageTypes map[string]imageType
buildPackages []string
}
type arch struct {
name string
bootloaderPackages []string
buildPackages []string
uefi bool
}
type imageType struct {
name string
mimeType string
packages []string
excludedPackages []string
enabledServices []string
disabledServices []string
bootable bool
defaultTarget string
kernelOptions string
defaultSize uint64
assembler func(uefi bool, size uint64) *osbuild.Assembler
}
type rhel83Arch struct {
name string
distro *RHEL83
arch *arch
}
type rhel83ImageType struct {
name string
arch *rhel83Arch
imageType *imageType
}
func (a *rhel83Arch) Distro() distro.Distro {
return a.distro
}
func (t *rhel83ImageType) Arch() distro.Arch {
return t.arch
}
func (d *RHEL83) ListArches() []string {
archs := make([]string, 0, len(d.arches))
for name := range d.arches {
archs = append(archs, name)
}
sort.Strings(archs)
return archs
}
func (d *RHEL83) GetArch(arch string) (distro.Arch, error) {
a, exists := d.arches[arch]
if !exists {
return nil, errors.New("invalid architecture: " + arch)
}
return &rhel83Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *rhel83Arch) Name() string {
return a.name
}
func (a *rhel83Arch) ListImageTypes() []string {
formats := make([]string, 0, len(a.distro.imageTypes))
for name := range a.distro.imageTypes {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
}
func (a *rhel83Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &rhel83ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *rhel83ImageType) Name() string {
return t.name
}
func (t *rhel83ImageType) Filename() string {
return t.imageType.name
}
func (t *rhel83ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *rhel83ImageType) Size(size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if t.name == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
}
if size == 0 {
size = t.imageType.defaultSize
}
return size
}
func (t *rhel83ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.imageType.excludedPackages
}
func (t *rhel83ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *rhel83ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func New() *RHEL83 {
const GigaByte = 1024 * 1024 * 1024
r := RHEL83{
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
"e2fsprogs",
"glibc",
"policycoreutils",
"python36",
"qemu-img",
"systemd",
"tar",
"xfsprogs",
"xz",
},
arches: map[string]arch{
"x86_64": arch{
name: "x86_64",
bootloaderPackages: []string{
"dracut-config-generic",
"grub2-pc",
},
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
uefi: true,
},
},
}
r.imageTypes["ami"] = imageType{
name: "image.vhdx",
mimeType: "application/octet-stream",
packages: []string{
"checkpolicy",
"chrony",
"cloud-init",
"cloud-init",
"cloud-utils-growpart",
"@core",
"dhcp-client",
"gdisk",
"insights-client",
"kernel",
"langpacks-en",
"net-tools",
"NetworkManager",
"redhat-release",
"redhat-release-eula",
"rng-tools",
"rsync",
"selinux-policy-targeted",
"tar",
"yum-utils",
// TODO this doesn't exist in BaseOS or AppStream
// "rh-amazon-rhui-client",
},
excludedPackages: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-tools-firmware",
"biosdevname",
"dracut-config-rescue",
"firewalld",
"iprutils",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"plymouth",
// TODO this cannot be removed, because the kernel (?)
// depends on it. The ec2 kickstart force-removes it.
// "linux-firmware",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
defaultTarget: "multi-user.target",
bootable: true,
kernelOptions: "ro console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto",
defaultSize: 6 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vhdx", "image.vhdx", uefi, size)
},
}
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
"firewalld",
"chrony",
"langpacks-en",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: false,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
}
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"firewalld",
"kernel",
"langpacks-en",
"selinux-policy-targeted",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw", "disk.img", uefi, size)
},
}
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@core",
"chrony",
"dnf",
"kernel",
"yum",
"nfs-utils",
"dnf-utils",
"cloud-init",
"python3-jsonschema",
"qemu-guest-agent",
"cloud-utils-growpart",
"dracut-norescue",
"tar",
"tcpdump",
"rsync",
"dnf-plugin-spacewalk",
"rhn-client-tools",
"rhnlib",
"rhnsd",
"rhn-setup",
"NetworkManager",
"dhcp-client",
"cockpit-ws",
"cockpit-system",
"subscription-manager-cockpit",
"redhat-release",
"redhat-release-eula",
"rng-tools",
"insights-client",
// TODO: rh-amazon-rhui-client
},
excludedPackages: []string{
"dracut-config-rescue",
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-tools-firmware",
"firewalld",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"langpacks-*",
"langpacks-en",
"biosdevname",
"plymouth",
"iprutils",
"langpacks-en",
"fedora-release",
"fedora-repos",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
kernelOptions: "console=ttyS0 console=ttyS0,115200n8 no_timer_check crashkernel=auto net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
// From the lorax kickstart
"kernel",
"selinux-policy-targeted",
"cloud-init",
"qemu-guest-agent",
"spice-vdagent",
},
excludedPackages: []string{
"dracut-config-rescue",
},
bootable: true,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
"firewalld",
"chrony",
"langpacks-en",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: false,
kernelOptions: "ro net.ifnames=0",
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
// From the lorax kickstart
"kernel",
"selinux-policy-targeted",
"chrony",
"WALinuxAgent",
"python3",
"net-tools",
"cloud-init",
"cloud-utils-growpart",
"gdisk",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
enabledServices: []string{
"sshd",
"waagent",
},
defaultTarget: "multi-user.target",
bootable: true,
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vpc", "disk.vhd", uefi, size)
},
}
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"firewalld",
"kernel",
"langpacks-en",
"open-vm-tools",
"selinux-policy-targeted",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
kernelOptions: "ro net.ifnames=0",
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vmdk", "disk.vmdk", uefi, size)
},
}
return &r
}
func (r *RHEL83) Name() string {
return name
}
func (r *RHEL83) ModulePlatformID() string {
return modulePlatformID
}
func (r *RHEL83) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.imageTypes[outputFormat]
if !exists {
return nil, nil, errors.New("invalid output format: " + outputFormat)
}
packages := output.packages
if output.bootable {
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, nil, errors.New("invalid architecture: " + outputArchitecture)
}
packages = append(packages, arch.bootloaderPackages...)
}
return packages, output.excludedPackages, nil
}
func (r *RHEL83) BuildPackages(outputArchitecture string) ([]string, error) {
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
}
return append(r.buildPackages, arch.buildPackages...), nil
}
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
}
func (t *rhel83ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.rhel83")
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
kernelOptions := t.imageType.kernelOptions
if kernel := c.GetKernel(); kernel != nil {
kernelOptions += " " + kernel.Append
}
p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(kernelOptions, t.arch.arch.uefi)))
// TODO support setting all languages and install corresponding langpack-* package
language, keyboard := c.GetPrimaryLocale()
if language != nil {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{*language}))
} else {
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{"en_US"}))
}
if keyboard != nil {
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{*keyboard}))
}
if hostname := c.GetHostname(); hostname != nil {
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{*hostname}))
}
timezone, ntpServers := c.GetTimezoneSettings()
// TODO install chrony when this is set?
if timezone != nil {
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{*timezone}))
}
if len(ntpServers) > 0 {
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{ntpServers}))
}
if users := c.GetUsers(); len(users) > 0 {
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
p.AddStage(osbuild.NewUsersStage(options))
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if services := c.GetServices(); services != nil || t.imageType.enabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.imageType.enabledServices, t.imageType.disabledServices, services, t.imageType.defaultTarget)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *rhel83ImageType) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
p := &osbuild.Pipeline{}
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, buildPackageSpecs)))
return p
}
func (r *rhel83ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
continue
}
gpgKeys = append(gpgKeys, repo.GPGKey)
}
var packages []string
for _, spec := range specs {
packages = append(packages, spec.Checksum)
}
return &osbuild.RPMStageOptions{
GPGKeys: gpgKeys,
Packages: packages,
}
}
func (r *rhel83ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
for _, c := range users {
if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) {
cryptedPassword, err := crypt.CryptSHA512(*c.Password)
if err != nil {
return nil, err
}
c.Password = &cryptedPassword
}
user := osbuild.UsersStageOptionsUser{
Groups: c.Groups,
Description: c.Description,
Home: c.Home,
Shell: c.Shell,
Password: c.Password,
Key: c.Key,
}
if c.UID != nil {
uid := strconv.Itoa(*c.UID)
user.UID = &uid
}
if c.GID != nil {
gid := strconv.Itoa(*c.GID)
user.GID = &gid
}
options.Users[c.Name] = user
}
return &options, nil
}
func (r *rhel83ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
for _, group := range groups {
groupData := osbuild.GroupsStageOptionsGroup{
Name: group.Name,
}
if group.GID != nil {
gid := strconv.Itoa(*group.GID)
groupData.GID = &gid
}
options.Groups[group.Name] = groupData
}
return &options
}
func (r *rhel83ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
if firewall.Services != nil {
options.EnabledServices = firewall.Services.Enabled
options.DisabledServices = firewall.Services.Disabled
}
return &options
}
func (r *rhel83ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
}
return &osbuild.SystemdStageOptions{
EnabledServices: enabledServices,
DisabledServices: disabledServices,
DefaultTarget: target,
}
}
func (r *rhel83ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("0bd700f8-090f-4556-b797-b340297ea1bd", "xfs", "/", "defaults", 0, 0)
if uefi {
options.AddFilesystem("46BB-8120", "vfat", "/boot/efi", "umask=0077,shortname=winnt", 0, 2)
}
return &options
}
func (r *rhel83ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
var uefiOptions *osbuild.GRUB2UEFI
if uefi {
uefiOptions = &osbuild.GRUB2UEFI{
Vendor: "redhat",
}
}
return &osbuild.GRUB2StageOptions{
RootFilesystemUUID: id,
KernelOptions: kernelOptions,
Legacy: !uefi,
UEFI: uefiOptions,
}
}
func (r *rhel83ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}
}
func (r *RHEL83) qemuAssembler(format string, filename string, uefi bool, size uint64) *osbuild.Assembler {
var options osbuild.QEMUAssemblerOptions
if uefi {
fstype := uuid.MustParse("C12A7328-F81F-11D2-BA4B-00A0C93EC93B")
options = osbuild.QEMUAssemblerOptions{
Format: format,
Filename: filename,
Size: size,
PTUUID: "8DFDFF87-C96E-EA48-A3A6-9408F1F6B1EF",
PTType: "gpt",
Partitions: []osbuild.QEMUPartition{
{
Start: 2048,
Size: 972800,
Type: &fstype,
Filesystem: osbuild.QEMUFilesystem{
Type: "vfat",
UUID: "46BB-8120",
Label: "EFI System Partition",
Mountpoint: "/boot/efi",
},
},
{
Start: 976896,
Filesystem: osbuild.QEMUFilesystem{
Type: "xfs",
UUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
Mountpoint: "/",
},
},
},
}
} else {
options = osbuild.QEMUAssemblerOptions{
Format: format,
Filename: filename,
Size: size,
PTUUID: "0x14fc63d2",
PTType: "mbr",
Partitions: []osbuild.QEMUPartition{
{
Start: 2048,
Bootable: true,
Filesystem: osbuild.QEMUFilesystem{
Type: "xfs",
UUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
Mountpoint: "/",
},
},
},
}
}
return osbuild.NewQEMUAssembler(&options)
}
func (r *RHEL83) tarAssembler(filename, compression string) *osbuild.Assembler {
return osbuild.NewTarAssembler(
&osbuild.TarAssemblerOptions{
Filename: filename,
Compression: compression,
})
}
func (r *RHEL83) rawFSAssembler(filename string, size uint64) *osbuild.Assembler {
id := uuid.MustParse("0bd700f8-090f-4556-b797-b340297ea1bd")
return osbuild.NewRawFSAssembler(
&osbuild.RawFSAssemblerOptions{
Filename: filename,
RootFilesystemUUID: id,
Size: size,
FilesystemType: "xfs",
})
}

View file

@ -1,415 +0,0 @@
package rhel83_test
import (
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/rhel83"
"github.com/stretchr/testify/assert"
)
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string
}
tests := []struct {
name string
args args
want string
want1 string
wantErr bool
}{
{
name: "ami",
args: args{"ami"},
want: "image.vhdx",
want1: "application/octet-stream",
},
{
name: "ext4",
args: args{"ext4-filesystem"},
want: "filesystem.img",
want1: "application/octet-stream",
},
{
name: "openstack",
args: args{"openstack"},
want: "disk.qcow2",
want1: "application/x-qemu-disk",
},
{
name: "partitioned-disk",
args: args{"partitioned-disk"},
want: "disk.img",
want1: "application/octet-stream",
},
{
name: "qcow2",
args: args{"qcow2"},
want: "disk.qcow2",
want1: "application/x-qemu-disk",
},
{
name: "tar",
args: args{"tar"},
want: "root.tar.xz",
want1: "application/x-tar",
},
{
name: "vhd",
args: args{"vhd"},
want: "disk.vhd",
want1: "application/x-vhd",
},
{
name: "vmdk",
args: args{"vmdk"},
want: "disk.vmdk",
want1: "application/x-vmdk",
},
{
name: "invalid-output-type",
args: args{"foobar"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dist := rhel83.New()
arch, _ := dist.GetArch("x86_64")
imgType, err := arch.GetImageType(tt.args.outputFormat)
if (err != nil) != tt.wantErr {
t.Errorf("Arch.GetImageType() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
got := imgType.Filename()
got1 := imgType.MIMEType()
if got != tt.want {
t.Errorf("ImageType.Filename() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("ImageType.MIMEType() got1 = %v, want %v", got1, tt.want1)
}
}
})
}
}
func TestImageType_BuildPackages(t *testing.T) {
x8664BuildPackages := []string{
"dnf",
"dosfstools",
"e2fsprogs",
"grub2-pc",
"policycoreutils",
"qemu-img",
"systemd",
"tar",
"xz",
}
aarch64BuildPackages := []string{
"dnf",
"dosfstools",
"e2fsprogs",
"policycoreutils",
"qemu-img",
"systemd",
"tar",
"xz",
}
buildPackages := map[string][]string{
"x86_64": x8664BuildPackages,
"aarch64": aarch64BuildPackages,
}
d := rhel83.New()
for _, archLabel := range d.ListArches() {
archStruct, err := d.GetArch(archLabel)
if assert.NoErrorf(t, err, "d.GetArch(%v) returned err = %v; expected nil", archLabel, err) {
continue
}
for _, itLabel := range archStruct.ListImageTypes() {
itStruct, err := archStruct.GetImageType(itLabel)
if assert.NoErrorf(t, err, "d.GetArch(%v) returned err = %v; expected nil", archLabel, err) {
continue
}
assert.ElementsMatch(t, buildPackages[archLabel], itStruct.BuildPackages())
}
}
}
func TestImageType_Name(t *testing.T) {
distro := rhel83.New()
imgMap := []struct {
arch string
imgNames []string
}{
{
arch: "x86_64",
imgNames: []string{
"ami",
"ext4-filesystem",
"partitioned-disk",
"qcow2",
"openstack",
"tar",
"vhd",
"vmdk",
},
},
{
arch: "aarch64",
imgNames: []string{
"ami",
"ext4-filesystem",
"partitioned-disk",
"qcow2",
"openstack",
"tar",
},
},
}
for _, mapping := range imgMap {
arch, err := distro.GetArch(mapping.arch)
if assert.NoError(t, err) {
for _, imgName := range mapping.imgNames {
imgType, err := arch.GetImageType(imgName)
if assert.NoError(t, err) {
assert.Equalf(t, imgName, imgType.Name(), "arch: %s", mapping.arch)
}
}
}
}
}
func TestImageType_Size(t *testing.T) {
const gigaByte = 1024 * 1024 * 1024
sizeMap := []struct {
name string
inputSize uint64
outputSize uint64
}{
{
name: "ami",
inputSize: 6*gigaByte + 1,
outputSize: 6*gigaByte + 1,
},
{
name: "ami",
inputSize: 0,
outputSize: 6 * gigaByte,
},
{
name: "vhd",
inputSize: 10 * gigaByte,
outputSize: 10 * gigaByte,
},
{
name: "vhd",
inputSize: 10*gigaByte - 1,
outputSize: 10 * gigaByte,
},
}
distro := rhel83.New()
arch, err := distro.GetArch("x86_64")
if assert.NoError(t, err) {
for _, mapping := range sizeMap {
imgType, err := arch.GetImageType(mapping.name)
if assert.NoError(t, err) {
size := imgType.Size(mapping.inputSize)
assert.Equalf(t, mapping.outputSize, size, "Image type: %s, input size: %d, expected: %d, got: %d",
mapping.name, mapping.inputSize, mapping.outputSize, size)
}
}
}
}
func TestImageType_BasePackages(t *testing.T) {
pkgMaps := []struct {
name string
basePackages []string
bootloaderPackages []string
excludedPackages []string
bootable bool
}{
{
name: "ami",
basePackages: []string{
"checkpolicy",
"chrony",
"cloud-init",
"cloud-init",
"cloud-utils-growpart",
"@core",
"dhcp-client",
"gdisk",
"insights-client",
"kernel",
"langpacks-en",
"net-tools",
"NetworkManager",
"redhat-release",
"redhat-release-eula",
"rng-tools",
"rsync",
"selinux-policy-targeted",
"tar",
"yum-utils",
},
bootloaderPackages: []string{
"dracut-config-generic",
"grub2-pc",
},
excludedPackages: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
"alsa-tools-firmware",
"biosdevname",
"dracut-config-rescue",
"firewalld",
"iprutils",
"ivtv-firmware",
"iwl1000-firmware",
"iwl100-firmware",
"iwl105-firmware",
"iwl135-firmware",
"iwl2000-firmware",
"iwl2030-firmware",
"iwl3160-firmware",
"iwl3945-firmware",
"iwl4965-firmware",
"iwl5000-firmware",
"iwl5150-firmware",
"iwl6000-firmware",
"iwl6000g2a-firmware",
"iwl6000g2b-firmware",
"iwl6050-firmware",
"iwl7260-firmware",
"libertas-sd8686-firmware",
"libertas-sd8787-firmware",
"libertas-usb8388-firmware",
"plymouth",
// TODO this cannot be removed, because the kernel (?)
// depends on it. The ec2 kickstart force-removes it.
// "linux-firmware",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
},
{
name: "ext4-filesystem",
basePackages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
"firewalld",
"chrony",
"langpacks-en",
},
excludedPackages: []string{
"dracut-config-rescue",
// TODO setfiles failes because of usr/sbin/timedatex. Exlude until
// https://errata.devel.redhat.com/advisory/47339 lands
"timedatex",
},
bootable: true,
},
{
name: "openstack",
basePackages: []string{
// Defaults
"@Core",
"langpacks-en",
// From the lorax kickstart
"kernel",
"selinux-policy-targeted",
"cloud-init",
"qemu-guest-agent",
"spice-vdagent",
},
bootloaderPackages: []string{
"dracut-config-generic",
"grub2-pc",
},
excludedPackages: []string{
"dracut-config-rescue",
},
bootable: true,
},
}
distro := rhel83.New()
arch, err := distro.GetArch("x86_64")
assert.NoError(t, err)
for _, pkgMap := range pkgMaps {
imgType, err := arch.GetImageType(pkgMap.name)
assert.NoError(t, err)
basePackages, excludedPackages := imgType.BasePackages()
assert.Equalf(
t,
append(pkgMap.basePackages, pkgMap.bootloaderPackages...),
basePackages,
"image type: %s",
pkgMap.name,
)
assert.Equalf(t, pkgMap.excludedPackages, excludedPackages, "image type: %s", pkgMap.name)
}
}
func TestDistro_Manifest(t *testing.T) {
// disabled as there is no usable manifest file available ATM
// distro_test_common.TestDistro_Manifest(t, "../../../test/cases/", "rhel_8.3*", rhel83.New())
}
func TestRhel83_ListArches(t *testing.T) {
distro := rhel83.New()
arches := distro.ListArches()
assert.Equal(t, []string{"aarch64", "x86_64"}, arches)
}
func TestRhel83_GetArch(t *testing.T) {
distro := rhel83.New()
arches := []struct {
name string
errorExpected bool
}{
{
name: "x86_64",
},
{
name: "aarch64",
},
{
name: "foo-arch",
errorExpected: true,
},
}
for _, a := range arches {
actualArch, err := distro.GetArch(a.name)
if !a.errorExpected {
assert.Equal(t, a.name, actualArch.Name())
assert.NoError(t, err)
} else {
assert.Nil(t, actualArch)
assert.Error(t, err)
}
}
}
func TestRhel83_Name(t *testing.T) {
distro := rhel83.New()
assert.Equal(t, "rhel-8.3", distro.Name())
}
func TestRhel83_ModulePlatformID(t *testing.T) {
distro := rhel83.New()
assert.Equal(t, "platform:el8", distro.ModulePlatformID())
}