summaryrefslogtreecommitdiff
path: root/pkg/bindings/images/push.go
diff options
context:
space:
mode:
authorValentin Rothberg <vrothberg@redhat.com>2022-07-21 14:09:44 +0200
committerValentin Rothberg <vrothberg@redhat.com>2022-07-21 17:13:36 +0200
commitb79ac0aca2ba7f8a5176197da9fa5992d0b6d497 (patch)
tree976d1d0d5ac4038974128fc12f26a0096538dfda /pkg/bindings/images/push.go
parent04ed519e9d38e2ae12ec0b568e6418e750ff203d (diff)
downloadpodman-b79ac0aca2ba7f8a5176197da9fa5992d0b6d497.tar.gz
podman-b79ac0aca2ba7f8a5176197da9fa5992d0b6d497.tar.bz2
podman-b79ac0aca2ba7f8a5176197da9fa5992d0b6d497.zip
remote push: show copy progress
`podman-remote push` has shown absolutely no progress at all. Fix that by doing essentially the same as the remote-pull code does. The get-free-out-of-jail-card for backwards compatibility is to let the `quiet` parameter default to true. Since the --quioet flag wasn't working before either, older Podman clients do not set it. Also add regression tests to make sure we won't regress again. Fixes: #11554 Fixes: #14971 Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
Diffstat (limited to 'pkg/bindings/images/push.go')
-rw-r--r--pkg/bindings/images/push.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/pkg/bindings/images/push.go b/pkg/bindings/images/push.go
new file mode 100644
index 000000000..8db3726e6
--- /dev/null
+++ b/pkg/bindings/images/push.go
@@ -0,0 +1,96 @@
+package images
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "strconv"
+
+ imageTypes "github.com/containers/image/v5/types"
+ "github.com/containers/podman/v4/pkg/auth"
+ "github.com/containers/podman/v4/pkg/bindings"
+ "github.com/containers/podman/v4/pkg/domain/entities"
+)
+
+// Push is the binding for libpod's endpoints for push images. Note that
+// `source` must be a referring to an image in the remote's container storage.
+// The destination must be a reference to a registry (i.e., of docker transport
+// or be normalized to one). Other transports are rejected as they do not make
+// sense in a remote context.
+func Push(ctx context.Context, source string, destination string, options *PushOptions) error {
+ if options == nil {
+ options = new(PushOptions)
+ }
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
+ if err != nil {
+ return err
+ }
+
+ params, err := options.ToParams()
+ if err != nil {
+ return err
+ }
+ // SkipTLSVerify is special. We need to delete the param added by
+ // toparams and change the key and flip the bool
+ if options.SkipTLSVerify != nil {
+ params.Del("SkipTLSVerify")
+ params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
+ }
+ params.Set("destination", destination)
+
+ path := fmt.Sprintf("/images/%s/push", source)
+ response, err := conn.DoRequest(ctx, nil, http.MethodPost, path, params, header)
+ if err != nil {
+ return err
+ }
+ defer response.Body.Close()
+
+ if !response.IsSuccess() {
+ return response.Process(err)
+ }
+
+ // Historically push writes status to stderr
+ writer := io.Writer(os.Stderr)
+ if options.GetQuiet() {
+ writer = ioutil.Discard
+ }
+
+ dec := json.NewDecoder(response.Body)
+ for {
+ var report entities.ImagePushReport
+ if err := dec.Decode(&report); err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ return err
+ }
+
+ select {
+ case <-response.Request.Context().Done():
+ break
+ default:
+ // non-blocking select
+ }
+
+ switch {
+ case report.Stream != "":
+ fmt.Fprint(writer, report.Stream)
+ case report.Error != "":
+ // There can only be one error.
+ return errors.New(report.Error)
+ default:
+ return fmt.Errorf("failed to parse push results stream, unexpected input: %v", report)
+ }
+ }
+
+ return nil
+}