diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2022-08-11 19:53:17 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-11 19:53:17 +0000 |
commit | 57387da27e43e7bd7973d91975b10a66aff134e8 (patch) | |
tree | 5b70ebe1aeae69f1542820f191f7fc9488a50663 /pkg/api | |
parent | 1798cccf3ea3145a82c0948437758a865d7c4c94 (diff) | |
parent | a4efd401cd87d98dced4f4eda41a8a1b86e72379 (diff) | |
download | podman-57387da27e43e7bd7973d91975b10a66aff134e8.tar.gz podman-57387da27e43e7bd7973d91975b10a66aff134e8.tar.bz2 podman-57387da27e43e7bd7973d91975b10a66aff134e8.zip |
Merge pull request #15285 from YoitoFes/fix-15210
remote manifest push: show copy progress
Diffstat (limited to 'pkg/api')
-rw-r--r-- | pkg/api/handlers/libpod/manifests.go | 70 | ||||
-rw-r--r-- | pkg/api/server/register_manifest.go | 5 |
2 files changed, 71 insertions, 4 deletions
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index 2d6223e4e..b0c93f3b9 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -19,12 +19,14 @@ import ( "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" "github.com/containers/podman/v4/pkg/auth" + "github.com/containers/podman/v4/pkg/channel" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/errorhandling" "github.com/gorilla/mux" "github.com/gorilla/schema" "github.com/opencontainers/go-digest" + "github.com/sirupsen/logrus" ) func ManifestCreate(w http.ResponseWriter, r *http.Request) { @@ -311,9 +313,13 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { Format string `schema:"format"` RemoveSignatures bool `schema:"removeSignatures"` TLSVerify bool `schema:"tlsVerify"` + Quiet bool `schema:"quiet"` }{ // Add defaults here once needed. TLSVerify: true, + // #15210: older versions did not sent *any* data, so we need + // to be quiet by default to remain backwards compatible + Quiet: true, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, @@ -344,6 +350,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { CompressionFormat: query.CompressionFormat, Format: query.Format, Password: password, + Quiet: true, RemoveSignatures: query.RemoveSignatures, Username: username, } @@ -356,12 +363,67 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} source := utils.GetName(r) - digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options) - if err != nil { - utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err)) + + // Let's keep thing simple when running in quiet mode and push directly. + if query.Quiet { + digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options) + if err != nil { + utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err)) + return + } + utils.WriteResponse(w, http.StatusOK, entities.ManifestPushReport{ID: digest}) return } - utils.WriteResponse(w, http.StatusOK, entities.IDResponse{ID: digest}) + + writer := channel.NewWriter(make(chan []byte)) + defer writer.Close() + options.Writer = writer + + pushCtx, pushCancel := context.WithCancel(r.Context()) + var digest string + var pushError error + go func() { + defer pushCancel() + digest, pushError = imageEngine.ManifestPush(pushCtx, source, destination, options) + }() + + flush := func() { + if flusher, ok := w.(http.Flusher); ok { + flusher.Flush() + } + } + + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + flush() + + enc := json.NewEncoder(w) + enc.SetEscapeHTML(true) + for { + var report entities.ManifestPushReport + select { + case s := <-writer.Chan(): + report.Stream = string(s) + if err := enc.Encode(report); err != nil { + logrus.Warnf("Failed to encode json: %v", err) + } + flush() + case <-pushCtx.Done(): + if pushError != nil { + report.Error = pushError.Error() + } else { + report.ID = digest + } + if err := enc.Encode(report); err != nil { + logrus.Warnf("Failed to encode json: %v", err) + } + flush() + return + case <-r.Context().Done(): + // Client has closed connection + return + } + } } // ManifestModify efficiently updates the named manifest list diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go index 19b507047..c22479cf9 100644 --- a/pkg/api/server/register_manifest.go +++ b/pkg/api/server/register_manifest.go @@ -75,6 +75,11 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error { // type: boolean // default: true // description: Require HTTPS and verify signatures when contacting registries. + // - in: query + // name: quiet + // description: "silences extra stream data on push" + // type: boolean + // default: true // responses: // 200: // schema: |