mirror of https://github.com/docker/cli.git
Compare commits
26 Commits
0ae25b3bca
...
9655e76504
Author | SHA1 | Date |
---|---|---|
Sebastiaan van Stijn | 9655e76504 | |
Sebastiaan van Stijn | abb8e9b78a | |
Laura Brehm | 7029147458 | |
Paweł Gronowski | d2b87a0a3b | |
Sebastiaan van Stijn | 24ee5f228a | |
Sebastiaan van Stijn | 8b6133a2b7 | |
Sebastiaan van Stijn | d3f6867e4d | |
Sebastiaan van Stijn | 6b9083776f | |
Sebastiaan van Stijn | fb61156b05 | |
Sebastiaan van Stijn | 062eecf14a | |
Harald Albers | 3f7b156c85 | |
Sebastiaan van Stijn | 54e3685bcd | |
Sebastiaan van Stijn | 87acf77aef | |
Sebastiaan van Stijn | 9b525bc9d1 | |
Sebastiaan van Stijn | 8a7c5ae68f | |
Sebastiaan van Stijn | da9e984231 | |
Sebastiaan van Stijn | 670f81803f | |
Paweł Gronowski | 38653277af | |
Sebastiaan van Stijn | 12dcc6e25c | |
Sebastiaan van Stijn | cbbb917323 | |
Paweł Gronowski | 3590f946a3 | |
David Karlsson | 2c6b80491b | |
Sebastiaan van Stijn | a829217d2f | |
Sebastiaan van Stijn | c2ba0a01b2 | |
Sebastiaan van Stijn | 25b5c27833 | |
Sebastiaan van Stijn | 0b68511f52 |
|
@ -86,7 +86,8 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigureAuth handles prompting of user's username and password if needed.
|
// ConfigureAuth handles prompting of user's username and password if needed.
|
||||||
// Deprecated: use PromptUserForCredentials instead.
|
//
|
||||||
|
// Deprecated: use [PromptUserForCredentials] instead.
|
||||||
func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, authConfig *registrytypes.AuthConfig, _ bool) error {
|
func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, authConfig *registrytypes.AuthConfig, _ bool) error {
|
||||||
defaultUsername := authConfig.Username
|
defaultUsername := authConfig.Username
|
||||||
serverAddress := authConfig.ServerAddress
|
serverAddress := authConfig.ServerAddress
|
||||||
|
|
|
@ -58,9 +58,9 @@ func NewLoginCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyloginOptions(dockerCli command.Cli, opts *loginOptions) error {
|
func verifyLoginOptions(dockerCli command.Cli, opts *loginOptions) error {
|
||||||
if opts.password != "" {
|
if opts.password != "" {
|
||||||
fmt.Fprintln(dockerCli.Err(), "WARNING! Using --password via the CLI is insecure. Use --password-stdin.")
|
_, _ = fmt.Fprintln(dockerCli.Err(), "WARNING! Using --password via the CLI is insecure. Use --password-stdin.")
|
||||||
if opts.passwordStdin {
|
if opts.passwordStdin {
|
||||||
return errors.New("--password and --password-stdin are mutually exclusive")
|
return errors.New("--password and --password-stdin are mutually exclusive")
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ func verifyloginOptions(dockerCli command.Cli, opts *loginOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runLogin(ctx context.Context, dockerCli command.Cli, opts loginOptions) error {
|
func runLogin(ctx context.Context, dockerCli command.Cli, opts loginOptions) error {
|
||||||
if err := verifyloginOptions(dockerCli, &opts); err != nil {
|
if err := verifyLoginOptions(dockerCli, &opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
|
@ -174,7 +174,7 @@ func loginUser(ctx context.Context, dockerCli command.Cli, opts loginOptions, de
|
||||||
if !errors.Is(err, manager.ErrDeviceLoginStartFail) {
|
if !errors.Is(err, manager.ErrDeviceLoginStartFail) {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
fmt.Fprint(dockerCli.Err(), "Failed to start web-based login - falling back to command line login...\n\n")
|
_, _ = fmt.Fprint(dockerCli.Err(), "Failed to start web-based login - falling back to command line login...\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return loginWithUsernameAndPassword(ctx, dockerCli, opts, defaultUsername, serverAddress)
|
return loginWithUsernameAndPassword(ctx, dockerCli, opts, defaultUsername, serverAddress)
|
||||||
|
|
|
@ -199,7 +199,7 @@ func PruneFilters(dockerCli Cli, pruneFilters filters.Args) filters.Args {
|
||||||
// AddPlatformFlag adds `platform` to a set of flags for API version 1.32 and later.
|
// AddPlatformFlag adds `platform` to a set of flags for API version 1.32 and later.
|
||||||
func AddPlatformFlag(flags *pflag.FlagSet, target *string) {
|
func AddPlatformFlag(flags *pflag.FlagSet, target *string) {
|
||||||
flags.StringVar(target, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
|
flags.StringVar(target, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
|
||||||
flags.SetAnnotation("platform", "version", []string{"1.32"})
|
_ = flags.SetAnnotation("platform", "version", []string{"1.32"})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateOutputPath validates the output paths of the `export` and `save` commands.
|
// ValidateOutputPath validates the output paths of the `export` and `save` commands.
|
||||||
|
|
|
@ -30,6 +30,10 @@ func NewFileStore(file store) Store {
|
||||||
|
|
||||||
// Erase removes the given credentials from the file store.
|
// Erase removes the given credentials from the file store.
|
||||||
func (c *fileStore) Erase(serverAddress string) error {
|
func (c *fileStore) Erase(serverAddress string) error {
|
||||||
|
if _, exists := c.file.GetAuthConfigs()[serverAddress]; !exists {
|
||||||
|
// nothing to do; no credentials found for the given serverAddress
|
||||||
|
return nil
|
||||||
|
}
|
||||||
delete(c.file.GetAuthConfigs(), serverAddress)
|
delete(c.file.GetAuthConfigs(), serverAddress)
|
||||||
return c.file.Save()
|
return c.file.Save()
|
||||||
}
|
}
|
||||||
|
@ -70,9 +74,14 @@ https://docs.docker.com/go/credential-store/
|
||||||
// CLI invocation (no need to warn the user multiple times per command).
|
// CLI invocation (no need to warn the user multiple times per command).
|
||||||
var alreadyPrinted atomic.Bool
|
var alreadyPrinted atomic.Bool
|
||||||
|
|
||||||
// Store saves the given credentials in the file store.
|
// Store saves the given credentials in the file store. This function is
|
||||||
|
// idempotent and does not update the file if credentials did not change.
|
||||||
func (c *fileStore) Store(authConfig types.AuthConfig) error {
|
func (c *fileStore) Store(authConfig types.AuthConfig) error {
|
||||||
authConfigs := c.file.GetAuthConfigs()
|
authConfigs := c.file.GetAuthConfigs()
|
||||||
|
if oldAuthConfig, ok := authConfigs[authConfig.ServerAddress]; ok && oldAuthConfig == authConfig {
|
||||||
|
// Credentials didn't change, so skip updating the configuration file.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
authConfigs[authConfig.ServerAddress] = authConfig
|
authConfigs[authConfig.ServerAddress] = authConfig
|
||||||
if err := c.file.Save(); err != nil {
|
if err := c.file.Save(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -5,7 +5,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enabled returns whether cli hints are enabled or not
|
// Enabled returns whether cli hints are enabled or not. Hints are enabled by
|
||||||
|
// default, but can be disabled through the "DOCKER_CLI_HINTS" environment
|
||||||
|
// variable.
|
||||||
func Enabled() bool {
|
func Enabled() bool {
|
||||||
if v := os.Getenv("DOCKER_CLI_HINTS"); v != "" {
|
if v := os.Getenv("DOCKER_CLI_HINTS"); v != "" {
|
||||||
enabled, err := strconv.ParseBool(v)
|
enabled, err := strconv.ParseBool(v)
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
package hints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnabled(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
doc string
|
||||||
|
env string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
doc: "default",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "DOCKER_CLI_HINTS=1",
|
||||||
|
env: "1",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "DOCKER_CLI_HINTS=true",
|
||||||
|
env: "true",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "DOCKER_CLI_HINTS=0",
|
||||||
|
env: "0",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "DOCKER_CLI_HINTS=false",
|
||||||
|
env: "false",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "DOCKER_CLI_HINTS=not-a-bool",
|
||||||
|
env: "not-a-bool",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.doc, func(t *testing.T) {
|
||||||
|
t.Setenv("DOCKER_CLI_HINTS", tc.env)
|
||||||
|
assert.Equal(t, Enabled(), tc.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/cli/cli/command/completion"
|
|
||||||
"github.com/docker/cli/cli/context/store"
|
"github.com/docker/cli/cli/context/store"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -10,18 +9,15 @@ type contextStoreProvider interface {
|
||||||
ContextStore() store.Store
|
ContextStore() store.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerCompletionFuncForGlobalFlags(dockerCLI contextStoreProvider, cmd *cobra.Command) error {
|
func completeContextNames(dockerCLI contextStoreProvider) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
err := cmd.RegisterFlagCompletionFunc("context", func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
return func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
names, _ := store.Names(dockerCLI.ContextStore())
|
names, _ := store.Names(dockerCLI.ContextStore())
|
||||||
return names, cobra.ShellCompDirectiveNoFileComp
|
return names, cobra.ShellCompDirectiveNoFileComp
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
err = cmd.RegisterFlagCompletionFunc("log-level", completion.FromList("debug", "info", "warn", "error", "fatal"))
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
var logLevels = []string{"debug", "info", "warn", "error", "fatal", "panic"}
|
||||||
}
|
|
||||||
|
func completeLogLevels(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
return nil
|
return cobra.FixedCompletions(logLevels, cobra.ShellCompDirectiveNoFileComp)(nil, nil, "")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/context/store"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
is "gotest.tools/v3/assert/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeCLI struct {
|
||||||
|
contextStore store.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeCLI) ContextStore() store.Store {
|
||||||
|
return c.contextStore
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeContextStore struct {
|
||||||
|
store.Store
|
||||||
|
names []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fakeContextStore) List() (c []store.Metadata, _ error) {
|
||||||
|
for _, name := range f.names {
|
||||||
|
c = append(c, store.Metadata{Name: name})
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompleteContextNames(t *testing.T) {
|
||||||
|
expectedNames := []string{"context-b", "context-c", "context-a"}
|
||||||
|
cli := &fakeCLI{
|
||||||
|
contextStore: fakeContextStore{
|
||||||
|
names: expectedNames,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
values, directives := completeContextNames(cli)(nil, nil, "")
|
||||||
|
assert.Check(t, is.Equal(directives, cobra.ShellCompDirectiveNoFileComp))
|
||||||
|
assert.Check(t, is.DeepEqual(values, expectedNames))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompleteLogLevels(t *testing.T) {
|
||||||
|
values, directives := completeLogLevels(nil, nil, "")
|
||||||
|
assert.Check(t, is.Equal(directives, cobra.ShellCompDirectiveNoFileComp))
|
||||||
|
assert.Check(t, is.DeepEqual(values, logLevels))
|
||||||
|
}
|
|
@ -100,7 +100,11 @@ func newDockerCommand(dockerCli *command.DockerCli) *cli.TopLevelCommand {
|
||||||
cmd.SetErr(dockerCli.Err())
|
cmd.SetErr(dockerCli.Err())
|
||||||
|
|
||||||
opts, helpCmd = cli.SetupRootCommand(cmd)
|
opts, helpCmd = cli.SetupRootCommand(cmd)
|
||||||
_ = registerCompletionFuncForGlobalFlags(dockerCli, cmd)
|
|
||||||
|
// TODO(thaJeztah): move configuring completion for these flags to where the flags are added.
|
||||||
|
_ = cmd.RegisterFlagCompletionFunc("context", completeContextNames(dockerCli))
|
||||||
|
_ = cmd.RegisterFlagCompletionFunc("log-level", completeLogLevels)
|
||||||
|
|
||||||
cmd.Flags().BoolP("version", "v", false, "Print version information and quit")
|
cmd.Flags().BoolP("version", "v", false, "Print version information and quit")
|
||||||
setFlagErrorFunc(dockerCli, cmd)
|
setFlagErrorFunc(dockerCli, cmd)
|
||||||
|
|
||||||
|
|
|
@ -5081,7 +5081,7 @@ _docker_system_events() {
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
daemon)
|
daemon)
|
||||||
local name=$(__docker_q info | sed -n 's/^\(ID\|Name\): //p')
|
local name=$(__docker_q info --format '{{.Info.Name}} {{.Info.ID}}')
|
||||||
COMPREPLY=( $( compgen -W "$name" -- "${cur##*=}" ) )
|
COMPREPLY=( $( compgen -W "$name" -- "${cur##*=}" ) )
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -31,6 +31,7 @@ target "_platforms" {
|
||||||
"darwin/amd64",
|
"darwin/amd64",
|
||||||
"darwin/arm64",
|
"darwin/arm64",
|
||||||
"linux/amd64",
|
"linux/amd64",
|
||||||
|
"linux/arm/v5",
|
||||||
"linux/arm/v6",
|
"linux/arm/v6",
|
||||||
"linux/arm/v7",
|
"linux/arm/v7",
|
||||||
"linux/arm64",
|
"linux/arm64",
|
||||||
|
@ -183,6 +184,7 @@ target "bin-image-cross" {
|
||||||
"darwin/amd64",
|
"darwin/amd64",
|
||||||
"darwin/arm64",
|
"darwin/arm64",
|
||||||
"linux/amd64",
|
"linux/amd64",
|
||||||
|
"linux/arm/v5",
|
||||||
"linux/arm/v6",
|
"linux/arm/v6",
|
||||||
"linux/arm/v7",
|
"linux/arm/v7",
|
||||||
"linux/arm64",
|
"linux/arm64",
|
||||||
|
|
|
@ -3,7 +3,7 @@ module github.com/docker/cli/docs/generate
|
||||||
// dummy go.mod to avoid dealing with dependencies specific
|
// dummy go.mod to avoid dealing with dependencies specific
|
||||||
// to docs generation and not really part of the project.
|
// to docs generation and not really part of the project.
|
||||||
|
|
||||||
go 1.16
|
go 1.22.0
|
||||||
|
|
||||||
//require (
|
//require (
|
||||||
// github.com/docker/cli v0.0.0+incompatible
|
// github.com/docker/cli v0.0.0+incompatible
|
||||||
|
|
|
@ -12,38 +12,50 @@ Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
A full image name has the following format and components:
|
A Docker image reference consists of several components that describe where the
|
||||||
|
image is stored and its identity. These components are:
|
||||||
|
|
||||||
`[HOST[:PORT_NUMBER]/]PATH`
|
```text
|
||||||
|
[HOST[:PORT]/]NAMESPACE/REPOSITORY[:TAG]
|
||||||
|
```
|
||||||
|
|
||||||
- `HOST`: The optional registry hostname specifies where the image is located.
|
`HOST`
|
||||||
The hostname must comply with standard DNS rules, but may not contain
|
: Specifies the registry location where the image resides. If omitted, Docker
|
||||||
underscores. If you don't specify a hostname, the command uses Docker's public
|
defaults to Docker Hub (`docker.io`).
|
||||||
registry at `registry-1.docker.io` by default. Note that `docker.io` is the
|
|
||||||
canonical reference for Docker's public registry.
|
|
||||||
- `PORT_NUMBER`: If a hostname is present, it may optionally be followed by a
|
|
||||||
registry port number in the format `:8080`.
|
|
||||||
- `PATH`: The path consists of slash-separated components. Each
|
|
||||||
component may contain lowercase letters, digits and separators. A separator is
|
|
||||||
defined as a period, one or two underscores, or one or more hyphens. A component
|
|
||||||
may not start or end with a separator. While the
|
|
||||||
[OCI Distribution Specification](https://github.com/opencontainers/distribution-spec)
|
|
||||||
supports more than two slash-separated components, most registries only support
|
|
||||||
two slash-separated components. For Docker's public registry, the path format is
|
|
||||||
as follows:
|
|
||||||
- `[NAMESPACE/]REPOSITORY`: The first, optional component is typically a
|
|
||||||
user's or an organization's namespace. The second, mandatory component is the
|
|
||||||
repository name. When the namespace is not present, Docker uses `library`
|
|
||||||
as the default namespace.
|
|
||||||
|
|
||||||
After the image name, the optional `TAG` is a custom, human-readable manifest
|
`PORT`
|
||||||
identifier that's typically a specific version or variant of an image. The tag
|
: An optional port number for the registry, if necessary (for example, `:5000`).
|
||||||
must be valid ASCII and can contain lowercase and uppercase letters, digits,
|
|
||||||
underscores, periods, and hyphens. It can't start with a period or hyphen and
|
|
||||||
must be no longer than 128 characters. If you don't specify a tag, the command uses `latest` by default.
|
|
||||||
|
|
||||||
You can group your images together using names and tags, and then
|
`NAMESPACE/REPOSITORY`
|
||||||
[push](image_push.md) them to a registry.
|
: The namespace (optional) usually represents a user or organization. The
|
||||||
|
repository is required and identifies the specific image. If the namespace is
|
||||||
|
omitted, Docker defaults to `library`, the namespace reserved for Docker
|
||||||
|
Official Images.
|
||||||
|
|
||||||
|
`TAG`
|
||||||
|
: An optional identifier used to specify a particular version or variant of the
|
||||||
|
image. If no tag is provided, Docker defaults to `latest`.
|
||||||
|
|
||||||
|
### Example image references
|
||||||
|
|
||||||
|
`example.com:5000/team/my-app:2.0`
|
||||||
|
|
||||||
|
- Host: `example.com`
|
||||||
|
- Port: `5000`
|
||||||
|
- Namespace: `team`
|
||||||
|
- Repository: `my-app`
|
||||||
|
- Tag: `2.0`
|
||||||
|
|
||||||
|
`alpine`
|
||||||
|
|
||||||
|
- Host: `docker.io` (default)
|
||||||
|
- Namespace: `library` (default)
|
||||||
|
- Repository: `alpine`
|
||||||
|
- Tag: `latest` (default)
|
||||||
|
|
||||||
|
For more information on the structure and rules of image naming, refer to the
|
||||||
|
[Distribution reference](https://pkg.go.dev/github.com/distribution/reference#pkg-overview)
|
||||||
|
as the canonical definition of the format.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ module github.com/docker/cli/man
|
||||||
// dummy go.mod to avoid dealing with dependencies specific
|
// dummy go.mod to avoid dealing with dependencies specific
|
||||||
// to manpages generation and not really part of the project.
|
// to manpages generation and not really part of the project.
|
||||||
|
|
||||||
go 1.16
|
go 1.12.0
|
||||||
|
|
||||||
//require (
|
//require (
|
||||||
// github.com/docker/cli v0.0.0+incompatible
|
// github.com/docker/cli v0.0.0+incompatible
|
||||||
|
|
|
@ -21,5 +21,5 @@ for p in cli-plugins/examples/* "$@" ; do
|
||||||
mkdir -p "$(dirname "${TARGET_PLUGIN}")"
|
mkdir -p "$(dirname "${TARGET_PLUGIN}")"
|
||||||
|
|
||||||
echo "Building $GO_LINKMODE $(basename "${TARGET_PLUGIN}")"
|
echo "Building $GO_LINKMODE $(basename "${TARGET_PLUGIN}")"
|
||||||
(set -x ; GO111MODULE=auto go build -o "${TARGET_PLUGIN}" -tags "${GO_BUILDTAGS}" -ldflags "${GO_LDFLAGS}" ${GO_BUILDMODE} "github.com/docker/cli/${p}")
|
(set -x ; GO111MODULE=auto go build -o "${TARGET_PLUGIN}" -tags "${GO_BUILDTAGS}" -ldflags "${GO_LDFLAGS}" "github.com/docker/cli/${p}")
|
||||||
done
|
done
|
||||||
|
|
|
@ -18,7 +18,7 @@ init() {
|
||||||
cat > go.mod <<EOL
|
cat > go.mod <<EOL
|
||||||
module github.com/docker/cli
|
module github.com/docker/cli
|
||||||
|
|
||||||
go 1.19
|
go 1.22.0
|
||||||
EOL
|
EOL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,3 +89,55 @@ func TestParseTruncateFunction(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHeaderFunctions(t *testing.T) {
|
||||||
|
const source = "hello world"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
doc string
|
||||||
|
template string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
doc: "json",
|
||||||
|
template: `{{ json .}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "split",
|
||||||
|
template: `{{ split . ","}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "join",
|
||||||
|
template: `{{ join . ","}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "title",
|
||||||
|
template: `{{ title .}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "lower",
|
||||||
|
template: `{{ lower .}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "upper",
|
||||||
|
template: `{{ upper .}}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "truncate",
|
||||||
|
template: `{{ truncate . 2}}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.doc, func(t *testing.T) {
|
||||||
|
tmpl, err := New("").Funcs(HeaderFunctions).Parse(tc.template)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
assert.NilError(t, tmpl.Execute(&b, source))
|
||||||
|
|
||||||
|
// All header-functions are currently stubs, and don't modify the input.
|
||||||
|
expected := source
|
||||||
|
assert.Equal(t, expected, b.String())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ module github.com/docker/cli
|
||||||
// There is no 'go.mod' file, as that would imply opting in for all the rules
|
// There is no 'go.mod' file, as that would imply opting in for all the rules
|
||||||
// around SemVer, which this repo cannot abide by as it uses CalVer.
|
// around SemVer, which this repo cannot abide by as it uses CalVer.
|
||||||
|
|
||||||
go 1.21.0
|
go 1.22.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
dario.cat/mergo v1.0.1
|
dario.cat/mergo v1.0.1
|
||||||
|
@ -13,7 +13,7 @@ require (
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli-docs-tool v0.8.0
|
github.com/docker/cli-docs-tool v0.8.0
|
||||||
github.com/docker/distribution v2.8.3+incompatible
|
github.com/docker/distribution v2.8.3+incompatible
|
||||||
github.com/docker/docker v27.0.2-0.20240912171519-164cae56ed95+incompatible // master (v-next)
|
github.com/docker/docker v27.0.2-0.20241018142220-36a3bd090489+incompatible // master (v-next)
|
||||||
github.com/docker/docker-credential-helpers v0.8.2
|
github.com/docker/docker-credential-helpers v0.8.2
|
||||||
github.com/docker/go-connections v0.5.0
|
github.com/docker/go-connections v0.5.0
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
|
@ -25,7 +25,7 @@ require (
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/mattn/go-runewidth v0.0.15
|
github.com/mattn/go-runewidth v0.0.15
|
||||||
github.com/moby/patternmatcher v0.6.0
|
github.com/moby/patternmatcher v0.6.0
|
||||||
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb
|
github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
|
||||||
github.com/moby/sys/capability v0.3.0
|
github.com/moby/sys/capability v0.3.0
|
||||||
github.com/moby/sys/sequential v0.6.0
|
github.com/moby/sys/sequential v0.6.0
|
||||||
github.com/moby/sys/signal v0.7.1
|
github.com/moby/sys/signal v0.7.1
|
||||||
|
|
|
@ -57,8 +57,8 @@ github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsB
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
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 h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v27.0.2-0.20240912171519-164cae56ed95+incompatible h1:HRK75BHG33htes7s+v/fJ8saCNw3B7f3spcgLsvbLRQ=
|
github.com/docker/docker v27.0.2-0.20241018142220-36a3bd090489+incompatible h1:utxxyIvPGk7UmtlGHirUyNUP2Spf8yL660PCbmb7tsk=
|
||||||
github.com/docker/docker v27.0.2-0.20240912171519-164cae56ed95+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v27.0.2-0.20241018142220-36a3bd090489+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||||
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 h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||||
|
@ -180,8 +180,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
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/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb h1:1UTTg2EgO3nuyV03wREDzldqqePzQ4+0a5G1C1y1bIo=
|
github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e h1:1yC8fRqStY6NirU/swI74fsrHvZVMbtxsHcvl8YpzDg=
|
||||||
github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb/go.mod h1:kNy225f/gWAnF8wPftteMc5nbAHhrH+HUfvyjmhFjeQ=
|
github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e/go.mod h1:mTTGIAz/59OGZR5Qe+QByIe3Nxc+sSuJkrsStFhr6Lg=
|
||||||
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
|
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
|
||||||
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||||
|
|
|
@ -6005,7 +6005,7 @@ definitions:
|
||||||
accept un-encrypted (HTTP) and/or untrusted (HTTPS with certificates
|
accept un-encrypted (HTTP) and/or untrusted (HTTPS with certificates
|
||||||
from unknown CAs) communication.
|
from unknown CAs) communication.
|
||||||
|
|
||||||
By default, local registries (`127.0.0.0/8`) are configured as
|
By default, local registries (`::1/128` and `127.0.0.0/8`) are configured as
|
||||||
insecure. All other registries are secure. Communicating with an
|
insecure. All other registries are secure. Communicating with an
|
||||||
insecure registry is not possible if the daemon assumes that registry
|
insecure registry is not possible if the daemon assumes that registry
|
||||||
is secure.
|
is secure.
|
||||||
|
@ -6170,6 +6170,8 @@ definitions:
|
||||||
Expected:
|
Expected:
|
||||||
description: |
|
description: |
|
||||||
Commit ID of external tool expected by dockerd as set at build time.
|
Commit ID of external tool expected by dockerd as set at build time.
|
||||||
|
|
||||||
|
**Deprecated**: This field is deprecated and will be omitted in a API v1.49.
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4"
|
example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4"
|
||||||
|
|
||||||
|
@ -7881,10 +7883,12 @@ paths:
|
||||||
type: "string"
|
type: "string"
|
||||||
- name: "h"
|
- name: "h"
|
||||||
in: "query"
|
in: "query"
|
||||||
|
required: true
|
||||||
description: "Height of the TTY session in characters"
|
description: "Height of the TTY session in characters"
|
||||||
type: "integer"
|
type: "integer"
|
||||||
- name: "w"
|
- name: "w"
|
||||||
in: "query"
|
in: "query"
|
||||||
|
required: true
|
||||||
description: "Width of the TTY session in characters"
|
description: "Width of the TTY session in characters"
|
||||||
type: "integer"
|
type: "integer"
|
||||||
tags: ["Container"]
|
tags: ["Container"]
|
||||||
|
@ -10236,10 +10240,12 @@ paths:
|
||||||
type: "string"
|
type: "string"
|
||||||
- name: "h"
|
- name: "h"
|
||||||
in: "query"
|
in: "query"
|
||||||
|
required: true
|
||||||
description: "Height of the TTY session in characters"
|
description: "Height of the TTY session in characters"
|
||||||
type: "integer"
|
type: "integer"
|
||||||
- name: "w"
|
- name: "w"
|
||||||
in: "query"
|
in: "query"
|
||||||
|
required: true
|
||||||
description: "Width of the TTY session in characters"
|
description: "Width of the TTY session in characters"
|
||||||
type: "integer"
|
type: "integer"
|
||||||
tags: ["Exec"]
|
tags: ["Exec"]
|
||||||
|
|
|
@ -137,8 +137,13 @@ type PluginsInfo struct {
|
||||||
// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
|
// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
|
||||||
// in the version-string of external tools, such as containerd, or runC.
|
// in the version-string of external tools, such as containerd, or runC.
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
ID string // ID is the actual commit ID of external tool.
|
// ID is the actual commit ID or version of external tool.
|
||||||
Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time.
|
ID string
|
||||||
|
|
||||||
|
// Expected is the commit ID of external tool expected by dockerd as set at build time.
|
||||||
|
//
|
||||||
|
// Deprecated: this field is no longer used in API v1.49, but kept for backward-compatibility with older API versions.
|
||||||
|
Expected string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkAddressPool is a temp struct used by [Info] struct.
|
// NetworkAddressPool is a temp struct used by [Info] struct.
|
||||||
|
|
|
@ -172,4 +172,6 @@ type BuildCachePruneOptions struct {
|
||||||
All bool
|
All bool
|
||||||
KeepStorage int64
|
KeepStorage int64
|
||||||
Filters filters.Args
|
Filters filters.Args
|
||||||
|
|
||||||
|
// FIXME(thaJeztah): add new options; see https://github.com/moby/moby/issues/48639
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Package client is a Go client for the Docker Engine API.
|
Package client is a Go client for the Docker Engine API.
|
||||||
|
|
||||||
For more information about the Engine API, see the documentation:
|
For more information about the Engine API, see the documentation:
|
||||||
https://docs.docker.com/engine/api/
|
https://docs.docker.com/reference/api/engine/
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
|
@ -12,12 +14,6 @@ import (
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type configWrapper struct {
|
|
||||||
*container.Config
|
|
||||||
HostConfig *container.HostConfig
|
|
||||||
NetworkingConfig *network.NetworkingConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerCreate creates a new container based on the given configuration.
|
// ContainerCreate creates a new container based on the given configuration.
|
||||||
// It can be associated with a name, but it's not mandatory.
|
// It can be associated with a name, but it's not mandatory.
|
||||||
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
|
||||||
|
@ -58,6 +54,9 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
|
||||||
// When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize
|
// When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize
|
||||||
hostConfig.ConsoleSize = [2]uint{0, 0}
|
hostConfig.ConsoleSize = [2]uint{0, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd)
|
||||||
|
hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since API 1.44, the container-wide MacAddress is deprecated and will trigger a WARNING if it's specified.
|
// Since API 1.44, the container-wide MacAddress is deprecated and will trigger a WARNING if it's specified.
|
||||||
|
@ -74,7 +73,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
|
||||||
query.Set("name", containerName)
|
query.Set("name", containerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := configWrapper{
|
body := container.CreateRequest{
|
||||||
Config: config,
|
Config: config,
|
||||||
HostConfig: hostConfig,
|
HostConfig: hostConfig,
|
||||||
NetworkingConfig: networkingConfig,
|
NetworkingConfig: networkingConfig,
|
||||||
|
@ -114,3 +113,42 @@ func hasEndpointSpecificMacAddress(networkingConfig *network.NetworkingConfig) b
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allCapabilities is a magic value for "all capabilities"
|
||||||
|
const allCapabilities = "ALL"
|
||||||
|
|
||||||
|
// normalizeCapabilities normalizes capabilities to their canonical form,
|
||||||
|
// removes duplicates, and sorts the results.
|
||||||
|
//
|
||||||
|
// It is similar to [github.com/docker/docker/oci/caps.NormalizeLegacyCapabilities],
|
||||||
|
// but performs no validation based on supported capabilities.
|
||||||
|
func normalizeCapabilities(caps []string) []string {
|
||||||
|
var normalized []string
|
||||||
|
|
||||||
|
unique := make(map[string]struct{})
|
||||||
|
for _, c := range caps {
|
||||||
|
c = normalizeCap(c)
|
||||||
|
if _, ok := unique[c]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
unique[c] = struct{}{}
|
||||||
|
normalized = append(normalized, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(normalized)
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizeCap normalizes a capability to its canonical format by upper-casing
|
||||||
|
// and adding a "CAP_" prefix (if not yet present). It also accepts the "ALL"
|
||||||
|
// magic-value.
|
||||||
|
func normalizeCap(cap string) string {
|
||||||
|
cap = strings.ToUpper(cap)
|
||||||
|
if cap == allCapabilities {
|
||||||
|
return cap
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(cap, "CAP_") {
|
||||||
|
cap = "CAP_" + cap
|
||||||
|
}
|
||||||
|
return cap
|
||||||
|
}
|
||||||
|
|
|
@ -19,9 +19,10 @@ func (cli *Client) ContainerExecResize(ctx context.Context, execID string, optio
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) resize(ctx context.Context, basePath string, height, width uint) error {
|
func (cli *Client) resize(ctx context.Context, basePath string, height, width uint) error {
|
||||||
|
// FIXME(thaJeztah): the API / backend accepts uint32, but container.ResizeOptions uses uint.
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
query.Set("h", strconv.Itoa(int(height)))
|
query.Set("h", strconv.FormatUint(uint64(height), 10))
|
||||||
query.Set("w", strconv.Itoa(int(width)))
|
query.Set("w", strconv.FormatUint(uint64(width), 10))
|
||||||
|
|
||||||
resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil)
|
resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil)
|
||||||
ensureReaderClosed(resp)
|
ensureReaderClosed(resp)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageBuild sends a request to the daemon to build images.
|
// ImageBuild sends a request to the daemon to build images.
|
||||||
|
@ -44,10 +45,15 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.ImageBuildOptions) (url.Values, error) {
|
func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.ImageBuildOptions) (url.Values, error) {
|
||||||
query := url.Values{
|
query := url.Values{}
|
||||||
"t": options.Tags,
|
if len(options.Tags) > 0 {
|
||||||
"securityopt": options.SecurityOpt,
|
query["t"] = options.Tags
|
||||||
"extrahosts": options.ExtraHosts,
|
}
|
||||||
|
if len(options.SecurityOpt) > 0 {
|
||||||
|
query["securityopt"] = options.SecurityOpt
|
||||||
|
}
|
||||||
|
if len(options.ExtraHosts) > 0 {
|
||||||
|
query["extrahosts"] = options.ExtraHosts
|
||||||
}
|
}
|
||||||
if options.SuppressOutput {
|
if options.SuppressOutput {
|
||||||
query.Set("q", "1")
|
query.Set("q", "1")
|
||||||
|
@ -58,9 +64,11 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I
|
||||||
if options.NoCache {
|
if options.NoCache {
|
||||||
query.Set("nocache", "1")
|
query.Set("nocache", "1")
|
||||||
}
|
}
|
||||||
if options.Remove {
|
if !options.Remove {
|
||||||
query.Set("rm", "1")
|
// only send value when opting out because the daemon's default is
|
||||||
} else {
|
// to remove intermediate containers after a successful build,
|
||||||
|
//
|
||||||
|
// TODO(thaJeztah): deprecate "Remove" option, and provide a "NoRemove" or "Keep" option instead.
|
||||||
query.Set("rm", "0")
|
query.Set("rm", "0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,42 +91,70 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I
|
||||||
query.Set("isolation", string(options.Isolation))
|
query.Set("isolation", string(options.Isolation))
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Set("cpusetcpus", options.CPUSetCPUs)
|
if options.CPUSetCPUs != "" {
|
||||||
query.Set("networkmode", options.NetworkMode)
|
query.Set("cpusetcpus", options.CPUSetCPUs)
|
||||||
query.Set("cpusetmems", options.CPUSetMems)
|
|
||||||
query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
|
|
||||||
query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
|
|
||||||
query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
|
|
||||||
query.Set("memory", strconv.FormatInt(options.Memory, 10))
|
|
||||||
query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
|
|
||||||
query.Set("cgroupparent", options.CgroupParent)
|
|
||||||
query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
|
|
||||||
query.Set("dockerfile", options.Dockerfile)
|
|
||||||
query.Set("target", options.Target)
|
|
||||||
|
|
||||||
ulimitsJSON, err := json.Marshal(options.Ulimits)
|
|
||||||
if err != nil {
|
|
||||||
return query, err
|
|
||||||
}
|
}
|
||||||
query.Set("ulimits", string(ulimitsJSON))
|
if options.NetworkMode != "" && options.NetworkMode != network.NetworkDefault {
|
||||||
|
query.Set("networkmode", options.NetworkMode)
|
||||||
buildArgsJSON, err := json.Marshal(options.BuildArgs)
|
|
||||||
if err != nil {
|
|
||||||
return query, err
|
|
||||||
}
|
}
|
||||||
query.Set("buildargs", string(buildArgsJSON))
|
if options.CPUSetMems != "" {
|
||||||
|
query.Set("cpusetmems", options.CPUSetMems)
|
||||||
labelsJSON, err := json.Marshal(options.Labels)
|
|
||||||
if err != nil {
|
|
||||||
return query, err
|
|
||||||
}
|
}
|
||||||
query.Set("labels", string(labelsJSON))
|
if options.CPUShares != 0 {
|
||||||
|
query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
|
||||||
cacheFromJSON, err := json.Marshal(options.CacheFrom)
|
}
|
||||||
if err != nil {
|
if options.CPUQuota != 0 {
|
||||||
return query, err
|
query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
|
||||||
|
}
|
||||||
|
if options.CPUPeriod != 0 {
|
||||||
|
query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
|
||||||
|
}
|
||||||
|
if options.Memory != 0 {
|
||||||
|
query.Set("memory", strconv.FormatInt(options.Memory, 10))
|
||||||
|
}
|
||||||
|
if options.MemorySwap != 0 {
|
||||||
|
query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
|
||||||
|
}
|
||||||
|
if options.CgroupParent != "" {
|
||||||
|
query.Set("cgroupparent", options.CgroupParent)
|
||||||
|
}
|
||||||
|
if options.ShmSize != 0 {
|
||||||
|
query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
|
||||||
|
}
|
||||||
|
if options.Dockerfile != "" {
|
||||||
|
query.Set("dockerfile", options.Dockerfile)
|
||||||
|
}
|
||||||
|
if options.Target != "" {
|
||||||
|
query.Set("target", options.Target)
|
||||||
|
}
|
||||||
|
if len(options.Ulimits) != 0 {
|
||||||
|
ulimitsJSON, err := json.Marshal(options.Ulimits)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
query.Set("ulimits", string(ulimitsJSON))
|
||||||
|
}
|
||||||
|
if len(options.BuildArgs) != 0 {
|
||||||
|
buildArgsJSON, err := json.Marshal(options.BuildArgs)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
query.Set("buildargs", string(buildArgsJSON))
|
||||||
|
}
|
||||||
|
if len(options.Labels) != 0 {
|
||||||
|
labelsJSON, err := json.Marshal(options.Labels)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
query.Set("labels", string(labelsJSON))
|
||||||
|
}
|
||||||
|
if len(options.CacheFrom) != 0 {
|
||||||
|
cacheFromJSON, err := json.Marshal(options.CacheFrom)
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
query.Set("cachefrom", string(cacheFromJSON))
|
||||||
}
|
}
|
||||||
query.Set("cachefrom", string(cacheFromJSON))
|
|
||||||
if options.SessionID != "" {
|
if options.SessionID != "" {
|
||||||
query.Set("session", options.SessionID)
|
query.Set("session", options.SessionID)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +167,9 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I
|
||||||
if options.BuildID != "" {
|
if options.BuildID != "" {
|
||||||
query.Set("buildid", options.BuildID)
|
query.Set("buildid", options.BuildID)
|
||||||
}
|
}
|
||||||
query.Set("version", string(options.Version))
|
if options.Version != "" {
|
||||||
|
query.Set("version", string(options.Version))
|
||||||
|
}
|
||||||
|
|
||||||
if options.Outputs != nil {
|
if options.Outputs != nil {
|
||||||
outputsJSON, err := json.Marshal(options.Outputs)
|
outputsJSON, err := json.Marshal(options.Outputs)
|
||||||
|
|
|
@ -654,7 +654,7 @@ func (ta *tarAppender) addTarFile(path, name string) error {
|
||||||
|
|
||||||
ta.Buffer.Reset(ta.TarWriter)
|
ta.Buffer.Reset(ta.TarWriter)
|
||||||
defer ta.Buffer.Reset(nil)
|
defer ta.Buffer.Reset(nil)
|
||||||
_, err = io.Copy(ta.Buffer, file)
|
_, err = pools.Copy(ta.Buffer, file)
|
||||||
file.Close()
|
file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -705,7 +705,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(file, reader); err != nil {
|
if _, err := pools.Copy(file, reader); err != nil {
|
||||||
file.Close()
|
file.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1375,7 +1375,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
|
||||||
if err := tw.WriteHeader(hdr); err != nil {
|
if err := tw.WriteHeader(hdr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(tw, srcF); err != nil {
|
if _, err := pools.Copy(tw, srcF); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -184,7 +184,7 @@ func (config *serviceConfig) loadMirrors(mirrors []string) error {
|
||||||
func (config *serviceConfig) loadInsecureRegistries(registries []string) error {
|
func (config *serviceConfig) loadInsecureRegistries(registries []string) error {
|
||||||
// Localhost is by default considered as an insecure registry. This is a
|
// Localhost is by default considered as an insecure registry. This is a
|
||||||
// stop-gap for people who are running a private registry on localhost.
|
// stop-gap for people who are running a private registry on localhost.
|
||||||
registries = append(registries, "127.0.0.0/8")
|
registries = append(registries, "::1/128", "127.0.0.0/8")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
insecureRegistryCIDRs = make([]*registry.NetIPNet, 0)
|
insecureRegistryCIDRs = make([]*registry.NetIPNet, 0)
|
||||||
|
|
|
@ -55,7 +55,7 @@ github.com/docker/distribution/registry/client/transport
|
||||||
github.com/docker/distribution/registry/storage/cache
|
github.com/docker/distribution/registry/storage/cache
|
||||||
github.com/docker/distribution/registry/storage/cache/memory
|
github.com/docker/distribution/registry/storage/cache/memory
|
||||||
github.com/docker/distribution/uuid
|
github.com/docker/distribution/uuid
|
||||||
# github.com/docker/docker v27.0.2-0.20240912171519-164cae56ed95+incompatible
|
# github.com/docker/docker v27.0.2-0.20241018142220-36a3bd090489+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/docker/api
|
github.com/docker/docker/api
|
||||||
github.com/docker/docker/api/types
|
github.com/docker/docker/api/types
|
||||||
|
@ -197,7 +197,7 @@ github.com/moby/docker-image-spec/specs-go/v1
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/moby/patternmatcher
|
github.com/moby/patternmatcher
|
||||||
github.com/moby/patternmatcher/ignorefile
|
github.com/moby/patternmatcher/ignorefile
|
||||||
# github.com/moby/swarmkit/v2 v2.0.0-20240611172349-ea1a7cec35cb
|
# github.com/moby/swarmkit/v2 v2.0.0-20241017191044-e8ecf83ee08e
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/moby/swarmkit/v2/api
|
github.com/moby/swarmkit/v2/api
|
||||||
github.com/moby/swarmkit/v2/api/deepcopy
|
github.com/moby/swarmkit/v2/api/deepcopy
|
||||||
|
|
Loading…
Reference in New Issue