Skip to content

Commit 5037c5a

Browse files
authored
Merge pull request moby#36688 from cpuguy83/volumes_service
Extract volume interaction to a volumes service
2 parents d7e94d6 + e4b6adc commit 5037c5a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1533
-639
lines changed

api/server/router/volume/backend.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package volume // import "github.com/docker/docker/api/server/router/volume"
33
import (
44
"context"
55

6+
"github.com/docker/docker/volume/service/opts"
67
// TODO return types need to be refactored into pkg
78
"github.com/docker/docker/api/types"
89
"github.com/docker/docker/api/types/filters"
@@ -11,9 +12,9 @@ import (
1112
// Backend is the methods that need to be implemented to provide
1213
// volume specific functionality
1314
type Backend interface {
14-
Volumes(filter string) ([]*types.Volume, []string, error)
15-
VolumeInspect(name string) (*types.Volume, error)
16-
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
17-
VolumeRm(name string, force bool) error
18-
VolumesPrune(ctx context.Context, pruneFilters filters.Args) (*types.VolumesPruneReport, error)
15+
List(ctx context.Context, filter filters.Args) ([]*types.Volume, []string, error)
16+
Get(ctx context.Context, name string, opts ...opts.GetOption) (*types.Volume, error)
17+
Create(ctx context.Context, name, driverName string, opts ...opts.CreateOption) (*types.Volume, error)
18+
Remove(ctx context.Context, name string, opts ...opts.RemoveOption) error
19+
Prune(ctx context.Context, pruneFilters filters.Args) (*types.VolumesPruneReport, error)
1920
}

api/server/router/volume/volume_routes.go

+11-6
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,27 @@ package volume // import "github.com/docker/docker/api/server/router/volume"
33
import (
44
"context"
55
"encoding/json"
6-
"errors"
76
"io"
87
"net/http"
98

109
"github.com/docker/docker/api/server/httputils"
1110
"github.com/docker/docker/api/types/filters"
1211
volumetypes "github.com/docker/docker/api/types/volume"
1312
"github.com/docker/docker/errdefs"
13+
"github.com/docker/docker/volume/service/opts"
14+
"github.com/pkg/errors"
1415
)
1516

1617
func (v *volumeRouter) getVolumesList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
1718
if err := httputils.ParseForm(r); err != nil {
1819
return err
1920
}
2021

21-
volumes, warnings, err := v.backend.Volumes(r.Form.Get("filters"))
22+
filters, err := filters.FromJSON(r.Form.Get("filters"))
23+
if err != nil {
24+
return errdefs.InvalidParameter(errors.Wrap(err, "error reading volume filters"))
25+
}
26+
volumes, warnings, err := v.backend.List(ctx, filters)
2227
if err != nil {
2328
return err
2429
}
@@ -30,7 +35,7 @@ func (v *volumeRouter) getVolumeByName(ctx context.Context, w http.ResponseWrite
3035
return err
3136
}
3237

33-
volume, err := v.backend.VolumeInspect(vars["name"])
38+
volume, err := v.backend.Get(ctx, vars["name"], opts.WithGetResolveStatus)
3439
if err != nil {
3540
return err
3641
}
@@ -54,7 +59,7 @@ func (v *volumeRouter) postVolumesCreate(ctx context.Context, w http.ResponseWri
5459
return err
5560
}
5661

57-
volume, err := v.backend.VolumeCreate(req.Name, req.Driver, req.DriverOpts, req.Labels)
62+
volume, err := v.backend.Create(ctx, req.Name, req.Driver, opts.WithCreateOptions(req.DriverOpts), opts.WithCreateLabels(req.Labels))
5863
if err != nil {
5964
return err
6065
}
@@ -66,7 +71,7 @@ func (v *volumeRouter) deleteVolumes(ctx context.Context, w http.ResponseWriter,
6671
return err
6772
}
6873
force := httputils.BoolValue(r, "force")
69-
if err := v.backend.VolumeRm(vars["name"], force); err != nil {
74+
if err := v.backend.Remove(ctx, vars["name"], opts.WithPurgeOnError(force)); err != nil {
7075
return err
7176
}
7277
w.WriteHeader(http.StatusNoContent)
@@ -83,7 +88,7 @@ func (v *volumeRouter) postVolumesPrune(ctx context.Context, w http.ResponseWrit
8388
return err
8489
}
8590

86-
pruneReport, err := v.backend.VolumesPrune(ctx, pruneFilters)
91+
pruneReport, err := v.backend.Prune(ctx, pruneFilters)
8792
if err != nil {
8893
return err
8994
}

cmd/dockerd/daemon.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ func initRouter(opts routerOptions) {
453453
container.NewRouter(opts.daemon, decoder),
454454
image.NewRouter(opts.daemon.ImageService()),
455455
systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache),
456-
volume.NewRouter(opts.daemon),
456+
volume.NewRouter(opts.daemon.VolumesService()),
457457
build.NewRouter(opts.buildBackend, opts.daemon),
458458
sessionrouter.NewRouter(opts.sessionManager),
459459
swarmrouter.NewRouter(opts.cluster),
@@ -595,6 +595,7 @@ func createAndStartCluster(cli *DaemonCli, d *daemon.Daemon) (*cluster.Cluster,
595595
Root: cli.Config.Root,
596596
Name: name,
597597
Backend: d,
598+
VolumeBackend: d.VolumesService(),
598599
ImageBackend: d.ImageService(),
599600
PluginBackend: d.PluginManager(),
600601
NetworkSubnetsProvider: d,

container/container_unix.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (container *Container) CopyImagePathContent(v volume.Volume, destination st
128128
return err
129129
}
130130

131-
if _, err = ioutil.ReadDir(rootfs); err != nil {
131+
if _, err := os.Stat(rootfs); err != nil {
132132
if os.IsNotExist(err) {
133133
return nil
134134
}

daemon/cluster/cluster.go

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type Config struct {
8585
Backend executorpkg.Backend
8686
ImageBackend executorpkg.ImageBackend
8787
PluginBackend plugin.Backend
88+
VolumeBackend executorpkg.VolumeBackend
8889
NetworkSubnetsProvider NetworkSubnetsProvider
8990

9091
// DefaultAdvertiseAddr is the default host/IP or network interface to use

daemon/cluster/executor/backend.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
clustertypes "github.com/docker/docker/daemon/cluster/provider"
1919
networkSettings "github.com/docker/docker/daemon/network"
2020
"github.com/docker/docker/plugin"
21+
volumeopts "github.com/docker/docker/volume/service/opts"
2122
"github.com/docker/libnetwork"
2223
"github.com/docker/libnetwork/cluster"
2324
networktypes "github.com/docker/libnetwork/types"
@@ -47,7 +48,6 @@ type Backend interface {
4748
SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error
4849
SetContainerConfigReferences(name string, refs []*swarmtypes.ConfigReference) error
4950
SystemInfo() (*types.Info, error)
50-
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
5151
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
5252
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
5353
DaemonJoinsCluster(provider cluster.Provider)
@@ -62,6 +62,11 @@ type Backend interface {
6262
GetAttachmentStore() *networkSettings.AttachmentStore
6363
}
6464

65+
// VolumeBackend is used by an executor to perform volume operations
66+
type VolumeBackend interface {
67+
Create(ctx context.Context, name, driverName string, opts ...volumeopts.CreateOption) (*types.Volume, error)
68+
}
69+
6570
// ImageBackend is used by an executor to perform image operations
6671
type ImageBackend interface {
6772
PullImage(ctx context.Context, image, tag, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error

daemon/cluster/executor/container/adapter.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/docker/docker/daemon"
2323
"github.com/docker/docker/daemon/cluster/convert"
2424
executorpkg "github.com/docker/docker/daemon/cluster/executor"
25+
volumeopts "github.com/docker/docker/volume/service/opts"
2526
"github.com/docker/libnetwork"
2627
"github.com/docker/swarmkit/agent/exec"
2728
"github.com/docker/swarmkit/api"
@@ -36,23 +37,25 @@ import (
3637
// are mostly naked calls to the client API, seeded with information from
3738
// containerConfig.
3839
type containerAdapter struct {
39-
backend executorpkg.Backend
40-
imageBackend executorpkg.ImageBackend
41-
container *containerConfig
42-
dependencies exec.DependencyGetter
40+
backend executorpkg.Backend
41+
imageBackend executorpkg.ImageBackend
42+
volumeBackend executorpkg.VolumeBackend
43+
container *containerConfig
44+
dependencies exec.DependencyGetter
4345
}
4446

45-
func newContainerAdapter(b executorpkg.Backend, i executorpkg.ImageBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*containerAdapter, error) {
47+
func newContainerAdapter(b executorpkg.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*containerAdapter, error) {
4648
ctnr, err := newContainerConfig(task, node)
4749
if err != nil {
4850
return nil, err
4951
}
5052

5153
return &containerAdapter{
52-
container: ctnr,
53-
backend: b,
54-
imageBackend: i,
55-
dependencies: dependencies,
54+
container: ctnr,
55+
backend: b,
56+
imageBackend: i,
57+
volumeBackend: v,
58+
dependencies: dependencies,
5659
}, nil
5760
}
5861

@@ -388,7 +391,10 @@ func (c *containerAdapter) createVolumes(ctx context.Context) error {
388391
req := c.container.volumeCreateRequest(&mount)
389392

390393
// Check if this volume exists on the engine
391-
if _, err := c.backend.VolumeCreate(req.Name, req.Driver, req.DriverOpts, req.Labels); err != nil {
394+
if _, err := c.volumeBackend.Create(ctx, req.Name, req.Driver,
395+
volumeopts.WithCreateOptions(req.DriverOpts),
396+
volumeopts.WithCreateLabels(req.Labels),
397+
); err != nil {
392398
// TODO(amitshukla): Today, volume create through the engine api does not return an error
393399
// when the named volume with the same parameters already exists.
394400
// It returns an error if the driver name is different - that is a valid error

daemon/cluster/executor/container/attachment.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ type networkAttacherController struct {
2121
closed chan struct{}
2222
}
2323

24-
func newNetworkAttacherController(b executorpkg.Backend, i executorpkg.ImageBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*networkAttacherController, error) {
25-
adapter, err := newContainerAdapter(b, i, task, node, dependencies)
24+
func newNetworkAttacherController(b executorpkg.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*networkAttacherController, error) {
25+
adapter, err := newContainerAdapter(b, i, v, task, node, dependencies)
2626
if err != nil {
2727
return nil, err
2828
}

daemon/cluster/executor/container/controller.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ type controller struct {
4040
var _ exec.Controller = &controller{}
4141

4242
// NewController returns a docker exec runner for the provided task.
43-
func newController(b executorpkg.Backend, i executorpkg.ImageBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*controller, error) {
44-
adapter, err := newContainerAdapter(b, i, task, node, dependencies)
43+
func newController(b executorpkg.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*controller, error) {
44+
adapter, err := newContainerAdapter(b, i, v, task, node, dependencies)
4545
if err != nil {
4646
return nil, err
4747
}

daemon/cluster/executor/container/executor.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@ type executor struct {
2828
backend executorpkg.Backend
2929
imageBackend executorpkg.ImageBackend
3030
pluginBackend plugin.Backend
31+
volumeBackend executorpkg.VolumeBackend
3132
dependencies exec.DependencyManager
3233
mutex sync.Mutex // This mutex protects the following node field
3334
node *api.NodeDescription
3435
}
3536

3637
// NewExecutor returns an executor from the docker client.
37-
func NewExecutor(b executorpkg.Backend, p plugin.Backend, i executorpkg.ImageBackend) exec.Executor {
38+
func NewExecutor(b executorpkg.Backend, p plugin.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend) exec.Executor {
3839
return &executor{
3940
backend: b,
4041
pluginBackend: p,
4142
imageBackend: i,
43+
volumeBackend: v,
4244
dependencies: agent.NewDependencyManager(),
4345
}
4446
}
@@ -211,7 +213,7 @@ func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
211213
e.mutex.Unlock()
212214

213215
if t.Spec.GetAttachment() != nil {
214-
return newNetworkAttacherController(e.backend, e.imageBackend, t, nodeDescription, dependencyGetter)
216+
return newNetworkAttacherController(e.backend, e.imageBackend, e.volumeBackend, t, nodeDescription, dependencyGetter)
215217
}
216218

217219
var ctlr exec.Controller
@@ -240,7 +242,7 @@ func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
240242
return ctlr, fmt.Errorf("unsupported runtime type: %q", runtimeKind)
241243
}
242244
case *api.TaskSpec_Container:
243-
c, err := newController(e.backend, e.imageBackend, t, nodeDescription, dependencyGetter)
245+
c, err := newController(e.backend, e.imageBackend, e.volumeBackend, t, nodeDescription, dependencyGetter)
244246
if err != nil {
245247
return ctlr, err
246248
}

daemon/cluster/executor/container/health_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestHealthStates(t *testing.T) {
5252
EventsService: e,
5353
}
5454

55-
controller, err := newController(daemon, nil, task, nil, nil)
55+
controller, err := newController(daemon, nil, nil, task, nil, nil)
5656
if err != nil {
5757
t.Fatalf("create controller fail %v", err)
5858
}

daemon/cluster/executor/container/validate_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
func newTestControllerWithMount(m api.Mount) (*controller, error) {
15-
return newController(&daemon.Daemon{}, nil, &api.Task{
15+
return newController(&daemon.Daemon{}, nil, nil, &api.Task{
1616
ID: stringid.GenerateRandomID(),
1717
ServiceID: stringid.GenerateRandomID(),
1818
Spec: api.TaskSpec{

daemon/cluster/noderunner.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ func (n *nodeRunner) start(conf nodeStartConfig) error {
123123
Executor: container.NewExecutor(
124124
n.cluster.config.Backend,
125125
n.cluster.config.PluginBackend,
126-
n.cluster.config.ImageBackend),
126+
n.cluster.config.ImageBackend,
127+
n.cluster.config.VolumeBackend,
128+
),
127129
HeartbeatTick: n.cluster.config.RaftHeartbeatTick,
128130
// Recommended value in etcd/raft is 10 x (HeartbeatTick).
129131
// Lower values were seen to have caused instability because of

daemon/create.go

+1-21
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,17 @@ import (
77
"strings"
88
"time"
99

10-
"github.com/pkg/errors"
11-
1210
"github.com/docker/docker/api/types"
1311
containertypes "github.com/docker/docker/api/types/container"
1412
networktypes "github.com/docker/docker/api/types/network"
1513
"github.com/docker/docker/container"
1614
"github.com/docker/docker/errdefs"
1715
"github.com/docker/docker/image"
1816
"github.com/docker/docker/pkg/idtools"
19-
"github.com/docker/docker/pkg/stringid"
2017
"github.com/docker/docker/pkg/system"
2118
"github.com/docker/docker/runconfig"
2219
"github.com/opencontainers/selinux/go-selinux/label"
20+
"github.com/pkg/errors"
2321
"github.com/sirupsen/logrus"
2422
)
2523

@@ -255,24 +253,6 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
255253
return nil, nil
256254
}
257255

258-
// VolumeCreate creates a volume with the specified name, driver, and opts
259-
// This is called directly from the Engine API
260-
func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error) {
261-
if name == "" {
262-
name = stringid.GenerateNonCryptoID()
263-
}
264-
265-
v, err := daemon.volumes.Create(name, driverName, opts, labels)
266-
if err != nil {
267-
return nil, err
268-
}
269-
270-
daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
271-
apiV := volumeToAPIType(v)
272-
apiV.Mountpoint = v.Path()
273-
return apiV, nil
274-
}
275-
276256
func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error {
277257
if img != nil && img.Config != nil {
278258
if err := merge(config, img.Config); err != nil {

daemon/create_unix.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package daemon // import "github.com/docker/docker/daemon"
44

55
import (
6+
"context"
67
"fmt"
78
"os"
89
"path/filepath"
@@ -11,6 +12,7 @@ import (
1112
mounttypes "github.com/docker/docker/api/types/mount"
1213
"github.com/docker/docker/container"
1314
"github.com/docker/docker/pkg/stringid"
15+
volumeopts "github.com/docker/docker/volume/service/opts"
1416
"github.com/opencontainers/selinux/go-selinux/label"
1517
"github.com/sirupsen/logrus"
1618
)
@@ -46,16 +48,16 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
4648
return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
4749
}
4850

49-
v, err := daemon.volumes.CreateWithRef(name, hostConfig.VolumeDriver, container.ID, nil, nil)
51+
v, err := daemon.volumes.Create(context.TODO(), name, hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID))
5052
if err != nil {
5153
return err
5254
}
5355

54-
if err := label.Relabel(v.Path(), container.MountLabel, true); err != nil {
56+
if err := label.Relabel(v.Mountpoint, container.MountLabel, true); err != nil {
5557
return err
5658
}
5759

58-
container.AddMountPointWithVolume(destination, v, true)
60+
container.AddMountPointWithVolume(destination, &volumeWrapper{v: v, s: daemon.volumes}, true)
5961
}
6062
return daemon.populateVolumes(container)
6163
}

0 commit comments

Comments
 (0)