This repository has been archived by the owner on Jun 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 190
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Introduce new yaml.Volume{,s} struct - Introduce new `docker/volume` package (like `network/volume`) Signed-off-by: Vincent Demeester <[email protected]>
- Loading branch information
1 parent
80e2cf9
commit ae73652
Showing
14 changed files
with
681 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
package volume | ||
|
||
import ( | ||
"fmt" | ||
|
||
"golang.org/x/net/context" | ||
|
||
"github.com/docker/engine-api/client" | ||
"github.com/docker/engine-api/types" | ||
"github.com/docker/libcompose/config" | ||
|
||
composeclient "github.com/docker/libcompose/docker/client" | ||
"github.com/docker/libcompose/project" | ||
) | ||
|
||
// Volume holds attributes and method for a volume definition in compose | ||
type Volume struct { | ||
client client.VolumeAPIClient | ||
projectName string | ||
name string | ||
driver string | ||
driverOptions map[string]string | ||
external bool | ||
// TODO (shouze) missing labels | ||
} | ||
|
||
func (v *Volume) fullName() string { | ||
name := v.projectName + "_" + v.name | ||
if v.external { | ||
name = v.name | ||
} | ||
return name | ||
} | ||
|
||
// Inspect inspect the current volume | ||
func (v *Volume) Inspect(ctx context.Context) (types.Volume, error) { | ||
return v.client.VolumeInspect(ctx, v.fullName()) | ||
} | ||
|
||
// Remove removes the current volume (from docker engine) | ||
func (v *Volume) Remove(ctx context.Context) error { | ||
if v.external { | ||
fmt.Printf("Volume %s is external, skipping", v.fullName()) | ||
return nil | ||
} | ||
fmt.Printf("Removing volume %q\n", v.fullName()) | ||
return v.client.VolumeRemove(ctx, v.fullName()) | ||
} | ||
|
||
// EnsureItExists make sure the volume exists and return an error if it does not exists | ||
// and cannot be created. | ||
func (v *Volume) EnsureItExists(ctx context.Context) error { | ||
volumeResource, err := v.Inspect(ctx) | ||
if v.external { | ||
if client.IsErrVolumeNotFound(err) { | ||
// FIXME(shouze) introduce some libcompose error type | ||
return fmt.Errorf("Volume %s declared as external, but could not be found. Please create the volume manually using docker volume create %s and try again", v.name, v.name) | ||
} | ||
return err | ||
} | ||
if err != nil && client.IsErrVolumeNotFound(err) { | ||
return v.create(ctx) | ||
} | ||
if volumeResource.Driver != v.driver { | ||
return fmt.Errorf("Volume %q needs to be recreated - driver has changed", v.name) | ||
} | ||
return err | ||
} | ||
|
||
func (v *Volume) create(ctx context.Context) error { | ||
fmt.Printf("Creating volume %q with driver %q\n", v.fullName(), v.driver) | ||
_, err := v.client.VolumeCreate(ctx, types.VolumeCreateRequest{ | ||
Name: v.fullName(), | ||
Driver: v.driver, | ||
DriverOpts: v.driverOptions, | ||
// TODO (shouze) missing labels | ||
}) | ||
|
||
return err | ||
} | ||
|
||
// NewVolume creates a new volume from the specified name and config. | ||
func NewVolume(projectName, name string, config *config.VolumeConfig, client client.VolumeAPIClient) *Volume { | ||
return &Volume{ | ||
client: client, | ||
projectName: projectName, | ||
name: name, | ||
driver: config.Driver, | ||
driverOptions: config.DriverOpts, | ||
external: config.External.External, | ||
} | ||
} | ||
|
||
// Volumes holds a list of volume | ||
type Volumes struct { | ||
volumes []*Volume | ||
volumeEnabled bool | ||
} | ||
|
||
// Initialize make sure volume exists if volume is enabled | ||
func (v *Volumes) Initialize(ctx context.Context) error { | ||
if !v.volumeEnabled { | ||
return nil | ||
} | ||
for _, volume := range v.volumes { | ||
err := volume.EnsureItExists(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// Remove removes volumes (clean-up) | ||
func (v *Volumes) Remove(ctx context.Context) error { | ||
if !v.volumeEnabled { | ||
return nil | ||
} | ||
for _, volume := range v.volumes { | ||
err := volume.Remove(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// VolumesFromServices creates a new Volumes struct based on volumes configurations and | ||
// services configuration. If a volume is defined but not used by any service, it will return | ||
// an error along the Volumes. | ||
func VolumesFromServices(cli client.VolumeAPIClient, projectName string, volumeConfigs map[string]*config.VolumeConfig, services *config.ServiceConfigs, volumeEnabled bool) (*Volumes, error) { | ||
var err error | ||
volumes := make([]*Volume, 0, len(volumeConfigs)) | ||
for name, config := range volumeConfigs { | ||
volume := NewVolume(projectName, name, config, cli) | ||
volumes = append(volumes, volume) | ||
} | ||
return &Volumes{ | ||
volumes: volumes, | ||
volumeEnabled: volumeEnabled, | ||
}, err | ||
} | ||
|
||
// DockerFactory implements project.VolumesFactory | ||
type DockerFactory struct { | ||
ClientFactory composeclient.Factory | ||
} | ||
|
||
// Create implements project.VolumesFactory Create method. | ||
// It creates a Volumes (that implements project.Volumes) from specified configurations. | ||
func (f *DockerFactory) Create(projectName string, volumeConfigs map[string]*config.VolumeConfig, serviceConfigs *config.ServiceConfigs, volumeEnabled bool) (project.Volumes, error) { | ||
cli := f.ClientFactory.Create(nil) | ||
return VolumesFromServices(cli, projectName, volumeConfigs, serviceConfigs, volumeEnabled) | ||
} |
Oops, something went wrong.