pipelines: cleanups

This is a collection of minor cleanups:
 - Start documenting the API
 - Enforce dependent pipelines have the correct type where necessary
 - Use data from dependent pipelines where possible
 - Start enforcing required fields
 - Move logic into the pipeline implementation where we can
This commit is contained in:
Tom Gundersen 2022-06-26 18:30:29 +01:00
parent 040a4ef6a1
commit e024ceb138
13 changed files with 203 additions and 146 deletions

View file

@ -1,23 +1,20 @@
package fedora
import (
"fmt"
"math/rand"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/disk"
"github.com/osbuild/osbuild-composer/internal/distro"
pipeline "github.com/osbuild/osbuild-composer/internal/distro/pipelines"
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2"
"github.com/osbuild/osbuild-composer/internal/pipeline"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
@ -32,8 +29,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packageSetSpecs[osPkgsKey], customizations.GetKernel().Name)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch, kernelVer)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatQCOW2, osbuild.QCOW2Options{Compat: "1.1"})
@ -45,9 +41,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
func vhdPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
@ -62,8 +56,7 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packageSetSpecs[osPkgsKey], customizations.GetKernel().Name)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch, kernelVer)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatVPC, nil)
@ -74,9 +67,7 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option
func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
@ -91,8 +82,7 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packageSetSpecs[osPkgsKey], customizations.GetKernel().Name)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch, kernelVer)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatVMDK, osbuild.VMDKOptions{Subformat: osbuild.VMDKSubformatStreamOptimized})
@ -103,9 +93,7 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio
func openstackPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
@ -120,8 +108,7 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations,
pipelines = append(pipelines, treePipeline.Serialize())
diskfile := "disk.img"
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packageSetSpecs[osPkgsKey], customizations.GetKernel().Name)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch, kernelVer)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
qemuPipeline := qemuPipeline(&buildPipeline, &imagePipeline, diskfile, t.filename, osbuild.QEMUFormatQCOW2, nil)
@ -134,9 +121,7 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
rng *rand.Rand, diskfile string) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
partitionTable, err := t.getPartitionTable(customizations.GetFilesystems(), options, rng)
@ -150,8 +135,7 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations,
}
pipelines = append(pipelines, treePipeline.Serialize())
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packageSetSpecs[osPkgsKey], customizations.GetKernel().Name)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch, kernelVer)
imagePipeline := liveImagePipeline(&buildPipeline, &treePipeline, diskfile, partitionTable, t.arch)
pipelines = append(pipelines, imagePipeline.Serialize())
return pipelines, nil
}
@ -164,29 +148,22 @@ func ec2Pipelines(t *imageType, customizations *blueprint.Customizations, option
func iotInstallerPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
pipelines := make([]osbuild.Pipeline, 0)
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
pipelines = append(pipelines, buildPipeline.Serialize())
installerPackages := packageSetSpecs[installerPkgsKey]
d := t.arch.distro
archName := t.Arch().Name()
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(installerPackages, "kernel")
ksUsers := len(customizations.GetUsers())+len(customizations.GetGroups()) > 0
isolabel := fmt.Sprintf(d.isolabelTmpl, archName)
anacondaTreePipeline := anacondaTreePipeline(&buildPipeline, repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "IoT", ksUsers)
isoTreePipeline := bootISOTreePipeline(&buildPipeline, &anacondaTreePipeline.Pipeline, options, kernelVer, archName, d.vendor, d.product, d.osVersion, isolabel, customizations.GetUsers(), customizations.GetGroups())
isoPipeline := bootISOPipeline(&buildPipeline, &isoTreePipeline, t.Filename(), isolabel, false)
anacondaTreePipeline := anacondaTreePipeline(&buildPipeline, repos, installerPackages, t.Arch().Name(), d.product, d.osVersion, "IoT", ksUsers)
isoTreePipeline := bootISOTreePipeline(&buildPipeline, &anacondaTreePipeline, options, d.vendor, d.isolabelTmpl, customizations.GetUsers(), customizations.GetGroups())
isoPipeline := bootISOPipeline(&buildPipeline, &isoTreePipeline, t.Filename(), false)
return append(pipelines, anacondaTreePipeline.Serialize(), isoTreePipeline.Serialize(), isoPipeline.Serialize()), nil
}
func iotCorePipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec) (*pipeline.BuildPipeline, *pipeline.OSPipeline, *pipeline.OSTreeCommitPipeline, error) {
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner)
buildPipeline.Repos = repos
buildPipeline.PackageSpecs = packageSetSpecs[buildPkgsKey]
buildPipeline := pipeline.NewBuildPipeline(t.arch.distro.runner, repos, packageSetSpecs[buildPkgsKey])
treePipeline, err := osPipeline(&buildPipeline, t, repos, packageSetSpecs[osPkgsKey], customizations, options, nil)
if err != nil {
return nil, nil, nil, err
@ -236,7 +213,7 @@ func osPipeline(buildPipeline *pipeline.BuildPipeline,
imageConfig := t.getDefaultImageConfig()
pl := pipeline.NewOSPipeline(buildPipeline, t.rpmOstree)
pl := pipeline.NewOSPipeline(buildPipeline, t.rpmOstree, repos, packages, c.GetKernel().Name)
pl.PartitionTable = pt
@ -258,13 +235,9 @@ func osPipeline(buildPipeline *pipeline.BuildPipeline,
kernelOptions = append(kernelOptions, bpKernel.Append)
}
pl.KernelOptionsAppend = kernelOptions
pl.KernelName = c.GetKernel().Name
pl.OSTreeParent = options.OSTree.Parent
pl.OSTreeURL = options.OSTree.URL
pl.Repos = repos
pl.PackageSpecs = packages
pl.GPGKeyFiles = imageConfig.GPGKeyFiles
if !t.bootISO {
@ -340,8 +313,7 @@ func osPipeline(buildPipeline *pipeline.BuildPipeline,
}
func ostreeCommitPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.OSPipeline, options distro.ImageOptions, osVersion string) pipeline.OSTreeCommitPipeline {
p := pipeline.NewOSTreeCommitPipeline(buildPipeline, treePipeline)
p.Ref = options.OSTree.Ref
p := pipeline.NewOSTreeCommitPipeline(buildPipeline, treePipeline, options.OSTree.Ref)
p.OSVersion = osVersion
p.Parent = options.OSTree.Parent
return p
@ -369,30 +341,19 @@ func containerPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipe
return p
}
func anacondaTreePipeline(buildPipeline *pipeline.BuildPipeline, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, kernelVer, arch, product, osVersion, variant string, users bool) pipeline.AnacondaPipeline {
p := pipeline.NewAnacondaPipeline(buildPipeline)
p.Repos = repos
p.PackageSpecs = packages
func anacondaTreePipeline(buildPipeline *pipeline.BuildPipeline, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, arch, product, osVersion, variant string, users bool) pipeline.AnacondaPipeline {
p := pipeline.NewAnacondaPipeline(buildPipeline, repos, packages, "kernel", arch, product, osVersion)
p.Users = users
p.KernelVer = kernelVer
p.Arch = arch
p.Product = product
p.OSVersion = osVersion
p.Variant = variant
p.Biosdevname = (p.Arch == distro.X86_64ArchName)
p.Biosdevname = (arch == distro.X86_64ArchName)
return p
}
func bootISOTreePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.Pipeline, options distro.ImageOptions, kernelVer, arch, vendor, product, osVersion, isolabel string, users []blueprint.UserCustomization, groups []blueprint.GroupCustomization) pipeline.ISOTreePipeline {
p := pipeline.NewISOTreePipeline(buildPipeline, treePipeline)
p.KernelVer = kernelVer
p.Arch = arch
func bootISOTreePipeline(buildPipeline *pipeline.BuildPipeline, anacondaPipeline *pipeline.AnacondaPipeline, options distro.ImageOptions, vendor, isoLabelTempl string, users []blueprint.UserCustomization, groups []blueprint.GroupCustomization) pipeline.ISOTreePipeline {
p := pipeline.NewISOTreePipeline(buildPipeline, anacondaPipeline, isoLabelTempl)
p.Release = "202010217.n.0"
p.Vendor = vendor
p.Product = product
p.OSName = "fedora"
p.OSVersion = osVersion
p.ISOLabel = isolabel
p.Vendor = vendor
p.Users = users
p.Groups = groups
p.OSTreeRef = options.OSTree.Ref
@ -401,15 +362,14 @@ func bootISOTreePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pi
return p
}
func bootISOPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.ISOTreePipeline, filename, isolabel string, isolinux bool) pipeline.ISOPipeline {
func bootISOPipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.ISOTreePipeline, filename string, isolinux bool) pipeline.ISOPipeline {
p := pipeline.NewISOPipeline(buildPipeline, treePipeline)
p.Filename = filename
p.ISOLabel = isolabel
p.ISOLinux = isolinux
return p
}
func liveImagePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.OSPipeline, outputFilename string, pt *disk.PartitionTable, arch *architecture, kernelVer string) pipeline.LiveImgPipeline {
func liveImagePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipeline.OSPipeline, outputFilename string, pt *disk.PartitionTable, arch *architecture) pipeline.LiveImgPipeline {
p := pipeline.NewLiveImgPipeline(buildPipeline, treePipeline)
p.Filename = outputFilename
@ -421,7 +381,6 @@ func liveImagePipeline(buildPipeline *pipeline.BuildPipeline, treePipeline *pipe
p.GRUBLegacy = arch.legacy
}
p.KernelVer = kernelVer
p.PartitionTable = *pt
return p

View file

@ -5,34 +5,87 @@ import (
"github.com/osbuild/osbuild-composer/internal/rpmmd"
)
// An AnacondaPipeline represents the installer tree as found on an ISO.
type AnacondaPipeline struct {
Pipeline
Repos []rpmmd.RepoConfig
PackageSpecs []rpmmd.PackageSpec
Users bool
KernelVer string
Arch string
Product string
OSVersion string
Variant string
Biosdevname bool
// Users indicate whether or not the user spoke should be enabled in
// anaconda. If it is, users specified in a kickstart will be configured,
// and in case no users are provided in a kickstart the user will be
// prompted to configure them at install time. If this is set to false
// any kickstart provided users are ignored and the user is never
// prompted to configure users during installation.
Users bool
// Biosdevname indicates whether or not biosdevname should be used to
// name network devices when booting the installer. This may affect
// the naming of network devices on the target system.
Biosdevname bool
// Variant is the variant of the product being installed.
// TODO: what should be the default value?
Variant string
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
kernelVer string
arch string
product string
version string
}
func NewAnacondaPipeline(buildPipeline *BuildPipeline) AnacondaPipeline {
// NewAnacondaPipeline creates an anaconda pipeline object. repos and packages
// indicate the content to build the installer from, which is distinct from the
// packages the installer will install on the target system. kernelName is the
// name of the kernel package the intsaller will use. arch is the supported
// architecture. Product and version refers to the product the installer is the
// installer for.
func NewAnacondaPipeline(buildPipeline *BuildPipeline,
repos []rpmmd.RepoConfig,
packages []rpmmd.PackageSpec,
kernelName,
arch,
product,
version string) AnacondaPipeline {
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packages, kernelName)
return AnacondaPipeline{
Pipeline: New("anaconda-tree", &buildPipeline.Pipeline),
Pipeline: New("anaconda-tree", buildPipeline, nil),
repos: repos,
packageSpecs: packages,
kernelVer: kernelVer,
arch: arch,
product: product,
version: version,
}
}
// KernelVer returns the NEVRA of the kernel package the installer will use at
// install time.
func (p AnacondaPipeline) KernelVer() string {
return p.kernelVer
}
// Arch returns the supported architecture.
func (p AnacondaPipeline) Arch() string {
return p.arch
}
// Product returns the product being installed.
func (p AnacondaPipeline) Product() string {
return p.product
}
// Version returns the version of the product being installed.
func (p AnacondaPipeline) Version() string {
return p.version
}
func (p AnacondaPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
pipeline.AddStage(osbuild2.NewRPMStage(osbuild2.NewRPMStageOptions(p.Repos), osbuild2.NewRpmStageSourceFilesInputs(p.PackageSpecs)))
pipeline.AddStage(osbuild2.NewRPMStage(osbuild2.NewRPMStageOptions(p.repos), osbuild2.NewRpmStageSourceFilesInputs(p.packageSpecs)))
pipeline.AddStage(osbuild2.NewBuildstampStage(&osbuild2.BuildstampStageOptions{
Arch: p.Arch,
Product: p.Product,
Version: p.OSVersion,
Arch: p.Arch(),
Product: p.Product(),
Variant: p.Variant,
Version: p.Version(),
Final: true,
}))
pipeline.AddStage(osbuild2.NewLocaleStage(&osbuild2.LocaleStageOptions{Language: "en_US.UTF-8"}))
@ -65,9 +118,9 @@ func (p AnacondaPipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewAnacondaStage(osbuild2.NewAnacondaStageOptions(p.Users)))
pipeline.AddStage(osbuild2.NewLoraxScriptStage(&osbuild2.LoraxScriptStageOptions{
Path: "99-generic/runtime-postinstall.tmpl",
BaseArch: p.Arch,
BaseArch: p.Arch(),
}))
pipeline.AddStage(osbuild2.NewDracutStage(dracutStageOptions(p.KernelVer, p.Biosdevname, []string{
pipeline.AddStage(osbuild2.NewDracutStage(dracutStageOptions(p.KernelVer(), p.Biosdevname, []string{
"anaconda",
"rdma",
"rngd",

View file

@ -7,22 +7,24 @@ import (
type BuildPipeline struct {
Pipeline
Repos []rpmmd.RepoConfig
PackageSpecs []rpmmd.PackageSpec
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
}
func NewBuildPipeline(runner string) BuildPipeline {
func NewBuildPipeline(runner string, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec) BuildPipeline {
pipeline := BuildPipeline{
Pipeline: New("build", nil),
Pipeline: New("build", nil, &runner),
repos: repos,
packageSpecs: packages,
}
pipeline.runner = &runner
return pipeline
}
func (p BuildPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
pipeline.AddStage(osbuild2.NewRPMStage(osbuild2.NewRPMStageOptions(p.Repos), osbuild2.NewRpmStageSourceFilesInputs(p.PackageSpecs)))
pipeline.AddStage(osbuild2.NewRPMStage(osbuild2.NewRPMStageOptions(p.repos), osbuild2.NewRpmStageSourceFilesInputs(p.packageSpecs)))
pipeline.AddStage(osbuild2.NewSELinuxStage(selinuxStageOptions(true)))
return pipeline

View file

@ -7,18 +7,24 @@ import (
type OSTreeCommitPipeline struct {
Pipeline
treePipeline *OSPipeline
Ref string
OSVersion string
Parent string
ref string
}
func NewOSTreeCommitPipeline(buildPipeline *BuildPipeline, treePipeline *OSPipeline) OSTreeCommitPipeline {
func NewOSTreeCommitPipeline(buildPipeline *BuildPipeline, treePipeline *OSPipeline, ref string) OSTreeCommitPipeline {
return OSTreeCommitPipeline{
Pipeline: New("ostree-commit", &buildPipeline.Pipeline),
Pipeline: New("ostree-commit", buildPipeline, nil),
treePipeline: treePipeline,
ref: ref,
}
}
func (p OSTreeCommitPipeline) Ref() string {
return p.ref
}
func (p OSTreeCommitPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
@ -31,7 +37,7 @@ func (p OSTreeCommitPipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewOSTreeCommitStage(
&osbuild2.OSTreeCommitStageOptions{
Ref: p.Ref,
Ref: p.Ref(),
OSVersion: p.OSVersion,
Parent: p.Parent,
},

View file

@ -20,7 +20,7 @@ type OSTreeCommitServerTreePipeline struct {
func NewOSTreeCommitServerTreePipeline(buildPipeline *BuildPipeline, commitPipeline *OSTreeCommitPipeline) OSTreeCommitServerTreePipeline {
return OSTreeCommitServerTreePipeline{
Pipeline: New("container-tree", &buildPipeline.Pipeline),
Pipeline: New("container-tree", buildPipeline, nil),
commitPipeline: commitPipeline,
Language: "en_US",
}
@ -38,7 +38,7 @@ func (p OSTreeCommitServerTreePipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewOSTreePullStage(
&osbuild2.OSTreePullStageOptions{Repo: repoPath},
osbuild2.NewOstreePullStageInputs("org.osbuild.pipeline", "name:"+p.commitPipeline.Name(), p.commitPipeline.Ref),
osbuild2.NewOstreePullStageInputs("org.osbuild.pipeline", "name:"+p.commitPipeline.Name(), p.commitPipeline.Ref()),
))
// make nginx log and lib directories world writeable, otherwise nginx can't start in

View file

@ -8,13 +8,12 @@ type ISOPipeline struct {
Pipeline
treePipeline *ISOTreePipeline
Filename string
ISOLabel string
ISOLinux bool
}
func NewISOPipeline(buildPipeline *BuildPipeline, treePipeline *ISOTreePipeline) ISOPipeline {
return ISOPipeline{
Pipeline: New("bootiso", &buildPipeline.Pipeline),
Pipeline: New("bootiso", buildPipeline, nil),
treePipeline: treePipeline,
}
}
@ -22,7 +21,7 @@ func NewISOPipeline(buildPipeline *BuildPipeline, treePipeline *ISOTreePipeline)
func (p ISOPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
pipeline.AddStage(osbuild2.NewXorrisofsStage(xorrisofsStageOptions(p.Filename, p.ISOLabel, p.ISOLinux), osbuild2.NewXorrisofsStagePipelineTreeInputs(p.treePipeline.Name())))
pipeline.AddStage(osbuild2.NewXorrisofsStage(xorrisofsStageOptions(p.Filename, p.treePipeline.ISOLabel(), p.ISOLinux), osbuild2.NewXorrisofsStagePipelineTreeInputs(p.treePipeline.Name())))
pipeline.AddStage(osbuild2.NewImplantisomd5Stage(&osbuild2.Implantisomd5StageOptions{Filename: p.Filename}))
return pipeline

View file

@ -11,35 +11,40 @@ import (
type ISOTreePipeline struct {
Pipeline
treePipeline *Pipeline
KernelVer string
Arch string
Release string
Vendor string
Product string
OSName string
OSVersion string
ISOLabel string
Users []blueprint.UserCustomization
Groups []blueprint.GroupCustomization
OSTreeParent string
OSTreeRef string
anacondaPipeline *AnacondaPipeline
Vendor string
OSName string
Release string
Users []blueprint.UserCustomization
Groups []blueprint.GroupCustomization
OSTreeParent string
OSTreeRef string
isoLabel string
}
func NewISOTreePipeline(buildPipeline *BuildPipeline, treePipeline *Pipeline) ISOTreePipeline {
func NewISOTreePipeline(buildPipeline *BuildPipeline, anacondaPipeline *AnacondaPipeline, isoLabelTmpl string) ISOTreePipeline {
// TODO: replace isoLabelTmpl with more high-level properties
isoLabel := fmt.Sprintf(isoLabelTmpl, anacondaPipeline.Arch())
return ISOTreePipeline{
Pipeline: New("bootiso-tree", &buildPipeline.Pipeline),
treePipeline: treePipeline,
Pipeline: New("bootiso-tree", buildPipeline, nil),
anacondaPipeline: anacondaPipeline,
isoLabel: isoLabel,
}
}
func (p ISOTreePipeline) ISOLabel() string {
return p.isoLabel
}
func (p ISOTreePipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
kspath := "/osbuild.ks"
ostreeRepoPath := "/ostree/repo"
pipeline.AddStage(osbuild2.NewBootISOMonoStage(bootISOMonoStageOptions(p.KernelVer, p.Arch, p.Vendor, p.Product, p.OSVersion, p.ISOLabel, kspath), osbuild2.NewBootISOMonoStagePipelineTreeInputs(p.treePipeline.Name())))
pipeline.AddStage(osbuild2.NewBootISOMonoStage(bootISOMonoStageOptions(p.anacondaPipeline.KernelVer(), p.anacondaPipeline.Arch(), p.Vendor, 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 {
@ -48,7 +53,7 @@ func (p ISOTreePipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewKickstartStage(kickstartOptions))
pipeline.AddStage(osbuild2.NewDiscinfoStage(&osbuild2.DiscinfoStageOptions{
BaseArch: p.Arch,
BaseArch: p.anacondaPipeline.Arch(),
Release: p.Release,
}))

View file

@ -10,15 +10,14 @@ type LiveImgPipeline struct {
PartitionTable disk.PartitionTable
BootLoader BootLoader
GRUBLegacy string
KernelVer string
treePipeline *Pipeline
treePipeline *OSPipeline
Filename string
}
func NewLiveImgPipeline(buildPipeline *BuildPipeline, treePipeline *OSPipeline) LiveImgPipeline {
return LiveImgPipeline{
Pipeline: New("image", &buildPipeline.Pipeline),
treePipeline: &treePipeline.Pipeline,
Pipeline: New("image", buildPipeline, nil),
treePipeline: treePipeline,
}
}
@ -45,7 +44,7 @@ func (p LiveImgPipeline) Serialize() osbuild2.Pipeline {
}
case BOOTLOADER_ZIPL:
loopback := osbuild2.NewLoopbackDevice(&osbuild2.LoopbackDeviceOptions{Filename: p.Filename})
pipeline.AddStage(osbuild2.NewZiplInstStage(osbuild2.NewZiplInstStageOptions(p.KernelVer, &p.PartitionTable), loopback, copyDevices, copyMounts))
pipeline.AddStage(osbuild2.NewZiplInstStage(osbuild2.NewZiplInstStageOptions(p.treePipeline.KernelVer(), &p.PartitionTable), loopback, copyDevices, copyMounts))
}
return pipeline

View file

@ -15,7 +15,7 @@ type OCIContainerPipeline struct {
func NewOCIContainerPipeline(buildPipeline *BuildPipeline, treePipeline *Pipeline) OCIContainerPipeline {
return OCIContainerPipeline{
Pipeline: New("container", &buildPipeline.Pipeline),
Pipeline: New("container", buildPipeline, nil),
treePipeline: treePipeline,
}
}

View file

@ -14,17 +14,13 @@ import (
type OSPipeline struct {
Pipeline
osTree bool
OSTreeParent string
OSTreeURL string
KernelName string
KernelOptionsAppend []string
BootLoader BootLoader
UEFI bool
GRUBLegacy string
Vendor string
Repos []rpmmd.RepoConfig
PackageSpecs []rpmmd.PackageSpec
GPGKeyFiles []string
PartitionTable *disk.PartitionTable
Language string
@ -58,20 +54,33 @@ type OSPipeline struct {
AuthConfig *osbuild2.AuthconfigStageOptions
PwQuality *osbuild2.PwqualityConfStageOptions
WAAgentConfig *osbuild2.WAAgentConfStageOptions
osTree bool
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
kernelVer string
}
func NewOSPipeline(buildPipeline *BuildPipeline, osTree bool) OSPipeline {
func NewOSPipeline(buildPipeline *BuildPipeline, osTree bool, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, kernelName string) OSPipeline {
name := "os"
if osTree {
name = "ostree-tree"
}
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packages, kernelName)
return OSPipeline{
Pipeline: New(name, &buildPipeline.Pipeline),
osTree: osTree,
Hostname: "localhost.localdomain",
Pipeline: New(name, buildPipeline, nil),
osTree: osTree,
repos: repos,
packageSpecs: packages,
kernelVer: kernelVer,
Hostname: "localhost.localdomain",
}
}
func (p OSPipeline) KernelVer() string {
return p.kernelVer
}
func (p OSPipeline) Serialize() osbuild2.Pipeline {
pipeline := p.Pipeline.Serialize()
@ -79,9 +88,9 @@ func (p OSPipeline) Serialize() osbuild2.Pipeline {
pipeline.AddStage(osbuild2.NewOSTreePasswdStage("org.osbuild.source", p.OSTreeParent))
}
rpmOptions := osbuild2.NewRPMStageOptions(p.Repos)
rpmOptions := osbuild2.NewRPMStageOptions(p.repos)
rpmOptions.GPGKeysFromTree = p.GPGKeyFiles
pipeline.AddStage(osbuild2.NewRPMStage(rpmOptions, osbuild2.NewRpmStageSourceFilesInputs(p.PackageSpecs)))
pipeline.AddStage(osbuild2.NewRPMStage(rpmOptions, osbuild2.NewRpmStageSourceFilesInputs(p.packageSpecs)))
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
if p.PartitionTable == nil || p.PartitionTable.FindMountable("/boot") == nil {
@ -229,8 +238,7 @@ func (p OSPipeline) Serialize() osbuild2.Pipeline {
var bootloader *osbuild2.Stage
switch p.BootLoader {
case BOOTLOADER_GRUB:
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(p.PackageSpecs, p.KernelName)
options := osbuild2.NewGrub2StageOptionsUnified(p.PartitionTable, kernelVer, p.UEFI, p.GRUBLegacy, p.Vendor, false)
options := osbuild2.NewGrub2StageOptionsUnified(p.PartitionTable, p.kernelVer, p.UEFI, p.GRUBLegacy, p.Vendor, false)
if cfg := p.Grub2Config; cfg != nil {
// TODO: don't store Grub2Config in OSPipeline, making the overrides unnecessary
// grub2.Config.Default is owned and set by `NewGrub2StageOptionsUnified`

View file

@ -1,3 +1,9 @@
// Package pipeline implements a standard set of osbuild pipelines. A pipeline
// conceptually represents a named filesystem tree, optionally generated
// in a provided build root (represented by another pipeline). All inputs
// to a pipeline must be explicitly specified, either in terms of other
// pipeline, in terms of content addressable inputs or in terms of static
// parameters to the inherited Pipeline structs.
package pipeline
import (
@ -11,35 +17,55 @@ const (
BOOTLOADER_ZIPL
)
// A Pipeline represents the core functionality shared between each of the pipeline
// implementations, and the Pipeline struct must be embedded in each of them.
type Pipeline struct {
name string
runner *string
build *Pipeline
runner string
build *BuildPipeline
}
// Name returns the name of the pipeline. The name must be unique for a given manifest.
// Pipeline names are used to refer to pipelines either as dependencies between pipelines
// or for exporting them.
func (p Pipeline) Name() string {
return p.name
}
func New(name string, build *Pipeline) Pipeline {
return Pipeline{
// New returns a generic Pipeline object. The name is mandatory, immutable and must
// be unique among all the pipelines used in a manifest, which is currently not enforced.
// The build argument is a pipeline representing a build root in which the rest of the
// pipeline is built. In order to ensure reproducibility a build pipeline must always be
// provided, except for int he build pipeline itself. When a build pipeline is not provided
// the build host's filesystem is used as the build root, and in this case a runner must be
// specified which knows how to interpret the host filesystem as a build root.
func New(name string, build *BuildPipeline, runner *string) Pipeline {
p := Pipeline{
name: name,
build: build,
}
if runner != nil {
if build != nil {
panic("both runner and build pipeline specified")
}
p.runner = *runner
} else if build == nil {
panic("neither build pipeline nor runner specified")
}
return p
}
// Serialize turns a given pipeline into an osbuild2.Pipeline object. This object is
// meant to be treated as opaque and not to be modified further outside of the pipeline
// package.
func (p Pipeline) Serialize() osbuild2.Pipeline {
var buildName string
if p.build != nil {
buildName = "name:" + p.build.Name()
}
var runner string
if p.runner != nil {
runner = *p.runner
}
return osbuild2.Pipeline{
Name: p.name,
Runner: runner,
Runner: p.runner,
Build: buildName,
}
}

View file

@ -16,7 +16,7 @@ type QemuPipeline struct {
func NewQemuPipeline(buildPipeline *BuildPipeline, imgPipeline *LiveImgPipeline, name string) QemuPipeline {
return QemuPipeline{
Pipeline: New(name, &buildPipeline.Pipeline),
Pipeline: New(name, buildPipeline, nil),
imgPipeline: &imgPipeline.Pipeline,
}
}

View file

@ -12,7 +12,7 @@ type TarPipeline struct {
func NewTarPipeline(buildPipeline *BuildPipeline, inputPipeline *Pipeline, name string) TarPipeline {
return TarPipeline{
Pipeline: New(name, &buildPipeline.Pipeline),
Pipeline: New(name, buildPipeline, nil),
inputPipeline: inputPipeline,
}
}