go.mod: update osbuild/images to v0.148.0

tag v0.145.0
Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com>

Changes with 0.145.0

----------------
  * github: run dependabot gomod action weekly (osbuild/images#1476)
    * Author: Achilleas Koutsou, Reviewers: Lukáš Zapletal

— Somewhere on the Internet, 2025-05-12

---

tag v0.146.0
Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com>

Changes with 0.146.0

----------------
  * Fixes for ESP partition: Make optional, set label (osbuild/images#1525)
    * Author: Alexander Larsson, Reviewers: Achilleas Koutsou, Brian C. Lane
  * Initial automotive work: custom selinux policy, separate build container for bootc, and ext4 verity (osbuild/images#1519)
    * Author: Alexander Larsson, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * Update snapshots to 20250512 (osbuild/images#1515)
    * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * disk: make auto-generated /boot 1 GiB big (osbuild/images#1499)
    * Author: Ondřej Budai, Reviewers: Achilleas Koutsou, Michael Vogt
  * distro.yaml: Clean up yamllint errors and warnings (osbuild/images#1523)
    * Author: Brian C. Lane, Reviewers: Michael Vogt, Simon de Vlieger
  * distro/rhel9: make /boot 1 GiB everywhere (osbuild/images#1498)
    * Author: Ondřej Budai, Reviewers: Michael Vogt, Simon de Vlieger
  * distro: move disk/container image types into pure YAML (COMPOSER-2533) (osbuild/images#1508)
    * Author: Michael Vogt, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * fedora: move all image types into pure YAML (osbuild/images#1514)
    * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger
  * fsnode: fix go-1.24 errors  (osbuild/images#1521)
    * Author: Michael Vogt, Reviewers: Ondřej Budai, Tomáš Hozza
  * osbuild: add JSON/YAML unmarshal to UdevRulesStageOptions (osbuild/images#1489)
    * Author: Michael Vogt, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * test: Run more distro tests in parallel (osbuild/images#1483)
    * Author: Brian C. Lane, Reviewers: Michael Vogt, Simon de Vlieger

— Somewhere on the Internet, 2025-05-19

---

tag v0.147.0
Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com>

Changes with 0.147.0

----------------
  * Add support for setting partition uuid and label (osbuild/images#1543)
    * Author: Alexander Larsson, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * Cleanup of new APIs (mkfs options and build container) (osbuild/images#1526)
    * Author: Alexander Larsson, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * distro/rhel: remove the user/group warnings for edge-commits (osbuild/images#1538)
    * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Simon de Vlieger

— Somewhere on the Internet, 2025-05-20

---

tag v0.148.0
Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com>

Changes with 0.148.0

----------------
  * Makefile: add vet command to check for consistent struct tags (osbuild/images#1554)
    * Author: Michael Vogt, Reviewers: Lukáš Zapletal, Simon de Vlieger
  * disk: tiny tweaks for the new MkfsOptions support (osbuild/images#1545)
    * Author: Michael Vogt, Reviewers: Achilleas Koutsou, Alexander Larsson, Lukáš Zapletal
  * fedora/many: increase `/boot` to 1 GiB (HMS-8604) (osbuild/images#1557)
    * Author: Simon de Vlieger, Reviewers: Achilleas Koutsou, Ondřej Budai
  * fedora/wsl: include `wsl-setup` (HMS-8573) (osbuild/images#1550)
    * Author: Simon de Vlieger, Reviewers: Brian C. Lane, Michael Vogt
  * fedora: add `anaconda.ModuleUsers` to ImageInstallerImage (osbuild/images#1558)
    * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger
  * fedora: implement setting of the RootfsType via YAML (osbuild/images#1544)
    * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger
  * rhel10: move ImageConfig into pure YAML (osbuild/images#1542)
    * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger

— Somewhere on the Internet, 2025-05-26

---
This commit is contained in:
Achilleas Koutsou 2025-05-27 16:35:51 +02:00
parent 12dd0b0be4
commit c77ca66191
88 changed files with 5093 additions and 4979 deletions

2
go.mod
View file

@ -46,7 +46,7 @@ require (
github.com/openshift-online/ocm-sdk-go v0.1.438
github.com/oracle/oci-go-sdk/v54 v54.0.0
github.com/osbuild/blueprint v1.6.0
github.com/osbuild/images v0.144.0
github.com/osbuild/images v0.148.0
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d
github.com/osbuild/pulp-client v0.1.0
github.com/prometheus/client_golang v1.20.5

4
go.sum
View file

@ -578,8 +578,8 @@ github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXch
github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc=
github.com/osbuild/blueprint v1.6.0 h1:HUV1w/dMxpgqOgVtHhfTZE3zRmWQkuW/qTfx9smKImI=
github.com/osbuild/blueprint v1.6.0/go.mod h1:0d3dlY8aSJ6jM6NHwBmJFF1VIySsp/GsDpcJQ0yrOqM=
github.com/osbuild/images v0.144.0 h1:p8l71YH+x7yE1XJF7Qy74/xdicJ6VTF93I0mKZVmsfc=
github.com/osbuild/images v0.144.0/go.mod h1:jY21PhkxIozII4M0xCqZL7poLtFwDJlEGj88pb3lalQ=
github.com/osbuild/images v0.148.0 h1:jRLpl/z50FF7Vylio7oD7GddKftiqf2RZZV1h5U8XhI=
github.com/osbuild/images v0.148.0/go.mod h1:jY21PhkxIozII4M0xCqZL7poLtFwDJlEGj88pb3lalQ=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d h1:r9BFPDv0uuA9k1947Jybcxs36c/pTywWS1gjeizvtcQ=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d/go.mod h1:zR1iu/hOuf+OQNJlk70tju9IqzzM4ycq0ectkFBm94U=
github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8=

View file

@ -23,3 +23,25 @@ func (p BaseEnvironment) GetRepos() []rpmmd.RepoConfig {
func (p BaseEnvironment) GetServices() []string {
return []string{}
}
// EnvironmentConf is an environment that is fully defined via YAML
// and implements the "Environment" interface
type EnvironmentConf struct {
Packages []string
Repos []rpmmd.RepoConfig
Services []string
}
var _ = Environment(&EnvironmentConf{})
func (p *EnvironmentConf) GetPackages() []string {
return p.Packages
}
func (p *EnvironmentConf) GetRepos() []rpmmd.RepoConfig {
return p.Repos
}
func (p *EnvironmentConf) GetServices() []string {
return p.Services
}

View file

@ -1,7 +1,11 @@
package arch
import (
"encoding/json"
"fmt"
"runtime"
"github.com/osbuild/images/internal/common"
)
type Arch uint64
@ -34,27 +38,40 @@ func (a Arch) String() string {
}
}
func FromString(a string) Arch {
func (a *Arch) UnmarshalJSON(data []byte) (err error) {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*a, err = FromString(s)
return err
}
func (a *Arch) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(a, unmarshal)
}
func FromString(a string) (Arch, error) {
switch a {
case "amd64", "x86_64":
return ARCH_X86_64
return ARCH_X86_64, nil
case "arm64", "aarch64":
return ARCH_AARCH64
return ARCH_AARCH64, nil
case "s390x":
return ARCH_S390X
return ARCH_S390X, nil
case "ppc64le":
return ARCH_PPC64LE
return ARCH_PPC64LE, nil
case "riscv64":
return ARCH_RISCV64
return ARCH_RISCV64, nil
default:
panic("unsupported architecture")
return ARCH_UNSET, fmt.Errorf("unsupported architecture %q", a)
}
}
var runtimeGOARCH = runtime.GOARCH
func Current() Arch {
return FromString(runtimeGOARCH)
return common.Must(FromString(runtimeGOARCH))
}
func IsX86_64() bool {

View file

@ -15,7 +15,7 @@ type Blueprint struct {
Groups []Group `json:"groups" toml:"groups"`
Containers []Container `json:"containers,omitempty" toml:"containers,omitempty"`
Customizations *Customizations `json:"customizations,omitempty" toml:"customizations"`
Customizations *Customizations `json:"customizations,omitempty" toml:"customizations,omitempty"`
Distro string `json:"distro" toml:"distro"`
// EXPERIMENTAL

View file

@ -9,6 +9,7 @@ import (
"regexp"
"slices"
"strings"
"unicode/utf16"
"github.com/google/uuid"
"github.com/osbuild/images/pkg/datasizes"
@ -72,6 +73,14 @@ type PartitionCustomization struct {
// or the payload type.
PartType string `json:"part_type,omitempty" toml:"part_type,omitempty"`
// The partition label for GPT partitions, not supported for dos partitions.
// Note: This is not the same as the label, which can be set in "Label"
PartLabel string `json:"part_label,omitempty" toml:"part_label,omitempty"`
// The partition GUID for GPT partitions, not supported for dos partitions.
// Note: This is the unique uuid, not the type guid, that is PartType
PartUUID string `json:"part_uuid,omitempty" toml:"part_uuid,omitempty"`
BtrfsVolumeCustomization
VGCustomization
@ -162,9 +171,11 @@ type BtrfsSubvolumeCustomization struct {
func (v *PartitionCustomization) UnmarshalJSON(data []byte) error {
errPrefix := "JSON unmarshal:"
var typeSniffer struct {
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
PartLabel string `json:"part_label"`
PartUUID string `json:"part_uuid"`
}
if err := json.Unmarshal(data, &typeSniffer); err != nil {
return fmt.Errorf("%s %w", errPrefix, err)
@ -194,6 +205,8 @@ func (v *PartitionCustomization) UnmarshalJSON(data []byte) error {
v.Type = partType
v.PartType = typeSniffer.PartType
v.PartLabel = typeSniffer.PartLabel
v.PartUUID = typeSniffer.PartUUID
if typeSniffer.MinSize == nil {
return fmt.Errorf("minsize is required")
@ -213,11 +226,13 @@ func (v *PartitionCustomization) UnmarshalJSON(data []byte) error {
// the type is "plain", none of the fields for btrfs or lvm are used.
func decodePlain(v *PartitionCustomization, data []byte) error {
var plain struct {
// Type, minsize, and part_type are handled by the caller. These are added here to
// Type, minsize, and part_* are handled by the caller. These are added here to
// satisfy "DisallowUnknownFields" when decoding.
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
PartLabel string `json:"part_label"`
PartUUID string `json:"part_uuid"`
FilesystemTypedCustomization
}
@ -237,11 +252,13 @@ func decodePlain(v *PartitionCustomization, data []byte) error {
// the type is btrfs, none of the fields for plain or lvm are used.
func decodeBtrfs(v *PartitionCustomization, data []byte) error {
var btrfs struct {
// Type, minsize, and part_type are handled by the caller. These are added here to
// Type, minsize, and part_* are handled by the caller. These are added here to
// satisfy "DisallowUnknownFields" when decoding.
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
PartLabel string `json:"part_label"`
PartUUID string `json:"part_uuid"`
BtrfsVolumeCustomization
}
@ -261,11 +278,13 @@ func decodeBtrfs(v *PartitionCustomization, data []byte) error {
// is lvm, none of the fields for plain or btrfs are used.
func decodeLVM(v *PartitionCustomization, data []byte) error {
var vg struct {
// Type, minsize, and part_type are handled by the caller. These are added here to
// Type, minsize, and part_* are handled by the caller. These are added here to
// satisfy "DisallowUnknownFields" when decoding.
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
Type string `json:"type"`
MinSize any `json:"minsize"`
PartType string `json:"part_type"`
PartLabel string `json:"part_label"`
PartUUID string `json:"part_uuid"`
VGCustomization
}
@ -383,6 +402,12 @@ func (p *DiskCustomization) Validate() error {
if err := part.ValidatePartitionTypeID(p.Type); err != nil {
errs = append(errs, err)
}
if err := part.ValidatePartitionID(p.Type); err != nil {
errs = append(errs, err)
}
if err := part.ValidatePartitionLabel(p.Type); err != nil {
errs = append(errs, err)
}
switch part.Type {
case "plain", "":
errs = append(errs, part.validatePlain(mountpoints))
@ -525,6 +550,48 @@ func (p *PartitionCustomization) ValidatePartitionTypeID(ptType string) error {
return nil
}
// ValidatePartitionID returns an error if the partition ID is not
// valid given the partition table type. If the partition table type is an
// empty string, the function returns an error only if the partition type ID is
// invalid for both gpt and dos partition tables.
func (p *PartitionCustomization) ValidatePartitionID(ptType string) error {
// Empty PartUUID is fine, it will be selected automatically if needed
if p.PartUUID == "" {
return nil
}
if ptType == "dos" {
return fmt.Errorf("part_type is not supported for dos partition tables")
}
_, uuidErr := uuid.Parse(p.PartUUID)
if uuidErr != nil {
return fmt.Errorf("invalid partition part_uuid %q (must be a valid UUID): %w", p.PartUUID, uuidErr)
}
return nil
}
// ValidatePartitionID returns an error if the partition ID is not
// valid given the partition table type.
func (p *PartitionCustomization) ValidatePartitionLabel(ptType string) error {
// Empty PartLabel is fine
if p.PartLabel == "" {
return nil
}
if ptType == "dos" {
return fmt.Errorf("part_label is not supported for dos partition tables")
}
// GPT Labels are up to 36 utf-16 chars
if len(utf16.Encode([]rune(p.PartLabel))) > 36 {
return fmt.Errorf("part_label is not a valid GPT label, it is too long")
}
return nil
}
func (p *PartitionCustomization) validatePlain(mountpoints map[string]bool) error {
if p.FSType == "swap" {
// make sure the mountpoint is empty and return

View file

@ -370,8 +370,8 @@ func (cl *Client) resolveContainerImageArch(ctx context.Context, ref types.Image
if err != nil {
return nil, err
}
a := arch.FromString(info.Architecture)
return &a, nil
a, err := arch.FromString(info.Architecture)
return &a, err
}
func (cl *Client) getLocalImageIDFromDigest(instance digest.Digest) (string, error) {

View file

@ -1,6 +1,12 @@
package fsnode
import "os"
import (
"bytes"
"encoding/json"
"os"
"github.com/osbuild/images/internal/common"
)
type Directory struct {
baseFsNode
@ -14,6 +20,27 @@ func (d *Directory) EnsureParentDirs() bool {
return d.ensureParentDirs
}
func (d *Directory) UnmarshalJSON(data []byte) error {
var v struct {
baseFsNodeJSON
EnsureParentDirs bool `json:"ensure_parent_dirs"`
}
dec := json.NewDecoder(bytes.NewBuffer(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&v); err != nil {
return err
}
d.baseFsNode.baseFsNodeJSON = v.baseFsNodeJSON
d.ensureParentDirs = v.EnsureParentDirs
return d.validate()
}
func (d *Directory) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(d, unmarshal)
}
// NewDirectory creates a new directory with the given path, mode, user and group.
// user and group can be either a string (user name/group name), an int64 (UID/GID) or nil.
func NewDirectory(path string, mode *os.FileMode, user interface{}, group interface{}, ensureParentDirs bool) (*Directory, error) {

View file

@ -1,7 +1,11 @@
package fsnode
import (
"bytes"
"encoding/json"
"os"
"github.com/osbuild/images/internal/common"
)
type File struct {
@ -16,6 +20,27 @@ func (f *File) Data() []byte {
return f.data
}
func (f *File) UnmarshalJSON(data []byte) error {
var v struct {
baseFsNodeJSON
Data string `json:"data,omitempty"`
}
dec := json.NewDecoder(bytes.NewBuffer(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&v); err != nil {
return err
}
f.baseFsNode.baseFsNodeJSON = v.baseFsNodeJSON
f.data = []byte(v.Data)
return f.validate()
}
func (f *File) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(f, unmarshal)
}
// NewFile creates a new file with the given path, data, mode, user and group.
// user and group can be either a string (user name/group name), an int64 (UID/GID) or nil.
func NewFile(path string, mode *os.FileMode, user interface{}, group interface{}, data []byte) (*File, error) {

View file

@ -1,34 +1,42 @@
package fsnode
import (
"bytes"
"encoding/json"
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"github.com/osbuild/images/internal/common"
)
const usernameRegex = `^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$`
const groupnameRegex = `^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$`
type baseFsNodeJSON struct {
Path string
Mode *os.FileMode
User interface{}
Group interface{}
}
type baseFsNode struct {
path string
mode *os.FileMode
user interface{}
group interface{}
baseFsNodeJSON
}
func (f *baseFsNode) Path() string {
if f == nil {
return ""
}
return f.path
return f.baseFsNodeJSON.Path
}
func (f *baseFsNode) Mode() *os.FileMode {
if f == nil {
return nil
}
return f.mode
return f.baseFsNodeJSON.Mode
}
// User can return either a string (user name) or an int64 (UID)
@ -36,7 +44,7 @@ func (f *baseFsNode) User() interface{} {
if f == nil {
return nil
}
return f.user
return f.baseFsNodeJSON.User
}
// Group can return either a string (group name) or an int64 (GID)
@ -44,15 +52,17 @@ func (f *baseFsNode) Group() interface{} {
if f == nil {
return nil
}
return f.group
return f.baseFsNodeJSON.Group
}
func newBaseFsNode(path string, mode *os.FileMode, user interface{}, group interface{}) (*baseFsNode, error) {
node := &baseFsNode{
path: path,
mode: mode,
user: user,
group: group,
baseFsNodeJSON: baseFsNodeJSON{
Path: path,
Mode: mode,
User: user,
Group: group,
},
}
err := node.validate()
@ -63,32 +73,43 @@ func newBaseFsNode(path string, mode *os.FileMode, user interface{}, group inter
}
func (f *baseFsNode) validate() error {
return f.baseFsNodeJSON.validate()
}
func (f *baseFsNodeJSON) validate() error {
// Check that the path is valid
if f.path == "" {
if f.Path == "" {
return fmt.Errorf("path must not be empty")
}
if f.path[0] != '/' {
if f.Path[0] != '/' {
return fmt.Errorf("path must be absolute")
}
if f.path[len(f.path)-1] == '/' {
if f.Path[len(f.Path)-1] == '/' {
return fmt.Errorf("path must not end with a slash")
}
if f.path != path.Clean(f.path) {
if f.Path != filepath.Clean(f.Path) {
return fmt.Errorf("path must be canonical")
}
// Check that the mode is valid
if f.mode != nil && *f.mode&os.ModeType != 0 {
if f.Mode != nil && *f.Mode&os.ModeType != 0 {
return fmt.Errorf("mode must not contain file type bits")
}
// Check that the user and group are valid
switch user := f.user.(type) {
switch user := f.User.(type) {
case string:
nameRegex := regexp.MustCompile(usernameRegex)
if !nameRegex.MatchString(user) {
return fmt.Errorf("user name %q doesn't conform to validating regex (%s)", user, nameRegex.String())
}
case float64:
if user != float64(int64(user)) {
return fmt.Errorf("user ID must be int")
}
if user < 0 {
return fmt.Errorf("user ID must be non-negative")
}
case int64:
if user < 0 {
return fmt.Errorf("user ID must be non-negative")
@ -99,12 +120,19 @@ func (f *baseFsNode) validate() error {
return fmt.Errorf("user must be either a string or an int64, got %T", user)
}
switch group := f.group.(type) {
switch group := f.Group.(type) {
case string:
nameRegex := regexp.MustCompile(groupnameRegex)
if !nameRegex.MatchString(group) {
return fmt.Errorf("group name %q doesn't conform to validating regex (%s)", group, nameRegex.String())
}
case float64:
if group != float64(int64(group)) {
return fmt.Errorf("group ID must be int")
}
if group < 0 {
return fmt.Errorf("group ID must be non-negative")
}
case int64:
if group < 0 {
return fmt.Errorf("group ID must be non-negative")
@ -117,3 +145,22 @@ func (f *baseFsNode) validate() error {
return nil
}
func (f *baseFsNode) UnmarshalJSON(data []byte) error {
var fv baseFsNodeJSON
dec := json.NewDecoder(bytes.NewBuffer(data))
if err := dec.Decode(&fv); err != nil {
return err
}
if err := fv.validate(); err != nil {
return err
}
f.baseFsNodeJSON = fv
return nil
}
func (f *baseFsNode) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(f, unmarshal)
}

View file

@ -50,12 +50,12 @@ type DNFPluginConfig struct {
}
type SubManDNFPluginsConfig struct {
ProductID DNFPluginConfig
SubscriptionManager DNFPluginConfig
ProductID DNFPluginConfig `yaml:"product_id,omitempty"`
SubscriptionManager DNFPluginConfig `yaml:"subscription_manager,omitempty"`
}
type RHSMConfig struct {
DnfPlugins SubManDNFPluginsConfig
DnfPlugins SubManDNFPluginsConfig `yaml:"dnf_plugin,omitempty"`
YumPlugins SubManDNFPluginsConfig
SubMan SubManConfig
}

View file

@ -1,12 +1,57 @@
package disk
import (
"encoding/json"
"fmt"
"math/rand"
"reflect"
"github.com/google/uuid"
)
type MkfsOption int
const ( // MkfsOption type enum
MkfsVerity MkfsOption = iota // Enable fs-verity option if needed (typically for EXT4)
)
func getMkfsOptionMapping() []string {
return []string{"verity"}
}
// String converts MkfsOption into a human readable string
func (option MkfsOption) String() string {
return getMkfsOptionMapping()[int(option)]
}
func unmarshalHelper(data []byte, mapping []string) (int, error) {
var stringInput string
err := json.Unmarshal(data, &stringInput)
if err != nil {
return 0, err
}
for n, str := range mapping {
if str == stringInput {
return n, nil
}
}
return 0, fmt.Errorf("invalid mkfsoption: %s", stringInput)
}
// UnmarshalJSON converts a JSON string into an MkfsOption
func (option *MkfsOption) UnmarshalJSON(data []byte) error {
val, err := unmarshalHelper(data, getMkfsOptionMapping())
if err != nil {
return err
}
*option = MkfsOption(val)
return nil
}
func (option MkfsOption) MarshalJSON() ([]byte, error) {
return json.Marshal(getMkfsOptionMapping()[option])
}
// Filesystem related functions
type Filesystem struct {
Type string `json:"type" yaml:"type"`
@ -22,6 +67,8 @@ type Filesystem struct {
FSTabFreq uint64 `json:"fstab_freq,omitempty" yaml:"fstab_freq,omitempty"`
// The sixth field of fstab(5); fs_passno
FSTabPassNo uint64 `json:"fstab_passno,omitempty" yaml:"fstab_passno,omitempty"`
// Custom mkfs options
MkfsOptions []MkfsOption `json:"mkfs_options,omitempty" yaml:"mkfs_options,omitempty"`
}
func init() {
@ -46,6 +93,7 @@ func (fs *Filesystem) Clone() Entity {
FSTabOptions: fs.FSTabOptions,
FSTabFreq: fs.FSTabFreq,
FSTabPassNo: fs.FSTabPassNo,
MkfsOptions: fs.MkfsOptions,
}
}

View file

@ -21,6 +21,9 @@ type Partition struct {
// is just a string.
UUID string `json:"uuid,omitempty" yaml:"uuid,omitempty"`
// Partition name (not filesystem label), only supported for GPT
Label string `json:"label,omitempty" yaml:"label,omitempty"`
// If nil, the partition is raw; It doesn't contain a payload.
Payload PayloadEntity `json:"payload,omitempty" yaml:"payload,omitempty"`
}
@ -36,6 +39,7 @@ func (p *Partition) Clone() Entity {
Type: p.Type,
Bootable: p.Bootable,
UUID: p.UUID,
Label: p.Label,
}
if p.Payload != nil {

View file

@ -51,6 +51,11 @@ const (
DefaultPartitioningMode PartitioningMode = ""
)
// DefaultBootPartitionSize is the default size of the /boot partition if it
// needs to be auto-created. This happens if the custom partitioning don't
// specify one, but the image requires one to boot (/ is on btrfs, or an LV).
const DefaultBootPartitionSize = 1 * datasizes.GiB
// NewPartitionTable takes an existing base partition table and some parameters
// and returns a new version of the base table modified to satisfy the
// parameters.
@ -725,7 +730,7 @@ func (pt *PartitionTable) ensureLVM() error {
// we need a /boot partition to boot LVM, ensure one exists
bootPath := entityPath(pt, "/boot")
if bootPath == nil {
_, err := pt.CreateMountpoint("/boot", 512*datasizes.MiB)
_, err := pt.CreateMountpoint("/boot", DefaultBootPartitionSize)
if err != nil {
return err
@ -784,7 +789,7 @@ func (pt *PartitionTable) ensureBtrfs(architecture arch.Arch) error {
// we need a /boot partition to boot btrfs, ensure one exists
bootPath := entityPath(pt, "/boot")
if bootPath == nil {
_, err := pt.CreateMountpoint("/boot", 512*datasizes.MiB)
_, err := pt.CreateMountpoint("/boot", DefaultBootPartitionSize)
if err != nil {
return fmt.Errorf("failed to create /boot partition when ensuring btrfs: %w", err)
}
@ -1066,7 +1071,7 @@ func addBootPartition(pt *PartitionTable, bootFsType FSType) error {
}
bootPart := Partition{
Type: partType,
Size: 512 * datasizes.MiB,
Size: DefaultBootPartitionSize,
Payload: &Filesystem{
Type: bootFsType.String(),
Label: bootLabel,
@ -1078,6 +1083,20 @@ func addBootPartition(pt *PartitionTable, bootFsType FSType) error {
return nil
}
func hasESP(disk *blueprint.DiskCustomization) bool {
if disk == nil {
return false
}
for _, part := range disk.Partitions {
if part.Type == "plain" && part.Mountpoint == "/boot/efi" {
return true
}
}
return false
}
// addPartitionsForBootMode creates partitions to satisfy the boot mode requirements:
// - BIOS/legacy: adds a 1 MiB BIOS boot partition.
// - UEFI: adds a 200 MiB EFI system partition.
@ -1086,7 +1105,7 @@ func addBootPartition(pt *PartitionTable, bootFsType FSType) error {
// The function will append the new partitions to the end of the existing
// partition table therefore it is best to call this function early to put them
// near the front (as is conventional).
func addPartitionsForBootMode(pt *PartitionTable, bootMode platform.BootMode) error {
func addPartitionsForBootMode(pt *PartitionTable, disk *blueprint.DiskCustomization, bootMode platform.BootMode) error {
switch bootMode {
case platform.BOOT_LEGACY:
// add BIOS boot partition
@ -1097,12 +1116,14 @@ func addPartitionsForBootMode(pt *PartitionTable, bootMode platform.BootMode) er
pt.Partitions = append(pt.Partitions, part)
return nil
case platform.BOOT_UEFI:
// add ESP
part, err := mkESP(200*datasizes.MiB, pt.Type)
if err != nil {
return err
// add ESP if needed
if !hasESP(disk) {
part, err := mkESP(200*datasizes.MiB, pt.Type)
if err != nil {
return err
}
pt.Partitions = append(pt.Partitions, part)
}
pt.Partitions = append(pt.Partitions, part)
return nil
case platform.BOOT_HYBRID:
// add both
@ -1110,11 +1131,14 @@ func addPartitionsForBootMode(pt *PartitionTable, bootMode platform.BootMode) er
if err != nil {
return err
}
esp, err := mkESP(200*datasizes.MiB, pt.Type)
if err != nil {
return err
pt.Partitions = append(pt.Partitions, bios)
if !hasESP(disk) {
esp, err := mkESP(200*datasizes.MiB, pt.Type)
if err != nil {
return err
}
pt.Partitions = append(pt.Partitions, esp)
}
pt.Partitions = append(pt.Partitions, bios, esp)
return nil
case platform.BOOT_NONE:
return nil
@ -1149,7 +1173,7 @@ func mkESP(size uint64, ptType PartitionTableType) (Partition, error) {
Type: "vfat",
UUID: EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
Label: "ESP",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
@ -1268,8 +1292,7 @@ func NewCustomPartitionTable(customizations *blueprint.DiskCustomization, option
// add any partition(s) that are needed for booting (like /boot/efi)
// if needed
//
// TODO: switch to ensure ESP in case customizations already include it
if err := addPartitionsForBootMode(pt, options.BootMode); err != nil {
if err := addPartitionsForBootMode(pt, customizations, options.BootMode); err != nil {
return nil, fmt.Errorf("%s %w", errPrefix, err)
}
// add the /boot partition (if it is needed)
@ -1279,10 +1302,16 @@ func NewCustomPartitionTable(customizations *blueprint.DiskCustomization, option
// add user customized partitions
for _, part := range customizations.Partitions {
if part.PartType != "" {
// check the partition type now that we also know the partition table type
// check the partition details now that we also know the partition table type
if err := part.ValidatePartitionTypeID(pt.Type.String()); err != nil {
return nil, fmt.Errorf("%s error validating partition type ID for %q: %w", errPrefix, part.Mountpoint, err)
}
if err := part.ValidatePartitionID(pt.Type.String()); err != nil {
return nil, fmt.Errorf("%s error validating partition ID for %q: %w", errPrefix, part.Mountpoint, err)
}
if err := part.ValidatePartitionLabel(pt.Type.String()); err != nil {
return nil, fmt.Errorf("%s error validating partition label for %q: %w", errPrefix, part.Mountpoint, err)
}
}
switch part.Type {
@ -1377,6 +1406,8 @@ func addPlainPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
newpart := Partition{
Type: partType,
UUID: partition.PartUUID,
Label: partition.PartLabel,
Size: partition.MinSize,
Payload: payload,
}
@ -1449,6 +1480,8 @@ func addLVMPartition(pt *PartitionTable, partition blueprint.PartitionCustomizat
newpart := Partition{
Type: partType,
UUID: partition.PartUUID,
Label: partition.PartLabel,
Size: partition.MinSize,
Bootable: false,
Payload: newvg,
@ -1482,6 +1515,8 @@ func addBtrfsPartition(pt *PartitionTable, partition blueprint.PartitionCustomiz
}
newpart := Partition{
Type: partType,
UUID: partition.PartUUID,
Label: partition.PartLabel,
Bootable: false,
Payload: newvol,
Size: partition.MinSize,

File diff suppressed because it is too large Load diff

View file

@ -17,10 +17,12 @@ import (
"gopkg.in/yaml.v3"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/experimentalflags"
"github.com/osbuild/images/pkg/olog"
"github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd"
)
@ -36,26 +38,95 @@ var data embed.FS
var DataFS fs.FS = data
type toplevelYAML struct {
ImageConfig imageConfig `yaml:"image_config,omitempty"`
ImageConfig distroImageConfig `yaml:"image_config,omitempty"`
ImageTypes map[string]imageType `yaml:"image_types"`
Common map[string]any `yaml:".common,omitempty"`
}
type imageConfig struct {
Default *distro.ImageConfig `yaml:"default"`
Condition *imageConfigConditions `yaml:"condition,omitempty"`
type distroImageConfig struct {
Default *distro.ImageConfig `yaml:"default"`
Condition *distroImageConfigConditions `yaml:"condition,omitempty"`
}
type imageConfigConditions struct {
type distroImageConfigConditions struct {
DistroName map[string]*distro.ImageConfig `yaml:"distro_name,omitempty"`
}
// XXX: this should eventually implement the "distro.ImageType"
// interface, then we don't need to convert into a fedora/rhel
// imagetype anymore (those will go away in subsequent refactors)
type ImageTypeYAML = imageType
type imageType struct {
PackageSets []packageSet `yaml:"package_sets"`
// This maps "pkgsKey" to their package sets. The
// map key here is a string that can either be:
// - "os": packages for the os
// - "installer": packages for the installer
// - "container": extra package into an iot container
//
// - "blueprint": unused AFAICT
// - "build": unused AFAICT
// Note that this does not directly maps to pipeline names
// but we should look into making it so.
PackageSets map[string][]packageSet `yaml:"package_sets"`
// archStr->partitionTable
PartitionTables map[string]*disk.PartitionTable `yaml:"partition_table"`
// override specific aspects of the partition table
PartitionTablesOverrides *partitionTablesOverrides `yaml:"partition_tables_override"`
ImageConfig imageConfig `yaml:"image_config,omitempty"`
InstallerConfig installerConfig `yaml:"installer_config,omitempty"`
Filename string `yaml:"filename"`
MimeType string `yaml:"mime_type"`
Compression string `yaml:"compression"`
Environment environment.EnvironmentConf `yaml:"environment"`
Bootable bool `yaml:"bootable"`
BootISO bool `yaml:"boot_iso"`
ISOLabel string `yaml:"iso_label"`
RPMOSTree bool `yaml:"rpm_ostree"`
DefaultSize uint64 `yaml:"default_size"`
// the image func name: disk,container,live-installer,...
Image string `yaml:"image_func"`
BuildPipelines []string `yaml:"build_pipelines"`
PayloadPipelines []string `yaml:"payload_pipelines"`
Exports []string `yaml:"exports"`
RequiredPartitionSizes map[string]uint64 `yaml:"required_partition_sizes"`
Platforms []platform.PlatformConf `yaml:"platforms"`
NameAliases []string `yaml:"name_aliases"`
// name is set by the loader
name string
}
func (it *imageType) Name() string {
return it.name
}
type imageConfig struct {
*distro.ImageConfig `yaml:",inline"`
Condition *conditionsImgConf `yaml:"condition,omitempty"`
}
type conditionsImgConf struct {
Architecture map[string]*distro.ImageConfig `yaml:"architecture,omitempty"`
DistroName map[string]*distro.ImageConfig `yaml:"distro_name,omitempty"`
VersionLessThan map[string]*distro.ImageConfig `yaml:"version_less_than,omitempty"`
}
type installerConfig struct {
*distro.InstallerConfig `yaml:",inline"`
Condition *conditionsInstallerConf `yaml:"condition,omitempty"`
}
type conditionsInstallerConf struct {
Architecture map[string]*distro.InstallerConfig `yaml:"architecture,omitempty"`
DistroName map[string]*distro.InstallerConfig `yaml:"distro_name,omitempty"`
VersionLessThan map[string]*distro.InstallerConfig `yaml:"version_less_than,omitempty"`
}
type packageSet struct {
@ -136,16 +207,10 @@ func DistroImageConfig(distroNameVer string) (*distro.ImageConfig, error) {
return imgConfig, nil
}
// PackageSet loads the PackageSet from the yaml source file discovered via the
// imagetype. By default the imagetype name is used to load the packageset
// but with "overrideTypeName" this can be overriden (useful for e.g.
// installer image types).
func PackageSet(it distro.ImageType, overrideTypeName string, replacements map[string]string) (rpmmd.PackageSet, error) {
// PackageSets loads the PackageSets from the yaml source file
// discovered via the imagetype.
func PackageSets(it distro.ImageType, replacements map[string]string) (map[string]rpmmd.PackageSet, error) {
typeName := it.Name()
if overrideTypeName != "" {
typeName = overrideTypeName
}
typeName = strings.ReplaceAll(typeName, "-", "_")
arch := it.Arch()
archName := arch.Name()
@ -155,77 +220,6 @@ func PackageSet(it distro.ImageType, overrideTypeName string, replacements map[s
// each imagetype can have multiple package sets, so that we can
// use yaml aliases/anchors to de-duplicate them
toplevel, err := load(distroNameVer)
if err != nil {
return rpmmd.PackageSet{}, err
}
imgType, ok := toplevel.ImageTypes[typeName]
if !ok {
return rpmmd.PackageSet{}, fmt.Errorf("%w: %q", ErrImageTypeNotFound, typeName)
}
var rpmmdPkgSet rpmmd.PackageSet
for _, pkgSet := range imgType.PackageSets {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: pkgSet.Include,
Exclude: pkgSet.Exclude,
})
if pkgSet.Condition != nil {
// process conditions
if archSet, ok := pkgSet.Condition.Architecture[archName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: archSet.Include,
Exclude: archSet.Exclude,
})
}
if distroNameSet, ok := pkgSet.Condition.DistroName[distroName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: distroNameSet.Include,
Exclude: distroNameSet.Exclude,
})
}
// note that we don't need to order here, as
// packageSets are strictly additive the order
// is irrelevant
for ltVer, ltSet := range pkgSet.Condition.VersionLessThan {
if r, ok := replacements[ltVer]; ok {
ltVer = r
}
if common.VersionLessThan(distroVersion, ltVer) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: ltSet.Include,
Exclude: ltSet.Exclude,
})
}
}
for gteqVer, gteqSet := range pkgSet.Condition.VersionGreaterOrEqual {
if r, ok := replacements[gteqVer]; ok {
gteqVer = r
}
if common.VersionGreaterThanOrEqual(distroVersion, gteqVer) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: gteqSet.Include,
Exclude: gteqSet.Exclude,
})
}
}
}
}
// mostly for tests
sort.Strings(rpmmdPkgSet.Include)
sort.Strings(rpmmdPkgSet.Exclude)
return rpmmdPkgSet, nil
}
// PartitionTable returns the partionTable for the given distro/imgType.
func PartitionTable(it distro.ImageType, replacements map[string]string) (*disk.PartitionTable, error) {
distroNameVer := it.Arch().Distro().Name()
typeName := strings.ReplaceAll(it.Name(), "-", "_")
toplevel, err := load(distroNameVer)
if err != nil {
return nil, err
@ -235,8 +229,82 @@ func PartitionTable(it distro.ImageType, replacements map[string]string) (*disk.
if !ok {
return nil, fmt.Errorf("%w: %q", ErrImageTypeNotFound, typeName)
}
res := make(map[string]rpmmd.PackageSet)
for key, pkgSets := range imgType.PackageSets {
var rpmmdPkgSet rpmmd.PackageSet
for _, pkgSet := range pkgSets {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: pkgSet.Include,
Exclude: pkgSet.Exclude,
})
if pkgSet.Condition != nil {
// process conditions
if archSet, ok := pkgSet.Condition.Architecture[archName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: archSet.Include,
Exclude: archSet.Exclude,
})
}
if distroNameSet, ok := pkgSet.Condition.DistroName[distroName]; ok {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: distroNameSet.Include,
Exclude: distroNameSet.Exclude,
})
}
// note that we don't need to order here, as
// packageSets are strictly additive the order
// is irrelevant
for ltVer, ltSet := range pkgSet.Condition.VersionLessThan {
if r, ok := replacements[ltVer]; ok {
ltVer = r
}
if common.VersionLessThan(distroVersion, ltVer) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: ltSet.Include,
Exclude: ltSet.Exclude,
})
}
}
for gteqVer, gteqSet := range pkgSet.Condition.VersionGreaterOrEqual {
if r, ok := replacements[gteqVer]; ok {
gteqVer = r
}
if common.VersionGreaterThanOrEqual(distroVersion, gteqVer) {
rpmmdPkgSet = rpmmdPkgSet.Append(rpmmd.PackageSet{
Include: gteqSet.Include,
Exclude: gteqSet.Exclude,
})
}
}
}
}
// mostly for tests
sort.Strings(rpmmdPkgSet.Include)
sort.Strings(rpmmdPkgSet.Exclude)
res[key] = rpmmdPkgSet
}
return res, nil
}
// PartitionTable returns the partionTable for the given distro/imgType.
func PartitionTable(it distro.ImageType, replacements map[string]string) (*disk.PartitionTable, error) {
distroNameVer := it.Arch().Distro().Name()
toplevel, err := load(distroNameVer)
if err != nil {
return nil, err
}
imgType, ok := toplevel.ImageTypes[it.Name()]
if !ok {
return nil, fmt.Errorf("%w: %q", ErrImageTypeNotFound, it.Name())
}
if imgType.PartitionTables == nil {
return nil, fmt.Errorf("%w: %q", ErrNoPartitionTableForImgType, typeName)
return nil, fmt.Errorf("%w: %q", ErrNoPartitionTableForImgType, it.Name())
}
arch := it.Arch()
archName := arch.Name()
@ -278,7 +346,7 @@ func PartitionTable(it distro.ImageType, replacements map[string]string) (*disk.
pt, ok := imgType.PartitionTables[archName]
if !ok {
return nil, fmt.Errorf("%w (%q): %q", ErrNoPartitionTableForArch, typeName, archName)
return nil, fmt.Errorf("%w (%q): %q", ErrNoPartitionTableForArch, it.Name(), archName)
}
return pt, nil
@ -350,3 +418,107 @@ func load(distroNameVer string) (*toplevelYAML, error) {
return &toplevel, nil
}
// ImageConfig returns the image type specific ImageConfig
func ImageConfig(distroNameVer, archName, typeName string, replacements map[string]string) (*distro.ImageConfig, error) {
toplevel, err := load(distroNameVer)
if err != nil {
return nil, err
}
imgType, ok := toplevel.ImageTypes[typeName]
if !ok {
return nil, fmt.Errorf("%w: %q", ErrImageTypeNotFound, typeName)
}
imgConfig := imgType.ImageConfig.ImageConfig
cond := imgType.ImageConfig.Condition
if cond != nil {
distroName, distroVersion := splitDistroNameVer(distroNameVer)
if distroNameCnf, ok := cond.DistroName[distroName]; ok {
imgConfig = distroNameCnf.InheritFrom(imgConfig)
}
if archCnf, ok := cond.Architecture[archName]; ok {
imgConfig = archCnf.InheritFrom(imgConfig)
}
for ltVer, ltConf := range cond.VersionLessThan {
if r, ok := replacements[ltVer]; ok {
ltVer = r
}
if common.VersionLessThan(distroVersion, ltVer) {
imgConfig = ltConf.InheritFrom(imgConfig)
}
}
}
return imgConfig, nil
}
// nNonEmpty returns the number of non-empty maps in the given
// input
func nNonEmpty[K comparable, V any](maps ...map[K]V) int {
var nonEmpty int
for _, m := range maps {
if len(m) > 0 {
nonEmpty++
}
}
return nonEmpty
}
// InstallerConfig returns the InstallerConfig for the given imgType
// Note that on conditions the InstallerConfig is fully replaced, do
// any merging in YAML
func InstallerConfig(distroNameVer, archName, typeName string, replacements map[string]string) (*distro.InstallerConfig, error) {
toplevel, err := load(distroNameVer)
if err != nil {
return nil, err
}
imgType, ok := toplevel.ImageTypes[typeName]
if !ok {
return nil, fmt.Errorf("%w: %q", ErrImageTypeNotFound, typeName)
}
installerConfig := imgType.InstallerConfig.InstallerConfig
cond := imgType.InstallerConfig.Condition
if cond != nil {
if nNonEmpty(cond.DistroName, cond.Architecture, cond.VersionLessThan) > 1 {
return nil, fmt.Errorf("only a single conditional allowed in installer config for %v", typeName)
}
distroName, distroVersion := splitDistroNameVer(distroNameVer)
if distroNameCnf, ok := cond.DistroName[distroName]; ok {
installerConfig = distroNameCnf
}
if archCnf, ok := cond.Architecture[archName]; ok {
installerConfig = archCnf
}
for ltVer, ltConf := range cond.VersionLessThan {
if r, ok := replacements[ltVer]; ok {
ltVer = r
}
if common.VersionLessThan(distroVersion, ltVer) {
installerConfig = ltConf
}
}
}
return installerConfig, nil
}
func ImageTypes(distroNameVer string) (map[string]ImageTypeYAML, error) {
toplevel, err := load(distroNameVer)
if err != nil {
return nil, err
}
// We have a bunch of names like "server-ami" that are writen
// in the YAML as "server_ami" so we need to normalize
imgTypes := make(map[string]ImageTypeYAML, len(toplevel.ImageTypes))
for name := range toplevel.ImageTypes {
v := toplevel.ImageTypes[name]
v.name = name
imgTypes[name] = v
}
return imgTypes, nil
}

File diff suppressed because it is too large Load diff

View file

@ -2,42 +2,42 @@
.common:
azure_rhui_common_pkgset: &azure_rhui_common_pkgset
include:
- "@base"
- "@core"
- "authconfig"
- "bpftool"
- "bzip2"
- "chrony"
- "cloud-init"
- "cloud-utils-growpart"
- "dracut-config-generic"
- "dracut-norescue"
- "efibootmgr"
- "firewalld"
- "gdisk"
- "grub2-efi-x64"
- "grub2-pc"
- "grub2"
- "hyperv-daemons"
- "kernel"
- "lvm2"
- "redhat-release-eula"
- "redhat-support-tool"
- "rh-dotnetcore11"
- "rhn-setup"
- "rhui-azure-rhel7"
- "rsync"
- "shim-x64"
- "tar"
- "tcpdump"
- "WALinuxAgent"
- "yum-rhn-plugin"
- "yum-utils"
- "@base"
- "@core"
- "authconfig"
- "bpftool"
- "bzip2"
- "chrony"
- "cloud-init"
- "cloud-utils-growpart"
- "dracut-config-generic"
- "dracut-norescue"
- "efibootmgr"
- "firewalld"
- "gdisk"
- "grub2-efi-x64"
- "grub2-pc"
- "grub2"
- "hyperv-daemons"
- "kernel"
- "lvm2"
- "redhat-release-eula"
- "redhat-support-tool"
- "rh-dotnetcore11"
- "rhn-setup"
- "rhui-azure-rhel7"
- "rsync"
- "shim-x64"
- "tar"
- "tcpdump"
- "WALinuxAgent"
- "yum-rhn-plugin"
- "yum-utils"
exclude:
- "dracut-config-rescue"
- "mariadb-libs"
- "NetworkManager-config-server"
- "postfix"
- "dracut-config-rescue"
- "mariadb-libs"
- "NetworkManager-config-server"
- "postfix"
condition:
distro_name:
"rhel":
@ -85,7 +85,7 @@
type: vfat
uuid: *efi_filesystem_uuid
mountpoint: "/boot/efi"
label: "EFI-SYSTEM"
label: "ESP"
fstab_options: "defaults,uid=0,gid=0,umask=077,shortname=winnt"
fstab_freq: 0
fstab_passno: 2
@ -118,7 +118,7 @@
image_config:
default:
timezone: "America/New_York"
locale: "en_US.UTF-8"
locale: "en_US.UTF-8"
gpgkey_files:
- "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
sysconfig:
@ -133,119 +133,122 @@ image_config:
install_weak_deps: true
image_types:
azure_rhui:
"azure-rhui":
partition_table:
<<: *default_partition_tables
package_sets:
- *azure_rhui_common_pkgset
os:
- *azure_rhui_common_pkgset
ec2:
partition_table:
<<: *default_partition_tables
package_sets:
- include:
- "@core"
- "authconfig"
- "kernel"
- "yum-utils"
- "cloud-init"
- "dracut-config-generic"
- "dracut-norescue"
- "grub2"
- "tar"
- "rsync"
- "rh-amazon-rhui-client"
- "redhat-cloud-client-configuration"
- "chrony"
- "cloud-utils-growpart"
- "gdisk"
exclude:
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-lib"
- "alsa-tools-firmware"
- "ivtv-firmware"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "libertas-sd8686-firmware"
- "libertas-sd8787-firmware"
- "libertas-usb8388-firmware"
- "biosdevname"
- "plymouth"
# NM is excluded by the original KS, but it is in the image built from it.
# - "NetworkManager"
- "iprutils"
# linux-firmware is uninstalled by the original KS, but it is a direct dependency of kernel,
# so we can't exclude it.
# - "linux-firmware"
- "firewalld"
os:
- include:
- "@core"
- "authconfig"
- "kernel"
- "yum-utils"
- "cloud-init"
- "dracut-config-generic"
- "dracut-norescue"
- "grub2"
- "tar"
- "rsync"
- "rh-amazon-rhui-client"
- "redhat-cloud-client-configuration"
- "chrony"
- "cloud-utils-growpart"
- "gdisk"
exclude:
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-lib"
- "alsa-tools-firmware"
- "ivtv-firmware"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "libertas-sd8686-firmware"
- "libertas-sd8787-firmware"
- "libertas-usb8388-firmware"
- "biosdevname"
- "plymouth"
# NM is excluded by the original KS, but it is in the image built from it.
# - "NetworkManager"
- "iprutils"
# linux-firmware is uninstalled by the original KS, but it is a direct dependency of kernel,
# so we can't exclude it.
# - "linux-firmware"
- "firewalld"
qcow2:
partition_table:
<<: *default_partition_tables
package_sets:
- include:
- "@core"
- "kernel"
- "nfs-utils"
- "yum-utils"
- "cloud-init"
# - "ovirt-guest-agent-common"
- "rhn-setup"
- "yum-rhn-plugin"
- "cloud-utils-growpart"
- "dracut-config-generic"
- "tar"
- "tcpdump"
- "rsync"
exclude:
- "biosdevname"
- "dracut-config-rescue"
- "iprutils"
- "NetworkManager-team"
- "NetworkManager-tui"
- "NetworkManager"
- "plymouth"
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-lib"
- "alsa-tools-firmware"
- "ivtv-firmware"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "libertas-sd8686-firmware"
- "libertas-sd8787-firmware"
- "libertas-usb8388-firmware"
condition:
distro_name:
"rhel":
include:
- "insights-client"
os:
- include:
- "@core"
- "kernel"
- "nfs-utils"
- "yum-utils"
- "cloud-init"
# - "ovirt-guest-agent-common"
- "rhn-setup"
- "yum-rhn-plugin"
- "cloud-utils-growpart"
- "dracut-config-generic"
- "tar"
- "tcpdump"
- "rsync"
exclude:
- "biosdevname"
- "dracut-config-rescue"
- "iprutils"
- "NetworkManager-team"
- "NetworkManager-tui"
- "NetworkManager"
- "plymouth"
- "aic94xx-firmware"
- "alsa-firmware"
- "alsa-lib"
- "alsa-tools-firmware"
- "ivtv-firmware"
- "iwl1000-firmware"
- "iwl100-firmware"
- "iwl105-firmware"
- "iwl135-firmware"
- "iwl2000-firmware"
- "iwl2030-firmware"
- "iwl3160-firmware"
- "iwl3945-firmware"
- "iwl4965-firmware"
- "iwl5000-firmware"
- "iwl5150-firmware"
- "iwl6000-firmware"
- "iwl6000g2a-firmware"
- "iwl6000g2b-firmware"
- "iwl6050-firmware"
- "iwl7260-firmware"
- "libertas-sd8686-firmware"
- "libertas-sd8787-firmware"
- "libertas-usb8388-firmware"
condition:
distro_name:
"rhel":
include:
- "insights-client"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -368,6 +368,31 @@ func diskImage(workload workload.Workload,
return img, nil
}
func tarImage(workload workload.Workload,
t *imageType,
bp *blueprint.Blueprint,
options distro.ImageOptions,
packageSets map[string]rpmmd.PackageSet,
containers []container.SourceSpec,
rng *rand.Rand) (image.ImageKind, error) {
img := image.NewArchive()
img.Platform = t.platform
var err error
img.OSCustomizations, err = osCustomizations(t, packageSets[osPkgsKey], containers, bp.Customizations)
if err != nil {
return nil, err
}
img.Environment = t.environment
img.Workload = workload
img.Filename = t.Filename()
return img, nil
}
func containerImage(workload workload.Workload,
t *imageType,
bp *blueprint.Blueprint,
@ -423,10 +448,6 @@ func liveInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
}
// Enable grub2 BIOS iso on x86_64 only
if img.Platform.GetArch() == arch.ARCH_X86_64 {
img.ISOBoot = manifest.Grub2ISOBoot
@ -446,6 +467,11 @@ func liveInstallerImage(workload workload.Workload,
img.AdditionalDrivers = append(img.AdditionalDrivers, installerConfig.AdditionalDrivers...)
}
imgConfig := t.getDefaultImageConfig()
if imgConfig != nil && imgConfig.IsoRootfsType != nil {
img.RootfsType = *imgConfig.IsoRootfsType
}
return img, nil
}
@ -493,6 +519,7 @@ func imageInstallerImage(workload workload.Workload,
img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, instCust.Modules.Enable...)
img.DisabledAnacondaModules = append(img.DisabledAnacondaModules, instCust.Modules.Disable...)
}
img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers)
img.Platform = t.platform
img.Workload = workload
@ -532,8 +559,9 @@ func imageInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
img.RootfsCompression = "xz" // This also triggers using the bcj filter
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
imgConfig := t.getDefaultImageConfig()
if imgConfig != nil && imgConfig.IsoRootfsType != nil {
img.RootfsType = *imgConfig.IsoRootfsType
}
// Enable grub2 BIOS iso on x86_64 only
@ -751,8 +779,9 @@ func iotInstallerImage(workload workload.Workload,
img.Filename = t.Filename()
img.RootfsCompression = "xz" // This also triggers using the bcj filter
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs
imgConfig := t.getDefaultImageConfig()
if imgConfig != nil && imgConfig.IsoRootfsType != nil {
img.RootfsType = *imgConfig.IsoRootfsType
}
// Enable grub2 BIOS iso on x86_64 only
@ -946,13 +975,3 @@ func makeOSTreePayloadCommit(options *ostree.ImageOptions, defaultRef string) (o
RHSM: options.RHSM,
}, nil
}
// initialSetupKickstart returns the File configuration for a kickstart file
// that's required to enable initial-setup to run on first boot.
func initialSetupKickstart() *fsnode.File {
file, err := fsnode.NewFile("/root/anaconda-ks.cfg", nil, "root", "root", []byte("# Run initial-setup on first boot\n# Created by osbuild\nfirstboot --reconfig\n"))
if err != nil {
panic(err)
}
return file
}

View file

@ -28,7 +28,7 @@ import (
type imageFunc func(workload workload.Workload, t *imageType, bp *blueprint.Blueprint, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error)
type packageSetFunc func(t *imageType) (rpmmd.PackageSet, error)
type packageSetFunc func(t *imageType) (map[string]rpmmd.PackageSet, error)
type isoLabelFunc func(t *imageType) string
@ -42,7 +42,7 @@ type imageType struct {
filename string
compression string
mimeType string
packageSets map[string]packageSetFunc
packageSets packageSetFunc
defaultImageConfig *distro.ImageConfig
defaultInstallerConfig *distro.InstallerConfig
defaultSize uint64
@ -237,12 +237,12 @@ func (t *imageType) Manifest(bp *blueprint.Blueprint,
staticPackageSets := make(map[string]rpmmd.PackageSet)
// don't add any static packages if Minimal was selected
if !bp.Minimal {
for name, getter := range t.packageSets {
pkgSet, err := getter(t)
if err != nil {
return nil, nil, err
}
if !bp.Minimal && t.packageSets != nil {
pkgSets, err := t.packageSets(t)
if err != nil {
return nil, nil, err
}
for name, pkgSet := range pkgSets {
staticPackageSets[name] = pkgSet
}
}

View file

@ -1,10 +1,80 @@
package fedora
import (
"fmt"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/rpmmd"
)
func packageSetLoader(t *imageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "", VersionReplacements())
func packageSetLoader(t *imageType) (map[string]rpmmd.PackageSet, error) {
return defs.PackageSets(t, VersionReplacements())
}
func imageConfig(d distribution, imageType string) *distro.ImageConfig {
// arch is currently not used in fedora
arch := ""
return common.Must(defs.ImageConfig(d.name, arch, imageType, VersionReplacements()))
}
func installerConfig(d distribution, imageType string) *distro.InstallerConfig {
// arch is currently not used in fedora
arch := ""
return common.Must(defs.InstallerConfig(d.name, arch, imageType, VersionReplacements()))
}
func newImageTypeFrom(d distribution, imgYAML defs.ImageTypeYAML) imageType {
it := imageType{
name: imgYAML.Name(),
nameAliases: imgYAML.NameAliases,
filename: imgYAML.Filename,
compression: imgYAML.Compression,
mimeType: imgYAML.MimeType,
bootable: imgYAML.Bootable,
bootISO: imgYAML.BootISO,
rpmOstree: imgYAML.RPMOSTree,
isoLabel: getISOLabelFunc(imgYAML.ISOLabel),
defaultSize: imgYAML.DefaultSize,
buildPipelines: imgYAML.BuildPipelines,
payloadPipelines: imgYAML.PayloadPipelines,
exports: imgYAML.Exports,
requiredPartitionSizes: imgYAML.RequiredPartitionSizes,
environment: &imgYAML.Environment,
}
// XXX: make this a helper on imgYAML()
it.defaultImageConfig = imageConfig(d, imgYAML.Name())
it.defaultInstallerConfig = installerConfig(d, imgYAML.Name())
it.packageSets = packageSetLoader
switch imgYAML.Image {
case "disk":
it.image = diskImage
case "container":
it.image = containerImage
case "image_installer":
it.image = imageInstallerImage
case "live_installer":
it.image = liveInstallerImage
case "bootable_container":
it.image = bootableContainerImage
case "iot":
it.image = iotImage
case "iot_commit":
it.image = iotCommitImage
case "iot_container":
it.image = iotContainerImage
case "iot_installer":
it.image = iotInstallerImage
case "iot_simplified_installer":
it.image = iotSimplifiedInstallerImage
case "tar":
it.image = tarImage
default:
err := fmt.Errorf("unknown image func: %v for %v", imgYAML.Image, imgYAML.Name())
panic(err)
}
return it
}

View file

@ -3,21 +3,13 @@ package fedora
const VERSION_BRANCHED = "43"
const VERSION_RAWHIDE = "43"
// Fedora version 41 and later use a plain squashfs rootfs on the iso instead of
// compressing an ext4 filesystem.
const VERSION_ROOTFS_SQUASHFS = "41"
// Fedora 43 and later we reset the machine-id file to align ourselves with the
// other Fedora variants.
const VERSION_FIRSTBOOT = "43"
// Version at which we stop installing weak dependencies for Fedora Minimal
const VERSION_MINIMAL_WEAKDEPS = "43"
func VersionReplacements() map[string]string {
return map[string]string{
"VERSION_BRANCHED": VERSION_BRANCHED,
"VERSION_RAWHIDE": VERSION_RAWHIDE,
"VERSION_ROOTFS_SQUASHFS": VERSION_ROOTFS_SQUASHFS,
"VERSION_BRANCHED": VERSION_BRANCHED,
"VERSION_RAWHIDE": VERSION_RAWHIDE,
}
}

View file

@ -8,20 +8,21 @@ import (
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/shell"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/osbuild"
)
// ImageConfig represents a (default) configuration applied to the image payload.
type ImageConfig struct {
Hostname *string `yaml:"hostname,omitempty"`
Timezone *string `yaml:"timezone,omitempty"`
TimeSynchronization *osbuild.ChronyStageOptions
Locale *string `yaml:"locale,omitempty"`
Hostname *string `yaml:"hostname,omitempty"`
Timezone *string `yaml:"timezone,omitempty"`
TimeSynchronization *osbuild.ChronyStageOptions `yaml:"time_synchronization,omitempty"`
Locale *string `yaml:"locale,omitempty"`
Keyboard *osbuild.KeymapStageOptions
EnabledServices []string
DisabledServices []string
EnabledServices []string `yaml:"enabled_services,omitempty"`
DisabledServices []string `yaml:"disabled_services,omitempty"`
MaskedServices []string
DefaultTarget *string
DefaultTarget *string `yaml:"default_target,omitempty"`
Sysconfig *Sysconfig `yaml:"sysconfig,omitempty"`
DefaultKernel *string `yaml:"default_kernel,omitempty"`
@ -32,49 +33,49 @@ type ImageConfig struct {
GPGKeyFiles []string `yaml:"gpgkey_files,omitempty"`
// Disable SELinux labelling
NoSElinux *bool
NoSElinux *bool `yaml:"no_selinux,omitempty"`
// Do not use. Forces auto-relabelling on first boot.
// See https://github.com/osbuild/osbuild/commit/52cb27631b587c1df177cd17625c5b473e1e85d2
SELinuxForceRelabel *bool
// Disable documentation
ExcludeDocs *bool
ExcludeDocs *bool `yaml:"exclude_docs,omitempty"`
ShellInit []shell.InitFile
// for RHSM configuration, we need to potentially distinguish the case
// when the user want the image to be subscribed on first boot and when not
RHSMConfig map[subscription.RHSMStatus]*subscription.RHSMConfig
SystemdLogind []*osbuild.SystemdLogindStageOptions
CloudInit []*osbuild.CloudInitStageOptions
RHSMConfig map[subscription.RHSMStatus]*subscription.RHSMConfig `yaml:"rhsm_config,omitempty"`
SystemdLogind []*osbuild.SystemdLogindStageOptions `yaml:"systemd_logind,omitempty"`
CloudInit []*osbuild.CloudInitStageOptions `yaml:"cloud_init"`
Modprobe []*osbuild.ModprobeStageOptions
DracutConf []*osbuild.DracutConfStageOptions
SystemdDropin []*osbuild.SystemdUnitStageOptions
SystemdUnit []*osbuild.SystemdUnitCreateStageOptions
DracutConf []*osbuild.DracutConfStageOptions `yaml:"dracut_conf"`
SystemdDropin []*osbuild.SystemdUnitStageOptions `yaml:"systemd_dropin,omitempty"`
SystemdUnit []*osbuild.SystemdUnitCreateStageOptions `yaml:"systemd_unit,omitempty"`
Authselect *osbuild.AuthselectStageOptions
SELinuxConfig *osbuild.SELinuxConfigStageOptions
SELinuxConfig *osbuild.SELinuxConfigStageOptions `yaml:"selinux_config,omitempty"`
Tuned *osbuild.TunedStageOptions
Tmpfilesd []*osbuild.TmpfilesdStageOptions
PamLimitsConf []*osbuild.PamLimitsConfStageOptions
PamLimitsConf []*osbuild.PamLimitsConfStageOptions `yaml:"pam_limits_conf,omitempty"`
Sysctld []*osbuild.SysctldStageOptions
// Do not use DNFConfig directly, call "DNFConfigOptions()"
DNFConfig []*osbuild.DNFConfigStageOptions
DNFSetReleaseVerVar *bool
SshdConfig *osbuild.SshdConfigStageOptions
DNFConfig []*osbuild.DNFConfigStageOptions `yaml:"dnf_config,omitempty"`
DNFSetReleaseVerVar *bool `yaml:"dnf_set_release_ver_var,omitempty"`
SshdConfig *osbuild.SshdConfigStageOptions `yaml:"sshd_config"`
Authconfig *osbuild.AuthconfigStageOptions
PwQuality *osbuild.PwqualityConfStageOptions
WAAgentConfig *osbuild.WAAgentConfStageOptions
Grub2Config *osbuild.GRUB2Config
DNFAutomaticConfig *osbuild.DNFAutomaticConfigStageOptions
WAAgentConfig *osbuild.WAAgentConfStageOptions `yaml:"waagent_config,omitempty"`
Grub2Config *osbuild.GRUB2Config `yaml:"grub2_config,omitempty"`
DNFAutomaticConfig *osbuild.DNFAutomaticConfigStageOptions `yaml:"dnf_automatic_config"`
YumConfig *osbuild.YumConfigStageOptions
YUMRepos []*osbuild.YumReposStageOptions
YUMRepos []*osbuild.YumReposStageOptions `yaml:"yum_repos,omitempty"`
Firewall *osbuild.FirewallStageOptions
UdevRules *osbuild.UdevRulesStageOptions
GCPGuestAgentConfig *osbuild.GcpGuestAgentConfigOptions
NetworkManager *osbuild.NMConfStageOptions
UdevRules *osbuild.UdevRulesStageOptions `yaml:"udev_rules,omitempty"`
GCPGuestAgentConfig *osbuild.GcpGuestAgentConfigOptions `yaml:"gcp_guest_agent_config,omitempty"`
NetworkManager *osbuild.NMConfStageOptions `yaml:"network_manager,omitempty"`
WSLConfig *WSLConfig
WSLConfig *WSLConfig `yaml:"wsl_config,omitempty"`
Files []*fsnode.File
Directories []*fsnode.Directory
@ -98,13 +99,13 @@ type ImageConfig struct {
// OSTree specific configuration
// Read only sysroot and boot
OSTreeConfSysrootReadOnly *bool
OSTreeConfSysrootReadOnly *bool `yaml:"ostree_conf_sysroot_readonly,omitempty"`
// Lock the root account in the deployment unless the user defined root
// user options in the build configuration.
LockRootUser *bool
LockRootUser *bool `yaml:"lock_root_user,omitempty"`
IgnitionPlatform *string
IgnitionPlatform *string `yaml:"ignition_platform,omitempty"`
// InstallWeakDeps enables installation of weak dependencies for packages
// that are statically defined for the pipeline.
@ -117,11 +118,15 @@ type ImageConfig struct {
// MountUnits creates systemd .mount units to describe the filesystem
// instead of writing to /etc/fstab
MountUnits *bool
MountUnits *bool `yaml:"mount_units,omitempty"`
// IsoRootfsType defines what rootfs (squashfs, erofs,ext4)
// is used
IsoRootfsType *manifest.RootfsType `yaml:"iso_rootfs_type,omitempty"`
}
type WSLConfig struct {
BootSystemd bool
BootSystemd bool `yaml:"boot_systemd,omitempty"`
}
// InheritFrom inherits unset values from the provided parent configuration and

View file

@ -4,6 +4,6 @@ package distro
// part of an Installer image type.
type InstallerConfig struct {
// Additional dracut modules and drivers to enable
AdditionalDracutModules []string
AdditionalDrivers []string
AdditionalDracutModules []string `yaml:"additional_dracut_modules"`
AdditionalDrivers []string `yaml:"additional_drivers"`
}

View file

@ -49,7 +49,7 @@ var requiredDirectorySizes = map[string]uint64{
type ImageFunc func(workload workload.Workload, t *ImageType, customizations *blueprint.Customizations, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error)
type PackageSetFunc func(t *ImageType) (rpmmd.PackageSet, error)
type PackageSetFunc func(t *ImageType) (map[string]rpmmd.PackageSet, error)
type BasePartitionTableFunc func(t *ImageType) (disk.PartitionTable, bool)
@ -62,7 +62,7 @@ type ImageType struct {
name string
filename string
mimeType string
packageSets map[string]PackageSetFunc
packageSets PackageSetFunc
buildPipelines []string
payloadPipelines []string
exports []string
@ -306,12 +306,14 @@ func (t *ImageType) Manifest(bp *blueprint.Blueprint,
// of the same name from the distro and arch
staticPackageSets := make(map[string]rpmmd.PackageSet)
for name, getter := range t.packageSets {
pkgSets, err := getter(t)
if t.packageSets != nil {
pkgSets, err := t.packageSets(t)
if err != nil {
return nil, nil, err
}
staticPackageSets[name] = pkgSets
for name, pkgSet := range pkgSets {
staticPackageSets[name] = pkgSet
}
}
// amend with repository information and collect payload repos
@ -428,7 +430,7 @@ func (t *ImageType) checkOptions(bp *blueprint.Blueprint, options distro.ImageOp
func NewImageType(
name, filename, mimeType string,
pkgSets map[string]PackageSetFunc,
pkgSets PackageSetFunc,
imgFunc ImageFunc,
buildPipelines, payloadPipelines, exports []string,
) *ImageType {

View file

@ -1,35 +1,16 @@
package rhel10
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
)
// TODO: move these to the EC2 environment
func amiKernelOptions() []string {
return []string{"console=tty0", "console=ttyS0,115200n8", "nvme_core.io_timeout=4294967295"}
}
func amiAarch64KernelOptions() []string {
return append(amiKernelOptions(), "iommu.strict=0")
}
func amiSapKernelOptions() []string {
return append(amiKernelOptions(), []string{"processor.max_cstate=1", "intel_idle.max_cstate=1"}...)
}
func mkAMIImgTypeX86_64() *rhel.ImageType {
func mkAMIImgTypeX86_64(d *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image"},
@ -38,21 +19,18 @@ func mkAMIImgTypeX86_64() *rhel.ImageType {
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
it.DefaultImageConfig.KernelOptions = amiKernelOptions()
it.DefaultImageConfig = imageConfig(d, "x86_64", "ami")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
func mkAMIImgTypeAarch64() *rhel.ImageType {
func mkAMIImgTypeAarch64(rd *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image"},
@ -61,22 +39,19 @@ func mkAMIImgTypeAarch64() *rhel.ImageType {
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfig()
it.DefaultImageConfig.KernelOptions = amiAarch64KernelOptions()
it.DefaultImageConfig = imageConfig(rd, "aarch64", "ami")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
// RHEL internal-only x86_64 EC2 image type
func mkEc2ImgTypeX86_64() *rhel.ImageType {
func mkEc2ImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -86,22 +61,19 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
it.Compression = "xz"
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
it.DefaultImageConfig.KernelOptions = amiKernelOptions()
it.DefaultImageConfig = imageConfig(rd, "x86_64", "ec2")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
// RHEL internal-only aarch64 EC2 image type
func mkEC2ImgTypeAarch64() *rhel.ImageType {
func mkEC2ImgTypeAarch64(rd *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -111,22 +83,19 @@ func mkEC2ImgTypeAarch64() *rhel.ImageType {
it.Compression = "xz"
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfig()
it.DefaultImageConfig.KernelOptions = amiAarch64KernelOptions()
it.DefaultImageConfig = imageConfig(rd, "aarch64", "ec2")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
// RHEL internal-only x86_64 EC2 HA image type
func mkEc2HaImgTypeX86_64() *rhel.ImageType {
func mkEc2HaImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ec2-ha",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -136,21 +105,18 @@ func mkEc2HaImgTypeX86_64() *rhel.ImageType {
it.Compression = "xz"
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = defaultEc2ImageConfigX86_64()
it.DefaultImageConfig.KernelOptions = amiKernelOptions()
it.DefaultImageConfig = imageConfig(rd, "x86_64", "ec2-ha")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
func mkEC2SapImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ec2-sap",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -160,134 +126,8 @@ func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
it.Compression = "xz"
it.Bootable = true
it.DefaultSize = 10 * datasizes.GibiByte
it.DefaultImageConfig = sapImageConfig(osVersion).InheritFrom(defaultEc2ImageConfigX86_64())
it.DefaultImageConfig.KernelOptions = amiSapKernelOptions()
it.DefaultImageConfig = imageConfig(rd, "x86_64", "ec2-sap")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
// IMAGE CONFIG
// default EC2 images config (common for all architectures)
func defaultEc2ImageConfig() *distro.ImageConfig {
return &distro.ImageConfig{
TimeSynchronization: &osbuild.ChronyStageOptions{
Servers: []osbuild.ChronyConfigServer{
{
Hostname: "169.254.169.123",
Prefer: common.ToPtr(true),
Iburst: common.ToPtr(true),
Minpoll: common.ToPtr(4),
Maxpoll: common.ToPtr(4),
},
},
// empty string will remove any occurrences of the option from the configuration
LeapsecTz: common.ToPtr(""),
},
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: common.ToPtr("multi-user.target"),
UpdateDefaultKernel: common.ToPtr(true),
DefaultKernel: common.ToPtr("kernel"),
Sysconfig: &distro.Sysconfig{
Networking: true,
NoZeroConf: true,
},
SystemdLogind: []*osbuild.SystemdLogindStageOptions{
{
Filename: "00-getty-fixes.conf",
Config: osbuild.SystemdLogindConfigDropin{
Login: osbuild.SystemdLogindConfigLoginSection{
NAutoVTs: common.ToPtr(0),
},
},
},
},
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "00-rhel-default-user.cfg",
Config: osbuild.CloudInitConfigFile{
SystemInfo: &osbuild.CloudInitConfigSystemInfo{
DefaultUser: &osbuild.CloudInitConfigDefaultUser{
Name: "ec2-user",
},
},
},
},
},
Modprobe: []*osbuild.ModprobeStageOptions{
{
Filename: "blacklist-nouveau.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("nouveau"),
},
},
{
Filename: "blacklist-amdgpu.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("amdgpu"),
},
},
// https://issues.redhat.com/browse/RHEL-71926
{
Filename: "blacklist-i2c_piix4.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("i2c_piix4"),
},
},
},
SystemdDropin: []*osbuild.SystemdUnitStageOptions{
// RHBZ#1822863
{
Unit: "nm-cloud-setup.service",
Dropin: "10-rh-enable-for-ec2.conf",
Config: osbuild.SystemdServiceUnitDropin{
Service: &osbuild.SystemdUnitServiceSection{
Environment: []osbuild.EnvironmentVariable{{Key: "NM_CLOUD_SETUP_EC2", Value: "yes"}},
},
},
},
},
SshdConfig: &osbuild.SshdConfigStageOptions{
Config: osbuild.SshdConfigConfig{
PasswordAuthentication: common.ToPtr(false),
},
},
}
}
func appendEC2DracutX86_64(ic *distro.ImageConfig) *distro.ImageConfig {
ic.DracutConf = append(ic.DracutConf,
&osbuild.DracutConfStageOptions{
Filename: "ec2.conf",
Config: osbuild.DracutConfigFile{
AddDrivers: []string{
"nvme",
"xen-blkfront",
},
},
})
return ic
}
func defaultEc2ImageConfigX86_64() *distro.ImageConfig {
ic := defaultEc2ImageConfig()
return appendEC2DracutX86_64(ic)
}

View file

@ -1,14 +1,9 @@
package rhel10
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
)
// Azure image type
@ -17,9 +12,7 @@ func mkAzureImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType {
"vhd",
"disk.vhd",
"application/x-vhd",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc"},
@ -28,8 +21,7 @@ func mkAzureImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType {
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.DefaultImageConfig = defaultAzureImageConfig(rd)
it.DefaultImageConfig.KernelOptions = defaultAzureKernelOptions(a)
it.DefaultImageConfig = imageConfig(rd, a.String(), "vhd")
it.BasePartitionTables = defaultBasePartitionTables
return it
@ -41,9 +33,7 @@ func mkAzureInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType
"azure-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},
@ -53,9 +43,8 @@ func mkAzureInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType
it.Compression = "xz"
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.DefaultImageConfig = defaultAzureImageConfig(rd)
it.DefaultImageConfig.KernelOptions = defaultAzureKernelOptions(a)
it.BasePartitionTables = azureInternalBasePartitionTables
it.DefaultImageConfig = imageConfig(rd, a.String(), "azure-rhui")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
@ -65,9 +54,7 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageTy
"azure-sap-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},
@ -77,444 +64,8 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageTy
it.Compression = "xz"
it.Bootable = true
it.DefaultSize = 64 * datasizes.GibiByte
it.DefaultImageConfig = sapAzureImageConfig(rd)
it.DefaultImageConfig.KernelOptions = defaultAzureKernelOptions(a)
it.BasePartitionTables = azureInternalBasePartitionTables
it.DefaultImageConfig = imageConfig(rd, a.String(), "azure-sap-rhui")
it.BasePartitionTables = defaultBasePartitionTables
return it
}
// PARTITION TABLES
func azureInternalBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
switch t.Arch().Name() {
case arch.ARCH_X86_64.String():
return disk.PartitionTable{
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: disk.PT_GPT,
Size: 64 * datasizes.GibiByte,
Partitions: []disk.Partition{
{
Size: 500 * datasizes.MebiByte,
Type: disk.EFISystemPartitionGUID,
UUID: disk.EFISystemPartitionUUID,
Payload: &disk.Filesystem{
Type: "vfat",
UUID: disk.EFIFilesystemUUID,
Mountpoint: "/boot/efi",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
// NB: we currently don't support /boot on LVM
{
Size: 1 * datasizes.GibiByte,
Type: disk.FilesystemDataGUID,
UUID: disk.DataPartitionUUID,
Payload: &disk.Filesystem{
Type: "xfs",
Mountpoint: "/boot",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 2 * datasizes.MebiByte,
Bootable: true,
Type: disk.BIOSBootPartitionGUID,
UUID: disk.BIOSBootPartitionUUID,
},
{
Type: disk.LVMPartitionGUID,
UUID: disk.RootPartitionUUID,
Payload: &disk.LVMVolumeGroup{
Name: "rootvg",
Description: "built with lvm2 and osbuild",
LogicalVolumes: []disk.LVMLogicalVolume{
{
Size: 1 * datasizes.GibiByte,
Name: "homelv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "home",
Mountpoint: "/home",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 2 * datasizes.GibiByte,
Name: "rootlv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 2 * datasizes.GibiByte,
Name: "tmplv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "tmp",
Mountpoint: "/tmp",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 10 * datasizes.GibiByte,
Name: "usrlv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "usr",
Mountpoint: "/usr",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 10 * datasizes.GibiByte,
Name: "varlv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "var",
Mountpoint: "/var",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
},
},
},
}, true
case arch.ARCH_AARCH64.String():
return disk.PartitionTable{
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: disk.PT_GPT,
Size: 64 * datasizes.GibiByte,
Partitions: []disk.Partition{
{
Size: 500 * datasizes.MebiByte,
Type: disk.EFISystemPartitionGUID,
UUID: disk.EFISystemPartitionUUID,
Payload: &disk.Filesystem{
Type: "vfat",
UUID: disk.EFIFilesystemUUID,
Mountpoint: "/boot/efi",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
// NB: we currently don't support /boot on LVM
{
Size: 1 * datasizes.GibiByte,
Type: disk.FilesystemDataGUID,
UUID: disk.DataPartitionUUID,
Payload: &disk.Filesystem{
Type: "xfs",
Mountpoint: "/boot",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Type: disk.LVMPartitionGUID,
UUID: disk.RootPartitionUUID,
Payload: &disk.LVMVolumeGroup{
Name: "rootvg",
Description: "built with lvm2 and osbuild",
LogicalVolumes: []disk.LVMLogicalVolume{
{
Size: 1 * datasizes.GibiByte,
Name: "homelv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "home",
Mountpoint: "/home",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 2 * datasizes.GibiByte,
Name: "rootlv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 2 * datasizes.GibiByte,
Name: "tmplv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "tmp",
Mountpoint: "/tmp",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 10 * datasizes.GibiByte,
Name: "usrlv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "usr",
Mountpoint: "/usr",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 10 * datasizes.GibiByte,
Name: "varlv",
Payload: &disk.Filesystem{
Type: "xfs",
Label: "var",
Mountpoint: "/var",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
},
},
},
}, true
default:
return disk.PartitionTable{}, false
}
}
// IMAGE CONFIG
func defaultAzureKernelOptions(a arch.Arch) []string {
kargs := []string{"ro", "loglevel=3", "nvme_core.io_timeout=240"}
switch a {
case arch.ARCH_AARCH64:
kargs = append(kargs, "console=ttyAMA0")
case arch.ARCH_X86_64:
kargs = append(kargs, "console=tty1", "console=ttyS0", "earlyprintk=ttyS0", "rootdelay=300")
}
return kargs
}
// based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure
func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig {
datalossWarningScript, datalossSystemdUnit, err := rhel.CreateAzureDatalossWarningScriptAndUnit()
if err != nil {
panic(err)
}
ic := &distro.ImageConfig{
Keyboard: &osbuild.KeymapStageOptions{
Keymap: "us",
X11Keymap: &osbuild.X11KeymapOptions{
Layouts: []string{"us"},
},
},
UpdateDefaultKernel: common.ToPtr(true),
DefaultKernel: common.ToPtr("kernel-core"),
Sysconfig: &distro.Sysconfig{
Networking: true,
NoZeroConf: true,
},
EnabledServices: []string{
"firewalld",
"nm-cloud-setup.service",
"nm-cloud-setup.timer",
"sshd",
"waagent",
datalossSystemdUnit.Filename,
},
SshdConfig: &osbuild.SshdConfigStageOptions{
Config: osbuild.SshdConfigConfig{
ClientAliveInterval: common.ToPtr(180),
},
},
Modprobe: []*osbuild.ModprobeStageOptions{
{
Filename: "blacklist-amdgpu.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("amdgpu"),
},
},
{
Filename: "blacklist-intel-cstate.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("intel_cstate"),
},
},
{
Filename: "blacklist-floppy.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("floppy"),
},
},
{
Filename: "blacklist-nouveau.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("nouveau"),
osbuild.NewModprobeConfigCmdBlacklist("lbm-nouveau"),
},
},
{
Filename: "blacklist-skylake-edac.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("skx_edac"),
},
},
{
Filename: "blacklist-intel_uncore.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("intel_uncore"),
},
},
{
Filename: "blacklist-acpi_cpufreq.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("acpi_cpufreq"),
},
},
},
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "10-azure-kvp.cfg",
Config: osbuild.CloudInitConfigFile{
Reporting: &osbuild.CloudInitConfigReporting{
Logging: &osbuild.CloudInitConfigReportingHandlers{
Type: "log",
},
Telemetry: &osbuild.CloudInitConfigReportingHandlers{
Type: "hyperv",
},
},
},
},
{
Filename: "91-azure_datasource.cfg",
Config: osbuild.CloudInitConfigFile{
Datasource: &osbuild.CloudInitConfigDatasource{
Azure: &osbuild.CloudInitConfigDatasourceAzure{
ApplyNetworkConfig: false,
},
},
DatasourceList: []string{
"Azure",
},
},
},
},
PwQuality: &osbuild.PwqualityConfStageOptions{
Config: osbuild.PwqualityConfConfig{
Minlen: common.ToPtr(6),
Minclass: common.ToPtr(3),
Dcredit: common.ToPtr(0),
Ucredit: common.ToPtr(0),
Lcredit: common.ToPtr(0),
Ocredit: common.ToPtr(0),
},
},
WAAgentConfig: &osbuild.WAAgentConfStageOptions{
Config: osbuild.WAAgentConfig{
RDFormat: common.ToPtr(false),
RDEnableSwap: common.ToPtr(false),
ProvisioningUseCloudInit: common.ToPtr(true),
ProvisioningEnabled: common.ToPtr(false),
},
},
Grub2Config: &osbuild.GRUB2Config{
DisableRecovery: common.ToPtr(true),
DisableSubmenu: common.ToPtr(true),
Distributor: "$(sed 's, release .*$,,g' /etc/system-release)",
Terminal: []string{"serial", "console"},
Serial: "serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1",
Timeout: 10,
TimeoutStyle: osbuild.GRUB2ConfigTimeoutStyleCountdown,
},
UdevRules: &osbuild.UdevRulesStageOptions{
Filename: "/etc/udev/rules.d/68-azure-sriov-nm-unmanaged.rules",
Rules: osbuild.UdevRules{
osbuild.UdevRuleComment{
Comment: []string{
"Accelerated Networking on Azure exposes a new SRIOV interface to the VM.",
"This interface is transparently bonded to the synthetic interface,",
"so NetworkManager should just ignore any SRIOV interfaces.",
},
},
osbuild.NewUdevRule(
[]osbuild.UdevKV{
{K: "SUBSYSTEM", O: "==", V: "net"},
{K: "DRIVERS", O: "==", V: "hv_pci"},
{K: "ACTION", O: "==", V: "add"},
{K: "ENV", A: "NM_UNMANAGED", O: "=", V: "1"},
},
),
},
},
SystemdDropin: []*osbuild.SystemdUnitStageOptions{
{
Unit: "nm-cloud-setup.service",
Dropin: "10-rh-enable-for-azure.conf",
Config: osbuild.SystemdServiceUnitDropin{
Service: &osbuild.SystemdUnitServiceSection{
Environment: []osbuild.EnvironmentVariable{{Key: "NM_CLOUD_SETUP_AZURE", Value: "yes"}},
},
},
},
},
DefaultTarget: common.ToPtr("multi-user.target"),
TimeSynchronization: &osbuild.ChronyStageOptions{
Refclocks: []osbuild.ChronyConfigRefclock{
{
Driver: osbuild.NewChronyDriverPHC("/dev/ptp_hyperv"),
Poll: common.ToPtr(3),
Dpoll: common.ToPtr(-2),
Offset: common.ToPtr(0.0),
},
},
},
Files: []*fsnode.File{datalossWarningScript},
SystemdUnit: []*osbuild.SystemdUnitCreateStageOptions{datalossSystemdUnit},
NetworkManager: &osbuild.NMConfStageOptions{
Path: "/etc/NetworkManager/conf.d/99-azure-unmanaged-devices.conf",
Settings: osbuild.NMConfStageSettings{
Keyfile: &osbuild.NMConfSettingsKeyfile{
UnmanagedDevices: []string{
"driver:mlx4_core",
"driver:mlx5_core",
},
},
},
},
}
if rd.IsRHEL() {
ic.GPGKeyFiles = append(ic.GPGKeyFiles, "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release")
}
return ic
}
func sapAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig {
return sapImageConfig(rd.OsVersion()).InheritFrom(defaultAzureImageConfig(rd))
}

View file

@ -2,9 +2,7 @@ package rhel10
import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkTarImgType() *rhel.ImageType {
@ -12,9 +10,7 @@ func mkTarImgType() *rhel.ImageType {
"tar",
"root.tar.xz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.TarImage,
[]string{"build"},
[]string{"os", "archive"},
@ -27,12 +23,7 @@ func mkImageInstallerImgType() *rhel.ImageType {
"image-installer",
"installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: func(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "bare-metal", nil)
},
rhel.InstallerPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.ImageInstallerImage,
[]string{"build"},
[]string{"anaconda-tree", "efiboot-tree", "os", "bootiso-tree", "bootiso"},

View file

@ -83,7 +83,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
QCOW2Compat: "1.1",
},
},
mkQcow2ImgType(rd),
mkQcow2ImgType(rd, arch.ARCH_X86_64),
mkOCIImgType(rd),
)
@ -95,7 +95,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
ImageFormat: platform.FORMAT_VMDK,
},
},
mkVMDKImgType(),
mkVMDKImgType(rd),
)
x86_64.AddImageTypes(
@ -106,19 +106,19 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
ImageFormat: platform.FORMAT_OVA,
},
},
mkOVAImgType(),
mkOVAImgType(rd),
)
x86_64.AddImageTypes(
&platform.X86{},
mkTarImgType(),
mkWSLImgType(),
mkWSLImgType(rd),
)
aarch64.AddImageTypes(
&platform.Aarch64{},
mkTarImgType(),
mkWSLImgType(),
mkWSLImgType(rd),
)
aarch64.AddImageTypes(
@ -129,7 +129,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
QCOW2Compat: "1.1",
},
},
mkQcow2ImgType(rd),
mkQcow2ImgType(rd, arch.ARCH_AARCH64),
)
ppc64le.AddImageTypes(
@ -140,7 +140,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
QCOW2Compat: "1.1",
},
},
mkQcow2ImgType(rd),
mkQcow2ImgType(rd, arch.ARCH_PPC64LE),
)
ppc64le.AddImageTypes(
&platform.PPC64LE{},
@ -155,7 +155,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
QCOW2Compat: "1.1",
},
},
mkQcow2ImgType(rd),
mkQcow2ImgType(rd, arch.ARCH_S390X),
)
s390x.AddImageTypes(
&platform.S390X{},
@ -171,7 +171,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
}
x86_64.AddImageTypes(
ec2X86Platform,
mkAMIImgTypeX86_64(),
mkAMIImgTypeX86_64(rd),
)
ec2Aarch64Platform := &platform.Aarch64{
@ -182,7 +182,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
}
aarch64.AddImageTypes(
ec2Aarch64Platform,
mkAMIImgTypeAarch64(),
mkAMIImgTypeAarch64(rd),
)
azureX64Platform := &platform.X86{
@ -211,7 +211,7 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
}
x86_64.AddImageTypes(
gceX86Platform,
mkGCEImageType(),
mkGCEImageType(rd, arch.ARCH_X86_64),
)
x86_64.AddImageTypes(
@ -251,8 +251,8 @@ func newDistro(name string, major, minor int) *rhel.Distribution {
x86_64.AddImageTypes(azureX64Platform, mkAzureSapInternalImgType(rd, azureX64Platform.GetArch()))
x86_64.AddImageTypes(ec2X86Platform, mkEc2ImgTypeX86_64(), mkEc2HaImgTypeX86_64(), mkEC2SapImgTypeX86_64(rd.OsVersion()))
aarch64.AddImageTypes(ec2Aarch64Platform, mkEC2ImgTypeAarch64())
x86_64.AddImageTypes(ec2X86Platform, mkEc2ImgTypeX86_64(rd), mkEc2HaImgTypeX86_64(rd), mkEC2SapImgTypeX86_64(rd))
aarch64.AddImageTypes(ec2Aarch64Platform, mkEC2ImgTypeAarch64(rd))
}
rd.AddArches(x86_64, aarch64, ppc64le, s390x)

View file

@ -1,33 +1,24 @@
package rhel10
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
)
func gceKernelOptions() []string {
return []string{"biosdevname=0", "scsi_mod.use_blk_mq=Y", "console=ttyS0,38400n8d"}
}
func mkGCEImageType() *rhel.ImageType {
func mkGCEImageType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType {
it := rhel.NewImageType(
"gce",
"image.tar.gz",
"application/gzip",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "archive"},
[]string{"archive"},
)
it.DefaultImageConfig = baseGCEImageConfig()
it.DefaultImageConfig.KernelOptions = gceKernelOptions()
it.DefaultImageConfig = imageConfig(rd, a.String(), "gce")
it.DefaultSize = 20 * datasizes.GibiByte
it.Bootable = true
// TODO: the base partition table still contains the BIOS boot partition, but the image is UEFI-only
@ -35,104 +26,3 @@ func mkGCEImageType() *rhel.ImageType {
return it
}
func baseGCEImageConfig() *distro.ImageConfig {
ic := &distro.ImageConfig{
TimeSynchronization: &osbuild.ChronyStageOptions{
Servers: []osbuild.ChronyConfigServer{{Hostname: "metadata.google.internal"}},
},
Firewall: &osbuild.FirewallStageOptions{
DefaultZone: "trusted",
},
EnabledServices: []string{
"sshd",
"rngd",
"dnf-automatic.timer",
// TODO: remove cloud-init services once we switch back to GCP guest tools
"cloud-init",
"cloud-init-local",
"cloud-config",
"cloud-final",
},
DisabledServices: []string{
"sshd-keygen@",
"reboot.target",
},
DefaultTarget: common.ToPtr("multi-user.target"),
Keyboard: &osbuild.KeymapStageOptions{
Keymap: "us",
},
DNFConfig: []*osbuild.DNFConfigStageOptions{
{
Config: &osbuild.DNFConfig{
Main: &osbuild.DNFConfigMain{
IPResolve: "4",
},
},
},
},
DNFAutomaticConfig: &osbuild.DNFAutomaticConfigStageOptions{
Config: &osbuild.DNFAutomaticConfig{
Commands: &osbuild.DNFAutomaticConfigCommands{
ApplyUpdates: common.ToPtr(true),
UpgradeType: osbuild.DNFAutomaticUpgradeTypeSecurity,
},
},
},
YUMRepos: []*osbuild.YumReposStageOptions{
{
Filename: "google-cloud.repo",
Repos: []osbuild.YumRepository{
{
Id: "google-compute-engine",
Name: "Google Compute Engine",
// TODO: use el10 repo once it's available
BaseURLs: []string{"https://packages.cloud.google.com/yum/repos/google-compute-engine-el9-x86_64-stable"},
Enabled: common.ToPtr(true),
// TODO: enable GPG check once Google stops using SHA-1 in their keys
// https://issuetracker.google.com/issues/360905189
GPGCheck: common.ToPtr(false),
RepoGPGCheck: common.ToPtr(false),
GPGKey: []string{
"https://packages.cloud.google.com/yum/doc/yum-key.gpg",
"https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg",
},
},
},
},
},
SshdConfig: &osbuild.SshdConfigStageOptions{
Config: osbuild.SshdConfigConfig{
PasswordAuthentication: common.ToPtr(false),
ClientAliveInterval: common.ToPtr(420),
PermitRootLogin: osbuild.PermitRootLoginValueNo,
},
},
UpdateDefaultKernel: common.ToPtr(true),
DefaultKernel: common.ToPtr("kernel-core"),
// XXX: ensure the "old" behavior is preserved (that is
// likely a bug) where for GCE the sysconfig network
// options are not set because the merge of imageConfig
// is shallow and the previous setup was changing the
// kernel without also changing the network options.
Sysconfig: &distro.Sysconfig{},
Modprobe: []*osbuild.ModprobeStageOptions{
{
Filename: "blacklist-floppy.conf",
Commands: osbuild.ModprobeConfigCmdList{
osbuild.NewModprobeConfigCmdBlacklist("floppy"),
},
},
},
GCPGuestAgentConfig: &osbuild.GcpGuestAgentConfigOptions{
ConfigScope: osbuild.GcpGuestAgentConfigScopeDistro,
Config: &osbuild.GcpGuestAgentConfig{
InstanceSetup: &osbuild.GcpGuestAgentConfigInstanceSetup{
SetBotoConfig: common.ToPtr(false),
},
},
},
}
return ic
}

View file

@ -3,11 +3,17 @@ package rhel10
// This file defines package sets that are used by more than one image type.
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
func packageSetLoader(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "", nil)
func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) {
return defs.PackageSets(t, nil)
}
func imageConfig(d *rhel.Distribution, archName, imageType string) *distro.ImageConfig {
return common.Must(defs.ImageConfig(d.Name(), archName, imageType, nil))
}

View file

@ -1,29 +1,24 @@
package rhel10
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
)
func mkQcow2ImgType(d *rhel.Distribution) *rhel.ImageType {
func mkQcow2ImgType(d *rhel.Distribution, a arch.Arch) *rhel.ImageType {
it := rhel.NewImageType(
"qcow2",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},
[]string{"qcow2"},
)
it.DefaultImageConfig = qcowImageConfig(d)
it.DefaultImageConfig.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check"}
it.DefaultImageConfig = imageConfig(d, a.String(), "qcow2")
it.DefaultSize = 10 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables
@ -36,41 +31,17 @@ func mkOCIImgType(d *rhel.Distribution) *rhel.ImageType {
"oci",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},
[]string{"qcow2"},
)
it.DefaultImageConfig = qcowImageConfig(d)
it.DefaultImageConfig.KernelOptions = []string{"console=tty0", "console=ttyS0,115200n8", "no_timer_check"}
it.DefaultImageConfig = imageConfig(d, "", "oci")
it.DefaultSize = 10 * datasizes.GibiByte
it.Bootable = true
it.BasePartitionTables = defaultBasePartitionTables
return it
}
func qcowImageConfig(d *rhel.Distribution) *distro.ImageConfig {
ic := &distro.ImageConfig{
DefaultTarget: common.ToPtr("multi-user.target"),
}
if d.IsRHEL() {
ic.RHSMConfig = map[subscription.RHSMStatus]*subscription.RHSMConfig{
subscription.RHSMConfigNoSubscription: {
DnfPlugins: subscription.SubManDNFPluginsConfig{
ProductID: subscription.DNFPluginConfig{
Enabled: common.ToPtr(false),
},
SubscriptionManager: subscription.DNFPluginConfig{
Enabled: common.ToPtr(false),
},
},
},
}
}
return ic
}

View file

@ -1,109 +0,0 @@
package rhel10
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/osbuild"
)
// sapImageConfig returns the SAP specific ImageConfig data
func sapImageConfig(osVersion string) *distro.ImageConfig {
return &distro.ImageConfig{
SELinuxConfig: &osbuild.SELinuxConfigStageOptions{
State: osbuild.SELinuxStatePermissive,
},
// RHBZ#1960617
Tuned: osbuild.NewTunedStageOptions("sap-hana"),
// RHBZ#1959979
Tmpfilesd: []*osbuild.TmpfilesdStageOptions{
osbuild.NewTmpfilesdStageOptions("sap.conf",
[]osbuild.TmpfilesdConfigLine{
{
Type: "x",
Path: "/tmp/.sap*",
},
{
Type: "x",
Path: "/tmp/.hdb*lock",
},
{
Type: "x",
Path: "/tmp/.trex*lock",
},
},
),
},
// RHBZ#1959963
PamLimitsConf: []*osbuild.PamLimitsConfStageOptions{
osbuild.NewPamLimitsConfStageOptions("99-sap.conf",
[]osbuild.PamLimitsConfigLine{
{
Domain: "@sapsys",
Type: osbuild.PamLimitsTypeHard,
Item: osbuild.PamLimitsItemNofile,
Value: osbuild.PamLimitsValueInt(1048576),
},
{
Domain: "@sapsys",
Type: osbuild.PamLimitsTypeSoft,
Item: osbuild.PamLimitsItemNofile,
Value: osbuild.PamLimitsValueInt(1048576),
},
{
Domain: "@dba",
Type: osbuild.PamLimitsTypeHard,
Item: osbuild.PamLimitsItemNofile,
Value: osbuild.PamLimitsValueInt(1048576),
},
{
Domain: "@dba",
Type: osbuild.PamLimitsTypeSoft,
Item: osbuild.PamLimitsItemNofile,
Value: osbuild.PamLimitsValueInt(1048576),
},
{
Domain: "@sapsys",
Type: osbuild.PamLimitsTypeHard,
Item: osbuild.PamLimitsItemNproc,
Value: osbuild.PamLimitsValueUnlimited,
},
{
Domain: "@sapsys",
Type: osbuild.PamLimitsTypeSoft,
Item: osbuild.PamLimitsItemNproc,
Value: osbuild.PamLimitsValueUnlimited,
},
{
Domain: "@dba",
Type: osbuild.PamLimitsTypeHard,
Item: osbuild.PamLimitsItemNproc,
Value: osbuild.PamLimitsValueUnlimited,
},
{
Domain: "@dba",
Type: osbuild.PamLimitsTypeSoft,
Item: osbuild.PamLimitsItemNproc,
Value: osbuild.PamLimitsValueUnlimited,
},
},
),
},
// RHBZ#1959962
Sysctld: []*osbuild.SysctldStageOptions{
osbuild.NewSysctldStageOptions("sap.conf",
[]osbuild.SysctldConfigLine{
{
Key: "kernel.pid_max",
Value: "4194304",
},
{
Key: "vm.max_map_count",
Value: "2147483647",
},
},
),
},
// E4S/EUS
DNFSetReleaseVerVar: common.ToPtr(true),
}
}

View file

@ -1,46 +1,21 @@
package rhel10
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
)
func mkWSLImgType() *rhel.ImageType {
func mkWSLImgType(rd *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"wsl",
"disk.tar.gz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.TarImage,
[]string{"build"},
[]string{"os", "archive"},
[]string{"archive"},
)
it.DefaultImageConfig = &distro.ImageConfig{
CloudInit: []*osbuild.CloudInitStageOptions{
{
Filename: "99_wsl.cfg",
Config: osbuild.CloudInitConfigFile{
DatasourceList: []string{
"WSL",
"None",
},
Network: &osbuild.CloudInitConfigNetwork{
Config: "disabled",
},
},
},
},
NoSElinux: common.ToPtr(true),
WSLConfig: &distro.WSLConfig{
BootSystemd: true,
},
}
it.DefaultImageConfig = imageConfig(rd, "", "wsl")
return it
}

View file

@ -2,31 +2,21 @@ package rhel10
import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel"
)
func vmdkKernelOptions() []string {
return []string{"ro"}
}
func mkVMDKImgType() *rhel.ImageType {
func mkVMDKImgType(d *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"vmdk",
"disk.vmdk",
"application/x-vmdk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vmdk"},
[]string{"vmdk"},
)
it.DefaultImageConfig = &distro.ImageConfig{
KernelOptions: vmdkKernelOptions(),
}
it.DefaultImageConfig = imageConfig(d, "x86_64", "vmdk")
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables
@ -34,23 +24,18 @@ func mkVMDKImgType() *rhel.ImageType {
return it
}
func mkOVAImgType() *rhel.ImageType {
func mkOVAImgType(d *rhel.Distribution) *rhel.ImageType {
it := rhel.NewImageType(
"ova",
"image.ova",
"application/ovf",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vmdk", "ovf", "archive"},
[]string{"archive"},
)
it.DefaultImageConfig = &distro.ImageConfig{
KernelOptions: vmdkKernelOptions(),
}
it.DefaultImageConfig = imageConfig(d, "x86_64", "ova")
it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte
it.BasePartitionTables = defaultBasePartitionTables

View file

@ -18,9 +18,7 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},

View file

@ -16,9 +16,7 @@ func mkAzureRhuiImgType() *rhel.ImageType {
"azure-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},

View file

@ -6,6 +6,6 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
func packageSetLoader(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "", nil)
func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) {
return defs.PackageSets(t, nil)
}

View file

@ -14,9 +14,7 @@ func mkQcow2ImgType() *rhel.ImageType {
"qcow2",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},

View file

@ -26,9 +26,7 @@ func mkAmiImgTypeX86_64() *rhel.ImageType {
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image"},
@ -49,9 +47,7 @@ func mkEc2ImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -73,9 +69,7 @@ func mkEc2HaImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
"ec2-ha",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -97,9 +91,7 @@ func mkAmiImgTypeAarch64() *rhel.ImageType {
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image"},
@ -120,9 +112,7 @@ func mkEc2ImgTypeAarch64(rd *rhel.Distribution) *rhel.ImageType {
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -144,9 +134,7 @@ func mkEc2SapImgTypeX86_64(rd *rhel.Distribution) *rhel.ImageType {
"ec2-sap",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},

View file

@ -22,9 +22,7 @@ func mkAzureRhuiImgType() *rhel.ImageType {
"azure-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},
@ -46,9 +44,7 @@ func mkAzureSapRhuiImgType(rd *rhel.Distribution) *rhel.ImageType {
"azure-sap-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},
@ -70,9 +66,7 @@ func mkAzureByosImgType() *rhel.ImageType {
"vhd",
"disk.vhd",
"application/x-vhd",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc"},
@ -94,9 +88,7 @@ func mkAzureImgType() *rhel.ImageType {
"vhd",
"disk.vhd",
"application/x-vhd",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc"},
@ -117,9 +109,7 @@ func mkAzureEap7RhuiImgType() *rhel.ImageType {
"azure-eap7-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},

View file

@ -2,9 +2,7 @@ package rhel8
import (
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkImageInstaller() *rhel.ImageType {
@ -12,12 +10,7 @@ func mkImageInstaller() *rhel.ImageType {
"image-installer",
"installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: func(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "bare-metal", nil)
},
rhel.InstallerPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.ImageInstallerImage,
[]string{"build"},
[]string{"anaconda-tree", "rootfs-image", "efiboot-tree", "os", "bootiso-tree", "bootiso"},
@ -42,9 +35,7 @@ func mkTarImgType() *rhel.ImageType {
"tar",
"root.tar.xz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.TarImage,
[]string{"build"},
[]string{"os", "archive"},

View file

@ -6,10 +6,8 @@ import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkEdgeCommitImgType(rd *rhel.Distribution) *rhel.ImageType {
@ -17,9 +15,7 @@ func mkEdgeCommitImgType(rd *rhel.Distribution) *rhel.ImageType {
"edge-commit",
"commit.tar",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.EdgeCommitImage,
[]string{"build"},
[]string{"os", "ostree-commit", "commit-archive"},
@ -41,12 +37,7 @@ func mkEdgeOCIImgType(rd *rhel.Distribution) *rhel.ImageType {
"edge-container",
"container.tar",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
rhel.ContainerPkgsKey: func(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "edge_container_pipeline_pkgset", nil)
},
},
packageSetLoader,
rhel.EdgeContainerImage,
[]string{"build"},
[]string{"os", "ostree-commit", "container-tree", "container"},
@ -102,9 +93,7 @@ func mkEdgeInstallerImgType(rd *rhel.Distribution) *rhel.ImageType {
"edge-installer",
"installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.InstallerPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.EdgeInstallerImage,
[]string{"build"},
[]string{"anaconda-tree", "rootfs-image", "efiboot-tree", "bootiso-tree", "bootiso"},
@ -132,9 +121,7 @@ func mkEdgeSimplifiedInstallerImgType(rd *rhel.Distribution) *rhel.ImageType {
"edge-simplified-installer",
"simplified-installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.InstallerPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.EdgeSimplifiedInstallerImage,
[]string{"build"},
[]string{"ostree-deployment", "image", "xz", "coi-tree", "efiboot-tree", "bootiso-tree", "bootiso"},
@ -176,9 +163,7 @@ func mkMinimalRawImgType() *rhel.ImageType {
"minimal-raw",
"disk.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},

View file

@ -14,9 +14,7 @@ func mkGceImgType(rd distro.Distro) *rhel.ImageType {
"gce",
"image.tar.gz",
"application/gzip",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "archive"},
@ -37,9 +35,7 @@ func mkGceRhuiImgType(rd distro.Distro) *rhel.ImageType {
"gce-rhui",
"image.tar.gz",
"application/gzip",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "archive"},

View file

@ -87,17 +87,6 @@ func checkOptions(t *rhel.ImageType, bp *blueprint.Blueprint, options distro.Ima
// TODO: consider additional checks, such as those in "edge-simplified-installer"
}
// warn that user & group customizations on edge-commit, edge-container are deprecated
// TODO(edge): directly error if these options are provided when rhel-9.5's time arrives
if t.Name() == "edge-commit" || t.Name() == "edge-container" {
if customizations.GetUsers() != nil {
warnings = append(warnings, fmt.Sprintf("Please note that user customizations on %q image type are deprecated and will be removed in the near future\n", t.Name()))
}
if customizations.GetGroups() != nil {
warnings = append(warnings, fmt.Sprintf("Please note that group customizations on %q image type are deprecated and will be removed in the near future\n", t.Name()))
}
}
if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.RPMOSTree && t.Name() != "edge-raw-image" && t.Name() != "edge-simplified-installer" {
return warnings, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
}

View file

@ -8,6 +8,6 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
func packageSetLoader(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "", nil)
func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) {
return defs.PackageSets(t, nil)
}

View file

@ -13,9 +13,7 @@ func mkQcow2ImgType(rd *rhel.Distribution) *rhel.ImageType {
"qcow2",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},
@ -35,9 +33,7 @@ func mkOCIImgType(rd *rhel.Distribution) *rhel.ImageType {
"oci",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},
@ -57,9 +53,7 @@ func mkOpenstackImgType() *rhel.ImageType {
"openstack",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},

View file

@ -11,9 +11,7 @@ func mkWslImgType() *rhel.ImageType {
"wsl",
"disk.tar.gz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.TarImage,
[]string{"build"},
[]string{"os", "archive"},

View file

@ -15,9 +15,7 @@ func mkVmdkImgType() *rhel.ImageType {
"vmdk",
"disk.vmdk",
"application/x-vmdk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vmdk"},
@ -38,9 +36,7 @@ func mkOvaImgType() *rhel.ImageType {
"ova",
"image.ova",
"application/ovf",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vmdk", "ovf", "archive"},

View file

@ -151,9 +151,7 @@ func mkEc2ImgTypeX86_64() *rhel.ImageType {
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -175,9 +173,7 @@ func mkAMIImgTypeX86_64() *rhel.ImageType {
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image"},
@ -198,9 +194,7 @@ func mkEC2SapImgTypeX86_64(osVersion string) *rhel.ImageType {
"ec2-sap",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -222,9 +216,7 @@ func mkEc2HaImgTypeX86_64() *rhel.ImageType {
"ec2-ha",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -246,9 +238,7 @@ func mkAMIImgTypeAarch64() *rhel.ImageType {
"ami",
"image.raw",
"application/octet-stream",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image"},
@ -269,9 +259,7 @@ func mkEC2ImgTypeAarch64() *rhel.ImageType {
"ec2",
"image.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},

View file

@ -16,9 +16,7 @@ func mkAzureImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType {
"vhd",
"disk.vhd",
"application/x-vhd",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc"},
@ -40,9 +38,7 @@ func mkAzureInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageType
"azure-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},
@ -64,9 +60,7 @@ func mkAzureSapInternalImgType(rd *rhel.Distribution, a arch.Arch) *rhel.ImageTy
"azure-sap-rhui",
"disk.vhd.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vpc", "xz"},

View file

@ -3,9 +3,7 @@ package rhel9
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkTarImgType() *rhel.ImageType {
@ -13,9 +11,7 @@ func mkTarImgType() *rhel.ImageType {
"tar",
"root.tar.xz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.TarImage,
[]string{"build"},
[]string{"os", "archive"},
@ -28,12 +24,7 @@ func mkImageInstallerImgType() *rhel.ImageType {
"image-installer",
"installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: func(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "bare-metal", nil)
},
rhel.InstallerPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.ImageInstallerImage,
[]string{"build"},
[]string{"anaconda-tree", "rootfs-image", "efiboot-tree", "os", "bootiso-tree", "bootiso"},

View file

@ -8,10 +8,8 @@ import (
"github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
)
func mkEdgeCommitImgType(d *rhel.Distribution) *rhel.ImageType {
@ -19,9 +17,7 @@ func mkEdgeCommitImgType(d *rhel.Distribution) *rhel.ImageType {
"edge-commit",
"commit.tar",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.EdgeCommitImage,
[]string{"build"},
[]string{"os", "ostree-commit", "commit-archive"},
@ -51,12 +47,7 @@ func mkEdgeOCIImgType(d *rhel.Distribution) *rhel.ImageType {
"edge-container",
"container.tar",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
rhel.ContainerPkgsKey: func(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "edge_container_pipeline_pkgset", nil)
},
},
packageSetLoader,
rhel.EdgeContainerImage,
[]string{"build"},
[]string{"os", "ostree-commit", "container-tree", "container"},
@ -126,9 +117,7 @@ func mkEdgeInstallerImgType() *rhel.ImageType {
"edge-installer",
"installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
rhel.InstallerPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.EdgeInstallerImage,
[]string{"build"},
[]string{"anaconda-tree", "rootfs-image", "efiboot-tree", "bootiso-tree", "bootiso"},
@ -163,16 +152,14 @@ func mkEdgeSimplifiedInstallerImgType(d *rhel.Distribution) *rhel.ImageType {
"edge-simplified-installer",
"simplified-installer.iso",
"application/x-iso9660-image",
map[string]rhel.PackageSetFunc{
// TODO: non-arch-specific package set handling for installers
// This image type requires build packages for installers and
// ostree/edge. For now we only have x86-64 installer build
// package sets defined. When we add installer build package sets
// for other architectures, this will need to be moved to the
// architecture and the merging will happen in the PackageSets()
// method like the other sets.
rhel.InstallerPkgsKey: packageSetLoader,
},
// TODO: non-arch-specific package set handling for installers
// This image type requires build packages for installers and
// ostree/edge. For now we only have x86-64 installer build
// package sets defined. When we add installer build package sets
// for other architectures, this will need to be moved to the
// architecture and the merging will happen in the PackageSets()
// method like the other sets.
packageSetLoader,
rhel.EdgeSimplifiedInstallerImage,
[]string{"build"},
[]string{"ostree-deployment", "image", "xz", "coi-tree", "efiboot-tree", "bootiso-tree", "bootiso"},
@ -298,9 +285,7 @@ func mkMinimalrawImgType() *rhel.ImageType {
"minimal-raw",
"disk.raw.xz",
"application/xz",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "xz"},
@ -380,7 +365,7 @@ func minimalrawPartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Type: "vfat",
UUID: disk.EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
Label: "ESP",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
@ -428,7 +413,7 @@ func minimalrawPartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Type: "vfat",
UUID: disk.EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
Label: "ESP",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
@ -488,7 +473,7 @@ func edgeBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Type: "vfat",
UUID: disk.EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
Label: "ESP",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
@ -559,7 +544,7 @@ func edgeBasePartitionTables(t *rhel.ImageType) (disk.PartitionTable, bool) {
Type: "vfat",
UUID: disk.EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
Label: "ESP",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,

View file

@ -17,9 +17,7 @@ func mkGCEImageType() *rhel.ImageType {
"gce",
"image.tar.gz",
"application/gzip",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "archive"},

View file

@ -99,17 +99,6 @@ func checkOptions(t *rhel.ImageType, bp *blueprint.Blueprint, options distro.Ima
// TODO: consider additional checks, such as those in "edge-simplified-installer"
}
// warn that user & group customizations on edge-commit, edge-container are deprecated
// TODO(edge): directly error if these options are provided when rhel-9.5's time arrives
if t.Name() == "edge-commit" || t.Name() == "edge-container" {
if customizations.GetUsers() != nil {
warnings = append(warnings, fmt.Sprintf("Please note that user customizations on %q image type are deprecated and will be removed in the near future\n", t.Name()))
}
if customizations.GetGroups() != nil {
warnings = append(warnings, fmt.Sprintf("Please note that group customizations on %q image type are deprecated and will be removed in the near future\n", t.Name()))
}
}
if kernelOpts := customizations.GetKernel(); kernelOpts.Append != "" && t.RPMOSTree && t.Name() != "edge-raw-image" && t.Name() != "edge-simplified-installer" {
return warnings, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
}

View file

@ -6,6 +6,6 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
func packageSetLoader(t *rhel.ImageType) (rpmmd.PackageSet, error) {
return defs.PackageSet(t, "", nil)
func packageSetLoader(t *rhel.ImageType) (map[string]rpmmd.PackageSet, error) {
return defs.PackageSets(t, nil)
}

View file

@ -13,9 +13,7 @@ func mkQcow2ImgType(d *rhel.Distribution) *rhel.ImageType {
"qcow2",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},
@ -36,9 +34,7 @@ func mkOCIImgType(d *rhel.Distribution) *rhel.ImageType {
"oci",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},
@ -59,9 +55,7 @@ func mkOpenstackImgType() *rhel.ImageType {
"openstack",
"disk.qcow2",
"application/x-qemu-disk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "qcow2"},

View file

@ -12,9 +12,7 @@ func mkWSLImgType() *rhel.ImageType {
"wsl",
"disk.tar.gz",
"application/x-tar",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.TarImage,
[]string{"build"},
[]string{"os", "archive"},

View file

@ -16,9 +16,7 @@ func mkVMDKImgType() *rhel.ImageType {
"vmdk",
"disk.vmdk",
"application/x-vmdk",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vmdk"},
@ -41,9 +39,7 @@ func mkOVAImgType() *rhel.ImageType {
"ova",
"image.ova",
"application/ovf",
map[string]rhel.PackageSetFunc{
rhel.OSPkgsKey: packageSetLoader,
},
packageSetLoader,
rhel.DiskImage,
[]string{"build"},
[]string{"os", "image", "vmdk", "ovf", "archive"},

View file

@ -22,7 +22,8 @@ type BootcDiskImage struct {
Filename string
ContainerSource *container.SourceSpec
ContainerSource *container.SourceSpec
BuildContainerSource *container.SourceSpec
// Customizations
KernelOptionsAppend []string
@ -38,13 +39,15 @@ type BootcDiskImage struct {
// SELinux policy, when set it enables the labeling of the tree with the
// selected profile
SELinux string
SELinux string
BuildSELinux string
}
func NewBootcDiskImage(container container.SourceSpec) *BootcDiskImage {
func NewBootcDiskImage(container container.SourceSpec, buildContainer container.SourceSpec) *BootcDiskImage {
return &BootcDiskImage{
Base: NewBase("bootc-raw-image"),
ContainerSource: &container,
Base: NewBase("bootc-raw-image"),
ContainerSource: &container,
BuildContainerSource: &buildContainer,
}
}
@ -53,7 +56,16 @@ func (img *BootcDiskImage) InstantiateManifestFromContainers(m *manifest.Manifes
runner runner.Runner,
rng *rand.Rand) error {
buildPipeline := manifest.NewBuildFromContainer(m, runner, containers, &manifest.BuildOptions{ContainerBuildable: true})
policy := img.SELinux
if img.BuildSELinux != "" {
policy = img.BuildSELinux
}
buildContainers := []container.SourceSpec{*img.BuildContainerSource}
buildPipeline := manifest.NewBuildFromContainer(m, runner, buildContainers,
&manifest.BuildOptions{
ContainerBuildable: true,
SELinuxPolicy: policy,
})
buildPipeline.Checkpoint()
// In the bootc flow, we reuse the host container context for tools;

View file

@ -1,6 +1,7 @@
package manifest
import (
"encoding/json"
"fmt"
"path"
"path/filepath"
@ -25,6 +26,29 @@ const ( // Rootfs type enum
ErofsRootfs // Create a plain erofs rootfs
)
func (r *RootfsType) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
switch s {
case "squashfs-ext4", "":
*r = SquashfsExt4Rootfs
case "squashfs":
*r = SquashfsRootfs
case "erofs":
*r = ErofsRootfs
default:
return fmt.Errorf("unknown RootfsType: %q", s)
}
return nil
}
func (r *RootfsType) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(r, unmarshal)
}
type ISOBootType uint64
// These constants are used by the ISO images to control the type of bootable iso

View file

@ -43,6 +43,8 @@ type BuildrootFromPackages struct {
// buildroot itself when running setfiles. Once osbuild has
// this then this option would become "useChrootSetfiles"
disableSelinux bool
selinuxPolicy string
}
type BuildOptions struct {
@ -54,12 +56,24 @@ type BuildOptions struct {
// currently needed when using (experimental) cross-arch building.
DisableSELinux bool
// The SELinux policy to use in the buildroot, defaults to 'targeted' if not specified
SELinuxPolicy string
// BootstrapPipeline add the given bootstrap pipeline to the
// build pipeline. This is only needed when doing cross-arch
// building
BootstrapPipeline Build
}
// policy or default returns the selinuxPolicy or (if unset) the
// default policy
func policyOrDefault(selinuxPolicy string) string {
if selinuxPolicy != "" {
return selinuxPolicy
}
return "targeted"
}
// NewBuild creates a new build pipeline from the repositories in repos
// and the specified packages.
func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig, opts *BuildOptions) Build {
@ -75,6 +89,7 @@ func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig, opts
repos: filterRepos(repos, name),
containerBuildable: opts.ContainerBuildable,
disableSelinux: opts.DisableSELinux,
selinuxPolicy: policyOrDefault(opts.SELinuxPolicy),
}
m.addPipeline(pipeline)
@ -93,10 +108,11 @@ func (p *BuildrootFromPackages) addDependent(dep Pipeline) {
func (p *BuildrootFromPackages) getPackageSetChain(distro Distro) []rpmmd.PackageSet {
// TODO: make the /usr/bin/cp dependency conditional
// TODO: make the /usr/bin/xz dependency conditional
policyPackage := fmt.Sprintf("selinux-policy-%s", p.selinuxPolicy)
packages := []string{
"selinux-policy-targeted", // needed to build the build pipeline
"coreutils", // /usr/bin/cp - used all over
"xz", // usage unclear
policyPackage, // needed to build the build pipeline
"coreutils", // /usr/bin/cp - used all over
"xz", // usage unclear
}
packages = append(packages, p.runner.GetBuildPackages()...)
@ -143,7 +159,7 @@ func (p *BuildrootFromPackages) serialize() osbuild.Pipeline {
pipeline.AddStage(osbuild.NewRPMStage(osbuild.NewRPMStageOptions(p.repos), osbuild.NewRpmStageSourceFilesInputs(p.packageSpecs)))
if !p.disableSelinux {
pipeline.AddStage(osbuild.NewSELinuxStage(&osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
FileContexts: fmt.Sprintf("etc/selinux/%s/contexts/files/file_contexts", p.selinuxPolicy),
Labels: p.getSELinuxLabels(),
},
))
@ -182,6 +198,7 @@ type BuildrootFromContainer struct {
containerBuildable bool
disableSelinux bool
selinuxPolicy string
}
// NewBuildFromContainer creates a new build pipeline from the given
@ -200,6 +217,7 @@ func NewBuildFromContainer(m *Manifest, runner runner.Runner, containerSources [
containerBuildable: opts.ContainerBuildable,
disableSelinux: opts.DisableSELinux,
selinuxPolicy: policyOrDefault(opts.SELinuxPolicy),
}
m.addPipeline(pipeline)
return pipeline
@ -273,7 +291,7 @@ func (p *BuildrootFromContainer) serialize() osbuild.Pipeline {
if !p.disableSelinux {
pipeline.AddStage(osbuild.NewSELinuxStage(
&osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
FileContexts: fmt.Sprintf("etc/selinux/%s/contexts/files/file_contexts", p.selinuxPolicy),
ExcludePaths: []string{"/sysroot"},
Labels: p.getSELinuxLabels(),
},

View file

@ -740,7 +740,12 @@ func (p *OS) serialize() osbuild.Pipeline {
p.platform.GetUEFIVendor() != "",
p.platform.GetBIOSPlatform(),
p.platform.GetUEFIVendor(), false)
if cfg := p.OSCustomizations.Grub2Config; cfg != nil {
// Avoid a race condition because Grub2Config may be shared when set (yay pointers!)
if p.OSCustomizations.Grub2Config != nil {
// Make a COPY of it
cfg := *p.OSCustomizations.Grub2Config
// TODO: don't store Grub2Config in OSPipeline, making the overrides unnecessary
// grub2.Config.Default is owned and set by `NewGrub2StageOptionsUnified`
// and thus we need to preserve it
@ -748,7 +753,8 @@ func (p *OS) serialize() osbuild.Pipeline {
cfg.Default = options.Config.Default
}
options.Config = cfg
// Point to the COPY with the possibly new Default value
options.Config = &cfg
}
if p.OSCustomizations.KernelOptionsBootloader {
options.WriteCmdLine = nil

View file

@ -1,8 +1,11 @@
package osbuild
import (
"encoding/json"
"fmt"
"regexp"
"github.com/osbuild/images/internal/common"
)
const (
@ -66,6 +69,65 @@ type ChronyConfigRefclock struct {
Offset *float64 `json:"offset,omitempty"`
}
type chronyConfigRefclockData struct {
Driver *json.RawMessage
Poll *int `json:"poll,omitempty"`
Dpoll *int `json:"dpoll,omitempty"`
Offset *float64 `json:"offset,omitempty"`
}
func (c *ChronyConfigRefclock) UnmarshalJSON(data []byte) (err error) {
var d chronyConfigRefclockData
if err := json.Unmarshal(data, &d); err != nil {
return err
}
c.Poll = d.Poll
c.Dpoll = d.Dpoll
c.Offset = d.Offset
var peek struct {
Name string
}
if err := json.Unmarshal(*d.Driver, &peek); err != nil {
return err
}
switch peek.Name {
case "PPS":
var drv ChronyDriverPPS
if err := json.Unmarshal(*d.Driver, &drv); err != nil {
return err
}
c.Driver = &drv
case "SHM":
var drv ChronyDriverSHM
if err := json.Unmarshal(*d.Driver, &drv); err != nil {
return err
}
c.Driver = &drv
case "SOCK":
var drv ChronyDriverSOCK
if err := json.Unmarshal(*d.Driver, &drv); err != nil {
return err
}
c.Driver = &drv
case "PHC":
var drv ChronyDriverPHC
if err := json.Unmarshal(*d.Driver, &drv); err != nil {
return err
}
c.Driver = &drv
default:
return fmt.Errorf("unsupported reflock name: %q", peek.Name)
}
return c.validate()
}
func (c *ChronyConfigRefclock) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(c, unmarshal)
}
func (o ChronyConfigRefclock) validate() error {
return o.Driver.validate()
}

View file

@ -25,17 +25,17 @@ func NewCloudInitStage(options *CloudInitStageOptions) *Stage {
// Represents a cloud-init configuration file
type CloudInitConfigFile struct {
SystemInfo *CloudInitConfigSystemInfo `json:"system_info,omitempty"`
SystemInfo *CloudInitConfigSystemInfo `json:"system_info,omitempty" yaml:"system_info,omitempty"`
Reporting *CloudInitConfigReporting `json:"reporting,omitempty"`
Datasource *CloudInitConfigDatasource `json:"datasource,omitempty"`
DatasourceList []string `json:"datasource_list,omitempty"`
DatasourceList []string `json:"datasource_list,omitempty" yaml:"datasource_list,omitempty"`
Output *CloudInitConfigOutput `json:"output,omitempty"`
Network *CloudInitConfigNetwork `json:"network,omitempty"`
}
// Represents the 'system_info' configuration section
type CloudInitConfigSystemInfo struct {
DefaultUser *CloudInitConfigDefaultUser `json:"default_user,omitempty"`
DefaultUser *CloudInitConfigDefaultUser `json:"default_user,omitempty" yaml:"default_user,omitempty"`
}
// Represents the 'reporting' configuration section
@ -54,7 +54,7 @@ type CloudInitConfigDatasource struct {
}
type CloudInitConfigDatasourceAzure struct {
ApplyNetworkConfig bool `json:"apply_network_config"`
ApplyNetworkConfig bool `json:"apply_network_config" yaml:"apply_network_config"`
}
// Represents the 'output' configuration section

View file

@ -19,6 +19,7 @@ func sfdiskStageOptions(pt *disk.PartitionTable) *SfdiskStageOptions {
Size: pt.BytesToSectors(p.Size),
Type: p.Type,
UUID: p.UUID,
Name: p.Label,
}
}
stageOptions := &SfdiskStageOptions{
@ -40,6 +41,7 @@ func sgdiskStageOptions(pt *disk.PartitionTable) *SgdiskStageOptions {
Start: pt.BytesToSectors(p.Start),
Size: pt.BytesToSectors(p.Size),
Type: p.Type,
Name: p.Label,
}
if p.UUID != "" {

View file

@ -13,9 +13,9 @@ const (
// DNFAutomaticConfigCommands represents the 'commands' configuration section.
type DNFAutomaticConfigCommands struct {
// Whether packages comprising the available updates should be installed
ApplyUpdates *bool `json:"apply_updates,omitempty"`
ApplyUpdates *bool `json:"apply_updates,omitempty" yaml:"apply_updates,omitempty"`
// What kind of upgrades to look at
UpgradeType DNFAutomaticUpgradeTypeValue `json:"upgrade_type,omitempty"`
UpgradeType DNFAutomaticUpgradeTypeValue `json:"upgrade_type,omitempty" yaml:"upgrade_type,omitempty"`
}
// DNFAutomaticConfig represents DNF Automatic configuration.

View file

@ -28,7 +28,7 @@ type DracutConfigFile struct {
Modules []string `json:"dracutmodules,omitempty"`
// Additional dracut modules to include
AddModules []string `json:"add_dracutmodules,omitempty"`
AddModules []string `json:"add_dracutmodules,omitempty" yaml:"add_dracutmodules,omitempty"`
// Dracut modules to not include
OmitModules []string `json:"omit_dracutmodules,omitempty"`
@ -37,7 +37,7 @@ type DracutConfigFile struct {
Drivers []string `json:"drivers,omitempty"`
// Add a specific kernel module
AddDrivers []string `json:"add_drivers,omitempty"`
AddDrivers []string `json:"add_drivers,omitempty" yaml:"add_drivers,omitempty"`
// Add driver and ensure that they are tried to be loaded
ForceDrivers []string `json:"force_drivers,omitempty"`

View file

@ -20,7 +20,7 @@ type DracutStageOptions struct {
Drivers []string `json:"drivers,omitempty"`
// Add a specific kernel module
AddDrivers []string `json:"add_drivers,omitempty"`
AddDrivers []string `json:"add_drivers,omitempty" yaml:"add_drivers,omitempty"`
// Add driver and ensure that they are tried to be loaded
ForceDrivers []string `json:"force_drivers,omitempty"`

View file

@ -6,7 +6,7 @@ type FirewallStageOptions struct {
Ports []string `json:"ports,omitempty"`
EnabledServices []string `json:"enabled_services,omitempty"`
DisabledServices []string `json:"disabled_services,omitempty"`
DefaultZone string `json:"default_zone,omitempty"`
DefaultZone string `json:"default_zone,omitempty" yaml:"default_zone,omitempty"`
Zones []FirewallZone `json:"zones,omitempty"`
}

View file

@ -32,7 +32,7 @@ type GcpGuestAgentConfigInstanceSetup struct {
HostKeyTypes []string `json:"host_key_types,omitempty"`
OptimizeLocalSsd *bool `json:"optimize_local_ssd,omitempty"`
NetworkEnabled *bool `json:"network_enabled,omitempty"`
SetBotoConfig *bool `json:"set_boto_config,omitempty"`
SetBotoConfig *bool `json:"set_boto_config,omitempty" yaml:"set_boto_config,omitempty"`
SetHostKeys *bool `json:"set_host_keys,omitempty"`
SetMultiqueue *bool `json:"set_multiqueue,omitempty"`
}
@ -59,14 +59,14 @@ type GcpGuestAgentConfigNetworkInterfaces struct {
type GcpGuestAgentConfig struct {
Accounts *GcpGuestAgentConfigAccounts `json:"Accounts,omitempty"`
Daemons *GcpGuestAgentConfigDaemons `json:"Daemons,omitempty"`
InstanceSetup *GcpGuestAgentConfigInstanceSetup `json:"InstanceSetup,omitempty"`
InstanceSetup *GcpGuestAgentConfigInstanceSetup `json:"InstanceSetup,omitempty" yaml:"InstanceSetup,omitempty"`
IpForwarding *GcpGuestAgentConfigIpForwarding `json:"IpForwarding,omitempty"`
MetadataScripts *GcpGuestAgentConfigMetadataScripts `json:"MetadataScripts,omitempty"`
NetworkInterfaces *GcpGuestAgentConfigNetworkInterfaces `json:"NetworkInterfaces,omitempty"`
}
type GcpGuestAgentConfigOptions struct {
ConfigScope GcpGuestAgentConfigScopeValue `json:"config_scope,omitempty"`
ConfigScope GcpGuestAgentConfigScopeValue `json:"config_scope,omitempty" yaml:"config_scope,omitempty"`
Config *GcpGuestAgentConfig `json:"config"`
}

View file

@ -44,14 +44,14 @@ const (
type GRUB2Config struct {
Default string `json:"default,omitempty"`
DisableRecovery *bool `json:"disable_recovery,omitempty"`
DisableSubmenu *bool `json:"disable_submenu,omitempty"`
DisableRecovery *bool `json:"disable_recovery,omitempty" yaml:"disable_recovery,omitempty"`
DisableSubmenu *bool `json:"disable_submenu,omitempty" yaml:"disable_submenu,omitempty"`
Distributor string `json:"distributor,omitempty"`
Terminal []string `json:"terminal,omitempty"`
TerminalInput []string `json:"terminal_input,omitempty"`
TerminalOutput []string `json:"terminal_output,omitempty"`
Timeout int `json:"timeout,omitempty"`
TimeoutStyle GRUB2ConfigTimeoutStyle `json:"timeout_style,omitempty"`
TimeoutStyle GRUB2ConfigTimeoutStyle `json:"timeout_style,omitempty" yaml:"timeout_style,omitempty"`
Serial string `json:"serial,omitempty"`
}

View file

@ -7,7 +7,7 @@ import (
type KeymapStageOptions struct {
Keymap string `json:"keymap"`
X11Keymap *X11KeymapOptions `json:"x11-keymap,omitempty"`
X11Keymap *X11KeymapOptions `json:"x11-keymap,omitempty" yaml:"x11-keymap,omitempty"`
}
func (KeymapStageOptions) isStageOptions() {}

View file

@ -1,8 +1,9 @@
package osbuild
type MkfsExt4StageOptions struct {
UUID string `json:"uuid"`
Label string `json:"label,omitempty"`
UUID string `json:"uuid"`
Label string `json:"label,omitempty"`
Verity *bool `json:"verity,omitempty"`
}
func (MkfsExt4StageOptions) isStageOptions() {}

View file

@ -2,8 +2,10 @@ package osbuild
import (
"fmt"
"slices"
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/disk"
)
@ -38,6 +40,7 @@ func GenFsStages(pt *disk.PartitionTable, filename string) []*Stage {
case "vfat":
options := &MkfsFATStageOptions{
VolID: strings.Replace(e.UUID, "-", "", -1),
Label: e.Label,
}
stages = append(stages, NewMkfsFATStage(options, stageDevices))
case "ext4":
@ -45,6 +48,10 @@ func GenFsStages(pt *disk.PartitionTable, filename string) []*Stage {
UUID: e.UUID,
Label: e.Label,
}
if slices.Contains(e.MkfsOptions, disk.MkfsVerity) {
options.Verity = common.ToPtr(true)
}
stages = append(stages, NewMkfsExt4Stage(options, stageDevices))
default:
panic(fmt.Sprintf("unknown fs type: %s", e.GetFSType()))

View file

@ -38,7 +38,7 @@ type NMConfSettingsGlobalDNSDomainConfig struct {
}
type NMConfSettingsKeyfile struct {
UnmanagedDevices []string `json:"unmanaged-devices,omitempty"`
UnmanagedDevices []string `json:"unmanaged-devices,omitempty" yaml:"unmanaged-devices,omitempty"`
}
type NMConfDeviceConfig struct {

View file

@ -3,6 +3,8 @@ package osbuild
import (
"encoding/json"
"fmt"
"github.com/osbuild/images/internal/common"
)
// PamLimitsConfStageOptions represents a single pam_limits module configuration file.
@ -152,3 +154,7 @@ func (l *PamLimitsConfigLine) UnmarshalJSON(data []byte) error {
return nil
}
func (l *PamLimitsConfigLine) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(l, unmarshal)
}

View file

@ -8,10 +8,10 @@ import (
)
type SshdConfigConfig struct {
PasswordAuthentication *bool `json:"PasswordAuthentication,omitempty"`
ChallengeResponseAuthentication *bool `json:"ChallengeResponseAuthentication,omitempty"`
ClientAliveInterval *int `json:"ClientAliveInterval,omitempty"`
PermitRootLogin PermitRootLoginValue `json:"PermitRootLogin,omitempty"`
PasswordAuthentication *bool `json:"PasswordAuthentication,omitempty" yaml:"PasswordAuthentication,omitempty"`
ChallengeResponseAuthentication *bool `json:"ChallengeResponseAuthentication,omitempty" yaml:"ChallengeResponseAuthentication,omitempty"`
ClientAliveInterval *int `json:"ClientAliveInterval,omitempty" yaml:"ClientAliveInterval,omitempty"`
PermitRootLogin PermitRootLoginValue `json:"PermitRootLogin,omitempty" yaml:"PermitRootLogin,omitempty"`
}
// PermitRootLoginValue is defined to represent all valid types of the
@ -45,10 +45,10 @@ const (
// Unexported struct used for Unmarshalling of SshdConfigConfig due to
// 'PermitRootLogin' being a boolean or a string.
type rawSshdConfigConfig struct {
PasswordAuthentication *bool `json:"PasswordAuthentication,omitempty"`
ChallengeResponseAuthentication *bool `json:"ChallengeResponseAuthentication,omitempty"`
ClientAliveInterval *int `json:"ClientAliveInterval,omitempty"`
PermitRootLogin interface{} `json:"PermitRootLogin,omitempty"`
PasswordAuthentication *bool `json:"PasswordAuthentication,omitempty" yaml:"PasswordAuthentication,omitempty"`
ChallengeResponseAuthentication *bool `json:"ChallengeResponseAuthentication,omitempty" yaml:"ChallengeResponseAuthentication,omitempty"`
ClientAliveInterval *int `json:"ClientAliveInterval,omitempty" yaml:"ClientAliveInterval,omitempty"`
PermitRootLogin interface{} `json:"PermitRootLogin,omitempty" yaml:"PermitRootLogin,omitempty"`
}
func (c *SshdConfigConfig) UnmarshalJSON(data []byte) error {
@ -82,7 +82,7 @@ func (c *SshdConfigConfig) UnmarshalYAML(unmarshal func(any) error) error {
}
type SshdConfigStageOptions struct {
Config SshdConfigConfig `json:"config"`
Config SshdConfigConfig `json:"config" yaml:"config"`
}
func (SshdConfigStageOptions) isStageOptions() {}

View file

@ -5,7 +5,7 @@ type SysconfigStageOptions struct {
Network *SysconfigNetworkOptions `json:"network,omitempty" yaml:"network,omitempty"`
NetworkScripts *NetworkScriptsOptions `json:"network-scripts,omitempty" yaml:"network-scripts,omitempty"`
Desktop *SysconfigDesktopOptions `json:"desktop,omitempty" yaml:"desktop,omitempty"`
LiveSys *SysconfigLivesysOptions `json:"livesys,omitempty" yaml:"libesys,omitempty"`
LiveSys *SysconfigLivesysOptions `json:"livesys,omitempty" yaml:"livesys,omitempty"`
}
func (SysconfigStageOptions) isStageOptions() {}

View file

@ -41,75 +41,75 @@ const (
)
type UnitSection struct {
Description string `json:"Description,omitempty"`
DefaultDependencies *bool `json:"DefaultDependencies,omitempty"`
ConditionPathExists []string `json:"ConditionPathExists,omitempty"`
ConditionPathIsDirectory []string `json:"ConditionPathIsDirectory,omitempty"`
Requires []string `json:"Requires,omitempty"`
Wants []string `json:"Wants,omitempty"`
After []string `json:"After,omitempty"`
Before []string `json:"Before,omitempty"`
Description string `json:"Description,omitempty" yaml:"Description,omitempty"`
DefaultDependencies *bool `json:"DefaultDependencies,omitempty" yaml:"DefaultDependencies,omitempty"`
ConditionPathExists []string `json:"ConditionPathExists,omitempty" yaml:"ConditionPathExists,omitempty"`
ConditionPathIsDirectory []string `json:"ConditionPathIsDirectory,omitempty" yaml:"ConditionPathIsDirectory,omitempty"`
Requires []string `json:"Requires,omitempty" yaml:"Requires,omitempty"`
Wants []string `json:"Wants,omitempty" yaml:"Wants,omitempty"`
After []string `json:"After,omitempty" yaml:"After,omitempty"`
Before []string `json:"Before,omitempty" yaml:"Before,omitempty"`
}
type ServiceSection struct {
Type SystemdServiceType `json:"Type,omitempty"`
RemainAfterExit bool `json:"RemainAfterExit,omitempty"`
ExecStartPre []string `json:"ExecStartPre,omitempty"`
ExecStopPost []string `json:"ExecStopPost,omitempty"`
ExecStart []string `json:"ExecStart,omitempty"`
Environment []EnvironmentVariable `json:"Environment,omitempty"`
EnvironmentFile []string `json:"EnvironmentFile,omitempty"`
StandardOutput string `json:"StandardOutput,omitempty"`
Type SystemdServiceType `json:"Type,omitempty" yaml:"Type,omitempty"`
RemainAfterExit bool `json:"RemainAfterExit,omitempty" yaml:"RemainAfterExit,omitempty"`
ExecStartPre []string `json:"ExecStartPre,omitempty" yaml:"ExecStartPre,omitempty"`
ExecStopPost []string `json:"ExecStopPost,omitempty" yaml:"ExecStopPost,omitempty"`
ExecStart []string `json:"ExecStart,omitempty" yaml:"ExecStart,omitempty"`
Environment []EnvironmentVariable `json:"Environment,omitempty" yaml:"Environment,omitempty"`
EnvironmentFile []string `json:"EnvironmentFile,omitempty" yaml:"EnvironmentFile,omitempty"`
StandardOutput string `json:"StandardOutput,omitempty" yaml:"StandardOutput,omitempty"`
}
type MountSection struct {
What string `json:"What"`
Where string `json:"Where"`
Type string `json:"Type,omitempty"`
Options string `json:"Options,omitempty"`
What string `json:"What" yaml:"What"`
Where string `json:"Where" yaml:"Where"`
Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
Options string `json:"Options,omitempty" yaml:"Options,omitempty"`
}
type SwapSection struct {
What string `json:"What"`
Priority *int `json:"Priority,omitempty"`
Options string `json:"Options,omitempty"`
TimeoutSec string `json:"TimeoutSec,omitempty"`
What string `json:"What" yaml:"What"`
Priority *int `json:"Priority,omitempty" yaml:"Priority,omitempty"`
Options string `json:"Options,omitempty" yaml:"Options,omitempty"`
TimeoutSec string `json:"TimeoutSec,omitempty" yaml:"TimeoutSec,omitempty"`
}
type SocketSection struct {
Service string `json:"Service,omitempty"`
ListenStream string `json:"ListenStream,omitempty"`
ListenDatagram string `json:"ListenDatagram,omitempty"`
ListenSequentialPacket string `json:"ListenSequentialPacket,omitempty"`
ListenFifo string `json:"ListenFifo,omitempty"`
SocketUser string `json:"SocketUser,omitempty"`
SocketGroup string `json:"SocketGroup,omitempty"`
SocketMode string `json:"SocketMode,omitempty"`
DirectoryMode string `json:"DirectoryMode,omitempty"`
Accept string `json:"Accept,omitempty"`
RuntimeDirectory string `json:"RuntimeDirectory,omitempty"`
RemoveOnStop string `json:"RemoveOnStop,omitempty"`
Service string `json:"Service,omitempty" yaml:"Service,omitempty"`
ListenStream string `json:"ListenStream,omitempty" yaml:"ListenStream,omitempty"`
ListenDatagram string `json:"ListenDatagram,omitempty" yaml:"ListenDatagram,omitempty"`
ListenSequentialPacket string `json:"ListenSequentialPacket,omitempty" yaml:"ListenSequentialPacket,omitempty"`
ListenFifo string `json:"ListenFifo,omitempty" yaml:"ListenFifo,omitempty"`
SocketUser string `json:"SocketUser,omitempty" yaml:"SocketUser,omitempty"`
SocketGroup string `json:"SocketGroup,omitempty" yaml:"SocketGroup,omitempty"`
SocketMode string `json:"SocketMode,omitempty" yaml:"SocketMode,omitempty"`
DirectoryMode string `json:"DirectoryMode,omitempty" yaml:"DirectoryMode,omitempty"`
Accept string `json:"Accept,omitempty" yaml:"Accept,omitempty"`
RuntimeDirectory string `json:"RuntimeDirectory,omitempty" yaml:"RuntimeDirectory,omitempty"`
RemoveOnStop string `json:"RemoveOnStop,omitempty" yaml:"RemoveOnStop,omitempty"`
}
type InstallSection struct {
RequiredBy []string `json:"RequiredBy,omitempty"`
WantedBy []string `json:"WantedBy,omitempty"`
RequiredBy []string `json:"RequiredBy,omitempty" yaml:"RequiredBy,omitempty"`
WantedBy []string `json:"WantedBy,omitempty" yaml:"WantedBy,omitempty"`
}
type SystemdUnit struct {
Unit *UnitSection `json:"Unit"`
Service *ServiceSection `json:"Service,omitempty"`
Mount *MountSection `json:"Mount,omitempty"`
Socket *SocketSection `json:"Socket,omitempty"`
Swap *SwapSection `json:"Swap,omitempty"`
Install *InstallSection `json:"Install,omitempty"`
Unit *UnitSection `json:"Unit" yaml:"Unit"`
Service *ServiceSection `json:"Service,omitempty" yaml:"Service,omitempty"`
Mount *MountSection `json:"Mount,omitempty" yaml:"Mount,omitempty"`
Socket *SocketSection `json:"Socket,omitempty" yaml:"Socket,omitempty"`
Swap *SwapSection `json:"Swap,omitempty" yaml:"Swap,omitempty"`
Install *InstallSection `json:"Install,omitempty" yaml:"Install,omitempty"`
}
type SystemdUnitCreateStageOptions struct {
Filename string `json:"filename"`
UnitType unitType `json:"unit-type,omitempty"` // unitType defined in ./systemd_unit_stage.go
UnitPath SystemdUnitPath `json:"unit-path,omitempty"`
Config SystemdUnit `json:"config"`
Filename string `json:"filename" yaml:"filename"`
UnitType unitType `json:"unit-type,omitempty" yaml:"unit-type,omitempty"` // unitType defined in ./systemd_unit_stage.go
UnitPath SystemdUnitPath `json:"unit-path,omitempty" yaml:"unit-path,omitempty"`
Config SystemdUnit `json:"config" yaml:"config"`
}
func (SystemdUnitCreateStageOptions) isStageOptions() {}

View file

@ -1,8 +1,11 @@
package osbuild
import (
"encoding/json"
"fmt"
"regexp"
"github.com/osbuild/images/internal/common"
)
type udevOpType int
@ -134,6 +137,50 @@ type UdevRule interface {
isUdevRule()
}
func (u *UdevRules) UnmarshalJSON(data []byte) error {
var rawRules []map[string]interface{}
if err := json.Unmarshal(data, &rawRules); err != nil {
return err
}
var newRules []UdevRule
for _, rawRule := range rawRules {
if v, ok := rawRule["comment"].([]interface{}); ok {
var vs []string
for _, vv := range v {
vs = append(vs, vv.(string))
}
newRules = append(newRules, NewUdevRuleComment(vs))
} else if v, ok := rawRule["rule"].([]interface{}); ok {
var vkv []map[string]interface{}
for _, vv := range v {
vkv = append(vkv, vv.(map[string]interface{}))
}
var kvs []UdevKV
for _, rawKV := range vkv {
var k, a, o, v string
k, _ = rawKV["K"].(string)
a, _ = rawKV["A"].(string)
o, _ = rawKV["O"].(string)
v, _ = rawKV["V"].(string)
kvs = append(kvs, UdevKV{
K: k,
A: a,
O: o,
V: v,
})
}
newRules = append(newRules, NewUdevRule(kvs))
}
}
*u = newRules
return nil
}
func (u *UdevRules) UnmarshalYAML(unmarshal func(any) error) error {
return common.UnmarshalYAMLviaJSON(u, unmarshal)
}
// Comments
type UdevRuleComment struct {
Comment []string `json:"comment"`

View file

@ -1,10 +1,10 @@
package osbuild
type WAAgentConfig struct {
ProvisioningUseCloudInit *bool `json:"Provisioning.UseCloudInit,omitempty"`
ProvisioningEnabled *bool `json:"Provisioning.Enabled,omitempty"`
RDFormat *bool `json:"ResourceDisk.Format,omitempty"`
RDEnableSwap *bool `json:"ResourceDisk.EnableSwap,omitempty"`
ProvisioningUseCloudInit *bool `json:"Provisioning.UseCloudInit,omitempty" yaml:"Provisioning.UseCloudInit,omitempty"`
ProvisioningEnabled *bool `json:"Provisioning.Enabled,omitempty" yaml:"Provisioning.Enabled,omitempty"`
RDFormat *bool `json:"ResourceDisk.Format,omitempty" yaml:"ResourceDisk.Format,omitempty"`
RDEnableSwap *bool `json:"ResourceDisk.EnableSwap,omitempty" yaml:"ResourceDisk.EnableSwap,omitempty"`
}
type WAAgentConfStageOptions struct {

View file

@ -14,17 +14,17 @@ const repoIDRegex = "^[\\w.\\-:]+$"
// YumRepository represents a single DNF / YUM repository.
type YumRepository struct {
Id string `json:"id"`
BaseURLs []string `json:"baseurl,omitempty"`
BaseURLs []string `json:"baseurl,omitempty" yaml:"baseurl,omitempty"`
Cost *int `json:"cost,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
Priority *int `json:"priority,omitempty"`
GPGKey []string `json:"gpgkey,omitempty"`
GPGKey []string `json:"gpgkey,omitempty" yaml:"gpgkey,omitempty"`
Metalink string `json:"metalink,omitempty"`
Mirrorlist string `json:"mirrorlist,omitempty"`
ModuleHotfixes *bool `json:"module_hotfixes,omitempty"`
Name string `json:"name,omitempty"`
GPGCheck *bool `json:"gpgcheck,omitempty"`
RepoGPGCheck *bool `json:"repo_gpgcheck,omitempty"`
GPGCheck *bool `json:"gpgcheck,omitempty" yaml:"gpgcheck,omitempty"`
RepoGPGCheck *bool `json:"repo_gpgcheck,omitempty" yaml:"repo_gpgcheck,omitempty"`
SSLVerify *bool `json:"sslverify,omitempty"`
}

62
vendor/github.com/osbuild/images/pkg/platform/yaml.go generated vendored Normal file
View file

@ -0,0 +1,62 @@
package platform
import (
"github.com/osbuild/images/pkg/arch"
)
// PlatformConf is a platform configured from YAML inputs
// that implements the "Platform" interface
type PlatformConf struct {
Arch arch.Arch `yaml:"arch"`
ImageFormat ImageFormat `yaml:"image_format"`
QCOW2Compat string `yaml:"qcow2_compat"`
BIOSPlatform string `yaml:"bios_platform"`
UEFIVendor string `yaml:"uefi_vendor"`
ZiplSupport bool `yaml:"zipl_support"`
// packages are index by an arbitrary string key to
// make them YAML mergable, a good key is e.g. "bios"
// to indicate that these packages are needed for
// bios support
Packages map[string][]string `yaml:"packages"`
BuildPackages map[string][]string `yaml:"build_packages"`
BootFiles [][2]string `yaml:"boot_files"`
}
// ensure PlatformConf implements the Platform interface
var _ = Platform(&PlatformConf{})
func (pc *PlatformConf) GetArch() arch.Arch {
return pc.Arch
}
func (pc *PlatformConf) GetImageFormat() ImageFormat {
return pc.ImageFormat
}
func (pc *PlatformConf) GetQCOW2Compat() string {
return pc.QCOW2Compat
}
func (pc *PlatformConf) GetBIOSPlatform() string {
return pc.BIOSPlatform
}
func (pc *PlatformConf) GetUEFIVendor() string {
return pc.UEFIVendor
}
func (pc *PlatformConf) GetZiplSupport() bool {
return pc.ZiplSupport
}
func (pc *PlatformConf) GetPackages() []string {
var merged []string
for _, pkgList := range pc.Packages {
merged = append(merged, pkgList...)
}
return merged
}
func (pc *PlatformConf) GetBuildPackages() []string {
var merged []string
for _, pkgList := range pc.BuildPackages {
merged = append(merged, pkgList...)
}
return merged
}
func (pc *PlatformConf) GetBootFiles() [][2]string {
return pc.BootFiles
}

2
vendor/modules.txt vendored
View file

@ -1049,7 +1049,7 @@ github.com/oracle/oci-go-sdk/v54/workrequests
## explicit; go 1.22.8
github.com/osbuild/blueprint/internal/common
github.com/osbuild/blueprint/pkg/blueprint
# github.com/osbuild/images v0.144.0
# github.com/osbuild/images v0.148.0
## explicit; go 1.22.8
github.com/osbuild/images/data/dependencies
github.com/osbuild/images/data/repositories