mirror of https://github.com/docker/cli.git
Add support for service-level 'volumes' key
Support volume driver + options Support external volumes Support hostname in Compose file Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
parent
f702b722d8
commit
a9fc9b60fe
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"github.com/aanand/compose-file/loader"
|
"github.com/aanand/compose-file/loader"
|
||||||
composetypes "github.com/aanand/compose-file/types"
|
composetypes "github.com/aanand/compose-file/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/mount"
|
||||||
networktypes "github.com/docker/docker/api/types/network"
|
networktypes "github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/cli"
|
"github.com/docker/docker/cli"
|
||||||
|
@ -92,7 +94,14 @@ func getConfigFile(filename string) (*composetypes.ConfigFile, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return loader.ParseYAML(bytes, filename)
|
config, err := loader.ParseYAML(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &composetypes.ConfigFile{
|
||||||
|
Filename: filename,
|
||||||
|
Config: config,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNetworks(
|
func createNetworks(
|
||||||
|
@ -114,7 +123,7 @@ func createNetworks(
|
||||||
}
|
}
|
||||||
|
|
||||||
for internalName, network := range networks {
|
for internalName, network := range networks {
|
||||||
if network.ExternalName != "" {
|
if network.External.Name != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +174,80 @@ func convertNetworks(
|
||||||
return nets
|
return nets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertVolumes(
|
||||||
|
serviceVolumes []string,
|
||||||
|
stackVolumes map[string]composetypes.VolumeConfig,
|
||||||
|
namespace string,
|
||||||
|
) ([]mount.Mount, error) {
|
||||||
|
var mounts []mount.Mount
|
||||||
|
|
||||||
|
for _, volumeString := range serviceVolumes {
|
||||||
|
var (
|
||||||
|
source, target string
|
||||||
|
mountType mount.Type
|
||||||
|
readOnly bool
|
||||||
|
volumeOptions *mount.VolumeOptions
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: split Windows path mappings properly
|
||||||
|
parts := strings.SplitN(volumeString, ":", 3)
|
||||||
|
|
||||||
|
if len(parts) == 3 {
|
||||||
|
source = parts[0]
|
||||||
|
target = parts[1]
|
||||||
|
if parts[2] == "ro" {
|
||||||
|
readOnly = true
|
||||||
|
}
|
||||||
|
} else if len(parts) == 2 {
|
||||||
|
source = parts[0]
|
||||||
|
target = parts[1]
|
||||||
|
} else if len(parts) == 1 {
|
||||||
|
target = parts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: catch Windows paths here
|
||||||
|
if strings.HasPrefix(source, "/") {
|
||||||
|
mountType = mount.TypeBind
|
||||||
|
} else {
|
||||||
|
mountType = mount.TypeVolume
|
||||||
|
|
||||||
|
stackVolume, exists := stackVolumes[source]
|
||||||
|
if !exists {
|
||||||
|
// TODO: better error message (include service name)
|
||||||
|
return nil, fmt.Errorf("Undefined volume: %s", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stackVolume.External.Name != "" {
|
||||||
|
source = stackVolume.External.Name
|
||||||
|
} else {
|
||||||
|
volumeOptions = &mount.VolumeOptions{
|
||||||
|
Labels: stackVolume.Labels,
|
||||||
|
}
|
||||||
|
|
||||||
|
if stackVolume.Driver != "" {
|
||||||
|
volumeOptions.DriverConfig = &mount.Driver{
|
||||||
|
Name: stackVolume.Driver,
|
||||||
|
Options: stackVolume.DriverOpts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove this duplication
|
||||||
|
source = fmt.Sprintf("%s_%s", namespace, source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mounts = append(mounts, mount.Mount{
|
||||||
|
Type: mountType,
|
||||||
|
Source: source,
|
||||||
|
Target: target,
|
||||||
|
ReadOnly: readOnly,
|
||||||
|
VolumeOptions: volumeOptions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return mounts, nil
|
||||||
|
}
|
||||||
|
|
||||||
func deployServices(
|
func deployServices(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
dockerCli *command.DockerCli,
|
dockerCli *command.DockerCli,
|
||||||
|
@ -255,6 +338,11 @@ func convertService(
|
||||||
return swarm.ServiceSpec{}, err
|
return swarm.ServiceSpec{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mounts, err := convertVolumes(service.Volumes, volumes, namespace)
|
||||||
|
if err != nil {
|
||||||
|
return swarm.ServiceSpec{}, err
|
||||||
|
}
|
||||||
|
|
||||||
serviceSpec := swarm.ServiceSpec{
|
serviceSpec := swarm.ServiceSpec{
|
||||||
Annotations: swarm.Annotations{
|
Annotations: swarm.Annotations{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -262,13 +350,15 @@ func convertService(
|
||||||
},
|
},
|
||||||
TaskTemplate: swarm.TaskSpec{
|
TaskTemplate: swarm.TaskSpec{
|
||||||
ContainerSpec: swarm.ContainerSpec{
|
ContainerSpec: swarm.ContainerSpec{
|
||||||
Image: service.Image,
|
Image: service.Image,
|
||||||
Command: service.Entrypoint,
|
Command: service.Entrypoint,
|
||||||
Args: service.Command,
|
Args: service.Command,
|
||||||
Env: convertEnvironment(service.Environment),
|
Hostname: service.Hostname,
|
||||||
Labels: getStackLabels(namespace, service.Deploy.Labels),
|
Env: convertEnvironment(service.Environment),
|
||||||
Dir: service.WorkingDir,
|
Labels: getStackLabels(namespace, service.Deploy.Labels),
|
||||||
User: service.User,
|
Dir: service.WorkingDir,
|
||||||
|
User: service.User,
|
||||||
|
Mounts: mounts,
|
||||||
},
|
},
|
||||||
Placement: &swarm.Placement{
|
Placement: &swarm.Placement{
|
||||||
Constraints: service.Deploy.Placement.Constraints,
|
Constraints: service.Deploy.Placement.Constraints,
|
||||||
|
|
Loading…
Reference in New Issue