api/compat: Backport jsonmessage.JSONProgress.String()

The JSONProgress is not part of moby/moby API anymore:
f4127d76c5

To stay compatible with the previous client version, this commit backports
the jsonmessage.JSONProgress.String() and uses it to genereate
the progress report.

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
This commit is contained in:
Jan Kaluza
2026-02-27 12:33:20 +01:00
parent 65585e4338
commit c10f685b43
2 changed files with 66 additions and 9 deletions

View File

@@ -155,7 +155,7 @@ func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, statuses []abi
Driver: network.Driver,
Created: network.Created,
Scope: "local",
EnableIPv4: true, // set appropriately for your network (see note below)
EnableIPv4: true,
EnableIPv6: network.IPv6Enabled,
IPAM: ipam,
Internal: network.Internal,

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"net/http"
"strings"
"time"
"github.com/containers/podman/v6/libpod"
"github.com/containers/podman/v6/pkg/api/handlers"
@@ -14,6 +15,7 @@ import (
api "github.com/containers/podman/v6/pkg/api/types"
"github.com/containers/podman/v6/pkg/errorhandling"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/jsonstream"
"github.com/sirupsen/logrus"
"go.podman.io/common/libimage"
@@ -125,6 +127,68 @@ type pullResult struct {
err error
}
// This function is inherited from moby/moby and licensed as Apache-2.0.
// It is used to keep backward compatibility with older docker clients.
func jsonProgressToString(p *jsonstream.Progress) string {
var (
pbBox string
numbersBox string
)
if p.Current <= 0 && p.Total <= 0 {
return ""
}
if p.Total <= 0 {
switch p.Units {
case "":
return fmt.Sprintf("%8v", units.HumanSize(float64(p.Current)))
default:
return fmt.Sprintf("%d %s", p.Current, p.Units)
}
}
percentage := int(float64(p.Current)/float64(p.Total)*100) / 2
if percentage > 50 {
percentage = 50
}
numSpaces := 0
if 50-percentage > 0 {
numSpaces = 50 - percentage
}
pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces))
switch {
case p.HideCounts:
case p.Units == "": // no units, use bytes
current := units.HumanSize(float64(p.Current))
total := units.HumanSize(float64(p.Total))
numbersBox = fmt.Sprintf("%8v/%v", current, total)
if p.Current > p.Total {
// remove total display if the reported current is wonky.
numbersBox = fmt.Sprintf("%8v", current)
}
default:
numbersBox = fmt.Sprintf("%d/%d %s", p.Current, p.Total, p.Units)
if p.Current > p.Total {
// remove total display if the reported current is wonky.
numbersBox = fmt.Sprintf("%d %s", p.Current, p.Units)
}
}
// Show approximation of remaining time if there's enough width.
var timeLeftBox string
if p.Current > 0 && p.Start > 0 && percentage < 50 {
fromStart := time.Now().UTC().Sub(time.Unix(p.Start, 0))
perEntry := fromStart / time.Duration(p.Current)
left := time.Duration(p.Total-p.Current) * perEntry
timeLeftBox = " " + left.Round(time.Second).String()
}
return pbBox + numbersBox + timeLeftBox
}
func CompatPull(r *http.Request, w http.ResponseWriter, runtime *libpod.Runtime, reference string, pullPolicy config.PullPolicy, pullOptions *libimage.PullOptions) {
ctx := r.Context()
progress := make(chan types.ProgressProperties)
@@ -173,14 +237,7 @@ loop: // break out of for/select infinite loop
report.Progress.Total = e.Artifact.Size
// Deprecated field, but because consumers might still read it keep it.
if _, err := apiutil.SupportedVersion(r, "<1.52.0"); err == nil {
b, err := json.Marshal(&jsonstream.Message{
Status: report.Status,
Progress: report.Progress,
ID: report.ID,
})
if err == nil {
report.ProgressMessage = string(b)
}
report.ProgressMessage = jsonProgressToString(report.Progress)
}
case types.ProgressEventSkipped:
report.Status = "Already exists"