weldr/store: add getImage

This allows images to be downloaded for completed composes.

Signed-off-by: Tom Gundersen <teg@jklm.no>
This commit is contained in:
Tom Gundersen 2019-10-04 23:08:33 +02:00 committed by Lars Karlitski
parent 0880014edf
commit 2e979c8b82
2 changed files with 65 additions and 0 deletions

View file

@ -2,6 +2,8 @@ package weldr
import (
"encoding/json"
"fmt"
"io"
"log"
"net"
"net/http"
@ -79,6 +81,7 @@ func New(repo rpmmd.RepoConfig, packages rpmmd.PackageList, logger *log.Logger,
api.router.GET("/api/v0/compose/status/:uuids", api.composeStatusHandler)
api.router.GET("/api/v0/compose/finished", api.composeFinishedHandler)
api.router.GET("/api/v0/compose/failed", api.composeFailedHandler)
api.router.GET("/api/v0/compose/image/:id", api.composeImageHandler)
return api
}
@ -698,6 +701,33 @@ func (api *API) composeStatusHandler(writer http.ResponseWriter, request *http.R
json.NewEncoder(writer).Encode(reply)
}
func (api *API) composeImageHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
idString := params.ByName("id")
id, err := uuid.Parse(idString)
if err != nil {
statusResponseError(writer, http.StatusBadRequest, "invalid UUID")
return
}
image, err := api.store.getImage(id)
if err != nil {
statusResponseError(writer, http.StatusNotFound, "image for compose not found")
return
}
stat, err := image.file.Stat()
if err != nil {
statusResponseError(writer, http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Disposition", "attachment; filename="+id.String()+"-"+image.name)
writer.Header().Set("Content-Type", image.mime)
writer.Header().Set("Content-Length", fmt.Sprintf("%d", stat.Size()))
io.Copy(writer, image.file)
}
func (api *API) composeFinishedHandler(writer http.ResponseWriter, request *http.Request, _ httprouter.Params) {
var reply struct {
Finished []interface{} `json:"finished"`

View file

@ -2,7 +2,9 @@ package weldr
import (
"encoding/json"
"errors"
"log"
"os"
"osbuild-composer/internal/blueprint"
"osbuild-composer/internal/job"
"osbuild-composer/internal/target"
@ -284,3 +286,36 @@ func (s *store) addCompose(composeID uuid.UUID, bp *blueprint.Blueprint, compose
Targets: targets,
}
}
type image struct {
file *os.File
name string
mime string
}
func (s *store) getImage(composeID uuid.UUID) (*image, error) {
s.mu.RLock()
defer s.mu.RUnlock()
if compose, exists := s.Composes[composeID]; exists {
if compose.QueueStatus != "FINISHED" {
return nil, errors.New("compose not ready")
}
name, mime := blueprint.FilenameFromType(compose.OutputType)
for _, t := range compose.Targets {
switch options := t.Options.(type) {
case *target.LocalTargetOptions:
file, err := os.Open(options.Location + "/" + name)
if err == nil {
return &image{
file: file,
name: name,
mime: mime,
}, nil
}
}
}
}
return nil, errors.New("image not found")
}