diff options
Diffstat (limited to 'pkg/api')
-rw-r--r-- | pkg/api/handlers/compat/images.go | 76 |
1 files changed, 37 insertions, 39 deletions
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index 3f4320efa..7b336c470 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -1,7 +1,6 @@ package compat import ( - "context" "encoding/json" "fmt" "io/ioutil" @@ -13,12 +12,12 @@ import ( "github.com/containers/common/libimage" "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/pkg/shortnames" "github.com/containers/image/v5/types" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers" "github.com/containers/podman/v3/pkg/api/handlers/utils" "github.com/containers/podman/v3/pkg/auth" - "github.com/containers/podman/v3/pkg/channel" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/infra/abi" "github.com/containers/storage" @@ -210,6 +209,11 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { }) } +type pullResult struct { + images []*libimage.Image + err error +} + func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { // 200 no error // 404 repo does not exist or no read access @@ -231,6 +235,14 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { fromImage := mergeNameAndTagOrDigest(query.FromImage, query.Tag) + // without this early check this function would return 200 but reported error via body stream soon after + // it's better to let caller know early via HTTP status code that request cannot be processed + _, err := shortnames.Resolve(runtime.SystemContext(), fromImage) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrap(err, "failed to resolve image name")) + return + } + authConf, authfile, key, err := auth.GetCredentials(r) if err != nil { utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) @@ -247,26 +259,14 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { } pullOptions.Writer = os.Stderr // allows for debugging on the server - stderr := channel.NewWriter(make(chan []byte)) - defer stderr.Close() - progress := make(chan types.ProgressProperties) + pullOptions.Progress = progress - var img string - runCtx, cancel := context.WithCancel(context.Background()) + pullResChan := make(chan pullResult) go func() { - defer cancel() - pulledImages, err := runtime.LibimageRuntime().Pull(runCtx, fromImage, config.PullPolicyAlways, pullOptions) - if err != nil { - stderr.Write([]byte(err.Error() + "\n")) - } else { - if len(pulledImages) == 0 { - utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.New("internal error: no images pulled")) - return - } - img = pulledImages[0].ID() - } + pulledImages, err := runtime.LibimageRuntime().Pull(r.Context(), fromImage, config.PullPolicyAlways, pullOptions) + pullResChan <- pullResult{images: pulledImages, err: err} }() flush := func() { @@ -281,7 +281,6 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) enc.SetEscapeHTML(true) - var failed bool loop: // break out of for/select infinite loop for { @@ -312,32 +311,31 @@ loop: // break out of for/select infinite loop } report.Id = e.Artifact.Digest.Encoded()[0:12] if err := enc.Encode(report); err != nil { - stderr.Write([]byte(err.Error())) - } - flush() - case e := <-stderr.Chan(): - failed = true - report.Error = string(e) - if err := enc.Encode(report); err != nil { logrus.Warnf("Failed to json encode error %q", err.Error()) } flush() - case <-runCtx.Done(): - if !failed { - if utils.IsLibpodRequest(r) { - report.Status = "Pull complete" + case pullRes := <-pullResChan: + err := pullRes.err + pulledImages := pullRes.images + if err != nil { + report.Error = err.Error() + } else { + if len(pulledImages) > 0 { + img := pulledImages[0].ID() + if utils.IsLibpodRequest(r) { + report.Status = "Pull complete" + } else { + report.Status = "Download complete" + } + report.Id = img[0:12] } else { - report.Status = "Download complete" - } - report.Id = img[0:12] - if err := enc.Encode(report); err != nil { - logrus.Warnf("Failed to json encode error %q", err.Error()) + report.Error = "internal error: no images pulled" } - flush() } - break loop // break out of for/select infinite loop - case <-r.Context().Done(): - // Client has closed connection + if err := enc.Encode(report); err != nil { + logrus.Warnf("Failed to json encode error %q", err.Error()) + } + flush() break loop // break out of for/select infinite loop } } |