diff --git a/bib/internal/container/solver.go b/bib/internal/container/solver.go index 0214bb51d..201ad9cfc 100644 --- a/bib/internal/container/solver.go +++ b/bib/internal/container/solver.go @@ -2,6 +2,7 @@ package container import ( "fmt" + "os" "os/exec" "path/filepath" @@ -31,38 +32,71 @@ func (c *Container) InitDNF() error { return nil } -func (cnt *Container) injectDNFJson() ([]string, error) { - if err := cnt.CopyInto("/usr/libexec/osbuild-depsolve-dnf", "/osbuild-depsolve-dnf"); err != nil { - return nil, fmt.Errorf("cannot prepare depsolve in the container: %w", err) +func (cnt *Container) hasRunSecrets() bool { + _, err := os.Stat(filepath.Join(cnt.root, "/run/secrets/redhat.repo")) + return err == nil +} + +// setupRunSecretsBindMount will synthesise a /run/secrets dir +// in the container root +func (cnt *Container) setupRunSecrets() error { + if cnt.hasRunSecrets() { + return nil + } + dst := filepath.Join(cnt.root, "/run/secrets") + if err := os.MkdirAll(dst, 0755); err != nil { + return err } - // copy the python module too - globPath := "/usr/lib/*/site-packages/osbuild" - matches, err := filepath.Glob(globPath) - if err != nil || len(matches) == 0 { - return nil, fmt.Errorf("cannot find osbuild python module in %q: %w", globPath, err) + + // We cannot just bind mount here because + // /usr/share/rhel/secrets contains a bunch of symlinks and + // we also want to be able to run "bootc-image-builder manifest" + // outside a container so supporting this is nice. + // + // So instead of bind mounting we create a copy of the + // /run/secrets/ - they are static so that should be fineq + for _, src := range []string{"/run/secrets", "/usr/share/rhel/secrets"} { + if st, err := os.Stat(src); err != nil || !st.IsDir() { + continue + } + + dents, err := filepath.Glob(src + "/*") + if err != nil { + return err + } + for _, ent := range dents { + if output, err := exec.Command("cp", "-rvL", ent, dst).CombinedOutput(); err != nil { + return fmt.Errorf("failed to setup /run/secrets: %w, output:\n%s", err, string(output)) + } + } } - if len(matches) != 1 { - return nil, fmt.Errorf("unexpected number of osbuild python module matches: %v", matches) + + // XXX: we need to twist arms here, f41 uses an aboslute link to link back to entitlements-host and rhsm-host , it needs to be relative for us + // + // XXX2: check golang for "ln -f" for atomic exchange + if output, err := exec.Command("ln", "-sf", "../../run/secrets/etc-pki-entitlement", filepath.Join(cnt.root, "/etc/pki/entitlement-host")).CombinedOutput(); err != nil { + return fmt.Errorf("cannot run ls: %werr, output:\n%s", err, output) } - if err := cnt.CopyInto(matches[0], "/"); err != nil { - return nil, fmt.Errorf("cannot prepare depsolve python-modules in the container: %w", err) + if output, err := exec.Command("ln", "-sf", "../run/secrets/rhsm-host", filepath.Join(cnt.root, "/etc/rhsm-host")).CombinedOutput(); err != nil { + return fmt.Errorf("cannot run ls: %werr, output:\n%s", err, output) } - return append(cnt.ExecArgv(), "/osbuild-depsolve-dnf"), nil + + return nil } func (cnt *Container) NewContainerSolver(cacheRoot string, architecture arch.Arch, sourceInfo *source.Info) (*dnfjson.Solver, error) { - depsolverCmd, err := cnt.injectDNFJson() - if err != nil { - return nil, fmt.Errorf("cannot inject depsolve into the container: %w", err) - } - solver := dnfjson.NewSolver( sourceInfo.OSRelease.PlatformID, sourceInfo.OSRelease.VersionID, architecture.String(), fmt.Sprintf("%s-%s", sourceInfo.OSRelease.ID, sourceInfo.OSRelease.VersionID), cacheRoot) - solver.SetDNFJSONPath(depsolverCmd[0], depsolverCmd[1:]...) - solver.SetRootDir("/") + + // we copy the data directly into the cnt.root, no need to + // cleanup here because podman stop will remove the dir + if err := cnt.setupRunSecrets(); err != nil { + return nil, err + } + solver.SetRootDir(cnt.root) return solver, nil } diff --git a/bib/internal/container/solver_test.go b/bib/internal/container/solver_test.go index a5ab9e5eb..834899219 100644 --- a/bib/internal/container/solver_test.go +++ b/bib/internal/container/solver_test.go @@ -33,6 +33,8 @@ func TestDNFJsonWorks(t *testing.T) { cnt, err := container.New(dnfTestingImageCentos) require.NoError(t, err) + defer cnt.Stop() + err = cnt.InitDNF() require.NoError(t, err) @@ -116,6 +118,8 @@ func TestDNFJsonWorkWithSubscribedContent(t *testing.T) { cnt, err := container.New(dnfTestingImageRHEL) require.NoError(t, err) + defer cnt.Stop() + err = cnt.InitDNF() require.NoError(t, err) @@ -123,6 +127,7 @@ func TestDNFJsonWorkWithSubscribedContent(t *testing.T) { require.NoError(t, err) solver, err := cnt.NewContainerSolver(cacheRoot, arch.ARCH_X86_64, sourceInfo) require.NoError(t, err) + res, err := solver.Depsolve([]rpmmd.PackageSet{ { Include: []string{"coreutils"},