distro/rhel8: update edge commit and container to new definitions
This commit is contained in:
parent
fad1d528ee
commit
3b1a51fd0d
6 changed files with 76 additions and 704 deletions
|
|
@ -15,8 +15,7 @@ func edgeCommitImgType(rd distribution) imageType {
|
|||
filename: "commit.tar",
|
||||
mimeType: "application/x-tar",
|
||||
packageSets: map[string]packageSetFunc{
|
||||
buildPkgsKey: edgeBuildPackageSet,
|
||||
osPkgsKey: edgeCommitPackageSet,
|
||||
osPkgsKey: edgeCommitPackageSet,
|
||||
},
|
||||
packageSetChains: map[string][]string{
|
||||
osPkgsKey: {osPkgsKey, blueprintPkgsKey},
|
||||
|
|
@ -25,9 +24,9 @@ func edgeCommitImgType(rd distribution) imageType {
|
|||
EnabledServices: edgeServices(rd),
|
||||
},
|
||||
rpmOstree: true,
|
||||
pipelines: edgeCommitPipelines,
|
||||
image: edgeCommitImage,
|
||||
buildPipelines: []string{"build"},
|
||||
payloadPipelines: []string{"ostree-tree", "ostree-commit", "commit-archive"},
|
||||
payloadPipelines: []string{"os", "ostree-commit", "commit-archive"},
|
||||
exports: []string{"commit-archive"},
|
||||
}
|
||||
return it
|
||||
|
|
@ -40,8 +39,7 @@ func edgeOCIImgType(rd distribution) imageType {
|
|||
filename: "container.tar",
|
||||
mimeType: "application/x-tar",
|
||||
packageSets: map[string]packageSetFunc{
|
||||
buildPkgsKey: edgeBuildPackageSet,
|
||||
osPkgsKey: edgeCommitPackageSet,
|
||||
osPkgsKey: edgeCommitPackageSet,
|
||||
containerPkgsKey: func(t *imageType) rpmmd.PackageSet {
|
||||
return rpmmd.PackageSet{
|
||||
Include: []string{"nginx"},
|
||||
|
|
@ -56,13 +54,14 @@ func edgeOCIImgType(rd distribution) imageType {
|
|||
},
|
||||
rpmOstree: true,
|
||||
bootISO: false,
|
||||
pipelines: edgeContainerPipelines,
|
||||
image: edgeContainerImage,
|
||||
buildPipelines: []string{"build"},
|
||||
payloadPipelines: []string{"ostree-tree", "ostree-commit", "container-tree", "container"},
|
||||
payloadPipelines: []string{"os", "ostree-commit", "container-tree", "container"},
|
||||
exports: []string{"container"},
|
||||
}
|
||||
return it
|
||||
}
|
||||
|
||||
func edgeRawImgType() imageType {
|
||||
it := imageType{
|
||||
name: "edge-raw-image",
|
||||
|
|
@ -144,17 +143,6 @@ func edgeSimplifiedInstallerImgType(rd distribution) imageType {
|
|||
return it
|
||||
}
|
||||
|
||||
// common edge image build package set
|
||||
func edgeBuildPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
return distroBuildPackageSet(t).Append(
|
||||
rpmmd.PackageSet{
|
||||
Include: []string{
|
||||
"rpm-ostree",
|
||||
},
|
||||
Exclude: nil,
|
||||
})
|
||||
}
|
||||
|
||||
// edge commit OS package set
|
||||
func edgeCommitPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
ps := rpmmd.PackageSet{
|
||||
|
|
|
|||
|
|
@ -260,6 +260,75 @@ func tarImage(workload workload.Workload,
|
|||
|
||||
}
|
||||
|
||||
func edgeCommitImage(workload workload.Workload,
|
||||
t *imageType,
|
||||
customizations *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
packageSets map[string]rpmmd.PackageSet,
|
||||
containers []container.Spec,
|
||||
rng *rand.Rand) (image.ImageKind, error) {
|
||||
|
||||
img := image.NewOSTreeArchive(options.OSTree.ImageRef)
|
||||
|
||||
img.Platform = t.platform
|
||||
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], options, containers, customizations)
|
||||
img.Environment = t.environment
|
||||
img.Workload = workload
|
||||
|
||||
if options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" {
|
||||
img.OSTreeParent = &ostree.CommitSpec{
|
||||
Checksum: options.OSTree.FetchChecksum,
|
||||
URL: options.OSTree.URL,
|
||||
ContentURL: options.OSTree.ContentURL,
|
||||
}
|
||||
if options.OSTree.RHSM {
|
||||
img.OSTreeParent.Secrets = "org.osbuild.rhsm.consumer"
|
||||
}
|
||||
}
|
||||
|
||||
img.OSVersion = t.arch.distro.osVersion
|
||||
|
||||
img.Filename = t.Filename()
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func edgeContainerImage(workload workload.Workload,
|
||||
t *imageType,
|
||||
customizations *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
packageSets map[string]rpmmd.PackageSet,
|
||||
containers []container.Spec,
|
||||
rng *rand.Rand) (image.ImageKind, error) {
|
||||
|
||||
img := image.NewOSTreeContainer(options.OSTree.ImageRef)
|
||||
|
||||
img.Platform = t.platform
|
||||
img.OSCustomizations = osCustomizations(t, packageSets[osPkgsKey], options, containers, customizations)
|
||||
img.ContainerLanguage = img.OSCustomizations.Language
|
||||
img.Environment = t.environment
|
||||
img.Workload = workload
|
||||
|
||||
if options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" {
|
||||
img.OSTreeParent = &ostree.CommitSpec{
|
||||
Checksum: options.OSTree.FetchChecksum,
|
||||
URL: options.OSTree.URL,
|
||||
ContentURL: options.OSTree.ContentURL,
|
||||
}
|
||||
if options.OSTree.RHSM {
|
||||
img.OSTreeParent.Secrets = "org.osbuild.rhsm.consumer"
|
||||
}
|
||||
}
|
||||
|
||||
img.OSVersion = t.arch.distro.osVersion
|
||||
|
||||
img.ExtraContainerPackages = packageSets[containerPkgsKey]
|
||||
|
||||
img.Filename = t.Filename()
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func edgeInstallerImage(workload workload.Workload,
|
||||
t *imageType,
|
||||
customizations *blueprint.Customizations,
|
||||
|
|
|
|||
|
|
@ -239,14 +239,6 @@ func (t *imageType) getBootType() distro.BootType {
|
|||
return bootType
|
||||
}
|
||||
|
||||
func (t *imageType) supportsUEFI() bool {
|
||||
bootType := t.getBootType()
|
||||
if bootType == distro.HybridBootType || bootType == distro.UEFIBootType {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *imageType) getPartitionTable(
|
||||
mountpoints []blueprint.FilesystemCustomization,
|
||||
options distro.ImageOptions,
|
||||
|
|
|
|||
|
|
@ -9,57 +9,6 @@ import (
|
|||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
// BUILD PACKAGE SETS
|
||||
|
||||
// distro-wide build package set
|
||||
func distroBuildPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
ps := rpmmd.PackageSet{
|
||||
Include: []string{
|
||||
"dnf",
|
||||
"dosfstools",
|
||||
"e2fsprogs",
|
||||
"glibc",
|
||||
"lorax-templates-generic",
|
||||
"lorax-templates-rhel",
|
||||
"lvm2",
|
||||
"policycoreutils",
|
||||
"python36",
|
||||
"python3-iniparse",
|
||||
"qemu-img",
|
||||
"selinux-policy-targeted",
|
||||
"systemd",
|
||||
"tar",
|
||||
"xfsprogs",
|
||||
"xz",
|
||||
},
|
||||
}
|
||||
|
||||
switch t.arch.Name() {
|
||||
|
||||
case distro.X86_64ArchName:
|
||||
ps = ps.Append(x8664BuildPackageSet(t))
|
||||
|
||||
case distro.Ppc64leArchName:
|
||||
ps = ps.Append(ppc64leBuildPackageSet(t))
|
||||
}
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
// x86_64 build package set
|
||||
func x8664BuildPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
return rpmmd.PackageSet{
|
||||
Include: []string{"grub2-pc"},
|
||||
}
|
||||
}
|
||||
|
||||
// ppc64le build package set
|
||||
func ppc64leBuildPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
return rpmmd.PackageSet{
|
||||
Include: []string{"grub2-ppc64le", "grub2-ppc64le-modules"},
|
||||
}
|
||||
}
|
||||
|
||||
// installer boot package sets, needed for booting and
|
||||
// also in the build host
|
||||
|
||||
|
|
|
|||
|
|
@ -1,509 +0,0 @@
|
|||
package rhel8
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
||||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/container"
|
||||
"github.com/osbuild/osbuild-composer/internal/disk"
|
||||
"github.com/osbuild/osbuild-composer/internal/distro"
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
"github.com/osbuild/osbuild-composer/internal/users"
|
||||
)
|
||||
|
||||
func prependKernelCmdlineStage(pipeline *osbuild.Pipeline, t *imageType, pt *disk.PartitionTable) *osbuild.Pipeline {
|
||||
if t.Arch().Name() == distro.S390xArchName {
|
||||
rootFs := pt.FindMountable("/")
|
||||
if rootFs == nil {
|
||||
panic("s390x image must have a root filesystem, this is a programming error")
|
||||
}
|
||||
kernelStage := osbuild.NewKernelCmdlineStage(osbuild.NewKernelCmdlineStageOptions(rootFs.GetFSSpec().UUID, t.kernelOptions))
|
||||
pipeline.Stages = append([]*osbuild.Stage{kernelStage}, pipeline.Stages...)
|
||||
}
|
||||
return pipeline
|
||||
}
|
||||
|
||||
func edgeCorePipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, containers []container.Spec) ([]osbuild.Pipeline, error) {
|
||||
pipelines := make([]osbuild.Pipeline, 0)
|
||||
pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner.String()))
|
||||
|
||||
treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], containers, customizations, options, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pipelines = append(pipelines, *treePipeline)
|
||||
pipelines = append(pipelines, *ostreeCommitPipeline(options, t.arch.distro.osVersion))
|
||||
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func edgeCommitPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, containers []container.Spec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines, err := edgeCorePipelines(t, customizations, options, repos, packageSetSpecs, containers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tarPipeline := tarArchivePipeline("commit-archive", "ostree-commit", &osbuild.TarStageOptions{Filename: t.Filename()})
|
||||
pipelines = append(pipelines, *tarPipeline)
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func edgeContainerPipelines(t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, containers []container.Spec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
pipelines, err := edgeCorePipelines(t, customizations, options, repos, packageSetSpecs, containers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nginxConfigPath := "/etc/nginx.conf"
|
||||
httpPort := "8080"
|
||||
pipelines = append(pipelines, *containerTreePipeline(repos, packageSetSpecs[containerPkgsKey], options, customizations, nginxConfigPath, httpPort))
|
||||
pipelines = append(pipelines, *containerPipeline(t, nginxConfigPath, httpPort))
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func buildPipeline(repos []rpmmd.RepoConfig, buildPackageSpecs []rpmmd.PackageSpec, runner string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "build"
|
||||
p.Runner = runner
|
||||
p.AddStage(osbuild.NewRPMStage(osbuild.NewRPMStageOptions(repos), osbuild.NewRpmStageSourceFilesInputs(buildPackageSpecs)))
|
||||
p.AddStage(osbuild.NewSELinuxStage(selinuxStageOptions(true)))
|
||||
return p
|
||||
}
|
||||
|
||||
func osPipeline(t *imageType,
|
||||
repos []rpmmd.RepoConfig,
|
||||
packages []rpmmd.PackageSpec,
|
||||
containers []container.Spec,
|
||||
c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
pt *disk.PartitionTable) (*osbuild.Pipeline, error) {
|
||||
imageConfig := t.getDefaultImageConfig()
|
||||
p := new(osbuild.Pipeline)
|
||||
if t.rpmOstree {
|
||||
p.Name = "ostree-tree"
|
||||
} else {
|
||||
p.Name = "os"
|
||||
}
|
||||
p.Build = "name:build"
|
||||
|
||||
if t.rpmOstree && options.OSTree.FetchChecksum != "" && options.OSTree.URL != "" {
|
||||
p.AddStage(osbuild.NewOSTreePasswdStage("org.osbuild.source", options.OSTree.FetchChecksum))
|
||||
}
|
||||
|
||||
rpmOptions := osbuild.NewRPMStageOptions(repos)
|
||||
rpmOptions.GPGKeysFromTree = imageConfig.GPGKeyFiles
|
||||
|
||||
if imageConfig.ExcludeDocs != nil && *imageConfig.ExcludeDocs {
|
||||
if rpmOptions.Exclude == nil {
|
||||
rpmOptions.Exclude = &osbuild.Exclude{}
|
||||
}
|
||||
rpmOptions.Exclude.Docs = true
|
||||
}
|
||||
p.AddStage(osbuild.NewRPMStage(rpmOptions, osbuild.NewRpmStageSourceFilesInputs(packages)))
|
||||
|
||||
// If the /boot is on a separate partition, the prefix for the BLS stage must be ""
|
||||
if pt == nil || pt.FindMountable("/boot") == nil {
|
||||
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{}))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.ToPtr("")}))
|
||||
}
|
||||
|
||||
if len(containers) > 0 {
|
||||
images := osbuild.NewContainersInputForSources(containers)
|
||||
|
||||
var storagePath string
|
||||
|
||||
// OSTree commits do not include data in `/var` since that is tied to the
|
||||
// deployment, rather than the commit. Therefore the containers need to be
|
||||
// stored in a different location, like `/usr/share`, and the container
|
||||
// storage engine configured accordingly.
|
||||
if t.rpmOstree {
|
||||
storagePath = "/usr/share/containers/storage"
|
||||
storageConf := "/etc/containers/storage.conf"
|
||||
|
||||
containerStoreOpts := osbuild.NewContainerStorageOptions(storageConf, storagePath)
|
||||
p.AddStage(osbuild.NewContainersStorageConfStage(containerStoreOpts))
|
||||
}
|
||||
|
||||
skopeo := osbuild.NewSkopeoStage(images, storagePath)
|
||||
p.AddStage(skopeo)
|
||||
}
|
||||
|
||||
language, keyboard := c.GetPrimaryLocale()
|
||||
if language != nil {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
|
||||
} else if imageConfig.Locale != nil {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *imageConfig.Locale}))
|
||||
}
|
||||
if keyboard != nil {
|
||||
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
|
||||
} else if imageConfig.Keyboard != nil {
|
||||
p.AddStage(osbuild.NewKeymapStage(imageConfig.Keyboard))
|
||||
}
|
||||
|
||||
if hostname := c.GetHostname(); hostname != nil {
|
||||
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
|
||||
}
|
||||
|
||||
timezone, ntpServers := c.GetTimezoneSettings()
|
||||
if timezone != nil {
|
||||
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
|
||||
} else if imageConfig.Timezone != nil {
|
||||
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *imageConfig.Timezone}))
|
||||
}
|
||||
|
||||
if len(ntpServers) > 0 {
|
||||
servers := make([]osbuild.ChronyConfigServer, len(ntpServers))
|
||||
for idx, server := range ntpServers {
|
||||
servers[idx] = osbuild.ChronyConfigServer{Hostname: server}
|
||||
}
|
||||
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Servers: servers}))
|
||||
} else if imageConfig.TimeSynchronization != nil {
|
||||
p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization))
|
||||
}
|
||||
|
||||
if !t.bootISO {
|
||||
// don't put users and groups in the payload of an installer
|
||||
// add them via kickstart instead
|
||||
if groups := c.GetGroups(); len(groups) > 0 {
|
||||
p.AddStage(osbuild.NewGroupsStage(osbuild.NewGroupsStageOptions(users.GroupsFromBP(groups))))
|
||||
}
|
||||
|
||||
if userOptions, err := osbuild.NewUsersStageOptions(users.UsersFromBP(c.GetUsers()), false); err != nil {
|
||||
return nil, err
|
||||
} else if userOptions != nil {
|
||||
if t.rpmOstree {
|
||||
// for ostree, writing the key during user creation is
|
||||
// redundant and can cause issues so create users without keys
|
||||
// and write them on first boot
|
||||
userOptionsSansKeys, err := osbuild.NewUsersStageOptions(users.UsersFromBP(c.GetUsers()), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.AddStage(osbuild.NewUsersStage(userOptionsSansKeys))
|
||||
p.AddStage(osbuild.NewFirstBootStage(usersFirstBootOptions(userOptions)))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewUsersStage(userOptions))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil ||
|
||||
imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != nil {
|
||||
defaultTarget := ""
|
||||
if imageConfig.DefaultTarget != nil {
|
||||
defaultTarget = *imageConfig.DefaultTarget
|
||||
}
|
||||
p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(
|
||||
imageConfig.EnabledServices,
|
||||
imageConfig.DisabledServices,
|
||||
services,
|
||||
defaultTarget,
|
||||
)))
|
||||
}
|
||||
|
||||
var fwStageOptions *osbuild.FirewallStageOptions
|
||||
if firewallCustomization := c.GetFirewall(); firewallCustomization != nil {
|
||||
fwStageOptions = firewallStageOptions(firewallCustomization)
|
||||
}
|
||||
if firewallConfig := imageConfig.Firewall; firewallConfig != nil {
|
||||
// merge the user-provided firewall config with the default one
|
||||
if fwStageOptions != nil {
|
||||
fwStageOptions = &osbuild.FirewallStageOptions{
|
||||
// Prefer the firewall ports, services and zone settings provided
|
||||
// via BP customization.
|
||||
Ports: fwStageOptions.Ports,
|
||||
EnabledServices: fwStageOptions.EnabledServices,
|
||||
DisabledServices: fwStageOptions.DisabledServices,
|
||||
Zones: fwStageOptions.Zones,
|
||||
// Default zone can not be set using BP customizations, therefore
|
||||
// default to the one provided in the default image configuration.
|
||||
DefaultZone: firewallConfig.DefaultZone,
|
||||
}
|
||||
} else {
|
||||
fwStageOptions = firewallConfig
|
||||
}
|
||||
}
|
||||
if fwStageOptions != nil {
|
||||
p.AddStage(osbuild.NewFirewallStage(fwStageOptions))
|
||||
}
|
||||
|
||||
for _, sysconfigConfig := range imageConfig.Sysconfig {
|
||||
p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig))
|
||||
}
|
||||
|
||||
if t.arch.distro.isRHEL() {
|
||||
if options.Subscription != nil {
|
||||
commands := []string{
|
||||
fmt.Sprintf("/usr/sbin/subscription-manager register --org=%s --activationkey=%s --serverurl %s --baseurl %s", options.Subscription.Organization, options.Subscription.ActivationKey, options.Subscription.ServerUrl, options.Subscription.BaseUrl),
|
||||
}
|
||||
if options.Subscription.Insights {
|
||||
commands = append(commands, "/usr/bin/insights-client --register")
|
||||
}
|
||||
p.AddStage(osbuild.NewFirstBootStage(&osbuild.FirstBootStageOptions{
|
||||
Commands: commands,
|
||||
WaitForNetwork: true,
|
||||
}))
|
||||
|
||||
if rhsmConfig, exists := imageConfig.RHSMConfig[distro.RHSMConfigWithSubscription]; exists {
|
||||
p.AddStage(osbuild.NewRHSMStage(rhsmConfig))
|
||||
}
|
||||
} else {
|
||||
if rhsmConfig, exists := imageConfig.RHSMConfig[distro.RHSMConfigNoSubscription]; exists {
|
||||
p.AddStage(osbuild.NewRHSMStage(rhsmConfig))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, systemdLogindConfig := range imageConfig.SystemdLogind {
|
||||
p.AddStage(osbuild.NewSystemdLogindStage(systemdLogindConfig))
|
||||
}
|
||||
|
||||
for _, cloudInitConfig := range imageConfig.CloudInit {
|
||||
p.AddStage(osbuild.NewCloudInitStage(cloudInitConfig))
|
||||
}
|
||||
|
||||
for _, modprobeConfig := range imageConfig.Modprobe {
|
||||
p.AddStage(osbuild.NewModprobeStage(modprobeConfig))
|
||||
}
|
||||
|
||||
for _, dracutConfConfig := range imageConfig.DracutConf {
|
||||
p.AddStage(osbuild.NewDracutConfStage(dracutConfConfig))
|
||||
}
|
||||
|
||||
for _, systemdUnitConfig := range imageConfig.SystemdUnit {
|
||||
p.AddStage(osbuild.NewSystemdUnitStage(systemdUnitConfig))
|
||||
}
|
||||
|
||||
if authselectConfig := imageConfig.Authselect; authselectConfig != nil {
|
||||
p.AddStage(osbuild.NewAuthselectStage(authselectConfig))
|
||||
}
|
||||
|
||||
if seLinuxConfig := imageConfig.SELinuxConfig; seLinuxConfig != nil {
|
||||
p.AddStage(osbuild.NewSELinuxConfigStage(seLinuxConfig))
|
||||
}
|
||||
|
||||
if tunedConfig := imageConfig.Tuned; tunedConfig != nil {
|
||||
p.AddStage(osbuild.NewTunedStage(tunedConfig))
|
||||
}
|
||||
|
||||
for _, tmpfilesdConfig := range imageConfig.Tmpfilesd {
|
||||
p.AddStage(osbuild.NewTmpfilesdStage(tmpfilesdConfig))
|
||||
}
|
||||
|
||||
for _, pamLimitsConfConfig := range imageConfig.PamLimitsConf {
|
||||
p.AddStage(osbuild.NewPamLimitsConfStage(pamLimitsConfConfig))
|
||||
}
|
||||
|
||||
for _, sysctldConfig := range imageConfig.Sysctld {
|
||||
p.AddStage(osbuild.NewSysctldStage(sysctldConfig))
|
||||
}
|
||||
|
||||
for _, dnfConfig := range imageConfig.DNFConfig {
|
||||
p.AddStage(osbuild.NewDNFConfigStage(dnfConfig))
|
||||
}
|
||||
|
||||
if sshdConfig := imageConfig.SshdConfig; sshdConfig != nil {
|
||||
p.AddStage((osbuild.NewSshdConfigStage(sshdConfig)))
|
||||
}
|
||||
|
||||
if authConfig := imageConfig.Authconfig; authConfig != nil {
|
||||
p.AddStage(osbuild.NewAuthconfigStage(authConfig))
|
||||
}
|
||||
|
||||
if pwQuality := imageConfig.PwQuality; pwQuality != nil {
|
||||
p.AddStage(osbuild.NewPwqualityConfStage(pwQuality))
|
||||
}
|
||||
|
||||
if waConfig := imageConfig.WAAgentConfig; waConfig != nil {
|
||||
p.AddStage(osbuild.NewWAAgentConfStage(waConfig))
|
||||
}
|
||||
|
||||
if dnfAutomaticConfig := imageConfig.DNFAutomaticConfig; dnfAutomaticConfig != nil {
|
||||
p.AddStage(osbuild.NewDNFAutomaticConfigStage(dnfAutomaticConfig))
|
||||
}
|
||||
|
||||
for _, yumRepo := range imageConfig.YUMRepos {
|
||||
p.AddStage(osbuild.NewYumReposStage(yumRepo))
|
||||
}
|
||||
|
||||
if gcpGuestAgentConfig := imageConfig.GCPGuestAgentConfig; gcpGuestAgentConfig != nil {
|
||||
p.AddStage(osbuild.NewGcpGuestAgentConfigStage(gcpGuestAgentConfig))
|
||||
}
|
||||
|
||||
if udevRules := imageConfig.UdevRules; udevRules != nil {
|
||||
p.AddStage(osbuild.NewUdevRulesStage(udevRules))
|
||||
}
|
||||
|
||||
if pt != nil {
|
||||
p = prependKernelCmdlineStage(p, t, pt)
|
||||
p.AddStage(osbuild.NewFSTabStage(osbuild.NewFSTabStageOptions(pt)))
|
||||
kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(packages, c.GetKernel().Name)
|
||||
bootloader := bootloaderConfigStage(t, *pt, c.GetKernel(), kernelVer, false, false)
|
||||
|
||||
if cfg := imageConfig.Grub2Config; cfg != nil {
|
||||
if grub2, ok := bootloader.Options.(*osbuild.GRUB2StageOptions); ok {
|
||||
|
||||
// grub2.Config.Default is owned and set by `NewGrub2StageOptions`
|
||||
// and thus we need to preserve it
|
||||
if grub2.Config != nil {
|
||||
cfg.Default = grub2.Config.Default
|
||||
}
|
||||
|
||||
grub2.Config = cfg
|
||||
}
|
||||
}
|
||||
|
||||
p.AddStage(bootloader)
|
||||
}
|
||||
|
||||
if oscapConfig := c.GetOpenSCAP(); oscapConfig != nil {
|
||||
if t.rpmOstree {
|
||||
return nil, fmt.Errorf("unexpected oscap options for ostree image type")
|
||||
}
|
||||
remediationOptions := osbuild.NewOscapRemediationStageOptions(
|
||||
osbuild.OscapConfig{
|
||||
Datastream: oscapConfig.DataStream,
|
||||
ProfileID: oscapConfig.ProfileID,
|
||||
},
|
||||
)
|
||||
p.AddStage(osbuild.NewOscapRemediationStage(remediationOptions))
|
||||
}
|
||||
|
||||
if t.arch.distro.isRHEL() && options.Facts != nil {
|
||||
p.AddStage(osbuild.NewRHSMFactsStage(&osbuild.RHSMFactsStageOptions{
|
||||
Facts: osbuild.RHSMFacts{
|
||||
ApiType: options.Facts.ApiType,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
if t.rpmOstree {
|
||||
p.AddStage(osbuild.NewSystemdJournaldStage(
|
||||
&osbuild.SystemdJournaldStageOptions{
|
||||
Filename: "10-persistent.conf",
|
||||
Config: osbuild.SystemdJournaldConfigDropin{
|
||||
Journal: osbuild.SystemdJournaldConfigJournalSection{
|
||||
Storage: osbuild.StoragePresistent,
|
||||
},
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
// Relabel the tree, unless the `NoSElinux` flag is explicitly set to `true`
|
||||
if imageConfig.NoSElinux == nil || imageConfig.NoSElinux != nil && !*imageConfig.NoSElinux {
|
||||
p.AddStage(osbuild.NewSELinuxStage(selinuxStageOptions(false)))
|
||||
}
|
||||
|
||||
if t.rpmOstree {
|
||||
p.AddStage(osbuild.NewOSTreePrepTreeStage(&osbuild.OSTreePrepTreeStageOptions{
|
||||
EtcGroupMembers: []string{
|
||||
// NOTE: We may want to make this configurable.
|
||||
"wheel", "docker",
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "ostree-commit"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: "/repo"}))
|
||||
|
||||
p.AddStage(
|
||||
osbuild.NewOSTreeCommitStage(
|
||||
&osbuild.OSTreeCommitStageOptions{
|
||||
Ref: options.OSTree.ImageRef,
|
||||
OSVersion: osVersion,
|
||||
Parent: options.OSTree.FetchChecksum,
|
||||
},
|
||||
"ostree-tree",
|
||||
),
|
||||
)
|
||||
return p
|
||||
}
|
||||
|
||||
func containerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, options distro.ImageOptions, c *blueprint.Customizations, nginxConfigPath, listenPort string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "container-tree"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewRPMStage(osbuild.NewRPMStageOptions(repos), osbuild.NewRpmStageSourceFilesInputs(packages)))
|
||||
language, _ := c.GetPrimaryLocale()
|
||||
if language != nil {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US"}))
|
||||
}
|
||||
|
||||
htmlRoot := "/usr/share/nginx/html"
|
||||
repoPath := filepath.Join(htmlRoot, "repo")
|
||||
p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: repoPath}))
|
||||
|
||||
p.AddStage(osbuild.NewOSTreePullStage(
|
||||
&osbuild.OSTreePullStageOptions{Repo: repoPath},
|
||||
osbuild.NewOstreePullStageInputs("org.osbuild.pipeline", "name:ostree-commit", options.OSTree.ImageRef),
|
||||
))
|
||||
|
||||
// make nginx log directory world writeable, otherwise nginx can't start in
|
||||
// an unprivileged container
|
||||
p.AddStage(osbuild.NewChmodStage(chmodStageOptions("/var/log/nginx", "o+w", true)))
|
||||
|
||||
p.AddStage(osbuild.NewNginxConfigStage(nginxConfigStageOptions(nginxConfigPath, htmlRoot, listenPort)))
|
||||
return p
|
||||
}
|
||||
|
||||
func containerPipeline(t *imageType, nginxConfigPath, listenPort string) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "container"
|
||||
p.Build = "name:build"
|
||||
options := &osbuild.OCIArchiveStageOptions{
|
||||
Architecture: t.arch.Name(),
|
||||
Filename: t.Filename(),
|
||||
Config: &osbuild.OCIArchiveConfig{
|
||||
Cmd: []string{"nginx", "-c", nginxConfigPath},
|
||||
ExposedPorts: []string{listenPort},
|
||||
},
|
||||
}
|
||||
baseInput := osbuild.NewTreeInput("name:container-tree")
|
||||
inputs := &osbuild.OCIArchiveStageInputs{Base: baseInput}
|
||||
p.AddStage(osbuild.NewOCIArchiveStage(options, inputs))
|
||||
return p
|
||||
}
|
||||
|
||||
func tarArchivePipeline(name, inputPipelineName string, tarOptions *osbuild.TarStageOptions) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = name
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewTarStage(tarOptions, inputPipelineName))
|
||||
return p
|
||||
}
|
||||
|
||||
func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, kernel *blueprint.KernelCustomization, kernelVer string, install, greenboot bool) *osbuild.Stage {
|
||||
if t.Arch().Name() == distro.S390xArchName {
|
||||
return osbuild.NewZiplStage(new(osbuild.ZiplStageOptions))
|
||||
}
|
||||
|
||||
kernelOptions := t.kernelOptions
|
||||
uefi := t.supportsUEFI()
|
||||
legacy := t.arch.legacy
|
||||
|
||||
options := osbuild.NewGrub2StageOptions(&partitionTable, kernelOptions, kernel, kernelVer, uefi, legacy, t.arch.distro.vendor, install)
|
||||
options.Greenboot = greenboot
|
||||
|
||||
// before unifying the org.osbuild.grub2 stage option generator, we didn't
|
||||
// set the following for RHEL 8.5, so we need to revert here to maintain
|
||||
// the old behaviour
|
||||
if uefi {
|
||||
options.UEFI.Unified = false
|
||||
}
|
||||
|
||||
return osbuild.NewGRUB2Stage(options)
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
package rhel8
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
||||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild"
|
||||
)
|
||||
|
||||
// selinuxStageOptions returns the options for the org.osbuild.selinux stage.
|
||||
// Setting the argument to 'true' relabels the '/usr/bin/cp' and '/usr/bin/tar'
|
||||
// binaries with 'install_exec_t'. This should be set in the build root.
|
||||
func selinuxStageOptions(labelcp bool) *osbuild.SELinuxStageOptions {
|
||||
options := &osbuild.SELinuxStageOptions{
|
||||
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
|
||||
}
|
||||
if labelcp {
|
||||
options.Labels = map[string]string{
|
||||
"/usr/bin/cp": "system_u:object_r:install_exec_t:s0",
|
||||
"/usr/bin/tar": "system_u:object_r:install_exec_t:s0",
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func usersFirstBootOptions(usersStageOptions *osbuild.UsersStageOptions) *osbuild.FirstBootStageOptions {
|
||||
cmds := make([]string, 0, 3*len(usersStageOptions.Users)+2)
|
||||
// workaround for creating authorized_keys file for user
|
||||
// need to special case the root user, which has its home in a different place
|
||||
varhome := filepath.Join("/var", "home")
|
||||
roothome := filepath.Join("/var", "roothome")
|
||||
|
||||
for name, user := range usersStageOptions.Users {
|
||||
if user.Key != nil {
|
||||
var home string
|
||||
|
||||
if name == "root" {
|
||||
home = roothome
|
||||
} else {
|
||||
home = filepath.Join(varhome, name)
|
||||
}
|
||||
|
||||
sshdir := filepath.Join(home, ".ssh")
|
||||
|
||||
cmds = append(cmds, fmt.Sprintf("mkdir -p %s", sshdir))
|
||||
cmds = append(cmds, fmt.Sprintf("sh -c 'echo %q >> %q'", *user.Key, filepath.Join(sshdir, "authorized_keys")))
|
||||
cmds = append(cmds, fmt.Sprintf("chown %s:%s -Rc %s", name, name, sshdir))
|
||||
}
|
||||
}
|
||||
cmds = append(cmds, fmt.Sprintf("restorecon -rvF %s", varhome))
|
||||
cmds = append(cmds, fmt.Sprintf("restorecon -rvF %s", roothome))
|
||||
|
||||
options := &osbuild.FirstBootStageOptions{
|
||||
Commands: cmds,
|
||||
WaitForNetwork: false,
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
func firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
|
||||
options := osbuild.FirewallStageOptions{
|
||||
Ports: firewall.Ports,
|
||||
}
|
||||
|
||||
if firewall.Services != nil {
|
||||
options.EnabledServices = firewall.Services.Enabled
|
||||
options.DisabledServices = firewall.Services.Disabled
|
||||
}
|
||||
|
||||
if len(firewall.Zones) != 0 {
|
||||
for _, z := range firewall.Zones {
|
||||
options.Zones = append(options.Zones, osbuild.FirewallZone{
|
||||
Name: *z.Name,
|
||||
Sources: z.Sources,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &options
|
||||
}
|
||||
|
||||
func systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
|
||||
if s != nil {
|
||||
enabledServices = append(enabledServices, s.Enabled...)
|
||||
disabledServices = append(disabledServices, s.Disabled...)
|
||||
}
|
||||
return &osbuild.SystemdStageOptions{
|
||||
EnabledServices: enabledServices,
|
||||
DisabledServices: disabledServices,
|
||||
DefaultTarget: target,
|
||||
}
|
||||
}
|
||||
|
||||
func nginxConfigStageOptions(path, htmlRoot, listen string) *osbuild.NginxConfigStageOptions {
|
||||
// configure nginx to work in an unprivileged container
|
||||
cfg := &osbuild.NginxConfig{
|
||||
Listen: listen,
|
||||
Root: htmlRoot,
|
||||
Daemon: common.ToPtr(false),
|
||||
PID: "/tmp/nginx.pid",
|
||||
}
|
||||
return &osbuild.NginxConfigStageOptions{
|
||||
Path: path,
|
||||
Config: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func chmodStageOptions(path, mode string, recursive bool) *osbuild.ChmodStageOptions {
|
||||
return &osbuild.ChmodStageOptions{
|
||||
Items: map[string]osbuild.ChmodStagePathOptions{
|
||||
path: {Mode: mode, Recursive: recursive},
|
||||
},
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue