|
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 |
}
|