mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Finally rid of capital Sirupsen??
This commit is contained in:
12
vendor/github.com/docker/cli/Jenkinsfile
generated
vendored
Normal file
12
vendor/github.com/docker/cli/Jenkinsfile
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
wrappedNode(label: 'linux && x86_64', cleanWorkspace: true) {
|
||||
timeout(time: 60, unit: 'MINUTES') {
|
||||
stage "Git Checkout"
|
||||
checkout scm
|
||||
|
||||
stage "Run end-to-end test suite"
|
||||
sh "docker version"
|
||||
sh "E2E_UNIQUE_ID=clie2e${BUILD_NUMBER} \
|
||||
IMAGE_TAG=clie2e${BUILD_NUMBER} \
|
||||
make -f docker.Makefile test-e2e"
|
||||
}
|
||||
}
|
||||
6
vendor/github.com/docker/cli/MAINTAINERS
generated
vendored
6
vendor/github.com/docker/cli/MAINTAINERS
generated
vendored
@@ -27,6 +27,7 @@
|
||||
|
||||
people = [
|
||||
"aaronlehmann",
|
||||
"albers",
|
||||
"aluzzardi",
|
||||
"anusha",
|
||||
"cpuguy83",
|
||||
@@ -84,6 +85,11 @@
|
||||
Email = "aaron.lehmann@docker.com"
|
||||
GitHub = "aaronlehmann"
|
||||
|
||||
[people.albers]
|
||||
Name = "Harald Albers"
|
||||
Email = "github@albersweb.de"
|
||||
GitHub = "albers"
|
||||
|
||||
[people.aluzzardi]
|
||||
Name = "Andrea Luzzardi"
|
||||
Email = "al@docker.com"
|
||||
|
||||
9
vendor/github.com/docker/cli/Makefile
generated
vendored
9
vendor/github.com/docker/cli/Makefile
generated
vendored
@@ -10,13 +10,16 @@ _:=$(shell ./scripts/warn-outside-container $(MAKECMDGOALS))
|
||||
clean: ## remove build artifacts
|
||||
rm -rf ./build/* cli/winresources/rsrc_* ./man/man[1-9] docs/yaml/gen
|
||||
|
||||
.PHONY: test-unit
|
||||
test-unit: ## run unit test
|
||||
./scripts/test/unit $(shell go list ./... | grep -vE '/vendor/|/e2e/')
|
||||
|
||||
.PHONY: test
|
||||
test: ## run go test
|
||||
./scripts/test/unit $(shell go list ./... | grep -v '/vendor/')
|
||||
test: test-unit ## run tests
|
||||
|
||||
.PHONY: test-coverage
|
||||
test-coverage: ## run test coverage
|
||||
./scripts/test/unit-with-coverage $(shell go list ./... | grep -v '/vendor/')
|
||||
./scripts/test/unit-with-coverage $(shell go list ./... | grep -vE '/vendor/|/e2e/')
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## run all the lint tools
|
||||
|
||||
87
vendor/github.com/docker/cli/TESTING.md
generated
vendored
Normal file
87
vendor/github.com/docker/cli/TESTING.md
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
# Testing
|
||||
|
||||
The following guidelines summarize the testing policy for docker/cli.
|
||||
|
||||
## Unit Test Suite
|
||||
|
||||
All code changes should have unit test coverage.
|
||||
|
||||
Error cases should be tested with unit tests.
|
||||
|
||||
Bug fixes should be covered by new unit tests or additional assertions in
|
||||
existing unit tests.
|
||||
|
||||
### Details
|
||||
|
||||
The unit test suite follows the standard Go testing convention. Tests are
|
||||
located in the package directory in `_test.go` files.
|
||||
|
||||
Unit tests should be named using the convention:
|
||||
|
||||
```
|
||||
Test<Function Name><Test Case Name>
|
||||
```
|
||||
|
||||
[Table tests](https://github.com/golang/go/wiki/TableDrivenTests) should be used
|
||||
where appropriate, but may not be appropriate in all cases.
|
||||
|
||||
Assertions should be made using
|
||||
[testify/assert](https://godoc.org/github.com/stretchr/testify/assert) and test
|
||||
requirements should be verified using
|
||||
[testify/require](https://godoc.org/github.com/stretchr/testify/require).
|
||||
|
||||
Fakes, and testing utilities can be found in
|
||||
[internal/test](https://godoc.org/github.com/docker/cli/internal/test) and
|
||||
[gotestyourself](https://godoc.org/github.com/gotestyourself/gotestyourself).
|
||||
|
||||
## End-to-End Test Suite
|
||||
|
||||
The end-to-end test suite tests a cli binary against a real API backend.
|
||||
|
||||
### Guidelines
|
||||
|
||||
Each feature (subcommand) should have a single end-to-end test for
|
||||
the success case. The test should include all (or most) flags/options supported
|
||||
by that feature.
|
||||
|
||||
In some rare cases a couple additional end-to-end tests may be written for a
|
||||
sufficiently complex and critical feature (ex: `container run`, `service
|
||||
create`, `service update`, and `docker build` may have ~3-5 cases each).
|
||||
|
||||
In some rare cases a sufficiently critical error paths may have a single
|
||||
end-to-end test case.
|
||||
|
||||
In all other cases the behaviour should be covered by unit tests.
|
||||
|
||||
If a code change adds a new flag, that flag should be added to the existing
|
||||
"success case" end-to-end test.
|
||||
|
||||
If a code change fixes a bug, that bug fix should be covered either by adding
|
||||
assertions to the existing end-to-end test, or with one or more unit test.
|
||||
|
||||
### Details
|
||||
|
||||
The end-to-end test suite is located in
|
||||
[./e2e](https://github.com/docker/cli/tree/master/e2e). Each directory in `e2e`
|
||||
corresponds to a directory in `cli/command` and contains the tests for that
|
||||
subcommand. Files in each directory should be named `<command>_test.go` where
|
||||
command is the basename of the command (ex: the test for `docker stack deploy`
|
||||
is found in `e2e/stack/deploy_test.go`).
|
||||
|
||||
Tests should be named using the convention:
|
||||
|
||||
```
|
||||
Test<Command Basename>[<Test Case Name>]
|
||||
```
|
||||
|
||||
where the test case name is only required when there are multiple test cases for
|
||||
a single command.
|
||||
|
||||
End-to-end test should run the `docker` binary using
|
||||
[gotestyourself/icmd](https://godoc.org/github.com/gotestyourself/gotestyourself/icmd)
|
||||
and make assertions about the exit code, stdout, stderr, and local file system.
|
||||
|
||||
Any Docker image or registry operations should use `registry:5000/<image name>`
|
||||
to communicate with the local instance of the Docker registry. To load
|
||||
additional fixture images to the registry see
|
||||
[scripts/test/e2e/run](https://github.com/docker/cli/blob/master/scripts/test/e2e/run).
|
||||
2
vendor/github.com/docker/cli/VERSION
generated
vendored
2
vendor/github.com/docker/cli/VERSION
generated
vendored
@@ -1 +1 @@
|
||||
17.08.0-dev
|
||||
17.10.0-dev
|
||||
|
||||
45
vendor/github.com/docker/cli/cli/command/container/attach.go
generated
vendored
45
vendor/github.com/docker/cli/cli/command/container/attach.go
generated
vendored
@@ -4,13 +4,13 @@ import (
|
||||
"io"
|
||||
"net/http/httputil"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -120,18 +120,7 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
||||
}
|
||||
|
||||
if c.Config.Tty && dockerCli.Out().IsTerminal() {
|
||||
height, width := dockerCli.Out().GetTtySize()
|
||||
// To handle the case where a user repeatedly attaches/detaches without resizing their
|
||||
// terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially
|
||||
// resize it, then go back to normal. Without this, every attach after the first will
|
||||
// require the user to manually resize or hit enter.
|
||||
resizeTtyTo(ctx, client, opts.container, height+1, width+1, false)
|
||||
|
||||
// After the above resizing occurs, the call to MonitorTtySize below will handle resetting back
|
||||
// to the actual size.
|
||||
if err := MonitorTtySize(ctx, dockerCli, opts.container, false); err != nil {
|
||||
logrus.Debugf("Error monitoring TTY size: %s", err)
|
||||
}
|
||||
resizeTTY(ctx, dockerCli, opts.container)
|
||||
}
|
||||
|
||||
streamer := hijackedIOStreamer{
|
||||
@@ -151,14 +140,36 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
||||
if errAttach != nil {
|
||||
return errAttach
|
||||
}
|
||||
return getExitStatus(ctx, dockerCli.Client(), opts.container)
|
||||
}
|
||||
|
||||
_, status, err := getExitCode(ctx, dockerCli, opts.container)
|
||||
if err != nil {
|
||||
return err
|
||||
func resizeTTY(ctx context.Context, dockerCli command.Cli, containerID string) {
|
||||
height, width := dockerCli.Out().GetTtySize()
|
||||
// To handle the case where a user repeatedly attaches/detaches without resizing their
|
||||
// terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially
|
||||
// resize it, then go back to normal. Without this, every attach after the first will
|
||||
// require the user to manually resize or hit enter.
|
||||
resizeTtyTo(ctx, dockerCli.Client(), containerID, height+1, width+1, false)
|
||||
|
||||
// After the above resizing occurs, the call to MonitorTtySize below will handle resetting back
|
||||
// to the actual size.
|
||||
if err := MonitorTtySize(ctx, dockerCli, containerID, false); err != nil {
|
||||
logrus.Debugf("Error monitoring TTY size: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func getExitStatus(ctx context.Context, apiclient client.ContainerAPIClient, containerID string) error {
|
||||
container, err := apiclient.ContainerInspect(ctx, containerID)
|
||||
if err != nil {
|
||||
// If we can't connect, then the daemon probably died.
|
||||
if !client.IsErrConnectionFailed(err) {
|
||||
return err
|
||||
}
|
||||
return cli.StatusError{StatusCode: -1}
|
||||
}
|
||||
status := container.State.ExitCode
|
||||
if status != 0 {
|
||||
return cli.StatusError{StatusCode: status}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
44
vendor/github.com/docker/cli/cli/command/container/attach_test.go
generated
vendored
44
vendor/github.com/docker/cli/cli/command/container/attach_test.go
generated
vendored
@@ -4,10 +4,13 @@ import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/testutil"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestNewAttachCommandErrors(t *testing.T) {
|
||||
@@ -67,9 +70,48 @@ func TestNewAttachCommandErrors(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{containerInspectFunc: tc.containerInspectFunc}))
|
||||
cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc}))
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExitStatus(t *testing.T) {
|
||||
containerID := "the exec id"
|
||||
expecatedErr := errors.New("unexpected error")
|
||||
|
||||
testcases := []struct {
|
||||
inspectError error
|
||||
exitCode int
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
inspectError: nil,
|
||||
exitCode: 0,
|
||||
},
|
||||
{
|
||||
inspectError: expecatedErr,
|
||||
expectedError: expecatedErr,
|
||||
},
|
||||
{
|
||||
exitCode: 15,
|
||||
expectedError: cli.StatusError{StatusCode: 15},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
client := &fakeClient{
|
||||
inspectFunc: func(id string) (types.ContainerJSON, error) {
|
||||
assert.Equal(t, containerID, id)
|
||||
return types.ContainerJSON{
|
||||
ContainerJSONBase: &types.ContainerJSONBase{
|
||||
State: &types.ContainerState{ExitCode: testcase.exitCode},
|
||||
},
|
||||
}, testcase.inspectError
|
||||
},
|
||||
}
|
||||
err := getExitStatus(context.Background(), client, containerID)
|
||||
assert.Equal(t, testcase.expectedError, err)
|
||||
}
|
||||
}
|
||||
|
||||
62
vendor/github.com/docker/cli/cli/command/container/client_test.go
generated
vendored
62
vendor/github.com/docker/cli/cli/command/container/client_test.go
generated
vendored
@@ -1,19 +1,73 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type fakeClient struct {
|
||||
client.Client
|
||||
containerInspectFunc func(string) (types.ContainerJSON, error)
|
||||
inspectFunc func(string) (types.ContainerJSON, error)
|
||||
execInspectFunc func(execID string) (types.ContainerExecInspect, error)
|
||||
execCreateFunc func(container string, config types.ExecConfig) (types.IDResponse, error)
|
||||
createContainerFunc func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error)
|
||||
imageCreateFunc func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
|
||||
infoFunc func() (types.Info, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ContainerInspect(_ context.Context, containerID string) (types.ContainerJSON, error) {
|
||||
if cli.containerInspectFunc != nil {
|
||||
return cli.containerInspectFunc(containerID)
|
||||
func (f *fakeClient) ContainerInspect(_ context.Context, containerID string) (types.ContainerJSON, error) {
|
||||
if f.inspectFunc != nil {
|
||||
return f.inspectFunc(containerID)
|
||||
}
|
||||
return types.ContainerJSON{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerExecCreate(_ context.Context, container string, config types.ExecConfig) (types.IDResponse, error) {
|
||||
if f.execCreateFunc != nil {
|
||||
return f.execCreateFunc(container, config)
|
||||
}
|
||||
return types.IDResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerExecInspect(_ context.Context, execID string) (types.ContainerExecInspect, error) {
|
||||
if f.execInspectFunc != nil {
|
||||
return f.execInspectFunc(execID)
|
||||
}
|
||||
return types.ContainerExecInspect{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerCreate(
|
||||
_ context.Context,
|
||||
config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
containerName string,
|
||||
) (container.ContainerCreateCreatedBody, error) {
|
||||
if f.createContainerFunc != nil {
|
||||
return f.createContainerFunc(config, hostConfig, networkingConfig, containerName)
|
||||
}
|
||||
return container.ContainerCreateCreatedBody{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
if f.imageCreateFunc != nil {
|
||||
return f.imageCreateFunc(parentReference, options)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) Info(_ context.Context) (types.Info, error) {
|
||||
if f.infoFunc != nil {
|
||||
return f.infoFunc()
|
||||
}
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
35
vendor/github.com/docker/cli/cli/command/container/create.go
generated
vendored
35
vendor/github.com/docker/cli/cli/command/container/create.go
generated
vendored
@@ -113,6 +113,9 @@ type cidFile struct {
|
||||
}
|
||||
|
||||
func (cid *cidFile) Close() error {
|
||||
if cid.file == nil {
|
||||
return nil
|
||||
}
|
||||
cid.file.Close()
|
||||
|
||||
if cid.written {
|
||||
@@ -126,6 +129,9 @@ func (cid *cidFile) Close() error {
|
||||
}
|
||||
|
||||
func (cid *cidFile) Write(id string) error {
|
||||
if cid.file == nil {
|
||||
return nil
|
||||
}
|
||||
if _, err := cid.file.Write([]byte(id)); err != nil {
|
||||
return errors.Errorf("Failed to write the container ID to the file: %s", err)
|
||||
}
|
||||
@@ -134,6 +140,9 @@ func (cid *cidFile) Write(id string) error {
|
||||
}
|
||||
|
||||
func newCIDFile(path string) (*cidFile, error) {
|
||||
if path == "" {
|
||||
return &cidFile{}, nil
|
||||
}
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return nil, errors.Errorf("Container ID file found, make sure the other container isn't running or delete %s", path)
|
||||
}
|
||||
@@ -153,19 +162,15 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
stderr := dockerCli.Err()
|
||||
|
||||
var (
|
||||
containerIDFile *cidFile
|
||||
trustedRef reference.Canonical
|
||||
namedRef reference.Named
|
||||
trustedRef reference.Canonical
|
||||
namedRef reference.Named
|
||||
)
|
||||
|
||||
cidfile := hostConfig.ContainerIDFile
|
||||
if cidfile != "" {
|
||||
var err error
|
||||
if containerIDFile, err = newCIDFile(cidfile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer containerIDFile.Close()
|
||||
containerIDFile, err := newCIDFile(hostConfig.ContainerIDFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer containerIDFile.Close()
|
||||
|
||||
ref, err := reference.ParseAnyReference(config.Image)
|
||||
if err != nil {
|
||||
@@ -193,7 +198,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
fmt.Fprintf(stderr, "Unable to find image '%s' locally\n", reference.FamiliarString(namedRef))
|
||||
|
||||
// we don't want to write to stdout anything apart from container.ID
|
||||
if err = pullImage(ctx, dockerCli, config.Image, stderr); err != nil {
|
||||
if err := pullImage(ctx, dockerCli, config.Image, stderr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
|
||||
@@ -215,10 +220,6 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
for _, warning := range response.Warnings {
|
||||
fmt.Fprintf(stderr, "WARNING: %s\n", warning)
|
||||
}
|
||||
if containerIDFile != nil {
|
||||
if err = containerIDFile.Write(response.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &response, nil
|
||||
err = containerIDFile.Write(response.ID)
|
||||
return &response, err
|
||||
}
|
||||
|
||||
120
vendor/github.com/docker/cli/cli/command/container/create_test.go
generated
vendored
Normal file
120
vendor/github.com/docker/cli/cli/command/container/create_test.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/testutil"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/gotestyourself/gotestyourself/fs"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCIDFileNoOPWithNoFilename(t *testing.T) {
|
||||
file, err := newCIDFile("")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &cidFile{}, file)
|
||||
|
||||
assert.NoError(t, file.Write("id"))
|
||||
assert.NoError(t, file.Close())
|
||||
}
|
||||
|
||||
func TestNewCIDFileWhenFileAlreadyExists(t *testing.T) {
|
||||
tempfile := fs.NewFile(t, "test-cid-file")
|
||||
defer tempfile.Remove()
|
||||
|
||||
_, err := newCIDFile(tempfile.Path())
|
||||
testutil.ErrorContains(t, err, "Container ID file found")
|
||||
}
|
||||
|
||||
func TestCIDFileCloseWithNoWrite(t *testing.T) {
|
||||
tempdir := fs.NewDir(t, "test-cid-file")
|
||||
defer tempdir.Remove()
|
||||
|
||||
path := tempdir.Join("cidfile")
|
||||
file, err := newCIDFile(path)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, file.path, path)
|
||||
|
||||
assert.NoError(t, file.Close())
|
||||
_, err = os.Stat(path)
|
||||
assert.True(t, os.IsNotExist(err))
|
||||
}
|
||||
|
||||
func TestCIDFileCloseWithWrite(t *testing.T) {
|
||||
tempdir := fs.NewDir(t, "test-cid-file")
|
||||
defer tempdir.Remove()
|
||||
|
||||
path := tempdir.Join("cidfile")
|
||||
file, err := newCIDFile(path)
|
||||
require.NoError(t, err)
|
||||
|
||||
content := "id"
|
||||
assert.NoError(t, file.Write(content))
|
||||
|
||||
actual, err := ioutil.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, content, string(actual))
|
||||
|
||||
assert.NoError(t, file.Close())
|
||||
_, err = os.Stat(path)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestCreateContainerPullsImageIfMissing(t *testing.T) {
|
||||
imageName := "does-not-exist-locally"
|
||||
responseCounter := 0
|
||||
containerID := "abcdef"
|
||||
|
||||
client := &fakeClient{
|
||||
createContainerFunc: func(
|
||||
config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
networkingConfig *network.NetworkingConfig,
|
||||
containerName string,
|
||||
) (container.ContainerCreateCreatedBody, error) {
|
||||
defer func() { responseCounter++ }()
|
||||
switch responseCounter {
|
||||
case 0:
|
||||
return container.ContainerCreateCreatedBody{}, fakeNotFound{}
|
||||
case 1:
|
||||
return container.ContainerCreateCreatedBody{ID: containerID}, nil
|
||||
default:
|
||||
return container.ContainerCreateCreatedBody{}, errors.New("unexpected")
|
||||
}
|
||||
},
|
||||
imageCreateFunc: func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(strings.NewReader("")), nil
|
||||
},
|
||||
infoFunc: func() (types.Info, error) {
|
||||
return types.Info{IndexServerAddress: "http://indexserver"}, nil
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(client)
|
||||
config := &containerConfig{
|
||||
Config: &container.Config{
|
||||
Image: imageName,
|
||||
},
|
||||
HostConfig: &container.HostConfig{},
|
||||
}
|
||||
body, err := createContainer(context.Background(), cli, config, "name")
|
||||
require.NoError(t, err)
|
||||
expected := container.ContainerCreateCreatedBody{ID: containerID}
|
||||
assert.Equal(t, expected, *body)
|
||||
stderr := cli.ErrBuffer().String()
|
||||
assert.Contains(t, stderr, "Unable to find image 'does-not-exist-locally:latest' locally")
|
||||
}
|
||||
|
||||
type fakeNotFound struct{}
|
||||
|
||||
func (f fakeNotFound) NotFound() bool { return true }
|
||||
func (f fakeNotFound) Error() string { return "error fake not found" }
|
||||
93
vendor/github.com/docker/cli/cli/command/container/exec.go
generated
vendored
93
vendor/github.com/docker/cli/cli/command/container/exec.go
generated
vendored
@@ -4,13 +4,15 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types"
|
||||
apiclient "github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -22,14 +24,13 @@ type execOptions struct {
|
||||
detach bool
|
||||
user string
|
||||
privileged bool
|
||||
env *opts.ListOpts
|
||||
env opts.ListOpts
|
||||
container string
|
||||
command []string
|
||||
}
|
||||
|
||||
func newExecOptions() *execOptions {
|
||||
var values []string
|
||||
return &execOptions{
|
||||
env: opts.NewListOptsRef(&values, opts.ValidateEnv),
|
||||
}
|
||||
func newExecOptions() execOptions {
|
||||
return execOptions{env: opts.NewListOpts(opts.ValidateEnv)}
|
||||
}
|
||||
|
||||
// NewExecCommand creates a new cobra.Command for `docker exec`
|
||||
@@ -41,9 +42,9 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
|
||||
Short: "Run a command in a running container",
|
||||
Args: cli.RequiresMinArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
container := args[0]
|
||||
execCmd := args[1:]
|
||||
return runExec(dockerCli, options, container, execCmd)
|
||||
options.container = args[0]
|
||||
options.command = args[1:]
|
||||
return runExec(dockerCli, options)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -56,27 +57,14 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
|
||||
flags.BoolVarP(&options.detach, "detach", "d", false, "Detached mode: run command in the background")
|
||||
flags.StringVarP(&options.user, "user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])")
|
||||
flags.BoolVarP(&options.privileged, "privileged", "", false, "Give extended privileges to the command")
|
||||
flags.VarP(options.env, "env", "e", "Set environment variables")
|
||||
flags.VarP(&options.env, "env", "e", "Set environment variables")
|
||||
flags.SetAnnotation("env", "version", []string{"1.25"})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func runExec(dockerCli command.Cli, options *execOptions, container string, execCmd []string) error {
|
||||
execConfig, err := parseExec(options, execCmd)
|
||||
// just in case the ParseExec does not exit
|
||||
if container == "" || err != nil {
|
||||
return cli.StatusError{StatusCode: 1}
|
||||
}
|
||||
|
||||
if options.detachKeys != "" {
|
||||
dockerCli.ConfigFile().DetachKeys = options.detachKeys
|
||||
}
|
||||
|
||||
// Send client escape keys
|
||||
execConfig.DetachKeys = dockerCli.ConfigFile().DetachKeys
|
||||
|
||||
func runExec(dockerCli command.Cli, options execOptions) error {
|
||||
execConfig := parseExec(options, dockerCli.ConfigFile())
|
||||
ctx := context.Background()
|
||||
client := dockerCli.Client()
|
||||
|
||||
@@ -84,7 +72,7 @@ func runExec(dockerCli command.Cli, options *execOptions, container string, exec
|
||||
// otherwise if we error out we will leak execIDs on the server (and
|
||||
// there's no easy way to clean those up). But also in order to make "not
|
||||
// exist" errors take precedence we do a dummy inspect first.
|
||||
if _, err := client.ContainerInspect(ctx, container); err != nil {
|
||||
if _, err := client.ContainerInspect(ctx, options.container); err != nil {
|
||||
return err
|
||||
}
|
||||
if !execConfig.Detach {
|
||||
@@ -93,27 +81,27 @@ func runExec(dockerCli command.Cli, options *execOptions, container string, exec
|
||||
}
|
||||
}
|
||||
|
||||
response, err := client.ContainerExecCreate(ctx, container, *execConfig)
|
||||
response, err := client.ContainerExecCreate(ctx, options.container, *execConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
execID := response.ID
|
||||
if execID == "" {
|
||||
fmt.Fprintln(dockerCli.Out(), "exec ID empty")
|
||||
return nil
|
||||
return errors.New("exec ID empty")
|
||||
}
|
||||
|
||||
// Temp struct for execStart so that we don't need to transfer all the execConfig.
|
||||
if execConfig.Detach {
|
||||
execStartCheck := types.ExecStartCheck{
|
||||
Detach: execConfig.Detach,
|
||||
Tty: execConfig.Tty,
|
||||
}
|
||||
|
||||
return client.ContainerExecStart(ctx, execID, execStartCheck)
|
||||
}
|
||||
return interactiveExec(ctx, dockerCli, execConfig, execID)
|
||||
}
|
||||
|
||||
func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *types.ExecConfig, execID string) error {
|
||||
// Interactive exec requested.
|
||||
var (
|
||||
out, stderr io.Writer
|
||||
@@ -135,6 +123,7 @@ func runExec(dockerCli command.Cli, options *execOptions, container string, exec
|
||||
}
|
||||
}
|
||||
|
||||
client := dockerCli.Client()
|
||||
resp, err := client.ContainerExecAttach(ctx, execID, *execConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -165,42 +154,35 @@ func runExec(dockerCli command.Cli, options *execOptions, container string, exec
|
||||
return err
|
||||
}
|
||||
|
||||
var status int
|
||||
if _, status, err = getExecExitCode(ctx, client, execID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if status != 0 {
|
||||
return cli.StatusError{StatusCode: status}
|
||||
}
|
||||
|
||||
return nil
|
||||
return getExecExitStatus(ctx, client, execID)
|
||||
}
|
||||
|
||||
// getExecExitCode perform an inspect on the exec command. It returns
|
||||
// the running state and the exit code.
|
||||
func getExecExitCode(ctx context.Context, client apiclient.ContainerAPIClient, execID string) (bool, int, error) {
|
||||
func getExecExitStatus(ctx context.Context, client apiclient.ContainerAPIClient, execID string) error {
|
||||
resp, err := client.ContainerExecInspect(ctx, execID)
|
||||
if err != nil {
|
||||
// If we can't connect, then the daemon probably died.
|
||||
if !apiclient.IsErrConnectionFailed(err) {
|
||||
return false, -1, err
|
||||
return err
|
||||
}
|
||||
return false, -1, nil
|
||||
return cli.StatusError{StatusCode: -1}
|
||||
}
|
||||
|
||||
return resp.Running, resp.ExitCode, nil
|
||||
status := resp.ExitCode
|
||||
if status != 0 {
|
||||
return cli.StatusError{StatusCode: status}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseExec parses the specified args for the specified command and generates
|
||||
// an ExecConfig from it.
|
||||
func parseExec(opts *execOptions, execCmd []string) (*types.ExecConfig, error) {
|
||||
func parseExec(opts execOptions, configFile *configfile.ConfigFile) *types.ExecConfig {
|
||||
execConfig := &types.ExecConfig{
|
||||
User: opts.user,
|
||||
Privileged: opts.privileged,
|
||||
Tty: opts.tty,
|
||||
Cmd: execCmd,
|
||||
Cmd: opts.command,
|
||||
Detach: opts.detach,
|
||||
Env: opts.env.GetAll(),
|
||||
}
|
||||
|
||||
// If -d is not set, attach to everything by default
|
||||
@@ -212,9 +194,10 @@ func parseExec(opts *execOptions, execCmd []string) (*types.ExecConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if opts.env != nil {
|
||||
execConfig.Env = opts.env.GetAll()
|
||||
if opts.detachKeys != "" {
|
||||
execConfig.DetachKeys = opts.detachKeys
|
||||
} else {
|
||||
execConfig.DetachKeys = configFile.DetachKeys
|
||||
}
|
||||
|
||||
return execConfig, nil
|
||||
return execConfig
|
||||
}
|
||||
|
||||
233
vendor/github.com/docker/cli/cli/command/container/exec_test.go
generated
vendored
233
vendor/github.com/docker/cli/cli/command/container/exec_test.go
generated
vendored
@@ -4,118 +4,201 @@ import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/testutil"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type arguments struct {
|
||||
options execOptions
|
||||
execCmd []string
|
||||
func withDefaultOpts(options execOptions) execOptions {
|
||||
options.env = opts.NewListOpts(opts.ValidateEnv)
|
||||
if len(options.command) == 0 {
|
||||
options.command = []string{"command"}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func TestParseExec(t *testing.T) {
|
||||
valids := map[*arguments]*types.ExecConfig{
|
||||
testcases := []struct {
|
||||
options execOptions
|
||||
configFile configfile.ConfigFile
|
||||
expected types.ExecConfig
|
||||
}{
|
||||
{
|
||||
execCmd: []string{"command"},
|
||||
}: {
|
||||
Cmd: []string{"command"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
expected: types.ExecConfig{
|
||||
Cmd: []string{"command"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
},
|
||||
options: withDefaultOpts(execOptions{}),
|
||||
},
|
||||
{
|
||||
execCmd: []string{"command1", "command2"},
|
||||
}: {
|
||||
Cmd: []string{"command1", "command2"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
expected: types.ExecConfig{
|
||||
Cmd: []string{"command1", "command2"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
},
|
||||
options: withDefaultOpts(execOptions{
|
||||
command: []string{"command1", "command2"},
|
||||
}),
|
||||
},
|
||||
{
|
||||
options: execOptions{
|
||||
options: withDefaultOpts(execOptions{
|
||||
interactive: true,
|
||||
tty: true,
|
||||
user: "uid",
|
||||
}),
|
||||
expected: types.ExecConfig{
|
||||
User: "uid",
|
||||
AttachStdin: true,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Tty: true,
|
||||
Cmd: []string{"command"},
|
||||
},
|
||||
execCmd: []string{"command"},
|
||||
}: {
|
||||
User: "uid",
|
||||
AttachStdin: true,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Tty: true,
|
||||
Cmd: []string{"command"},
|
||||
},
|
||||
{
|
||||
options: execOptions{
|
||||
detach: true,
|
||||
options: withDefaultOpts(execOptions{detach: true}),
|
||||
expected: types.ExecConfig{
|
||||
Detach: true,
|
||||
Cmd: []string{"command"},
|
||||
},
|
||||
execCmd: []string{"command"},
|
||||
}: {
|
||||
AttachStdin: false,
|
||||
AttachStdout: false,
|
||||
AttachStderr: false,
|
||||
Detach: true,
|
||||
Cmd: []string{"command"},
|
||||
},
|
||||
{
|
||||
options: execOptions{
|
||||
options: withDefaultOpts(execOptions{
|
||||
tty: true,
|
||||
interactive: true,
|
||||
detach: true,
|
||||
}),
|
||||
expected: types.ExecConfig{
|
||||
Detach: true,
|
||||
Tty: true,
|
||||
Cmd: []string{"command"},
|
||||
},
|
||||
},
|
||||
{
|
||||
options: withDefaultOpts(execOptions{detach: true}),
|
||||
configFile: configfile.ConfigFile{DetachKeys: "de"},
|
||||
expected: types.ExecConfig{
|
||||
Cmd: []string{"command"},
|
||||
DetachKeys: "de",
|
||||
Detach: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
options: withDefaultOpts(execOptions{
|
||||
detach: true,
|
||||
detachKeys: "ab",
|
||||
}),
|
||||
configFile: configfile.ConfigFile{DetachKeys: "de"},
|
||||
expected: types.ExecConfig{
|
||||
Cmd: []string{"command"},
|
||||
DetachKeys: "ab",
|
||||
Detach: true,
|
||||
},
|
||||
execCmd: []string{"command"},
|
||||
}: {
|
||||
AttachStdin: false,
|
||||
AttachStdout: false,
|
||||
AttachStderr: false,
|
||||
Detach: true,
|
||||
Tty: true,
|
||||
Cmd: []string{"command"},
|
||||
},
|
||||
}
|
||||
|
||||
for valid, expectedExecConfig := range valids {
|
||||
execConfig, err := parseExec(&valid.options, valid.execCmd)
|
||||
require.NoError(t, err)
|
||||
if !compareExecConfig(expectedExecConfig, execConfig) {
|
||||
t.Fatalf("Expected [%v] for %v, got [%v]", expectedExecConfig, valid, execConfig)
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
execConfig := parseExec(testcase.options, &testcase.configFile)
|
||||
assert.Equal(t, testcase.expected, *execConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func compareExecConfig(config1 *types.ExecConfig, config2 *types.ExecConfig) bool {
|
||||
if config1.AttachStderr != config2.AttachStderr {
|
||||
return false
|
||||
func TestRunExec(t *testing.T) {
|
||||
var testcases = []struct {
|
||||
doc string
|
||||
options execOptions
|
||||
client fakeClient
|
||||
expectedError string
|
||||
expectedOut string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
doc: "successful detach",
|
||||
options: withDefaultOpts(execOptions{
|
||||
container: "thecontainer",
|
||||
detach: true,
|
||||
}),
|
||||
client: fakeClient{execCreateFunc: execCreateWithID},
|
||||
},
|
||||
{
|
||||
doc: "inspect error",
|
||||
options: newExecOptions(),
|
||||
client: fakeClient{
|
||||
inspectFunc: func(string) (types.ContainerJSON, error) {
|
||||
return types.ContainerJSON{}, errors.New("failed inspect")
|
||||
},
|
||||
},
|
||||
expectedError: "failed inspect",
|
||||
},
|
||||
{
|
||||
doc: "missing exec ID",
|
||||
options: newExecOptions(),
|
||||
expectedError: "exec ID empty",
|
||||
},
|
||||
}
|
||||
if config1.AttachStdin != config2.AttachStdin {
|
||||
return false
|
||||
|
||||
for _, testcase := range testcases {
|
||||
t.Run(testcase.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&testcase.client)
|
||||
|
||||
err := runExec(cli, testcase.options)
|
||||
if testcase.expectedError != "" {
|
||||
testutil.ErrorContains(t, err, testcase.expectedError)
|
||||
} else {
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
assert.Equal(t, testcase.expectedOut, cli.OutBuffer().String())
|
||||
assert.Equal(t, testcase.expectedErr, cli.ErrBuffer().String())
|
||||
})
|
||||
}
|
||||
if config1.AttachStdout != config2.AttachStdout {
|
||||
return false
|
||||
}
|
||||
|
||||
func execCreateWithID(_ string, _ types.ExecConfig) (types.IDResponse, error) {
|
||||
return types.IDResponse{ID: "execid"}, nil
|
||||
}
|
||||
|
||||
func TestGetExecExitStatus(t *testing.T) {
|
||||
execID := "the exec id"
|
||||
expecatedErr := errors.New("unexpected error")
|
||||
|
||||
testcases := []struct {
|
||||
inspectError error
|
||||
exitCode int
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
inspectError: nil,
|
||||
exitCode: 0,
|
||||
},
|
||||
{
|
||||
inspectError: expecatedErr,
|
||||
expectedError: expecatedErr,
|
||||
},
|
||||
{
|
||||
exitCode: 15,
|
||||
expectedError: cli.StatusError{StatusCode: 15},
|
||||
},
|
||||
}
|
||||
if config1.Detach != config2.Detach {
|
||||
return false
|
||||
}
|
||||
if config1.Privileged != config2.Privileged {
|
||||
return false
|
||||
}
|
||||
if config1.Tty != config2.Tty {
|
||||
return false
|
||||
}
|
||||
if config1.User != config2.User {
|
||||
return false
|
||||
}
|
||||
if len(config1.Cmd) != len(config2.Cmd) {
|
||||
return false
|
||||
}
|
||||
for index, value := range config1.Cmd {
|
||||
if value != config2.Cmd[index] {
|
||||
return false
|
||||
|
||||
for _, testcase := range testcases {
|
||||
client := &fakeClient{
|
||||
execInspectFunc: func(id string) (types.ContainerExecInspect, error) {
|
||||
assert.Equal(t, execID, id)
|
||||
return types.ContainerExecInspect{ExitCode: testcase.exitCode}, testcase.inspectError
|
||||
},
|
||||
}
|
||||
err := getExecExitStatus(context.Background(), client, execID)
|
||||
assert.Equal(t, testcase.expectedError, err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestNewExecCommandErrors(t *testing.T) {
|
||||
@@ -135,7 +218,7 @@ func TestNewExecCommandErrors(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{containerInspectFunc: tc.containerInspectFunc})
|
||||
cli := test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc})
|
||||
cmd := NewExecCommand(cli)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
cmd.SetArgs(tc.args)
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/container/hijack.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/container/hijack.go
generated
vendored
@@ -6,12 +6,12 @@ import (
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
||||
11
vendor/github.com/docker/cli/cli/command/container/opts.go
generated
vendored
11
vendor/github.com/docker/cli/cli/command/container/opts.go
generated
vendored
@@ -11,7 +11,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/compose/loader"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
@@ -20,6 +19,7 @@ import (
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
@@ -274,7 +274,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
|
||||
// Low-level execution (cgroups, namespaces, ...)
|
||||
flags.StringVar(&copts.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
|
||||
flags.StringVar(&copts.ipcMode, "ipc", "", "IPC namespace to use")
|
||||
flags.StringVar(&copts.ipcMode, "ipc", "", "IPC mode to use")
|
||||
flags.StringVar(&copts.isolation, "isolation", "", "Container isolation technology")
|
||||
flags.StringVar(&copts.pidMode, "pid", "", "PID namespace to use")
|
||||
flags.Var(&copts.shmSize, "shm-size", "Size of /dev/shm")
|
||||
@@ -421,11 +421,6 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ipcMode := container.IpcMode(copts.ipcMode)
|
||||
if !ipcMode.Valid() {
|
||||
return nil, errors.Errorf("--ipc: invalid IPC mode")
|
||||
}
|
||||
|
||||
pidMode := container.PidMode(copts.pidMode)
|
||||
if !pidMode.Valid() {
|
||||
return nil, errors.Errorf("--pid: invalid PID mode")
|
||||
@@ -584,7 +579,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
ExtraHosts: copts.extraHosts.GetAll(),
|
||||
VolumesFrom: copts.volumesFrom.GetAll(),
|
||||
NetworkMode: container.NetworkMode(copts.netMode),
|
||||
IpcMode: ipcMode,
|
||||
IpcMode: container.IpcMode(copts.ipcMode),
|
||||
PidMode: pidMode,
|
||||
UTSMode: utsMode,
|
||||
UsernsMode: usernsMode,
|
||||
|
||||
175
vendor/github.com/docker/cli/cli/command/container/opts_test.go
generated
vendored
175
vendor/github.com/docker/cli/cli/command/container/opts_test.go
generated
vendored
@@ -1,8 +1,6 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -14,7 +12,6 @@ import (
|
||||
"github.com/docker/cli/internal/test/testutil"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
@@ -115,7 +112,7 @@ func TestParseRunWithInvalidArgs(t *testing.T) {
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func TestParseRunVolumes(t *testing.T) {
|
||||
func TestParseWithVolumes(t *testing.T) {
|
||||
|
||||
// A single volume
|
||||
arr, tryit := setupPlatformVolume([]string{`/tmp`}, []string{`c:\tmp`})
|
||||
@@ -366,23 +363,12 @@ func TestParseDevice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseModes(t *testing.T) {
|
||||
// ipc ko
|
||||
_, _, _, err := parseRun([]string{"--ipc=container:", "img", "cmd"})
|
||||
testutil.ErrorContains(t, err, "--ipc: invalid IPC mode")
|
||||
|
||||
// ipc ok
|
||||
_, hostconfig, _, err := parseRun([]string{"--ipc=host", "img", "cmd"})
|
||||
require.NoError(t, err)
|
||||
if !hostconfig.IpcMode.Valid() {
|
||||
t.Fatalf("Expected a valid IpcMode, got %v", hostconfig.IpcMode)
|
||||
}
|
||||
|
||||
// pid ko
|
||||
_, _, _, err = parseRun([]string{"--pid=container:", "img", "cmd"})
|
||||
_, _, _, err := parseRun([]string{"--pid=container:", "img", "cmd"})
|
||||
testutil.ErrorContains(t, err, "--pid: invalid PID mode")
|
||||
|
||||
// pid ok
|
||||
_, hostconfig, _, err = parseRun([]string{"--pid=host", "img", "cmd"})
|
||||
_, hostconfig, _, err := parseRun([]string{"--pid=host", "img", "cmd"})
|
||||
require.NoError(t, err)
|
||||
if !hostconfig.PidMode.Valid() {
|
||||
t.Fatalf("Expected a valid PidMode, got %v", hostconfig.PidMode)
|
||||
@@ -595,161 +581,6 @@ func TestParseEntryPoint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// This tests the cases for binds which are generated through
|
||||
// DecodeContainerConfig rather than Parse()
|
||||
// nolint: gocyclo
|
||||
func TestDecodeContainerConfigVolumes(t *testing.T) {
|
||||
|
||||
// Root to root
|
||||
bindsOrVols, _ := setupPlatformVolume([]string{`/:/`}, []string{os.Getenv("SystemDrive") + `\:c:\`})
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// No destination path
|
||||
bindsOrVols, _ = setupPlatformVolume([]string{`/tmp:`}, []string{os.Getenv("TEMP") + `\:`})
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// // No destination path or mode
|
||||
bindsOrVols, _ = setupPlatformVolume([]string{`/tmp::`}, []string{os.Getenv("TEMP") + `\::`})
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// A whole lot of nothing
|
||||
bindsOrVols = []string{`:`}
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// A whole lot of nothing with no mode
|
||||
bindsOrVols = []string{`::`}
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// Too much including an invalid mode
|
||||
wTmp := os.Getenv("TEMP")
|
||||
bindsOrVols, _ = setupPlatformVolume([]string{`/tmp:/tmp:/tmp:/tmp`}, []string{wTmp + ":" + wTmp + ":" + wTmp + ":" + wTmp})
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// Windows specific error tests
|
||||
if runtime.GOOS == "windows" {
|
||||
// Volume which does not include a drive letter
|
||||
bindsOrVols = []string{`\tmp`}
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// Root to C-Drive
|
||||
bindsOrVols = []string{os.Getenv("SystemDrive") + `\:c:`}
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// Container path that does not include a drive letter
|
||||
bindsOrVols = []string{`c:\windows:\somewhere`}
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
}
|
||||
|
||||
// Linux-specific error tests
|
||||
if runtime.GOOS != "windows" {
|
||||
// Just root
|
||||
bindsOrVols = []string{`/`}
|
||||
if _, _, err := callDecodeContainerConfig(nil, bindsOrVols); err == nil {
|
||||
t.Fatalf("binds %v should have failed", bindsOrVols)
|
||||
}
|
||||
if _, _, err := callDecodeContainerConfig(bindsOrVols, nil); err == nil {
|
||||
t.Fatalf("volume %v should have failed", bindsOrVols)
|
||||
}
|
||||
|
||||
// A single volume that looks like a bind mount passed in Volumes.
|
||||
// This should be handled as a bind mount, not a volume.
|
||||
vols := []string{`/foo:/bar`}
|
||||
if config, hostConfig, err := callDecodeContainerConfig(vols, nil); err != nil {
|
||||
t.Fatal("Volume /foo:/bar should have succeeded as a volume name")
|
||||
} else if hostConfig.Binds != nil {
|
||||
t.Fatalf("Error parsing volume flags, /foo:/bar should not mount-bind anything. Received %v", hostConfig.Binds)
|
||||
} else if _, exists := config.Volumes[vols[0]]; !exists {
|
||||
t.Fatalf("Error parsing volume flags, /foo:/bar is missing from volumes. Received %v", config.Volumes)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// callDecodeContainerConfig is a utility function used by TestDecodeContainerConfigVolumes
|
||||
// to call DecodeContainerConfig. It effectively does what a client would
|
||||
// do when calling the daemon by constructing a JSON stream of a
|
||||
// ContainerConfigWrapper which is populated by the set of volume specs
|
||||
// passed into it. It returns a config and a hostconfig which can be
|
||||
// validated to ensure DecodeContainerConfig has manipulated the structures
|
||||
// correctly.
|
||||
func callDecodeContainerConfig(volumes []string, binds []string) (*container.Config, *container.HostConfig, error) {
|
||||
var (
|
||||
b []byte
|
||||
err error
|
||||
c *container.Config
|
||||
h *container.HostConfig
|
||||
)
|
||||
w := runconfig.ContainerConfigWrapper{
|
||||
Config: &container.Config{
|
||||
Volumes: map[string]struct{}{},
|
||||
},
|
||||
HostConfig: &container.HostConfig{
|
||||
NetworkMode: "none",
|
||||
Binds: binds,
|
||||
},
|
||||
}
|
||||
for _, v := range volumes {
|
||||
w.Config.Volumes[v] = struct{}{}
|
||||
}
|
||||
if b, err = json.Marshal(w); err != nil {
|
||||
return nil, nil, errors.Errorf("Error on marshal %s", err.Error())
|
||||
}
|
||||
c, h, _, err = runconfig.DecodeContainerConfig(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Errorf("Error parsing %s: %v", string(b), err)
|
||||
}
|
||||
if c == nil || h == nil {
|
||||
return nil, nil, errors.Errorf("Empty config or hostconfig")
|
||||
}
|
||||
|
||||
return c, h, err
|
||||
}
|
||||
|
||||
func TestValidateDevice(t *testing.T) {
|
||||
valid := []string{
|
||||
"/home",
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/container/run.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/container/run.go
generated
vendored
@@ -10,7 +10,6 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/opts"
|
||||
@@ -20,6 +19,7 @@ import (
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/container/stats_helpers.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/container/stats_helpers.go
generated
vendored
@@ -7,11 +7,11 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/container/tty.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/container/tty.go
generated
vendored
@@ -7,11 +7,11 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
||||
17
vendor/github.com/docker/cli/cli/command/container/utils.go
generated
vendored
17
vendor/github.com/docker/cli/cli/command/container/utils.go
generated
vendored
@@ -3,14 +3,13 @@ package container
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
clientapi "github.com/docker/docker/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
@@ -125,20 +124,6 @@ func legacyWaitExitOrRemoved(ctx context.Context, dockerCli *command.DockerCli,
|
||||
return statusChan
|
||||
}
|
||||
|
||||
// getExitCode performs an inspect on the container. It returns
|
||||
// the running state and the exit code.
|
||||
func getExitCode(ctx context.Context, dockerCli command.Cli, containerID string) (bool, int, error) {
|
||||
c, err := dockerCli.Client().ContainerInspect(ctx, containerID)
|
||||
if err != nil {
|
||||
// If we can't connect, then the daemon probably died.
|
||||
if !clientapi.IsErrConnectionFailed(err) {
|
||||
return false, -1, err
|
||||
}
|
||||
return false, -1, nil
|
||||
}
|
||||
return c.State.Running, c.State.ExitCode, nil
|
||||
}
|
||||
|
||||
func parallelOperation(ctx context.Context, containers []string, op func(ctx context.Context, container string) error) chan error {
|
||||
if len(containers) == 0 {
|
||||
return nil
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/events_utils.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/events_utils.go
generated
vendored
@@ -3,8 +3,8 @@ package command
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
eventtypes "github.com/docker/docker/api/types/events"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// EventHandler is abstract interface for user to customize
|
||||
|
||||
6
vendor/github.com/docker/cli/cli/command/formatter/container_test.go
generated
vendored
6
vendor/github.com/docker/cli/cli/command/formatter/container_test.go
generated
vendored
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -230,10 +231,7 @@ size: 0B
|
||||
// Special headers for customized table format
|
||||
{
|
||||
Context{Format: NewContainerFormat(`table {{truncate .ID 5}}\t{{json .Image}} {{.RunningFor}}/{{title .Status}}/{{pad .Ports 2 2}}.{{upper .Names}} {{lower .Status}}`, false, true)},
|
||||
`CONTAINER ID IMAGE CREATED/STATUS/ PORTS .NAMES STATUS
|
||||
conta "ubuntu" 24 hours ago//.FOOBAR_BAZ
|
||||
conta "ubuntu" 24 hours ago//.FOOBAR_BAR
|
||||
`,
|
||||
string(golden.Get(t, "container-context-write-special-headers.golden")),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
7
vendor/github.com/docker/cli/cli/command/formatter/custom_test.go
generated
vendored
7
vendor/github.com/docker/cli/cli/command/formatter/custom_test.go
generated
vendored
@@ -1,9 +1,10 @@
|
||||
package formatter
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func compareMultipleValues(t *testing.T, value, expected string) {
|
||||
@@ -22,7 +23,5 @@ func compareMultipleValues(t *testing.T, value, expected string) {
|
||||
keyval := strings.Split(expected, "=")
|
||||
expMap[keyval[0]] = keyval[1]
|
||||
}
|
||||
if !reflect.DeepEqual(expMap, entriesMap) {
|
||||
t.Fatalf("Expected entries: %v, got: %v", expected, value)
|
||||
}
|
||||
assert.Equal(t, expMap, entriesMap)
|
||||
}
|
||||
|
||||
34
vendor/github.com/docker/cli/cli/command/formatter/disk_usage_test.go
generated
vendored
34
vendor/github.com/docker/cli/cli/command/formatter/disk_usage_test.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -83,12 +84,7 @@ Build Cache 0B
|
||||
Format: NewDiskUsageFormat("table {{.Type}}\t{{.Active}}"),
|
||||
},
|
||||
},
|
||||
`TYPE ACTIVE
|
||||
Images 0
|
||||
Containers 0
|
||||
Local Volumes 0
|
||||
Build Cache
|
||||
`,
|
||||
string(golden.Get(t, "disk-usage-context-write-custom.golden")),
|
||||
},
|
||||
// Raw Format
|
||||
{
|
||||
@@ -97,31 +93,7 @@ Build Cache
|
||||
Format: NewDiskUsageFormat("raw"),
|
||||
},
|
||||
},
|
||||
`type: Images
|
||||
total: 0
|
||||
active: 0
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
type: Containers
|
||||
total: 0
|
||||
active: 0
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
type: Local Volumes
|
||||
total: 0
|
||||
active: 0
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
type: Build Cache
|
||||
total:
|
||||
active:
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
`,
|
||||
string(golden.Get(t, "disk-usage-raw-format.golden")),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
165
vendor/github.com/docker/cli/cli/command/formatter/image.go
generated
vendored
165
vendor/github.com/docker/cli/cli/command/formatter/image.go
generated
vendored
@@ -86,9 +86,9 @@ func needDigest(ctx ImageContext) bool {
|
||||
|
||||
func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subContext subContext) error) error {
|
||||
for _, image := range images {
|
||||
images := []*imageContext{}
|
||||
formatted := []*imageContext{}
|
||||
if isDangling(image) {
|
||||
images = append(images, &imageContext{
|
||||
formatted = append(formatted, &imageContext{
|
||||
trunc: ctx.Trunc,
|
||||
i: image,
|
||||
repo: "<none>",
|
||||
@@ -96,90 +96,9 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
|
||||
digest: "<none>",
|
||||
})
|
||||
} else {
|
||||
repoTags := map[string][]string{}
|
||||
repoDigests := map[string][]string{}
|
||||
|
||||
for _, refString := range image.RepoTags {
|
||||
ref, err := reference.ParseNormalizedNamed(refString)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if nt, ok := ref.(reference.NamedTagged); ok {
|
||||
familiarRef := reference.FamiliarName(ref)
|
||||
repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag())
|
||||
}
|
||||
}
|
||||
for _, refString := range image.RepoDigests {
|
||||
ref, err := reference.ParseNormalizedNamed(refString)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if c, ok := ref.(reference.Canonical); ok {
|
||||
familiarRef := reference.FamiliarName(ref)
|
||||
repoDigests[familiarRef] = append(repoDigests[familiarRef], c.Digest().String())
|
||||
}
|
||||
}
|
||||
|
||||
for repo, tags := range repoTags {
|
||||
digests := repoDigests[repo]
|
||||
|
||||
// Do not display digests as their own row
|
||||
delete(repoDigests, repo)
|
||||
|
||||
if !needDigest(ctx) {
|
||||
// Ignore digest references, just show tag once
|
||||
digests = nil
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
if len(digests) == 0 {
|
||||
images = append(images, &imageContext{
|
||||
trunc: ctx.Trunc,
|
||||
i: image,
|
||||
repo: repo,
|
||||
tag: tag,
|
||||
digest: "<none>",
|
||||
})
|
||||
continue
|
||||
}
|
||||
// Display the digests for each tag
|
||||
for _, dgst := range digests {
|
||||
images = append(images, &imageContext{
|
||||
trunc: ctx.Trunc,
|
||||
i: image,
|
||||
repo: repo,
|
||||
tag: tag,
|
||||
digest: dgst,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Show rows for remaining digest only references
|
||||
for repo, digests := range repoDigests {
|
||||
// If digests are displayed, show row per digest
|
||||
if ctx.Digest {
|
||||
for _, dgst := range digests {
|
||||
images = append(images, &imageContext{
|
||||
trunc: ctx.Trunc,
|
||||
i: image,
|
||||
repo: repo,
|
||||
tag: "<none>",
|
||||
digest: dgst,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
images = append(images, &imageContext{
|
||||
trunc: ctx.Trunc,
|
||||
i: image,
|
||||
repo: repo,
|
||||
tag: "<none>",
|
||||
})
|
||||
}
|
||||
}
|
||||
formatted = imageFormatTaggedAndDigest(ctx, image)
|
||||
}
|
||||
for _, imageCtx := range images {
|
||||
for _, imageCtx := range formatted {
|
||||
if err := format(imageCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -188,6 +107,82 @@ func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subC
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageFormatTaggedAndDigest(ctx ImageContext, image types.ImageSummary) []*imageContext {
|
||||
repoTags := map[string][]string{}
|
||||
repoDigests := map[string][]string{}
|
||||
images := []*imageContext{}
|
||||
|
||||
for _, refString := range image.RepoTags {
|
||||
ref, err := reference.ParseNormalizedNamed(refString)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if nt, ok := ref.(reference.NamedTagged); ok {
|
||||
familiarRef := reference.FamiliarName(ref)
|
||||
repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag())
|
||||
}
|
||||
}
|
||||
for _, refString := range image.RepoDigests {
|
||||
ref, err := reference.ParseNormalizedNamed(refString)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if c, ok := ref.(reference.Canonical); ok {
|
||||
familiarRef := reference.FamiliarName(ref)
|
||||
repoDigests[familiarRef] = append(repoDigests[familiarRef], c.Digest().String())
|
||||
}
|
||||
}
|
||||
|
||||
addImage := func(repo, tag, digest string) {
|
||||
image := &imageContext{
|
||||
trunc: ctx.Trunc,
|
||||
i: image,
|
||||
repo: repo,
|
||||
tag: tag,
|
||||
digest: digest,
|
||||
}
|
||||
images = append(images, image)
|
||||
}
|
||||
|
||||
for repo, tags := range repoTags {
|
||||
digests := repoDigests[repo]
|
||||
|
||||
// Do not display digests as their own row
|
||||
delete(repoDigests, repo)
|
||||
|
||||
if !needDigest(ctx) {
|
||||
// Ignore digest references, just show tag once
|
||||
digests = nil
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
if len(digests) == 0 {
|
||||
addImage(repo, tag, "<none>")
|
||||
continue
|
||||
}
|
||||
// Display the digests for each tag
|
||||
for _, dgst := range digests {
|
||||
addImage(repo, tag, dgst)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Show rows for remaining digest only references
|
||||
for repo, digests := range repoDigests {
|
||||
// If digests are displayed, show row per digest
|
||||
if ctx.Digest {
|
||||
for _, dgst := range digests {
|
||||
addImage(repo, "<none>", dgst)
|
||||
}
|
||||
} else {
|
||||
addImage(repo, "<none>", "")
|
||||
|
||||
}
|
||||
}
|
||||
return images
|
||||
}
|
||||
|
||||
type imageContext struct {
|
||||
HeaderContext
|
||||
trunc bool
|
||||
|
||||
24
vendor/github.com/docker/cli/cli/command/formatter/image_test.go
generated
vendored
24
vendor/github.com/docker/cli/cli/command/formatter/image_test.go
generated
vendored
@@ -55,6 +55,26 @@ func TestImageContext(t *testing.T) {
|
||||
i: types.ImageSummary{},
|
||||
digest: "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a",
|
||||
}, "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", ctx.Digest},
|
||||
{
|
||||
imageContext{
|
||||
i: types.ImageSummary{Containers: 10},
|
||||
}, "10", ctx.Containers,
|
||||
},
|
||||
{
|
||||
imageContext{
|
||||
i: types.ImageSummary{VirtualSize: 10000},
|
||||
}, "10kB", ctx.VirtualSize,
|
||||
},
|
||||
{
|
||||
imageContext{
|
||||
i: types.ImageSummary{SharedSize: 10000},
|
||||
}, "10kB", ctx.SharedSize,
|
||||
},
|
||||
{
|
||||
imageContext{
|
||||
i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000},
|
||||
}, "15kB", ctx.UniqueSize,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@@ -62,8 +82,8 @@ func TestImageContext(t *testing.T) {
|
||||
v := c.call()
|
||||
if strings.Contains(v, ",") {
|
||||
compareMultipleValues(t, v, c.expValue)
|
||||
} else if v != c.expValue {
|
||||
t.Fatalf("Expected %s, was %s\n", c.expValue, v)
|
||||
} else {
|
||||
assert.Equal(t, c.expValue, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
vendor/github.com/docker/cli/cli/command/formatter/search_test.go
generated
vendored
10
vendor/github.com/docker/cli/cli/command/formatter/search_test.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -120,10 +121,7 @@ func TestSearchContextWrite(t *testing.T) {
|
||||
// Table format
|
||||
{
|
||||
Context{Format: NewSearchFormat("table")},
|
||||
`NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
||||
result1 Official build 5000 [OK]
|
||||
result2 Not official 5 [OK]
|
||||
`,
|
||||
string(golden.Get(t, "search-context-write-table.golden")),
|
||||
},
|
||||
{
|
||||
Context{Format: NewSearchFormat("table {{.Name}}")},
|
||||
@@ -210,9 +208,7 @@ func TestSearchContextWriteStars(t *testing.T) {
|
||||
// Table format
|
||||
{
|
||||
Context{Format: NewSearchFormat("table")},
|
||||
`NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
||||
result1 Official build 5000 [OK]
|
||||
`,
|
||||
string(golden.Get(t, "search-context-write-stars-table.golden")),
|
||||
},
|
||||
{
|
||||
Context{Format: NewSearchFormat("table {{.Name}}")},
|
||||
|
||||
26
vendor/github.com/docker/cli/cli/command/formatter/secret.go
generated
vendored
26
vendor/github.com/docker/cli/cli/command/formatter/secret.go
generated
vendored
@@ -12,19 +12,20 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.CreatedAt}}\t{{.UpdatedAt}}"
|
||||
defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}"
|
||||
secretIDHeader = "ID"
|
||||
secretCreatedHeader = "CREATED"
|
||||
secretUpdatedHeader = "UPDATED"
|
||||
secretInspectPrettyTemplate Format = `ID: {{.ID}}
|
||||
Name: {{.Name}}
|
||||
secretInspectPrettyTemplate Format = `ID: {{.ID}}
|
||||
Name: {{.Name}}
|
||||
{{- if .Labels }}
|
||||
Labels:
|
||||
{{- range $k, $v := .Labels }}
|
||||
- {{ $k }}{{if $v }}={{ $v }}{{ end }}
|
||||
{{- end }}{{ end }}
|
||||
Created at: {{.CreatedAt}}
|
||||
Updated at: {{.UpdatedAt}}`
|
||||
Driver: {{.Driver}}
|
||||
Created at: {{.CreatedAt}}
|
||||
Updated at: {{.UpdatedAt}}`
|
||||
)
|
||||
|
||||
// NewSecretFormat returns a Format for rendering using a secret Context
|
||||
@@ -61,6 +62,7 @@ func newSecretContext() *secretContext {
|
||||
sCtx.header = map[string]string{
|
||||
"ID": secretIDHeader,
|
||||
"Name": nameHeader,
|
||||
"Driver": driverHeader,
|
||||
"CreatedAt": secretCreatedHeader,
|
||||
"UpdatedAt": secretUpdatedHeader,
|
||||
"Labels": labelsHeader,
|
||||
@@ -89,6 +91,13 @@ func (c *secretContext) CreatedAt() string {
|
||||
return units.HumanDuration(time.Now().UTC().Sub(c.s.Meta.CreatedAt)) + " ago"
|
||||
}
|
||||
|
||||
func (c *secretContext) Driver() string {
|
||||
if c.s.Spec.Driver == nil {
|
||||
return ""
|
||||
}
|
||||
return c.s.Spec.Driver.Name
|
||||
}
|
||||
|
||||
func (c *secretContext) UpdatedAt() string {
|
||||
return units.HumanDuration(time.Now().UTC().Sub(c.s.Meta.UpdatedAt)) + " ago"
|
||||
}
|
||||
@@ -153,6 +162,13 @@ func (ctx *secretInspectContext) Labels() map[string]string {
|
||||
return ctx.Secret.Spec.Labels
|
||||
}
|
||||
|
||||
func (ctx *secretInspectContext) Driver() string {
|
||||
if ctx.Secret.Spec.Driver == nil {
|
||||
return ""
|
||||
}
|
||||
return ctx.Secret.Spec.Driver.Name
|
||||
}
|
||||
|
||||
func (ctx *secretInspectContext) CreatedAt() string {
|
||||
return command.PrettyPrint(ctx.Secret.CreatedAt)
|
||||
}
|
||||
|
||||
6
vendor/github.com/docker/cli/cli/command/formatter/secret_test.go
generated
vendored
6
vendor/github.com/docker/cli/cli/command/formatter/secret_test.go
generated
vendored
@@ -28,9 +28,9 @@ func TestSecretContextFormatWrite(t *testing.T) {
|
||||
},
|
||||
// Table format
|
||||
{Context{Format: NewSecretFormat("table", false)},
|
||||
`ID NAME CREATED UPDATED
|
||||
1 passwords Less than a second ago Less than a second ago
|
||||
2 id_rsa Less than a second ago Less than a second ago
|
||||
`ID NAME DRIVER CREATED UPDATED
|
||||
1 passwords Less than a second ago Less than a second ago
|
||||
2 id_rsa Less than a second ago Less than a second ago
|
||||
`},
|
||||
{Context{Format: NewSecretFormat("table {{.Name}}", true)},
|
||||
`NAME
|
||||
|
||||
5
vendor/github.com/docker/cli/cli/command/formatter/service.go
generated
vendored
5
vendor/github.com/docker/cli/cli/command/formatter/service.go
generated
vendored
@@ -504,7 +504,10 @@ func (c *serviceContext) Replicas() string {
|
||||
}
|
||||
|
||||
func (c *serviceContext) Image() string {
|
||||
image := c.service.Spec.TaskTemplate.ContainerSpec.Image
|
||||
var image string
|
||||
if c.service.Spec.TaskTemplate.ContainerSpec != nil {
|
||||
image = c.service.Spec.TaskTemplate.ContainerSpec.Image
|
||||
}
|
||||
if ref, err := reference.ParseNormalizedNamed(image); err == nil {
|
||||
// update image string for display, (strips any digest)
|
||||
if nt, ok := ref.(reference.NamedTagged); ok {
|
||||
|
||||
17
vendor/github.com/docker/cli/cli/command/formatter/service_test.go
generated
vendored
17
vendor/github.com/docker/cli/cli/command/formatter/service_test.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -59,21 +60,7 @@ bar
|
||||
// Raw Format
|
||||
{
|
||||
Context{Format: NewServiceListFormat("raw", false)},
|
||||
`id: id_baz
|
||||
name: baz
|
||||
mode: global
|
||||
replicas: 2/4
|
||||
image:
|
||||
ports: *:80->8080/tcp
|
||||
|
||||
id: id_bar
|
||||
name: bar
|
||||
mode: replicated
|
||||
replicas: 2/4
|
||||
image:
|
||||
ports: *:80->8080/tcp
|
||||
|
||||
`,
|
||||
string(golden.Get(t, "service-context-write-raw.golden")),
|
||||
},
|
||||
{
|
||||
Context{Format: NewServiceListFormat("raw", true)},
|
||||
|
||||
6
vendor/github.com/docker/cli/cli/command/formatter/task_test.go
generated
vendored
6
vendor/github.com/docker/cli/cli/command/formatter/task_test.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -33,10 +34,7 @@ taskID2
|
||||
},
|
||||
{
|
||||
Context{Format: NewTaskFormat("table {{.Name}}\t{{.Node}}\t{{.Ports}}", false)},
|
||||
`NAME NODE PORTS
|
||||
foobar_baz foo1
|
||||
foobar_bar foo2
|
||||
`,
|
||||
string(golden.Get(t, "task-context-write-table-custom.golden")),
|
||||
},
|
||||
{
|
||||
Context{Format: NewTaskFormat("table {{.Name}}", true)},
|
||||
|
||||
3
vendor/github.com/docker/cli/cli/command/formatter/testdata/container-context-write-special-headers.golden
generated
vendored
Normal file
3
vendor/github.com/docker/cli/cli/command/formatter/testdata/container-context-write-special-headers.golden
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
CONTAINER ID IMAGE CREATED/STATUS/ PORTS .NAMES STATUS
|
||||
conta "ubuntu" 24 hours ago//.FOOBAR_BAZ
|
||||
conta "ubuntu" 24 hours ago//.FOOBAR_BAR
|
||||
5
vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-context-write-custom.golden
generated
vendored
Normal file
5
vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-context-write-custom.golden
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
TYPE ACTIVE
|
||||
Images 0
|
||||
Containers 0
|
||||
Local Volumes 0
|
||||
Build Cache
|
||||
24
vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-raw-format.golden
generated
vendored
Normal file
24
vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-raw-format.golden
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
type: Images
|
||||
total: 0
|
||||
active: 0
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
type: Containers
|
||||
total: 0
|
||||
active: 0
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
type: Local Volumes
|
||||
total: 0
|
||||
active: 0
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
type: Build Cache
|
||||
total:
|
||||
active:
|
||||
size: 0B
|
||||
reclaimable: 0B
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-stars-table.golden
generated
vendored
Normal file
2
vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-stars-table.golden
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
||||
result1 Official build 5000 [OK]
|
||||
3
vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-table.golden
generated
vendored
Normal file
3
vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-table.golden
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
||||
result1 Official build 5000 [OK]
|
||||
result2 Not official 5 [OK]
|
||||
14
vendor/github.com/docker/cli/cli/command/formatter/testdata/service-context-write-raw.golden
generated
vendored
Normal file
14
vendor/github.com/docker/cli/cli/command/formatter/testdata/service-context-write-raw.golden
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
id: id_baz
|
||||
name: baz
|
||||
mode: global
|
||||
replicas: 2/4
|
||||
image:
|
||||
ports: *:80->8080/tcp
|
||||
|
||||
id: id_bar
|
||||
name: bar
|
||||
mode: replicated
|
||||
replicas: 2/4
|
||||
image:
|
||||
ports: *:80->8080/tcp
|
||||
|
||||
3
vendor/github.com/docker/cli/cli/command/formatter/testdata/task-context-write-table-custom.golden
generated
vendored
Normal file
3
vendor/github.com/docker/cli/cli/command/formatter/testdata/task-context-write-table-custom.golden
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
NAME NODE PORTS
|
||||
foobar_baz foo1
|
||||
foobar_bar foo2
|
||||
4
vendor/github.com/docker/cli/cli/command/image/build.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/image/build.go
generated
vendored
@@ -12,7 +12,6 @@ import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/image/build"
|
||||
@@ -22,12 +21,14 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
"github.com/docker/docker/pkg/urlutil"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -243,6 +244,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
excludes = build.TrimBuildFilesFromExcludes(excludes, relDockerfile, options.dockerfileFromStdin())
|
||||
buildCtx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
|
||||
ExcludePatterns: excludes,
|
||||
ChownOpts: &idtools.IDPair{UID: 0, GID: 0},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
4
vendor/github.com/docker/cli/cli/command/image/build_session.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/image/build_session.go
generated
vendored
@@ -17,9 +17,9 @@ import (
|
||||
"github.com/docker/cli/cli/command/image/build"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/client/session"
|
||||
"github.com/docker/docker/client/session/filesync"
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/session/filesync"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
39
vendor/github.com/docker/cli/cli/command/image/build_test.go
generated
vendored
39
vendor/github.com/docker/cli/cli/command/image/build_test.go
generated
vendored
@@ -6,18 +6,57 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/gotestyourself/gotestyourself/fs"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
|
||||
skip.IfCondition(t, runtime.GOOS == "windows", "uid and gid not relevant on windows")
|
||||
dest := fs.NewDir(t, "test-build-context-dest")
|
||||
defer dest.Remove()
|
||||
|
||||
fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
||||
assert.NoError(t, archive.Untar(context, dest.Path(), nil))
|
||||
|
||||
body := new(bytes.Buffer)
|
||||
return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil
|
||||
}
|
||||
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
|
||||
|
||||
dir := fs.NewDir(t, "test-build-context",
|
||||
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
|
||||
fs.WithFile("Dockerfile", `
|
||||
FROM alpine:3.6
|
||||
COPY foo bar /
|
||||
`),
|
||||
)
|
||||
defer dir.Remove()
|
||||
|
||||
options := newBuildOptions()
|
||||
options.context = dir.Path()
|
||||
|
||||
err := runBuild(cli, options)
|
||||
require.NoError(t, err)
|
||||
|
||||
files, err := ioutil.ReadDir(dest.Path())
|
||||
require.NoError(t, err)
|
||||
for _, fileInfo := range files {
|
||||
assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid)
|
||||
assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid)
|
||||
}
|
||||
}
|
||||
func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
|
||||
dest, err := ioutil.TempDir("", "test-build-compress-dest")
|
||||
require.NoError(t, err)
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/image/trust.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/image/trust.go
generated
vendored
@@ -8,7 +8,6 @@ import (
|
||||
"path"
|
||||
"sort"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/distribution/reference"
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
"github.com/docker/notary/tuf/data"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/inspect/inspector.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/inspect/inspector.go
generated
vendored
@@ -7,10 +7,10 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Inspector defines an interface to implement to process elements
|
||||
|
||||
8
vendor/github.com/docker/cli/cli/command/network/client_test.go
generated
vendored
8
vendor/github.com/docker/cli/cli/command/network/client_test.go
generated
vendored
@@ -12,6 +12,7 @@ type fakeClient struct {
|
||||
networkCreateFunc func(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
|
||||
networkConnectFunc func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
|
||||
networkDisconnectFunc func(ctx context.Context, networkID, container string, force bool) error
|
||||
networkListFunc func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
|
||||
}
|
||||
|
||||
func (c *fakeClient) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
|
||||
@@ -34,3 +35,10 @@ func (c *fakeClient) NetworkDisconnect(ctx context.Context, networkID, container
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
if c.networkListFunc != nil {
|
||||
return c.networkListFunc(ctx, options)
|
||||
}
|
||||
return []types.NetworkResource{}, nil
|
||||
}
|
||||
|
||||
69
vendor/github.com/docker/cli/cli/command/network/list_test.go
generated
vendored
Normal file
69
vendor/github.com/docker/cli/cli/command/network/list_test.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
. "github.com/docker/cli/internal/test/builders"
|
||||
"github.com/docker/cli/internal/test/testutil"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestNetworkListErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
networkListFunc func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
return []types.NetworkResource{}, errors.Errorf("error creating network")
|
||||
},
|
||||
expectedError: "error creating network",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
cmd := newListCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
networkListFunc: tc.networkListFunc,
|
||||
}),
|
||||
)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkListWithFlags(t *testing.T) {
|
||||
|
||||
filterArgs := filters.NewArgs()
|
||||
filterArgs.Add("image.name", "ubuntu")
|
||||
|
||||
expectedOpts := types.NetworkListOptions{
|
||||
Filters: filterArgs,
|
||||
}
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
assert.Equal(t, expectedOpts, options, "not expected options error")
|
||||
return []types.NetworkResource{*NetworkResource(NetworkResourceID("123454321"),
|
||||
NetworkResourceName("network_1"),
|
||||
NetworkResourceDriver("09.7.01"),
|
||||
NetworkResourceScope("global"))}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
|
||||
cmd.Flags().Set("filter", "image.name=ubuntu")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
golden.Assert(t, strings.TrimSpace(cli.OutBuffer().String()), "network-list.golden")
|
||||
}
|
||||
2
vendor/github.com/docker/cli/cli/command/network/testdata/network-list.golden
generated
vendored
Normal file
2
vendor/github.com/docker/cli/cli/command/network/testdata/network-list.golden
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
123454321 network_1 09.7.01 global
|
||||
2
vendor/github.com/docker/cli/cli/command/out.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/out.go
generated
vendored
@@ -4,8 +4,8 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// OutStream is an output stream used by the DockerCli to write normal program
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/plugin/create.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/plugin/create.go
generated
vendored
@@ -7,13 +7,13 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
49
vendor/github.com/docker/cli/cli/command/secret/create.go
generated
vendored
49
vendor/github.com/docker/cli/cli/command/secret/create.go
generated
vendored
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
type createOptions struct {
|
||||
name string
|
||||
driver string
|
||||
file string
|
||||
labels opts.ListOpts
|
||||
}
|
||||
@@ -27,17 +28,21 @@ func newSecretCreateCommand(dockerCli command.Cli) *cobra.Command {
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "create [OPTIONS] SECRET file|-",
|
||||
Use: "create [OPTIONS] SECRET [file|-]",
|
||||
Short: "Create a secret from a file or STDIN as content",
|
||||
Args: cli.ExactArgs(2),
|
||||
Args: cli.RequiresRangeArgs(1, 2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
options.name = args[0]
|
||||
options.file = args[1]
|
||||
if len(args) == 2 {
|
||||
options.file = args[1]
|
||||
}
|
||||
return runSecretCreate(dockerCli, options)
|
||||
},
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.VarP(&options.labels, "label", "l", "Secret labels")
|
||||
flags.StringVarP(&options.driver, "driver", "d", "", "Secret driver")
|
||||
flags.SetAnnotation("driver", "version", []string{"1.31"})
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -46,21 +51,14 @@ func runSecretCreate(dockerCli command.Cli, options createOptions) error {
|
||||
client := dockerCli.Client()
|
||||
ctx := context.Background()
|
||||
|
||||
var in io.Reader = dockerCli.In()
|
||||
if options.file != "-" {
|
||||
file, err := system.OpenSequential(options.file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
in = file
|
||||
defer file.Close()
|
||||
if options.driver != "" && options.file != "" {
|
||||
return errors.Errorf("When using secret driver secret data must be empty")
|
||||
}
|
||||
|
||||
secretData, err := ioutil.ReadAll(in)
|
||||
secretData, err := readSecretData(dockerCli.In(), options.file)
|
||||
if err != nil {
|
||||
return errors.Errorf("Error reading content from %q: %v", options.file, err)
|
||||
}
|
||||
|
||||
spec := swarm.SecretSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: options.name,
|
||||
@@ -68,6 +66,11 @@ func runSecretCreate(dockerCli command.Cli, options createOptions) error {
|
||||
},
|
||||
Data: secretData,
|
||||
}
|
||||
if options.driver != "" {
|
||||
spec.Driver = &swarm.Driver{
|
||||
Name: options.driver,
|
||||
}
|
||||
}
|
||||
|
||||
r, err := client.SecretCreate(ctx, spec)
|
||||
if err != nil {
|
||||
@@ -77,3 +80,23 @@ func runSecretCreate(dockerCli command.Cli, options createOptions) error {
|
||||
fmt.Fprintln(dockerCli.Out(), r.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func readSecretData(in io.ReadCloser, file string) ([]byte, error) {
|
||||
// Read secret value from external driver
|
||||
if file == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if file != "-" {
|
||||
var err error
|
||||
in, err = system.OpenSequential(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer in.Close()
|
||||
}
|
||||
data, err := ioutil.ReadAll(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
38
vendor/github.com/docker/cli/cli/command/secret/create_test.go
generated
vendored
38
vendor/github.com/docker/cli/cli/command/secret/create_test.go
generated
vendored
@@ -24,12 +24,11 @@ func TestSecretCreateErrors(t *testing.T) {
|
||||
secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
args: []string{"too_few"},
|
||||
expectedError: "requires exactly 2 arguments",
|
||||
},
|
||||
{args: []string{"too", "many", "arguments"},
|
||||
expectedError: "requires exactly 2 arguments",
|
||||
expectedError: "requires at least 1 and at most 2 arguments",
|
||||
},
|
||||
{args: []string{"create", "--driver", "driver", "-"},
|
||||
expectedError: "secret data must be empty",
|
||||
},
|
||||
{
|
||||
args: []string{"name", filepath.Join("testdata", secretDataFile)},
|
||||
@@ -75,6 +74,35 @@ func TestSecretCreateWithName(t *testing.T) {
|
||||
assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String()))
|
||||
}
|
||||
|
||||
func TestSecretCreateWithDriver(t *testing.T) {
|
||||
expectedDriver := &swarm.Driver{
|
||||
Name: "secret-driver",
|
||||
}
|
||||
name := "foo"
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
if spec.Name != name {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(spec.Driver.Name, expectedDriver.Name) {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("expected driver %v, got %v", expectedDriver, spec.Labels)
|
||||
}
|
||||
|
||||
return types.SecretCreateResponse{
|
||||
ID: "ID-" + spec.Name,
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
|
||||
cmd := newSecretCreateCommand(cli)
|
||||
cmd.SetArgs([]string{name})
|
||||
cmd.Flags().Set("driver", expectedDriver.Name)
|
||||
assert.NoError(t, cmd.Execute())
|
||||
assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String()))
|
||||
}
|
||||
|
||||
func TestSecretCreateWithLabels(t *testing.T) {
|
||||
expectedLabels := map[string]string{
|
||||
"lbl1": "Label-foo",
|
||||
|
||||
1
vendor/github.com/docker/cli/cli/command/secret/inspect_test.go
generated
vendored
1
vendor/github.com/docker/cli/cli/command/secret/inspect_test.go
generated
vendored
@@ -154,6 +154,7 @@ func TestSecretInspectPretty(t *testing.T) {
|
||||
}),
|
||||
SecretID("secretID"),
|
||||
SecretName("secretName"),
|
||||
SecretDriver("driver"),
|
||||
SecretCreatedAt(time.Time{}),
|
||||
SecretUpdatedAt(time.Time{}),
|
||||
), []byte{}, nil
|
||||
|
||||
1
vendor/github.com/docker/cli/cli/command/secret/ls_test.go
generated
vendored
1
vendor/github.com/docker/cli/cli/command/secret/ls_test.go
generated
vendored
@@ -63,6 +63,7 @@ func TestSecretList(t *testing.T) {
|
||||
SecretVersion(swarm.Version{Index: 11}),
|
||||
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
|
||||
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
|
||||
SecretDriver("driver"),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
ID: secretID
|
||||
Name: secretName
|
||||
ID: secretID
|
||||
Name: secretName
|
||||
Labels:
|
||||
- lbl1=value1
|
||||
Created at: 0001-01-01 00:00:00 +0000 utc
|
||||
Updated at: 0001-01-01 00:00:00 +0000 utc
|
||||
Driver: driver
|
||||
Created at: 0001-01-01 00:00:00 +0000 utc
|
||||
Updated at: 0001-01-01 00:00:00 +0000 utc
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
ID NAME CREATED UPDATED
|
||||
ID-foo foo 2 hours ago About an hour ago
|
||||
ID-bar bar 2 hours ago About an hour ago
|
||||
ID NAME DRIVER CREATED UPDATED
|
||||
ID-foo foo 2 hours ago About an hour ago
|
||||
ID-bar bar 2 hours ago About an hour ago
|
||||
|
||||
6
vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list.golden
generated
vendored
6
vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list.golden
generated
vendored
@@ -1,3 +1,3 @@
|
||||
ID NAME CREATED UPDATED
|
||||
ID-foo foo 2 hours ago About an hour ago
|
||||
ID-bar bar 2 hours ago About an hour ago
|
||||
ID NAME DRIVER CREATED UPDATED
|
||||
ID-foo foo 2 hours ago About an hour ago
|
||||
ID-bar bar driver 2 hours ago About an hour ago
|
||||
|
||||
8
vendor/github.com/docker/cli/cli/command/service/client_test.go
generated
vendored
8
vendor/github.com/docker/cli/cli/command/service/client_test.go
generated
vendored
@@ -14,6 +14,7 @@ type fakeClient struct {
|
||||
serviceInspectWithRawFunc func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error)
|
||||
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
|
||||
serviceListFunc func(context.Context, types.ServiceListOptions) ([]swarm.Service, error)
|
||||
infoFunc func(ctx context.Context) (types.Info, error)
|
||||
}
|
||||
|
||||
func (f *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
@@ -48,6 +49,13 @@ func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, versio
|
||||
return types.ServiceUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) Info(ctx context.Context) (types.Info, error) {
|
||||
if f.infoFunc == nil {
|
||||
return types.Info{}, nil
|
||||
}
|
||||
return f.infoFunc(ctx)
|
||||
}
|
||||
|
||||
func newService(id string, name string) swarm.Service {
|
||||
return swarm.Service{
|
||||
ID: id,
|
||||
|
||||
3
vendor/github.com/docker/cli/cli/command/service/create.go
generated
vendored
3
vendor/github.com/docker/cli/cli/command/service/create.go
generated
vendored
@@ -123,8 +123,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "%s\n", response.ID)
|
||||
|
||||
if opts.detach {
|
||||
warnDetachDefault(dockerCli.Err(), apiClient.ClientVersion(), flags, "created")
|
||||
if opts.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
11
vendor/github.com/docker/cli/cli/command/service/helpers.go
generated
vendored
11
vendor/github.com/docker/cli/cli/command/service/helpers.go
generated
vendored
@@ -1,15 +1,12 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/service/progress"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
@@ -34,11 +31,3 @@ func waitOnService(ctx context.Context, dockerCli command.Cli, serviceID string,
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// warnDetachDefault warns about the --detach flag future change if it's supported.
|
||||
func warnDetachDefault(err io.Writer, clientVersion string, flags *pflag.FlagSet, msg string) {
|
||||
if !flags.Changed("detach") && versions.GreaterThanOrEqualTo(clientVersion, "1.29") {
|
||||
fmt.Fprintf(err, "Since --detach=false was not specified, tasks will be %s in the background.\n"+
|
||||
"In a future release, --detach=false will become the default.\n", msg)
|
||||
}
|
||||
}
|
||||
|
||||
40
vendor/github.com/docker/cli/cli/command/service/helpers_test.go
generated
vendored
40
vendor/github.com/docker/cli/cli/command/service/helpers_test.go
generated
vendored
@@ -1,40 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestWarnDetachDefault(t *testing.T) {
|
||||
var detach bool
|
||||
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
addDetachFlag(flags, &detach)
|
||||
|
||||
var tests = []struct {
|
||||
detach bool
|
||||
version string
|
||||
|
||||
expectWarning bool
|
||||
}{
|
||||
{true, "1.28", false},
|
||||
{true, "1.29", false},
|
||||
{false, "1.28", false},
|
||||
{false, "1.29", true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
out := new(bytes.Buffer)
|
||||
flags.Lookup(flagDetach).Changed = test.detach
|
||||
|
||||
warnDetachDefault(out, test.version, flags, "")
|
||||
|
||||
if test.expectWarning {
|
||||
assert.NotEmpty(t, out.String(), "expected warning")
|
||||
} else {
|
||||
assert.Empty(t, out.String(), "expected no warning")
|
||||
}
|
||||
}
|
||||
}
|
||||
2
vendor/github.com/docker/cli/cli/command/service/inspect_test.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/service/inspect_test.go
generated
vendored
@@ -41,7 +41,7 @@ func formatServiceInspect(t *testing.T, format formatter.Format, now time.Time)
|
||||
Labels: map[string]string{"com.label": "foo"},
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: "foo/bar@sha256:this_is_a_test",
|
||||
},
|
||||
Networks: []swarm.NetworkAttachmentConfig{
|
||||
|
||||
3
vendor/github.com/docker/cli/cli/command/service/logs.go
generated
vendored
3
vendor/github.com/docker/cli/cli/command/service/logs.go
generated
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/idresolver"
|
||||
"github.com/docker/cli/service/logs"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
@@ -257,7 +258,7 @@ func (lw *logWriter) Write(buf []byte) (int, error) {
|
||||
return 0, errors.Errorf("invalid context in log message: %v", string(buf))
|
||||
}
|
||||
// parse the details out
|
||||
details, err := client.ParseLogDetails(string(parts[detailsIndex]))
|
||||
details, err := logs.ParseLogDetails(string(parts[detailsIndex]))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
4
vendor/github.com/docker/cli/cli/command/service/opts.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/service/opts.go
generated
vendored
@@ -592,7 +592,7 @@ func (options *serviceOptions) ToService(ctx context.Context, apiClient client.N
|
||||
Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()),
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: options.image,
|
||||
Args: options.args,
|
||||
Command: options.entrypoint.Value(),
|
||||
@@ -691,7 +691,7 @@ func buildServiceDefaultFlagMapping() flagDefaults {
|
||||
}
|
||||
|
||||
func addDetachFlag(flags *pflag.FlagSet, detach *bool) {
|
||||
flags.BoolVarP(detach, flagDetach, "d", true, "Exit immediately instead of waiting for the service to converge")
|
||||
flags.BoolVarP(detach, flagDetach, "d", false, "Exit immediately instead of waiting for the service to converge")
|
||||
flags.SetAnnotation(flagDetach, "version", []string{"1.29"})
|
||||
}
|
||||
|
||||
|
||||
11
vendor/github.com/docker/cli/cli/command/service/ps.go
generated
vendored
11
vendor/github.com/docker/cli/cli/command/service/ps.go
generated
vendored
@@ -56,6 +56,9 @@ func runPS(dockerCli command.Cli, options psOptions) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := updateNodeFilter(ctx, client, filter); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter})
|
||||
if err != nil {
|
||||
@@ -130,16 +133,20 @@ loop:
|
||||
if serviceCount == 0 {
|
||||
return filter, nil, errors.New(strings.Join(notfound, "\n"))
|
||||
}
|
||||
return filter, notfound, err
|
||||
}
|
||||
|
||||
func updateNodeFilter(ctx context.Context, client client.APIClient, filter filters.Args) error {
|
||||
if filter.Include("node") {
|
||||
nodeFilters := filter.Get("node")
|
||||
for _, nodeFilter := range nodeFilters {
|
||||
nodeReference, err := node.Reference(ctx, client, nodeFilter)
|
||||
if err != nil {
|
||||
return filter, nil, err
|
||||
return err
|
||||
}
|
||||
filter.Del("node", nodeFilter)
|
||||
filter.Add("node", nodeReference)
|
||||
}
|
||||
}
|
||||
return filter, notfound, err
|
||||
return nil
|
||||
}
|
||||
|
||||
22
vendor/github.com/docker/cli/cli/command/service/ps_test.go
generated
vendored
22
vendor/github.com/docker/cli/cli/command/service/ps_test.go
generated
vendored
@@ -89,3 +89,25 @@ func TestRunPSWarnsOnNotFound(t *testing.T) {
|
||||
err := runPS(cli, options)
|
||||
assert.EqualError(t, err, "no such service: bar")
|
||||
}
|
||||
|
||||
func TestUpdateNodeFilter(t *testing.T) {
|
||||
selfNodeID := "foofoo"
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("node", "one")
|
||||
filter.Add("node", "two")
|
||||
filter.Add("node", "self")
|
||||
|
||||
client := &fakeClient{
|
||||
infoFunc: func(_ context.Context) (types.Info, error) {
|
||||
return types.Info{Swarm: swarm.Info{NodeID: selfNodeID}}, nil
|
||||
},
|
||||
}
|
||||
|
||||
updateNodeFilter(context.Background(), client, filter)
|
||||
|
||||
expected := filters.NewArgs()
|
||||
expected.Add("node", "one")
|
||||
expected.Add("node", "two")
|
||||
expected.Add("node", selfNodeID)
|
||||
assert.Equal(t, expected, filter)
|
||||
}
|
||||
|
||||
9
vendor/github.com/docker/cli/cli/command/service/rollback.go
generated
vendored
9
vendor/github.com/docker/cli/cli/command/service/rollback.go
generated
vendored
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
|
||||
@@ -19,7 +19,7 @@ func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
|
||||
Short: "Revert changes to a service's configuration",
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRollback(dockerCli, cmd.Flags(), options, args[0])
|
||||
return runRollback(dockerCli, options, args[0])
|
||||
},
|
||||
Tags: map[string]string{"version": "1.31"},
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runRollback(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
|
||||
func runRollback(dockerCli command.Cli, options *serviceOptions, serviceID string) error {
|
||||
apiClient := dockerCli.Client()
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -56,8 +56,7 @@ func runRollback(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOp
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID)
|
||||
|
||||
if options.detach {
|
||||
warnDetachDefault(dockerCli.Err(), apiClient.ClientVersion(), flags, "rolled back")
|
||||
if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
10
vendor/github.com/docker/cli/cli/command/service/scale.go
generated
vendored
10
vendor/github.com/docker/cli/cli/command/service/scale.go
generated
vendored
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
type scaleOptions struct {
|
||||
@@ -27,7 +27,7 @@ func newScaleCommand(dockerCli command.Cli) *cobra.Command {
|
||||
Short: "Scale one or multiple replicated services",
|
||||
Args: scaleArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runScale(dockerCli, cmd.Flags(), options, args)
|
||||
return runScale(dockerCli, options, args)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func scaleArgs(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runScale(dockerCli command.Cli, flags *pflag.FlagSet, options *scaleOptions, args []string) error {
|
||||
func runScale(dockerCli command.Cli, options *scaleOptions, args []string) error {
|
||||
var errs []string
|
||||
var serviceIDs []string
|
||||
ctx := context.Background()
|
||||
@@ -79,9 +79,7 @@ func runScale(dockerCli command.Cli, flags *pflag.FlagSet, options *scaleOptions
|
||||
}
|
||||
|
||||
if len(serviceIDs) > 0 {
|
||||
if options.detach {
|
||||
warnDetachDefault(dockerCli.Err(), dockerCli.Client().ClientVersion(), flags, "scaled")
|
||||
} else {
|
||||
if !options.detach && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.29") {
|
||||
for _, serviceID := range serviceIDs {
|
||||
if err := waitOnService(ctx, dockerCli, serviceID, false); err != nil {
|
||||
errs = append(errs, fmt.Sprintf("%s: %v", serviceID, err))
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/service/trust.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/service/trust.go
generated
vendored
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/distribution/reference"
|
||||
@@ -12,6 +11,7 @@ import (
|
||||
"github.com/docker/notary/tuf/data"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
||||
5
vendor/github.com/docker/cli/cli/command/service/update.go
generated
vendored
5
vendor/github.com/docker/cli/cli/command/service/update.go
generated
vendored
@@ -216,8 +216,7 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID)
|
||||
|
||||
if options.detach {
|
||||
warnDetachDefault(dockerCli.Err(), dockerCli.Client().ClientVersion(), flags, "updated")
|
||||
if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -270,7 +269,7 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
|
||||
}
|
||||
}
|
||||
|
||||
cspec := &spec.TaskTemplate.ContainerSpec
|
||||
cspec := spec.TaskTemplate.ContainerSpec
|
||||
task := &spec.TaskTemplate
|
||||
|
||||
taskResources := func() *swarm.ResourceRequirements {
|
||||
|
||||
24
vendor/github.com/docker/cli/cli/command/service/update_test.go
generated
vendored
24
vendor/github.com/docker/cli/cli/command/service/update_test.go
generated
vendored
@@ -19,8 +19,12 @@ func TestUpdateServiceArgs(t *testing.T) {
|
||||
flags := newUpdateCommand(nil).Flags()
|
||||
flags.Set("args", "the \"new args\"")
|
||||
|
||||
spec := &swarm.ServiceSpec{}
|
||||
cspec := &spec.TaskTemplate.ContainerSpec
|
||||
spec := &swarm.ServiceSpec{
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{},
|
||||
},
|
||||
}
|
||||
cspec := spec.TaskTemplate.ContainerSpec
|
||||
cspec.Args = []string{"old", "args"}
|
||||
|
||||
updateService(nil, nil, flags, spec)
|
||||
@@ -452,8 +456,12 @@ func TestUpdateSecretUpdateInPlace(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateReadOnly(t *testing.T) {
|
||||
spec := &swarm.ServiceSpec{}
|
||||
cspec := &spec.TaskTemplate.ContainerSpec
|
||||
spec := &swarm.ServiceSpec{
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{},
|
||||
},
|
||||
}
|
||||
cspec := spec.TaskTemplate.ContainerSpec
|
||||
|
||||
// Update with --read-only=true, changed to true
|
||||
flags := newUpdateCommand(nil).Flags()
|
||||
@@ -474,8 +482,12 @@ func TestUpdateReadOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateStopSignal(t *testing.T) {
|
||||
spec := &swarm.ServiceSpec{}
|
||||
cspec := &spec.TaskTemplate.ContainerSpec
|
||||
spec := &swarm.ServiceSpec{
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{},
|
||||
},
|
||||
}
|
||||
cspec := spec.TaskTemplate.ContainerSpec
|
||||
|
||||
// Update with --stop-signal=SIGUSR1
|
||||
flags := newUpdateCommand(nil).Flags()
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go
generated
vendored
2
vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go
generated
vendored
@@ -64,7 +64,7 @@ func deployBundle(ctx context.Context, dockerCli command.Cli, opts deployOptions
|
||||
Labels: convert.AddStackLabel(namespace, service.Labels),
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: service.Image,
|
||||
Command: service.Command,
|
||||
Args: service.Args,
|
||||
|
||||
4
vendor/github.com/docker/cli/cli/command/stack/deploy_test.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/stack/deploy_test.go
generated
vendored
@@ -45,7 +45,7 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) {
|
||||
Labels: map[string]string{"com.docker.stack.image": "foobar:1.2.3"},
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: "foobar:1.2.3@sha256:deadbeef",
|
||||
},
|
||||
},
|
||||
@@ -86,7 +86,7 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) {
|
||||
spec := map[string]swarm.ServiceSpec{
|
||||
"myservice": {
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: testcase.image,
|
||||
},
|
||||
},
|
||||
|
||||
3
vendor/github.com/docker/cli/cli/command/stack/ps.go
generated
vendored
3
vendor/github.com/docker/cli/cli/command/stack/ps.go
generated
vendored
@@ -57,8 +57,7 @@ func runPS(dockerCli command.Cli, options psOptions) error {
|
||||
}
|
||||
|
||||
if len(tasks) == 0 {
|
||||
fmt.Fprintf(dockerCli.Err(), "Nothing found in stack: %s\n", namespace)
|
||||
return nil
|
||||
return fmt.Errorf("nothing found in stack: %s", namespace)
|
||||
}
|
||||
|
||||
format := options.format
|
||||
|
||||
4
vendor/github.com/docker/cli/cli/command/stack/ps_test.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/stack/ps_test.go
generated
vendored
@@ -60,9 +60,9 @@ func TestStackPsEmptyStack(t *testing.T) {
|
||||
cmd := newPsCommand(fakeCli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
|
||||
assert.NoError(t, cmd.Execute())
|
||||
assert.Error(t, cmd.Execute())
|
||||
assert.EqualError(t, cmd.Execute(), "nothing found in stack: foo")
|
||||
assert.Equal(t, "", fakeCli.OutBuffer().String())
|
||||
assert.Equal(t, "Nothing found in stack: foo\n", fakeCli.ErrBuffer().String())
|
||||
}
|
||||
|
||||
func TestStackPsWithQuietOption(t *testing.T) {
|
||||
|
||||
16
vendor/github.com/docker/cli/cli/command/stack/remove.go
generated
vendored
16
vendor/github.com/docker/cli/cli/command/stack/remove.go
generated
vendored
@@ -2,6 +2,7 @@ package stack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
@@ -88,14 +89,21 @@ func runRemove(dockerCli command.Cli, opts removeOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortServiceByName(services []swarm.Service) func(i, j int) bool {
|
||||
return func(i, j int) bool {
|
||||
return services[i].Spec.Name < services[j].Spec.Name
|
||||
}
|
||||
}
|
||||
|
||||
func removeServices(
|
||||
ctx context.Context,
|
||||
dockerCli command.Cli,
|
||||
services []swarm.Service,
|
||||
) bool {
|
||||
var hasError bool
|
||||
sort.Slice(services, sortServiceByName(services))
|
||||
for _, service := range services {
|
||||
fmt.Fprintf(dockerCli.Err(), "Removing service %s\n", service.Spec.Name)
|
||||
fmt.Fprintf(dockerCli.Out(), "Removing service %s\n", service.Spec.Name)
|
||||
if err := dockerCli.Client().ServiceRemove(ctx, service.ID); err != nil {
|
||||
hasError = true
|
||||
fmt.Fprintf(dockerCli.Err(), "Failed to remove service %s: %s", service.ID, err)
|
||||
@@ -111,7 +119,7 @@ func removeNetworks(
|
||||
) bool {
|
||||
var hasError bool
|
||||
for _, network := range networks {
|
||||
fmt.Fprintf(dockerCli.Err(), "Removing network %s\n", network.Name)
|
||||
fmt.Fprintf(dockerCli.Out(), "Removing network %s\n", network.Name)
|
||||
if err := dockerCli.Client().NetworkRemove(ctx, network.ID); err != nil {
|
||||
hasError = true
|
||||
fmt.Fprintf(dockerCli.Err(), "Failed to remove network %s: %s", network.ID, err)
|
||||
@@ -127,7 +135,7 @@ func removeSecrets(
|
||||
) bool {
|
||||
var hasError bool
|
||||
for _, secret := range secrets {
|
||||
fmt.Fprintf(dockerCli.Err(), "Removing secret %s\n", secret.Spec.Name)
|
||||
fmt.Fprintf(dockerCli.Out(), "Removing secret %s\n", secret.Spec.Name)
|
||||
if err := dockerCli.Client().SecretRemove(ctx, secret.ID); err != nil {
|
||||
hasError = true
|
||||
fmt.Fprintf(dockerCli.Err(), "Failed to remove secret %s: %s", secret.ID, err)
|
||||
@@ -143,7 +151,7 @@ func removeConfigs(
|
||||
) bool {
|
||||
var hasError bool
|
||||
for _, config := range configs {
|
||||
fmt.Fprintf(dockerCli.Err(), "Removing config %s\n", config.Spec.Name)
|
||||
fmt.Fprintf(dockerCli.Out(), "Removing config %s\n", config.Spec.Name)
|
||||
if err := dockerCli.Client().ConfigRemove(ctx, config.ID); err != nil {
|
||||
hasError = true
|
||||
fmt.Fprintf(dockerCli.Err(), "Failed to remove config %s: %s", config.ID, err)
|
||||
|
||||
8
vendor/github.com/docker/cli/cli/command/stack/remove_test.go
generated
vendored
8
vendor/github.com/docker/cli/cli/command/stack/remove_test.go
generated
vendored
@@ -101,7 +101,13 @@ func TestRemoveStackSkipEmpty(t *testing.T) {
|
||||
cmd.SetArgs([]string{"foo", "bar"})
|
||||
|
||||
assert.NoError(t, cmd.Execute())
|
||||
assert.Equal(t, "", fakeCli.OutBuffer().String())
|
||||
expectedList := []string{"Removing service bar_service1",
|
||||
"Removing service bar_service2",
|
||||
"Removing secret bar_secret1",
|
||||
"Removing config bar_config1",
|
||||
"Removing network bar_network1\n",
|
||||
}
|
||||
assert.Equal(t, strings.Join(expectedList, "\n"), fakeCli.OutBuffer().String())
|
||||
assert.Contains(t, fakeCli.ErrBuffer().String(), "Nothing found in stack: foo\n")
|
||||
assert.Equal(t, allServiceIDs, fakeClient.removedServices)
|
||||
assert.Equal(t, allNetworkIDs, fakeClient.removedNetworks)
|
||||
|
||||
236
vendor/github.com/docker/cli/cli/command/system/info.go
generated
vendored
236
vendor/github.com/docker/cli/cli/command/system/info.go
generated
vendored
@@ -54,109 +54,51 @@ func runInfo(dockerCli *command.DockerCli, opts *infoOptions) error {
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
||||
fmt.Fprintf(dockerCli.Out(), "Containers: %d\n", info.Containers)
|
||||
fmt.Fprintf(dockerCli.Out(), " Running: %d\n", info.ContainersRunning)
|
||||
fmt.Fprintf(dockerCli.Out(), " Paused: %d\n", info.ContainersPaused)
|
||||
fmt.Fprintf(dockerCli.Out(), " Stopped: %d\n", info.ContainersStopped)
|
||||
fmt.Fprintf(dockerCli.Out(), "Images: %d\n", info.Images)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Server Version: %s\n", info.ServerVersion)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Storage Driver: %s\n", info.Driver)
|
||||
func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
|
||||
fmt.Fprintln(dockerCli.Out(), "Containers:", info.Containers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Running:", info.ContainersRunning)
|
||||
fmt.Fprintln(dockerCli.Out(), " Paused:", info.ContainersPaused)
|
||||
fmt.Fprintln(dockerCli.Out(), " Stopped:", info.ContainersStopped)
|
||||
fmt.Fprintln(dockerCli.Out(), "Images:", info.Images)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Storage Driver:", info.Driver)
|
||||
if info.DriverStatus != nil {
|
||||
for _, pair := range info.DriverStatus {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
|
||||
}
|
||||
if info.SystemStatus != nil {
|
||||
for _, pair := range info.SystemStatus {
|
||||
fmt.Fprintf(dockerCli.Out(), "%s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Logging Driver: %s\n", info.LoggingDriver)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Cgroup Driver: %s\n", info.CgroupDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Cgroup Driver:", info.CgroupDriver)
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "Plugins: \n")
|
||||
fmt.Fprintf(dockerCli.Out(), " Volume:")
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Volume, " "))
|
||||
fmt.Fprintf(dockerCli.Out(), "\n")
|
||||
fmt.Fprintf(dockerCli.Out(), " Network:")
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Network, " "))
|
||||
fmt.Fprintf(dockerCli.Out(), "\n")
|
||||
fmt.Fprintln(dockerCli.Out(), "Plugins:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
|
||||
if len(info.Plugins.Authorization) != 0 {
|
||||
fmt.Fprintf(dockerCli.Out(), " Authorization:")
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Authorization, " "))
|
||||
fmt.Fprintf(dockerCli.Out(), "\n")
|
||||
fmt.Fprintln(dockerCli.Out(), " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
}
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), " Log:")
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Log, " "))
|
||||
fmt.Fprintf(dockerCli.Out(), "\n")
|
||||
fmt.Fprintln(dockerCli.Out(), " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "Swarm: %v\n", info.Swarm.LocalNodeState)
|
||||
if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked {
|
||||
fmt.Fprintf(dockerCli.Out(), " NodeID: %s\n", info.Swarm.NodeID)
|
||||
if info.Swarm.Error != "" {
|
||||
fmt.Fprintf(dockerCli.Out(), " Error: %v\n", info.Swarm.Error)
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Is Manager: %v\n", info.Swarm.ControlAvailable)
|
||||
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
|
||||
fmt.Fprintf(dockerCli.Out(), " ClusterID: %s\n", info.Swarm.Cluster.ID)
|
||||
fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers)
|
||||
fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes)
|
||||
fmt.Fprintf(dockerCli.Out(), " Orchestration:\n")
|
||||
taskHistoryRetentionLimit := int64(0)
|
||||
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
|
||||
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Task History Retention Limit: %d\n", taskHistoryRetentionLimit)
|
||||
fmt.Fprintf(dockerCli.Out(), " Raft:\n")
|
||||
fmt.Fprintf(dockerCli.Out(), " Snapshot Interval: %d\n", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
|
||||
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Heartbeat Tick: %d\n", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fmt.Fprintf(dockerCli.Out(), " Election Tick: %d\n", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fmt.Fprintf(dockerCli.Out(), " Dispatcher:\n")
|
||||
fmt.Fprintf(dockerCli.Out(), " Heartbeat Period: %s\n", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fmt.Fprintf(dockerCli.Out(), " CA Configuration:\n")
|
||||
fmt.Fprintf(dockerCli.Out(), " Expiry Duration: %s\n", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fmt.Fprintf(dockerCli.Out(), " Force Rotate: %d\n", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert))
|
||||
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
|
||||
fmt.Fprintf(dockerCli.Out(), " External CAs:\n")
|
||||
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Root Rotation In Progress: %v\n", info.Swarm.Cluster.RootRotationInProgress)
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Node Address: %s\n", info.Swarm.NodeAddr)
|
||||
managers := []string{}
|
||||
for _, entry := range info.Swarm.RemoteManagers {
|
||||
managers = append(managers, entry.Addr)
|
||||
}
|
||||
if len(managers) > 0 {
|
||||
sort.Strings(managers)
|
||||
fmt.Fprintf(dockerCli.Out(), " Manager Addresses:\n")
|
||||
for _, entry := range managers {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), "Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(dockerCli, info)
|
||||
|
||||
if len(info.Runtimes) > 0 {
|
||||
fmt.Fprintf(dockerCli.Out(), "Runtimes:")
|
||||
fmt.Fprint(dockerCli.Out(), "Runtimes:")
|
||||
for name := range info.Runtimes {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", name)
|
||||
}
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
fmt.Fprintf(dockerCli.Out(), "Default Runtime: %s\n", info.DefaultRuntime)
|
||||
fmt.Fprintln(dockerCli.Out(), "Default Runtime:", info.DefaultRuntime)
|
||||
}
|
||||
|
||||
if info.OSType == "linux" {
|
||||
fmt.Fprintf(dockerCli.Out(), "Init Binary: %v\n", info.InitBinary)
|
||||
fmt.Fprintln(dockerCli.Out(), "Init Binary:", info.InitBinary)
|
||||
|
||||
for _, ci := range []struct {
|
||||
Name string
|
||||
@@ -170,23 +112,23 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
||||
if ci.Commit.ID != ci.Commit.Expected {
|
||||
fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected)
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), "\n")
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
}
|
||||
if len(info.SecurityOptions) != 0 {
|
||||
kvs, err := types.DecodeSecurityOptions(info.SecurityOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), "Security Options:\n")
|
||||
fmt.Fprintln(dockerCli.Out(), "Security Options:")
|
||||
for _, so := range kvs {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", so.Name)
|
||||
fmt.Fprintln(dockerCli.Out(), " "+so.Name)
|
||||
for _, o := range so.Options {
|
||||
switch o.Key {
|
||||
case "profile":
|
||||
if o.Value != "default" {
|
||||
fmt.Fprintf(dockerCli.Err(), " WARNING: You're not using the default seccomp profile\n")
|
||||
fmt.Fprintln(dockerCli.Err(), " WARNING: You're not using the default seccomp profile")
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Profile: %s\n", o.Value)
|
||||
fmt.Fprintln(dockerCli.Out(), " Profile:", o.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,44 +137,44 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
||||
|
||||
// Isolation only has meaning on a Windows daemon.
|
||||
if info.OSType == "windows" {
|
||||
fmt.Fprintf(dockerCli.Out(), "Default Isolation: %v\n", info.Isolation)
|
||||
fmt.Fprintln(dockerCli.Out(), "Default Isolation:", info.Isolation)
|
||||
}
|
||||
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Kernel Version: %s\n", info.KernelVersion)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Operating System: %s\n", info.OperatingSystem)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "OSType: %s\n", info.OSType)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Architecture: %s\n", info.Architecture)
|
||||
fmt.Fprintf(dockerCli.Out(), "CPUs: %d\n", info.NCPU)
|
||||
fmt.Fprintf(dockerCli.Out(), "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Name: %s\n", info.Name)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "ID: %s\n", info.ID)
|
||||
fmt.Fprintf(dockerCli.Out(), "Docker Root Dir: %s\n", info.DockerRootDir)
|
||||
fmt.Fprintf(dockerCli.Out(), "Debug Mode (client): %v\n", debug.IsEnabled())
|
||||
fmt.Fprintf(dockerCli.Out(), "Debug Mode (server): %v\n", info.Debug)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "OSType:", info.OSType)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Architecture:", info.Architecture)
|
||||
fmt.Fprintln(dockerCli.Out(), "CPUs:", info.NCPU)
|
||||
fmt.Fprintln(dockerCli.Out(), "Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Name:", info.Name)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "ID:", info.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), "Docker Root Dir:", info.DockerRootDir)
|
||||
fmt.Fprintln(dockerCli.Out(), "Debug Mode (client):", debug.IsEnabled())
|
||||
fmt.Fprintln(dockerCli.Out(), "Debug Mode (server):", info.Debug)
|
||||
|
||||
if info.Debug {
|
||||
fmt.Fprintf(dockerCli.Out(), " File Descriptors: %d\n", info.NFd)
|
||||
fmt.Fprintf(dockerCli.Out(), " Goroutines: %d\n", info.NGoroutines)
|
||||
fmt.Fprintf(dockerCli.Out(), " System Time: %s\n", info.SystemTime)
|
||||
fmt.Fprintf(dockerCli.Out(), " EventsListeners: %d\n", info.NEventsListener)
|
||||
fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd)
|
||||
fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines)
|
||||
fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime)
|
||||
fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener)
|
||||
}
|
||||
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Http Proxy: %s\n", info.HTTPProxy)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "Https Proxy: %s\n", info.HTTPSProxy)
|
||||
fprintfIfNotEmpty(dockerCli.Out(), "No Proxy: %s\n", info.NoProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "No Proxy:", info.NoProxy)
|
||||
|
||||
if info.IndexServerAddress != "" {
|
||||
u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username
|
||||
if len(u) > 0 {
|
||||
fmt.Fprintf(dockerCli.Out(), "Username: %v\n", u)
|
||||
fmt.Fprintln(dockerCli.Out(), "Username:", u)
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress)
|
||||
fmt.Fprintln(dockerCli.Out(), "Registry:", info.IndexServerAddress)
|
||||
}
|
||||
|
||||
if info.Labels != nil {
|
||||
fmt.Fprintln(dockerCli.Out(), "Labels:")
|
||||
for _, attribute := range info.Labels {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", attribute)
|
||||
for _, lbl := range info.Labels {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+lbl)
|
||||
}
|
||||
// TODO: Engine labels with duplicate keys has been deprecated in 1.13 and will be error out
|
||||
// after 3 release cycles (17.12). For now, a WARNING will be generated. The following will
|
||||
@@ -251,20 +193,15 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild)
|
||||
if info.ClusterStore != "" {
|
||||
fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore)
|
||||
}
|
||||
|
||||
if info.ClusterAdvertise != "" {
|
||||
fmt.Fprintf(dockerCli.Out(), "Cluster Advertise: %s\n", info.ClusterAdvertise)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), "Experimental:", info.ExperimentalBuild)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Cluster Store:", info.ClusterStore)
|
||||
fprintlnNonEmpty(dockerCli.Out(), "Cluster Advertise:", info.ClusterAdvertise)
|
||||
|
||||
if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) {
|
||||
fmt.Fprintln(dockerCli.Out(), "Insecure Registries:")
|
||||
for _, registry := range info.RegistryConfig.IndexConfigs {
|
||||
if !registry.Secure {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", registry.Name)
|
||||
fmt.Fprintln(dockerCli.Out(), " "+registry.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,11 +214,12 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
||||
if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), "Registry Mirrors:")
|
||||
for _, mirror := range info.RegistryConfig.Mirrors {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", mirror)
|
||||
fmt.Fprintln(dockerCli.Out(), " "+mirror)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n\n", info.LiveRestoreEnabled)
|
||||
fmt.Fprintln(dockerCli.Out(), "Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
|
||||
// Only output these warnings if the server does not support these features
|
||||
if info.OSType != "windows" {
|
||||
@@ -325,7 +263,64 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func printStorageDriverWarnings(dockerCli *command.DockerCli, info types.Info) {
|
||||
func printSwarmInfo(dockerCli command.Cli, info types.Info) {
|
||||
if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " NodeID:", info.Swarm.NodeID)
|
||||
if info.Swarm.Error != "" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Error:", info.Swarm.Error)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Is Manager:", info.Swarm.ControlAvailable)
|
||||
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
|
||||
fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes)
|
||||
fmt.Fprintln(dockerCli.Out(), " Orchestration:")
|
||||
taskHistoryRetentionLimit := int64(0)
|
||||
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
|
||||
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fmt.Fprintln(dockerCli.Out(), " Raft:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
|
||||
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Dispatcher:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fmt.Fprintln(dockerCli.Out(), " CA Configuration:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fmt.Fprintln(dockerCli.Out(), " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
if caCert := strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert); caCert != "" {
|
||||
fmt.Fprintf(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
}
|
||||
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " External CAs:")
|
||||
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Node Address:", info.Swarm.NodeAddr)
|
||||
if len(info.Swarm.RemoteManagers) > 0 {
|
||||
managers := []string{}
|
||||
for _, entry := range info.Swarm.RemoteManagers {
|
||||
managers = append(managers, entry.Addr)
|
||||
}
|
||||
sort.Strings(managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Manager Addresses:")
|
||||
for _, entry := range managers {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printStorageDriverWarnings(dockerCli command.Cli, info types.Info) {
|
||||
if info.DriverStatus == nil {
|
||||
return
|
||||
}
|
||||
@@ -373,9 +368,8 @@ func formatInfo(dockerCli *command.DockerCli, info types.Info, format string) er
|
||||
return err
|
||||
}
|
||||
|
||||
func fprintfIfNotEmpty(w io.Writer, format, value string) (int, error) {
|
||||
func fprintlnNonEmpty(w io.Writer, label, value string) {
|
||||
if value != "" {
|
||||
return fmt.Fprintf(w, format, value)
|
||||
fmt.Fprintln(w, label, value)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
237
vendor/github.com/docker/cli/cli/command/system/info_test.go
generated
vendored
Normal file
237
vendor/github.com/docker/cli/cli/command/system/info_test.go
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/gotestyourself/gotestyourself/golden"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// helper function that base64 decodes a string and ignores the error
|
||||
func base64Decode(val string) []byte {
|
||||
decoded, _ := base64.StdEncoding.DecodeString(val)
|
||||
return decoded
|
||||
}
|
||||
|
||||
var sampleInfoNoSwarm = types.Info{
|
||||
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: [][2]string{
|
||||
{"Root Dir", "/var/lib/docker/aufs"},
|
||||
{"Backing Filesystem", "extfs"},
|
||||
{"Dirs", "0"},
|
||||
{"Dirperm1 Supported", "true"},
|
||||
},
|
||||
SystemStatus: nil,
|
||||
Plugins: types.PluginsInfo{
|
||||
Volume: []string{"local"},
|
||||
Network: []string{"bridge", "host", "macvlan", "null", "overlay"},
|
||||
Authorization: nil,
|
||||
Log: []string{"awslogs", "fluentd", "gcplogs", "gelf", "journald", "json-file", "logentries", "splunk", "syslog"},
|
||||
},
|
||||
MemoryLimit: true,
|
||||
SwapLimit: true,
|
||||
KernelMemory: true,
|
||||
CPUCfsPeriod: true,
|
||||
CPUCfsQuota: true,
|
||||
CPUShares: true,
|
||||
CPUSet: true,
|
||||
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",
|
||||
OSType: "linux",
|
||||
Architecture: "x86_64",
|
||||
IndexServerAddress: "https://index.docker.io/v1/",
|
||||
RegistryConfig: ®istry.ServiceConfig{
|
||||
AllowNondistributableArtifactsCIDRs: nil,
|
||||
AllowNondistributableArtifactsHostnames: nil,
|
||||
InsecureRegistryCIDRs: []*registry.NetIPNet{
|
||||
{
|
||||
IP: net.ParseIP("127.0.0.0"),
|
||||
Mask: net.IPv4Mask(255, 0, 0, 0),
|
||||
},
|
||||
},
|
||||
IndexConfigs: map[string]*registry.IndexInfo{
|
||||
"docker.io": {
|
||||
Name: "docker.io",
|
||||
Mirrors: nil,
|
||||
Secure: true,
|
||||
Official: true,
|
||||
},
|
||||
},
|
||||
Mirrors: nil,
|
||||
},
|
||||
NCPU: 2,
|
||||
MemTotal: 2097356800,
|
||||
DockerRootDir: "/var/lib/docker",
|
||||
HTTPProxy: "",
|
||||
HTTPSProxy: "",
|
||||
NoProxy: "",
|
||||
Name: "system-sample",
|
||||
Labels: []string{"provider=digitalocean"},
|
||||
ExperimentalBuild: false,
|
||||
ServerVersion: "17.06.1-ce",
|
||||
ClusterStore: "",
|
||||
ClusterAdvertise: "",
|
||||
Runtimes: map[string]types.Runtime{
|
||||
"runc": {
|
||||
Path: "docker-runc",
|
||||
Args: nil,
|
||||
},
|
||||
},
|
||||
DefaultRuntime: "runc",
|
||||
Swarm: swarm.Info{LocalNodeState: "inactive"},
|
||||
LiveRestoreEnabled: false,
|
||||
Isolation: "",
|
||||
InitBinary: "docker-init",
|
||||
ContainerdCommit: types.Commit{
|
||||
ID: "6e23458c129b551d5c9871e5174f6b1b7f6d1170",
|
||||
Expected: "6e23458c129b551d5c9871e5174f6b1b7f6d1170",
|
||||
},
|
||||
RuncCommit: types.Commit{
|
||||
ID: "810190ceaa507aa2727d7ae6f4790c76ec150bd2",
|
||||
Expected: "810190ceaa507aa2727d7ae6f4790c76ec150bd2",
|
||||
},
|
||||
InitCommit: types.Commit{
|
||||
ID: "949e6fa",
|
||||
Expected: "949e6fa",
|
||||
},
|
||||
SecurityOptions: []string{"name=apparmor", "name=seccomp,profile=default"},
|
||||
}
|
||||
|
||||
var sampleSwarmInfo = swarm.Info{
|
||||
NodeID: "qo2dfdig9mmxqkawulggepdih",
|
||||
NodeAddr: "165.227.107.89",
|
||||
LocalNodeState: "active",
|
||||
ControlAvailable: true,
|
||||
Error: "",
|
||||
RemoteManagers: []swarm.Peer{
|
||||
{
|
||||
NodeID: "qo2dfdig9mmxqkawulggepdih",
|
||||
Addr: "165.227.107.89:2377",
|
||||
},
|
||||
},
|
||||
Nodes: 1,
|
||||
Managers: 1,
|
||||
Cluster: &swarm.ClusterInfo{
|
||||
ID: "9vs5ygs0gguyyec4iqf2314c0",
|
||||
Meta: swarm.Meta{
|
||||
Version: swarm.Version{Index: 11},
|
||||
CreatedAt: time.Date(2017, 8, 24, 17, 34, 19, 278062352, time.UTC),
|
||||
UpdatedAt: time.Date(2017, 8, 24, 17, 34, 42, 398815481, time.UTC),
|
||||
},
|
||||
Spec: swarm.Spec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: "default",
|
||||
Labels: nil,
|
||||
},
|
||||
Orchestration: swarm.OrchestrationConfig{
|
||||
TaskHistoryRetentionLimit: &[]int64{5}[0],
|
||||
},
|
||||
Raft: swarm.RaftConfig{
|
||||
SnapshotInterval: 10000,
|
||||
KeepOldSnapshots: &[]uint64{0}[0],
|
||||
LogEntriesForSlowFollowers: 500,
|
||||
ElectionTick: 3,
|
||||
HeartbeatTick: 1,
|
||||
},
|
||||
Dispatcher: swarm.DispatcherConfig{
|
||||
HeartbeatPeriod: 5000000000,
|
||||
},
|
||||
CAConfig: swarm.CAConfig{
|
||||
NodeCertExpiry: 7776000000000000,
|
||||
},
|
||||
TaskDefaults: swarm.TaskDefaults{},
|
||||
EncryptionConfig: swarm.EncryptionConfig{
|
||||
AutoLockManagers: true,
|
||||
},
|
||||
},
|
||||
TLSInfo: swarm.TLSInfo{
|
||||
TrustRoot: `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBajCCARCgAwIBAgIUaFCW5xsq8eyiJ+Pmcv3MCflMLnMwCgYIKoZIzj0EAwIw
|
||||
EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwODI0MTcyOTAwWhcNMzcwODE5MTcy
|
||||
OTAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
|
||||
A0IABDy7NebyUJyUjWJDBUdnZoV6GBxEGKO4TZPNDwnxDxJcUdLVaB7WGa4/DLrW
|
||||
UfsVgh1JGik2VTiLuTMA1tLlNPOjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
|
||||
Af8EBTADAQH/MB0GA1UdDgQWBBQl16XFtaaXiUAwEuJptJlDjfKskDAKBggqhkjO
|
||||
PQQDAgNIADBFAiEAo9fTQNM5DP9bHVcTJYfl2Cay1bFu1E+lnpmN+EYJfeACIGKH
|
||||
1pCUkZ+D0IB6CiEZGWSHyLuXPM1rlP+I5KuS7sB8
|
||||
-----END CERTIFICATE-----
|
||||
`,
|
||||
CertIssuerSubject: base64Decode("MBMxETAPBgNVBAMTCHN3YXJtLWNh"),
|
||||
CertIssuerPublicKey: base64Decode(
|
||||
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPLs15vJQnJSNYkMFR2dmhXoYHEQYo7hNk80PCfEPElxR0tVoHtYZrj8MutZR+xWCHUkaKTZVOIu5MwDW0uU08w=="),
|
||||
},
|
||||
RootRotationInProgress: false,
|
||||
},
|
||||
}
|
||||
|
||||
func TestPrettyPrintInfo(t *testing.T) {
|
||||
infoWithSwarm := sampleInfoNoSwarm
|
||||
infoWithSwarm.Swarm = sampleSwarmInfo
|
||||
|
||||
infoWithWarningsLinux := sampleInfoNoSwarm
|
||||
infoWithWarningsLinux.MemoryLimit = false
|
||||
infoWithWarningsLinux.SwapLimit = false
|
||||
infoWithWarningsLinux.KernelMemory = false
|
||||
infoWithWarningsLinux.OomKillDisable = false
|
||||
infoWithWarningsLinux.CPUCfsQuota = false
|
||||
infoWithWarningsLinux.CPUCfsPeriod = false
|
||||
infoWithWarningsLinux.CPUShares = false
|
||||
infoWithWarningsLinux.CPUSet = false
|
||||
infoWithWarningsLinux.IPv4Forwarding = false
|
||||
infoWithWarningsLinux.BridgeNfIptables = false
|
||||
infoWithWarningsLinux.BridgeNfIP6tables = false
|
||||
|
||||
for _, tc := range []struct {
|
||||
dockerInfo types.Info
|
||||
expectedGolden string
|
||||
warningsGolden string
|
||||
}{
|
||||
{
|
||||
dockerInfo: sampleInfoNoSwarm,
|
||||
expectedGolden: "docker-info-no-swarm",
|
||||
},
|
||||
{
|
||||
dockerInfo: infoWithSwarm,
|
||||
expectedGolden: "docker-info-with-swarm",
|
||||
},
|
||||
{
|
||||
dockerInfo: infoWithWarningsLinux,
|
||||
expectedGolden: "docker-info-no-swarm",
|
||||
warningsGolden: "docker-info-warnings",
|
||||
},
|
||||
} {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
assert.NoError(t, prettyPrintInfo(cli, tc.dockerInfo))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.expectedGolden+".golden")
|
||||
if tc.warningsGolden != "" {
|
||||
golden.Assert(t, cli.ErrBuffer().String(), tc.warningsGolden+".golden")
|
||||
} else {
|
||||
assert.Equal(t, "", cli.ErrBuffer().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
51
vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-no-swarm.golden
generated
vendored
Normal file
51
vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-no-swarm.golden
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
Containers: 0
|
||||
Running: 0
|
||||
Paused: 0
|
||||
Stopped: 0
|
||||
Images: 0
|
||||
Server Version: 17.06.1-ce
|
||||
Storage Driver: aufs
|
||||
Root Dir: /var/lib/docker/aufs
|
||||
Backing Filesystem: extfs
|
||||
Dirs: 0
|
||||
Dirperm1 Supported: true
|
||||
Logging Driver: json-file
|
||||
Cgroup Driver: cgroupfs
|
||||
Plugins:
|
||||
Volume: local
|
||||
Network: bridge host macvlan null overlay
|
||||
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
|
||||
Swarm: inactive
|
||||
Runtimes: runc
|
||||
Default Runtime: runc
|
||||
Init Binary: docker-init
|
||||
containerd version: 6e23458c129b551d5c9871e5174f6b1b7f6d1170
|
||||
runc version: 810190ceaa507aa2727d7ae6f4790c76ec150bd2
|
||||
init version: 949e6fa
|
||||
Security Options:
|
||||
apparmor
|
||||
seccomp
|
||||
Profile: default
|
||||
Kernel Version: 4.4.0-87-generic
|
||||
Operating System: Ubuntu 16.04.3 LTS
|
||||
OSType: linux
|
||||
Architecture: x86_64
|
||||
CPUs: 2
|
||||
Total Memory: 1.953GiB
|
||||
Name: system-sample
|
||||
ID: EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX
|
||||
Docker Root Dir: /var/lib/docker
|
||||
Debug Mode (client): false
|
||||
Debug Mode (server): true
|
||||
File Descriptors: 33
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
Live Restore Enabled: false
|
||||
|
||||
11
vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-warnings.golden
generated
vendored
Normal file
11
vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-warnings.golden
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
WARNING: No memory limit support
|
||||
WARNING: No swap limit support
|
||||
WARNING: No kernel memory 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
|
||||
73
vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-with-swarm.golden
generated
vendored
Normal file
73
vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-with-swarm.golden
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
Containers: 0
|
||||
Running: 0
|
||||
Paused: 0
|
||||
Stopped: 0
|
||||
Images: 0
|
||||
Server Version: 17.06.1-ce
|
||||
Storage Driver: aufs
|
||||
Root Dir: /var/lib/docker/aufs
|
||||
Backing Filesystem: extfs
|
||||
Dirs: 0
|
||||
Dirperm1 Supported: true
|
||||
Logging Driver: json-file
|
||||
Cgroup Driver: cgroupfs
|
||||
Plugins:
|
||||
Volume: local
|
||||
Network: bridge host macvlan null overlay
|
||||
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
|
||||
Swarm: active
|
||||
NodeID: qo2dfdig9mmxqkawulggepdih
|
||||
Is Manager: true
|
||||
ClusterID: 9vs5ygs0gguyyec4iqf2314c0
|
||||
Managers: 1
|
||||
Nodes: 1
|
||||
Orchestration:
|
||||
Task History Retention Limit: 5
|
||||
Raft:
|
||||
Snapshot Interval: 10000
|
||||
Number of Old Snapshots to Retain: 0
|
||||
Heartbeat Tick: 1
|
||||
Election Tick: 3
|
||||
Dispatcher:
|
||||
Heartbeat Period: 5 seconds
|
||||
CA Configuration:
|
||||
Expiry Duration: 3 months
|
||||
Force Rotate: 0
|
||||
Autolock Managers: true
|
||||
Root Rotation In Progress: false
|
||||
Node Address: 165.227.107.89
|
||||
Manager Addresses:
|
||||
165.227.107.89:2377
|
||||
Runtimes: runc
|
||||
Default Runtime: runc
|
||||
Init Binary: docker-init
|
||||
containerd version: 6e23458c129b551d5c9871e5174f6b1b7f6d1170
|
||||
runc version: 810190ceaa507aa2727d7ae6f4790c76ec150bd2
|
||||
init version: 949e6fa
|
||||
Security Options:
|
||||
apparmor
|
||||
seccomp
|
||||
Profile: default
|
||||
Kernel Version: 4.4.0-87-generic
|
||||
Operating System: Ubuntu 16.04.3 LTS
|
||||
OSType: linux
|
||||
Architecture: x86_64
|
||||
CPUs: 2
|
||||
Total Memory: 1.953GiB
|
||||
Name: system-sample
|
||||
ID: EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX
|
||||
Docker Root Dir: /var/lib/docker
|
||||
Debug Mode (client): false
|
||||
Debug Mode (server): true
|
||||
File Descriptors: 33
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
Live Restore Enabled: false
|
||||
|
||||
4
vendor/github.com/docker/cli/cli/command/trust.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/trust.go
generated
vendored
@@ -12,6 +12,10 @@ var (
|
||||
untrusted bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
untrusted = !getDefaultTrustState()
|
||||
}
|
||||
|
||||
// AddTrustVerificationFlags adds content trust flags to the provided flagset
|
||||
func AddTrustVerificationFlags(fs *pflag.FlagSet) {
|
||||
trusted := getDefaultTrustState()
|
||||
|
||||
40
vendor/github.com/docker/cli/cli/compose/convert/service.go
generated
vendored
40
vendor/github.com/docker/cli/cli/compose/convert/service.go
generated
vendored
@@ -128,7 +128,7 @@ func Service(
|
||||
Labels: AddStackLabel(namespace, service.Deploy.Labels),
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: service.Image,
|
||||
Command: service.Entrypoint,
|
||||
Args: service.Command,
|
||||
@@ -295,7 +295,13 @@ func convertServiceSecrets(
|
||||
})
|
||||
}
|
||||
|
||||
return servicecli.ParseSecrets(client, refs)
|
||||
secrs, err := servicecli.ParseSecrets(client, refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// sort to ensure idempotence (don't restart services just because the entries are in different order)
|
||||
sort.SliceStable(secrs, func(i, j int) bool { return secrs[i].SecretName < secrs[j].SecretName })
|
||||
return secrs, err
|
||||
}
|
||||
|
||||
// TODO: fix configs API so that ConfigsAPIClient is not required here
|
||||
@@ -346,7 +352,13 @@ func convertServiceConfigObjs(
|
||||
})
|
||||
}
|
||||
|
||||
return servicecli.ParseConfigs(client, refs)
|
||||
confs, err := servicecli.ParseConfigs(client, refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// sort to ensure idempotence (don't restart services just because the entries are in different order)
|
||||
sort.SliceStable(confs, func(i, j int) bool { return confs[i].ConfigName < confs[j].ConfigName })
|
||||
return confs, err
|
||||
}
|
||||
|
||||
func uint32Ptr(value uint32) *uint32 {
|
||||
@@ -366,7 +378,6 @@ func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container
|
||||
return nil, nil
|
||||
}
|
||||
var (
|
||||
err error
|
||||
timeout, interval, startPeriod time.Duration
|
||||
retries int
|
||||
)
|
||||
@@ -379,23 +390,14 @@ func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container
|
||||
}, nil
|
||||
|
||||
}
|
||||
if healthcheck.Timeout != "" {
|
||||
timeout, err = time.ParseDuration(healthcheck.Timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if healthcheck.Timeout != nil {
|
||||
timeout = *healthcheck.Timeout
|
||||
}
|
||||
if healthcheck.Interval != "" {
|
||||
interval, err = time.ParseDuration(healthcheck.Interval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if healthcheck.Interval != nil {
|
||||
interval = *healthcheck.Interval
|
||||
}
|
||||
if healthcheck.StartPeriod != "" {
|
||||
startPeriod, err = time.ParseDuration(healthcheck.StartPeriod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if healthcheck.StartPeriod != nil {
|
||||
startPeriod = *healthcheck.StartPeriod
|
||||
}
|
||||
if healthcheck.Retries != nil {
|
||||
retries = int(*healthcheck.Retries)
|
||||
|
||||
10
vendor/github.com/docker/cli/cli/compose/convert/service_test.go
generated
vendored
10
vendor/github.com/docker/cli/cli/compose/convert/service_test.go
generated
vendored
@@ -109,16 +109,18 @@ func TestConvertResourcesOnlyMemory(t *testing.T) {
|
||||
|
||||
func TestConvertHealthcheck(t *testing.T) {
|
||||
retries := uint64(10)
|
||||
timeout := 30 * time.Second
|
||||
interval := 2 * time.Millisecond
|
||||
source := &composetypes.HealthCheckConfig{
|
||||
Test: []string{"EXEC", "touch", "/foo"},
|
||||
Timeout: "30s",
|
||||
Interval: "2ms",
|
||||
Timeout: &timeout,
|
||||
Interval: &interval,
|
||||
Retries: &retries,
|
||||
}
|
||||
expected := &container.HealthConfig{
|
||||
Test: source.Test,
|
||||
Timeout: 30 * time.Second,
|
||||
Interval: 2 * time.Millisecond,
|
||||
Timeout: timeout,
|
||||
Interval: interval,
|
||||
Retries: 10,
|
||||
}
|
||||
|
||||
|
||||
16
vendor/github.com/docker/cli/cli/compose/loader/full-example.yml
generated
vendored
16
vendor/github.com/docker/cli/cli/compose/loader/full-example.yml
generated
vendored
@@ -2,6 +2,21 @@ version: "3.4"
|
||||
|
||||
services:
|
||||
foo:
|
||||
|
||||
build:
|
||||
context: ./dir
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
foo: bar
|
||||
target: foo
|
||||
network: foo
|
||||
cache_from:
|
||||
- foo
|
||||
- bar
|
||||
labels: [FOO=BAR]
|
||||
|
||||
|
||||
|
||||
cap_add:
|
||||
- ALL
|
||||
|
||||
@@ -114,6 +129,7 @@ services:
|
||||
interval: 10s
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
start_period: 15s
|
||||
|
||||
# Any valid image reference - repo, tag, id, sha
|
||||
image: redis
|
||||
|
||||
9
vendor/github.com/docker/cli/cli/compose/loader/loader.go
generated
vendored
9
vendor/github.com/docker/cli/cli/compose/loader/loader.go
generated
vendored
@@ -8,7 +8,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/compose/interpolation"
|
||||
"github.com/docker/cli/cli/compose/schema"
|
||||
"github.com/docker/cli/cli/compose/template"
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
shellwords "github.com/mattn/go-shellwords"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@@ -93,11 +93,7 @@ func Load(configDetails types.ConfigDetails) (*types.Config, error) {
|
||||
}
|
||||
|
||||
cfg.Configs, err = LoadConfigObjs(config["configs"], configDetails.WorkingDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
return &cfg, err
|
||||
}
|
||||
|
||||
func interpolateConfig(configDict map[string]interface{}, lookupEnv template.Mapping) (map[string]map[string]interface{}, error) {
|
||||
@@ -576,7 +572,6 @@ func transformServiceVolumeConfig(data interface{}) (interface{}, error) {
|
||||
default:
|
||||
return data, errors.Errorf("invalid type %T for service volume", value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func transformServiceNetworkMap(value interface{}) (interface{}, error) {
|
||||
|
||||
24
vendor/github.com/docker/cli/cli/compose/loader/loader_test.go
generated
vendored
24
vendor/github.com/docker/cli/cli/compose/loader/loader_test.go
generated
vendored
@@ -517,12 +517,14 @@ version: "3"
|
||||
services:
|
||||
web:
|
||||
image: web
|
||||
build: ./web
|
||||
build:
|
||||
context: ./web
|
||||
links:
|
||||
- bar
|
||||
db:
|
||||
image: db
|
||||
build: ./db
|
||||
build:
|
||||
context: ./db
|
||||
`))
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -686,6 +688,15 @@ func TestFullExample(t *testing.T) {
|
||||
expectedServiceConfig := types.ServiceConfig{
|
||||
Name: "foo",
|
||||
|
||||
Build: types.BuildConfig{
|
||||
Context: "./dir",
|
||||
Dockerfile: "Dockerfile",
|
||||
Args: map[string]*string{"foo": strPtr("bar")},
|
||||
Target: "foo",
|
||||
Network: "foo",
|
||||
CacheFrom: []string{"foo", "bar"},
|
||||
Labels: map[string]string{"FOO": "BAR"},
|
||||
},
|
||||
CapAdd: []string{"ALL"},
|
||||
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
|
||||
CgroupParent: "m-executor-abcd",
|
||||
@@ -756,10 +767,11 @@ func TestFullExample(t *testing.T) {
|
||||
"somehost": "162.242.195.82",
|
||||
},
|
||||
HealthCheck: &types.HealthCheckConfig{
|
||||
Test: types.HealthCheckTest([]string{"CMD-SHELL", "echo \"hello world\""}),
|
||||
Interval: "10s",
|
||||
Timeout: "1s",
|
||||
Retries: uint64Ptr(5),
|
||||
Test: types.HealthCheckTest([]string{"CMD-SHELL", "echo \"hello world\""}),
|
||||
Interval: durationPtr(10 * time.Second),
|
||||
Timeout: durationPtr(1 * time.Second),
|
||||
Retries: uint64Ptr(5),
|
||||
StartPeriod: durationPtr(15 * time.Second),
|
||||
},
|
||||
Hostname: "foo",
|
||||
Image: "redis",
|
||||
|
||||
10
vendor/github.com/docker/cli/cli/compose/loader/volume_test.go
generated
vendored
10
vendor/github.com/docker/cli/cli/compose/loader/volume_test.go
generated
vendored
@@ -200,3 +200,13 @@ func TestParseVolumeSplitCases(t *testing.T) {
|
||||
assert.Equal(t, expected, parsed.Source != "", msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseVolumeInvalidEmptySpec(t *testing.T) {
|
||||
_, err := ParseVolume("")
|
||||
testutil.ErrorContains(t, err, "invalid empty volume spec")
|
||||
}
|
||||
|
||||
func TestParseVolumeInvalidSections(t *testing.T) {
|
||||
_, err := ParseVolume("/foo::rw")
|
||||
testutil.ErrorContains(t, err, "invalid spec")
|
||||
}
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/compose/schema/bindata.go
generated
vendored
2
vendor/github.com/docker/cli/cli/compose/schema/bindata.go
generated
vendored
File diff suppressed because one or more lines are too long
10
vendor/github.com/docker/cli/cli/compose/schema/schema_test.go
generated
vendored
10
vendor/github.com/docker/cli/cli/compose/schema/schema_test.go
generated
vendored
@@ -36,6 +36,16 @@ func TestValidateUndefinedTopLevelOption(t *testing.T) {
|
||||
assert.Contains(t, err.Error(), "Additional property helicopters is not allowed")
|
||||
}
|
||||
|
||||
func TestValidateAllowsXTopLevelFields(t *testing.T) {
|
||||
config := dict{
|
||||
"version": "3.4",
|
||||
"x-extra-stuff": dict{},
|
||||
}
|
||||
|
||||
err := Validate(config, "3.4")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestValidateInvalidVersion(t *testing.T) {
|
||||
config := dict{
|
||||
"version": "2.1",
|
||||
|
||||
20
vendor/github.com/docker/cli/cli/compose/types/types.go
generated
vendored
20
vendor/github.com/docker/cli/cli/compose/types/types.go
generated
vendored
@@ -23,6 +23,7 @@ var UnsupportedProperties = []string{
|
||||
"shm_size",
|
||||
"sysctls",
|
||||
"tmpfs",
|
||||
"ulimits",
|
||||
"userns_mode",
|
||||
}
|
||||
|
||||
@@ -78,6 +79,7 @@ type Config struct {
|
||||
type ServiceConfig struct {
|
||||
Name string
|
||||
|
||||
Build BuildConfig
|
||||
CapAdd []string `mapstructure:"cap_add"`
|
||||
CapDrop []string `mapstructure:"cap_drop"`
|
||||
CgroupParent string `mapstructure:"cgroup_parent"`
|
||||
@@ -125,6 +127,18 @@ type ServiceConfig struct {
|
||||
WorkingDir string `mapstructure:"working_dir"`
|
||||
}
|
||||
|
||||
// BuildConfig is a type for build
|
||||
// using the same format at libcompose: https://github.com/docker/libcompose/blob/master/yaml/build.go#L12
|
||||
type BuildConfig struct {
|
||||
Context string
|
||||
Dockerfile string
|
||||
Args MappingWithEquals
|
||||
Labels Labels
|
||||
CacheFrom StringList `mapstructure:"cache_from"`
|
||||
Network string
|
||||
Target string
|
||||
}
|
||||
|
||||
// ShellCommand is a string or list of string args
|
||||
type ShellCommand []string
|
||||
|
||||
@@ -169,10 +183,10 @@ type DeployConfig struct {
|
||||
// HealthCheckConfig the healthcheck configuration for a service
|
||||
type HealthCheckConfig struct {
|
||||
Test HealthCheckTest
|
||||
Timeout string
|
||||
Interval string
|
||||
Timeout *time.Duration
|
||||
Interval *time.Duration
|
||||
Retries *uint64
|
||||
StartPeriod string
|
||||
StartPeriod *time.Duration `mapstructure:"start_period"`
|
||||
Disable bool
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/debug/debug.go
generated
vendored
2
vendor/github.com/docker/cli/cli/debug/debug.go
generated
vendored
@@ -3,7 +3,7 @@ package debug
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Enable sets the DEBUG env var to true
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/debug/debug_test.go
generated
vendored
2
vendor/github.com/docker/cli/cli/debug/debug_test.go
generated
vendored
@@ -4,7 +4,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func TestEnable(t *testing.T) {
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/flags/common.go
generated
vendored
2
vendor/github.com/docker/cli/cli/flags/common.go
generated
vendored
@@ -5,10 +5,10 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
|
||||
2
vendor/github.com/docker/cli/cli/trust/trust.go
generated
vendored
2
vendor/github.com/docker/cli/cli/trust/trust.go
generated
vendored
@@ -10,7 +10,6 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
@@ -29,6 +28,7 @@ import (
|
||||
"github.com/docker/notary/tuf/data"
|
||||
"github.com/docker/notary/tuf/signed"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
2
vendor/github.com/docker/cli/cmd/docker/docker.go
generated
vendored
2
vendor/github.com/docker/cli/cmd/docker/docker.go
generated
vendored
@@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/commands"
|
||||
@@ -16,6 +15,7 @@ import (
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
2
vendor/github.com/docker/cli/cmd/docker/docker_test.go
generated
vendored
2
vendor/github.com/docker/cli/cmd/docker/docker_test.go
generated
vendored
@@ -5,9 +5,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/debug"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
17
vendor/github.com/docker/cli/contrib/completion/bash/docker
generated
vendored
17
vendor/github.com/docker/cli/contrib/completion/bash/docker
generated
vendored
@@ -441,18 +441,23 @@ __docker_complete_stacks() {
|
||||
# precedence over the environment setting.
|
||||
# Completions may be added with `--add`, e.g. `--add self`.
|
||||
__docker_nodes() {
|
||||
local format
|
||||
if [ "$DOCKER_COMPLETION_SHOW_NODE_IDS" = yes ] ; then
|
||||
format='{{.ID}} {{.Hostname}}'
|
||||
else
|
||||
format='{{.Hostname}}'
|
||||
fi
|
||||
|
||||
local add=()
|
||||
local fields='$2' # default: node name only
|
||||
[ "${DOCKER_COMPLETION_SHOW_NODE_IDS}" = yes ] && fields='$1,$2' # ID and name
|
||||
|
||||
while true ; do
|
||||
case "$1" in
|
||||
--id)
|
||||
fields='$1' # IDs only
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
;;
|
||||
--name)
|
||||
fields='$2' # names only
|
||||
format='{{.Hostname}}'
|
||||
shift
|
||||
;;
|
||||
--add)
|
||||
@@ -465,7 +470,7 @@ __docker_nodes() {
|
||||
esac
|
||||
done
|
||||
|
||||
echo "$(__docker_q node ls "$@" | tr -d '*' | awk "NR>1 {print $fields}")" "${add[@]}"
|
||||
echo "$(__docker_q node ls --format "$format" "$@")" "${add[@]}"
|
||||
}
|
||||
|
||||
# __docker_complete_nodes applies completion of nodes based on the current
|
||||
@@ -1862,7 +1867,7 @@ _docker_container_run_and_create() {
|
||||
__docker_complete_containers_running
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W 'none host private shareable container:' -- "$cur" ) )
|
||||
# shellcheck disable=SC2128
|
||||
if [ "$COMPREPLY" = "container:" ]; then
|
||||
__docker_nospace
|
||||
|
||||
19
vendor/github.com/docker/cli/docker.Makefile
generated
vendored
19
vendor/github.com/docker/cli/docker.Makefile
generated
vendored
@@ -4,10 +4,10 @@
|
||||
# Makefile for developing using Docker
|
||||
#
|
||||
|
||||
DEV_DOCKER_IMAGE_NAME = docker-cli-dev
|
||||
LINTER_IMAGE_NAME = docker-cli-lint
|
||||
CROSS_IMAGE_NAME = docker-cli-cross
|
||||
VALIDATE_IMAGE_NAME = docker-cli-shell-validate
|
||||
DEV_DOCKER_IMAGE_NAME = docker-cli-dev$(IMAGE_TAG)
|
||||
LINTER_IMAGE_NAME = docker-cli-lint$(IMAGE_TAG)
|
||||
CROSS_IMAGE_NAME = docker-cli-cross$(IMAGE_TAG)
|
||||
VALIDATE_IMAGE_NAME = docker-cli-shell-validate$(IMAGE_TAG)
|
||||
MOUNTS = -v "$(CURDIR)":/go/src/github.com/docker/cli
|
||||
VERSION = $(shell cat VERSION)
|
||||
ENVVARS = -e VERSION=$(VERSION) -e GITCOMMIT
|
||||
@@ -42,9 +42,12 @@ clean: build_docker_image
|
||||
docker run --rm $(ENVVARS) $(MOUNTS) $(DEV_DOCKER_IMAGE_NAME) make clean
|
||||
|
||||
# run go test
|
||||
.PHONY: test-unit
|
||||
test-unit: build_docker_image
|
||||
docker run --rm $(ENVVARS) $(MOUNTS) $(DEV_DOCKER_IMAGE_NAME) make test-unit
|
||||
|
||||
.PHONY: test
|
||||
test: build_docker_image
|
||||
docker run --rm $(ENVVARS) $(MOUNTS) $(DEV_DOCKER_IMAGE_NAME) make test
|
||||
test: test-unit test-e2e
|
||||
|
||||
# build the CLI for multiple architectures using a container
|
||||
.PHONY: cross
|
||||
@@ -90,3 +93,7 @@ yamldocs: build_docker_image
|
||||
.PHONY: shellcheck
|
||||
shellcheck: build_shell_validate_image
|
||||
docker run -ti --rm $(ENVVARS) $(MOUNTS) $(VALIDATE_IMAGE_NAME) make shellcheck
|
||||
|
||||
.PHONY: test-e2e
|
||||
test-e2e: binary
|
||||
./scripts/test/e2e/wrapper
|
||||
|
||||
17
vendor/github.com/docker/cli/dockerfiles/Dockerfile.test-e2e-env
generated
vendored
Normal file
17
vendor/github.com/docker/cli/dockerfiles/Dockerfile.test-e2e-env
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM docker/compose:1.15.0
|
||||
|
||||
RUN apk add -U bash curl
|
||||
|
||||
ARG DOCKER_CHANNEL=edge
|
||||
ARG DOCKER_VERSION=17.06.0-ce
|
||||
RUN export URL=https://download.docker.com/linux/static; \
|
||||
curl -Ls $URL/$DOCKER_CHANNEL/x86_64/docker-$DOCKER_VERSION.tgz | \
|
||||
tar -xz docker/docker && \
|
||||
mv docker/docker /usr/local/bin/ && \
|
||||
rmdir docker
|
||||
ENV DISABLE_WARN_OUTSIDE_CONTAINER=1
|
||||
WORKDIR /work
|
||||
COPY scripts/test/e2e scripts/test/e2e
|
||||
COPY e2e/compose-env.yaml e2e/compose-env.yaml
|
||||
|
||||
ENTRYPOINT ["bash", "/work/scripts/test/e2e/run"]
|
||||
4
vendor/github.com/docker/cli/docs/deprecated.md
generated
vendored
4
vendor/github.com/docker/cli/docs/deprecated.md
generated
vendored
@@ -24,7 +24,7 @@ see [Feature Deprecation Policy](https://docs.docker.com/engine/#feature-depreca
|
||||
|
||||
**Deprecated In Release: v17.05.0**
|
||||
|
||||
**Disabled by default in release: v17.09**
|
||||
**Disabled by default in release: [v17.09](https://github.com/docker/docker-ce/releases/tag/v17.09.0-ce)**
|
||||
|
||||
Docker 17.05.0 added an optional `--detach=false` option to make the
|
||||
`docker service create` and `docker service update` work synchronously. This
|
||||
@@ -315,7 +315,7 @@ Since 1.9, Docker Content Trust Offline key has been renamed to Root key and the
|
||||
|
||||
**Deprecated In Release: [v1.6.0](https://github.com/docker/docker/releases/tag/v1.6.0)**
|
||||
|
||||
**Target For Removal In Release: v17.09**
|
||||
**Removed In Release: [v17.09](https://github.com/docker/docker-ce/releases/tag/v17.09.0-ce)**
|
||||
|
||||
The flag `--api-enable-cors` is deprecated since v1.6.0. Use the flag
|
||||
`--api-cors-header` instead.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user