pipeline: fully encapsulate manifest generation

Make it the responsibility of each pipeline to track its required
sources, and use this to generate a manifest from its pipelines.

This removes the dependency on osbuild2 from distro.go, and the
only other uses of osbuild2 are to specify parameters in
ImageConfig, which will eventually go away too.

As a consequence, this only attaches the required sources for a
given manifest, rather than all known packages in the package set
map.
This commit is contained in:
Tom Gundersen 2022-06-27 13:58:28 +01:00
parent d8f540c5cf
commit f791bde0e4
17 changed files with 332 additions and 214 deletions

View file

@ -0,0 +1,133 @@
package manifest
import (
"fmt"
"path"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/osbuild2"
)
// An ISOTreePipeline represents a tree containing the anaconda installer,
// configuration in terms of a kickstart file, as well as an embedded
// payload to be installed.
type ISOTreePipeline struct {
BasePipeline
// TODO: review optional and mandatory fields and their meaning
UEFIVendor string
OSName string
Release string
Users []blueprint.UserCustomization
Groups []blueprint.GroupCustomization
anacondaPipeline *AnacondaPipeline
isoLabel string
osTreeCommit string
osTreeURL string
osTreeRef string
}
func NewISOTreePipeline(buildPipeline *BuildPipeline, anacondaPipeline *AnacondaPipeline, osTreeCommit, osTreeURL, osTreeRef, isoLabelTmpl string) ISOTreePipeline {
// TODO: replace isoLabelTmpl with more high-level properties
isoLabel := fmt.Sprintf(isoLabelTmpl, anacondaPipeline.Arch())
return ISOTreePipeline{
BasePipeline: NewBasePipeline("bootiso-tree", buildPipeline, nil),
anacondaPipeline: anacondaPipeline,
isoLabel: isoLabel,
osTreeCommit: osTreeCommit,
osTreeURL: osTreeURL,
osTreeRef: osTreeRef,
}
}
func (p ISOTreePipeline) getOSTreeCommits() []osTreeCommit {
return []osTreeCommit{
{
checksum: p.osTreeCommit,
url: p.osTreeURL,
},
}
}
func (p ISOTreePipeline) ISOLabel() string {
return p.isoLabel
}
func (p ISOTreePipeline) serialize() osbuild2.Pipeline {
pipeline := p.BasePipeline.serialize()
kspath := "/osbuild.ks"
ostreeRepoPath := "/ostree/repo"
pipeline.AddStage(osbuild2.NewBootISOMonoStage(bootISOMonoStageOptions(p.anacondaPipeline.KernelVer(), p.anacondaPipeline.Arch(), p.UEFIVendor, p.anacondaPipeline.Product(), p.anacondaPipeline.Version(), p.ISOLabel(), kspath), osbuild2.NewBootISOMonoStagePipelineTreeInputs(p.anacondaPipeline.Name())))
kickstartOptions, err := osbuild2.NewKickstartStageOptions(kspath, "", p.Users, p.Groups, makeISORootPath(ostreeRepoPath), p.osTreeRef, p.OSName)
if err != nil {
panic("password encryption failed")
}
pipeline.AddStage(osbuild2.NewKickstartStage(kickstartOptions))
pipeline.AddStage(osbuild2.NewDiscinfoStage(&osbuild2.DiscinfoStageOptions{
BaseArch: p.anacondaPipeline.Arch(),
Release: p.Release,
}))
pipeline.AddStage(osbuild2.NewOSTreeInitStage(&osbuild2.OSTreeInitStageOptions{Path: ostreeRepoPath}))
pipeline.AddStage(osbuild2.NewOSTreePullStage(
&osbuild2.OSTreePullStageOptions{Repo: ostreeRepoPath},
osbuild2.NewOstreePullStageInputs("org.osbuild.source", p.osTreeCommit, p.osTreeRef),
))
return pipeline
}
func bootISOMonoStageOptions(kernelVer, arch, vendor, product, osVersion, isolabel, kspath string) *osbuild2.BootISOMonoStageOptions {
comprOptions := new(osbuild2.FSCompressionOptions)
if bcj := osbuild2.BCJOption(arch); bcj != "" {
comprOptions.BCJ = bcj
}
var architectures []string
if arch == distro.X86_64ArchName {
architectures = []string{"X64"}
} else if arch == distro.Aarch64ArchName {
architectures = []string{"AA64"}
} else {
panic("unsupported architecture")
}
return &osbuild2.BootISOMonoStageOptions{
Product: osbuild2.Product{
Name: product,
Version: osVersion,
},
ISOLabel: isolabel,
Kernel: kernelVer,
KernelOpts: fmt.Sprintf("inst.ks=hd:LABEL=%s:%s", isolabel, kspath),
EFI: osbuild2.EFI{
Architectures: architectures,
Vendor: vendor,
},
ISOLinux: osbuild2.ISOLinux{
Enabled: arch == distro.X86_64ArchName,
Debug: false,
},
Templates: "99-generic",
RootFS: osbuild2.RootFS{
Size: 9216,
Compression: osbuild2.FSCompression{
Method: "xz",
Options: comprOptions,
},
},
}
}
//makeISORootPath return a path that can be used to address files and folders in
//the root of the iso
func makeISORootPath(p string) string {
fullpath := path.Join("/run/install/repo", p)
return fmt.Sprintf("file://%s", fullpath)
}