Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions cmd/image-builder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/osbuild/images/pkg/customizations/subscription"
"github.com/osbuild/images/pkg/distro/bootc"
"github.com/osbuild/images/pkg/imagefilter"
"github.com/osbuild/images/pkg/manifestgen"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"

Expand Down Expand Up @@ -134,14 +135,10 @@ func subscriptionImageOptions(cmd *cobra.Command) (*subscription.ImageOptions, e
return regs.Redhat.Subscription, nil
}

type cmdManifestWrapperOptions struct {
useBootstrapIfNeeded bool
}
// used in tests
var manifestgenDepsolver manifestgen.DepsolveFunc

func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []string, w io.Writer, wd io.Writer, wrapperOpts *cmdManifestWrapperOptions) (*imagefilter.Result, error) {
if wrapperOpts == nil {
wrapperOpts = &cmdManifestWrapperOptions{}
}
func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []string, w io.Writer, wd io.Writer) (*imagefilter.Result, error) {
dataDir, err := cmd.Flags().GetString("force-data-dir")
if err != nil {
return nil, err
Expand Down Expand Up @@ -213,6 +210,10 @@ func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []st
if err != nil {
return nil, err
}
disableBootstrapContainer, err := cmd.Flags().GetBool("without-bootstrap-container")
if err != nil {
return nil, err
}
bootcRef, err := cmd.Flags().GetString("bootc-ref")
if err != nil {
return nil, err
Expand Down Expand Up @@ -304,27 +305,31 @@ func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []st
}

opts := &manifestOptions{
ManifestgenOptions: manifestgen.Options{
Cachedir: rpmmdCacheDir,
CustomSeed: customSeed,
RpmDownloader: rpmDownloader,
DepsolveWarningsOutput: wd,
Depsolve: manifestgenDepsolver,
UseBootstrapContainer: !disableBootstrapContainer,
},
OutputDir: outputDir,
OutputFilename: outputFilename,
BlueprintPath: blueprintPath,
Ostree: ostreeImgOpts,
BootcRef: bootcRef,
BootcInstallerPayloadRef: bootcInstallerPayloadRef,
RpmDownloader: rpmDownloader,
WithSBOM: withSBOM,
IgnoreWarnings: ignoreWarnings,
CustomSeed: customSeed,
Subscription: subscription,
RpmmdCacheDir: rpmmdCacheDir,

ForceRepos: forceRepos,
}
opts.UseBootstrapContainer = wrapperOpts.useBootstrapIfNeeded && (img.ImgType.Arch().Name() != arch.Current().String())
if opts.UseBootstrapContainer {
if img.ImgType.Arch().Name() != arch.Current().String() {
fmt.Fprintf(os.Stderr, "WARNING: using experimental cross-architecture building to build %q\n", img.ImgType.Arch().Name())
}

err = generateManifest(dataDir, extraRepos, img, w, wd, opts)
err = generateManifest(dataDir, extraRepos, img, w, opts)
return img, err
}

Expand All @@ -333,7 +338,7 @@ func cmdManifest(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
_, err = cmdManifestWrapper(pbar, cmd, args, osStdout, io.Discard, nil)
_, err = cmdManifestWrapper(pbar, cmd, args, osStdout, io.Discard)
return err
}

Expand Down Expand Up @@ -401,13 +406,9 @@ func cmdBuild(cmd *cobra.Command, args []string) error {
}()

var mf bytes.Buffer
opts := &cmdManifestWrapperOptions{
useBootstrapIfNeeded: true,
}

// We discard any warnings from the depsolver until we figure out a better
// idea (likely in manifestgen)
res, err := cmdManifestWrapper(pbar, cmd, args, &mf, io.Discard, opts)
res, err := cmdManifestWrapper(pbar, cmd, args, &mf, io.Discard)
if err != nil {
return err
}
Expand Down Expand Up @@ -576,6 +577,7 @@ operating systems like Fedora, CentOS and RHEL with easy customizations support.
manifestCmd.Flags().Bool("ignore-warnings", false, `ignore warnings during manifest generation`)
manifestCmd.Flags().String("registrations", "", `filename of a registrations file with e.g. subscription details`)
manifestCmd.Flags().String("rpmmd-cache", "", `osbuild directory to cache rpm metadata`)
manifestCmd.Flags().Bool("without-bootstrap-container", false, `disable using a "bootstrap" container to generate the initial buildroot`)
rootCmd.AddCommand(manifestCmd)

uploadCmd := &cobra.Command{
Expand Down
48 changes: 45 additions & 3 deletions cmd/image-builder/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -899,18 +899,60 @@ func TestBuildCrossArchSmoke(t *testing.T) {
assert.NoError(t, err)
pipelines, err := manifesttest.PipelineNamesFrom(manifest)
assert.NoError(t, err)
crossArchPipeline := "bootstrap-buildroot"
bootstrapPipeline := "bootstrap-buildroot"
crossArchWarning := `WARNING: using experimental cross-architecture building to build "aarch64"`
// the bootstrap pipeline is the default for all builds
assert.Contains(t, pipelines, bootstrapPipeline)
if withCrossArch {
assert.Contains(t, pipelines, crossArchPipeline)
assert.Contains(t, stderr, crossArchWarning)
} else {
assert.NotContains(t, pipelines, crossArchPipeline)
assert.NotContains(t, stderr, crossArchWarning)
}
}
}

func TestManifestBootstrapContainer(t *testing.T) {
if testing.Short() {
t.Skip("manifest generation takes a while")
}
if !hasDepsolveDnf() {
t.Skip("no osbuild-depsolve-dnf binary found")
}

restore := main.MockNewRepoRegistry(testrepos.New)
defer restore()

for _, disableBootstrapContainer := range []bool{false, true} {
cmd := []string{
"manifest",
"tar",
"--distro", "centos-10",
}
if disableBootstrapContainer {
cmd = append(cmd, "--without-bootstrap-container")
}
restore = main.MockOsArgs(cmd)
defer restore()

var fakeStdout bytes.Buffer
restore = main.MockOsStdout(&fakeStdout)
defer restore()

// XXX: capture stderr here too to ensure no cross build warning
err := main.Run()
assert.NoError(t, err)

pipelines, err := manifesttest.PipelineNamesFrom(fakeStdout.Bytes())
assert.NoError(t, err)
bootstrapPipeline := "bootstrap-buildroot"
if disableBootstrapContainer {
assert.NotContains(t, pipelines, bootstrapPipeline)
} else {
assert.Contains(t, pipelines, bootstrapPipeline)
}
}
}

func TestBuildIntegrationOutputFilename(t *testing.T) {
if testing.Short() {
t.Skip("manifest generation takes a while")
Expand Down
21 changes: 5 additions & 16 deletions cmd/image-builder/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
)

type manifestOptions struct {
ManifestgenOptions manifestgen.Options

OutputDir string
OutputFilename string
BlueprintPath string
Expand All @@ -30,11 +32,8 @@ type manifestOptions struct {
RpmDownloader osbuild.RpmDownloader
WithSBOM bool
IgnoreWarnings bool
CustomSeed *int64
RpmmdCacheDir string

ForceRepos []string
UseBootstrapContainer bool
ForceRepos []string
}

func sbomWriter(outputDir, filename string, content io.Reader) error {
Expand All @@ -55,23 +54,13 @@ func sbomWriter(outputDir, filename string, content io.Reader) error {
return f.Sync()
}

// used in tests
var manifestgenDepsolver manifestgen.DepsolveFunc

// XXX: just return []byte instead of using output writer
func generateManifest(dataDir string, extraRepos []string, img *imagefilter.Result, output io.Writer, depsolveWarningsOutput io.Writer, opts *manifestOptions) error {
func generateManifest(dataDir string, extraRepos []string, img *imagefilter.Result, output io.Writer, opts *manifestOptions) error {
repos, err := newRepoRegistry(dataDir, extraRepos)
if err != nil {
return err
}
manifestGenOpts := &manifestgen.Options{
DepsolveWarningsOutput: depsolveWarningsOutput,
RpmDownloader: opts.RpmDownloader,
UseBootstrapContainer: opts.UseBootstrapContainer,
CustomSeed: opts.CustomSeed,
Depsolve: manifestgenDepsolver,
Cachedir: opts.RpmmdCacheDir,
}
manifestGenOpts := &opts.ManifestgenOptions
if opts.WithSBOM {
outputDir := basenameFor(img, opts.OutputDir)
manifestGenOpts.SBOMWriter = func(filename string, content io.Reader, docType sbom.StandardType) error {
Expand Down
Loading