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
cbbc6b4d9b
commit
0884e3c868
1 changed files with 99 additions and 9 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"github.com/aanand/compose-file/loader"
|
||||
composetypes "github.com/aanand/compose-file/types"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/cli"
|
||||
|
@ -92,7 +94,14 @@ func getConfigFile(filename string) (*composetypes.ConfigFile, error) {
|
|||
if err != nil {
|
||||
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(
|
||||
|
@ -114,7 +123,7 @@ func createNetworks(
|
|||
}
|
||||
|
||||
for internalName, network := range networks {
|
||||
if network.ExternalName != "" {
|
||||
if network.External.Name != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -165,6 +174,80 @@ func convertNetworks(
|
|||
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(
|
||||
ctx context.Context,
|
||||
dockerCli *command.DockerCli,
|
||||
|
@ -255,6 +338,11 @@ func convertService(
|
|||
return swarm.ServiceSpec{}, err
|
||||
}
|
||||
|
||||
mounts, err := convertVolumes(service.Volumes, volumes, namespace)
|
||||
if err != nil {
|
||||
return swarm.ServiceSpec{}, err
|
||||
}
|
||||
|
||||
serviceSpec := swarm.ServiceSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: name,
|
||||
|
@ -262,13 +350,15 @@ func convertService(
|
|||
},
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
ContainerSpec: swarm.ContainerSpec{
|
||||
Image: service.Image,
|
||||
Command: service.Entrypoint,
|
||||
Args: service.Command,
|
||||
Env: convertEnvironment(service.Environment),
|
||||
Labels: getStackLabels(namespace, service.Deploy.Labels),
|
||||
Dir: service.WorkingDir,
|
||||
User: service.User,
|
||||
Image: service.Image,
|
||||
Command: service.Entrypoint,
|
||||
Args: service.Command,
|
||||
Hostname: service.Hostname,
|
||||
Env: convertEnvironment(service.Environment),
|
||||
Labels: getStackLabels(namespace, service.Deploy.Labels),
|
||||
Dir: service.WorkingDir,
|
||||
User: service.User,
|
||||
Mounts: mounts,
|
||||
},
|
||||
Placement: &swarm.Placement{
|
||||
Constraints: service.Deploy.Placement.Constraints,
|
||||
|
|
Loading…
Reference in a new issue