From b200fa8fcdd78c66ff2bccd2ace70979fee9f34f Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Thu, 16 Dec 2021 13:37:39 +0100 Subject: [PATCH] RHEL-90: introduce default image config data structure Introduce a new data structure `ImageConfig` holding the default OS configuration applied when building an image. The structure can be used to hold the default image configuration on the distribution level with possible overrides defined on the image-type level. As a starting point, move hard-coded default values and configuration common for `osPipeline`, `ec2BaseTreePipeline` and `ostreeTreePipeline` to the distribution and image-type default image configuration. This is preparing the ground for merging all of these three pipeline functions into `osPipeline`, which will produce the appropriate OS pipeline based on the image-type configuration and the fact if it is rpmOstree or not. Regenerate affected EC2 and AMI manifests. There is however no change in the resulting image configuration and image-info report. Signed-off-by: Tomas Hozza --- internal/distro/image_config.go | 48 ++++ internal/distro/image_config_test.go | 167 ++++++++++++ internal/distro/rhel90/distro.go | 239 ++++++++++++------ internal/distro/rhel90/pipelines.go | 183 ++++++-------- .../manifests/rhel_90-aarch64-ami-boot.json | 22 +- .../manifests/rhel_90-aarch64-ec2-boot.json | 22 +- .../manifests/rhel_90-x86_64-ami-boot.json | 22 +- .../manifests/rhel_90-x86_64-ec2-boot.json | 22 +- .../manifests/rhel_90-x86_64-ec2_ha-boot.json | 22 +- .../rhel_90-x86_64-ec2_sap-boot.json | 22 +- 10 files changed, 526 insertions(+), 243 deletions(-) create mode 100644 internal/distro/image_config.go create mode 100644 internal/distro/image_config_test.go diff --git a/internal/distro/image_config.go b/internal/distro/image_config.go new file mode 100644 index 000000000..146c6f516 --- /dev/null +++ b/internal/distro/image_config.go @@ -0,0 +1,48 @@ +package distro + +import "github.com/osbuild/osbuild-composer/internal/osbuild2" + +// ImageConfig represents a (default) configuration applied to the image +type ImageConfig struct { + Timezone string + TimeSynchronization *osbuild2.ChronyStageOptions + Locale string + Keyboard *osbuild2.KeymapStageOptions + EnabledServices []string + DisabledServices []string + DefaultTarget string + Sysconfig []*osbuild2.SysconfigStageOptions +} + +// InheritFrom inherits unset values from the provided parent configuration and +// returns a new structure instance, which is a result of the inheritance. +func (c *ImageConfig) InheritFrom(parentConfig *ImageConfig) *ImageConfig { + finalConfig := ImageConfig(*c) + if parentConfig != nil { + if finalConfig.Timezone == "" { + finalConfig.Timezone = parentConfig.Timezone + } + if finalConfig.TimeSynchronization == nil { + finalConfig.TimeSynchronization = parentConfig.TimeSynchronization + } + if finalConfig.Locale == "" { + finalConfig.Locale = parentConfig.Locale + } + if finalConfig.Keyboard == nil { + finalConfig.Keyboard = parentConfig.Keyboard + } + if finalConfig.EnabledServices == nil { + finalConfig.EnabledServices = parentConfig.EnabledServices + } + if finalConfig.DisabledServices == nil { + finalConfig.DisabledServices = parentConfig.DisabledServices + } + if finalConfig.DefaultTarget == "" { + finalConfig.DefaultTarget = parentConfig.DefaultTarget + } + if finalConfig.Sysconfig == nil { + finalConfig.Sysconfig = parentConfig.Sysconfig + } + } + return &finalConfig +} diff --git a/internal/distro/image_config_test.go b/internal/distro/image_config_test.go new file mode 100644 index 000000000..dc5c57199 --- /dev/null +++ b/internal/distro/image_config_test.go @@ -0,0 +1,167 @@ +package distro + +import ( + "testing" + + "github.com/osbuild/osbuild-composer/internal/common" + "github.com/osbuild/osbuild-composer/internal/osbuild2" + "github.com/stretchr/testify/assert" +) + +func TestImageConfigInheritFrom(t *testing.T) { + tests := []struct { + name string + distroConfig *ImageConfig + imageConfig *ImageConfig + expectedConfig *ImageConfig + }{ + { + name: "inheritance with overridden values", + distroConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + imageConfig: &ImageConfig{ + Timezone: "UTC", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Servers: []osbuild2.ChronyConfigServer{ + { + Hostname: "169.254.169.123", + Prefer: common.BoolToPtr(true), + Iburst: common.BoolToPtr(true), + Minpoll: common.IntToPtr(4), + Maxpoll: common.IntToPtr(4), + }, + }, + LeapsecTz: common.StringToPtr(""), + }, + }, + expectedConfig: &ImageConfig{ + Timezone: "UTC", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Servers: []osbuild2.ChronyConfigServer{ + { + Hostname: "169.254.169.123", + Prefer: common.BoolToPtr(true), + Iburst: common.BoolToPtr(true), + Minpoll: common.IntToPtr(4), + Maxpoll: common.IntToPtr(4), + }, + }, + LeapsecTz: common.StringToPtr(""), + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + }, + { + name: "empty image type configuration", + distroConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + imageConfig: &ImageConfig{}, + expectedConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + }, + { + name: "empty distro configuration", + distroConfig: &ImageConfig{}, + imageConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + expectedConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + }, + { + name: "empty distro configuration", + distroConfig: nil, + imageConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + expectedConfig: &ImageConfig{ + Timezone: "America/New_York", + TimeSynchronization: &osbuild2.ChronyStageOptions{ + Timeservers: []string{"127.0.0.1"}, + }, + Locale: "en_US.UTF-8", + Keyboard: &osbuild2.KeymapStageOptions{ + Keymap: "us", + }, + EnabledServices: []string{"sshd"}, + DisabledServices: []string{"named"}, + DefaultTarget: "multi-user.target", + }, + }, + } + for idx, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.expectedConfig, tt.imageConfig.InheritFrom(tt.distroConfig), "test case %q failed (idx %d)", tt.name, idx) + }) + } +} diff --git a/internal/distro/rhel90/distro.go b/internal/distro/rhel90/distro.go index 9588846c2..2379cb913 100644 --- a/internal/distro/rhel90/distro.go +++ b/internal/distro/rhel90/distro.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/osbuild/osbuild-composer/internal/blueprint" + "github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/disk" "github.com/osbuild/osbuild-composer/internal/distro" osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2" @@ -40,41 +41,62 @@ var mountpointAllowList = []string{ } type distribution struct { - name string - product string - osVersion string - releaseVersion string - modulePlatformID string - vendor string - ostreeRefTmpl string - isolabelTmpl string - runner string - arches map[string]distro.Arch + name string + product string + osVersion string + releaseVersion string + modulePlatformID string + vendor string + ostreeRefTmpl string + isolabelTmpl string + runner string + arches map[string]distro.Arch + defaultImageConfig *distro.ImageConfig +} + +// RHEL-based OS image configuration defaults +var defaultDistroImageConfig = &distro.ImageConfig{ + Timezone: "America/New_York", + Locale: "en_US.UTF-8", + Sysconfig: []*osbuild.SysconfigStageOptions{ + { + Kernel: &osbuild.SysconfigKernelOptions{ + UpdateDefault: true, + DefaultKernel: "kernel", + }, + Network: &osbuild.SysconfigNetworkOptions{ + Networking: true, + NoZeroConf: true, + }, + }, + }, } // distribution objects without the arches > image types var distroMap = map[string]distribution{ "rhel-90": { - name: "rhel-90", - product: "Red Hat Enterprise Linux", - osVersion: "9.0", - releaseVersion: "9", - modulePlatformID: "platform:el9", - vendor: "redhat", - ostreeRefTmpl: "rhel/9/%s/edge", - isolabelTmpl: "RHEL-9-0-0-BaseOS-%s", - runner: "org.osbuild.rhel90", + name: "rhel-90", + product: "Red Hat Enterprise Linux", + osVersion: "9.0", + releaseVersion: "9", + modulePlatformID: "platform:el9", + vendor: "redhat", + ostreeRefTmpl: "rhel/9/%s/edge", + isolabelTmpl: "RHEL-9-0-0-BaseOS-%s", + runner: "org.osbuild.rhel90", + defaultImageConfig: defaultDistroImageConfig, }, "centos-9": { - name: "centos-9", - product: "CentOS Stream", - osVersion: "9-stream", - releaseVersion: "9", - modulePlatformID: "platform:el9", - vendor: "centos", - ostreeRefTmpl: "centos/9/%s/edge", - isolabelTmpl: "CentOS-Stream-9-%s-dvd", - runner: "org.osbuild.centos9", + name: "centos-9", + product: "CentOS Stream", + osVersion: "9-stream", + releaseVersion: "9", + modulePlatformID: "platform:el9", + vendor: "centos", + ostreeRefTmpl: "centos/9/%s/edge", + isolabelTmpl: "CentOS-Stream-9-%s-dvd", + runner: "org.osbuild.centos9", + defaultImageConfig: defaultDistroImageConfig, }, } @@ -128,6 +150,10 @@ func (d *distribution) isRHEL() bool { return strings.HasPrefix(d.name, "rhel") } +func (d *distribution) getDefaultImageConfig() *distro.ImageConfig { + return d.defaultImageConfig +} + type architecture struct { distro *distribution name string @@ -194,21 +220,19 @@ type pipelinesFunc func(t *imageType, customizations *blueprint.Customizations, type packageSetFunc func(t *imageType) rpmmd.PackageSet type imageType struct { - arch *architecture - name string - nameAliases []string - filename string - mimeType string - packageSets map[string]packageSetFunc - enabledServices []string - disabledServices []string - defaultTarget string - kernelOptions string - defaultSize uint64 - buildPipelines []string - payloadPipelines []string - exports []string - pipelines pipelinesFunc + arch *architecture + name string + nameAliases []string + filename string + mimeType string + packageSets map[string]packageSetFunc + defaultImageConfig *distro.ImageConfig + kernelOptions string + defaultSize uint64 + buildPipelines []string + payloadPipelines []string + exports []string + pipelines pipelinesFunc // bootISO: installable ISO bootISO bool @@ -359,6 +383,15 @@ func (t *imageType) getPartitionTable( return disk.CreatePartitionTable(mountpoints, options.Size, basePartitionTable, rng), nil } +func (t *imageType) getDefaultImageConfig() *distro.ImageConfig { + // ensure that image always returns non-nil default config + imageConfig := t.defaultImageConfig + if imageConfig == nil { + imageConfig = &distro.ImageConfig{} + } + return imageConfig.InheritFrom(t.arch.distro.getDefaultImageConfig()) +} + // local type for ostree commit metadata used to define commit sources type ostreeCommit struct { Checksum string @@ -569,7 +602,9 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: edgeBuildPackageSet, osPkgsKey: edgeCommitPackageSet, }, - enabledServices: edgeServices, + defaultImageConfig: &distro.ImageConfig{ + EnabledServices: edgeServices, + }, rpmOstree: true, pipelines: edgeCommitPipelines, buildPipelines: []string{"build"}, @@ -591,7 +626,9 @@ func newDistro(distroName string) distro.Distro { } }, }, - enabledServices: edgeServices, + defaultImageConfig: &distro.ImageConfig{ + EnabledServices: edgeServices, + }, rpmOstree: true, bootISO: false, pipelines: edgeContainerPipelines, @@ -636,7 +673,9 @@ func newDistro(distroName string) distro.Distro { osPkgsKey: edgeCommitPackageSet, installerPkgsKey: edgeInstallerPackageSet, }, - enabledServices: edgeServices, + defaultImageConfig: &distro.ImageConfig{ + EnabledServices: edgeServices, + }, rpmOstree: true, bootISO: true, pipelines: edgeInstallerPipelines, @@ -661,7 +700,9 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: edgeInstallerBuildPackageSet, installerPkgsKey: edgeSimplifiedInstallerPackageSet, }, - enabledServices: edgeServices, + defaultImageConfig: &distro.ImageConfig{ + EnabledServices: edgeServices, + }, defaultSize: 10 * GigaByte, rpmOstree: true, bootable: true, @@ -677,12 +718,14 @@ func newDistro(distroName string) distro.Distro { name: "qcow2", filename: "disk.qcow2", mimeType: "application/x-qemu-disk", - defaultTarget: "multi-user.target", kernelOptions: "console=tty0 console=ttyS0,115200n8 no_timer_check net.ifnames=0 crashkernel=auto", packageSets: map[string]packageSetFunc{ buildPkgsKey: distroBuildPackageSet, osPkgsKey: qcow2CommonPackageSet, }, + defaultImageConfig: &distro.ImageConfig{ + DefaultTarget: "multi-user.target", + }, bootable: true, defaultSize: 10 * GigaByte, pipelines: qcow2Pipelines, @@ -700,11 +743,13 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: distroBuildPackageSet, osPkgsKey: vhdCommonPackageSet, }, - enabledServices: []string{ - "sshd", - "waagent", + defaultImageConfig: &distro.ImageConfig{ + EnabledServices: []string{ + "sshd", + "waagent", + }, + DefaultTarget: "multi-user.target", }, - defaultTarget: "multi-user.target", kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0", bootable: true, defaultSize: 4 * GigaByte, @@ -751,18 +796,66 @@ func newDistro(distroName string) distro.Distro { basePartitionTables: defaultBasePartitionTables, } - // EC2 services - ec2EnabledServices := []string{ - "sshd", - "NetworkManager", - "nm-cloud-setup.service", - "nm-cloud-setup.timer", - "cloud-init", - "cloud-init-local", - "cloud-config", - "cloud-final", - "reboot.target", - "tuned", + // default EC2 images config + defaultEc2ImageConfig := &distro.ImageConfig{ + Timezone: "UTC", + TimeSynchronization: &osbuild.ChronyStageOptions{ + Servers: []osbuild.ChronyConfigServer{ + { + Hostname: "169.254.169.123", + Prefer: common.BoolToPtr(true), + Iburst: common.BoolToPtr(true), + Minpoll: common.IntToPtr(4), + Maxpoll: common.IntToPtr(4), + }, + }, + // empty string will remove any occurrences of the option from the configuration + LeapsecTz: common.StringToPtr(""), + }, + Keyboard: &osbuild.KeymapStageOptions{ + Keymap: "us", + X11Keymap: &osbuild.X11KeymapOptions{ + Layouts: []string{"us"}, + }, + }, + EnabledServices: []string{ + "sshd", + "NetworkManager", + "nm-cloud-setup.service", + "nm-cloud-setup.timer", + "cloud-init", + "cloud-init-local", + "cloud-config", + "cloud-final", + "reboot.target", + "tuned", + }, + DefaultTarget: "multi-user.target", + Sysconfig: []*osbuild.SysconfigStageOptions{ + { + Kernel: &osbuild.SysconfigKernelOptions{ + UpdateDefault: true, + DefaultKernel: "kernel", + }, + Network: &osbuild.SysconfigNetworkOptions{ + Networking: true, + NoZeroConf: true, + }, + NetworkScripts: &osbuild.NetworkScriptsOptions{ + IfcfgFiles: map[string]osbuild.IfcfgFile{ + "eth0": { + Device: "eth0", + Bootproto: osbuild.IfcfgBootprotoDHCP, + OnBoot: common.BoolToPtr(true), + Type: osbuild.IfcfgTypeEthernet, + UserCtl: common.BoolToPtr(true), + PeerDNS: common.BoolToPtr(true), + IPv6Init: common.BoolToPtr(false), + }, + }, + }, + }, + }, } amiImgTypeX86_64 := imageType{ @@ -773,8 +866,7 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: ec2BuildPackageSet, osPkgsKey: ec2CommonPackageSet, }, - defaultTarget: "multi-user.target", - enabledServices: ec2EnabledServices, + defaultImageConfig: defaultEc2ImageConfig, kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto", bootable: true, bootType: distro.LegacyBootType, @@ -794,8 +886,7 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: ec2BuildPackageSet, osPkgsKey: ec2CommonPackageSet, }, - defaultTarget: "multi-user.target", - enabledServices: ec2EnabledServices, + defaultImageConfig: defaultEc2ImageConfig, kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto", bootable: true, defaultSize: 10 * GigaByte, @@ -814,8 +905,7 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: ec2BuildPackageSet, osPkgsKey: rhelEc2PackageSet, }, - defaultTarget: "multi-user.target", - enabledServices: ec2EnabledServices, + defaultImageConfig: defaultEc2ImageConfig, kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto", bootable: true, bootType: distro.LegacyBootType, @@ -835,8 +925,7 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: ec2BuildPackageSet, osPkgsKey: rhelEc2PackageSet, }, - defaultTarget: "multi-user.target", - enabledServices: ec2EnabledServices, + defaultImageConfig: defaultEc2ImageConfig, kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 iommu.strict=0 crashkernel=auto", bootable: true, defaultSize: 10 * GigaByte, @@ -855,8 +944,7 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: ec2BuildPackageSet, osPkgsKey: rhelEc2HaPackageSet, }, - defaultTarget: "multi-user.target", - enabledServices: ec2EnabledServices, + defaultImageConfig: defaultEc2ImageConfig, kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto", bootable: true, bootType: distro.LegacyBootType, @@ -876,8 +964,7 @@ func newDistro(distroName string) distro.Distro { buildPkgsKey: ec2BuildPackageSet, osPkgsKey: rhelEc2SapPackageSet, }, - defaultTarget: "multi-user.target", - enabledServices: ec2EnabledServices, + defaultImageConfig: defaultEc2ImageConfig, kernelOptions: "console=ttyS0,115200n8 console=tty0 net.ifnames=0 rd.blacklist=nouveau nvme_core.io_timeout=4294967295 crashkernel=auto processor.max_cstate=1 intel_idle.max_cstate=1", bootable: true, bootType: distro.LegacyBootType, diff --git a/internal/distro/rhel90/pipelines.go b/internal/distro/rhel90/pipelines.go index a5b31f4cb..23bf8924f 100644 --- a/internal/distro/rhel90/pipelines.go +++ b/internal/distro/rhel90/pipelines.go @@ -24,7 +24,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti return nil, err } - treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable) + treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable) if err != nil { return nil, err } @@ -77,7 +77,7 @@ func vhdPipelines(t *imageType, customizations *blueprint.Customizations, option return nil, err } - treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable) + treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func vmdkPipelines(t *imageType, customizations *blueprint.Customizations, optio return nil, err } - treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable) + treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable) if err != nil { return nil, err } @@ -137,7 +137,7 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations, return nil, err } - treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, &partitionTable) + treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, &partitionTable) if err != nil { return nil, err } @@ -169,16 +169,17 @@ func openstackPipelines(t *imageType, customizations *blueprint.Customizations, // as the last one to the returned pipeline. The stage is not appended on purpose, to allow caller to append // any additional stages to the pipeline, but before the SELinuxStage, which must be always the last one. func ec2BaseTreePipeline( + t *imageType, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, c *blueprint.Customizations, options distro.ImageOptions, - enabledServices, disabledServices []string, - defaultTarget string, - withRHUI, isRHEL bool, + withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) { + // COMMON WITH osPipeline - START + imageConfig := t.getDefaultImageConfig() p := new(osbuild.Pipeline) p.Name = "os" p.Build = "name:build" @@ -196,17 +197,12 @@ func ec2BaseTreePipeline( if language != nil { p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language})) } else { - p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) + p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: imageConfig.Locale})) } if keyboard != nil { p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard})) - } else { - p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{ - Keymap: "us", - X11Keymap: &osbuild.X11KeymapOptions{ - Layouts: []string{"us"}, - }, - })) + } else if imageConfig.Keyboard != nil { + p.AddStage(osbuild.NewKeymapStage(imageConfig.Keyboard)) } if hostname := c.GetHostname(); hostname != nil { @@ -217,25 +213,13 @@ func ec2BaseTreePipeline( if timezone != nil { p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone})) } else { - p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "UTC"})) + p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone})) } if len(ntpServers) > 0 { p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers})) - } else { - p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{ - Servers: []osbuild.ChronyConfigServer{ - { - Hostname: "169.254.169.123", - Prefer: common.BoolToPtr(true), - Iburst: common.BoolToPtr(true), - Minpoll: common.IntToPtr(4), - Maxpoll: common.IntToPtr(4), - }, - }, - // empty string will remove any occurrences of the option from the configuration - LeapsecTz: common.StringToPtr(""), - })) + } else if imageConfig.TimeSynchronization != nil { + p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization)) } if groups := c.GetGroups(); len(groups) > 0 { @@ -250,14 +234,25 @@ func ec2BaseTreePipeline( p.AddStage(osbuild.NewUsersStage(userOptions)) } - if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" { - p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget))) + if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil || + imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" { + p.AddStage(osbuild.NewSystemdStage(systemdStageOptions( + imageConfig.EnabledServices, + imageConfig.DisabledServices, + services, + imageConfig.DefaultTarget, + ))) } if firewall := c.GetFirewall(); firewall != nil { p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall))) } + for _, sysconfigConfig := range imageConfig.Sysconfig { + p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig)) + } + // COMMON WITH osPipeline - END + p.AddStage(osbuild.NewSystemdLogindStage(&osbuild.SystemdLogindStageOptions{ Filename: "00-getty-fixes.conf", Config: osbuild.SystemdLogindConfigDropin{ @@ -268,30 +263,6 @@ func ec2BaseTreePipeline( }, })) - p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{ - Kernel: &osbuild.SysconfigKernelOptions{ - UpdateDefault: true, - DefaultKernel: "kernel", - }, - Network: &osbuild.SysconfigNetworkOptions{ - Networking: true, - NoZeroConf: true, - }, - NetworkScripts: &osbuild.NetworkScriptsOptions{ - IfcfgFiles: map[string]osbuild.IfcfgFile{ - "eth0": { - Device: "eth0", - Bootproto: osbuild.IfcfgBootprotoDHCP, - OnBoot: common.BoolToPtr(true), - Type: osbuild.IfcfgTypeEthernet, - UserCtl: common.BoolToPtr(true), - PeerDNS: common.BoolToPtr(true), - IPv6Init: common.BoolToPtr(false), - }, - }, - }, - })) - p.AddStage(osbuild.NewCloudInitStage(&osbuild.CloudInitStageOptions{ Filename: "00-rhel-default-user.cfg", Config: osbuild.CloudInitConfigFile{ @@ -332,7 +303,7 @@ func ec2BaseTreePipeline( Profile: "sssd", })) - if isRHEL { + 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), @@ -375,11 +346,10 @@ func ec2BaseTreePipeline( return p, nil } -func ec2X86_64BaseTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, - c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string, - defaultTarget string, withRHUI, isRHEL bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) { +func ec2X86_64BaseTreePipeline(t *imageType, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, + c *blueprint.Customizations, options distro.ImageOptions, withRHUI bool, pt *disk.PartitionTable) (*osbuild.Pipeline, error) { - treePipeline, err := ec2BaseTreePipeline(repos, packages, bpPackages, c, options, enabledServices, disabledServices, defaultTarget, withRHUI, isRHEL, pt) + treePipeline, err := ec2BaseTreePipeline(t, repos, packages, bpPackages, c, options, withRHUI, pt) if err != nil { return nil, err } @@ -415,10 +385,10 @@ func ec2CommonPipelines(t *imageType, customizations *blueprint.Customizations, switch arch := t.arch.Name(); arch { // rhel-ec2-x86_64, rhel-ha-ec2 case distro.X86_64ArchName: - treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, t.arch.distro.isRHEL(), &partitionTable) + treePipeline, err = ec2X86_64BaseTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, withRHUI, &partitionTable) // rhel-ec2-aarch64 case distro.Aarch64ArchName: - treePipeline, err = ec2BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, t.arch.distro.isRHEL(), &partitionTable) + treePipeline, err = ec2BaseTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, withRHUI, &partitionTable) default: return nil, fmt.Errorf("ec2CommonPipelines: unsupported image architecture: %q", arch) } @@ -454,7 +424,7 @@ func ec2SapPipelines(t *imageType, customizations *blueprint.Customizations, opt switch arch := t.arch.Name(); arch { // rhel-sap-ec2 case distro.X86_64ArchName: - treePipeline, err = ec2X86_64BaseTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, withRHUI, t.arch.distro.isRHEL(), &partitionTable) + treePipeline, err = ec2X86_64BaseTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, withRHUI, &partitionTable) default: return nil, fmt.Errorf("ec2SapPipelines: unsupported image architecture: %q", arch) } @@ -619,7 +589,7 @@ func tarPipelines(t *imageType, customizations *blueprint.Customizations, option pipelines := make([]osbuild.Pipeline, 0) pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner)) - treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, nil) + treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, nil) if err != nil { return nil, err } @@ -662,7 +632,7 @@ func tarInstallerPipelines(t *imageType, customizations *blueprint.Customization pipelines := make([]osbuild.Pipeline, 0) pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner)) - treePipeline, err := osPipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget, nil) + treePipeline, err := osPipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, nil) if err != nil { return nil, err } @@ -700,7 +670,7 @@ func edgeCorePipelines(t *imageType, customizations *blueprint.Customizations, o pipelines := make([]osbuild.Pipeline, 0) pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner)) - treePipeline, err := ostreeTreePipeline(repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options, t.enabledServices, t.disabledServices, t.defaultTarget) + treePipeline, err := ostreeTreePipeline(t, repos, packageSetSpecs[osPkgsKey], packageSetSpecs[blueprintPkgsKey], customizations, options) if err != nil { return nil, err } @@ -789,34 +759,39 @@ func buildPipeline(repos []rpmmd.RepoConfig, buildPackageSpecs []rpmmd.PackageSp return p } -func osPipeline(repos []rpmmd.RepoConfig, +func osPipeline(t *imageType, + repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, c *blueprint.Customizations, options distro.ImageOptions, - enabledServices, disabledServices []string, - defaultTarget string, pt *disk.PartitionTable) (*osbuild.Pipeline, error) { + imageConfig := t.getDefaultImageConfig() p := new(osbuild.Pipeline) p.Name = "os" p.Build = "name:build" packages = append(packages, bpPackages...) p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages))) + // If the /boot is on a separate partition, the prefix for the BLS stage must be "" if pt == nil || pt.BootPartition() == nil { p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{})) } else { p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{Prefix: common.StringToPtr("")})) } + language, keyboard := c.GetPrimaryLocale() if language != nil { p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language})) } else { - p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) + 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})) } @@ -825,11 +800,13 @@ func osPipeline(repos []rpmmd.RepoConfig, if timezone != nil { p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone})) } else { - p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"})) + p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone})) } if len(ntpServers) > 0 { p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers})) + } else if imageConfig.TimeSynchronization != nil { + p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization)) } if groups := c.GetGroups(); len(groups) > 0 { @@ -844,25 +821,23 @@ func osPipeline(repos []rpmmd.RepoConfig, p.AddStage(osbuild.NewUsersStage(userOptions)) } - if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" { - p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget))) + if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil || + imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" { + p.AddStage(osbuild.NewSystemdStage(systemdStageOptions( + imageConfig.EnabledServices, + imageConfig.DisabledServices, + services, + imageConfig.DefaultTarget, + ))) } if firewall := c.GetFirewall(); firewall != nil { p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall))) } - // These are the current defaults for the sysconfig stage. This can be changed to be image type exclusive if different configs are needed. - p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{ - Kernel: &osbuild.SysconfigKernelOptions{ - UpdateDefault: true, - DefaultKernel: "kernel", - }, - Network: &osbuild.SysconfigNetworkOptions{ - Networking: true, - NoZeroConf: true, - }, - })) + for _, sysconfigConfig := range imageConfig.Sysconfig { + p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig)) + } if options.Subscription != nil { commands := []string{ @@ -881,7 +856,8 @@ func osPipeline(repos []rpmmd.RepoConfig, return p, nil } -func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, c *blueprint.Customizations, options distro.ImageOptions, enabledServices, disabledServices []string, defaultTarget string) (*osbuild.Pipeline, error) { +func ostreeTreePipeline(t *imageType, repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, bpPackages []rpmmd.PackageSpec, c *blueprint.Customizations, options distro.ImageOptions) (*osbuild.Pipeline, error) { + imageConfig := t.getDefaultImageConfig() p := new(osbuild.Pipeline) p.Name = "ostree-tree" p.Build = "name:build" @@ -894,15 +870,19 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, p.AddStage(osbuild.NewRPMStage(rpmStageOptions(repos), rpmStageInputs(packages))) p.AddStage(osbuild.NewFixBLSStage(&osbuild.FixBLSStageOptions{})) + language, keyboard := c.GetPrimaryLocale() if language != nil { p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language})) } else { - p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"})) + 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})) } @@ -911,11 +891,13 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, if timezone != nil { p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone})) } else { - p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"})) + p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: imageConfig.Timezone})) } if len(ntpServers) > 0 { p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers})) + } else if imageConfig.TimeSynchronization != nil { + p.AddStage(osbuild.NewChronyStage(imageConfig.TimeSynchronization)) } if groups := c.GetGroups(); len(groups) > 0 { @@ -931,25 +913,23 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, p.AddStage(osbuild.NewFirstBootStage(usersFirstBootOptions(userOptions))) } - if services := c.GetServices(); services != nil || enabledServices != nil || disabledServices != nil || defaultTarget != "" { - p.AddStage(osbuild.NewSystemdStage(systemdStageOptions(enabledServices, disabledServices, services, defaultTarget))) + if services := c.GetServices(); services != nil || imageConfig.EnabledServices != nil || + imageConfig.DisabledServices != nil || imageConfig.DefaultTarget != "" { + p.AddStage(osbuild.NewSystemdStage(systemdStageOptions( + imageConfig.EnabledServices, + imageConfig.DisabledServices, + services, + imageConfig.DefaultTarget, + ))) } if firewall := c.GetFirewall(); firewall != nil { p.AddStage(osbuild.NewFirewallStage(firewallStageOptions(firewall))) } - // These are the current defaults for the sysconfig stage. This can be changed to be image type exclusive if different configs are needed. - p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{ - Kernel: &osbuild.SysconfigKernelOptions{ - UpdateDefault: true, - DefaultKernel: "kernel", - }, - Network: &osbuild.SysconfigNetworkOptions{ - Networking: true, - NoZeroConf: true, - }, - })) + for _, sysconfigConfig := range imageConfig.Sysconfig { + p.AddStage(osbuild.NewSysconfigStage(sysconfigConfig)) + } if options.Subscription != nil { commands := []string{ @@ -975,6 +955,7 @@ func ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, })) return p, nil } + func ostreeCommitPipeline(options distro.ImageOptions, osVersion string) *osbuild.Pipeline { p := new(osbuild.Pipeline) p.Name = "ostree-commit" diff --git a/test/data/manifests/rhel_90-aarch64-ami-boot.json b/test/data/manifests/rhel_90-aarch64-ami-boot.json index d4ed9dc67..8712da5f0 100644 --- a/test/data/manifests/rhel_90-aarch64-ami-boot.json +++ b/test/data/manifests/rhel_90-aarch64-ami-boot.json @@ -876,17 +876,6 @@ "default_target": "multi-user.target" } }, - { - "type": "org.osbuild.systemd-logind", - "options": { - "filename": "00-getty-fixes.conf", - "config": { - "Login": { - "NAutoVTs": 0 - } - } - } - }, { "type": "org.osbuild.sysconfig", "options": { @@ -913,6 +902,17 @@ } } }, + { + "type": "org.osbuild.systemd-logind", + "options": { + "filename": "00-getty-fixes.conf", + "config": { + "Login": { + "NAutoVTs": 0 + } + } + } + }, { "type": "org.osbuild.cloud-init", "options": { diff --git a/test/data/manifests/rhel_90-aarch64-ec2-boot.json b/test/data/manifests/rhel_90-aarch64-ec2-boot.json index 8791d3ca1..65f078d43 100644 --- a/test/data/manifests/rhel_90-aarch64-ec2-boot.json +++ b/test/data/manifests/rhel_90-aarch64-ec2-boot.json @@ -887,17 +887,6 @@ "default_target": "multi-user.target" } }, - { - "type": "org.osbuild.systemd-logind", - "options": { - "filename": "00-getty-fixes.conf", - "config": { - "Login": { - "NAutoVTs": 0 - } - } - } - }, { "type": "org.osbuild.sysconfig", "options": { @@ -924,6 +913,17 @@ } } }, + { + "type": "org.osbuild.systemd-logind", + "options": { + "filename": "00-getty-fixes.conf", + "config": { + "Login": { + "NAutoVTs": 0 + } + } + } + }, { "type": "org.osbuild.cloud-init", "options": { diff --git a/test/data/manifests/rhel_90-x86_64-ami-boot.json b/test/data/manifests/rhel_90-x86_64-ami-boot.json index e7bd5cac9..7cb8087e6 100644 --- a/test/data/manifests/rhel_90-x86_64-ami-boot.json +++ b/test/data/manifests/rhel_90-x86_64-ami-boot.json @@ -859,17 +859,6 @@ "default_target": "multi-user.target" } }, - { - "type": "org.osbuild.systemd-logind", - "options": { - "filename": "00-getty-fixes.conf", - "config": { - "Login": { - "NAutoVTs": 0 - } - } - } - }, { "type": "org.osbuild.sysconfig", "options": { @@ -896,6 +885,17 @@ } } }, + { + "type": "org.osbuild.systemd-logind", + "options": { + "filename": "00-getty-fixes.conf", + "config": { + "Login": { + "NAutoVTs": 0 + } + } + } + }, { "type": "org.osbuild.cloud-init", "options": { diff --git a/test/data/manifests/rhel_90-x86_64-ec2-boot.json b/test/data/manifests/rhel_90-x86_64-ec2-boot.json index aba1aa8a8..c10f2ac4b 100644 --- a/test/data/manifests/rhel_90-x86_64-ec2-boot.json +++ b/test/data/manifests/rhel_90-x86_64-ec2-boot.json @@ -872,17 +872,6 @@ "default_target": "multi-user.target" } }, - { - "type": "org.osbuild.systemd-logind", - "options": { - "filename": "00-getty-fixes.conf", - "config": { - "Login": { - "NAutoVTs": 0 - } - } - } - }, { "type": "org.osbuild.sysconfig", "options": { @@ -909,6 +898,17 @@ } } }, + { + "type": "org.osbuild.systemd-logind", + "options": { + "filename": "00-getty-fixes.conf", + "config": { + "Login": { + "NAutoVTs": 0 + } + } + } + }, { "type": "org.osbuild.cloud-init", "options": { diff --git a/test/data/manifests/rhel_90-x86_64-ec2_ha-boot.json b/test/data/manifests/rhel_90-x86_64-ec2_ha-boot.json index aed55bd96..39ec872bc 100644 --- a/test/data/manifests/rhel_90-x86_64-ec2_ha-boot.json +++ b/test/data/manifests/rhel_90-x86_64-ec2_ha-boot.json @@ -1066,17 +1066,6 @@ "default_target": "multi-user.target" } }, - { - "type": "org.osbuild.systemd-logind", - "options": { - "filename": "00-getty-fixes.conf", - "config": { - "Login": { - "NAutoVTs": 0 - } - } - } - }, { "type": "org.osbuild.sysconfig", "options": { @@ -1103,6 +1092,17 @@ } } }, + { + "type": "org.osbuild.systemd-logind", + "options": { + "filename": "00-getty-fixes.conf", + "config": { + "Login": { + "NAutoVTs": 0 + } + } + } + }, { "type": "org.osbuild.cloud-init", "options": { diff --git a/test/data/manifests/rhel_90-x86_64-ec2_sap-boot.json b/test/data/manifests/rhel_90-x86_64-ec2_sap-boot.json index 07efe56b3..3a9ffdcdb 100644 --- a/test/data/manifests/rhel_90-x86_64-ec2_sap-boot.json +++ b/test/data/manifests/rhel_90-x86_64-ec2_sap-boot.json @@ -1120,17 +1120,6 @@ "default_target": "multi-user.target" } }, - { - "type": "org.osbuild.systemd-logind", - "options": { - "filename": "00-getty-fixes.conf", - "config": { - "Login": { - "NAutoVTs": 0 - } - } - } - }, { "type": "org.osbuild.sysconfig", "options": { @@ -1157,6 +1146,17 @@ } } }, + { + "type": "org.osbuild.systemd-logind", + "options": { + "filename": "00-getty-fixes.conf", + "config": { + "Login": { + "NAutoVTs": 0 + } + } + } + }, { "type": "org.osbuild.cloud-init", "options": {