debian-forge-composer/internal/distro/test_distro/distro.go
Achilleas Koutsou 5dba246813 manifest: remove Content field from manifest
Do not expose the content of the manifest statically and instead rely on
the public methods to retrieve source specifications dynamically.

Since the methods require iterating through the pipelines to collect
source specifications, we should avoid calling the function multiple
times when we can reuse the returned values.
2023-06-14 11:19:29 +02:00

428 lines
10 KiB
Go

package test_distro
import (
"crypto/sha256"
"errors"
"fmt"
"sort"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/container"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/distroregistry"
"github.com/osbuild/osbuild-composer/internal/manifest"
dnfjson_mock "github.com/osbuild/osbuild-composer/internal/mocks/dnfjson"
"github.com/osbuild/osbuild-composer/internal/ostree"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
const (
// package set names
// build package set name
buildPkgsKey = "build"
// main/common os image package set name
osPkgsKey = "os"
// blueprint package set name
blueprintPkgsKey = "blueprint"
)
type TestDistro struct {
name string
releasever string
modulePlatformID string
ostreeRef string
arches map[string]distro.Arch
}
type TestArch struct {
distribution *TestDistro
name string
imageTypes map[string]distro.ImageType
}
type TestImageType struct {
architecture *TestArch
name string
}
const (
TestDistroName = "test-distro"
TestDistro2Name = "test-distro-2"
TestDistroReleasever = "1"
TestDistro2Releasever = "2"
TestDistroModulePlatformID = "platform:test"
TestDistro2ModulePlatformID = "platform:test-2"
TestArchName = "test_arch"
TestArch2Name = "test_arch2"
TestArch3Name = "test_arch3"
TestImageTypeName = "test_type"
TestImageType2Name = "test_type2"
TestImageTypeOSTree = "test_ostree_type"
// added for cloudapi tests
TestImageTypeAmi = "ami"
TestImageTypeGce = "gce"
TestImageTypeVhd = "vhd"
TestImageTypeEdgeCommit = "rhel-edge-commit"
TestImageTypeEdgeInstaller = "rhel-edge-installer"
TestImageTypeImageInstaller = "image-installer"
TestImageTypeQcow2 = "qcow2"
TestImageTypeVmdk = "vmdk"
)
// TestDistro
func (d *TestDistro) Name() string {
return d.name
}
func (d *TestDistro) Releasever() string {
return d.releasever
}
func (d *TestDistro) ModulePlatformID() string {
return d.modulePlatformID
}
func (d *TestDistro) OSTreeRef() string {
return d.ostreeRef
}
func (d *TestDistro) ListArches() []string {
archs := make([]string, 0, len(d.arches))
for name := range d.arches {
archs = append(archs, name)
}
sort.Strings(archs)
return archs
}
func (d *TestDistro) GetArch(arch string) (distro.Arch, error) {
a, exists := d.arches[arch]
if !exists {
return nil, errors.New("invalid arch: " + arch)
}
return a, nil
}
func (d *TestDistro) addArches(arches ...*TestArch) {
if d.arches == nil {
d.arches = map[string]distro.Arch{}
}
for _, a := range arches {
a.distribution = d
d.arches[a.Name()] = a
}
}
// TestArch
func (a *TestArch) Name() string {
return a.name
}
func (a *TestArch) Distro() distro.Distro {
return a.distribution
}
func (a *TestArch) ListImageTypes() []string {
formats := make([]string, 0, len(a.imageTypes))
for name := range a.imageTypes {
formats = append(formats, name)
}
sort.Strings(formats)
return formats
}
func (a *TestArch) GetImageType(imageType string) (distro.ImageType, error) {
t, exists := a.imageTypes[imageType]
if !exists {
return nil, errors.New("invalid image type: " + imageType)
}
return t, nil
}
func (a *TestArch) addImageTypes(imageTypes ...TestImageType) {
if a.imageTypes == nil {
a.imageTypes = map[string]distro.ImageType{}
}
for idx := range imageTypes {
it := imageTypes[idx]
it.architecture = a
a.imageTypes[it.Name()] = &it
}
}
// TestImageType
func (t *TestImageType) Name() string {
return t.name
}
func (t *TestImageType) Arch() distro.Arch {
return t.architecture
}
func (t *TestImageType) Filename() string {
return "test.img"
}
func (t *TestImageType) MIMEType() string {
return "application/x-test"
}
func (t *TestImageType) OSTreeRef() string {
if t.name == TestImageTypeEdgeCommit || t.name == TestImageTypeEdgeInstaller || t.name == TestImageTypeOSTree {
return t.architecture.distribution.OSTreeRef()
}
return ""
}
func (t *TestImageType) Size(size uint64) uint64 {
return 0
}
func (t *TestImageType) PartitionType() string {
return ""
}
func (t *TestImageType) BootMode() distro.BootMode {
return distro.BOOT_HYBRID
}
func (t *TestImageType) BuildPipelines() []string {
return distro.BuildPipelinesFallback()
}
func (t *TestImageType) PayloadPipelines() []string {
return distro.PayloadPipelinesFallback()
}
func (t *TestImageType) PayloadPackageSets() []string {
return []string{blueprintPkgsKey}
}
func (t *TestImageType) PackageSetsChains() map[string][]string {
return map[string][]string{
osPkgsKey: {osPkgsKey, blueprintPkgsKey},
}
}
func (t *TestImageType) Exports() []string {
return distro.ExportsFallback()
}
func (t *TestImageType) Manifest(b *blueprint.Blueprint, options distro.ImageOptions, repos []rpmmd.RepoConfig, seed int64) (*manifest.Manifest, []string, error) {
var bpPkgs []string
if b != nil {
mountpoints := b.Customizations.GetFilesystems()
invalidMountpoints := []string{}
for _, m := range mountpoints {
if m.Mountpoint != "/" {
invalidMountpoints = append(invalidMountpoints, m.Mountpoint)
}
}
if len(invalidMountpoints) > 0 {
return nil, nil, fmt.Errorf("The following custom mountpoints are not supported %+q", invalidMountpoints)
}
bpPkgs = b.GetPackages()
}
var ostreeSources []ostree.SourceSpec
if defaultRef := t.OSTreeRef(); defaultRef != "" {
// ostree image type
ostreeSource := ostree.SourceSpec{ // init with default
Ref: defaultRef,
}
if ostreeOptions := options.OSTree; ostreeOptions != nil {
if ostreeOptions.ImageRef != "" { // override with ref from image options
ostreeSource.Ref = ostreeOptions.ImageRef
}
// copy any other options that might be specified
ostreeSource.URL = options.OSTree.URL
ostreeSource.Parent = options.OSTree.ParentRef
ostreeSource.RHSM = options.OSTree.RHSM
}
ostreeSources = []ostree.SourceSpec{ostreeSource}
}
buildPackages := []rpmmd.PackageSet{{
Include: []string{
"dep-package1",
"dep-package2",
"dep-package3",
},
Repositories: repos,
}}
osPackages := []rpmmd.PackageSet{
{
Include: bpPkgs,
Repositories: repos,
},
{
Include: []string{
"dep-package1",
"dep-package2",
"dep-package3",
},
Repositories: repos,
},
}
m := &manifest.Manifest{}
manifest.NewContentTest(m, buildPkgsKey, buildPackages, nil, nil)
manifest.NewContentTest(m, osPkgsKey, osPackages, nil, ostreeSources)
return m, nil, nil
}
// newTestDistro returns a new instance of TestDistro with the
// given name and modulePlatformID.
//
// It contains two architectures "test_arch" and "test_arch2".
// "test_arch" contains one image type "test_type".
// "test_arch2" contains two image types "test_type" and "test_type2".
func newTestDistro(name, modulePlatformID, releasever string) *TestDistro {
td := TestDistro{
name: name,
releasever: releasever,
modulePlatformID: modulePlatformID,
ostreeRef: "test/13/x86_64/edge",
}
ta1 := TestArch{
name: TestArchName,
}
ta2 := TestArch{
name: TestArch2Name,
}
ta3 := TestArch{
name: TestArch3Name,
}
it1 := TestImageType{
name: TestImageTypeName,
}
it2 := TestImageType{
name: TestImageType2Name,
}
it3 := TestImageType{
name: TestImageTypeAmi,
}
it4 := TestImageType{
name: TestImageTypeVhd,
}
it5 := TestImageType{
name: TestImageTypeEdgeCommit,
}
it6 := TestImageType{
name: TestImageTypeEdgeInstaller,
}
it7 := TestImageType{
name: TestImageTypeImageInstaller,
}
it8 := TestImageType{
name: TestImageTypeQcow2,
}
it9 := TestImageType{
name: TestImageTypeVmdk,
}
it10 := TestImageType{
name: TestImageTypeGce,
}
it11 := TestImageType{
name: TestImageTypeOSTree,
}
ta1.addImageTypes(it1, it11)
ta2.addImageTypes(it1, it2)
ta3.addImageTypes(it3, it4, it5, it6, it7, it8, it9, it10)
td.addArches(&ta1, &ta2, &ta3)
return &td
}
// New returns new instance of TestDistro named "test-distro".
func New() *TestDistro {
return newTestDistro(TestDistroName, TestDistroModulePlatformID, TestDistroReleasever)
}
func NewRegistry() *distroregistry.Registry {
td := New()
registry, err := distroregistry.New(td, td)
if err != nil {
panic(err)
}
// Override the host's architecture name with the test's name
registry.SetHostArchName(TestArchName)
return registry
}
// New2 returns new instance of TestDistro named "test-distro-2".
func New2() *TestDistro {
return newTestDistro(TestDistro2Name, TestDistro2ModulePlatformID, TestDistro2Releasever)
}
// ResolveContent transforms content source specs into resolved specs for serialization.
// For packages, it uses the dnfjson_mock.BaseDeps() every time, but retains
// the map keys from the input.
// For ostree commits it hashes the URL+Ref to create a checksum.
func ResolveContent(pkgs map[string][]rpmmd.PackageSet, containers map[string][]container.SourceSpec, commits map[string][]ostree.SourceSpec) (map[string][]rpmmd.PackageSpec, map[string][]container.Spec, map[string][]ostree.CommitSpec) {
pkgSpecs := make(map[string][]rpmmd.PackageSpec, len(pkgs))
for name := range pkgs {
pkgSpecs[name] = dnfjson_mock.BaseDeps()
}
containerSpecs := make(map[string][]container.Spec, len(containers))
for name := range containers {
containerSpecs[name] = make([]container.Spec, len(containers[name]))
for idx := range containers[name] {
containerSpecs[name][idx] = container.Spec{
Source: containers[name][idx].Source,
TLSVerify: containers[name][idx].TLSVerify,
LocalName: containers[name][idx].Name,
}
}
}
commitSpecs := make(map[string][]ostree.CommitSpec, len(commits))
for name := range commits {
commitSpecs[name] = make([]ostree.CommitSpec, len(commits[name]))
for idx := range commits[name] {
commitSpecs[name][idx] = ostree.CommitSpec{
Ref: commits[name][idx].Ref,
URL: commits[name][idx].URL,
Checksum: fmt.Sprintf("%x", sha256.Sum256([]byte(commits[name][idx].URL+commits[name][idx].Ref))),
}
fmt.Printf("Test distro spec: %+v\n", commitSpecs[name][idx])
}
}
return pkgSpecs, containerSpecs, commitSpecs
}