From fae51095d2c60551e8e856de9a3f4484c2419108 Mon Sep 17 00:00:00 2001 From: Jacob Kozol Date: Fri, 14 Feb 2020 15:11:32 +0100 Subject: [PATCH] distro: add fedora 32 support Images can be built for fedora 32. The pipeline generation and distro tests are based off of the fedora 30 ones. Repository information has also been added for the fedora 32 repos. --- internal/common/types.go | 2 + internal/distro/distro.go | 2 + internal/distro/fedora32/distro.go | 719 ++++++++++++++++++++++++ internal/distro/fedora32/distro_test.go | 113 ++++ repositories/fedora-32.json | 18 + 5 files changed, 854 insertions(+) create mode 100644 internal/distro/fedora32/distro.go create mode 100644 internal/distro/fedora32/distro_test.go create mode 100644 repositories/fedora-32.json diff --git a/internal/common/types.go b/internal/common/types.go index 292e9d35a..c3b2af0c2 100644 --- a/internal/common/types.go +++ b/internal/common/types.go @@ -236,6 +236,7 @@ type Distribution int const ( Fedora30 Distribution = iota Fedora31 + Fedora32 RHEL82 ) @@ -245,6 +246,7 @@ func getDistributionMapping() map[string]int { mapping := map[string]int{ "fedora-30": int(Fedora30), "fedora-31": int(Fedora31), + "fedora-32": int(Fedora32), "rhel-8.2": int(RHEL82), } return mapping diff --git a/internal/distro/distro.go b/internal/distro/distro.go index a18d9f7f9..3efacb92d 100644 --- a/internal/distro/distro.go +++ b/internal/distro/distro.go @@ -15,6 +15,7 @@ import ( "github.com/osbuild/osbuild-composer/internal/distro/fedora30" "github.com/osbuild/osbuild-composer/internal/distro/fedora31" + "github.com/osbuild/osbuild-composer/internal/distro/fedora32" "github.com/osbuild/osbuild-composer/internal/distro/rhel82" ) @@ -74,6 +75,7 @@ func NewRegistry(confPaths []string) *Registry { } distros.register(fedora30.New(confPaths)) distros.register(fedora31.New(confPaths)) + distros.register(fedora32.New(confPaths)) distros.register(rhel82.New(confPaths)) return distros } diff --git a/internal/distro/fedora32/distro.go b/internal/distro/fedora32/distro.go new file mode 100644 index 000000000..d2a7b737e --- /dev/null +++ b/internal/distro/fedora32/distro.go @@ -0,0 +1,719 @@ +package fedora32 + +import ( + "errors" + "log" + "sort" + "strconv" + + "github.com/osbuild/osbuild-composer/internal/common" + "github.com/osbuild/osbuild-composer/internal/osbuild" + + "github.com/google/uuid" + + "github.com/osbuild/osbuild-composer/internal/blueprint" + "github.com/osbuild/osbuild-composer/internal/crypt" + "github.com/osbuild/osbuild-composer/internal/rpmmd" +) + +type Fedora32 struct { + arches map[string]arch + outputs map[string]output + buildPackages []string +} + +type arch struct { + Name string + BootloaderPackages []string + BuildPackages []string + UEFI bool + Repositories []rpmmd.RepoConfig +} + +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" + +func New(confPaths []string) *Fedora32 { + const GigaByte = 1024 * 1024 * 1024 + + r := Fedora32{ + arches: map[string]arch{}, + outputs: map[string]output{}, + buildPackages: []string{ + "dnf", + "dosfstools", + "e2fsprogs", + "policycoreutils", + "qemu-img", + "systemd", + "tar", + }, + } + + repoMap, err := rpmmd.LoadRepositories(confPaths, r.Name()) + if err != nil { + log.Printf("Could not load repository data for %s: %s", r.Name(), err.Error()) + return nil + } + + repos, exists := repoMap["x86_64"] + if !exists { + log.Printf("Could not load architecture-specific repository data for x86_64 (%s): %s", r.Name(), err.Error()) + } else { + r.arches["x86_64"] = arch{ + Name: "x86_64", + BootloaderPackages: []string{ + "grub2-pc", + }, + BuildPackages: []string{ + "grub2-pc", + }, + Repositories: repos, + } + } + + repos, exists = repoMap["aarch64"] + if !exists { + log.Printf("Could not load architecture-specific repository data for x86_64 (%s): %s", r.Name(), err.Error()) + } else { + r.arches["aarch64"] = arch{ + Name: "aarch64", + BootloaderPackages: []string{ + "dracut-config-generic", + "efibootmgr", + "grub2-efi-aa64", + "grub2-tools", + "shim-aa64", + }, + UEFI: true, + Repositories: repos, + } + } + + r.outputs["ami"] = output{ + Name: "image.raw.xz", + MimeType: "application/octet-stream", + Packages: []string{ + "@Core", + "chrony", + "kernel", + "selinux-policy-targeted", + "langpacks-en", + "libxcrypt-compat", + "xfsprogs", + "cloud-init", + "checkpolicy", + "net-tools", + }, + ExcludedPackages: []string{ + "dracut-config-rescue", + }, + 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 { + return r.qemuAssembler("raw.xz", "image.raw.xz", uefi, size) + }, + } + + r.outputs["ext4-filesystem"] = output{ + Name: "filesystem.img", + MimeType: "application/octet-stream", + Packages: []string{ + "policycoreutils", + "selinux-policy-targeted", + "kernel", + "firewalld", + "chrony", + "langpacks-en", + }, + 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) }, + } + + r.outputs["partitioned-disk"] = output{ + Name: "disk.img", + MimeType: "application/octet-stream", + Packages: []string{ + "@core", + "chrony", + "firewalld", + "kernel", + "langpacks-en", + "selinux-policy-targeted", + }, + 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 { + return r.qemuAssembler("raw", "disk.img", uefi, size) + }, + } + + r.outputs["qcow2"] = output{ + Name: "disk.qcow2", + MimeType: "application/x-qemu-disk", + Packages: []string{ + "kernel-core", + "@Fedora Cloud Server", + "chrony", + "polkit", + "systemd-udev", + "selinux-policy-targeted", + "langpacks-en", + }, + 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 { + return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size) + }, + } + + r.outputs["openstack"] = output{ + Name: "disk.qcow2", + MimeType: "application/x-qemu-disk", + Packages: []string{ + "@Core", + "chrony", + "kernel", + "selinux-policy-targeted", + "spice-vdagent", + "qemu-guest-agent", + "xen-libs", + "langpacks-en", + "cloud-init", + "libdrm", + }, + 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 { + return r.qemuAssembler("qcow2", "disk.qcow2", uefi, size) + }, + } + + r.outputs["tar"] = output{ + Name: "root.tar.xz", + MimeType: "application/x-tar", + Packages: []string{ + "policycoreutils", + "selinux-policy-targeted", + "kernel", + "firewalld", + "chrony", + "langpacks-en", + }, + 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") }, + } + + r.outputs["vhd"] = output{ + Name: "disk.vhd", + MimeType: "application/x-vhd", + Packages: []string{ + "@Core", + "chrony", + "kernel", + "selinux-policy-targeted", + "langpacks-en", + "net-tools", + "ntfsprogs", + "WALinuxAgent", + "libxcrypt-compat", + "initscripts", + "glibc-all-langpacks", + "dracut-config-generic", + }, + ExcludedPackages: []string{ + "dracut-config-rescue", + }, + EnabledServices: []string{ + "sshd", + "waagent", // needed to run in Azure + }, + 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 { + return r.qemuAssembler("vpc", "disk.vhd", uefi, size) + }, + } + + r.outputs["vmdk"] = output{ + Name: "disk.vmdk", + MimeType: "application/x-vmdk", + Packages: []string{ + "@core", + "chrony", + "firewalld", + "kernel", + "langpacks-en", + "open-vm-tools", + "selinux-policy-targeted", + }, + ExcludedPackages: []string{ + "dracut-config-rescue", + }, + 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) + }, + } + + return &r +} + +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) Repositories(arch string) []rpmmd.RepoConfig { + return r.arches[arch].Repositories +} + +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 +} + +func (r *Fedora32) FilenameFromType(outputFormat string) (string, string, error) { + if output, exists := r.outputs[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 + } + if size == 0 { + size = r.outputs[outputFormat].DefaultSize + } + 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(b *blueprint.Blueprint, additionalRepos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec, checksums map[string]string, 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) + } + + p := &osbuild.Pipeline{} + p.SetBuild(r.buildPipeline(arch, checksums), "org.osbuild.fedora32") + + packages, excludedPackages, err := r.BasePackages(outputFormat, outputArchitecture) + if err != nil { + return nil, err + } + packages = append(packages, b.GetPackages()...) + + p.AddStage(osbuild.NewDNFStage(r.dnfStageOptions(arch, additionalRepos, checksums, packages, excludedPackages))) + p.AddStage(osbuild.NewFixBLSStage()) + + // TODO support setting all languages and install corresponding langpack-* package + language, keyboard := b.GetPrimaryLocale() + + if language != nil { + p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{*language})) + } else { + p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{"en_US"})) + } + + if keyboard != nil { + p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{*keyboard})) + } + + if hostname := b.GetHostname(); hostname != nil { + p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{*hostname})) + } + + timezone, ntpServers := b.GetTimezoneSettings() + + // TODO install chrony when this is set? + if timezone != nil { + p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{*timezone})) + } + + if len(ntpServers) > 0 { + p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{ntpServers})) + } + + if users := b.GetUsers(); len(users) > 0 { + options, err := r.userStageOptions(users) + if err != nil { + return nil, err + } + p.AddStage(osbuild.NewUsersStage(options)) + } + + if groups := b.GetGroups(); len(groups) > 0 { + p.AddStage(osbuild.NewGroupsStage(r.groupStageOptions(groups))) + } + + if output.Bootable { + p.AddStage(osbuild.NewFSTabStage(r.fsTabStageOptions(arch.UEFI))) + } + p.AddStage(osbuild.NewGRUB2Stage(r.grub2StageOptions(output.KernelOptions, b.GetKernel(), arch.UEFI))) + + if services := b.GetServices(); services != nil || output.EnabledServices != nil { + p.AddStage(osbuild.NewSystemdStage(r.systemdStageOptions(output.EnabledServices, output.DisabledServices, services))) + } + + if firewall := b.GetFirewall(); firewall != nil { + p.AddStage(osbuild.NewFirewallStage(r.firewallStageOptions(firewall))) + } + + p.AddStage(osbuild.NewSELinuxStage(r.selinuxStageOptions())) + + p.Assembler = output.Assembler(arch.UEFI, size) + + return p, nil +} + +func (r *Fedora32) Sources(packages []rpmmd.PackageSpec) *osbuild.Sources { + return &osbuild.Sources{} +} + +func (r *Fedora32) Runner() string { + return "org.osbuild.fedora32" +} + +func (r *Fedora32) buildPipeline(arch arch, checksums map[string]string) *osbuild.Pipeline { + packages, err := r.BuildPackages(arch.Name) + if err != nil { + panic("impossibly invalid arch") + } + + p := &osbuild.Pipeline{} + p.AddStage(osbuild.NewDNFStage(r.dnfStageOptions(arch, nil, checksums, packages, nil))) + return p +} + +func (r *Fedora32) dnfStageOptions(arch arch, additionalRepos []rpmmd.RepoConfig, checksums map[string]string, packages, excludedPackages []string) *osbuild.DNFStageOptions { + options := &osbuild.DNFStageOptions{ + ReleaseVersion: "32", + BaseArchitecture: arch.Name, + ModulePlatformId: ModulePlatformID, + } + + for _, repo := range append(arch.Repositories, additionalRepos...) { + options.AddRepository(&osbuild.DNFRepository{ + BaseURL: repo.BaseURL, + MetaLink: repo.Metalink, + MirrorList: repo.MirrorList, + GPGKey: repo.GPGKey, + Checksum: checksums[repo.Id], + }) + } + + sort.Strings(packages) + for _, pkg := range packages { + options.AddPackage(pkg) + } + + sort.Strings(excludedPackages) + for _, pkg := range excludedPackages { + options.ExcludePackage(pkg) + } + + return options +} + +func (r *Fedora32) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) { + options := osbuild.UsersStageOptions{ + Users: make(map[string]osbuild.UsersStageOptionsUser), + } + + for _, c := range users { + if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) { + cryptedPassword, err := crypt.CryptSHA512(*c.Password) + if err != nil { + return nil, err + } + + c.Password = &cryptedPassword + } + + user := osbuild.UsersStageOptionsUser{ + Groups: c.Groups, + Description: c.Description, + Home: c.Home, + Shell: c.Shell, + Password: c.Password, + Key: c.Key, + } + + if c.UID != nil { + uid := strconv.Itoa(*c.UID) + user.UID = &uid + } + + if c.GID != nil { + gid := strconv.Itoa(*c.GID) + user.GID = &gid + } + + options.Users[c.Name] = user + } + + return &options, nil +} + +func (r *Fedora32) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions { + options := osbuild.GroupsStageOptions{ + Groups: map[string]osbuild.GroupsStageOptionsGroup{}, + } + + for _, group := range groups { + groupData := osbuild.GroupsStageOptionsGroup{ + Name: group.Name, + } + if group.GID != nil { + gid := strconv.Itoa(*group.GID) + groupData.GID = &gid + } + + options.Groups[group.Name] = groupData + } + + return &options +} + +func (r *Fedora32) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions { + options := osbuild.FirewallStageOptions{ + Ports: firewall.Ports, + } + + if firewall.Services != nil { + options.EnabledServices = firewall.Services.Enabled + options.DisabledServices = firewall.Services.Disabled + } + + return &options +} + +func (r *Fedora32) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions { + if s != nil { + enabledServices = append(enabledServices, s.Enabled...) + disabledServices = append(disabledServices, s.Disabled...) + } + return &osbuild.SystemdStageOptions{ + EnabledServices: enabledServices, + DisabledServices: disabledServices, + } +} + +func (r *Fedora32) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions { + options := osbuild.FSTabStageOptions{} + options.AddFilesystem("76a22bf4-f153-4541-b6c7-0332c0dfaeac", "ext4", "/", "defaults", 1, 1) + if uefi { + options.AddFilesystem("46BB-8120", "vfat", "/boot/efi", "umask=0077,shortname=winnt", 0, 2) + } + return &options +} + +func (r *Fedora32) 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") + } + + if kernel != nil { + kernelOptions += " " + kernel.Append + } + + var uefiOptions *osbuild.GRUB2UEFI + if uefi { + uefiOptions = &osbuild.GRUB2UEFI{ + Vendor: "fedora", + } + } + + return &osbuild.GRUB2StageOptions{ + RootFilesystemUUID: id, + KernelOptions: kernelOptions, + Legacy: !uefi, + UEFI: uefiOptions, + } +} + +func (r *Fedora32) selinuxStageOptions() *osbuild.SELinuxStageOptions { + return &osbuild.SELinuxStageOptions{ + FileContexts: "etc/selinux/targeted/contexts/files/file_contexts", + } +} + +func (r *Fedora32) qemuAssembler(format string, filename string, uefi bool, size uint64) *osbuild.Assembler { + var options osbuild.QEMUAssemblerOptions + if uefi { + fstype := uuid.MustParse("C12A7328-F81F-11D2-BA4B-00A0C93EC93B") + options = osbuild.QEMUAssemblerOptions{ + Format: format, + Filename: filename, + Size: size, + PTUUID: "8DFDFF87-C96E-EA48-A3A6-9408F1F6B1EF", + PTType: "gpt", + Partitions: []osbuild.QEMUPartition{ + { + Start: 2048, + Size: 972800, + Type: &fstype, + Filesystem: osbuild.QEMUFilesystem{ + Type: "vfat", + UUID: "46BB-8120", + Label: "EFI System Partition", + Mountpoint: "/boot/efi", + }, + }, + { + Start: 976896, + Filesystem: osbuild.QEMUFilesystem{ + Type: "ext4", + UUID: "76a22bf4-f153-4541-b6c7-0332c0dfaeac", + Mountpoint: "/", + }, + }, + }, + } + } else { + options = osbuild.QEMUAssemblerOptions{ + Format: format, + Filename: filename, + Size: size, + PTUUID: "0x14fc63d2", + PTType: "mbr", + Partitions: []osbuild.QEMUPartition{ + { + Start: 2048, + Bootable: true, + Filesystem: osbuild.QEMUFilesystem{ + Type: "ext4", + UUID: "76a22bf4-f153-4541-b6c7-0332c0dfaeac", + Mountpoint: "/", + }, + }, + }, + } + } + return osbuild.NewQEMUAssembler(&options) +} + +func (r *Fedora32) tarAssembler(filename, compression string) *osbuild.Assembler { + return osbuild.NewTarAssembler( + &osbuild.TarAssemblerOptions{ + Filename: filename, + Compression: compression, + }) +} + +func (r *Fedora32) rawFSAssembler(filename string, size uint64) *osbuild.Assembler { + id, err := uuid.Parse("76a22bf4-f153-4541-b6c7-0332c0dfaeac") + if err != nil { + panic("invalid UUID") + } + return osbuild.NewRawFSAssembler( + &osbuild.RawFSAssemblerOptions{ + Filename: filename, + RootFilesystemUUDI: id, + Size: size, + }) +} diff --git a/internal/distro/fedora32/distro_test.go b/internal/distro/fedora32/distro_test.go new file mode 100644 index 000000000..0ceb192ab --- /dev/null +++ b/internal/distro/fedora32/distro_test.go @@ -0,0 +1,113 @@ +package fedora32_test + +import ( + "reflect" + "testing" + + "github.com/osbuild/osbuild-composer/internal/distro" +) + +func TestListOutputFormats(t *testing.T) { + want := []string{ + "ami", + "ext4-filesystem", + "openstack", + "partitioned-disk", + "qcow2", + "tar", + "vhd", + "vmdk", + } + + distros := distro.NewRegistry([]string{"../../../"}) + f32 := distros.GetDistro("fedora-32") + 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 + } + tests := []struct { + name string + args args + want string + want1 string + wantErr bool + }{ + { + name: "ami", + args: args{"ami"}, + want: "image.raw.xz", + want1: "application/octet-stream", + }, + { + name: "ext4", + args: args{"ext4-filesystem"}, + want: "filesystem.img", + want1: "application/octet-stream", + }, + { + name: "openstack", + args: args{"openstack"}, + want: "disk.qcow2", + want1: "application/x-qemu-disk", + }, + { + name: "partitioned-disk", + args: args{"partitioned-disk"}, + want: "disk.img", + want1: "application/octet-stream", + }, + { + name: "qcow2", + args: args{"qcow2"}, + want: "disk.qcow2", + want1: "application/x-qemu-disk", + }, + { + name: "tar", + args: args{"tar"}, + want: "root.tar.xz", + want1: "application/x-tar", + }, + { + name: "vhd", + args: args{"vhd"}, + want: "disk.vhd", + want1: "application/x-vhd", + }, + { + name: "vmdk", + args: args{"vmdk"}, + want: "disk.vmdk", + want1: "application/x-vmdk", + }, + { + name: "invalid-output-type", + args: args{"foobar"}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + distros := distro.NewRegistry([]string{"../../../"}) + f32 := distros.GetDistro("fedora-32") + got, got1, err := f32.FilenameFromType(tt.args.outputFormat) + if (err != nil) != tt.wantErr { + t.Errorf("FilenameFromType() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr { + if got != tt.want { + t.Errorf("FilenameFromType() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("FilenameFromType() got1 = %v, want %v", got1, tt.want1) + } + } + }) + } +} diff --git a/repositories/fedora-32.json b/repositories/fedora-32.json new file mode 100644 index 000000000..d930f0d79 --- /dev/null +++ b/repositories/fedora-32.json @@ -0,0 +1,18 @@ +{ + "x86_64": [ + { + "id": "fedora", + "name": "Fedora 32", + "metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=x86_64", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBF1RVqsBEADWMBqYv/G1r4PwyiPQCfg5fXFGXV1FCZ32qMi9gLUTv1CX7rYy\nH4Inj93oic+lt1kQ0kQCkINOwQczOkm6XDkEekmMrHknJpFLwrTK4AS28bYF2RjL\nM+QJ/dGXDMPYsP0tkLvoxaHr9WTRq89A+AmONcUAQIMJg3JxXAAafBi2UszUUEPI\nU35MyufFt2ePd1k/6hVAO8S2VT72TxXSY7Ha4X2J0pGzbqQ6Dq3AVzogsnoIi09A\n7fYutYZPVVAEGRUqavl0th8LyuZShASZ38CdAHBMvWV4bVZghd/wDV5ev3LXUE0o\nitLAqNSeiDJ3grKWN6v0qdU0l3Ya60sugABd3xaE+ROe8kDCy3WmAaO51Q880ZA2\niXOTJFObqkBTP9j9+ZeQ+KNE8SBoiH1EybKtBU8HmygZvu8ZC1TKUyL5gwGUJt8v\nergy5Bw3Q7av520sNGD3cIWr4fBAVYwdBoZT8RcsnU1PP67NmOGFcwSFJ/LpiOMC\npZ1IBvjOC7KyKEZY2/63kjW73mB7OHOd18BHtGVkA3QAdVlcSule/z68VOAy6bih\nE6mdxP28D4INsts8w6yr4G+3aEIN8u0qRQq66Ri5mOXTyle+ONudtfGg3U9lgicg\nz6oVk17RT0jV9uL6K41sGZ1sH/6yTXQKagdAYr3w1ix2L46JgzC+/+6SSwARAQAB\ntDFGZWRvcmEgKDMyKSA8ZmVkb3JhLTMyLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQI4BBMBAgAiBQJdUVarAhsPBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK\nCRBsEwJtEslE0LdAD/wKdAMtfzr7O2y06/sOPnrb3D39Y2DXbB8y0iEmRdBL29Bq\n5btxwmAka7JZRJVFxPsOVqZ6KARjS0/oCBmJc0jCRANFCtM4UjVHTSsxrJfuPkel\nvrlNE9tcR6OCRpuj/PZgUa39iifF/FTUfDgh4Q91xiQoLqfBxOJzravQHoK9VzrM\nNTOu6J6l4zeGzY/ocj6DpT+5fdUO/3HgGFNiNYPC6GVzeiA3AAVR0sCyGENuqqdg\nwUxV3BIht05M5Wcdvxg1U9x5I3yjkLQw+idvX4pevTiCh9/0u+4g80cT/21Cxsdx\n7+DVHaewXbF87QQIcOAing0S5QE67r2uPVxmWy/56TKUqDoyP8SNsV62lT2jutsj\nLevNxUky011g5w3bc61UeaeKrrurFdRs+RwBVkXmtqm/i6g0ZTWZyWGO6gJd+HWA\nqY1NYiq4+cMvNLatmA2sOoCsRNmE9q6jM/ESVgaH8hSp8GcLuzt9/r4PZZGl5CvU\neldOiD221u8rzuHmLs4dsgwJJ9pgLT0cUAsOpbMPI0JpGIPQ2SG6yK7LmO6HFOxb\nAkz7IGUt0gy1MzPTyBvnB+WgD1I+IQXXsJbhP5+d+d3mOnqsd6oDM/grKBzrhoUe\noNadc9uzjqKlOrmrdIR3Bz38SSiWlde5fu6xPqJdmGZRNjXtcyJlbSPVDIloxw==\n=QWRO\n-----END PGP PUBLIC KEY BLOCK-----\n" + } + ], + "aarch64": [ + { + "id": "fedora", + "name": "Fedora 32", + "metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-32&arch=aarch64", + "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBF1RVqsBEADWMBqYv/G1r4PwyiPQCfg5fXFGXV1FCZ32qMi9gLUTv1CX7rYy\nH4Inj93oic+lt1kQ0kQCkINOwQczOkm6XDkEekmMrHknJpFLwrTK4AS28bYF2RjL\nM+QJ/dGXDMPYsP0tkLvoxaHr9WTRq89A+AmONcUAQIMJg3JxXAAafBi2UszUUEPI\nU35MyufFt2ePd1k/6hVAO8S2VT72TxXSY7Ha4X2J0pGzbqQ6Dq3AVzogsnoIi09A\n7fYutYZPVVAEGRUqavl0th8LyuZShASZ38CdAHBMvWV4bVZghd/wDV5ev3LXUE0o\nitLAqNSeiDJ3grKWN6v0qdU0l3Ya60sugABd3xaE+ROe8kDCy3WmAaO51Q880ZA2\niXOTJFObqkBTP9j9+ZeQ+KNE8SBoiH1EybKtBU8HmygZvu8ZC1TKUyL5gwGUJt8v\nergy5Bw3Q7av520sNGD3cIWr4fBAVYwdBoZT8RcsnU1PP67NmOGFcwSFJ/LpiOMC\npZ1IBvjOC7KyKEZY2/63kjW73mB7OHOd18BHtGVkA3QAdVlcSule/z68VOAy6bih\nE6mdxP28D4INsts8w6yr4G+3aEIN8u0qRQq66Ri5mOXTyle+ONudtfGg3U9lgicg\nz6oVk17RT0jV9uL6K41sGZ1sH/6yTXQKagdAYr3w1ix2L46JgzC+/+6SSwARAQAB\ntDFGZWRvcmEgKDMyKSA8ZmVkb3JhLTMyLXByaW1hcnlAZmVkb3JhcHJvamVjdC5v\ncmc+iQI4BBMBAgAiBQJdUVarAhsPBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK\nCRBsEwJtEslE0LdAD/wKdAMtfzr7O2y06/sOPnrb3D39Y2DXbB8y0iEmRdBL29Bq\n5btxwmAka7JZRJVFxPsOVqZ6KARjS0/oCBmJc0jCRANFCtM4UjVHTSsxrJfuPkel\nvrlNE9tcR6OCRpuj/PZgUa39iifF/FTUfDgh4Q91xiQoLqfBxOJzravQHoK9VzrM\nNTOu6J6l4zeGzY/ocj6DpT+5fdUO/3HgGFNiNYPC6GVzeiA3AAVR0sCyGENuqqdg\nwUxV3BIht05M5Wcdvxg1U9x5I3yjkLQw+idvX4pevTiCh9/0u+4g80cT/21Cxsdx\n7+DVHaewXbF87QQIcOAing0S5QE67r2uPVxmWy/56TKUqDoyP8SNsV62lT2jutsj\nLevNxUky011g5w3bc61UeaeKrrurFdRs+RwBVkXmtqm/i6g0ZTWZyWGO6gJd+HWA\nqY1NYiq4+cMvNLatmA2sOoCsRNmE9q6jM/ESVgaH8hSp8GcLuzt9/r4PZZGl5CvU\neldOiD221u8rzuHmLs4dsgwJJ9pgLT0cUAsOpbMPI0JpGIPQ2SG6yK7LmO6HFOxb\nAkz7IGUt0gy1MzPTyBvnB+WgD1I+IQXXsJbhP5+d+d3mOnqsd6oDM/grKBzrhoUe\noNadc9uzjqKlOrmrdIR3Bz38SSiWlde5fu6xPqJdmGZRNjXtcyJlbSPVDIloxw==\n=QWRO\n-----END PGP PUBLIC KEY BLOCK-----\n" + } + ] +} \ No newline at end of file