internal/rpmmd: RepoConfig baseurl change

Update the internal RepoConfig object to
accept a slice of baseurls rather than a
single field. This change was needed to
align RepoConfig with the dnf spec [1].

Additionally, this change adds custom json
marshal and unmarshal functions to ensure
backwards compatibility with older workers.
Add json tags to the internal rpmmd config
since this is serialized in dnfjson.
Add unit tests to check the serialization
is okay.

[1] See dnf.config
This commit is contained in:
Gianluca Zuccarelli 2023-01-23 16:07:21 +00:00 committed by Tomáš Hozza
parent 17d730593c
commit 4d42808b6a
23 changed files with 368 additions and 198 deletions

View file

@ -28,18 +28,18 @@ type repository struct {
}
type RepoConfig struct {
Name string
BaseURL string
Metalink string
MirrorList string
GPGKeys []string
CheckGPG bool
CheckRepoGPG bool
IgnoreSSL bool
MetadataExpire string
RHSM bool
ImageTypeTags []string
PackageSets []string
Name string `json:"name,omitempty"`
BaseURLs []string `json:"baseurls,omitempty"`
Metalink string `json:"metalink,omitempty"`
MirrorList string `json:"mirrorlist,omitempty"`
GPGKeys []string `json:"gpgkeys,omitempty"`
CheckGPG bool `json:"check_gpg,omitempty"`
CheckRepoGPG bool `json:"check_repo_gpg,omitempty"`
IgnoreSSL bool `json:"ignore_ssl,omitempty"`
MetadataExpire string `json:"metadata_expire,omitempty"`
RHSM bool `json:"rhsm,omitempty"`
ImageTypeTags []string `json:"image_type_tags,omitempty"`
PackageSets []string `json:"package_sets,omitempty"`
}
// Hash calculates an ID string that uniquely represents a repository
@ -52,7 +52,7 @@ func (r *RepoConfig) Hash() string {
ats := func(s []string) string {
return strings.Join(s, "")
}
return fmt.Sprintf("%x", sha256.Sum256([]byte(r.BaseURL+
return fmt.Sprintf("%x", sha256.Sum256([]byte(ats(r.BaseURLs)+
r.Metalink+
r.MirrorList+
ats(r.GPGKeys)+
@ -223,14 +223,17 @@ func loadRepositoriesFromFile(filename string) (map[string][]RepoConfig, error)
for arch, repos := range reposMap {
for _, repo := range repos {
var urls []string
if repo.BaseURL != "" {
urls = []string{repo.BaseURL}
}
var keys []string
if repo.GPGKey != "" {
keys = []string{repo.GPGKey}
}
config := RepoConfig{
Name: repo.Name,
BaseURL: repo.BaseURL,
BaseURLs: urls,
Metalink: repo.Metalink,
MirrorList: repo.MirrorList,
GPGKeys: keys,
@ -375,3 +378,57 @@ func (packages PackageList) ToPackageInfos() []PackageInfo {
return results
}
// Backwards compatibility for old workers:
// This was added since the custom repository
// PR changes the baseurl field to a list of baseurls.
// This can be removed after 3 releases since the
// old-worker-regression test tests the current
// osbuild-composer with a worker from 3 releases ago
func (r RepoConfig) MarshalJSON() ([]byte, error) {
type aliasType RepoConfig
type compatType struct {
aliasType
BaseURL string `json:"baseurl,omitempty"`
}
compatRepo := compatType{
aliasType: aliasType(r),
}
var baseUrl string
if len(r.BaseURLs) > 0 {
baseUrl = strings.Join(r.BaseURLs, ",")
}
compatRepo.BaseURL = baseUrl
return json.Marshal(compatRepo)
}
// Backwards compatibility for old workers:
// This was added since the custom repository
// PR changes the baseurl field to a list of baseurls.
// This can be removed after 3 releases since the
// old-worker-regression test tests the current
// osbuild-composer with a worker from 3 releases ago
func (r *RepoConfig) UnmarshalJSON(data []byte) error {
type aliasType RepoConfig
type compatType struct {
aliasType
BaseURL string `json:"baseurl,omitempty"`
}
var compatRepo compatType
if err := json.Unmarshal(data, &compatRepo); err != nil {
return err
}
if compatRepo.BaseURL != "" {
compatRepo.BaseURLs = strings.Split(compatRepo.BaseURL, ",")
}
*r = RepoConfig(compatRepo.aliasType)
return nil
}

View file

@ -1,6 +1,7 @@
package rpmmdtests
import (
"encoding/json"
"fmt"
"path/filepath"
"reflect"
@ -189,3 +190,98 @@ func TestPackageSetResolveConflictExclude(t *testing.T) {
})
}
}
func TestOldWorkerRepositoryCompatUnmarshal(t *testing.T) {
testCases := []struct {
repoJSON []byte
repo rpmmd.RepoConfig
}{
{
repoJSON: []byte(`{"name":"fedora","baseurl":"http://example.com/fedora"}`),
repo: rpmmd.RepoConfig{
Name: "fedora",
BaseURLs: []string{"http://example.com/fedora"},
},
},
{
repoJSON: []byte(`{"name":"multiple","baseurl":"http://example.com/one,http://example.com/two"}`),
repo: rpmmd.RepoConfig{
Name: "multiple",
BaseURLs: []string{"http://example.com/one", "http://example.com/two"},
},
},
{
repoJSON: []byte(`{"name":"all","baseurls":["http://example.com/all"],"metalink":"http://example.com/metalink","mirrorlist":"http://example.com/mirrorlist","gpgkeys":["key1","key2"],"check_gpg":true,"check_repo_gpg":true,"ignore_ssl":true,"metadata_expire":"test","rhsm":true,"image_type_tags":["one","two"],"package_sets":["1","2"],"baseurl":"http://example.com/all"}`),
repo: rpmmd.RepoConfig{
Name: "all",
BaseURLs: []string{"http://example.com/all"},
Metalink: "http://example.com/metalink",
MirrorList: "http://example.com/mirrorlist",
GPGKeys: []string{"key1", "key2"},
CheckGPG: true,
CheckRepoGPG: true,
IgnoreSSL: true,
MetadataExpire: "test",
RHSM: true,
ImageTypeTags: []string{"one", "two"},
PackageSets: []string{"1", "2"},
},
},
}
for _, tc := range testCases {
t.Run(tc.repo.Name, func(t *testing.T) {
var repo rpmmd.RepoConfig
err := json.Unmarshal(tc.repoJSON, &repo)
assert.Nil(t, err)
assert.Equal(t, tc.repo, repo)
})
}
}
func TestOldWorkerRepositoryCompatMarshal(t *testing.T) {
testCases := []struct {
repoJSON []byte
repo rpmmd.RepoConfig
}{
{
repoJSON: []byte(`{"name":"fedora","baseurls":["http://example.com/fedora"],"baseurl":"http://example.com/fedora"}`),
repo: rpmmd.RepoConfig{
Name: "fedora",
BaseURLs: []string{"http://example.com/fedora"},
},
},
{
repoJSON: []byte(`{"name":"multiple","baseurls":["http://example.com/one","http://example.com/two"],"baseurl":"http://example.com/one,http://example.com/two"}`),
repo: rpmmd.RepoConfig{
Name: "multiple",
BaseURLs: []string{"http://example.com/one", "http://example.com/two"},
},
},
{
repoJSON: []byte(`{"name":"all","baseurls":["http://example.com/all"],"metalink":"http://example.com/metalink","mirrorlist":"http://example.com/mirrorlist","gpgkeys":["key1","key2"],"check_gpg":true,"check_repo_gpg":true,"ignore_ssl":true,"metadata_expire":"test","rhsm":true,"image_type_tags":["one","two"],"package_sets":["1","2"],"baseurl":"http://example.com/all"}`),
repo: rpmmd.RepoConfig{
Name: "all",
BaseURLs: []string{"http://example.com/all"},
Metalink: "http://example.com/metalink",
MirrorList: "http://example.com/mirrorlist",
GPGKeys: []string{"key1", "key2"},
CheckGPG: true,
CheckRepoGPG: true,
IgnoreSSL: true,
MetadataExpire: "test",
RHSM: true,
ImageTypeTags: []string{"one", "two"},
PackageSets: []string{"1", "2"},
},
},
}
for _, tc := range testCases {
t.Run(tc.repo.Name, func(t *testing.T) {
gotJson, err := json.Marshal(tc.repo)
assert.Nil(t, err)
assert.Equal(t, tc.repoJSON, gotJson)
})
}
}