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:
parent
1e29ab291e
commit
cc231e0ed1
30 changed files with 63835 additions and 66140 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
@ -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())
|
||||
}
|
||||
|
|
@ -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",
|
||||
})
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -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",
|
||||
})
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue