add better generate
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
3fc6abf56b
commit
cdd93563f5
5655 changed files with 1187011 additions and 392 deletions
378
vendor/github.com/docker/docker-ce/components/engine/integration/build/build_test.go
generated
vendored
Normal file
378
vendor/github.com/docker/docker-ce/components/engine/integration/build/build_test.go
generated
vendored
Normal file
|
@ -0,0 +1,378 @@
|
|||
package build // import "github.com/docker/docker/integration/build"
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestBuildWithRemoveAndForceRemove(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
t.Parallel()
|
||||
cases := []struct {
|
||||
name string
|
||||
dockerfile string
|
||||
numberOfIntermediateContainers int
|
||||
rm bool
|
||||
forceRm bool
|
||||
}{
|
||||
{
|
||||
name: "successful build with no removal",
|
||||
dockerfile: `FROM busybox
|
||||
RUN exit 0
|
||||
RUN exit 0`,
|
||||
numberOfIntermediateContainers: 2,
|
||||
rm: false,
|
||||
forceRm: false,
|
||||
},
|
||||
{
|
||||
name: "successful build with remove",
|
||||
dockerfile: `FROM busybox
|
||||
RUN exit 0
|
||||
RUN exit 0`,
|
||||
numberOfIntermediateContainers: 0,
|
||||
rm: true,
|
||||
forceRm: false,
|
||||
},
|
||||
{
|
||||
name: "successful build with remove and force remove",
|
||||
dockerfile: `FROM busybox
|
||||
RUN exit 0
|
||||
RUN exit 0`,
|
||||
numberOfIntermediateContainers: 0,
|
||||
rm: true,
|
||||
forceRm: true,
|
||||
},
|
||||
{
|
||||
name: "failed build with no removal",
|
||||
dockerfile: `FROM busybox
|
||||
RUN exit 0
|
||||
RUN exit 1`,
|
||||
numberOfIntermediateContainers: 2,
|
||||
rm: false,
|
||||
forceRm: false,
|
||||
},
|
||||
{
|
||||
name: "failed build with remove",
|
||||
dockerfile: `FROM busybox
|
||||
RUN exit 0
|
||||
RUN exit 1`,
|
||||
numberOfIntermediateContainers: 1,
|
||||
rm: true,
|
||||
forceRm: false,
|
||||
},
|
||||
{
|
||||
name: "failed build with remove and force remove",
|
||||
dockerfile: `FROM busybox
|
||||
RUN exit 0
|
||||
RUN exit 1`,
|
||||
numberOfIntermediateContainers: 0,
|
||||
rm: true,
|
||||
forceRm: true,
|
||||
},
|
||||
}
|
||||
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dockerfile := []byte(c.dockerfile)
|
||||
|
||||
buff := bytes.NewBuffer(nil)
|
||||
tw := tar.NewWriter(buff)
|
||||
assert.NilError(t, tw.WriteHeader(&tar.Header{
|
||||
Name: "Dockerfile",
|
||||
Size: int64(len(dockerfile)),
|
||||
}))
|
||||
_, err := tw.Write(dockerfile)
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, tw.Close())
|
||||
resp, err := client.ImageBuild(ctx, buff, types.ImageBuildOptions{Remove: c.rm, ForceRemove: c.forceRm, NoCache: true})
|
||||
assert.NilError(t, err)
|
||||
defer resp.Body.Close()
|
||||
filter, err := buildContainerIdsFilter(resp.Body)
|
||||
assert.NilError(t, err)
|
||||
remainingContainers, err := client.ContainerList(ctx, types.ContainerListOptions{Filters: filter, All: true})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, c.numberOfIntermediateContainers, len(remainingContainers), "Expected %v remaining intermediate containers, got %v", c.numberOfIntermediateContainers, len(remainingContainers))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func buildContainerIdsFilter(buildOutput io.Reader) (filters.Args, error) {
|
||||
const intermediateContainerPrefix = " ---> Running in "
|
||||
filter := filters.NewArgs()
|
||||
|
||||
dec := json.NewDecoder(buildOutput)
|
||||
for {
|
||||
m := jsonmessage.JSONMessage{}
|
||||
err := dec.Decode(&m)
|
||||
if err == io.EOF {
|
||||
return filter, nil
|
||||
}
|
||||
if err != nil {
|
||||
return filter, err
|
||||
}
|
||||
if ix := strings.Index(m.Stream, intermediateContainerPrefix); ix != -1 {
|
||||
filter.Add("id", strings.TrimSpace(m.Stream[ix+len(intermediateContainerPrefix):]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildMultiStageParentConfig(t *testing.T) {
|
||||
dockerfile := `
|
||||
FROM busybox AS stage0
|
||||
ENV WHO=parent
|
||||
WORKDIR /foo
|
||||
|
||||
FROM stage0
|
||||
ENV WHO=sibling1
|
||||
WORKDIR sub1
|
||||
|
||||
FROM stage0
|
||||
WORKDIR sub2
|
||||
`
|
||||
ctx := context.Background()
|
||||
source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile))
|
||||
defer source.Close()
|
||||
|
||||
apiclient := testEnv.APIClient()
|
||||
resp, err := apiclient.ImageBuild(ctx,
|
||||
source.AsTarReader(t),
|
||||
types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
Tags: []string{"build1"},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(ioutil.Discard, resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NilError(t, err)
|
||||
|
||||
image, _, err := apiclient.ImageInspectWithRaw(ctx, "build1")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Equal("/foo/sub2", image.Config.WorkingDir))
|
||||
assert.Check(t, is.Contains(image.Config.Env, "WHO=parent"))
|
||||
}
|
||||
|
||||
func TestBuildWithEmptyLayers(t *testing.T) {
|
||||
dockerfile := `
|
||||
FROM busybox
|
||||
COPY 1/ /target/
|
||||
COPY 2/ /target/
|
||||
COPY 3/ /target/
|
||||
`
|
||||
ctx := context.Background()
|
||||
source := fakecontext.New(t, "",
|
||||
fakecontext.WithDockerfile(dockerfile),
|
||||
fakecontext.WithFile("1/a", "asdf"),
|
||||
fakecontext.WithFile("2/a", "asdf"),
|
||||
fakecontext.WithFile("3/a", "asdf"))
|
||||
defer source.Close()
|
||||
|
||||
apiclient := testEnv.APIClient()
|
||||
resp, err := apiclient.ImageBuild(ctx,
|
||||
source.AsTarReader(t),
|
||||
types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(ioutil.Discard, resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
// TestBuildMultiStageOnBuild checks that ONBUILD commands are applied to
|
||||
// multiple subsequent stages
|
||||
// #35652
|
||||
func TestBuildMultiStageOnBuild(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
// test both metadata and layer based commands as they may be implemented differently
|
||||
dockerfile := `FROM busybox AS stage1
|
||||
ONBUILD RUN echo 'foo' >somefile
|
||||
ONBUILD ENV bar=baz
|
||||
|
||||
FROM stage1
|
||||
RUN cat somefile # fails if ONBUILD RUN fails
|
||||
|
||||
FROM stage1
|
||||
RUN cat somefile`
|
||||
|
||||
ctx := context.Background()
|
||||
source := fakecontext.New(t, "",
|
||||
fakecontext.WithDockerfile(dockerfile))
|
||||
defer source.Close()
|
||||
|
||||
apiclient := testEnv.APIClient()
|
||||
resp, err := apiclient.ImageBuild(ctx,
|
||||
source.AsTarReader(t),
|
||||
types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
})
|
||||
|
||||
out := bytes.NewBuffer(nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Contains(out.String(), "Successfully built"))
|
||||
|
||||
imageIDs, err := getImageIDsFromBuild(out.Bytes())
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(3, len(imageIDs)))
|
||||
|
||||
image, _, err := apiclient.ImageInspectWithRaw(context.Background(), imageIDs[2])
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(image.Config.Env, "bar=baz"))
|
||||
}
|
||||
|
||||
// #35403 #36122
|
||||
func TestBuildUncleanTarFilenames(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
defer setupTest(t)()
|
||||
|
||||
dockerfile := `FROM scratch
|
||||
COPY foo /
|
||||
FROM scratch
|
||||
COPY bar /`
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
w := tar.NewWriter(buf)
|
||||
writeTarRecord(t, w, "Dockerfile", dockerfile)
|
||||
writeTarRecord(t, w, "../foo", "foocontents0")
|
||||
writeTarRecord(t, w, "/bar", "barcontents0")
|
||||
err := w.Close()
|
||||
assert.NilError(t, err)
|
||||
|
||||
apiclient := testEnv.APIClient()
|
||||
resp, err := apiclient.ImageBuild(ctx,
|
||||
buf,
|
||||
types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
})
|
||||
|
||||
out := bytes.NewBuffer(nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// repeat with changed data should not cause cache hits
|
||||
|
||||
buf = bytes.NewBuffer(nil)
|
||||
w = tar.NewWriter(buf)
|
||||
writeTarRecord(t, w, "Dockerfile", dockerfile)
|
||||
writeTarRecord(t, w, "../foo", "foocontents1")
|
||||
writeTarRecord(t, w, "/bar", "barcontents1")
|
||||
err = w.Close()
|
||||
assert.NilError(t, err)
|
||||
|
||||
resp, err = apiclient.ImageBuild(ctx,
|
||||
buf,
|
||||
types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
})
|
||||
|
||||
out = bytes.NewBuffer(nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, !strings.Contains(out.String(), "Using cache"))
|
||||
}
|
||||
|
||||
// docker/for-linux#135
|
||||
// #35641
|
||||
func TestBuildMultiStageLayerLeak(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
defer setupTest(t)()
|
||||
|
||||
// all commands need to match until COPY
|
||||
dockerfile := `FROM busybox
|
||||
WORKDIR /foo
|
||||
COPY foo .
|
||||
FROM busybox
|
||||
WORKDIR /foo
|
||||
COPY bar .
|
||||
RUN [ -f bar ]
|
||||
RUN [ ! -f foo ]
|
||||
`
|
||||
|
||||
source := fakecontext.New(t, "",
|
||||
fakecontext.WithFile("foo", "0"),
|
||||
fakecontext.WithFile("bar", "1"),
|
||||
fakecontext.WithDockerfile(dockerfile))
|
||||
defer source.Close()
|
||||
|
||||
apiclient := testEnv.APIClient()
|
||||
resp, err := apiclient.ImageBuild(ctx,
|
||||
source.AsTarReader(t),
|
||||
types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
})
|
||||
|
||||
out := bytes.NewBuffer(nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Contains(out.String(), "Successfully built"))
|
||||
}
|
||||
|
||||
func writeTarRecord(t *testing.T, w *tar.Writer, fn, contents string) {
|
||||
err := w.WriteHeader(&tar.Header{
|
||||
Name: fn,
|
||||
Mode: 0600,
|
||||
Size: int64(len(contents)),
|
||||
Typeflag: '0',
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
_, err = w.Write([]byte(contents))
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
type buildLine struct {
|
||||
Stream string
|
||||
Aux struct {
|
||||
ID string
|
||||
}
|
||||
}
|
||||
|
||||
func getImageIDsFromBuild(output []byte) ([]string, error) {
|
||||
ids := []string{}
|
||||
for _, line := range bytes.Split(output, []byte("\n")) {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
entry := buildLine{}
|
||||
if err := json.Unmarshal(line, &entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entry.Aux.ID != "" {
|
||||
ids = append(ids, entry.Aux.ID)
|
||||
}
|
||||
}
|
||||
return ids, nil
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/build/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/build/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package build // import "github.com/docker/docker/integration/build"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
354
vendor/github.com/docker/docker-ce/components/engine/integration/config/config_test.go
generated
vendored
Normal file
354
vendor/github.com/docker/docker-ce/components/engine/integration/config/config_test.go
generated
vendored
Normal file
|
@ -0,0 +1,354 @@
|
|||
package config // import "github.com/docker/docker/integration/config"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/swarm"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestConfigList(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// This test case is ported from the original TestConfigsEmptyList
|
||||
configs, err := client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(configs), 0))
|
||||
|
||||
testName0 := "test0"
|
||||
testName1 := "test1"
|
||||
testNames := []string{testName0, testName1}
|
||||
sort.Strings(testNames)
|
||||
|
||||
// create config test0
|
||||
createConfig(ctx, t, client, testName0, []byte("TESTINGDATA0"), map[string]string{"type": "test"})
|
||||
|
||||
config1ID := createConfig(ctx, t, client, testName1, []byte("TESTINGDATA1"), map[string]string{"type": "production"})
|
||||
|
||||
names := func(entries []swarmtypes.Config) []string {
|
||||
values := []string{}
|
||||
for _, entry := range entries {
|
||||
values = append(values, entry.Spec.Name)
|
||||
}
|
||||
sort.Strings(values)
|
||||
return values
|
||||
}
|
||||
|
||||
// test by `config ls`
|
||||
entries, err := client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(names(entries), testNames))
|
||||
|
||||
testCases := []struct {
|
||||
filters filters.Args
|
||||
expected []string
|
||||
}{
|
||||
// test filter by name `config ls --filter name=xxx`
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("name", testName0)),
|
||||
expected: []string{testName0},
|
||||
},
|
||||
// test filter by id `config ls --filter id=xxx`
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("id", config1ID)),
|
||||
expected: []string{testName1},
|
||||
},
|
||||
// test filter by label `config ls --filter label=xxx`
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("label", "type")),
|
||||
expected: testNames,
|
||||
},
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("label", "type=test")),
|
||||
expected: []string{testName0},
|
||||
},
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("label", "type=production")),
|
||||
expected: []string{testName1},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
entries, err = client.ConfigList(ctx, types.ConfigListOptions{
|
||||
Filters: tc.filters,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(names(entries), tc.expected))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func createConfig(ctx context.Context, t *testing.T, client client.APIClient, name string, data []byte, labels map[string]string) string {
|
||||
config, err := client.ConfigCreate(ctx, swarmtypes.ConfigSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: name,
|
||||
Labels: labels,
|
||||
},
|
||||
Data: data,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, config.ID != "")
|
||||
return config.ID
|
||||
}
|
||||
|
||||
func TestConfigsCreateAndDelete(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_config"
|
||||
|
||||
// This test case is ported from the original TestConfigsCreate
|
||||
configID := createConfig(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
insp, _, err := client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Name, testName))
|
||||
|
||||
// This test case is ported from the original TestConfigsDelete
|
||||
err = client.ConfigRemove(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.ConfigInspectWithRaw(ctx, configID)
|
||||
testutil.ErrorContains(t, err, "No such config")
|
||||
}
|
||||
|
||||
func TestConfigsUpdate(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_config"
|
||||
|
||||
// This test case is ported from the original TestConfigsCreate
|
||||
configID := createConfig(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
insp, _, err := client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.ID, configID))
|
||||
|
||||
// test UpdateConfig with full ID
|
||||
insp.Spec.Labels = map[string]string{"test": "test1"}
|
||||
err = client.ConfigUpdate(ctx, configID, insp.Version, insp.Spec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test1"))
|
||||
|
||||
// test UpdateConfig with full name
|
||||
insp.Spec.Labels = map[string]string{"test": "test2"}
|
||||
err = client.ConfigUpdate(ctx, testName, insp.Version, insp.Spec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test2"))
|
||||
|
||||
// test UpdateConfig with prefix ID
|
||||
insp.Spec.Labels = map[string]string{"test": "test3"}
|
||||
err = client.ConfigUpdate(ctx, configID[:1], insp.Version, insp.Spec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test3"))
|
||||
|
||||
// test UpdateConfig in updating Data which is not supported in daemon
|
||||
// this test will produce an error in func UpdateConfig
|
||||
insp.Spec.Data = []byte("TESTINGDATA2")
|
||||
err = client.ConfigUpdate(ctx, configID, insp.Version, insp.Spec)
|
||||
testutil.ErrorContains(t, err, "only updates to Labels are allowed")
|
||||
}
|
||||
|
||||
func TestTemplatedConfig(t *testing.T) {
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
|
||||
ctx := context.Background()
|
||||
client := swarm.GetClient(t, d)
|
||||
|
||||
referencedSecretSpec := swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "referencedsecret",
|
||||
},
|
||||
Data: []byte("this is a secret"),
|
||||
}
|
||||
referencedSecret, err := client.SecretCreate(ctx, referencedSecretSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
referencedConfigSpec := swarmtypes.ConfigSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "referencedconfig",
|
||||
},
|
||||
Data: []byte("this is a config"),
|
||||
}
|
||||
referencedConfig, err := client.ConfigCreate(ctx, referencedConfigSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
configSpec := swarmtypes.ConfigSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "templated_config",
|
||||
},
|
||||
Templating: &swarmtypes.Driver{
|
||||
Name: "golang",
|
||||
},
|
||||
Data: []byte("SERVICE_NAME={{.Service.Name}}\n" +
|
||||
"{{secret \"referencedsecrettarget\"}}\n" +
|
||||
"{{config \"referencedconfigtarget\"}}\n"),
|
||||
}
|
||||
|
||||
templatedConfig, err := client.ConfigCreate(ctx, configSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
serviceID := swarm.CreateService(t, d,
|
||||
swarm.ServiceWithConfig(
|
||||
&swarmtypes.ConfigReference{
|
||||
File: &swarmtypes.ConfigReferenceFileTarget{
|
||||
Name: "/templated_config",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0600,
|
||||
},
|
||||
ConfigID: templatedConfig.ID,
|
||||
ConfigName: "templated_config",
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithConfig(
|
||||
&swarmtypes.ConfigReference{
|
||||
File: &swarmtypes.ConfigReferenceFileTarget{
|
||||
Name: "referencedconfigtarget",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0600,
|
||||
},
|
||||
ConfigID: referencedConfig.ID,
|
||||
ConfigName: "referencedconfig",
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithSecret(
|
||||
&swarmtypes.SecretReference{
|
||||
File: &swarmtypes.SecretReferenceFileTarget{
|
||||
Name: "referencedsecrettarget",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0600,
|
||||
},
|
||||
SecretID: referencedSecret.ID,
|
||||
SecretName: "referencedsecret",
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithName("svc"),
|
||||
)
|
||||
|
||||
var tasks []swarmtypes.Task
|
||||
waitAndAssert(t, 60*time.Second, func(t *testing.T) bool {
|
||||
tasks = swarm.GetRunningTasks(t, d, serviceID)
|
||||
return len(tasks) > 0
|
||||
})
|
||||
|
||||
task := tasks[0]
|
||||
waitAndAssert(t, 60*time.Second, func(t *testing.T) bool {
|
||||
if task.NodeID == "" || (task.Status.ContainerStatus == nil || task.Status.ContainerStatus.ContainerID == "") {
|
||||
task, _, _ = client.TaskInspectWithRaw(context.Background(), task.ID)
|
||||
}
|
||||
return task.NodeID != "" && task.Status.ContainerStatus != nil && task.Status.ContainerStatus.ContainerID != ""
|
||||
})
|
||||
|
||||
attach := swarm.ExecTask(t, d, task, types.ExecConfig{
|
||||
Cmd: []string{"/bin/cat", "/templated_config"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
})
|
||||
|
||||
expect := "SERVICE_NAME=svc\n" +
|
||||
"this is a secret\n" +
|
||||
"this is a config\n"
|
||||
assertAttachedStream(t, attach, expect)
|
||||
|
||||
attach = swarm.ExecTask(t, d, task, types.ExecConfig{
|
||||
Cmd: []string{"mount"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
})
|
||||
assertAttachedStream(t, attach, "tmpfs on /templated_config type tmpfs")
|
||||
}
|
||||
|
||||
func assertAttachedStream(t *testing.T, attach types.HijackedResponse, expect string) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_, err := stdcopy.StdCopy(buf, buf, attach.Reader)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(buf.String(), expect))
|
||||
}
|
||||
|
||||
func waitAndAssert(t *testing.T, timeout time.Duration, f func(*testing.T) bool) {
|
||||
t.Helper()
|
||||
after := time.After(timeout)
|
||||
for {
|
||||
select {
|
||||
case <-after:
|
||||
t.Fatalf("timed out waiting for condition")
|
||||
default:
|
||||
}
|
||||
if f(t) {
|
||||
return
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigInspect(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := t.Name()
|
||||
configID := createConfig(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
insp, body, err := client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Name, testName))
|
||||
|
||||
var config swarmtypes.Config
|
||||
err = json.Unmarshal(body, &config)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(config, insp))
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/config/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/config/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package config // import "github.com/docker/docker/integration/config"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
66
vendor/github.com/docker/docker-ce/components/engine/integration/container/copy_test.go
generated
vendored
Normal file
66
vendor/github.com/docker/docker-ce/components/engine/integration/container/copy_test.go
generated
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestCopyFromContainerPathDoesNotExist(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
|
||||
ctx := context.Background()
|
||||
apiclient := testEnv.APIClient()
|
||||
cid := container.Create(t, ctx, apiclient)
|
||||
|
||||
_, _, err := apiclient.CopyFromContainer(ctx, cid, "/dne")
|
||||
assert.Assert(t, client.IsErrNotFound(err))
|
||||
expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne")
|
||||
testutil.ErrorContains(t, err, expected)
|
||||
}
|
||||
|
||||
func TestCopyFromContainerPathIsNotDir(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
skip.If(t, testEnv.OSType == "windows")
|
||||
|
||||
ctx := context.Background()
|
||||
apiclient := testEnv.APIClient()
|
||||
cid := container.Create(t, ctx, apiclient)
|
||||
|
||||
_, _, err := apiclient.CopyFromContainer(ctx, cid, "/etc/passwd/")
|
||||
assert.Assert(t, is.Contains(err.Error(), "not a directory"))
|
||||
}
|
||||
|
||||
func TestCopyToContainerPathDoesNotExist(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
skip.If(t, testEnv.OSType == "windows")
|
||||
|
||||
ctx := context.Background()
|
||||
apiclient := testEnv.APIClient()
|
||||
cid := container.Create(t, ctx, apiclient)
|
||||
|
||||
err := apiclient.CopyToContainer(ctx, cid, "/dne", nil, types.CopyToContainerOptions{})
|
||||
assert.Assert(t, client.IsErrNotFound(err))
|
||||
expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne")
|
||||
testutil.ErrorContains(t, err, expected)
|
||||
}
|
||||
|
||||
func TestCopyToContainerPathIsNotDir(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
skip.If(t, testEnv.OSType == "windows")
|
||||
|
||||
ctx := context.Background()
|
||||
apiclient := testEnv.APIClient()
|
||||
cid := container.Create(t, ctx, apiclient)
|
||||
|
||||
err := apiclient.CopyToContainer(ctx, cid, "/etc/passwd/", nil, types.CopyToContainerOptions{})
|
||||
assert.Assert(t, is.Contains(err.Error(), "not a directory"))
|
||||
}
|
138
vendor/github.com/docker/docker-ce/components/engine/integration/container/create_test.go
generated
vendored
Normal file
138
vendor/github.com/docker/docker-ce/components/engine/integration/container/create_test.go
generated
vendored
Normal file
|
@ -0,0 +1,138 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
testCases := []struct {
|
||||
doc string
|
||||
image string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
doc: "image and tag",
|
||||
image: "test456:v1",
|
||||
expectedError: "No such image: test456:v1",
|
||||
},
|
||||
{
|
||||
doc: "image no tag",
|
||||
image: "test456",
|
||||
expectedError: "No such image: test456",
|
||||
},
|
||||
{
|
||||
doc: "digest",
|
||||
image: "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
|
||||
expectedError: "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := client.ContainerCreate(context.Background(),
|
||||
&container.Config{Image: tc.image},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{},
|
||||
"foo",
|
||||
)
|
||||
testutil.ErrorContains(t, err, tc.expectedError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateWithInvalidEnv(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
testCases := []struct {
|
||||
env string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
env: "",
|
||||
expectedError: "invalid environment variable:",
|
||||
},
|
||||
{
|
||||
env: "=",
|
||||
expectedError: "invalid environment variable: =",
|
||||
},
|
||||
{
|
||||
env: "=foo",
|
||||
expectedError: "invalid environment variable: =foo",
|
||||
},
|
||||
}
|
||||
|
||||
for index, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(strconv.Itoa(index), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := client.ContainerCreate(context.Background(),
|
||||
&container.Config{
|
||||
Image: "busybox",
|
||||
Env: []string{tc.env},
|
||||
},
|
||||
&container.HostConfig{},
|
||||
&network.NetworkingConfig{},
|
||||
"foo",
|
||||
)
|
||||
testutil.ErrorContains(t, err, tc.expectedError)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test case for #30166 (target was not validated)
|
||||
func TestCreateTmpfsMountsTarget(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
testCases := []struct {
|
||||
target string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
target: ".",
|
||||
expectedError: "mount path must be absolute",
|
||||
},
|
||||
{
|
||||
target: "foo",
|
||||
expectedError: "mount path must be absolute",
|
||||
},
|
||||
{
|
||||
target: "/",
|
||||
expectedError: "destination can't be '/'",
|
||||
},
|
||||
{
|
||||
target: "//",
|
||||
expectedError: "destination can't be '/'",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
_, err := client.ContainerCreate(context.Background(),
|
||||
&container.Config{
|
||||
Image: "busybox",
|
||||
},
|
||||
&container.HostConfig{
|
||||
Tmpfs: map[string]string{tc.target: ""},
|
||||
},
|
||||
&network.NetworkingConfig{},
|
||||
"",
|
||||
)
|
||||
testutil.ErrorContains(t, err, tc.expectedError)
|
||||
}
|
||||
}
|
78
vendor/github.com/docker/docker-ce/components/engine/integration/container/daemon_linux_test.go
generated
vendored
Normal file
78
vendor/github.com/docker/docker-ce/components/engine/integration/container/daemon_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// This is a regression test for #36145
|
||||
// It ensures that a container can be started when the daemon was improperly
|
||||
// shutdown when the daemon is brought back up.
|
||||
//
|
||||
// The regression is due to improper error handling preventing a container from
|
||||
// being restored and as such have the resources cleaned up.
|
||||
//
|
||||
// To test this, we need to kill dockerd, then kill both the containerd-shim and
|
||||
// the container process, then start dockerd back up and attempt to start the
|
||||
// container again.
|
||||
func TestContainerStartOnDaemonRestart(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon(), "cannot start daemon on remote test run")
|
||||
t.Parallel()
|
||||
|
||||
d := daemon.New(t, "", "dockerd", daemon.Config{})
|
||||
d.StartWithBusybox(t, "--iptables=false")
|
||||
defer d.Stop(t)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.Check(t, err, "error creating client")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Create(t, ctx, client)
|
||||
defer client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
|
||||
|
||||
err = client.ContainerStart(ctx, cID, types.ContainerStartOptions{})
|
||||
assert.Check(t, err, "error starting test container")
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.Check(t, err, "error getting inspect data")
|
||||
|
||||
ppid := getContainerdShimPid(t, inspect)
|
||||
|
||||
err = d.Kill()
|
||||
assert.Check(t, err, "failed to kill test daemon")
|
||||
|
||||
err = unix.Kill(inspect.State.Pid, unix.SIGKILL)
|
||||
assert.Check(t, err, "failed to kill container process")
|
||||
|
||||
err = unix.Kill(ppid, unix.SIGKILL)
|
||||
assert.Check(t, err, "failed to kill containerd-shim")
|
||||
|
||||
d.Start(t, "--iptables=false")
|
||||
|
||||
err = client.ContainerStart(ctx, cID, types.ContainerStartOptions{})
|
||||
assert.Check(t, err, "failed to start test container")
|
||||
}
|
||||
|
||||
func getContainerdShimPid(t *testing.T, c types.ContainerJSON) int {
|
||||
statB, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", c.State.Pid))
|
||||
assert.Check(t, err, "error looking up containerd-shim pid")
|
||||
|
||||
// ppid is the 4th entry in `/proc/pid/stat`
|
||||
ppid, err := strconv.Atoi(strings.Fields(string(statB))[3])
|
||||
assert.Check(t, err, "error converting ppid field to int")
|
||||
|
||||
assert.Check(t, ppid != 1, "got unexpected ppid")
|
||||
return ppid
|
||||
}
|
42
vendor/github.com/docker/docker-ce/components/engine/integration/container/diff_test.go
generated
vendored
Normal file
42
vendor/github.com/docker/docker-ce/components/engine/integration/container/diff_test.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
)
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", `mkdir /foo; echo xyzzy > /foo/bar`))
|
||||
|
||||
// Wait for it to exit as cannot diff a running container on Windows, and
|
||||
// it will take a few seconds to exit. Also there's no way in Windows to
|
||||
// differentiate between an Add or a Modify, and all files are under
|
||||
// a "Files/" prefix.
|
||||
expected := []containertypes.ContainerChangeResponseItem{
|
||||
{Kind: archive.ChangeAdd, Path: "/foo"},
|
||||
{Kind: archive.ChangeAdd, Path: "/foo/bar"},
|
||||
}
|
||||
if testEnv.OSType == "windows" {
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(60*time.Second))
|
||||
expected = []containertypes.ContainerChangeResponseItem{
|
||||
{Kind: archive.ChangeModify, Path: "Files/foo"},
|
||||
{Kind: archive.ChangeModify, Path: "Files/foo/bar"},
|
||||
}
|
||||
}
|
||||
|
||||
items, err := client.ContainerDiff(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, expected, items)
|
||||
}
|
47
vendor/github.com/docker/docker-ce/components/engine/integration/container/exec_test.go
generated
vendored
Normal file
47
vendor/github.com/docker/docker-ce/components/engine/integration/container/exec_test.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithTty(true), container.WithWorkingDir("/root"))
|
||||
|
||||
id, err := client.ContainerExecCreate(ctx, cID,
|
||||
types.ExecConfig{
|
||||
WorkingDir: "/tmp",
|
||||
Env: strslice.StrSlice([]string{"FOO=BAR"}),
|
||||
AttachStdout: true,
|
||||
Cmd: strslice.StrSlice([]string{"sh", "-c", "env"}),
|
||||
},
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
resp, err := client.ContainerExecAttach(ctx, id.ID,
|
||||
types.ExecStartCheck{
|
||||
Detach: false,
|
||||
Tty: false,
|
||||
},
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
defer resp.Close()
|
||||
r, err := ioutil.ReadAll(resp.Reader)
|
||||
assert.NilError(t, err)
|
||||
out := string(r)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Contains(out, "PWD=/tmp"), "exec command not running in expected /tmp working directory")
|
||||
assert.Assert(t, is.Contains(out, "FOO=BAR"), "exec command not running with expected environment variable FOO")
|
||||
}
|
84
vendor/github.com/docker/docker-ce/components/engine/integration/container/export_test.go
generated
vendored
Normal file
84
vendor/github.com/docker/docker-ce/components/engine/integration/container/export_test.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
containerTypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
// export an image and try to import it into a new one
|
||||
func TestExportContainerAndImportImage(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("true"))
|
||||
poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
reference := "repo/testexp:v1"
|
||||
exportResp, err := client.ContainerExport(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
importResp, err := client.ImageImport(ctx, types.ImageImportSource{
|
||||
Source: exportResp,
|
||||
SourceName: "-",
|
||||
}, reference, types.ImageImportOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// If the import is successfully, then the message output should contain
|
||||
// the image ID and match with the output from `docker images`.
|
||||
|
||||
dec := json.NewDecoder(importResp)
|
||||
var jm jsonmessage.JSONMessage
|
||||
err = dec.Decode(&jm)
|
||||
assert.NilError(t, err)
|
||||
|
||||
images, err := client.ImageList(ctx, types.ImageListOptions{
|
||||
Filters: filters.NewArgs(filters.Arg("reference", reference)),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(jm.Status, images[0].ID))
|
||||
}
|
||||
|
||||
// TestExportContainerAfterDaemonRestart checks that a container
|
||||
// created before start of the currently running dockerd
|
||||
// can be exported (as reported in #36561). To satisfy this
|
||||
// condition, daemon restart is needed after container creation.
|
||||
func TestExportContainerAfterDaemonRestart(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
d := daemon.New(t, "", "dockerd", daemon.Config{})
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
d.StartWithBusybox(t)
|
||||
defer d.Stop(t)
|
||||
|
||||
ctx := context.Background()
|
||||
cfg := containerTypes.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"top"},
|
||||
}
|
||||
ctr, err := client.ContainerCreate(ctx, &cfg, nil, nil, "")
|
||||
assert.NilError(t, err)
|
||||
|
||||
d.Restart(t)
|
||||
|
||||
_, err = client.ContainerExport(ctx, ctr.ID)
|
||||
assert.NilError(t, err)
|
||||
}
|
47
vendor/github.com/docker/docker-ce/components/engine/integration/container/health_test.go
generated
vendored
Normal file
47
vendor/github.com/docker/docker-ce/components/engine/integration/container/health_test.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
)
|
||||
|
||||
// TestHealthCheckWorkdir verifies that health-checks inherit the containers'
|
||||
// working-dir.
|
||||
func TestHealthCheckWorkdir(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithTty(true), container.WithWorkingDir("/foo"), func(c *container.TestContainerConfig) {
|
||||
c.Config.Healthcheck = &containertypes.HealthConfig{
|
||||
Test: []string{"CMD-SHELL", "if [ \"$PWD\" = \"/foo\" ]; then exit 0; else exit 1; fi;"},
|
||||
Interval: 50 * time.Millisecond,
|
||||
Retries: 3,
|
||||
}
|
||||
})
|
||||
|
||||
poll.WaitOn(t, pollForHealthStatus(ctx, client, cID, types.Healthy), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
|
||||
func pollForHealthStatus(ctx context.Context, client client.APIClient, containerID string, healthStatus string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
inspect, err := client.ContainerInspect(ctx, containerID)
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case inspect.State.Health.Status == healthStatus:
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("waiting for container to become %s", healthStatus)
|
||||
}
|
||||
}
|
||||
}
|
48
vendor/github.com/docker/docker-ce/components/engine/integration/container/inspect_test.go
generated
vendored
Normal file
48
vendor/github.com/docker/docker-ce/components/engine/integration/container/inspect_test.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestInspectCpusetInConfigPre120(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux" || !testEnv.DaemonInfo.CPUSet)
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t, client.WithVersion("1.19"))
|
||||
ctx := context.Background()
|
||||
|
||||
name := "cpusetinconfig-pre120"
|
||||
// Create container with up to-date-API
|
||||
container.Run(t, ctx, request.NewAPIClient(t), container.WithName(name),
|
||||
container.WithCmd("true"),
|
||||
func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.Resources.CpusetCpus = "0"
|
||||
},
|
||||
)
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, name, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
_, body, err := client.ContainerInspectWithRaw(ctx, name, false)
|
||||
assert.NilError(t, err)
|
||||
|
||||
var inspectJSON map[string]interface{}
|
||||
err = json.Unmarshal(body, &inspectJSON)
|
||||
assert.NilError(t, err, "unable to unmarshal body for version 1.19: %s", err)
|
||||
|
||||
config, ok := inspectJSON["Config"]
|
||||
assert.Check(t, is.Equal(true, ok), "Unable to find 'Config'")
|
||||
|
||||
cfg := config.(map[string]interface{})
|
||||
_, ok = cfg["Cpuset"]
|
||||
assert.Check(t, is.Equal(true, ok), "API version 1.19 expected to include Cpuset in 'Config'")
|
||||
}
|
183
vendor/github.com/docker/docker-ce/components/engine/integration/container/kill_test.go
generated
vendored
Normal file
183
vendor/github.com/docker/docker-ce/components/engine/integration/container/kill_test.go
generated
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestKillContainerInvalidSignal(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
id := container.Run(t, ctx, client)
|
||||
|
||||
err := client.ContainerKill(ctx, id, "0")
|
||||
assert.Error(t, err, "Error response from daemon: Invalid signal: 0")
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err = client.ContainerKill(ctx, id, "SIG42")
|
||||
assert.Error(t, err, "Error response from daemon: Invalid signal: SIG42")
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
|
||||
func TestKillContainer(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
testCases := []struct {
|
||||
doc string
|
||||
signal string
|
||||
status string
|
||||
}{
|
||||
{
|
||||
doc: "no signal",
|
||||
signal: "",
|
||||
status: "exited",
|
||||
},
|
||||
{
|
||||
doc: "non killing signal",
|
||||
signal: "SIGWINCH",
|
||||
status: "running",
|
||||
},
|
||||
{
|
||||
doc: "killing signal",
|
||||
signal: "SIGTERM",
|
||||
status: "exited",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
id := container.Run(t, ctx, client)
|
||||
err := client.ContainerKill(ctx, id, tc.signal)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKillWithStopSignalAndRestartPolicies(t *testing.T) {
|
||||
skip.If(t, testEnv.OSType != "linux", "Windows only supports 1.25 or later")
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
testCases := []struct {
|
||||
doc string
|
||||
stopsignal string
|
||||
status string
|
||||
}{
|
||||
{
|
||||
doc: "same-signal-disables-restart-policy",
|
||||
stopsignal: "TERM",
|
||||
status: "exited",
|
||||
},
|
||||
{
|
||||
doc: "different-signal-keep-restart-policy",
|
||||
stopsignal: "CONT",
|
||||
status: "running",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
id := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.Config.StopSignal = tc.stopsignal
|
||||
c.HostConfig.RestartPolicy = containertypes.RestartPolicy{
|
||||
Name: "always",
|
||||
}
|
||||
})
|
||||
err := client.ContainerKill(ctx, id, "TERM")
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, id, tc.status), poll.WithDelay(100*time.Millisecond))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKillStoppedContainer(t *testing.T) {
|
||||
skip.If(t, testEnv.OSType != "linux") // Windows only supports 1.25 or later
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
id := container.Create(t, ctx, client)
|
||||
err := client.ContainerKill(ctx, id, "SIGKILL")
|
||||
assert.Assert(t, is.ErrorContains(err, ""))
|
||||
assert.Assert(t, is.Contains(err.Error(), "is not running"))
|
||||
}
|
||||
|
||||
func TestKillStoppedContainerAPIPre120(t *testing.T) {
|
||||
skip.If(t, testEnv.OSType != "linux") // Windows only supports 1.25 or later
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t, client.WithVersion("1.19"))
|
||||
id := container.Create(t, ctx, client)
|
||||
err := client.ContainerKill(ctx, id, "SIGKILL")
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestKillDifferentUserContainer(t *testing.T) {
|
||||
// TODO Windows: Windows does not yet support -u (Feb 2016).
|
||||
skip.If(t, testEnv.OSType != "linux", "User containers (container.Config.User) are not yet supported on %q platform", testEnv.OSType)
|
||||
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t, client.WithVersion("1.19"))
|
||||
|
||||
id := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.Config.User = "daemon"
|
||||
})
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerKill(ctx, id, "SIGKILL")
|
||||
assert.NilError(t, err)
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, id, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
|
||||
func TestInspectOomKilledTrue(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux" || !testEnv.DaemonInfo.MemoryLimit || !testEnv.DaemonInfo.SwapLimit)
|
||||
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", "x=a; while true; do x=$x$x$x$x; done"), func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.Resources.Memory = 32 * 1024 * 1024
|
||||
})
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(true, inspect.State.OOMKilled))
|
||||
}
|
||||
|
||||
func TestInspectOomKilledFalse(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux" || !testEnv.DaemonInfo.MemoryLimit || !testEnv.DaemonInfo.SwapLimit)
|
||||
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", "echo hello world"))
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(false, inspect.State.OOMKilled))
|
||||
}
|
55
vendor/github.com/docker/docker-ce/components/engine/integration/container/links_linux_test.go
generated
vendored
Normal file
55
vendor/github.com/docker/docker-ce/components/engine/integration/container/links_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestLinksEtcHostsContentMatch(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
hosts, err := ioutil.ReadFile("/etc/hosts")
|
||||
skip.If(t, os.IsNotExist(err))
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithNetworkMode("host"))
|
||||
res, err := container.Exec(ctx, client, cID, []string{"cat", "/etc/hosts"})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Len(res.Stderr(), 0))
|
||||
assert.Equal(t, 0, res.ExitCode)
|
||||
|
||||
assert.Check(t, is.Equal(string(hosts), res.Stdout()))
|
||||
}
|
||||
|
||||
func TestLinksContainerNames(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
container.Run(t, ctx, client, container.WithName("first"))
|
||||
container.Run(t, ctx, client, container.WithName("second"), container.WithLinks("first:first"))
|
||||
|
||||
f := filters.NewArgs(filters.Arg("name", "first"))
|
||||
|
||||
containers, err := client.ContainerList(ctx, types.ContainerListOptions{
|
||||
Filters: f,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(1, len(containers)))
|
||||
assert.Check(t, is.DeepEqual([]string{"/first", "/second/first"}, containers[0].Names))
|
||||
}
|
32
vendor/github.com/docker/docker-ce/components/engine/integration/container/logs_test.go
generated
vendored
Normal file
32
vendor/github.com/docker/docker-ce/components/engine/integration/container/logs_test.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
// Regression test for #35370
|
||||
// Makes sure that when following we don't get an EOF error when there are no logs
|
||||
func TestLogsFollowTailEmpty(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
id := container.Run(t, ctx, client, container.WithCmd("sleep", "100000"))
|
||||
|
||||
logs, err := client.ContainerLogs(ctx, id, types.ContainerLogsOptions{ShowStdout: true, Tail: "2"})
|
||||
if logs != nil {
|
||||
defer logs.Close()
|
||||
}
|
||||
assert.Check(t, err)
|
||||
|
||||
_, err = stdcopy.StdCopy(ioutil.Discard, ioutil.Discard, logs)
|
||||
assert.Check(t, err)
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/container/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/container/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
281
vendor/github.com/docker/docker-ce/components/engine/integration/container/mounts_linux_test.go
generated
vendored
Normal file
281
vendor/github.com/docker/docker-ce/components/engine/integration/container/mounts_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,281 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/fs"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestContainerShmNoLeak(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon(), "cannot start daemon on remote test run")
|
||||
t.Parallel()
|
||||
d := daemon.New(t, "docker", "dockerd", daemon.Config{})
|
||||
client, err := d.NewClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d.StartWithBusybox(t, "--iptables=false")
|
||||
defer d.Stop(t)
|
||||
|
||||
ctx := context.Background()
|
||||
cfg := container.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"top"},
|
||||
}
|
||||
|
||||
ctr, err := client.ContainerCreate(ctx, &cfg, nil, nil, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer client.ContainerRemove(ctx, ctr.ID, types.ContainerRemoveOptions{Force: true})
|
||||
|
||||
if err := client.ContainerStart(ctx, ctr.ID, types.ContainerStartOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// this should recursively bind mount everything in the test daemons root
|
||||
// except of course we are hoping that the previous containers /dev/shm mount did not leak into this new container
|
||||
hc := container.HostConfig{
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: mount.TypeBind,
|
||||
Source: d.Root,
|
||||
Target: "/testdaemonroot",
|
||||
},
|
||||
},
|
||||
}
|
||||
cfg.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("mount | grep testdaemonroot | grep containers | grep %s", ctr.ID)}
|
||||
cfg.AttachStdout = true
|
||||
cfg.AttachStderr = true
|
||||
ctrLeak, err := client.ContainerCreate(ctx, &cfg, &hc, nil, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
attach, err := client.ContainerAttach(ctx, ctrLeak.ID, types.ContainerAttachOptions{
|
||||
Stream: true,
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := client.ContainerStart(ctx, ctrLeak.ID, types.ContainerStartOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
if _, err := stdcopy.StdCopy(buf, buf, attach.Reader); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
out := bytes.TrimSpace(buf.Bytes())
|
||||
if !bytes.Equal(out, []byte{}) {
|
||||
t.Fatalf("mount leaked: %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerNetworkMountsNoChown(t *testing.T) {
|
||||
// chown only applies to Linux bind mounted volumes; must be same host to verify
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux" || testEnv.IsRemoteDaemon())
|
||||
|
||||
defer setupTest(t)()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
tmpDir := fs.NewDir(t, "network-file-mounts", fs.WithMode(0755), fs.WithFile("nwfile", "network file bind mount", fs.WithMode(0644)))
|
||||
defer tmpDir.Remove()
|
||||
|
||||
tmpNWFileMount := tmpDir.Join("nwfile")
|
||||
|
||||
config := container.Config{
|
||||
Image: "busybox",
|
||||
}
|
||||
hostConfig := container.HostConfig{
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: "bind",
|
||||
Source: tmpNWFileMount,
|
||||
Target: "/etc/resolv.conf",
|
||||
},
|
||||
{
|
||||
Type: "bind",
|
||||
Source: tmpNWFileMount,
|
||||
Target: "/etc/hostname",
|
||||
},
|
||||
{
|
||||
Type: "bind",
|
||||
Source: tmpNWFileMount,
|
||||
Target: "/etc/hosts",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cli, err := client.NewEnvClient()
|
||||
assert.NilError(t, err)
|
||||
defer cli.Close()
|
||||
|
||||
ctrCreate, err := cli.ContainerCreate(ctx, &config, &hostConfig, &network.NetworkingConfig{}, "")
|
||||
assert.NilError(t, err)
|
||||
// container will exit immediately because of no tty, but we only need the start sequence to test the condition
|
||||
err = cli.ContainerStart(ctx, ctrCreate.ID, types.ContainerStartOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Check that host-located bind mount network file did not change ownership when the container was started
|
||||
// Note: If the user specifies a mountpath from the host, we should not be
|
||||
// attempting to chown files outside the daemon's metadata directory
|
||||
// (represented by `daemon.repository` at init time).
|
||||
// This forces users who want to use user namespaces to handle the
|
||||
// ownership needs of any external files mounted as network files
|
||||
// (/etc/resolv.conf, /etc/hosts, /etc/hostname) separately from the
|
||||
// daemon. In all other volume/bind mount situations we have taken this
|
||||
// same line--we don't chown host file content.
|
||||
// See GitHub PR 34224 for details.
|
||||
statT, err := system.Stat(tmpNWFileMount)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(uint32(0), statT.UID()), "bind mounted network file should not change ownership from root")
|
||||
}
|
||||
|
||||
func TestMountDaemonRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
info, err := client.Info(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, test := range []struct {
|
||||
desc string
|
||||
propagation mount.Propagation
|
||||
expected mount.Propagation
|
||||
}{
|
||||
{
|
||||
desc: "default",
|
||||
propagation: "",
|
||||
expected: mount.PropagationRSlave,
|
||||
},
|
||||
{
|
||||
desc: "private",
|
||||
propagation: mount.PropagationPrivate,
|
||||
},
|
||||
{
|
||||
desc: "rprivate",
|
||||
propagation: mount.PropagationRPrivate,
|
||||
},
|
||||
{
|
||||
desc: "slave",
|
||||
propagation: mount.PropagationSlave,
|
||||
},
|
||||
{
|
||||
desc: "rslave",
|
||||
propagation: mount.PropagationRSlave,
|
||||
expected: mount.PropagationRSlave,
|
||||
},
|
||||
{
|
||||
desc: "shared",
|
||||
propagation: mount.PropagationShared,
|
||||
},
|
||||
{
|
||||
desc: "rshared",
|
||||
propagation: mount.PropagationRShared,
|
||||
expected: mount.PropagationRShared,
|
||||
},
|
||||
} {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
test := test
|
||||
t.Parallel()
|
||||
|
||||
propagationSpec := fmt.Sprintf(":%s", test.propagation)
|
||||
if test.propagation == "" {
|
||||
propagationSpec = ""
|
||||
}
|
||||
bindSpecRoot := info.DockerRootDir + ":" + "/foo" + propagationSpec
|
||||
bindSpecSub := filepath.Join(info.DockerRootDir, "containers") + ":/foo" + propagationSpec
|
||||
|
||||
for name, hc := range map[string]*container.HostConfig{
|
||||
"bind root": {Binds: []string{bindSpecRoot}},
|
||||
"bind subpath": {Binds: []string{bindSpecSub}},
|
||||
"mount root": {
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: mount.TypeBind,
|
||||
Source: info.DockerRootDir,
|
||||
Target: "/foo",
|
||||
BindOptions: &mount.BindOptions{Propagation: test.propagation},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mount subpath": {
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: mount.TypeBind,
|
||||
Source: filepath.Join(info.DockerRootDir, "containers"),
|
||||
Target: "/foo",
|
||||
BindOptions: &mount.BindOptions{Propagation: test.propagation},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
hc := hc
|
||||
t.Parallel()
|
||||
|
||||
c, err := client.ContainerCreate(ctx, &container.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"true"},
|
||||
}, hc, nil, "")
|
||||
|
||||
if err != nil {
|
||||
if test.expected != "" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// expected an error, so this is ok and should not continue
|
||||
return
|
||||
}
|
||||
if test.expected == "" {
|
||||
t.Fatal("expected create to fail")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := client.ContainerRemove(ctx, c.ID, types.ContainerRemoveOptions{Force: true}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, c.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(inspect.Mounts) != 1 {
|
||||
t.Fatalf("unexpected number of mounts: %+v", inspect.Mounts)
|
||||
}
|
||||
|
||||
m := inspect.Mounts[0]
|
||||
if m.Propagation != test.expected {
|
||||
t.Fatalf("got unexpected propagation mode, expected %q, got: %v", test.expected, m.Propagation)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
118
vendor/github.com/docker/docker-ce/components/engine/integration/container/nat_test.go
generated
vendored
Normal file
118
vendor/github.com/docker/docker-ce/components/engine/integration/container/nat_test.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestNetworkNat(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
defer setupTest(t)()
|
||||
|
||||
msg := "it works"
|
||||
startServerContainer(t, msg, 8080)
|
||||
|
||||
endpoint := getExternalAddress(t)
|
||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", endpoint.String(), 8080))
|
||||
assert.NilError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(conn)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(msg, strings.TrimSpace(string(data))))
|
||||
}
|
||||
|
||||
func TestNetworkLocalhostTCPNat(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
defer setupTest(t)()
|
||||
|
||||
msg := "hi yall"
|
||||
startServerContainer(t, msg, 8081)
|
||||
|
||||
conn, err := net.Dial("tcp", "localhost:8081")
|
||||
assert.NilError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(conn)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(msg, strings.TrimSpace(string(data))))
|
||||
}
|
||||
|
||||
func TestNetworkLoopbackNat(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
msg := "it works"
|
||||
startServerContainer(t, msg, 8080)
|
||||
|
||||
endpoint := getExternalAddress(t)
|
||||
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", fmt.Sprintf("stty raw && nc -w 5 %s 8080", endpoint.String())), container.WithTty(true), container.WithNetworkMode("container:server"))
|
||||
|
||||
poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
body, err := client.ContainerLogs(ctx, cID, types.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
defer body.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
_, err = io.Copy(&b, body)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Equal(msg, strings.TrimSpace(b.String())))
|
||||
}
|
||||
|
||||
func startServerContainer(t *testing.T, msg string, port int) string {
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithName("server"), container.WithCmd("sh", "-c", fmt.Sprintf("echo %q | nc -lp %d", msg, port)), container.WithExposedPorts(fmt.Sprintf("%d/tcp", port)), func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.PortBindings = nat.PortMap{
|
||||
nat.Port(fmt.Sprintf("%d/tcp", port)): []nat.PortBinding{
|
||||
{
|
||||
HostPort: fmt.Sprintf("%d", port),
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
return cID
|
||||
}
|
||||
|
||||
func getExternalAddress(t *testing.T) net.IP {
|
||||
iface, err := net.InterfaceByName("eth0")
|
||||
skip.If(t, err != nil, "Test not running with `make test-integration`. Interface eth0 not found: %s", err)
|
||||
|
||||
ifaceAddrs, err := iface.Addrs()
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, 0 != len(ifaceAddrs))
|
||||
|
||||
ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String())
|
||||
assert.NilError(t, err)
|
||||
|
||||
return ifaceIP
|
||||
}
|
97
vendor/github.com/docker/docker-ce/components/engine/integration/container/pause_test.go
generated
vendored
Normal file
97
vendor/github.com/docker/docker-ce/components/engine/integration/container/pause_test.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestPause(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows" && testEnv.DaemonInfo.Isolation == "process")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
since := request.DaemonUnixTime(ctx, t, client, testEnv)
|
||||
|
||||
err := client.ContainerPause(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(true, inspect.State.Paused))
|
||||
|
||||
err = client.ContainerUnpause(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
until := request.DaemonUnixTime(ctx, t, client, testEnv)
|
||||
|
||||
messages, errs := client.Events(ctx, types.EventsOptions{
|
||||
Since: since,
|
||||
Until: until,
|
||||
Filters: filters.NewArgs(filters.Arg("container", cID)),
|
||||
})
|
||||
assert.Check(t, is.DeepEqual([]string{"pause", "unpause"}, getEventActions(t, messages, errs)))
|
||||
}
|
||||
|
||||
func TestPauseFailsOnWindowsServerContainers(t *testing.T) {
|
||||
skip.If(t, (testEnv.DaemonInfo.OSType != "windows" || testEnv.DaemonInfo.Isolation != "process"))
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerPause(ctx, cID)
|
||||
testutil.ErrorContains(t, err, "cannot pause Windows Server Containers")
|
||||
}
|
||||
|
||||
func TestPauseStopPausedContainer(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerPause(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ContainerStop(ctx, cID, nil)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
|
||||
func getEventActions(t *testing.T, messages <-chan events.Message, errs <-chan error) []string {
|
||||
actions := []string{}
|
||||
for {
|
||||
select {
|
||||
case err := <-errs:
|
||||
assert.Check(t, err == nil || err == io.EOF)
|
||||
return actions
|
||||
case e := <-messages:
|
||||
actions = append(actions, e.Status)
|
||||
}
|
||||
}
|
||||
}
|
49
vendor/github.com/docker/docker-ce/components/engine/integration/container/ps_test.go
generated
vendored
Normal file
49
vendor/github.com/docker/docker-ce/components/engine/integration/container/ps_test.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestPsFilter(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
prev := container.Create(t, ctx, client, container.WithName("prev"))
|
||||
container.Create(t, ctx, client, container.WithName("top"))
|
||||
next := container.Create(t, ctx, client, container.WithName("next"))
|
||||
|
||||
containerIDs := func(containers []types.Container) []string {
|
||||
entries := []string{}
|
||||
for _, container := range containers {
|
||||
entries = append(entries, container.ID)
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
f1 := filters.NewArgs()
|
||||
f1.Add("since", "top")
|
||||
q1, err := client.ContainerList(ctx, types.ContainerListOptions{
|
||||
All: true,
|
||||
Filters: f1,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(containerIDs(q1), next))
|
||||
|
||||
f2 := filters.NewArgs()
|
||||
f2.Add("before", "top")
|
||||
q2, err := client.ContainerList(ctx, types.ContainerListOptions{
|
||||
All: true,
|
||||
Filters: f2,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(containerIDs(q2), prev))
|
||||
}
|
113
vendor/github.com/docker/docker-ce/components/engine/integration/container/remove_test.go
generated
vendored
Normal file
113
vendor/github.com/docker/docker-ce/components/engine/integration/container/remove_test.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/fs"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
|
||||
if testEnv.OSType == "windows" {
|
||||
return "c:", `\`
|
||||
}
|
||||
return "", "/"
|
||||
}
|
||||
|
||||
// Test case for #5244: `docker rm` fails if bind dir doesn't exist anymore
|
||||
func TestRemoveContainerWithRemovedVolume(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
|
||||
|
||||
tempDir := fs.NewDir(t, "test-rm-container-with-removed-volume", fs.WithMode(0755))
|
||||
defer tempDir.Remove()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("true"), container.WithBind(tempDir.Path(), prefix+slash+"test"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := os.RemoveAll(tempDir.Path())
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, _, err = client.ContainerInspectWithRaw(ctx, cID, true)
|
||||
testutil.ErrorContains(t, err, "No such container")
|
||||
}
|
||||
|
||||
// Test case for #2099/#2125
|
||||
func TestRemoveContainerWithVolume(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("true"), container.WithVolume(prefix+slash+"srv"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
insp, _, err := client.ContainerInspectWithRaw(ctx, cID, true)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(1, len(insp.Mounts)))
|
||||
volName := insp.Mounts[0].Name
|
||||
|
||||
err = client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
volumes, err := client.VolumeList(ctx, filters.NewArgs(filters.Arg("name", volName)))
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(0, len(volumes.Volumes)))
|
||||
}
|
||||
|
||||
func TestRemoveContainerRunning(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
err := client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{})
|
||||
testutil.ErrorContains(t, err, "cannot remove a running container")
|
||||
}
|
||||
|
||||
func TestRemoveContainerForceRemoveRunning(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
err := client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{
|
||||
Force: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestRemoveInvalidContainer(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
err := client.ContainerRemove(ctx, "unknown", types.ContainerRemoveOptions{})
|
||||
testutil.ErrorContains(t, err, "No such container")
|
||||
}
|
200
vendor/github.com/docker/docker-ce/components/engine/integration/container/rename_test.go
generated
vendored
Normal file
200
vendor/github.com/docker/docker-ce/components/engine/integration/container/rename_test.go
generated
vendored
Normal file
|
@ -0,0 +1,200 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
// This test simulates the scenario mentioned in #31392:
|
||||
// Having two linked container, renaming the target and bringing a replacement
|
||||
// and then deleting and recreating the source container linked to the new target.
|
||||
// This checks that "rename" updates source container correctly and doesn't set it to null.
|
||||
func TestRenameLinkedContainer(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
aID := container.Run(t, ctx, client, container.WithName("a0"))
|
||||
bID := container.Run(t, ctx, client, container.WithName("b0"), container.WithLinks("a0"))
|
||||
|
||||
err := client.ContainerRename(ctx, aID, "a1")
|
||||
assert.NilError(t, err)
|
||||
|
||||
container.Run(t, ctx, client, container.WithName("a0"))
|
||||
|
||||
err = client.ContainerRemove(ctx, bID, types.ContainerRemoveOptions{Force: true})
|
||||
assert.NilError(t, err)
|
||||
|
||||
bID = container.Run(t, ctx, client, container.WithName("b0"), container.WithLinks("a0"))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, bID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual([]string{"/a0:/b0/a0"}, inspect.HostConfig.Links))
|
||||
}
|
||||
|
||||
func TestRenameStoppedContainer(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
oldName := "first_name"
|
||||
cID := container.Run(t, ctx, client, container.WithName(oldName), container.WithCmd("sh"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("/"+oldName, inspect.Name))
|
||||
|
||||
newName := "new_name" + stringid.GenerateNonCryptoID()
|
||||
err = client.ContainerRename(ctx, oldName, newName)
|
||||
assert.NilError(t, err)
|
||||
|
||||
inspect, err = client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("/"+newName, inspect.Name))
|
||||
}
|
||||
|
||||
func TestRenameRunningContainerAndReuse(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
oldName := "first_name"
|
||||
cID := container.Run(t, ctx, client, container.WithName(oldName))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
newName := "new_name" + stringid.GenerateNonCryptoID()
|
||||
err := client.ContainerRename(ctx, oldName, newName)
|
||||
assert.NilError(t, err)
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("/"+newName, inspect.Name))
|
||||
|
||||
_, err = client.ContainerInspect(ctx, oldName)
|
||||
testutil.ErrorContains(t, err, "No such container: "+oldName)
|
||||
|
||||
cID = container.Run(t, ctx, client, container.WithName(oldName))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err = client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("/"+oldName, inspect.Name))
|
||||
}
|
||||
|
||||
func TestRenameInvalidName(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
oldName := "first_name"
|
||||
cID := container.Run(t, ctx, client, container.WithName(oldName))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerRename(ctx, oldName, "new:invalid")
|
||||
testutil.ErrorContains(t, err, "Invalid container name")
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, oldName)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(cID, inspect.ID))
|
||||
}
|
||||
|
||||
// Test case for GitHub issue 22466
|
||||
// Docker's service discovery works for named containers so
|
||||
// ping to a named container should work, and an anonymous
|
||||
// container without a name does not work with service discovery.
|
||||
// However, an anonymous could be renamed to a named container.
|
||||
// This test is to make sure once the container has been renamed,
|
||||
// the service discovery for the (re)named container works.
|
||||
func TestRenameAnonymousContainer(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
_, err := client.NetworkCreate(ctx, "network1", types.NetworkCreate{})
|
||||
assert.NilError(t, err)
|
||||
cID := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.NetworkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
|
||||
"network1": {},
|
||||
}
|
||||
c.HostConfig.NetworkMode = "network1"
|
||||
})
|
||||
err = client.ContainerRename(ctx, cID, "container1")
|
||||
assert.NilError(t, err)
|
||||
// Stop/Start the container to get registered
|
||||
// FIXME(vdemeester) this is a really weird behavior as it fails otherwise
|
||||
err = client.ContainerStop(ctx, "container1", nil)
|
||||
assert.NilError(t, err)
|
||||
err = client.ContainerStart(ctx, "container1", types.ContainerStartOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
count := "-c"
|
||||
if testEnv.OSType == "windows" {
|
||||
count = "-n"
|
||||
}
|
||||
cID = container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.NetworkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
|
||||
"network1": {},
|
||||
}
|
||||
c.HostConfig.NetworkMode = "network1"
|
||||
}, container.WithCmd("ping", count, "1", "container1"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(0, inspect.State.ExitCode), "container %s exited with the wrong exitcode: %+v", cID, inspect)
|
||||
}
|
||||
|
||||
// TODO: should be a unit test
|
||||
func TestRenameContainerWithSameName(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithName("old"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
err := client.ContainerRename(ctx, "old", "old")
|
||||
testutil.ErrorContains(t, err, "Renaming a container with the same name")
|
||||
err = client.ContainerRename(ctx, cID, "old")
|
||||
testutil.ErrorContains(t, err, "Renaming a container with the same name")
|
||||
}
|
||||
|
||||
// Test case for GitHub issue 23973
|
||||
// When a container is being renamed, the container might
|
||||
// be linked to another container. In that case, the meta data
|
||||
// of the linked container should be updated so that the other
|
||||
// container could still reference to the container that is renamed.
|
||||
func TestRenameContainerWithLinkedContainer(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
db1ID := container.Run(t, ctx, client, container.WithName("db1"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, db1ID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
app1ID := container.Run(t, ctx, client, container.WithName("app1"), container.WithLinks("db1:/mysql"))
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, app1ID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerRename(ctx, "app1", "app2")
|
||||
assert.NilError(t, err)
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, "app2/mysql")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(db1ID, inspect.ID))
|
||||
}
|
64
vendor/github.com/docker/docker-ce/components/engine/integration/container/resize_test.go
generated
vendored
Normal file
64
vendor/github.com/docker/docker-ce/components/engine/integration/container/resize_test.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
req "github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
)
|
||||
|
||||
func TestResize(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerResize(ctx, cID, types.ResizeOptions{
|
||||
Height: 40,
|
||||
Width: 40,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestResizeWithInvalidSize(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
endpoint := "/containers/" + cID + "/resize?h=foo&w=bar"
|
||||
res, _, err := req.Post(endpoint)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(http.StatusBadRequest, res.StatusCode))
|
||||
}
|
||||
|
||||
func TestResizeWhenContainerNotStarted(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("echo"))
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
err := client.ContainerResize(ctx, cID, types.ResizeOptions{
|
||||
Height: 40,
|
||||
Width: 40,
|
||||
})
|
||||
testutil.ErrorContains(t, err, "is not running")
|
||||
}
|
114
vendor/github.com/docker/docker-ce/components/engine/integration/container/restart_test.go
generated
vendored
Normal file
114
vendor/github.com/docker/docker-ce/components/engine/integration/container/restart_test.go
generated
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestDaemonRestartKillContainers(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon(), "cannot start daemon on remote test run")
|
||||
type testCase struct {
|
||||
desc string
|
||||
config *container.Config
|
||||
hostConfig *container.HostConfig
|
||||
|
||||
xRunning bool
|
||||
xRunningLiveRestore bool
|
||||
}
|
||||
|
||||
for _, c := range []testCase{
|
||||
{
|
||||
desc: "container without restart policy",
|
||||
config: &container.Config{Image: "busybox", Cmd: []string{"top"}},
|
||||
xRunningLiveRestore: true,
|
||||
},
|
||||
{
|
||||
desc: "container with restart=always",
|
||||
config: &container.Config{Image: "busybox", Cmd: []string{"top"}},
|
||||
hostConfig: &container.HostConfig{RestartPolicy: container.RestartPolicy{Name: "always"}},
|
||||
xRunning: true,
|
||||
xRunningLiveRestore: true,
|
||||
},
|
||||
} {
|
||||
for _, liveRestoreEnabled := range []bool{false, true} {
|
||||
for fnName, stopDaemon := range map[string]func(*testing.T, *daemon.Daemon){
|
||||
"kill-daemon": func(t *testing.T, d *daemon.Daemon) {
|
||||
if err := d.Kill(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
},
|
||||
"stop-daemon": func(t *testing.T, d *daemon.Daemon) {
|
||||
d.Stop(t)
|
||||
},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("live-restore=%v/%s/%s", liveRestoreEnabled, c.desc, fnName), func(t *testing.T) {
|
||||
c := c
|
||||
liveRestoreEnabled := liveRestoreEnabled
|
||||
stopDaemon := stopDaemon
|
||||
|
||||
t.Parallel()
|
||||
|
||||
d := daemon.New(t, "", "dockerd", daemon.Config{})
|
||||
client, err := d.NewClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
args := []string{"--iptables=false"}
|
||||
if liveRestoreEnabled {
|
||||
args = append(args, "--live-restore")
|
||||
}
|
||||
|
||||
d.StartWithBusybox(t, args...)
|
||||
defer d.Stop(t)
|
||||
ctx := context.Background()
|
||||
|
||||
resp, err := client.ContainerCreate(ctx, c.config, c.hostConfig, nil, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer client.ContainerRemove(ctx, resp.ID, types.ContainerRemoveOptions{Force: true})
|
||||
|
||||
if err := client.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stopDaemon(t, d)
|
||||
d.Start(t, args...)
|
||||
|
||||
expected := c.xRunning
|
||||
if liveRestoreEnabled {
|
||||
expected = c.xRunningLiveRestore
|
||||
}
|
||||
|
||||
var running bool
|
||||
for i := 0; i < 30; i++ {
|
||||
inspect, err := client.ContainerInspect(ctx, resp.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
running = inspect.State.Running
|
||||
if running == expected {
|
||||
break
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
}
|
||||
|
||||
if running != expected {
|
||||
t.Fatalf("got unexpected running state, expected %v, got: %v", expected, running)
|
||||
}
|
||||
// TODO(cpuguy83): test pause states... this seems to be rather undefined currently
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
vendor/github.com/docker/docker-ce/components/engine/integration/container/stats_test.go
generated
vendored
Normal file
43
vendor/github.com/docker/docker-ce/components/engine/integration/container/stats_test.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestStats(t *testing.T) {
|
||||
skip.If(t, !testEnv.DaemonInfo.MemoryLimit)
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
info, err := client.Info(ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
resp, err := client.ContainerStats(ctx, cID, false)
|
||||
assert.NilError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var v *types.Stats
|
||||
err = json.NewDecoder(resp.Body).Decode(&v)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(int64(v.MemoryStats.Limit), info.MemTotal))
|
||||
err = json.NewDecoder(resp.Body).Decode(&v)
|
||||
assert.Assert(t, is.ErrorContains(err, ""), io.EOF)
|
||||
}
|
71
vendor/github.com/docker/docker-ce/components/engine/integration/container/stop_test.go
generated
vendored
Normal file
71
vendor/github.com/docker/docker-ce/components/engine/integration/container/stop_test.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/icmd"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestStopContainerWithRestartPolicyAlways(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
names := []string{"verifyRestart1", "verifyRestart2"}
|
||||
for _, name := range names {
|
||||
container.Run(t, ctx, client, container.WithName(name), container.WithCmd("false"), func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.RestartPolicy.Name = "always"
|
||||
})
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, name, "running", "restarting"), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
err := client.ContainerStop(ctx, name, nil)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
poll.WaitOn(t, container.IsStopped(ctx, client, name), poll.WithDelay(100*time.Millisecond))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteDevicemapper(t *testing.T) {
|
||||
skip.IfCondition(t, testEnv.DaemonInfo.Driver != "devicemapper")
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
id := container.Run(t, ctx, client, container.WithName("foo"), container.WithCmd("echo"))
|
||||
|
||||
poll.WaitOn(t, container.IsStopped(ctx, client, id), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, id)
|
||||
assert.NilError(t, err)
|
||||
|
||||
deviceID := inspect.GraphDriver.Data["DeviceId"]
|
||||
|
||||
// Find pool name from device name
|
||||
deviceName := inspect.GraphDriver.Data["DeviceName"]
|
||||
devicePrefix := deviceName[:strings.LastIndex(deviceName, "-")]
|
||||
devicePool := fmt.Sprintf("/dev/mapper/%s-pool", devicePrefix)
|
||||
|
||||
result := icmd.RunCommand("dmsetup", "message", devicePool, "0", fmt.Sprintf("delete %s", deviceID))
|
||||
result.Assert(t, icmd.Success)
|
||||
|
||||
err = client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{})
|
||||
assert.NilError(t, err)
|
||||
}
|
107
vendor/github.com/docker/docker-ce/components/engine/integration/container/update_linux_test.go
generated
vendored
Normal file
107
vendor/github.com/docker/docker-ce/components/engine/integration/container/update_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestUpdateMemory(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
skip.If(t, !testEnv.DaemonInfo.MemoryLimit)
|
||||
skip.If(t, !testEnv.DaemonInfo.SwapLimit)
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.Resources = containertypes.Resources{
|
||||
Memory: 200 * 1024 * 1024,
|
||||
}
|
||||
})
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
const (
|
||||
setMemory int64 = 314572800
|
||||
setMemorySwap int64 = 524288000
|
||||
)
|
||||
|
||||
_, err := client.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{
|
||||
Resources: containertypes.Resources{
|
||||
Memory: setMemory,
|
||||
MemorySwap: setMemorySwap,
|
||||
},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(setMemory, inspect.HostConfig.Memory))
|
||||
assert.Check(t, is.Equal(setMemorySwap, inspect.HostConfig.MemorySwap))
|
||||
|
||||
res, err := container.Exec(ctx, client, cID,
|
||||
[]string{"cat", "/sys/fs/cgroup/memory/memory.limit_in_bytes"})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Len(res.Stderr(), 0))
|
||||
assert.Equal(t, 0, res.ExitCode)
|
||||
assert.Check(t, is.Equal(strconv.FormatInt(setMemory, 10), strings.TrimSpace(res.Stdout())))
|
||||
|
||||
res, err = container.Exec(ctx, client, cID,
|
||||
[]string{"cat", "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Len(res.Stderr(), 0))
|
||||
assert.Equal(t, 0, res.ExitCode)
|
||||
assert.Check(t, is.Equal(strconv.FormatInt(setMemorySwap, 10), strings.TrimSpace(res.Stdout())))
|
||||
}
|
||||
|
||||
func TestUpdateCPUQuota(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
for _, test := range []struct {
|
||||
desc string
|
||||
update int64
|
||||
}{
|
||||
{desc: "some random value", update: 15000},
|
||||
{desc: "a higher value", update: 20000},
|
||||
{desc: "a lower value", update: 10000},
|
||||
{desc: "unset value", update: -1},
|
||||
} {
|
||||
if _, err := client.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{
|
||||
Resources: containertypes.Resources{
|
||||
CPUQuota: test.update,
|
||||
},
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(test.update, inspect.HostConfig.CPUQuota))
|
||||
|
||||
res, err := container.Exec(ctx, client, cID,
|
||||
[]string{"/bin/cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Len(res.Stderr(), 0))
|
||||
assert.Equal(t, 0, res.ExitCode)
|
||||
|
||||
assert.Check(t, is.Equal(strconv.FormatInt(test.update, 10), strings.TrimSpace(res.Stdout())))
|
||||
}
|
||||
}
|
65
vendor/github.com/docker/docker-ce/components/engine/integration/container/update_test.go
generated
vendored
Normal file
65
vendor/github.com/docker/docker-ce/components/engine/integration/container/update_test.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
package container // import "github.com/docker/docker/integration/container"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
)
|
||||
|
||||
func TestUpdateRestartPolicy(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, container.WithCmd("sh", "-c", "sleep 1 && false"), func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.RestartPolicy = containertypes.RestartPolicy{
|
||||
Name: "on-failure",
|
||||
MaximumRetryCount: 3,
|
||||
}
|
||||
})
|
||||
|
||||
_, err := client.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{
|
||||
RestartPolicy: containertypes.RestartPolicy{
|
||||
Name: "on-failure",
|
||||
MaximumRetryCount: 5,
|
||||
},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
timeout := 60 * time.Second
|
||||
if testEnv.OSType == "windows" {
|
||||
timeout = 180 * time.Second
|
||||
}
|
||||
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cID, "exited"), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(timeout))
|
||||
|
||||
inspect, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(inspect.RestartCount, 5))
|
||||
assert.Check(t, is.Equal(inspect.HostConfig.RestartPolicy.MaximumRetryCount, 5))
|
||||
}
|
||||
|
||||
func TestUpdateRestartWithAutoRemove(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID := container.Run(t, ctx, client, func(c *container.TestContainerConfig) {
|
||||
c.HostConfig.AutoRemove = true
|
||||
})
|
||||
|
||||
_, err := client.ContainerUpdate(ctx, cID, containertypes.UpdateConfig{
|
||||
RestartPolicy: containertypes.RestartPolicy{
|
||||
Name: "always",
|
||||
},
|
||||
})
|
||||
testutil.ErrorContains(t, err, "Restart policy cannot be updated because AutoRemove is enabled for the container")
|
||||
}
|
3
vendor/github.com/docker/docker-ce/components/engine/integration/doc.go
generated
vendored
Normal file
3
vendor/github.com/docker/docker-ce/components/engine/integration/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
// Package integration provides integrations tests for Moby (API).
|
||||
// These tests require a daemon (dockerd for now) to run.
|
||||
package integration // import "github.com/docker/docker/integration"
|
45
vendor/github.com/docker/docker-ce/components/engine/integration/image/commit_test.go
generated
vendored
Normal file
45
vendor/github.com/docker/docker-ce/components/engine/integration/image/commit_test.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package image // import "github.com/docker/docker/integration/image"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestCommitInheritsEnv(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
cID1 := container.Create(t, ctx, client)
|
||||
|
||||
commitResp1, err := client.ContainerCommit(ctx, cID1, types.ContainerCommitOptions{
|
||||
Changes: []string{"ENV PATH=/bin"},
|
||||
Reference: "test-commit-image",
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
image1, _, err := client.ImageInspectWithRaw(ctx, commitResp1.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedEnv1 := []string{"PATH=/bin"}
|
||||
assert.Check(t, is.DeepEqual(expectedEnv1, image1.Config.Env))
|
||||
|
||||
cID2 := container.Create(t, ctx, client, container.WithImage(image1.ID))
|
||||
|
||||
commitResp2, err := client.ContainerCommit(ctx, cID2, types.ContainerCommitOptions{
|
||||
Changes: []string{"ENV PATH=/usr/bin:$PATH"},
|
||||
Reference: "test-commit-image",
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
image2, _, err := client.ImageInspectWithRaw(ctx, commitResp2.ID)
|
||||
assert.NilError(t, err)
|
||||
expectedEnv2 := []string{"PATH=/usr/bin:/bin"}
|
||||
assert.Check(t, is.DeepEqual(expectedEnv2, image2.Config.Env))
|
||||
}
|
42
vendor/github.com/docker/docker-ce/components/engine/integration/image/import_test.go
generated
vendored
Normal file
42
vendor/github.com/docker/docker-ce/components/engine/integration/image/import_test.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package image // import "github.com/docker/docker/integration/image"
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
)
|
||||
|
||||
// Ensure we don't regress on CVE-2017-14992.
|
||||
func TestImportExtremelyLargeImageWorks(t *testing.T) {
|
||||
if runtime.GOARCH == "arm64" {
|
||||
t.Skip("effective test will be time out")
|
||||
}
|
||||
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
// Construct an empty tar archive with about 8GB of junk padding at the
|
||||
// end. This should not cause any crashes (the padding should be mostly
|
||||
// ignored).
|
||||
var tarBuffer bytes.Buffer
|
||||
|
||||
tw := tar.NewWriter(&tarBuffer)
|
||||
if err := tw.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
imageRdr := io.MultiReader(&tarBuffer, io.LimitReader(testutil.DevZero, 8*1024*1024*1024))
|
||||
|
||||
_, err := client.ImageImport(context.Background(),
|
||||
types.ImageImportSource{Source: imageRdr, SourceName: "-"},
|
||||
"test1234:v42",
|
||||
types.ImageImportOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/image/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/image/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package image // import "github.com/docker/docker/integration/image"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
60
vendor/github.com/docker/docker-ce/components/engine/integration/image/remove_test.go
generated
vendored
Normal file
60
vendor/github.com/docker/docker-ce/components/engine/integration/image/remove_test.go
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
package image // import "github.com/docker/docker/integration/image"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestRemoveImageOrphaning(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
img := "test-container-orphaning"
|
||||
|
||||
// Create a container from busybox, and commit a small change so we have a new image
|
||||
cID1 := container.Create(t, ctx, client, container.WithCmd(""))
|
||||
commitResp1, err := client.ContainerCommit(ctx, cID1, types.ContainerCommitOptions{
|
||||
Changes: []string{`ENTRYPOINT ["true"]`},
|
||||
Reference: img,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// verifies that reference now points to first image
|
||||
resp, _, err := client.ImageInspectWithRaw(ctx, img)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(resp.ID, commitResp1.ID))
|
||||
|
||||
// Create a container from created image, and commit a small change with same reference name
|
||||
cID2 := container.Create(t, ctx, client, container.WithImage(img), container.WithCmd(""))
|
||||
commitResp2, err := client.ContainerCommit(ctx, cID2, types.ContainerCommitOptions{
|
||||
Changes: []string{`LABEL Maintainer="Integration Tests"`},
|
||||
Reference: img,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// verifies that reference now points to second image
|
||||
resp, _, err = client.ImageInspectWithRaw(ctx, img)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(resp.ID, commitResp2.ID))
|
||||
|
||||
// try to remove the image, should not error out.
|
||||
_, err = client.ImageRemove(ctx, img, types.ImageRemoveOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// check if the first image is still there
|
||||
resp, _, err = client.ImageInspectWithRaw(ctx, commitResp1.ID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(resp.ID, commitResp1.ID))
|
||||
|
||||
// check if the second image has been deleted
|
||||
_, _, err = client.ImageInspectWithRaw(ctx, commitResp2.ID)
|
||||
testutil.ErrorContains(t, err, "No such image:")
|
||||
}
|
54
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/container.go
generated
vendored
Normal file
54
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/container.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
// TestContainerConfig holds container configuration struct that
|
||||
// are used in api calls.
|
||||
type TestContainerConfig struct {
|
||||
Name string
|
||||
Config *container.Config
|
||||
HostConfig *container.HostConfig
|
||||
NetworkingConfig *network.NetworkingConfig
|
||||
}
|
||||
|
||||
// Create creates a container with the specified options
|
||||
func Create(t *testing.T, ctx context.Context, client client.APIClient, ops ...func(*TestContainerConfig)) string { // nolint: golint
|
||||
t.Helper()
|
||||
config := &TestContainerConfig{
|
||||
Config: &container.Config{
|
||||
Image: "busybox",
|
||||
Cmd: []string{"top"},
|
||||
},
|
||||
HostConfig: &container.HostConfig{},
|
||||
NetworkingConfig: &network.NetworkingConfig{},
|
||||
}
|
||||
|
||||
for _, op := range ops {
|
||||
op(config)
|
||||
}
|
||||
|
||||
c, err := client.ContainerCreate(ctx, config.Config, config.HostConfig, config.NetworkingConfig, config.Name)
|
||||
assert.NilError(t, err)
|
||||
|
||||
return c.ID
|
||||
}
|
||||
|
||||
// Run creates and start a container with the specified options
|
||||
func Run(t *testing.T, ctx context.Context, client client.APIClient, ops ...func(*TestContainerConfig)) string { // nolint: golint
|
||||
t.Helper()
|
||||
id := Create(t, ctx, client, ops...)
|
||||
|
||||
err := client.ContainerStart(ctx, id, types.ContainerStartOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
return id
|
||||
}
|
86
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/exec.go
generated
vendored
Normal file
86
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/exec.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ExecResult represents a result returned from Exec()
|
||||
type ExecResult struct {
|
||||
ExitCode int
|
||||
outBuffer *bytes.Buffer
|
||||
errBuffer *bytes.Buffer
|
||||
}
|
||||
|
||||
// Stdout returns stdout output of a command run by Exec()
|
||||
func (res *ExecResult) Stdout() string {
|
||||
return res.outBuffer.String()
|
||||
}
|
||||
|
||||
// Stderr returns stderr output of a command run by Exec()
|
||||
func (res *ExecResult) Stderr() string {
|
||||
return res.errBuffer.String()
|
||||
}
|
||||
|
||||
// Combined returns combined stdout and stderr output of a command run by Exec()
|
||||
func (res *ExecResult) Combined() string {
|
||||
return res.outBuffer.String() + res.errBuffer.String()
|
||||
}
|
||||
|
||||
// Exec executes a command inside a container, returning the result
|
||||
// containing stdout, stderr, and exit code. Note:
|
||||
// - this is a synchronous operation;
|
||||
// - cmd stdin is closed.
|
||||
func Exec(ctx context.Context, cli client.APIClient, id string, cmd []string) (ExecResult, error) {
|
||||
// prepare exec
|
||||
execConfig := types.ExecConfig{
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
Cmd: cmd,
|
||||
}
|
||||
cresp, err := cli.ContainerExecCreate(ctx, id, execConfig)
|
||||
if err != nil {
|
||||
return ExecResult{}, err
|
||||
}
|
||||
execID := cresp.ID
|
||||
|
||||
// run it, with stdout/stderr attached
|
||||
aresp, err := cli.ContainerExecAttach(ctx, execID, types.ExecStartCheck{})
|
||||
if err != nil {
|
||||
return ExecResult{}, err
|
||||
}
|
||||
defer aresp.Close()
|
||||
|
||||
// read the output
|
||||
var outBuf, errBuf bytes.Buffer
|
||||
outputDone := make(chan error)
|
||||
|
||||
go func() {
|
||||
// StdCopy demultiplexes the stream into two buffers
|
||||
_, err = stdcopy.StdCopy(&outBuf, &errBuf, aresp.Reader)
|
||||
outputDone <- err
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-outputDone:
|
||||
if err != nil {
|
||||
return ExecResult{}, err
|
||||
}
|
||||
break
|
||||
|
||||
case <-ctx.Done():
|
||||
return ExecResult{}, ctx.Err()
|
||||
}
|
||||
|
||||
// get the exit code
|
||||
iresp, err := cli.ContainerExecInspect(ctx, execID)
|
||||
if err != nil {
|
||||
return ExecResult{}, err
|
||||
}
|
||||
|
||||
return ExecResult{ExitCode: iresp.ExitCode, outBuffer: &outBuf, errBuffer: &errBuf}, nil
|
||||
}
|
85
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/ops.go
generated
vendored
Normal file
85
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/ops.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
// WithName sets the name of the container
|
||||
func WithName(name string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Name = name
|
||||
}
|
||||
}
|
||||
|
||||
// WithLinks sets the links of the container
|
||||
func WithLinks(links ...string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.Links = links
|
||||
}
|
||||
}
|
||||
|
||||
// WithImage sets the image of the container
|
||||
func WithImage(image string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Config.Image = image
|
||||
}
|
||||
}
|
||||
|
||||
// WithCmd sets the comannds of the container
|
||||
func WithCmd(cmds ...string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Config.Cmd = strslice.StrSlice(cmds)
|
||||
}
|
||||
}
|
||||
|
||||
// WithNetworkMode sets the network mode of the container
|
||||
func WithNetworkMode(mode string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.NetworkMode = containertypes.NetworkMode(mode)
|
||||
}
|
||||
}
|
||||
|
||||
// WithExposedPorts sets the exposed ports of the container
|
||||
func WithExposedPorts(ports ...string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Config.ExposedPorts = map[nat.Port]struct{}{}
|
||||
for _, port := range ports {
|
||||
c.Config.ExposedPorts[nat.Port(port)] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithTty sets the TTY mode of the container
|
||||
func WithTty(tty bool) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Config.Tty = tty
|
||||
}
|
||||
}
|
||||
|
||||
// WithWorkingDir sets the working dir of the container
|
||||
func WithWorkingDir(dir string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.Config.WorkingDir = dir
|
||||
}
|
||||
}
|
||||
|
||||
// WithVolume sets the volume of the container
|
||||
func WithVolume(name string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
if c.Config.Volumes == nil {
|
||||
c.Config.Volumes = map[string]struct{}{}
|
||||
}
|
||||
c.Config.Volumes[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// WithBind sets the bind mount of the container
|
||||
func WithBind(src, target string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.Binds = append(c.HostConfig.Binds, fmt.Sprintf("%s:%s", src, target))
|
||||
}
|
||||
}
|
41
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/states.go
generated
vendored
Normal file
41
vendor/github.com/docker/docker-ce/components/engine/integration/internal/container/states.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// IsStopped verifies the container is in stopped state.
|
||||
func IsStopped(ctx context.Context, client client.APIClient, containerID string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
inspect, err := client.ContainerInspect(ctx, containerID)
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case !inspect.State.Running:
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("waiting for container to be stopped")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsInState verifies the container is in one of the specified state, e.g., "running", "exited", etc.
|
||||
func IsInState(ctx context.Context, client client.APIClient, containerID string, state ...string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
inspect, err := client.ContainerInspect(ctx, containerID)
|
||||
if err != nil {
|
||||
return poll.Error(err)
|
||||
}
|
||||
for _, v := range state {
|
||||
if inspect.State.Status == v {
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
||||
return poll.Continue("waiting for container to be one of (%s), currently %s", strings.Join(state, ", "), inspect.State.Status)
|
||||
}
|
||||
}
|
42
vendor/github.com/docker/docker-ce/components/engine/integration/internal/request/client.go
generated
vendored
Normal file
42
vendor/github.com/docker/docker-ce/components/engine/integration/internal/request/client.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package request // import "github.com/docker/docker/integration/internal/request"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
// NewAPIClient returns a docker API client configured from environment variables
|
||||
func NewAPIClient(t *testing.T, ops ...func(*client.Client) error) client.APIClient {
|
||||
ops = append([]func(*client.Client) error{client.FromEnv}, ops...)
|
||||
clt, err := client.NewClientWithOpts(ops...)
|
||||
assert.NilError(t, err)
|
||||
return clt
|
||||
}
|
||||
|
||||
// DaemonTime provides the current time on the daemon host
|
||||
func DaemonTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
|
||||
if testEnv.IsLocalDaemon() {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
info, err := client.Info(ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||
assert.NilError(t, err, "invalid time format in GET /info response")
|
||||
return dt
|
||||
}
|
||||
|
||||
// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision.
|
||||
// It return the time formatted how the client sends timestamps to the server.
|
||||
func DaemonUnixTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) string {
|
||||
dt := DaemonTime(ctx, t, client, testEnv)
|
||||
return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
|
||||
}
|
26
vendor/github.com/docker/docker-ce/components/engine/integration/internal/requirement/requirement.go
generated
vendored
Normal file
26
vendor/github.com/docker/docker-ce/components/engine/integration/internal/requirement/requirement.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
package requirement // import "github.com/docker/docker/integration/internal/requirement"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HasHubConnectivity checks to see if https://hub.docker.com is
|
||||
// accessible from the present environment
|
||||
func HasHubConnectivity(t *testing.T) bool {
|
||||
// Set a timeout on the GET at 15s
|
||||
var timeout = 15 * time.Second
|
||||
var url = "https://hub.docker.com"
|
||||
|
||||
client := http.Client{Timeout: timeout}
|
||||
resp, err := client.Get(url)
|
||||
if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
||||
t.Fatalf("Timeout for GET request on %s", url)
|
||||
}
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
return err == nil
|
||||
}
|
158
vendor/github.com/docker/docker-ce/components/engine/integration/internal/swarm/service.go
generated
vendored
Normal file
158
vendor/github.com/docker/docker-ce/components/engine/integration/internal/swarm/service.go
generated
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
package swarm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
dockerdBinary = "dockerd"
|
||||
defaultSwarmPort = 2477
|
||||
)
|
||||
|
||||
// NewSwarm creates a swarm daemon for testing
|
||||
func NewSwarm(t *testing.T, testEnv *environment.Execution) *daemon.Swarm {
|
||||
d := &daemon.Swarm{
|
||||
Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{
|
||||
Experimental: testEnv.DaemonInfo.ExperimentalBuild,
|
||||
}),
|
||||
// TODO: better method of finding an unused port
|
||||
Port: defaultSwarmPort,
|
||||
}
|
||||
// TODO: move to a NewSwarm constructor
|
||||
d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port)
|
||||
|
||||
// avoid networking conflicts
|
||||
args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
|
||||
d.StartWithBusybox(t, args...)
|
||||
|
||||
assert.NilError(t, d.Init(swarmtypes.InitRequest{}))
|
||||
return d
|
||||
}
|
||||
|
||||
// ServiceSpecOpt is used with `CreateService` to pass in service spec modifiers
|
||||
type ServiceSpecOpt func(*swarmtypes.ServiceSpec)
|
||||
|
||||
// CreateService creates a service on the passed in swarm daemon.
|
||||
func CreateService(t *testing.T, d *daemon.Swarm, opts ...ServiceSpecOpt) string {
|
||||
spec := defaultServiceSpec()
|
||||
for _, o := range opts {
|
||||
o(&spec)
|
||||
}
|
||||
|
||||
client := GetClient(t, d)
|
||||
|
||||
resp, err := client.ServiceCreate(context.Background(), spec, types.ServiceCreateOptions{})
|
||||
assert.NilError(t, err, "error creating service")
|
||||
return resp.ID
|
||||
}
|
||||
|
||||
func defaultServiceSpec() swarmtypes.ServiceSpec {
|
||||
var spec swarmtypes.ServiceSpec
|
||||
ServiceWithImage("busybox:latest")(&spec)
|
||||
ServiceWithCommand([]string{"/bin/top"})(&spec)
|
||||
ServiceWithReplicas(1)(&spec)
|
||||
return spec
|
||||
}
|
||||
|
||||
// ServiceWithImage sets the image to use for the service
|
||||
func ServiceWithImage(image string) func(*swarmtypes.ServiceSpec) {
|
||||
return func(spec *swarmtypes.ServiceSpec) {
|
||||
ensureContainerSpec(spec)
|
||||
spec.TaskTemplate.ContainerSpec.Image = image
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceWithCommand sets the command to use for the service
|
||||
func ServiceWithCommand(cmd []string) ServiceSpecOpt {
|
||||
return func(spec *swarmtypes.ServiceSpec) {
|
||||
ensureContainerSpec(spec)
|
||||
spec.TaskTemplate.ContainerSpec.Command = cmd
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceWithConfig adds the config reference to the service
|
||||
func ServiceWithConfig(configRef *swarmtypes.ConfigReference) ServiceSpecOpt {
|
||||
return func(spec *swarmtypes.ServiceSpec) {
|
||||
ensureContainerSpec(spec)
|
||||
spec.TaskTemplate.ContainerSpec.Configs = append(spec.TaskTemplate.ContainerSpec.Configs, configRef)
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceWithSecret adds the secret reference to the service
|
||||
func ServiceWithSecret(secretRef *swarmtypes.SecretReference) ServiceSpecOpt {
|
||||
return func(spec *swarmtypes.ServiceSpec) {
|
||||
ensureContainerSpec(spec)
|
||||
spec.TaskTemplate.ContainerSpec.Secrets = append(spec.TaskTemplate.ContainerSpec.Secrets, secretRef)
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceWithReplicas sets the replicas for the service
|
||||
func ServiceWithReplicas(n uint64) ServiceSpecOpt {
|
||||
return func(spec *swarmtypes.ServiceSpec) {
|
||||
spec.Mode = swarmtypes.ServiceMode{
|
||||
Replicated: &swarmtypes.ReplicatedService{
|
||||
Replicas: &n,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceWithName sets the name of the service
|
||||
func ServiceWithName(name string) ServiceSpecOpt {
|
||||
return func(spec *swarmtypes.ServiceSpec) {
|
||||
spec.Annotations.Name = name
|
||||
}
|
||||
}
|
||||
|
||||
// GetRunningTasks gets the list of running tasks for a service
|
||||
func GetRunningTasks(t *testing.T, d *daemon.Swarm, serviceID string) []swarmtypes.Task {
|
||||
client := GetClient(t, d)
|
||||
|
||||
filterArgs := filters.NewArgs()
|
||||
filterArgs.Add("desired-state", "running")
|
||||
filterArgs.Add("service", serviceID)
|
||||
|
||||
options := types.TaskListOptions{
|
||||
Filters: filterArgs,
|
||||
}
|
||||
tasks, err := client.TaskList(context.Background(), options)
|
||||
assert.NilError(t, err)
|
||||
return tasks
|
||||
}
|
||||
|
||||
// ExecTask runs the passed in exec config on the given task
|
||||
func ExecTask(t *testing.T, d *daemon.Swarm, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse {
|
||||
client := GetClient(t, d)
|
||||
|
||||
ctx := context.Background()
|
||||
resp, err := client.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, config)
|
||||
assert.NilError(t, err, "error creating exec")
|
||||
|
||||
startCheck := types.ExecStartCheck{}
|
||||
attach, err := client.ContainerExecAttach(ctx, resp.ID, startCheck)
|
||||
assert.NilError(t, err, "error attaching to exec")
|
||||
return attach
|
||||
}
|
||||
|
||||
func ensureContainerSpec(spec *swarmtypes.ServiceSpec) {
|
||||
if spec.TaskTemplate.ContainerSpec == nil {
|
||||
spec.TaskTemplate.ContainerSpec = &swarmtypes.ContainerSpec{}
|
||||
}
|
||||
}
|
||||
|
||||
// GetClient creates a new client for the passed in swarm daemon.
|
||||
func GetClient(t *testing.T, d *daemon.Swarm) client.APIClient {
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
return client
|
||||
}
|
72
vendor/github.com/docker/docker-ce/components/engine/integration/network/delete_test.go
generated
vendored
Normal file
72
vendor/github.com/docker/docker-ce/components/engine/integration/network/delete_test.go
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
package network // import "github.com/docker/docker/integration/network"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func containsNetwork(nws []types.NetworkResource, nw types.NetworkCreateResponse) bool {
|
||||
for _, n := range nws {
|
||||
if n.ID == nw.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// createAmbiguousNetworks creates three networks, of which the second network
|
||||
// uses a prefix of the first network's ID as name. The third network uses the
|
||||
// first network's ID as name.
|
||||
//
|
||||
// After successful creation, properties of all three networks is returned
|
||||
func createAmbiguousNetworks(t *testing.T) (types.NetworkCreateResponse, types.NetworkCreateResponse, types.NetworkCreateResponse) {
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
testNet, err := client.NetworkCreate(ctx, "testNet", types.NetworkCreate{})
|
||||
assert.NilError(t, err)
|
||||
idPrefixNet, err := client.NetworkCreate(ctx, testNet.ID[:12], types.NetworkCreate{})
|
||||
assert.NilError(t, err)
|
||||
fullIDNet, err := client.NetworkCreate(ctx, testNet.ID, types.NetworkCreate{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
nws, err := client.NetworkList(ctx, types.NetworkListOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Equal(true, containsNetwork(nws, testNet)), "failed to create network testNet")
|
||||
assert.Check(t, is.Equal(true, containsNetwork(nws, idPrefixNet)), "failed to create network idPrefixNet")
|
||||
assert.Check(t, is.Equal(true, containsNetwork(nws, fullIDNet)), "failed to create network fullIDNet")
|
||||
return testNet, idPrefixNet, fullIDNet
|
||||
}
|
||||
|
||||
// TestDockerNetworkDeletePreferID tests that if a network with a name
|
||||
// equal to another network's ID exists, the Network with the given
|
||||
// ID is removed, and not the network with the given name.
|
||||
func TestDockerNetworkDeletePreferID(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
testNet, idPrefixNet, fullIDNet := createAmbiguousNetworks(t)
|
||||
|
||||
// Delete the network using a prefix of the first network's ID as name.
|
||||
// This should the network name with the id-prefix, not the original network.
|
||||
err := client.NetworkRemove(ctx, testNet.ID[:12])
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Delete the network using networkID. This should remove the original
|
||||
// network, not the network with the name equal to the networkID
|
||||
err = client.NetworkRemove(ctx, testNet.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// networks "testNet" and "idPrefixNet" should be removed, but "fullIDNet" should still exist
|
||||
nws, err := client.NetworkList(ctx, types.NetworkListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(false, containsNetwork(nws, testNet)), "Network testNet not removed")
|
||||
assert.Check(t, is.Equal(false, containsNetwork(nws, idPrefixNet)), "Network idPrefixNet not removed")
|
||||
assert.Check(t, is.Equal(true, containsNetwork(nws, fullIDNet)), "Network fullIDNet not found")
|
||||
}
|
220
vendor/github.com/docker/docker-ce/components/engine/integration/network/inspect_test.go
generated
vendored
Normal file
220
vendor/github.com/docker/docker-ce/components/engine/integration/network/inspect_test.go
generated
vendored
Normal file
|
@ -0,0 +1,220 @@
|
|||
package network // import "github.com/docker/docker/integration/network"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const defaultSwarmPort = 2477
|
||||
const dockerdBinary = "dockerd"
|
||||
|
||||
func TestInspectNetwork(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := newSwarm(t)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
overlayName := "overlay1"
|
||||
networkCreate := types.NetworkCreate{
|
||||
CheckDuplicate: true,
|
||||
Driver: "overlay",
|
||||
}
|
||||
|
||||
netResp, err := client.NetworkCreate(context.Background(), overlayName, networkCreate)
|
||||
assert.NilError(t, err)
|
||||
overlayID := netResp.ID
|
||||
|
||||
var instances uint64 = 4
|
||||
serviceName := "TestService"
|
||||
serviceSpec := swarmServiceSpec(serviceName, instances)
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: overlayName})
|
||||
|
||||
serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
pollSettings := func(config *poll.Settings) {
|
||||
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
|
||||
config.Timeout = 30 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
}
|
||||
}
|
||||
|
||||
serviceID := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), pollSettings)
|
||||
|
||||
_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Test inspect verbose with full NetworkID
|
||||
networkVerbose, err := client.NetworkInspect(context.Background(), overlayID, types.NetworkInspectOptions{
|
||||
Verbose: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, validNetworkVerbose(networkVerbose, serviceName, instances))
|
||||
|
||||
// Test inspect verbose with partial NetworkID
|
||||
networkVerbose, err = client.NetworkInspect(context.Background(), overlayID[0:11], types.NetworkInspectOptions{
|
||||
Verbose: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, validNetworkVerbose(networkVerbose, serviceName, instances))
|
||||
|
||||
// Test inspect verbose with Network name and swarm scope
|
||||
networkVerbose, err = client.NetworkInspect(context.Background(), overlayName, types.NetworkInspectOptions{
|
||||
Verbose: true,
|
||||
Scope: "swarm",
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, validNetworkVerbose(networkVerbose, serviceName, instances))
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
serviceResp, err = client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
serviceID2 := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), pollSettings)
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID2)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID2), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
err = client.NetworkRemove(context.Background(), overlayID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
|
||||
}
|
||||
|
||||
func newSwarm(t *testing.T) *daemon.Swarm {
|
||||
d := &daemon.Swarm{
|
||||
Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{
|
||||
Experimental: testEnv.DaemonInfo.ExperimentalBuild,
|
||||
}),
|
||||
// TODO: better method of finding an unused port
|
||||
Port: defaultSwarmPort,
|
||||
}
|
||||
// TODO: move to a NewSwarm constructor
|
||||
d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port)
|
||||
|
||||
// avoid networking conflicts
|
||||
args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
|
||||
d.StartWithBusybox(t, args...)
|
||||
|
||||
assert.NilError(t, d.Init(swarm.InitRequest{}))
|
||||
return d
|
||||
}
|
||||
|
||||
func swarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec {
|
||||
return swarm.ServiceSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: name,
|
||||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: &swarm.ContainerSpec{
|
||||
Image: "busybox:latest",
|
||||
Command: []string{"/bin/top"},
|
||||
},
|
||||
},
|
||||
Mode: swarm.ServiceMode{
|
||||
Replicated: &swarm.ReplicatedService{
|
||||
Replicas: &replicas,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceID)
|
||||
tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case len(tasks) == int(instances):
|
||||
for _, task := range tasks {
|
||||
if task.Status.State != swarm.TaskStateRunning {
|
||||
return poll.Continue("waiting for tasks to enter run state")
|
||||
}
|
||||
}
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("task count at %d waiting for %d", len(tasks), instances)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func networkIsRemoved(client client.NetworkAPIClient, networkID string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
_, err := client.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
|
||||
if err == nil {
|
||||
return poll.Continue("waiting for network %s to be removed", networkID)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
||||
|
||||
func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceID)
|
||||
_, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
if err == nil {
|
||||
return poll.Continue("waiting for service %s to be deleted", serviceID)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
||||
|
||||
func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case len(tasks) == 0:
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("task count at %d waiting for 0", len(tasks))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if Service and Tasks info are part of the inspect verbose response
|
||||
func validNetworkVerbose(network types.NetworkResource, service string, instances uint64) bool {
|
||||
if service, ok := network.Services[service]; ok {
|
||||
if len(service.Tasks) == int(instances) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/network/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/network/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package network // import "github.com/docker/docker/integration/network"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
161
vendor/github.com/docker/docker-ce/components/engine/integration/network/service_test.go
generated
vendored
Normal file
161
vendor/github.com/docker/docker-ce/components/engine/integration/network/service_test.go
generated
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
package network // import "github.com/docker/docker/integration/network"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestServiceWithPredefinedNetwork(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := newSwarm(t)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
hostName := "host"
|
||||
var instances uint64 = 1
|
||||
serviceName := "TestService"
|
||||
serviceSpec := swarmServiceSpec(serviceName, instances)
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: hostName})
|
||||
|
||||
serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
pollSettings := func(config *poll.Settings) {
|
||||
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
|
||||
config.Timeout = 50 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
} else {
|
||||
config.Timeout = 30 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
}
|
||||
}
|
||||
|
||||
serviceID := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningCount(client, serviceID, instances), pollSettings)
|
||||
|
||||
_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
}
|
||||
|
||||
const ingressNet = "ingress"
|
||||
|
||||
func TestServiceWithIngressNetwork(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := newSwarm(t)
|
||||
defer d.Stop(t)
|
||||
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
pollSettings := func(config *poll.Settings) {
|
||||
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
|
||||
config.Timeout = 50 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
} else {
|
||||
config.Timeout = 30 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
}
|
||||
}
|
||||
|
||||
poll.WaitOn(t, swarmIngressReady(client), pollSettings)
|
||||
|
||||
var instances uint64 = 1
|
||||
serviceName := "TestIngressService"
|
||||
serviceSpec := swarmServiceSpec(serviceName, instances)
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: ingressNet})
|
||||
serviceSpec.EndpointSpec = &swarm.EndpointSpec{
|
||||
Ports: []swarm.PortConfig{
|
||||
{
|
||||
Protocol: swarm.PortConfigProtocolTCP,
|
||||
TargetPort: 80,
|
||||
PublishMode: swarm.PortConfigPublishModeIngress,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
serviceID := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningCount(client, serviceID, instances), pollSettings)
|
||||
|
||||
_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
// Ensure that "ingress" is not removed or corrupted
|
||||
time.Sleep(10 * time.Second)
|
||||
netInfo, err := client.NetworkInspect(context.Background(), ingressNet, types.NetworkInspectOptions{
|
||||
Verbose: true,
|
||||
Scope: "swarm",
|
||||
})
|
||||
assert.NilError(t, err, "Ingress network was removed after removing service!")
|
||||
assert.Assert(t, len(netInfo.Containers) != 0, "No load balancing endpoints in ingress network")
|
||||
assert.Assert(t, len(netInfo.Peers) != 0, "No peers (including self) in ingress network")
|
||||
_, ok := netInfo.Containers["ingress-sbox"]
|
||||
assert.Assert(t, ok, "ingress-sbox not present in ingress network")
|
||||
}
|
||||
|
||||
func serviceRunningCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceID)
|
||||
services, err := client.ServiceList(context.Background(), types.ServiceListOptions{})
|
||||
if err != nil {
|
||||
return poll.Error(err)
|
||||
}
|
||||
|
||||
if len(services) != int(instances) {
|
||||
return poll.Continue("Service count at %d waiting for %d", len(services), instances)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
||||
|
||||
func swarmIngressReady(client client.NetworkAPIClient) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
netInfo, err := client.NetworkInspect(context.Background(), ingressNet, types.NetworkInspectOptions{
|
||||
Verbose: true,
|
||||
Scope: "swarm",
|
||||
})
|
||||
if err != nil {
|
||||
return poll.Error(err)
|
||||
}
|
||||
np := len(netInfo.Peers)
|
||||
nc := len(netInfo.Containers)
|
||||
if np == 0 || nc == 0 {
|
||||
return poll.Continue("ingress not ready: %d peers and %d containers", nc, np)
|
||||
}
|
||||
_, ok := netInfo.Containers["ingress-sbox"]
|
||||
if !ok {
|
||||
return poll.Continue("ingress not ready: does not contain the ingress-sbox")
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
470
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/authz/authz_plugin_test.go
generated
vendored
Normal file
470
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/authz/authz_plugin_test.go
generated
vendored
Normal file
|
@ -0,0 +1,470 @@
|
|||
// +build !windows
|
||||
|
||||
package authz // import "github.com/docker/docker/integration/plugin/authz"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
eventtypes "github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/docker/docker/pkg/authorization"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
const (
|
||||
testAuthZPlugin = "authzplugin"
|
||||
unauthorizedMessage = "User unauthorized authz plugin"
|
||||
errorMessage = "something went wrong..."
|
||||
serverVersionAPI = "/version"
|
||||
)
|
||||
|
||||
var (
|
||||
alwaysAllowed = []string{"/_ping", "/info"}
|
||||
ctrl *authorizationController
|
||||
)
|
||||
|
||||
type authorizationController struct {
|
||||
reqRes authorization.Response // reqRes holds the plugin response to the initial client request
|
||||
resRes authorization.Response // resRes holds the plugin response to the daemon response
|
||||
versionReqCount int // versionReqCount counts the number of requests to the server version API endpoint
|
||||
versionResCount int // versionResCount counts the number of responses from the server version API endpoint
|
||||
requestsURIs []string // requestsURIs stores all request URIs that are sent to the authorization controller
|
||||
reqUser string
|
||||
resUser string
|
||||
}
|
||||
|
||||
func setupTestV1(t *testing.T) func() {
|
||||
ctrl = &authorizationController{}
|
||||
teardown := setupTest(t)
|
||||
|
||||
err := os.MkdirAll("/etc/docker/plugins", 0755)
|
||||
assert.NilError(t, err)
|
||||
|
||||
fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", testAuthZPlugin)
|
||||
err = ioutil.WriteFile(fileName, []byte(server.URL), 0644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
return func() {
|
||||
err := os.RemoveAll("/etc/docker/plugins")
|
||||
assert.NilError(t, err)
|
||||
|
||||
teardown()
|
||||
ctrl = nil
|
||||
}
|
||||
}
|
||||
|
||||
// check for always allowed endpoints to not inhibit test framework functions
|
||||
func isAllowed(reqURI string) bool {
|
||||
for _, endpoint := range alwaysAllowed {
|
||||
if strings.HasSuffix(reqURI, endpoint) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestAuthZPluginAllowRequest(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = true
|
||||
d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Ensure command successful
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
assertURIRecorded(t, ctrl.requestsURIs, "/containers/create")
|
||||
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", cID))
|
||||
|
||||
_, err = client.ServerVersion(ctx)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 1, ctrl.versionReqCount)
|
||||
assert.Equal(t, 1, ctrl.versionResCount)
|
||||
}
|
||||
|
||||
func TestAuthZPluginTLS(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
const (
|
||||
testDaemonHTTPSAddr = "tcp://localhost:4271"
|
||||
cacertPath = "../../testdata/https/ca.pem"
|
||||
serverCertPath = "../../testdata/https/server-cert.pem"
|
||||
serverKeyPath = "../../testdata/https/server-key.pem"
|
||||
clientCertPath = "../../testdata/https/client-cert.pem"
|
||||
clientKeyPath = "../../testdata/https/client-key.pem"
|
||||
)
|
||||
|
||||
d.Start(t,
|
||||
"--authorization-plugin="+testAuthZPlugin,
|
||||
"--tlsverify",
|
||||
"--tlscacert", cacertPath,
|
||||
"--tlscert", serverCertPath,
|
||||
"--tlskey", serverKeyPath,
|
||||
"-H", testDaemonHTTPSAddr)
|
||||
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = true
|
||||
|
||||
client, err := newTLSAPIClient(testDaemonHTTPSAddr, cacertPath, clientCertPath, clientKeyPath)
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, "client", ctrl.reqUser)
|
||||
assert.Equal(t, "client", ctrl.resUser)
|
||||
}
|
||||
|
||||
func newTLSAPIClient(host, cacertPath, certPath, keyPath string) (client.APIClient, error) {
|
||||
dialer := &net.Dialer{
|
||||
KeepAlive: 30 * time.Second,
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
return client.NewClientWithOpts(
|
||||
client.WithTLSClientConfig(cacertPath, certPath, keyPath),
|
||||
client.WithDialer(dialer),
|
||||
client.WithHost(host))
|
||||
}
|
||||
|
||||
func TestAuthZPluginDenyRequest(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
d.Start(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
ctrl.reqRes.Allow = false
|
||||
ctrl.reqRes.Msg = unauthorizedMessage
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Equal(t, 1, ctrl.versionReqCount)
|
||||
assert.Equal(t, 0, ctrl.versionResCount)
|
||||
|
||||
// Ensure unauthorized message appears in response
|
||||
assert.Equal(t, fmt.Sprintf("Error response from daemon: authorization denied by plugin %s: %s", testAuthZPlugin, unauthorizedMessage), err.Error())
|
||||
}
|
||||
|
||||
// TestAuthZPluginAPIDenyResponse validates that when authorization
|
||||
// plugin deny the request, the status code is forbidden
|
||||
func TestAuthZPluginAPIDenyResponse(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
d.Start(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
ctrl.reqRes.Allow = false
|
||||
ctrl.resRes.Msg = unauthorizedMessage
|
||||
|
||||
daemonURL, err := url.Parse(d.Sock())
|
||||
assert.NilError(t, err)
|
||||
|
||||
conn, err := net.DialTimeout(daemonURL.Scheme, daemonURL.Path, time.Second*10)
|
||||
assert.NilError(t, err)
|
||||
client := httputil.NewClientConn(conn, nil)
|
||||
req, err := http.NewRequest("GET", "/version", nil)
|
||||
assert.NilError(t, err)
|
||||
resp, err := client.Do(req)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, http.StatusForbidden, resp.StatusCode)
|
||||
}
|
||||
|
||||
func TestAuthZPluginDenyResponse(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
d.Start(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = false
|
||||
ctrl.resRes.Msg = unauthorizedMessage
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Equal(t, 1, ctrl.versionReqCount)
|
||||
assert.Equal(t, 1, ctrl.versionResCount)
|
||||
|
||||
// Ensure unauthorized message appears in response
|
||||
assert.Equal(t, fmt.Sprintf("Error response from daemon: authorization denied by plugin %s: %s", testAuthZPlugin, unauthorizedMessage), err.Error())
|
||||
}
|
||||
|
||||
// TestAuthZPluginAllowEventStream verifies event stream propagates
|
||||
// correctly after request pass through by the authorization plugin
|
||||
func TestAuthZPluginAllowEventStream(t *testing.T) {
|
||||
skip.IfCondition(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTestV1(t)()
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = true
|
||||
d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
startTime := strconv.FormatInt(systemTime(t, client, testEnv).Unix(), 10)
|
||||
events, errs, cancel := systemEventsSince(client, startTime)
|
||||
defer cancel()
|
||||
|
||||
// Create a container and wait for the creation events
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
c, err := client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
if c.State.Running {
|
||||
break
|
||||
}
|
||||
if i == 99 {
|
||||
t.Fatal("Container didn't run within 10s")
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
created := false
|
||||
started := false
|
||||
for !created && !started {
|
||||
select {
|
||||
case event := <-events:
|
||||
if event.Type == eventtypes.ContainerEventType && event.Actor.ID == cID {
|
||||
if event.Action == "create" {
|
||||
created = true
|
||||
}
|
||||
if event.Action == "start" {
|
||||
started = true
|
||||
}
|
||||
}
|
||||
case err := <-errs:
|
||||
if err == io.EOF {
|
||||
t.Fatal("premature end of event stream")
|
||||
}
|
||||
assert.NilError(t, err)
|
||||
case <-time.After(30 * time.Second):
|
||||
// Fail the test
|
||||
t.Fatal("event stream timeout")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure both events and container endpoints are passed to the
|
||||
// authorization plugin
|
||||
assertURIRecorded(t, ctrl.requestsURIs, "/events")
|
||||
assertURIRecorded(t, ctrl.requestsURIs, "/containers/create")
|
||||
assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", cID))
|
||||
}
|
||||
|
||||
func systemTime(t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
|
||||
if testEnv.IsLocalDaemon() {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
info, err := client.Info(ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
|
||||
assert.NilError(t, err, "invalid time format in GET /info response")
|
||||
return dt
|
||||
}
|
||||
|
||||
func systemEventsSince(client client.APIClient, since string) (<-chan eventtypes.Message, <-chan error, func()) {
|
||||
eventOptions := types.EventsOptions{
|
||||
Since: since,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
events, errs := client.Events(ctx, eventOptions)
|
||||
|
||||
return events, errs, cancel
|
||||
}
|
||||
|
||||
func TestAuthZPluginErrorResponse(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
d.Start(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Err = errorMessage
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiResponse, errorMessage), err.Error())
|
||||
}
|
||||
|
||||
func TestAuthZPluginErrorRequest(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
d.Start(t, "--authorization-plugin="+testAuthZPlugin)
|
||||
ctrl.reqRes.Err = errorMessage
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Ensure command is blocked
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiRequest, errorMessage), err.Error())
|
||||
}
|
||||
|
||||
func TestAuthZPluginEnsureNoDuplicatePluginRegistration(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
d.Start(t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin)
|
||||
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = true
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = client.ServerVersion(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
// assert plugin is only called once..
|
||||
assert.Equal(t, 1, ctrl.versionReqCount)
|
||||
assert.Equal(t, 1, ctrl.versionResCount)
|
||||
}
|
||||
|
||||
func TestAuthZPluginEnsureLoadImportWorking(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = true
|
||||
d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
tmp, err := ioutil.TempDir("", "test-authz-load-import")
|
||||
assert.NilError(t, err)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
savedImagePath := filepath.Join(tmp, "save.tar")
|
||||
|
||||
err = imageSave(client, savedImagePath, "busybox")
|
||||
assert.NilError(t, err)
|
||||
err = imageLoad(client, savedImagePath)
|
||||
assert.NilError(t, err)
|
||||
|
||||
exportedImagePath := filepath.Join(tmp, "export.tar")
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
responseReader, err := client.ContainerExport(context.Background(), cID)
|
||||
assert.NilError(t, err)
|
||||
defer responseReader.Close()
|
||||
file, err := os.Create(exportedImagePath)
|
||||
assert.NilError(t, err)
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, responseReader)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = imageImport(client, exportedImagePath)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func imageSave(client client.APIClient, path, image string) error {
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ImageSave(ctx, []string{image})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(file, responseReader)
|
||||
return err
|
||||
}
|
||||
|
||||
func imageLoad(client client.APIClient, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
quiet := true
|
||||
ctx := context.Background()
|
||||
response, err := client.ImageLoad(ctx, file, quiet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageImport(client client.APIClient, path string) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
options := types.ImageImportOptions{}
|
||||
ref := ""
|
||||
source := types.ImageImportSource{
|
||||
Source: file,
|
||||
SourceName: "-",
|
||||
}
|
||||
ctx := context.Background()
|
||||
responseReader, err := client.ImageImport(ctx, source, ref, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestAuthZPluginHeader(t *testing.T) {
|
||||
defer setupTestV1(t)()
|
||||
ctrl.reqRes.Allow = true
|
||||
ctrl.resRes.Allow = true
|
||||
d.StartWithBusybox(t, "--debug", "--authorization-plugin="+testAuthZPlugin)
|
||||
|
||||
daemonURL, err := url.Parse(d.Sock())
|
||||
assert.NilError(t, err)
|
||||
|
||||
conn, err := net.DialTimeout(daemonURL.Scheme, daemonURL.Path, time.Second*10)
|
||||
assert.NilError(t, err)
|
||||
client := httputil.NewClientConn(conn, nil)
|
||||
req, err := http.NewRequest("GET", "/version", nil)
|
||||
assert.NilError(t, err)
|
||||
resp, err := client.Do(req)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, "application/json", resp.Header["Content-Type"][0])
|
||||
}
|
||||
|
||||
// assertURIRecorded verifies that the given URI was sent and recorded
|
||||
// in the authz plugin
|
||||
func assertURIRecorded(t *testing.T, uris []string, uri string) {
|
||||
var found bool
|
||||
for _, u := range uris {
|
||||
if strings.Contains(u, uri) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("Expected to find URI '%s', recorded uris '%s'", uri, strings.Join(uris, ","))
|
||||
}
|
||||
}
|
175
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/authz/authz_plugin_v2_test.go
generated
vendored
Normal file
175
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/authz/authz_plugin_v2_test.go
generated
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
// +build !windows
|
||||
|
||||
package authz // import "github.com/docker/docker/integration/plugin/authz"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/requirement"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
var (
|
||||
authzPluginName = "riyaz/authz-no-volume-plugin"
|
||||
authzPluginTag = "latest"
|
||||
authzPluginNameWithTag = authzPluginName + ":" + authzPluginTag
|
||||
authzPluginBadManifestName = "riyaz/authz-plugin-bad-manifest"
|
||||
nonexistentAuthzPluginName = "riyaz/nonexistent-authz-plugin"
|
||||
)
|
||||
|
||||
func setupTestV2(t *testing.T) func() {
|
||||
skip.IfCondition(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
skip.IfCondition(t, !requirement.HasHubConnectivity(t))
|
||||
|
||||
teardown := setupTest(t)
|
||||
|
||||
d.Start(t)
|
||||
|
||||
return teardown
|
||||
}
|
||||
|
||||
func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) {
|
||||
skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
|
||||
defer setupTestV2(t)()
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Install authz plugin
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
assert.NilError(t, err)
|
||||
// start the daemon with the plugin and load busybox, --net=none build fails otherwise
|
||||
// because it needs to pull busybox
|
||||
d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
|
||||
d.LoadBusybox(t)
|
||||
|
||||
// Ensure docker run command and accompanying docker ps are successful
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
_, err = client.ContainerInspect(ctx, cID)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestAuthZPluginV2Disable(t *testing.T) {
|
||||
skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
|
||||
defer setupTestV2(t)()
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Install authz plugin
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
assert.NilError(t, err)
|
||||
|
||||
d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
|
||||
d.LoadBusybox(t)
|
||||
|
||||
_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
// disable the plugin
|
||||
err = client.PluginDisable(context.Background(), authzPluginNameWithTag, types.PluginDisableOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// now test to see if the docker api works.
|
||||
_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestAuthZPluginV2RejectVolumeRequests(t *testing.T) {
|
||||
skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
|
||||
defer setupTestV2(t)()
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Install authz plugin
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginNameWithTag)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// restart the daemon with the plugin
|
||||
d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag)
|
||||
|
||||
_, err = client.VolumeCreate(context.Background(), volumetypes.VolumesCreateBody{Driver: "local"})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
_, err = client.VolumeList(context.Background(), filters.Args{})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
// The plugin will block the command before it can determine the volume does not exist
|
||||
err = client.VolumeRemove(context.Background(), "test", false)
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
_, err = client.VolumeInspect(context.Background(), "test")
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
|
||||
_, err = client.VolumesPrune(context.Background(), filters.Args{})
|
||||
assert.Assert(t, err != nil)
|
||||
assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag)))
|
||||
}
|
||||
|
||||
func TestAuthZPluginV2BadManifestFailsDaemonStart(t *testing.T) {
|
||||
skip.IfCondition(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
|
||||
defer setupTestV2(t)()
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Install authz plugin with bad manifest
|
||||
err = pluginInstallGrantAllPermissions(client, authzPluginBadManifestName)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// start the daemon with the plugin, it will error
|
||||
err = d.RestartWithError("--authorization-plugin=" + authzPluginBadManifestName)
|
||||
assert.Assert(t, err != nil)
|
||||
|
||||
// restarting the daemon without requiring the plugin will succeed
|
||||
d.Start(t)
|
||||
}
|
||||
|
||||
func TestAuthZPluginV2NonexistentFailsDaemonStart(t *testing.T) {
|
||||
defer setupTestV2(t)()
|
||||
|
||||
// start the daemon with a non-existent authz plugin, it will error
|
||||
err := d.RestartWithError("--authorization-plugin=" + nonexistentAuthzPluginName)
|
||||
assert.Assert(t, err != nil)
|
||||
|
||||
// restarting the daemon without requiring the plugin will succeed
|
||||
d.Start(t)
|
||||
}
|
||||
|
||||
func pluginInstallGrantAllPermissions(client client.APIClient, name string) error {
|
||||
ctx := context.Background()
|
||||
options := types.PluginInstallOptions{
|
||||
RemoteRef: name,
|
||||
AcceptAllPermissions: true,
|
||||
}
|
||||
responseReader, err := client.PluginInstall(ctx, "", options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseReader.Close()
|
||||
// we have to read the response out here because the client API
|
||||
// actually starts a goroutine which we can only be sure has
|
||||
// completed when we get EOF from reading responseBody
|
||||
_, err = ioutil.ReadAll(responseReader)
|
||||
return err
|
||||
}
|
182
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/authz/main_test.go
generated
vendored
Normal file
182
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/authz/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,182 @@
|
|||
// +build !windows
|
||||
|
||||
package authz // import "github.com/docker/docker/integration/plugin/authz"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/docker/docker/pkg/authorization"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
)
|
||||
|
||||
var (
|
||||
testEnv *environment.Execution
|
||||
d *daemon.Daemon
|
||||
server *httptest.Server
|
||||
)
|
||||
|
||||
const dockerdBinary = "dockerd"
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
setupSuite()
|
||||
exitCode := m.Run()
|
||||
teardownSuite()
|
||||
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
|
||||
d = daemon.New(t, "", dockerdBinary, daemon.Config{
|
||||
Experimental: testEnv.DaemonInfo.ExperimentalBuild,
|
||||
})
|
||||
|
||||
return func() {
|
||||
if d != nil {
|
||||
d.Stop(t)
|
||||
}
|
||||
testEnv.Clean(t)
|
||||
}
|
||||
}
|
||||
|
||||
func setupSuite() {
|
||||
mux := http.NewServeMux()
|
||||
server = httptest.NewServer(mux)
|
||||
|
||||
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := json.Marshal(plugins.Manifest{Implements: []string{authorization.AuthZApiImplements}})
|
||||
if err != nil {
|
||||
panic("could not marshal json for /Plugin.Activate: " + err.Error())
|
||||
}
|
||||
w.Write(b)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/AuthZPlugin.AuthZReq", func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
panic("could not read body for /AuthZPlugin.AuthZReq: " + err.Error())
|
||||
}
|
||||
authReq := authorization.Request{}
|
||||
err = json.Unmarshal(body, &authReq)
|
||||
if err != nil {
|
||||
panic("could not unmarshal json for /AuthZPlugin.AuthZReq: " + err.Error())
|
||||
}
|
||||
|
||||
assertBody(authReq.RequestURI, authReq.RequestHeaders, authReq.RequestBody)
|
||||
assertAuthHeaders(authReq.RequestHeaders)
|
||||
|
||||
// Count only server version api
|
||||
if strings.HasSuffix(authReq.RequestURI, serverVersionAPI) {
|
||||
ctrl.versionReqCount++
|
||||
}
|
||||
|
||||
ctrl.requestsURIs = append(ctrl.requestsURIs, authReq.RequestURI)
|
||||
|
||||
reqRes := ctrl.reqRes
|
||||
if isAllowed(authReq.RequestURI) {
|
||||
reqRes = authorization.Response{Allow: true}
|
||||
}
|
||||
if reqRes.Err != "" {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
b, err := json.Marshal(reqRes)
|
||||
if err != nil {
|
||||
panic("could not marshal json for /AuthZPlugin.AuthZReq: " + err.Error())
|
||||
}
|
||||
|
||||
ctrl.reqUser = authReq.User
|
||||
w.Write(b)
|
||||
})
|
||||
|
||||
mux.HandleFunc("/AuthZPlugin.AuthZRes", func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
panic("could not read body for /AuthZPlugin.AuthZRes: " + err.Error())
|
||||
}
|
||||
authReq := authorization.Request{}
|
||||
err = json.Unmarshal(body, &authReq)
|
||||
if err != nil {
|
||||
panic("could not unmarshal json for /AuthZPlugin.AuthZRes: " + err.Error())
|
||||
}
|
||||
|
||||
assertBody(authReq.RequestURI, authReq.ResponseHeaders, authReq.ResponseBody)
|
||||
assertAuthHeaders(authReq.ResponseHeaders)
|
||||
|
||||
// Count only server version api
|
||||
if strings.HasSuffix(authReq.RequestURI, serverVersionAPI) {
|
||||
ctrl.versionResCount++
|
||||
}
|
||||
resRes := ctrl.resRes
|
||||
if isAllowed(authReq.RequestURI) {
|
||||
resRes = authorization.Response{Allow: true}
|
||||
}
|
||||
if resRes.Err != "" {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
b, err := json.Marshal(resRes)
|
||||
if err != nil {
|
||||
panic("could not marshal json for /AuthZPlugin.AuthZRes: " + err.Error())
|
||||
}
|
||||
ctrl.resUser = authReq.User
|
||||
w.Write(b)
|
||||
})
|
||||
}
|
||||
|
||||
func teardownSuite() {
|
||||
if server == nil {
|
||||
return
|
||||
}
|
||||
|
||||
server.Close()
|
||||
}
|
||||
|
||||
// assertAuthHeaders validates authentication headers are removed
|
||||
func assertAuthHeaders(headers map[string]string) error {
|
||||
for k := range headers {
|
||||
if strings.Contains(strings.ToLower(k), "auth") || strings.Contains(strings.ToLower(k), "x-registry") {
|
||||
panic(fmt.Sprintf("Found authentication headers in request '%v'", headers))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// assertBody asserts that body is removed for non text/json requests
|
||||
func assertBody(requestURI string, headers map[string]string, body []byte) {
|
||||
if strings.Contains(strings.ToLower(requestURI), "auth") && len(body) > 0 {
|
||||
panic("Body included for authentication endpoint " + string(body))
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
if strings.EqualFold(k, "Content-Type") && strings.HasPrefix(v, "text/") || v == "application/json" {
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(body) > 0 {
|
||||
panic(fmt.Sprintf("Body included while it should not (Headers: '%v')", headers))
|
||||
}
|
||||
}
|
1
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/cmd/cmd_test.go
generated
vendored
Normal file
1
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/cmd/cmd_test.go
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
package cmd
|
19
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/cmd/dummy/main.go
generated
vendored
Normal file
19
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/cmd/dummy/main.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l, err := net.Listen("unix", "/run/docker/plugins/plugin.sock")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
server := http.Server{
|
||||
Addr: l.Addr().String(),
|
||||
Handler: http.NewServeMux(),
|
||||
}
|
||||
server.Serve(l)
|
||||
}
|
1
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/cmd/dummy/main_test.go
generated
vendored
Normal file
1
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/cmd/dummy/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
package main
|
69
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/helpers_test.go
generated
vendored
Normal file
69
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/helpers_test.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration-cli/fixtures/plugin"
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const dockerdBinary = "dockerd"
|
||||
|
||||
var pluginBuildLock = locker.New()
|
||||
|
||||
func ensurePlugin(t *testing.T, name string) string {
|
||||
pluginBuildLock.Lock(name)
|
||||
defer pluginBuildLock.Unlock(name)
|
||||
|
||||
installPath := filepath.Join(os.Getenv("GOPATH"), "bin", name)
|
||||
if _, err := os.Stat(installPath); err == nil {
|
||||
return installPath
|
||||
}
|
||||
|
||||
goBin, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(goBin, "build", "-o", installPath, "./"+filepath.Join("cmd", name))
|
||||
cmd.Env = append(cmd.Env, "CGO_ENABLED=0")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatal(errors.Wrapf(err, "error building basic plugin bin: %s", string(out)))
|
||||
}
|
||||
|
||||
return installPath
|
||||
}
|
||||
|
||||
func withSockPath(name string) func(*plugin.Config) {
|
||||
return func(cfg *plugin.Config) {
|
||||
cfg.Interface.Socket = name
|
||||
}
|
||||
}
|
||||
|
||||
func createPlugin(t *testing.T, client plugin.CreateClient, alias, bin string, opts ...plugin.CreateOpt) {
|
||||
pluginBin := ensurePlugin(t, bin)
|
||||
|
||||
opts = append(opts, withSockPath("plugin.sock"))
|
||||
opts = append(opts, plugin.WithBinary(pluginBin))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
err := plugin.Create(ctx, client, alias, opts...)
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func asLogDriver(cfg *plugin.Config) {
|
||||
cfg.Interface.Types = []types.PluginInterfaceType{
|
||||
{Capability: "logdriver", Prefix: "docker", Version: "1.0"},
|
||||
}
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/validation_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/logging/validation_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
// Regression test for #35553
|
||||
// Ensure that a daemon with a log plugin set as the default logger for containers
|
||||
// does not keep the daemon from starting.
|
||||
func TestDaemonStartWithLogOpt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
d := daemon.New(t, "", dockerdBinary, daemon.Config{})
|
||||
d.Start(t, "--iptables=false")
|
||||
defer d.Stop(t)
|
||||
|
||||
client, err := d.NewClient()
|
||||
assert.Check(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
createPlugin(t, client, "test", "dummy", asLogDriver)
|
||||
err = client.PluginEnable(ctx, "test", types.PluginEnableOptions{Timeout: 30})
|
||||
assert.Check(t, err)
|
||||
defer client.PluginRemove(ctx, "test", types.PluginRemoveOptions{Force: true})
|
||||
|
||||
d.Stop(t)
|
||||
d.Start(t, "--iptables=false", "--log-driver=test", "--log-opt=foo=bar")
|
||||
}
|
1
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/pkg_test.go
generated
vendored
Normal file
1
vendor/github.com/docker/docker-ce/components/engine/integration/plugin/pkg_test.go
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
package plugin // import "github.com/docker/docker/integration/plugin"
|
35
vendor/github.com/docker/docker-ce/components/engine/integration/secret/main_test.go
generated
vendored
Normal file
35
vendor/github.com/docker/docker-ce/components/engine/integration/secret/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
package secret // import "github.com/docker/docker/integration/secret"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
const dockerdBinary = "dockerd"
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
367
vendor/github.com/docker/docker-ce/components/engine/integration/secret/secret_test.go
generated
vendored
Normal file
367
vendor/github.com/docker/docker-ce/components/engine/integration/secret/secret_test.go
generated
vendored
Normal file
|
@ -0,0 +1,367 @@
|
|||
package secret // import "github.com/docker/docker/integration/secret"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/swarm"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestSecretInspect(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_secret"
|
||||
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
secret, _, err := client.SecretInspectWithRaw(context.Background(), secretID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(secret.Spec.Name, testName))
|
||||
|
||||
secret, _, err = client.SecretInspectWithRaw(context.Background(), testName)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(secretID, secretID))
|
||||
}
|
||||
|
||||
func TestSecretList(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName0 := "test0"
|
||||
testName1 := "test1"
|
||||
testNames := []string{testName0, testName1}
|
||||
sort.Strings(testNames)
|
||||
|
||||
// create secret test0
|
||||
createSecret(ctx, t, client, testName0, []byte("TESTINGDATA0"), map[string]string{"type": "test"})
|
||||
|
||||
// create secret test1
|
||||
secret1ID := createSecret(ctx, t, client, testName1, []byte("TESTINGDATA1"), map[string]string{"type": "production"})
|
||||
|
||||
names := func(entries []swarmtypes.Secret) []string {
|
||||
values := []string{}
|
||||
for _, entry := range entries {
|
||||
values = append(values, entry.Spec.Name)
|
||||
}
|
||||
sort.Strings(values)
|
||||
return values
|
||||
}
|
||||
|
||||
// test by `secret ls`
|
||||
entries, err := client.SecretList(ctx, types.SecretListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(names(entries), testNames))
|
||||
|
||||
testCases := []struct {
|
||||
filters filters.Args
|
||||
expected []string
|
||||
}{
|
||||
// test filter by name `secret ls --filter name=xxx`
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("name", testName0)),
|
||||
expected: []string{testName0},
|
||||
},
|
||||
// test filter by id `secret ls --filter id=xxx`
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("id", secret1ID)),
|
||||
expected: []string{testName1},
|
||||
},
|
||||
// test filter by label `secret ls --filter label=xxx`
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("label", "type")),
|
||||
expected: testNames,
|
||||
},
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("label", "type=test")),
|
||||
expected: []string{testName0},
|
||||
},
|
||||
{
|
||||
filters: filters.NewArgs(filters.Arg("label", "type=production")),
|
||||
expected: []string{testName1},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
entries, err = client.SecretList(ctx, types.SecretListOptions{
|
||||
Filters: tc.filters,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(names(entries), tc.expected))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func createSecret(ctx context.Context, t *testing.T, client client.APIClient, name string, data []byte, labels map[string]string) string {
|
||||
secret, err := client.SecretCreate(ctx, swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: name,
|
||||
Labels: labels,
|
||||
},
|
||||
Data: data,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, secret.ID != "")
|
||||
return secret.ID
|
||||
}
|
||||
|
||||
func TestSecretsCreateAndDelete(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_secret"
|
||||
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
// create an already existin secret, daemon should return a status code of 409
|
||||
_, err = client.SecretCreate(ctx, swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: testName,
|
||||
},
|
||||
Data: []byte("TESTINGDATA"),
|
||||
})
|
||||
testutil.ErrorContains(t, err, "already exists")
|
||||
|
||||
// Ported from original TestSecretsDelete
|
||||
err = client.SecretRemove(ctx, secretID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
||||
testutil.ErrorContains(t, err, "No such secret")
|
||||
|
||||
err = client.SecretRemove(ctx, "non-existin")
|
||||
testutil.ErrorContains(t, err, "No such secret: non-existin")
|
||||
|
||||
// Ported from original TestSecretsCreteaWithLabels
|
||||
testName = "test_secret_with_labels"
|
||||
secretID = createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
})
|
||||
|
||||
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Name, testName))
|
||||
assert.Check(t, is.Equal(len(insp.Spec.Labels), 2))
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["key1"], "value1"))
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["key2"], "value2"))
|
||||
}
|
||||
|
||||
func TestSecretsUpdate(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_secret"
|
||||
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.ID, secretID))
|
||||
|
||||
// test UpdateSecret with full ID
|
||||
insp.Spec.Labels = map[string]string{"test": "test1"}
|
||||
err = client.SecretUpdate(ctx, secretID, insp.Version, insp.Spec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test1"))
|
||||
|
||||
// test UpdateSecret with full name
|
||||
insp.Spec.Labels = map[string]string{"test": "test2"}
|
||||
err = client.SecretUpdate(ctx, testName, insp.Version, insp.Spec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test2"))
|
||||
|
||||
// test UpdateSecret with prefix ID
|
||||
insp.Spec.Labels = map[string]string{"test": "test3"}
|
||||
err = client.SecretUpdate(ctx, secretID[:1], insp.Version, insp.Spec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
insp, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Labels["test"], "test3"))
|
||||
|
||||
// test UpdateSecret in updating Data which is not supported in daemon
|
||||
// this test will produce an error in func UpdateSecret
|
||||
insp.Spec.Data = []byte("TESTINGDATA2")
|
||||
err = client.SecretUpdate(ctx, secretID, insp.Version, insp.Spec)
|
||||
testutil.ErrorContains(t, err, "only updates to Labels are allowed")
|
||||
}
|
||||
|
||||
func TestTemplatedSecret(t *testing.T) {
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
|
||||
ctx := context.Background()
|
||||
client := swarm.GetClient(t, d)
|
||||
|
||||
referencedSecretSpec := swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "referencedsecret",
|
||||
},
|
||||
Data: []byte("this is a secret"),
|
||||
}
|
||||
referencedSecret, err := client.SecretCreate(ctx, referencedSecretSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
referencedConfigSpec := swarmtypes.ConfigSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "referencedconfig",
|
||||
},
|
||||
Data: []byte("this is a config"),
|
||||
}
|
||||
referencedConfig, err := client.ConfigCreate(ctx, referencedConfigSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
secretSpec := swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "templated_secret",
|
||||
},
|
||||
Templating: &swarmtypes.Driver{
|
||||
Name: "golang",
|
||||
},
|
||||
Data: []byte("SERVICE_NAME={{.Service.Name}}\n" +
|
||||
"{{secret \"referencedsecrettarget\"}}\n" +
|
||||
"{{config \"referencedconfigtarget\"}}\n"),
|
||||
}
|
||||
|
||||
templatedSecret, err := client.SecretCreate(ctx, secretSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
serviceID := swarm.CreateService(t, d,
|
||||
swarm.ServiceWithSecret(
|
||||
&swarmtypes.SecretReference{
|
||||
File: &swarmtypes.SecretReferenceFileTarget{
|
||||
Name: "templated_secret",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0600,
|
||||
},
|
||||
SecretID: templatedSecret.ID,
|
||||
SecretName: "templated_secret",
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithConfig(
|
||||
&swarmtypes.ConfigReference{
|
||||
File: &swarmtypes.ConfigReferenceFileTarget{
|
||||
Name: "referencedconfigtarget",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0600,
|
||||
},
|
||||
ConfigID: referencedConfig.ID,
|
||||
ConfigName: "referencedconfig",
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithSecret(
|
||||
&swarmtypes.SecretReference{
|
||||
File: &swarmtypes.SecretReferenceFileTarget{
|
||||
Name: "referencedsecrettarget",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0600,
|
||||
},
|
||||
SecretID: referencedSecret.ID,
|
||||
SecretName: "referencedsecret",
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithName("svc"),
|
||||
)
|
||||
|
||||
var tasks []swarmtypes.Task
|
||||
waitAndAssert(t, 60*time.Second, func(t *testing.T) bool {
|
||||
tasks = swarm.GetRunningTasks(t, d, serviceID)
|
||||
return len(tasks) > 0
|
||||
})
|
||||
|
||||
task := tasks[0]
|
||||
waitAndAssert(t, 60*time.Second, func(t *testing.T) bool {
|
||||
if task.NodeID == "" || (task.Status.ContainerStatus == nil || task.Status.ContainerStatus.ContainerID == "") {
|
||||
task, _, _ = client.TaskInspectWithRaw(context.Background(), task.ID)
|
||||
}
|
||||
return task.NodeID != "" && task.Status.ContainerStatus != nil && task.Status.ContainerStatus.ContainerID != ""
|
||||
})
|
||||
|
||||
attach := swarm.ExecTask(t, d, task, types.ExecConfig{
|
||||
Cmd: []string{"/bin/cat", "/run/secrets/templated_secret"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
})
|
||||
|
||||
expect := "SERVICE_NAME=svc\n" +
|
||||
"this is a secret\n" +
|
||||
"this is a config\n"
|
||||
assertAttachedStream(t, attach, expect)
|
||||
|
||||
attach = swarm.ExecTask(t, d, task, types.ExecConfig{
|
||||
Cmd: []string{"mount"},
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
})
|
||||
assertAttachedStream(t, attach, "tmpfs on /run/secrets/templated_secret type tmpfs")
|
||||
}
|
||||
|
||||
func assertAttachedStream(t *testing.T, attach types.HijackedResponse, expect string) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
_, err := stdcopy.StdCopy(buf, buf, attach.Reader)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(buf.String(), expect))
|
||||
}
|
||||
|
||||
func waitAndAssert(t *testing.T, timeout time.Duration, f func(*testing.T) bool) {
|
||||
t.Helper()
|
||||
after := time.After(timeout)
|
||||
for {
|
||||
select {
|
||||
case <-after:
|
||||
t.Fatalf("timed out waiting for condition")
|
||||
default:
|
||||
}
|
||||
if f(t) {
|
||||
return
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
391
vendor/github.com/docker/docker-ce/components/engine/integration/service/create_test.go
generated
vendored
Normal file
391
vendor/github.com/docker/docker-ce/components/engine/integration/service/create_test.go
generated
vendored
Normal file
|
@ -0,0 +1,391 @@
|
|||
package service // import "github.com/docker/docker/integration/service"
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/swarm"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestCreateServiceMultipleTimes(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
overlayName := "overlay1"
|
||||
networkCreate := types.NetworkCreate{
|
||||
CheckDuplicate: true,
|
||||
Driver: "overlay",
|
||||
}
|
||||
|
||||
netResp, err := client.NetworkCreate(context.Background(), overlayName, networkCreate)
|
||||
assert.NilError(t, err)
|
||||
overlayID := netResp.ID
|
||||
|
||||
var instances uint64 = 4
|
||||
serviceSpec := swarmServiceSpec("TestService", instances)
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarmtypes.NetworkAttachmentConfig{Target: overlayName})
|
||||
|
||||
serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
pollSettings := func(config *poll.Settings) {
|
||||
// It takes about ~25s to finish the multi services creation in this case per the pratical observation on arm64/arm platform
|
||||
if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
|
||||
config.Timeout = 30 * time.Second
|
||||
config.Delay = 100 * time.Millisecond
|
||||
}
|
||||
}
|
||||
|
||||
serviceID := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), pollSettings)
|
||||
|
||||
_, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
serviceResp, err = client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
serviceID2 := serviceResp.ID
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), pollSettings)
|
||||
|
||||
err = client.ServiceRemove(context.Background(), serviceID2)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceID2), pollSettings)
|
||||
poll.WaitOn(t, noTasks(client), pollSettings)
|
||||
|
||||
err = client.NetworkRemove(context.Background(), overlayID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
|
||||
}
|
||||
|
||||
func TestCreateWithDuplicateNetworkNames(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
name := "foo"
|
||||
networkCreate := types.NetworkCreate{
|
||||
CheckDuplicate: false,
|
||||
Driver: "bridge",
|
||||
}
|
||||
|
||||
n1, err := client.NetworkCreate(context.Background(), name, networkCreate)
|
||||
assert.NilError(t, err)
|
||||
|
||||
n2, err := client.NetworkCreate(context.Background(), name, networkCreate)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Dupliates with name but with different driver
|
||||
networkCreate.Driver = "overlay"
|
||||
n3, err := client.NetworkCreate(context.Background(), name, networkCreate)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Create Service with the same name
|
||||
var instances uint64 = 1
|
||||
serviceSpec := swarmServiceSpec("top", instances)
|
||||
|
||||
serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarmtypes.NetworkAttachmentConfig{Target: name})
|
||||
|
||||
service, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, service.ID, instances))
|
||||
|
||||
resp, _, err := client.ServiceInspectWithRaw(context.Background(), service.ID, types.ServiceInspectOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(n3.ID, resp.Spec.TaskTemplate.Networks[0].Target))
|
||||
|
||||
// Remove Service
|
||||
err = client.ServiceRemove(context.Background(), service.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Make sure task has been destroyed.
|
||||
poll.WaitOn(t, serviceIsRemoved(client, service.ID))
|
||||
|
||||
// Remove networks
|
||||
err = client.NetworkRemove(context.Background(), n3.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.NetworkRemove(context.Background(), n2.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.NetworkRemove(context.Background(), n1.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Make sure networks have been destroyed.
|
||||
poll.WaitOn(t, networkIsRemoved(client, n3.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
|
||||
poll.WaitOn(t, networkIsRemoved(client, n2.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
|
||||
poll.WaitOn(t, networkIsRemoved(client, n1.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
|
||||
}
|
||||
|
||||
func TestCreateServiceSecretFileMode(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
secretResp, err := client.SecretCreate(ctx, swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "TestSecret",
|
||||
},
|
||||
Data: []byte("TESTSECRET"),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
var instances uint64 = 1
|
||||
serviceSpec := swarmtypes.ServiceSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "TestService",
|
||||
},
|
||||
TaskTemplate: swarmtypes.TaskSpec{
|
||||
ContainerSpec: &swarmtypes.ContainerSpec{
|
||||
Image: "busybox:latest",
|
||||
Command: []string{"/bin/sh", "-c", "ls -l /etc/secret || /bin/top"},
|
||||
Secrets: []*swarmtypes.SecretReference{
|
||||
{
|
||||
File: &swarmtypes.SecretReferenceFileTarget{
|
||||
Name: "/etc/secret",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0777,
|
||||
},
|
||||
SecretID: secretResp.ID,
|
||||
SecretName: "TestSecret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Mode: swarmtypes.ServiceMode{
|
||||
Replicated: &swarmtypes.ReplicatedService{
|
||||
Replicas: &instances,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
serviceResp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, serviceResp.ID, instances))
|
||||
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceResp.ID)
|
||||
tasks, err := client.TaskList(ctx, types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(tasks), 1))
|
||||
|
||||
body, err := client.ContainerLogs(ctx, tasks[0].Status.ContainerStatus.ContainerID, types.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
defer body.Close()
|
||||
|
||||
content, err := ioutil.ReadAll(body)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(string(content), "-rwxrwxrwx"))
|
||||
|
||||
err = client.ServiceRemove(ctx, serviceResp.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceResp.ID))
|
||||
poll.WaitOn(t, noTasks(client))
|
||||
|
||||
err = client.SecretRemove(ctx, "TestSecret")
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestCreateServiceConfigFileMode(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.Background()
|
||||
configResp, err := client.ConfigCreate(ctx, swarmtypes.ConfigSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "TestConfig",
|
||||
},
|
||||
Data: []byte("TESTCONFIG"),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
var instances uint64 = 1
|
||||
serviceSpec := swarmtypes.ServiceSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "TestService",
|
||||
},
|
||||
TaskTemplate: swarmtypes.TaskSpec{
|
||||
ContainerSpec: &swarmtypes.ContainerSpec{
|
||||
Image: "busybox:latest",
|
||||
Command: []string{"/bin/sh", "-c", "ls -l /etc/config || /bin/top"},
|
||||
Configs: []*swarmtypes.ConfigReference{
|
||||
{
|
||||
File: &swarmtypes.ConfigReferenceFileTarget{
|
||||
Name: "/etc/config",
|
||||
UID: "0",
|
||||
GID: "0",
|
||||
Mode: 0777,
|
||||
},
|
||||
ConfigID: configResp.ID,
|
||||
ConfigName: "TestConfig",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Mode: swarmtypes.ServiceMode{
|
||||
Replicated: &swarmtypes.ReplicatedService{
|
||||
Replicas: &instances,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
serviceResp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceRunningTasksCount(client, serviceResp.ID, instances))
|
||||
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceResp.ID)
|
||||
tasks, err := client.TaskList(ctx, types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(tasks), 1))
|
||||
|
||||
body, err := client.ContainerLogs(ctx, tasks[0].Status.ContainerStatus.ContainerID, types.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
defer body.Close()
|
||||
|
||||
content, err := ioutil.ReadAll(body)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(string(content), "-rwxrwxrwx"))
|
||||
|
||||
err = client.ServiceRemove(ctx, serviceResp.ID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
poll.WaitOn(t, serviceIsRemoved(client, serviceResp.ID))
|
||||
poll.WaitOn(t, noTasks(client))
|
||||
|
||||
err = client.ConfigRemove(ctx, "TestConfig")
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func swarmServiceSpec(name string, replicas uint64) swarmtypes.ServiceSpec {
|
||||
return swarmtypes.ServiceSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: name,
|
||||
},
|
||||
TaskTemplate: swarmtypes.TaskSpec{
|
||||
ContainerSpec: &swarmtypes.ContainerSpec{
|
||||
Image: "busybox:latest",
|
||||
Command: []string{"/bin/top"},
|
||||
},
|
||||
},
|
||||
Mode: swarmtypes.ServiceMode{
|
||||
Replicated: &swarmtypes.ReplicatedService{
|
||||
Replicas: &replicas,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceID)
|
||||
tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case len(tasks) == int(instances):
|
||||
for _, task := range tasks {
|
||||
if task.Status.State != swarmtypes.TaskStateRunning {
|
||||
return poll.Continue("waiting for tasks to enter run state")
|
||||
}
|
||||
}
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("task count at %d waiting for %d", len(tasks), instances)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case len(tasks) == 0:
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("task count at %d waiting for 0", len(tasks))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", serviceID)
|
||||
_, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
if err == nil {
|
||||
return poll.Continue("waiting for service %s to be deleted", serviceID)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
||||
|
||||
func networkIsRemoved(client client.NetworkAPIClient, networkID string) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
_, err := client.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
|
||||
if err == nil {
|
||||
return poll.Continue("waiting for network %s to be removed", networkID)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
}
|
153
vendor/github.com/docker/docker-ce/components/engine/integration/service/inspect_test.go
generated
vendored
Normal file
153
vendor/github.com/docker/docker-ce/components/engine/integration/service/inspect_test.go
generated
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
package service // import "github.com/docker/docker/integration/service"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/swarm"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/poll"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestInspect(t *testing.T) {
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
|
||||
var now = time.Now()
|
||||
var instances uint64 = 2
|
||||
serviceSpec := fullSwarmServiceSpec("test-service-inspect", instances)
|
||||
|
||||
ctx := context.Background()
|
||||
resp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{
|
||||
QueryRegistry: false,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
id := resp.ID
|
||||
poll.WaitOn(t, serviceContainerCount(client, id, instances))
|
||||
|
||||
service, _, err := client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := swarmtypes.Service{
|
||||
ID: id,
|
||||
Spec: serviceSpec,
|
||||
Meta: swarmtypes.Meta{
|
||||
Version: swarmtypes.Version{Index: uint64(11)},
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
}
|
||||
assert.Check(t, is.DeepEqual(service, expected, cmpServiceOpts()))
|
||||
}
|
||||
|
||||
// TODO: use helpers from gotestyourself/assert/opt when available
|
||||
func cmpServiceOpts() cmp.Option {
|
||||
const threshold = 20 * time.Second
|
||||
|
||||
metaTimeFields := func(path cmp.Path) bool {
|
||||
switch path.String() {
|
||||
case "Meta.CreatedAt", "Meta.UpdatedAt":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
withinThreshold := cmp.Comparer(func(x, y time.Time) bool {
|
||||
delta := x.Sub(y)
|
||||
return delta < threshold && delta > -threshold
|
||||
})
|
||||
|
||||
return cmp.FilterPath(metaTimeFields, withinThreshold)
|
||||
}
|
||||
|
||||
func fullSwarmServiceSpec(name string, replicas uint64) swarmtypes.ServiceSpec {
|
||||
restartDelay := 100 * time.Millisecond
|
||||
maxAttempts := uint64(4)
|
||||
|
||||
return swarmtypes.ServiceSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: name,
|
||||
Labels: map[string]string{
|
||||
"service-label": "service-label-value",
|
||||
},
|
||||
},
|
||||
TaskTemplate: swarmtypes.TaskSpec{
|
||||
ContainerSpec: &swarmtypes.ContainerSpec{
|
||||
Image: "busybox:latest",
|
||||
Labels: map[string]string{"container-label": "container-value"},
|
||||
Command: []string{"/bin/top"},
|
||||
Args: []string{"-u", "root"},
|
||||
Hostname: "hostname",
|
||||
Env: []string{"envvar=envvalue"},
|
||||
Dir: "/work",
|
||||
User: "root",
|
||||
StopSignal: "SIGINT",
|
||||
StopGracePeriod: &restartDelay,
|
||||
Hosts: []string{"8.8.8.8 google"},
|
||||
DNSConfig: &swarmtypes.DNSConfig{
|
||||
Nameservers: []string{"8.8.8.8"},
|
||||
Search: []string{"somedomain"},
|
||||
},
|
||||
Isolation: container.IsolationDefault,
|
||||
},
|
||||
RestartPolicy: &swarmtypes.RestartPolicy{
|
||||
Delay: &restartDelay,
|
||||
Condition: swarmtypes.RestartPolicyConditionOnFailure,
|
||||
MaxAttempts: &maxAttempts,
|
||||
},
|
||||
Runtime: swarmtypes.RuntimeContainer,
|
||||
},
|
||||
Mode: swarmtypes.ServiceMode{
|
||||
Replicated: &swarmtypes.ReplicatedService{
|
||||
Replicas: &replicas,
|
||||
},
|
||||
},
|
||||
UpdateConfig: &swarmtypes.UpdateConfig{
|
||||
Parallelism: 2,
|
||||
Delay: 200 * time.Second,
|
||||
FailureAction: swarmtypes.UpdateFailureActionContinue,
|
||||
Monitor: 2 * time.Second,
|
||||
MaxFailureRatio: 0.2,
|
||||
Order: swarmtypes.UpdateOrderStopFirst,
|
||||
},
|
||||
RollbackConfig: &swarmtypes.UpdateConfig{
|
||||
Parallelism: 3,
|
||||
Delay: 300 * time.Second,
|
||||
FailureAction: swarmtypes.UpdateFailureActionPause,
|
||||
Monitor: 3 * time.Second,
|
||||
MaxFailureRatio: 0.3,
|
||||
Order: swarmtypes.UpdateOrderStartFirst,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func serviceContainerCount(client client.ServiceAPIClient, id string, count uint64) func(log poll.LogT) poll.Result {
|
||||
return func(log poll.LogT) poll.Result {
|
||||
filter := filters.NewArgs()
|
||||
filter.Add("service", id)
|
||||
tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
|
||||
Filters: filter,
|
||||
})
|
||||
switch {
|
||||
case err != nil:
|
||||
return poll.Error(err)
|
||||
case len(tasks) == int(count):
|
||||
return poll.Success()
|
||||
default:
|
||||
return poll.Continue("task count at %d waiting for %d", len(tasks), count)
|
||||
}
|
||||
}
|
||||
}
|
35
vendor/github.com/docker/docker-ce/components/engine/integration/service/main_test.go
generated
vendored
Normal file
35
vendor/github.com/docker/docker-ce/components/engine/integration/service/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
package service // import "github.com/docker/docker/integration/service"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
const dockerdBinary = "dockerd"
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
76
vendor/github.com/docker/docker-ce/components/engine/integration/service/network_test.go
generated
vendored
Normal file
76
vendor/github.com/docker/docker-ce/components/engine/integration/service/network_test.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
package service // import "github.com/docker/docker/integration/service"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/swarm"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestDockerNetworkConnectAlias(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||
assert.NilError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
name := "test-alias"
|
||||
_, err = client.NetworkCreate(ctx, name, types.NetworkCreate{
|
||||
Driver: "overlay",
|
||||
Attachable: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
container.Create(t, ctx, client, container.WithName("ng1"), func(c *container.TestContainerConfig) {
|
||||
c.NetworkingConfig = &network.NetworkingConfig{
|
||||
map[string]*network.EndpointSettings{
|
||||
name: {},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
err = client.NetworkConnect(ctx, name, "ng1", &network.EndpointSettings{
|
||||
Aliases: []string{
|
||||
"aaa",
|
||||
},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ContainerStart(ctx, "ng1", types.ContainerStartOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
ng1, err := client.ContainerInspect(ctx, "ng1")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(ng1.NetworkSettings.Networks[name].Aliases), 2))
|
||||
assert.Check(t, is.Equal(ng1.NetworkSettings.Networks[name].Aliases[0], "aaa"))
|
||||
|
||||
container.Create(t, ctx, client, container.WithName("ng2"), func(c *container.TestContainerConfig) {
|
||||
c.NetworkingConfig = &network.NetworkingConfig{
|
||||
map[string]*network.EndpointSettings{
|
||||
name: {},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
err = client.NetworkConnect(ctx, name, "ng2", &network.EndpointSettings{
|
||||
Aliases: []string{
|
||||
"bbb",
|
||||
},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ContainerStart(ctx, "ng2", types.ContainerStartOptions{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
ng2, err := client.ContainerInspect(ctx, "ng2")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(len(ng2.NetworkSettings.Networks[name].Aliases), 2))
|
||||
assert.Check(t, is.Equal(ng2.NetworkSettings.Networks[name].Aliases[0], "bbb"))
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/session/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/session/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package session // import "github.com/docker/docker/integration/session"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
48
vendor/github.com/docker/docker-ce/components/engine/integration/session/session_test.go
generated
vendored
Normal file
48
vendor/github.com/docker/docker-ce/components/engine/integration/session/session_test.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package session // import "github.com/docker/docker/integration/session"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
req "github.com/docker/docker/integration-cli/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
)
|
||||
|
||||
func TestSessionCreate(t *testing.T) {
|
||||
skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild)
|
||||
|
||||
defer setupTest(t)()
|
||||
|
||||
res, body, err := req.Post("/session", func(r *http.Request) error {
|
||||
r.Header.Set("X-Docker-Expose-Session-Uuid", "testsessioncreate") // so we don't block default name if something else is using it
|
||||
r.Header.Set("Upgrade", "h2c")
|
||||
return nil
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, body.Close())
|
||||
assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusSwitchingProtocols))
|
||||
assert.Check(t, is.Equal(res.Header.Get("Upgrade"), "h2c"))
|
||||
}
|
||||
|
||||
func TestSessionCreateWithBadUpgrade(t *testing.T) {
|
||||
skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild)
|
||||
|
||||
res, body, err := req.Post("/session")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusBadRequest))
|
||||
buf, err := req.ReadBody(body)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(string(buf), "no upgrade"))
|
||||
|
||||
res, body, err = req.Post("/session", func(r *http.Request) error {
|
||||
r.Header.Set("Upgrade", "foo")
|
||||
return nil
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusBadRequest))
|
||||
buf, err = req.ReadBody(body)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Contains(string(buf), "not supported"))
|
||||
}
|
119
vendor/github.com/docker/docker-ce/components/engine/integration/system/event_test.go
generated
vendored
Normal file
119
vendor/github.com/docker/docker-ce/components/engine/integration/system/event_test.go
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
req "github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestEvents(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
cID := container.Run(t, ctx, client)
|
||||
|
||||
id, err := client.ContainerExecCreate(ctx, cID,
|
||||
types.ExecConfig{
|
||||
Cmd: strslice.StrSlice([]string{"echo", "hello"}),
|
||||
},
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
filters := filters.NewArgs(
|
||||
filters.Arg("container", cID),
|
||||
filters.Arg("event", "exec_die"),
|
||||
)
|
||||
msg, errors := client.Events(ctx, types.EventsOptions{
|
||||
Filters: filters,
|
||||
})
|
||||
|
||||
err = client.ContainerExecStart(ctx, id.ID,
|
||||
types.ExecStartCheck{
|
||||
Detach: true,
|
||||
Tty: false,
|
||||
},
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
select {
|
||||
case m := <-msg:
|
||||
assert.Equal(t, m.Type, "container")
|
||||
assert.Equal(t, m.Actor.ID, cID)
|
||||
assert.Equal(t, m.Action, "exec_die")
|
||||
assert.Equal(t, m.Actor.Attributes["execID"], id.ID)
|
||||
assert.Equal(t, m.Actor.Attributes["exitCode"], "0")
|
||||
case err = <-errors:
|
||||
t.Fatal(err)
|
||||
case <-time.After(time.Second * 3):
|
||||
t.Fatal("timeout hit")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test case for #18888: Events messages have been switched from generic
|
||||
// `JSONMessage` to `events.Message` types. The switch does not break the
|
||||
// backward compatibility so old `JSONMessage` could still be used.
|
||||
// This test verifies that backward compatibility maintains.
|
||||
func TestEventsBackwardsCompatible(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
ctx := context.Background()
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
since := request.DaemonTime(ctx, t, client, testEnv)
|
||||
ts := strconv.FormatInt(since.Unix(), 10)
|
||||
|
||||
cID := container.Create(t, ctx, client)
|
||||
|
||||
// In case there is no events, the API should have responded immediately (not blocking),
|
||||
// The test here makes sure the response time is less than 3 sec.
|
||||
expectedTime := time.Now().Add(3 * time.Second)
|
||||
emptyResp, emptyBody, err := req.Get("/events")
|
||||
assert.NilError(t, err)
|
||||
defer emptyBody.Close()
|
||||
assert.Check(t, is.DeepEqual(http.StatusOK, emptyResp.StatusCode))
|
||||
assert.Check(t, time.Now().Before(expectedTime), "timeout waiting for events api to respond, should have responded immediately")
|
||||
|
||||
// We also test to make sure the `events.Message` is compatible with `JSONMessage`
|
||||
q := url.Values{}
|
||||
q.Set("since", ts)
|
||||
_, body, err := req.Get("/events?" + q.Encode())
|
||||
assert.NilError(t, err)
|
||||
defer body.Close()
|
||||
|
||||
dec := json.NewDecoder(body)
|
||||
var containerCreateEvent *jsonmessage.JSONMessage
|
||||
for {
|
||||
var event jsonmessage.JSONMessage
|
||||
if err := dec.Decode(&event); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if event.Status == "create" && event.ID == cID {
|
||||
containerCreateEvent = &event
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.Check(t, containerCreateEvent != nil)
|
||||
assert.Check(t, is.Equal("create", containerCreateEvent.Status))
|
||||
assert.Check(t, is.Equal(cID, containerCreateEvent.ID))
|
||||
assert.Check(t, is.Equal("busybox", containerCreateEvent.From))
|
||||
}
|
48
vendor/github.com/docker/docker-ce/components/engine/integration/system/info_linux_test.go
generated
vendored
Normal file
48
vendor/github.com/docker/docker-ce/components/engine/integration/system/info_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
// +build !windows
|
||||
|
||||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
req "github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestInfoBinaryCommits(t *testing.T) {
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
info, err := client.Info(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, "N/A" != info.ContainerdCommit.ID)
|
||||
assert.Check(t, is.Equal(testEnv.DaemonInfo.ContainerdCommit.Expected, info.ContainerdCommit.Expected))
|
||||
assert.Check(t, is.Equal(info.ContainerdCommit.Expected, info.ContainerdCommit.ID))
|
||||
|
||||
assert.Check(t, "N/A" != info.InitCommit.ID)
|
||||
assert.Check(t, is.Equal(testEnv.DaemonInfo.InitCommit.Expected, info.InitCommit.Expected))
|
||||
assert.Check(t, is.Equal(info.InitCommit.Expected, info.InitCommit.ID))
|
||||
|
||||
assert.Check(t, "N/A" != info.RuncCommit.ID)
|
||||
assert.Check(t, is.Equal(testEnv.DaemonInfo.RuncCommit.Expected, info.RuncCommit.Expected))
|
||||
assert.Check(t, is.Equal(info.RuncCommit.Expected, info.RuncCommit.ID))
|
||||
}
|
||||
|
||||
func TestInfoAPIVersioned(t *testing.T) {
|
||||
// Windows only supports 1.25 or later
|
||||
|
||||
res, body, err := req.Get("/v1.20/info")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusOK))
|
||||
|
||||
b, err := req.ReadBody(body)
|
||||
assert.NilError(t, err)
|
||||
|
||||
out := string(b)
|
||||
assert.Check(t, is.Contains(out, "ExecutionDriver"))
|
||||
assert.Check(t, is.Contains(out, "not supported"))
|
||||
}
|
42
vendor/github.com/docker/docker-ce/components/engine/integration/system/info_test.go
generated
vendored
Normal file
42
vendor/github.com/docker/docker-ce/components/engine/integration/system/info_test.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestInfoAPI(t *testing.T) {
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
info, err := client.Info(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
// always shown fields
|
||||
stringsToCheck := []string{
|
||||
"ID",
|
||||
"Containers",
|
||||
"ContainersRunning",
|
||||
"ContainersPaused",
|
||||
"ContainersStopped",
|
||||
"Images",
|
||||
"LoggingDriver",
|
||||
"OperatingSystem",
|
||||
"NCPU",
|
||||
"OSType",
|
||||
"Architecture",
|
||||
"MemTotal",
|
||||
"KernelVersion",
|
||||
"Driver",
|
||||
"ServerVersion",
|
||||
"SecurityOptions"}
|
||||
|
||||
out := fmt.Sprintf("%+v", info)
|
||||
for _, linePrefix := range stringsToCheck {
|
||||
assert.Check(t, is.Contains(out, linePrefix))
|
||||
}
|
||||
}
|
28
vendor/github.com/docker/docker-ce/components/engine/integration/system/login_test.go
generated
vendored
Normal file
28
vendor/github.com/docker/docker-ce/components/engine/integration/system/login_test.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/integration/internal/requirement"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"github.com/gotestyourself/gotestyourself/skip"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Test case for GitHub 22244
|
||||
func TestLoginFailsWithBadCredentials(t *testing.T) {
|
||||
skip.IfCondition(t, !requirement.HasHubConnectivity(t))
|
||||
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
config := types.AuthConfig{
|
||||
Username: "no-user",
|
||||
Password: "no-password",
|
||||
}
|
||||
_, err := client.RegistryLogin(context.Background(), config)
|
||||
expected := "Error response from daemon: Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password"
|
||||
assert.Check(t, is.Error(err, expected))
|
||||
}
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/system/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/system/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
23
vendor/github.com/docker/docker-ce/components/engine/integration/system/version_test.go
generated
vendored
Normal file
23
vendor/github.com/docker/docker-ce/components/engine/integration/system/version_test.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
client := request.NewAPIClient(t)
|
||||
|
||||
version, err := client.ServerVersion(context.Background())
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, version.APIVersion != "")
|
||||
assert.Check(t, version.Version != "")
|
||||
assert.Check(t, version.MinAPIVersion != "")
|
||||
assert.Check(t, is.Equal(testEnv.DaemonInfo.ExperimentalBuild, version.Experimental))
|
||||
assert.Check(t, is.Equal(testEnv.OSType, version.Os))
|
||||
}
|
23
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/ca.pem
generated
vendored
Normal file
23
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/ca.pem
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIID0TCCAzqgAwIBAgIJAP2r7GqEJwSnMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMG
|
||||
A1UEChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTERMA8GA1UEAxMI
|
||||
Y2hhbmdlbWUxETAPBgNVBCkTCGNoYW5nZW1lMR8wHQYJKoZIhvcNAQkBFhBtYWls
|
||||
QGhvc3QuZG9tYWluMB4XDTEzMTIwMzE2NTYzMFoXDTIzMTIwMTE2NTYzMFowgaIx
|
||||
CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2Nv
|
||||
MRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMREwDwYD
|
||||
VQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEW
|
||||
EG1haWxAaG9zdC5kb21haW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALAn
|
||||
0xDw+5y7ZptQacq66pUhRu82JP2WU6IDgo5QUtNU6/CX5PwQATe/OnYTZQFbksxp
|
||||
AU9boG0FCkgxfsgPYXEuZxVEGKI2fxfKHOZZI8mrkWmj6eWU/0cvCjGVc9rTITP5
|
||||
sNQvg+hORyVDdNp2IdsbMJayiB3AQYMFx3vSDOMTAgMBAAGjggELMIIBBzAdBgNV
|
||||
HQ4EFgQUZu7DFz09q0QBa2+ymRm9qgK1NPswgdcGA1UdIwSBzzCBzIAUZu7DFz09
|
||||
q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJD
|
||||
QTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24x
|
||||
ETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMI
|
||||
Y2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQD9q+xq
|
||||
hCcEpzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAF8fJKKM+/oOdnNi
|
||||
zEd0M1+PmZOyqvjYQn/2ZR8UHH6Imgc/OPQKZXf0bVE1Txc/DaUNn9Isd1SuCuaE
|
||||
ic3vAIYYU7PmgeNN6vwec48V96T7jr+GAi6AVMhQEc2hHCfVtx11Xx+x6aHDZzJt
|
||||
Zxtf5lL6KSO9Y+EFwM+rju6hm5hW
|
||||
-----END CERTIFICATE-----
|
73
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/client-cert.pem
generated
vendored
Normal file
73
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/client-cert.pem
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 3 (0x3)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain
|
||||
Validity
|
||||
Not Before: Dec 4 14:17:54 2013 GMT
|
||||
Not After : Dec 2 14:17:54 2023 GMT
|
||||
Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=client/name=changeme/emailAddress=mail@host.domain
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (1024 bit)
|
||||
Modulus:
|
||||
00:ca:c9:05:d0:09:4e:3e:a4:fc:d5:14:f4:a5:e8:
|
||||
34:d3:6b:51:e3:f3:62:ea:a1:f0:e8:ed:c4:2a:bc:
|
||||
f0:4f:ca:07:df:e3:88:fa:f4:21:99:35:0e:3d:ea:
|
||||
b0:86:e7:c4:d2:8a:83:2b:42:b8:ec:a3:99:62:70:
|
||||
81:46:cc:fc:a5:1d:d2:63:e8:eb:07:25:9a:e2:25:
|
||||
6d:11:56:f2:1a:51:a1:b6:3e:1c:57:32:e9:7b:2c:
|
||||
aa:1b:cc:97:2d:89:2d:b1:c9:5e:35:28:4d:7c:fa:
|
||||
65:31:3e:f7:70:dd:6e:0b:3c:58:af:a8:2e:24:c0:
|
||||
7e:4e:78:7d:0a:9e:8f:42:43
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
Netscape Comment:
|
||||
Easy-RSA Generated Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
DE:42:EF:2D:98:A3:6C:A8:AA:E0:8C:71:2C:9D:64:23:A9:E2:7E:81
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:66:EE:C3:17:3D:3D:AB:44:01:6B:6F:B2:99:19:BD:AA:02:B5:34:FB
|
||||
DirName:/C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain
|
||||
serial:FD:AB:EC:6A:84:27:04:A7
|
||||
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Client Authentication
|
||||
X509v3 Key Usage:
|
||||
Digital Signature
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
1c:44:26:ea:e1:66:25:cb:e4:8e:57:1c:f6:b9:17:22:62:40:
|
||||
12:90:8f:3b:b2:61:7a:54:94:8f:b1:20:0b:bf:a3:51:e3:fa:
|
||||
1c:a1:be:92:3a:d0:76:44:c0:57:83:ab:6a:e4:1a:45:49:a4:
|
||||
af:39:0d:60:32:fc:3a:be:d7:fb:5d:99:7a:1f:87:e7:d5:ab:
|
||||
84:a2:5e:90:d8:bf:fa:89:6d:32:26:02:5e:31:35:68:7f:31:
|
||||
f5:6b:51:46:bc:af:70:ed:5a:09:7d:ec:b2:48:4f:fe:c5:2f:
|
||||
56:04:ad:f6:c1:d2:2a:e4:6a:c4:87:fe:08:35:c5:38:cb:5e:
|
||||
4a:c4
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEFTCCA36gAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx
|
||||
CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xFTATBgNVBAoTDEZv
|
||||
cnQtRnVuc3RvbjERMA8GA1UECxMIY2hhbmdlbWUxETAPBgNVBAMTCGNoYW5nZW1l
|
||||
MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRv
|
||||
bWFpbjAeFw0xMzEyMDQxNDE3NTRaFw0yMzEyMDIxNDE3NTRaMIGgMQswCQYDVQQG
|
||||
EwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UE
|
||||
ChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTEPMA0GA1UEAxMGY2xp
|
||||
ZW50MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0
|
||||
LmRvbWFpbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyskF0AlOPqT81RT0
|
||||
peg002tR4/Ni6qHw6O3EKrzwT8oH3+OI+vQhmTUOPeqwhufE0oqDK0K47KOZYnCB
|
||||
Rsz8pR3SY+jrByWa4iVtEVbyGlGhtj4cVzLpeyyqG8yXLYktscleNShNfPplMT73
|
||||
cN1uCzxYr6guJMB+Tnh9Cp6PQkMCAwEAAaOCAVkwggFVMAkGA1UdEwQCMAAwLQYJ
|
||||
YIZIAYb4QgENBCAWHkVhc3ktUlNBIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV
|
||||
HQ4EFgQU3kLvLZijbKiq4IxxLJ1kI6nifoEwgdcGA1UdIwSBzzCBzIAUZu7DFz09
|
||||
q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJD
|
||||
QTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUwEwYDVQQKEwxGb3J0LUZ1bnN0b24x
|
||||
ETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQDEwhjaGFuZ2VtZTERMA8GA1UEKRMI
|
||||
Y2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21haW6CCQD9q+xq
|
||||
hCcEpzATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCB4AwDQYJKoZIhvcN
|
||||
AQEFBQADgYEAHEQm6uFmJcvkjlcc9rkXImJAEpCPO7JhelSUj7EgC7+jUeP6HKG+
|
||||
kjrQdkTAV4OrauQaRUmkrzkNYDL8Or7X+12Zeh+H59WrhKJekNi/+oltMiYCXjE1
|
||||
aH8x9WtRRryvcO1aCX3sskhP/sUvVgSt9sHSKuRqxIf+CDXFOMteSsQ=
|
||||
-----END CERTIFICATE-----
|
16
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/client-key.pem
generated
vendored
Normal file
16
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/client-key.pem
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMrJBdAJTj6k/NUU
|
||||
9KXoNNNrUePzYuqh8OjtxCq88E/KB9/jiPr0IZk1Dj3qsIbnxNKKgytCuOyjmWJw
|
||||
gUbM/KUd0mPo6wclmuIlbRFW8hpRobY+HFcy6XssqhvMly2JLbHJXjUoTXz6ZTE+
|
||||
93Ddbgs8WK+oLiTAfk54fQqej0JDAgMBAAECgYBOFEzKp2qbMEexe9ofL2N3rDDh
|
||||
xkrl8OijpzkLA6i78BxMFn4dsnZlWUpciMrjhsYAExkiRRSS+QMMJimAq1jzQqc3
|
||||
FAQV2XGYwkd0cUn7iZGvfNnEPysjsfyYQM+m+sT0ATj4BZjVShC6kkSjTdm1leLN
|
||||
OSvcHdcu3Xxg9ufF0QJBAPYdnNt5sIndt2WECePuRVi+uF4mlxTobFY0fjn26yhC
|
||||
4RsnhhD3Vldygo9gvnkwrAZYaALGSPBewes2InxvjA8CQQDS7erKiNXpwoqz5XiU
|
||||
SVEsIIVTdWzBjGbIqMOu/hUwM5FK4j6JTBks0aTGMyh0YV9L1EzM0X79J29JahCe
|
||||
iQKNAkBKNMOGqTpBV0hko1sYDk96YobUXG5RL4L6uvkUIQ7mJMQam+AgXXL7Ctuy
|
||||
v0iu4a38e8tgisiTMP7nHHtpaXihAkAOiN54/lzfMsykANgCP9scE1GcoqbP34Dl
|
||||
qttxH4kOPT9xzY1JoLjLYdbc4YGUI3GRpBt2sajygNkmUey7P+2xAkBBsVCZFvTw
|
||||
qHvOpPS2kX5ml5xoc/QAHK9N7kR+X7XFYx82RTVSqJEK4lPb+aEWn+CjiIewO4Q5
|
||||
ksDFuNxAzbhl
|
||||
-----END PRIVATE KEY-----
|
76
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/server-cert.pem
generated
vendored
Normal file
76
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/server-cert.pem
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 4 (0x4)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=changeme/name=changeme/emailAddress=mail@host.domain
|
||||
Validity
|
||||
Not Before: Dec 4 15:01:20 2013 GMT
|
||||
Not After : Dec 2 15:01:20 2023 GMT
|
||||
Subject: C=US, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=changeme, CN=*/name=changeme/emailAddress=mail@host.domain
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (1024 bit)
|
||||
Modulus:
|
||||
00:c1:ff:7d:30:6f:64:4a:b1:92:b1:71:d1:c1:74:
|
||||
e2:1d:db:2d:11:24:e1:00:d4:00:ae:6f:c8:9e:ae:
|
||||
67:b3:4a:bd:f7:e6:9e:57:6d:19:4c:3c:23:94:2d:
|
||||
3d:d6:63:84:d8:fa:76:2b:38:12:c1:ed:20:9d:32:
|
||||
e0:e8:c2:bf:9a:77:70:04:3f:7f:ca:8c:2c:82:d6:
|
||||
3d:25:5c:02:1a:4f:64:93:03:dd:9c:42:97:5e:09:
|
||||
49:af:f0:c2:e1:30:08:0e:21:46:95:d1:13:59:c0:
|
||||
c8:76:be:94:0d:8b:43:67:21:33:b2:08:60:9d:76:
|
||||
a8:05:32:1e:f9:95:09:14:75
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
Netscape Cert Type:
|
||||
SSL Server
|
||||
Netscape Comment:
|
||||
Easy-RSA Generated Server Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
14:02:FD:FD:DD:13:38:E0:71:EA:D1:BE:C0:0E:89:1A:2D:B6:19:06
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:66:EE:C3:17:3D:3D:AB:44:01:6B:6F:B2:99:19:BD:AA:02:B5:34:FB
|
||||
DirName:/C=US/ST=CA/L=SanFrancisco/O=Fort-Funston/OU=changeme/CN=changeme/name=changeme/emailAddress=mail@host.domain
|
||||
serial:FD:AB:EC:6A:84:27:04:A7
|
||||
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication
|
||||
X509v3 Key Usage:
|
||||
Digital Signature, Key Encipherment
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
40:0f:10:39:c4:b7:0f:0d:2f:bf:d2:16:cc:8e:d3:9a:fb:8b:
|
||||
ce:4b:7b:0d:48:77:ce:f1:fe:d5:8f:ea:b1:71:ed:49:1d:9f:
|
||||
23:3a:16:d4:70:7c:c5:29:bf:e4:90:34:d0:f0:00:24:f4:e4:
|
||||
df:2c:c3:83:01:66:61:c9:a8:ab:29:e7:98:6d:27:89:4a:76:
|
||||
c9:2e:19:8e:fe:6e:d5:f8:99:11:0e:97:67:4b:34:e3:1e:e3:
|
||||
9f:35:00:a5:32:f9:b5:2c:f2:e0:c5:2e:cc:81:bd:18:dd:5c:
|
||||
12:c8:6b:fa:0c:17:74:30:55:f6:6e:20:9a:6c:1e:09:b4:0c:
|
||||
15:42
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEKjCCA5OgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMCVVMx
|
||||
CzAJBgNVBAgTAkNBMRUwEwYDVQQHEwxTYW5GcmFuY2lzY28xFTATBgNVBAoTDEZv
|
||||
cnQtRnVuc3RvbjERMA8GA1UECxMIY2hhbmdlbWUxETAPBgNVBAMTCGNoYW5nZW1l
|
||||
MREwDwYDVQQpEwhjaGFuZ2VtZTEfMB0GCSqGSIb3DQEJARYQbWFpbEBob3N0LmRv
|
||||
bWFpbjAeFw0xMzEyMDQxNTAxMjBaFw0yMzEyMDIxNTAxMjBaMIGbMQswCQYDVQQG
|
||||
EwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFNhbkZyYW5jaXNjbzEVMBMGA1UE
|
||||
ChMMRm9ydC1GdW5zdG9uMREwDwYDVQQLEwhjaGFuZ2VtZTEKMAgGA1UEAxQBKjER
|
||||
MA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1haWxAaG9zdC5kb21h
|
||||
aW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMH/fTBvZEqxkrFx0cF04h3b
|
||||
LREk4QDUAK5vyJ6uZ7NKvffmnldtGUw8I5QtPdZjhNj6dis4EsHtIJ0y4OjCv5p3
|
||||
cAQ/f8qMLILWPSVcAhpPZJMD3ZxCl14JSa/wwuEwCA4hRpXRE1nAyHa+lA2LQ2ch
|
||||
M7IIYJ12qAUyHvmVCRR1AgMBAAGjggFzMIIBbzAJBgNVHRMEAjAAMBEGCWCGSAGG
|
||||
+EIBAQQEAwIGQDA0BglghkgBhvhCAQ0EJxYlRWFzeS1SU0EgR2VuZXJhdGVkIFNl
|
||||
cnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUFAL9/d0TOOBx6tG+wA6JGi22GQYw
|
||||
gdcGA1UdIwSBzzCBzIAUZu7DFz09q0QBa2+ymRm9qgK1NPuhgaikgaUwgaIxCzAJ
|
||||
BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVMBMGA1UEBxMMU2FuRnJhbmNpc2NvMRUw
|
||||
EwYDVQQKEwxGb3J0LUZ1bnN0b24xETAPBgNVBAsTCGNoYW5nZW1lMREwDwYDVQQD
|
||||
EwhjaGFuZ2VtZTERMA8GA1UEKRMIY2hhbmdlbWUxHzAdBgkqhkiG9w0BCQEWEG1h
|
||||
aWxAaG9zdC5kb21haW6CCQD9q+xqhCcEpzATBgNVHSUEDDAKBggrBgEFBQcDATAL
|
||||
BgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADgYEAQA8QOcS3Dw0vv9IWzI7TmvuL
|
||||
zkt7DUh3zvH+1Y/qsXHtSR2fIzoW1HB8xSm/5JA00PAAJPTk3yzDgwFmYcmoqynn
|
||||
mG0niUp2yS4Zjv5u1fiZEQ6XZ0s04x7jnzUApTL5tSzy4MUuzIG9GN1cEshr+gwX
|
||||
dDBV9m4gmmweCbQMFUI=
|
||||
-----END CERTIFICATE-----
|
16
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/server-key.pem
generated
vendored
Normal file
16
vendor/github.com/docker/docker-ce/components/engine/integration/testdata/https/server-key.pem
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMH/fTBvZEqxkrFx
|
||||
0cF04h3bLREk4QDUAK5vyJ6uZ7NKvffmnldtGUw8I5QtPdZjhNj6dis4EsHtIJ0y
|
||||
4OjCv5p3cAQ/f8qMLILWPSVcAhpPZJMD3ZxCl14JSa/wwuEwCA4hRpXRE1nAyHa+
|
||||
lA2LQ2chM7IIYJ12qAUyHvmVCRR1AgMBAAECgYAmwckb9RUfSwyYgLm8IYLPHiuJ
|
||||
wkllZfVg5Bo7gXJcQnFjZmJ56uTj8xvUjZlODIHM63TSO5ibv6kFXtXKCqZGd2M+
|
||||
wGbhZ0f+2GvKcwMmJERnIQjuoNaYSQLT0tM0VB9Iz0rJlZC+tzPZ+5pPqEumRdsS
|
||||
IzWNXfF42AhcbwAQYQJBAPVXtMYIJc9EZsz86ZcQiMPWUpCX5vnRmtwL8kKyR8D5
|
||||
4KfYeiowyFffSRMMcclwNHq7TgSXN+nIXM9WyzyzwikCQQDKbNA28AgZp9aT54HP
|
||||
WnbeE2pmt+uk/zl/BtxJSoK6H+69Jec+lf7EgL7HgOWYRSNot4uQWu8IhsHLTiUq
|
||||
+0FtAkEAqwlRxRy4/x24bP+D+QRV0/D97j93joFJbE4Hved7jlSlAV4xDGilwlyv
|
||||
HNB4Iu5OJ6Gcaibhm+FKkmD3noHSwQJBAIpu3fokLzX0bS+bDFBU6qO3HXX/47xj
|
||||
+tsfQvkwZrSI8AkU6c8IX0HdVhsz0FBRQAT2ORDQz1XCarfxykNZrwUCQQCGCBIc
|
||||
BBCWzhHlswlGidWJg3HqqO6hPPClEr3B5G87oCsdeYwiO23XT6rUnoJXfJHp6oCW
|
||||
5nCwDu5ZTP+khltg
|
||||
-----END PRIVATE KEY-----
|
33
vendor/github.com/docker/docker-ce/components/engine/integration/volume/main_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/docker-ce/components/engine/integration/volume/main_test.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package volume // import "github.com/docker/docker/integration/volume"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
113
vendor/github.com/docker/docker-ce/components/engine/integration/volume/volume_test.go
generated
vendored
Normal file
113
vendor/github.com/docker/docker-ce/components/engine/integration/volume/volume_test.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/request"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
)
|
||||
|
||||
func TestVolumesCreateAndList(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
name := t.Name()
|
||||
vol, err := client.VolumeCreate(ctx, volumetypes.VolumesCreateBody{
|
||||
Name: name,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := types.Volume{
|
||||
// Ignore timestamp of CreatedAt
|
||||
CreatedAt: vol.CreatedAt,
|
||||
Driver: "local",
|
||||
Scope: "local",
|
||||
Name: name,
|
||||
Mountpoint: fmt.Sprintf("%s/volumes/%s/_data", testEnv.DaemonInfo.DockerRootDir, name),
|
||||
}
|
||||
assert.Check(t, is.DeepEqual(vol, expected))
|
||||
|
||||
volumes, err := client.VolumeList(ctx, filters.Args{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Equal(len(volumes.Volumes), 1))
|
||||
assert.Check(t, volumes.Volumes[0] != nil)
|
||||
assert.Check(t, is.DeepEqual(*volumes.Volumes[0], expected))
|
||||
}
|
||||
|
||||
func TestVolumesRemove(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
prefix, _ := getPrefixAndSlashFromDaemonPlatform()
|
||||
|
||||
id := container.Create(t, ctx, client, container.WithVolume(prefix+"foo"))
|
||||
|
||||
c, err := client.ContainerInspect(ctx, id)
|
||||
assert.NilError(t, err)
|
||||
vname := c.Mounts[0].Name
|
||||
|
||||
err = client.VolumeRemove(ctx, vname, false)
|
||||
testutil.ErrorContains(t, err, "volume is in use")
|
||||
|
||||
err = client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{
|
||||
Force: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.VolumeRemove(ctx, vname, false)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestVolumesInspect(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
client := request.NewAPIClient(t)
|
||||
ctx := context.Background()
|
||||
|
||||
// sampling current time minus a minute so to now have false positive in case of delays
|
||||
now := time.Now().Truncate(time.Minute)
|
||||
|
||||
name := t.Name()
|
||||
_, err := client.VolumeCreate(ctx, volumetypes.VolumesCreateBody{
|
||||
Name: name,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
vol, err := client.VolumeInspect(ctx, name)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := types.Volume{
|
||||
// Ignore timestamp of CreatedAt
|
||||
CreatedAt: vol.CreatedAt,
|
||||
Driver: "local",
|
||||
Scope: "local",
|
||||
Name: name,
|
||||
Mountpoint: fmt.Sprintf("%s/volumes/%s/_data", testEnv.DaemonInfo.DockerRootDir, name),
|
||||
}
|
||||
assert.Check(t, is.DeepEqual(vol, expected))
|
||||
|
||||
// comparing CreatedAt field time for the new volume to now. Removing a minute from both to avoid false positive
|
||||
testCreatedAt, err := time.Parse(time.RFC3339, strings.TrimSpace(vol.CreatedAt))
|
||||
assert.NilError(t, err)
|
||||
testCreatedAt = testCreatedAt.Truncate(time.Minute)
|
||||
assert.Check(t, is.Equal(testCreatedAt.Equal(now), true), "Time Volume is CreatedAt not equal to current time")
|
||||
}
|
||||
|
||||
func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
|
||||
if testEnv.OSType == "windows" {
|
||||
return "c:", `\`
|
||||
}
|
||||
return "", "/"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue