vendor: github.com/moby/moby/api v1.52.0, moby/client v0.1.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-11-12 01:30:02 +01:00
parent c1fbb49e9b
commit 18dc2e088a
458 changed files with 9914 additions and 22191 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ linters:
alias:
- pkg: "github.com/containerd/errdefs"
alias: "cerrdefs"
- pkg: "github.com/docker/docker/client"
- pkg: "github.com/moby/moby/client"
alias: "dockerclient"
- pkg: "github.com/opencontainers/image-spec/specs-go/v1"
alias: "ocispecs"
+7 -5
View File
@@ -29,8 +29,6 @@ import (
"github.com/docker/buildx/util/resolver"
"github.com/docker/buildx/util/waitmap"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
@@ -43,6 +41,8 @@ import (
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/progress/progresswriter"
"github.com/moby/buildkit/util/tracing"
"github.com/moby/moby/api/types/jsonstream"
dockerclient "github.com/moby/moby/client"
"github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -802,7 +802,7 @@ func pushWithMoby(ctx context.Context, d *driver.DriverHandle, name string, l pr
return err
}
rc, err := api.ImagePush(ctx, name, image.PushOptions{
rc, err := api.ImagePush(ctx, name, dockerclient.ImagePushOptions{
RegistryAuth: creds,
})
if err != nil {
@@ -824,7 +824,7 @@ func pushWithMoby(ctx context.Context, d *driver.DriverHandle, name string, l pr
dec := json.NewDecoder(rc)
var parsedError error
for {
var jm jsonmessage.JSONMessage
var jm jsonstream.Message
if err := dec.Decode(&jm); err != nil {
if parsedError != nil {
return parsedError
@@ -888,7 +888,9 @@ func remoteDigestWithMoby(ctx context.Context, d *driver.DriverHandle, name stri
if len(img.RepoDigests) == 0 {
return "", nil
}
remoteImage, err := api.DistributionInspect(ctx, name, creds)
remoteImage, err := api.DistributionInspect(ctx, name, dockerclient.DistributionInspectOptions{
EncodedRegistryAuth: creds,
})
if err != nil {
return "", err
}
+2 -1
View File
@@ -25,6 +25,7 @@ import (
dopts "github.com/docker/cli/opts"
"github.com/google/shlex"
"github.com/moby/buildkit/util/progress/progressui"
dockerclient "github.com/moby/moby/client"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"github.com/tonistiigi/go-csvvalue"
@@ -247,7 +248,7 @@ func (b *Builder) Factory(ctx context.Context, dialMeta map[string][]string) (_
}
// check if endpoint is healthy is needed to determine the driver type.
// if this fails then can't continue with driver selection.
if _, err = dockerapi.Ping(ctx); err != nil {
if _, err = dockerapi.Ping(ctx, dockerclient.PingOptions{}); err != nil {
return
}
b.driverFactory.Factory, err = driver.GetDefaultFactory(ctx, ep, dockerapi, false, dialMeta)
+1 -1
View File
@@ -36,7 +36,6 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
dockeropts "github.com/docker/cli/opts"
"github.com/docker/docker/api/types/versions"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/frontend/subrequests"
@@ -49,6 +48,7 @@ import (
sourcepolicy "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/grpcerrors"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/moby/moby/client/pkg/versions"
"github.com/moby/sys/atomicwriter"
"github.com/morikuni/aec"
"github.com/pkg/errors"
+1 -1
View File
@@ -169,7 +169,7 @@ func runDiskUsage(ctx context.Context, dockerCli command.Cli, opts duOptions) er
}
defer func() {
if (fctx.Format != duDefaultTableFormat && fctx.Format != duDefaultPrettyTemplate) || fctx.Format.IsJSON() || opts.filter.Value().Len() > 0 {
if (fctx.Format != duDefaultTableFormat && fctx.Format != duDefaultPrettyTemplate) || fctx.Format.IsJSON() || len(opts.filter.Value()) > 0 {
return
}
printSummary(dockerCli.Out(), out)
+20 -18
View File
@@ -4,7 +4,9 @@ import (
"context"
"fmt"
"io"
"maps"
"os"
"slices"
"strings"
"text/tabwriter"
"time"
@@ -14,12 +16,12 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types/filters"
"github.com/docker/go-units"
"github.com/moby/buildkit/client"
gateway "github.com/moby/buildkit/frontend/gateway/client"
pb "github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/apicaps"
dclient "github.com/moby/moby/client"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
@@ -42,9 +44,7 @@ const (
)
func runPrune(ctx context.Context, dockerCli command.Cli, opts pruneOptions) error {
pruneFilters := opts.filter.Value()
pruneFilters = command.PruneFilters(dockerCli, pruneFilters)
pruneFilters := command.PruneFilters(dockerCli, opts.filter.Value())
pi, err := toBuildkitPruneInfo(pruneFilters)
if err != nil {
return err
@@ -189,20 +189,22 @@ func pruneCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
return cmd
}
func toBuildkitPruneInfo(f filters.Args) (*client.PruneInfo, error) {
var until time.Duration
untilValues := f.Get("until") // canonical
unusedForValues := f.Get("unused-for") // deprecated synonym for "until" filter
// getFilter returns the list of values associated with the key
func getFilter(f dclient.Filters, key string) []string {
return slices.Collect(maps.Keys(f[key]))
}
if len(untilValues) > 0 && len(unusedForValues) > 0 {
return nil, errors.Errorf("conflicting filters %q and %q", "until", "unused-for")
func toBuildkitPruneInfo(pruneFilters dclient.Filters) (*client.PruneInfo, error) {
var until time.Duration
if len(pruneFilters["until"]) > 0 && len(pruneFilters["unused-for"]) > 0 {
return nil, errors.New(`conflicting filters "until" and "unused-for"`)
}
untilKey := "until"
if len(unusedForValues) > 0 {
untilKey = "unused-for"
if len(pruneFilters["unused-for"]) > 0 {
untilKey = "unused-for" // deprecated synonym for "until" filter
}
untilValues = append(untilValues, unusedForValues...)
untilValues := getFilter(pruneFilters, untilKey)
switch len(untilValues) {
case 0:
// nothing to do
@@ -213,16 +215,16 @@ func toBuildkitPruneInfo(f filters.Args) (*client.PruneInfo, error) {
return nil, errors.Wrapf(err, "%q filter expects a duration (e.g., '24h')", untilKey)
}
default:
return nil, errors.Errorf("filters expect only one value")
return nil, errors.Errorf("%q filter expects only one value", untilKey)
}
filters := make([]string, 0, f.Len())
for _, filterKey := range f.Keys() {
filters := make([]string, 0, len(pruneFilters))
for filterKey := range pruneFilters {
if filterKey == untilKey {
continue
}
values := f.Get(filterKey)
values := getFilter(pruneFilters, filterKey)
switch len(values) {
case 0:
filters = append(filters, filterKey)
@@ -235,7 +237,7 @@ func toBuildkitPruneInfo(f filters.Args) (*client.PruneInfo, error) {
filters = append(filters, filterKey+"=="+values[0])
}
default:
return nil, errors.Errorf("filters expect only one value")
return nil, errors.Errorf("%q filter expects only one value", filterKey)
}
}
return &client.PruneInfo{
+52 -47
View File
@@ -21,15 +21,14 @@ import (
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/system"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/stdcopy"
"github.com/moby/buildkit/client"
mobyarchive "github.com/moby/go-archive"
"github.com/moby/moby/api/pkg/stdcopy"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/mount"
dockerclient "github.com/moby/moby/client"
"github.com/moby/moby/client/pkg/jsonmessage"
"github.com/moby/moby/client/pkg/security"
"github.com/pkg/errors"
)
@@ -71,7 +70,7 @@ func (d *Driver) Config() driver.InitConfig {
func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
return progress.Wrap("[internal] booting buildkit", l, func(sub progress.SubLogger) error {
_, err := d.DockerAPI.ContainerInspect(ctx, d.Name)
_, err := d.DockerAPI.ContainerInspect(ctx, d.Name, dockerclient.ContainerInspectOptions{})
if err != nil {
if cerrdefs.IsNotFound(err) {
return d.create(ctx, sub)
@@ -98,7 +97,7 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
if err != nil {
return err
}
resp, err := d.DockerAPI.ImageCreate(ctx, imageName, image.CreateOptions{
resp, err := d.DockerAPI.ImagePull(ctx, imageName, dockerclient.ImagePullOptions{
RegistryAuth: ra,
})
if err != nil {
@@ -198,8 +197,8 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
if len(d.gpus) > 0 && d.hasGPUCapability(ctx, cfg.Image, d.gpus) {
hc.DeviceRequests = d.gpus
}
if info, err := d.DockerAPI.Info(ctx); err == nil {
if info.CgroupDriver == "cgroupfs" {
if resp, err := d.DockerAPI.Info(ctx, dockerclient.InfoOptions{}); err == nil {
if resp.Info.CgroupDriver == "cgroupfs" {
// Place all buildkit containers inside this cgroup by default so limits can be attached
// to all build activity on the host.
hc.CgroupParent = "/docker/buildx"
@@ -208,18 +207,18 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
}
}
secOpts, err := system.DecodeSecurityOptions(info.SecurityOptions)
if err != nil {
return err
}
for _, f := range secOpts {
for _, f := range security.DecodeOptions(resp.Info.SecurityOptions) {
if f.Name == "userns" {
hc.UsernsMode = "host"
break
}
}
}
_, err := d.DockerAPI.ContainerCreate(ctx, cfg, hc, &network.NetworkingConfig{}, nil, d.Name)
_, err := d.DockerAPI.ContainerCreate(ctx, dockerclient.ContainerCreateOptions{
Config: cfg,
HostConfig: hc,
Name: d.Name,
})
if err != nil && !cerrdefs.IsConflict(err) {
return err
}
@@ -264,7 +263,7 @@ func (d *Driver) wait(ctx context.Context, l progress.SubLogger) error {
}
func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error {
rc, err := d.DockerAPI.ContainerLogs(ctx, d.Name, container.LogsOptions{
rc, err := d.DockerAPI.ContainerLogs(ctx, d.Name, dockerclient.ContainerLogsOptions{
ShowStdout: true, ShowStderr: true,
})
if err != nil {
@@ -294,12 +293,15 @@ func (d *Driver) copyToContainer(ctx context.Context, files map[string][]byte) e
}
defer srcArchive.Close()
baseDir := path.Dir(confutil.DefaultBuildKitConfigDir)
return d.DockerAPI.CopyToContainer(ctx, d.Name, baseDir, srcArchive, container.CopyToContainerOptions{})
_, err = d.DockerAPI.CopyToContainer(ctx, d.Name, dockerclient.CopyToContainerOptions{
DestinationPath: path.Dir(confutil.DefaultBuildKitConfigDir),
Content: srcArchive,
})
return err
}
func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, error) {
response, err := d.DockerAPI.ContainerExecCreate(ctx, d.Name, container.ExecOptions{
response, err := d.DockerAPI.ExecCreate(ctx, d.Name, dockerclient.ExecCreateOptions{
Cmd: cmd,
AttachStdin: true,
AttachStdout: true,
@@ -314,7 +316,7 @@ func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, erro
return "", nil, errors.New("exec ID empty")
}
resp, err := d.DockerAPI.ContainerExecAttach(ctx, execID, container.ExecStartOptions{})
resp, err := d.DockerAPI.ExecAttach(ctx, execID, dockerclient.ExecAttachOptions{})
if err != nil {
return "", nil, err
}
@@ -330,7 +332,7 @@ func (d *Driver) run(ctx context.Context, cmd []string, stdout, stderr io.Writer
return err
}
conn.Close()
resp, err := d.DockerAPI.ContainerExecInspect(ctx, id)
resp, err := d.DockerAPI.ExecInspect(ctx, id, dockerclient.ExecInspectOptions{})
if err != nil {
return err
}
@@ -341,11 +343,12 @@ func (d *Driver) run(ctx context.Context, cmd []string, stdout, stderr io.Writer
}
func (d *Driver) start(ctx context.Context) error {
return d.DockerAPI.ContainerStart(ctx, d.Name, container.StartOptions{})
_, err := d.DockerAPI.ContainerStart(ctx, d.Name, dockerclient.ContainerStartOptions{})
return err
}
func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
ctn, err := d.DockerAPI.ContainerInspect(ctx, d.Name)
res, err := d.DockerAPI.ContainerInspect(ctx, d.Name, dockerclient.ContainerInspectOptions{})
if err != nil {
if cerrdefs.IsNotFound(err) {
return &driver.Info{
@@ -355,7 +358,7 @@ func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
return nil, err
}
if ctn.State.Running {
if res.Container.State.Running {
return &driver.Info{
Status: driver.Running,
}, nil
@@ -388,7 +391,8 @@ func (d *Driver) Stop(ctx context.Context, force bool) error {
return err
}
if info.Status == driver.Running {
return d.DockerAPI.ContainerStop(ctx, d.Name, container.StopOptions{})
_, err = d.DockerAPI.ContainerStop(ctx, d.Name, dockerclient.ContainerStopOptions{})
return err
}
return nil
}
@@ -399,23 +403,23 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
return err
}
if info.Status != driver.Inactive {
ctr, err := d.DockerAPI.ContainerInspect(ctx, d.Name)
res, err := d.DockerAPI.ContainerInspect(ctx, d.Name, dockerclient.ContainerInspectOptions{})
if err != nil {
return err
}
if rmDaemon {
if err := d.DockerAPI.ContainerRemove(ctx, d.Name, container.RemoveOptions{
if _, err := d.DockerAPI.ContainerRemove(ctx, d.Name, dockerclient.ContainerRemoveOptions{
RemoveVolumes: true,
Force: force,
}); err != nil {
return err
}
for _, v := range ctr.Mounts {
if v.Name != d.Name+volumeStateSuffix {
continue
}
if rmVolume {
return d.DockerAPI.VolumeRemove(ctx, d.Name+volumeStateSuffix, false)
if rmVolume {
for _, v := range res.Container.Mounts {
if v.Name == d.Name+volumeStateSuffix {
_, err = d.DockerAPI.VolumeRemove(ctx, v.Name, dockerclient.VolumeRemoveOptions{})
return err
}
}
}
}
@@ -473,22 +477,23 @@ func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) {
// a dummy container with GPU device to check if the daemon has this capability
// because there is no API to check it yet.
func (d *Driver) hasGPUCapability(ctx context.Context, image string, gpus []container.DeviceRequest) bool {
cfg := &container.Config{
Image: image,
Entrypoint: []string{"/bin/true"},
}
hc := &container.HostConfig{
NetworkMode: container.NetworkMode(container.IPCModeNone),
AutoRemove: true,
Resources: container.Resources{
DeviceRequests: gpus,
resp, err := d.DockerAPI.ContainerCreate(ctx, dockerclient.ContainerCreateOptions{
Config: &container.Config{
Image: image,
Entrypoint: []string{"/bin/true"},
},
}
resp, err := d.DockerAPI.ContainerCreate(ctx, cfg, hc, &network.NetworkingConfig{}, nil, "")
HostConfig: &container.HostConfig{
NetworkMode: container.NetworkMode(container.IPCModeNone),
AutoRemove: true,
Resources: container.Resources{
DeviceRequests: gpus,
},
},
})
if err != nil {
return false
}
if err := d.DockerAPI.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
if _, err := d.DockerAPI.ContainerStart(ctx, resp.ID, dockerclient.ContainerStartOptions{}); err != nil {
return false
}
return true
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/docker/buildx/driver"
dockeropts "github.com/docker/cli/opts"
dockerclient "github.com/docker/docker/client"
dockerclient "github.com/moby/moby/client"
"github.com/pkg/errors"
)
+5 -2
View File
@@ -9,6 +9,7 @@ import (
"github.com/docker/buildx/driver"
"github.com/docker/buildx/util/progress"
"github.com/moby/buildkit/client"
dockerclient "github.com/moby/moby/client"
"github.com/pkg/errors"
)
@@ -27,7 +28,8 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
}
func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
_, err := d.DockerAPI.ServerVersion(ctx)
// TODO(thaJeztah): is "ping" enough for this?
_, err := d.DockerAPI.ServerVersion(ctx, dockerclient.ServerVersionOptions{})
if err != nil {
return nil, errors.Wrap(driver.ErrNotConnecting{}, err.Error())
}
@@ -37,10 +39,11 @@ func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
}
func (d *Driver) Version(ctx context.Context) (string, error) {
v, err := d.DockerAPI.ServerVersion(ctx)
v, err := d.DockerAPI.ServerVersion(ctx, dockerclient.ServerVersionOptions{})
if err != nil {
return "", errors.Wrap(driver.ErrNotConnecting{}, err.Error())
}
// TODO(thaJeztah): this code is only used for docker <= v23.0, which are deprecated.
if bkversion, _ := resolveBuildKitVersion(v.Version); bkversion != "" {
return bkversion, nil
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"context"
"github.com/docker/buildx/driver"
dockerclient "github.com/docker/docker/client"
dockerclient "github.com/moby/moby/client"
"github.com/pkg/errors"
)
+1 -1
View File
@@ -12,7 +12,7 @@ import (
ctxkube "github.com/docker/buildx/driver/kubernetes/context"
"github.com/docker/buildx/driver/kubernetes/manifest"
"github.com/docker/buildx/driver/kubernetes/podchooser"
dockerclient "github.com/docker/docker/client"
dockerclient "github.com/moby/moby/client"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
+1 -1
View File
@@ -6,9 +6,9 @@ import (
"sync"
"github.com/docker/cli/cli/context/store"
dockerclient "github.com/docker/docker/client"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/util/tracing/delegated"
dockerclient "github.com/moby/moby/client"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"github.com/docker/buildx/driver"
util "github.com/docker/buildx/driver/remote/util"
dockerclient "github.com/docker/docker/client"
dockerclient "github.com/moby/moby/client"
"github.com/pkg/errors"
// import connhelpers for special url schemes
+7 -5
View File
@@ -16,9 +16,9 @@ require (
github.com/creack/pty v1.1.24
github.com/davecgh/go-spew v1.1.1
github.com/distribution/reference v0.6.0
github.com/docker/cli v28.5.1+incompatible
github.com/docker/cli v29.0.0+incompatible
github.com/docker/cli-docs-tool v0.10.0
github.com/docker/docker v28.5.1+incompatible
github.com/docker/docker v28.5.2+incompatible
github.com/docker/go-units v0.5.0
github.com/gofrs/flock v0.13.0
github.com/google/go-dap v0.12.0
@@ -31,6 +31,8 @@ require (
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/moby/buildkit v0.26.0-rc2
github.com/moby/go-archive v0.1.0
github.com/moby/moby/api v1.52.0
github.com/moby/moby/client v0.1.0
github.com/moby/sys/atomicwriter v0.1.0
github.com/moby/sys/mountinfo v0.7.2
github.com/morikuni/aec v1.0.0
@@ -95,10 +97,10 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fvbommel/sortorder v1.0.1 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
@@ -110,6 +112,7 @@ require (
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/gorilla/mux v1.7.0 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@@ -141,7 +144,6 @@ require (
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/theupdateframework/notary v0.7.0 // indirect
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect
+14 -101
View File
@@ -2,14 +2,12 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8af
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boSWAHyK/tNAaYZL0c=
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
@@ -46,20 +44,12 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 h1:iV1Ko4Em/lkJIsoKyGfc0nQySi+v
github.com/aws/aws-sdk-go-v2/service/sts v1.38.0/go.mod h1:bEPcjW7IbolPfK67G1nilqWyoxYMSPrDiIQ3RdIdKgo=
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.9.1 h1:8UwI+ujNU+9Ffkf/YgAm/qM9/eU7Jn8nHzWG721W4rs=
@@ -104,42 +94,32 @@ github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfv
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v28.5.1+incompatible h1:ESutzBALAD6qyCLqbQSEf1a/U8Ybms5agw59yGVc+yY=
github.com/docker/cli v28.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v29.0.0+incompatible h1:KgsN2RUFMNM8wChxryicn4p46BdQWpXOA1XLGBGPGAw=
github.com/docker/cli v29.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.10.0 h1:bOD6mKynPQgojQi3s2jgcUWGp/Ebqy1SeCr9VfKQLLU=
github.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09fzRHP4aX1qwp1U=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -155,7 +135,6 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
@@ -164,17 +143,12 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -194,7 +168,6 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -206,27 +179,18 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE=
github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -234,24 +198,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/buildkit v0.26.0-rc2 h1:HLS1HtBlxdaz8NjHI5YAaN4c8NOPtUrIJ5jIq/b6tpI=
github.com/moby/buildkit v0.26.0-rc2/go.mod h1:ylDa7IqzVJgLdi/wO7H1qLREFQpmhFbw2fbn4yoTw40=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
@@ -260,6 +216,10 @@ github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby/api v1.52.0 h1:00BtlJY4MXkkt84WhUZPRqt5TvPbgig2FZvTbe3igYg=
github.com/moby/moby/api v1.52.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
github.com/moby/moby/client v0.1.0 h1:nt+hn6O9cyJQqq5UWnFGqsZRTS/JirUqzPjEl0Bdc/8=
github.com/moby/moby/client v0.1.0/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
@@ -290,48 +250,34 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
@@ -348,41 +294,27 @@ github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b h1:h+3JX2VoWTFuyQ
github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c=
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4=
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=
github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f h1:MoxeMfHAe5Qj/ySSBfL8A7l1V+hxuluj8owsIEEZipI=
@@ -448,18 +380,14 @@ go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -468,25 +396,19 @@ golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -511,30 +433,19 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -552,6 +463,8 @@ k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOP
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
+2 -2
View File
@@ -3,7 +3,7 @@ package dockerutil
import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/docker"
dockerclient "github.com/docker/docker/client"
dockerclient "github.com/moby/moby/client"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/propagation"
)
@@ -42,7 +42,7 @@ func NewClientAPI(cli command.Cli, ep string) (*ClientAPI, error) {
propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}),
)))
ca.APIClient, err = dockerclient.NewClientWithOpts(clientOpts...)
ca.APIClient, err = dockerclient.New(clientOpts...)
if err != nil {
return nil, err
}
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
dockerclient "github.com/docker/docker/client"
dockerclient "github.com/moby/moby/client"
)
// Client represents an active docker object.
@@ -61,7 +61,7 @@ func (c *Client) LoadImage(ctx context.Context, name string, status progress.Wri
status = progress.ResetTime(status)
if err := progress.Wrap("importing to docker", status.Write, func(l progress.SubLogger) error {
return fromReader(l, resp.Body)
return fromReader(l, resp)
}); err != nil {
handleErr(err)
}
@@ -83,8 +83,8 @@ func (c *Client) Features(ctx context.Context, name string) map[Feature]bool {
func (c *Client) features(ctx context.Context, name string) map[Feature]bool {
features := make(map[Feature]bool)
if dapi, err := c.API(name); err == nil {
if info, err := dapi.Info(ctx); err == nil {
for _, v := range info.DriverStatus {
if res, err := dapi.Info(ctx, dockerclient.InfoOptions{}); err == nil {
for _, v := range res.Info.DriverStatus {
switch v[0] {
case "driver-type":
if v[1] == "io.containerd.snapshotter.v1" {
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"time"
"github.com/docker/buildx/util/progress"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/buildkit/client"
"github.com/moby/moby/api/types/jsonstream"
)
const minTimeDelta = 2 * time.Second
@@ -27,7 +27,7 @@ func fromReader(l progress.SubLogger, rc io.ReadCloser) error {
dec := json.NewDecoder(rc)
var parsedErr error
var jm jsonmessage.JSONMessage
var jm jsonstream.Message
for {
if err := dec.Decode(&jm); err != nil {
if parsedErr != nil {
+10 -2
View File
@@ -63,6 +63,7 @@ Andreas Köhler <andi5.py@gmx.net>
Andres G. Aragoneses <knocte@gmail.com>
Andres Leon Rangel <aleon1220@gmail.com>
Andrew France <andrew@avito.co.uk>
Andrew He <he.andrew.mail@gmail.com>
Andrew Hsu <andrewhsu@docker.com>
Andrew Macpherson <hopscotch23@gmail.com>
Andrew McDonnell <bugs@andrewmcdonnell.net>
@@ -86,11 +87,12 @@ Archimedes Trajano <developer@trajano.net>
Arko Dasgupta <arko@tetrate.io>
Arnaud Porterie <icecrime@gmail.com>
Arnaud Rebillout <elboulangero@gmail.com>
Arthur Flageul <arthur.flageul@gmail.com>
Arthur Peka <arthur.peka@outlook.com>
Ashly Mathew <ashly.mathew@sap.com>
Ashwini Oruganti <ashwini.oruganti@gmail.com>
Aslam Ahemad <aslamahemad@gmail.com>
Austin Vazquez <austin.vazquez.dev@gmail.com>
Austin Vazquez <austin.vazquez@docker.com>
Azat Khuyiyakhmetov <shadow_uz@mail.ru>
Bardia Keyoumarsi <bkeyouma@ucsc.edu>
Barnaby Gray <barnaby@pickle.me.uk>
@@ -135,10 +137,12 @@ Cao Weiwei <cao.weiwei30@zte.com.cn>
Carlo Mion <mion00@gmail.com>
Carlos Alexandro Becker <caarlos0@gmail.com>
Carlos de Paula <me@carlosedp.com>
carsontham <carsontham@outlook.com>
Carston Schilds <Carston.Schilds@visier.com>
Casey Korver <casey@korver.dev>
Ce Gao <ce.gao@outlook.com>
Cedric Davies <cedricda@microsoft.com>
Cesar Talledo <cesar.talledo@docker.com>
Cezar Sa Espinola <cezarsa@gmail.com>
Chad Faragher <wyckster@hotmail.com>
Chao Wang <wangchao.fnst@cn.fujitsu.com>
@@ -220,7 +224,7 @@ David Alvarez <david.alvarez@flyeralarm.com>
David Beitey <david@davidjb.com>
David Calavera <david.calavera@gmail.com>
David Cramer <davcrame@cisco.com>
David Dooling <dooling@gmail.com>
David Dooling <david.dooling@docker.com>
David Gageot <david@gageot.net>
David Karlsson <david.karlsson@docker.com>
David le Blanc <systemmonkey42@users.noreply.github.com>
@@ -265,6 +269,7 @@ Eli Uriegas <eli.uriegas@docker.com>
Eli Uriegas <seemethere101@gmail.com>
Elias Faxö <elias.faxo@tre.se>
Elliot Luo <956941328@qq.com>
Eng Zer Jun <engzerjun@gmail.com>
Eric Bode <eric.bode@foundries.io>
Eric Curtin <ericcurtin17@gmail.com>
Eric Engestrom <eric@engestrom.ch>
@@ -345,6 +350,7 @@ Henning Sprang <henning.sprang@gmail.com>
Henry N <henrynmail-github@yahoo.de>
Hernan Garcia <hernandanielg@gmail.com>
Hongbin Lu <hongbin034@gmail.com>
Hossein Abbasi <16090309+hsnabszhdn@users.noreply.github.com>
Hu Keping <hukeping@huawei.com>
Huayi Zhang <irachex@gmail.com>
Hugo Chastel <Hugo-C@users.noreply.github.com>
@@ -595,6 +601,7 @@ Michael Prokop <github@michael-prokop.at>
Michael Scharf <github@scharf.gr>
Michael Spetsiotis <michael_spets@hotmail.com>
Michael Steinert <mike.steinert@gmail.com>
Michael Tews <michael@tews.dev>
Michael West <mwest@mdsol.com>
Michal Minář <miminar@redhat.com>
Michał Czeraszkiewicz <czerasz@gmail.com>
@@ -896,6 +903,7 @@ Wenlong Zhang <zhangwenlong@loongson.cn>
Wenzhi Liang <wenzhi.liang@gmail.com>
Wes Morgan <cap10morgan@gmail.com>
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
Will Wang <willww64@gmail.com>
William Henry <whenry@redhat.com>
Xianglin Gao <xlgao@zju.edu.cn>
Xiaodong Liu <liuxiaodong@loongson.cn>
+2
View File
@@ -33,4 +33,6 @@ type Metadata struct {
ShortDescription string `json:",omitempty"`
// URL is a pointer to the plugin's homepage.
URL string `json:",omitempty"`
// Hidden hides the plugin in completion and help message output.
Hidden bool `json:",omitempty"`
}
+7 -2
View File
@@ -14,7 +14,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/connhelper"
"github.com/docker/cli/cli/debug"
"github.com/docker/docker/client"
"github.com/moby/moby/client"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel"
)
@@ -139,7 +139,7 @@ func withPluginClientConn(name string) command.CLIOption {
if err != nil {
return err
}
apiClient, err := client.NewClientWithOpts(client.WithDialContext(helper.Dialer))
apiClient, err := client.New(client.WithDialContext(helper.Dialer))
if err != nil {
return err
}
@@ -168,6 +168,11 @@ func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta
DisableDescriptions: os.Getenv("DOCKER_CLI_DISABLE_COMPLETION_DESCRIPTION") != "",
},
}
// Disable file-completion by default. Most commands and flags should not
// complete with filenames.
cmd.CompletionOptions.SetDefaultShellCompDirective(cobra.ShellCompDirectiveNoFileComp)
opts, _ := cli.SetupPluginRootCommand(cmd)
cmd.SetIn(dockerCli.In())
+7 -35
View File
@@ -12,7 +12,6 @@ import (
"github.com/fvbommel/sortorder"
"github.com/moby/term"
"github.com/morikuni/aec"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@@ -167,31 +166,6 @@ func (tcmd *TopLevelCommand) Initialize(ops ...command.CLIOption) error {
return tcmd.dockerCli.Initialize(tcmd.opts, ops...)
}
// VisitAll will traverse all commands from the root.
//
// Deprecated: this utility was only used internally and will be removed in the next release.
func VisitAll(root *cobra.Command, fn func(*cobra.Command)) {
visitAll(root, fn)
}
func visitAll(root *cobra.Command, fn func(*cobra.Command)) {
for _, cmd := range root.Commands() {
visitAll(cmd, fn)
}
fn(root)
}
// DisableFlagsInUseLine sets the DisableFlagsInUseLine flag on all
// commands within the tree rooted at cmd.
//
// Deprecated: this utility was only used internally and will be removed in the next release.
func DisableFlagsInUseLine(cmd *cobra.Command) {
visitAll(cmd, func(ccmd *cobra.Command) {
// do not add a `[flags]` to the end of the usage line.
ccmd.DisableFlagsInUseLine = true
})
}
var helpCommand = &cobra.Command{
Use: "help [command]",
Short: "Help about the command",
@@ -200,7 +174,7 @@ var helpCommand = &cobra.Command{
RunE: func(c *cobra.Command, args []string) error {
cmd, args, e := c.Root().Find(args)
if cmd == nil || e != nil || len(args) > 0 {
return errors.Errorf("unknown help topic: %v", strings.Join(args, " "))
return fmt.Errorf("unknown help topic: %v", strings.Join(args, " "))
}
helpFunc := cmd.HelpFunc()
helpFunc(cmd, args)
@@ -276,11 +250,12 @@ func commandAliases(cmd *cobra.Command) string {
if cmd.HasParent() {
parentPath = cmd.Parent().CommandPath() + " "
}
aliases := cmd.CommandPath()
var aliases strings.Builder
aliases.WriteString(cmd.CommandPath())
for _, alias := range cmd.Aliases {
aliases += ", " + parentPath + alias
aliases.WriteString(", " + parentPath + alias)
}
return aliases
return aliases.String()
}
func topCommands(cmd *cobra.Command) []*cobra.Command {
@@ -376,13 +351,10 @@ func orchestratorSubCommands(cmd *cobra.Command) []*cobra.Command {
func allManagementSubCommands(cmd *cobra.Command) []*cobra.Command {
cmds := []*cobra.Command{}
for _, sub := range cmd.Commands() {
if isPlugin(sub) {
if invalidPluginReason(sub) == "" {
cmds = append(cmds, sub)
}
if invalidPluginReason(sub) != "" {
continue
}
if sub.IsAvailableCommand() && sub.HasSubCommands() {
if sub.IsAvailableCommand() && (isPlugin(sub) || sub.HasSubCommands()) {
cmds = append(cmds, sub)
}
}
+15 -50
View File
@@ -1,10 +1,11 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package command
import (
"context"
"errors"
"fmt"
"io"
"os"
@@ -23,11 +24,8 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/version"
dopts "github.com/docker/cli/opts"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/moby/moby/api/types/build"
"github.com/moby/moby/client"
"github.com/spf13/cobra"
)
@@ -45,7 +43,6 @@ type Cli interface {
Client() client.APIClient
Streams
SetIn(in *streams.In)
Apply(ops ...CLIOption) error
config.Provider
ServerInfo() ServerInfo
CurrentVersion() string
@@ -68,7 +65,6 @@ type DockerCli struct {
err *streams.Out
client client.APIClient
serverInfo ServerInfo
contentTrust bool
contextStore store.Store
currentContext string
init sync.Once
@@ -87,19 +83,12 @@ type DockerCli struct {
enableGlobalMeter, enableGlobalTracer bool
}
// DefaultVersion returns [api.DefaultVersion].
//
// Deprecated: this function is no longer used and will be removed in the next release.
func (*DockerCli) DefaultVersion() string {
return api.DefaultVersion
}
// CurrentVersion returns the API version currently negotiated, or the default
// version otherwise.
func (cli *DockerCli) CurrentVersion() string {
_ = cli.initialize()
if cli.client == nil {
return api.DefaultVersion
return client.MaxAPIVersion
}
return cli.client.ClientVersion()
}
@@ -158,21 +147,13 @@ func (cli *DockerCli) ServerInfo() ServerInfo {
return cli.serverInfo
}
// ContentTrustEnabled returns whether content trust has been enabled by an
// environment variable.
//
// Deprecated: check the value of the DOCKER_CONTENT_TRUST environment variable to detect whether content-trust is enabled.
func (cli *DockerCli) ContentTrustEnabled() bool {
return cli.contentTrust
}
// BuildKitEnabled returns buildkit is enabled or not.
func (cli *DockerCli) BuildKitEnabled() (bool, error) {
// use DOCKER_BUILDKIT env var value if set and not empty
if v := os.Getenv("DOCKER_BUILDKIT"); v != "" {
enabled, err := strconv.ParseBool(v)
if err != nil {
return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
return false, fmt.Errorf("DOCKER_BUILDKIT environment variable expects boolean value: %w", err)
}
return enabled, nil
}
@@ -314,7 +295,7 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
}
endpoint, err := resolveDockerEndpoint(contextStore, resolveContextName(opts, configFile))
if err != nil {
return nil, errors.Wrap(err, "unable to resolve docker endpoint")
return nil, fmt.Errorf("unable to resolve docker endpoint: %w", err)
}
return newAPIClientFromEndpoint(endpoint, configFile, client.WithUserAgent(UserAgent()))
}
@@ -335,7 +316,7 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
opts = append(opts, withCustomHeaders)
}
opts = append(opts, extraOpts...)
return client.NewClientWithOpts(opts...)
return client.New(opts...)
}
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {
@@ -396,24 +377,21 @@ func (cli *DockerCli) initializeFromClient() {
ctx, cancel := context.WithTimeout(cli.baseCtx, cli.getInitTimeout())
defer cancel()
ping, err := cli.client.Ping(ctx)
ping, err := cli.client.Ping(ctx, client.PingOptions{
NegotiateAPIVersion: true,
ForceNegotiate: true,
})
if err != nil {
// Default to true if we fail to connect to daemon
cli.serverInfo = ServerInfo{HasExperimental: true}
if ping.APIVersion != "" {
cli.client.NegotiateAPIVersionPing(ping)
}
return
}
cli.serverInfo = ServerInfo{
HasExperimental: ping.Experimental,
OSType: ping.OSType,
BuildkitVersion: ping.BuilderVersion,
SwarmStatus: ping.SwarmStatus,
}
cli.client.NegotiateAPIVersionPing(ping)
}
// ContextStore returns the ContextStore
@@ -551,7 +529,7 @@ func (cli *DockerCli) initialize() error {
cli.init.Do(func() {
cli.dockerEndpoint, cli.initErr = cli.getDockerEndPoint()
if cli.initErr != nil {
cli.initErr = errors.Wrap(cli.initErr, "unable to resolve docker endpoint")
cli.initErr = fmt.Errorf("unable to resolve docker endpoint: %w", cli.initErr)
return
}
if cli.client == nil {
@@ -568,18 +546,6 @@ func (cli *DockerCli) initialize() error {
return cli.initErr
}
// Apply all the operation on the cli
//
// Deprecated: this method is no longer used and will be removed in the next release if there are no remaining users.
func (cli *DockerCli) Apply(ops ...CLIOption) error {
for _, op := range ops {
if err := op(cli); err != nil {
return err
}
}
return nil
}
// ServerInfo stores details about the supported features and platform of the
// server
type ServerInfo struct {
@@ -594,7 +560,7 @@ type ServerInfo struct {
// in the ping response, or if an error occurred, in which case the client
// should use other ways to get the current swarm status, such as the /swarm
// endpoint.
SwarmStatus *swarm.Status
SwarmStatus *client.SwarmStatus
}
// NewDockerCli returns a DockerCli instance with all operators applied on it.
@@ -602,7 +568,6 @@ type ServerInfo struct {
// environment.
func NewDockerCli(ops ...CLIOption) (*DockerCli, error) {
defaultOps := []CLIOption{
withContentTrustFromEnv(),
WithDefaultContextStoreConfig(),
WithStandardStreams(),
WithUserAgent(UserAgent()),
@@ -625,7 +590,7 @@ func getServerHost(hosts []string, defaultToTLS bool) (string, error) {
case 1:
return dopts.ParseHost(defaultToTLS, hosts[0])
default:
return "", errors.New("Specify only one -H")
return "", errors.New("specify only one -H")
}
}
+6 -37
View File
@@ -3,16 +3,16 @@ package command
import (
"context"
"encoding/csv"
"errors"
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/client"
"github.com/moby/moby/client"
"github.com/moby/term"
"github.com/pkg/errors"
)
// CLIOption is a functional argument to apply options to a [DockerCli]. These
@@ -75,37 +75,6 @@ func WithErrorStream(err io.Writer) CLIOption {
}
}
// withContentTrustFromEnv enables content trust on a cli from environment variable DOCKER_CONTENT_TRUST value.
func withContentTrustFromEnv() CLIOption {
return func(cli *DockerCli) error {
cli.contentTrust = false
if e := os.Getenv("DOCKER_CONTENT_TRUST"); e != "" {
if t, err := strconv.ParseBool(e); t || err != nil {
// treat any other value as true
cli.contentTrust = true
}
}
return nil
}
}
// WithContentTrustFromEnv enables content trust on a cli from environment variable DOCKER_CONTENT_TRUST value.
//
// Deprecated: this option is no longer used, and will be removed in the next release.
func WithContentTrustFromEnv() CLIOption {
return withContentTrustFromEnv()
}
// WithContentTrust enables content trust on a cli.
//
// Deprecated: this option is no longer used, and will be removed in the next release.
func WithContentTrust(enabled bool) CLIOption {
return func(cli *DockerCli) error {
cli.contentTrust = enabled
return nil
}
}
// WithDefaultContextStoreConfig configures the cli to use the default context store configuration.
func WithDefaultContextStoreConfig() CLIOption {
return func(cli *DockerCli) error {
@@ -197,7 +166,7 @@ func withCustomHeadersFromEnv() (client.Opt, error) {
csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read()
if err != nil {
return nil, invalidParameter(errors.Errorf(
return nil, invalidParameter(fmt.Errorf(
"failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs",
envOverrideHTTPHeaders,
))
@@ -214,7 +183,7 @@ func withCustomHeadersFromEnv() (client.Opt, error) {
k = strings.TrimSpace(k)
if k == "" {
return nil, invalidParameter(errors.Errorf(
return nil, invalidParameter(fmt.Errorf(
`failed to set custom headers from %s environment variable: value contains a key=value pair with an empty key: '%s'`,
envOverrideHTTPHeaders, kv,
))
@@ -225,7 +194,7 @@ func withCustomHeadersFromEnv() (client.Opt, error) {
// from an environment variable with the same name). In the meantime,
// produce an error to prevent users from depending on this.
if !hasValue {
return nil, invalidParameter(errors.Errorf(
return nil, invalidParameter(fmt.Errorf(
`failed to set custom headers from %s environment variable: missing "=" in key=value pair: '%s'`,
envOverrideHTTPHeaders, kv,
))
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package command
+5 -10
View File
@@ -1,13 +1,15 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package command
import (
"errors"
"fmt"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/cli/context/store"
cliflags "github.com/docker/cli/cli/flags"
"github.com/pkg/errors"
)
const (
@@ -51,13 +53,6 @@ type EndpointDefaultResolver interface {
ResolveDefault() (any, *store.EndpointTLSData, error)
}
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
//
// Deprecated: this function is exported for testing and meant for internal use. It will be removed in the next release.
func ResolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) {
return resolveDefaultContext(opts, config)
}
// resolveDefaultContext creates a Metadata for the current CLI invocation parameters
func resolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) {
contextTLSData := store.ContextTLSData{
@@ -192,7 +187,7 @@ func (s *ContextStoreWithDefault) GetTLSData(contextName, endpointName, fileName
return nil, err
}
if defaultContext.TLS.Endpoints[endpointName].Files[fileName] == nil {
return nil, notFound(errors.Errorf("TLS data for %s/%s/%s does not exist", DefaultContextName, endpointName, fileName))
return nil, notFound(fmt.Errorf("TLS data for %s/%s/%s does not exist", DefaultContextName, endpointName, fileName))
}
return defaultContext.TLS.Endpoints[endpointName].Files[fileName], nil
}
+4 -6
View File
@@ -6,8 +6,8 @@ import (
"strings"
"time"
"github.com/docker/docker/api/types/build"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/build"
)
const (
@@ -51,7 +51,7 @@ shared: {{.Shared}}
return Format(source)
}
func buildCacheSort(buildCache []*build.CacheRecord) {
func buildCacheSort(buildCache []build.CacheRecord) {
sort.Slice(buildCache, func(i, j int) bool {
lui, luj := buildCache[i].LastUsedAt, buildCache[j].LastUsedAt
switch {
@@ -70,7 +70,7 @@ func buildCacheSort(buildCache []*build.CacheRecord) {
}
// BuildCacheWrite renders the context for a list of containers
func BuildCacheWrite(ctx Context, buildCaches []*build.CacheRecord) error {
func BuildCacheWrite(ctx Context, buildCaches []build.CacheRecord) error {
render := func(format func(subContext SubContext) error) error {
buildCacheSort(buildCaches)
for _, bc := range buildCaches {
@@ -87,7 +87,7 @@ func BuildCacheWrite(ctx Context, buildCaches []*build.CacheRecord) error {
type buildCacheContext struct {
HeaderContext
trunc bool
v *build.CacheRecord
v build.CacheRecord
}
func newBuildCacheContext() *buildCacheContext {
@@ -126,8 +126,6 @@ func (c *buildCacheContext) Parent() string {
var parent string
if len(c.v.Parents) > 0 {
parent = strings.Join(c.v.Parents, ", ")
} else {
parent = c.v.Parent //nolint:staticcheck // Ignore SA1019: Field was deprecated in API v1.42, but kept for backward compatibility
}
if c.trunc {
return TruncateID(parent)
+31 -25
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package formatter
@@ -13,8 +13,8 @@ import (
"github.com/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/container"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
@@ -170,27 +170,33 @@ func (c *ContainerContext) Image() string {
if c.c.Image == "" {
return "<no image>"
}
if c.trunc {
if trunc := TruncateID(c.c.ImageID); trunc == TruncateID(c.c.Image) {
return trunc
if !c.trunc {
return c.c.Image
}
if trunc := TruncateID(c.c.ImageID); trunc == TruncateID(c.c.Image) {
return trunc
}
ref, err := reference.ParseNormalizedNamed(c.c.Image)
if err != nil {
return c.c.Image
}
if _, ok := ref.(reference.Digested); ok {
// strip the digest, but preserve the tag (if any)
var tag string
if t, ok := ref.(reference.Tagged); ok {
tag = t.Tag()
}
// truncate digest if no-trunc option was not selected
ref, err := reference.ParseNormalizedNamed(c.c.Image)
if err == nil {
if nt, ok := ref.(reference.NamedTagged); ok {
// case for when a tag is provided
if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
return reference.FamiliarString(namedTagged)
}
} else {
// case for when a tag is not provided
named := reference.TrimNamed(ref)
return reference.FamiliarString(named)
ref = reference.TrimNamed(ref)
if tag != "" {
if out, err := reference.WithTag(ref, tag); err == nil {
ref = out
}
}
}
return c.c.Image
// Format as "familiar" name with "docker.io[/library]" trimmed.
return reference.FamiliarString(ref)
}
// Command returns's the container's command. If the trunc option is set, the
@@ -241,7 +247,7 @@ func (c *ContainerContext) Ports() string {
// State returns the container's current state (e.g. "running" or "paused").
// Refer to [container.ContainerState] for possible states.
func (c *ContainerContext) State() string {
return c.c.State
return string(c.c.State)
}
// Status returns the container's status in a human readable form (for example,
@@ -338,7 +344,7 @@ func (c *ContainerContext) Networks() string {
// DisplayablePorts returns formatted string representing open ports of container
// e.g. "0.0.0.0:80->9090/tcp, 9988/tcp"
// it's used by command 'docker ps'
func DisplayablePorts(ports []container.Port) string {
func DisplayablePorts(ports []container.PortSummary) string {
type portGroup struct {
first uint16
last uint16
@@ -354,13 +360,13 @@ func DisplayablePorts(ports []container.Port) string {
for _, port := range ports {
current := port.PrivatePort
portKey := port.Type
if port.IP != "" {
if port.IP.IsValid() {
if port.PublicPort != current {
hAddrPort := net.JoinHostPort(port.IP, strconv.Itoa(int(port.PublicPort)))
hAddrPort := net.JoinHostPort(port.IP.String(), strconv.Itoa(int(port.PublicPort)))
hostMappings = append(hostMappings, fmt.Sprintf("%s->%d/%s", hAddrPort, port.PrivatePort, port.Type))
continue
}
portKey = port.IP + "/" + port.Type
portKey = port.IP.String() + "/" + port.Type
}
group := groupMap[portKey]
@@ -404,13 +410,13 @@ func formGroup(key string, start, last uint16) string {
return group + "/" + groupType
}
func comparePorts(i, j container.Port) bool {
func comparePorts(i, j container.PortSummary) bool {
if i.PrivatePort != j.PrivatePort {
return i.PrivatePort < j.PrivatePort
}
if i.IP != j.IP {
return i.IP < j.IP
return i.IP.String() < j.IP.String()
}
if i.PublicPort != j.PublicPort {
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package formatter
+94 -159
View File
@@ -7,19 +7,20 @@ import (
"text/template"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/volume"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/build"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/image"
"github.com/moby/moby/api/types/volume"
"github.com/moby/moby/client"
)
const (
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
defaultDiskUsageTableFormat = "table {{.Type}}\t{{.TotalCount}}\t{{.Active}}\t{{.Size}}\t{{.Reclaimable}}"
defaultDiskUsageImageTableFormat Format = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
defaultDiskUsageContainerTableFormat Format = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
defaultDiskUsageVolumeTableFormat Format = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
defaultDiskUsageBuildCacheTableFormat Format = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
defaultDiskUsageTableFormat Format = "table {{.Type}}\t{{.TotalCount}}\t{{.Active}}\t{{.Size}}\t{{.Reclaimable}}"
typeHeader = "TYPE"
totalHeader = "TOTAL"
@@ -33,19 +34,18 @@ const (
// DiskUsageContext contains disk usage specific information required by the formatter, encapsulate a Context struct.
type DiskUsageContext struct {
Context
Verbose bool
LayersSize int64
Images []*image.Summary
Containers []*container.Summary
Volumes []*volume.Volume
BuildCache []*build.CacheRecord
BuilderSize int64
Verbose bool
ImageDiskUsage client.ImagesDiskUsage
BuildCacheDiskUsage client.BuildCacheDiskUsage
ContainerDiskUsage client.ContainersDiskUsage
VolumeDiskUsage client.VolumesDiskUsage
}
func (ctx *DiskUsageContext) startSubsection(format string) (*template.Template, error) {
func (ctx *DiskUsageContext) startSubsection(format Format) (*template.Template, error) {
ctx.buffer = &bytes.Buffer{}
ctx.header = ""
ctx.Format = Format(format)
ctx.Format = format
ctx.preFormat()
return ctx.parseFormat()
@@ -69,7 +69,7 @@ func NewDiskUsageFormat(source string, verbose bool) Format {
{{end -}}`
return format
case !verbose && source == TableFormatKey:
return Format(defaultDiskUsageTableFormat)
return defaultDiskUsageTableFormat
case !verbose && source == RawFormatKey:
format := `type: {{.Type}}
total: {{.TotalCount}}
@@ -96,35 +96,49 @@ func (ctx *DiskUsageContext) Write() (err error) {
}
err = ctx.contextFormat(tmpl, &diskUsageImagesContext{
totalSize: ctx.LayersSize,
images: ctx.Images,
totalCount: ctx.ImageDiskUsage.TotalCount,
activeCount: ctx.ImageDiskUsage.ActiveCount,
totalSize: ctx.ImageDiskUsage.TotalSize,
reclaimable: ctx.ImageDiskUsage.Reclaimable,
images: ctx.ImageDiskUsage.Items,
})
if err != nil {
return err
}
err = ctx.contextFormat(tmpl, &diskUsageContainersContext{
containers: ctx.Containers,
totalCount: ctx.ContainerDiskUsage.TotalCount,
activeCount: ctx.ContainerDiskUsage.ActiveCount,
totalSize: ctx.ContainerDiskUsage.TotalSize,
reclaimable: ctx.ContainerDiskUsage.Reclaimable,
containers: ctx.ContainerDiskUsage.Items,
})
if err != nil {
return err
}
err = ctx.contextFormat(tmpl, &diskUsageVolumesContext{
volumes: ctx.Volumes,
totalCount: ctx.VolumeDiskUsage.TotalCount,
activeCount: ctx.VolumeDiskUsage.ActiveCount,
totalSize: ctx.VolumeDiskUsage.TotalSize,
reclaimable: ctx.VolumeDiskUsage.Reclaimable,
volumes: ctx.VolumeDiskUsage.Items,
})
if err != nil {
return err
}
err = ctx.contextFormat(tmpl, &diskUsageBuilderContext{
builderSize: ctx.BuilderSize,
buildCache: ctx.BuildCache,
totalCount: ctx.BuildCacheDiskUsage.TotalCount,
activeCount: ctx.BuildCacheDiskUsage.ActiveCount,
builderSize: ctx.BuildCacheDiskUsage.TotalSize,
reclaimable: ctx.BuildCacheDiskUsage.Reclaimable,
buildCache: ctx.BuildCacheDiskUsage.Items,
})
if err != nil {
return err
}
diskUsageContainersCtx := diskUsageContainersContext{containers: []*container.Summary{}}
diskUsageContainersCtx := diskUsageContainersContext{containers: []container.Summary{}}
diskUsageContainersCtx.Header = SubHeaderContext{
"Type": typeHeader,
"TotalCount": totalHeader,
@@ -146,18 +160,18 @@ type diskUsageContext struct {
func (ctx *DiskUsageContext) verboseWrite() error {
duc := &diskUsageContext{
Images: make([]*imageContext, 0, len(ctx.Images)),
Containers: make([]*ContainerContext, 0, len(ctx.Containers)),
Volumes: make([]*volumeContext, 0, len(ctx.Volumes)),
BuildCache: make([]*buildCacheContext, 0, len(ctx.BuildCache)),
Images: make([]*imageContext, 0, len(ctx.ImageDiskUsage.Items)),
Containers: make([]*ContainerContext, 0, len(ctx.ContainerDiskUsage.Items)),
Volumes: make([]*volumeContext, 0, len(ctx.VolumeDiskUsage.Items)),
BuildCache: make([]*buildCacheContext, 0, len(ctx.BuildCacheDiskUsage.Items)),
}
trunc := ctx.Format.IsTable()
// First images
for _, i := range ctx.Images {
for _, i := range ctx.ImageDiskUsage.Items {
repo := "<none>"
tag := "<none>"
if len(i.RepoTags) > 0 && !isDangling(*i) {
if len(i.RepoTags) > 0 && !isDangling(i) {
// Only show the first tag
ref, err := reference.ParseNormalizedNamed(i.RepoTags[0])
if err != nil {
@@ -173,25 +187,25 @@ func (ctx *DiskUsageContext) verboseWrite() error {
repo: repo,
tag: tag,
trunc: trunc,
i: *i,
i: i,
})
}
// Now containers
for _, c := range ctx.Containers {
for _, c := range ctx.ContainerDiskUsage.Items {
// Don't display the virtual size
c.SizeRootFs = 0
duc.Containers = append(duc.Containers, &ContainerContext{trunc: trunc, c: *c})
duc.Containers = append(duc.Containers, &ContainerContext{trunc: trunc, c: c})
}
// And volumes
for _, v := range ctx.Volumes {
duc.Volumes = append(duc.Volumes, &volumeContext{v: *v})
for _, v := range ctx.VolumeDiskUsage.Items {
duc.Volumes = append(duc.Volumes, &volumeContext{v: v})
}
// And build cache
buildCacheSort(ctx.BuildCache)
for _, v := range ctx.BuildCache {
buildCacheSort(ctx.BuildCacheDiskUsage.Items)
for _, v := range ctx.BuildCacheDiskUsage.Items {
duc.BuildCache = append(duc.BuildCache, &buildCacheContext{v: v, trunc: trunc})
}
@@ -212,7 +226,7 @@ func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error {
if err != nil {
return err
}
ctx.Output.Write([]byte("Images space usage:\n\n"))
_, _ = ctx.Output.Write([]byte("Images space usage:\n\n"))
for _, img := range duc.Images {
if err := ctx.contextFormat(tmpl, img); err != nil {
return err
@@ -224,7 +238,7 @@ func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error {
if err != nil {
return err
}
ctx.Output.Write([]byte("\nContainers space usage:\n\n"))
_, _ = ctx.Output.Write([]byte("\nContainers space usage:\n\n"))
for _, c := range duc.Containers {
if err := ctx.contextFormat(tmpl, c); err != nil {
return err
@@ -248,7 +262,7 @@ func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error {
if err != nil {
return err
}
_, _ = fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuilderSize)))
_, _ = fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuildCacheDiskUsage.TotalSize)))
for _, v := range duc.BuildCache {
if err := ctx.contextFormat(tmpl, v); err != nil {
return err
@@ -261,8 +275,11 @@ func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error {
type diskUsageImagesContext struct {
HeaderContext
totalSize int64
images []*image.Summary
totalSize int64
reclaimable int64
totalCount int64
activeCount int64
images []image.Summary
}
func (c *diskUsageImagesContext) MarshalJSON() ([]byte, error) {
@@ -274,18 +291,11 @@ func (*diskUsageImagesContext) Type() string {
}
func (c *diskUsageImagesContext) TotalCount() string {
return strconv.Itoa(len(c.images))
return strconv.FormatInt(c.totalCount, 10)
}
func (c *diskUsageImagesContext) Active() string {
used := 0
for _, i := range c.images {
if i.Containers > 0 {
used++
}
}
return strconv.Itoa(used)
return strconv.FormatInt(c.activeCount, 10)
}
func (c *diskUsageImagesContext) Size() string {
@@ -293,27 +303,19 @@ func (c *diskUsageImagesContext) Size() string {
}
func (c *diskUsageImagesContext) Reclaimable() string {
var used int64
for _, i := range c.images {
if i.Containers != 0 {
if i.Size == -1 || i.SharedSize == -1 {
continue
}
used += i.Size - i.SharedSize
}
}
reclaimable := c.totalSize - used
if c.totalSize > 0 {
return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(reclaimable)), (reclaimable*100)/c.totalSize)
return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(c.reclaimable)), (c.reclaimable*100)/c.totalSize)
}
return units.HumanSize(float64(reclaimable))
return units.HumanSize(float64(c.reclaimable))
}
type diskUsageContainersContext struct {
HeaderContext
containers []*container.Summary
totalCount int64
activeCount int64
totalSize int64
reclaimable int64
containers []container.Summary
}
func (c *diskUsageContainersContext) MarshalJSON() ([]byte, error) {
@@ -325,62 +327,32 @@ func (*diskUsageContainersContext) Type() string {
}
func (c *diskUsageContainersContext) TotalCount() string {
return strconv.Itoa(len(c.containers))
}
func (*diskUsageContainersContext) isActive(ctr container.Summary) bool {
switch ctr.State {
case container.StateRunning, container.StatePaused, container.StateRestarting:
return true
case container.StateCreated, container.StateRemoving, container.StateExited, container.StateDead:
return false
default:
// Unknown state (should never happen).
return false
}
return strconv.FormatInt(c.totalCount, 10)
}
func (c *diskUsageContainersContext) Active() string {
used := 0
for _, ctr := range c.containers {
if c.isActive(*ctr) {
used++
}
}
return strconv.Itoa(used)
return strconv.FormatInt(c.activeCount, 10)
}
func (c *diskUsageContainersContext) Size() string {
var size int64
for _, ctr := range c.containers {
size += ctr.SizeRw
}
return units.HumanSize(float64(size))
return units.HumanSize(float64(c.totalSize))
}
func (c *diskUsageContainersContext) Reclaimable() string {
var reclaimable, totalSize int64
for _, ctr := range c.containers {
if !c.isActive(*ctr) {
reclaimable += ctr.SizeRw
}
totalSize += ctr.SizeRw
if c.totalSize > 0 {
return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(c.reclaimable)), (c.reclaimable*100)/c.totalSize)
}
if totalSize > 0 {
return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(reclaimable)), (reclaimable*100)/totalSize)
}
return units.HumanSize(float64(reclaimable))
return units.HumanSize(float64(c.reclaimable))
}
type diskUsageVolumesContext struct {
HeaderContext
volumes []*volume.Volume
totalCount int64
activeCount int64
totalSize int64
reclaimable int64
volumes []volume.Volume
}
func (c *diskUsageVolumesContext) MarshalJSON() ([]byte, error) {
@@ -392,56 +364,32 @@ func (*diskUsageVolumesContext) Type() string {
}
func (c *diskUsageVolumesContext) TotalCount() string {
return strconv.Itoa(len(c.volumes))
return strconv.FormatInt(c.totalCount, 10)
}
func (c *diskUsageVolumesContext) Active() string {
used := 0
for _, v := range c.volumes {
if v.UsageData.RefCount > 0 {
used++
}
}
return strconv.Itoa(used)
return strconv.FormatInt(c.activeCount, 10)
}
func (c *diskUsageVolumesContext) Size() string {
var size int64
for _, v := range c.volumes {
if v.UsageData.Size != -1 {
size += v.UsageData.Size
}
}
return units.HumanSize(float64(size))
return units.HumanSize(float64(c.totalSize))
}
func (c *diskUsageVolumesContext) Reclaimable() string {
var reclaimable int64
var totalSize int64
for _, v := range c.volumes {
if v.UsageData.Size != -1 {
if v.UsageData.RefCount == 0 {
reclaimable += v.UsageData.Size
}
totalSize += v.UsageData.Size
}
if c.totalSize > 0 {
return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(c.reclaimable)), (c.reclaimable*100)/c.totalSize)
}
if totalSize > 0 {
return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(reclaimable)), (reclaimable*100)/totalSize)
}
return units.HumanSize(float64(reclaimable))
return units.HumanSize(float64(c.reclaimable))
}
type diskUsageBuilderContext struct {
HeaderContext
totalCount int64
activeCount int64
builderSize int64
buildCache []*build.CacheRecord
reclaimable int64
buildCache []build.CacheRecord
}
func (c *diskUsageBuilderContext) MarshalJSON() ([]byte, error) {
@@ -453,17 +401,11 @@ func (*diskUsageBuilderContext) Type() string {
}
func (c *diskUsageBuilderContext) TotalCount() string {
return strconv.Itoa(len(c.buildCache))
return strconv.FormatInt(c.totalCount, 10)
}
func (c *diskUsageBuilderContext) Active() string {
numActive := 0
for _, bc := range c.buildCache {
if bc.InUse {
numActive++
}
}
return strconv.Itoa(numActive)
return strconv.FormatInt(c.activeCount, 10)
}
func (c *diskUsageBuilderContext) Size() string {
@@ -471,12 +413,5 @@ func (c *diskUsageBuilderContext) Size() string {
}
func (c *diskUsageBuilderContext) Reclaimable() string {
var inUseBytes int64
for _, bc := range c.buildCache {
if bc.InUse && !bc.Shared {
inUseBytes += bc.Size
}
}
return units.HumanSize(float64(c.builderSize - inUseBytes))
return units.HumanSize(float64(c.reclaimable))
}
+4 -14
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package formatter
@@ -8,6 +8,7 @@ import (
"strings"
"unicode/utf8"
"github.com/moby/moby/client/pkg/stringid"
"golang.org/x/text/width"
)
@@ -27,23 +28,12 @@ func charWidth(r rune) int {
}
}
const shortLen = 12
// TruncateID returns a shorthand version of a string identifier for presentation,
// after trimming digest algorithm prefix (if any).
//
// This function is a copy of [stringid.TruncateID] for presentation / formatting
// purposes.
//
// [stringid.TruncateID]: https://github.com/moby/moby/blob/v28.3.2/pkg/stringid/stringid.go#L19
// This function is a wrapper for [stringid.TruncateID] for convenience.
func TruncateID(id string) string {
if i := strings.IndexRune(id, ':'); i >= 0 {
id = id[i+1:]
}
if len(id) > shortLen {
id = id[:shortLen]
}
return id
return stringid.TruncateID(id)
}
// Ellipsis truncates a string to fit within maxDisplayWidth, and appends ellipsis (…).
+4 -4
View File
@@ -1,17 +1,17 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package formatter
import (
"bytes"
"fmt"
"io"
"strings"
"text/template"
"github.com/docker/cli/cli/command/formatter/tabwriter"
"github.com/docker/cli/templates"
"github.com/pkg/errors"
)
// Format keys used to specify certain kinds of output formats
@@ -76,7 +76,7 @@ func (c *Context) preFormat() {
func (c *Context) parseFormat() (*template.Template, error) {
tmpl, err := templates.Parse(c.finalFormat)
if err != nil {
return nil, errors.Wrap(err, "template parsing error")
return nil, fmt.Errorf("template parsing error: %w", err)
}
return tmpl, nil
}
@@ -100,7 +100,7 @@ func (c *Context) postFormat(tmpl *template.Template, subContext SubContext) {
func (c *Context) contextFormat(tmpl *template.Template, subContext SubContext) error {
if err := tmpl.Execute(c.buffer, subContext); err != nil {
return errors.Wrap(err, "template parsing error")
return fmt.Errorf("template parsing error: %w", err)
}
if c.Format.IsTable() && c.header != nil {
c.header = subContext.FullHeader()
+1 -11
View File
@@ -5,8 +5,8 @@ import (
"time"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/image"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/image"
)
const (
@@ -202,7 +202,6 @@ func newImageContext() *imageContext {
"CreatedAt": CreatedAtHeader,
"Size": SizeHeader,
"Containers": containersHeader,
"VirtualSize": SizeHeader, // Deprecated: VirtualSize is deprecated, and equivalent to Size.
"SharedSize": sharedSizeHeader,
"UniqueSize": uniqueSizeHeader,
}
@@ -257,15 +256,6 @@ func (c *imageContext) Containers() string {
return strconv.FormatInt(c.i.Containers, 10)
}
// VirtualSize shows the virtual size of the image and all of its parent
// images. Starting with docker 1.10, images are self-contained, and
// the VirtualSize is identical to Size.
//
// Deprecated: VirtualSize is deprecated, and equivalent to [imageContext.Size].
func (c *imageContext) VirtualSize() string {
return units.HumanSize(float64(c.i.Size))
}
func (c *imageContext) SharedSize() string {
if c.i.SharedSize == -1 {
return "N/A"
+7 -7
View File
@@ -1,14 +1,14 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package formatter
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"unicode"
"github.com/pkg/errors"
)
// MarshalJSON marshals x into json
@@ -25,14 +25,14 @@ func MarshalJSON(x any) ([]byte, error) {
func marshalMap(x any) (map[string]any, error) {
val := reflect.ValueOf(x)
if val.Kind() != reflect.Ptr {
return nil, errors.Errorf("expected a pointer to a struct, got %v", val.Kind())
return nil, fmt.Errorf("expected a pointer to a struct, got %v", val.Kind())
}
if val.IsNil() {
return nil, errors.Errorf("expected a pointer to a struct, got nil pointer")
return nil, errors.New("expected a pointer to a struct, got nil pointer")
}
valElem := val.Elem()
if valElem.Kind() != reflect.Struct {
return nil, errors.Errorf("expected a pointer to a struct, got a pointer to %v", valElem.Kind())
return nil, fmt.Errorf("expected a pointer to a struct, got a pointer to %v", valElem.Kind())
}
typ := val.Type()
m := make(map[string]any)
@@ -54,7 +54,7 @@ var unmarshallableNames = map[string]struct{}{"FullHeader": {}}
// It returns ("", nil, nil) for valid but non-marshallable parameter. (e.g. "unexportedFunc()")
func marshalForMethod(typ reflect.Method, val reflect.Value) (string, any, error) {
if val.Kind() != reflect.Func {
return "", nil, errors.Errorf("expected func, got %v", val.Kind())
return "", nil, fmt.Errorf("expected func, got %v", val.Kind())
}
name, numIn, numOut := typ.Name, val.Type().NumIn(), val.Type().NumOut()
_, blackListed := unmarshallableNames[name]
+3 -3
View File
@@ -5,8 +5,8 @@ import (
"strconv"
"strings"
"github.com/docker/docker/api/types/volume"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/volume"
)
const (
@@ -40,10 +40,10 @@ func NewVolumeFormat(source string, quiet bool) Format {
}
// VolumeWrite writes formatted volumes using the Context
func VolumeWrite(ctx Context, volumes []*volume.Volume) error {
func VolumeWrite(ctx Context, volumes []volume.Volume) error {
render := func(format func(subContext SubContext) error) error {
for _, vol := range volumes {
if err := format(&volumeContext{v: *vol}); err != nil {
if err := format(&volumeContext{v: vol}); err != nil {
return err
}
}
+7 -37
View File
@@ -2,6 +2,7 @@ package command
import (
"context"
"errors"
"fmt"
"os"
"runtime"
@@ -15,9 +16,9 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/prompt"
"github.com/docker/cli/internal/tui"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/moby/moby/api/pkg/authconfig"
registrytypes "github.com/moby/moby/api/types/registry"
"github.com/morikuni/aec"
"github.com/pkg/errors"
)
const (
@@ -34,42 +35,11 @@ const (
// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#IndexServer
const authConfigKey = "https://index.docker.io/v1/"
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
// for the given command to prompt the user for username and password.
//
// Deprecated: this function is no longer used and will be removed in the next release.
func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) registrytypes.RequestAuthConfig {
configKey := getAuthConfigKey(index.Name)
isDefaultRegistry := configKey == authConfigKey || index.Official
return func(ctx context.Context) (string, error) {
_, _ = fmt.Fprintf(cli.Out(), "\nLogin prior to %s:\n", cmdName)
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, configKey, isDefaultRegistry)
if err != nil {
_, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", configKey, err)
}
select {
case <-ctx.Done():
return "", ctx.Err()
default:
}
authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, configKey)
if err != nil {
return "", err
}
return registrytypes.EncodeAuthConfig(authConfig)
}
}
// ResolveAuthConfig returns auth-config for the given registry from the
// credential-store. It returns an empty AuthConfig if no credentials were
// found.
//
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
// store, instead of looking up credentials from a map.
//
// [registry.ResolveAuthConfig]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#ResolveAuthConfig
// Deprecated: this function is no longer used, and will be removed in the next release.
func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
configKey := index.Name
if index.Official {
@@ -170,7 +140,7 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
argUser = defaultUsername
}
if argUser == "" {
return registrytypes.AuthConfig{}, errors.Errorf("Error: Non-null Username Required")
return registrytypes.AuthConfig{}, errors.New("error: username is required")
}
}
@@ -202,7 +172,7 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
}
_, _ = fmt.Fprintln(cli.Out())
if argPassword == "" {
return registrytypes.AuthConfig{}, errors.Errorf("Error: Password Required")
return registrytypes.AuthConfig{}, errors.New("error: password is required")
}
}
@@ -230,7 +200,7 @@ func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (strin
return "", err
}
encodedAuth, err := registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{
encodedAuth, err := authconfig.Encode(registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
+17 -3
View File
@@ -11,11 +11,12 @@ import (
"github.com/google/uuid"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/metric"
otelsdk "go.opentelemetry.io/otel/sdk"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/trace"
)
@@ -146,7 +147,7 @@ func defaultResourceOptions() []resource.Option {
semconv.ServiceInstanceID(uuid.NewString()),
),
resource.WithFromEnv(),
resource.WithTelemetrySDK(),
resource.WithDetectors(telemetrySDK{}),
}
}
@@ -157,7 +158,10 @@ func (r *telemetryResource) AppendOptions(opts ...resource.Option) {
r.opts = append(r.opts, opts...)
}
type serviceNameDetector struct{}
type (
serviceNameDetector struct{}
telemetrySDK struct{}
)
func (serviceNameDetector) Detect(ctx context.Context) (*resource.Resource, error) {
return resource.StringDetector(
@@ -169,6 +173,16 @@ func (serviceNameDetector) Detect(ctx context.Context) (*resource.Resource, erro
).Detect(ctx)
}
// Detect returns a *Resource that describes the OpenTelemetry SDK used.
func (telemetrySDK) Detect(context.Context) (*resource.Resource, error) {
return resource.NewWithAttributes(
semconv.SchemaURL,
semconv.TelemetrySDKName("opentelemetry"),
semconv.TelemetrySDKLanguageGo,
semconv.TelemetrySDKVersion(otelsdk.Version()),
), nil
}
// cliReader is an implementation of Reader that will automatically
// report to a designated Exporter when Shutdown is called.
type cliReader struct {
+3 -4
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package command
@@ -14,7 +14,6 @@ import (
"strings"
"unicode"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
@@ -48,7 +47,7 @@ func dockerExporterOTLPEndpoint(cli Cli) (endpoint string, secure bool) {
if otelCfg != nil {
otelMap, ok := otelCfg.(map[string]any)
if !ok {
otel.Handle(errors.Errorf(
otel.Handle(fmt.Errorf(
"unexpected type for field %q: %T (expected: %T)",
otelContextFieldName,
otelCfg,
@@ -76,7 +75,7 @@ func dockerExporterOTLPEndpoint(cli Cli) (endpoint string, secure bool) {
// We pretend we're the same as the environment reader.
u, err := url.Parse(endpoint)
if err != nil {
otel.Handle(errors.Errorf("docker otel endpoint is invalid: %s", err))
otel.Handle(fmt.Errorf("docker otel endpoint is invalid: %s", err))
return "", false
}
+1 -1
View File
@@ -2,12 +2,12 @@ package command
import (
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/docker/cli/cli/version"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
+13 -57
View File
@@ -1,74 +1,30 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package command
import (
"context"
"io"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/prompt"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
"github.com/moby/moby/client"
)
// ErrPromptTerminated is returned if the user terminated the prompt.
//
// Deprecated: this error is for internal use and will be removed in the next release.
const ErrPromptTerminated = prompt.ErrTerminated
// DisableInputEcho disables input echo on the provided streams.In.
// This is useful when the user provides sensitive information like passwords.
// The function returns a restore function that should be called to restore the
// terminal state.
//
// Deprecated: this function is for internal use and will be removed in the next release.
func DisableInputEcho(ins *streams.In) (restore func() error, err error) {
return prompt.DisableInputEcho(ins)
}
// PromptForInput requests input from the user.
//
// If the user terminates the CLI with SIGINT or SIGTERM while the prompt is
// active, the prompt will return an empty string ("") with an ErrPromptTerminated error.
// When the prompt returns an error, the caller should propagate the error up
// the stack and close the io.Reader used for the prompt which will prevent the
// background goroutine from blocking indefinitely.
//
// Deprecated: this function is for internal use and will be removed in the next release.
func PromptForInput(ctx context.Context, in io.Reader, out io.Writer, message string) (string, error) {
return prompt.ReadInput(ctx, in, out, message)
}
// PromptForConfirmation requests and checks confirmation from the user.
// This will display the provided message followed by ' [y/N] '. If the user
// input 'y' or 'Y' it returns true otherwise false. If no message is provided,
// "Are you sure you want to proceed? [y/N] " will be used instead.
//
// If the user terminates the CLI with SIGINT or SIGTERM while the prompt is
// active, the prompt will return false with an ErrPromptTerminated error.
// When the prompt returns an error, the caller should propagate the error up
// the stack and close the io.Reader used for the prompt which will prevent the
// background goroutine from blocking indefinitely.
//
// Deprecated: this function is for internal use and will be removed in the next release.
func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, message string) (bool, error) {
return prompt.Confirm(ctx, ins, outs, message)
}
// PruneFilters merges prune filters specified in config.json with those specified
// as command-line flags.
// as command-line flags. It returns a deep copy of filters to prevent mutating
// the original.
//
// CLI label filters have precedence over those specified in config.json. If a
// label filter specified as flag conflicts with a label defined in config.json
// (i.e., "label=some-value" conflicts with "label!=some-value", and vice versa),
// then the filter defined in config.json is omitted.
func PruneFilters(dockerCLI config.Provider, pruneFilters filters.Args) filters.Args {
func PruneFilters(dockerCLI config.Provider, filters client.Filters) client.Filters {
pruneFilters := filters.Clone()
cfg := dockerCLI.ConfigFile()
if cfg == nil {
return pruneFilters
@@ -84,13 +40,13 @@ func PruneFilters(dockerCLI config.Provider, pruneFilters filters.Args) filters.
switch k {
case "label":
// "label != some-value" conflicts with "label = some-value"
if pruneFilters.ExactMatch("label!", v) {
if pruneFilters["label!"][v] {
continue
}
pruneFilters.Add(k, v)
case "label!":
// "label != some-value" conflicts with "label = some-value"
if pruneFilters.ExactMatch("label", v) {
if pruneFilters["label"][v] {
continue
}
pruneFilters.Add(k, v)
@@ -107,7 +63,7 @@ func ValidateOutputPath(path string) error {
dir := filepath.Dir(filepath.Clean(path))
if dir != "" && dir != "." {
if _, err := os.Stat(dir); os.IsNotExist(err) {
return errors.Errorf("invalid output path: directory %q does not exist", dir)
return fmt.Errorf("invalid output path: directory %q does not exist", dir)
}
}
// check whether `path` points to a regular file
@@ -122,7 +78,7 @@ func ValidateOutputPath(path string) error {
}
if err := ValidateOutputPathFileMode(fileInfo.Mode()); err != nil {
return errors.Wrapf(err, "invalid output path: %q must be a directory or a regular file", path)
return fmt.Errorf("invalid output path: %q must be a directory or a regular file: %w", path, err)
}
}
return nil
+4 -5
View File
@@ -13,7 +13,6 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/cli/cli/config/types"
"github.com/pkg/errors"
)
const (
@@ -101,7 +100,7 @@ func SetDir(dir string) {
func Path(p ...string) (string, error) {
path := filepath.Join(append([]string{Dir()}, p...)...)
if !strings.HasPrefix(path, Dir()+string(filepath.Separator)) {
return "", errors.Errorf("path %q is outside of root config directory %q", path, Dir())
return "", fmt.Errorf("path %q is outside of root config directory %q", path, Dir())
}
return path, nil
}
@@ -143,12 +142,12 @@ func load(configDir string) (*configfile.ConfigFile, error) {
return configFile, nil
}
// Any other error happening when failing to read the file must be returned.
return configFile, errors.Wrap(err, "loading config file")
return configFile, fmt.Errorf("loading config file: %w", err)
}
defer file.Close()
defer func() { _ = file.Close() }()
err = configFile.LoadFromReader(file)
if err != nil {
err = errors.Wrapf(err, "parsing config file (%s)", filename)
err = fmt.Errorf("parsing config file (%s): %w", filename, err)
}
return configFile, err
}
+5 -8
View File
@@ -3,6 +3,7 @@ package configfile
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"os"
@@ -12,7 +13,6 @@ import (
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/cli/cli/config/memorystore"
"github.com/docker/cli/cli/config/types"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -43,9 +43,6 @@ type ConfigFile struct {
Plugins map[string]map[string]string `json:"plugins,omitempty"`
Aliases map[string]string `json:"aliases,omitempty"`
Features map[string]string `json:"features,omitempty"`
// Deprecated: experimental CLI features are always enabled and this field is no longer used. Use [Features] instead for optional features. This field will be removed in a future release.
Experimental string `json:"experimental,omitempty"`
}
type configEnvAuth struct {
@@ -167,7 +164,7 @@ func (configFile *ConfigFile) SaveToWriter(writer io.Writer) error {
// Save encodes and writes out all the authorization information
func (configFile *ConfigFile) Save() (retErr error) {
if configFile.Filename == "" {
return errors.Errorf("Can't save config with empty filename")
return errors.New("can't save config with empty filename")
}
dir := filepath.Dir(configFile.Filename)
@@ -194,7 +191,7 @@ func (configFile *ConfigFile) Save() (retErr error) {
}
if err := temp.Close(); err != nil {
return errors.Wrap(err, "error closing temp file")
return fmt.Errorf("error closing temp file: %w", err)
}
// Handle situation where the configfile is a symlink, and allow for dangling symlinks
@@ -278,11 +275,11 @@ func decodeAuth(authStr string) (string, string, error) {
return "", "", err
}
if n > decLen {
return "", "", errors.Errorf("Something went wrong decoding auth config")
return "", "", errors.New("something went wrong decoding auth config")
}
userName, password, ok := strings.Cut(string(decoded), ":")
if !ok || userName == "" {
return "", "", errors.Errorf("Invalid auth configuration file")
return "", "", errors.New("invalid auth configuration file")
}
return userName, strings.Trim(password, "\x00"), nil
}
+2 -1
View File
@@ -1,4 +1,5 @@
//go:build go1.23
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.24
package memorystore
-5
View File
@@ -6,11 +6,6 @@ type AuthConfig struct {
Password string `json:"password,omitempty"`
Auth string `json:"auth,omitempty"`
// Email is an optional value associated with the username.
//
// Deprecated: This field is deprecated since docker 1.11 (API v1.23) and will be removed in the next release.
Email string `json:"email,omitempty"`
ServerAddress string `json:"serveraddress,omitempty"`
// IdentityToken is used to authenticate the user and get
@@ -233,11 +233,9 @@ func (c *commandConn) Close() error {
defer c.closing.Store(false)
if err := c.CloseRead(); err != nil {
logrus.Warnf("commandConn.Close: CloseRead: %v", err)
return err
}
if err := c.CloseWrite(); err != nil {
logrus.Warnf("commandConn.Close: CloseWrite: %v", err)
return err
}
+1 -1
View File
@@ -175,7 +175,7 @@ func quoteCommand(commandAndArgs ...string) (string, error) {
quotedCmd = a
continue
}
quotedCmd += " " + a
quotedCmd += " " + a //nolint:perfsprint // ignore "concat-loop"; no need to use a string-builder for this.
}
// each part is quoted appropriately, so now we'll have a full
// shell command to pass off to "ssh"
+5 -4
View File
@@ -4,6 +4,8 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"net"
"net/http"
"strings"
@@ -12,9 +14,8 @@ import (
"github.com/docker/cli/cli/connhelper"
"github.com/docker/cli/cli/context"
"github.com/docker/cli/cli/context/store"
"github.com/docker/docker/client"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
"github.com/moby/moby/client"
)
// EndpointMeta is a typed wrapper around a context-store generic endpoint describing
@@ -68,7 +69,7 @@ func (ep *Endpoint) tlsConfig() (*tls.Config, error) {
x509cert, err := tls.X509KeyPair(ep.TLSData.Cert, keyBytes)
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve context tls info")
return nil, fmt.Errorf("failed to retrieve context tls info: %w", err)
}
tlsOpts = append(tlsOpts, func(cfg *tls.Config) {
cfg.Certificates = []tls.Certificate{x509cert}
@@ -156,7 +157,7 @@ func EndpointFromContext(metadata store.Metadata) (EndpointMeta, error) {
}
typed, ok := ep.(EndpointMeta)
if !ok {
return EndpointMeta{}, errors.Errorf("endpoint %q is not of type EndpointMeta", DockerEndpoint)
return EndpointMeta{}, fmt.Errorf("endpoint %q is not of type EndpointMeta", DockerEndpoint)
}
return typed, nil
}
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package store
+34 -8
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package store
@@ -18,14 +18,9 @@ import (
"path/filepath"
"strings"
"github.com/docker/cli/internal/lazyregexp"
"github.com/opencontainers/go-digest"
)
const restrictedNamePattern = "^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$"
var restrictedNameRegEx = lazyregexp.New(restrictedNamePattern)
// Store provides a context store for easily remembering endpoints configuration
type Store interface {
Reader
@@ -225,12 +220,43 @@ func ValidateContextName(name string) error {
if name == "default" {
return errors.New(`"default" is a reserved context name`)
}
if !restrictedNameRegEx.MatchString(name) {
return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, restrictedNamePattern)
if !isValidName(name) {
return fmt.Errorf("context name %q is invalid, names are validated against regexp %q", name, validNameFormat)
}
return nil
}
// validNameFormat is used as part of errors for invalid context-names.
// We should consider making this less technical ("must start with "a-z",
// and only consist of alphanumeric characters and separators").
const validNameFormat = `^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$`
// isValidName checks if the context-name is valid ("^[a-zA-Z0-9][a-zA-Z0-9_.+-]+$").
//
// Names must start with an alphanumeric character (a-zA-Z0-9), followed by
// alphanumeric or separators ("_", ".", "+", "-").
func isValidName(s string) bool {
if len(s) < 2 || !isAlphaNum(s[0]) {
return false
}
for i := 1; i < len(s); i++ {
c := s[i]
if isAlphaNum(c) || c == '_' || c == '.' || c == '+' || c == '-' {
continue
}
return false
}
return true
}
func isAlphaNum(c byte) bool {
return (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9')
}
// Export exports an existing namespace into an opaque data stream
// This stream is actually a tarball containing context metadata and TLS materials, but it does
// not map 1:1 the layout of the context store (don't try to restore it manually without calling store.Import)
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package store
+3 -3
View File
@@ -1,10 +1,10 @@
package context
import (
"fmt"
"os"
"github.com/docker/cli/cli/context/store"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -45,14 +45,14 @@ func (data *TLSData) ToStoreTLSData() *store.EndpointTLSData {
func LoadTLSData(s store.Reader, contextName, endpointName string) (*TLSData, error) {
tlsFiles, err := s.ListTLSFiles(contextName)
if err != nil {
return nil, errors.Wrapf(err, "failed to retrieve TLS files for context %q", contextName)
return nil, fmt.Errorf("failed to retrieve TLS files for context %q: %w", contextName, err)
}
if epTLSFiles, ok := tlsFiles[endpointName]; ok {
var tlsData TLSData
for _, f := range epTLSFiles {
data, err := s.GetTLSData(contextName, endpointName, f)
if err != nil {
return nil, errors.Wrapf(err, "failed to retrieve TLS data (%s) for context %q", f, contextName)
return nil, fmt.Errorf("failed to retrieve TLS data (%s) for context %q: %w", f, contextName, err)
}
switch f {
case caKey:
+9 -41
View File
@@ -7,8 +7,8 @@ import (
"path/filepath"
"github.com/docker/cli/cli/config"
"github.com/docker/docker/client"
"github.com/docker/go-connections/tlsconfig"
"github.com/moby/moby/client"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
)
@@ -110,22 +110,20 @@ func (o *ClientOptions) InstallFlags(flags *pflag.FlagSet) {
if dockerCertPath == "" {
dockerCertPath = configDir
}
o.TLSOptions = &tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, DefaultCaFile),
CertFile: filepath.Join(dockerCertPath, DefaultCertFile),
KeyFile: filepath.Join(dockerCertPath, DefaultKeyFile),
}
flags.StringVar(&o.ConfigDir, "config", configDir, "Location of client config files")
flags.BoolVarP(&o.Debug, "debug", "D", false, "Enable debug mode")
flags.StringVarP(&o.LogLevel, "log-level", "l", "info", `Set the logging level ("debug", "info", "warn", "error", "fatal")`)
flags.BoolVar(&o.TLS, "tls", dockerTLS, "Use TLS; implied by --tlsverify")
flags.BoolVar(&o.TLSVerify, FlagTLSVerify, dockerTLSVerify, "Use TLS and verify the remote")
o.TLSOptions = &tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, DefaultCaFile),
CertFile: filepath.Join(dockerCertPath, DefaultCertFile),
KeyFile: filepath.Join(dockerCertPath, DefaultKeyFile),
}
tlsOptions := o.TLSOptions
flags.Var(&quotedString{&tlsOptions.CAFile}, "tlscacert", "Trust certs signed only by this CA")
flags.Var(&quotedString{&tlsOptions.CertFile}, "tlscert", "Path to TLS certificate file")
flags.Var(&quotedString{&tlsOptions.KeyFile}, "tlskey", "Path to TLS key file")
flags.StringVar(&o.TLSOptions.CAFile, "tlscacert", o.TLSOptions.CAFile, "Trust certs signed only by this CA")
flags.StringVar(&o.TLSOptions.CertFile, "tlscert", o.TLSOptions.CertFile, "Path to TLS certificate file")
flags.StringVar(&o.TLSOptions.KeyFile, "tlskey", o.TLSOptions.KeyFile, "Path to TLS key file")
// TODO(thaJeztah): show the default host.
// TODO(thaJeztah): this should be a string, not an "array" as we only allow a single host.
@@ -179,33 +177,3 @@ func SetLogLevel(logLevel string) {
logrus.SetLevel(logrus.InfoLevel)
}
}
type quotedString struct {
value *string
}
func (s *quotedString) Set(val string) error {
*s.value = trimQuotes(val)
return nil
}
func (*quotedString) Type() string {
return "string"
}
func (s *quotedString) String() string {
return *s.value
}
func trimQuotes(value string) string {
if len(value) < 2 {
return value
}
lastIndex := len(value) - 1
for _, char := range []byte{'\'', '"'} {
if value[0] == char && value[lastIndex] == char {
return value[1:lastIndex]
}
}
return value
}
+9 -8
View File
@@ -1,7 +1,8 @@
package cli
import (
"github.com/pkg/errors"
"fmt"
"github.com/spf13/cobra"
)
@@ -12,7 +13,7 @@ func NoArgs(cmd *cobra.Command, args []string) error {
}
if cmd.HasSubCommands() {
return errors.Errorf(
return fmt.Errorf(
"%[1]s: unknown command: %[2]s %[3]s\n\nUsage: %[4]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@@ -21,7 +22,7 @@ func NoArgs(cmd *cobra.Command, args []string) error {
)
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' accepts no arguments\n\nUsage: %[3]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@@ -35,7 +36,7 @@ func RequiresMinArgs(minArgs int) cobra.PositionalArgs {
if len(args) >= minArgs {
return nil
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' requires at least %[3]d %[4]s\n\nUsage: %[5]s\n\nSee '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@@ -52,8 +53,8 @@ func RequiresMaxArgs(maxArgs int) cobra.PositionalArgs {
if len(args) <= maxArgs {
return nil
}
return errors.Errorf(
"%[1]s: '%[2]s' requires at most %[3]d %[4]s\n\nUsage: %[5]s\n\nSRun '%[2]s --help' for more information",
return fmt.Errorf(
"%[1]s: '%[2]s' requires at most %[3]d %[4]s\n\nUsage: %[5]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
maxArgs,
@@ -69,7 +70,7 @@ func RequiresRangeArgs(minArgs int, maxArgs int) cobra.PositionalArgs {
if len(args) >= minArgs && len(args) <= maxArgs {
return nil
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' requires at least %[3]d and at most %[4]d %[5]s\n\nUsage: %[6]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@@ -87,7 +88,7 @@ func ExactArgs(number int) cobra.PositionalArgs {
if len(args) == number {
return nil
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' requires %[3]d %[4]s\n\nUsage: %[5]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package tui
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package tui
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package tui
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package tui
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package tui
+1 -1
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package tui
-14
View File
@@ -1,14 +0,0 @@
package opts
import (
"os"
"github.com/docker/cli/pkg/kvfile"
)
// ParseEnvFile reads a file with environment variables enumerated by lines
//
// Deprecated: use [kvfile.Parse] and pass [os.LookupEnv] to lookup env-vars from the current environment.
func ParseEnvFile(filename string) ([]string, error) {
return kvfile.Parse(filename, os.LookupEnv)
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"strconv"
"strings"
"github.com/docker/docker/api/types/container"
"github.com/moby/moby/api/types/container"
)
// GpuOpts is a Value type for parsing mounts
-17
View File
@@ -32,23 +32,6 @@ const (
hostGatewayName = "host-gateway"
)
// ValidateHost validates that the specified string is a valid host and returns it.
//
// Deprecated: this function is no longer used, and will be removed in the next release.
func ValidateHost(val string) (string, error) {
host := strings.TrimSpace(val)
// The empty string means default and is not handled by parseDockerDaemonHost
if host != "" {
_, err := parseDockerDaemonHost(host)
if err != nil {
return val, err
}
}
// Note: unlike most flag validators, we don't return the mutated value here
// we need to know what the user entered later (using ParseHost) to adjust for TLS
return val, nil
}
// ParseHost and set defaults for a Daemon host string
func ParseHost(defaultToTLS bool, val string) (string, error) {
host := strings.TrimSpace(val)
+4 -10
View File
@@ -9,9 +9,8 @@ import (
"strconv"
"strings"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
mounttypes "github.com/moby/moby/api/types/mount"
)
// MountOpt is a Value type for parsing mounts
@@ -88,8 +87,7 @@ func (m *MountOpt) Set(value string) error {
volumeOptions().NoCopy = true
continue
case "bind-nonrecursive":
bindOptions().NonRecursive = true
continue
return errors.New("bind-nonrecursive is deprecated, use bind-recursive=disabled instead")
default:
return fmt.Errorf("invalid field '%s' must be a key=value pair", field)
}
@@ -117,16 +115,12 @@ func (m *MountOpt) Set(value string) error {
case "bind-propagation":
bindOptions().Propagation = mounttypes.Propagation(strings.ToLower(val))
case "bind-nonrecursive":
bindOptions().NonRecursive, err = strconv.ParseBool(val)
if err != nil {
return fmt.Errorf("invalid value for %s: %s", key, val)
}
logrus.Warn("bind-nonrecursive is deprecated, use bind-recursive=disabled instead")
return errors.New("bind-nonrecursive is deprecated, use bind-recursive=disabled instead")
case "bind-recursive":
switch val {
case "enabled": // read-only mounts are recursively read-only if Engine >= v25 && kernel >= v5.12, otherwise writable
// NOP
case "disabled": // alias of bind-nonrecursive=true
case "disabled": // previously "bind-nonrecursive=true"
bindOptions().NonRecursive = true
case "writable": // conforms to the default read-only bind-mount of Docker v24; read-only mounts are recursively mounted but not recursively read-only
bindOptions().ReadOnlyNonRecursive = true
+17 -6
View File
@@ -4,6 +4,7 @@ import (
"encoding/csv"
"errors"
"fmt"
"net/netip"
"regexp"
"strconv"
"strings"
@@ -26,9 +27,9 @@ type NetworkAttachmentOpts struct {
Aliases []string
DriverOpts map[string]string
Links []string // TODO add support for links in the csv notation of `--network`
IPv4Address string
IPv6Address string
LinkLocalIPs []string
IPv4Address netip.Addr
IPv6Address netip.Addr
LinkLocalIPs []netip.Addr
MacAddress string
GwPriority int
}
@@ -70,13 +71,23 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo
case networkOptAlias:
netOpt.Aliases = append(netOpt.Aliases, val)
case networkOptIPv4Address:
netOpt.IPv4Address = val
netOpt.IPv4Address, err = netip.ParseAddr(val)
if err != nil {
return err
}
case networkOptIPv6Address:
netOpt.IPv6Address = val
netOpt.IPv6Address, err = netip.ParseAddr(val)
if err != nil {
return err
}
case networkOptMacAddress:
netOpt.MacAddress = val
case networkOptLinkLocalIP:
netOpt.LinkLocalIPs = append(netOpt.LinkLocalIPs, val)
a, err := netip.ParseAddr(val)
if err != nil {
return err
}
netOpt.LinkLocalIPs = append(netOpt.LinkLocalIPs, a)
case driverOpt:
key, val, err = parseDriverOpt(val)
if err != nil {
+14 -79
View File
@@ -1,6 +1,7 @@
package opts
import (
"encoding/json"
"errors"
"fmt"
"math/big"
@@ -9,8 +10,8 @@ import (
"strings"
"github.com/docker/cli/internal/lazyregexp"
"github.com/docker/docker/api/types/filters"
"github.com/docker/go-units"
"github.com/moby/moby/client"
)
var (
@@ -60,6 +61,8 @@ func (opts *ListOpts) Set(value string) error {
}
// Delete removes the specified element from the slice.
//
// Deprecated: this method is no longer used and will be removed in the next release.
func (opts *ListOpts) Delete(key string) {
for i, k := range *opts.values {
if k == key {
@@ -79,13 +82,6 @@ func (opts *ListOpts) GetMap() map[string]struct{} {
return ret
}
// GetAll returns the values of slice.
//
// Deprecated: use [ListOpts.GetSlice] instead. This method will be removed in a future release.
func (opts *ListOpts) GetAll() []string {
return *opts.values
}
// GetSlice returns the values of slice.
//
// It implements [cobra.SliceValue] to allow shell completion to be provided
@@ -132,43 +128,6 @@ func (opts *ListOpts) WithValidator(validator ValidatorFctType) *ListOpts {
return opts
}
// NamedOption is an interface that list and map options
// with names implement.
//
// Deprecated: NamedOption is no longer used and will be removed in the next release.
type NamedOption interface {
Name() string
}
// NamedListOpts is a ListOpts with a configuration name.
// This struct is useful to keep reference to the assigned
// field name in the internal configuration struct.
//
// Deprecated: NamedListOpts is no longer used and will be removed in the next release.
type NamedListOpts struct {
name string
ListOpts
}
var _ NamedOption = &NamedListOpts{}
// NewNamedListOptsRef creates a reference to a new NamedListOpts struct.
//
// Deprecated: NewNamedListOptsRef is no longer used and will be removed in the next release.
func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts {
return &NamedListOpts{
name: name,
ListOpts: *NewListOptsRef(values, validator),
}
}
// Name returns the name of the NamedListOpts in the configuration.
//
// Deprecated: NamedListOpts is no longer used and will be removed in the next release.
func (o *NamedListOpts) Name() string {
return o.name
}
// MapOpts holds a map of values and a validation function.
type MapOpts struct {
values map[string]string
@@ -215,35 +174,6 @@ func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts {
}
}
// NamedMapOpts is a MapOpts struct with a configuration name.
// This struct is useful to keep reference to the assigned
// field name in the internal configuration struct.
//
// Deprecated: NamedMapOpts is no longer used and will be removed in the next release.
type NamedMapOpts struct {
name string
MapOpts
}
var _ NamedOption = &NamedMapOpts{}
// NewNamedMapOpts creates a reference to a new NamedMapOpts struct.
//
// Deprecated: NamedMapOpts is no longer used and will be removed in the next release.
func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts {
return &NamedMapOpts{
name: name,
MapOpts: *NewMapOpts(values, validator),
}
}
// Name returns the name of the NamedMapOpts in the configuration.
//
// Deprecated: NamedMapOpts is no longer used and will be removed in the next release.
func (o *NamedMapOpts) Name() string {
return o.name
}
// ValidatorFctType defines a validator function that returns a validated string and/or an error.
type ValidatorFctType func(val string) (string, error)
@@ -264,6 +194,8 @@ func ValidateIPAddress(val string) (string, error) {
}
// ValidateMACAddress validates a MAC address.
//
// Deprecated: use [net.ParseMAC]. This function will be removed in the next release.
func ValidateMACAddress(val string) (string, error) {
_, err := net.ParseMAC(strings.TrimSpace(val))
if err != nil {
@@ -350,20 +282,23 @@ func ValidateSysctl(val string) (string, error) {
// FilterOpt is a flag type for validating filters
type FilterOpt struct {
filter filters.Args
filter client.Filters
}
// NewFilterOpt returns a new FilterOpt
func NewFilterOpt() FilterOpt {
return FilterOpt{filter: filters.NewArgs()}
return FilterOpt{filter: make(client.Filters)}
}
func (o *FilterOpt) String() string {
repr, err := filters.ToJSON(o.filter)
if o == nil || len(o.filter) == 0 {
return ""
}
repr, err := json.Marshal(o.filter)
if err != nil {
return "invalid filters"
}
return repr
return string(repr)
}
// Set sets the value of the opt by parsing the command line value
@@ -389,7 +324,7 @@ func (*FilterOpt) Type() string {
}
// Value returns the value of this option
func (o *FilterOpt) Value() filters.Args {
func (o *FilterOpt) Value() client.Filters {
return o.filter
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"strings"
"github.com/docker/cli/pkg/kvfile"
"github.com/docker/docker/api/types/container"
"github.com/moby/moby/api/types/container"
)
// ReadKVStrings reads a file of line terminated key=value pairs, and overrides any keys
-44
View File
@@ -1,44 +0,0 @@
package opts
// QuotedString is a string that may have extra quotes around the value. The
// quotes are stripped from the value.
//
// Deprecated: This option type is no longer used and will be removed in the next release.
type QuotedString struct {
value *string
}
// Set sets a new value
func (s *QuotedString) Set(val string) error {
*s.value = trimQuotes(val)
return nil
}
// Type returns the type of the value
func (*QuotedString) Type() string {
return "string"
}
func (s *QuotedString) String() string {
return *s.value
}
func trimQuotes(value string) string {
if len(value) < 2 {
return value
}
lastIndex := len(value) - 1
for _, char := range []byte{'\'', '"'} {
if value[0] == char && value[lastIndex] == char {
return value[1:lastIndex]
}
}
return value
}
// NewQuotedString returns a new quoted string option
//
// Deprecated: This option type is no longer used and will be removed in the next release.
func NewQuotedString(value *string) *QuotedString {
return &QuotedString{value: value}
}
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"strconv"
"strings"
"github.com/docker/docker/api/types/blkiodev"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/blkiodev"
)
// ValidatorThrottleFctType defines a validator function that returns a validated struct and/or an error.
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"fmt"
"sort"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-units"
"github.com/moby/moby/api/types/container"
)
// UlimitOpt defines a map of Ulimits
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"strconv"
"strings"
"github.com/docker/docker/api/types/blkiodev"
"github.com/moby/moby/api/types/blkiodev"
)
// ValidatorWeightFctType defines a validator function that returns a validated struct and/or an error.
+15 -21
View File
@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
//go:build go1.24
package templates
@@ -13,18 +13,7 @@ import (
// basicFunctions are the set of initial
// functions provided to every template.
var basicFunctions = template.FuncMap{
"json": func(v any) string {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(v)
if err != nil {
panic(err)
}
// Remove the trailing new line added by the encoder
return strings.TrimSpace(buf.String())
},
"json": formatJSON,
"split": strings.Split,
"join": strings.Join,
"title": strings.Title, //nolint:nolintlint,staticcheck // strings.Title is deprecated, but we only use it for ASCII, so replacing with golang.org/x/text is out of scope
@@ -80,14 +69,6 @@ func New(tag string) *template.Template {
return template.New(tag).Funcs(basicFunctions)
}
// NewParse creates a new tagged template with the basic functions
// and parses the given format.
//
// Deprecated: this function is unused and will be removed in the next release. Use [New] if you need to set a tag, or [Parse] instead.
func NewParse(tag, format string) (*template.Template, error) {
return template.New(tag).Funcs(basicFunctions).Parse(format)
}
// padWithSpace adds whitespace to the input if the input is non-empty
func padWithSpace(source string, prefix, suffix int) string {
if source == "" {
@@ -103,3 +84,16 @@ func truncateWithLength(source string, length int) string {
}
return source[:length]
}
func formatJSON(v any) string {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(v)
if err != nil {
panic(err)
}
// Remove the trailing new line added by the encoder
return strings.TrimSpace(buf.String())
}
-42
View File
@@ -1,42 +0,0 @@
# Working on the Engine API
The Engine API is an HTTP API used by the command-line client to communicate with the daemon. It can also be used by third-party software to control the daemon.
It consists of various components in this repository:
- `api/swagger.yaml` A Swagger definition of the API.
- `api/types/` Types shared by both the client and server, representing various objects, options, responses, etc. Most are written manually, but some are automatically generated from the Swagger definition. See [#27919](https://github.com/docker/docker/issues/27919) for progress on this.
- `cli/` The command-line client.
- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs.
- `daemon/` The daemon, which serves the API.
## Swagger definition
The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
1. Automatically generate documentation.
2. Automatically generate the Go server and client. (A work-in-progress.)
3. Provide a machine readable version of the API for introspecting what it can do, automatically generating clients for other languages, etc.
## Updating the API documentation
The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, edit this file to represent the change in the documentation.
The file is split into two main sections:
- `definitions`, which defines re-usable objects used in requests and responses
- `paths`, which defines the API endpoints (and some inline objects which don't need to be reusable)
To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section.
There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919).
`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful when making edits to ensure you are doing the right thing.
## Viewing the API documentation
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
Run `make swagger-docs` and a preview will be running at `http://localhost:9000`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).
-20
View File
@@ -1,20 +0,0 @@
package api
// Common constants for daemon and client.
const (
// DefaultVersion of the current REST API.
DefaultVersion = "1.51"
// MinSupportedAPIVersion is the minimum API version that can be supported
// by the API server, specified as "major.minor". Note that the daemon
// may be configured with a different minimum API version, as returned
// in [github.com/docker/docker/api/types.Version.MinAPIVersion].
//
// API requests for API versions lower than the configured version produce
// an error.
MinSupportedAPIVersion = "1.24"
// NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used.
NoBaseImageSpecifier = "scratch"
)
-12
View File
@@ -1,12 +0,0 @@
layout:
models:
- name: definition
source: asset:model
target: "{{ joinFilePath .Target .ModelPackage }}"
file_name: "{{ (snakize (pascalize .Name)) }}.go"
operations:
- name: handler
source: asset:serverOperation
target: "{{ joinFilePath .Target .APIPackage .Package }}"
file_name: "{{ (snakize (pascalize .Name)) }}.go"
-13387
View File
File diff suppressed because it is too large Load Diff
-10
View File
@@ -1,10 +0,0 @@
package build
// CacheDiskUsage contains disk usage for the build cache.
//
// Deprecated: this type is no longer used and will be removed in the next release.
type CacheDiskUsage struct {
TotalSize int64
Reclaimable int64
Items []*CacheRecord
}
-19
View File
@@ -1,19 +0,0 @@
package checkpoint
// CreateOptions holds parameters to create a checkpoint from a container.
type CreateOptions struct {
CheckpointID string
CheckpointDir string
Exit bool
}
// ListOptions holds parameters to list checkpoints for a container.
type ListOptions struct {
CheckpointDir string
}
// DeleteOptions holds parameters to delete a checkpoint from a container.
type DeleteOptions struct {
CheckpointID string
CheckpointDir string
}
-85
View File
@@ -1,85 +0,0 @@
package types
import (
"bufio"
"context"
"net"
)
// NewHijackedResponse initializes a [HijackedResponse] type.
func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse {
return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType}
}
// HijackedResponse holds connection information for a hijacked request.
type HijackedResponse struct {
mediaType string
Conn net.Conn
Reader *bufio.Reader
}
// Close closes the hijacked connection and reader.
func (h *HijackedResponse) Close() {
h.Conn.Close()
}
// MediaType let client know if HijackedResponse hold a raw or multiplexed stream.
// returns false if HTTP Content-Type is not relevant, and container must be inspected
func (h *HijackedResponse) MediaType() (string, bool) {
if h.mediaType == "" {
return "", false
}
return h.mediaType, true
}
// CloseWriter is an interface that implements structs
// that close input streams to prevent from writing.
type CloseWriter interface {
CloseWrite() error
}
// CloseWrite closes a readWriter for writing.
func (h *HijackedResponse) CloseWrite() error {
if conn, ok := h.Conn.(CloseWriter); ok {
return conn.CloseWrite()
}
return nil
}
// PluginRemoveOptions holds parameters to remove plugins.
type PluginRemoveOptions struct {
Force bool
}
// PluginEnableOptions holds parameters to enable plugins.
type PluginEnableOptions struct {
Timeout int
}
// PluginDisableOptions holds parameters to disable plugins.
type PluginDisableOptions struct {
Force bool
}
// PluginInstallOptions holds parameters to install a plugin.
type PluginInstallOptions struct {
Disabled bool
AcceptAllPermissions bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
RemoteRef string // RemoteRef is the plugin name on the registry
// PrivilegeFunc is a function that clients can supply to retry operations
// after getting an authorization error. This function returns the registry
// authentication header value in base64 encoded format, or an error if the
// privilege request fails.
//
// For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig].
PrivilegeFunc func(context.Context) (string, error)
AcceptPermissionsFunc func(context.Context, PluginPrivileges) (bool, error)
Args []string
}
// PluginCreateOptions hold all options to plugin create.
type PluginCreateOptions struct {
RepoName string
}
-10
View File
@@ -1,10 +0,0 @@
package container
// DiskUsage contains disk usage for containers.
//
// Deprecated: this type is no longer used and will be removed in the next release.
type DiskUsage struct {
TotalSize int64
Reclaimable int64
Items []*Summary
}
-53
View File
@@ -1,53 +0,0 @@
package container
import "github.com/docker/docker/api/types/common"
// ExecCreateResponse is the response for a successful exec-create request.
// It holds the ID of the exec that was created.
//
// TODO(thaJeztah): make this a distinct type.
type ExecCreateResponse = common.IDResponse
// ExecOptions is a small subset of the Config struct that holds the configuration
// for the exec feature of docker.
type ExecOptions struct {
User string // User that will run the command
Privileged bool // Is the container in privileged mode
Tty bool // Attach standard streams to a tty.
ConsoleSize *[2]uint `json:",omitempty"` // Initial console size [height, width]
AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStderr bool // Attach the standard error
AttachStdout bool // Attach the standard output
DetachKeys string // Escape keys for detach
Env []string // Environment variables
WorkingDir string // Working directory
Cmd []string // Execution commands and args
// Deprecated: the Detach field is not used, and will be removed in a future release.
Detach bool
}
// ExecStartOptions is a temp struct used by execStart
// Config fields is part of ExecConfig in runconfig package
type ExecStartOptions struct {
// ExecStart will first check if it's detached
Detach bool
// Check if there's a tty
Tty bool
// Terminal size [height, width], unused if Tty == false
ConsoleSize *[2]uint `json:",omitempty"`
}
// ExecAttachOptions is a temp struct used by execAttach.
//
// TODO(thaJeztah): make this a separate type; ContainerExecAttach does not use the Detach option, and cannot run detached.
type ExecAttachOptions = ExecStartOptions
// ExecInspect holds information returned by exec inspect.
type ExecInspect struct {
ExecID string `json:"ID"`
ContainerID string
Running bool
ExitCode int
Pid int
}
@@ -1,85 +0,0 @@
package container
import (
"github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
)
// NetworkSettings exposes the network settings in the api
type NetworkSettings struct {
NetworkSettingsBase
DefaultNetworkSettings
Networks map[string]*network.EndpointSettings
}
// NetworkSettingsBase holds networking state for a container when inspecting it.
//
// Deprecated: Most fields in NetworkSettingsBase are deprecated. Fields which aren't deprecated will move to
// NetworkSettings in v29.0, and this struct will be removed.
type NetworkSettingsBase struct {
Bridge string // Deprecated: This field is only set when the daemon is started with the --bridge flag specified.
SandboxID string // SandboxID uniquely represents a container's network stack
SandboxKey string // SandboxKey identifies the sandbox
Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port
// HairpinMode specifies if hairpin NAT should be enabled on the virtual interface
//
// Deprecated: This field is never set and will be removed in a future release.
HairpinMode bool
// LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix
//
// Deprecated: This field is never set and will be removed in a future release.
LinkLocalIPv6Address string
// LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address
//
// Deprecated: This field is never set and will be removed in a future release.
LinkLocalIPv6PrefixLen int
SecondaryIPAddresses []network.Address // Deprecated: This field is never set and will be removed in a future release.
SecondaryIPv6Addresses []network.Address // Deprecated: This field is never set and will be removed in a future release.
}
// DefaultNetworkSettings holds the networking state for the default bridge, if the container is connected to that
// network.
//
// Deprecated: this struct is deprecated since Docker v1.11 and will be removed in v29. You should look for the default
// network in NetworkSettings.Networks instead.
type DefaultNetworkSettings struct {
// EndpointID uniquely represents a service endpoint in a Sandbox
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
EndpointID string
// Gateway holds the gateway address for the network
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
Gateway string
// GlobalIPv6Address holds network's global IPv6 address
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
GlobalIPv6Address string
// GlobalIPv6PrefixLen represents mask length of network's global IPv6 address
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
GlobalIPv6PrefixLen int
// IPAddress holds the IPv4 address for the network
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
IPAddress string
// IPPrefixLen represents mask length of network's IPv4 address
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
IPPrefixLen int
// IPv6Gateway holds gateway address specific for IPv6
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
IPv6Gateway string
// MacAddress holds the MAC address for the network
//
// Deprecated: This field will be removed in v29. You should look for the default network in NetworkSettings.Networks instead.
MacAddress string
}
// NetworkSettingsSummary provides a summary of container's networks
// in /containers/json
type NetworkSettingsSummary struct {
Networks map[string]*network.EndpointSettings
}
-67
View File
@@ -1,67 +0,0 @@
package container
import "github.com/docker/docker/api/types/filters"
// ResizeOptions holds parameters to resize a TTY.
// It can be used to resize container TTYs and
// exec process TTYs too.
type ResizeOptions struct {
Height uint
Width uint
}
// AttachOptions holds parameters to attach to a container.
type AttachOptions struct {
Stream bool
Stdin bool
Stdout bool
Stderr bool
DetachKeys string
Logs bool
}
// CommitOptions holds parameters to commit changes into a container.
type CommitOptions struct {
Reference string
Comment string
Author string
Changes []string
Pause bool
Config *Config
}
// RemoveOptions holds parameters to remove containers.
type RemoveOptions struct {
RemoveVolumes bool
RemoveLinks bool
Force bool
}
// StartOptions holds parameters to start containers.
type StartOptions struct {
CheckpointID string
CheckpointDir string
}
// ListOptions holds parameters to list containers with.
type ListOptions struct {
Size bool
All bool
Latest bool
Since string
Before string
Limit int
Filters filters.Args
}
// LogsOptions holds parameters to filter logs with.
type LogsOptions struct {
ShowStdout bool
ShowStderr bool
Since string
Until string
Timestamps bool
Follow bool
Tail string
Details bool
}
-24
View File
@@ -1,24 +0,0 @@
package filters
import "fmt"
// invalidFilter indicates that the provided filter or its value is invalid
type invalidFilter struct {
Filter string
Value []string
}
func (e invalidFilter) Error() string {
msg := "invalid filter"
if e.Filter != "" {
msg += " '" + e.Filter
if e.Value != nil {
msg = fmt.Sprintf("%s=%s", msg, e.Value)
}
msg += "'"
}
return msg
}
// InvalidParameter marks this error as ErrInvalidParameter
func (e invalidFilter) InvalidParameter() {}
@@ -1,61 +0,0 @@
package filters
import (
"encoding/json"
"github.com/docker/docker/api/types/versions"
)
// ToParamWithVersion encodes Args as a JSON string. If version is less than 1.22
// then the encoded format will use an older legacy format where the values are a
// list of strings, instead of a set.
//
// Deprecated: do not use in any new code; use ToJSON instead
func ToParamWithVersion(version string, a Args) (string, error) {
out, err := ToJSON(a)
if out == "" || err != nil {
return "", nil
}
if version != "" && versions.LessThan(version, "1.22") {
return encodeLegacyFilters(out)
}
return out, nil
}
// encodeLegacyFilters encodes Args in the legacy format as used in API v1.21 and older.
// where values are a list of strings, instead of a set.
//
// Don't use in any new code; use [filters.ToJSON]] instead.
func encodeLegacyFilters(currentFormat string) (string, error) {
// The Args.fields field is not exported, but used to marshal JSON,
// so we'll marshal to the new format, then unmarshal to get the
// fields, and marshal again.
//
// This is far from optimal, but this code is only used for deprecated
// API versions, so should not be hit commonly.
var argsFields map[string]map[string]bool
err := json.Unmarshal([]byte(currentFormat), &argsFields)
if err != nil {
return "", err
}
buf, err := json.Marshal(convertArgsToSlice(argsFields))
if err != nil {
return "", err
}
return string(buf), nil
}
func convertArgsToSlice(f map[string]map[string]bool) map[string][]string {
m := map[string][]string{}
for k, v := range f {
values := []string{}
for kk := range v {
if v[kk] {
values = append(values, kk)
}
}
m[k] = values
}
return m
}
-302
View File
@@ -1,302 +0,0 @@
/*
Package filters provides tools for encoding a mapping of keys to a set of
multiple values.
*/
package filters
import (
"encoding/json"
"regexp"
"strings"
)
// Args stores a mapping of keys to a set of multiple values.
type Args struct {
fields map[string]map[string]bool
}
// KeyValuePair are used to initialize a new Args
type KeyValuePair struct {
Key string
Value string
}
// Arg creates a new KeyValuePair for initializing Args
func Arg(key, value string) KeyValuePair {
return KeyValuePair{Key: key, Value: value}
}
// NewArgs returns a new Args populated with the initial args
func NewArgs(initialArgs ...KeyValuePair) Args {
args := Args{fields: map[string]map[string]bool{}}
for _, arg := range initialArgs {
args.Add(arg.Key, arg.Value)
}
return args
}
// Keys returns all the keys in list of Args
func (args Args) Keys() []string {
keys := make([]string, 0, len(args.fields))
for k := range args.fields {
keys = append(keys, k)
}
return keys
}
// MarshalJSON returns a JSON byte representation of the Args
func (args Args) MarshalJSON() ([]byte, error) {
if len(args.fields) == 0 {
return []byte("{}"), nil
}
return json.Marshal(args.fields)
}
// ToJSON returns the Args as a JSON encoded string
func ToJSON(a Args) (string, error) {
if a.Len() == 0 {
return "", nil
}
buf, err := json.Marshal(a)
return string(buf), err
}
// FromJSON decodes a JSON encoded string into Args
func FromJSON(p string) (Args, error) {
args := NewArgs()
if p == "" {
return args, nil
}
raw := []byte(p)
err := json.Unmarshal(raw, &args)
if err == nil {
return args, nil
}
// Fallback to parsing arguments in the legacy slice format
deprecated := map[string][]string{}
if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil {
return args, &invalidFilter{}
}
args.fields = deprecatedArgs(deprecated)
return args, nil
}
// UnmarshalJSON populates the Args from JSON encode bytes
func (args Args) UnmarshalJSON(raw []byte) error {
return json.Unmarshal(raw, &args.fields)
}
// Get returns the list of values associated with the key
func (args Args) Get(key string) []string {
values := args.fields[key]
if values == nil {
return make([]string, 0)
}
slice := make([]string, 0, len(values))
for key := range values {
slice = append(slice, key)
}
return slice
}
// Add a new value to the set of values
func (args Args) Add(key, value string) {
if _, ok := args.fields[key]; ok {
args.fields[key][value] = true
} else {
args.fields[key] = map[string]bool{value: true}
}
}
// Del removes a value from the set
func (args Args) Del(key, value string) {
if _, ok := args.fields[key]; ok {
delete(args.fields[key], value)
if len(args.fields[key]) == 0 {
delete(args.fields, key)
}
}
}
// Len returns the number of keys in the mapping
func (args Args) Len() int {
return len(args.fields)
}
// MatchKVList returns true if all the pairs in sources exist as key=value
// pairs in the mapping at key, or if there are no values at key.
func (args Args) MatchKVList(key string, sources map[string]string) bool {
fieldValues := args.fields[key]
// do not filter if there is no filter set or cannot determine filter
if len(fieldValues) == 0 {
return true
}
if len(sources) == 0 {
return false
}
for value := range fieldValues {
testK, testV, hasValue := strings.Cut(value, "=")
v, ok := sources[testK]
if !ok {
return false
}
if hasValue && testV != v {
return false
}
}
return true
}
// Match returns true if any of the values at key match the source string
func (args Args) Match(field, source string) bool {
if args.ExactMatch(field, source) {
return true
}
fieldValues := args.fields[field]
for name2match := range fieldValues {
match, err := regexp.MatchString(name2match, source)
if err != nil {
continue
}
if match {
return true
}
}
return false
}
// GetBoolOrDefault returns a boolean value of the key if the key is present
// and is interpretable as a boolean value. Otherwise the default value is returned.
// Error is not nil only if the filter values are not valid boolean or are conflicting.
func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
fieldValues, ok := args.fields[key]
if !ok {
return defaultValue, nil
}
if len(fieldValues) == 0 {
return defaultValue, &invalidFilter{key, nil}
}
isFalse := fieldValues["0"] || fieldValues["false"]
isTrue := fieldValues["1"] || fieldValues["true"]
if isFalse == isTrue {
// Either no or conflicting truthy/falsy value were provided
return defaultValue, &invalidFilter{key, args.Get(key)}
}
return isTrue, nil
}
// ExactMatch returns true if the source matches exactly one of the values.
func (args Args) ExactMatch(key, source string) bool {
fieldValues, ok := args.fields[key]
// do not filter if there is no filter set or cannot determine filter
if !ok || len(fieldValues) == 0 {
return true
}
// try to match full name value to avoid O(N) regular expression matching
return fieldValues[source]
}
// UniqueExactMatch returns true if there is only one value and the source
// matches exactly the value.
func (args Args) UniqueExactMatch(key, source string) bool {
fieldValues := args.fields[key]
// do not filter if there is no filter set or cannot determine filter
if len(fieldValues) == 0 {
return true
}
if len(args.fields[key]) != 1 {
return false
}
// try to match full name value to avoid O(N) regular expression matching
return fieldValues[source]
}
// FuzzyMatch returns true if the source matches exactly one value, or the
// source has one of the values as a prefix.
func (args Args) FuzzyMatch(key, source string) bool {
if args.ExactMatch(key, source) {
return true
}
fieldValues := args.fields[key]
for prefix := range fieldValues {
if strings.HasPrefix(source, prefix) {
return true
}
}
return false
}
// Contains returns true if the key exists in the mapping
func (args Args) Contains(field string) bool {
_, ok := args.fields[field]
return ok
}
// Validate compared the set of accepted keys against the keys in the mapping.
// An error is returned if any mapping keys are not in the accepted set.
func (args Args) Validate(accepted map[string]bool) error {
for name := range args.fields {
if !accepted[name] {
return &invalidFilter{name, nil}
}
}
return nil
}
// WalkValues iterates over the list of values for a key in the mapping and calls
// op() for each value. If op returns an error the iteration stops and the
// error is returned.
func (args Args) WalkValues(field string, op func(value string) error) error {
if _, ok := args.fields[field]; !ok {
return nil
}
for v := range args.fields[field] {
if err := op(v); err != nil {
return err
}
}
return nil
}
// Clone returns a copy of args.
func (args Args) Clone() (newArgs Args) {
newArgs.fields = make(map[string]map[string]bool, len(args.fields))
for k, m := range args.fields {
var mm map[string]bool
if m != nil {
mm = make(map[string]bool, len(m))
for kk, v := range m {
mm[kk] = v
}
}
newArgs.fields[k] = mm
}
return newArgs
}
func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
m := map[string]map[string]bool{}
for k, v := range d {
values := map[string]bool{}
for _, vv := range v {
values[vv] = true
}
m[k] = values
}
return m
}
-10
View File
@@ -1,10 +0,0 @@
package image
// DiskUsage contains disk usage for images.
//
// Deprecated: this type is no longer used and will be removed in the next release.
type DiskUsage struct {
TotalSize int64
Reclaimable int64
Items []*Summary
}
-47
View File
@@ -1,47 +0,0 @@
package image
import (
"io"
"time"
)
// Metadata contains engine-local data about the image.
type Metadata struct {
// LastTagTime is the date and time at which the image was last tagged.
LastTagTime time.Time `json:",omitempty"`
}
// PruneReport contains the response for Engine API:
// POST "/images/prune"
type PruneReport struct {
ImagesDeleted []DeleteResponse
SpaceReclaimed uint64
}
// LoadResponse returns information to the client about a load process.
//
// TODO(thaJeztah): remove this type, and just use an io.ReadCloser
//
// This type was added in https://github.com/moby/moby/pull/18878, related
// to https://github.com/moby/moby/issues/19177;
//
// Make docker load to output json when the response content type is json
// Swarm hijacks the response from docker load and returns JSON rather
// than plain text like the Engine does. This makes the API library to return
// information to figure that out.
//
// However the "load" endpoint unconditionally returns JSON;
// https://github.com/moby/moby/blob/7b9d2ef6e5518a3d3f3cc418459f8df786cfbbd1/api/server/router/image/image_routes.go#L248-L255
//
// PR https://github.com/moby/moby/pull/21959 made the response-type depend
// on whether "quiet" was set, but this logic got changed in a follow-up
// https://github.com/moby/moby/pull/25557, which made the JSON response-type
// unconditionally, but the output produced depend on whether"quiet" was set.
//
// We should deprecated the "quiet" option, as it's really a client
// responsibility.
type LoadResponse struct {
// Body must be closed to avoid a resource leak
Body io.ReadCloser
JSON bool
}
-124
View File
@@ -1,124 +0,0 @@
package image
import (
"context"
"io"
"github.com/docker/docker/api/types/filters"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImportSource holds source information for ImageImport
type ImportSource struct {
Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this.
SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute.
}
// ImportOptions holds information to import images from the client host.
type ImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
}
// CreateOptions holds information to create images.
type CreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
}
// PullOptions holds information to pull images.
type PullOptions struct {
All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
// PrivilegeFunc is a function that clients can supply to retry operations
// after getting an authorization error. This function returns the registry
// authentication header value in base64 encoded format, or an error if the
// privilege request fails.
//
// For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig].
PrivilegeFunc func(context.Context) (string, error)
Platform string
}
// PushOptions holds information to push images.
type PushOptions struct {
All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
// PrivilegeFunc is a function that clients can supply to retry operations
// after getting an authorization error. This function returns the registry
// authentication header value in base64 encoded format, or an error if the
// privilege request fails.
//
// For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig].
PrivilegeFunc func(context.Context) (string, error)
// Platform is an optional field that selects a specific platform to push
// when the image is a multi-platform image.
// Using this will only push a single platform-specific manifest.
Platform *ocispec.Platform `json:",omitempty"`
}
// ListOptions holds parameters to list images with.
type ListOptions struct {
// All controls whether all images in the graph are filtered, or just
// the heads.
All bool
// Filters is a JSON-encoded set of filter arguments.
Filters filters.Args
// SharedSize indicates whether the shared size of images should be computed.
SharedSize bool
// ContainerCount indicates whether container count should be computed.
//
// Deprecated: This field has been unused and is no longer required and will be removed in a future version.
ContainerCount bool
// Manifests indicates whether the image manifests should be returned.
Manifests bool
}
// RemoveOptions holds parameters to remove images.
type RemoveOptions struct {
Platforms []ocispec.Platform
Force bool
PruneChildren bool
}
// HistoryOptions holds parameters to get image history.
type HistoryOptions struct {
// Platform from the manifest list to use for history.
Platform *ocispec.Platform
}
// LoadOptions holds parameters to load images.
type LoadOptions struct {
// Quiet suppresses progress output
Quiet bool
// Platforms selects the platforms to load if the image is a
// multi-platform image and has multiple variants.
Platforms []ocispec.Platform
}
type InspectOptions struct {
// Manifests returns the image manifests.
Manifests bool
// Platform selects the specific platform of a multi-platform image to inspect.
//
// This option is only available for API version 1.49 and up.
Platform *ocispec.Platform
}
// SaveOptions holds parameters to save images.
type SaveOptions struct {
// Platforms selects the platforms to save if the image is a
// multi-platform image and has multiple variants.
Platforms []ocispec.Platform
}
-151
View File
@@ -1,151 +0,0 @@
package network
import (
"errors"
"fmt"
"net"
)
// EndpointSettings stores the network endpoint details
type EndpointSettings struct {
// Configurations
IPAMConfig *EndpointIPAMConfig
Links []string
Aliases []string // Aliases holds the list of extra, user-specified DNS names for this endpoint.
// MacAddress may be used to specify a MAC address when the container is created.
// Once the container is running, it becomes operational data (it may contain a
// generated address).
MacAddress string
DriverOpts map[string]string
// GwPriority determines which endpoint will provide the default gateway
// for the container. The endpoint with the highest priority will be used.
// If multiple endpoints have the same priority, they are lexicographically
// sorted based on their network name, and the one that sorts first is picked.
GwPriority int
// Operational data
NetworkID string
EndpointID string
Gateway string
IPAddress string
IPPrefixLen int
IPv6Gateway string
GlobalIPv6Address string
GlobalIPv6PrefixLen int
// DNSNames holds all the (non fully qualified) DNS names associated to this endpoint. First entry is used to
// generate PTR records.
DNSNames []string
}
// Copy makes a deep copy of `EndpointSettings`
func (es *EndpointSettings) Copy() *EndpointSettings {
epCopy := *es
if es.IPAMConfig != nil {
epCopy.IPAMConfig = es.IPAMConfig.Copy()
}
if es.Links != nil {
links := make([]string, 0, len(es.Links))
epCopy.Links = append(links, es.Links...)
}
if es.Aliases != nil {
aliases := make([]string, 0, len(es.Aliases))
epCopy.Aliases = append(aliases, es.Aliases...)
}
if len(es.DNSNames) > 0 {
epCopy.DNSNames = make([]string, len(es.DNSNames))
copy(epCopy.DNSNames, es.DNSNames)
}
return &epCopy
}
// EndpointIPAMConfig represents IPAM configurations for the endpoint
type EndpointIPAMConfig struct {
IPv4Address string `json:",omitempty"`
IPv6Address string `json:",omitempty"`
LinkLocalIPs []string `json:",omitempty"`
}
// Copy makes a copy of the endpoint ipam config
func (cfg *EndpointIPAMConfig) Copy() *EndpointIPAMConfig {
cfgCopy := *cfg
cfgCopy.LinkLocalIPs = make([]string, 0, len(cfg.LinkLocalIPs))
cfgCopy.LinkLocalIPs = append(cfgCopy.LinkLocalIPs, cfg.LinkLocalIPs...)
return &cfgCopy
}
// NetworkSubnet describes a user-defined subnet for a specific network. It's only used to validate if an
// EndpointIPAMConfig is valid for a specific network.
type NetworkSubnet interface {
// Contains checks whether the NetworkSubnet contains [addr].
Contains(addr net.IP) bool
// IsStatic checks whether the subnet was statically allocated (ie. user-defined).
IsStatic() bool
}
// IsInRange checks whether static IP addresses are valid in a specific network.
func (cfg *EndpointIPAMConfig) IsInRange(v4Subnets []NetworkSubnet, v6Subnets []NetworkSubnet) error {
var errs []error
if err := validateEndpointIPAddress(cfg.IPv4Address, v4Subnets); err != nil {
errs = append(errs, err)
}
if err := validateEndpointIPAddress(cfg.IPv6Address, v6Subnets); err != nil {
errs = append(errs, err)
}
return errJoin(errs...)
}
func validateEndpointIPAddress(epAddr string, ipamSubnets []NetworkSubnet) error {
if epAddr == "" {
return nil
}
var staticSubnet bool
parsedAddr := net.ParseIP(epAddr)
for _, subnet := range ipamSubnets {
if subnet.IsStatic() {
staticSubnet = true
if subnet.Contains(parsedAddr) {
return nil
}
}
}
if staticSubnet {
return fmt.Errorf("no configured subnet or ip-range contain the IP address %s", epAddr)
}
return errors.New("user specified IP address is supported only when connecting to networks with user configured subnets")
}
// Validate checks whether cfg is valid.
func (cfg *EndpointIPAMConfig) Validate() error {
if cfg == nil {
return nil
}
var errs []error
if cfg.IPv4Address != "" {
if addr := net.ParseIP(cfg.IPv4Address); addr == nil || addr.To4() == nil || addr.IsUnspecified() {
errs = append(errs, fmt.Errorf("invalid IPv4 address: %s", cfg.IPv4Address))
}
}
if cfg.IPv6Address != "" {
if addr := net.ParseIP(cfg.IPv6Address); addr == nil || addr.To4() != nil || addr.IsUnspecified() {
errs = append(errs, fmt.Errorf("invalid IPv6 address: %s", cfg.IPv6Address))
}
}
for _, addr := range cfg.LinkLocalIPs {
if parsed := net.ParseIP(addr); parsed == nil || parsed.IsUnspecified() {
errs = append(errs, fmt.Errorf("invalid link-local IP address: %s", addr))
}
}
return errJoin(errs...)
}
-173
View File
@@ -1,173 +0,0 @@
package network
import (
"errors"
"fmt"
"net/netip"
"strings"
)
// IPAM represents IP Address Management
type IPAM struct {
Driver string
Options map[string]string // Per network IPAM driver options
Config []IPAMConfig
}
// IPAMConfig represents IPAM configurations
type IPAMConfig struct {
Subnet string `json:",omitempty"`
IPRange string `json:",omitempty"`
Gateway string `json:",omitempty"`
AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
}
type ipFamily string
const (
ip4 ipFamily = "IPv4"
ip6 ipFamily = "IPv6"
)
// ValidateIPAM checks whether the network's IPAM passed as argument is valid. It returns a joinError of the list of
// errors found.
func ValidateIPAM(ipam *IPAM, enableIPv6 bool) error {
if ipam == nil {
return nil
}
var errs []error
for _, cfg := range ipam.Config {
subnet, err := netip.ParsePrefix(cfg.Subnet)
if err != nil {
errs = append(errs, fmt.Errorf("invalid subnet %s: invalid CIDR block notation", cfg.Subnet))
continue
}
subnetFamily := ip4
if subnet.Addr().Is6() {
subnetFamily = ip6
}
if !enableIPv6 && subnetFamily == ip6 {
continue
}
if subnet != subnet.Masked() {
errs = append(errs, fmt.Errorf("invalid subnet %s: it should be %s", subnet, subnet.Masked()))
}
if ipRangeErrs := validateIPRange(cfg.IPRange, subnet, subnetFamily); len(ipRangeErrs) > 0 {
errs = append(errs, ipRangeErrs...)
}
if err := validateAddress(cfg.Gateway, subnet, subnetFamily); err != nil {
errs = append(errs, fmt.Errorf("invalid gateway %s: %w", cfg.Gateway, err))
}
for auxName, aux := range cfg.AuxAddress {
if err := validateAddress(aux, subnet, subnetFamily); err != nil {
errs = append(errs, fmt.Errorf("invalid auxiliary address %s: %w", auxName, err))
}
}
}
if err := errJoin(errs...); err != nil {
return fmt.Errorf("invalid network config:\n%w", err)
}
return nil
}
func validateIPRange(ipRange string, subnet netip.Prefix, subnetFamily ipFamily) []error {
if ipRange == "" {
return nil
}
prefix, err := netip.ParsePrefix(ipRange)
if err != nil {
return []error{fmt.Errorf("invalid ip-range %s: invalid CIDR block notation", ipRange)}
}
family := ip4
if prefix.Addr().Is6() {
family = ip6
}
if family != subnetFamily {
return []error{fmt.Errorf("invalid ip-range %s: parent subnet is an %s block", ipRange, subnetFamily)}
}
var errs []error
if prefix.Bits() < subnet.Bits() {
errs = append(errs, fmt.Errorf("invalid ip-range %s: CIDR block is bigger than its parent subnet %s", ipRange, subnet))
}
if prefix != prefix.Masked() {
errs = append(errs, fmt.Errorf("invalid ip-range %s: it should be %s", prefix, prefix.Masked()))
}
if !subnet.Overlaps(prefix) {
errs = append(errs, fmt.Errorf("invalid ip-range %s: parent subnet %s doesn't contain ip-range", ipRange, subnet))
}
return errs
}
func validateAddress(address string, subnet netip.Prefix, subnetFamily ipFamily) error {
if address == "" {
return nil
}
addr, err := netip.ParseAddr(address)
if err != nil {
return errors.New("invalid address")
}
family := ip4
if addr.Is6() {
family = ip6
}
if family != subnetFamily {
return fmt.Errorf("parent subnet is an %s block", subnetFamily)
}
if !subnet.Contains(addr) {
return fmt.Errorf("parent subnet %s doesn't contain this address", subnet)
}
return nil
}
func errJoin(errs ...error) error {
n := 0
for _, err := range errs {
if err != nil {
n++
}
}
if n == 0 {
return nil
}
e := &joinError{
errs: make([]error, 0, n),
}
for _, err := range errs {
if err != nil {
e.errs = append(e.errs, err)
}
}
return e
}
type joinError struct {
errs []error
}
func (e *joinError) Error() string {
if len(e.errs) == 1 {
return strings.TrimSpace(e.errs[0].Error())
}
stringErrs := make([]string, 0, len(e.errs))
for _, subErr := range e.errs {
stringErrs = append(stringErrs, strings.ReplaceAll(subErr.Error(), "\n", "\n\t"))
}
return "* " + strings.Join(stringErrs, "\n* ")
}
func (e *joinError) Unwrap() []error {
return e.errs
}
-168
View File
@@ -1,168 +0,0 @@
package network
import (
"time"
"github.com/docker/docker/api/types/filters"
)
const (
// NetworkDefault is a platform-independent alias to choose the platform-specific default network stack.
NetworkDefault = "default"
// NetworkHost is the name of the predefined network used when the NetworkMode host is selected (only available on Linux)
NetworkHost = "host"
// NetworkNone is the name of the predefined network used when the NetworkMode none is selected (available on both Linux and Windows)
NetworkNone = "none"
// NetworkBridge is the name of the default network on Linux
NetworkBridge = "bridge"
// NetworkNat is the name of the default network on Windows
NetworkNat = "nat"
)
// CreateRequest is the request message sent to the server for network create call.
type CreateRequest struct {
CreateOptions
Name string // Name is the requested name of the network.
// Deprecated: CheckDuplicate is deprecated since API v1.44, but it defaults to true when sent by the client
// package to older daemons.
CheckDuplicate *bool `json:",omitempty"`
}
// CreateOptions holds options to create a network.
type CreateOptions struct {
Driver string // Driver is the driver-name used to create the network (e.g. `bridge`, `overlay`)
Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level).
EnableIPv4 *bool `json:",omitempty"` // EnableIPv4 represents whether to enable IPv4.
EnableIPv6 *bool `json:",omitempty"` // EnableIPv6 represents whether to enable IPv6.
IPAM *IPAM // IPAM is the network's IP Address Management.
Internal bool // Internal represents if the network is used internal only.
Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode.
Ingress bool // Ingress indicates the network is providing the routing-mesh for the swarm cluster.
ConfigOnly bool // ConfigOnly creates a config-only network. Config-only networks are place-holder networks for network configurations to be used by other networks. ConfigOnly networks cannot be used directly to run containers or services.
ConfigFrom *ConfigReference // ConfigFrom specifies the source which will provide the configuration for this network. The specified network must be a config-only network; see [CreateOptions.ConfigOnly].
Options map[string]string // Options specifies the network-specific options to use for when creating the network.
Labels map[string]string // Labels holds metadata specific to the network being created.
}
// ListOptions holds parameters to filter the list of networks with.
type ListOptions struct {
Filters filters.Args
}
// InspectOptions holds parameters to inspect network.
type InspectOptions struct {
Scope string
Verbose bool
}
// ConnectOptions represents the data to be used to connect a container to the
// network.
type ConnectOptions struct {
Container string
EndpointConfig *EndpointSettings `json:",omitempty"`
}
// DisconnectOptions represents the data to be used to disconnect a container
// from the network.
type DisconnectOptions struct {
Container string
Force bool
}
// Inspect is the body of the "get network" http response message.
type Inspect struct {
Name string // Name is the name of the network
ID string `json:"Id"` // ID uniquely identifies a network on a single machine
Created time.Time // Created is the time the network created
Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level)
Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`)
EnableIPv4 bool // EnableIPv4 represents whether IPv4 is enabled
EnableIPv6 bool // EnableIPv6 represents whether IPv6 is enabled
IPAM IPAM // IPAM is the network's IP Address Management
Internal bool // Internal represents if the network is used internal only
Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode.
Ingress bool // Ingress indicates the network is providing the routing-mesh for the swarm cluster.
ConfigFrom ConfigReference // ConfigFrom specifies the source which will provide the configuration for this network.
ConfigOnly bool // ConfigOnly networks are place-holder networks for network configurations to be used by other networks. ConfigOnly networks cannot be used directly to run containers or services.
Containers map[string]EndpointResource // Containers contains endpoints belonging to the network
Options map[string]string // Options holds the network specific options to use for when creating the network
Labels map[string]string // Labels holds metadata specific to the network being created
Peers []PeerInfo `json:",omitempty"` // List of peer nodes for an overlay network
Services map[string]ServiceInfo `json:",omitempty"`
}
// Summary is used as response when listing networks. It currently is an alias
// for [Inspect], but may diverge in the future, as not all information may
// be included when listing networks.
type Summary = Inspect
// Address represents an IP address
type Address struct {
Addr string
PrefixLen int
}
// PeerInfo represents one peer of an overlay network
type PeerInfo struct {
Name string
IP string
}
// Task carries the information about one backend task
type Task struct {
Name string
EndpointID string
EndpointIP string
Info map[string]string
}
// ServiceInfo represents service parameters with the list of service's tasks
type ServiceInfo struct {
VIP string
Ports []string
LocalLBIndex int
Tasks []Task
}
// EndpointResource contains network resources allocated and used for a
// container in a network.
type EndpointResource struct {
Name string
EndpointID string
MacAddress string
IPv4Address string
IPv6Address string
}
// NetworkingConfig represents the container's networking configuration for each of its interfaces
// Carries the networking configs specified in the `docker run` and `docker network connect` commands
type NetworkingConfig struct {
EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network
}
// ConfigReference specifies the source which provides a network's configuration
type ConfigReference struct {
Network string
}
var acceptedFilters = map[string]bool{
"dangling": true,
"driver": true,
"id": true,
"label": true,
"name": true,
"scope": true,
"type": true,
}
// ValidateFilters validates the list of filter args with the available filters.
func ValidateFilters(filter filters.Args) error {
return filter.Validate(acceptedFilters)
}
// PruneReport contains the response for Engine API:
// POST "/networks/prune"
type PruneReport struct {
NetworksDeleted []string
}
-21
View File
@@ -1,21 +0,0 @@
package types
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// PluginInterfaceType plugin interface type
// swagger:model PluginInterfaceType
type PluginInterfaceType struct {
// capability
// Required: true
Capability string `json:"Capability"`
// prefix
// Required: true
Prefix string `json:"Prefix"`
// version
// Required: true
Version string `json:"Version"`
}
-71
View File
@@ -1,71 +0,0 @@
package types
import (
"encoding/json"
"fmt"
"sort"
)
// PluginsListResponse contains the response for the Engine API
type PluginsListResponse []*Plugin
// UnmarshalJSON implements json.Unmarshaler for PluginInterfaceType
func (t *PluginInterfaceType) UnmarshalJSON(p []byte) error {
versionIndex := len(p)
prefixIndex := 0
if len(p) < 2 || p[0] != '"' || p[len(p)-1] != '"' {
return fmt.Errorf("%q is not a plugin interface type", p)
}
p = p[1 : len(p)-1]
loop:
for i, b := range p {
switch b {
case '.':
prefixIndex = i
case '/':
versionIndex = i
break loop
}
}
t.Prefix = string(p[:prefixIndex])
t.Capability = string(p[prefixIndex+1 : versionIndex])
if versionIndex < len(p) {
t.Version = string(p[versionIndex+1:])
}
return nil
}
// MarshalJSON implements json.Marshaler for PluginInterfaceType
func (t *PluginInterfaceType) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
// String implements fmt.Stringer for PluginInterfaceType
func (t PluginInterfaceType) String() string {
return fmt.Sprintf("%s.%s/%s", t.Prefix, t.Capability, t.Version)
}
// PluginPrivilege describes a permission the user has to accept
// upon installing a plugin.
type PluginPrivilege struct {
Name string
Description string
Value []string
}
// PluginPrivileges is a list of PluginPrivilege
type PluginPrivileges []PluginPrivilege
func (s PluginPrivileges) Len() int {
return len(s)
}
func (s PluginPrivileges) Less(i, j int) bool {
return s[i].Name < s[j].Name
}
func (s PluginPrivileges) Swap(i, j int) {
sort.Strings(s[i].Value)
sort.Strings(s[j].Value)
s[i], s[j] = s[j], s[i]
}
-112
View File
@@ -1,112 +0,0 @@
package registry
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"strings"
)
// AuthHeader is the name of the header used to send encoded registry
// authorization credentials for registry operations (push/pull).
const AuthHeader = "X-Registry-Auth"
// RequestAuthConfig is a function interface that clients can supply
// to retry operations after getting an authorization error.
//
// The function must return the [AuthHeader] value ([AuthConfig]), encoded
// in base64url format ([RFC4648, section 5]), which can be decoded by
// [DecodeAuthConfig].
//
// It must return an error if the privilege request fails.
//
// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5
type RequestAuthConfig func(context.Context) (string, error)
// AuthConfig contains authorization information for connecting to a Registry.
type AuthConfig struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Auth string `json:"auth,omitempty"`
// Email is an optional value associated with the username.
//
// Deprecated: This field is deprecated since docker 1.11 (API v1.23) and will be removed in the next release.
Email string `json:"email,omitempty"`
ServerAddress string `json:"serveraddress,omitempty"`
// IdentityToken is used to authenticate the user and get
// an access token for the registry.
IdentityToken string `json:"identitytoken,omitempty"`
// RegistryToken is a bearer token to be sent to a registry
RegistryToken string `json:"registrytoken,omitempty"`
}
// EncodeAuthConfig serializes the auth configuration as a base64url encoded
// ([RFC4648, section 5]) JSON string for sending through the X-Registry-Auth header.
//
// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5
func EncodeAuthConfig(authConfig AuthConfig) (string, error) {
buf, err := json.Marshal(authConfig)
if err != nil {
return "", errInvalidParameter{err}
}
return base64.URLEncoding.EncodeToString(buf), nil
}
// DecodeAuthConfig decodes base64url encoded ([RFC4648, section 5]) JSON
// authentication information as sent through the X-Registry-Auth header.
//
// This function always returns an [AuthConfig], even if an error occurs. It is up
// to the caller to decide if authentication is required, and if the error can
// be ignored.
//
// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5
func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) {
if authEncoded == "" {
return &AuthConfig{}, nil
}
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
return decodeAuthConfigFromReader(authJSON)
}
// DecodeAuthConfigBody decodes authentication information as sent as JSON in the
// body of a request. This function is to provide backward compatibility with old
// clients and API versions. Current clients and API versions expect authentication
// to be provided through the X-Registry-Auth header.
//
// Like [DecodeAuthConfig], this function always returns an [AuthConfig], even if an
// error occurs. It is up to the caller to decide if authentication is required,
// and if the error can be ignored.
//
// Deprecated: this function is no longer used and will be removed in the next release.
func DecodeAuthConfigBody(rdr io.ReadCloser) (*AuthConfig, error) {
return decodeAuthConfigFromReader(rdr)
}
func decodeAuthConfigFromReader(rdr io.Reader) (*AuthConfig, error) {
authConfig := &AuthConfig{}
if err := json.NewDecoder(rdr).Decode(authConfig); err != nil {
// always return an (empty) AuthConfig to increase compatibility with
// the existing API.
return &AuthConfig{}, invalid(err)
}
return authConfig, nil
}
func invalid(err error) error {
return errInvalidParameter{fmt.Errorf("invalid X-Registry-Auth header: %w", err)}
}
type errInvalidParameter struct{ error }
func (errInvalidParameter) InvalidParameter() {}
func (e errInvalidParameter) Cause() error { return e.error }
func (e errInvalidParameter) Unwrap() error { return e.error }
-21
View File
@@ -1,21 +0,0 @@
package registry
// ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
//
// See hack/generate-swagger-api.sh
// ----------------------------------------------------------------------------
// AuthenticateOKBody authenticate o k body
// swagger:model AuthenticateOKBody
type AuthenticateOKBody struct {
// An opaque token used to authenticate a user after a successful login
// Required: true
IdentityToken string `json:"IdentityToken"`
// The status of the authentication
// Required: true
Status string `json:"Status"`
}
-122
View File
@@ -1,122 +0,0 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.23
package registry
import (
"encoding/json"
"net"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ServiceConfig stores daemon registry services configuration.
type ServiceConfig struct {
AllowNondistributableArtifactsCIDRs []*NetIPNet `json:"AllowNondistributableArtifactsCIDRs,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release.
AllowNondistributableArtifactsHostnames []string `json:"AllowNondistributableArtifactsHostnames,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release.
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
Mirrors []string
// ExtraFields is for internal use to include deprecated fields on older API versions.
ExtraFields map[string]any `json:"-"`
}
// MarshalJSON implements a custom marshaler to include legacy fields
// in API responses.
func (sc *ServiceConfig) MarshalJSON() ([]byte, error) {
type tmp ServiceConfig
base, err := json.Marshal((*tmp)(sc))
if err != nil {
return nil, err
}
var merged map[string]any
_ = json.Unmarshal(base, &merged)
for k, v := range sc.ExtraFields {
merged[k] = v
}
return json.Marshal(merged)
}
// NetIPNet is the net.IPNet type, which can be marshalled and
// unmarshalled to JSON
type NetIPNet net.IPNet
// String returns the CIDR notation of ipnet
func (ipnet *NetIPNet) String() string {
return (*net.IPNet)(ipnet).String()
}
// MarshalJSON returns the JSON representation of the IPNet
func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) {
return json.Marshal((*net.IPNet)(ipnet).String())
}
// UnmarshalJSON sets the IPNet from a byte array of JSON
func (ipnet *NetIPNet) UnmarshalJSON(b []byte) error {
var ipnetStr string
if err := json.Unmarshal(b, &ipnetStr); err != nil {
return err
}
_, cidr, err := net.ParseCIDR(ipnetStr)
if err != nil {
return err
}
*ipnet = NetIPNet(*cidr)
return nil
}
// IndexInfo contains information about a registry
//
// RepositoryInfo Examples:
//
// {
// "Index" : {
// "Name" : "docker.io",
// "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"],
// "Secure" : true,
// "Official" : true,
// },
// "RemoteName" : "library/debian",
// "LocalName" : "debian",
// "CanonicalName" : "docker.io/debian"
// "Official" : true,
// }
//
// {
// "Index" : {
// "Name" : "127.0.0.1:5000",
// "Mirrors" : [],
// "Secure" : false,
// "Official" : false,
// },
// "RemoteName" : "user/repo",
// "LocalName" : "127.0.0.1:5000/user/repo",
// "CanonicalName" : "127.0.0.1:5000/user/repo",
// "Official" : false,
// }
type IndexInfo struct {
// Name is the name of the registry, such as "docker.io"
Name string
// Mirrors is a list of mirrors, expressed as URIs
Mirrors []string
// Secure is set to false if the registry is part of the list of
// insecure registries. Insecure registries accept HTTP and/or accept
// HTTPS with certificates from unknown CAs.
Secure bool
// Official indicates whether this is an official registry
Official bool
}
// DistributionInspect describes the result obtained from contacting the
// registry to retrieve image metadata
type DistributionInspect struct {
// Descriptor contains information about the manifest, including
// the content addressable digest
Descriptor ocispec.Descriptor
// Platforms contains the list of platforms supported by the image,
// obtained by parsing the manifest
Platforms []ocispec.Platform
}
-30
View File
@@ -1,30 +0,0 @@
package strslice
import "encoding/json"
// StrSlice represents a string or an array of strings.
// We need to override the json decoder to accept both options.
type StrSlice []string
// UnmarshalJSON decodes the byte slice whether it's a string or an array of
// strings. This method is needed to implement json.Unmarshaler.
func (e *StrSlice) UnmarshalJSON(b []byte) error {
if len(b) == 0 {
// With no input, we preserve the existing value by returning nil and
// leaving the target alone. This allows defining default values for
// the type.
return nil
}
p := make([]string, 0, 1)
if err := json.Unmarshal(b, &p); err != nil {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
p = append(p, s)
}
*e = p
return nil
}
-27
View File
@@ -1,27 +0,0 @@
package runtime
import "fmt"
// PluginSpec defines the base payload which clients can specify for creating
// a service with the plugin runtime.
type PluginSpec struct {
Name string `json:"name,omitempty"`
Remote string `json:"remote,omitempty"`
Privileges []*PluginPrivilege `json:"privileges,omitempty"`
Disabled bool `json:"disabled,omitempty"`
Env []string `json:"env,omitempty"`
}
// PluginPrivilege describes a permission the user has to accept
// upon installing a plugin.
type PluginPrivilege struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Value []string `json:"value,omitempty"`
}
var (
ErrInvalidLengthPlugin = fmt.Errorf("proto: negative length found during unmarshaling") // Deprecated: this error was only used internally and is no longer used.
ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow") // Deprecated: this error was only used internally and is no longer used.
ErrUnexpectedEndOfGroupPlugin = fmt.Errorf("proto: unexpected end of group") // Deprecated: this error was only used internally and is no longer used.
)
-48
View File
@@ -1,48 +0,0 @@
package system
import (
"errors"
"fmt"
"strings"
)
// SecurityOpt contains the name and options of a security option
type SecurityOpt struct {
Name string
Options []KeyValue
}
// DecodeSecurityOptions decodes a security options string slice to a
// type-safe [SecurityOpt].
func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) {
so := []SecurityOpt{}
for _, opt := range opts {
// support output from a < 1.13 docker daemon
if !strings.Contains(opt, "=") {
so = append(so, SecurityOpt{Name: opt})
continue
}
secopt := SecurityOpt{}
for _, s := range strings.Split(opt, ",") {
k, v, ok := strings.Cut(s, "=")
if !ok {
return nil, fmt.Errorf("invalid security option %q", s)
}
if k == "" || v == "" {
return nil, errors.New("invalid empty security option")
}
if k == "name" {
secopt.Name = v
continue
}
secopt.Options = append(secopt.Options, KeyValue{Key: k, Value: v})
}
so = append(so, secopt)
}
return so, nil
}
// KeyValue holds a key/value pair.
type KeyValue struct {
Key, Value string
}
-103
View File
@@ -1,103 +0,0 @@
package types
import (
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/volume"
)
const (
// MediaTypeRawStream is vendor specific MIME-Type set for raw TTY streams
MediaTypeRawStream = "application/vnd.docker.raw-stream"
// MediaTypeMultiplexedStream is vendor specific MIME-Type set for stdin/stdout/stderr multiplexed streams
MediaTypeMultiplexedStream = "application/vnd.docker.multiplexed-stream"
)
// Ping contains response of Engine API:
// GET "/_ping"
type Ping struct {
APIVersion string
OSType string
Experimental bool
BuilderVersion build.BuilderVersion
// SwarmStatus provides information about the current swarm status of the
// engine, obtained from the "Swarm" header in the API response.
//
// It can be a nil struct if the API version does not provide this header
// in the ping response, or if an error occurred, in which case the client
// should use other ways to get the current swarm status, such as the /swarm
// endpoint.
SwarmStatus *swarm.Status
}
// ComponentVersion describes the version information for a specific component.
type ComponentVersion struct {
Name string
Version string
Details map[string]string `json:",omitempty"`
}
// Version contains response of Engine API:
// GET "/version"
type Version struct {
Platform struct{ Name string } `json:",omitempty"`
Components []ComponentVersion `json:",omitempty"`
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
Version string
APIVersion string `json:"ApiVersion"`
MinAPIVersion string `json:"MinAPIVersion,omitempty"`
GitCommit string
GoVersion string
Os string
Arch string
KernelVersion string `json:",omitempty"`
Experimental bool `json:",omitempty"`
BuildTime string `json:",omitempty"`
}
// DiskUsageObject represents an object type used for disk usage query filtering.
type DiskUsageObject string
const (
// ContainerObject represents a container DiskUsageObject.
ContainerObject DiskUsageObject = "container"
// ImageObject represents an image DiskUsageObject.
ImageObject DiskUsageObject = "image"
// VolumeObject represents a volume DiskUsageObject.
VolumeObject DiskUsageObject = "volume"
// BuildCacheObject represents a build-cache DiskUsageObject.
BuildCacheObject DiskUsageObject = "build-cache"
)
// DiskUsageOptions holds parameters for system disk usage query.
type DiskUsageOptions struct {
// Types specifies what object types to include in the response. If empty,
// all object types are returned.
Types []DiskUsageObject
}
// DiskUsage contains response of Engine API:
// GET "/system/df"
type DiskUsage struct {
LayersSize int64
Images []*image.Summary
Containers []*container.Summary
Volumes []*volume.Volume
BuildCache []*build.CacheRecord
BuilderSize int64 `json:",omitempty"` // Deprecated: deprecated in API 1.38, and no longer used since API 1.40.
}
// PushResult contains the tag, manifest digest, and manifest size from the
// push. It's used to signal this information to the trust code in the client
// so it can sign the manifest if necessary.
type PushResult struct {
Tag string
Digest string
Size int
}

Some files were not shown because too many files have changed in this diff Show More