Each pipeline constructor receives the full list of repositories and filters the list based on its own internal name.
114 lines
3.3 KiB
Go
114 lines
3.3 KiB
Go
package manifest
|
|
|
|
import (
|
|
"github.com/osbuild/osbuild-composer/internal/osbuild"
|
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
|
"github.com/osbuild/osbuild-composer/internal/runner"
|
|
)
|
|
|
|
// A Build represents the build environment for other pipelines. As a
|
|
// general rule, tools required to build pipelines are used from the build
|
|
// environment, rather than from the pipeline itself. Without a specified
|
|
// build environment, the build host's root filesystem would be used, which
|
|
// is not predictable nor reproducible. For the purposes of building the
|
|
// build pipeline, we do use the build host's filesystem, this means we should
|
|
// make minimal assumptions about what's available there.
|
|
type Build struct {
|
|
Base
|
|
|
|
runner runner.Runner
|
|
dependents []Pipeline
|
|
repos []rpmmd.RepoConfig
|
|
packageSpecs []rpmmd.PackageSpec
|
|
}
|
|
|
|
// NewBuild creates a new build pipeline from the repositories in repos
|
|
// and the specified packages.
|
|
func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig) *Build {
|
|
name := "build"
|
|
pipeline := &Build{
|
|
Base: NewBase(m, name, nil),
|
|
runner: runner,
|
|
dependents: make([]Pipeline, 0),
|
|
repos: filterRepos(repos, name),
|
|
}
|
|
m.addPipeline(pipeline)
|
|
return pipeline
|
|
}
|
|
|
|
func (p *Build) addDependent(dep Pipeline) {
|
|
p.dependents = append(p.dependents, dep)
|
|
}
|
|
|
|
func (p *Build) getPackageSetChain() []rpmmd.PackageSet {
|
|
// TODO: make the /usr/bin/cp dependency conditional
|
|
// TODO: make the /usr/bin/xz dependency conditional
|
|
packages := []string{
|
|
"selinux-policy-targeted", // needed to build the build pipeline
|
|
"coreutils", // /usr/bin/cp - used all over
|
|
"xz", // usage unclear
|
|
}
|
|
|
|
packages = append(packages, p.runner.GetBuildPackages()...)
|
|
|
|
for _, pipeline := range p.dependents {
|
|
packages = append(packages, pipeline.getBuildPackages()...)
|
|
}
|
|
|
|
return []rpmmd.PackageSet{
|
|
{
|
|
Include: packages,
|
|
Repositories: p.repos,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (p *Build) getPackageSpecs() []rpmmd.PackageSpec {
|
|
return p.packageSpecs
|
|
}
|
|
|
|
func (p *Build) serializeStart(packages []rpmmd.PackageSpec) {
|
|
if len(p.packageSpecs) > 0 {
|
|
panic("double call to serializeStart()")
|
|
}
|
|
p.packageSpecs = packages
|
|
}
|
|
|
|
func (p *Build) serializeEnd() {
|
|
if len(p.packageSpecs) == 0 {
|
|
panic("serializeEnd() call when serialization not in progress")
|
|
}
|
|
p.packageSpecs = nil
|
|
}
|
|
|
|
func (p *Build) serialize() osbuild.Pipeline {
|
|
if len(p.packageSpecs) == 0 {
|
|
panic("serialization not started")
|
|
}
|
|
pipeline := p.Base.serialize()
|
|
pipeline.Runner = p.runner.String()
|
|
|
|
pipeline.AddStage(osbuild.NewRPMStage(osbuild.NewRPMStageOptions(p.repos), osbuild.NewRpmStageSourceFilesInputs(p.packageSpecs)))
|
|
pipeline.AddStage(osbuild.NewSELinuxStage(&osbuild.SELinuxStageOptions{
|
|
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
|
|
Labels: p.getSELinuxLabels(),
|
|
},
|
|
))
|
|
|
|
return pipeline
|
|
}
|
|
|
|
// Returns a map of paths to labels for the SELinux stage based on specific
|
|
// packages found in the pipeline.
|
|
func (p *Build) getSELinuxLabels() map[string]string {
|
|
labels := make(map[string]string)
|
|
for _, pkg := range p.getPackageSpecs() {
|
|
switch pkg.Name {
|
|
case "coreutils":
|
|
labels["/usr/bin/cp"] = "system_u:object_r:install_exec_t:s0"
|
|
case "tar":
|
|
labels["/usr/bin/tar"] = "system_u:object_r:install_exec_t:s0"
|
|
}
|
|
}
|
|
return labels
|
|
}
|