simplify package set chain handling

Move package set chain collation to the distro package and add
repositories to the package sets while returning the package sets from
their source, i.e., the ImageType.PackageSets() method.

This also removes the concept of "base repositories".  There are no
longer repositories that are added implicitly to all package sets but
instead each package set needs to specify *all* the repositories it will
be depsolved against.

This paves the way for the requirement we have for building RHEL 7
images with a RHEL 8 build root.  The build root package set has to be
depsolved against RHEL 8 repositories without any "base repos" included.
This is now possible since package sets and repositories are explicitly
associated from the start and there is no implicit global repository
set.

The change requires adding a list of PackageSet names to the core
rpmmd.RepoConfig.  In the cloud API, repositories that are limited to
specific package sets already contain the correct package set names and
these are now copied to the internal RepoConfig when converting types in
genRepoConfig().
The user-specified repositories are only associated with the payload
package sets like before.
This commit is contained in:
Achilleas Koutsou 2022-05-09 17:41:13 +02:00 committed by Tom Gundersen
parent 6fbddeea35
commit c092783a70
33 changed files with 323 additions and 401 deletions

View file

@ -107,12 +107,11 @@ func splitExtension(filename string) string {
}
type imageRequest struct {
imageType distro.ImageType
arch distro.Arch
repositories []rpmmd.RepoConfig
packageSetsRepositories map[string][]rpmmd.RepoConfig
imageOptions distro.ImageOptions
target *target.Target
imageType distro.ImageType
arch distro.Arch
repositories []rpmmd.RepoConfig
imageOptions distro.ImageOptions
target *target.Target
}
func (h *apiHandlers) PostCompose(ctx echo.Context) error {
@ -238,7 +237,7 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error {
return HTTPError(ErrorUnsupportedImageType)
}
repos, pkgSetsRepos, err := collectRepos(ir.Repositories, payloadRepositories, imageType.PayloadPackageSets())
repos, err := convertRepos(ir.Repositories, payloadRepositories, imageType.PayloadPackageSets())
if err != nil {
return err
}
@ -426,12 +425,11 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error {
}
irs = append(irs, imageRequest{
imageType: imageType,
arch: arch,
repositories: repos,
imageOptions: imageOptions,
packageSetsRepositories: pkgSetsRepos,
target: irTarget,
imageType: imageType,
arch: arch,
repositories: repos,
imageOptions: imageOptions,
target: irTarget,
})
}
@ -972,38 +970,32 @@ func (h *apiHandlers) GetComposeManifests(ctx echo.Context, id string) error {
return ctx.JSON(http.StatusOK, resp)
}
func collectRepos(irRepos, payloadRepositories []Repository, payloadPackageSets []string) ([]rpmmd.RepoConfig, map[string][]rpmmd.RepoConfig, error) {
// build package set repository map and base repository set based on repository package sets
// No package_sets -> base set
mainRepoConfigs := make([]rpmmd.RepoConfig, 0, len(irRepos))
pkgSetsRepoConfigs := make(map[string][]rpmmd.RepoConfig, len(irRepos))
// Converts repositories in the request to the internal rpmmd.RepoConfig representation
func convertRepos(irRepos, payloadRepositories []Repository, payloadPackageSets []string) ([]rpmmd.RepoConfig, error) {
repos := make([]rpmmd.RepoConfig, 0, len(irRepos)+len(payloadRepositories))
for _, irRepo := range irRepos {
repo, err := genRepoConfig(irRepo)
for idx := range irRepos {
r, err := genRepoConfig(irRepos[idx])
if err != nil {
return nil, nil, err
}
if pkgSets := irRepo.PackageSets; pkgSets != nil && len(*irRepo.PackageSets) > 0 {
for _, pkgSet := range *pkgSets {
pkgSetsRepoConfigs[pkgSet] = append(pkgSetsRepoConfigs[pkgSet], *repo)
}
} else {
mainRepoConfigs = append(mainRepoConfigs, *repo)
return nil, err
}
repos = append(repos, *r)
}
// add user custom repos to all payload package sets
for _, plRepo := range payloadRepositories {
for _, payloadName := range payloadPackageSets {
repo, err := genRepoConfig(plRepo)
if err != nil {
return nil, nil, err
}
pkgSetsRepoConfigs[payloadName] = append(pkgSetsRepoConfigs[payloadName], *repo)
for idx := range payloadRepositories {
// the PackageSets (package_sets) field for these repositories is
// ignored (see openapi.v2.yml description for payload_repositories)
// and we replace any value in it with the names of the payload package
// sets
r, err := genRepoConfig(payloadRepositories[idx])
if err != nil {
return nil, err
}
r.PackageSets = payloadPackageSets
repos = append(repos, *r)
}
return mainRepoConfigs, pkgSetsRepoConfigs, nil
return repos, nil
}
func genRepoConfig(repo Repository) (*rpmmd.RepoConfig, error) {
@ -1035,5 +1027,9 @@ func genRepoConfig(repo Repository) (*rpmmd.RepoConfig, error) {
return nil, HTTPError(ErrorNoGPGKey)
}
if repo.PackageSets != nil {
repoConfig.PackageSets = *repo.PackageSets
}
return repoConfig, nil
}

View file

@ -132,13 +132,10 @@ func (s *Server) enqueueCompose(distribution distro.Distro, bp blueprint.Bluepri
ir := irs[0]
depsolveJobID, err := s.workers.EnqueueDepsolve(&worker.DepsolveJob{
PackageSetsChains: ir.imageType.PackageSetsChains(),
PackageSets: ir.imageType.PackageSets(bp),
Repos: ir.repositories,
ModulePlatformID: distribution.ModulePlatformID(),
Arch: ir.arch.Name(),
Releasever: distribution.Releasever(),
PackageSetsRepos: ir.packageSetsRepositories,
PackageSets: ir.imageType.PackageSets(bp, ir.repositories),
ModulePlatformID: distribution.ModulePlatformID(),
Arch: ir.arch.Name(),
Releasever: distribution.Releasever(),
}, channel)
if err != nil {
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
@ -188,12 +185,10 @@ func (s *Server) enqueueKojiCompose(taskID uint64, server, name, version, releas
var buildIDs []uuid.UUID
for _, ir := range irs {
depsolveJobID, err := s.workers.EnqueueDepsolve(&worker.DepsolveJob{
PackageSets: ir.imageType.PackageSets(bp),
Repos: ir.repositories,
PackageSets: ir.imageType.PackageSets(bp, ir.repositories),
ModulePlatformID: distribution.ModulePlatformID(),
Arch: ir.arch.Name(),
Releasever: distribution.Releasever(),
PackageSetsRepos: ir.packageSetsRepositories,
}, channel)
if err != nil {
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)

View file

@ -51,7 +51,7 @@ func TestCollectRepos(t *testing.T) {
Baseurl: common.StringToPtr("http://example.com/appstream"), // empty field -> all package sets
},
{
Baseurl: common.StringToPtr("http://example.com/baseos-rhel7"), // only build
Baseurl: common.StringToPtr("http://example.com/baseos-rhel7"), // build only
PackageSets: &[]string{"build"},
},
{
@ -59,63 +59,28 @@ func TestCollectRepos(t *testing.T) {
PackageSets: &[]string{"build", "archive"},
},
{
Baseurl: common.StringToPtr("http://example.com/custom-os-stuff"), // blueprint -> merge with custom
Baseurl: common.StringToPtr("http://example.com/custom-os-stuff"), // blueprint only
PackageSets: &[]string{"blueprint"},
},
}
expectedPkgSetRepos := map[string][]rpmmd.RepoConfig{
"build": {
{
BaseURL: "http://example.com/baseos-rhel7",
},
{
BaseURL: "http://example.com/extra-tools",
},
},
"archive": {
{
BaseURL: "http://example.com/extra-tools",
},
},
"blueprint": {
{
BaseURL: "http://example.com/custom-os-stuff",
},
{
BaseURL: "http://example.com/repoone",
},
{
BaseURL: "http://example.com/repotwo",
},
},
expectedRepos := []rpmmd.RepoConfig{
{BaseURL: "http://example.com/baseos", PackageSets: nil},
{BaseURL: "http://example.com/appstream", PackageSets: nil},
{BaseURL: "http://example.com/baseos-rhel7", PackageSets: []string{"build"}},
{BaseURL: "http://example.com/extra-tools", PackageSets: []string{"build", "archive"}},
{BaseURL: "http://example.com/custom-os-stuff", PackageSets: []string{"blueprint"}},
{BaseURL: "http://example.com/repoone", PackageSets: []string{"blueprint"}},
{BaseURL: "http://example.com/repotwo", PackageSets: []string{"blueprint"}},
}
payloadPkgSets := []string{"blueprint"}
baseRepos, pkgSetRepos, err := collectRepos(irRepos, customRepos, payloadPkgSets)
repos, err := convertRepos(irRepos, customRepos, payloadPkgSets)
// check lengths
assert.NoError(err)
assert.Len(baseRepos, 2)
assert.Len(pkgSetRepos, 3)
// check tags in package set repo map
for _, tag := range []string{"blueprint", "build", "archive"} {
assert.Contains(pkgSetRepos, tag)
}
assert.NotContains(pkgSetRepos, "should-be-ignored")
// check URLs
baseRepoURLs := make([]string, len(baseRepos))
for idx, baseRepo := range baseRepos {
baseRepoURLs[idx] = baseRepo.BaseURL
}
for _, url := range []string{"http://example.com/baseos", "http://example.com/appstream"} {
assert.Contains(baseRepoURLs, url)
}
assert.Equal(pkgSetRepos, expectedPkgSetRepos)
assert.Equal(repos, expectedRepos)
}
func TestRepoConfigConversion(t *testing.T) {