From bc584c7cbf537e73a8bd1cf5b63acc4e10edae00 Mon Sep 17 00:00:00 2001 From: Achilleas Koutsou Date: Tue, 16 May 2023 00:52:56 +0200 Subject: [PATCH] weldr: resolve containers after Manifest() Use the new workflow for generating the manifest before resolving containers. The resolver function is adjusted to handle a map of container slices, but with all current use cases, the map should only ever have one key for the payload (os) pipeline. --- internal/weldr/api.go | 114 ++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/internal/weldr/api.go b/internal/weldr/api.go index 47f54110d..6b39cbe35 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -2265,65 +2265,71 @@ func (api *API) depsolve(packageSets map[string][]rpmmd.PackageSet, distro distr return depsolvedSets, nil } -func (api *API) resolveContainersForImageType(bp blueprint.Blueprint, imageType distro.ImageType) ([]container.Spec, error) { +func (api *API) resolveContainers(sourceSpecs map[string][]container.SourceSpec) (map[string][]container.Spec, error) { - specs := make([]container.Spec, len(bp.Containers)) + specs := make(map[string][]container.Spec, len(sourceSpecs)) // shortcut - if len(bp.Containers) == 0 { + if len(sourceSpecs) == 0 { return specs, nil } - job := worker.ContainerResolveJob{ - Arch: api.archName, - 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, + // Run one job for each value in the sourceSpecs in order. + // Currently this should still only be one job, but if containers are added + // to multiple pipelines at any point, this should work. + for name, sources := range sourceSpecs { + job := worker.ContainerResolveJob{ + Arch: api.archName, + Specs: make([]worker.ContainerSpec, len(sources)), } - } - jobId, err := api.workers.EnqueueContainerResolveJob(&job, "") + for i, c := range sources { + job.Specs[i] = worker.ContainerSpec{ + Source: c.Source, + Name: c.Name, + TLSVerify: c.TLSVerify, + } + } - if err != nil { - return specs, err - } - - var result worker.ContainerResolveJobResult - - for { - jobInfo, err := api.workers.ContainerResolveJobInfo(jobId, &result) + jobId, err := api.workers.EnqueueContainerResolveJob(&job, "") if err != nil { return specs, err } - if result.JobError != nil { - return specs, errors.New(result.JobError.Reason) - } else if jobInfo.JobStatus.Canceled { - return specs, fmt.Errorf("Failed to resolve containers: job cancelled") - } else if !jobInfo.JobStatus.Finished.IsZero() { - break + var result worker.ContainerResolveJobResult + + for { + jobInfo, err := api.workers.ContainerResolveJobInfo(jobId, &result) + + if err != nil { + return specs, err + } + + if result.JobError != nil { + return specs, errors.New(result.JobError.Reason) + } else if jobInfo.JobStatus.Canceled { + return specs, fmt.Errorf("Failed to resolve containers: job cancelled") + } else if !jobInfo.JobStatus.Finished.IsZero() { + break + } + + time.Sleep(time.Millisecond * 250) } - time.Sleep(time.Millisecond * 250) - } + if len(result.Specs) != len(sources) { + panic("programming error: input / output length don't match") + } - if len(result.Specs) != len(specs) { - panic("programming error: input / output length don't match") - } - - for i, s := range result.Specs { - specs[i].Source = s.Source - specs[i].Digest = s.Digest - specs[i].LocalName = s.Name - specs[i].TLSVerify = s.TLSVerify - specs[i].ImageID = s.ImageID - specs[i].ListDigest = s.ListDigest + specs[name] = make([]container.Spec, len(sources)) + for i, s := range result.Specs { + specs[name][i].Source = s.Source + specs[name][i].Digest = s.Digest + specs[name][i].LocalName = s.Name + specs[name][i].TLSVerify = s.TLSVerify + specs[name][i].ImageID = s.ImageID + specs[name][i].ListDigest = s.ListDigest + } } return specs, nil @@ -2497,21 +2503,11 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request return } - containerSpecs, err := api.resolveContainersForImageType(*bp, imageType) - if err != nil { - errors := responseError{ - ID: "ContainerResolveError", - Msg: err.Error(), - } - statusResponseError(writer, http.StatusInternalServerError, errors) - return - } - manifest, warnings, err := imageType.Manifest(bp, options, imageRepos, nil, - containerSpecs, + nil, seed) if err != nil { errors := responseError{ @@ -2532,7 +2528,17 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request return } - mf, err := manifest.Serialize(packageSets, nil) + containerSpecs, err := api.resolveContainers(manifest.Content.Containers) + if err != nil { + errors := responseError{ + ID: "ContainerResolveError", + Msg: err.Error(), + } + statusResponseError(writer, http.StatusInternalServerError, errors) + return + } + + mf, err := manifest.Serialize(packageSets, containerSpecs) if err != nil { errors := responseError{ ID: "ManifestCreationFailed",