debian-forge-composer/cmd/osbuild-playground/main.go
Tom Gundersen ff1451d8ce 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.
2022-07-04 23:04:29 +01:00

116 lines
3.1 KiB
Go

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())
}
}