cloudapi: save and return compose request details

The original compose request contains useful details that are not
preserved when it is converted to a manifest. Things like the
distribution, arch, image type, blueprint or customizations are useful
when examining builds later.

This saves the original request json using the job id and a new
directory (ComposeRequest) under the artifacts directory. The original
request, if present, is then added to the compose/<id>/metadata response
alongside the package list.

Related: RHEL-60120
This commit is contained in:
Brian C. Lane 2024-10-25 15:26:45 -07:00 committed by Tomáš Hozza
parent 199a3d31f8
commit d8e9a86921
2 changed files with 58 additions and 0 deletions

View file

@ -6,6 +6,8 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"path"
"slices"
"sort"
"strconv"
@ -22,6 +24,7 @@ import (
"github.com/osbuild/images/pkg/sbom"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/common"
"github.com/osbuild/osbuild-composer/internal/jsondb"
"github.com/osbuild/osbuild-composer/internal/target"
"github.com/osbuild/osbuild-composer/internal/worker"
"github.com/osbuild/osbuild-composer/internal/worker/clienterrors"
@ -150,6 +153,11 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error {
ctx.Logger().Infof("Job ID %s enqueued for operationID %s", id, ctx.Get(common.OperationIDKey))
// Save the request in the artifacts directory, log errors but continue
if err := saveComposeRequest(h.server.workers.ArtifactsDir(), id, request); err != nil {
ctx.Logger().Warnf("Failed to save compose request: %v", err)
}
return ctx.JSON(http.StatusCreated, &ComposeId{
ObjectReference: ObjectReference{
Href: "/api/image-builder-composer/v2/compose",
@ -622,6 +630,12 @@ func (h *apiHandlers) getComposeMetadataImpl(ctx echo.Context, id string) error
return HTTPErrorWithInternal(ErrorComposeNotFound, err)
}
// Get the original compose request, if present
request, err := readComposeRequest(h.server.workers.ArtifactsDir(), jobId)
if err != nil {
ctx.Logger().Warnf("Failed to read compose request: %v", err)
}
if buildInfo.JobStatus.Finished.IsZero() {
// job still running: empty response
return ctx.JSON(200, ComposeMetadata{
@ -630,6 +644,7 @@ func (h *apiHandlers) getComposeMetadataImpl(ctx echo.Context, id string) error
Id: jobId.String(),
Kind: "ComposeMetadata",
},
Request: request,
})
}
@ -641,6 +656,7 @@ func (h *apiHandlers) getComposeMetadataImpl(ctx echo.Context, id string) error
Id: jobId.String(),
Kind: "ComposeMetadata",
},
Request: request,
})
}
@ -675,6 +691,7 @@ func (h *apiHandlers) getComposeMetadataImpl(ctx echo.Context, id string) error
Kind: "ComposeMetadata",
},
Packages: &packages,
Request: request,
}
if ostreeCommitMetadata != nil {
@ -1571,3 +1588,41 @@ func (h *apiHandlers) getComposeDownloadImpl(ctx echo.Context, id string) error
}
return ctx.Attachment(file, fmt.Sprintf("%s-%s", jobId, tr.OsbuildArtifact.ExportFilename))
}
// saveComposeRequest stores the compose request's json on disk
// This is saved in the ComposeRequest directory of the artifacts directory
// If no artifacts directory has been configured it saves nothing and silently returns
func saveComposeRequest(artifactsDir string, id uuid.UUID, request ComposeRequest) error {
if artifactsDir == "" {
return nil
}
p := path.Join(artifactsDir, "ComposeRequest")
err := os.MkdirAll(p, 0700)
if err != nil {
return err
}
db := jsondb.New(p, 0700)
return db.Write(id.String(), request)
}
// readComposeRequest reads the compose request's json on disk
// This reads the original compose request json from the ComposeRequest directory of
// the artifacts directory.
// If no artifacts directory had been setup it silently returns nothing
func readComposeRequest(artifactsDir string, id uuid.UUID) (*ComposeRequest, error) {
if artifactsDir == "" {
return nil, nil
}
p := path.Join(artifactsDir, "ComposeRequest")
err := os.MkdirAll(p, 0700)
if err != nil {
return nil, err
}
db := jsondb.New(p, 0700)
var request ComposeRequest
exists, err := db.Read(id.String(), &request)
if !exists {
return nil, err
}
return &request, err
}

View file

@ -676,6 +676,9 @@ func (s *Server) DeleteArtifacts(id uuid.UUID) error {
return fmt.Errorf("Cannot delete artifacts before job is finished: %s", id)
}
// Remove the ComposeRequest but ignore any errors
_ = os.Remove(path.Join(s.config.ArtifactsDir, "ComposeRequest", id.String()+".json"))
return os.RemoveAll(path.Join(s.config.ArtifactsDir, id.String()))
}