store: add error types and rudimentary error handling

This will allow us to better distinguish between different error
conditions in the API.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2019-10-06 00:09:21 +02:00 committed by Lars Karlitski
parent 2e4063c78b
commit 94e1e6f42b

View file

@ -4,7 +4,6 @@ package store
import (
"encoding/json"
"errors"
"io/ioutil"
"log"
"os"
@ -57,6 +56,30 @@ type Image struct {
Mime string
}
type NotFoundError struct {
message string
}
func (e *NotFoundError) Error() string {
return e.message
}
type NotPendingError struct {
message string
}
func (e *NotPendingError) Error() string {
return e.message
}
type InvalidRequestError struct {
message string
}
func (e *InvalidRequestError) Error() string {
return e.message
}
func New(stateFile *string) *Store {
var s Store
@ -132,11 +155,11 @@ func writeFileAtomically(filename string, data []byte, mode os.FileMode) error {
return nil
}
func (s *Store) change(f func()) {
func (s *Store) change(f func() error) error {
s.mu.Lock()
defer s.mu.Unlock()
f()
result := f()
if s.stateChannel != nil {
serialized, err := json.Marshal(s)
@ -147,6 +170,7 @@ func (s *Store) change(f func()) {
s.stateChannel <- serialized
}
return result
}
func (s *Store) ListBlueprints() []string {
@ -287,28 +311,32 @@ func (s *Store) GetBlueprintCommitted(name string, bp *blueprint.Blueprint) bool
}
func (s *Store) PushBlueprint(bp blueprint.Blueprint) {
s.change(func() {
s.change(func() error {
delete(s.Workspace, bp.Name)
s.Blueprints[bp.Name] = bp
return nil
})
}
func (s *Store) PushBlueprintToWorkspace(bp blueprint.Blueprint) {
s.change(func() {
s.change(func() error {
s.Workspace[bp.Name] = bp
return nil
})
}
func (s *Store) DeleteBlueprint(name string) {
s.change(func() {
s.change(func() error {
delete(s.Workspace, name)
delete(s.Blueprints, name)
return nil
})
}
func (s *Store) DeleteBlueprintFromWorkspace(name string) {
s.change(func() {
s.change(func() error {
delete(s.Workspace, name)
return nil
})
}
@ -316,7 +344,7 @@ func (s *Store) PushCompose(composeID uuid.UUID, bp *blueprint.Blueprint, compos
targets := []*target.Target{
target.NewLocalTarget(target.NewLocalTargetOptions("/var/lib/osbuild-composer/outputs/" + composeID.String())),
}
s.change(func() {
s.change(func() error {
s.Composes[composeID] = Compose{
QueueStatus: "WAITING",
Blueprint: bp,
@ -324,6 +352,7 @@ func (s *Store) PushCompose(composeID uuid.UUID, bp *blueprint.Blueprint, compos
Targets: targets,
JobCreated: time.Now(),
}
return nil
})
s.pendingJobs <- Job{
ComposeID: composeID,
@ -336,24 +365,38 @@ func (s *Store) PopCompose() Job {
return <-s.pendingJobs
}
func (s *Store) UpdateCompose(composeID uuid.UUID, status string) {
s.change(func() {
func (s *Store) UpdateCompose(composeID uuid.UUID, status string) error {
return s.change(func() error {
compose, exists := s.Composes[composeID]
if !exists {
return
return &NotFoundError{"compose does not exist"}
}
if compose.QueueStatus != status {
switch status {
case "RUNNING":
switch status {
case "RUNNING":
switch compose.QueueStatus {
case "WAITING":
compose.JobStarted = time.Now()
case "FINISHED":
fallthrough
case "FAILED":
case "RUNNING":
default:
return &NotPendingError{"compose was not pending"}
}
case "FINISHED", "FAILED":
switch compose.QueueStatus {
case "WAITING":
now := time.Now()
compose.JobStarted = now
compose.JobFinished = now
case "RUNNING":
compose.JobFinished = time.Now()
default:
return &NotPendingError{"compose was not pending"}
}
compose.QueueStatus = status
s.Composes[composeID] = compose
default:
return &InvalidRequestError{"invalid state transition"}
}
return nil
})
}
@ -363,7 +406,7 @@ func (s *Store) GetImage(composeID uuid.UUID) (*Image, error) {
if compose, exists := s.Composes[composeID]; exists {
if compose.QueueStatus != "FINISHED" {
return nil, errors.New("compose not ready")
return nil, &InvalidRequestError{"compose was not finished"}
}
name, mime := blueprint.FilenameFromType(compose.OutputType)
for _, t := range compose.Targets {
@ -379,7 +422,8 @@ func (s *Store) GetImage(composeID uuid.UUID) (*Image, error) {
}
}
}
return nil, &NotFoundError{"image could not be found"}
}
return nil, errors.New("image not found")
return nil, &NotFoundError{"compose could not be found"}
}