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 (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/osbuild/osbuild-composer/internal/fsnode"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
type RepositoryCustomization struct {
|
||||
|
|
@ -33,3 +37,68 @@ func validateCustomRepository(repo *RepositoryCustomization) error {
|
|||
}
|
||||
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"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
|
|
@ -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