cloudapi: support container embedding
Add support for embedding container images via the cloud API. For this the container resolve job was plumbed into the cloud api's handler and the API specification updated with a new `containers` section that mimics the blueprint section with the same name.
This commit is contained in:
parent
45850639a0
commit
388154d7f6
7 changed files with 341 additions and 119 deletions
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/osbuild/osbuild-composer/internal/blueprint"
|
||||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/container"
|
||||
"github.com/osbuild/osbuild-composer/internal/distro"
|
||||
"github.com/osbuild/osbuild-composer/internal/distroregistry"
|
||||
"github.com/osbuild/osbuild-composer/internal/prometheus"
|
||||
|
|
@ -112,7 +113,33 @@ func (s *Server) enqueueCompose(distribution distro.Distro, bp blueprint.Bluepri
|
|||
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
|
||||
}
|
||||
|
||||
manifestJobID, err := s.workers.EnqueueManifestJobByID(&worker.ManifestJobByID{}, depsolveJobID, channel)
|
||||
dependencies := []uuid.UUID{depsolveJobID}
|
||||
var containerResolveJob uuid.UUID
|
||||
if len(bp.Containers) > 0 {
|
||||
job := worker.ContainerResolveJob{
|
||||
Arch: ir.arch.Name(),
|
||||
Specs: make([]worker.ContainerSpec, len(bp.Containers)),
|
||||
}
|
||||
|
||||
for i, c := range bp.Containers {
|
||||
job.Specs[i] = worker.ContainerSpec{
|
||||
Source: c.Source,
|
||||
Name: c.Name,
|
||||
TLSVerify: c.TLSVerify,
|
||||
}
|
||||
}
|
||||
|
||||
jobId, err := s.workers.EnqueueContainerResolveJob(&job, channel)
|
||||
|
||||
if err != nil {
|
||||
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
|
||||
}
|
||||
|
||||
containerResolveJob = jobId
|
||||
dependencies = append(dependencies, jobId)
|
||||
}
|
||||
|
||||
manifestJobID, err := s.workers.EnqueueManifestJobByID(&worker.ManifestJobByID{}, dependencies, channel)
|
||||
if err != nil {
|
||||
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
|
||||
}
|
||||
|
|
@ -130,7 +157,7 @@ func (s *Server) enqueueCompose(distribution distro.Distro, bp blueprint.Bluepri
|
|||
|
||||
s.goroutinesGroup.Add(1)
|
||||
go func() {
|
||||
generateManifest(s.goroutinesCtx, s.workers, depsolveJobID, manifestJobID, ir.imageType, ir.repositories, ir.imageOptions, manifestSeed, bp.Customizations)
|
||||
generateManifest(s.goroutinesCtx, s.workers, depsolveJobID, containerResolveJob, manifestJobID, ir.imageType, ir.repositories, ir.imageOptions, manifestSeed, bp.Customizations)
|
||||
defer s.goroutinesGroup.Done()
|
||||
}()
|
||||
|
||||
|
|
@ -164,7 +191,33 @@ func (s *Server) enqueueKojiCompose(taskID uint64, server, name, version, releas
|
|||
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
|
||||
}
|
||||
|
||||
manifestJobID, err := s.workers.EnqueueManifestJobByID(&worker.ManifestJobByID{}, depsolveJobID, channel)
|
||||
var containerResolveJob uuid.UUID
|
||||
dependencies := []uuid.UUID{depsolveJobID}
|
||||
if len(bp.Containers) > 0 {
|
||||
job := worker.ContainerResolveJob{
|
||||
Arch: ir.arch.Name(),
|
||||
Specs: make([]worker.ContainerSpec, len(bp.Containers)),
|
||||
}
|
||||
|
||||
for i, c := range bp.Containers {
|
||||
job.Specs[i] = worker.ContainerSpec{
|
||||
Source: c.Source,
|
||||
Name: c.Name,
|
||||
TLSVerify: c.TLSVerify,
|
||||
}
|
||||
}
|
||||
|
||||
jobId, err := s.workers.EnqueueContainerResolveJob(&job, channel)
|
||||
|
||||
if err != nil {
|
||||
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
|
||||
}
|
||||
|
||||
containerResolveJob = jobId
|
||||
dependencies = append(dependencies, jobId)
|
||||
}
|
||||
|
||||
manifestJobID, err := s.workers.EnqueueManifestJobByID(&worker.ManifestJobByID{}, dependencies, channel)
|
||||
if err != nil {
|
||||
return id, HTTPErrorWithInternal(ErrorEnqueueingJob, err)
|
||||
}
|
||||
|
|
@ -208,7 +261,7 @@ func (s *Server) enqueueKojiCompose(taskID uint64, server, name, version, releas
|
|||
// copy the image request while passing it into the goroutine to prevent data races
|
||||
s.goroutinesGroup.Add(1)
|
||||
go func(ir imageRequest) {
|
||||
generateManifest(s.goroutinesCtx, s.workers, depsolveJobID, manifestJobID, ir.imageType, ir.repositories, ir.imageOptions, manifestSeed, bp.Customizations)
|
||||
generateManifest(s.goroutinesCtx, s.workers, depsolveJobID, containerResolveJob, manifestJobID, ir.imageType, ir.repositories, ir.imageOptions, manifestSeed, bp.Customizations)
|
||||
defer s.goroutinesGroup.Done()
|
||||
}(ir)
|
||||
}
|
||||
|
|
@ -229,7 +282,7 @@ func (s *Server) enqueueKojiCompose(taskID uint64, server, name, version, releas
|
|||
return id, nil
|
||||
}
|
||||
|
||||
func generateManifest(ctx context.Context, workers *worker.Server, depsolveJobID uuid.UUID, manifestJobID uuid.UUID, imageType distro.ImageType, repos []rpmmd.RepoConfig, options distro.ImageOptions, seed int64, b *blueprint.Customizations) {
|
||||
func generateManifest(ctx context.Context, workers *worker.Server, depsolveJobID, containerResolveJobID, manifestJobID uuid.UUID, imageType distro.ImageType, repos []rpmmd.RepoConfig, options distro.ImageOptions, seed int64, b *blueprint.Customizations) {
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Minute*5)
|
||||
defer cancel()
|
||||
|
||||
|
|
@ -313,7 +366,36 @@ func generateManifest(ctx context.Context, workers *worker.Server, depsolveJobID
|
|||
return
|
||||
}
|
||||
|
||||
manifest, err := imageType.Manifest(b, options, repos, depsolveResults.PackageSpecs, nil, seed)
|
||||
var containerSpecs []container.Spec
|
||||
if len(dynArgs) == 2 {
|
||||
// Container resolve job
|
||||
var result worker.ContainerResolveJobResult
|
||||
|
||||
_, err := workers.ContainerResolveJobInfo(containerResolveJobID, &result)
|
||||
|
||||
if err != nil {
|
||||
reason := "Error reading container resolve job status"
|
||||
jobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorReadingJobStatus, reason, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if jobErr := result.JobError; jobErr != nil {
|
||||
jobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorContainerDependency, "Error in container resolve job dependency", nil)
|
||||
return
|
||||
}
|
||||
|
||||
containerSpecs = make([]container.Spec, len(result.Specs))
|
||||
|
||||
for i, s := range result.Specs {
|
||||
containerSpecs[i].Source = s.Source
|
||||
containerSpecs[i].Digest = s.Digest
|
||||
containerSpecs[i].LocalName = s.Name
|
||||
containerSpecs[i].TLSVerify = s.TLSVerify
|
||||
containerSpecs[i].ImageID = s.ImageID
|
||||
}
|
||||
}
|
||||
|
||||
manifest, err := imageType.Manifest(b, options, repos, depsolveResults.PackageSpecs, containerSpecs, seed)
|
||||
if err != nil {
|
||||
reason := "Error generating manifest"
|
||||
jobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorManifestGeneration, reason, nil)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue