mirror of
https://github.com/docker/cli.git
synced 2026-08-26 10:05:28 -05:00
Compare commits
222
Commits
@@ -58,7 +58,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v3
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
set: |
|
||||
@@ -74,13 +74,13 @@ jobs:
|
||||
platformPair=${platform//\//-}
|
||||
tar -cvzf "/tmp/out/docker-${platformPair}.tar.gz" .
|
||||
if [ -z "${{ matrix.use_glibc }}" ]; then
|
||||
echo "ARTIFACT_NAME=${{ matrix.target }}-${platformPair}" >> $GITHUB_ENV
|
||||
echo "ARTIFACT_NAME=${{ matrix.target }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ARTIFACT_NAME=${{ matrix.target }}-${platformPair}-glibc" >> $GITHUB_ENV
|
||||
echo "ARTIFACT_NAME=${{ matrix.target }}-glibc" >> $GITHUB_ENV
|
||||
fi
|
||||
-
|
||||
name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: /tmp/out/*
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@v3
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: plugins-cross
|
||||
set: |
|
||||
|
||||
@@ -16,9 +16,6 @@ on:
|
||||
jobs:
|
||||
codeql:
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
DISABLE_WARN_OUTSIDE_CONTAINER: '1'
|
||||
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
@@ -35,16 +32,6 @@ jobs:
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: go
|
||||
# CodeQL 2.16.4's auto-build added support for multi-module repositories,
|
||||
# and is trying to be smart by searching for modules in every directory,
|
||||
# including vendor directories. If no module is found, it's creating one
|
||||
# which is ... not what we want, so let's give it a "go.mod".
|
||||
# see: https://github.com/docker/cli/pull/4944#issuecomment-2002034698
|
||||
-
|
||||
name: Create go.mod
|
||||
run: |
|
||||
ln -s vendor.mod go.mod
|
||||
ln -s vendor.sum go.sum
|
||||
-
|
||||
name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v3
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: test-coverage
|
||||
-
|
||||
@@ -45,8 +45,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- macos-13 # macOS 13 on Intel
|
||||
- macos-14 # macOS 14 on arm64 (Apple Silicon M1)
|
||||
- macos-11
|
||||
# - windows-2022 # FIXME: some tests are failing on the Windows runner, as well as on Appveyor since June 24, 2018: https://ci.appveyor.com/project/docker/cli/history
|
||||
steps:
|
||||
-
|
||||
@@ -62,9 +61,9 @@ jobs:
|
||||
path: ${{ env.GOPATH }}/src/github.com/docker/cli
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.22.6
|
||||
go-version: 1.20.3
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
@@ -78,4 +77,3 @@ jobs:
|
||||
with:
|
||||
file: /tmp/coverage.txt
|
||||
working-directory: ${{ env.GOPATH }}/src/github.com/docker/cli
|
||||
version: v0.7.3 # Work around https://github.com/codecov/uploader/issues/1687 -- uploader v0.8.0 for mac is built for arm64, not x86_64
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Run
|
||||
uses: docker/bake-action@v3
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
|
||||
+12
-18
@@ -26,26 +26,27 @@ linters:
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
skip-files:
|
||||
- cli/compose/schema/bindata.go
|
||||
- .*generated.*
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
deny:
|
||||
- pkg: io/ioutil
|
||||
desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
|
||||
list-type: blacklist
|
||||
include-go-root: true
|
||||
packages:
|
||||
# The io/ioutil package has been deprecated.
|
||||
# https://go.dev/doc/go1.16#ioutil
|
||||
- io/ioutil
|
||||
gocyclo:
|
||||
min-complexity: 16
|
||||
govet:
|
||||
check-shadowing: false
|
||||
lll:
|
||||
line-length: 200
|
||||
nakedret:
|
||||
command: nakedret
|
||||
pattern: ^(?P<path>.*?\\.go):(?P<line>\\d+)\\s*(?P<message>.*)$
|
||||
revive:
|
||||
rules:
|
||||
- name: unused-parameter
|
||||
severity: warning
|
||||
disabled: true
|
||||
|
||||
issues:
|
||||
# The default exclusion rules are a bit too permissive, so copying the relevant ones below
|
||||
@@ -54,10 +55,6 @@ issues:
|
||||
exclude:
|
||||
- parameter .* always receives
|
||||
|
||||
exclude-files:
|
||||
- cli/compose/schema/bindata.go
|
||||
- .*generated.*
|
||||
|
||||
exclude-rules:
|
||||
# We prefer to use an "exclude-list" so that new "default" exclusions are not
|
||||
# automatically inherited. We can decide whether or not to follow upstream
|
||||
@@ -120,10 +117,7 @@ issues:
|
||||
- text: "package-comments: should have a package comment"
|
||||
linters:
|
||||
- revive
|
||||
# FIXME temporarily suppress these (see https://github.com/gotestyourself/gotest.tools/issues/272)
|
||||
- text: "SA1019: (assert|cmp|is)\\.ErrorType is deprecated"
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
|
||||
+26
-26
@@ -1,18 +1,17 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.22.6
|
||||
ARG ALPINE_VERSION=3.20
|
||||
ARG XX_VERSION=1.6.1
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG XX_VERSION=1.1.1
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
ARG GOTESTSUM_VERSION=v1.10.0
|
||||
ARG BUILDX_VERSION=0.11.2
|
||||
ARG COMPOSE_VERSION=v2.22.0
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS build-base-alpine
|
||||
COPY --link --from=xx / /
|
||||
COPY --from=xx / /
|
||||
RUN apk add --no-cache bash clang lld llvm file git
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
|
||||
@@ -22,7 +21,7 @@ ARG TARGETPLATFORM
|
||||
RUN xx-apk add --no-cache musl-dev gcc
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-bullseye
|
||||
COPY --link --from=xx / /
|
||||
COPY --from=xx / /
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y bash clang lld llvm file
|
||||
WORKDIR /go/src/github.com/docker/cli
|
||||
|
||||
@@ -41,13 +40,13 @@ FROM build-base-${BASE_VARIANT} AS goversioninfo
|
||||
ARG GOVERSIONINFO_VERSION
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
GOBIN=/out GO111MODULE=on CGO_ENABLED=0 go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}"
|
||||
GOBIN=/out GO111MODULE=on go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}"
|
||||
|
||||
FROM build-base-${BASE_VARIANT} AS gotestsum
|
||||
ARG GOTESTSUM_VERSION
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
GOBIN=/out GO111MODULE=on CGO_ENABLED=0 go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}" \
|
||||
GOBIN=/out GO111MODULE=on go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}" \
|
||||
&& /out/gotestsum --version
|
||||
|
||||
FROM build-${BASE_VARIANT} AS build
|
||||
@@ -63,7 +62,7 @@ ARG CGO_ENABLED
|
||||
ARG VERSION
|
||||
# PACKAGER_NAME sets the company that produced the windows binary
|
||||
ARG PACKAGER_NAME
|
||||
COPY --link --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
|
||||
COPY --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
|
||||
# in bullseye arm64 target does not link with lld so configure it to use ld instead
|
||||
RUN [ ! -f /etc/alpine-release ] && xx-info is-cross && [ "$(xx-info arch)" = "arm64" ] && XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple || true
|
||||
RUN --mount=type=bind,target=.,ro \
|
||||
@@ -77,7 +76,7 @@ RUN --mount=type=bind,target=.,ro \
|
||||
xx-verify $([ "$GO_LINKMODE" = "static" ] && echo "--static") /out/docker
|
||||
|
||||
FROM build-${BASE_VARIANT} AS test
|
||||
COPY --link --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
COPY --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
ENV GO111MODULE=auto
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
@@ -99,34 +98,35 @@ RUN --mount=ro --mount=type=cache,target=/root/.cache \
|
||||
TARGET=/out ./scripts/build/plugins e2e/cli-plugins/plugins/*
|
||||
|
||||
FROM build-base-alpine AS e2e-base-alpine
|
||||
RUN apk add --no-cache build-base curl openssl openssh-client
|
||||
RUN apk add --no-cache build-base curl docker-compose openssl openssh-client
|
||||
|
||||
FROM build-base-bullseye AS e2e-base-bullseye
|
||||
RUN apt-get update && apt-get install -y build-essential curl openssl openssh-client
|
||||
ARG COMPOSE_VERSION=1.29.2
|
||||
RUN curl -fsSL https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && \
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
FROM docker/compose-bin:${COMPOSE_VERSION} AS compose
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
|
||||
FROM e2e-base-${BASE_VARIANT} AS e2e
|
||||
ARG NOTARY_VERSION=v0.6.1
|
||||
ADD --chmod=0755 https://github.com/theupdateframework/notary/releases/download/${NOTARY_VERSION}/notary-Linux-amd64 /usr/local/bin/notary
|
||||
COPY --link e2e/testdata/notary/root-ca.cert /usr/share/ca-certificates/notary.cert
|
||||
COPY e2e/testdata/notary/root-ca.cert /usr/share/ca-certificates/notary.cert
|
||||
RUN echo 'notary.cert' >> /etc/ca-certificates.conf && update-ca-certificates
|
||||
COPY --link --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
COPY --link --from=build /out ./build/
|
||||
COPY --link --from=build-plugins /out ./build/
|
||||
COPY --link --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
|
||||
COPY --link --from=compose /docker-compose /usr/libexec/docker/cli-plugins/docker-compose
|
||||
COPY --link . .
|
||||
COPY --from=gotestsum /out/gotestsum /usr/bin/gotestsum
|
||||
COPY --from=build /out ./build/
|
||||
COPY --from=build-plugins /out ./build/
|
||||
COPY --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
|
||||
COPY . .
|
||||
ENV DOCKER_BUILDKIT=1
|
||||
ENV PATH=/go/src/github.com/docker/cli/build:$PATH
|
||||
CMD ./scripts/test/e2e/entry
|
||||
|
||||
FROM build-base-${BASE_VARIANT} AS dev
|
||||
COPY --link . .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /out .
|
||||
COPY . .
|
||||
|
||||
FROM scratch AS plugins
|
||||
COPY --from=build-plugins /out .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /out .
|
||||
|
||||
+6
-1
@@ -49,9 +49,9 @@
|
||||
|
||||
people = [
|
||||
"bsousaa",
|
||||
"neersighted",
|
||||
"programmerq",
|
||||
"sam-thibault",
|
||||
"thajeztah",
|
||||
"vvoland"
|
||||
]
|
||||
|
||||
@@ -103,6 +103,11 @@
|
||||
Email = "nicolas.deloof@gmail.com"
|
||||
GitHub = "ndeloof"
|
||||
|
||||
[people.neersighted]
|
||||
Name = "Bjorn Neergaard"
|
||||
Email = "bneergaard@mirantis.com"
|
||||
GitHub = "neersighted"
|
||||
|
||||
[people.programmerq]
|
||||
Name = "Jeff Anderson"
|
||||
Email = "jeff@docker.com"
|
||||
|
||||
@@ -2,7 +2,7 @@ package manager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -13,7 +13,7 @@ func TestPluginError(t *testing.T) {
|
||||
err := NewPluginError("new error")
|
||||
assert.Check(t, is.Error(err, "new error"))
|
||||
|
||||
inner := errors.New("testing")
|
||||
inner := fmt.Errorf("testing")
|
||||
err = wrapAsPluginError(inner, "wrapping")
|
||||
assert.Check(t, is.Error(err, "wrapping: testing"))
|
||||
assert.Check(t, is.ErrorIs(err, inner))
|
||||
|
||||
@@ -23,7 +23,6 @@ type Metadata struct {
|
||||
// URL is a pointer to the plugin's homepage.
|
||||
URL string `json:",omitempty"`
|
||||
// Experimental specifies whether the plugin is experimental.
|
||||
//
|
||||
// Deprecated: experimental features are now always enabled in the CLI
|
||||
Experimental bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
+2
-2
@@ -426,7 +426,7 @@ func invalidPluginReason(cmd *cobra.Command) string {
|
||||
return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
|
||||
}
|
||||
|
||||
var usageTemplate = `Usage:
|
||||
const usageTemplate = `Usage:
|
||||
|
||||
{{- if not .HasSubCommands}} {{.UseLine}}{{end}}
|
||||
{{- if .HasSubCommands}} {{ .CommandPath}}{{- if .HasAvailableFlags}} [OPTIONS]{{end}} COMMAND{{end}}
|
||||
@@ -525,5 +525,5 @@ Run '{{.CommandPath}} COMMAND --help' for more information on a command.
|
||||
{{- end}}
|
||||
`
|
||||
|
||||
var helpTemplate = `
|
||||
const helpTemplate = `
|
||||
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
||||
|
||||
+5
-7
@@ -48,9 +48,7 @@ type Streams interface {
|
||||
// Cli represents the docker command line client.
|
||||
type Cli interface {
|
||||
Client() client.APIClient
|
||||
Out() *streams.Out
|
||||
Err() io.Writer
|
||||
In() *streams.In
|
||||
Streams
|
||||
SetIn(in *streams.In)
|
||||
Apply(ops ...DockerCliOption) error
|
||||
ConfigFile() *configfile.ConfigFile
|
||||
@@ -164,8 +162,8 @@ func (cli *DockerCli) ContentTrustEnabled() bool {
|
||||
|
||||
// BuildKitEnabled returns buildkit is enabled or not.
|
||||
func (cli *DockerCli) BuildKitEnabled() (bool, error) {
|
||||
// use DOCKER_BUILDKIT env var value if set and not empty
|
||||
if v := os.Getenv("DOCKER_BUILDKIT"); v != "" {
|
||||
// use DOCKER_BUILDKIT env var value if set
|
||||
if v, ok := os.LookupEnv("DOCKER_BUILDKIT"); ok {
|
||||
enabled, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
|
||||
@@ -191,7 +189,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
|
||||
// RegistryClient returns a client for communicating with a Docker distribution
|
||||
// registry
|
||||
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
||||
resolver := func(ctx context.Context, index *registry.IndexInfo) types.AuthConfig {
|
||||
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
|
||||
return ResolveAuthConfig(ctx, cli, index)
|
||||
}
|
||||
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
||||
@@ -278,7 +276,7 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
|
||||
|
||||
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {
|
||||
if s == nil {
|
||||
return docker.Endpoint{}, errors.New("no context store initialized")
|
||||
return docker.Endpoint{}, fmt.Errorf("no context store initialized")
|
||||
}
|
||||
ctxMeta, err := s.GetMetadata(contextName)
|
||||
if err != nil {
|
||||
|
||||
@@ -192,7 +192,7 @@ func TestInitializeFromClientHangs(t *testing.T) {
|
||||
ts.Start()
|
||||
defer ts.Close()
|
||||
|
||||
opts := &flags.ClientOptions{Hosts: []string{"unix://" + socket}}
|
||||
opts := &flags.ClientOptions{Hosts: []string{fmt.Sprintf("unix://%s", socket)}}
|
||||
configFile := &configfile.ConfigFile{}
|
||||
apiClient, err := NewAPIClientFromFlags(opts, configFile)
|
||||
assert.NilError(t, err)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -66,13 +66,13 @@ func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Conta
|
||||
// VolumeNames offers completion for volumes
|
||||
func VolumeNames(dockerCli command.Cli) ValidArgsFn {
|
||||
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
list, err := dockerCli.Client().VolumeList(cmd.Context(), filters.Args{})
|
||||
list, err := dockerCli.Client().VolumeList(cmd.Context(), volume.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
var names []string
|
||||
for _, volume := range list.Volumes {
|
||||
names = append(names, volume.Name)
|
||||
for _, vol := range list.Volumes {
|
||||
names = append(names, vol.Name)
|
||||
}
|
||||
return names, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -43,7 +43,7 @@ func TestConfigInspectErrors(t *testing.T) {
|
||||
args: []string{"foo", "bar"},
|
||||
configInspectFunc: func(_ context.Context, configID string) (swarm.Config, []byte, error) {
|
||||
if configID == "foo" {
|
||||
return *builders.Config(builders.ConfigName("foo")), nil, nil
|
||||
return *Config(ConfigName("foo")), nil, nil
|
||||
}
|
||||
return swarm.Config{}, nil, errors.Errorf("error while inspecting the config")
|
||||
},
|
||||
@@ -58,7 +58,7 @@ func TestConfigInspectErrors(t *testing.T) {
|
||||
)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -78,14 +78,14 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
|
||||
if name != "foo" {
|
||||
return swarm.Config{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name)
|
||||
}
|
||||
return *builders.Config(builders.ConfigID("ID-foo"), builders.ConfigName("foo")), nil, nil
|
||||
return *Config(ConfigID("ID-foo"), ConfigName("foo")), nil, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple-configs-with-labels",
|
||||
args: []string{"foo", "bar"},
|
||||
configInspectFunc: func(_ context.Context, name string) (swarm.Config, []byte, error) {
|
||||
return *builders.Config(builders.ConfigID("ID-"+name), builders.ConfigName(name), builders.ConfigLabels(map[string]string{
|
||||
return *Config(ConfigID("ID-"+name), ConfigName(name), ConfigLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
},
|
||||
@@ -102,7 +102,7 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
|
||||
|
||||
func TestConfigInspectWithFormat(t *testing.T) {
|
||||
configInspectFunc := func(_ context.Context, name string) (swarm.Config, []byte, error) {
|
||||
return *builders.Config(builders.ConfigName("foo"), builders.ConfigLabels(map[string]string{
|
||||
return *Config(ConfigName("foo"), ConfigLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func TestConfigInspectWithFormat(t *testing.T) {
|
||||
})
|
||||
cmd := newConfigInspectCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
assert.Check(t, cmd.Flags().Set("format", tc.format))
|
||||
cmd.Flags().Set("format", tc.format)
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-with-format.%s.golden", tc.name))
|
||||
}
|
||||
@@ -145,15 +145,15 @@ func TestConfigInspectPretty(t *testing.T) {
|
||||
{
|
||||
name: "simple",
|
||||
configInspectFunc: func(_ context.Context, id string) (swarm.Config, []byte, error) {
|
||||
return *builders.Config(
|
||||
builders.ConfigLabels(map[string]string{
|
||||
return *Config(
|
||||
ConfigLabels(map[string]string{
|
||||
"lbl1": "value1",
|
||||
}),
|
||||
builders.ConfigID("configID"),
|
||||
builders.ConfigName("configName"),
|
||||
builders.ConfigCreatedAt(time.Time{}),
|
||||
builders.ConfigUpdatedAt(time.Time{}),
|
||||
builders.ConfigData([]byte("payload here")),
|
||||
ConfigID("configID"),
|
||||
ConfigName("configName"),
|
||||
ConfigCreatedAt(time.Time{}),
|
||||
ConfigUpdatedAt(time.Time{}),
|
||||
ConfigData([]byte("payload here")),
|
||||
), []byte{}, nil
|
||||
},
|
||||
},
|
||||
@@ -165,7 +165,7 @@ func TestConfigInspectPretty(t *testing.T) {
|
||||
cmd := newConfigInspectCommand(cli)
|
||||
|
||||
cmd.SetArgs([]string{"configID"})
|
||||
assert.Check(t, cmd.Flags().Set("pretty", "true"))
|
||||
cmd.Flags().Set("pretty", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-pretty.%s.golden", tc.name))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -50,23 +50,23 @@ func TestConfigList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*builders.Config(builders.ConfigID("ID-1-foo"),
|
||||
builders.ConfigName("1-foo"),
|
||||
builders.ConfigVersion(swarm.Version{Index: 10}),
|
||||
builders.ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Config(ConfigID("ID-1-foo"),
|
||||
ConfigName("1-foo"),
|
||||
ConfigVersion(swarm.Version{Index: 10}),
|
||||
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
*builders.Config(builders.ConfigID("ID-10-foo"),
|
||||
builders.ConfigName("10-foo"),
|
||||
builders.ConfigVersion(swarm.Version{Index: 11}),
|
||||
builders.ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Config(ConfigID("ID-10-foo"),
|
||||
ConfigName("10-foo"),
|
||||
ConfigVersion(swarm.Version{Index: 11}),
|
||||
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
*builders.Config(builders.ConfigID("ID-2-foo"),
|
||||
builders.ConfigName("2-foo"),
|
||||
builders.ConfigVersion(swarm.Version{Index: 11}),
|
||||
builders.ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Config(ConfigID("ID-2-foo"),
|
||||
ConfigName("2-foo"),
|
||||
ConfigVersion(swarm.Version{Index: 11}),
|
||||
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
@@ -80,15 +80,15 @@ func TestConfigListWithQuietOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*builders.Config(builders.ConfigID("ID-foo"), builders.ConfigName("foo")),
|
||||
*builders.Config(builders.ConfigID("ID-bar"), builders.ConfigName("bar"), builders.ConfigLabels(map[string]string{
|
||||
*Config(ConfigID("ID-foo"), ConfigName("foo")),
|
||||
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
|
||||
"label": "label-bar",
|
||||
})),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newConfigListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("quiet", "true"))
|
||||
cmd.Flags().Set("quiet", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-quiet-option.golden")
|
||||
}
|
||||
@@ -97,8 +97,8 @@ func TestConfigListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*builders.Config(builders.ConfigID("ID-foo"), builders.ConfigName("foo")),
|
||||
*builders.Config(builders.ConfigID("ID-bar"), builders.ConfigName("bar"), builders.ConfigLabels(map[string]string{
|
||||
*Config(ConfigID("ID-foo"), ConfigName("foo")),
|
||||
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
|
||||
"label": "label-bar",
|
||||
})),
|
||||
}, nil
|
||||
@@ -116,15 +116,15 @@ func TestConfigListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*builders.Config(builders.ConfigID("ID-foo"), builders.ConfigName("foo")),
|
||||
*builders.Config(builders.ConfigID("ID-bar"), builders.ConfigName("bar"), builders.ConfigLabels(map[string]string{
|
||||
*Config(ConfigID("ID-foo"), ConfigName("foo")),
|
||||
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
|
||||
"label": "label-bar",
|
||||
})),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newConfigListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}"))
|
||||
cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-format.golden")
|
||||
}
|
||||
@@ -135,24 +135,24 @@ func TestConfigListWithFilter(t *testing.T) {
|
||||
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]))
|
||||
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
|
||||
return []swarm.Config{
|
||||
*builders.Config(builders.ConfigID("ID-foo"),
|
||||
builders.ConfigName("foo"),
|
||||
builders.ConfigVersion(swarm.Version{Index: 10}),
|
||||
builders.ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Config(ConfigID("ID-foo"),
|
||||
ConfigName("foo"),
|
||||
ConfigVersion(swarm.Version{Index: 10}),
|
||||
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
*builders.Config(builders.ConfigID("ID-bar"),
|
||||
builders.ConfigName("bar"),
|
||||
builders.ConfigVersion(swarm.Version{Index: 11}),
|
||||
builders.ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Config(ConfigID("ID-bar"),
|
||||
ConfigName("bar"),
|
||||
ConfigVersion(swarm.Version{Index: 11}),
|
||||
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newConfigListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("filter", "name=foo"))
|
||||
assert.Check(t, cmd.Flags().Set("filter", "label=lbl1=Label-bar"))
|
||||
cmd.Flags().Set("filter", "name=foo")
|
||||
cmd.Flags().Set("filter", "label=lbl1=Label-bar")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-filter.golden")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
@@ -152,7 +153,7 @@ func getExitStatus(errC <-chan error, resultC <-chan container.WaitResponse) err
|
||||
select {
|
||||
case result := <-resultC:
|
||||
if result.Error != nil {
|
||||
return errors.New(result.Error.Message)
|
||||
return fmt.Errorf(result.Error.Message)
|
||||
}
|
||||
if result.StatusCode != 0 {
|
||||
return cli.StatusError{StatusCode: int(result.StatusCode)}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
@@ -78,7 +79,7 @@ func TestNewAttachCommandErrors(t *testing.T) {
|
||||
|
||||
func TestGetExitStatus(t *testing.T) {
|
||||
var (
|
||||
expectedErr = errors.New("unexpected error")
|
||||
expectedErr = fmt.Errorf("unexpected error")
|
||||
errC = make(chan error, 1)
|
||||
resultC = make(chan container.WaitResponse, 1)
|
||||
)
|
||||
|
||||
@@ -209,7 +209,7 @@ func resolveLocalPath(localPath string) (absPath string, err error) {
|
||||
if absPath, err = filepath.Abs(localPath); err != nil {
|
||||
return
|
||||
}
|
||||
return archive.PreserveTrailingDotOrSeparator(absPath, localPath, filepath.Separator), nil
|
||||
return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil
|
||||
}
|
||||
|
||||
func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpConfig) (err error) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
@@ -19,7 +20,6 @@ import (
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
apiclient "github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -95,16 +95,16 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
|
||||
}
|
||||
}
|
||||
copts.env = *opts.NewListOptsRef(&newEnv, nil)
|
||||
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
containerCfg, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
if err != nil {
|
||||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
if err = validateAPIVersion(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
|
||||
if err = validateAPIVersion(containerCfg, dockerCli.Client().ClientVersion()); err != nil {
|
||||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
response, err := createContainer(context.Background(), dockerCli, containerConfig, options)
|
||||
response, err := createContainer(context.Background(), dockerCli, containerCfg, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,41 +112,27 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
|
||||
return nil
|
||||
}
|
||||
|
||||
func pullImage(ctx context.Context, dockerCli command.Cli, image string, platform string, out io.Writer) error {
|
||||
ref, err := reference.ParseNormalizedNamed(image)
|
||||
// FIXME(thaJeztah): this is the only code-path that uses APIClient.ImageCreate. Rewrite this to use the regular "pull" code (or vice-versa).
|
||||
func pullImage(ctx context.Context, dockerCli command.Cli, image string, opts *createOptions) error {
|
||||
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options := types.ImageCreateOptions{
|
||||
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, types.ImageCreateOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
Platform: platform,
|
||||
}
|
||||
|
||||
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options)
|
||||
Platform: opts.platform,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
|
||||
return jsonmessage.DisplayJSONMessagesStream(
|
||||
responseBody,
|
||||
out,
|
||||
dockerCli.Out().FD(),
|
||||
dockerCli.Out().IsTerminal(),
|
||||
nil)
|
||||
out := dockerCli.Err()
|
||||
if opts.quiet {
|
||||
out = io.Discard
|
||||
}
|
||||
return jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(out), nil)
|
||||
}
|
||||
|
||||
type cidFile struct {
|
||||
@@ -199,10 +185,10 @@ func newCIDFile(path string) (*cidFile, error) {
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
|
||||
config := containerConfig.Config
|
||||
hostConfig := containerConfig.HostConfig
|
||||
networkingConfig := containerConfig.NetworkingConfig
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
|
||||
config := containerCfg.Config
|
||||
hostConfig := containerCfg.HostConfig
|
||||
networkingConfig := containerCfg.NetworkingConfig
|
||||
|
||||
warnOnOomKillDisable(*hostConfig, dockerCli.Err())
|
||||
warnOnLocalhostDNS(*hostConfig, dockerCli.Err())
|
||||
@@ -227,7 +213,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !opts.untrusted {
|
||||
var err error
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil)
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -236,11 +222,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
}
|
||||
|
||||
pullAndTagImage := func() error {
|
||||
pullOut := dockerCli.Err()
|
||||
if opts.quiet {
|
||||
pullOut = io.Discard
|
||||
}
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts.platform, pullOut); err != nil {
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
|
||||
@@ -293,8 +275,8 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
}
|
||||
}
|
||||
|
||||
for _, warning := range response.Warnings {
|
||||
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", warning)
|
||||
for _, w := range response.Warnings {
|
||||
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", w)
|
||||
}
|
||||
err = containerIDFile.Write(response.ID)
|
||||
return &response, err
|
||||
|
||||
@@ -3,6 +3,7 @@ package container
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -224,7 +225,7 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
|
||||
platform *specs.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{}, errors.New("shouldn't try to pull image")
|
||||
return container.CreateResponse{}, fmt.Errorf("shouldn't try to pull image")
|
||||
},
|
||||
}, test.EnableContentTrust)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
|
||||
@@ -120,6 +120,8 @@ func runPs(dockerCli command.Cli, options *psOptions) error {
|
||||
if len(options.format) == 0 {
|
||||
// load custom psFormat from CLI config (if any)
|
||||
options.format = dockerCli.ConfigFile().PsFormat
|
||||
} else if options.quiet {
|
||||
_, _ = dockerCli.Err().Write([]byte("WARNING: Ignoring custom format, because both --format and --quiet are set.\n"))
|
||||
}
|
||||
|
||||
listOptions, err := buildContainerListOptions(options)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -146,7 +146,7 @@ func TestContainerListErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return nil, errors.New("error listing containers")
|
||||
return nil, fmt.Errorf("error listing containers")
|
||||
},
|
||||
expectedError: "error listing containers",
|
||||
},
|
||||
@@ -159,7 +159,7 @@ func TestContainerListErrors(t *testing.T) {
|
||||
)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -170,11 +170,11 @@ func TestContainerListWithoutFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*builders.Container("c1"),
|
||||
*builders.Container("c2", builders.WithName("foo")),
|
||||
*builders.Container("c3", builders.WithPort(80, 80, builders.TCP), builders.WithPort(81, 81, builders.TCP), builders.WithPort(82, 82, builders.TCP)),
|
||||
*builders.Container("c4", builders.WithPort(81, 81, builders.UDP)),
|
||||
*builders.Container("c5", builders.WithPort(82, 82, builders.IP("8.8.8.8"), builders.TCP)),
|
||||
*Container("c1"),
|
||||
*Container("c2", WithName("foo")),
|
||||
*Container("c3", WithPort(80, 80, TCP), WithPort(81, 81, TCP), WithPort(82, 82, TCP)),
|
||||
*Container("c4", WithPort(81, 81, UDP)),
|
||||
*Container("c5", WithPort(82, 82, IP("8.8.8.8"), TCP)),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
@@ -187,13 +187,13 @@ func TestContainerListNoTrunc(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*builders.Container("c1"),
|
||||
*builders.Container("c2", builders.WithName("foo/bar")),
|
||||
*Container("c1"),
|
||||
*Container("c2", WithName("foo/bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("no-trunc", "true"))
|
||||
cmd.Flags().Set("no-trunc", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format-no-trunc.golden")
|
||||
}
|
||||
@@ -203,13 +203,13 @@ func TestContainerListNamesMultipleTime(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*builders.Container("c1"),
|
||||
*builders.Container("c2", builders.WithName("foo/bar")),
|
||||
*Container("c1"),
|
||||
*Container("c2", WithName("foo/bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{.Names}} {{.Names}}"))
|
||||
cmd.Flags().Set("format", "{{.Names}} {{.Names}}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-name-name.golden")
|
||||
}
|
||||
@@ -219,13 +219,13 @@ func TestContainerListFormatTemplateWithArg(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*builders.Container("c1", builders.WithLabel("some.label", "value")),
|
||||
*builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar")),
|
||||
*Container("c1", WithLabel("some.label", "value")),
|
||||
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", `{{.Names}} {{.Label "some.label"}}`))
|
||||
cmd.Flags().Set("format", `{{.Names}} {{.Label "some.label"}}`)
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-with-arg.golden")
|
||||
}
|
||||
@@ -274,9 +274,9 @@ func TestContainerListFormatSizeSetsOption(t *testing.T) {
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", tc.format))
|
||||
cmd.Flags().Set("format", tc.format)
|
||||
if tc.sizeFlag != "" {
|
||||
assert.Check(t, cmd.Flags().Set("size", tc.sizeFlag))
|
||||
cmd.Flags().Set("size", tc.sizeFlag)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
})
|
||||
@@ -287,8 +287,8 @@ func TestContainerListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*builders.Container("c1", builders.WithLabel("some.label", "value"), builders.WithSize(10700000)),
|
||||
*builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar"), builders.WithSize(3200000)),
|
||||
*Container("c1", WithLabel("some.label", "value"), WithSize(10700000)),
|
||||
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar"), WithSize(3200000)),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
@@ -304,13 +304,27 @@ func TestContainerListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
|
||||
return []types.Container{
|
||||
*builders.Container("c1", builders.WithLabel("some.label", "value")),
|
||||
*builders.Container("c2", builders.WithName("foo/bar"), builders.WithLabel("foo", "bar")),
|
||||
*Container("c1", WithLabel("some.label", "value")),
|
||||
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
|
||||
|
||||
t.Run("with format", func(t *testing.T) {
|
||||
cli.OutBuffer().Reset()
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
|
||||
})
|
||||
|
||||
t.Run("with format and quiet", func(t *testing.T) {
|
||||
cli.OutBuffer().Reset()
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
|
||||
assert.Check(t, cmd.Flags().Set("quiet", "true"))
|
||||
assert.NilError(t, cmd.Execute())
|
||||
assert.Equal(t, cli.ErrBuffer().String(), "WARNING: Ignoring custom format, because both --format and --quiet are set.\n")
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-quiet.golden")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -541,7 +541,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
||||
return nil, errors.Errorf("--health-retries cannot be negative")
|
||||
}
|
||||
if copts.healthStartPeriod < 0 {
|
||||
return nil, errors.New("--health-start-period cannot be negative")
|
||||
return nil, fmt.Errorf("--health-start-period cannot be negative")
|
||||
}
|
||||
|
||||
healthConfig = &container.HealthConfig{
|
||||
|
||||
@@ -49,11 +49,11 @@ func parseRun(args []string) (*container.Config, *container.HostConfig, *network
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
// TODO: fix tests to accept ContainerConfig
|
||||
containerConfig, err := parse(flags, copts, runtime.GOOS)
|
||||
containerCfg, err := parse(flags, copts, runtime.GOOS)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return containerConfig.Config, containerConfig.HostConfig, containerConfig.NetworkingConfig, err
|
||||
return containerCfg.Config, containerCfg.HostConfig, containerCfg.NetworkingConfig, err
|
||||
}
|
||||
|
||||
func setupRunFlags() (*pflag.FlagSet, *containerOptions) {
|
||||
@@ -329,7 +329,7 @@ func TestParseHostname(t *testing.T) {
|
||||
hostnameWithDomain := "--hostname=hostname.domainname"
|
||||
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
|
||||
for hostname, expectedHostname := range validHostnames {
|
||||
if config, _ := mustParse(t, "--hostname="+hostname); config.Hostname != expectedHostname {
|
||||
if config, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname {
|
||||
t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -37,7 +37,7 @@ func TestRemoveForce(t *testing.T) {
|
||||
mutex.Unlock()
|
||||
|
||||
if container == "nosuchcontainer" {
|
||||
return errdefs.NotFound(errors.New("Error: no such container: " + container))
|
||||
return errdefs.NotFound(fmt.Errorf("Error: no such container: " + container))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -105,22 +105,22 @@ func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copt
|
||||
}
|
||||
}
|
||||
copts.env = *opts.NewListOptsRef(&newEnv, nil)
|
||||
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
containerCfg, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
// just in case the parse does not exit
|
||||
if err != nil {
|
||||
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
if err = validateAPIVersion(containerConfig, dockerCli.CurrentVersion()); err != nil {
|
||||
if err = validateAPIVersion(containerCfg, dockerCli.CurrentVersion()); err != nil {
|
||||
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
return runContainer(dockerCli, ropts, copts, containerConfig)
|
||||
return runContainer(dockerCli, ropts, copts, containerCfg)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerConfig *containerConfig) error {
|
||||
config := containerConfig.Config
|
||||
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerCfg *containerConfig) error {
|
||||
config := containerCfg.Config
|
||||
stdout, stderr := dockerCli.Out(), dockerCli.Err()
|
||||
client := dockerCli.Client()
|
||||
|
||||
@@ -144,7 +144,7 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
|
||||
ctx, cancelFun := context.WithCancel(context.Background())
|
||||
defer cancelFun()
|
||||
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerConfig, &opts.createOptions)
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerCfg, &opts.createOptions)
|
||||
if err != nil {
|
||||
reportError(stderr, "run", err.Error(), true)
|
||||
return runStartContainerErr(err)
|
||||
|
||||
@@ -2,6 +2,7 @@ package container
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
@@ -64,7 +65,7 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) {
|
||||
platform *specs.Platform,
|
||||
containerName string,
|
||||
) (container.CreateResponse, error) {
|
||||
return container.CreateResponse{}, errors.New("shouldn't try to pull image")
|
||||
return container.CreateResponse{}, fmt.Errorf("shouldn't try to pull image")
|
||||
},
|
||||
}, test.EnableContentTrust)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
container_id
|
||||
container_id
|
||||
@@ -1,6 +1,7 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -76,7 +77,7 @@ func validateConfig(config map[string]string, allowedKeys map[string]struct{}) e
|
||||
var errs []string
|
||||
for k := range config {
|
||||
if _, ok := allowedKeys[k]; !ok {
|
||||
errs = append(errs, "unrecognized config key: "+k)
|
||||
errs = append(errs, fmt.Sprintf("%s: unrecognized config key", k))
|
||||
}
|
||||
}
|
||||
if len(errs) == 0 {
|
||||
|
||||
@@ -55,6 +55,9 @@ ports: {{- pad .Ports 1 0}}
|
||||
}
|
||||
return Format(format)
|
||||
default: // custom format
|
||||
if quiet {
|
||||
return DefaultQuietFormat
|
||||
}
|
||||
return Format(source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ containerID2 ubuntu "" 24 hours ago foobar_bar
|
||||
},
|
||||
{
|
||||
Context{Format: NewContainerFormat("table {{.Image}}", true, false)},
|
||||
"IMAGE\nubuntu\nubuntu\n",
|
||||
"containerID1\ncontainerID2\n",
|
||||
},
|
||||
{
|
||||
Context{Format: NewContainerFormat("table", true, false)},
|
||||
|
||||
@@ -84,10 +84,3 @@ func (c *clientContextContext) Error() string {
|
||||
// TODO(thaJeztah) add "--no-trunc" option to context ls and set default to 30 cols to match "docker service ps"
|
||||
return Ellipsis(c.c.Error, maxErrLength)
|
||||
}
|
||||
|
||||
// KubernetesEndpoint returns the kubernetes endpoint.
|
||||
//
|
||||
// Deprecated: support for kubernetes endpoints in contexts has been removed, and this formatting option will always be empty.
|
||||
func (c *clientContextContext) KubernetesEndpoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -50,7 +50,7 @@ func TestResolveWithCache(t *testing.T) {
|
||||
cli := &fakeClient{
|
||||
nodeInspectFunc: func(nodeID string) (swarm.Node, []byte, error) {
|
||||
inspectCounter++
|
||||
return *builders.Node(builders.NodeName("node-foo")), []byte{}, nil
|
||||
return *Node(NodeName("node-foo")), []byte{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -82,14 +82,14 @@ func TestResolveNode(t *testing.T) {
|
||||
{
|
||||
nodeID: "nodeID",
|
||||
nodeInspectFunc: func(string) (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeName("node-foo")), []byte{}, nil
|
||||
return *Node(NodeName("node-foo")), []byte{}, nil
|
||||
},
|
||||
expectedID: "node-foo",
|
||||
},
|
||||
{
|
||||
nodeID: "nodeID",
|
||||
nodeInspectFunc: func(string) (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeName(""), builders.Hostname("node-hostname")), []byte{}, nil
|
||||
return *Node(NodeName(""), Hostname("node-hostname")), []byte{}, nil
|
||||
},
|
||||
expectedID: "node-hostname",
|
||||
},
|
||||
@@ -124,7 +124,7 @@ func TestResolveService(t *testing.T) {
|
||||
{
|
||||
serviceID: "serviceID",
|
||||
serviceInspectFunc: func(string) (swarm.Service, []byte, error) {
|
||||
return *builders.Service(builders.ServiceName("service-foo")), []byte{}, nil
|
||||
return *Service(ServiceName("service-foo")), []byte{}, nil
|
||||
},
|
||||
expectedID: "service-foo",
|
||||
},
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/builder/remotecontext/urlutil"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
@@ -279,7 +280,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
var resolvedTags []*resolvedTag
|
||||
if !options.untrusted {
|
||||
translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
return TrustedReference(ctx, dockerCli, ref, nil)
|
||||
return TrustedReference(ctx, dockerCli, ref)
|
||||
}
|
||||
// if there is a tar wrapper, the dockerfile needs to be replaced inside it
|
||||
if buildCtx != nil {
|
||||
@@ -322,9 +323,9 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
|
||||
configFile := dockerCli.ConfigFile()
|
||||
creds, _ := configFile.GetAllCredentials()
|
||||
authConfigs := make(map[string]types.AuthConfig, len(creds))
|
||||
authConfigs := make(map[string]registrytypes.AuthConfig, len(creds))
|
||||
for k, auth := range creds {
|
||||
authConfigs[k] = types.AuthConfig(auth)
|
||||
authConfigs[k] = registrytypes.AuthConfig(auth)
|
||||
}
|
||||
buildOptions := imageBuildOptions(dockerCli, options)
|
||||
buildOptions.Version = types.BuilderV1
|
||||
@@ -459,7 +460,7 @@ func rewriteDockerfileFromForContentTrust(ctx context.Context, dockerfile io.Rea
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, "FROM "+reference.FamiliarString(trustedRef))
|
||||
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", reference.FamiliarString(trustedRef)))
|
||||
resolvedTags = append(resolvedTags, &resolvedTag{
|
||||
digestRef: trustedRef,
|
||||
tagRef: ref,
|
||||
|
||||
@@ -223,7 +223,7 @@ func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.Read
|
||||
progressOutput := streamformatter.NewProgressOutput(out)
|
||||
|
||||
// Pass the response body through a progress reader.
|
||||
progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", "Downloading build context from remote url: "+remoteURL)
|
||||
progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", fmt.Sprintf("Downloading build context from remote url: %s", remoteURL))
|
||||
|
||||
return GetContextFromReader(ioutils.NewReadCloserWrapper(progReader, func() error { return response.Body.Close() }), dockerfileName)
|
||||
}
|
||||
@@ -231,7 +231,7 @@ func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.Read
|
||||
// getWithStatusError does an http.Get() and returns an error if the
|
||||
// status code is 4xx or 5xx.
|
||||
func getWithStatusError(url string) (resp *http.Response, err error) {
|
||||
//nolint:gosec // Ignore G107: Potential HTTP request made with variable url
|
||||
// #nosec G107
|
||||
if resp, err = http.Get(url); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ func TestGetContextFromReaderString(t *testing.T) {
|
||||
tarReader := tar.NewReader(tarArchive)
|
||||
|
||||
_, err = tarReader.Next()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error when reading tar archive: %s", err)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func RunPull(cli command.Cli, opts PullOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), distributionRef.String())
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
@@ -113,7 +112,7 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
imagePullFunc: func(ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
|
||||
return io.NopCloser(strings.NewReader("")), errors.New("shouldn't try to pull image")
|
||||
return io.NopCloser(strings.NewReader("")), fmt.Errorf("shouldn't try to pull image")
|
||||
},
|
||||
}, test.EnableContentTrust)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
@@ -76,7 +77,7 @@ func RunPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
|
||||
// Resolve the Auth config relevant for this server
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ type notFound struct {
|
||||
}
|
||||
|
||||
func (n notFound) Error() string {
|
||||
return "Error: No such image: " + n.imageID
|
||||
return fmt.Sprintf("Error: No such image: %s", n.imageID)
|
||||
}
|
||||
|
||||
func (n notFound) NotFound() bool {
|
||||
|
||||
+10
-13
@@ -30,7 +30,7 @@ type target struct {
|
||||
}
|
||||
|
||||
// TrustedPush handles content trust pushing of an image
|
||||
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, options types.ImagePushOptions) error {
|
||||
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, options types.ImagePushOptions) error {
|
||||
responseBody, err := cli.Client().ImagePush(ctx, reference.FamiliarString(ref), options)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -44,7 +44,7 @@ func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
|
||||
// PushTrustedReference pushes a canonical reference to the trust server.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, in io.Reader) error {
|
||||
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error {
|
||||
// If it is a trusted push we would like to find the target entry which match the
|
||||
// tag provided in the function and then do an AddTarget later.
|
||||
target := &client.Target{}
|
||||
@@ -186,7 +186,7 @@ func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.Image
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), trustedRef.String())
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -262,20 +262,17 @@ func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth)
|
||||
|
||||
// imagePullPrivileged pulls the image and displays it to the output
|
||||
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, opts PullOptions) error {
|
||||
ref := reference.FamiliarString(imgRefAndAuth.Reference())
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(*imgRefAndAuth.AuthConfig())
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(*imgRefAndAuth.AuthConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
|
||||
options := types.ImagePullOptions{
|
||||
responseBody, err := cli.Client().ImagePull(ctx, reference.FamiliarString(imgRefAndAuth.Reference()), types.ImagePullOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
PrivilegeFunc: requestPrivilege,
|
||||
All: opts.all,
|
||||
Platform: opts.platform,
|
||||
}
|
||||
responseBody, err := cli.Client().ImagePull(ctx, ref, options)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -289,8 +286,8 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
|
||||
}
|
||||
|
||||
// TrustedReference returns the canonical trusted reference for an image reference
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) {
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, rs, AuthResolver(cli), ref.String())
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), ref.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -340,8 +337,8 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
|
||||
}
|
||||
|
||||
// AuthResolver returns an auth resolver function from a command.Cli
|
||||
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
return func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
return func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, cli, index)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -37,14 +36,14 @@ func newConnectCommand(dockerCli command.Cli) *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
options.network = args[0]
|
||||
options.container = args[1]
|
||||
return runConnect(cmd.Context(), dockerCli.Client(), options)
|
||||
return runConnect(dockerCli, options)
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
if len(args) == 0 {
|
||||
return completion.NetworkNames(dockerCli)(cmd, args, toComplete)
|
||||
}
|
||||
nw := args[0]
|
||||
return completion.ContainerNames(dockerCli, true, not(isConnected(nw)))(cmd, args, toComplete)
|
||||
network := args[0]
|
||||
return completion.ContainerNames(dockerCli, true, not(isConnected(network)))(cmd, args, toComplete)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -58,13 +57,14 @@ func newConnectCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runConnect(ctx context.Context, apiClient client.NetworkAPIClient, options connectOptions) error {
|
||||
func runConnect(dockerCli command.Cli, options connectOptions) error {
|
||||
client := dockerCli.Client()
|
||||
|
||||
driverOpts, err := convertDriverOpt(options.driverOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return apiClient.NetworkConnect(ctx, options.network, options.container, &network.EndpointSettings{
|
||||
epConfig := &network.EndpointSettings{
|
||||
IPAMConfig: &network.EndpointIPAMConfig{
|
||||
IPv4Address: options.ipaddress,
|
||||
IPv6Address: options.ipv6address,
|
||||
@@ -73,7 +73,9 @@ func runConnect(ctx context.Context, apiClient client.NetworkAPIClient, options
|
||||
Links: options.links.GetAll(),
|
||||
Aliases: options.aliases,
|
||||
DriverOpts: driverOpts,
|
||||
})
|
||||
}
|
||||
|
||||
return client.NetworkConnect(context.Background(), options.network, options.container, epConfig)
|
||||
}
|
||||
|
||||
func convertDriverOpt(opts []string) (map[string]string, error) {
|
||||
@@ -83,7 +85,7 @@ func convertDriverOpt(opts []string) (map[string]string, error) {
|
||||
// TODO(thaJeztah): we should probably not accept whitespace here (both for key and value).
|
||||
k = strings.TrimSpace(k)
|
||||
if !ok || k == "" {
|
||||
return nil, errors.New("invalid key/value pair format in driver options")
|
||||
return nil, fmt.Errorf("invalid key/value pair format in driver options")
|
||||
}
|
||||
driverOpt[k] = strings.TrimSpace(v)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@@ -59,10 +59,10 @@ func TestNetworkList(t *testing.T) {
|
||||
}
|
||||
assert.Check(t, is.DeepEqual(expectedOpts, options, cmp.AllowUnexported(filters.Args{})))
|
||||
|
||||
return []types.NetworkResource{*builders.NetworkResource(builders.NetworkResourceID("123454321"),
|
||||
builders.NetworkResourceName("network_1"),
|
||||
builders.NetworkResourceDriver("09.7.01"),
|
||||
builders.NetworkResourceScope("global"))}, nil
|
||||
return []types.NetworkResource{*NetworkResource(NetworkResourceID("123454321"),
|
||||
NetworkResourceName("network_1"),
|
||||
NetworkResourceDriver("09.7.01"),
|
||||
NetworkResourceScope("global"))}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -73,9 +73,9 @@ func TestNetworkList(t *testing.T) {
|
||||
golden: "network-list-sort.golden",
|
||||
networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
return []types.NetworkResource{
|
||||
*builders.NetworkResource(builders.NetworkResourceName("network-2-foo")),
|
||||
*builders.NetworkResource(builders.NetworkResourceName("network-1-foo")),
|
||||
*builders.NetworkResource(builders.NetworkResourceName("network-10-foo")),
|
||||
*NetworkResource(NetworkResourceName("network-2-foo")),
|
||||
*NetworkResource(NetworkResourceName("network-1-foo")),
|
||||
*NetworkResource(NetworkResourceName("network-10-foo")),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
@@ -86,7 +86,7 @@ func TestNetworkList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{networkListFunc: tc.networkListFunc})
|
||||
cmd := newListCommand(cli)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.golden)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package functions
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -52,7 +52,7 @@ func TestNodeDemoteNoChange(t *testing.T) {
|
||||
cmd := newDemoteCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if node.Role != swarm.NodeRoleWorker {
|
||||
@@ -69,7 +69,7 @@ func TestNodeDemoteMultipleNode(t *testing.T) {
|
||||
cmd := newDemoteCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if node.Role != swarm.NodeRoleWorker {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package functions
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -71,7 +71,7 @@ func TestNodeInspectErrors(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -86,7 +86,7 @@ func TestNodeInspectPretty(t *testing.T) {
|
||||
{
|
||||
name: "simple",
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeLabels(map[string]string{
|
||||
return *Node(NodeLabels(map[string]string{
|
||||
"lbl1": "value1",
|
||||
})), []byte{}, nil
|
||||
},
|
||||
@@ -94,13 +94,13 @@ func TestNodeInspectPretty(t *testing.T) {
|
||||
{
|
||||
name: "manager",
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "manager-leader",
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager(builders.Leader())), []byte{}, nil
|
||||
return *Node(Manager(Leader())), []byte{}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func TestNodeInspectPretty(t *testing.T) {
|
||||
})
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"nodeID"})
|
||||
assert.Check(t, cmd.Flags().Set("pretty", "true"))
|
||||
cmd.Flags().Set("pretty", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-inspect-pretty.%s.golden", tc.name))
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -56,9 +56,9 @@ func TestNodeList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
nodeListFunc: func() ([]swarm.Node, error) {
|
||||
return []swarm.Node{
|
||||
*builders.Node(builders.NodeID("nodeID1"), builders.Hostname("node-2-foo"), builders.Manager(builders.Leader()), builders.EngineVersion(".")),
|
||||
*builders.Node(builders.NodeID("nodeID2"), builders.Hostname("node-10-foo"), builders.Manager(), builders.EngineVersion("18.03.0-ce")),
|
||||
*builders.Node(builders.NodeID("nodeID3"), builders.Hostname("node-1-foo")),
|
||||
*Node(NodeID("nodeID1"), Hostname("node-2-foo"), Manager(Leader()), EngineVersion(".")),
|
||||
*Node(NodeID("nodeID2"), Hostname("node-10-foo"), Manager(), EngineVersion("18.03.0-ce")),
|
||||
*Node(NodeID("nodeID3"), Hostname("node-1-foo")),
|
||||
}, nil
|
||||
},
|
||||
infoFunc: func() (types.Info, error) {
|
||||
@@ -79,12 +79,12 @@ func TestNodeListQuietShouldOnlyPrintIDs(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
nodeListFunc: func() ([]swarm.Node, error) {
|
||||
return []swarm.Node{
|
||||
*builders.Node(builders.NodeID("nodeID1")),
|
||||
*Node(NodeID("nodeID1")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("quiet", "true"))
|
||||
cmd.Flags().Set("quiet", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
assert.Check(t, is.Equal(cli.OutBuffer().String(), "nodeID1\n"))
|
||||
}
|
||||
@@ -93,9 +93,9 @@ func TestNodeListDefaultFormatFromConfig(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
nodeListFunc: func() ([]swarm.Node, error) {
|
||||
return []swarm.Node{
|
||||
*builders.Node(builders.NodeID("nodeID1"), builders.Hostname("nodeHostname1"), builders.Manager(builders.Leader())),
|
||||
*builders.Node(builders.NodeID("nodeID2"), builders.Hostname("nodeHostname2"), builders.Manager()),
|
||||
*builders.Node(builders.NodeID("nodeID3"), builders.Hostname("nodeHostname3")),
|
||||
*Node(NodeID("nodeID1"), Hostname("nodeHostname1"), Manager(Leader())),
|
||||
*Node(NodeID("nodeID2"), Hostname("nodeHostname2"), Manager()),
|
||||
*Node(NodeID("nodeID3"), Hostname("nodeHostname3")),
|
||||
}, nil
|
||||
},
|
||||
infoFunc: func() (types.Info, error) {
|
||||
@@ -118,8 +118,8 @@ func TestNodeListFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
nodeListFunc: func() ([]swarm.Node, error) {
|
||||
return []swarm.Node{
|
||||
*builders.Node(builders.NodeID("nodeID1"), builders.Hostname("nodeHostname1"), builders.Manager(builders.Leader())),
|
||||
*builders.Node(builders.NodeID("nodeID2"), builders.Hostname("nodeHostname2"), builders.Manager()),
|
||||
*Node(NodeID("nodeID1"), Hostname("nodeHostname1"), Manager(Leader())),
|
||||
*Node(NodeID("nodeID2"), Hostname("nodeHostname2"), Manager()),
|
||||
}, nil
|
||||
},
|
||||
infoFunc: func() (types.Info, error) {
|
||||
@@ -134,7 +134,7 @@ func TestNodeListFormat(t *testing.T) {
|
||||
NodesFormat: "{{.ID}}: {{.Hostname}} {{.Status}}/{{.ManagerStatus}}",
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{.Hostname}}: {{.ManagerStatus}}"))
|
||||
cmd.Flags().Set("format", "{{.Hostname}}: {{.ManagerStatus}}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "node-list-format-flag.golden")
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -52,7 +52,7 @@ func TestNodePromoteNoChange(t *testing.T) {
|
||||
cmd := newPromoteCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if node.Role != swarm.NodeRoleManager {
|
||||
@@ -69,7 +69,7 @@ func TestNodePromoteMultipleNode(t *testing.T) {
|
||||
cmd := newPromoteCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if node.Role != swarm.NodeRoleManager {
|
||||
|
||||
+12
-12
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -57,7 +57,7 @@ func TestNodePsErrors(t *testing.T) {
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.Error(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -79,11 +79,11 @@ func TestNodePs(t *testing.T) {
|
||||
name: "simple",
|
||||
args: []string{"nodeID"},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{
|
||||
*builders.Task(builders.WithStatus(builders.Timestamp(time.Now().Add(-2*time.Hour)), builders.PortStatus([]swarm.PortConfig{
|
||||
*Task(WithStatus(Timestamp(time.Now().Add(-2*time.Hour)), PortStatus([]swarm.PortConfig{
|
||||
{
|
||||
TargetPort: 80,
|
||||
PublishedPort: 80,
|
||||
@@ -107,16 +107,16 @@ func TestNodePs(t *testing.T) {
|
||||
name: "with-errors",
|
||||
args: []string{"nodeID"},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{
|
||||
*builders.Task(builders.TaskID("taskID1"), builders.TaskServiceID("failure"),
|
||||
builders.WithStatus(builders.Timestamp(time.Now().Add(-2*time.Hour)), builders.StatusErr("a task error"))),
|
||||
*builders.Task(builders.TaskID("taskID2"), builders.TaskServiceID("failure"),
|
||||
builders.WithStatus(builders.Timestamp(time.Now().Add(-3*time.Hour)), builders.StatusErr("a task error"))),
|
||||
*builders.Task(builders.TaskID("taskID3"), builders.TaskServiceID("failure"),
|
||||
builders.WithStatus(builders.Timestamp(time.Now().Add(-4*time.Hour)), builders.StatusErr("a task error"))),
|
||||
*Task(TaskID("taskID1"), TaskServiceID("failure"),
|
||||
WithStatus(Timestamp(time.Now().Add(-2*time.Hour)), StatusErr("a task error"))),
|
||||
*Task(TaskID("taskID2"), TaskServiceID("failure"),
|
||||
WithStatus(Timestamp(time.Now().Add(-3*time.Hour)), StatusErr("a task error"))),
|
||||
*Task(TaskID("taskID3"), TaskServiceID("failure"),
|
||||
WithStatus(Timestamp(time.Now().Add(-4*time.Hour)), StatusErr("a task error"))),
|
||||
}, nil
|
||||
},
|
||||
serviceInspectFunc: func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
@@ -142,7 +142,7 @@ func TestNodePs(t *testing.T) {
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-ps.%s.golden", tc.name))
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -43,7 +43,7 @@ func TestNodeUpdateErrors(t *testing.T) {
|
||||
{
|
||||
args: []string{"nodeID"},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeLabels(map[string]string{
|
||||
return *Node(NodeLabels(map[string]string{
|
||||
"key": "value",
|
||||
})), []byte{}, nil
|
||||
},
|
||||
@@ -61,7 +61,7 @@ func TestNodeUpdateErrors(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -81,7 +81,7 @@ func TestNodeUpdate(t *testing.T) {
|
||||
"role": "manager",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if node.Role != swarm.NodeRoleManager {
|
||||
@@ -96,7 +96,7 @@ func TestNodeUpdate(t *testing.T) {
|
||||
"availability": "drain",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if node.Availability != swarm.NodeAvailabilityDrain {
|
||||
@@ -111,7 +111,7 @@ func TestNodeUpdate(t *testing.T) {
|
||||
"label-add": "lbl",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if _, present := node.Annotations.Labels["lbl"]; !present {
|
||||
@@ -126,7 +126,7 @@ func TestNodeUpdate(t *testing.T) {
|
||||
"label-add": "key=value",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(), []byte{}, nil
|
||||
return *Node(), []byte{}, nil
|
||||
},
|
||||
nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if value, present := node.Annotations.Labels["key"]; !present || value != "value" {
|
||||
@@ -141,7 +141,7 @@ func TestNodeUpdate(t *testing.T) {
|
||||
"label-rm": "key",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeLabels(map[string]string{
|
||||
return *Node(NodeLabels(map[string]string{
|
||||
"key": "value",
|
||||
})), []byte{}, nil
|
||||
},
|
||||
@@ -161,7 +161,7 @@ func TestNodeUpdate(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ func runCreate(dockerCli command.Cli, options pluginCreateOptions) error {
|
||||
createCtx, err = archive.TarWithOptions(absContextDir, &archive.TarOptions{
|
||||
Compression: compression,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"testing"
|
||||
@@ -91,14 +91,16 @@ func TestCreateErrorFromDaemon(t *testing.T) {
|
||||
fs.WithFile("config.json", `{ "Name": "plugin-foo" }`))
|
||||
defer tmpDir.Remove()
|
||||
|
||||
cmd := newCreateCommand(test.NewFakeCli(&fakeClient{
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
pluginCreateFunc: func(createContext io.Reader, createOptions types.PluginCreateOptions) error {
|
||||
return errors.New("error creating plugin")
|
||||
return fmt.Errorf("Error creating plugin")
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
cmd := newCreateCommand(cli)
|
||||
cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()})
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), "error creating plugin")
|
||||
assert.ErrorContains(t, cmd.Execute(), "Error creating plugin")
|
||||
}
|
||||
|
||||
func TestCreatePlugin(t *testing.T) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
@@ -27,9 +27,9 @@ func TestPluginDisableErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"plugin-foo"},
|
||||
expectedError: "error disabling plugin",
|
||||
expectedError: "Error disabling plugin",
|
||||
pluginDisableFunc: func(name string, disableOptions types.PluginDisableOptions) error {
|
||||
return errors.New("error disabling plugin")
|
||||
return fmt.Errorf("Error disabling plugin")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestPluginEnableErrors(t *testing.T) {
|
||||
{
|
||||
args: []string{"plugin-foo"},
|
||||
pluginEnableFunc: func(name string, options types.PluginEnableOptions) error {
|
||||
return errors.New("failed to enable plugin")
|
||||
return fmt.Errorf("failed to enable plugin")
|
||||
},
|
||||
expectedError: "failed to enable plugin",
|
||||
},
|
||||
@@ -43,9 +43,10 @@ func TestPluginEnableErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
cmd := newEnableCommand(test.NewFakeCli(&fakeClient{
|
||||
pluginEnableFunc: tc.pluginEnableFunc,
|
||||
}))
|
||||
cmd := newEnableCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
pluginEnableFunc: tc.pluginEnableFunc,
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
)
|
||||
@@ -52,7 +52,7 @@ func TestInspectErrors(t *testing.T) {
|
||||
args: []string{"foo"},
|
||||
expectedError: "error inspecting plugin",
|
||||
inspectFunc: func(name string) (*types.Plugin, []byte, error) {
|
||||
return nil, nil, errors.New("error inspecting plugin")
|
||||
return nil, nil, fmt.Errorf("error inspecting plugin")
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
@@ -54,26 +55,6 @@ func newInstallCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
type pluginRegistryService struct {
|
||||
registry.Service
|
||||
}
|
||||
|
||||
func (s pluginRegistryService) ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error) {
|
||||
repoInfo, err := s.Service.ResolveRepository(name)
|
||||
if repoInfo != nil {
|
||||
repoInfo.Class = "plugin"
|
||||
}
|
||||
return repoInfo, err
|
||||
}
|
||||
|
||||
func newRegistryService() (registry.Service, error) {
|
||||
svc, err := registry.NewService(registry.ServiceOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pluginRegistryService{Service: svc}, nil
|
||||
}
|
||||
|
||||
func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) {
|
||||
// Names with both tag and digest will be treated by the daemon
|
||||
// as a pull by digest with a local name for the tag
|
||||
@@ -98,12 +79,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
||||
return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String())
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
svc, err := newRegistryService()
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
trusted, err := image.TrustedReference(ctx, dockerCli, nt, svc)
|
||||
trusted, err := image.TrustedReference(context.Background(), dockerCli, nt)
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
@@ -111,8 +87,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
||||
}
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -38,9 +38,9 @@ func TestInstallErrors(t *testing.T) {
|
||||
{
|
||||
description: "installation error",
|
||||
args: []string{"foo"},
|
||||
expectedError: "error installing plugin",
|
||||
expectedError: "Error installing plugin",
|
||||
installFunc: func(name string, options types.PluginInstallOptions) (io.ReadCloser, error) {
|
||||
return nil, errors.New("error installing plugin")
|
||||
return nil, fmt.Errorf("Error installing plugin")
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -48,7 +48,7 @@ func TestInstallErrors(t *testing.T) {
|
||||
args: []string{"foo"},
|
||||
expectedError: "docker image pull",
|
||||
installFunc: func(name string, options types.PluginInstallOptions) (io.ReadCloser, error) {
|
||||
return nil, errors.New("(image) when fetching")
|
||||
return nil, fmt.Errorf("(image) when fetching")
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func TestInstallContentTrustErrors(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
pluginInstallFunc: func(name string, options types.PluginInstallOptions) (io.ReadCloser, error) {
|
||||
return nil, errors.New("should not try to install plugin")
|
||||
return nil, fmt.Errorf("should not try to install plugin")
|
||||
},
|
||||
}, test.EnableContentTrust)
|
||||
cli.SetNotaryClient(tc.notaryFunc)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestListErrors(t *testing.T) {
|
||||
args: []string{},
|
||||
expectedError: "error listing plugins",
|
||||
listFunc: func(filter filters.Args) (types.PluginsListResponse, error) {
|
||||
return types.PluginsListResponse{}, errors.New("error listing plugins")
|
||||
return types.PluginsListResponse{}, fmt.Errorf("error listing plugins")
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/distribution/reference"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
@@ -55,8 +56,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
return err
|
||||
}
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,7 +68,6 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
defer responseBody.Close()
|
||||
|
||||
if !opts.untrusted {
|
||||
repoInfo.Class = "plugin"
|
||||
return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
@@ -24,9 +24,9 @@ func TestRemoveErrors(t *testing.T) {
|
||||
{
|
||||
args: []string{"plugin-foo"},
|
||||
pluginRemoveFunc: func(name string, options types.PluginRemoveOptions) error {
|
||||
return errors.New("error removing plugin")
|
||||
return fmt.Errorf("Error removing plugin")
|
||||
},
|
||||
expectedError: "error removing plugin",
|
||||
expectedError: "Error removing plugin",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+49
-41
@@ -3,8 +3,6 @@ package command
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -21,20 +19,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ElectAuthServer returns the default registry to use.
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload.
|
||||
//
|
||||
// Deprecated: use [registry.IndexServer] instead.
|
||||
func ElectAuthServer(_ context.Context, _ Cli) string {
|
||||
return registry.IndexServer
|
||||
}
|
||||
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload
|
||||
func EncodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
|
||||
buf, err := json.Marshal(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(buf), nil
|
||||
// Deprecated: use [registrytypes.EncodeAuthConfig] instead.
|
||||
func EncodeAuthToBase64(authConfig registrytypes.AuthConfig) (string, error) {
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
}
|
||||
|
||||
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
|
||||
@@ -52,7 +41,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return EncodeAuthToBase64(authConfig)
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,19 +51,19 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
//
|
||||
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
|
||||
// store, instead of looking up credentials from a map.
|
||||
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
configKey := index.Name
|
||||
if index.Official {
|
||||
configKey = registry.IndexServer
|
||||
}
|
||||
|
||||
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
|
||||
return types.AuthConfig(a)
|
||||
return registrytypes.AuthConfig(a)
|
||||
}
|
||||
|
||||
// GetDefaultAuthConfig gets the default auth config given a serverAddress
|
||||
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
|
||||
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
|
||||
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
|
||||
if !isDefaultRegistry {
|
||||
serverAddress = registry.ConvertToHostname(serverAddress)
|
||||
}
|
||||
@@ -83,20 +72,27 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
|
||||
if checkCredStore {
|
||||
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
|
||||
if err != nil {
|
||||
return types.AuthConfig{
|
||||
return registrytypes.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
authconfig.ServerAddress = serverAddress
|
||||
authconfig.IdentityToken = ""
|
||||
res := types.AuthConfig(authconfig)
|
||||
res := registrytypes.AuthConfig(authconfig)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ConfigureAuth handles prompting of user's username and password if needed
|
||||
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthConfig, isDefaultRegistry bool) error {
|
||||
// On Windows, force the use of the regular OS stdin stream. Fixes #14336/#14210
|
||||
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes.AuthConfig, isDefaultRegistry bool) error {
|
||||
// On Windows, force the use of the regular OS stdin stream.
|
||||
//
|
||||
// See:
|
||||
// - https://github.com/moby/moby/issues/14336
|
||||
// - https://github.com/moby/moby/issues/14210
|
||||
// - https://github.com/moby/moby/pull/17738
|
||||
//
|
||||
// TODO(thaJeztah): we need to confirm if this special handling is still needed, as we may not be doing this in other places.
|
||||
if runtime.GOOS == "windows" {
|
||||
cli.SetIn(streams.NewIn(os.Stdin))
|
||||
}
|
||||
@@ -120,8 +116,11 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthCon
|
||||
fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
|
||||
}
|
||||
promptWithDefault(cli.Out(), "Username", authconfig.Username)
|
||||
flUser = readInput(cli.In(), cli.Out())
|
||||
flUser = strings.TrimSpace(flUser)
|
||||
var err error
|
||||
flUser, err = readInput(cli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if flUser == "" {
|
||||
flUser = authconfig.Username
|
||||
}
|
||||
@@ -135,12 +134,15 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthCon
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(cli.Out(), "Password: ")
|
||||
term.DisableEcho(cli.In().FD(), oldState)
|
||||
|
||||
flPassword = readInput(cli.In(), cli.Out())
|
||||
_ = term.DisableEcho(cli.In().FD(), oldState)
|
||||
defer func() {
|
||||
_ = term.RestoreTerminal(cli.In().FD(), oldState)
|
||||
}()
|
||||
flPassword, err = readInput(cli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprint(cli.Out(), "\n")
|
||||
|
||||
term.RestoreTerminal(cli.In().FD(), oldState)
|
||||
if flPassword == "" {
|
||||
return errors.Errorf("Error: Password Required")
|
||||
}
|
||||
@@ -152,14 +154,15 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthCon
|
||||
return nil
|
||||
}
|
||||
|
||||
func readInput(in io.Reader, out io.Writer) string {
|
||||
reader := bufio.NewReader(in)
|
||||
line, _, err := reader.ReadLine()
|
||||
// readInput reads, and returns user input from in. It tries to return a
|
||||
// single line, not including the end-of-line bytes, and trims leading
|
||||
// and trailing whitespace.
|
||||
func readInput(in io.Reader) (string, error) {
|
||||
line, _, err := bufio.NewReader(in).ReadLine()
|
||||
if err != nil {
|
||||
fmt.Fprintln(out, err.Error())
|
||||
os.Exit(1)
|
||||
return "", errors.Wrap(err, "error while reading input")
|
||||
}
|
||||
return string(line)
|
||||
return strings.TrimSpace(string(line)), nil
|
||||
}
|
||||
|
||||
func promptWithDefault(out io.Writer, prompt string, configDefault string) {
|
||||
@@ -170,14 +173,19 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) {
|
||||
}
|
||||
}
|
||||
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete
|
||||
// image. The auth configuration is serialized as a base64url encoded RFC4648,
|
||||
// section 5) JSON string for sending through the X-Registry-Auth header.
|
||||
//
|
||||
// For details on base64url encoding, see:
|
||||
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
|
||||
func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) {
|
||||
// Retrieve encoded auth token from the image reference
|
||||
authConfig, err := resolveAuthConfigFromImage(ctx, cli, image)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
encodedAuth, err := EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -185,14 +193,14 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
|
||||
}
|
||||
|
||||
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
|
||||
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (types.AuthConfig, error) {
|
||||
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) {
|
||||
registryRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return types.AuthConfig{}, err
|
||||
return registrytypes.AuthConfig{}, err
|
||||
}
|
||||
repoInfo, err := registry.ParseRepositoryInfo(registryRef)
|
||||
if err != nil {
|
||||
return types.AuthConfig{}, err
|
||||
return registrytypes.AuthConfig{}, err
|
||||
}
|
||||
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/errdefs"
|
||||
@@ -164,7 +163,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo
|
||||
return nil
|
||||
}
|
||||
|
||||
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
fmt.Fprintf(dockerCli.Out(), "Authenticating with existing credentials...\n")
|
||||
cliClient := dockerCli.Client()
|
||||
response, err := cliClient.RegistryLogin(ctx, *authConfig)
|
||||
@@ -178,7 +177,7 @@ func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authCon
|
||||
return response, err
|
||||
}
|
||||
|
||||
func loginClientSide(ctx context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func loginClientSide(ctx context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
svc, err := registry.NewService(registry.ServiceOptions{})
|
||||
if err != nil {
|
||||
return registrytypes.AuthenticateOKBody{}, err
|
||||
|
||||
@@ -3,7 +3,6 @@ package registry
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
@@ -39,9 +38,9 @@ func (c fakeClient) Info(context.Context) (types.Info, error) {
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
func (c fakeClient) RegistryLogin(_ context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
if auth.Password == expiredPassword {
|
||||
return registrytypes.AuthenticateOKBody{}, errors.New("Invalid Username or Password")
|
||||
return registrytypes.AuthenticateOKBody{}, fmt.Errorf("Invalid Username or Password")
|
||||
}
|
||||
if auth.Password == useToken {
|
||||
return registrytypes.AuthenticateOKBody{
|
||||
@@ -54,16 +53,16 @@ func (c fakeClient) RegistryLogin(_ context.Context, auth types.AuthConfig) (reg
|
||||
|
||||
func TestLoginWithCredStoreCreds(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputAuthConfig types.AuthConfig
|
||||
inputAuthConfig registrytypes.AuthConfig
|
||||
expectedMsg string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
inputAuthConfig: types.AuthConfig{},
|
||||
inputAuthConfig: registrytypes.AuthConfig{},
|
||||
expectedMsg: "Authenticating with existing credentials...\n",
|
||||
},
|
||||
{
|
||||
inputAuthConfig: types.AuthConfig{
|
||||
inputAuthConfig: registrytypes.AuthConfig{
|
||||
Username: userErr,
|
||||
},
|
||||
expectedMsg: "Authenticating with existing credentials...\n",
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -54,25 +55,19 @@ func runSearch(dockerCli command.Cli, options searchOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo)
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
searchOptions := types.ImageSearchOptions{
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
|
||||
results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
PrivilegeFunc: requestPrivilege,
|
||||
Filters: options.filter.Value(),
|
||||
Limit: options.limit,
|
||||
}
|
||||
|
||||
clnt := dockerCli.Client()
|
||||
|
||||
results, err := clnt.ImageSearch(ctx, options.term, searchOptions)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ package command_test
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"path/filepath"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
. "github.com/docker/cli/cli/command" // Prevents a circular import with "github.com/docker/cli/internal/test"
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@@ -20,7 +21,7 @@ type fakeClient struct {
|
||||
infoFunc func() (types.Info, error)
|
||||
}
|
||||
|
||||
var testAuthConfigs = []types.AuthConfig{
|
||||
var testAuthConfigs = []registry.AuthConfig{
|
||||
{
|
||||
ServerAddress: "https://index.docker.io/v1/",
|
||||
Username: "u0",
|
||||
@@ -44,12 +45,14 @@ func TestGetDefaultAuthConfig(t *testing.T) {
|
||||
testCases := []struct {
|
||||
checkCredStore bool
|
||||
inputServerAddress string
|
||||
expectedAuthConfig types.AuthConfig
|
||||
expectedErr string
|
||||
expectedAuthConfig registry.AuthConfig
|
||||
}{
|
||||
{
|
||||
checkCredStore: false,
|
||||
inputServerAddress: "",
|
||||
expectedAuthConfig: types.AuthConfig{
|
||||
expectedErr: "",
|
||||
expectedAuthConfig: registry.AuthConfig{
|
||||
ServerAddress: "",
|
||||
Username: "",
|
||||
Password: "",
|
||||
@@ -58,31 +61,38 @@ func TestGetDefaultAuthConfig(t *testing.T) {
|
||||
{
|
||||
checkCredStore: true,
|
||||
inputServerAddress: testAuthConfigs[0].ServerAddress,
|
||||
expectedErr: "",
|
||||
expectedAuthConfig: testAuthConfigs[0],
|
||||
},
|
||||
{
|
||||
checkCredStore: true,
|
||||
inputServerAddress: testAuthConfigs[1].ServerAddress,
|
||||
expectedErr: "",
|
||||
expectedAuthConfig: testAuthConfigs[1],
|
||||
},
|
||||
{
|
||||
checkCredStore: true,
|
||||
inputServerAddress: "https://" + testAuthConfigs[1].ServerAddress,
|
||||
inputServerAddress: fmt.Sprintf("https://%s", testAuthConfigs[1].ServerAddress),
|
||||
expectedErr: "",
|
||||
expectedAuthConfig: testAuthConfigs[1],
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
errBuf := new(bytes.Buffer)
|
||||
cli.SetErr(errBuf)
|
||||
cli.ConfigFile().Filename = filepath.Join(t.TempDir(), "config")
|
||||
for _, authconfig := range testAuthConfigs {
|
||||
assert.Check(t, cli.ConfigFile().GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig)))
|
||||
cli.ConfigFile().GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig))
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
serverAddress := tc.inputServerAddress
|
||||
authconfig, err := command.GetDefaultAuthConfig(cli, tc.checkCredStore, serverAddress, serverAddress == "https://index.docker.io/v1/")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(tc.expectedAuthConfig, authconfig))
|
||||
authconfig, err := GetDefaultAuthConfig(cli, tc.checkCredStore, serverAddress, serverAddress == "https://index.docker.io/v1/")
|
||||
if tc.expectedErr != "" {
|
||||
assert.Check(t, err != nil)
|
||||
assert.Check(t, is.Equal(tc.expectedErr, err.Error()))
|
||||
} else {
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(tc.expectedAuthConfig, authconfig))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,11 +102,10 @@ func TestGetDefaultAuthConfig_HelperError(t *testing.T) {
|
||||
cli.SetErr(errBuf)
|
||||
cli.ConfigFile().CredentialsStore = "fake-does-not-exist"
|
||||
serverAddress := "test-server-address"
|
||||
expectedAuthConfig := types.AuthConfig{
|
||||
expectedAuthConfig := registry.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}
|
||||
const isDefaultRegistry = false // registry is not "https://index.docker.io/v1/"
|
||||
authconfig, err := command.GetDefaultAuthConfig(cli, true, serverAddress, isDefaultRegistry)
|
||||
authconfig, err := GetDefaultAuthConfig(cli, true, serverAddress, serverAddress == "https://index.docker.io/v1/")
|
||||
assert.Check(t, is.DeepEqual(expectedAuthConfig, authconfig))
|
||||
assert.Check(t, is.ErrorContains(err, "docker-credential-fake-does-not-exist"))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -43,7 +43,7 @@ func TestSecretInspectErrors(t *testing.T) {
|
||||
args: []string{"foo", "bar"},
|
||||
secretInspectFunc: func(_ context.Context, secretID string) (swarm.Secret, []byte, error) {
|
||||
if secretID == "foo" {
|
||||
return *builders.Secret(builders.SecretName("foo")), nil, nil
|
||||
return *Secret(SecretName("foo")), nil, nil
|
||||
}
|
||||
return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret")
|
||||
},
|
||||
@@ -58,7 +58,7 @@ func TestSecretInspectErrors(t *testing.T) {
|
||||
)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -78,14 +78,14 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
|
||||
if name != "foo" {
|
||||
return swarm.Secret{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name)
|
||||
}
|
||||
return *builders.Secret(builders.SecretID("ID-foo"), builders.SecretName("foo")), nil, nil
|
||||
return *Secret(SecretID("ID-foo"), SecretName("foo")), nil, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple-secrets-with-labels",
|
||||
args: []string{"foo", "bar"},
|
||||
secretInspectFunc: func(_ context.Context, name string) (swarm.Secret, []byte, error) {
|
||||
return *builders.Secret(builders.SecretID("ID-"+name), builders.SecretName(name), builders.SecretLabels(map[string]string{
|
||||
return *Secret(SecretID("ID-"+name), SecretName(name), SecretLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
},
|
||||
@@ -104,7 +104,7 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
|
||||
|
||||
func TestSecretInspectWithFormat(t *testing.T) {
|
||||
secretInspectFunc := func(_ context.Context, name string) (swarm.Secret, []byte, error) {
|
||||
return *builders.Secret(builders.SecretName("foo"), builders.SecretLabels(map[string]string{
|
||||
return *Secret(SecretName("foo"), SecretLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func TestSecretInspectWithFormat(t *testing.T) {
|
||||
})
|
||||
cmd := newSecretInspectCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
assert.Check(t, cmd.Flags().Set("format", tc.format))
|
||||
cmd.Flags().Set("format", tc.format)
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-with-format.%s.golden", tc.name))
|
||||
}
|
||||
@@ -147,15 +147,15 @@ func TestSecretInspectPretty(t *testing.T) {
|
||||
{
|
||||
name: "simple",
|
||||
secretInspectFunc: func(_ context.Context, id string) (swarm.Secret, []byte, error) {
|
||||
return *builders.Secret(
|
||||
builders.SecretLabels(map[string]string{
|
||||
return *Secret(
|
||||
SecretLabels(map[string]string{
|
||||
"lbl1": "value1",
|
||||
}),
|
||||
builders.SecretID("secretID"),
|
||||
builders.SecretName("secretName"),
|
||||
builders.SecretDriver("driver"),
|
||||
builders.SecretCreatedAt(time.Time{}),
|
||||
builders.SecretUpdatedAt(time.Time{}),
|
||||
SecretID("secretID"),
|
||||
SecretName("secretName"),
|
||||
SecretDriver("driver"),
|
||||
SecretCreatedAt(time.Time{}),
|
||||
SecretUpdatedAt(time.Time{}),
|
||||
), []byte{}, nil
|
||||
},
|
||||
},
|
||||
@@ -166,7 +166,7 @@ func TestSecretInspectPretty(t *testing.T) {
|
||||
})
|
||||
cmd := newSecretInspectCommand(cli)
|
||||
cmd.SetArgs([]string{"secretID"})
|
||||
assert.Check(t, cmd.Flags().Set("pretty", "true"))
|
||||
cmd.Flags().Set("pretty", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-pretty.%s.golden", tc.name))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -50,25 +50,25 @@ func TestSecretList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*builders.Secret(builders.SecretID("ID-1-foo"),
|
||||
builders.SecretName("1-foo"),
|
||||
builders.SecretVersion(swarm.Version{Index: 10}),
|
||||
builders.SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Secret(SecretID("ID-1-foo"),
|
||||
SecretName("1-foo"),
|
||||
SecretVersion(swarm.Version{Index: 10}),
|
||||
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
*builders.Secret(builders.SecretID("ID-10-foo"),
|
||||
builders.SecretName("10-foo"),
|
||||
builders.SecretVersion(swarm.Version{Index: 11}),
|
||||
builders.SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
builders.SecretDriver("driver"),
|
||||
*Secret(SecretID("ID-10-foo"),
|
||||
SecretName("10-foo"),
|
||||
SecretVersion(swarm.Version{Index: 11}),
|
||||
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
SecretDriver("driver"),
|
||||
),
|
||||
*builders.Secret(builders.SecretID("ID-2-foo"),
|
||||
builders.SecretName("2-foo"),
|
||||
builders.SecretVersion(swarm.Version{Index: 11}),
|
||||
builders.SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
builders.SecretDriver("driver"),
|
||||
*Secret(SecretID("ID-2-foo"),
|
||||
SecretName("2-foo"),
|
||||
SecretVersion(swarm.Version{Index: 11}),
|
||||
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
SecretDriver("driver"),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
@@ -82,15 +82,15 @@ func TestSecretListWithQuietOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*builders.Secret(builders.SecretID("ID-foo"), builders.SecretName("foo")),
|
||||
*builders.Secret(builders.SecretID("ID-bar"), builders.SecretName("bar"), builders.SecretLabels(map[string]string{
|
||||
*Secret(SecretID("ID-foo"), SecretName("foo")),
|
||||
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
|
||||
"label": "label-bar",
|
||||
})),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newSecretListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("quiet", "true"))
|
||||
cmd.Flags().Set("quiet", "true")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-quiet-option.golden")
|
||||
}
|
||||
@@ -99,8 +99,8 @@ func TestSecretListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*builders.Secret(builders.SecretID("ID-foo"), builders.SecretName("foo")),
|
||||
*builders.Secret(builders.SecretID("ID-bar"), builders.SecretName("bar"), builders.SecretLabels(map[string]string{
|
||||
*Secret(SecretID("ID-foo"), SecretName("foo")),
|
||||
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
|
||||
"label": "label-bar",
|
||||
})),
|
||||
}, nil
|
||||
@@ -118,15 +118,15 @@ func TestSecretListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*builders.Secret(builders.SecretID("ID-foo"), builders.SecretName("foo")),
|
||||
*builders.Secret(builders.SecretID("ID-bar"), builders.SecretName("bar"), builders.SecretLabels(map[string]string{
|
||||
*Secret(SecretID("ID-foo"), SecretName("foo")),
|
||||
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
|
||||
"label": "label-bar",
|
||||
})),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newSecretListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}"))
|
||||
cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-format.golden")
|
||||
}
|
||||
@@ -137,24 +137,24 @@ func TestSecretListWithFilter(t *testing.T) {
|
||||
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]), "foo")
|
||||
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
|
||||
return []swarm.Secret{
|
||||
*builders.Secret(builders.SecretID("ID-foo"),
|
||||
builders.SecretName("foo"),
|
||||
builders.SecretVersion(swarm.Version{Index: 10}),
|
||||
builders.SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Secret(SecretID("ID-foo"),
|
||||
SecretName("foo"),
|
||||
SecretVersion(swarm.Version{Index: 10}),
|
||||
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
*builders.Secret(builders.SecretID("ID-bar"),
|
||||
builders.SecretName("bar"),
|
||||
builders.SecretVersion(swarm.Version{Index: 11}),
|
||||
builders.SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
builders.SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
*Secret(SecretID("ID-bar"),
|
||||
SecretName("bar"),
|
||||
SecretVersion(swarm.Version{Index: 11}),
|
||||
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newSecretListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("filter", "name=foo"))
|
||||
assert.Check(t, cmd.Flags().Set("filter", "label=lbl1=Label-bar"))
|
||||
cmd.Flags().Set("filter", "name=foo")
|
||||
cmd.Flags().Set("filter", "label=lbl1=Label-bar")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-filter.golden")
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
@@ -39,7 +39,7 @@ func (f *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string
|
||||
return f.serviceInspectWithRawFunc(ctx, serviceID, options)
|
||||
}
|
||||
|
||||
return *builders.Service(builders.ServiceID(serviceID)), []byte{}, nil
|
||||
return *Service(ServiceID(serviceID)), []byte{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
@@ -73,5 +73,5 @@ func (f *fakeClient) NetworkInspect(ctx context.Context, networkID string, optio
|
||||
}
|
||||
|
||||
func newService(id string, name string) swarm.Service {
|
||||
return *builders.Service(builders.ServiceID(id), builders.ServiceName(name))
|
||||
return *Service(ServiceID(id), ServiceName(name))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
// Import builders to get the builder function as package function
|
||||
. "github.com/docker/cli/internal/test/builders"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
@@ -29,7 +30,7 @@ func TestServiceListOrder(t *testing.T) {
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.SetArgs([]string{})
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{.Name}}"))
|
||||
cmd.Flags().Set("format", "{{.Name}}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "service-list-sort.golden")
|
||||
}
|
||||
@@ -247,21 +248,21 @@ func generateServices(t *testing.T, opts clusterOpts) []swarm.Service {
|
||||
}
|
||||
|
||||
return []swarm.Service{
|
||||
*builders.Service(
|
||||
builders.ServiceID("replicated"),
|
||||
builders.ServiceName("01-replicated-service"),
|
||||
builders.ReplicatedService(opts.desiredTasks),
|
||||
builders.ServiceStatus(opts.desiredTasks, opts.runningTasks),
|
||||
*Service(
|
||||
ServiceID("replicated"),
|
||||
ServiceName("01-replicated-service"),
|
||||
ReplicatedService(opts.desiredTasks),
|
||||
ServiceStatus(opts.desiredTasks, opts.runningTasks),
|
||||
),
|
||||
*builders.Service(
|
||||
builders.ServiceID("global"),
|
||||
builders.ServiceName("02-global-service"),
|
||||
builders.GlobalService(),
|
||||
builders.ServiceStatus(opts.activeNodes, globalTasks),
|
||||
*Service(
|
||||
ServiceID("global"),
|
||||
ServiceName("02-global-service"),
|
||||
GlobalService(),
|
||||
ServiceStatus(opts.activeNodes, globalTasks),
|
||||
),
|
||||
*builders.Service(
|
||||
builders.ServiceID("none-id"),
|
||||
builders.ServiceName("03-none-service"),
|
||||
*Service(
|
||||
ServiceID("none-id"),
|
||||
ServiceName("03-none-service"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,9 +214,9 @@ func (f *taskFormatter) format(ctx context.Context, logCtx logContext) (string,
|
||||
taskName := fmt.Sprintf("%s.%d", serviceName, task.Slot)
|
||||
if !f.opts.noTaskIDs {
|
||||
if f.opts.noTrunc {
|
||||
taskName += "." + task.ID
|
||||
taskName += fmt.Sprintf(".%s", task.ID)
|
||||
} else {
|
||||
taskName += "." + stringid.TruncateID(task.ID)
|
||||
taskName += fmt.Sprintf(".%s", stringid.TruncateID(task.ID))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1001,7 +1001,7 @@ const (
|
||||
flagTTY = "tty"
|
||||
flagUpdateDelay = "update-delay"
|
||||
flagUpdateFailureAction = "update-failure-action"
|
||||
flagUpdateMaxFailureRatio = "update-max-failure-ratio" // #nosec G101 -- ignoring: Potential hardcoded credentials (gosec)
|
||||
flagUpdateMaxFailureRatio = "update-max-failure-ratio"
|
||||
flagUpdateMonitor = "update-monitor"
|
||||
flagUpdateOrder = "update-order"
|
||||
flagUpdateParallelism = "update-parallelism"
|
||||
|
||||
@@ -874,7 +874,7 @@ func TestGlobalJobProgressUpdaterLarge(t *testing.T) {
|
||||
tasks := []swarm.Task{}
|
||||
for nodeID := range activeNodes {
|
||||
tasks = append(tasks, swarm.Task{
|
||||
ID: "task" + nodeID,
|
||||
ID: fmt.Sprintf("task%s", nodeID),
|
||||
NodeID: nodeID,
|
||||
DesiredState: swarm.TaskStateComplete,
|
||||
Status: swarm.TaskStatus{
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -38,7 +38,7 @@ func TestListErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*builders.Service()}, nil
|
||||
return []swarm.Service{*Service()}, nil
|
||||
},
|
||||
expectedError: "cannot get label",
|
||||
},
|
||||
@@ -51,7 +51,7 @@ func TestListErrors(t *testing.T) {
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOut(io.Discard)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
@@ -101,8 +101,8 @@ func TestStackList(t *testing.T) {
|
||||
var services []swarm.Service
|
||||
for _, name := range tc.serviceNames {
|
||||
services = append(services,
|
||||
*builders.Service(
|
||||
builders.ServiceLabels(map[string]string{
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": name,
|
||||
}),
|
||||
),
|
||||
@@ -115,7 +115,7 @@ func TestStackList(t *testing.T) {
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.golden)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -76,7 +76,7 @@ func TestStackPs(t *testing.T) {
|
||||
{
|
||||
doc: "WithQuietOption",
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task(builders.TaskID("id-foo"))}, nil
|
||||
return []swarm.Task{*Task(TaskID("id-foo"))}, nil
|
||||
},
|
||||
args: []string{"foo"},
|
||||
flags: map[string]string{
|
||||
@@ -87,7 +87,7 @@ func TestStackPs(t *testing.T) {
|
||||
{
|
||||
doc: "WithNoTruncOption",
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task(builders.TaskID("xn4cypcov06f2w8gsbaf2lst3"))}, nil
|
||||
return []swarm.Task{*Task(TaskID("xn4cypcov06f2w8gsbaf2lst3"))}, nil
|
||||
},
|
||||
args: []string{"foo"},
|
||||
flags: map[string]string{
|
||||
@@ -99,12 +99,12 @@ func TestStackPs(t *testing.T) {
|
||||
{
|
||||
doc: "WithNoResolveOption",
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task(
|
||||
builders.TaskNodeID("id-node-foo"),
|
||||
return []swarm.Task{*Task(
|
||||
TaskNodeID("id-node-foo"),
|
||||
)}, nil
|
||||
},
|
||||
nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeName("node-name-bar")), nil, nil
|
||||
return *Node(NodeName("node-name-bar")), nil, nil
|
||||
},
|
||||
args: []string{"foo"},
|
||||
flags: map[string]string{
|
||||
@@ -116,7 +116,7 @@ func TestStackPs(t *testing.T) {
|
||||
{
|
||||
doc: "WithFormat",
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task(builders.TaskServiceID("service-id-foo"))}, nil
|
||||
return []swarm.Task{*Task(TaskServiceID("service-id-foo"))}, nil
|
||||
},
|
||||
args: []string{"foo"},
|
||||
flags: map[string]string{
|
||||
@@ -127,7 +127,7 @@ func TestStackPs(t *testing.T) {
|
||||
{
|
||||
doc: "WithConfigFormat",
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task(builders.TaskServiceID("service-id-foo"))}, nil
|
||||
return []swarm.Task{*Task(TaskServiceID("service-id-foo"))}, nil
|
||||
},
|
||||
config: configfile.ConfigFile{
|
||||
TasksFormat: "{{ .Name }}",
|
||||
@@ -138,17 +138,17 @@ func TestStackPs(t *testing.T) {
|
||||
{
|
||||
doc: "WithoutFormat",
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task(
|
||||
builders.TaskID("id-foo"),
|
||||
builders.TaskServiceID("service-id-foo"),
|
||||
builders.TaskNodeID("id-node"),
|
||||
builders.WithTaskSpec(builders.TaskImage("myimage:mytag")),
|
||||
builders.TaskDesiredState(swarm.TaskStateReady),
|
||||
builders.WithStatus(builders.TaskState(swarm.TaskStateFailed), builders.Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
return []swarm.Task{*Task(
|
||||
TaskID("id-foo"),
|
||||
TaskServiceID("service-id-foo"),
|
||||
TaskNodeID("id-node"),
|
||||
WithTaskSpec(TaskImage("myimage:mytag")),
|
||||
TaskDesiredState(swarm.TaskStateReady),
|
||||
WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
)}, nil
|
||||
},
|
||||
nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeName("node-name-bar")), nil, nil
|
||||
return *Node(NodeName("node-name-bar")), nil, nil
|
||||
},
|
||||
args: []string{"foo"},
|
||||
golden: "stack-ps-without-format.golden",
|
||||
@@ -166,7 +166,7 @@ func TestStackPs(t *testing.T) {
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -34,20 +34,20 @@ func TestStackServicesErrors(t *testing.T) {
|
||||
{
|
||||
args: []string{"foo"},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*builders.Service(builders.GlobalService())}, nil
|
||||
return []swarm.Service{*Service(GlobalService())}, nil
|
||||
},
|
||||
nodeListFunc: func(options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
return nil, errors.Errorf("error getting nodes")
|
||||
},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*builders.Task()}, nil
|
||||
return []swarm.Task{*Task()}, nil
|
||||
},
|
||||
expectedError: "error getting nodes",
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*builders.Service(builders.GlobalService())}, nil
|
||||
return []swarm.Service{*Service(GlobalService())}, nil
|
||||
},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return nil, errors.Errorf("error getting tasks")
|
||||
@@ -60,7 +60,7 @@ func TestStackServicesErrors(t *testing.T) {
|
||||
"format": "{{invalid format}}",
|
||||
},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*builders.Service()}, nil
|
||||
return []swarm.Service{*Service()}, nil
|
||||
},
|
||||
expectedError: "template parsing error",
|
||||
},
|
||||
@@ -77,7 +77,7 @@ func TestStackServicesErrors(t *testing.T) {
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -109,11 +109,11 @@ func TestStackServicesEmptyServiceList(t *testing.T) {
|
||||
func TestStackServicesWithQuietOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*builders.Service(builders.ServiceID("id-foo"))}, nil
|
||||
return []swarm.Service{*Service(ServiceID("id-foo"))}, nil
|
||||
},
|
||||
})
|
||||
cmd := newServicesCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("quiet", "true"))
|
||||
cmd.Flags().Set("quiet", "true")
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-quiet-option.golden")
|
||||
@@ -123,13 +123,13 @@ func TestStackServicesWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*builders.Service(builders.ServiceName("service-name-foo")),
|
||||
*Service(ServiceName("service-name-foo")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Name }}"))
|
||||
cmd.Flags().Set("format", "{{ .Name }}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-format.golden")
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func TestStackServicesWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*builders.Service(builders.ServiceName("service-name-foo")),
|
||||
*Service(ServiceName("service-name-foo")),
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
@@ -154,12 +154,12 @@ func TestStackServicesWithConfigFormat(t *testing.T) {
|
||||
func TestStackServicesWithoutFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*builders.Service(
|
||||
builders.ServiceName("name-foo"),
|
||||
builders.ServiceID("id-foo"),
|
||||
builders.ReplicatedService(2),
|
||||
builders.ServiceImage("busybox:latest"),
|
||||
builders.ServicePort(swarm.PortConfig{
|
||||
return []swarm.Service{*Service(
|
||||
ServiceName("name-foo"),
|
||||
ServiceID("id-foo"),
|
||||
ReplicatedService(2),
|
||||
ServiceImage("busybox:latest"),
|
||||
ServicePort(swarm.PortConfig{
|
||||
PublishMode: swarm.PortConfigPublishModeIngress,
|
||||
PublishedPort: 0,
|
||||
TargetPort: 3232,
|
||||
|
||||
@@ -58,7 +58,7 @@ func RunRemove(dockerCli command.Cli, opts options.Remove) error {
|
||||
hasError = removeNetworks(ctx, dockerCli, networks) || hasError
|
||||
|
||||
if hasError {
|
||||
errs = append(errs, "Failed to remove some resources from stack: "+namespace)
|
||||
errs = append(errs, fmt.Sprintf("Failed to remove some resources from stack: %s", namespace))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestIPNets(t *testing.T) {
|
||||
f := setUpIPNetFlagSet(&ips)
|
||||
|
||||
vals := []string{"192.168.1.1/24", "10.0.0.1/16", "fd00:0:0:0:0:0:0:2/64"}
|
||||
arg := "--cidrs=" + strings.Join(vals, ",")
|
||||
arg := fmt.Sprintf("--cidrs=%s", strings.Join(vals, ","))
|
||||
err := f.Parse([]string{arg})
|
||||
if err != nil {
|
||||
t.Fatal("expected no error; got", err)
|
||||
@@ -135,7 +135,7 @@ func TestIPNetBadQuoting(t *testing.T) {
|
||||
var cidrs []net.IPNet
|
||||
f := setUpIPNetFlagSet(&cidrs)
|
||||
|
||||
if err := f.Parse([]string{"--cidrs=" + strings.Join(test.FlagArg, ",")}); err != nil {
|
||||
if err := f.Parse([]string{fmt.Sprintf("--cidrs=%s", strings.Join(test.FlagArg, ","))}); err != nil {
|
||||
t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%s",
|
||||
err, test.FlagArg, test.Want[i])
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -96,7 +96,7 @@ func TestSwarmJoinTokenErrors(t *testing.T) {
|
||||
cmd := newJoinTokenCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -123,10 +123,10 @@ func TestSwarmJoinToken(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -140,10 +140,10 @@ func TestSwarmJoinToken(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -160,10 +160,10 @@ func TestSwarmJoinToken(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -173,10 +173,10 @@ func TestSwarmJoinToken(t *testing.T) {
|
||||
flagQuiet: "true",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -186,10 +186,10 @@ func TestSwarmJoinToken(t *testing.T) {
|
||||
flagQuiet: "true",
|
||||
},
|
||||
nodeInspectFunc: func() (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.Manager()), []byte{}, nil
|
||||
return *Node(Manager()), []byte{}, nil
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func TestSwarmJoinToken(t *testing.T) {
|
||||
cmd := newJoinTokenCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("jointoken-%s.golden", tc.name))
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -45,7 +45,7 @@ func TestSwarmUnlockKeyErrors(t *testing.T) {
|
||||
flagRotate: "true",
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
expectedError: "cannot rotate because autolock is not turned on",
|
||||
},
|
||||
@@ -55,7 +55,7 @@ func TestSwarmUnlockKeyErrors(t *testing.T) {
|
||||
flagRotate: "true",
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(builders.Autolock()), nil
|
||||
return *Swarm(Autolock()), nil
|
||||
},
|
||||
swarmUpdateFunc: func(swarm swarm.Spec, flags swarm.UpdateFlags) error {
|
||||
return errors.Errorf("error updating the swarm")
|
||||
@@ -88,7 +88,7 @@ func TestSwarmUnlockKeyErrors(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -129,7 +129,7 @@ func TestSwarmUnlockKey(t *testing.T) {
|
||||
flagRotate: "true",
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(builders.Autolock()), nil
|
||||
return *Swarm(Autolock()), nil
|
||||
},
|
||||
swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) {
|
||||
return types.SwarmUnlockKeyResponse{
|
||||
@@ -144,7 +144,7 @@ func TestSwarmUnlockKey(t *testing.T) {
|
||||
flagRotate: "true",
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(builders.Autolock()), nil
|
||||
return *Swarm(Autolock()), nil
|
||||
},
|
||||
swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) {
|
||||
return types.SwarmUnlockKeyResponse{
|
||||
@@ -162,7 +162,7 @@ func TestSwarmUnlockKey(t *testing.T) {
|
||||
cmd := newUnlockKeyCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("unlockkeys-%s.golden", tc.name))
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/pkg/errors"
|
||||
@@ -56,7 +56,7 @@ func TestSwarmUpdateErrors(t *testing.T) {
|
||||
flagAutolock: "true",
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) {
|
||||
return types.SwarmUnlockKeyResponse{}, errors.Errorf("error getting unlock key")
|
||||
@@ -73,7 +73,7 @@ func TestSwarmUpdateErrors(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
@@ -81,7 +81,7 @@ func TestSwarmUpdateErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSwarmUpdate(t *testing.T) {
|
||||
swarmInfo := builders.Swarm()
|
||||
swarmInfo := Swarm()
|
||||
swarmInfo.ClusterInfo.TLSInfo.TrustRoot = "trustroot"
|
||||
|
||||
testCases := []struct {
|
||||
@@ -105,6 +105,7 @@ func TestSwarmUpdate(t *testing.T) {
|
||||
flagMaxSnapshots: "10",
|
||||
flagSnapshotInterval: "100",
|
||||
flagAutolock: "true",
|
||||
flagQuiet: "true",
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *swarmInfo, nil
|
||||
@@ -155,7 +156,7 @@ func TestSwarmUpdate(t *testing.T) {
|
||||
return nil
|
||||
},
|
||||
swarmInspectFunc: func() (swarm.Swarm, error) {
|
||||
return *builders.Swarm(), nil
|
||||
return *Swarm(), nil
|
||||
},
|
||||
swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) {
|
||||
return types.SwarmUnlockKeyResponse{
|
||||
@@ -173,7 +174,7 @@ func TestSwarmUpdate(t *testing.T) {
|
||||
cmd := newUpdateCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
assert.Check(t, cmd.Flags().Set(key, value))
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(cli.OutBuffer())
|
||||
assert.NilError(t, cmd.Execute())
|
||||
|
||||
@@ -2,7 +2,6 @@ package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
@@ -29,8 +28,8 @@ type infoOptions struct {
|
||||
}
|
||||
|
||||
type clientInfo struct {
|
||||
Debug bool
|
||||
Context string
|
||||
Debug bool
|
||||
clientVersion
|
||||
Plugins []pluginmanager.Plugin
|
||||
Warnings []string
|
||||
}
|
||||
@@ -47,6 +46,13 @@ type info struct {
|
||||
ClientErrors []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (i *info) clientPlatform() string {
|
||||
if i.ClientInfo != nil && i.ClientInfo.Platform != nil {
|
||||
return i.ClientInfo.Platform.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewInfoCommand creates a new cobra.Command for `docker info`
|
||||
func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var opts infoOptions
|
||||
@@ -72,8 +78,11 @@ func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
|
||||
func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error {
|
||||
info := info{
|
||||
ClientInfo: &clientInfo{
|
||||
Context: dockerCli.CurrentContext(),
|
||||
Debug: debug.IsEnabled(),
|
||||
// Don't pass a dockerCLI to newClientVersion(), because we currently
|
||||
// don't include negotiated API version, and want to avoid making an
|
||||
// API connection when only printing the Client section.
|
||||
clientVersion: newClientVersion(dockerCli.CurrentContext(), nil),
|
||||
Debug: debug.IsEnabled(),
|
||||
},
|
||||
Info: &types.Info{},
|
||||
}
|
||||
@@ -148,7 +157,12 @@ func needsServerInfo(template string, info info) bool {
|
||||
}
|
||||
|
||||
func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
// Only append the platform info if it's not empty, to prevent printing a trailing space.
|
||||
if p := info.clientPlatform(); p != "" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:", p)
|
||||
} else {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
}
|
||||
if info.ClientInfo != nil {
|
||||
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
|
||||
}
|
||||
@@ -168,12 +182,13 @@ func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
}
|
||||
|
||||
if len(info.ServerErrors) > 0 || len(info.ClientErrors) > 0 {
|
||||
return errors.New("errors pretty printing info")
|
||||
return fmt.Errorf("errors pretty printing info")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", info.Version)
|
||||
fmt.Fprintln(dockerCli.Out(), " Context: ", info.Context)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
|
||||
@@ -309,7 +324,6 @@ func prettyPrintServerInfo(dockerCli command.Cli, info types.Info) []error {
|
||||
if len(u) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Username:", u)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Registry:", info.IndexServerAddress)
|
||||
}
|
||||
|
||||
if len(info.Labels) > 0 {
|
||||
|
||||
@@ -278,8 +278,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -290,8 +294,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Plugins: samplePluginsInfo,
|
||||
clientVersion: clientVersion{Context: "default"},
|
||||
Plugins: samplePluginsInfo,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-plugins",
|
||||
@@ -302,7 +306,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
doc: "info with nil labels",
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoLabelsNil,
|
||||
ClientInfo: &clientInfo{Context: "default"},
|
||||
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
|
||||
},
|
||||
prettyGolden: "docker-info-with-labels-nil",
|
||||
},
|
||||
@@ -310,7 +314,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
doc: "info with empty labels",
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoLabelsEmpty,
|
||||
ClientInfo: &clientInfo{Context: "default"},
|
||||
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
|
||||
},
|
||||
prettyGolden: "docker-info-with-labels-empty",
|
||||
},
|
||||
@@ -319,8 +323,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &infoWithSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: false,
|
||||
clientVersion: clientVersion{Context: "default"},
|
||||
Debug: false,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-with-swarm",
|
||||
@@ -331,8 +335,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &infoWithWarningsLinux,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -344,8 +352,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoDaemonWarnings,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -376,6 +388,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
expectedError: "errors pretty printing info",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
err := prettyPrintInfo(cli, tc.dockerInfo)
|
||||
@@ -429,6 +442,7 @@ func TestFormatInfo(t *testing.T) {
|
||||
expectedError: `template: :1:2: executing "" at <.badString>: can't evaluate field badString in type system.info`,
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
info := info{
|
||||
|
||||
@@ -2,7 +2,6 @@ package system
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"text/template"
|
||||
@@ -72,7 +71,7 @@ Are you sure you want to continue?`
|
||||
func runPrune(dockerCli command.Cli, options pruneOptions) error {
|
||||
// TODO version this once "until" filter is supported for volumes
|
||||
if options.pruneVolumes && options.filter.Value().Contains("until") {
|
||||
return errors.New(`ERROR: The "until" filter is not supported with "--volumes"`)
|
||||
return fmt.Errorf(`ERROR: The "until" filter is not supported with "--volumes"`)
|
||||
}
|
||||
if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(dockerCli, options)) {
|
||||
return nil
|
||||
@@ -97,11 +96,11 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error {
|
||||
}
|
||||
spaceReclaimed += spc
|
||||
if output != "" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), output)
|
||||
fmt.Fprintln(dockerCli.Out(), output)
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed)))
|
||||
fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"Client":{"Platform":{"Name":""},"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}}
|
||||
{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}}
|
||||
|
||||
@@ -41,7 +41,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":true,"NFd":33,"OomKillDisable":false,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":true,"NFd":33,"OomKillDisable":false,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
+2
-2
@@ -1,4 +1,5 @@
|
||||
Client:
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Context: default
|
||||
Debug Mode: true
|
||||
|
||||
@@ -45,7 +46,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
@@ -51,7 +51,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -45,7 +45,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
|
||||
@@ -45,7 +45,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
|
||||
@@ -67,7 +67,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
const defaultVersionTemplate = `{{with .Client -}}
|
||||
Client:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
Client:{{if ne .Platform nil}}{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}{{end}}
|
||||
Version: {{.Version}}
|
||||
API version: {{.APIVersion}}{{if ne .APIVersion .DefaultAPIVersion}} (downgraded from {{.DefaultAPIVersion}}){{end}}
|
||||
Go version: {{.GoVersion}}
|
||||
@@ -33,7 +33,7 @@ Client:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
Context: {{.Context}}
|
||||
{{- end}}
|
||||
|
||||
{{- if .ServerOK}}{{with .Server}}
|
||||
{{- if ne .Server nil}}{{with .Server}}
|
||||
|
||||
Server:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
{{- range $component := .Components}}
|
||||
@@ -66,24 +66,45 @@ type versionInfo struct {
|
||||
Server *types.Version
|
||||
}
|
||||
|
||||
type clientVersion struct {
|
||||
Platform struct{ Name string } `json:",omitempty"`
|
||||
|
||||
Version string
|
||||
APIVersion string `json:"ApiVersion"`
|
||||
DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"`
|
||||
GitCommit string
|
||||
GoVersion string
|
||||
Os string
|
||||
Arch string
|
||||
BuildTime string `json:",omitempty"`
|
||||
Context string
|
||||
type platformInfo struct {
|
||||
Name string `json:"Name,omitempty"`
|
||||
}
|
||||
|
||||
// ServerOK returns true when the client could connect to the docker server
|
||||
// and parse the information received. It returns false otherwise.
|
||||
func (v versionInfo) ServerOK() bool {
|
||||
return v.Server != nil
|
||||
type clientVersion struct {
|
||||
Platform *platformInfo `json:"Platform,omitempty"`
|
||||
Version string `json:"Version,omitempty"`
|
||||
APIVersion string `json:"ApiVersion,omitempty"`
|
||||
DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"`
|
||||
GitCommit string `json:"GitCommit,omitempty"`
|
||||
GoVersion string `json:"GoVersion,omitempty"`
|
||||
Os string `json:"Os,omitempty"`
|
||||
Arch string `json:"Arch,omitempty"`
|
||||
BuildTime string `json:"BuildTime,omitempty"`
|
||||
Context string `json:"Context"`
|
||||
}
|
||||
|
||||
// newClientVersion constructs a new clientVersion. If a dockerCLI is
|
||||
// passed as argument, additional information is included (API version),
|
||||
// which may invoke an API connection. Pass nil to omit the additional
|
||||
// information.
|
||||
func newClientVersion(contextName string, dockerCli command.Cli) clientVersion {
|
||||
v := clientVersion{
|
||||
Version: version.Version,
|
||||
GoVersion: runtime.Version(),
|
||||
GitCommit: version.GitCommit,
|
||||
BuildTime: reformatDate(version.BuildTime),
|
||||
Os: runtime.GOOS,
|
||||
Arch: arch(),
|
||||
Context: contextName,
|
||||
}
|
||||
if version.PlatformName != "" {
|
||||
v.Platform = &platformInfo{Name: version.PlatformName}
|
||||
}
|
||||
if dockerCli != nil {
|
||||
v.APIVersion = dockerCli.CurrentVersion()
|
||||
v.DefaultAPIVersion = dockerCli.DefaultVersion()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// NewVersionCommand creates a new cobra.Command for `docker version`
|
||||
@@ -133,20 +154,8 @@ func runVersion(dockerCli command.Cli, opts *versionOptions) error {
|
||||
// TODO print error if kubernetes is used?
|
||||
|
||||
vd := versionInfo{
|
||||
Client: clientVersion{
|
||||
Platform: struct{ Name string }{version.PlatformName},
|
||||
Version: version.Version,
|
||||
APIVersion: dockerCli.CurrentVersion(),
|
||||
DefaultAPIVersion: dockerCli.DefaultVersion(),
|
||||
GoVersion: runtime.Version(),
|
||||
GitCommit: version.GitCommit,
|
||||
BuildTime: reformatDate(version.BuildTime),
|
||||
Os: runtime.GOOS,
|
||||
Arch: arch(),
|
||||
Context: dockerCli.CurrentContext(),
|
||||
},
|
||||
Client: newClientVersion(dockerCli.CurrentContext(), dockerCli),
|
||||
}
|
||||
|
||||
sv, err := dockerCli.Client().ServerVersion(context.Background())
|
||||
if err == nil {
|
||||
vd.Server = &sv
|
||||
|
||||
@@ -2,7 +2,7 @@ package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
func TestVersionWithoutServer(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serverVersion: func(ctx context.Context) (types.Version, error) {
|
||||
return types.Version{}, errors.New("no server")
|
||||
return types.Version{}, fmt.Errorf("no server")
|
||||
},
|
||||
})
|
||||
cmd := NewVersionCommand(cli)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/cli/cli/command/idresolver"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"gotest.tools/v3/assert"
|
||||
@@ -19,29 +19,29 @@ func TestTaskPrintSorted(t *testing.T) {
|
||||
apiClient := &fakeClient{
|
||||
serviceInspectWithRaw: func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
if ref == "service-id-one" {
|
||||
return *builders.Service(builders.ServiceName("service-name-1")), nil, nil
|
||||
return *Service(ServiceName("service-name-1")), nil, nil
|
||||
}
|
||||
return *builders.Service(builders.ServiceName("service-name-10")), nil, nil
|
||||
return *Service(ServiceName("service-name-10")), nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{
|
||||
*builders.Task(
|
||||
builders.TaskID("id-foo"),
|
||||
builders.TaskServiceID("service-id-ten"),
|
||||
builders.TaskNodeID("id-node"),
|
||||
builders.WithTaskSpec(builders.TaskImage("myimage:mytag")),
|
||||
builders.TaskDesiredState(swarm.TaskStateReady),
|
||||
builders.WithStatus(builders.TaskState(swarm.TaskStateFailed), builders.Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
*Task(
|
||||
TaskID("id-foo"),
|
||||
TaskServiceID("service-id-ten"),
|
||||
TaskNodeID("id-node"),
|
||||
WithTaskSpec(TaskImage("myimage:mytag")),
|
||||
TaskDesiredState(swarm.TaskStateReady),
|
||||
WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
),
|
||||
*builders.Task(
|
||||
builders.TaskID("id-bar"),
|
||||
builders.TaskServiceID("service-id-one"),
|
||||
builders.TaskNodeID("id-node"),
|
||||
builders.WithTaskSpec(builders.TaskImage("myimage:mytag")),
|
||||
builders.TaskDesiredState(swarm.TaskStateReady),
|
||||
builders.WithStatus(builders.TaskState(swarm.TaskStateFailed), builders.Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
*Task(
|
||||
TaskID("id-bar"),
|
||||
TaskServiceID("service-id-one"),
|
||||
TaskNodeID("id-node"),
|
||||
WithTaskSpec(TaskImage("myimage:mytag")),
|
||||
TaskDesiredState(swarm.TaskStateReady),
|
||||
WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
),
|
||||
}
|
||||
|
||||
@@ -51,25 +51,25 @@ func TestTaskPrintSorted(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTaskPrintWithQuietOption(t *testing.T) {
|
||||
const quiet = true
|
||||
const trunc = false
|
||||
const noResolve = true
|
||||
quiet := true
|
||||
trunc := false
|
||||
noResolve := true
|
||||
apiClient := &fakeClient{}
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{*builders.Task(builders.TaskID("id-foo"))}
|
||||
tasks := []swarm.Task{*Task(TaskID("id-foo"))}
|
||||
err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, formatter.TableFormatKey)
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, cli.OutBuffer().String(), "task-print-with-quiet-option.golden")
|
||||
}
|
||||
|
||||
func TestTaskPrintWithNoTruncOption(t *testing.T) {
|
||||
const quiet = false
|
||||
const trunc = false
|
||||
const noResolve = true
|
||||
quiet := false
|
||||
trunc := false
|
||||
noResolve := true
|
||||
apiClient := &fakeClient{}
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{
|
||||
*builders.Task(builders.TaskID("id-foo-yov6omdek8fg3k5stosyp2m50")),
|
||||
*Task(TaskID("id-foo-yov6omdek8fg3k5stosyp2m50")),
|
||||
}
|
||||
err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .ID }}")
|
||||
assert.NilError(t, err)
|
||||
@@ -77,13 +77,13 @@ func TestTaskPrintWithNoTruncOption(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTaskPrintWithGlobalService(t *testing.T) {
|
||||
const quiet = false
|
||||
const trunc = false
|
||||
const noResolve = true
|
||||
quiet := false
|
||||
trunc := false
|
||||
noResolve := true
|
||||
apiClient := &fakeClient{}
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{
|
||||
*builders.Task(builders.TaskServiceID("service-id-foo"), builders.TaskNodeID("node-id-bar"), builders.TaskSlot(0)),
|
||||
*Task(TaskServiceID("service-id-foo"), TaskNodeID("node-id-bar"), TaskSlot(0)),
|
||||
}
|
||||
err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .Name }}")
|
||||
assert.NilError(t, err)
|
||||
@@ -91,13 +91,13 @@ func TestTaskPrintWithGlobalService(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTaskPrintWithReplicatedService(t *testing.T) {
|
||||
const quiet = false
|
||||
const trunc = false
|
||||
const noResolve = true
|
||||
quiet := false
|
||||
trunc := false
|
||||
noResolve := true
|
||||
apiClient := &fakeClient{}
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{
|
||||
*builders.Task(builders.TaskServiceID("service-id-foo"), builders.TaskSlot(1)),
|
||||
*Task(TaskServiceID("service-id-foo"), TaskSlot(1)),
|
||||
}
|
||||
err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .Name }}")
|
||||
assert.NilError(t, err)
|
||||
@@ -105,34 +105,34 @@ func TestTaskPrintWithReplicatedService(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTaskPrintWithIndentation(t *testing.T) {
|
||||
const quiet = false
|
||||
const trunc = false
|
||||
const noResolve = false
|
||||
quiet := false
|
||||
trunc := false
|
||||
noResolve := false
|
||||
apiClient := &fakeClient{
|
||||
serviceInspectWithRaw: func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
return *builders.Service(builders.ServiceName("service-name-foo")), nil, nil
|
||||
return *Service(ServiceName("service-name-foo")), nil, nil
|
||||
},
|
||||
nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeName("node-name-bar")), nil, nil
|
||||
return *Node(NodeName("node-name-bar")), nil, nil
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{
|
||||
*builders.Task(
|
||||
builders.TaskID("id-foo"),
|
||||
builders.TaskServiceID("service-id-foo"),
|
||||
builders.TaskNodeID("id-node"),
|
||||
builders.WithTaskSpec(builders.TaskImage("myimage:mytag")),
|
||||
builders.TaskDesiredState(swarm.TaskStateReady),
|
||||
builders.WithStatus(builders.TaskState(swarm.TaskStateFailed), builders.Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
*Task(
|
||||
TaskID("id-foo"),
|
||||
TaskServiceID("service-id-foo"),
|
||||
TaskNodeID("id-node"),
|
||||
WithTaskSpec(TaskImage("myimage:mytag")),
|
||||
TaskDesiredState(swarm.TaskStateReady),
|
||||
WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
),
|
||||
*builders.Task(
|
||||
builders.TaskID("id-bar"),
|
||||
builders.TaskServiceID("service-id-foo"),
|
||||
builders.TaskNodeID("id-node"),
|
||||
builders.WithTaskSpec(builders.TaskImage("myimage:mytag")),
|
||||
builders.TaskDesiredState(swarm.TaskStateReady),
|
||||
builders.WithStatus(builders.TaskState(swarm.TaskStateFailed), builders.Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
*Task(
|
||||
TaskID("id-bar"),
|
||||
TaskServiceID("service-id-foo"),
|
||||
TaskNodeID("id-node"),
|
||||
WithTaskSpec(TaskImage("myimage:mytag")),
|
||||
TaskDesiredState(swarm.TaskStateReady),
|
||||
WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
),
|
||||
}
|
||||
err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, formatter.TableFormatKey)
|
||||
@@ -141,20 +141,20 @@ func TestTaskPrintWithIndentation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTaskPrintWithResolution(t *testing.T) {
|
||||
const quiet = false
|
||||
const trunc = false
|
||||
const noResolve = false
|
||||
quiet := false
|
||||
trunc := false
|
||||
noResolve := false
|
||||
apiClient := &fakeClient{
|
||||
serviceInspectWithRaw: func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
return *builders.Service(builders.ServiceName("service-name-foo")), nil, nil
|
||||
return *Service(ServiceName("service-name-foo")), nil, nil
|
||||
},
|
||||
nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) {
|
||||
return *builders.Node(builders.NodeName("node-name-bar")), nil, nil
|
||||
return *Node(NodeName("node-name-bar")), nil, nil
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(apiClient)
|
||||
tasks := []swarm.Task{
|
||||
*builders.Task(builders.TaskServiceID("service-id-foo"), builders.TaskSlot(1)),
|
||||
*Task(TaskServiceID("service-id-foo"), TaskSlot(1)),
|
||||
}
|
||||
err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .Name }} {{ .Node }}")
|
||||
assert.NilError(t, err)
|
||||
|
||||
@@ -53,7 +53,7 @@ type trustKey struct {
|
||||
// This information is to be pretty printed or serialized into a machine-readable format.
|
||||
func lookupTrustInfo(cli command.Cli, remote string) ([]trustTagRow, []client.RoleWithSignatures, []data.Role, error) {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return []trustTagRow{}, []client.RoleWithSignatures{}, []data.Role{}, err
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func decodePrivKeyIfNecessary(privPemBytes []byte, passRet notary.PassRetriever)
|
||||
if _, ok := pemBlock.Headers["path"]; !ok {
|
||||
privKey, _, err := trustmanager.GetPasswdDecryptBytes(passRet, privPemBytes, "", "encrypted")
|
||||
if err != nil {
|
||||
return []byte{}, errors.New("could not decrypt key")
|
||||
return []byte{}, fmt.Errorf("could not decrypt key")
|
||||
}
|
||||
privPemBytes = privKey.Private()
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ func newRevokeCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tag := imgRefAndAuth.Tag()
|
||||
if imgRefAndAuth.Tag() == "" && imgRefAndAuth.Digest() != "" {
|
||||
return errors.New("cannot use a digest reference for IMAGE:TAG")
|
||||
return fmt.Errorf("cannot use a digest reference for IMAGE:TAG")
|
||||
}
|
||||
if imgRefAndAuth.Tag() == "" && !options.forceYes {
|
||||
deleteRemote := command.PromptForConfirmation(os.Stdin, cli.Out(), fmt.Sprintf("Please confirm you would like to delete all signature data for %s?", remote))
|
||||
@@ -64,7 +64,7 @@ func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||
if err := revokeSignature(notaryRepo, tag); err != nil {
|
||||
return errors.Wrapf(err, "could not remove signature for %s", remote)
|
||||
}
|
||||
_, _ = fmt.Fprintf(cli.Out(), "Successfully deleted signature for %s\n", remote)
|
||||
fmt.Fprintf(cli.Out(), "Successfully deleted signature for %s\n", remote)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ func revokeAllSigs(notaryRepo client.Repository) error {
|
||||
}
|
||||
|
||||
if len(releasedTargetWithRoleList) == 0 {
|
||||
return errors.New("no signed tags to remove")
|
||||
return fmt.Errorf("no signed tags to remove")
|
||||
}
|
||||
|
||||
// we need all the roles that signed each released target so we can remove from all roles.
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/theupdateframework/notary/client"
|
||||
@@ -43,7 +44,7 @@ func newSignCommand(dockerCli command.Cli) *cobra.Command {
|
||||
func runSignImage(cli command.Cli, options signOptions) error {
|
||||
imageName := options.imageName
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), imageName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -93,7 +94,7 @@ func runSignImage(cli command.Cli, options signOptions) error {
|
||||
fmt.Fprintf(cli.Err(), "Signing and pushing trust data for local image %s, may overwrite remote trust data\n", imageName)
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, cli, imgRefAndAuth.RepoInfo().Index)
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user