Add support for image type tags in rpmmd and add RepoRegistry API
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>
This commit is contained in:
parent
4c5d4de387
commit
dda9cce03e
6 changed files with 513 additions and 9 deletions
82
docs/news/unreleased/repo-conf-image-type-tags.md
Normal file
82
docs/news/unreleased/repo-conf-image-type-tags.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Allow image type-specific repositories using Image Type Tags
|
||||
|
||||
The schema of the repository definitions used by *Weldr API*, located in `/usr/share/osbuild-composer/repositories/` or `/etc/osbuild-composer/repositories` is extended with a new field called **`image_type_tags`** and is expected to be an array of strings representing specific image types.
|
||||
|
||||
The behavior of how are defined repositories processed and used by osbuild-composer* is extended in the following way:
|
||||
|
||||
1. If the repository definition does not have the `image_type_tags` field specified, then it will be used for building all types of images for a given distribution and architecture. This is how all repository definitions had been used before this change.
|
||||
|
||||
1. If the repository definition has the `image_type_tags` field specified and set to a non-empty array of strings, then it will be used **only** for building image types, which names are specified in the array.
|
||||
|
||||
An example of a user-defined repository override for Fedora 33 in `/etc/osbuild-composer/repositories/fedora-33.json` follows. In addition to Fedora distribution repositories, it defines an additional repository called `my-custom-repo`, which should be used only for `ami` images built on both architectures.
|
||||
|
||||
```json
|
||||
{
|
||||
"x86_64": [
|
||||
{
|
||||
"name": "fedora",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-33&arch=x86_64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "updates",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=updates-released-f33&arch=x86_64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "fedora-modular",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-modular-33&arch=x86_64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "updates-modular",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=updates-released-modular-f33&arch=x86_64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "my-repo",
|
||||
"metalink": "https://repos.example.org/f33/x86_64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true,
|
||||
"image_type_tags": ["ami"]
|
||||
}
|
||||
],
|
||||
"aarch64": [
|
||||
{
|
||||
"name": "fedora",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-33&arch=aarch64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "updates",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=updates-released-f33&arch=aarch64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "fedora-modular",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-modular-33&arch=aarch64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
},
|
||||
{
|
||||
"name": "updates-modular",
|
||||
"metalink": "https://mirrors.fedoraproject.org/metalink?repo=updates-released-modular-f33&arch=aarch64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true
|
||||
}
|
||||
{
|
||||
"name": "my-repo",
|
||||
"metalink": "https://repos.example.org/f33/aarch64",
|
||||
"gpgkey": "...",
|
||||
"check_gpg": true,
|
||||
"image_type_tags": ["ami"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
77
internal/reporegistry/reporegistry.go
Normal file
77
internal/reporegistry/reporegistry.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
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
|
||||
}
|
||||
227
internal/reporegistry/reporegistry_test.go
Normal file
227
internal/reporegistry/reporegistry_test.go
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
package reporegistry
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/distro"
|
||||
"github.com/osbuild/osbuild-composer/internal/distro/test_distro"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func getTestingRepoRegistry() *RepoRegistry {
|
||||
return &RepoRegistry{
|
||||
map[string]map[string][]rpmmd.RepoConfig{
|
||||
test_distro.TestDistroName: {
|
||||
test_distro.TestArchName: {
|
||||
{
|
||||
Name: "baseos",
|
||||
BaseURL: "https://cdn.redhat.com/content/dist/rhel8/8/x86_64/baseos/os",
|
||||
},
|
||||
{
|
||||
Name: "appstream",
|
||||
BaseURL: "https://cdn.redhat.com/content/dist/rhel8/8/x86_64/appstream/os",
|
||||
},
|
||||
},
|
||||
test_distro.TestArch2Name: {
|
||||
{
|
||||
Name: "baseos",
|
||||
BaseURL: "https://cdn.redhat.com/content/dist/rhel8/8/aarch64/baseos/os",
|
||||
},
|
||||
{
|
||||
Name: "appstream",
|
||||
BaseURL: "https://cdn.redhat.com/content/dist/rhel8/8/aarch64/appstream/os",
|
||||
ImageTypeTags: []string{},
|
||||
},
|
||||
{
|
||||
Name: "google-compute-engine",
|
||||
BaseURL: "https://packages.cloud.google.com/yum/repos/google-compute-engine-el8-x86_64-stable",
|
||||
ImageTypeTags: []string{test_distro.TestImageType2Name},
|
||||
},
|
||||
{
|
||||
Name: "google-cloud-sdk",
|
||||
BaseURL: "https://packages.cloud.google.com/yum/repos/cloud-sdk-el8-x86_64",
|
||||
ImageTypeTags: []string{test_distro.TestImageType2Name},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestReposByImageType_reposByImageTypeName(t *testing.T) {
|
||||
rr := getTestingRepoRegistry()
|
||||
testDistro := test_distro.New()
|
||||
|
||||
ta, _ := testDistro.GetArch(test_distro.TestArchName)
|
||||
ta2, _ := testDistro.GetArch(test_distro.TestArch2Name)
|
||||
|
||||
ta_it, _ := ta.GetImageType(test_distro.TestImageTypeName)
|
||||
|
||||
ta2_it, _ := ta2.GetImageType(test_distro.TestImageTypeName)
|
||||
ta2_it2, _ := ta2.GetImageType(test_distro.TestImageType2Name)
|
||||
|
||||
type args struct {
|
||||
input distro.ImageType
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "NoAdditionalReposNeeded_NoAdditionalReposDefined",
|
||||
args: args{
|
||||
input: ta_it,
|
||||
},
|
||||
want: []string{"baseos", "appstream"},
|
||||
},
|
||||
{
|
||||
name: "NoAdditionalReposNeeded_AdditionalReposDefined",
|
||||
args: args{
|
||||
input: ta2_it,
|
||||
},
|
||||
want: []string{"baseos", "appstream"},
|
||||
},
|
||||
{
|
||||
name: "AdditionalReposNeeded_AdditionalReposDefined",
|
||||
args: args{
|
||||
input: ta2_it2,
|
||||
},
|
||||
want: []string{"baseos", "appstream", "google-compute-engine", "google-cloud-sdk"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := rr.ReposByImageType(tt.args.input)
|
||||
assert.Nil(t, err)
|
||||
|
||||
var gotNames []string
|
||||
for _, r := range got {
|
||||
gotNames = append(gotNames, r.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotNames, tt.want) {
|
||||
t.Errorf("ReposByImageType() =\n got: %#v\n want: %#v", gotNames, tt.want)
|
||||
}
|
||||
|
||||
got, err = rr.reposByImageTypeName(tt.args.input.Arch().Distro().Name(), tt.args.input.Arch().Name(), tt.args.input.Name())
|
||||
assert.Nil(t, err)
|
||||
gotNames = []string{}
|
||||
for _, r := range got {
|
||||
gotNames = append(gotNames, r.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotNames, tt.want) {
|
||||
t.Errorf("reposByImageTypeName() =\n got: %#v\n want: %#v", gotNames, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestInvalidReposByImageType tests return values from ReposByImageType
|
||||
// for invalid values
|
||||
func TestInvalidReposByImageType(t *testing.T) {
|
||||
rr := getTestingRepoRegistry()
|
||||
|
||||
ti := test_distro.TestImageType{}
|
||||
|
||||
repos, err := rr.ReposByImageType(&ti)
|
||||
assert.Nil(t, repos)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
// TestInvalidReposByImageTypeName tests return values from reposByImageTypeName
|
||||
// for invalid distro name, arch and image type
|
||||
func TestInvalidReposByImageTypeName(t *testing.T) {
|
||||
rr := getTestingRepoRegistry()
|
||||
|
||||
type args struct {
|
||||
distro string
|
||||
arch string
|
||||
imageType string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want func(repos []rpmmd.RepoConfig, err error) bool
|
||||
}{
|
||||
{
|
||||
name: "invalid distro, valid arch and image type",
|
||||
args: args{
|
||||
distro: test_distro.TestDistroName + "-invalid",
|
||||
arch: test_distro.TestArchName,
|
||||
imageType: test_distro.TestImageTypeName,
|
||||
},
|
||||
want: func(repos []rpmmd.RepoConfig, err error) bool {
|
||||
// the list of repos should be nil and an error should be returned
|
||||
if repos != nil || err == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid arch, valid distro and image type",
|
||||
args: args{
|
||||
distro: test_distro.TestDistroName,
|
||||
arch: test_distro.TestArchName + "-invalid",
|
||||
imageType: test_distro.TestImageTypeName,
|
||||
},
|
||||
want: func(repos []rpmmd.RepoConfig, err error) bool {
|
||||
// the list of repos should be nil and an error should be returned
|
||||
if repos != nil || err == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid image type, valid distro and arch, without tagged repos",
|
||||
args: args{
|
||||
distro: test_distro.TestDistroName,
|
||||
arch: test_distro.TestArchName,
|
||||
imageType: test_distro.TestImageTypeName + "-invalid",
|
||||
},
|
||||
want: func(repos []rpmmd.RepoConfig, err error) bool {
|
||||
// a non-empty list of repos should be returned without an error
|
||||
if repos == nil || err != nil {
|
||||
return false
|
||||
}
|
||||
// only the list of common distro-arch repos should be returned
|
||||
// these are repos without any explicit imageType tag
|
||||
if len(repos) != 2 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid image type, valid distro and arch, with tagged repos",
|
||||
args: args{
|
||||
distro: test_distro.TestDistroName,
|
||||
arch: test_distro.TestArch2Name,
|
||||
imageType: test_distro.TestImageTypeName + "-invalid",
|
||||
},
|
||||
want: func(repos []rpmmd.RepoConfig, err error) bool {
|
||||
// a non-empty list of repos should be returned without an error
|
||||
if repos == nil || err != nil {
|
||||
return false
|
||||
}
|
||||
// only the list of common distro-arch repos should be returned
|
||||
// these are repos without any explicit imageType tag
|
||||
if len(repos) != 2 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := rr.reposByImageTypeName(tt.args.distro, tt.args.arch, tt.args.imageType)
|
||||
assert.True(t, tt.want(got, err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -16,14 +16,15 @@ import (
|
|||
)
|
||||
|
||||
type repository struct {
|
||||
Name string `json:"name"`
|
||||
BaseURL string `json:"baseurl,omitempty"`
|
||||
Metalink string `json:"metalink,omitempty"`
|
||||
MirrorList string `json:"mirrorlist,omitempty"`
|
||||
GPGKey string `json:"gpgkey,omitempty"`
|
||||
CheckGPG bool `json:"check_gpg,omitempty"`
|
||||
RHSM bool `json:"rhsm,omitempty"`
|
||||
MetadataExpire string `json:"metadata_expire,omitempty"`
|
||||
Name string `json:"name"`
|
||||
BaseURL string `json:"baseurl,omitempty"`
|
||||
Metalink string `json:"metalink,omitempty"`
|
||||
MirrorList string `json:"mirrorlist,omitempty"`
|
||||
GPGKey string `json:"gpgkey,omitempty"`
|
||||
CheckGPG bool `json:"check_gpg,omitempty"`
|
||||
RHSM bool `json:"rhsm,omitempty"`
|
||||
MetadataExpire string `json:"metadata_expire,omitempty"`
|
||||
ImageTypeTags []string `json:"image_type_tags,omitempty"`
|
||||
}
|
||||
|
||||
type dnfRepoConfig struct {
|
||||
|
|
@ -49,8 +50,11 @@ type RepoConfig struct {
|
|||
IgnoreSSL bool
|
||||
MetadataExpire string
|
||||
RHSM bool
|
||||
ImageTypeTags []string
|
||||
}
|
||||
|
||||
type DistrosRepoConfigs map[string]map[string][]RepoConfig
|
||||
|
||||
type PackageList []Package
|
||||
|
||||
type Package struct {
|
||||
|
|
@ -236,6 +240,7 @@ func loadRepositoriesFromFile(filename string) (map[string][]RepoConfig, error)
|
|||
CheckGPG: repo.CheckGPG,
|
||||
RHSM: repo.RHSM,
|
||||
MetadataExpire: repo.MetadataExpire,
|
||||
ImageTypeTags: repo.ImageTypeTags,
|
||||
}
|
||||
|
||||
repoConfigs[arch] = append(repoConfigs[arch], config)
|
||||
|
|
@ -245,6 +250,50 @@ func loadRepositoriesFromFile(filename string) (map[string][]RepoConfig, error)
|
|||
return repoConfigs, nil
|
||||
}
|
||||
|
||||
// LoadAllRepositories loads all repositories for given distros from the given list of paths.
|
||||
// Behavior is the same as with the LoadRepositories() method.
|
||||
func LoadAllRepositories(confPaths []string) (DistrosRepoConfigs, error) {
|
||||
distrosRepoConfigs := DistrosRepoConfigs{}
|
||||
|
||||
for _, confPath := range confPaths {
|
||||
reposPath := filepath.Join(confPath, "repositories")
|
||||
|
||||
fileEntries, err := ioutil.ReadDir(reposPath)
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, fileEntry := range fileEntries {
|
||||
// Skip all directories
|
||||
if fileEntry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// distro repositories definition is expected to be named "<distro_name>.json"
|
||||
if strings.HasSuffix(fileEntry.Name(), ".json") {
|
||||
distro := strings.TrimSuffix(fileEntry.Name(), ".json")
|
||||
|
||||
// skip the distro repos definition, if it has been already read
|
||||
_, ok := distrosRepoConfigs[distro]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
|
||||
distroRepos, err := loadRepositoriesFromFile(filepath.Join(reposPath, fileEntry.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
distrosRepoConfigs[distro] = distroRepos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distrosRepoConfigs, nil
|
||||
}
|
||||
|
||||
// LoadRepositories loads distribution repositories from the given list of paths.
|
||||
// If there are duplicate distro repositories definitions found in multiple paths, the first
|
||||
// encounter is preferred. For this reason, the order of paths in the passed list should
|
||||
|
|
|
|||
|
|
@ -21,6 +21,18 @@
|
|||
"name": "appstream-p2",
|
||||
"baseurl": "https://rpmrepo.osbuild.org/v1/psi/el8/el8-aarch64-appstream-8.4.0.n-20201108/",
|
||||
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF\n0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF\n0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c\nu7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh\nXGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H\n5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW\n9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj\n/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1\nPcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY\nHVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF\nbuhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB\ntDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0\nLmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK\nCRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC\n2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf\nC/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5\nun3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E\n0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE\nIGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh\n8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL\nGht5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki\nJUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25\nOFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq\ndzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw==\n=zbHE\n-----END PGP PUBLIC KEY BLOCK-----\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n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\nvt61kpkXoRGxjTlc6h+69aidSg==\n=ls8J\n-----END PGP PUBLIC KEY BLOCK-----\n"
|
||||
},
|
||||
{
|
||||
"name": "google-compute-engine",
|
||||
"baseurl": "https://packages.cloud.google.com/yum/repos/google-compute-engine-el8-x86_64-stable",
|
||||
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQENBGA9EFkBCAC1ilzST0wns+uwZyEA5IVtYeyAuXTaQUEAd70SqIlQpDd4EyVi\nx3SCanQIu8dG9Zq3+x28WBb2OuXP9oc06ybOWdu2m7N5PY0BUT4COA36JV/YrxmN\ns+5/M+YnDHppv63jgRIOkzXzXNo6SwTsl2xG9fKB3TS0IMvBkWdw5PGrBM5GghRc\necgoSAAwRbWJXORHGKVwlV6tOxQZ/xqA08hPJneMfsMFPOXsitgGRHoXjlUWLVeJ\n70mmIYsC/pBglIwCzmdD8Ee39MrlSXbuXVQiz38iHfnvXYpLEmgNXKzI0DH9tKg8\n323kALzqaJlLFOLJm/uVJXRUEfKS3LhVZQMzABEBAAG0UVJhcHR1cmUgQXV0b21h\ndGljIFNpZ25pbmcgS2V5IChjbG91ZC1yYXB0dXJlLXNpZ25pbmcta2V5LTIwMjEt\nMDMtMDEtMDhfMDFfMDkucHViKYkBKAQTAQgAHAUCYD0QWQkQ/uqRaTB+oHECGwMF\nCQPDCrACGQEAAHtlCACxSWMp3yRcLmsHhxGDt59nhSNXhouWiNePSMe5vETQA/lh\nip9Zx/NPRCa4q5jpIDBlEYOg67YanztcjSWGSI35Xblq43H4uLSxh4PtKzZMo+Uj\n8n2VNHOZXBdGcsODcU3ynF64r7eTQevUe2aU0KN2o656O3HrE4itOVKYwnnkmNsk\nG45b9b7DJnsQ6WPszUc8lNhsa2gBI6vfLl68vjj7PlWw030BM/RoMEPpoOApohHo\nsfnNhxJmE1AxwBkMEzyo2kZhPZGh85LDnDbAvjSFKqYSPReKmRFjLlo3DPVHZ/de\nQn6noHbgUChLo21FefhlZO6tysrb283MWMIyY/YSuQENBGA9EFkBCADcdO/Aw1qu\ndZORZCNLz3vTiQSFcUFYyScfJJnwUsg8fy0kgg9olFY0GK5icT6n/shc1RlIpuqr\nOQYBZgtK3dSZfOAXE2N20HUvC+nrKKuXXX+jcM/X1kHxwX5tG6fB1fyNH0p/Qqsz\nEfYRHJu0Y4PonTYIslITnEzlN4hUN6/mx1+mWPl4P4R7/h6+p7Q2jtaClEtddF0e\neOf16Ma5S8fff80uZCLJoVu3lOXCT22oCf7qmH2XddmqGisUScqwmbmuv30tdQed\nn+8njKo2pfpVF1Oa67CWRXdKTknuZybxI9Ipcivy8CISL2Do0uzij7SR7keVf7G1\nQ3K3iJ0wn6mDABEBAAGJAR8EGAEIABMFAmA9EFkJEP7qkWkwfqBxAhsMAAA/3Af9\nFJ2hEp2144fzgtNWHOVFv27hsrO7wYFZwoic9lHSl4iEw8mJc/3kEXdg9Vf9m1zb\nG/kZ6slmzpfv7zDAdN3h3HT0B1yrb3xXzRX0zhOYAbQSUnc6DemhDZoDWt/wVceK\nfzvebB9VTDzRBUVzxCduvY6ij0p2APZpnTrznvCPoCHkfzBMC3Zyk1FueiPTPoP1\n9M0BProMy8qDVSkFr0uX3PM54hQN6mGRQg5HVVBxUNaMnn2yOQcxbQ/T/dKlojdp\nRmvpGyYjfrvyExE8owYn8L7ly2N76GcY6kiN1CmTnCgdrbU0SPacm7XbxTYlQHwJ\nCEa9Hf4/nuiBaxwXKuc/y5kBDQRfyX5eAQgA0z1F3ZDbtOe1/j90k1cQsyaVNjJ/\nrVGpinUnVWpmxnmBSDXKfxBsDRoXW9GtQWx7NUlmGW88IeHevqd5OAAc1TDvkaTL\nv2gcfROWjp+XPBsx42f1RGoXqiy4UlHEgswoUmXDeY89IUxoZgBmr4jLekTM0n2y\nIWT49ZA8wYhndEMHf6zj5ya+LWj67kd3nAY4R7YtfwTBnf5Y9Be80Jwo6ez66oKR\nDwU/I6PcF9sLzsl7MEiPxrH2xYmjiXw52Hp4GhIPLBfrt1jrNGdtHEq+pEu+ih6U\n32tyY2LHx7fDQ8PMOHtx/D8EMzYkT/bV3jAEikM93pjI/3pOh8Y4oWPahQARAQAB\ntLpnTGludXggUmFwdHVyZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKC8vZGVwb3Qv\nZ29vZ2xlMy9wcm9kdWN0aW9uL2JvcmcvY2xvdWQtcmFwdHVyZS9rZXlzL2Nsb3Vk\nLXJhcHR1cmUtcHVia2V5cy9jbG91ZC1yYXB0dXJlLXNpZ25pbmcta2V5LTIwMjAt\nMTItMDMtMTZfMDhfMDUucHViKSA8Z2xpbnV4LXRlYW1AZ29vZ2xlLmNvbT6JASgE\nEwEIABwFAl/Jfl4JEItXxcKDb0vrAhsDBQkDwwqwAhkBAABBeggAmnpK6OmlCSXd\n5lba7SzjnsFfHrdY3qeXsJqTq3sP6Wo0VQXiG1dWsFZ9P/BHHpxXo5j+lhXHQlqL\ng1SEv0JkRUFfTemFzfD4sGpa0Vd20yhQR5MGtXBB+AGnwhqNHA7yW/DdyZzP0Zm9\nSkhiq+2V6ZpC7WFaq+h4M5frJ65R9F8LJea90sr6gYL0WE0CmaSqpgRHdbnYnlaC\n0hffPJCnjQ4xWvkNUo2Txlvl7pIBPJAVG0g8fGPKugrM4d1VWPuSVHqopkYCdgA2\nNv95RLQGTrZsHAZYWNHD1laoGteBO5ExkligulvejX8vSuy+GKafJ0zBK7rNfNWq\nsMDXzKp6Z7kBDQRfyX5eAQgAw0ofinQXjYyHJVVZ0SrdEE+efd8heFlWbf04Dbmh\nGebypJ6KFVSKvnCSH2P95VKqvE3uHRI6HbRcinuV7noKOqo87PE2BXQgB16V0aFK\nJU9eJvqpCfK4Uq6TdE8SI1iWyXZtzZa4E2puUSicN0ocqTVMcqJZx3pV8asigwpM\nQUg5kesXHX7d8HUJeSJCAMMXup8sJklLaZ3Ri0SXSa2iYmlhdiAYxTYN70xGI+Hq\nHoWXeF67xMi1azGymeZun9aOkFEbs0q1B/SU/4r2agpoT6aLApV119G24vStGf/r\nlcpOr++prNzudKyKtC9GHoTPBvvqphjuNtftKgi5HQ+f4wARAQABiQEfBBgBCAAT\nBQJfyX5eCRCLV8XCg29L6wIbDAAAGxoIAMO5YUlhJWaRldUiNm9itujwfd31SNbU\nGFd+1iBJQibGoxfv2Q3ySdnep3LkEpXh+VkXHHOIWXysMrAP3qaqwp8HO8irE6Ge\nLMPMbCRdVLUORDbZHQK1YgSR0uGNlWeQxFJq+RIIRrWRYfWumi6HjFTP562Qi7LQ\n1aDyhKS6JB7v4HmwsH0/5/VNXaJRSKL4OnigApecTsfq83AFae0eD+du4337nc93\nSjHS4T67LRtMOWG8nzz8FjDj6fpFBeOXmHUe5CipNPVayTZBBidCkEOopqkdU59J\nMruHL5H6pwlBdK65+wnQai0gr9UEYYK+kwoUH+8p1rD8+YBnVY4d7SM=\n=UVi6\n-----END PGP PUBLIC KEY BLOCK-----\n-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFWKtqgBCADmKQWYQF9YoPxLEQZ5XA6DFVg9ZHG4HIuehsSJETMPQ+W9K5c5\nUs5assCZBjG/k5i62SmWb09eHtWsbbEgexURBWJ7IxA8kM3kpTo7bx+LqySDsSC3\n/8JRkiyibVV0dDNv/EzRQsGDxmk5Xl8SbQJ/C2ECSUT2ok225f079m2VJsUGHG+5\nRpyHHgoMaRNedYP8ksYBPSD6sA3Xqpsh/0cF4sm8QtmsxkBmCCIjBa0B0LybDtdX\nXIq5kPJsIrC2zvERIPm1ez/9FyGmZKEFnBGeFC45z5U//pHdB1z03dYKGrKdDpID\n17kNbC5wl24k/IeYyTY9IutMXvuNbVSXaVtRABEBAAG0Okdvb2dsZSBDbG91ZCBQ\nYWNrYWdlcyBSUE0gU2lnbmluZyBLZXkgPGdjLXRlYW1AZ29vZ2xlLmNvbT6JATgE\nEwECACIFAlWKtqgCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPCcOUw+\nG6jV+QwH/0wRH+XovIwLGfkg6kYLEvNPvOIYNQWnrT6zZ+XcV47WkJ+i5SR+QpUI\nudMSWVf4nkv+XVHruxydafRIeocaXY0E8EuIHGBSB2KR3HxG6JbgUiWlCVRNt4Qd\n6udC6Ep7maKEIpO40M8UHRuKrp4iLGIhPm3ELGO6uc8rks8qOBMH4ozU+3PB9a0b\nGnPBEsZdOBI1phyftLyyuEvG8PeUYD+uzSx8jp9xbMg66gQRMP9XGzcCkD+b8w1o\n7v3J3juKKpgvx5Lqwvwv2ywqn/Wr5d5OBCHEw8KtU/tfxycz/oo6XUIshgEbS/+P\n6yKDuYhRp6qxrYXjmAszIT25cftb4d4=\n=/PbX\n-----END PGP PUBLIC KEY BLOCK-----",
|
||||
"image_type_tags": ["test_type2"]
|
||||
},
|
||||
{
|
||||
"name": "google-cloud-sdk",
|
||||
"baseurl": "https://packages.cloud.google.com/yum/repos/cloud-sdk-el8-x86_64",
|
||||
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQENBGA9EFkBCAC1ilzST0wns+uwZyEA5IVtYeyAuXTaQUEAd70SqIlQpDd4EyVi\nx3SCanQIu8dG9Zq3+x28WBb2OuXP9oc06ybOWdu2m7N5PY0BUT4COA36JV/YrxmN\ns+5/M+YnDHppv63jgRIOkzXzXNo6SwTsl2xG9fKB3TS0IMvBkWdw5PGrBM5GghRc\necgoSAAwRbWJXORHGKVwlV6tOxQZ/xqA08hPJneMfsMFPOXsitgGRHoXjlUWLVeJ\n70mmIYsC/pBglIwCzmdD8Ee39MrlSXbuXVQiz38iHfnvXYpLEmgNXKzI0DH9tKg8\n323kALzqaJlLFOLJm/uVJXRUEfKS3LhVZQMzABEBAAG0UVJhcHR1cmUgQXV0b21h\ndGljIFNpZ25pbmcgS2V5IChjbG91ZC1yYXB0dXJlLXNpZ25pbmcta2V5LTIwMjEt\nMDMtMDEtMDhfMDFfMDkucHViKYkBKAQTAQgAHAUCYD0QWQkQ/uqRaTB+oHECGwMF\nCQPDCrACGQEAAHtlCACxSWMp3yRcLmsHhxGDt59nhSNXhouWiNePSMe5vETQA/lh\nip9Zx/NPRCa4q5jpIDBlEYOg67YanztcjSWGSI35Xblq43H4uLSxh4PtKzZMo+Uj\n8n2VNHOZXBdGcsODcU3ynF64r7eTQevUe2aU0KN2o656O3HrE4itOVKYwnnkmNsk\nG45b9b7DJnsQ6WPszUc8lNhsa2gBI6vfLl68vjj7PlWw030BM/RoMEPpoOApohHo\nsfnNhxJmE1AxwBkMEzyo2kZhPZGh85LDnDbAvjSFKqYSPReKmRFjLlo3DPVHZ/de\nQn6noHbgUChLo21FefhlZO6tysrb283MWMIyY/YSuQENBGA9EFkBCADcdO/Aw1qu\ndZORZCNLz3vTiQSFcUFYyScfJJnwUsg8fy0kgg9olFY0GK5icT6n/shc1RlIpuqr\nOQYBZgtK3dSZfOAXE2N20HUvC+nrKKuXXX+jcM/X1kHxwX5tG6fB1fyNH0p/Qqsz\nEfYRHJu0Y4PonTYIslITnEzlN4hUN6/mx1+mWPl4P4R7/h6+p7Q2jtaClEtddF0e\neOf16Ma5S8fff80uZCLJoVu3lOXCT22oCf7qmH2XddmqGisUScqwmbmuv30tdQed\nn+8njKo2pfpVF1Oa67CWRXdKTknuZybxI9Ipcivy8CISL2Do0uzij7SR7keVf7G1\nQ3K3iJ0wn6mDABEBAAGJAR8EGAEIABMFAmA9EFkJEP7qkWkwfqBxAhsMAAA/3Af9\nFJ2hEp2144fzgtNWHOVFv27hsrO7wYFZwoic9lHSl4iEw8mJc/3kEXdg9Vf9m1zb\nG/kZ6slmzpfv7zDAdN3h3HT0B1yrb3xXzRX0zhOYAbQSUnc6DemhDZoDWt/wVceK\nfzvebB9VTDzRBUVzxCduvY6ij0p2APZpnTrznvCPoCHkfzBMC3Zyk1FueiPTPoP1\n9M0BProMy8qDVSkFr0uX3PM54hQN6mGRQg5HVVBxUNaMnn2yOQcxbQ/T/dKlojdp\nRmvpGyYjfrvyExE8owYn8L7ly2N76GcY6kiN1CmTnCgdrbU0SPacm7XbxTYlQHwJ\nCEa9Hf4/nuiBaxwXKuc/y5kBDQRfyX5eAQgA0z1F3ZDbtOe1/j90k1cQsyaVNjJ/\nrVGpinUnVWpmxnmBSDXKfxBsDRoXW9GtQWx7NUlmGW88IeHevqd5OAAc1TDvkaTL\nv2gcfROWjp+XPBsx42f1RGoXqiy4UlHEgswoUmXDeY89IUxoZgBmr4jLekTM0n2y\nIWT49ZA8wYhndEMHf6zj5ya+LWj67kd3nAY4R7YtfwTBnf5Y9Be80Jwo6ez66oKR\nDwU/I6PcF9sLzsl7MEiPxrH2xYmjiXw52Hp4GhIPLBfrt1jrNGdtHEq+pEu+ih6U\n32tyY2LHx7fDQ8PMOHtx/D8EMzYkT/bV3jAEikM93pjI/3pOh8Y4oWPahQARAQAB\ntLpnTGludXggUmFwdHVyZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKC8vZGVwb3Qv\nZ29vZ2xlMy9wcm9kdWN0aW9uL2JvcmcvY2xvdWQtcmFwdHVyZS9rZXlzL2Nsb3Vk\nLXJhcHR1cmUtcHVia2V5cy9jbG91ZC1yYXB0dXJlLXNpZ25pbmcta2V5LTIwMjAt\nMTItMDMtMTZfMDhfMDUucHViKSA8Z2xpbnV4LXRlYW1AZ29vZ2xlLmNvbT6JASgE\nEwEIABwFAl/Jfl4JEItXxcKDb0vrAhsDBQkDwwqwAhkBAABBeggAmnpK6OmlCSXd\n5lba7SzjnsFfHrdY3qeXsJqTq3sP6Wo0VQXiG1dWsFZ9P/BHHpxXo5j+lhXHQlqL\ng1SEv0JkRUFfTemFzfD4sGpa0Vd20yhQR5MGtXBB+AGnwhqNHA7yW/DdyZzP0Zm9\nSkhiq+2V6ZpC7WFaq+h4M5frJ65R9F8LJea90sr6gYL0WE0CmaSqpgRHdbnYnlaC\n0hffPJCnjQ4xWvkNUo2Txlvl7pIBPJAVG0g8fGPKugrM4d1VWPuSVHqopkYCdgA2\nNv95RLQGTrZsHAZYWNHD1laoGteBO5ExkligulvejX8vSuy+GKafJ0zBK7rNfNWq\nsMDXzKp6Z7kBDQRfyX5eAQgAw0ofinQXjYyHJVVZ0SrdEE+efd8heFlWbf04Dbmh\nGebypJ6KFVSKvnCSH2P95VKqvE3uHRI6HbRcinuV7noKOqo87PE2BXQgB16V0aFK\nJU9eJvqpCfK4Uq6TdE8SI1iWyXZtzZa4E2puUSicN0ocqTVMcqJZx3pV8asigwpM\nQUg5kesXHX7d8HUJeSJCAMMXup8sJklLaZ3Ri0SXSa2iYmlhdiAYxTYN70xGI+Hq\nHoWXeF67xMi1azGymeZun9aOkFEbs0q1B/SU/4r2agpoT6aLApV119G24vStGf/r\nlcpOr++prNzudKyKtC9GHoTPBvvqphjuNtftKgi5HQ+f4wARAQABiQEfBBgBCAAT\nBQJfyX5eCRCLV8XCg29L6wIbDAAAGxoIAMO5YUlhJWaRldUiNm9itujwfd31SNbU\nGFd+1iBJQibGoxfv2Q3ySdnep3LkEpXh+VkXHHOIWXysMrAP3qaqwp8HO8irE6Ge\nLMPMbCRdVLUORDbZHQK1YgSR0uGNlWeQxFJq+RIIRrWRYfWumi6HjFTP562Qi7LQ\n1aDyhKS6JB7v4HmwsH0/5/VNXaJRSKL4OnigApecTsfq83AFae0eD+du4337nc93\nSjHS4T67LRtMOWG8nzz8FjDj6fpFBeOXmHUe5CipNPVayTZBBidCkEOopqkdU59J\nMruHL5H6pwlBdK65+wnQai0gr9UEYYK+kwoUH+8p1rD8+YBnVY4d7SM=\n=UVi6\n-----END PGP PUBLIC KEY BLOCK-----\n-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFWKtqgBCADmKQWYQF9YoPxLEQZ5XA6DFVg9ZHG4HIuehsSJETMPQ+W9K5c5\nUs5assCZBjG/k5i62SmWb09eHtWsbbEgexURBWJ7IxA8kM3kpTo7bx+LqySDsSC3\n/8JRkiyibVV0dDNv/EzRQsGDxmk5Xl8SbQJ/C2ECSUT2ok225f079m2VJsUGHG+5\nRpyHHgoMaRNedYP8ksYBPSD6sA3Xqpsh/0cF4sm8QtmsxkBmCCIjBa0B0LybDtdX\nXIq5kPJsIrC2zvERIPm1ez/9FyGmZKEFnBGeFC45z5U//pHdB1z03dYKGrKdDpID\n17kNbC5wl24k/IeYyTY9IutMXvuNbVSXaVtRABEBAAG0Okdvb2dsZSBDbG91ZCBQ\nYWNrYWdlcyBSUE0gU2lnbmluZyBLZXkgPGdjLXRlYW1AZ29vZ2xlLmNvbT6JATgE\nEwECACIFAlWKtqgCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPCcOUw+\nG6jV+QwH/0wRH+XovIwLGfkg6kYLEvNPvOIYNQWnrT6zZ+XcV47WkJ+i5SR+QpUI\nudMSWVf4nkv+XVHruxydafRIeocaXY0E8EuIHGBSB2KR3HxG6JbgUiWlCVRNt4Qd\n6udC6Ep7maKEIpO40M8UHRuKrp4iLGIhPm3ELGO6uc8rks8qOBMH4ozU+3PB9a0b\nGnPBEsZdOBI1phyftLyyuEvG8PeUYD+uzSx8jp9xbMg66gQRMP9XGzcCkD+b8w1o\n7v3J3juKKpgvx5Lqwvwv2ywqn/Wr5d5OBCHEw8KtU/tfxycz/oo6XUIshgEbS/+P\n6yKDuYhRp6qxrYXjmAszIT25cftb4d4=\n=/PbX\n-----END PGP PUBLIC KEY BLOCK-----",
|
||||
"image_type_tags": ["test_type2"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ func TestLoadRepositoriesExisting(t *testing.T) {
|
|||
},
|
||||
want: map[string][]string{
|
||||
test_distro.TestArchName: {"baseos-p2", "appstream-p2"},
|
||||
test_distro.TestArch2Name: {"baseos-p2", "appstream-p2"},
|
||||
test_distro.TestArch2Name: {"baseos-p2", "appstream-p2", "google-compute-engine", "google-cloud-sdk"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -86,3 +86,60 @@ func TestLoadRepositoriesNonExisting(t *testing.T) {
|
|||
assert.Nil(t, repos)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func Test_LoadAllRepositories(t *testing.T) {
|
||||
confPaths := getConfPaths(t)
|
||||
|
||||
distroReposMap, err := rpmmd.LoadAllRepositories(confPaths)
|
||||
assert.NotNil(t, distroReposMap)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(distroReposMap), 2)
|
||||
|
||||
// test-distro
|
||||
testDistroRepos, exists := distroReposMap[test_distro.TestDistroName]
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, len(testDistroRepos), 2)
|
||||
|
||||
// test-distro - arches
|
||||
for _, arch := range []string{test_distro.TestArchName, test_distro.TestArch2Name} {
|
||||
testDistroArchRepos, exists := testDistroRepos[arch]
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, len(testDistroArchRepos), 4)
|
||||
|
||||
var repoNames []string
|
||||
for _, r := range testDistroArchRepos {
|
||||
repoNames = append(repoNames, r.Name)
|
||||
}
|
||||
|
||||
wantRepos := []string{"fedora-p1", "updates-p1", "fedora-modular-p1", "updates-modular-p1"}
|
||||
|
||||
if !reflect.DeepEqual(repoNames, wantRepos) {
|
||||
t.Errorf("LoadAllRepositories() for %s/%s =\n got: %#v\n want: %#v", test_distro.TestDistroName, arch, repoNames, wantRepos)
|
||||
}
|
||||
}
|
||||
|
||||
// test-distro-2
|
||||
testDistro2Repos, exists := distroReposMap[test_distro.TestDistro2Name]
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, len(testDistro2Repos), 2)
|
||||
|
||||
// test-distro-2 - arches
|
||||
wantRepos := map[string][]string{
|
||||
test_distro.TestArchName: {"baseos-p2", "appstream-p2"},
|
||||
test_distro.TestArch2Name: {"baseos-p2", "appstream-p2", "google-compute-engine", "google-cloud-sdk"},
|
||||
}
|
||||
for _, arch := range []string{test_distro.TestArchName, test_distro.TestArch2Name} {
|
||||
testDistro2ArchRepos, exists := testDistro2Repos[arch]
|
||||
assert.True(t, exists)
|
||||
assert.Equal(t, len(testDistro2ArchRepos), len(wantRepos[arch]))
|
||||
|
||||
var repoNames []string
|
||||
for _, r := range testDistro2ArchRepos {
|
||||
repoNames = append(repoNames, r.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(repoNames, wantRepos[arch]) {
|
||||
t.Errorf("LoadAllRepositories() for %s/%s =\n got: %#v\n want: %#v", test_distro.TestDistro2Name, arch, repoNames, wantRepos[arch])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue