From 42eb0ecc3542fac55cdec2633e895d0646bfb60d Mon Sep 17 00:00:00 2001 From: Chris Crone Date: Tue, 3 Nov 2020 21:15:14 +0100 Subject: [PATCH] backend.local: Add rudimentary volume support Signed-off-by: Chris Crone --- local/backend.go | 6 ++-- local/containers.go | 13 +++++++ local/volumes.go | 84 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 local/volumes.go diff --git a/local/backend.go b/local/backend.go index e65a8348c..134fddb00 100644 --- a/local/backend.go +++ b/local/backend.go @@ -34,6 +34,7 @@ import ( type local struct { *containerService + *volumeService } func init() { @@ -48,6 +49,7 @@ func service(ctx context.Context) (backend.Service, error) { return &local{ containerService: &containerService{apiClient}, + volumeService: &volumeService{apiClient}, }, nil } @@ -63,8 +65,8 @@ func (ms *local) SecretsService() secrets.Service { return nil } -func (ms *local) VolumeService() volumes.Service { - return nil +func (vs *volumeService) VolumeService() volumes.Service { + return vs } func (ms *local) ResourceService() resources.Service { diff --git a/local/containers.go b/local/containers.go index 89282af62..ce83d87ef 100644 --- a/local/containers.go +++ b/local/containers.go @@ -27,6 +27,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/mount" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/stringid" @@ -104,6 +105,17 @@ func (cs *containerService) Run(ctx context.Context, r containers.ContainerConfi return err } + var mounts []mount.Mount + for _, v := range r.Volumes { + tokens := strings.Split(v, ":") + if len(tokens) != 2 { + return errors.Wrapf(errdefs.ErrParsingFailed, "volume %q has invalid format", v) + } + src := tokens[0] + tgt := tokens[1] + mounts = append(mounts, mount.Mount{Type: "volume", Source: src, Target: tgt}) + } + containerConfig := &container.Config{ Image: r.Image, Labels: r.Labels, @@ -112,6 +124,7 @@ func (cs *containerService) Run(ctx context.Context, r containers.ContainerConfi } hostConfig := &container.HostConfig{ PortBindings: hostBindings, + Mounts: mounts, AutoRemove: r.AutoRemove, RestartPolicy: toRestartPolicy(r.RestartPolicyCondition), Resources: container.Resources{ diff --git a/local/volumes.go b/local/volumes.go new file mode 100644 index 000000000..2f56d4444 --- /dev/null +++ b/local/volumes.go @@ -0,0 +1,84 @@ +// +build local + +/* + Copyright 2020 Docker Compose CLI authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package local + +import ( + "context" + "fmt" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/volume" + "github.com/docker/docker/client" + + "github.com/docker/compose-cli/api/volumes" +) + +type volumeService struct { + apiClient *client.Client +} + +func (vs *volumeService) List(ctx context.Context) ([]volumes.Volume, error) { + l, err := vs.apiClient.VolumeList(ctx, filters.NewArgs()) + if err != nil { + return []volumes.Volume{}, err + } + + res := []volumes.Volume{} + for _, v := range l.Volumes { + res = append(res, volumes.Volume{ + ID: v.Name, + Description: description(v), + }) + } + + return res, nil +} + +func (vs *volumeService) Create(ctx context.Context, name string, options interface{}) (volumes.Volume, error) { + v, err := vs.apiClient.VolumeCreate(ctx, volume.VolumeCreateBody{ + Driver: "local", + DriverOpts: nil, + Labels: nil, + Name: name, + }) + if err != nil { + return volumes.Volume{}, err + } + return volumes.Volume{ID: name, Description: description(&v)}, nil +} + +func (vs *volumeService) Delete(ctx context.Context, volumeID string, options interface{}) error { + if err := vs.apiClient.VolumeRemove(ctx, volumeID, false); err != nil { + return err + } + return nil +} + +func (vs *volumeService) Inspect(ctx context.Context, volumeID string) (volumes.Volume, error) { + v, err := vs.apiClient.VolumeInspect(ctx, volumeID) + if err != nil { + return volumes.Volume{}, err + } + return volumes.Volume{ID: volumeID, Description: description(&v)}, nil +} + +func description(v *types.Volume) string { + return fmt.Sprintf("Created %s", v.CreatedAt) +}