image: add image kind abstraction

This abstracts away the manifest instantiation. The idea is that we define one
of these image kind types to represent a group of image types that are
sufficiently similar. Each image kind will have a struct with with all the
properties that can be customised for the image and a function to turn that into
an actual manifest. This is similar to how distro/fedora/manifest.go and
cmd/osbuild-playground works today, and aspires to move these closer together
and to eventually make the distro definitions simpler.

For now cmd/osbuild-playground is moved over to using the new abstraction.
This commit is contained in:
Tom Gundersen 2022-07-10 13:45:24 +01:00 committed by Christian Kellner
parent ce40e1d810
commit 5a15608c89
5 changed files with 63 additions and 51 deletions

View file

@ -12,21 +12,13 @@ import (
"github.com/osbuild/osbuild-composer/internal/common" "github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/distroregistry" "github.com/osbuild/osbuild-composer/internal/distroregistry"
"github.com/osbuild/osbuild-composer/internal/manifest" "github.com/osbuild/osbuild-composer/internal/image"
"github.com/osbuild/osbuild-composer/internal/rpmmd" "github.com/osbuild/osbuild-composer/internal/rpmmd"
"github.com/osbuild/osbuild-composer/internal/runner"
) )
var ImageTypes = make(map[string]ImageType) var ImageTypes = make(map[string]image.ImageKind)
type ImageType interface { func AddImageType(img image.ImageKind) {
Name() string
InstantiateManifest(m *manifest.Manifest, repos []rpmmd.RepoConfig, runner runner.Runner) error
GetExports() []string
GetCheckpoints() []string
}
func AddImageType(img ImageType) {
ImageTypes[img.Name()] = img ImageTypes[img.Name()] = img
} }

View file

@ -1,6 +1,9 @@
package main package main
import ( import (
"math/rand"
"github.com/osbuild/osbuild-composer/internal/artifact"
"github.com/osbuild/osbuild-composer/internal/manifest" "github.com/osbuild/osbuild-composer/internal/manifest"
"github.com/osbuild/osbuild-composer/internal/platform" "github.com/osbuild/osbuild-composer/internal/platform"
"github.com/osbuild/osbuild-composer/internal/rpmmd" "github.com/osbuild/osbuild-composer/internal/rpmmd"
@ -36,11 +39,15 @@ func init() {
// Return nil when you are done, or an error if something // Return nil when you are done, or an error if something
// went wrong. Your manifest will be streamed to osbuild // went wrong. Your manifest will be streamed to osbuild
// for building. // for building.
func (img *MyContainer) InstantiateManifest(m *manifest.Manifest, repos []rpmmd.RepoConfig, runner runner.Runner) error { func (img *MyContainer) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
// Let's create a simple OCI container! // Let's create a simple OCI container!
// configure a build pipeline // configure a build pipeline
build := manifest.NewBuild(m, runner, repos) build := manifest.NewBuild(m, runner, repos)
build.Checkpoint()
// create a minimal non-bootable OS tree // create a minimal non-bootable OS tree
os := manifest.NewOS(m, build, &platform.X86{}, repos) os := manifest.NewOS(m, build, &platform.X86{}, repos)
@ -50,26 +57,8 @@ func (img *MyContainer) InstantiateManifest(m *manifest.Manifest, repos []rpmmd.
os.OSCustomizations.Timezone = "UTC" os.OSCustomizations.Timezone = "UTC"
// create an OCI container containing the OS tree created above // create an OCI container containing the OS tree created above
manifest.NewOCIContainer(m, build, os) container := manifest.NewOCIContainer(m, build, os)
artifact := container.Export()
return nil return artifact, nil
}
// GetExports returns a list of the pipelines osbuild should export.
// These are the pipelines containing the artefact you want returned.
//
// TODO: Move this to be implemented in terms ofthe Manifest package.
// We should not need to know the pipeline names.
func (img *MyContainer) GetExports() []string {
return []string{"container"}
}
// GetCheckpoints returns a list of the pipelines osbuild should
// checkpoint. These are the pipelines likely to be reusable in
// future runs.
//
// TODO: Move this to be implemented in terms ofthe Manifest package.
// We should not need to know the pipeline names.
func (img *MyContainer) GetCheckpoints() []string {
return []string{"build"}
} }

View file

@ -3,6 +3,7 @@ package main
import ( import (
"math/rand" "math/rand"
"github.com/osbuild/osbuild-composer/internal/artifact"
"github.com/osbuild/osbuild-composer/internal/disk" "github.com/osbuild/osbuild-composer/internal/disk"
"github.com/osbuild/osbuild-composer/internal/manifest" "github.com/osbuild/osbuild-composer/internal/manifest"
"github.com/osbuild/osbuild-composer/internal/platform" "github.com/osbuild/osbuild-composer/internal/platform"
@ -22,11 +23,15 @@ func init() {
AddImageType(&MyImage{}) AddImageType(&MyImage{})
} }
func (img *MyImage) InstantiateManifest(m *manifest.Manifest, repos []rpmmd.RepoConfig, runner runner.Runner) error { func (img *MyImage) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
// Let's create a simple raw image! // Let's create a simple raw image!
// configure a build pipeline // configure a build pipeline
build := manifest.NewBuild(m, runner, repos) build := manifest.NewBuild(m, runner, repos)
build.Checkpoint()
// create an x86_64 platform with bios boot // create an x86_64 platform with bios boot
platform := &platform.X86{ platform := &platform.X86{
@ -34,9 +39,7 @@ func (img *MyImage) InstantiateManifest(m *manifest.Manifest, repos []rpmmd.Repo
} }
// TODO: add helper // TODO: add helper
// math/rand is good enough in this case pt, err := disk.NewPartitionTable(&basePT, nil, 0, false, rng)
/* #nosec G404 */
pt, err := disk.NewPartitionTable(&basePT, nil, 0, false, rand.New(rand.NewSource(0)))
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -47,16 +50,8 @@ func (img *MyImage) InstantiateManifest(m *manifest.Manifest, repos []rpmmd.Repo
os.KernelName = "kernel" // use the default fedora kernel os.KernelName = "kernel" // use the default fedora kernel
// create a raw image containing the OS tree created above // create a raw image containing the OS tree created above
manifest.NewRawImage(m, build, os) raw := manifest.NewRawImage(m, build, os)
artifact := raw.Export()
return nil return artifact, nil
}
// TODO: make internal
func (img *MyImage) GetExports() []string {
return []string{"image"}
}
func (img *MyImage) GetCheckpoints() []string {
return []string{"build"}
} }

View file

@ -2,18 +2,20 @@ package main
import ( import (
"fmt" "fmt"
"math/rand"
"os" "os"
"path" "path"
"github.com/osbuild/osbuild-composer/internal/distro" "github.com/osbuild/osbuild-composer/internal/distro"
"github.com/osbuild/osbuild-composer/internal/dnfjson" "github.com/osbuild/osbuild-composer/internal/dnfjson"
"github.com/osbuild/osbuild-composer/internal/image"
"github.com/osbuild/osbuild-composer/internal/manifest" "github.com/osbuild/osbuild-composer/internal/manifest"
"github.com/osbuild/osbuild-composer/internal/osbuild" "github.com/osbuild/osbuild-composer/internal/osbuild"
"github.com/osbuild/osbuild-composer/internal/rpmmd" "github.com/osbuild/osbuild-composer/internal/rpmmd"
"github.com/osbuild/osbuild-composer/internal/runner" "github.com/osbuild/osbuild-composer/internal/runner"
) )
func RunPlayground(img ImageType, d distro.Distro, arch distro.Arch, repos map[string][]rpmmd.RepoConfig, state_dir string) { func RunPlayground(img image.ImageKind, d distro.Distro, arch distro.Arch, repos map[string][]rpmmd.RepoConfig, state_dir string) {
solver := dnfjson.NewSolver(d.ModulePlatformID(), d.Releasever(), arch.Name(), path.Join(state_dir, "rpmmd")) solver := dnfjson.NewSolver(d.ModulePlatformID(), d.Releasever(), arch.Name(), path.Join(state_dir, "rpmmd"))
solver.SetDNFJSONPath(findDnfJsonBin()) solver.SetDNFJSONPath(findDnfJsonBin())
@ -23,8 +25,11 @@ func RunPlayground(img ImageType, d distro.Distro, arch distro.Arch, repos map[s
manifest := manifest.New() manifest := manifest.New()
/* #nosec G404 */
rnd := rand.New(rand.NewSource(0))
// TODO: query distro for runner // TODO: query distro for runner
err := img.InstantiateManifest(&manifest, repos[arch.Name()], &runner.Fedora{Version: 36}) artifact, err := img.InstantiateManifest(&manifest, repos[arch.Name()], &runner.Fedora{Version: 36}, rnd)
if err != nil { if err != nil {
panic("InstantiateManifest() failed: " + err.Error()) panic("InstantiateManifest() failed: " + err.Error())
} }
@ -50,8 +55,10 @@ func RunPlayground(img ImageType, d distro.Distro, arch distro.Arch, repos map[s
store := path.Join(state_dir, "osbuild-store") store := path.Join(state_dir, "osbuild-store")
_, err = osbuild.RunOSBuild(bytes, store, "./", img.GetExports(), []string{"build"}, false, os.Stdout) _, err = osbuild.RunOSBuild(bytes, store, "./", manifest.GetExports(), manifest.GetCheckpoints(), false, os.Stdout)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "could not run osbuild: %s", err.Error()) fmt.Fprintf(os.Stderr, "could not run osbuild: %s", err.Error())
} }
fmt.Fprintf(os.Stderr, "built ./%s/%s (%s)\n", artifact.Export(), artifact.Filename(), artifact.MIMEType())
} }

29
internal/image/image.go Normal file
View file

@ -0,0 +1,29 @@
package image
import (
"math/rand"
"github.com/osbuild/osbuild-composer/internal/artifact"
"github.com/osbuild/osbuild-composer/internal/manifest"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
"github.com/osbuild/osbuild-composer/internal/runner"
)
type ImageKind interface {
Name() string
InstantiateManifest(m *manifest.Manifest, repos []rpmmd.RepoConfig, runner runner.Runner, rng *rand.Rand) (*artifact.Artifact, error)
}
type Base struct {
name string
}
func (img Base) Name() string {
return img.name
}
func NewBase(name string) Base {
return Base{
name: name,
}
}