Skip to content

Commit 283f407

Browse files
committed
main: always use a bootstrap buildroot (but support disabling)
We recently had two issues where creating our buildroot was broken in certain situations because the local rpm would not be compatible with the requirements of the package that got installed in the buildroot: https://issues.redhat.com/browse/RHEL-128741 #413 The issue here is that the local rpm is something we do not control but we need a way to "bootstrap" our buildroot (once we have a buildroot we use that for everything else). This commit enables the "bootstrap" container feature of the images library by default to avoid this dependency. This means that we "podman pull" a minimal container (e.g. ubi for rhel) that contains python3 and rpm to then use it to install our real buildroot. Note that this enables it all the time even if the host distribution and target distribution match. The reason is rebuildability - ie. the same manifest should always produce the same result and in the general case we do not know if e.g. a manifest that was part of `image-builder build --with-manifest` is used somewhere else again. For restricted environment where pulling a container is a problem or for situations where its known that the host rpm is fine we provide: `--without-bootstrap-container` to disable this function.
1 parent 3f44230 commit 283f407

File tree

2 files changed

+55
-19
lines changed

2 files changed

+55
-19
lines changed

cmd/image-builder/main.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,10 @@ func subscriptionImageOptions(cmd *cobra.Command) (*subscription.ImageOptions, e
135135
return regs.Redhat.Subscription, nil
136136
}
137137

138-
type cmdManifestWrapperOptions struct {
139-
useBootstrapIfNeeded bool
140-
}
141-
142138
// used in tests
143139
var manifestgenDepsolver manifestgen.DepsolveFunc
144140

145-
func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []string, w io.Writer, wd io.Writer, wrapperOpts *cmdManifestWrapperOptions) (*imagefilter.Result, error) {
146-
if wrapperOpts == nil {
147-
wrapperOpts = &cmdManifestWrapperOptions{}
148-
}
141+
func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []string, w io.Writer, wd io.Writer) (*imagefilter.Result, error) {
149142
dataDir, err := cmd.Flags().GetString("force-data-dir")
150143
if err != nil {
151144
return nil, err
@@ -217,6 +210,10 @@ func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []st
217210
if err != nil {
218211
return nil, err
219212
}
213+
disableBootstrapContainer, err := cmd.Flags().GetBool("without-bootstrap-container")
214+
if err != nil {
215+
return nil, err
216+
}
220217
bootcRef, err := cmd.Flags().GetString("bootc-ref")
221218
if err != nil {
222219
return nil, err
@@ -314,6 +311,7 @@ func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []st
314311
RpmDownloader: rpmDownloader,
315312
DepsolveWarningsOutput: wd,
316313
Depsolve: manifestgenDepsolver,
314+
UseBootstrapContainer: !disableBootstrapContainer,
317315
},
318316
OutputDir: outputDir,
319317
OutputFilename: outputFilename,
@@ -327,8 +325,7 @@ func cmdManifestWrapper(pbar progress.ProgressBar, cmd *cobra.Command, args []st
327325

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

@@ -341,7 +338,7 @@ func cmdManifest(cmd *cobra.Command, args []string) error {
341338
if err != nil {
342339
return err
343340
}
344-
_, err = cmdManifestWrapper(pbar, cmd, args, osStdout, io.Discard, nil)
341+
_, err = cmdManifestWrapper(pbar, cmd, args, osStdout, io.Discard)
345342
return err
346343
}
347344

@@ -409,13 +406,9 @@ func cmdBuild(cmd *cobra.Command, args []string) error {
409406
}()
410407

411408
var mf bytes.Buffer
412-
opts := &cmdManifestWrapperOptions{
413-
useBootstrapIfNeeded: true,
414-
}
415-
416409
// We discard any warnings from the depsolver until we figure out a better
417410
// idea (likely in manifestgen)
418-
res, err := cmdManifestWrapper(pbar, cmd, args, &mf, io.Discard, opts)
411+
res, err := cmdManifestWrapper(pbar, cmd, args, &mf, io.Discard)
419412
if err != nil {
420413
return err
421414
}
@@ -584,6 +577,7 @@ operating systems like Fedora, CentOS and RHEL with easy customizations support.
584577
manifestCmd.Flags().Bool("ignore-warnings", false, `ignore warnings during manifest generation`)
585578
manifestCmd.Flags().String("registrations", "", `filename of a registrations file with e.g. subscription details`)
586579
manifestCmd.Flags().String("rpmmd-cache", "", `osbuild directory to cache rpm metadata`)
580+
manifestCmd.Flags().Bool("without-bootstrap-container", false, `disable using a "bootstrap" container to generate the initial buildroot`)
587581
rootCmd.AddCommand(manifestCmd)
588582

589583
uploadCmd := &cobra.Command{

cmd/image-builder/main_test.go

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -899,18 +899,60 @@ func TestBuildCrossArchSmoke(t *testing.T) {
899899
assert.NoError(t, err)
900900
pipelines, err := manifesttest.PipelineNamesFrom(manifest)
901901
assert.NoError(t, err)
902-
crossArchPipeline := "bootstrap-buildroot"
902+
bootstrapPipeline := "bootstrap-buildroot"
903903
crossArchWarning := `WARNING: using experimental cross-architecture building to build "aarch64"`
904+
// the bootstrap pipeline is the default for all builds
905+
assert.Contains(t, pipelines, bootstrapPipeline)
904906
if withCrossArch {
905-
assert.Contains(t, pipelines, crossArchPipeline)
906907
assert.Contains(t, stderr, crossArchWarning)
907908
} else {
908-
assert.NotContains(t, pipelines, crossArchPipeline)
909909
assert.NotContains(t, stderr, crossArchWarning)
910910
}
911911
}
912912
}
913913

914+
func TestManifestBootstrapContainer(t *testing.T) {
915+
if testing.Short() {
916+
t.Skip("manifest generation takes a while")
917+
}
918+
if !hasDepsolveDnf() {
919+
t.Skip("no osbuild-depsolve-dnf binary found")
920+
}
921+
922+
restore := main.MockNewRepoRegistry(testrepos.New)
923+
defer restore()
924+
925+
for _, disableBootstrapContainer := range []bool{false, true} {
926+
cmd := []string{
927+
"manifest",
928+
"tar",
929+
"--distro", "centos-10",
930+
}
931+
if disableBootstrapContainer {
932+
cmd = append(cmd, "--without-bootstrap-container")
933+
}
934+
restore = main.MockOsArgs(cmd)
935+
defer restore()
936+
937+
var fakeStdout bytes.Buffer
938+
restore = main.MockOsStdout(&fakeStdout)
939+
defer restore()
940+
941+
// XXX: capture stderr here too to ensure no cross build warning
942+
err := main.Run()
943+
assert.NoError(t, err)
944+
945+
pipelines, err := manifesttest.PipelineNamesFrom(fakeStdout.Bytes())
946+
assert.NoError(t, err)
947+
bootstrapPipeline := "bootstrap-buildroot"
948+
if disableBootstrapContainer {
949+
assert.NotContains(t, pipelines, bootstrapPipeline)
950+
} else {
951+
assert.Contains(t, pipelines, bootstrapPipeline)
952+
}
953+
}
954+
}
955+
914956
func TestBuildIntegrationOutputFilename(t *testing.T) {
915957
if testing.Short() {
916958
t.Skip("manifest generation takes a while")

0 commit comments

Comments
 (0)