osbuild1: DELETED

This commit is contained in:
Achilleas Koutsou 2022-07-12 12:37:29 +02:00
parent dcef56c75a
commit 01d87b4e60
57 changed files with 0 additions and 1976 deletions

View file

@ -1,55 +0,0 @@
package osbuild1
import (
"encoding/json"
"errors"
)
// An Assembler turns a filesystem tree into a target image.
type Assembler struct {
Name string `json:"name"`
Options AssemblerOptions `json:"options"`
}
// AssemblerOptions specify the operations of a given assembler-type.
type AssemblerOptions interface {
isAssemblerOptions()
}
type rawAssembler struct {
Name string `json:"name"`
Options json.RawMessage `json:"options"`
}
// UnmarshalJSON unmarshals JSON into an Assembler object. Each type of
// assembler has a custom unmarshaller for its options, selected based on the
// stage name.
func (assembler *Assembler) UnmarshalJSON(data []byte) error {
var rawAssembler rawAssembler
err := json.Unmarshal(data, &rawAssembler)
if err != nil {
return err
}
var options AssemblerOptions
switch rawAssembler.Name {
case "org.osbuild.ostree.commit":
options = new(OSTreeCommitAssemblerOptions)
case "org.osbuild.qemu":
options = new(QEMUAssemblerOptions)
case "org.osbuild.rawfs":
options = new(RawFSAssemblerOptions)
case "org.osbuild.tar":
options = new(TarAssemblerOptions)
default:
return errors.New("unexpected assembler name")
}
err = json.Unmarshal(rawAssembler.Options, options)
if err != nil {
return err
}
assembler.Name = rawAssembler.Name
assembler.Options = options
return nil
}

View file

@ -1,171 +0,0 @@
package osbuild1
import (
"encoding/json"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestAssembler_UnmarshalJSON(t *testing.T) {
tests := []struct {
name string
assembler Assembler
data []byte
errorExpected bool
}{
{
// invalid JSON - note the missing brace at the end of the string
name: "invalid json",
data: []byte(`{"name":"org.osbuild.tar","options":{"filename":""}`),
errorExpected: true,
},
{
// valid JSON, but with an unknown assembler (org.osbuild.foo)
name: "unknown assembler",
data: []byte(`{"name":"org.osbuild.foo","options":{"bar":null}}`),
errorExpected: true,
},
{
name: "missing options",
data: []byte(`{"name":"org.osbuild.rawfs"`),
errorExpected: true,
},
{
name: "missing name",
data: []byte(`{"options":{"bar":null}}`),
errorExpected: true,
},
{
name: "qemu assembler empty",
assembler: Assembler{
Name: "org.osbuild.qemu",
Options: &QEMUAssemblerOptions{},
},
data: []byte(`{"name":"org.osbuild.qemu","options":{"format":"","filename":"","size":0,"ptuuid":"","pttype":"","partitions":null}}`),
},
{
name: "qemu assembler full",
assembler: Assembler{
Name: "org.osbuild.qemu",
Options: &QEMUAssemblerOptions{
Format: "qcow2",
Filename: "disk.qcow2",
Size: 2147483648,
PTUUID: "0x14fc63d2",
PTType: "mbr",
Partitions: []QEMUPartition{QEMUPartition{
Start: 2048,
Bootable: true,
Filesystem: &QEMUFilesystem{
Type: "ext4",
UUID: "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
Label: "root",
Mountpoint: "/",
},
}},
},
},
data: []byte(`{"name":"org.osbuild.qemu","options":{"format":"qcow2","filename":"disk.qcow2","size":2147483648,"ptuuid":"0x14fc63d2","pttype":"mbr","partitions":[{"start":2048,"bootable":true,"filesystem":{"type":"ext4","uuid":"76a22bf4-f153-4541-b6c7-0332c0dfaeac","label":"root","mountpoint":"/"}}]}}`),
},
{
name: "tar assembler empty",
assembler: Assembler{
Name: "org.osbuild.tar",
Options: &TarAssemblerOptions{},
},
data: []byte(`{"name":"org.osbuild.tar","options":{"filename":""}}`),
},
{
name: "tar assembler full",
assembler: Assembler{
Name: "org.osbuild.tar",
Options: &TarAssemblerOptions{
Filename: "root.tar.xz",
Compression: "xz",
},
},
data: []byte(`{"name":"org.osbuild.tar","options":{"filename":"root.tar.xz","compression":"xz"}}`),
},
{
name: "rawfs assembler empty",
assembler: Assembler{
Name: "org.osbuild.rawfs",
Options: &RawFSAssemblerOptions{},
},
data: []byte(`{"name":"org.osbuild.rawfs","options":{"filename":"","root_fs_uuid":"00000000-0000-0000-0000-000000000000","size":0}}`),
},
{
name: "rawfs assembler full",
assembler: Assembler{
Name: "org.osbuild.rawfs",
Options: &RawFSAssemblerOptions{
Filename: "filesystem.img",
RootFilesystemUUID: uuid.MustParse("76a22bf4-f153-4541-b6c7-0332c0dfaeac"),
Size: 2147483648,
},
},
data: []byte(`{"name":"org.osbuild.rawfs","options":{"filename":"filesystem.img","root_fs_uuid":"76a22bf4-f153-4541-b6c7-0332c0dfaeac","size":2147483648}}`),
},
{
name: "ostree commit assembler",
assembler: Assembler{
Name: "org.osbuild.ostree.commit",
Options: &OSTreeCommitAssemblerOptions{
Ref: "foo",
Tar: OSTreeCommitAssemblerTarOptions{
Filename: "foo.tar",
},
},
},
data: []byte(`{"name":"org.osbuild.ostree.commit","options":{"ref":"foo","tar":{"filename":"foo.tar"}}}`),
},
}
assert := assert.New(t)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assembler := &tt.assembler
var gotAssembler Assembler
err := gotAssembler.UnmarshalJSON(tt.data)
if tt.errorExpected {
assert.NotNil(err)
return
} else {
assert.Nil(err)
}
gotBytes, err := json.Marshal(assembler)
assert.Nilf(err, "Could not marshal assembler: %v", err)
assert.Equal(tt.data, gotBytes)
assert.Equal(&gotAssembler, assembler)
})
}
}
func TestNewQEMUAssembler(t *testing.T) {
options := &QEMUAssemblerOptions{}
expectedAssembler := &Assembler{
Name: "org.osbuild.qemu",
Options: &QEMUAssemblerOptions{},
}
assert.Equal(t, expectedAssembler, NewQEMUAssembler(options))
}
func TestNewTarAssembler(t *testing.T) {
options := &TarAssemblerOptions{}
expectedAssembler := &Assembler{
Name: "org.osbuild.tar",
Options: &TarAssemblerOptions{},
}
assert.Equal(t, expectedAssembler, NewTarAssembler(options))
}
func TestNewRawFSAssembler(t *testing.T) {
options := &RawFSAssemblerOptions{}
expectedAssembler := &Assembler{
Name: "org.osbuild.rawfs",
Options: &RawFSAssemblerOptions{},
}
assert.Equal(t, expectedAssembler, NewRawFSAssembler(options))
}

View file

@ -1,14 +0,0 @@
package osbuild1
type ChronyStageOptions struct {
Timeservers []string `json:"timeservers"`
}
func (ChronyStageOptions) isStageOptions() {}
func NewChronyStage(options *ChronyStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.chrony",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewChronyStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.chrony",
Options: &ChronyStageOptions{},
}
actualStage := NewChronyStage(&ChronyStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,16 +0,0 @@
package osbuild1
type Secret struct {
Name string `json:"name,omitempty"`
}
type FileSource struct {
URL string `json:"url"`
Secrets *Secret `json:"secrets,omitempty"`
}
// The FilesSourceOptions specifies a custom script to run in the image
type FilesSource struct {
URLs map[string]FileSource `json:"urls"`
}
func (FilesSource) isSource() {}

View file

@ -1,16 +0,0 @@
package osbuild1
type FirewallStageOptions struct {
Ports []string `json:"ports,omitempty"`
EnabledServices []string `json:"enabled_services,omitempty"`
DisabledServices []string `json:"disabled_services,omitempty"`
}
func (FirewallStageOptions) isStageOptions() {}
func NewFirewallStage(options *FirewallStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.firewall",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewFirewallStage(t *testing.T) {
expectedFirewall := &Stage{
Name: "org.osbuild.firewall",
Options: &FirewallStageOptions{},
}
actualFirewall := NewFirewallStage(&FirewallStageOptions{})
assert.Equal(t, expectedFirewall, actualFirewall)
}

View file

@ -1,15 +0,0 @@
package osbuild1
type FirstBootStageOptions struct {
Commands []string `json:"commands"`
WaitForNetwork bool `json:"wait_for_network,omitempty"`
}
func (FirstBootStageOptions) isStageOptions() {}
func NewFirstBootStage(options *FirstBootStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.first-boot",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewFirstBootStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.first-boot",
Options: &FirstBootStageOptions{},
}
actualStage := NewFirstBootStage(&FirstBootStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,21 +0,0 @@
package osbuild1
// A FixBLSStageOptions struct is empty, as the stage takes no options.
//
// The FixBLSStage fixes the paths in the Boot Loader Specification
// snippets installed into /boot. grub2's kernel install script will
// try to guess the correct path to the kernel and bootloader, and adjust
// the boot loader scripts accordingly. When run under OSBuild this does
// not work correctly, so this stage essentially reverts the "fixup".
type FixBLSStageOptions struct {
}
func (FixBLSStageOptions) isStageOptions() {}
// NewFixBLSStage creates a new FixBLSStage.
func NewFixBLSStage() *Stage {
return &Stage{
Name: "org.osbuild.fix-bls",
Options: &FixBLSStageOptions{},
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewFixBLSStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.fix-bls",
Options: &FixBLSStageOptions{},
}
actualStage := NewFixBLSStage()
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,67 +0,0 @@
package osbuild1
import (
"sort"
"github.com/osbuild/osbuild-composer/internal/disk"
)
// The FSTabStageOptions describe the content of the /etc/fstab file.
//
// The structure of the options follows the format of /etc/fstab, except
// that filesystem must be identified by their UUID and ommitted fields
// are set to their defaults (if possible).
type FSTabStageOptions struct {
FileSystems []*FSTabEntry `json:"filesystems"`
}
func (FSTabStageOptions) isStageOptions() {}
// NewFSTabStage creates a now FSTabStage object
func NewFSTabStage(options *FSTabStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.fstab",
Options: options,
}
}
// An FSTabEntry represents one line in /etc/fstab. With the one exception
// that the the spec field must be represented as an UUID.
type FSTabEntry struct {
UUID string `json:"uuid,omitempty"`
Label string `json:"label,omitempty"`
VFSType string `json:"vfs_type"`
Path string `json:"path,omitempty"`
Options string `json:"options,omitempty"`
Freq uint64 `json:"freq,omitempty"`
PassNo uint64 `json:"passno,omitempty"`
}
// AddFilesystem adds one entry to and FSTabStageOptions object.
func (options *FSTabStageOptions) AddFilesystem(id string, vfsType string, path string, opts string, freq uint64, passNo uint64) {
options.FileSystems = append(options.FileSystems, &FSTabEntry{
UUID: id,
VFSType: vfsType,
Path: path,
Options: opts,
Freq: freq,
PassNo: passNo,
})
}
func NewFSTabStageOptions(pt *disk.PartitionTable) *FSTabStageOptions {
var options FSTabStageOptions
genOption := func(mnt disk.Mountable, path []disk.Entity) error {
fsSpec := mnt.GetFSSpec()
fsOptions := mnt.GetFSTabOptions()
options.AddFilesystem(fsSpec.UUID, mnt.GetFSType(), mnt.GetMountpoint(), fsOptions.MntOps, fsOptions.Freq, fsOptions.PassNo)
return nil
}
_ = pt.ForEachMountable(genOption)
// sort the entries by PassNo to maintain backward compatibility
sort.Slice(options.FileSystems, func(i, j int) bool {
return options.FileSystems[i].PassNo < options.FileSystems[j].PassNo
})
return &options
}

View file

@ -1,52 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewFSTabStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.fstab",
Options: &FSTabStageOptions{},
}
actualStage := NewFSTabStage(&FSTabStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}
func TestAddFilesystem(t *testing.T) {
options := &FSTabStageOptions{}
filesystems := []*FSTabEntry{
{
UUID: "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
VFSType: "ext4",
Path: "/",
Options: "defaults",
Freq: 1,
PassNo: 1,
},
{
UUID: "bba22bf4-f153-4541-b6c7-0332c0dfaeac",
VFSType: "xfs",
Path: "/home",
Options: "defaults",
Freq: 1,
PassNo: 2,
},
{
UUID: "cca22bf4-f153-4541-b6c7-0332c0dfaeac",
VFSType: "xfs",
Path: "/var",
Options: "defaults",
Freq: 1,
PassNo: 1,
},
}
for i, fs := range filesystems {
options.AddFilesystem(fs.UUID, fs.VFSType, fs.Path, fs.Options, fs.Freq, fs.PassNo)
assert.Equal(t, options.FileSystems[i], fs)
}
assert.Equal(t, len(filesystems), len(options.FileSystems))
}

View file

@ -1,35 +0,0 @@
package osbuild1
import "github.com/osbuild/osbuild-composer/internal/blueprint"
type GroupsStageOptions struct {
Groups map[string]GroupsStageOptionsGroup `json:"groups"`
}
func (GroupsStageOptions) isStageOptions() {}
type GroupsStageOptionsGroup struct {
Name string `json:"name,omitempty"`
GID *int `json:"gid,omitempty"`
}
func NewGroupsStage(options *GroupsStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.groups",
Options: options,
}
}
func NewGroupsStageOptions(groups []blueprint.GroupCustomization) *GroupsStageOptions {
options := GroupsStageOptions{
Groups: map[string]GroupsStageOptionsGroup{},
}
for _, group := range groups {
options.Groups[group.Name] = GroupsStageOptionsGroup{
GID: group.GID,
}
}
return &options
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewGroupsStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.groups",
Options: &GroupsStageOptions{},
}
actualStage := NewGroupsStage(&GroupsStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,34 +0,0 @@
package osbuild1
import "github.com/google/uuid"
// The GRUB2StageOptions describes the bootloader configuration.
//
// The stage is responsible for installing all bootloader files in
// /boot as well as config files in /etc necessary for regenerating
// the configuration in /boot.
//
// Note that it is the role of an assembler to install any necessary
// bootloaders that are stored in the image outside of any filesystem.
type GRUB2StageOptions struct {
RootFilesystemUUID uuid.UUID `json:"root_fs_uuid"`
BootFilesystemUUID *uuid.UUID `json:"boot_fs_uuid,omitempty"`
KernelOptions string `json:"kernel_opts,omitempty"`
Legacy string `json:"legacy,omitempty"`
UEFI *GRUB2UEFI `json:"uefi,omitempty"`
SavedEntry string `json:"saved_entry,omitempty"`
}
type GRUB2UEFI struct {
Vendor string `json:"vendor"`
}
func (GRUB2StageOptions) isStageOptions() {}
// NewGRUB2Stage creates a new GRUB2 stage object.
func NewGRUB2Stage(options *GRUB2StageOptions) *Stage {
return &Stage{
Name: "org.osbuild.grub2",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewGRUB2Stage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.grub2",
Options: &GRUB2StageOptions{},
}
actualStage := NewGRUB2Stage(&GRUB2StageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,14 +0,0 @@
package osbuild1
type HostnameStageOptions struct {
Hostname string `json:"hostname"`
}
func (HostnameStageOptions) isStageOptions() {}
func NewHostnameStage(options *HostnameStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.hostname",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewHostnameStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.hostname",
Options: &HostnameStageOptions{},
}
actualStage := NewHostnameStage(&HostnameStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,19 +0,0 @@
package osbuild1
// KernelCmdlineStageOptions describe how to create kernel-cmdline stage
//
// Configures the kernel boot parameters, also known as the kernel command line.
type KernelCmdlineStageOptions struct {
RootFsUUID string `json:"root_fs_uuid,omitempty"`
KernelOpts string `json:"kernel_opts,omitempty"`
}
func (KernelCmdlineStageOptions) isStageOptions() {}
// NewKernelCmdlineStage creates a new kernel-cmdline Stage object.
func NewKernelCmdlineStage(options *KernelCmdlineStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.kernel-cmdline",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewKernelCmdlineStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.kernel-cmdline",
Options: &KernelCmdlineStageOptions{},
}
actualStage := NewKernelCmdlineStage(&KernelCmdlineStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,19 +0,0 @@
package osbuild1
type X11Keymap struct {
Layouts []string `json:"layouts"`
}
type KeymapStageOptions struct {
Keymap string `json:"keymap"`
X11Keymap *X11Keymap `json:"x11-keymap,omitempty"`
}
func (KeymapStageOptions) isStageOptions() {}
func NewKeymapStage(options *KeymapStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.keymap",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewKeymapStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.keymap",
Options: &KeymapStageOptions{},
}
actualStage := NewKeymapStage(&KeymapStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,19 +0,0 @@
package osbuild1
// The LocaleStageOptions describes the image's locale.
//
// A locale is typically specified as language_[territory], where language
// is specified in ISO 639 and territory in ISO 3166.
type LocaleStageOptions struct {
Language string `json:"language"`
}
func (LocaleStageOptions) isStageOptions() {}
// NewLocaleStage creates a new Locale Stage object.
func NewLocaleStage(options *LocaleStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.locale",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewLocaleStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.locale",
Options: &LocaleStageOptions{},
}
actualStage := NewLocaleStage(&LocaleStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,47 +0,0 @@
// Package osbuild provides primitives for representing and (un)marshalling
// OSBuild (schema v1) types.
package osbuild1
// A Manifest represents an OSBuild source and pipeline manifest
type Manifest struct {
Sources Sources `json:"sources"`
Pipeline Pipeline `json:"pipeline"`
}
// A Pipeline represents an OSBuild pipeline
type Pipeline struct {
// The build environment which can run this pipeline
Build *Build `json:"build,omitempty"`
// Sequence of stages that produce the filesystem tree, which is the
// payload of the produced image.
Stages []*Stage `json:"stages,omitempty"`
// Assembler that assembles the filesystem tree into the target image.
Assembler *Assembler `json:"assembler,omitempty"`
}
type Build struct {
// Pipeline describes how to create the build root
Pipeline *Pipeline `json:"pipeline"`
// The runner to use in this build root
Runner string `json:"runner"`
}
// SetBuild sets the pipeline and runner for generating the build environment
// for a pipeline.
func (p *Pipeline) SetBuild(pipeline *Pipeline, runner string) {
p.Build = &Build{
Pipeline: pipeline,
Runner: runner,
}
}
// AddStage appends a stage to the list of stages of a pipeline. The stages
// will be executed in the order they are appended.
func (p *Pipeline) AddStage(stage *Stage) {
p.Stages = append(p.Stages, stage)
}
// SetAssembler sets the assembler for a pipeline.
func (p *Pipeline) SetAssembler(assembler *Assembler) {
p.Assembler = assembler
}

View file

@ -1,59 +0,0 @@
// Package osbuild provides primitives for representing and (un)marshalling
// OSBuild types.
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPipeline_SetBuild(t *testing.T) {
expectedPipeline := &Pipeline{
Build: &Build{
Pipeline: &Pipeline{},
Runner: "org.osbuild.fedora32",
},
}
actualPipeline := &Pipeline{}
actualPipeline.SetBuild(&Pipeline{}, "org.osbuild.fedora32")
assert.Equal(t, expectedPipeline, actualPipeline)
}
func TestPipeline_AddStage(t *testing.T) {
expectedPipeline := &Pipeline{
Build: &Build{
Pipeline: &Pipeline{},
Runner: "org.osbuild.fedora32",
},
Stages: []*Stage{
{
Name: "org.osbuild.rpm",
},
},
}
actualPipeline := &Pipeline{
Build: &Build{
Pipeline: &Pipeline{},
Runner: "org.osbuild.fedora32",
},
}
actualPipeline.AddStage(&Stage{
Name: "org.osbuild.rpm",
})
assert.Equal(t, expectedPipeline, actualPipeline)
assert.Equal(t, 1, len(actualPipeline.Stages))
}
func TestPipeline_SetAssembler(t *testing.T) {
expectedPipeline := &Pipeline{
Assembler: &Assembler{
Name: "org.osbuild.testassembler",
},
}
actualPipeline := &Pipeline{}
actualPipeline.SetAssembler(&Assembler{
Name: "org.osbuild.testassembler",
})
assert.Equal(t, expectedPipeline, actualPipeline)
}

View file

@ -1,43 +0,0 @@
package osbuild1
// OSTreeCommitAssemblerOptions desrcibe how to assemble a tree into an OSTree commit.
type OSTreeCommitAssemblerOptions struct {
Ref string `json:"ref"`
Parent string `json:"parent,omitempty"`
Tar OSTreeCommitAssemblerTarOptions `json:"tar"`
}
// OSTreeCommitAssemblerTarOptions desrcibes the output tarball
type OSTreeCommitAssemblerTarOptions struct {
Filename string `json:"filename"`
}
func (OSTreeCommitAssemblerOptions) isAssemblerOptions() {}
// NewOSTreeCommitAssembler creates a new OSTree Commit Assembler object.
func NewOSTreeCommitAssembler(options *OSTreeCommitAssemblerOptions) *Assembler {
return &Assembler{
Name: "org.osbuild.ostree.commit",
Options: options,
}
}
type OSTreeCommitStageMetadata struct {
Compose OSTreeCommitStageMetadataCompose `json:"compose"`
}
type OSTreeCommitStageMetadataCompose struct {
Ref string `json:"ref"`
OSTreeNMetadataTotal int `json:"ostree-n-metadata-total"`
OSTreeNMetadataWritten int `json:"ostree-n-metadata-written"`
OSTreeNContentTotal int `json:"ostree-n-content-total"`
OSTreeNContentWritten int `json:"ostree-n-content-written"`
OSTreeNCacheHits int `json:"ostree-n-cache-hits"`
OSTreeContentBytesWritten int `json:"ostree-content-bytes-written"`
OSTreeCommit string `json:"ostree-commit"`
OSTreeContentChecksum string `json:"ostree-content-checksum"`
OSTreeTimestamp string `json:"ostree-timestamp"`
RPMOSTreeInputHash string `json:"rpm-ostree-inputhash"`
}
func (OSTreeCommitStageMetadata) isStageMetadata() {}

View file

@ -1,108 +0,0 @@
package osbuild1
import "github.com/osbuild/osbuild-composer/internal/disk"
type VMDKSubformat string
const (
VMDKSubformatMonolithicSparse VMDKSubformat = "monolithicSparse"
VMDKSubformatMonolithicFlat VMDKSubformat = "monolithicFlat"
VMDKSubformatTwoGbMaxExtentSparse VMDKSubformat = "twoGbMaxExtentSparse"
VMDKSubformatTwoGbMaxExtentFlat VMDKSubformat = "twoGbMaxExtentFlat"
VMDKSubformatStreamOptimized VMDKSubformat = "streamOptimized"
)
// QEMUAssemblerOptions desrcibe how to assemble a tree into an image using qemu.
//
// The assembler creates an image of the given size, adds a GRUB2 bootloader
// and if necessary and a partition table to it with the given PTUUID
// containing the indicated partitions. Finally, the image is converted into
// the target format and stored with the given filename.
type QEMUAssemblerOptions struct {
Bootloader *QEMUBootloader `json:"bootloader,omitempty"`
Format string `json:"format"`
Qcow2Compat string `json:"qcow2_compat,omitempty"`
VMDKSubformat VMDKSubformat `json:"vmdk_subformat,omitempty"`
Filename string `json:"filename"`
Size uint64 `json:"size"`
PTUUID string `json:"ptuuid"`
PTType string `json:"pttype"`
Partitions []QEMUPartition `json:"partitions"`
}
type QEMUPartition struct {
Start uint64 `json:"start"`
Size uint64 `json:"size,omitempty"`
Type string `json:"type,omitempty"`
Bootable bool `json:"bootable,omitempty"`
UUID string `json:"uuid,omitempty"`
Filesystem *QEMUFilesystem `json:"filesystem,omitempty"`
}
type QEMUFilesystem struct {
Type string `json:"type"`
UUID string `json:"uuid"`
Label string `json:"label,omitempty"`
Mountpoint string `json:"mountpoint"`
}
type QEMUBootloader struct {
Type string `json:"type,omitempty"`
Platform string `json:"platform,omitempty"`
}
func (QEMUAssemblerOptions) isAssemblerOptions() {}
// NewQEMUAssembler creates a new QEMU Assembler object.
func NewQEMUAssembler(options *QEMUAssemblerOptions) *Assembler {
return &Assembler{
Name: "org.osbuild.qemu",
Options: options,
}
}
// NewQEMUAssemblerOptions creates and returns QEMUAssemblerOptions based on
// the given PartitionTable.
func NewQEMUAssemblerOptions(pt *disk.PartitionTable) QEMUAssemblerOptions {
var partitions []QEMUPartition
for idx := range pt.Partitions {
partitions = append(partitions, NewQEMUPartition(&pt.Partitions[idx]))
}
return QEMUAssemblerOptions{
Size: pt.Size,
PTUUID: pt.UUID,
PTType: pt.Type,
Partitions: partitions,
}
}
// NewQEMUPartition creates and returns a QEMUPartition based on the given
// Partition.
func NewQEMUPartition(p *disk.Partition) QEMUPartition {
var fs *QEMUFilesystem
if p.Payload != nil {
// NOTE: Partition Payload for QEMU assembler should always be a Filesystem
f := NewQEMUFilesystem(p.Payload.(*disk.Filesystem))
fs = &f
}
return QEMUPartition{
Start: p.Start,
Size: p.Size,
Type: p.Type,
Bootable: p.Bootable,
UUID: p.UUID,
Filesystem: fs,
}
}
// NewQEMUFilesystem creates and returns a QEMUFilesystem based on the given
// Filesystem.
func NewQEMUFilesystem(fs *disk.Filesystem) QEMUFilesystem {
return QEMUFilesystem{
Type: fs.Type,
UUID: fs.UUID,
Label: fs.Label,
Mountpoint: fs.Mountpoint,
}
}

View file

@ -1,22 +0,0 @@
package osbuild1
import "github.com/google/uuid"
// RawFSAssemblerOptions desrcibe how to assemble a tree into a raw filesystem
// image.
type RawFSAssemblerOptions struct {
Filename string `json:"filename"`
RootFilesystemUUID uuid.UUID `json:"root_fs_uuid"`
Size uint64 `json:"size"`
FilesystemType string `json:"fs_type,omitempty"`
}
func (RawFSAssemblerOptions) isAssemblerOptions() {}
// NewRawFSAssembler creates a new RawFS Assembler object.
func NewRawFSAssembler(options *RawFSAssemblerOptions) *Assembler {
return &Assembler{
Name: "org.osbuild.rawfs",
Options: options,
}
}

View file

@ -1,15 +0,0 @@
package osbuild1
type ResolvConfStageOptions struct {
Nameserver []string `json:"nameserver,omitempty"`
Search []string `json:"search,omitempty"`
}
func (ResolvConfStageOptions) isStageOptions() {}
func NewResolvConfStage(options *ResolvConfStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.resolv-conf",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewResolvConfStageStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.resolv-conf",
Options: &ResolvConfStageOptions{},
}
actualStage := NewResolvConfStage(&ResolvConfStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,130 +0,0 @@
package osbuild1
import (
"encoding/json"
"fmt"
"io"
"strings"
)
type StageResult struct {
Name string `json:"name"`
Options json.RawMessage `json:"options"`
Success bool `json:"success"`
Output string `json:"output"`
Metadata StageMetadata `json:"metadata"`
}
// StageMetadata specify the metadata of a given stage-type.
type StageMetadata interface {
isStageMetadata()
}
type RawStageMetadata json.RawMessage
func (RawStageMetadata) isStageMetadata() {}
type rawStageResult struct {
Name string `json:"name"`
Options json.RawMessage `json:"options"`
Success bool `json:"success"`
Output string `json:"output"`
Metadata json.RawMessage `json:"metadata"`
}
type buildResult struct {
Stages []StageResult `json:"stages"`
TreeID string `json:"tree_id"`
Success bool `json:"success"`
}
type Result struct {
TreeID string `json:"tree_id"`
OutputID string `json:"output_id"`
Build *buildResult `json:"build"`
Stages []StageResult `json:"stages"`
Assembler *StageResult `json:"assembler"`
Success bool `json:"success"`
}
func (result *StageResult) UnmarshalJSON(data []byte) error {
var rawStageResult rawStageResult
err := json.Unmarshal(data, &rawStageResult)
if err != nil {
return err
}
var metadata StageMetadata
switch {
case strings.HasSuffix(rawStageResult.Name, "org.osbuild.rpm"):
metadata = new(RPMStageMetadata)
err = json.Unmarshal(rawStageResult.Metadata, metadata)
if err != nil {
return err
}
case strings.HasSuffix(rawStageResult.Name, "org.osbuild.ostree.commit"):
metadata = new(OSTreeCommitStageMetadata)
err = json.Unmarshal(rawStageResult.Metadata, metadata)
if err != nil {
return err
}
default:
metadata = RawStageMetadata(rawStageResult.Metadata)
}
result.Name = rawStageResult.Name
result.Options = rawStageResult.Options
result.Success = rawStageResult.Success
result.Output = rawStageResult.Output
result.Metadata = metadata
return nil
}
func (cr *Result) Write(writer io.Writer) error {
if cr == nil || (cr.Build == nil && len(cr.Stages) == 0 && cr.Assembler == nil) {
fmt.Fprintf(writer, "The compose result is empty.\n")
return nil
}
if cr.Build != nil {
fmt.Fprintf(writer, "Build pipeline:\n")
for _, stage := range cr.Build.Stages {
fmt.Fprintf(writer, "Stage %s\n", stage.Name)
enc := json.NewEncoder(writer)
enc.SetIndent("", " ")
err := enc.Encode(stage.Options)
if err != nil {
return err
}
fmt.Fprintf(writer, "\nOutput:\n%s\n", stage.Output)
}
}
if len(cr.Stages) > 0 {
fmt.Fprintf(writer, "Stages:\n")
for _, stage := range cr.Stages {
fmt.Fprintf(writer, "Stage: %s\n", stage.Name)
enc := json.NewEncoder(writer)
enc.SetIndent("", " ")
err := enc.Encode(stage.Options)
if err != nil {
return err
}
fmt.Fprintf(writer, "\nOutput:\n%s\n", stage.Output)
}
}
if cr.Assembler != nil {
fmt.Fprintf(writer, "Assembler %s:\n", cr.Assembler.Name)
enc := json.NewEncoder(writer)
enc.SetIndent("", " ")
err := enc.Encode(cr.Assembler.Options)
if err != nil {
return err
}
fmt.Fprintf(writer, "\nOutput:\n%s\n", cr.Assembler.Output)
}
return nil
}

View file

@ -1,168 +0,0 @@
package osbuild1
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUnmarshal(t *testing.T) {
resultRaw := `{
"success": true,
"build": {
"success": true,
"stages": [
{
"name": "org.osbuild.rpm",
"id": "9eb0a6f6fd6e2995e107f5bcc6aa3b19643b02ec133bdc8a8ac614860b1bbf2d",
"success": true,
"output": "Building...",
"metadata": {
"packages": [
{
"name": "libgcc",
"version": "10.0.1",
"release": "0.11.fc32",
"epoch": null,
"arch": "x86_64",
"sigmd5": "84fc907a5047aeebaf8da1642925a417",
"sigpgp": null,
"siggpg": "883f0305005f2310139ec3e4c0f7e257e611023e11009f639c5fe64abaa76224dab3a9f70c2714a84c63bd009d1cc184fb4b428dfcd7c3556f4a5f860cc0187740"
},
{
"name": "whois-nls",
"version": "5.5.6",
"release": "1.fc32",
"epoch": null,
"arch": "noarch",
"sigmd5": "f868cd02046630c8ce3a9c48820e2437",
"sigpgp": "89023304000108001d162104963a2beb02009608fe67ea4249fd77499570ff3105025f5a272b000a091049fd77499570ff31ccdb0ffe38b95a55ebf3c021526b3cd4f2358c7e23f7767d1f5ce4b7cccef7b33653c6a96a23022313a818fbaf7abeb41837910f0d3ac15664e02838d5939d38ff459aa0076e248728a032d3ae09ddfaec955f941601081a2e3f9bbd49586fd65c1bc1b31685aeb0405687d1791471eab7359ccf00d5584ddef680e99ebc8a4846316391b9baa68ac8ed8ad696ee16fd625d847f8edd92517df3ea6920a46b77b4f119715a0f619f38835d25e0bd0eb5cfad08cd9c796eace6a2b28f4d3dee552e6068255d9748dc2a1906c951e0ba8aed9922ab24e1f659413a06083f8a0bfea56cfff14bddef23bced449f36bcd369da72f90ddf0512e7b0801ba5a0c8eaa8eb0582c630815e992192042cfb0a7c7239f76219197c2fdf18b6553260c105280806d4f037d7b04bdf3da9fd7e9a207db5c71f7e548f4288928f047c989c4cb9cbb8088eec7bd2fa5c252e693f51a3cfc660f666af6a255a5ca0fd2216d5ccd66cbd9c11afa61067d7f615ec8d0dc0c879b5fe633d8c9443f97285da597e4da8a3993af36f0be06acfa9b8058ec70bbc78b876e4c6c5d2108fb05c15a74ba48a3d7ded697cbc1748c228d77d1e0794a41fd5240fa67c3ed745fe47555a47c3d6163d8ce95fd6c2d0d6fa48f8e5b411e571e442109b1cb200d9a8117ee08bfe645f96aca34f7b7559622bbab75143dcad59f126ae0d319e6668ebba417e725638c4febf2e",
"siggpg": null
}
]
}
}
]
}
}`
var result Result
err := json.Unmarshal([]byte(resultRaw), &result)
assert.NoError(t, err)
assert.Equal(t, result.Build.Stages[0].Name, "org.osbuild.rpm")
metadata, ok := result.Build.Stages[0].Metadata.(*RPMStageMetadata)
assert.True(t, ok)
package1 := metadata.Packages[0]
assert.Equal(t, package1.Name, "libgcc")
assert.Nil(t, package1.Epoch)
assert.Equal(t, package1.Version, "10.0.1")
assert.Equal(t, package1.Release, "0.11.fc32")
assert.Equal(t, package1.Arch, "x86_64")
assert.Equal(t, package1.SigMD5, "84fc907a5047aeebaf8da1642925a417")
assert.Empty(t, package1.SigPGP)
assert.Equal(t, package1.SigGPG, "883f0305005f2310139ec3e4c0f7e257e611023e11009f639c5fe64abaa76224dab3a9f70c2714a84c63bd009d1cc184fb4b428dfcd7c3556f4a5f860cc0187740")
package2 := metadata.Packages[1]
assert.Equal(t, package2.SigPGP, "89023304000108001d162104963a2beb02009608fe67ea4249fd77499570ff3105025f5a272b000a091049fd77499570ff31ccdb0ffe38b95a55ebf3c021526b3cd4f2358c7e23f7767d1f5ce4b7cccef7b33653c6a96a23022313a818fbaf7abeb41837910f0d3ac15664e02838d5939d38ff459aa0076e248728a032d3ae09ddfaec955f941601081a2e3f9bbd49586fd65c1bc1b31685aeb0405687d1791471eab7359ccf00d5584ddef680e99ebc8a4846316391b9baa68ac8ed8ad696ee16fd625d847f8edd92517df3ea6920a46b77b4f119715a0f619f38835d25e0bd0eb5cfad08cd9c796eace6a2b28f4d3dee552e6068255d9748dc2a1906c951e0ba8aed9922ab24e1f659413a06083f8a0bfea56cfff14bddef23bced449f36bcd369da72f90ddf0512e7b0801ba5a0c8eaa8eb0582c630815e992192042cfb0a7c7239f76219197c2fdf18b6553260c105280806d4f037d7b04bdf3da9fd7e9a207db5c71f7e548f4288928f047c989c4cb9cbb8088eec7bd2fa5c252e693f51a3cfc660f666af6a255a5ca0fd2216d5ccd66cbd9c11afa61067d7f615ec8d0dc0c879b5fe633d8c9443f97285da597e4da8a3993af36f0be06acfa9b8058ec70bbc78b876e4c6c5d2108fb05c15a74ba48a3d7ded697cbc1748c228d77d1e0794a41fd5240fa67c3ed745fe47555a47c3d6163d8ce95fd6c2d0d6fa48f8e5b411e571e442109b1cb200d9a8117ee08bfe645f96aca34f7b7559622bbab75143dcad59f126ae0d319e6668ebba417e725638c4febf2e")
assert.Empty(t, package2.SigGPG)
}
func TestWriteFull(t *testing.T) {
const testOptions = `{"msg": "test"}`
dnfStage := StageResult{
Name: "org.osbuild.rpm",
Options: []byte(testOptions),
Success: true,
Output: "Finished",
Metadata: RPMStageMetadata{
Packages: []RPMPackageMetadata{
{
Name: "foobar",
Epoch: nil,
Version: "1",
Release: "1",
Arch: "noarch",
SigMD5: "deadbeef",
},
},
},
}
testStage := StageResult{
Name: "org.osbuild.test",
Options: []byte(testOptions),
Success: true,
Output: "Finished",
}
testBuild := buildResult{
Stages: []StageResult{testStage},
TreeID: "treeID",
Success: true,
}
testAssembler := StageResult{
Name: "testAssembler",
Options: []byte(testOptions),
Success: true,
Output: "Done",
}
testComposeResult := Result{
TreeID: "TreeID",
OutputID: "OutputID",
Build: &testBuild,
Stages: []StageResult{dnfStage},
Assembler: &testAssembler,
Success: true,
}
var b bytes.Buffer
assert.NoError(t, testComposeResult.Write(&b))
expectedMessage :=
`Build pipeline:
Stage org.osbuild.test
{
"msg": "test"
}
Output:
Finished
Stages:
Stage: org.osbuild.rpm
{
"msg": "test"
}
Output:
Finished
Assembler testAssembler:
{
"msg": "test"
}
Output:
Done
`
assert.Equal(t, expectedMessage, b.String())
}
func TestWriteEmpty(t *testing.T) {
var b bytes.Buffer
var testNilResult *Result
assert.NoError(t, testNilResult.Write(&b))
assert.Equal(t, "The compose result is empty.\n", b.String())
testComposeResult := Result{}
b.Reset()
assert.NoError(t, testComposeResult.Write(&b))
assert.Equal(t, "The compose result is empty.\n", b.String())
}

View file

@ -1,34 +0,0 @@
package osbuild1
// RHSMStageOptions describes configuration of the RHSM stage.
//
// The RHSM stage allows configuration of Red Hat Subscription Manager (RHSM)
// related components. Currently it allows only configuration of the enablement
// state of DNF plugins used by the Subscription Manager.
type RHSMStageOptions struct {
DnfPlugins *RHSMStageOptionsDnfPlugins `json:"dnf-plugins,omitempty"`
}
func (RHSMStageOptions) isStageOptions() {}
// RHSMStageOptionsDnfPlugins describes configuration of all RHSM DNF plugins
type RHSMStageOptionsDnfPlugins struct {
ProductID *RHSMStageOptionsDnfPlugin `json:"product-id,omitempty"`
SubscriptionManager *RHSMStageOptionsDnfPlugin `json:"subscription-manager,omitempty"`
}
// RHSMStageOptionsDnfPlugin describes configuration of a specific RHSM DNF
// plugin
//
// Only the enablement state of a DNF plugin can be currenlty set.
type RHSMStageOptionsDnfPlugin struct {
Enabled bool `json:"enabled"`
}
// NewRHSMStage creates a new RHSM stage
func NewRHSMStage(options *RHSMStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.rhsm",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewRhsmStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.rhsm",
Options: &RHSMStageOptions{},
}
actualStage := NewRHSMStage(&RHSMStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,17 +0,0 @@
package osbuild1
// RPMOSTreeStageOptions configures the invocation of the `rpm-ostree`
// process for generating an ostree commit.
type RPMOSTreeStageOptions struct {
EtcGroupMembers []string `json:"etc_group_members,omitempty"`
}
func (RPMOSTreeStageOptions) isStageOptions() {}
// NewRPMOSTreeStage creates a new rpm-ostree Stage object.
func NewRPMOSTreeStage(options *RPMOSTreeStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.rpm-ostree",
Options: options,
}
}

View file

@ -1,49 +0,0 @@
package osbuild1
// The RPMStageOptions describe the operations of the RPM stage.
//
// The RPM stage installs a given set of packages, identified by their
// content hash. This ensures that given a set of RPM stage options,
// the output is be reproducible, if the underlying tools are.
type RPMStageOptions struct {
GPGKeys []string `json:"gpgkeys,omitempty"`
Packages []RPMPackage `json:"packages"`
}
// RPMPackage represents one RPM, as referenced by its content hash
// (checksum). The files source must indicate where to fetch the given
// RPM. If CheckGPG is `true` the RPM must be signed with one of the
// GPGKeys given in the RPMStageOptions.
type RPMPackage struct {
Checksum string `json:"checksum"`
CheckGPG bool `json:"check_gpg,omitempty"`
}
func (RPMStageOptions) isStageOptions() {}
// NewRPMStage creates a new RPM stage.
func NewRPMStage(options *RPMStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.rpm",
Options: options,
}
}
// RPMStageMetadata gives the set of packages installed by the RPM stage
type RPMStageMetadata struct {
Packages []RPMPackageMetadata `json:"packages"`
}
// RPMPackageMetadata contains the metadata extracted from one RPM header
type RPMPackageMetadata struct {
Name string `json:"name"`
Version string `json:"version"`
Release string `json:"release"`
Epoch *string `json:"epoch"`
Arch string `json:"arch"`
SigMD5 string `json:"sigmd5"`
SigPGP string `json:"sigpgp"`
SigGPG string `json:"siggpg"`
}
func (RPMStageMetadata) isStageMetadata() {}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewRPMStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.rpm",
Options: &RPMStageOptions{},
}
actualStage := NewRPMStage(&RPMStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,24 +0,0 @@
package osbuild1
// The ScriptStageOptions specifies a custom script to run in the image
type ScriptStageOptions struct {
Script string `json:"script"`
}
func (ScriptStageOptions) isStageOptions() {}
// NewScriptStageOptions creates a new script stage options object, with
// the mandatory fields set.
func NewScriptStageOptions(script string) *ScriptStageOptions {
return &ScriptStageOptions{
Script: script,
}
}
// NewScriptStage creates a new Script Stage object.
func NewScriptStage(options *ScriptStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.script",
Options: options,
}
}

View file

@ -1,24 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewScriptStageOptions(t *testing.T) {
expectedOptions := &ScriptStageOptions{
Script: "/root/test.sh",
}
actualOptions := NewScriptStageOptions("/root/test.sh")
assert.Equal(t, expectedOptions, actualOptions)
}
func TestNewScriptStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.script",
Options: &ScriptStageOptions{},
}
actualStage := NewScriptStage(&ScriptStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,28 +0,0 @@
package osbuild1
// The SELinuxStageOptions describe how to apply selinux labels.
//
// A file contexts configuration file is sepcified that describes
// the filesystem labels to apply to the image.
type SELinuxStageOptions struct {
FileContexts string `json:"file_contexts"`
Labels map[string]string `json:"labels,omitempty"`
}
func (SELinuxStageOptions) isStageOptions() {}
// NewSELinuxStageOptions creates a new SELinuxStaeOptions object, with
// the mandatory fields set.
func NewSELinuxStageOptions(fileContexts string) *SELinuxStageOptions {
return &SELinuxStageOptions{
FileContexts: fileContexts,
}
}
// NewSELinuxStage creates a new SELinux Stage object.
func NewSELinuxStage(options *SELinuxStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.selinux",
Options: options,
}
}

View file

@ -1,24 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewSELinuxStageOptions(t *testing.T) {
expectedOptions := &SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
}
actualOptions := NewSELinuxStageOptions("etc/selinux/targeted/contexts/files/file_contexts")
assert.Equal(t, expectedOptions, actualOptions)
}
func TestNewSELinuxStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.selinux",
Options: &SELinuxStageOptions{},
}
actualStage := NewSELinuxStage(&SELinuxStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,43 +0,0 @@
package osbuild1
import (
"encoding/json"
"errors"
)
// A Sources map contains all the sources made available to an osbuild run
type Sources map[string]Source
// Source specifies the operations of a given source-type.
type Source interface {
isSource()
}
type rawSources map[string]json.RawMessage
// UnmarshalJSON unmarshals JSON into a Source object. Each type of source has
// a custom unmarshaller for its options, selected based on the source name.
func (sources *Sources) UnmarshalJSON(data []byte) error {
var rawSources rawSources
err := json.Unmarshal(data, &rawSources)
if err != nil {
return err
}
*sources = make(map[string]Source)
for name, rawSource := range rawSources {
var source Source
switch name {
case "org.osbuild.files":
source = new(FilesSource)
default:
return errors.New("unexpected source name: " + name)
}
err = json.Unmarshal(rawSource, source)
if err != nil {
return err
}
(*sources)[name] = source
}
return nil
}

View file

@ -1,100 +0,0 @@
package osbuild1
import (
"bytes"
"encoding/json"
"reflect"
"testing"
)
func TestSource_UnmarshalJSON(t *testing.T) {
type fields struct {
Name string
Source Source
}
type args struct {
data []byte
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{
name: "invalid json",
args: args{
data: []byte(`{"name":"org.osbuild.foo","options":{"bar":null}`),
},
wantErr: true,
},
{
name: "unknown source",
args: args{
data: []byte(`{"name":"org.osbuild.foo","options":{"bar":null}}`),
},
wantErr: true,
},
{
name: "missing options",
args: args{
data: []byte(`{"name":"org.osbuild.files"}`),
},
wantErr: true,
},
{
name: "missing name",
args: args{
data: []byte(`{"foo":null,"options":{"bar":null}}`),
},
wantErr: true,
},
{
name: "files-empty",
fields: fields{
Name: "org.osbuild.files",
Source: &FilesSource{URLs: map[string]FileSource{}},
},
args: args{
data: []byte(`{"org.osbuild.files":{"urls":{}}}`),
},
},
{
name: "files",
fields: fields{
Name: "org.osbuild.files",
Source: &FilesSource{URLs: map[string]FileSource{
"checksum1": FileSource{URL: "url1"},
"checksum2": FileSource{URL: "url2"},
}},
},
args: args{
data: []byte(`{"org.osbuild.files":{"urls":{"checksum1":{"url":"url1"},"checksum2":{"url":"url2"}}}}`),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sources := &Sources{
tt.fields.Name: tt.fields.Source,
}
var gotSources Sources
if err := gotSources.UnmarshalJSON(tt.args.data); (err != nil) != tt.wantErr {
t.Errorf("Sources.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantErr {
return
}
gotBytes, err := json.Marshal(sources)
if err != nil {
t.Errorf("Could not marshal source: %v", err)
}
if !bytes.Equal(gotBytes, tt.args.data) {
t.Errorf("Expected '%v', got '%v'", string(tt.args.data), string(gotBytes))
}
if !reflect.DeepEqual(&gotSources, sources) {
t.Errorf("got '%v', expected '%v'", &gotSources, sources)
}
})
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
// A Stage transforms a filesystem tree.
type Stage struct {
// Well-known name in reverse domain-name notation, uniquely identifying
// the stage type.
Name string `json:"name"`
// Stage-type specific options fully determining the operations of the
// stage.
Options StageOptions `json:"options"`
}
// StageOptions specify the operations of a given stage-type.
type StageOptions interface {
isStageOptions()
}

View file

@ -1,25 +0,0 @@
package osbuild1
type SysconfigStageOptions struct {
Kernel SysconfigKernelOptions `json:"kernel,omitempty"`
Network SysconfigNetworkOptions `json:"network,omitempty"`
}
type SysconfigNetworkOptions struct {
Networking bool `json:"networking,omitempty"`
NoZeroConf bool `json:"no_zero_conf,omitempty"`
}
type SysconfigKernelOptions struct {
UpdateDefault bool `json:"update_default,omitempty"`
DefaultKernel string `json:"default_kernel,omitempty"`
}
func (SysconfigStageOptions) isStageOptions() {}
func NewSysconfigStage(options *SysconfigStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.sysconfig",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewSysconfigStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.sysconfig",
Options: &SysconfigStageOptions{},
}
actualStage := NewSysconfigStage(&SysconfigStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,16 +0,0 @@
package osbuild1
type SystemdStageOptions struct {
EnabledServices []string `json:"enabled_services,omitempty"`
DisabledServices []string `json:"disabled_services,omitempty"`
DefaultTarget string `json:"default_target,omitempty"`
}
func (SystemdStageOptions) isStageOptions() {}
func NewSystemdStage(options *SystemdStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.systemd",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewSystemdStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.systemd",
Options: &SystemdStageOptions{},
}
actualStage := NewSystemdStage(&SystemdStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,20 +0,0 @@
package osbuild1
// TarAssemblerOptions desrcibe how to assemble a tree into a tar ball.
//
// The assembler tars and optionally compresses the tree using the provided
// compression type, and stores the output with the given filename.
type TarAssemblerOptions struct {
Filename string `json:"filename"`
Compression string `json:"compression,omitempty"`
}
func (TarAssemblerOptions) isAssemblerOptions() {}
// NewTarAssembler creates a new Tar Assembler object.
func NewTarAssembler(options *TarAssemblerOptions) *Assembler {
return &Assembler{
Name: "org.osbuild.tar",
Options: options,
}
}

View file

@ -1,14 +0,0 @@
package osbuild1
type TimezoneStageOptions struct {
Zone string `json:"zone"`
}
func (TimezoneStageOptions) isStageOptions() {}
func NewTimezoneStage(options *TimezoneStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.timezone",
Options: options,
}
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewTimezoneStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.timezone",
Options: &TimezoneStageOptions{},
}
actualStage := NewTimezoneStage(&TimezoneStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,62 +0,0 @@
package osbuild1
import (
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/crypt"
)
type UsersStageOptions struct {
Users map[string]UsersStageOptionsUser `json:"users"`
}
func (UsersStageOptions) isStageOptions() {}
type UsersStageOptionsUser struct {
UID *int `json:"uid,omitempty"`
GID *int `json:"gid,omitempty"`
Groups []string `json:"groups,omitempty"`
Description *string `json:"description,omitempty"`
Home *string `json:"home,omitempty"`
Shell *string `json:"shell,omitempty"`
Password *string `json:"password,omitempty"`
Key *string `json:"key,omitempty"`
}
func NewUsersStage(options *UsersStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.users",
Options: options,
}
}
func NewUsersStageOptions(userCustomizations []blueprint.UserCustomization) (*UsersStageOptions, error) {
if len(userCustomizations) == 0 {
return nil, nil
}
users := make(map[string]UsersStageOptionsUser, len(userCustomizations))
for _, uc := range userCustomizations {
if uc.Password != nil && !crypt.PasswordIsCrypted(*uc.Password) {
cryptedPassword, err := crypt.CryptSHA512(*uc.Password)
if err != nil {
return nil, err
}
uc.Password = &cryptedPassword
}
user := UsersStageOptionsUser{
UID: uc.UID,
GID: uc.GID,
Groups: uc.Groups,
Description: uc.Description,
Home: uc.Home,
Shell: uc.Shell,
Password: uc.Password,
Key: uc.Key,
}
users[uc.Name] = user
}
return &UsersStageOptions{Users: users}, nil
}

View file

@ -1,16 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewUsersStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.users",
Options: &UsersStageOptions{},
}
actualStage := NewUsersStage(&UsersStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}

View file

@ -1,25 +0,0 @@
package osbuild1
// The ZiplStageOptions describe how to create zipl stage
//
// The only configuration option available is a boot timeout and it is optional
type ZiplStageOptions struct {
Timeout int `json:"timeout,omitempty"`
}
func (ZiplStageOptions) isStageOptions() {}
// NewZiplStageOptions creates a new ZiplStageOptions object with no timeout
func NewZiplStageOptions() *ZiplStageOptions {
return &ZiplStageOptions{
Timeout: 0,
}
}
// NewZiplStage creates a new zipl Stage object.
func NewZiplStage(options *ZiplStageOptions) *Stage {
return &Stage{
Name: "org.osbuild.zipl",
Options: options,
}
}

View file

@ -1,24 +0,0 @@
package osbuild1
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewZiplStageOptions(t *testing.T) {
expectedOptions := &ZiplStageOptions{
Timeout: 0,
}
actualOptions := NewZiplStageOptions()
assert.Equal(t, expectedOptions, actualOptions)
}
func TestNewZiplStage(t *testing.T) {
expectedStage := &Stage{
Name: "org.osbuild.zipl",
Options: &ZiplStageOptions{},
}
actualStage := NewZiplStage(&ZiplStageOptions{})
assert.Equal(t, expectedStage, actualStage)
}