Blame internal/distro/rhel84/distro_v2.go

Packit Service 15f37d
package rhel84
Packit Service 15f37d
Packit Service 15f37d
import (
Packit Service 15f37d
	"encoding/json"
Packit Service 15f37d
	"fmt"
Packit Service 15f37d
	"math/rand"
Packit Service 15f37d
	"path/filepath"
Packit Service 15f37d
Packit Service 15f37d
	"github.com/osbuild/osbuild-composer/internal/crypt"
Packit Service 15f37d
	"github.com/osbuild/osbuild-composer/internal/distro"
Packit Service 15f37d
	osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2"
Packit Service 15f37d
Packit Service 15f37d
	"github.com/osbuild/osbuild-composer/internal/blueprint"
Packit Service 15f37d
	"github.com/osbuild/osbuild-composer/internal/rpmmd"
Packit Service 15f37d
)
Packit Service 15f37d
Packit Service 15f37d
type imageTypeS2 struct {
Packit Service 15f37d
	arch             *architecture
Packit Service 15f37d
	name             string
Packit Service 15f37d
	filename         string
Packit Service 15f37d
	mimeType         string
Packit Service 15f37d
	packageSets      map[string]rpmmd.PackageSet
Packit Service 15f37d
	enabledServices  []string
Packit Service 15f37d
	disabledServices []string
Packit Service 15f37d
	defaultTarget    string
Packit Service 15f37d
	kernelOptions    string
Packit Service 15f37d
	bootable         bool
Packit Service 15f37d
	bootISO          bool
Packit Service 15f37d
	rpmOstree        bool
Packit Service 15f37d
	defaultSize      uint64
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Arch() distro.Arch {
Packit Service 15f37d
	return t.arch
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Name() string {
Packit Service 15f37d
	return t.name
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Filename() string {
Packit Service 15f37d
	return t.filename
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) MIMEType() string {
Packit Service 15f37d
	return t.mimeType
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) OSTreeRef() string {
Packit Service 15f37d
	if t.rpmOstree {
Packit Service 15f37d
		return fmt.Sprintf(ostreeRef, t.arch.name)
Packit Service 15f37d
	}
Packit Service 15f37d
	return ""
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Size(size uint64) uint64 {
Packit Service 15f37d
	const MegaByte = 1024 * 1024
Packit Service 15f37d
	// Microsoft Azure requires vhd images to be rounded up to the nearest MB
Packit Service 15f37d
	if t.name == "vhd" && size%MegaByte != 0 {
Packit Service 15f37d
		size = (size/MegaByte + 1) * MegaByte
Packit Service 15f37d
	}
Packit Service 15f37d
	if size == 0 {
Packit Service 15f37d
		size = t.defaultSize
Packit Service 15f37d
	}
Packit Service 15f37d
	return size
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Packages(bp blueprint.Blueprint) ([]string, []string) {
Packit Service 15f37d
	packages := append(t.packageSets["packages"].Include, bp.GetPackages()...)
Packit Service 15f37d
	timezone, _ := bp.Customizations.GetTimezoneSettings()
Packit Service 15f37d
	if timezone != nil {
Packit Service 15f37d
		packages = append(packages, "chrony")
Packit Service 15f37d
	}
Packit Service 15f37d
	return packages, t.packageSets["packages"].Exclude
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) BuildPackages() []string {
Packit Service 15f37d
	buildPackages := append(t.arch.distro.buildPackages, t.arch.buildPackages...)
Packit Service 15f37d
	if t.rpmOstree {
Packit Service 15f37d
		buildPackages = append(buildPackages, "rpm-ostree")
Packit Service 15f37d
	}
Packit Service 15f37d
	if t.bootISO {
Packit Service 15f37d
		buildPackages = append(buildPackages, t.packageSets["build"].Include...)
Packit Service 15f37d
	}
Packit Service 15f37d
	return buildPackages
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.PackageSet {
Packit Service 15f37d
	sets := map[string]rpmmd.PackageSet{
Packit Service 15f37d
		"build-packages": {
Packit Service 15f37d
			Include: t.BuildPackages(),
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
	for name, pkgSet := range t.packageSets {
Packit Service 15f37d
		if name == "packages" {
Packit Service 15f37d
			// treat base packages separately to combine with blueprint
Packit Service 15f37d
			packages := new(rpmmd.PackageSet)
Packit Service 15f37d
			packages.Include, packages.Exclude = t.Packages(bp)
Packit Service 15f37d
			sets[name] = *packages
Packit Service 15f37d
			continue
Packit Service 15f37d
		}
Packit Service 15f37d
		sets[name] = pkgSet
Packit Service 15f37d
	}
Packit Service 15f37d
	return sets
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Exports() []string {
Packit Service 15f37d
	return []string{"assembler"}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) Manifest(c *blueprint.Customizations,
Packit Service 15f37d
	options distro.ImageOptions,
Packit Service 15f37d
	repos []rpmmd.RepoConfig,
Packit Service 15f37d
	packageSpecSets map[string][]rpmmd.PackageSpec,
Packit Service 15f37d
	seed int64) (distro.Manifest, error) {
Packit Service 15f37d
	source := rand.NewSource(seed)
Packit Service 15f37d
	rng := rand.New(source)
Packit Service 15f37d
	pipelines, err := t.pipelines(c, options, repos, packageSpecSets, rng)
Packit Service 15f37d
	if err != nil {
Packit Service 15f37d
		return distro.Manifest{}, err
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	// flatten spec sets for sources
Packit Service 15f37d
	allPackageSpecs := make([]rpmmd.PackageSpec, 0)
Packit Service 15f37d
	for _, specs := range packageSpecSets {
Packit Service 15f37d
		allPackageSpecs = append(allPackageSpecs, specs...)
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	var commits []ostreeCommit
Packit Service 15f37d
	if options.OSTree.Parent != "" && options.OSTree.URL != "" {
Packit Service 15f37d
		commit := ostreeCommit{Checksum: options.OSTree.Parent, URL: options.OSTree.URL}
Packit Service 15f37d
		commits = []ostreeCommit{commit}
Packit Service 15f37d
	}
Packit Service 15f37d
	return json.Marshal(
Packit Service 15f37d
		osbuild.Manifest{
Packit Service 15f37d
			Version:   "2",
Packit Service 15f37d
			Pipelines: pipelines,
Packit Service 15f37d
			Sources:   t.sources(allPackageSpecs, commits),
Packit Service 15f37d
		},
Packit Service 15f37d
	)
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
// local type for ostree sommit metadata used to define commit sources
Packit Service 15f37d
type ostreeCommit struct {
Packit Service 15f37d
	Checksum string
Packit Service 15f37d
	URL      string
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) sources(packages []rpmmd.PackageSpec, ostreeCommits []ostreeCommit) osbuild.Sources {
Packit Service 15f37d
	sources := osbuild.Sources{}
Packit Service 15f37d
	curl := &osbuild.CurlSource{
Packit Service 15f37d
		Items: make(map[string]osbuild.CurlSourceItem),
Packit Service 15f37d
	}
Packit Service 15f37d
	for _, pkg := range packages {
Packit Service 15f37d
		item := new(osbuild.URLWithSecrets)
Packit Service 15f37d
		item.URL = pkg.RemoteLocation
Packit Service 15f37d
		if pkg.Secrets == "org.osbuild.rhsm" {
Packit Service 15f37d
			item.Secrets = &osbuild.URLSecrets{
Packit Service 15f37d
				Name: "org.osbuild.rhsm",
Packit Service 15f37d
			}
Packit Service 15f37d
		}
Packit Service 15f37d
		curl.Items[pkg.Checksum] = item
Packit Service 15f37d
	}
Packit Service 15f37d
	if len(curl.Items) > 0 {
Packit Service 15f37d
		sources["org.osbuild.curl"] = curl
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	ostree := &osbuild.OSTreeSource{
Packit Service 15f37d
		Items: make(map[string]osbuild.OSTreeSourceItem),
Packit Service 15f37d
	}
Packit Service 15f37d
	for _, commit := range ostreeCommits {
Packit Service 15f37d
		item := new(osbuild.OSTreeSourceItem)
Packit Service 15f37d
		item.Remote.URL = commit.URL
Packit Service 15f37d
		ostree.Items[commit.Checksum] = *item
Packit Service 15f37d
	}
Packit Service 15f37d
	if len(ostree.Items) > 0 {
Packit Service 15f37d
		sources["org.osbuild.ostree"] = ostree
Packit Service 15f37d
	}
Packit Service 15f37d
	return sources
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) pipelines(customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
Packit Service 15f37d
Packit Service 15f37d
	if t.bootISO {
Packit Service 15f37d
		if options.OSTree.Parent == "" {
Packit Service 15f37d
			return nil, fmt.Errorf("boot ISO image type %q requires specifying a URL from which to retrieve the OSTree commit", t.name)
Packit Service 15f37d
		}
Packit Service 15f37d
		if customizations != nil {
Packit Service 15f37d
			return nil, fmt.Errorf("boot ISO image type %q does not support blueprint customizations", t.name)
Packit Service 15f37d
		}
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.rpmOstree {
Packit Service 15f37d
		return nil, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	pipelines := make([]osbuild.Pipeline, 0)
Packit Service 15f37d
Packit Service 15f37d
	pipelines = append(pipelines, *t.buildPipeline(repos, packageSetSpecs["build-packages"]))
Packit Service 15f37d
Packit Service 15f37d
	if t.bootISO {
Packit Service 15f37d
		var kernelPkg rpmmd.PackageSpec
Packit Service 15f37d
		for _, pkg := range packageSetSpecs["installer"] {
Packit Service 15f37d
			if pkg.Name == "kernel" {
Packit Service 15f37d
				kernelPkg = pkg
Packit Service 15f37d
				break
Packit Service 15f37d
			}
Packit Service 15f37d
		}
Packit Service 15f37d
		// TODO: panic if not found
Packit Service 15f37d
		kernelVer := fmt.Sprintf("%s-%s.%s", kernelPkg.Version, kernelPkg.Release, kernelPkg.Arch)
Packit Service 15f37d
		pipelines = append(pipelines, *t.anacondaTreePipeline(repos, packageSetSpecs["installer"], options, kernelVer))
Packit Service 15f37d
		pipelines = append(pipelines, *t.bootISOTreePipeline(kernelVer))
Packit Service 15f37d
		pipelines = append(pipelines, *t.bootISOPipeline())
Packit Service 15f37d
	} else {
Packit Service 15f37d
		treePipeline, err := t.ostreeTreePipeline(repos, packageSetSpecs["packages"], customizations)
Packit Service 15f37d
		if err != nil {
Packit Service 15f37d
			return nil, err
Packit Service 15f37d
		}
Packit Service 15f37d
		pipelines = append(pipelines, *treePipeline)
Packit Service 15f37d
		pipelines = append(pipelines, *t.ostreeCommitPipeline(options))
Packit Service 15f37d
		pipelines = append(pipelines, *t.containerTreePipeline(repos, packageSetSpecs["container"], options, customizations))
Packit Service 15f37d
		pipelines = append(pipelines, *t.containerPipeline())
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return pipelines, nil
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) buildPipeline(repos []rpmmd.RepoConfig, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	p.Name = "build"
Packit Service 15f37d
	p.Runner = "org.osbuild.rhel84"
Packit Service 15f37d
	p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(buildPackageSpecs)))
Packit Service 15f37d
	p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, c *blueprint.Customizations) (*osbuild.Pipeline, error) {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	p.Name = "ostree-tree"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
	p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(packages)))
Packit Service 15f37d
	language, keyboard := c.GetPrimaryLocale()
Packit Service 15f37d
	if language != nil {
Packit Service 15f37d
		p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
Packit Service 15f37d
	} else {
Packit Service 15f37d
		p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
Packit Service 15f37d
	}
Packit Service 15f37d
	if keyboard != nil {
Packit Service 15f37d
		p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
Packit Service 15f37d
	}
Packit Service 15f37d
	if hostname := c.GetHostname(); hostname != nil {
Packit Service 15f37d
		p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	timezone, ntpServers := c.GetTimezoneSettings()
Packit Service 15f37d
	if timezone != nil {
Packit Service 15f37d
		p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
Packit Service 15f37d
	} else {
Packit Service 15f37d
		p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"}))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if len(ntpServers) > 0 {
Packit Service 15f37d
		p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if groups := c.GetGroups(); len(groups) > 0 {
Packit Service 15f37d
		p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if users := c.GetUsers(); len(users) > 0 {
Packit Service 15f37d
		options, err := t.userStageOptions(users)
Packit Service 15f37d
		if err != nil {
Packit Service 15f37d
			return nil, err
Packit Service 15f37d
		}
Packit Service 15f37d
		p.AddStage(osbuild.NewUsersStage(options))
Packit Service 15f37d
		p.AddStage(osbuild.NewFirstBootStage(t.usersFirstBootOptions(options)))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if services := c.GetServices(); services != nil || t.enabledServices != nil || t.disabledServices != nil || t.defaultTarget != "" {
Packit Service 15f37d
		p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.enabledServices, t.disabledServices, services, t.defaultTarget)))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if firewall := c.GetFirewall(); firewall != nil {
Packit Service 15f37d
		p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if !t.bootISO {
Packit Service 15f37d
		p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	// These are the current defaults for the sysconfig stage. This can be changed to be image type exclusive if different configs are needed.
Packit Service 15f37d
	p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{
Packit Service 15f37d
		Kernel: osbuild.SysconfigKernelOptions{
Packit Service 15f37d
			UpdateDefault: true,
Packit Service 15f37d
			DefaultKernel: "kernel",
Packit Service 15f37d
		},
Packit Service 15f37d
		Network: osbuild.SysconfigNetworkOptions{
Packit Service 15f37d
			Networking: true,
Packit Service 15f37d
			NoZeroConf: true,
Packit Service 15f37d
		},
Packit Service 15f37d
	}))
Packit Service 15f37d
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreePrepTreeStage(&osbuild.OSTreePrepTreeStageOptions{
Packit Service 15f37d
		EtcGroupMembers: []string{
Packit Service 15f37d
			// NOTE: We may want to make this configurable.
Packit Service 15f37d
			"wheel", "docker",
Packit Service 15f37d
		},
Packit Service 15f37d
	}))
Packit Service 15f37d
	return p, nil
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) ostreeCommitPipeline(options distro.ImageOptions) *osbuild.Pipeline {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	p.Name = "ostree-commit"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: "/repo"}))
Packit Service 15f37d
Packit Service 15f37d
	commitStageInput := new(osbuild.OSTreeCommitStageInput)
Packit Service 15f37d
	commitStageInput.Type = "org.osbuild.tree"
Packit Service 15f37d
	commitStageInput.Origin = "org.osbuild.pipeline"
Packit Service 15f37d
	commitStageInput.References = osbuild.OSTreeCommitStageReferences{"name:ostree-tree"}
Packit Service 15f37d
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreeCommitStage(
Packit Service 15f37d
		&osbuild.OSTreeCommitStageOptions{
Packit Service 464a89
			Ref:       options.OSTree.Ref,
Packit Service 15f37d
			OSVersion: "8.4", // NOTE: Set on image type?
Packit Service 15f37d
			Parent:    options.OSTree.Parent,
Packit Service 15f37d
		},
Packit Service 15f37d
		&osbuild.OSTreeCommitStageInputs{Tree: commitStageInput}),
Packit Service 15f37d
	)
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) containerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, options distro.ImageOptions, c *blueprint.Customizations) *osbuild.Pipeline {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	p.Name = "container-tree"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
	p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(packages)))
Packit Service 15f37d
	language, _ := c.GetPrimaryLocale()
Packit Service 15f37d
	if language != nil {
Packit Service 15f37d
		p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
Packit Service 15f37d
	} else {
Packit Service 15f37d
		p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US"}))
Packit Service 15f37d
	}
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: "/var/www/html/repo"}))
Packit Service 15f37d
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreePullStage(
Packit Service 15f37d
		&osbuild.OSTreePullStageOptions{Repo: "/var/www/html/repo"},
Packit Service 464a89
		t.ostreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.Ref),
Packit Service 15f37d
	))
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) containerPipeline() *osbuild.Pipeline {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	// NOTE(akoutsou) 1to2t: final pipeline should always be named "assembler"
Packit Service 15f37d
	p.Name = "assembler"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
	options := &osbuild.OCIArchiveStageOptions{
Packit Service 15f37d
		Architecture: t.arch.Name(),
Packit Service 15f37d
		Filename:     t.Filename(),
Packit Service 15f37d
		Config: &osbuild.OCIArchiveConfig{
Packit Service 15f37d
			Cmd:          []string{"httpd", "-D", "FOREGROUND"},
Packit Service 15f37d
			ExposedPorts: []string{"80"},
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
	baseInput := new(osbuild.OCIArchiveStageInput)
Packit Service 15f37d
	baseInput.Type = "org.osbuild.tree"
Packit Service 15f37d
	baseInput.Origin = "org.osbuild.pipeline"
Packit Service 15f37d
	baseInput.References = []string{"name:container-tree"}
Packit Service 15f37d
	inputs := &osbuild.OCIArchiveStageInputs{Base: baseInput}
Packit Service 15f37d
	p.AddStage(osbuild.NewOCIArchiveStage(options, inputs))
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) anacondaTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, options distro.ImageOptions, kernelVer string) *osbuild.Pipeline {
Packit Service 15f37d
	ostreeRepoPath := "/ostree/repo"
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	p.Name = "anaconda-tree"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
	p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(packages)))
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: ostreeRepoPath}))
Packit Service 15f37d
	p.AddStage(osbuild.NewOSTreePullStage(
Packit Service 15f37d
		&osbuild.OSTreePullStageOptions{Repo: ostreeRepoPath},
Packit Service 15f37d
		t.ostreePullStageInputs("org.osbuild.source", options.OSTree.Parent, options.OSTree.Ref),
Packit Service 15f37d
	))
Packit Service 15f37d
	p.AddStage(osbuild.NewBuildstampStage(t.buildStampStageOptions()))
Packit Service 15f37d
	p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
Packit Service 15f37d
Packit Service 15f37d
	rootPassword := ""
Packit Service 15f37d
	rootUser := osbuild.UsersStageOptionsUser{
Packit Service 15f37d
		Password: &rootPassword,
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	installUID := 0
Packit Service 15f37d
	installGID := 0
Packit Service 15f37d
	installHome := "/root"
Packit Service 15f37d
	installShell := "/usr/libexec/anaconda/run-anaconda"
Packit Service 15f37d
	installPassword := ""
Packit Service 15f37d
	installUser := osbuild.UsersStageOptionsUser{
Packit Service 15f37d
		UID:      &installUID,
Packit Service 15f37d
		GID:      &installGID,
Packit Service 15f37d
		Home:     &installHome,
Packit Service 15f37d
		Shell:    &installShell,
Packit Service 15f37d
		Password: &installPassword,
Packit Service 15f37d
	}
Packit Service 15f37d
	usersStageOptions := &osbuild.UsersStageOptions{
Packit Service 15f37d
		Users: map[string]osbuild.UsersStageOptionsUser{
Packit Service 15f37d
			"root":    rootUser,
Packit Service 15f37d
			"install": installUser,
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	p.AddStage(osbuild.NewUsersStage(usersStageOptions))
Packit Service 15f37d
	p.AddStage(osbuild.NewAnacondaStage(t.anacondaStageOptions()))
Packit Service 15f37d
	p.AddStage(osbuild.NewLoraxScriptStage(t.loraxScriptStageOptions()))
Packit Service 15f37d
	p.AddStage(osbuild.NewDracutStage(t.dracutStageOptions(kernelVer)))
Packit Service 464a89
	p.AddStage(osbuild.NewKickstartStage(t.kickstartStageOptions(fmt.Sprintf("file://%s", ostreeRepoPath), options.OSTree.Ref)))
Packit Service 15f37d
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) bootISOTreePipeline(kernelVer string) *osbuild.Pipeline {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	p.Name = "bootiso-tree"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
Packit Service 15f37d
	p.AddStage(osbuild.NewBootISOMonoStage(t.bootISOMonoStageOptions(kernelVer), t.bootISOMonoStageInputs()))
Packit Service 15f37d
	p.AddStage(osbuild.NewDiscinfoStage(t.discinfoStageOptions()))
Packit Service 15f37d
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
func (t *imageTypeS2) bootISOPipeline() *osbuild.Pipeline {
Packit Service 15f37d
	p := new(osbuild.Pipeline)
Packit Service 15f37d
	// NOTE(akoutsou) 1to2t: final pipeline should always be named "assembler"
Packit Service 15f37d
	p.Name = "assembler"
Packit Service 15f37d
	p.Build = "name:build"
Packit Service 15f37d
Packit Service 15f37d
	p.AddStage(osbuild.NewXorrisofsStage(t.xorrisofsStageOptions(), t.xorrisofsStageInputs()))
Packit Service 15f37d
	p.AddStage(osbuild.NewImplantisomd5Stage(&osbuild.Implantisomd5StageOptions{Filename: t.Filename()}))
Packit Service 15f37d
Packit Service 15f37d
	return p
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) rpmStageInputs(specs []rpmmd.PackageSpec) *osbuild.RPMStageInputs {
Packit Service 15f37d
	stageInput := new(osbuild.RPMStageInput)
Packit Service 15f37d
	stageInput.Type = "org.osbuild.files"
Packit Service 15f37d
	stageInput.Origin = "org.osbuild.source"
Packit Service 15f37d
	stageInput.References = pkgRefs(specs)
Packit Service 15f37d
	return &osbuild.RPMStageInputs{Packages: stageInput}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func pkgRefs(specs []rpmmd.PackageSpec) osbuild.RPMStageReferences {
Packit Service 15f37d
	refs := make([]string, len(specs))
Packit Service 15f37d
	for idx, pkg := range specs {
Packit Service 15f37d
		refs[idx] = pkg.Checksum
Packit Service 15f37d
	}
Packit Service 15f37d
	return refs
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) ostreePullStageInputs(origin, source, commitRef string) *osbuild.OSTreePullStageInputs {
Packit Service 15f37d
	pullStageInput := new(osbuild.OSTreePullStageInput)
Packit Service 15f37d
	pullStageInput.Type = "org.osbuild.ostree"
Packit Service 15f37d
	pullStageInput.Origin = origin
Packit Service 15f37d
Packit Service 15f37d
	inputRefs := make(map[string]osbuild.OSTreePullStageReference)
Packit Service 15f37d
	inputRefs[source] = osbuild.OSTreePullStageReference{Ref: commitRef}
Packit Service 15f37d
	pullStageInput.References = inputRefs
Packit Service 15f37d
	return &osbuild.OSTreePullStageInputs{Commits: pullStageInput}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) rpmStageOptions(repos []rpmmd.RepoConfig) *osbuild.RPMStageOptions {
Packit Service 15f37d
	var gpgKeys []string
Packit Service 15f37d
	for _, repo := range repos {
Packit Service 15f37d
		if repo.GPGKey == "" {
Packit Service 15f37d
			continue
Packit Service 15f37d
		}
Packit Service 15f37d
		gpgKeys = append(gpgKeys, repo.GPGKey)
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return &osbuild.RPMStageOptions{
Packit Service 15f37d
		GPGKeys: gpgKeys,
Packit Service 15f37d
		Exclude: &osbuild.Exclude{
Packit Service 15f37d
			// NOTE: Make configurable?
Packit Service 15f37d
			Docs: true,
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) selinuxStageOptions() *osbuild.SELinuxStageOptions {
Packit Service 15f37d
Packit Service 15f37d
	options := &osbuild.SELinuxStageOptions{
Packit Service 15f37d
		FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
Packit Service 15f37d
	}
Packit Service 15f37d
	if t.bootISO {
Packit Service 15f37d
		options.Labels = map[string]string{
Packit Service 15f37d
			"/usr/bin/cp":  "system_u:object_r:install_exec_t:s0",
Packit Service 15f37d
			"/usr/bin/tar": "system_u:object_r:install_exec_t:s0",
Packit Service 15f37d
		}
Packit Service 15f37d
	}
Packit Service 15f37d
	return options
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
Packit Service 15f37d
	options := osbuild.UsersStageOptions{
Packit Service 15f37d
		Users: make(map[string]osbuild.UsersStageOptionsUser),
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	for _, c := range users {
Packit Service 15f37d
		if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) {
Packit Service 15f37d
			cryptedPassword, err := crypt.CryptSHA512(*c.Password)
Packit Service 15f37d
			if err != nil {
Packit Service 15f37d
				return nil, err
Packit Service 15f37d
			}
Packit Service 15f37d
Packit Service 15f37d
			c.Password = &cryptedPassword
Packit Service 15f37d
		}
Packit Service 15f37d
Packit Service 15f37d
		user := osbuild.UsersStageOptionsUser{
Packit Service 15f37d
			Groups:      c.Groups,
Packit Service 15f37d
			Description: c.Description,
Packit Service 15f37d
			Home:        c.Home,
Packit Service 15f37d
			Shell:       c.Shell,
Packit Service 15f37d
			Password:    c.Password,
Packit Service 15f37d
			Key:         c.Key,
Packit Service 15f37d
		}
Packit Service 15f37d
Packit Service 15f37d
		user.UID = c.UID
Packit Service 15f37d
		user.GID = c.GID
Packit Service 15f37d
Packit Service 15f37d
		options.Users[c.Name] = user
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return &options, nil
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) usersFirstBootOptions(usersStageOptions *osbuild.UsersStageOptions) *osbuild.FirstBootStageOptions {
Packit Service 15f37d
	cmds := make([]string, 0, 3*len(usersStageOptions.Users)+1)
Packit Service 15f37d
	// workaround for creating authorized_keys file for user
Packit Service 15f37d
	varhome := filepath.Join("/var", "home")
Packit Service 15f37d
	for name, user := range usersStageOptions.Users {
Packit Service 15f37d
		if user.Key != nil {
Packit Service 15f37d
			sshdir := filepath.Join(varhome, name, ".ssh")
Packit Service 15f37d
			cmds = append(cmds, fmt.Sprintf("mkdir -p %s", sshdir))
Packit Service 15f37d
			cmds = append(cmds, fmt.Sprintf("sh -c 'echo %q >> %q'", *user.Key, filepath.Join(sshdir, "authorized_keys")))
Packit Service 15f37d
			cmds = append(cmds, fmt.Sprintf("chown %s:%s -Rc %s", name, name, sshdir))
Packit Service 15f37d
		}
Packit Service 15f37d
	}
Packit Service 15f37d
	cmds = append(cmds, fmt.Sprintf("restorecon -rvF %s", varhome))
Packit Service 15f37d
	options := &osbuild.FirstBootStageOptions{
Packit Service 15f37d
		Commands:       cmds,
Packit Service 15f37d
		WaitForNetwork: false,
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return options
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
Packit Service 15f37d
	options := osbuild.GroupsStageOptions{
Packit Service 15f37d
		Groups: map[string]osbuild.GroupsStageOptionsGroup{},
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	for _, group := range groups {
Packit Service 15f37d
		groupData := osbuild.GroupsStageOptionsGroup{
Packit Service 15f37d
			Name: group.Name,
Packit Service 15f37d
		}
Packit Service 15f37d
		groupData.GID = group.GID
Packit Service 15f37d
Packit Service 15f37d
		options.Groups[group.Name] = groupData
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return &options
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
Packit Service 15f37d
	options := osbuild.FirewallStageOptions{
Packit Service 15f37d
		Ports: firewall.Ports,
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if firewall.Services != nil {
Packit Service 15f37d
		options.EnabledServices = firewall.Services.Enabled
Packit Service 15f37d
		options.DisabledServices = firewall.Services.Disabled
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return &options
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
Packit Service 15f37d
	if s != nil {
Packit Service 15f37d
		enabledServices = append(enabledServices, s.Enabled...)
Packit Service 15f37d
		disabledServices = append(disabledServices, s.Disabled...)
Packit Service 15f37d
	}
Packit Service 15f37d
	return &osbuild.SystemdStageOptions{
Packit Service 15f37d
		EnabledServices:  enabledServices,
Packit Service 15f37d
		DisabledServices: disabledServices,
Packit Service 15f37d
		DefaultTarget:    target,
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) buildStampStageOptions() *osbuild.BuildstampStageOptions {
Packit Service 15f37d
	return &osbuild.BuildstampStageOptions{
Packit Service 15f37d
		Arch:    t.Arch().Name(),
Packit Service 15f37d
		Product: "Red Hat Enterprise Linux",
Packit Service 15f37d
		Version: "8.4",
Packit Service 15f37d
		Variant: "edge",
Packit Service 15f37d
		Final:   true,
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) anacondaStageOptions() *osbuild.AnacondaStageOptions {
Packit Service 15f37d
	return &osbuild.AnacondaStageOptions{
Packit Service 15f37d
		KickstartModules: []string{
Packit Service 15f37d
			"org.fedoraproject.Anaconda.Modules.Network",
Packit Service 15f37d
			"org.fedoraproject.Anaconda.Modules.Payloads",
Packit Service 15f37d
			"org.fedoraproject.Anaconda.Modules.Storage",
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) loraxScriptStageOptions() *osbuild.LoraxScriptStageOptions {
Packit Service 15f37d
	return &osbuild.LoraxScriptStageOptions{
Packit Service 15f37d
		Path:     "99-generic/runtime-postinstall.tmpl",
Packit Service 15f37d
		BaseArch: t.Arch().Name(),
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) dracutStageOptions(kernelVer string) *osbuild.DracutStageOptions {
Packit Service 15f37d
	kernel := []string{kernelVer}
Packit Service 15f37d
	modules := []string{
Packit Service 15f37d
		"bash",
Packit Service 15f37d
		"systemd",
Packit Service 15f37d
		"fips",
Packit Service 15f37d
		"systemd-initrd",
Packit Service 15f37d
		"modsign",
Packit Service 15f37d
		"nss-softokn",
Packit Service 15f37d
		"rdma",
Packit Service 15f37d
		"rngd",
Packit Service 15f37d
		"i18n",
Packit Service 15f37d
		"convertfs",
Packit Service 15f37d
		"network-manager",
Packit Service 15f37d
		"network",
Packit Service 15f37d
		"ifcfg",
Packit Service 15f37d
		"url-lib",
Packit Service 15f37d
		"drm",
Packit Service 15f37d
		"plymouth",
Packit Service 15f37d
		"prefixdevname",
Packit Service 15f37d
		"prefixdevname-tools",
Packit Service 15f37d
		"anaconda",
Packit Service 15f37d
		"crypt",
Packit Service 15f37d
		"dm",
Packit Service 15f37d
		"dmsquash-live",
Packit Service 15f37d
		"kernel-modules",
Packit Service 15f37d
		"kernel-modules-extra",
Packit Service 15f37d
		"kernel-network-modules",
Packit Service 15f37d
		"livenet",
Packit Service 15f37d
		"lvm",
Packit Service 15f37d
		"mdraid",
Packit Service 15f37d
		"multipath",
Packit Service 15f37d
		"qemu",
Packit Service 15f37d
		"qemu-net",
Packit Service 15f37d
		"fcoe",
Packit Service 15f37d
		"fcoe-uefi",
Packit Service 15f37d
		"iscsi",
Packit Service 15f37d
		"lunmask",
Packit Service 15f37d
		"nfs",
Packit Service 15f37d
		"resume",
Packit Service 15f37d
		"rootfs-block",
Packit Service 15f37d
		"terminfo",
Packit Service 15f37d
		"udev-rules",
Packit Service 15f37d
		"biosdevname",
Packit Service 15f37d
		"dracut-systemd",
Packit Service 15f37d
		"pollcdrom",
Packit Service 15f37d
		"usrmount",
Packit Service 15f37d
		"base",
Packit Service 15f37d
		"fs-lib",
Packit Service 15f37d
		"img-lib",
Packit Service 15f37d
		"shutdown",
Packit Service 15f37d
		"uefi-lib",
Packit Service 15f37d
	}
Packit Service 15f37d
	return &osbuild.DracutStageOptions{
Packit Service 15f37d
		Kernel:  kernel,
Packit Service 15f37d
		Modules: modules,
Packit Service 15f37d
		Install: []string{"/.buildstamp"},
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 464a89
func (t *imageTypeS2) kickstartStageOptions(ostreeURL, ostreeRef string) *osbuild.KickstartStageOptions {
Packit Service 15f37d
	return &osbuild.KickstartStageOptions{
Packit Service 15f37d
		Path: "/usr/share/anaconda/interactive-defaults.ks",
Packit Service 15f37d
		OSTree: osbuild.OSTreeOptions{
Packit Service 15f37d
			OSName: "rhel",
Packit Service 15f37d
			URL:    ostreeURL,
Packit Service 464a89
			Ref:    ostreeRef,
Packit Service 15f37d
			GPG:    false,
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) bootISOMonoStageOptions(kernelVer string) *osbuild.BootISOMonoStageOptions {
Packit Service 15f37d
	return &osbuild.BootISOMonoStageOptions{
Packit Service 15f37d
		Product: osbuild.Product{
Packit Service 15f37d
			Name:    "Red Hat Enterprise Linux",
Packit Service 15f37d
			Version: "8.4",
Packit Service 15f37d
		},
Packit Service 15f37d
		ISOLabel: fmt.Sprintf("RHEL-8-4-0-BaseOS-%s", t.Arch().Name()),
Packit Service 15f37d
		Kernel:   kernelVer,
Packit Service 15f37d
		EFI: osbuild.EFI{
Packit Service 15f37d
			Architectures: []string{
Packit Service 15f37d
				"IA32",
Packit Service 15f37d
				"X64",
Packit Service 15f37d
			},
Packit Service 15f37d
			Vendor: "redhat",
Packit Service 15f37d
		},
Packit Service 15f37d
		ISOLinux: osbuild.ISOLinux{
Packit Service 15f37d
			Enabled: true,
Packit Service 15f37d
			Debug:   false,
Packit Service 15f37d
		},
Packit Service 15f37d
		Templates: "80-rhel",
Packit Service 15f37d
		RootFS: osbuild.RootFS{
Packit Service 15f37d
			Size: 4096,
Packit Service 15f37d
			Compression: osbuild.FSCompression{
Packit Service 15f37d
				Method: "xz",
Packit Service 15f37d
				Options: osbuild.FSCompressionOptions{
Packit Service 15f37d
					// TODO: based on image arch
Packit Service 15f37d
					BCJ: "x86",
Packit Service 15f37d
				},
Packit Service 15f37d
			},
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) bootISOMonoStageInputs() *osbuild.BootISOMonoStageInputs {
Packit Service 15f37d
	rootfsInput := new(osbuild.BootISOMonoStageInput)
Packit Service 15f37d
	rootfsInput.Type = "org.osbuild.tree"
Packit Service 15f37d
	rootfsInput.Origin = "org.osbuild.pipeline"
Packit Service 15f37d
	rootfsInput.References = osbuild.BootISOMonoStageReferences{"name:anaconda-tree"}
Packit Service 15f37d
	return &osbuild.BootISOMonoStageInputs{
Packit Service 15f37d
		RootFS: rootfsInput,
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) discinfoStageOptions() *osbuild.DiscinfoStageOptions {
Packit Service 15f37d
	return &osbuild.DiscinfoStageOptions{
Packit Service 15f37d
		BaseArch: t.Arch().Name(),
Packit Service 15f37d
		Release:  "202010217.n.0",
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) xorrisofsStageOptions() *osbuild.XorrisofsStageOptions {
Packit Service 15f37d
	return &osbuild.XorrisofsStageOptions{
Packit Service 15f37d
		Filename: t.Filename(),
Packit Service 15f37d
		VolID:    fmt.Sprintf("RHEL-8-4-0-BaseOS-%s", t.Arch().Name()),
Packit Service 15f37d
		SysID:    "LINUX",
Packit Service 15f37d
		Boot: osbuild.XorrisofsBoot{
Packit Service 15f37d
			Image:   "isolinux/isolinux.bin",
Packit Service 15f37d
			Catalog: "isolinux/boot.cat",
Packit Service 15f37d
		},
Packit Service 15f37d
		EFI:          "images/efiboot.img",
Packit Service 15f37d
		IsohybridMBR: "/usr/share/syslinux/isohdpfx.bin",
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageTypeS2) xorrisofsStageInputs() *osbuild.XorrisofsStageInputs {
Packit Service 15f37d
	input := new(osbuild.XorrisofsStageInput)
Packit Service 15f37d
	input.Type = "org.osbuild.tree"
Packit Service 15f37d
	input.Origin = "org.osbuild.pipeline"
Packit Service 15f37d
	input.References = osbuild.XorrisofsStageReferences{"name:bootiso-tree"}
Packit Service 15f37d
	return &osbuild.XorrisofsStageInputs{Tree: input}
Packit Service 15f37d
}