Extend the RepoConfig structure to contain new field ImageTypeTags. Extend also other structures and functions as needed, to support loading repository definitions, which use this new field. The idea is that a repository should be used for building all image types, unless it has some ImageTypeTags defined. In such case, it should be used only for building the specific image types, which names are specified in the new field. Add RepoRegistry as a higher-level API to load and manage repository definitions for each distribution. Currently it provides one method, which returns a set of repositories needed to build a given image type. The RepoRegistry uses the new ImageTypeTags field in the RepoConfig structure and returns all the needed repositories for the image type. Modify rpmmd unit tests and add unit tests for RepoRegistry. Add News entry describing the change done to RepoConfig and its JSON representation. Signed-off-by: Tomas Hozza <thozza@redhat.com>
77 lines
3 KiB
Go
77 lines
3 KiB
Go
package reporegistry
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
|
)
|
|
|
|
// RepoRegistry represents a database of distro and architecture
|
|
// specific RPM repositories. Image types are considered only
|
|
// if the loaded repository definition contains any ImageTypeTags.
|
|
type RepoRegistry struct {
|
|
repos rpmmd.DistrosRepoConfigs
|
|
}
|
|
|
|
// New returns a new RepoRegistry instance with the data
|
|
// loaded from the given repoConfigPaths
|
|
func New(repoConfigPaths []string) (*RepoRegistry, error) {
|
|
repositories, err := rpmmd.LoadAllRepositories(repoConfigPaths)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &RepoRegistry{repositories}, nil
|
|
}
|
|
|
|
// ReposByImageType returns a slice of rpmmd.RepoConfig instances, which should be used for building the specific
|
|
// image type. All repositories for the associated distribution and architecture, without any ImageTypeTags set,
|
|
// are always part of the returned slice. In addition, if there are repositories tagged with the specific image
|
|
// type name, these are added to the returned slice as well.
|
|
func (r *RepoRegistry) ReposByImageType(imageType distro.ImageType) ([]rpmmd.RepoConfig, error) {
|
|
if imageType.Arch() == nil || reflect.ValueOf(imageType.Arch()).IsNil() {
|
|
return nil, fmt.Errorf("there is no architecture associated with the provided image type")
|
|
}
|
|
if imageType.Arch().Distro() == nil || reflect.ValueOf(imageType.Arch().Distro()).IsNil() {
|
|
return nil, fmt.Errorf("there is no distribution associated with the architecture associated with the provided image type")
|
|
}
|
|
return r.reposByImageTypeName(imageType.Arch().Distro().Name(), imageType.Arch().Name(), imageType.Name())
|
|
}
|
|
|
|
// reposByImageTypeName returns a slice of rpmmd.RepoConfig instances, which should be used for building the specific
|
|
// image type name (of a given distribution and architecture). The method does not verify
|
|
// if the given image type name is actually part of the architecture definition of the provided name.
|
|
// Therefore in general, all common distro-arch-specific repositories are returned for any image type name,
|
|
// even for non-existing ones.
|
|
func (r *RepoRegistry) reposByImageTypeName(distro, arch, imageType string) ([]rpmmd.RepoConfig, error) {
|
|
repositories := []rpmmd.RepoConfig{}
|
|
|
|
distroRepos, found := r.repos[distro]
|
|
if !found {
|
|
return nil, fmt.Errorf("there are no repositories for distribution '%s'", distro)
|
|
}
|
|
archRepos, found := distroRepos[arch]
|
|
if !found {
|
|
return nil, fmt.Errorf("there are no repositories for distribution '%s' and architecture '%s'", distro, arch)
|
|
}
|
|
|
|
for _, repo := range archRepos {
|
|
// Add all repositories without image_type tags
|
|
if len(repo.ImageTypeTags) == 0 {
|
|
repositories = append(repositories, repo)
|
|
continue
|
|
}
|
|
|
|
// Add all repositories tagged with the image type
|
|
for _, imageNameTag := range repo.ImageTypeTags {
|
|
if imageNameTag == imageType {
|
|
repositories = append(repositories, repo)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return repositories, nil
|
|
}
|