Merge component 'engine' from git@github.com:moby/moby master
This commit is contained in:
@@ -221,9 +221,6 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
||||
|
||||
// Sets the Windows-specific fields of the OCI spec
|
||||
func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.Spec, isHyperV bool) error {
|
||||
if c.BaseFS == nil {
|
||||
return errors.New("createSpecWindowsFields: BaseFS of container " + c.ID + " is unexpectedly nil")
|
||||
}
|
||||
if len(s.Process.Cwd) == 0 {
|
||||
// We default to C:\ to workaround the oddity of the case that the
|
||||
// default directory for cmd running as LocalSystem (or
|
||||
@@ -237,6 +234,10 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S
|
||||
|
||||
s.Root.Readonly = false // Windows does not support a read-only root filesystem
|
||||
if !isHyperV {
|
||||
if c.BaseFS == nil {
|
||||
return errors.New("createSpecWindowsFields: BaseFS of container " + c.ID + " is unexpectedly nil")
|
||||
}
|
||||
|
||||
s.Root.Path = c.BaseFS.Path() // This is not set for Hyper-V containers
|
||||
if !strings.HasSuffix(s.Root.Path, `\`) {
|
||||
s.Root.Path = s.Root.Path + `\` // Ensure a correctly formatted volume GUID path \\?\Volume{GUID}\
|
||||
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
"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"
|
||||
@@ -51,3 +53,32 @@ func TestExportContainerAndImportImage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 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()
|
||||
require.NoError(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, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
d.Restart(t)
|
||||
|
||||
_, err = client.ContainerExport(ctx, ctr.ID)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ func TestVolumesCreateAndList(t *testing.T) {
|
||||
Driver: "local",
|
||||
Scope: "local",
|
||||
Name: name,
|
||||
Options: map[string]string{},
|
||||
Mountpoint: fmt.Sprintf("%s/volumes/%s/_data", testEnv.DaemonInfo.DockerRootDir, name),
|
||||
}
|
||||
assert.Equal(t, vol, expected)
|
||||
@@ -95,7 +94,6 @@ func TestVolumesInspect(t *testing.T) {
|
||||
Driver: "local",
|
||||
Scope: "local",
|
||||
Name: name,
|
||||
Options: map[string]string{},
|
||||
Mountpoint: fmt.Sprintf("%s/volumes/%s/_data", testEnv.DaemonInfo.DockerRootDir, name),
|
||||
}
|
||||
assert.Equal(t, vol, expected)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -28,7 +29,10 @@ func setMeta(tx *bolt.Tx, name string, meta volumeMetadata) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := tx.Bucket(volumeBucketName)
|
||||
b, err := tx.CreateBucketIfNotExists(volumeBucketName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating volume bucket")
|
||||
}
|
||||
return errors.Wrap(b.Put([]byte(name), metaJSON), "error setting volume metadata")
|
||||
}
|
||||
|
||||
@@ -42,8 +46,11 @@ func (s *VolumeStore) getMeta(name string) (volumeMetadata, error) {
|
||||
|
||||
func getMeta(tx *bolt.Tx, name string, meta *volumeMetadata) error {
|
||||
b := tx.Bucket(volumeBucketName)
|
||||
if b == nil {
|
||||
return errdefs.NotFound(errors.New("volume bucket does not exist"))
|
||||
}
|
||||
val := b.Get([]byte(name))
|
||||
if string(val) == "" {
|
||||
if len(val) == 0 {
|
||||
return nil
|
||||
}
|
||||
if err := json.Unmarshal(val, meta); err != nil {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSetGetMeta(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir, err := ioutil.TempDir("", "test-set-get")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
db, err := bolt.Open(filepath.Join(dir, "db"), 0600, &bolt.Options{Timeout: 1 * time.Second})
|
||||
require.NoError(t, err)
|
||||
|
||||
store := &VolumeStore{db: db}
|
||||
|
||||
_, err = store.getMeta("test")
|
||||
require.Error(t, err)
|
||||
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucket(volumeBucketName)
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
meta, err := store.getMeta("test")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, volumeMetadata{}, meta)
|
||||
|
||||
testMeta := volumeMetadata{
|
||||
Name: "test",
|
||||
Driver: "fake",
|
||||
Labels: map[string]string{"a": "1", "b": "2"},
|
||||
Options: map[string]string{"foo": "bar"},
|
||||
}
|
||||
err = store.setMeta("test", testMeta)
|
||||
require.NoError(t, err)
|
||||
|
||||
meta, err = store.getMeta("test")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testMeta, meta)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/volume"
|
||||
volumedrivers "github.com/docker/docker/volume/drivers"
|
||||
volumetestutils "github.com/docker/docker/volume/testutils"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRestore(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir, err := ioutil.TempDir("", "test-restore")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
driverName := "test-restore"
|
||||
volumedrivers.Register(volumetestutils.NewFakeDriver(driverName), driverName)
|
||||
defer volumedrivers.Unregister("test-restore")
|
||||
|
||||
s, err := New(dir)
|
||||
require.NoError(t, err)
|
||||
defer s.Shutdown()
|
||||
|
||||
_, err = s.Create("test1", driverName, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
testLabels := map[string]string{"a": "1"}
|
||||
testOpts := map[string]string{"foo": "bar"}
|
||||
_, err = s.Create("test2", driverName, testOpts, testLabels)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.Shutdown()
|
||||
|
||||
s, err = New(dir)
|
||||
require.NoError(t, err)
|
||||
|
||||
v, err := s.Get("test1")
|
||||
require.NoError(t, err)
|
||||
|
||||
dv := v.(volume.DetailedVolume)
|
||||
var nilMap map[string]string
|
||||
require.Equal(t, nilMap, dv.Options())
|
||||
require.Equal(t, nilMap, dv.Labels())
|
||||
|
||||
v, err = s.Get("test2")
|
||||
require.NoError(t, err)
|
||||
dv = v.(volume.DetailedVolume)
|
||||
require.Equal(t, testOpts, dv.Options())
|
||||
require.Equal(t, testLabels, dv.Labels())
|
||||
}
|
||||
@@ -29,7 +29,10 @@ type volumeWrapper struct {
|
||||
}
|
||||
|
||||
func (v volumeWrapper) Options() map[string]string {
|
||||
options := map[string]string{}
|
||||
if v.options == nil {
|
||||
return nil
|
||||
}
|
||||
options := make(map[string]string, len(v.options))
|
||||
for key, value := range v.options {
|
||||
options[key] = value
|
||||
}
|
||||
@@ -37,7 +40,15 @@ func (v volumeWrapper) Options() map[string]string {
|
||||
}
|
||||
|
||||
func (v volumeWrapper) Labels() map[string]string {
|
||||
return v.labels
|
||||
if v.labels == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
labels := make(map[string]string, len(v.labels))
|
||||
for key, value := range v.labels {
|
||||
labels[key] = value
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
func (v volumeWrapper) Scope() string {
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/docker/volume/drivers"
|
||||
volumetestutils "github.com/docker/docker/volume/testutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
@@ -291,6 +293,7 @@ func TestDefererencePluginOnCreateError(t *testing.T) {
|
||||
|
||||
pg := volumetestutils.NewFakePluginGetter(p)
|
||||
volumedrivers.RegisterPluginGetter(pg)
|
||||
defer volumedrivers.RegisterPluginGetter(nil)
|
||||
|
||||
dir, err := ioutil.TempDir("", "test-plugin-deref-err")
|
||||
if err != nil {
|
||||
@@ -320,3 +323,103 @@ func TestDefererencePluginOnCreateError(t *testing.T) {
|
||||
t.Fatalf("expected 1 plugin reference, got: %d", refs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefDerefRemove(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
driverName := "test-ref-deref-remove"
|
||||
s, cleanup := setupTest(t, driverName)
|
||||
defer cleanup(t)
|
||||
|
||||
v, err := s.CreateWithRef("test", driverName, "test-ref", nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Remove(v)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errVolumeInUse, err.(*OpErr).Err)
|
||||
|
||||
s.Dereference(v, "test-ref")
|
||||
err = s.Remove(v)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
driverName := "test-get"
|
||||
s, cleanup := setupTest(t, driverName)
|
||||
defer cleanup(t)
|
||||
|
||||
_, err := s.Get("not-exist")
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errNoSuchVolume, err.(*OpErr).Err)
|
||||
|
||||
v1, err := s.Create("test", driverName, nil, map[string]string{"a": "1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
v2, err := s.Get("test")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, v1, v2)
|
||||
|
||||
dv := v2.(volume.DetailedVolume)
|
||||
require.Equal(t, "1", dv.Labels()["a"])
|
||||
|
||||
err = s.Remove(v1)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGetWithRef(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
driverName := "test-get-with-ref"
|
||||
s, cleanup := setupTest(t, driverName)
|
||||
defer cleanup(t)
|
||||
|
||||
_, err := s.GetWithRef("not-exist", driverName, "test-ref")
|
||||
require.Error(t, err)
|
||||
|
||||
v1, err := s.Create("test", driverName, nil, map[string]string{"a": "1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
v2, err := s.GetWithRef("test", driverName, "test-ref")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, v1, v2)
|
||||
|
||||
err = s.Remove(v2)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, errVolumeInUse, err.(*OpErr).Err)
|
||||
|
||||
s.Dereference(v2, "test-ref")
|
||||
err = s.Remove(v2)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T, name string) (*VolumeStore, func(*testing.T)) {
|
||||
t.Helper()
|
||||
s, cleanup := newTestStore(t)
|
||||
|
||||
volumedrivers.Register(volumetestutils.NewFakeDriver(name), name)
|
||||
return s, func(t *testing.T) {
|
||||
cleanup(t)
|
||||
volumedrivers.Unregister(name)
|
||||
}
|
||||
}
|
||||
|
||||
func newTestStore(t *testing.T) (*VolumeStore, func(*testing.T)) {
|
||||
t.Helper()
|
||||
|
||||
dir, err := ioutil.TempDir("", "store-root")
|
||||
require.NoError(t, err)
|
||||
|
||||
cleanup := func(t *testing.T) {
|
||||
err := os.RemoveAll(dir)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
s, err := New(dir)
|
||||
assert.NoError(t, err)
|
||||
return s, func(t *testing.T) {
|
||||
s.Shutdown()
|
||||
cleanup(t)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user