Blame internal/store/store.go

Packit 63bb0d
// Package store contains primitives for representing and changing the
Packit 63bb0d
// osbuild-composer state.
Packit 63bb0d
package store
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"crypto/rand"
Packit 63bb0d
	"crypto/sha1"
Packit 63bb0d
	"encoding/hex"
Packit 63bb0d
	"errors"
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"log"
Packit 63bb0d
	"sort"
Packit 63bb0d
	"sync"
Packit 63bb0d
	"time"
Packit 63bb0d
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/distro"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/jsondb"
Packit 63bb0d
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/blueprint"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/common"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/rpmmd"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/target"
Packit 63bb0d
Packit 63bb0d
	"github.com/google/uuid"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// StoreDBName is the name under which to save the store to the underlying jsondb
Packit 63bb0d
const StoreDBName = "state"
Packit 63bb0d
Packit 63bb0d
// A Store contains all the persistent state of osbuild-composer, and is serialized
Packit 63bb0d
// on every change, and deserialized on start.
Packit 63bb0d
type Store struct {
Packit 63bb0d
	blueprints        map[string]blueprint.Blueprint
Packit 63bb0d
	workspace         map[string]blueprint.Blueprint
Packit 63bb0d
	composes          map[uuid.UUID]Compose
Packit 63bb0d
	sources           map[string]SourceConfig
Packit 63bb0d
	blueprintsChanges map[string]map[string]blueprint.Change
Packit 63bb0d
	blueprintsCommits map[string][]string
Packit 63bb0d
Packit 63bb0d
	mu       sync.RWMutex // protects all fields
Packit 63bb0d
	stateDir *string
Packit 63bb0d
	db       *jsondb.JSONDatabase
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type SourceConfig struct {
Packit 63bb0d
	Name     string `json:"name" toml:"name"`
Packit 63bb0d
	Type     string `json:"type" toml:"type"`
Packit 63bb0d
	URL      string `json:"url" toml:"url"`
Packit 63bb0d
	CheckGPG bool   `json:"check_gpg" toml:"check_gpg"`
Packit 63bb0d
	CheckSSL bool   `json:"check_ssl" toml:"check_ssl"`
Packit 63bb0d
	System   bool   `json:"system" toml:"system"`
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type NotFoundError struct {
Packit 63bb0d
	message string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (e *NotFoundError) Error() string {
Packit 63bb0d
	return e.message
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type NoLocalTargetError struct {
Packit 63bb0d
	message string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (e *NoLocalTargetError) Error() string {
Packit 63bb0d
	return e.message
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func New(stateDir *string, arch distro.Arch, log *log.Logger) *Store {
Packit 63bb0d
	var storeStruct storeV0
Packit 63bb0d
	var db *jsondb.JSONDatabase
Packit 63bb0d
Packit 63bb0d
	if stateDir != nil {
Packit 63bb0d
		db = jsondb.New(*stateDir, 0600)
Packit 63bb0d
		_, err := db.Read(StoreDBName, &storeStruct)
Packit 63bb0d
		if err != nil && log != nil {
Packit 63bb0d
			log.Fatalf("cannot read state: %v", err)
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	store := newStoreFromV0(storeStruct, arch, log)
Packit 63bb0d
Packit 63bb0d
	store.stateDir = stateDir
Packit 63bb0d
	store.db = db
Packit 63bb0d
Packit 63bb0d
	return store
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func randomSHA1String() (string, error) {
Packit 63bb0d
	hash := sha1.New()
Packit 63bb0d
	data := make([]byte, 20)
Packit 63bb0d
	n, err := rand.Read(data)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return "", err
Packit 63bb0d
	} else if n != 20 {
Packit 63bb0d
		return "", errors.New("randomSHA1String: short read from rand")
Packit 63bb0d
	}
Packit 63bb0d
	_, err = hash.Write(data)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return "", err
Packit 63bb0d
	}
Packit 63bb0d
	return hex.EncodeToString(hash.Sum(nil)), nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) change(f func() error) error {
Packit 63bb0d
	s.mu.Lock()
Packit 63bb0d
	defer s.mu.Unlock()
Packit 63bb0d
Packit 63bb0d
	result := f()
Packit 63bb0d
Packit 63bb0d
	if s.stateDir != nil {
Packit 63bb0d
		err := s.db.Write(StoreDBName, s.toStoreV0())
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			panic(err)
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return result
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) ListBlueprints() []string {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	names := make([]string, 0, len(s.blueprints))
Packit 63bb0d
	for name := range s.blueprints {
Packit 63bb0d
		names = append(names, name)
Packit 63bb0d
	}
Packit 63bb0d
	sort.Strings(names)
Packit 63bb0d
Packit 63bb0d
	return names
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) GetBlueprint(name string) (*blueprint.Blueprint, bool) {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	bp, inWorkspace := s.workspace[name]
Packit 63bb0d
	if !inWorkspace {
Packit 63bb0d
		var ok bool
Packit 63bb0d
		bp, ok = s.blueprints[name]
Packit 63bb0d
		if !ok {
Packit 63bb0d
			return nil, false
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &bp, inWorkspace
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) GetBlueprintCommitted(name string) *blueprint.Blueprint {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	bp, ok := s.blueprints[name]
Packit 63bb0d
	if !ok {
Packit 63bb0d
		return nil
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &bp
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetBlueprintChange returns a specific change to a blueprint
Packit 63bb0d
// If the blueprint or change do not exist then an error is returned
Packit 63bb0d
func (s *Store) GetBlueprintChange(name string, commit string) (*blueprint.Change, error) {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	if _, ok := s.blueprintsChanges[name]; !ok {
Packit 63bb0d
		return nil, errors.New("Unknown blueprint")
Packit 63bb0d
	}
Packit 63bb0d
	change, ok := s.blueprintsChanges[name][commit]
Packit 63bb0d
	if !ok {
Packit 63bb0d
		return nil, errors.New("Unknown commit")
Packit 63bb0d
	}
Packit 63bb0d
	return &change, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetBlueprintChanges returns the list of changes, oldest first
Packit 63bb0d
func (s *Store) GetBlueprintChanges(name string) []blueprint.Change {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	var changes []blueprint.Change
Packit 63bb0d
Packit 63bb0d
	for _, commit := range s.blueprintsCommits[name] {
Packit 63bb0d
		changes = append(changes, s.blueprintsChanges[name][commit])
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return changes
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) PushBlueprint(bp blueprint.Blueprint, commitMsg string) error {
Packit 63bb0d
	return s.change(func() error {
Packit 63bb0d
		commit, err := randomSHA1String()
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return err
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		// Make sure the blueprint has default values and that the version is valid
Packit 63bb0d
		err = bp.Initialize()
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return err
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		timestamp := time.Now().Format("2006-01-02T15:04:05Z")
Packit 63bb0d
		change := blueprint.Change{
Packit 63bb0d
			Commit:    commit,
Packit 63bb0d
			Message:   commitMsg,
Packit 63bb0d
			Timestamp: timestamp,
Packit 63bb0d
			Blueprint: bp,
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		delete(s.workspace, bp.Name)
Packit 63bb0d
		if s.blueprintsChanges[bp.Name] == nil {
Packit 63bb0d
			s.blueprintsChanges[bp.Name] = make(map[string]blueprint.Change)
Packit 63bb0d
		}
Packit 63bb0d
		s.blueprintsChanges[bp.Name][commit] = change
Packit 63bb0d
		// Keep track of the order of the commits
Packit 63bb0d
		s.blueprintsCommits[bp.Name] = append(s.blueprintsCommits[bp.Name], commit)
Packit 63bb0d
Packit 63bb0d
		if old, ok := s.blueprints[bp.Name]; ok {
Packit 63bb0d
			if bp.Version == "" || bp.Version == old.Version {
Packit 63bb0d
				bp.BumpVersion(old.Version)
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
		s.blueprints[bp.Name] = bp
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) PushBlueprintToWorkspace(bp blueprint.Blueprint) error {
Packit 63bb0d
	return s.change(func() error {
Packit 63bb0d
		// Make sure the blueprint has default values and that the version is valid
Packit 63bb0d
		err := bp.Initialize()
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return err
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		s.workspace[bp.Name] = bp
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// DeleteBlueprint will remove the named blueprint from the store
Packit 63bb0d
// if the blueprint does not exist it will return an error
Packit 63bb0d
// The workspace copy is deleted unconditionally, it will not return an error if it does not exist.
Packit 63bb0d
func (s *Store) DeleteBlueprint(name string) error {
Packit 63bb0d
	return s.change(func() error {
Packit 63bb0d
		delete(s.workspace, name)
Packit 63bb0d
		if _, ok := s.blueprints[name]; !ok {
Packit 63bb0d
			return fmt.Errorf("Unknown blueprint: %s", name)
Packit 63bb0d
		}
Packit 63bb0d
		delete(s.blueprints, name)
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// DeleteBlueprintFromWorkspace deletes the workspace copy of a blueprint
Packit 63bb0d
// if the blueprint doesn't exist in the workspace it returns an error
Packit 63bb0d
func (s *Store) DeleteBlueprintFromWorkspace(name string) error {
Packit 63bb0d
	return s.change(func() error {
Packit 63bb0d
		if _, ok := s.workspace[name]; !ok {
Packit 63bb0d
			return fmt.Errorf("Unknown blueprint: %s", name)
Packit 63bb0d
		}
Packit 63bb0d
		delete(s.workspace, name)
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// TagBlueprint will tag the most recent commit
Packit 63bb0d
// It will return an error if the blueprint doesn't exist
Packit 63bb0d
func (s *Store) TagBlueprint(name string) error {
Packit 63bb0d
	return s.change(func() error {
Packit 63bb0d
		_, ok := s.blueprints[name]
Packit 63bb0d
		if !ok {
Packit 63bb0d
			return errors.New("Unknown blueprint")
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		if len(s.blueprintsCommits[name]) == 0 {
Packit 63bb0d
			return errors.New("No commits for blueprint")
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		latest := s.blueprintsCommits[name][len(s.blueprintsCommits[name])-1]
Packit 63bb0d
		// If the most recent commit already has a revision, don't bump it
Packit 63bb0d
		if s.blueprintsChanges[name][latest].Revision != nil {
Packit 63bb0d
			return nil
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		// Get the latest revision for this blueprint
Packit 63bb0d
		var revision int
Packit 63bb0d
		var change blueprint.Change
Packit 63bb0d
		for i := len(s.blueprintsCommits[name]) - 1; i >= 0; i-- {
Packit 63bb0d
			commit := s.blueprintsCommits[name][i]
Packit 63bb0d
			change = s.blueprintsChanges[name][commit]
Packit 63bb0d
			if change.Revision != nil && *change.Revision > revision {
Packit 63bb0d
				revision = *change.Revision
Packit 63bb0d
				break
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		// Bump the revision (if there was none it will start at 1)
Packit 63bb0d
		revision++
Packit 63bb0d
		change.Revision = &revision
Packit 63bb0d
		s.blueprintsChanges[name][latest] = change
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) GetCompose(id uuid.UUID) (Compose, bool) {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	compose, exists := s.composes[id]
Packit 63bb0d
	return compose, exists
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetAllComposes creates a deep copy of all composes present in this store
Packit 63bb0d
// and returns them as a dictionary with compose UUIDs as keys
Packit 63bb0d
func (s *Store) GetAllComposes() map[uuid.UUID]Compose {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	composes := make(map[uuid.UUID]Compose)
Packit 63bb0d
Packit 63bb0d
	for id, singleCompose := range s.composes {
Packit 63bb0d
		newCompose := singleCompose.DeepCopy()
Packit 63bb0d
		composes[id] = newCompose
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return composes
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) PushCompose(composeID uuid.UUID, manifest distro.Manifest, imageType distro.ImageType, bp *blueprint.Blueprint, size uint64, targets []*target.Target, jobId uuid.UUID) error {
Packit 63bb0d
	if _, exists := s.GetCompose(composeID); exists {
Packit 63bb0d
		panic("a compose with this id already exists")
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if targets == nil {
Packit 63bb0d
		targets = []*target.Target{}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// FIXME: handle or comment this possible error
Packit 63bb0d
	_ = s.change(func() error {
Packit 63bb0d
		s.composes[composeID] = Compose{
Packit 63bb0d
			Blueprint: bp,
Packit 63bb0d
			ImageBuild: ImageBuild{
Packit 63bb0d
				Manifest:   manifest,
Packit 63bb0d
				ImageType:  imageType,
Packit 63bb0d
				Targets:    targets,
Packit 63bb0d
				JobCreated: time.Now(),
Packit 63bb0d
				Size:       size,
Packit 63bb0d
				JobID:      jobId,
Packit 63bb0d
			},
Packit 63bb0d
		}
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
	return nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// PushTestCompose is used for testing
Packit 63bb0d
// Set testSuccess to create a fake successful compose, otherwise it will create a failed compose
Packit 63bb0d
// It does not actually run a compose job
Packit 63bb0d
func (s *Store) PushTestCompose(composeID uuid.UUID, manifest distro.Manifest, imageType distro.ImageType, bp *blueprint.Blueprint, size uint64, targets []*target.Target, testSuccess bool) error {
Packit 63bb0d
	if targets == nil {
Packit 63bb0d
		targets = []*target.Target{}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var status common.ImageBuildState
Packit 63bb0d
	if testSuccess {
Packit 63bb0d
		status = common.IBFinished
Packit 63bb0d
	} else {
Packit 63bb0d
		status = common.IBFailed
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// FIXME: handle or comment this possible error
Packit 63bb0d
	_ = s.change(func() error {
Packit 63bb0d
		s.composes[composeID] = Compose{
Packit 63bb0d
			Blueprint: bp,
Packit 63bb0d
			ImageBuild: ImageBuild{
Packit 63bb0d
				QueueStatus: status,
Packit 63bb0d
				Manifest:    manifest,
Packit 63bb0d
				ImageType:   imageType,
Packit 63bb0d
				Targets:     targets,
Packit 63bb0d
				JobCreated:  time.Now(),
Packit 63bb0d
				JobStarted:  time.Now(),
Packit 63bb0d
				Size:        size,
Packit 63bb0d
			},
Packit 63bb0d
		}
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
Packit 63bb0d
	return nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// DeleteCompose deletes the compose from the state file and also removes all files on disk that are
Packit 63bb0d
// associated with this compose
Packit 63bb0d
func (s *Store) DeleteCompose(id uuid.UUID) error {
Packit 63bb0d
	return s.change(func() error {
Packit 63bb0d
		if _, exists := s.composes[id]; !exists {
Packit 63bb0d
			return &NotFoundError{}
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		delete(s.composes, id)
Packit 63bb0d
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// PushSource stores a SourceConfig in store.Sources
Packit 63bb0d
func (s *Store) PushSource(key string, source SourceConfig) {
Packit 63bb0d
	// FIXME: handle or comment this possible error
Packit 63bb0d
	_ = s.change(func() error {
Packit 63bb0d
		s.sources[key] = source
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// DeleteSourceByName removes a SourceConfig from store.Sources using the .Name field
Packit 63bb0d
func (s *Store) DeleteSourceByName(name string) {
Packit 63bb0d
	// FIXME: handle or comment this possible error
Packit 63bb0d
	_ = s.change(func() error {
Packit 63bb0d
		for key := range s.sources {
Packit 63bb0d
			if s.sources[key].Name == name {
Packit 63bb0d
				delete(s.sources, key)
Packit 63bb0d
				return nil
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// DeleteSourceByID removes a SourceConfig from store.Sources using the ID
Packit 63bb0d
func (s *Store) DeleteSourceByID(key string) {
Packit 63bb0d
	// FIXME: handle or comment this possible error
Packit 63bb0d
	_ = s.change(func() error {
Packit 63bb0d
		delete(s.sources, key)
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ListSourcesByName returns the repo source names
Packit 63bb0d
// Name is different than Id, it can be a full description of the repo
Packit 63bb0d
func (s *Store) ListSourcesByName() []string {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
	names := make([]string, 0, len(s.sources))
Packit 63bb0d
	for _, source := range s.sources {
Packit 63bb0d
		names = append(names, source.Name)
Packit 63bb0d
	}
Packit 63bb0d
	sort.Strings(names)
Packit 63bb0d
Packit 63bb0d
	return names
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ListSourcesById returns the repo source id
Packit 63bb0d
// Id is a short identifier for the repo, not a full name description
Packit 63bb0d
func (s *Store) ListSourcesById() []string {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
	names := make([]string, 0, len(s.sources))
Packit 63bb0d
	for name := range s.sources {
Packit 63bb0d
		names = append(names, name)
Packit 63bb0d
	}
Packit 63bb0d
	sort.Strings(names)
Packit 63bb0d
Packit 63bb0d
	return names
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *Store) GetSource(name string) *SourceConfig {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	source, ok := s.sources[name]
Packit 63bb0d
	if !ok {
Packit 63bb0d
		return nil
Packit 63bb0d
	}
Packit 63bb0d
	return &source
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetAllSourcesByName returns the sources using the repo name as the key
Packit 63bb0d
func (s *Store) GetAllSourcesByName() map[string]SourceConfig {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	sources := make(map[string]SourceConfig)
Packit 63bb0d
Packit 63bb0d
	for _, v := range s.sources {
Packit 63bb0d
		sources[v.Name] = v
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return sources
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// GetAllSourcesByID returns the sources using the repo id as the key
Packit 63bb0d
func (s *Store) GetAllSourcesByID() map[string]SourceConfig {
Packit 63bb0d
	s.mu.RLock()
Packit 63bb0d
	defer s.mu.RUnlock()
Packit 63bb0d
Packit 63bb0d
	sources := make(map[string]SourceConfig)
Packit 63bb0d
Packit 63bb0d
	for k, v := range s.sources {
Packit 63bb0d
		sources[k] = v
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return sources
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func NewSourceConfig(repo rpmmd.RepoConfig, system bool) SourceConfig {
Packit 63bb0d
	sc := SourceConfig{
Packit 63bb0d
		Name:     repo.Name,
Packit 63bb0d
		CheckGPG: repo.CheckGPG,
Packit 63bb0d
		CheckSSL: !repo.IgnoreSSL,
Packit 63bb0d
		System:   system,
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if repo.BaseURL != "" {
Packit 63bb0d
		sc.URL = repo.BaseURL
Packit 63bb0d
		sc.Type = "yum-baseurl"
Packit 63bb0d
	} else if repo.Metalink != "" {
Packit 63bb0d
		sc.URL = repo.Metalink
Packit 63bb0d
		sc.Type = "yum-metalink"
Packit 63bb0d
	} else if repo.MirrorList != "" {
Packit 63bb0d
		sc.URL = repo.MirrorList
Packit 63bb0d
		sc.Type = "yum-mirrorlist"
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return sc
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (s *SourceConfig) RepoConfig(name string) rpmmd.RepoConfig {
Packit 63bb0d
	var repo rpmmd.RepoConfig
Packit 63bb0d
Packit 63bb0d
	repo.Name = name
Packit 63bb0d
	repo.IgnoreSSL = !s.CheckSSL
Packit 63bb0d
	repo.CheckGPG = s.CheckGPG
Packit 63bb0d
Packit 63bb0d
	if s.Type == "yum-baseurl" {
Packit 63bb0d
		repo.BaseURL = s.URL
Packit 63bb0d
	} else if s.Type == "yum-metalink" {
Packit 63bb0d
		repo.Metalink = s.URL
Packit 63bb0d
	} else if s.Type == "yum-mirrorlist" {
Packit 63bb0d
		repo.MirrorList = s.URL
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return repo
Packit 63bb0d
}