customizations: custom repo utility functions
Create some utility functions that will be used for implementing custom repo configuration files. This commit adds these functions: - a helper to get the filename of a custom repo, or the `<repo-id>.repo` if the filename is empty - a function to convert the custom repos to a map of `RepoConfig`. This function also creates an `fsnode.File` for each inline gpg key set in the customizations and swaps the inline key for the file path. The function returns the map of `RepoConfig` and a list of `fsnode.File` containing the inline gpg keys.
This commit is contained in:
parent
3b6fddb14a
commit
29643c2e06
2 changed files with 324 additions and 0 deletions
|
|
@ -2,6 +2,10 @@ package blueprint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/osbuild/osbuild-composer/internal/fsnode"
|
||||||
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RepositoryCustomization struct {
|
type RepositoryCustomization struct {
|
||||||
|
|
@ -33,3 +37,68 @@ func validateCustomRepository(repo *RepositoryCustomization) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *RepositoryCustomization) getFilename() string {
|
||||||
|
if rc.Filename == "" {
|
||||||
|
return fmt.Sprintf("%s.repo", rc.Id)
|
||||||
|
}
|
||||||
|
return rc.Filename
|
||||||
|
}
|
||||||
|
|
||||||
|
func RepoCustomizationsToRepoConfigAndGPGKeyFiles(repos []RepositoryCustomization) (map[string][]rpmmd.RepoConfig, []*fsnode.File, error) {
|
||||||
|
if len(repos) == 0 {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
repoMap := make(map[string][]rpmmd.RepoConfig, len(repos))
|
||||||
|
var gpgKeyFiles []*fsnode.File
|
||||||
|
for _, repo := range repos {
|
||||||
|
filename := repo.getFilename()
|
||||||
|
convertedRepo := repo.customRepoToRepoConfig()
|
||||||
|
|
||||||
|
// convert any inline gpgkeys to fsnode.File and
|
||||||
|
// replace the gpgkey with the file path
|
||||||
|
for idx, gpgkey := range repo.GPGKeys {
|
||||||
|
if _, ok := url.ParseRequestURI(gpgkey); ok != nil {
|
||||||
|
// create the file path
|
||||||
|
path := fmt.Sprintf("/etc/pki/rpm-gpg/RPM-GPG-KEY-%s-%d", repo.Id, idx)
|
||||||
|
// replace the gpgkey with the file path
|
||||||
|
convertedRepo.GPGKeys[idx] = fmt.Sprintf("file://%s", path)
|
||||||
|
// create the fsnode for the gpgkey keyFile
|
||||||
|
keyFile, err := fsnode.NewFile(path, nil, nil, nil, []byte(gpgkey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
gpgKeyFiles = append(gpgKeyFiles, keyFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repoMap[filename] = append(repoMap[filename], convertedRepo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return repoMap, gpgKeyFiles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo RepositoryCustomization) customRepoToRepoConfig() rpmmd.RepoConfig {
|
||||||
|
urls := make([]string, len(repo.BaseURLs))
|
||||||
|
copy(urls, repo.BaseURLs)
|
||||||
|
|
||||||
|
keys := make([]string, len(repo.GPGKeys))
|
||||||
|
copy(keys, repo.GPGKeys)
|
||||||
|
|
||||||
|
repoConfig := rpmmd.RepoConfig{
|
||||||
|
Id: repo.Id,
|
||||||
|
BaseURLs: urls,
|
||||||
|
GPGKeys: keys,
|
||||||
|
Name: repo.Name,
|
||||||
|
Metalink: repo.Metalink,
|
||||||
|
MirrorList: repo.Mirrorlist,
|
||||||
|
CheckGPG: repo.GPGCheck,
|
||||||
|
CheckRepoGPG: repo.RepoGPGCheck,
|
||||||
|
Priority: repo.Priority,
|
||||||
|
Enabled: repo.Enabled,
|
||||||
|
IgnoreSSL: !repo.SSLVerify,
|
||||||
|
}
|
||||||
|
|
||||||
|
return repoConfig
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/osbuild/osbuild-composer/internal/common"
|
"github.com/osbuild/osbuild-composer/internal/common"
|
||||||
|
"github.com/osbuild/osbuild-composer/internal/fsnode"
|
||||||
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -78,3 +80,256 @@ func TestGetCustomRepositories(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomRepoFilename(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
Repo RepositoryCustomization
|
||||||
|
WantFilename string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "Test default filename #1",
|
||||||
|
Repo: RepositoryCustomization{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
},
|
||||||
|
WantFilename: "example-1.repo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Test default filename #2",
|
||||||
|
Repo: RepositoryCustomization{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
},
|
||||||
|
WantFilename: "example-2.repo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Test custom filename",
|
||||||
|
Repo: RepositoryCustomization{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
Filename: "test.repo",
|
||||||
|
},
|
||||||
|
WantFilename: "test.repo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testCases {
|
||||||
|
t.Run(tt.Name, func(t *testing.T) {
|
||||||
|
got := tt.Repo.getFilename()
|
||||||
|
assert.Equal(t, tt.WantFilename, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCustomRepoToRepoConfigAndGPGKeys(t *testing.T) {
|
||||||
|
ensureFileCreation := func(file *fsnode.File, err error) *fsnode.File {
|
||||||
|
t.Helper()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, file)
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
Repos []RepositoryCustomization
|
||||||
|
WantRepoConfig map[string][]rpmmd.RepoConfig
|
||||||
|
WantGPGKeys []*fsnode.File
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "Test no gpg keys, no filenames",
|
||||||
|
Repos: []RepositoryCustomization{
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantRepoConfig: map[string][]rpmmd.RepoConfig{
|
||||||
|
"example-1.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"example-2.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantGPGKeys: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Test no gpg keys, filenames",
|
||||||
|
Repos: []RepositoryCustomization{
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
SSLVerify: true,
|
||||||
|
Filename: "test-1.repo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
SSLVerify: true,
|
||||||
|
Filename: "test-2.repo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantRepoConfig: map[string][]rpmmd.RepoConfig{
|
||||||
|
"test-1.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-2.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantGPGKeys: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Test remote gpgkeys",
|
||||||
|
Repos: []RepositoryCustomization{
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{"http://example-1.com/gpgkey"},
|
||||||
|
GPGCheck: common.ToPtr(true),
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{"http://example-2.com/gpgkey"},
|
||||||
|
GPGCheck: common.ToPtr(true),
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantRepoConfig: map[string][]rpmmd.RepoConfig{
|
||||||
|
"example-1.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{"http://example-1.com/gpgkey"},
|
||||||
|
CheckGPG: common.ToPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"example-2.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{"http://example-2.com/gpgkey"},
|
||||||
|
CheckGPG: common.ToPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantGPGKeys: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Test inline gpgkeys",
|
||||||
|
Repos: []RepositoryCustomization{
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{"fake-gpg-key-1"},
|
||||||
|
GPGCheck: common.ToPtr(true),
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{"fake-gpg-key-2"},
|
||||||
|
GPGCheck: common.ToPtr(true),
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantRepoConfig: map[string][]rpmmd.RepoConfig{
|
||||||
|
"example-1.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{"file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example-1-0"},
|
||||||
|
CheckGPG: common.ToPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"example-2.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{"file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example-2-0"},
|
||||||
|
CheckGPG: common.ToPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantGPGKeys: []*fsnode.File{
|
||||||
|
ensureFileCreation(fsnode.NewFile("/etc/pki/rpm-gpg/RPM-GPG-KEY-example-1-0", nil, nil, nil, []byte("fake-gpg-key-1"))),
|
||||||
|
ensureFileCreation(fsnode.NewFile("/etc/pki/rpm-gpg/RPM-GPG-KEY-example-2-0", nil, nil, nil, []byte("fake-gpg-key-1"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Test multiple inline gpgkeys",
|
||||||
|
Repos: []RepositoryCustomization{
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{"fake-gpg-key-1", "fake-gpg-key-2"},
|
||||||
|
GPGCheck: common.ToPtr(true),
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{"fake-gpg-key-1", "fake-gpg-key-2"},
|
||||||
|
GPGCheck: common.ToPtr(true),
|
||||||
|
SSLVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantRepoConfig: map[string][]rpmmd.RepoConfig{
|
||||||
|
"example-1.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-1",
|
||||||
|
BaseURLs: []string{"http://example-1.com"},
|
||||||
|
GPGKeys: []string{"file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example-1-0", "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example-1-1"},
|
||||||
|
CheckGPG: common.ToPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"example-2.repo": {
|
||||||
|
{
|
||||||
|
Id: "example-2",
|
||||||
|
BaseURLs: []string{"http://example-2.com"},
|
||||||
|
GPGKeys: []string{"file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example-2-0", "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example-2-1"},
|
||||||
|
CheckGPG: common.ToPtr(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WantGPGKeys: []*fsnode.File{
|
||||||
|
ensureFileCreation(fsnode.NewFile("/etc/pki/rpm-gpg/RPM-GPG-KEY-example-1-0", nil, nil, nil, []byte("fake-gpg-key-1"))),
|
||||||
|
ensureFileCreation(fsnode.NewFile("/etc/pki/rpm-gpg/RPM-GPG-KEY-example-1-1", nil, nil, nil, []byte("fake-gpg-key-2"))),
|
||||||
|
ensureFileCreation(fsnode.NewFile("/etc/pki/rpm-gpg/RPM-GPG-KEY-example-2-0", nil, nil, nil, []byte("fake-gpg-key-1"))),
|
||||||
|
ensureFileCreation(fsnode.NewFile("/etc/pki/rpm-gpg/RPM-GPG-KEY-example-2-1", nil, nil, nil, []byte("fake-gpg-key-2"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testCases {
|
||||||
|
t.Run(tt.Name, func(t *testing.T) {
|
||||||
|
got, _, err := RepoCustomizationsToRepoConfigAndGPGKeyFiles(tt.Repos)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.WantRepoConfig, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue