osbuild-playground: introduce new tool
This is meant for rapid prototyping of single image types and for osbuild development, as an alternative to osbuild-mpp. The same primitives are used as in the image definitions, but without any policy or inheritance applied. The user is expected to only edit `playground.go` and then run the tool to produce osbuild manifests.
This commit is contained in:
parent
a199745796
commit
ff1451d8ce
2 changed files with 159 additions and 0 deletions
116
cmd/osbuild-playground/main.go
Normal file
116
cmd/osbuild-playground/main.go
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/distroregistry"
|
||||
"github.com/osbuild/osbuild-composer/internal/dnfjson"
|
||||
"github.com/osbuild/osbuild-composer/internal/manifest"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
// osbuild-playground is a utility command and is often run from within the
|
||||
// source tree. Find the dnf-json binary in case the osbuild-composer package
|
||||
// isn't installed. This prioritises the local source version over the system
|
||||
// version if run from within the source tree.
|
||||
func findDnfJsonBin() string {
|
||||
locations := []string{"./dnf-json", "/usr/libexec/osbuild-composer/dnf-json", "/usr/lib/osbuild-composer/dnf-json"}
|
||||
for _, djPath := range locations {
|
||||
_, err := os.Stat(djPath)
|
||||
if !os.IsNotExist(err) {
|
||||
return djPath
|
||||
}
|
||||
}
|
||||
|
||||
// can't run: panic
|
||||
panic(fmt.Sprintf("could not find 'dnf-json' in any of the known paths: %+v", locations))
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Path to MyOptions or '-' for stdin
|
||||
myOptionsArg := flag.Arg(0)
|
||||
|
||||
myOptions := &MyOptions{}
|
||||
if myOptionsArg != "" {
|
||||
var reader io.Reader
|
||||
if myOptionsArg == "-" {
|
||||
reader = os.Stdin
|
||||
} else {
|
||||
var err error
|
||||
reader, err = os.Open(myOptionsArg)
|
||||
if err != nil {
|
||||
panic("Could not open path to image options: " + err.Error())
|
||||
}
|
||||
}
|
||||
file, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
panic("Could not read image options: " + err.Error())
|
||||
}
|
||||
err = json.Unmarshal(file, &myOptions)
|
||||
if err != nil {
|
||||
panic("Could not parse image options: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
distros := distroregistry.NewDefault()
|
||||
d := distros.FromHost()
|
||||
if d == nil {
|
||||
panic("host distro not supported")
|
||||
}
|
||||
|
||||
arch, err := d.GetArch(common.CurrentArch())
|
||||
if err != nil {
|
||||
panic("host arch not supported")
|
||||
}
|
||||
|
||||
repos, err := rpmmd.LoadRepositories([]string{"./"}, d.Name())
|
||||
if err != nil {
|
||||
panic("could not load repositories for distro " + d.Name())
|
||||
}
|
||||
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
panic("os.UserHomeDir(): " + err.Error())
|
||||
}
|
||||
|
||||
solver := dnfjson.NewSolver(d.ModulePlatformID(), d.Releasever(), arch.Name(), path.Join(home, ".cache/osbuild-playground/rpmmd"))
|
||||
solver.SetDNFJSONPath(findDnfJsonBin())
|
||||
|
||||
// Set cache size to 3 GiB
|
||||
solver.SetMaxCacheSize(1 * 1024 * 1024 * 1024)
|
||||
|
||||
manifest := manifest.New()
|
||||
|
||||
// TODO: figure out the runner situation
|
||||
err = MyManifest(&manifest, myOptions, repos[arch.Name()], "org.osbuild.fedora36")
|
||||
if err != nil {
|
||||
panic("MyManifest() failed: " + err.Error())
|
||||
}
|
||||
|
||||
packageSpecs := make(map[string][]rpmmd.PackageSpec)
|
||||
for name, chain := range manifest.GetPackageSetChains() {
|
||||
packages, err := solver.Depsolve(chain)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to depsolve for pipeline %s: %s\n", name, err.Error()))
|
||||
}
|
||||
packageSpecs[name] = packages
|
||||
}
|
||||
|
||||
bytes, err := manifest.Serialize(packageSpecs)
|
||||
if err != nil {
|
||||
panic("failed to serialize manifest: " + err.Error())
|
||||
}
|
||||
|
||||
os.Stdout.Write(bytes)
|
||||
if err := solver.CleanCache(); err != nil {
|
||||
// print to stderr but don't exit with error
|
||||
fmt.Fprintf(os.Stderr, "could not clean dnf cache: %s", err.Error())
|
||||
}
|
||||
}
|
||||
43
cmd/osbuild-playground/playground.go
Normal file
43
cmd/osbuild-playground/playground.go
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/osbuild/osbuild-composer/internal/manifest"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
// MyOptions contains the arguments passed in as a JSON blob.
|
||||
// You can replace them with whatever you want to use to
|
||||
// configure your image. In the current example they are
|
||||
// unused.
|
||||
type MyOptions struct {
|
||||
MyOption string `json:"my_option"`
|
||||
}
|
||||
|
||||
// Build your manifest by attaching pipelines to it
|
||||
//
|
||||
// @m is the manifest you are constructing
|
||||
// @options are what was passed in on the commandline
|
||||
// @repos are the default repositories for the host OS/arch
|
||||
// @runner is needed by any build pipelines
|
||||
//
|
||||
// Return nil when you are done, or an error if something
|
||||
// went wrong. Your manifest will be streamed to stdout and
|
||||
// can be piped directly to either jq for inspection or
|
||||
// osbuild for building.
|
||||
func MyManifest(m *manifest.Manifest, options *MyOptions, repos []rpmmd.RepoConfig, runner string) error {
|
||||
// Let's create a simple OCI container!
|
||||
|
||||
// configure a build pipeline
|
||||
build := manifest.NewBuildPipeline(m, runner, repos)
|
||||
|
||||
// create a non-bootable OS tree containing the `core` comps group
|
||||
os := manifest.NewOSPipeline(m, build, false, "", "", repos, nil, manifest.BOOTLOADER_GRUB, "", "")
|
||||
os.ExtraBasePackages = []string{
|
||||
"@core",
|
||||
}
|
||||
|
||||
// create an OCI container containing the OS tree created above
|
||||
manifest.NewOCIContainerPipeline(m, build, &os.BasePipeline, "x86_64", "my-container.tar")
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue