distro/rhel84: new imageType implementation
imageTypeS2 implements the distro.ImageType interface buts generates a Manifest matching the new osbuild v2 schema. Two new image types are added to the rhel84 distro (x84_64 and aarch64) for generating OCI containers contain an Edge (ostree) commit and, when run, start a web serer to serve the commit. The image type uses the new PackageSets map to define packages (and excludes) for the image. The old methods (Packages() and BuildPackages()) are implemented for compatibility with the old workflow. The image also defines an extra package set for the container that will serve the package: "httpd" (and its dependencies). The distro.ImageType interface has a new method: Exports() It should return a list of names or IDs of artefacts that should be exported from osbuild when the job is complete. For the old image types, this is simply set to "assembler".
This commit is contained in:
parent
756d5b063f
commit
541cbab0f6
10 changed files with 640 additions and 23 deletions
|
|
@ -76,6 +76,9 @@ type ImageType interface {
|
|||
// image type.
|
||||
PackageSets(bp blueprint.Blueprint) map[string]rpmmd.PackageSet
|
||||
|
||||
// Returns the names of the stages that will produce the build output.
|
||||
Exports() []string
|
||||
|
||||
// Returns an osbuild manifest, containing the sources and pipeline necessary
|
||||
// to build an image, given output format with all packages and customizations
|
||||
// specified in the given blueprint. The packageSpecSets must be labelled in
|
||||
|
|
|
|||
|
|
@ -200,6 +200,10 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.Package
|
|||
}
|
||||
}
|
||||
|
||||
func (t *imageType) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *imageType) Manifest(c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
repos []rpmmd.RepoConfig,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,10 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.Package
|
|||
}
|
||||
}
|
||||
|
||||
func (t *imageType) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *imageType) Manifest(c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
repos []rpmmd.RepoConfig,
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.Package
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *imageType) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *imageType) Manifest(c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
repos []rpmmd.RepoConfig,
|
||||
|
|
|
|||
|
|
@ -201,6 +201,10 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.Package
|
|||
}
|
||||
}
|
||||
|
||||
func (t *imageType) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *imageType) Manifest(c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
repos []rpmmd.RepoConfig,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const ostreeRef = "rhel/8/%s/edge"
|
|||
|
||||
type distribution struct {
|
||||
arches map[string]architecture
|
||||
imageTypes map[string]imageType
|
||||
imageTypes map[string]distro.ImageType
|
||||
buildPackages []string
|
||||
isCentos bool
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ type architecture struct {
|
|||
buildPackages []string
|
||||
legacy string
|
||||
uefi bool
|
||||
imageTypes map[string]imageType
|
||||
imageTypes map[string]distro.ImageType
|
||||
}
|
||||
|
||||
type imageType struct {
|
||||
|
|
@ -121,16 +121,15 @@ func (a *architecture) GetImageType(imageType string) (distro.ImageType, error)
|
|||
return nil, errors.New("invalid image type: " + imageType)
|
||||
}
|
||||
|
||||
return &t, nil
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (a *architecture) addImageTypes(imageTypes ...imageType) {
|
||||
if a.imageTypes == nil {
|
||||
a.imageTypes = map[string]imageType{}
|
||||
a.imageTypes = map[string]distro.ImageType{}
|
||||
}
|
||||
|
||||
for _, it := range imageTypes {
|
||||
a.imageTypes[it.name] = imageType{
|
||||
a.imageTypes[it.name] = &imageType{
|
||||
arch: a,
|
||||
name: it.name,
|
||||
filename: it.filename,
|
||||
|
|
@ -150,6 +149,28 @@ func (a *architecture) addImageTypes(imageTypes ...imageType) {
|
|||
}
|
||||
}
|
||||
|
||||
// For the secondary implementation of image type.
|
||||
// Temporary; for supporting the new Manifest schema, until everything is
|
||||
// ported.
|
||||
func (a *architecture) addS2ImageTypes(imageTypes ...imageTypeS2) {
|
||||
for _, it := range imageTypes {
|
||||
a.imageTypes[it.name] = &imageTypeS2{
|
||||
arch: a,
|
||||
name: it.name,
|
||||
filename: it.filename,
|
||||
mimeType: it.mimeType,
|
||||
packageSets: it.packageSets,
|
||||
enabledServices: it.enabledServices,
|
||||
disabledServices: it.disabledServices,
|
||||
defaultTarget: it.defaultTarget,
|
||||
kernelOptions: it.kernelOptions,
|
||||
bootable: it.bootable,
|
||||
rpmOstree: it.rpmOstree,
|
||||
defaultSize: it.defaultSize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *imageType) Name() string {
|
||||
return t.name
|
||||
}
|
||||
|
|
@ -220,6 +241,10 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.Package
|
|||
}
|
||||
}
|
||||
|
||||
func (t *imageType) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *imageType) Manifest(c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
repos []rpmmd.RepoConfig,
|
||||
|
|
@ -1182,7 +1207,7 @@ func newDistro(isCentos bool) distro.Distro {
|
|||
}
|
||||
|
||||
r := distribution{
|
||||
imageTypes: map[string]imageType{},
|
||||
imageTypes: map[string]distro.ImageType{},
|
||||
buildPackages: []string{
|
||||
"dnf",
|
||||
"dosfstools",
|
||||
|
|
@ -1215,6 +1240,123 @@ func newDistro(isCentos bool) distro.Distro {
|
|||
legacy: "i386-pc",
|
||||
uefi: true,
|
||||
}
|
||||
|
||||
edgeOCIImgTypeX86_64 := imageTypeS2{
|
||||
name: "rhel-edge-container",
|
||||
filename: "rhel84-container.tar",
|
||||
mimeType: "application/x-tar",
|
||||
packageSets: map[string]rpmmd.PackageSet{
|
||||
"packages": {
|
||||
Include: []string{
|
||||
"redhat-release", // TODO: is this correct for Edge?
|
||||
"glibc", "glibc-minimal-langpack", "nss-altfiles",
|
||||
"dracut-config-generic", "dracut-network",
|
||||
"basesystem", "bash", "platform-python",
|
||||
"shadow-utils", "chrony", "setup", "shadow-utils",
|
||||
"sudo", "systemd", "coreutils", "util-linux",
|
||||
"curl", "vim-minimal",
|
||||
"rpm", "rpm-ostree", "polkit",
|
||||
"lvm2", "cryptsetup", "pinentry",
|
||||
"e2fsprogs", "dosfstools",
|
||||
"keyutils", "gnupg2",
|
||||
"attr", "xz", "gzip",
|
||||
"firewalld", "iptables",
|
||||
"NetworkManager", "NetworkManager-wifi", "NetworkManager-wwan",
|
||||
"wpa_supplicant",
|
||||
"dnsmasq", "traceroute",
|
||||
"hostname", "iproute", "iputils",
|
||||
"openssh-clients", "procps-ng", "rootfiles",
|
||||
"openssh-server", "passwd",
|
||||
"policycoreutils", "policycoreutils-python-utils",
|
||||
"selinux-policy-targeted", "setools-console",
|
||||
"less", "tar", "rsync",
|
||||
"fwupd", "usbguard",
|
||||
"bash-completion", "tmux",
|
||||
"ima-evm-utils",
|
||||
"audit",
|
||||
"podman", "container-selinux", "skopeo", "criu",
|
||||
"slirp4netns", "fuse-overlayfs",
|
||||
"clevis", "clevis-dracut", "clevis-luks",
|
||||
"greenboot", "greenboot-grub2", "greenboot-rpm-ostree-grub2", "greenboot-reboot", "greenboot-status",
|
||||
// x86 specific
|
||||
"grub2", "grub2-efi-x64", "efibootmgr", "shim-x64", "microcode_ctl",
|
||||
"iwl1000-firmware", "iwl100-firmware", "iwl105-firmware", "iwl135-firmware",
|
||||
"iwl2000-firmware", "iwl2030-firmware", "iwl3160-firmware", "iwl5000-firmware",
|
||||
"iwl5150-firmware", "iwl6000-firmware", "iwl6050-firmware", "iwl7260-firmware",
|
||||
},
|
||||
Exclude: []string{
|
||||
"rng-tools",
|
||||
"subscription-manager",
|
||||
},
|
||||
},
|
||||
"container": {Include: []string{"httpd"}},
|
||||
},
|
||||
enabledServices: []string{
|
||||
"NetworkManager.service", "firewalld.service", "sshd.service",
|
||||
"greenboot-grub2-set-counter", "greenboot-grub2-set-success", "greenboot-healthcheck",
|
||||
"greenboot-rpm-ostree-grub2-check-fallback", "greenboot-status", "greenboot-task-runner",
|
||||
"redboot-auto-reboot", "redboot-task-runner",
|
||||
},
|
||||
rpmOstree: true,
|
||||
}
|
||||
|
||||
edgeOCIImgTypeArch64 := imageTypeS2{
|
||||
name: "rhel-edge-container",
|
||||
filename: "rhel84-container.tar",
|
||||
mimeType: "application/x-tar",
|
||||
packageSets: map[string]rpmmd.PackageSet{
|
||||
"packages": {
|
||||
Include: []string{
|
||||
"redhat-release", // TODO: is this correct for Edge?
|
||||
"glibc", "glibc-minimal-langpack", "nss-altfiles",
|
||||
"dracut-config-generic", "dracut-network",
|
||||
"basesystem", "bash", "platform-python",
|
||||
"shadow-utils", "chrony", "setup", "shadow-utils",
|
||||
"sudo", "systemd", "coreutils", "util-linux",
|
||||
"curl", "vim-minimal",
|
||||
"rpm", "rpm-ostree", "polkit",
|
||||
"lvm2", "cryptsetup", "pinentry",
|
||||
"e2fsprogs", "dosfstools",
|
||||
"keyutils", "gnupg2",
|
||||
"attr", "xz", "gzip",
|
||||
"firewalld", "iptables",
|
||||
"NetworkManager", "NetworkManager-wifi", "NetworkManager-wwan",
|
||||
"wpa_supplicant",
|
||||
"dnsmasq", "traceroute",
|
||||
"hostname", "iproute", "iputils",
|
||||
"openssh-clients", "procps-ng", "rootfiles",
|
||||
"openssh-server", "passwd",
|
||||
"policycoreutils", "policycoreutils-python-utils",
|
||||
"selinux-policy-targeted", "setools-console",
|
||||
"less", "tar", "rsync",
|
||||
"fwupd", "usbguard",
|
||||
"bash-completion", "tmux",
|
||||
"ima-evm-utils",
|
||||
"audit",
|
||||
"podman", "container-selinux", "skopeo", "criu",
|
||||
"slirp4netns", "fuse-overlayfs",
|
||||
"clevis", "clevis-dracut", "clevis-luks",
|
||||
"greenboot", "greenboot-grub2", "greenboot-rpm-ostree-grub2", "greenboot-reboot", "greenboot-status",
|
||||
// aarch64 specific
|
||||
"grub2-efi-aa64", "efibootmgr", "shim-aa64",
|
||||
"iwl7260-firmware",
|
||||
},
|
||||
Exclude: []string{
|
||||
"rng-tools",
|
||||
"subscription-manager",
|
||||
},
|
||||
},
|
||||
"container": {Include: []string{"httpd"}},
|
||||
},
|
||||
enabledServices: []string{
|
||||
"NetworkManager.service", "firewalld.service", "sshd.service",
|
||||
"greenboot-grub2-set-counter", "greenboot-grub2-set-success", "greenboot-healthcheck",
|
||||
"greenboot-rpm-ostree-grub2-check-fallback", "greenboot-status", "greenboot-task-runner",
|
||||
"redboot-auto-reboot", "redboot-task-runner",
|
||||
},
|
||||
rpmOstree: true,
|
||||
}
|
||||
|
||||
x8664.addImageTypes(
|
||||
amiImgType,
|
||||
qcow2ImageType,
|
||||
|
|
@ -1226,6 +1368,7 @@ func newDistro(isCentos bool) distro.Distro {
|
|||
|
||||
if !isCentos {
|
||||
x8664.addImageTypes(edgeImgTypeX86_64)
|
||||
x8664.addS2ImageTypes(edgeOCIImgTypeX86_64)
|
||||
}
|
||||
|
||||
aarch64 := architecture{
|
||||
|
|
@ -1249,6 +1392,7 @@ func newDistro(isCentos bool) distro.Distro {
|
|||
|
||||
if !isCentos {
|
||||
aarch64.addImageTypes(edgeImgTypeAarch64)
|
||||
aarch64.addS2ImageTypes(edgeOCIImgTypeArch64)
|
||||
}
|
||||
|
||||
ppc64le := architecture{
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ func TestDistro_ManifestError(t *testing.T) {
|
|||
Size: imgType.Size(0),
|
||||
}
|
||||
_, err := imgType.Manifest(bp.Customizations, imgOpts, nil, nil, 0)
|
||||
if imgTypeName == "rhel-edge-commit" {
|
||||
if imgTypeName == "rhel-edge-commit" || imgTypeName == "rhel-edge-container" {
|
||||
assert.EqualError(t, err, "kernel boot parameter customizations are not supported for ostree types")
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
|
|
@ -466,7 +466,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) {
|
|||
"vhd",
|
||||
"vmdk",
|
||||
},
|
||||
rhelAdditionalImageTypes: []string{"rhel-edge-commit"},
|
||||
rhelAdditionalImageTypes: []string{"rhel-edge-commit", "rhel-edge-container"},
|
||||
},
|
||||
{
|
||||
arch: "aarch64",
|
||||
|
|
@ -476,7 +476,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) {
|
|||
"openstack",
|
||||
"tar",
|
||||
},
|
||||
rhelAdditionalImageTypes: []string{"rhel-edge-commit"},
|
||||
rhelAdditionalImageTypes: []string{"rhel-edge-commit", "rhel-edge-container"},
|
||||
},
|
||||
{
|
||||
arch: "ppc64le",
|
||||
|
|
|
|||
450
internal/distro/rhel84/distro_v2.go
Normal file
450
internal/distro/rhel84/distro_v2.go
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
package rhel84
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/crypt"
|
||||
"github.com/osbuild/osbuild-composer/internal/distro"
|
||||
osbuild "github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
type imageTypeS2 struct {
|
||||
arch *architecture
|
||||
name string
|
||||
filename string
|
||||
mimeType string
|
||||
packageSets map[string]rpmmd.PackageSet
|
||||
enabledServices []string
|
||||
disabledServices []string
|
||||
defaultTarget string
|
||||
kernelOptions string
|
||||
bootable bool
|
||||
rpmOstree bool
|
||||
defaultSize uint64
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Arch() distro.Arch {
|
||||
return t.arch
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Name() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Filename() string {
|
||||
return t.filename
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) MIMEType() string {
|
||||
return t.mimeType
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) OSTreeRef() string {
|
||||
if t.rpmOstree {
|
||||
return fmt.Sprintf(ostreeRef, t.arch.name)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Size(size uint64) uint64 {
|
||||
const MegaByte = 1024 * 1024
|
||||
// Microsoft Azure requires vhd images to be rounded up to the nearest MB
|
||||
if t.name == "vhd" && size%MegaByte != 0 {
|
||||
size = (size/MegaByte + 1) * MegaByte
|
||||
}
|
||||
if size == 0 {
|
||||
size = t.defaultSize
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Packages(bp blueprint.Blueprint) ([]string, []string) {
|
||||
packages := append(t.packageSets["packages"].Include, bp.GetPackages()...)
|
||||
timezone, _ := bp.Customizations.GetTimezoneSettings()
|
||||
if timezone != nil {
|
||||
packages = append(packages, "chrony")
|
||||
}
|
||||
if t.bootable {
|
||||
packages = append(packages, t.arch.bootloaderPackages...)
|
||||
}
|
||||
|
||||
return packages, t.packageSets["packages"].Exclude
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) BuildPackages() []string {
|
||||
packages := append(t.arch.distro.buildPackages, t.arch.buildPackages...)
|
||||
if t.rpmOstree {
|
||||
packages = append(packages, "rpm-ostree")
|
||||
}
|
||||
return packages
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.PackageSet {
|
||||
sets := map[string]rpmmd.PackageSet{
|
||||
"build-packages": {
|
||||
Include: t.BuildPackages(),
|
||||
},
|
||||
}
|
||||
for name, pkgSet := range t.packageSets {
|
||||
if name == "packages" {
|
||||
// treat base packages separately to combine with blueprint
|
||||
packages := new(rpmmd.PackageSet)
|
||||
packages.Include, packages.Exclude = t.Packages(bp)
|
||||
sets[name] = *packages
|
||||
continue
|
||||
}
|
||||
sets[name] = pkgSet
|
||||
}
|
||||
return sets
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) Manifest(c *blueprint.Customizations,
|
||||
options distro.ImageOptions,
|
||||
repos []rpmmd.RepoConfig,
|
||||
packageSpecSets map[string][]rpmmd.PackageSpec,
|
||||
seed int64) (distro.Manifest, error) {
|
||||
source := rand.NewSource(seed)
|
||||
rng := rand.New(source)
|
||||
pipelines, err := t.pipelines(c, options, repos, packageSpecSets, rng)
|
||||
if err != nil {
|
||||
return distro.Manifest{}, err
|
||||
}
|
||||
|
||||
// flatten spec sets for sources
|
||||
allPackageSpecs := make([]rpmmd.PackageSpec, 0)
|
||||
for _, specs := range packageSpecSets {
|
||||
|
||||
allPackageSpecs = append(allPackageSpecs, specs...)
|
||||
}
|
||||
return json.Marshal(
|
||||
osbuild.Manifest{
|
||||
Version: "2",
|
||||
Pipelines: pipelines,
|
||||
Sources: t.sources(allPackageSpecs),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) sources(packages []rpmmd.PackageSpec) osbuild.Sources {
|
||||
source := &osbuild.CurlSource{
|
||||
Items: make(map[string]osbuild.CurlSourceItem),
|
||||
}
|
||||
for _, pkg := range packages {
|
||||
item := new(osbuild.URLWithSecrets)
|
||||
item.URL = pkg.RemoteLocation
|
||||
if pkg.Secrets == "org.osbuild.rhsm" {
|
||||
item.Secrets = &osbuild.URLSecrets{
|
||||
Name: "org.osbuild.rhsm",
|
||||
}
|
||||
}
|
||||
source.Items[pkg.Checksum] = item
|
||||
}
|
||||
return osbuild.Sources{
|
||||
"org.osbuild.curl": source,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) pipelines(c *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSetSpecs map[string][]rpmmd.PackageSpec, rng *rand.Rand) ([]osbuild.Pipeline, error) {
|
||||
if kernelOpts := c.GetKernel(); kernelOpts.Append != "" && t.rpmOstree {
|
||||
return nil, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
|
||||
}
|
||||
|
||||
pipelines := make([]osbuild.Pipeline, 0, 5)
|
||||
|
||||
pipelines = append(pipelines, *t.buildPipeline(repos, packageSetSpecs["build-packages"]))
|
||||
|
||||
if t.rpmOstree {
|
||||
// NOTE(akoutsou) 1to2t: Currently all images of type imageTypeS2 are ostree
|
||||
treePipeline, err := t.ostreeTreePipeline(repos, packageSetSpecs["packages"], c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pipelines = append(pipelines, *treePipeline)
|
||||
pipelines = append(pipelines, *t.ostreeCommitPipeline(options))
|
||||
}
|
||||
|
||||
pipelines = append(pipelines, *t.containerTreePipeline(repos, packageSetSpecs["container"], options, c))
|
||||
pipelines = append(pipelines, *t.containerPipeline())
|
||||
|
||||
return pipelines, nil
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) buildPipeline(repos []rpmmd.RepoConfig, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "build"
|
||||
p.Runner = "org.osbuild.rhel84"
|
||||
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(buildPackageSpecs)))
|
||||
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
|
||||
return p
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) ostreeTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, c *blueprint.Customizations) (*osbuild.Pipeline, error) {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "ostree-tree"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(packages)))
|
||||
language, keyboard := c.GetPrimaryLocale()
|
||||
if language != nil {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
|
||||
}
|
||||
if keyboard != nil {
|
||||
p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
|
||||
}
|
||||
if hostname := c.GetHostname(); hostname != nil {
|
||||
p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
|
||||
}
|
||||
|
||||
timezone, ntpServers := c.GetTimezoneSettings()
|
||||
if timezone != nil {
|
||||
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: "America/New_York"}))
|
||||
}
|
||||
|
||||
if len(ntpServers) > 0 {
|
||||
p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
|
||||
}
|
||||
|
||||
if groups := c.GetGroups(); len(groups) > 0 {
|
||||
p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
|
||||
}
|
||||
|
||||
if users := c.GetUsers(); len(users) > 0 {
|
||||
options, err := t.userStageOptions(users)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.AddStage(osbuild.NewUsersStage(options))
|
||||
}
|
||||
|
||||
if services := c.GetServices(); services != nil || t.enabledServices != nil || t.disabledServices != nil || t.defaultTarget != "" {
|
||||
p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.enabledServices, t.disabledServices, services, t.defaultTarget)))
|
||||
}
|
||||
|
||||
if firewall := c.GetFirewall(); firewall != nil {
|
||||
p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
|
||||
}
|
||||
|
||||
p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
|
||||
|
||||
// These are the current defaults for the sysconfig stage. This can be changed to be image type exclusive if different configs are needed.
|
||||
p.AddStage(osbuild.NewSysconfigStage(&osbuild.SysconfigStageOptions{
|
||||
Kernel: osbuild.SysconfigKernelOptions{
|
||||
UpdateDefault: true,
|
||||
DefaultKernel: "kernel",
|
||||
},
|
||||
Network: osbuild.SysconfigNetworkOptions{
|
||||
Networking: true,
|
||||
NoZeroConf: true,
|
||||
},
|
||||
}))
|
||||
|
||||
p.AddStage(osbuild.NewRPMOSTreePrepTreeStage(&osbuild.RPMOSTreePrepTreeStageOptions{
|
||||
EtcGroupMembers: []string{
|
||||
// NOTE: We may want to make this configurable.
|
||||
"wheel", "docker",
|
||||
},
|
||||
}))
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) ostreeCommitPipeline(options distro.ImageOptions) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "ostree-commit"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: "/repo"}))
|
||||
|
||||
commitStageInput := new(osbuild.OSTreeCommitStageInput)
|
||||
commitStageInput.Type = "org.osbuild.tree"
|
||||
commitStageInput.Origin = "org.osbuild.pipeline"
|
||||
commitStageInput.References = osbuild.OSTreeCommitStageReferences{"name:ostree-tree"}
|
||||
|
||||
p.AddStage(osbuild.NewOSTreeCommitStage(
|
||||
&osbuild.OSTreeCommitStageOptions{
|
||||
Ref: t.OSTreeRef(),
|
||||
OSVersion: "8.4", // NOTE: Set on image type?
|
||||
Parent: options.OSTree.Parent,
|
||||
},
|
||||
&osbuild.OSTreeCommitStageInputs{Tree: commitStageInput}),
|
||||
)
|
||||
return p
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) containerTreePipeline(repos []rpmmd.RepoConfig, packages []rpmmd.PackageSpec, options distro.ImageOptions, c *blueprint.Customizations) *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
p.Name = "container-tree"
|
||||
p.Build = "name:build"
|
||||
p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(repos), t.rpmStageInputs(packages)))
|
||||
language, _ := c.GetPrimaryLocale()
|
||||
if language != nil {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
|
||||
} else {
|
||||
p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US"}))
|
||||
}
|
||||
p.AddStage(osbuild.NewOSTreeInitStage(&osbuild.OSTreeInitStageOptions{Path: "/var/www/html/repo"}))
|
||||
|
||||
p.AddStage(osbuild.NewOSTreePullStage(
|
||||
&osbuild.OSTreePullStageOptions{Repo: "/var/www/html/repo"},
|
||||
t.ostreePullStageInputs(options),
|
||||
))
|
||||
return p
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) containerPipeline() *osbuild.Pipeline {
|
||||
p := new(osbuild.Pipeline)
|
||||
// NOTE(akoutsou) 1to2t: final pipeline should always be named "assembler"
|
||||
p.Name = "assembler"
|
||||
p.Build = "name:build"
|
||||
options := &osbuild.OCIArchiveStageOptions{
|
||||
Architecture: t.arch.Name(),
|
||||
Filename: t.Filename(),
|
||||
Config: &osbuild.OCIArchiveConfig{
|
||||
Cmd: []string{"httpd", "-D", "FOREGROUND"},
|
||||
ExposedPorts: []string{"80"},
|
||||
},
|
||||
}
|
||||
baseInput := new(osbuild.OCIArchiveStageInput)
|
||||
baseInput.Type = "org.osbuild.tree"
|
||||
baseInput.Origin = "org.osbuild.pipeline"
|
||||
baseInput.References = []string{"name:container-tree"}
|
||||
inputs := &osbuild.OCIArchiveStageInputs{Base: baseInput}
|
||||
p.AddStage(osbuild.NewOCIArchiveStage(options, inputs))
|
||||
return p
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) rpmStageInputs(specs []rpmmd.PackageSpec) *osbuild.RPMStageInputs {
|
||||
stageInput := new(osbuild.RPMStageInput)
|
||||
stageInput.Type = "org.osbuild.files"
|
||||
stageInput.Origin = "org.osbuild.source"
|
||||
stageInput.References = pkgRefs(specs)
|
||||
return &osbuild.RPMStageInputs{Packages: stageInput}
|
||||
}
|
||||
|
||||
func pkgRefs(specs []rpmmd.PackageSpec) osbuild.RPMStageReferences {
|
||||
refs := make([]string, len(specs))
|
||||
for idx, pkg := range specs {
|
||||
refs[idx] = pkg.Checksum
|
||||
}
|
||||
return refs
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) ostreePullStageInputs(options distro.ImageOptions) *osbuild.OSTreePullStageInputs {
|
||||
pullStageInput := new(osbuild.OSTreePullStageInput)
|
||||
pullStageInput.Type = "org.osbuild.ostree"
|
||||
pullStageInput.Origin = "org.osbuild.pipeline"
|
||||
|
||||
inputRefs := make(map[string]osbuild.OSTreePullStageReference)
|
||||
inputRefs["name:ostree-commit"] = osbuild.OSTreePullStageReference{Ref: t.OSTreeRef()}
|
||||
pullStageInput.References = inputRefs
|
||||
return &osbuild.OSTreePullStageInputs{Commits: pullStageInput}
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) rpmStageOptions(repos []rpmmd.RepoConfig) *osbuild.RPMStageOptions {
|
||||
var gpgKeys []string
|
||||
for _, repo := range repos {
|
||||
if repo.GPGKey == "" {
|
||||
continue
|
||||
}
|
||||
gpgKeys = append(gpgKeys, repo.GPGKey)
|
||||
}
|
||||
|
||||
return &osbuild.RPMStageOptions{
|
||||
GPGKeys: gpgKeys,
|
||||
Exclude: &osbuild.Exclude{
|
||||
// NOTE: Make configurable?
|
||||
Docs: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) selinuxStageOptions() *osbuild.SELinuxStageOptions {
|
||||
return &osbuild.SELinuxStageOptions{
|
||||
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
|
||||
}
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
|
||||
options := osbuild.UsersStageOptions{
|
||||
Users: make(map[string]osbuild.UsersStageOptionsUser),
|
||||
}
|
||||
|
||||
for _, c := range users {
|
||||
if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) {
|
||||
cryptedPassword, err := crypt.CryptSHA512(*c.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Password = &cryptedPassword
|
||||
}
|
||||
|
||||
user := osbuild.UsersStageOptionsUser{
|
||||
Groups: c.Groups,
|
||||
Description: c.Description,
|
||||
Home: c.Home,
|
||||
Shell: c.Shell,
|
||||
Password: c.Password,
|
||||
Key: c.Key,
|
||||
}
|
||||
|
||||
user.UID = c.UID
|
||||
user.GID = c.GID
|
||||
|
||||
options.Users[c.Name] = user
|
||||
}
|
||||
|
||||
return &options, nil
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
|
||||
options := osbuild.GroupsStageOptions{
|
||||
Groups: map[string]osbuild.GroupsStageOptionsGroup{},
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
groupData := osbuild.GroupsStageOptionsGroup{
|
||||
Name: group.Name,
|
||||
}
|
||||
groupData.GID = group.GID
|
||||
|
||||
options.Groups[group.Name] = groupData
|
||||
}
|
||||
|
||||
return &options
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
|
||||
options := osbuild.FirewallStageOptions{
|
||||
Ports: firewall.Ports,
|
||||
}
|
||||
|
||||
if firewall.Services != nil {
|
||||
options.EnabledServices = firewall.Services.Enabled
|
||||
options.DisabledServices = firewall.Services.Disabled
|
||||
}
|
||||
|
||||
return &options
|
||||
}
|
||||
|
||||
func (t *imageTypeS2) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization, target string) *osbuild.SystemdStageOptions {
|
||||
if s != nil {
|
||||
enabledServices = append(enabledServices, s.Enabled...)
|
||||
disabledServices = append(disabledServices, s.Disabled...)
|
||||
}
|
||||
return &osbuild.SystemdStageOptions{
|
||||
EnabledServices: enabledServices,
|
||||
DisabledServices: disabledServices,
|
||||
DefaultTarget: target,
|
||||
}
|
||||
}
|
||||
|
|
@ -82,6 +82,9 @@ func (t *TestImageType) BuildPackages() []string {
|
|||
func (t *TestImageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.PackageSet {
|
||||
return nil
|
||||
}
|
||||
func (t *TestImageType) Exports() []string {
|
||||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
func (t *TestImageType) Manifest(b *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSpecSets map[string][]rpmmd.PackageSpec, seed int64) (distro.Manifest, error) {
|
||||
return json.Marshal(
|
||||
|
|
|
|||
|
|
@ -326,19 +326,20 @@ func (store *Store) toStoreV0() *storeV0 {
|
|||
}
|
||||
|
||||
var imageTypeCompatMapping = map[string]string{
|
||||
"vhd": "Azure",
|
||||
"ami": "AWS",
|
||||
"liveiso": "LiveISO",
|
||||
"openstack": "OpenStack",
|
||||
"qcow2": "qcow2",
|
||||
"vmdk": "VMWare",
|
||||
"ext4-filesystem": "Raw-filesystem",
|
||||
"partitioned-disk": "Partitioned-disk",
|
||||
"tar": "Tar",
|
||||
"fedora-iot-commit": "fedora-iot-commit",
|
||||
"rhel-edge-commit": "rhel-edge-commit",
|
||||
"test_type": "test_type", // used only in json_test.go
|
||||
"test_type_invalid": "test_type_invalid", // used only in json_test.go
|
||||
"vhd": "Azure",
|
||||
"ami": "AWS",
|
||||
"liveiso": "LiveISO",
|
||||
"openstack": "OpenStack",
|
||||
"qcow2": "qcow2",
|
||||
"vmdk": "VMWare",
|
||||
"ext4-filesystem": "Raw-filesystem",
|
||||
"partitioned-disk": "Partitioned-disk",
|
||||
"tar": "Tar",
|
||||
"fedora-iot-commit": "fedora-iot-commit",
|
||||
"rhel-edge-commit": "rhel-edge-commit",
|
||||
"rhel-edge-container": "rhen-edge-container",
|
||||
"test_type": "test_type", // used only in json_test.go
|
||||
"test_type_invalid": "test_type_invalid", // used only in json_test.go
|
||||
}
|
||||
|
||||
func imageTypeToCompatString(imgType distro.ImageType) string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue