Compare commits

...

39 Commits

Author SHA1 Message Date
Way2go cc5ea7c176
Merge b039c0e9af into 9861ce90fd 2024-11-18 15:50:32 +07:00
Sebastiaan van Stijn 9861ce90fd
Merge pull request #5621 from thaJeztah/more_go_build_tags
cli/command/container: fix missing go:build tag
2024-11-15 11:24:51 +01:00
Sebastiaan van Stijn d1d5353269
cli/command/container: fix missing go:build tag
make shell
    make -C ./internal/gocompat/

    GO111MODULE=on go test -v
    # github.com/docker/cli/cli/command/container
    ../../cli/command/container/completion.go:37:28: implicit function instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../cli/command/container/completion.go:82:25: implicit function instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../cli/command/container/completion.go:92:27: implicit function instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    FAIL	gocompat [build failed]

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-15 11:06:20 +01:00
Sebastiaan van Stijn 4adbb18f1c
Merge pull request #5580 from albers/container-completions
Improve Cobra completions for `run` and `create`
2024-11-14 16:58:54 +01:00
Sebastiaan van Stijn e00ed82399
Merge pull request #5615 from thaJeztah/bump_compose_buildx
Dockerfile: update buildx to v0.18.0, compose to v2.30.3
2024-11-14 14:42:05 +01:00
Sebastiaan van Stijn 3dd7621240
Dockerfile: update compose to v2.30.3
Update the compose cli plugin used in the dev-container

full diff: https://github.com/docker/compose/compare/v2.29.7...v2.30.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-14 10:35:52 +01:00
Sebastiaan van Stijn 4242cda826
Dockerfile: update buildx to v0.18.0
Update the buildx cli plugin used in the dev-container

full diff: https://github.com/docker/buildx/compare/0.17.1..0.18.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-14 10:35:25 +01:00
Sebastiaan van Stijn a4228409d2
Merge pull request #5608 from thaJeztah/go1.22_buildtags
update go:build tags to use go1.22
2024-11-12 14:12:00 +01:00
Sebastiaan van Stijn 7c80e4f938
update go:build tags to use go1.22
commit 4a7b04d412 configured golangci-lint
to use go1.23 semantics, which enabled the copyloopvar linter.

go1.22 now creates a copy of variables when assigned in a loop; make sure we
don't have files that may downgrade semantics to go1.21 in case that also means
disabling that feature; https://go.dev/ref/spec#Go_1.22

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-12 12:38:18 +01:00
Harald Albers 06260e68f3 Handle null completions with a default callback
Credits to thaJeztah

Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 4525fe37b4 Add completion for `--volume-driver`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers db0ed1e216 Add completion for `--cgroupns`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 2915749279 Add completion for `--uts`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 3a2503fa43 Add completion for --log-driver` and --log-opt`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 9a9ae231a9 Add completion for `--security-opt`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 5f7c43e5e6 Add completion for `--detach-keys`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 3292afe6e6 Add completion for `--userns`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 5d709a8d9f Add completion for `--ulimit`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers 2d89339b34 Add completion for `--storage-opt`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers ac7bde6f64 Add completion for `--pid`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:55:59 +00:00
Harald Albers e513454244 Add completion for `--link`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:35:34 +00:00
Harald Albers c555327f0b Add completion for `--ipc`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:35:34 +00:00
Harald Albers b598ec8cdb Add completion for `--attach`
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:35:34 +00:00
Harald Albers 761d76750c Share the container completions
Signed-off-by: Harald Albers <github@albersweb.de>
2024-11-08 15:35:34 +00:00
Sebastiaan van Stijn 917d2dc837
Merge pull request #5601 from vvoland/update-go
update to go1.23.3
2024-11-07 14:42:18 +01:00
Sebastiaan van Stijn f9497b8a46
Merge pull request #5600 from aevesdocker/desktop-link-fix
docs: change link to desktop docs
2024-11-07 13:56:47 +01:00
Paweł Gronowski 382d4c34a9
update to go1.23.3
- https://github.com/golang/go/issues?q=milestone%3AGo1.23.3+label%3ACherryPickApproved
- full diff: https://github.com/golang/go/compare/go1.23.2...go1.23.3

go1.23.3 (released 2024-11-06) includes fixes to the linker, the
runtime, and the net/http, os, and syscall packages. See the
[Go 1.23.3 milestone](https://github.com/golang/go/issues?q=milestone%3AGo1.23.3+label%3ACherryPickApproved)
for details.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-11-07 13:24:16 +01:00
aevesdocker 1440f9f8cf docs: change link to desktop docs
Signed-off-by: aevesdocker <allie.sadler@docker.com>
2024-11-07 09:38:19 +00:00
Sebastiaan van Stijn 9c01d924fb
Merge pull request #5595 from dvdksn/docs-redis-example-tags
docs: update example redis tags from 3.0.x to 7.4.x
2024-11-06 15:52:12 +01:00
David Karlsson 172f340112 docs: update example redis tags from 3.0.x to 7.4.x
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-11-05 11:20:17 +01:00
Wayne Cheng b039c0e9af show platforms for `docker manifest ls`
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng 46b474267b fixed string replace
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng c2919580b6 some additions for bash completion
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng 6fc8567ce6 check lint
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng 3ecd392a8c check fmt
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng dbd460a216 docs generate for `docker manifest ls`
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng 402a3400f0 bash completion for `docker manifest ls`
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng 72ef456387 test cases for `docker manifest ls`
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
Wayne Cheng 6bff05f02f feature: subcommand `docker manifest ls`
Signed-off-by: Wayne Cheng <zhengwei@tiduyun.com>
2024-01-06 22:26:54 +08:00
95 changed files with 891 additions and 172 deletions

View File

@ -62,7 +62,7 @@ jobs:
name: Update Go name: Update Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: 1.23.2 go-version: 1.23.3
- -
name: Initialize CodeQL name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v3

View File

@ -68,7 +68,7 @@ jobs:
name: Set up Go name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: 1.23.2 go-version: 1.23.3
- -
name: Test name: Test
run: | run: |

View File

@ -43,7 +43,7 @@ linters:
run: run:
# prevent golangci-lint from deducting the go version to lint for through go.mod, # prevent golangci-lint from deducting the go version to lint for through go.mod,
# which causes it to fallback to go1.17 semantics. # which causes it to fallback to go1.17 semantics.
go: "1.23.2" go: "1.23.3"
timeout: 5m timeout: 5m
linters-settings: linters-settings:

View File

@ -4,12 +4,12 @@ ARG BASE_VARIANT=alpine
ARG ALPINE_VERSION=3.20 ARG ALPINE_VERSION=3.20
ARG BASE_DEBIAN_DISTRO=bookworm ARG BASE_DEBIAN_DISTRO=bookworm
ARG GO_VERSION=1.23.2 ARG GO_VERSION=1.23.3
ARG XX_VERSION=1.5.0 ARG XX_VERSION=1.5.0
ARG GOVERSIONINFO_VERSION=v1.3.0 ARG GOVERSIONINFO_VERSION=v1.3.0
ARG GOTESTSUM_VERSION=v1.10.0 ARG GOTESTSUM_VERSION=v1.10.0
ARG BUILDX_VERSION=0.17.1 ARG BUILDX_VERSION=0.18.0
ARG COMPOSE_VERSION=v2.29.7 ARG COMPOSE_VERSION=v2.30.3
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package manager package manager

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package config package config

View File

@ -1,3 +1,7 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.22
// +build go1.22
package container package container
import ( import (
@ -44,6 +48,65 @@ var allLinuxCapabilities = sync.OnceValue(func() []string {
return out return out
}) })
// logDriverOptions provides the options for each built-in logging driver.
var logDriverOptions = map[string][]string{
"awslogs": {
"max-buffer-size", "mode", "awslogs-create-group", "awslogs-credentials-endpoint", "awslogs-datetime-format",
"awslogs-group", "awslogs-multiline-pattern", "awslogs-region", "awslogs-stream", "tag",
},
"fluentd": {
"max-buffer-size", "mode", "env", "env-regex", "labels", "fluentd-address", "fluentd-async",
"fluentd-buffer-limit", "fluentd-request-ack", "fluentd-retry-wait", "fluentd-max-retries",
"fluentd-sub-second-precision", "tag",
},
"gcplogs": {
"max-buffer-size", "mode", "env", "env-regex", "labels", "gcp-log-cmd", "gcp-meta-id", "gcp-meta-name",
"gcp-meta-zone", "gcp-project",
},
"gelf": {
"max-buffer-size", "mode", "env", "env-regex", "labels", "gelf-address", "gelf-compression-level",
"gelf-compression-type", "gelf-tcp-max-reconnect", "gelf-tcp-reconnect-delay", "tag",
},
"journald": {"max-buffer-size", "mode", "env", "env-regex", "labels", "tag"},
"json-file": {"max-buffer-size", "mode", "env", "env-regex", "labels", "compress", "max-file", "max-size"},
"local": {"max-buffer-size", "mode", "compress", "max-file", "max-size"},
"none": {},
"splunk": {
"max-buffer-size", "mode", "env", "env-regex", "labels", "splunk-caname", "splunk-capath", "splunk-format",
"splunk-gzip", "splunk-gzip-level", "splunk-index", "splunk-insecureskipverify", "splunk-source",
"splunk-sourcetype", "splunk-token", "splunk-url", "splunk-verify-connection", "tag",
},
"syslog": {
"max-buffer-size", "mode", "env", "env-regex", "labels", "syslog-address", "syslog-facility", "syslog-format",
"syslog-tls-ca-cert", "syslog-tls-cert", "syslog-tls-key", "syslog-tls-skip-verify", "tag",
},
}
// builtInLogDrivers provides a list of the built-in logging drivers.
var builtInLogDrivers = sync.OnceValue(func() []string {
drivers := make([]string, 0, len(logDriverOptions))
for driver := range logDriverOptions {
drivers = append(drivers, driver)
}
return drivers
})
// allLogDriverOptions provides all options of the built-in logging drivers.
// The list does not contain duplicates.
var allLogDriverOptions = sync.OnceValue(func() []string {
var result []string
seen := make(map[string]bool)
for driver := range logDriverOptions {
for _, opt := range logDriverOptions[driver] {
if !seen[opt] {
seen[opt] = true
result = append(result, opt)
}
}
}
return result
})
// restartPolicies is a list of all valid restart-policies.. // restartPolicies is a list of all valid restart-policies..
// //
// TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true") // TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true")
@ -54,6 +117,207 @@ var restartPolicies = []string{
string(container.RestartPolicyUnlessStopped), string(container.RestartPolicyUnlessStopped),
} }
// addCompletions adds the completions that `run` and `create` have in common.
func addCompletions(cmd *cobra.Command, dockerCLI completion.APIClientProvider) {
_ = cmd.RegisterFlagCompletionFunc("attach", completion.FromList("stderr", "stdin", "stdout"))
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cgroupns", completeCgroupns())
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc("ipc", completeIpc(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("link", completeLink(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("log-driver", completeLogDriver(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("log-opt", completeLogOpt)
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("pid", completePid(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms)
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever))
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies)
_ = cmd.RegisterFlagCompletionFunc("security-opt", completeSecurityOpt)
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
_ = cmd.RegisterFlagCompletionFunc("storage-opt", completeStorageOpt)
_ = cmd.RegisterFlagCompletionFunc("ulimit", completeUlimit)
_ = cmd.RegisterFlagCompletionFunc("userns", completion.FromList("host"))
_ = cmd.RegisterFlagCompletionFunc("uts", completion.FromList("host"))
_ = cmd.RegisterFlagCompletionFunc("volume-driver", completeVolumeDriver(dockerCLI))
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCLI, true))
}
// completeCgroupns implements shell completion for the `--cgroupns` option of `run` and `create`.
func completeCgroupns() completion.ValidArgsFn {
return completion.FromList(string(container.CgroupnsModeHost), string(container.CgroupnsModePrivate))
}
// completeDetachKeys implements shell completion for the `--detach-keys` option of `run` and `create`.
func completeDetachKeys(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"ctrl-"}, cobra.ShellCompDirectiveNoSpace
}
// completeIpc implements shell completion for the `--ipc` option of `run` and `create`.
// The completion is partly composite.
func completeIpc(dockerCLI completion.APIClientProvider) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(toComplete) > 0 && strings.HasPrefix("container", toComplete) { //nolint:gocritic // not swapped, matches partly typed "container"
return []string{"container:"}, cobra.ShellCompDirectiveNoSpace
}
if strings.HasPrefix(toComplete, "container:") {
names, _ := completion.ContainerNames(dockerCLI, true)(cmd, args, toComplete)
return prefixWith("container:", names), cobra.ShellCompDirectiveNoFileComp
}
return []string{
string(container.IPCModeContainer + ":"),
string(container.IPCModeHost),
string(container.IPCModeNone),
string(container.IPCModePrivate),
string(container.IPCModeShareable),
}, cobra.ShellCompDirectiveNoFileComp
}
}
// completeLink implements shell completion for the `--link` option of `run` and `create`.
func completeLink(dockerCLI completion.APIClientProvider) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return postfixWith(":", containerNames(dockerCLI, cmd, args, toComplete)), cobra.ShellCompDirectiveNoSpace
}
}
// completeLogDriver implements shell completion for the `--log-driver` option of `run` and `create`.
// The log drivers are collected from a call to the Info endpoint with a fallback to a hard-coded list
// of the build-in log drivers.
func completeLogDriver(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
info, err := dockerCLI.Client().Info(cmd.Context())
if err != nil {
return builtInLogDrivers(), cobra.ShellCompDirectiveNoFileComp
}
drivers := info.Plugins.Log
return drivers, cobra.ShellCompDirectiveNoFileComp
}
}
// completeLogOpt implements shell completion for the `--log-opt` option of `run` and `create`.
// If the user supplied a log-driver, only options for that driver are returned.
func completeLogOpt(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
driver, _ := cmd.Flags().GetString("log-driver")
if options, exists := logDriverOptions[driver]; exists {
return postfixWith("=", options), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
}
return postfixWith("=", allLogDriverOptions()), cobra.ShellCompDirectiveNoSpace
}
// completePid implements shell completion for the `--pid` option of `run` and `create`.
func completePid(dockerCLI completion.APIClientProvider) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(toComplete) > 0 && strings.HasPrefix("container", toComplete) { //nolint:gocritic // not swapped, matches partly typed "container"
return []string{"container:"}, cobra.ShellCompDirectiveNoSpace
}
if strings.HasPrefix(toComplete, "container:") {
names, _ := completion.ContainerNames(dockerCLI, true)(cmd, args, toComplete)
return prefixWith("container:", names), cobra.ShellCompDirectiveNoFileComp
}
return []string{"container:", "host"}, cobra.ShellCompDirectiveNoFileComp
}
}
// completeSecurityOpt implements shell completion for the `--security-opt` option of `run` and `create`.
// The completion is partly composite.
func completeSecurityOpt(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(toComplete) > 0 && strings.HasPrefix("apparmor=", toComplete) { //nolint:gocritic // not swapped, matches partly typed "apparmor="
return []string{"apparmor="}, cobra.ShellCompDirectiveNoSpace
}
if len(toComplete) > 0 && strings.HasPrefix("label", toComplete) { //nolint:gocritic // not swapped, matches partly typed "label"
return []string{"label="}, cobra.ShellCompDirectiveNoSpace
}
if strings.HasPrefix(toComplete, "label=") {
if strings.HasPrefix(toComplete, "label=d") {
return []string{"label=disable"}, cobra.ShellCompDirectiveNoFileComp
}
labels := []string{"disable", "level:", "role:", "type:", "user:"}
return prefixWith("label=", labels), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
}
// length must be > 1 here so that completion of "s" falls through.
if len(toComplete) > 1 && strings.HasPrefix("seccomp", toComplete) { //nolint:gocritic // not swapped, matches partly typed "seccomp"
return []string{"seccomp="}, cobra.ShellCompDirectiveNoSpace
}
if strings.HasPrefix(toComplete, "seccomp=") {
return []string{"seccomp=unconfined"}, cobra.ShellCompDirectiveNoFileComp
}
return []string{"apparmor=", "label=", "no-new-privileges", "seccomp=", "systempaths=unconfined"}, cobra.ShellCompDirectiveNoFileComp
}
// completeStorageOpt implements shell completion for the `--storage-opt` option of `run` and `create`.
func completeStorageOpt(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"size="}, cobra.ShellCompDirectiveNoSpace
}
// completeUlimit implements shell completion for the `--ulimit` option of `run` and `create`.
func completeUlimit(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
limits := []string{
"as",
"chroot",
"core",
"cpu",
"data",
"fsize",
"locks",
"maxlogins",
"maxsyslogins",
"memlock",
"msgqueue",
"nice",
"nofile",
"nproc",
"priority",
"rss",
"rtprio",
"sigpending",
"stack",
}
return postfixWith("=", limits), cobra.ShellCompDirectiveNoSpace
}
// completeVolumeDriver contacts the API to get the built-in and installed volume drivers.
func completeVolumeDriver(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
return func(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
info, err := dockerCLI.Client().Info(cmd.Context())
if err != nil {
// fallback: the built-in drivers
return []string{"local"}, cobra.ShellCompDirectiveNoFileComp
}
drivers := info.Plugins.Volume
return drivers, cobra.ShellCompDirectiveNoFileComp
}
}
// containerNames contacts the API to get names and optionally IDs of containers.
// In case of an error, an empty list is returned.
func containerNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command, args []string, toComplete string) []string {
names, _ := completion.ContainerNames(dockerCLI, true)(cmd, args, toComplete)
if names == nil {
return []string{}
}
return names
}
// prefixWith prefixes every element in the slice with the given prefix.
func prefixWith(prefix string, values []string) []string {
result := make([]string, len(values))
for i, v := range values {
result[i] = prefix + v
}
return result
}
// postfixWith appends postfix to every element in the slice.
func postfixWith(postfix string, values []string) []string {
result := make([]string, len(values))
for i, v := range values {
result[i] = v + postfix
}
return result
}
func completeLinuxCapabilityNames(cmd *cobra.Command, args []string, toComplete string) (names []string, _ cobra.ShellCompDirective) { func completeLinuxCapabilityNames(cmd *cobra.Command, args []string, toComplete string) (names []string, _ cobra.ShellCompDirective) {
return completion.FromList(allLinuxCapabilities()...)(cmd, args, toComplete) return completion.FromList(allLinuxCapabilities()...)(cmd, args, toComplete)
} }

View File

@ -4,6 +4,9 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/builders"
"github.com/docker/docker/api/types/container"
"github.com/moby/sys/signal" "github.com/moby/sys/signal"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
@ -21,6 +24,48 @@ func TestCompleteLinuxCapabilityNames(t *testing.T) {
} }
} }
func TestCompletePid(t *testing.T) {
tests := []struct {
containerListFunc func(container.ListOptions) ([]container.Summary, error)
toComplete string
expectedCompletions []string
expectedDirective cobra.ShellCompDirective
}{
{
toComplete: "",
expectedCompletions: []string{"container:", "host"},
expectedDirective: cobra.ShellCompDirectiveNoFileComp,
},
{
toComplete: "c",
expectedCompletions: []string{"container:"},
expectedDirective: cobra.ShellCompDirectiveNoSpace,
},
{
containerListFunc: func(container.ListOptions) ([]container.Summary, error) {
return []container.Summary{
*builders.Container("c1"),
*builders.Container("c2"),
}, nil
},
toComplete: "container:",
expectedCompletions: []string{"container:c1", "container:c2"},
expectedDirective: cobra.ShellCompDirectiveNoFileComp,
},
}
for _, tc := range tests {
t.Run(tc.toComplete, func(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: tc.containerListFunc,
})
completions, directive := completePid(cli)(NewRunCommand(cli), nil, tc.toComplete)
assert.Check(t, is.DeepEqual(completions, tc.expectedCompletions))
assert.Check(t, is.Equal(directive, tc.expectedDirective))
})
}
}
func TestCompleteRestartPolicies(t *testing.T) { func TestCompleteRestartPolicies(t *testing.T) {
values, directives := completeRestartPolicies(nil, nil, "") values, directives := completeRestartPolicies(nil, nil, "")
assert.Check(t, is.Equal(directives&cobra.ShellCompDirectiveNoFileComp, cobra.ShellCompDirectiveNoFileComp), "Should not perform file completion") assert.Check(t, is.Equal(directives&cobra.ShellCompDirectiveNoFileComp, cobra.ShellCompDirectiveNoFileComp), "Should not perform file completion")
@ -28,6 +73,59 @@ func TestCompleteRestartPolicies(t *testing.T) {
assert.Check(t, is.DeepEqual(values, expected)) assert.Check(t, is.DeepEqual(values, expected))
} }
func TestCompleteSecurityOpt(t *testing.T) {
tests := []struct {
toComplete string
expectedCompletions []string
expectedDirective cobra.ShellCompDirective
}{
{
toComplete: "",
expectedCompletions: []string{"apparmor=", "label=", "no-new-privileges", "seccomp=", "systempaths=unconfined"},
expectedDirective: cobra.ShellCompDirectiveNoFileComp,
},
{
toComplete: "apparmor=",
expectedCompletions: []string{"apparmor="},
expectedDirective: cobra.ShellCompDirectiveNoSpace,
},
{
toComplete: "label=",
expectedCompletions: []string{"label=disable", "label=level:", "label=role:", "label=type:", "label=user:"},
expectedDirective: cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp,
},
{
toComplete: "s",
// We do not filter matching completions but delegate this task to the shell script.
expectedCompletions: []string{"apparmor=", "label=", "no-new-privileges", "seccomp=", "systempaths=unconfined"},
expectedDirective: cobra.ShellCompDirectiveNoFileComp,
},
{
toComplete: "se",
expectedCompletions: []string{"seccomp="},
expectedDirective: cobra.ShellCompDirectiveNoSpace,
},
{
toComplete: "seccomp=",
expectedCompletions: []string{"seccomp=unconfined"},
expectedDirective: cobra.ShellCompDirectiveNoFileComp,
},
{
toComplete: "sy",
expectedCompletions: []string{"apparmor=", "label=", "no-new-privileges", "seccomp=", "systempaths=unconfined"},
expectedDirective: cobra.ShellCompDirectiveNoFileComp,
},
}
for _, tc := range tests {
t.Run(tc.toComplete, func(t *testing.T) {
completions, directive := completeSecurityOpt(nil, nil, tc.toComplete)
assert.Check(t, is.DeepEqual(completions, tc.expectedCompletions))
assert.Check(t, is.Equal(directive, tc.expectedDirective))
})
}
}
func TestCompleteSignals(t *testing.T) { func TestCompleteSignals(t *testing.T) {
values, directives := completeSignals(nil, nil, "") values, directives := completeSignals(nil, nil, "")
assert.Check(t, is.Equal(directives&cobra.ShellCompDirectiveNoFileComp, cobra.ShellCompDirectiveNoFileComp), "Should not perform file completion") assert.Check(t, is.Equal(directives&cobra.ShellCompDirectiveNoFileComp, cobra.ShellCompDirectiveNoFileComp), "Should not perform file completion")

View File

@ -78,16 +78,15 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled()) command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
copts = addFlags(flags) copts = addFlags(flags)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames) addCompletions(cmd, dockerCli)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames) flags.VisitAll(func(flag *pflag.Flag) {
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames) // Set a default completion function if none was set. We don't look
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCli)) // up if it does already have one set, because Cobra does this for
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms) // us, and returns an error (which we ignore for this reason).
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever)) _ = cmd.RegisterFlagCompletionFunc(flag.Name, completion.NoComplete)
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies) })
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCli, true))
return cmd return cmd
} }

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package container package container

View File

@ -69,16 +69,16 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled()) command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
copts = addFlags(flags) copts = addFlags(flags)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames) _ = cmd.RegisterFlagCompletionFunc("detach-keys", completeDetachKeys)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames) addCompletions(cmd, dockerCli)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames) flags.VisitAll(func(flag *pflag.Flag) {
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCli)) // Set a default completion function if none was set. We don't look
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms) // up if it does already have one set, because Cobra does this for
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever)) // us, and returns an error (which we ignore for this reason).
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies) _ = cmd.RegisterFlagCompletionFunc(flag.Name, completion.NoComplete)
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals) })
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCli, true))
return cmd return cmd
} }

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package context package context

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package context package context

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package context package context

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package context package context

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package formatter package formatter

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package idresolver package idresolver

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package image package image

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package image package image

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package inspect package inspect

View File

@ -28,6 +28,7 @@ func NewManifestCommand(dockerCli command.Cli) *cobra.Command {
newAnnotateCommand(dockerCli), newAnnotateCommand(dockerCli),
newPushListCommand(dockerCli), newPushListCommand(dockerCli),
newRmManifestListCommand(dockerCli), newRmManifestListCommand(dockerCli),
newListCommand(dockerCli),
) )
return cmd return cmd
} }

View File

@ -0,0 +1,103 @@
package manifest
import (
"fmt"
"strings"
"github.com/distribution/reference"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/cli/manifest/types"
)
const (
defaultManifestListQuietFormat = "{{.Name}}"
defaultManifestListTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.Platforms}}"
repositoryHeader = "REPOSITORY"
tagHeader = "TAG"
platformsHeader = "PLATFORMS"
)
// NewFormat returns a Format for rendering using a manifest list Context
func NewFormat(source string, quiet bool) formatter.Format {
switch source {
case formatter.TableFormatKey:
if quiet {
return defaultManifestListQuietFormat
}
return defaultManifestListTableFormat
case formatter.RawFormatKey:
if quiet {
return `name: {{.Name}}`
}
return `repo: {{.Repository}}\ntag: {{.Tag}}\n`
}
return formatter.Format(source)
}
// FormatWrite writes formatted manifestLists using the Context
func FormatWrite(ctx formatter.Context, manifestLists []reference.Reference, manifests map[string][]types.ImageManifest) error {
render := func(format func(subContext formatter.SubContext) error) error {
for _, manifestList := range manifestLists {
if n, ok := manifestList.(reference.Named); ok {
if nt, ok := n.(reference.NamedTagged); ok {
if err := format(&manifestListContext{
name: reference.FamiliarString(manifestList),
repo: reference.FamiliarName(nt),
tag: nt.Tag(),
imageManifests: manifests[manifestList.String()],
}); err != nil {
return err
}
}
}
}
return nil
}
return ctx.Write(newManifestListContext(), render)
}
type manifestListContext struct {
formatter.HeaderContext
name string
repo string
tag string
imageManifests []types.ImageManifest
}
func newManifestListContext() *manifestListContext {
manifestListCtx := manifestListContext{}
manifestListCtx.Header = formatter.SubHeaderContext{
"Name": formatter.NameHeader,
"Repository": repositoryHeader,
"Tag": tagHeader,
"Platforms": platformsHeader,
}
return &manifestListCtx
}
func (c *manifestListContext) MarshalJSON() ([]byte, error) {
return formatter.MarshalJSON(c)
}
func (c *manifestListContext) Name() string {
return c.name
}
func (c *manifestListContext) Repository() string {
return c.repo
}
func (c *manifestListContext) Tag() string {
return c.tag
}
func (c *manifestListContext) Platforms() string {
platforms := []string{}
for _, manifest := range c.imageManifests {
os := manifest.Descriptor.Platform.OS
arch := manifest.Descriptor.Platform.Architecture
platforms = append(platforms, fmt.Sprintf("%s/%s", os, arch))
}
return strings.Join(platforms, ", ")
}

View File

@ -0,0 +1,74 @@
package manifest
import (
"sort"
"github.com/distribution/reference"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
flagsHelper "github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/manifest/types"
"github.com/fvbommel/sortorder"
"github.com/spf13/cobra"
)
type listOptions struct {
quiet bool
format string
}
func newListCommand(dockerCli command.Cli) *cobra.Command {
var options listOptions
cmd := &cobra.Command{
Use: "ls [OPTIONS]",
Aliases: []string{"list"},
Short: "List local manifest lists",
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runList(dockerCli, options)
},
}
flags := cmd.Flags()
flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only show manifest list NAMEs")
flags.StringVar(&options.format, "format", "", flagsHelper.FormatHelp)
return cmd
}
func runList(dockerCli command.Cli, options listOptions) error {
manifestStore := dockerCli.ManifestStore()
var manifestLists []reference.Reference
manifestLists, err := manifestStore.List()
if err != nil {
return err
}
manifests := map[string][]types.ImageManifest{}
for _, manifestList := range manifestLists {
if imageManifests, err := manifestStore.GetList(manifestList); err == nil {
manifests[manifestList.String()] = imageManifests
}
}
format := options.format
if len(format) == 0 {
if len(dockerCli.ConfigFile().ManifestListsFormat) > 0 && !options.quiet {
format = dockerCli.ConfigFile().ManifestListsFormat
} else {
format = formatter.TableFormatKey
}
}
manifestListsCtx := formatter.Context{
Output: dockerCli.Out(),
Format: NewFormat(format, options.quiet),
}
sort.Slice(manifestLists, func(i, j int) bool {
return sortorder.NaturalLess(manifestLists[i].String(), manifestLists[j].String())
})
return FormatWrite(manifestListsCtx, manifestLists, manifests)
}

View File

@ -0,0 +1,105 @@
package manifest
import (
"io"
"testing"
"github.com/docker/cli/cli/manifest/store"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"gotest.tools/v3/assert"
"gotest.tools/v3/golden"
)
func TestListErrors(t *testing.T) {
manifestStore := store.NewStore(t.TempDir())
testCases := []struct {
description string
args []string
flags map[string]string
expectedError string
}{
{
description: "too many arguments",
args: []string{"foo"},
expectedError: "accepts no arguments",
},
{
description: "invalid format",
args: []string{},
flags: map[string]string{
"format": "{{invalid format}}",
},
expectedError: "template parsing error",
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(nil)
cli.SetManifestStore(manifestStore)
cmd := newListCommand(cli)
cmd.SetArgs(tc.args)
for key, value := range tc.flags {
cmd.Flags().Set(key, value)
}
cmd.SetOut(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestList(t *testing.T) {
manifestStore := store.NewStore(t.TempDir())
list1 := ref(t, "first:1")
namedRef := ref(t, "alpine:3.0")
err := manifestStore.Save(list1, namedRef, fullImageManifest(t, namedRef))
assert.NilError(t, err)
namedRef = ref(t, "alpine:3.1")
imageManifest := fullImageManifest(t, namedRef)
imageManifest.Descriptor.Platform.OS = "linux"
imageManifest.Descriptor.Platform.Architecture = "arm64"
err = manifestStore.Save(list1, namedRef, imageManifest)
assert.NilError(t, err)
list2 := ref(t, "second:2")
namedRef = ref(t, "alpine:3.2")
err = manifestStore.Save(list2, namedRef, fullImageManifest(t, namedRef))
assert.NilError(t, err)
testCases := []struct {
description string
args []string
flags map[string]string
golden string
listFunc func(filter filters.Args) (types.PluginsListResponse, error)
}{
{
description: "list with no additional flags",
args: []string{},
golden: "manifest-list.golden",
},
{
description: "list with quiet option",
args: []string{},
flags: map[string]string{
"quiet": "true",
},
golden: "manifest-list-with-quiet-option.golden",
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(nil)
cli.SetManifestStore(manifestStore)
cmd := newListCommand(cli)
cmd.SetArgs(tc.args)
for key, value := range tc.flags {
cmd.Flags().Set(key, value)
}
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), tc.golden)
}
}

View File

@ -0,0 +1,2 @@
example.com/first:1
example.com/second:2

View File

@ -0,0 +1,3 @@
REPOSITORY TAG PLATFORMS
example.com/first 1 linux/amd64, linux/arm64
example.com/second 2 linux/amd64

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package network package network

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package network package network

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package node package node

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package node package node

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package plugin package plugin

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package plugin package plugin

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package secret package secret

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package service package service

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package service package service

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package service package service

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package service package service

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package system package system

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package system package system

View File

@ -1,5 +1,5 @@
// FIXME(jsternberg): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package trust package trust

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package command package command

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package volume package volume

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package interpolation package interpolation

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package interpolation package interpolation

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package loader package loader

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package schema package schema

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package schema package schema

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package template package template

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package template package template

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package types package types

View File

@ -24,6 +24,7 @@ type ConfigFile struct {
PluginsFormat string `json:"pluginsFormat,omitempty"` PluginsFormat string `json:"pluginsFormat,omitempty"`
VolumesFormat string `json:"volumesFormat,omitempty"` VolumesFormat string `json:"volumesFormat,omitempty"`
StatsFormat string `json:"statsFormat,omitempty"` StatsFormat string `json:"statsFormat,omitempty"`
ManifestListsFormat string `json:"manifestListsFormat,omitempty"`
DetachKeys string `json:"detachKeys,omitempty"` DetachKeys string `json:"detachKeys,omitempty"`
CredentialsStore string `json:"credsStore,omitempty"` CredentialsStore string `json:"credsStore,omitempty"`
CredentialHelpers map[string]string `json:"credHelpers,omitempty"` CredentialHelpers map[string]string `json:"credHelpers,omitempty"`

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package store package store

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package store package store

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package store package store

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package store package store

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package store package store

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package store package store

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package api package api

View File

@ -20,6 +20,7 @@ type Store interface {
Get(listRef reference.Reference, manifest reference.Reference) (types.ImageManifest, error) Get(listRef reference.Reference, manifest reference.Reference) (types.ImageManifest, error)
GetList(listRef reference.Reference) ([]types.ImageManifest, error) GetList(listRef reference.Reference) ([]types.ImageManifest, error)
Save(listRef reference.Reference, manifest reference.Reference, image types.ImageManifest) error Save(listRef reference.Reference, manifest reference.Reference, image types.ImageManifest) error
List() ([]reference.Reference, error)
} }
// fsStore manages manifest files stored on the local filesystem // fsStore manages manifest files stored on the local filesystem
@ -85,6 +86,26 @@ func (s *fsStore) getFromFilename(ref reference.Reference, filename string) (typ
return manifestInfo.ImageManifest, nil return manifestInfo.ImageManifest, nil
} }
// List returns the local manifest lists for a transaction
func (s *fsStore) List() ([]reference.Reference, error) {
fileInfos, err := os.ReadDir(s.root)
switch {
case os.IsNotExist(err):
return nil, nil
case err != nil:
return nil, err
}
listRefs := make([]reference.Reference, 0, len(fileInfos))
for _, info := range fileInfos {
refString := filenameToRefString(info.Name())
if listRef, err := reference.Parse(refString); err == nil {
listRefs = append(listRefs, listRef)
}
}
return listRefs, nil
}
// GetList returns all the local manifests for a transaction // GetList returns all the local manifests for a transaction
func (s *fsStore) GetList(listRef reference.Reference) ([]types.ImageManifest, error) { func (s *fsStore) GetList(listRef reference.Reference) ([]types.ImageManifest, error) {
filenames, err := s.listManifests(listRef.String()) filenames, err := s.listManifests(listRef.String())
@ -148,8 +169,13 @@ func manifestToFilename(root, manifestList, manifest string) string {
} }
func makeFilesafeName(ref string) string { func makeFilesafeName(ref string) string {
fileName := strings.ReplaceAll(ref, ":", "-") fileName := strings.ReplaceAll(ref, ":", "%")
return strings.ReplaceAll(fileName, "/", "_") return strings.ReplaceAll(fileName, "/", "#")
}
func filenameToRefString(filename string) string {
refString := strings.ReplaceAll(filename, "%", ":")
return strings.ReplaceAll(refString, "#", "/")
} }
type notFoundError struct { type notFoundError struct {

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package main package main

View File

@ -4139,10 +4139,15 @@ _docker_manifest() {
annotate annotate
create create
inspect inspect
ls
push push
rm rm
" "
__docker_subcommands "$subcommands" && return
local aliases="
list
"
__docker_subcommands "$subcommands $aliases" && return
case "$cur" in case "$cur" in
-*) -*)
@ -4250,6 +4255,24 @@ _docker_manifest_rm() {
esac esac
} }
_docker_manifest_list() {
_docker_manifest_ls
}
_docker_manifest_ls() {
case "$prev" in
--format)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--format --help --quiet -q" -- "$cur" ) )
;;
esac
}
_docker_node() { _docker_node() {
local subcommands=" local subcommands="
demote demote

View File

@ -1,5 +1,5 @@
variable "GO_VERSION" { variable "GO_VERSION" {
default = "1.23.2" default = "1.23.3"
} }
variable "VERSION" { variable "VERSION" {
default = "" default = ""

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.23.2 ARG GO_VERSION=1.23.3
ARG ALPINE_VERSION=3.20 ARG ALPINE_VERSION=3.20
ARG BUILDX_VERSION=0.17.1 ARG BUILDX_VERSION=0.17.1

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.23.2 ARG GO_VERSION=1.23.3
ARG ALPINE_VERSION=3.20 ARG ALPINE_VERSION=3.20
ARG GOLANGCI_LINT_VERSION=v1.61.0 ARG GOLANGCI_LINT_VERSION=v1.61.0

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.23.2 ARG GO_VERSION=1.23.3
ARG ALPINE_VERSION=3.20 ARG ALPINE_VERSION=3.20
ARG MODOUTDATED_VERSION=v0.8.0 ARG MODOUTDATED_VERSION=v0.8.0

View File

@ -1283,7 +1283,7 @@ connect to services running on the host machine.
It's conventional to use `host.docker.internal` as the hostname referring to It's conventional to use `host.docker.internal` as the hostname referring to
`host-gateway`. Docker Desktop automatically resolves this hostname, see `host-gateway`. Docker Desktop automatically resolves this hostname, see
[Explore networking features](https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host). [Explore networking features](https://docs.docker.com/desktop/features/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host).
The following example shows how the special `host-gateway` value works. The The following example shows how the special `host-gateway` value works. The
example runs an HTTP server that serves a file from host to container over the example runs an HTTP server that serves a file from host to container over the

View File

@ -21,6 +21,7 @@ For full details on using docker manifest lists, see the registry v2 specificati
| [`annotate`](manifest_annotate.md) | Add additional information to a local image manifest | | [`annotate`](manifest_annotate.md) | Add additional information to a local image manifest |
| [`create`](manifest_create.md) | Create a local manifest list for annotating and pushing to a registry | | [`create`](manifest_create.md) | Create a local manifest list for annotating and pushing to a registry |
| [`inspect`](manifest_inspect.md) | Display an image manifest, or manifest list | | [`inspect`](manifest_inspect.md) | Display an image manifest, or manifest list |
| [`ls`](manifest_ls.md) | List local manifest lists |
| [`push`](manifest_push.md) | Push a manifest list to a repository | | [`push`](manifest_push.md) | Push a manifest list to a repository |
| [`rm`](manifest_rm.md) | Delete one or more manifest lists from local storage | | [`rm`](manifest_rm.md) | Delete one or more manifest lists from local storage |

View File

@ -0,0 +1,19 @@
# docker manifest ls
<!---MARKER_GEN_START-->
List local manifest lists
### Aliases
`docker manifest ls`, `docker manifest list`
### Options
| Name | Type | Default | Description |
|:----------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `--format` | `string` | | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `-q`, `--quiet` | | | Only show manifest list NAMEs |
<!---MARKER_GEN_END-->

View File

@ -34,11 +34,11 @@ information about available filter options.
$ docker node ps swarm-manager1 $ docker node ps swarm-manager1
NAME IMAGE NODE DESIRED STATE CURRENT STATE NAME IMAGE NODE DESIRED STATE CURRENT STATE
redis.1.7q92v0nr1hcgts2amcjyqg3pq redis:3.0.6 swarm-manager1 Running Running 5 hours redis.1.7q92v0nr1hcgts2amcjyqg3pq redis:7.4.1 swarm-manager1 Running Running 5 hours
redis.6.b465edgho06e318egmgjbqo4o redis:3.0.6 swarm-manager1 Running Running 29 seconds redis.6.b465edgho06e318egmgjbqo4o redis:7.4.1 swarm-manager1 Running Running 29 seconds
redis.7.bg8c07zzg87di2mufeq51a2qp redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.7.bg8c07zzg87di2mufeq51a2qp redis:7.4.1 swarm-manager1 Running Running 5 seconds
redis.9.dkkual96p4bb3s6b10r7coxxt redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.9.dkkual96p4bb3s6b10r7coxxt redis:7.4.1 swarm-manager1 Running Running 5 seconds
redis.10.0tgctg8h8cech4w0k0gwrmr23 redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.10.0tgctg8h8cech4w0k0gwrmr23 redis:7.4.1 swarm-manager1 Running Running 5 seconds
``` ```
### <a name="filter"></a> Filtering (--filter) ### <a name="filter"></a> Filtering (--filter)
@ -64,11 +64,11 @@ The following filter matches all tasks with a name containing the `redis` string
$ docker node ps -f name=redis swarm-manager1 $ docker node ps -f name=redis swarm-manager1
NAME IMAGE NODE DESIRED STATE CURRENT STATE NAME IMAGE NODE DESIRED STATE CURRENT STATE
redis.1.7q92v0nr1hcgts2amcjyqg3pq redis:3.0.6 swarm-manager1 Running Running 5 hours redis.1.7q92v0nr1hcgts2amcjyqg3pq redis:7.4.1 swarm-manager1 Running Running 5 hours
redis.6.b465edgho06e318egmgjbqo4o redis:3.0.6 swarm-manager1 Running Running 29 seconds redis.6.b465edgho06e318egmgjbqo4o redis:7.4.1 swarm-manager1 Running Running 29 seconds
redis.7.bg8c07zzg87di2mufeq51a2qp redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.7.bg8c07zzg87di2mufeq51a2qp redis:7.4.1 swarm-manager1 Running Running 5 seconds
redis.9.dkkual96p4bb3s6b10r7coxxt redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.9.dkkual96p4bb3s6b10r7coxxt redis:7.4.1 swarm-manager1 Running Running 5 seconds
redis.10.0tgctg8h8cech4w0k0gwrmr23 redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.10.0tgctg8h8cech4w0k0gwrmr23 redis:7.4.1 swarm-manager1 Running Running 5 seconds
``` ```
#### id #### id
@ -79,7 +79,7 @@ The `id` filter matches a task's id.
$ docker node ps -f id=bg8c07zzg87di2mufeq51a2qp swarm-manager1 $ docker node ps -f id=bg8c07zzg87di2mufeq51a2qp swarm-manager1
NAME IMAGE NODE DESIRED STATE CURRENT STATE NAME IMAGE NODE DESIRED STATE CURRENT STATE
redis.7.bg8c07zzg87di2mufeq51a2qp redis:3.0.6 swarm-manager1 Running Running 5 seconds redis.7.bg8c07zzg87di2mufeq51a2qp redis:7.4.1 swarm-manager1 Running Running 5 seconds
``` ```
#### label #### label
@ -93,8 +93,8 @@ The following filter matches tasks with the `usage` label regardless of its valu
$ docker node ps -f "label=usage" $ docker node ps -f "label=usage"
NAME IMAGE NODE DESIRED STATE CURRENT STATE NAME IMAGE NODE DESIRED STATE CURRENT STATE
redis.6.b465edgho06e318egmgjbqo4o redis:3.0.6 swarm-manager1 Running Running 10 minutes redis.6.b465edgho06e318egmgjbqo4o redis:7.4.1 swarm-manager1 Running Running 10 minutes
redis.7.bg8c07zzg87di2mufeq51a2qp redis:3.0.6 swarm-manager1 Running Running 9 minutes redis.7.bg8c07zzg87di2mufeq51a2qp redis:7.4.1 swarm-manager1 Running Running 9 minutes
``` ```

View File

@ -99,19 +99,19 @@ Creates a service as described by the specified parameters.
### Create a service ### Create a service
```console ```console
$ docker service create --name redis redis:3.0.6 $ docker service create --name redis redis:7.4.1
dmu1ept4cxcfe8k8lhtux3ro3 dmu1ept4cxcfe8k8lhtux3ro3
$ docker service create --mode global --name redis2 redis:3.0.6 $ docker service create --mode global --name redis2 redis:7.4.1
a8q9dasaafudfs8q8w32udass a8q9dasaafudfs8q8w32udass
$ docker service ls $ docker service ls
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
dmu1ept4cxcf redis replicated 1/1 redis:3.0.6 dmu1ept4cxcf redis replicated 1/1 redis:7.4.1
a8q9dasaafud redis2 global 1/1 redis:3.0.6 a8q9dasaafud redis2 global 1/1 redis:7.4.1
``` ```
#### <a name="with-registry-auth"></a> Create a service using an image on a private registry (--with-registry-auth) #### <a name="with-registry-auth"></a> Create a service using an image on a private registry (--with-registry-auth)
@ -140,7 +140,7 @@ Use the `--replicas` flag to set the number of replica tasks for a replicated
service. The following command creates a `redis` service with `5` replica tasks: service. The following command creates a `redis` service with `5` replica tasks:
```console ```console
$ docker service create --name redis --replicas=5 redis:3.0.6 $ docker service create --name redis --replicas=5 redis:7.4.1
4cdgfyky7ozwh3htjfw0d12qv 4cdgfyky7ozwh3htjfw0d12qv
``` ```
@ -157,7 +157,7 @@ number of `RUNNING` tasks is `3`:
$ docker service ls $ docker service ls
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
4cdgfyky7ozw redis replicated 3/5 redis:3.0.7 4cdgfyky7ozw redis replicated 3/5 redis:7.4.1
``` ```
Once all the tasks are created and `RUNNING`, the actual number of tasks is Once all the tasks are created and `RUNNING`, the actual number of tasks is
@ -167,7 +167,7 @@ equal to the desired number:
$ docker service ls $ docker service ls
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
4cdgfyky7ozw redis replicated 5/5 redis:3.0.7 4cdgfyky7ozw redis replicated 5/5 redis:7.4.1
``` ```
### <a name="secret"></a> Create a service with secrets (--secret) ### <a name="secret"></a> Create a service with secrets (--secret)
@ -178,7 +178,7 @@ Use the `--secret` flag to give a container access to a
Create a service specifying a secret: Create a service specifying a secret:
```console ```console
$ docker service create --name redis --secret secret.json redis:3.0.6 $ docker service create --name redis --secret secret.json redis:7.4.1
4cdgfyky7ozwh3htjfw0d12qv 4cdgfyky7ozwh3htjfw0d12qv
``` ```
@ -189,7 +189,7 @@ Create a service specifying the secret, target, user/group ID, and mode:
$ docker service create --name redis \ $ docker service create --name redis \
--secret source=ssh-key,target=ssh \ --secret source=ssh-key,target=ssh \
--secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \ --secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \
redis:3.0.6 redis:7.4.1
4cdgfyky7ozwh3htjfw0d12qv 4cdgfyky7ozwh3htjfw0d12qv
``` ```
@ -215,14 +215,14 @@ pre-exist in the container. The `mode` is specified as a 4-number sequence such
as `0755`. as `0755`.
```console ```console
$ docker service create --name=redis --config redis-conf redis:3.0.6 $ docker service create --name=redis --config redis-conf redis:7.4.1
``` ```
Create a service with a config and specify the target location and file mode: Create a service with a config and specify the target location and file mode:
```console ```console
$ docker service create --name redis \ $ docker service create --name redis \
--config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:3.0.6 --config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:7.4.1
``` ```
To grant a service access to multiple configs, use multiple `--config` flags. To grant a service access to multiple configs, use multiple `--config` flags.
@ -239,7 +239,7 @@ $ docker service create \
--name redis \ --name redis \
--update-delay 10s \ --update-delay 10s \
--update-parallelism 2 \ --update-parallelism 2 \
redis:3.0.6 redis:7.4.1
``` ```
When you run a [service update](service_update.md), the scheduler updates a When you run a [service update](service_update.md), the scheduler updates a
@ -256,7 +256,7 @@ $ docker service create \
--name redis_2 \ --name redis_2 \
--replicas 5 \ --replicas 5 \
--env MYVAR=foo \ --env MYVAR=foo \
redis:3.0.6 redis:7.4.1
``` ```
To specify multiple environment variables, specify multiple `--env` flags, each To specify multiple environment variables, specify multiple `--env` flags, each
@ -268,7 +268,7 @@ $ docker service create \
--replicas 5 \ --replicas 5 \
--env MYVAR=foo \ --env MYVAR=foo \
--env MYVAR2=bar \ --env MYVAR2=bar \
redis:3.0.6 redis:7.4.1
``` ```
### <a name="hostname"></a> Create a service with specific hostname (--hostname) ### <a name="hostname"></a> Create a service with specific hostname (--hostname)
@ -277,7 +277,7 @@ This option sets the docker service containers hostname to a specific string.
For example: For example:
```console ```console
$ docker service create --name redis --hostname myredis redis:3.0.6 $ docker service create --name redis --hostname myredis redis:7.4.1
``` ```
### <a name="label"></a> Set metadata on a service (-l, --label) ### <a name="label"></a> Set metadata on a service (-l, --label)
@ -290,7 +290,7 @@ $ docker service create \
--name redis_2 \ --name redis_2 \
--label com.example.foo="bar" \ --label com.example.foo="bar" \
--label bar=baz \ --label bar=baz \
redis:3.0.6 redis:7.4.1
``` ```
For more information about labels, refer to [apply custom For more information about labels, refer to [apply custom
@ -679,7 +679,7 @@ The following command creates a global service:
$ docker service create \ $ docker service create \
--name redis_2 \ --name redis_2 \
--mode global \ --mode global \
redis:3.0.6 redis:7.4.1
``` ```
### <a name="constraint"></a> Specify service constraints (--constraint) ### <a name="constraint"></a> Specify service constraints (--constraint)
@ -712,7 +712,7 @@ $ docker service create \
--name redis_2 \ --name redis_2 \
--constraint node.platform.os==linux \ --constraint node.platform.os==linux \
--constraint node.labels.type==queue \ --constraint node.labels.type==queue \
redis:3.0.6 redis:7.4.1
``` ```
If the service constraints exclude all nodes in the cluster, a message is printed If the service constraints exclude all nodes in the cluster, a message is printed
@ -760,7 +760,7 @@ $ docker service create \
--replicas 9 \ --replicas 9 \
--name redis_2 \ --name redis_2 \
--placement-pref spread=node.labels.datacenter \ --placement-pref spread=node.labels.datacenter \
redis:3.0.6 redis:7.4.1
``` ```
This uses `--placement-pref` with a `spread` strategy (currently the only This uses `--placement-pref` with a `spread` strategy (currently the only
@ -812,7 +812,7 @@ $ docker service create \
--name redis_2 \ --name redis_2 \
--placement-pref 'spread=node.labels.datacenter' \ --placement-pref 'spread=node.labels.datacenter' \
--placement-pref 'spread=node.labels.rack' \ --placement-pref 'spread=node.labels.rack' \
redis:3.0.6 redis:7.4.1
``` ```
When updating a service with `docker service update`, `--placement-pref-add` When updating a service with `docker service update`, `--placement-pref-add`

View File

@ -40,7 +40,7 @@ For example, given the following service;
```console ```console
$ docker service ls $ docker service ls
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
dmu1ept4cxcf redis replicated 3/3 redis:3.0.6 dmu1ept4cxcf redis replicated 3/3 redis:7.4.1
``` ```
Both `docker service inspect redis`, and `docker service inspect dmu1ept4cxcf` Both `docker service inspect redis`, and `docker service inspect dmu1ept4cxcf`
@ -65,7 +65,7 @@ The output is in JSON format, for example:
"Name": "redis", "Name": "redis",
"TaskTemplate": { "TaskTemplate": {
"ContainerSpec": { "ContainerSpec": {
"Image": "redis:3.0.6" "Image": "redis:7.4.1"
}, },
"Resources": { "Resources": {
"Limits": {}, "Limits": {},

View File

@ -37,7 +37,7 @@ $ docker service ls
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
c8wgl7q4ndfd frontend replicated 5/5 nginx:alpine c8wgl7q4ndfd frontend replicated 5/5 nginx:alpine
dmu1ept4cxcf redis replicated 3/3 redis:3.0.6 dmu1ept4cxcf redis replicated 3/3 redis:7.4.1
iwe3278osahj mongo global 7/7 mongo:3.3 iwe3278osahj mongo global 7/7 mongo:3.3
hh08h9uu8uwr job replicated-job 1/1 (3/5 completed) nginx:latest hh08h9uu8uwr job replicated-job 1/1 (3/5 completed) nginx:latest
``` ```
@ -68,7 +68,7 @@ The following filter matches services with an ID starting with `0bcjw`:
```console ```console
$ docker service ls -f "id=0bcjw" $ docker service ls -f "id=0bcjw"
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
0bcjwfh8ychr redis replicated 1/1 redis:3.0.6 0bcjwfh8ychr redis replicated 1/1 redis:7.4.1
``` ```
#### label #### label
@ -84,7 +84,7 @@ $ docker service ls --filter label=project
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
01sl1rp6nj5u frontend2 replicated 1/1 nginx:alpine 01sl1rp6nj5u frontend2 replicated 1/1 nginx:alpine
36xvvwwauej0 frontend replicated 5/5 nginx:alpine 36xvvwwauej0 frontend replicated 5/5 nginx:alpine
74nzcxxjv6fq backend replicated 3/3 redis:3.0.6 74nzcxxjv6fq backend replicated 3/3 redis:7.4.1
``` ```
The following filter matches only services with the `project` label with the The following filter matches only services with the `project` label with the
@ -94,7 +94,7 @@ The following filter matches only services with the `project` label with the
$ docker service ls --filter label=project=project-a $ docker service ls --filter label=project=project-a
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
36xvvwwauej0 frontend replicated 5/5 nginx:alpine 36xvvwwauej0 frontend replicated 5/5 nginx:alpine
74nzcxxjv6fq backend replicated 3/3 redis:3.0.6 74nzcxxjv6fq backend replicated 3/3 redis:7.4.1
``` ```
#### mode #### mode
@ -118,7 +118,7 @@ The following filter matches services with a name starting with `redis`.
```console ```console
$ docker service ls --filter name=redis $ docker service ls --filter name=redis
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
0bcjwfh8ychr redis replicated 1/1 redis:3.0.6 0bcjwfh8ychr redis replicated 1/1 redis:7.4.1
``` ```
### <a name="format"></a> Format the output (--format) ### <a name="format"></a> Format the output (--format)

View File

@ -36,35 +36,35 @@ The following command shows all the tasks that are part of the `redis` service:
$ docker service ps redis $ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
0qihejybwf1x redis.1 redis:3.0.5 manager1 Running Running 8 seconds 0qihejybwf1x redis.1 redis:7.4.0 manager1 Running Running 8 seconds
bk658fpbex0d redis.2 redis:3.0.5 worker2 Running Running 9 seconds bk658fpbex0d redis.2 redis:7.4.0 worker2 Running Running 9 seconds
5ls5s5fldaqg redis.3 redis:3.0.5 worker1 Running Running 9 seconds 5ls5s5fldaqg redis.3 redis:7.4.0 worker1 Running Running 9 seconds
8ryt076polmc redis.4 redis:3.0.5 worker1 Running Running 9 seconds 8ryt076polmc redis.4 redis:7.4.0 worker1 Running Running 9 seconds
1x0v8yomsncd redis.5 redis:3.0.5 manager1 Running Running 8 seconds 1x0v8yomsncd redis.5 redis:7.4.0 manager1 Running Running 8 seconds
71v7je3el7rr redis.6 redis:3.0.5 worker2 Running Running 9 seconds 71v7je3el7rr redis.6 redis:7.4.0 worker2 Running Running 9 seconds
4l3zm9b7tfr7 redis.7 redis:3.0.5 worker2 Running Running 9 seconds 4l3zm9b7tfr7 redis.7 redis:7.4.0 worker2 Running Running 9 seconds
9tfpyixiy2i7 redis.8 redis:3.0.5 worker1 Running Running 9 seconds 9tfpyixiy2i7 redis.8 redis:7.4.0 worker1 Running Running 9 seconds
3w1wu13yupln redis.9 redis:3.0.5 manager1 Running Running 8 seconds 3w1wu13yupln redis.9 redis:7.4.0 manager1 Running Running 8 seconds
8eaxrb2fqpbn redis.10 redis:3.0.5 manager1 Running Running 8 seconds 8eaxrb2fqpbn redis.10 redis:7.4.0 manager1 Running Running 8 seconds
``` ```
In addition to running tasks, the output also shows the task history. For In addition to running tasks, the output also shows the task history. For
example, after updating the service to use the `redis:3.0.6` image, the output example, after updating the service to use the `redis:7.4.1` image, the output
may look like this: may look like this:
```console ```console
$ docker service ps redis $ docker service ps redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
50qe8lfnxaxk redis.1 redis:3.0.6 manager1 Running Running 6 seconds ago 50qe8lfnxaxk redis.1 redis:7.4.1 manager1 Running Running 6 seconds ago
ky2re9oz86r9 \_ redis.1 redis:3.0.5 manager1 Shutdown Shutdown 8 seconds ago ky2re9oz86r9 \_ redis.1 redis:7.4.0 manager1 Shutdown Shutdown 8 seconds ago
3s46te2nzl4i redis.2 redis:3.0.6 worker2 Running Running less than a second ago 3s46te2nzl4i redis.2 redis:7.4.1 worker2 Running Running less than a second ago
nvjljf7rmor4 \_ redis.2 redis:3.0.6 worker2 Shutdown Rejected 23 seconds ago "No such image: redis@sha256:6…" nvjljf7rmor4 \_ redis.2 redis:7.4.1 worker2 Shutdown Rejected 23 seconds ago "No such image: redis@sha256:6…"
vtiuz2fpc0yb \_ redis.2 redis:3.0.5 worker2 Shutdown Shutdown 1 second ago vtiuz2fpc0yb \_ redis.2 redis:7.4.0 worker2 Shutdown Shutdown 1 second ago
jnarweeha8x4 redis.3 redis:3.0.6 worker1 Running Running 3 seconds ago jnarweeha8x4 redis.3 redis:7.4.1 worker1 Running Running 3 seconds ago
vs448yca2nz4 \_ redis.3 redis:3.0.5 worker1 Shutdown Shutdown 4 seconds ago vs448yca2nz4 \_ redis.3 redis:7.4.0 worker1 Shutdown Shutdown 4 seconds ago
jf1i992619ir redis.4 redis:3.0.6 worker1 Running Running 10 seconds ago jf1i992619ir redis.4 redis:7.4.1 worker1 Running Running 10 seconds ago
blkttv7zs8ee \_ redis.4 redis:3.0.5 worker1 Shutdown Shutdown 11 seconds ago blkttv7zs8ee \_ redis.4 redis:7.4.0 worker1 Shutdown Shutdown 11 seconds ago
``` ```
The number of items in the task history is determined by the The number of items in the task history is determined by the
@ -82,10 +82,10 @@ example:
$ docker service ps --no-trunc redis $ docker service ps --no-trunc redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
50qe8lfnxaxksi9w2a704wkp7 redis.1 redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 manager1 Running Running 5 minutes ago 50qe8lfnxaxksi9w2a704wkp7 redis.1 redis:7.4.1@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 manager1 Running Running 5 minutes ago
ky2re9oz86r9556i2szb8a8af \_ redis.1 redis:3.0.5@sha256:f8829e00d95672c48c60f468329d6693c4bdd28d1f057e755f8ba8b40008682e worker2 Shutdown Shutdown 5 minutes ago ky2re9oz86r9556i2szb8a8af \_ redis.1 redis:7.4.0@sha256:f8829e00d95672c48c60f468329d6693c4bdd28d1f057e755f8ba8b40008682e worker2 Shutdown Shutdown 5 minutes ago
bk658fpbex0d57cqcwoe3jthu redis.2 redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 worker2 Running Running 5 seconds bk658fpbex0d57cqcwoe3jthu redis.2 redis:7.4.1@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 worker2 Running Running 5 seconds
nvjljf7rmor4htv7l8rwcx7i7 \_ redis.2 redis:3.0.6@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 worker2 Shutdown Rejected 5 minutes ago "No such image: redis@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842" nvjljf7rmor4htv7l8rwcx7i7 \_ redis.2 redis:7.4.1@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842 worker2 Shutdown Rejected 5 minutes ago "No such image: redis@sha256:6a692a76c2081888b589e26e6ec835743119fe453d67ecf03df7de5b73d69842"
``` ```
### <a name="filter"></a> Filtering (--filter) ### <a name="filter"></a> Filtering (--filter)
@ -111,8 +111,8 @@ The `id` filter matches on all or a prefix of a task's ID.
$ docker service ps -f "id=8" redis $ docker service ps -f "id=8" redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
8ryt076polmc redis.4 redis:3.0.6 worker1 Running Running 9 seconds 8ryt076polmc redis.4 redis:7.4.1 worker1 Running Running 9 seconds
8eaxrb2fqpbn redis.10 redis:3.0.6 manager1 Running Running 8 seconds 8eaxrb2fqpbn redis.10 redis:7.4.1 manager1 Running Running 8 seconds
``` ```
#### name #### name
@ -123,7 +123,7 @@ The `name` filter matches on task names.
$ docker service ps -f "name=redis.1" redis $ docker service ps -f "name=redis.1" redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
qihejybwf1x5 redis.1 redis:3.0.6 manager1 Running Running 8 seconds qihejybwf1x5 redis.1 redis:7.4.1 manager1 Running Running 8 seconds
``` ```
@ -135,10 +135,10 @@ The `node` filter matches on a node name or a node ID.
$ docker service ps -f "node=manager1" redis $ docker service ps -f "node=manager1" redis
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
0qihejybwf1x redis.1 redis:3.0.6 manager1 Running Running 8 seconds 0qihejybwf1x redis.1 redis:7.4.1 manager1 Running Running 8 seconds
1x0v8yomsncd redis.5 redis:3.0.6 manager1 Running Running 8 seconds 1x0v8yomsncd redis.5 redis:7.4.1 manager1 Running Running 8 seconds
3w1wu13yupln redis.9 redis:3.0.6 manager1 Running Running 8 seconds 3w1wu13yupln redis.9 redis:7.4.1 manager1 Running Running 8 seconds
8eaxrb2fqpbn redis.10 redis:3.0.6 manager1 Running Running 8 seconds 8eaxrb2fqpbn redis.10 redis:7.4.1 manager1 Running Running 8 seconds
``` ```
#### desired-state #### desired-state

View File

@ -84,7 +84,7 @@ $ docker service ls
ID NAME MODE REPLICAS IMAGE ID NAME MODE REPLICAS IMAGE
3pr5mlvu3fh9 frontend replicated 5/5 nginx:alpine 3pr5mlvu3fh9 frontend replicated 5/5 nginx:alpine
74nzcxxjv6fq backend replicated 3/3 redis:3.0.6 74nzcxxjv6fq backend replicated 3/3 redis:7.4.1
``` ```
## Related commands ## Related commands

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.23.2 ARG GO_VERSION=1.23.3
FROM golang:${GO_VERSION}-alpine AS generated FROM golang:${GO_VERSION}-alpine AS generated
ENV GOTOOLCHAIN=local ENV GOTOOLCHAIN=local

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: // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21 //go:build go1.22
package templates package templates