Skip to content

Commit

Permalink
cli: implement messy/untested "image-builder manifest"
Browse files Browse the repository at this point in the history
  • Loading branch information
mvo5 committed Oct 30, 2024
1 parent a1cc037 commit edc3d8a
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 6 deletions.
19 changes: 14 additions & 5 deletions cmd/image-builder/list_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,32 @@ var repositoryConfigs = []string{
"/usr/share/osbuild-composer",
}

func listImages(out io.Writer, format string, filterExprs []string) error {
// XXX: move to pkg/reporegistry
func newRepoRegistry() (*reporegistry.RepoRegistry, error) {
// useful for development/debugging, e.g. run:
// go build && IMAGE_BUILDER_EXTRA_REPOS_PATH=../../test/data ./image-builder
if extraReposPath := os.Getenv("IMAGE_BUILDER_EXTRA_REPOS_PATH"); extraReposPath != "" {
repositoryConfigs = append(repositoryConfigs, strings.Split(extraReposPath, ":")...)
}

repos, err := reporegistry.New(repositoryConfigs)
return reporegistry.New(repositoryConfigs)
}

func getFilteredImages(filterExprs []string) ([]FilterResult, error) {
repos, err := newRepoRegistry()
if err != nil {
return err
return nil, err
}
filters, err := NewFilters(filterExprs)
if err != nil {
return err
return nil, err
}
fac := distrofactory.NewDefault()
filteredResult, err := FilterDistros(fac, repos.ListDistros(), filters)
return FilterDistros(fac, repos.ListDistros(), filters)
}

func listImages(out io.Writer, format string, filterExprs []string) error {
filteredResult, err := getFilteredImages(filterExprs)
if err != nil {
return err
}
Expand Down
27 changes: 26 additions & 1 deletion cmd/image-builder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"os"

"github.com/sirupsen/logrus"

"github.com/spf13/cobra"

"github.com/osbuild/images/pkg/arch"
)

var osStdout io.Writer = os.Stdout
Expand All @@ -25,6 +26,19 @@ func cmdListImages(cmd *cobra.Command, args []string) error {
return listImages(osStdout, format, filter)
}

func cmdManifest(cmd *cobra.Command, args []string) error {
distroName := args[0]
imgType := args[1]
var archStr string
if len(args) > 2 {
archStr = args[2]
} else {
archStr = arch.Current().String()
}

return outputManifest(osStdout, distroName, imgType, archStr)
}

func run() error {
// images logs a bunch of stuff to Debug/Info that we we do not
// want to show
Expand All @@ -44,13 +58,24 @@ operating sytsems like centos and RHEL with easy customizations support.`,
// distro names?
listImagesCmd := &cobra.Command{
Use: "list-images",
Short: "List buildable images, use --filter to limit further",
RunE: cmdListImages,
SilenceUsage: true,
}
listImagesCmd.Flags().StringArray("filter", nil, "Filter distributions by a specific criteria")
listImagesCmd.Flags().String("format", "", "Output in a specific format (text,json)")
rootCmd.AddCommand(listImagesCmd)

manifestCmd := &cobra.Command{
Use: "manifest <distro> <image-type> [<arch>]",
Short: "Build manifest for the given distro/image-type, e.g. centos-9 qcow2",
RunE: cmdManifest,
SilenceUsage: true,
Args: cobra.MinimumNArgs(2),
Hidden: true,
}
rootCmd.AddCommand(manifestCmd)

return rootCmd.Execute()
}

Expand Down
94 changes: 94 additions & 0 deletions cmd/image-builder/manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package main

import (
"fmt"
"io"
"os"
"strings"

"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/dnfjson"
"github.com/osbuild/images/pkg/rpmmd"
"github.com/osbuild/images/pkg/sbom"
)

// XXX: duplicated from cmd/build/main.go:depsolve (and probably more places)
func depsolve(cacheDir string, packageSets map[string][]rpmmd.PackageSet, d distro.Distro, arch string) (map[string][]rpmmd.PackageSpec, map[string][]rpmmd.RepoConfig, error) {
solver := dnfjson.NewSolver(d.ModulePlatformID(), d.Releasever(), arch, d.Name(), cacheDir)
depsolvedSets := make(map[string][]rpmmd.PackageSpec)
repoSets := make(map[string][]rpmmd.RepoConfig)
for name, pkgSet := range packageSets {
res, err := solver.Depsolve(pkgSet, sbom.StandardTypeNone)
if err != nil {
return nil, nil, err
}
depsolvedSets[name] = res.Packages
repoSets[name] = res.Repos
}
return depsolvedSets, repoSets, nil
}

func outputManifest(out io.Writer, distroName, imgTypeStr, archStr string) error {
filterExprs := []string{
fmt.Sprintf("name:%s", distroName),
fmt.Sprintf("arch:%s", archStr),
fmt.Sprintf("type:%s", imgTypeStr),
}
filteredResults, err := getFilteredImages(filterExprs)
if err != nil {
return err
}
switch len(filteredResults) {
case 0:
return fmt.Errorf("cannot find image for %s %s %s", distroName, imgTypeStr, archStr)
case 1:
// nothing
default:
return fmt.Errorf("internal error: found %v results for %s %s %s", len(filteredResults), distroName, imgTypeStr, archStr)
}

var bp blueprint.Blueprint
// XXX: what/how much do we expose here?
options := distro.ImageOptions{}
distro := filteredResults[0].Distro
imgType := filteredResults[0].ImgType

reporeg, err := newRepoRegistry()
if err != nil {
return err
}
repos, err := reporeg.ReposByImageTypeName(distroName, archStr, imgTypeStr)
if err != nil {
return err
}
preManifest, warnings, err := imgType.Manifest(&bp, options, repos, 0)
if err != nil {
return err
}
if len(warnings) > 0 {
// XXX: what can we do here? for things like json output?
// what are these warnings?
return fmt.Errorf("warnings during manifest creation: %v", strings.Join(warnings, "\n"))
}
// XXX: cleanup, use shared dir,etc
cacheDir, err := os.MkdirTemp("", "depsolve")
if err != nil {
return err
}
packageSpecs, _, err := depsolve(cacheDir, preManifest.GetPackageSetChains(), distro, archStr)
if err != nil {
return err
}
if packageSpecs == nil {
return fmt.Errorf("depsolve did not return any packages")
}
// XXX: support commit/container specs
mf, err := preManifest.Serialize(packageSpecs, nil, nil, nil)
if err != nil {
return err
}
fmt.Fprintf(out, "%s\n", mf)

return nil
}

0 comments on commit edc3d8a

Please sign in to comment.