distro: mass cleanup

Delete unused methods and make types and fields private where
possible. Some code is moved around, but apart from that there
is no change in behavior.

The naming of the distros were moved back into the distro
packages as the common types now only had one user, and this
allowed us to drop some redundant error checking.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2020-03-23 22:28:30 +01:00
parent cf2ad51243
commit 87b0bb6e5d
13 changed files with 968 additions and 1550 deletions

View file

@ -80,12 +80,6 @@ func toStringHelper(mapping map[string]int, tag int) (string, bool) {
return "", false
}
// See unmarshalHelper for introduction. Converts between string and TypeAlias(int)
func fromStringHelper(mapping map[string]int, stringInput string) (int, bool) {
value, exists := mapping[stringInput]
return value, exists
}
// Architecture represents one of the supported CPU architectures available for images
// produced by osbuild-composer. It is represented as an integer because if it
// was a string it would unmarshal from JSON just fine even in case that the architecture
@ -237,70 +231,6 @@ func (imgType ImageType) ToString() (string, bool) {
return toStringHelper(getImageTypeMapping(), int(imgType))
}
type Distribution int
// NOTE: If you want to add more constants here, don't forget to add a mapping below
const (
Fedora30 Distribution = iota
Fedora31
Fedora32
RHEL81
RHEL82
)
// getArchMapping is a helper function that defines the conversion from JSON string value
// to Distribution.
func getDistributionMapping() map[string]int {
// Don't forget to add module-platform-id mapping below
mapping := map[string]int{
"fedora-30": int(Fedora30),
"fedora-31": int(Fedora31),
"fedora-32": int(Fedora32),
"rhel-8.1": int(RHEL81),
"rhel-8.2": int(RHEL82),
}
return mapping
}
func (dist *Distribution) ModulePlatformID() (string, error) {
mapping := map[Distribution]string{
// TODO: this could be refactored so we don't have these strings hard coded in two places
Fedora30: "platform:f30",
Fedora31: "platform:f31",
Fedora32: "platform:f32",
RHEL81: "platform:el8",
RHEL82: "platform:el8",
}
id, exists := mapping[*dist]
if !exists {
return "", &CustomTypeError{reason: "Distribution does not have a module platform ID assigned"}
} else {
return id, nil
}
}
func (distro *Distribution) UnmarshalJSON(data []byte) error {
value, err := unmarshalHelper(data, " is not a valid JSON value", " is not a valid distribution", getDistributionMapping())
if err != nil {
return err
}
*distro = Distribution(value)
return nil
}
func (distro Distribution) MarshalJSON() ([]byte, error) {
return marshalHelper(int(distro), getDistributionMapping(), "is not a valid distribution tag")
}
func (distro Distribution) ToString() (string, bool) {
return toStringHelper(getDistributionMapping(), int(distro))
}
func DistributionFromString(distro string) (Distribution, bool) {
tag, exists := fromStringHelper(getDistributionMapping(), distro)
return Distribution(tag), exists
}
type UploadTarget int
// NOTE: If you want to add more constants here, don't forget to add a mapping below

View file

@ -5,7 +5,6 @@ import (
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
@ -16,45 +15,45 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
type arch struct {
Name string
BootloaderPackages []string
BuildPackages []string
UEFI bool
}
type output struct {
Name string
MimeType string
Packages []string
ExcludedPackages []string
EnabledServices []string
DisabledServices []string
KernelOptions string
Bootable bool
DefaultSize uint64
Assembler func(uefi bool, size uint64) *osbuild.Assembler
}
const Distro = common.Fedora30
const ModulePlatformID = "platform:f30"
const name = "fedora-30"
const modulePlatformID = "platform:f30"
type Fedora30 struct {
arches map[string]arch
outputs map[string]output
imageTypes map[string]imageType
buildPackages []string
}
type Fedora30Arch struct {
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
kernelOptions string
bootable bool
defaultSize uint64
assembler func(uefi bool, size uint64) *osbuild.Assembler
}
type fedora30Arch struct {
name string
distro *Fedora30
arch *arch
}
type Fedora30ImageType struct {
name string
arch *Fedora30Arch
output *output
type fedora30ImageType struct {
name string
arch *fedora30Arch
imageType *imageType
}
func (d *Fedora30) GetArch(arch string) (distro.Arch, error) {
@ -63,75 +62,88 @@ func (d *Fedora30) GetArch(arch string) (distro.Arch, error) {
return nil, errors.New("invalid architecture: " + arch)
}
return &Fedora30Arch{
return &fedora30Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *Fedora30Arch) Name() string {
func (a *fedora30Arch) Name() string {
return a.name
}
func (a *Fedora30Arch) ListImageTypes() []string {
return a.distro.ListOutputFormats()
func (a *fedora30Arch) 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 *Fedora30Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.outputs[imageType]
func (a *fedora30Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &Fedora30ImageType{
name: imageType,
arch: a,
output: &t,
return &fedora30ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *Fedora30ImageType) Name() string {
func (t *fedora30ImageType) Name() string {
return t.name
}
func (t *Fedora30ImageType) Filename() string {
return t.output.Name
func (t *fedora30ImageType) Filename() string {
return t.imageType.name
}
func (t *Fedora30ImageType) MIMEType() string {
return t.output.MimeType
func (t *fedora30ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *Fedora30ImageType) Size(size uint64) uint64 {
return t.arch.distro.GetSizeForOutputType(t.name, size)
func (t *fedora30ImageType) 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 *Fedora30ImageType) BasePackages() ([]string, []string) {
packages := t.output.Packages
if t.output.Bootable {
packages = append(packages, t.arch.arch.BootloaderPackages...)
func (t *fedora30ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.output.ExcludedPackages
return packages, t.imageType.excludedPackages
}
func (t *Fedora30ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.BuildPackages...)
func (t *fedora30ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *Fedora30ImageType) Manifest(c *blueprint.Customizations,
func (t *fedora30ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.arch.distro.pipeline(c, repos, packageSpecs, buildPackageSpecs, t.arch.name, t.name, size)
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *t.arch.distro.sources(append(packageSpecs, buildPackageSpecs...)),
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
@ -140,7 +152,7 @@ func New() *Fedora30 {
const GigaByte = 1024 * 1024 * 1024
r := Fedora30{
outputs: map[string]output{},
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
@ -152,32 +164,32 @@ func New() *Fedora30 {
},
arches: map[string]arch{
"x86_64": arch{
Name: "x86_64",
BootloaderPackages: []string{
name: "x86_64",
bootloaderPackages: []string{
"grub2-pc",
},
BuildPackages: []string{
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
Name: "aarch64",
BootloaderPackages: []string{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
UEFI: true,
uefi: true,
},
},
}
r.outputs["ami"] = output{
Name: "image.raw.xz",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ami"] = imageType{
name: "image.raw.xz",
mimeType: "application/octet-stream",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -189,24 +201,24 @@ func New() *Fedora30 {
"checkpolicy",
"net-tools",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
EnabledServices: []string{
enabledServices: []string{
"cloud-init.service",
},
KernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
Bootable: true,
DefaultSize: 6 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
bootable: true,
defaultSize: 6 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw.xz", "image.raw.xz", uefi, size)
},
}
r.outputs["ext4-filesystem"] = output{
Name: "filesystem.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -214,19 +226,19 @@ func New() *Fedora30 {
"chrony",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: false,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: false,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
}
r.outputs["partitioned-disk"] = output{
Name: "disk.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"firewalld",
@ -234,21 +246,21 @@ func New() *Fedora30 {
"langpacks-en",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw", "disk.img", uefi, size)
},
}
r.outputs["qcow2"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"kernel-core",
"@Fedora Cloud Server",
"chrony",
@ -257,25 +269,25 @@ func New() *Fedora30 {
"selinux-policy-targeted",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
"etables",
"firewalld",
"gobject-introspection",
"plymouth",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.outputs["openstack"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -287,21 +299,21 @@ func New() *Fedora30 {
"cloud-init",
"libdrm",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.outputs["tar"] = output{
Name: "root.tar.xz",
MimeType: "application/x-tar",
Packages: []string{
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -309,19 +321,19 @@ func New() *Fedora30 {
"chrony",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: false,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: false,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.outputs["vhd"] = output{
Name: "disk.vhd",
MimeType: "application/x-vhd",
Packages: []string{
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -335,30 +347,30 @@ func New() *Fedora30 {
"glibc-all-langpacks",
"dracut-config-generic",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
EnabledServices: []string{
enabledServices: []string{
"sshd",
"waagent", // needed to run in Azure
},
DisabledServices: []string{
disabledServices: []string{
"proc-sys-fs-binfmt_misc.mount",
"loadmodules.service",
},
// These kernel parameters are required by Azure documentation
KernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vpc", "disk.vhd", uefi, size)
},
}
r.outputs["vmdk"] = output{
Name: "disk.vmdk",
MimeType: "application/x-vmdk",
Packages: []string{
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"firewalld",
@ -367,13 +379,13 @@ func New() *Fedora30 {
"open-vm-tools",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vmdk", "disk.vmdk", uefi, size)
},
}
@ -382,92 +394,37 @@ func New() *Fedora30 {
}
func (r *Fedora30) Name() string {
name, exists := Distro.ToString()
if !exists {
panic("Fatal error, hardcoded distro value in fedora30 package is not valid!")
}
return name
}
func (r *Fedora30) Distribution() common.Distribution {
return Distro
}
func (r *Fedora30) ModulePlatformID() string {
return ModulePlatformID
}
func (r *Fedora30) ListOutputFormats() []string {
formats := make([]string, 0, len(r.outputs))
for name := range r.outputs {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
return modulePlatformID
}
func (r *Fedora30) FilenameFromType(outputFormat string) (string, string, error) {
if output, exists := r.outputs[outputFormat]; exists {
return output.Name, output.MimeType, nil
if output, exists := r.imageTypes[outputFormat]; exists {
return output.name, output.mimeType, nil
}
return "", "", errors.New("invalid output format: " + outputFormat)
}
func (r *Fedora30) GetSizeForOutputType(outputFormat string, size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if outputFormat == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
if size == 0 {
size = r.outputs[outputFormat].DefaultSize
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
return size
}
func (r *Fedora30) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.outputs[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 *Fedora30) 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 (r *Fedora30) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
output, exists := r.outputs[outputFormat]
if !exists {
return nil, errors.New("invalid output format: " + outputFormat)
}
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
}
func (t *fedora30ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(r.buildPipeline(repos, arch, buildPackageSpecs), "org.osbuild.fedora30")
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.fedora30")
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, packageSpecs)))
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
// TODO support setting all languages and install corresponding langpack-* package
@ -499,7 +456,7 @@ func (r *Fedora30) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfi
}
if users := c.GetUsers(); len(users) > 0 {
options, err := r.userStageOptions(users)
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
@ -507,64 +464,36 @@ func (r *Fedora30) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfi
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(r.groupStageOptions(groups)))
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if output.Bootable {
p.AddStage(osbuild.NewFSTabStage(r.fsTabStageOptions(arch.UEFI)))
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
p.AddStage(osbuild.NewGRUB2Stage(r.grub2StageOptions(output.KernelOptions, c.GetKernel(), arch.UEFI)))
p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(t.imageType.kernelOptions, c.GetKernel(), t.arch.arch.uefi)))
if services := c.GetServices(); services != nil || output.EnabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(r.systemdStageOptions(output.EnabledServices, output.DisabledServices, services)))
if services := c.GetServices(); services != nil || t.imageType.enabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.imageType.enabledServices, t.imageType.disabledServices, services)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(r.firewallStageOptions(firewall)))
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(r.selinuxStageOptions()))
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = output.Assembler(arch.UEFI, size)
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *Fedora30) 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 (r *Fedora30) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (r *Fedora30) Runner() string {
return "org.osbuild.fedora30"
}
func (r *Fedora30) buildPipeline(repos []rpmmd.RepoConfig, arch arch, packageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
func (r *fedora30ImageType) buildPipeline(repos []rpmmd.RepoConfig, arch arch, packageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
p := &osbuild.Pipeline{}
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, packageSpecs)))
return p
}
func (r *Fedora30) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
func (r *fedora30ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
@ -584,7 +513,7 @@ func (r *Fedora30) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []
}
}
func (r *Fedora30) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
func (r *fedora30ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
@ -624,7 +553,7 @@ func (r *Fedora30) userStageOptions(users []blueprint.UserCustomization) (*osbui
return &options, nil
}
func (r *Fedora30) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
func (r *fedora30ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
@ -644,7 +573,7 @@ func (r *Fedora30) groupStageOptions(groups []blueprint.GroupCustomization) *osb
return &options
}
func (r *Fedora30) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
func (r *fedora30ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
@ -657,7 +586,7 @@ func (r *Fedora30) firewallStageOptions(firewall *blueprint.FirewallCustomizatio
return &options
}
func (r *Fedora30) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
func (r *fedora30ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
@ -668,7 +597,7 @@ func (r *Fedora30) systemdStageOptions(enabledServices, disabledServices []strin
}
}
func (r *Fedora30) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
func (r *fedora30ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("76a22bf4-f153-4541-b6c7-0332c0dfaeac", "ext4", "/", "defaults", 1, 1)
if uefi {
@ -677,7 +606,7 @@ func (r *Fedora30) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
return &options
}
func (r *Fedora30) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
func (r *fedora30ImageType) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
id, err := uuid.Parse("76a22bf4-f153-4541-b6c7-0332c0dfaeac")
if err != nil {
panic("invalid UUID")
@ -702,7 +631,7 @@ func (r *Fedora30) grub2StageOptions(kernelOptions string, kernel *blueprint.Ker
}
}
func (r *Fedora30) selinuxStageOptions() *osbuild.SELinuxStageOptions {
func (r *fedora30ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}

View file

@ -1,31 +1,11 @@
package fedora30_test
import (
"reflect"
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/fedora30"
)
func TestListOutputFormats(t *testing.T) {
want := []string{
"ami",
"ext4-filesystem",
"openstack",
"partitioned-disk",
"qcow2",
"tar",
"vhd",
"vmdk",
}
f30 := fedora30.New()
if got := f30.ListOutputFormats(); !reflect.DeepEqual(got, want) {
t.Errorf("ListOutputFormats() = %v, want %v", got, want)
}
}
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string

View file

@ -5,7 +5,6 @@ import (
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
@ -16,45 +15,45 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
type arch struct {
Name string
BootloaderPackages []string
BuildPackages []string
UEFI bool
}
type output struct {
Name string
MimeType string
Packages []string
ExcludedPackages []string
EnabledServices []string
DisabledServices []string
KernelOptions string
Bootable bool
DefaultSize uint64
Assembler func(uefi bool, size uint64) *osbuild.Assembler
}
const Distro = common.Fedora31
const ModulePlatformID = "platform:f31"
const name = "fedora-31"
const modulePlatformID = "platform:f31"
type Fedora31 struct {
arches map[string]arch
outputs map[string]output
imageTypes map[string]imageType
buildPackages []string
}
type Fedora31Arch struct {
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
kernelOptions string
bootable bool
defaultSize uint64
assembler func(uefi bool, size uint64) *osbuild.Assembler
}
type fedora31Arch struct {
name string
distro *Fedora31
arch *arch
}
type Fedora31ImageType struct {
name string
arch *Fedora31Arch
output *output
type fedora31ImageType struct {
name string
arch *fedora31Arch
imageType *imageType
}
func (d *Fedora31) GetArch(arch string) (distro.Arch, error) {
@ -63,75 +62,88 @@ func (d *Fedora31) GetArch(arch string) (distro.Arch, error) {
return nil, errors.New("invalid architecture: " + arch)
}
return &Fedora31Arch{
return &fedora31Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *Fedora31Arch) Name() string {
func (a *fedora31Arch) Name() string {
return a.name
}
func (a *Fedora31Arch) ListImageTypes() []string {
return a.distro.ListOutputFormats()
func (a *fedora31Arch) 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 *Fedora31Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.outputs[imageType]
func (a *fedora31Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &Fedora31ImageType{
name: imageType,
arch: a,
output: &t,
return &fedora31ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *Fedora31ImageType) Name() string {
func (t *fedora31ImageType) Name() string {
return t.name
}
func (t *Fedora31ImageType) Filename() string {
return t.output.Name
func (t *fedora31ImageType) Filename() string {
return t.imageType.name
}
func (t *Fedora31ImageType) MIMEType() string {
return t.output.MimeType
func (t *fedora31ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *Fedora31ImageType) Size(size uint64) uint64 {
return t.arch.distro.GetSizeForOutputType(t.name, size)
func (t *fedora31ImageType) 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 *Fedora31ImageType) BasePackages() ([]string, []string) {
packages := t.output.Packages
if t.output.Bootable {
packages = append(packages, t.arch.arch.BootloaderPackages...)
func (t *fedora31ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.output.ExcludedPackages
return packages, t.imageType.excludedPackages
}
func (t *Fedora31ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.BuildPackages...)
func (t *fedora31ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *Fedora31ImageType) Manifest(c *blueprint.Customizations,
func (t *fedora31ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.arch.distro.pipeline(c, repos, packageSpecs, buildPackageSpecs, t.arch.name, t.name, size)
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *t.arch.distro.sources(append(packageSpecs, buildPackageSpecs...)),
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
@ -140,7 +152,7 @@ func New() *Fedora31 {
const GigaByte = 1024 * 1024 * 1024
r := Fedora31{
outputs: map[string]output{},
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
@ -152,32 +164,32 @@ func New() *Fedora31 {
},
arches: map[string]arch{
"x86_64": arch{
Name: "x86_64",
BootloaderPackages: []string{
name: "x86_64",
bootloaderPackages: []string{
"grub2-pc",
},
BuildPackages: []string{
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
Name: "aarch64",
BootloaderPackages: []string{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
UEFI: true,
uefi: true,
},
},
}
r.outputs["ami"] = output{
Name: "image.raw.xz",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ami"] = imageType{
name: "image.raw.xz",
mimeType: "application/octet-stream",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -189,24 +201,24 @@ func New() *Fedora31 {
"checkpolicy",
"net-tools",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
EnabledServices: []string{
enabledServices: []string{
"cloud-init.service",
},
KernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
Bootable: true,
DefaultSize: 6 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
bootable: true,
defaultSize: 6 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw.xz", "image.raw.xz", uefi, size)
},
}
r.outputs["ext4-filesystem"] = output{
Name: "filesystem.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -214,19 +226,19 @@ func New() *Fedora31 {
"chrony",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: false,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: false,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
}
r.outputs["partitioned-disk"] = output{
Name: "disk.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"firewalld",
@ -234,21 +246,21 @@ func New() *Fedora31 {
"langpacks-en",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw", "disk.img", uefi, size)
},
}
r.outputs["qcow2"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"kernel-core",
"@Fedora Cloud Server",
"chrony",
@ -257,25 +269,25 @@ func New() *Fedora31 {
"selinux-policy-targeted",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
"etables",
"firewalld",
"gobject-introspection",
"plymouth",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.outputs["openstack"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -287,21 +299,21 @@ func New() *Fedora31 {
"cloud-init",
"libdrm",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.outputs["tar"] = output{
Name: "root.tar.xz",
MimeType: "application/x-tar",
Packages: []string{
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -309,19 +321,19 @@ func New() *Fedora31 {
"chrony",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: false,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: false,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.outputs["vhd"] = output{
Name: "disk.vhd",
MimeType: "application/x-vhd",
Packages: []string{
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -335,30 +347,30 @@ func New() *Fedora31 {
"glibc-all-langpacks",
"dracut-config-generic",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
EnabledServices: []string{
enabledServices: []string{
"sshd",
"waagent", // needed to run in Azure
},
DisabledServices: []string{
disabledServices: []string{
"proc-sys-fs-binfmt_misc.mount",
"loadmodules.service",
},
// These kernel parameters are required by Azure documentation
KernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vpc", "disk.vhd", uefi, size)
},
}
r.outputs["vmdk"] = output{
Name: "disk.vmdk",
MimeType: "application/x-vmdk",
Packages: []string{
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"firewalld",
@ -367,13 +379,13 @@ func New() *Fedora31 {
"open-vm-tools",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vmdk", "disk.vmdk", uefi, size)
},
}
@ -382,92 +394,37 @@ func New() *Fedora31 {
}
func (r *Fedora31) Name() string {
name, exists := Distro.ToString()
if !exists {
panic("Fatal error, hardcoded distro value in fedora31 package is not valid!")
}
return name
}
func (r *Fedora31) Distribution() common.Distribution {
return Distro
}
func (r *Fedora31) ModulePlatformID() string {
return ModulePlatformID
}
func (r *Fedora31) ListOutputFormats() []string {
formats := make([]string, 0, len(r.outputs))
for name := range r.outputs {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
return modulePlatformID
}
func (r *Fedora31) FilenameFromType(outputFormat string) (string, string, error) {
if output, exists := r.outputs[outputFormat]; exists {
return output.Name, output.MimeType, nil
if output, exists := r.imageTypes[outputFormat]; exists {
return output.name, output.mimeType, nil
}
return "", "", errors.New("invalid output format: " + outputFormat)
}
func (r *Fedora31) GetSizeForOutputType(outputFormat string, size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if outputFormat == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
if size == 0 {
size = r.outputs[outputFormat].DefaultSize
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
return size
}
func (r *Fedora31) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.outputs[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 *Fedora31) 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 (r *Fedora31) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
output, exists := r.outputs[outputFormat]
if !exists {
return nil, errors.New("invalid output format: " + outputFormat)
}
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
}
func (t *fedora31ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(r.buildPipeline(repos, arch, buildPackageSpecs), "org.osbuild.fedora31")
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.fedora31")
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, packageSpecs)))
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
// TODO support setting all languages and install corresponding langpack-* package
@ -499,7 +456,7 @@ func (r *Fedora31) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfi
}
if users := c.GetUsers(); len(users) > 0 {
options, err := r.userStageOptions(users)
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
@ -507,64 +464,36 @@ func (r *Fedora31) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfi
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(r.groupStageOptions(groups)))
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if output.Bootable {
p.AddStage(osbuild.NewFSTabStage(r.fsTabStageOptions(arch.UEFI)))
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
p.AddStage(osbuild.NewGRUB2Stage(r.grub2StageOptions(output.KernelOptions, c.GetKernel(), arch.UEFI)))
p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(t.imageType.kernelOptions, c.GetKernel(), t.arch.arch.uefi)))
if services := c.GetServices(); services != nil || output.EnabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(r.systemdStageOptions(output.EnabledServices, output.DisabledServices, services)))
if services := c.GetServices(); services != nil || t.imageType.enabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.imageType.enabledServices, t.imageType.disabledServices, services)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(r.firewallStageOptions(firewall)))
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(r.selinuxStageOptions()))
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = output.Assembler(arch.UEFI, size)
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *Fedora31) 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 (r *Fedora31) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (r *Fedora31) Runner() string {
return "org.osbuild.fedora31"
}
func (r *Fedora31) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
func (r *fedora31ImageType) 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 *Fedora31) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
func (r *fedora31ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
@ -584,7 +513,7 @@ func (r *Fedora31) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []
}
}
func (r *Fedora31) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
func (r *fedora31ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
@ -624,7 +553,7 @@ func (r *Fedora31) userStageOptions(users []blueprint.UserCustomization) (*osbui
return &options, nil
}
func (r *Fedora31) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
func (r *fedora31ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
@ -644,7 +573,7 @@ func (r *Fedora31) groupStageOptions(groups []blueprint.GroupCustomization) *osb
return &options
}
func (r *Fedora31) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
func (r *fedora31ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
@ -657,7 +586,7 @@ func (r *Fedora31) firewallStageOptions(firewall *blueprint.FirewallCustomizatio
return &options
}
func (r *Fedora31) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
func (r *fedora31ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
@ -668,7 +597,7 @@ func (r *Fedora31) systemdStageOptions(enabledServices, disabledServices []strin
}
}
func (r *Fedora31) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
func (r *fedora31ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("76a22bf4-f153-4541-b6c7-0332c0dfaeac", "ext4", "/", "defaults", 1, 1)
if uefi {
@ -677,7 +606,7 @@ func (r *Fedora31) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
return &options
}
func (r *Fedora31) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
func (r *fedora31ImageType) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
id, err := uuid.Parse("76a22bf4-f153-4541-b6c7-0332c0dfaeac")
if err != nil {
panic("invalid UUID")
@ -702,7 +631,7 @@ func (r *Fedora31) grub2StageOptions(kernelOptions string, kernel *blueprint.Ker
}
}
func (r *Fedora31) selinuxStageOptions() *osbuild.SELinuxStageOptions {
func (r *fedora31ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}

View file

@ -1,31 +1,11 @@
package fedora31_test
import (
"reflect"
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/fedora31"
)
func TestListOutputFormats(t *testing.T) {
want := []string{
"ami",
"ext4-filesystem",
"openstack",
"partitioned-disk",
"qcow2",
"tar",
"vhd",
"vmdk",
}
f31 := fedora31.New()
if got := f31.ListOutputFormats(); !reflect.DeepEqual(got, want) {
t.Errorf("ListOutputFormats() = %v, want %v", got, want)
}
}
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string

View file

@ -5,7 +5,6 @@ import (
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
@ -16,45 +15,45 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
type arch struct {
Name string
BootloaderPackages []string
BuildPackages []string
UEFI bool
}
type output struct {
Name string
MimeType string
Packages []string
ExcludedPackages []string
EnabledServices []string
DisabledServices []string
KernelOptions string
Bootable bool
DefaultSize uint64
Assembler func(uefi bool, size uint64) *osbuild.Assembler
}
const Distro = common.Fedora32
const ModulePlatformID = "platform:f32"
const name = "fedora-32"
const modulePlatformID = "platform:f32"
type Fedora32 struct {
arches map[string]arch
outputs map[string]output
imageTypes map[string]imageType
buildPackages []string
}
type Fedora32Arch struct {
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
kernelOptions string
bootable bool
defaultSize uint64
assembler func(uefi bool, size uint64) *osbuild.Assembler
}
type fedora32Arch struct {
name string
distro *Fedora32
arch *arch
}
type Fedora32ImageType struct {
name string
arch *Fedora32Arch
output *output
type fedora32ImageType struct {
name string
arch *fedora32Arch
imageType *imageType
}
func (d *Fedora32) GetArch(arch string) (distro.Arch, error) {
@ -63,75 +62,88 @@ func (d *Fedora32) GetArch(arch string) (distro.Arch, error) {
return nil, errors.New("invalid architecture: " + arch)
}
return &Fedora32Arch{
return &fedora32Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *Fedora32Arch) Name() string {
func (a *fedora32Arch) Name() string {
return a.name
}
func (a *Fedora32Arch) ListImageTypes() []string {
return a.distro.ListOutputFormats()
func (a *fedora32Arch) 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 *Fedora32Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.outputs[imageType]
func (a *fedora32Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &Fedora32ImageType{
name: imageType,
arch: a,
output: &t,
return &fedora32ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *Fedora32ImageType) Name() string {
func (t *fedora32ImageType) Name() string {
return t.name
}
func (t *Fedora32ImageType) Filename() string {
return t.output.Name
func (t *fedora32ImageType) Filename() string {
return t.imageType.name
}
func (t *Fedora32ImageType) MIMEType() string {
return t.output.MimeType
func (t *fedora32ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *Fedora32ImageType) Size(size uint64) uint64 {
return t.arch.distro.GetSizeForOutputType(t.name, size)
func (t *fedora32ImageType) 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 *Fedora32ImageType) BasePackages() ([]string, []string) {
packages := t.output.Packages
if t.output.Bootable {
packages = append(packages, t.arch.arch.BootloaderPackages...)
func (t *fedora32ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.output.ExcludedPackages
return packages, t.imageType.excludedPackages
}
func (t *Fedora32ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.BuildPackages...)
func (t *fedora32ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *Fedora32ImageType) Manifest(c *blueprint.Customizations,
func (t *fedora32ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.arch.distro.pipeline(c, repos, packageSpecs, buildPackageSpecs, t.arch.name, t.name, size)
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *t.arch.distro.sources(append(packageSpecs, buildPackageSpecs...)),
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
@ -140,7 +152,7 @@ func New() *Fedora32 {
const GigaByte = 1024 * 1024 * 1024
r := Fedora32{
outputs: map[string]output{},
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
@ -152,32 +164,32 @@ func New() *Fedora32 {
},
arches: map[string]arch{
"x86_64": arch{
Name: "x86_64",
BootloaderPackages: []string{
name: "x86_64",
bootloaderPackages: []string{
"grub2-pc",
},
BuildPackages: []string{
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
Name: "aarch64",
BootloaderPackages: []string{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
UEFI: true,
uefi: true,
},
},
}
r.outputs["ami"] = output{
Name: "image.raw.xz",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ami"] = imageType{
name: "image.raw.xz",
mimeType: "application/octet-stream",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -189,24 +201,24 @@ func New() *Fedora32 {
"checkpolicy",
"net-tools",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
EnabledServices: []string{
enabledServices: []string{
"cloud-init.service",
},
KernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
Bootable: true,
DefaultSize: 6 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
bootable: true,
defaultSize: 6 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw.xz", "image.raw.xz", uefi, size)
},
}
r.outputs["ext4-filesystem"] = output{
Name: "filesystem.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -214,19 +226,19 @@ func New() *Fedora32 {
"chrony",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: false,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: false,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.rawFSAssembler("filesystem.img", size) },
}
r.outputs["partitioned-disk"] = output{
Name: "disk.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"firewalld",
@ -234,21 +246,21 @@ func New() *Fedora32 {
"langpacks-en",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("raw", "disk.img", uefi, size)
},
}
r.outputs["qcow2"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"kernel-core",
"@Fedora Cloud Server",
"chrony",
@ -257,25 +269,25 @@ func New() *Fedora32 {
"selinux-policy-targeted",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
"etables",
"firewalld",
"gobject-introspection",
"plymouth",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.outputs["openstack"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -287,21 +299,21 @@ func New() *Fedora32 {
"cloud-init",
"libdrm",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size)
},
}
r.outputs["tar"] = output{
Name: "root.tar.xz",
MimeType: "application/x-tar",
Packages: []string{
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -309,19 +321,19 @@ func New() *Fedora32 {
"chrony",
"langpacks-en",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: false,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: false,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.outputs["vhd"] = output{
Name: "disk.vhd",
MimeType: "application/x-vhd",
Packages: []string{
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
"@Core",
"chrony",
"kernel",
@ -335,30 +347,30 @@ func New() *Fedora32 {
"glibc-all-langpacks",
"dracut-config-generic",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
EnabledServices: []string{
enabledServices: []string{
"sshd",
"waagent", // needed to run in Azure
},
DisabledServices: []string{
disabledServices: []string{
"proc-sys-fs-binfmt_misc.mount",
"loadmodules.service",
},
// These kernel parameters are required by Azure documentation
KernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vpc", "disk.vhd", uefi, size)
},
}
r.outputs["vmdk"] = output{
Name: "disk.vmdk",
MimeType: "application/x-vmdk",
Packages: []string{
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"firewalld",
@ -367,13 +379,13 @@ func New() *Fedora32 {
"open-vm-tools",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
KernelOptions: "ro biosdevname=0 net.ifnames=0",
Bootable: true,
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
kernelOptions: "ro biosdevname=0 net.ifnames=0",
bootable: true,
defaultSize: 2 * GigaByte,
assembler: func(uefi bool, size uint64) *osbuild.Assembler {
return r.qemuAssembler("vmdk", "disk.vmdk", uefi, size)
},
}
@ -382,92 +394,37 @@ func New() *Fedora32 {
}
func (r *Fedora32) Name() string {
name, exists := Distro.ToString()
if !exists {
panic("Fatal error, hardcoded distro value in fedora32 package is not valid!")
}
return name
}
func (r *Fedora32) Distribution() common.Distribution {
return Distro
}
func (r *Fedora32) ModulePlatformID() string {
return ModulePlatformID
}
func (r *Fedora32) ListOutputFormats() []string {
formats := make([]string, 0, len(r.outputs))
for name := range r.outputs {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
return modulePlatformID
}
func (r *Fedora32) FilenameFromType(outputFormat string) (string, string, error) {
if output, exists := r.outputs[outputFormat]; exists {
return output.Name, output.MimeType, nil
if output, exists := r.imageTypes[outputFormat]; exists {
return output.name, output.mimeType, nil
}
return "", "", errors.New("invalid output format: " + outputFormat)
}
func (r *Fedora32) GetSizeForOutputType(outputFormat string, size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if outputFormat == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
if size == 0 {
size = r.outputs[outputFormat].DefaultSize
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
return size
}
func (r *Fedora32) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.outputs[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 *Fedora32) 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 (r *Fedora32) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
output, exists := r.outputs[outputFormat]
if !exists {
return nil, errors.New("invalid output format: " + outputFormat)
}
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
}
func (t *fedora32ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(r.buildPipeline(repos, arch, buildPackageSpecs), "org.osbuild.fedora32")
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.fedora32")
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, packageSpecs)))
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
// TODO support setting all languages and install corresponding langpack-* package
@ -499,7 +456,7 @@ func (r *Fedora32) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfi
}
if users := c.GetUsers(); len(users) > 0 {
options, err := r.userStageOptions(users)
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
@ -507,64 +464,36 @@ func (r *Fedora32) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfi
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(r.groupStageOptions(groups)))
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if output.Bootable {
p.AddStage(osbuild.NewFSTabStage(r.fsTabStageOptions(arch.UEFI)))
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
p.AddStage(osbuild.NewGRUB2Stage(r.grub2StageOptions(output.KernelOptions, c.GetKernel(), arch.UEFI)))
p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(t.imageType.kernelOptions, c.GetKernel(), t.arch.arch.uefi)))
if services := c.GetServices(); services != nil || output.EnabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(r.systemdStageOptions(output.EnabledServices, output.DisabledServices, services)))
if services := c.GetServices(); services != nil || t.imageType.enabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.imageType.enabledServices, t.imageType.disabledServices, services)))
}
if firewall := c.GetFirewall(); firewall != nil {
p.AddStage(osbuild.NewFirewallStage(r.firewallStageOptions(firewall)))
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(r.selinuxStageOptions()))
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = output.Assembler(arch.UEFI, size)
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *Fedora32) 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 (r *Fedora32) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (r *Fedora32) Runner() string {
return "org.osbuild.fedora32"
}
func (r *Fedora32) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
func (r *fedora32ImageType) 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 *Fedora32) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
func (r *fedora32ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
@ -584,7 +513,7 @@ func (r *Fedora32) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []
}
}
func (r *Fedora32) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
func (r *fedora32ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
@ -624,7 +553,7 @@ func (r *Fedora32) userStageOptions(users []blueprint.UserCustomization) (*osbui
return &options, nil
}
func (r *Fedora32) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
func (r *fedora32ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
@ -644,7 +573,7 @@ func (r *Fedora32) groupStageOptions(groups []blueprint.GroupCustomization) *osb
return &options
}
func (r *Fedora32) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
func (r *fedora32ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
@ -657,7 +586,7 @@ func (r *Fedora32) firewallStageOptions(firewall *blueprint.FirewallCustomizatio
return &options
}
func (r *Fedora32) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
func (r *fedora32ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
@ -668,7 +597,7 @@ func (r *Fedora32) systemdStageOptions(enabledServices, disabledServices []strin
}
}
func (r *Fedora32) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
func (r *fedora32ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("76a22bf4-f153-4541-b6c7-0332c0dfaeac", "ext4", "/", "defaults", 1, 1)
if uefi {
@ -677,7 +606,7 @@ func (r *Fedora32) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
return &options
}
func (r *Fedora32) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
func (r *fedora32ImageType) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
id, err := uuid.Parse("76a22bf4-f153-4541-b6c7-0332c0dfaeac")
if err != nil {
panic("invalid UUID")
@ -702,7 +631,7 @@ func (r *Fedora32) grub2StageOptions(kernelOptions string, kernel *blueprint.Ker
}
}
func (r *Fedora32) selinuxStageOptions() *osbuild.SELinuxStageOptions {
func (r *fedora32ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}

View file

@ -1,31 +1,11 @@
package fedora32_test
import (
"reflect"
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/fedora32"
)
func TestListOutputFormats(t *testing.T) {
want := []string{
"ami",
"ext4-filesystem",
"openstack",
"partitioned-disk",
"qcow2",
"tar",
"vhd",
"vmdk",
}
f32 := fedora32.New()
if got := f32.ListOutputFormats(); !reflect.DeepEqual(got, want) {
t.Errorf("ListOutputFormats() = %v, want %v", got, want)
}
}
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string

View file

@ -4,24 +4,24 @@ import (
"errors"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
const ModulePlatformID = "platform:f30"
const name = "fedora-30"
const modulePlatformID = "platform:f30"
type FedoraTestDistro struct{}
type FedoraTestDistroArch struct {
type fedoraTestDistroArch struct {
name string
distro *FedoraTestDistro
}
type FedoraTestDistroImageType struct {
type fedoraTestDistroImageType struct {
name string
arch *FedoraTestDistroArch
arch *fedoraTestDistroArch
}
func (d *FedoraTestDistro) GetArch(arch string) (distro.Arch, error) {
@ -29,56 +29,56 @@ func (d *FedoraTestDistro) GetArch(arch string) (distro.Arch, error) {
return nil, errors.New("invalid architecture: " + arch)
}
return &FedoraTestDistroArch{
return &fedoraTestDistroArch{
name: arch,
distro: d,
}, nil
}
func (a *FedoraTestDistroArch) Name() string {
func (a *fedoraTestDistroArch) Name() string {
return a.name
}
func (a *FedoraTestDistroArch) ListImageTypes() []string {
return a.distro.ListOutputFormats()
func (a *fedoraTestDistroArch) ListImageTypes() []string {
return []string{"qcow2"}
}
func (a *FedoraTestDistroArch) GetImageType(imageType string) (distro.ImageType, error) {
func (a *fedoraTestDistroArch) GetImageType(imageType string) (distro.ImageType, error) {
if imageType != "qcow2" {
return nil, errors.New("invalid image type: " + imageType)
}
return &FedoraTestDistroImageType{
return &fedoraTestDistroImageType{
name: imageType,
arch: a,
}, nil
}
func (t *FedoraTestDistroImageType) Name() string {
func (t *fedoraTestDistroImageType) Name() string {
return t.name
}
func (t *FedoraTestDistroImageType) Filename() string {
func (t *fedoraTestDistroImageType) Filename() string {
return "test.img"
}
func (t *FedoraTestDistroImageType) MIMEType() string {
func (t *fedoraTestDistroImageType) MIMEType() string {
return "application/x-test"
}
func (t *FedoraTestDistroImageType) Size(size uint64) uint64 {
return t.arch.distro.GetSizeForOutputType(t.name, size)
func (t *fedoraTestDistroImageType) Size(size uint64) uint64 {
return size
}
func (t *FedoraTestDistroImageType) BasePackages() ([]string, []string) {
func (t *fedoraTestDistroImageType) BasePackages() ([]string, []string) {
return nil, nil
}
func (t *FedoraTestDistroImageType) BuildPackages() []string {
func (t *fedoraTestDistroImageType) BuildPackages() []string {
return nil
}
func (t *FedoraTestDistroImageType) Manifest(c *blueprint.Customizations,
func (t *fedoraTestDistroImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
@ -94,19 +94,11 @@ func New() *FedoraTestDistro {
}
func (d *FedoraTestDistro) Name() string {
return "fedora-30"
}
func (d *FedoraTestDistro) Distribution() common.Distribution {
return common.Fedora30
return name
}
func (d *FedoraTestDistro) ModulePlatformID() string {
return ModulePlatformID
}
func (d *FedoraTestDistro) ListOutputFormats() []string {
return []string{"qcow2"}
return modulePlatformID
}
func (d *FedoraTestDistro) FilenameFromType(outputFormat string) (string, string, error) {
@ -116,43 +108,3 @@ func (d *FedoraTestDistro) FilenameFromType(outputFormat string) (string, string
return "", "", errors.New("invalid output format: " + outputFormat)
}
}
func (r *FedoraTestDistro) GetSizeForOutputType(outputFormat string, size uint64) uint64 {
return 0
}
func (d *FedoraTestDistro) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
return nil, nil, nil
}
func (d *FedoraTestDistro) BuildPackages(outputArchitecture string) ([]string, error) {
return nil, nil
}
func (d *FedoraTestDistro) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, buildPackages, basePackages []rpmmd.PackageSpec, outputArch, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
if outputFormat == "qcow2" && outputArch == "x86_64" {
return &osbuild.Pipeline{}, nil
} else {
return nil, errors.New("invalid output format or arch: " + outputFormat + " @ " + outputArch)
}
}
func (r *FedoraTestDistro) sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
return &osbuild.Sources{}
}
func (r *FedoraTestDistro) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (d *FedoraTestDistro) Runner() string {
return "org.osbuild.test"
}

View file

@ -5,7 +5,6 @@ import (
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
@ -16,46 +15,46 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
type arch struct {
Name string
BootloaderPackages []string
BuildPackages []string
UEFI bool
}
type output 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
}
const Distro = common.RHEL81
const ModulePlatformID = "platform:el8"
const name = "rhel-8.1"
const modulePlatformID = "platform:el8"
type RHEL81 struct {
arches map[string]arch
outputs map[string]output
imageTypes map[string]imageType
buildPackages []string
}
type RHEL81Arch struct {
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
output *output
type rhel81ImageType struct {
name string
arch *rhel81Arch
imageType *imageType
}
func (d *RHEL81) GetArch(arch string) (distro.Arch, error) {
@ -64,75 +63,88 @@ func (d *RHEL81) GetArch(arch string) (distro.Arch, error) {
return nil, errors.New("invalid architecture: " + arch)
}
return &RHEL81Arch{
return &rhel81Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *RHEL81Arch) Name() string {
func (a *rhel81Arch) Name() string {
return a.name
}
func (a *RHEL81Arch) ListImageTypes() []string {
return a.distro.ListOutputFormats()
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(imageType string) (distro.ImageType, error) {
t, exists := a.distro.outputs[imageType]
func (a *rhel81Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &RHEL81ImageType{
name: imageType,
arch: a,
output: &t,
return &rhel81ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *RHEL81ImageType) Name() string {
func (t *rhel81ImageType) Name() string {
return t.name
}
func (t *RHEL81ImageType) Filename() string {
return t.output.Name
func (t *rhel81ImageType) Filename() string {
return t.imageType.name
}
func (t *RHEL81ImageType) MIMEType() string {
return t.output.MimeType
func (t *rhel81ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *RHEL81ImageType) Size(size uint64) uint64 {
return t.arch.distro.GetSizeForOutputType(t.name, size)
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.output.Packages
if t.output.Bootable {
packages = append(packages, t.arch.arch.BootloaderPackages...)
func (t *rhel81ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.output.ExcludedPackages
return packages, t.imageType.excludedPackages
}
func (t *RHEL81ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.BuildPackages...)
func (t *rhel81ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *RHEL81ImageType) Manifest(c *blueprint.Customizations,
func (t *rhel81ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.arch.distro.pipeline(c, repos, packageSpecs, buildPackageSpecs, t.arch.name, t.name, size)
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *t.arch.distro.sources(append(packageSpecs, buildPackageSpecs...)),
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
@ -141,7 +153,7 @@ func New() *RHEL81 {
const GigaByte = 1024 * 1024 * 1024
r := RHEL81{
outputs: map[string]output{},
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
@ -157,32 +169,32 @@ func New() *RHEL81 {
},
arches: map[string]arch{
"x86_64": arch{
Name: "x86_64",
BootloaderPackages: []string{
name: "x86_64",
bootloaderPackages: []string{
"grub2-pc",
},
BuildPackages: []string{
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
Name: "aarch64",
BootloaderPackages: []string{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
UEFI: true,
uefi: true,
},
},
}
r.outputs["ami"] = output{
Name: "image.raw.xz",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ami"] = imageType{
name: "image.raw.xz",
mimeType: "application/octet-stream",
packages: []string{
"checkpolicy",
"chrony",
"cloud-init",
@ -208,7 +220,7 @@ func New() *RHEL81 {
// TODO this doesn't exist in BaseOS or AppStream
// "rh-amazon-rhui-client",
},
ExcludedPackages: []string{
excludedPackages: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
@ -247,19 +259,19 @@ func New() *RHEL81 {
// 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 {
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("raw.xz", "image.raw.xz", uefi, size)
},
}
r.outputs["ext4-filesystem"] = output{
Name: "filesystem.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -268,23 +280,23 @@ func New() *RHEL81 {
"dracut-config-generic",
"langpacks-en",
},
ExcludedPackages: []string{
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) },
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.outputs["partitioned-disk"] = output{
Name: "disk.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"dracut-config-generic",
@ -293,25 +305,25 @@ func New() *RHEL81 {
"langpacks-en",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
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 {
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.outputs["qcow2"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@core",
"chrony",
"dnf",
@ -344,7 +356,7 @@ func New() *RHEL81 {
"insights-client",
// TODO: rh-amazon-rhui-client
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
"aic94xx-firmware",
"alsa-firmware",
@ -384,18 +396,18 @@ func New() *RHEL81 {
// 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 {
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.outputs["openstack"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
@ -411,21 +423,21 @@ func New() *RHEL81 {
"qemu-guest-agent",
"spice-vdagent",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
Bootable: true,
KernelOptions: "ro net.ifnames=0",
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
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.outputs["tar"] = output{
Name: "root.tar.xz",
MimeType: "application/x-tar",
Packages: []string{
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -434,22 +446,22 @@ func New() *RHEL81 {
"dracut-config-generic",
"langpacks-en",
},
ExcludedPackages: []string{
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") },
bootable: false,
kernelOptions: "ro net.ifnames=0",
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.outputs["vhd"] = output{
Name: "disk.vhd",
MimeType: "application/x-vhd",
Packages: []string{
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
@ -469,30 +481,30 @@ func New() *RHEL81 {
"cloud-utils-growpart",
"gdisk",
},
ExcludedPackages: []string{
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{
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 {
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.outputs["vmdk"] = output{
Name: "disk.vmdk",
MimeType: "application/x-vmdk",
Packages: []string{
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"dracut-config-generic",
@ -502,17 +514,17 @@ func New() *RHEL81 {
"open-vm-tools",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
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 {
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)
},
}
@ -521,103 +533,48 @@ func New() *RHEL81 {
}
func (r *RHEL81) Name() string {
name, exists := Distro.ToString()
if !exists {
panic("Fatal error, hardcoded distro value in rhel81 package is not valid!")
}
return name
}
func (r *RHEL81) Distribution() common.Distribution {
return Distro
}
func (r *RHEL81) ModulePlatformID() string {
return ModulePlatformID
}
func (r *RHEL81) ListOutputFormats() []string {
formats := make([]string, 0, len(r.outputs))
for name := range r.outputs {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
return modulePlatformID
}
func (r *RHEL81) FilenameFromType(outputFormat string) (string, string, error) {
if output, exists := r.outputs[outputFormat]; exists {
return output.Name, output.MimeType, nil
if output, exists := r.imageTypes[outputFormat]; exists {
return output.name, output.mimeType, nil
}
return "", "", errors.New("invalid output format: " + outputFormat)
}
func (r *RHEL81) GetSizeForOutputType(outputFormat string, size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if outputFormat == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
if size == 0 {
size = r.outputs[outputFormat].DefaultSize
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
return size
}
func (r *RHEL81) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.outputs[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 *RHEL81) 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 (r *RHEL81) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
output, exists := r.outputs[outputFormat]
if !exists {
return nil, errors.New("invalid output format: " + outputFormat)
}
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
}
func (t *rhel81ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(r.buildPipeline(repos, arch, buildPackageSpecs), "org.osbuild.rhel81")
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.rhel81")
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, packageSpecs)))
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
if output.Bootable {
p.AddStage(osbuild.NewFSTabStage(r.fsTabStageOptions(arch.UEFI)))
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
kernelOptions := output.KernelOptions
kernelOptions := t.imageType.kernelOptions
if kernel := c.GetKernel(); kernel != nil {
kernelOptions += " " + kernel.Append
}
p.AddStage(osbuild.NewGRUB2Stage(r.grub2StageOptions(kernelOptions, arch.UEFI)))
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()
@ -648,7 +605,7 @@ func (r *RHEL81) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig,
}
if users := c.GetUsers(); len(users) > 0 {
options, err := r.userStageOptions(users)
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
@ -656,59 +613,31 @@ func (r *RHEL81) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig,
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(r.groupStageOptions(groups)))
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if services := c.GetServices(); services != nil || output.EnabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(r.systemdStageOptions(output.EnabledServices, output.DisabledServices, services, output.DefaultTarget)))
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(r.firewallStageOptions(firewall)))
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(r.selinuxStageOptions()))
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = output.Assembler(arch.UEFI, size)
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *RHEL81) 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 (r *RHEL81) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (r *RHEL81) Runner() string {
return "org.osbuild.rhel81"
}
func (r *RHEL81) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
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 *RHEL81) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
func (r *rhel81ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
@ -728,7 +657,7 @@ func (r *RHEL81) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rp
}
}
func (r *RHEL81) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
func (r *rhel81ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
@ -768,7 +697,7 @@ func (r *RHEL81) userStageOptions(users []blueprint.UserCustomization) (*osbuild
return &options, nil
}
func (r *RHEL81) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
func (r *rhel81ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
@ -788,7 +717,7 @@ func (r *RHEL81) groupStageOptions(groups []blueprint.GroupCustomization) *osbui
return &options
}
func (r *RHEL81) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
func (r *rhel81ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
@ -801,7 +730,7 @@ func (r *RHEL81) firewallStageOptions(firewall *blueprint.FirewallCustomization)
return &options
}
func (r *RHEL81) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
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...)
@ -813,7 +742,7 @@ func (r *RHEL81) systemdStageOptions(enabledServices, disabledServices []string,
}
}
func (r *RHEL81) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
func (r *rhel81ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("0bd700f8-090f-4556-b797-b340297ea1bd", "xfs", "/", "defaults", 0, 0)
if uefi {
@ -822,7 +751,7 @@ func (r *RHEL81) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
return &options
}
func (r *RHEL81) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
func (r *rhel81ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
id, err := uuid.Parse("0bd700f8-090f-4556-b797-b340297ea1bd")
if err != nil {
panic("invalid UUID")
@ -843,7 +772,7 @@ func (r *RHEL81) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRU
}
}
func (r *RHEL81) selinuxStageOptions() *osbuild.SELinuxStageOptions {
func (r *rhel81ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}

View file

@ -1,31 +1,11 @@
package rhel81_test
import (
"reflect"
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/rhel81"
)
func TestListOutputFormats(t *testing.T) {
want := []string{
"ami",
"ext4-filesystem",
"openstack",
"partitioned-disk",
"qcow2",
"tar",
"vhd",
"vmdk",
}
el81 := rhel81.New()
if got := el81.ListOutputFormats(); !reflect.DeepEqual(got, want) {
t.Errorf("ListOutputFormats() = %v, want %v", got, want)
}
}
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string

View file

@ -5,7 +5,6 @@ import (
"sort"
"strconv"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild"
@ -16,46 +15,46 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
type arch struct {
Name string
BootloaderPackages []string
BuildPackages []string
UEFI bool
}
type output 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
}
const Distro = common.RHEL82
const ModulePlatformID = "platform:el8"
const name = "rhel-8.2"
const modulePlatformID = "platform:el8"
type RHEL82 struct {
arches map[string]arch
outputs map[string]output
imageTypes map[string]imageType
buildPackages []string
}
type RHEL82Arch struct {
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 rhel82Arch struct {
name string
distro *RHEL82
arch *arch
}
type RHEL82ImageType struct {
name string
arch *RHEL82Arch
output *output
type rhel82ImageType struct {
name string
arch *rhel82Arch
imageType *imageType
}
func (d *RHEL82) GetArch(arch string) (distro.Arch, error) {
@ -64,75 +63,88 @@ func (d *RHEL82) GetArch(arch string) (distro.Arch, error) {
return nil, errors.New("invalid architecture: " + arch)
}
return &RHEL82Arch{
return &rhel82Arch{
name: arch,
distro: d,
arch: &a,
}, nil
}
func (a *RHEL82Arch) Name() string {
func (a *rhel82Arch) Name() string {
return a.name
}
func (a *RHEL82Arch) ListImageTypes() []string {
return a.distro.ListOutputFormats()
func (a *rhel82Arch) 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 *RHEL82Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.outputs[imageType]
func (a *rhel82Arch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.distro.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return &RHEL82ImageType{
name: imageType,
arch: a,
output: &t,
return &rhel82ImageType{
name: imageType,
arch: a,
imageType: &t,
}, nil
}
func (t *RHEL82ImageType) Name() string {
func (t *rhel82ImageType) Name() string {
return t.name
}
func (t *RHEL82ImageType) Filename() string {
return t.output.Name
func (t *rhel82ImageType) Filename() string {
return t.imageType.name
}
func (t *RHEL82ImageType) MIMEType() string {
return t.output.MimeType
func (t *rhel82ImageType) MIMEType() string {
return t.imageType.mimeType
}
func (t *RHEL82ImageType) Size(size uint64) uint64 {
return t.arch.distro.GetSizeForOutputType(t.name, size)
func (t *rhel82ImageType) 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 *RHEL82ImageType) BasePackages() ([]string, []string) {
packages := t.output.Packages
if t.output.Bootable {
packages = append(packages, t.arch.arch.BootloaderPackages...)
func (t *rhel82ImageType) BasePackages() ([]string, []string) {
packages := t.imageType.packages
if t.imageType.bootable {
packages = append(packages, t.arch.arch.bootloaderPackages...)
}
return packages, t.output.ExcludedPackages
return packages, t.imageType.excludedPackages
}
func (t *RHEL82ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.BuildPackages...)
func (t *rhel82ImageType) BuildPackages() []string {
return append(t.arch.distro.buildPackages, t.arch.arch.buildPackages...)
}
func (t *RHEL82ImageType) Manifest(c *blueprint.Customizations,
func (t *rhel82ImageType) Manifest(c *blueprint.Customizations,
repos []rpmmd.RepoConfig,
packageSpecs,
buildPackageSpecs []rpmmd.PackageSpec,
size uint64) (*osbuild.Manifest, error) {
pipeline, err := t.arch.distro.pipeline(c, repos, packageSpecs, buildPackageSpecs, t.arch.name, t.name, size)
pipeline, err := t.pipeline(c, repos, packageSpecs, buildPackageSpecs, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *t.arch.distro.sources(append(packageSpecs, buildPackageSpecs...)),
Sources: *sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
@ -141,7 +153,7 @@ func New() *RHEL82 {
const GigaByte = 1024 * 1024 * 1024
r := RHEL82{
outputs: map[string]output{},
imageTypes: map[string]imageType{},
buildPackages: []string{
"dnf",
"dosfstools",
@ -157,32 +169,32 @@ func New() *RHEL82 {
},
arches: map[string]arch{
"x86_64": arch{
Name: "x86_64",
BootloaderPackages: []string{
name: "x86_64",
bootloaderPackages: []string{
"grub2-pc",
},
BuildPackages: []string{
buildPackages: []string{
"grub2-pc",
},
},
"aarch64": arch{
Name: "aarch64",
BootloaderPackages: []string{
name: "aarch64",
bootloaderPackages: []string{
"dracut-config-generic",
"efibootmgr",
"grub2-efi-aa64",
"grub2-tools",
"shim-aa64",
},
UEFI: true,
uefi: true,
},
},
}
r.outputs["ami"] = output{
Name: "image.raw.xz",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ami"] = imageType{
name: "image.raw.xz",
mimeType: "application/octet-stream",
packages: []string{
"checkpolicy",
"chrony",
"cloud-init",
@ -208,7 +220,7 @@ func New() *RHEL82 {
// TODO this doesn't exist in BaseOS or AppStream
// "rh-amazon-rhui-client",
},
ExcludedPackages: []string{
excludedPackages: []string{
"aic94xx-firmware",
"alsa-firmware",
"alsa-lib",
@ -247,19 +259,19 @@ func New() *RHEL82 {
// 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 {
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("raw.xz", "image.raw.xz", uefi, size)
},
}
r.outputs["ext4-filesystem"] = output{
Name: "filesystem.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["ext4-filesystem"] = imageType{
name: "filesystem.img",
mimeType: "application/octet-stream",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -268,23 +280,23 @@ func New() *RHEL82 {
"dracut-config-generic",
"langpacks-en",
},
ExcludedPackages: []string{
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) },
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.outputs["partitioned-disk"] = output{
Name: "disk.img",
MimeType: "application/octet-stream",
Packages: []string{
r.imageTypes["partitioned-disk"] = imageType{
name: "disk.img",
mimeType: "application/octet-stream",
packages: []string{
"@core",
"chrony",
"dracut-config-generic",
@ -293,25 +305,25 @@ func New() *RHEL82 {
"langpacks-en",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
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 {
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.outputs["qcow2"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["qcow2"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
"@core",
"chrony",
"dnf",
@ -344,7 +356,7 @@ func New() *RHEL82 {
"insights-client",
// TODO: rh-amazon-rhui-client
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
"aic94xx-firmware",
"alsa-firmware",
@ -384,18 +396,18 @@ func New() *RHEL82 {
// 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 {
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.outputs["openstack"] = output{
Name: "disk.qcow2",
MimeType: "application/x-qemu-disk",
Packages: []string{
r.imageTypes["openstack"] = imageType{
name: "disk.qcow2",
mimeType: "application/x-qemu-disk",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
@ -411,21 +423,21 @@ func New() *RHEL82 {
"qemu-guest-agent",
"spice-vdagent",
},
ExcludedPackages: []string{
excludedPackages: []string{
"dracut-config-rescue",
},
Bootable: true,
KernelOptions: "ro net.ifnames=0",
DefaultSize: 2 * GigaByte,
Assembler: func(uefi bool, size uint64) *osbuild.Assembler {
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.outputs["tar"] = output{
Name: "root.tar.xz",
MimeType: "application/x-tar",
Packages: []string{
r.imageTypes["tar"] = imageType{
name: "root.tar.xz",
mimeType: "application/x-tar",
packages: []string{
"policycoreutils",
"selinux-policy-targeted",
"kernel",
@ -434,22 +446,22 @@ func New() *RHEL82 {
"dracut-config-generic",
"langpacks-en",
},
ExcludedPackages: []string{
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") },
bootable: false,
kernelOptions: "ro net.ifnames=0",
assembler: func(uefi bool, size uint64) *osbuild.Assembler { return r.tarAssembler("root.tar.xz", "xz") },
}
r.outputs["vhd"] = output{
Name: "disk.vhd",
MimeType: "application/x-vhd",
Packages: []string{
r.imageTypes["vhd"] = imageType{
name: "disk.vhd",
mimeType: "application/x-vhd",
packages: []string{
// Defaults
"@Core",
"langpacks-en",
@ -469,30 +481,30 @@ func New() *RHEL82 {
"cloud-utils-growpart",
"gdisk",
},
ExcludedPackages: []string{
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{
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 {
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.outputs["vmdk"] = output{
Name: "disk.vmdk",
MimeType: "application/x-vmdk",
Packages: []string{
r.imageTypes["vmdk"] = imageType{
name: "disk.vmdk",
mimeType: "application/x-vmdk",
packages: []string{
"@core",
"chrony",
"dracut-config-generic",
@ -502,17 +514,17 @@ func New() *RHEL82 {
"open-vm-tools",
"selinux-policy-targeted",
},
ExcludedPackages: []string{
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 {
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)
},
}
@ -521,66 +533,37 @@ func New() *RHEL82 {
}
func (r *RHEL82) Name() string {
name, exists := Distro.ToString()
if !exists {
panic("Fatal error, hardcoded distro value in rhel82 package is not valid!")
}
return name
}
func (r *RHEL82) Distribution() common.Distribution {
return Distro
}
func (r *RHEL82) ModulePlatformID() string {
return ModulePlatformID
}
func (r *RHEL82) ListOutputFormats() []string {
formats := make([]string, 0, len(r.outputs))
for name := range r.outputs {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
return modulePlatformID
}
func (r *RHEL82) FilenameFromType(outputFormat string) (string, string, error) {
if output, exists := r.outputs[outputFormat]; exists {
return output.Name, output.MimeType, nil
if output, exists := r.imageTypes[outputFormat]; exists {
return output.name, output.mimeType, nil
}
return "", "", errors.New("invalid output format: " + outputFormat)
}
func (r *RHEL82) GetSizeForOutputType(outputFormat string, size uint64) uint64 {
const MegaByte = 1024 * 1024
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
if outputFormat == "vhd" && size%MegaByte != 0 {
size = (size/MegaByte + 1) * MegaByte
}
if size == 0 {
size = r.outputs[outputFormat].DefaultSize
}
return size
}
func (r *RHEL82) BasePackages(outputFormat string, outputArchitecture string) ([]string, []string, error) {
output, exists := r.outputs[outputFormat]
output, exists := r.imageTypes[outputFormat]
if !exists {
return nil, nil, errors.New("invalid output format: " + outputFormat)
}
packages := output.Packages
if output.Bootable {
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...)
packages = append(packages, arch.bootloaderPackages...)
}
return packages, output.ExcludedPackages, nil
return packages, output.excludedPackages, nil
}
func (r *RHEL82) BuildPackages(outputArchitecture string) ([]string, error) {
@ -589,35 +572,37 @@ func (r *RHEL82) BuildPackages(outputArchitecture string) ([]string, error) {
return nil, errors.New("invalid architecture: " + outputArchitecture)
}
return append(r.buildPackages, arch.BuildPackages...), nil
return append(r.buildPackages, arch.buildPackages...), nil
}
func (r *RHEL82) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
output, exists := r.outputs[outputFormat]
if !exists {
return nil, errors.New("invalid output format: " + outputFormat)
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
files := &osbuild.FilesSource{
URLs: make(map[string]string),
}
arch, exists := r.arches[outputArchitecture]
if !exists {
return nil, errors.New("invalid architecture: " + outputArchitecture)
for _, pkg := range packages {
files.URLs[pkg.Checksum] = pkg.RemoteLocation
}
return &osbuild.Sources{
"org.osbuild.files": files,
}
}
func (t *rhel82ImageType) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Pipeline, error) {
p := &osbuild.Pipeline{}
p.SetBuild(r.buildPipeline(repos, arch, buildPackageSpecs), "org.osbuild.rhel82")
p.SetBuild(t.buildPipeline(repos, *t.arch.arch, buildPackageSpecs), "org.osbuild.rhel82")
p.AddStage(osbuild.NewRPMStage(r.rpmStageOptions(arch, repos, packageSpecs)))
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch.arch, repos, packageSpecs)))
p.AddStage(osbuild.NewFixBLSStage())
if output.Bootable {
p.AddStage(osbuild.NewFSTabStage(r.fsTabStageOptions(arch.UEFI)))
if t.imageType.bootable {
p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.arch.uefi)))
}
kernelOptions := output.KernelOptions
kernelOptions := t.imageType.kernelOptions
if kernel := c.GetKernel(); kernel != nil {
kernelOptions += " " + kernel.Append
}
p.AddStage(osbuild.NewGRUB2Stage(r.grub2StageOptions(kernelOptions, arch.UEFI)))
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()
@ -648,7 +633,7 @@ func (r *RHEL82) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig,
}
if users := c.GetUsers(); len(users) > 0 {
options, err := r.userStageOptions(users)
options, err := t.userStageOptions(users)
if err != nil {
return nil, err
}
@ -656,59 +641,31 @@ func (r *RHEL82) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig,
}
if groups := c.GetGroups(); len(groups) > 0 {
p.AddStage(osbuild.NewGroupsStage(r.groupStageOptions(groups)))
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
}
if services := c.GetServices(); services != nil || output.EnabledServices != nil {
p.AddStage(osbuild.NewSystemdStage(r.systemdStageOptions(output.EnabledServices, output.DisabledServices, services, output.DefaultTarget)))
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(r.firewallStageOptions(firewall)))
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
}
p.AddStage(osbuild.NewSELinuxStage(r.selinuxStageOptions()))
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
p.Assembler = output.Assembler(arch.UEFI, size)
p.Assembler = t.imageType.assembler(t.arch.arch.uefi, size)
return p, nil
}
func (r *RHEL82) 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 (r *RHEL82) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (r *RHEL82) Runner() string {
return "org.osbuild.rhel82"
}
func (r *RHEL82) buildPipeline(repos []rpmmd.RepoConfig, arch arch, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
func (r *rhel82ImageType) 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 *RHEL82) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
func (r *rhel82ImageType) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
var gpgKeys []string
for _, repo := range repos {
if repo.GPGKey == "" {
@ -727,7 +684,7 @@ func (r *RHEL82) rpmStageOptions(arch arch, repos []rpmmd.RepoConfig, specs []rp
Packages: packages,
}
}
func (r *RHEL82) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
func (r *rhel82ImageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
options := osbuild.UsersStageOptions{
Users: make(map[string]osbuild.UsersStageOptionsUser),
}
@ -767,7 +724,7 @@ func (r *RHEL82) userStageOptions(users []blueprint.UserCustomization) (*osbuild
return &options, nil
}
func (r *RHEL82) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
func (r *rhel82ImageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
options := osbuild.GroupsStageOptions{
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
}
@ -787,7 +744,7 @@ func (r *RHEL82) groupStageOptions(groups []blueprint.GroupCustomization) *osbui
return &options
}
func (r *RHEL82) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
func (r *rhel82ImageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
options := osbuild.FirewallStageOptions{
Ports: firewall.Ports,
}
@ -800,7 +757,7 @@ func (r *RHEL82) firewallStageOptions(firewall *blueprint.FirewallCustomization)
return &options
}
func (r *RHEL82) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
func (r *rhel82ImageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
if s != nil {
enabledServices = append(enabledServices, s.Enabled...)
disabledServices = append(disabledServices, s.Disabled...)
@ -812,7 +769,7 @@ func (r *RHEL82) systemdStageOptions(enabledServices, disabledServices []string,
}
}
func (r *RHEL82) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
func (r *rhel82ImageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
options := osbuild.FSTabStageOptions{}
options.AddFilesystem("0bd700f8-090f-4556-b797-b340297ea1bd", "xfs", "/", "defaults", 0, 0)
if uefi {
@ -821,7 +778,7 @@ func (r *RHEL82) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
return &options
}
func (r *RHEL82) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
func (r *rhel82ImageType) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRUB2StageOptions {
id, err := uuid.Parse("0bd700f8-090f-4556-b797-b340297ea1bd")
if err != nil {
panic("invalid UUID")
@ -842,7 +799,7 @@ func (r *RHEL82) grub2StageOptions(kernelOptions string, uefi bool) *osbuild.GRU
}
}
func (r *RHEL82) selinuxStageOptions() *osbuild.SELinuxStageOptions {
func (r *rhel82ImageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
return &osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}

View file

@ -1,31 +1,11 @@
package rhel82_test
import (
"reflect"
"testing"
"github.com/osbuild/osbuild-composer/internal/distro/rhel82"
)
func TestListOutputFormats(t *testing.T) {
want := []string{
"ami",
"ext4-filesystem",
"openstack",
"partitioned-disk",
"qcow2",
"tar",
"vhd",
"vmdk",
}
el82 := rhel82.New()
if got := el82.ListOutputFormats(); !reflect.DeepEqual(got, want) {
t.Errorf("ListOutputFormats() = %v, want %v", got, want)
}
}
func TestFilenameFromType(t *testing.T) {
type args struct {
outputFormat string

View file

@ -10,60 +10,63 @@ import (
)
type TestDistro struct{}
type TestArch struct{}
type TestImageType struct{}
type testArch struct{}
type testImageType struct{}
const Name = "test-distro"
const ModulePlatformID = "platform:test"
const name = "test-distro"
const modulePlatformID = "platform:test"
func (d *TestDistro) GetArch(arch string) (distro.Arch, error) {
if arch != "test_arch" {
return nil, errors.New("invalid arch: " + arch)
}
return &TestArch{}, nil
return &testArch{}, nil
}
func (a *TestArch) Name() string {
return Name
func (a *testArch) Name() string {
return "test_format"
}
func (a *TestArch) ListImageTypes() []string {
func (a *testArch) ListImageTypes() []string {
return []string{"test-format"}
}
func (a *TestArch) GetImageType(imageType string) (distro.ImageType, error) {
func (a *testArch) GetImageType(imageType string) (distro.ImageType, error) {
if imageType != "test_output" {
return nil, errors.New("invalid image type: " + imageType)
}
return &TestImageType{}, nil
return &testImageType{}, nil
}
func (t *TestImageType) Name() string {
func (t *testImageType) Name() string {
return "test-format"
}
func (t *TestImageType) Filename() string {
func (t *testImageType) Filename() string {
return "test.img"
}
func (t *TestImageType) MIMEType() string {
func (t *testImageType) MIMEType() string {
return "application/x-test"
}
func (t *TestImageType) Size(size uint64) uint64 {
func (t *testImageType) Size(size uint64) uint64 {
return 0
}
func (t *TestImageType) BasePackages() ([]string, []string) {
func (t *testImageType) BasePackages() ([]string, []string) {
return nil, nil
}
func (t *TestImageType) BuildPackages() []string {
func (t *testImageType) BuildPackages() []string {
return nil
}
func (t *TestImageType) Manifest(b *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Manifest, error) {
return &osbuild.Manifest{}, nil
func (t *testImageType) Manifest(b *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, size uint64) (*osbuild.Manifest, error) {
return &osbuild.Manifest{
Sources: osbuild.Sources{},
Pipeline: osbuild.Pipeline{},
}, nil
}
func New() *TestDistro {
@ -71,15 +74,11 @@ func New() *TestDistro {
}
func (d *TestDistro) Name() string {
return Name
return name
}
func (d *TestDistro) ModulePlatformID() string {
return ModulePlatformID
}
func (d *TestDistro) ListOutputFormats() []string {
return []string{"test_format"}
return modulePlatformID
}
func (d *TestDistro) FilenameFromType(outputFormat string) (string, string, error) {
@ -89,39 +88,3 @@ func (d *TestDistro) FilenameFromType(outputFormat string) (string, string, erro
return "", "", errors.New("invalid output format: " + outputFormat)
}
func (d *TestDistro) BasePackages(outputFormat, outputArchitecture string) ([]string, []string, error) {
return nil, nil, nil
}
func (d *TestDistro) BuildPackages(outputArchitecture string) ([]string, error) {
return nil, nil
}
func (d *TestDistro) pipeline(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArch, outputFormat string, size uint64) (*osbuild.Pipeline, error) {
if outputFormat == "test_output" && outputArch == "test_arch" {
return &osbuild.Pipeline{}, nil
}
return nil, errors.New("invalid output format or arch: " + outputFormat + " @ " + outputArch)
}
func (d *TestDistro) sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
return &osbuild.Sources{}
}
func (r *TestDistro) Manifest(c *blueprint.Customizations, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, outputArchitecture, outputFormat string, size uint64) (*osbuild.Manifest, error) {
pipeline, err := r.pipeline(c, repos, packageSpecs, buildPackageSpecs, outputArchitecture, outputFormat, size)
if err != nil {
return nil, err
}
return &osbuild.Manifest{
Sources: *r.sources(append(packageSpecs, buildPackageSpecs...)),
Pipeline: *pipeline,
}, nil
}
func (d *TestDistro) Runner() string {
return "org.osbuild.test"
}