Handling Volume at early stage

It will resolve #544 as well as refactor volume handling part.
This commit is contained in:
Suraj Narwade
2017-07-26 19:59:05 +05:30
parent be17e101b9
commit d5a5f42d8b
15 changed files with 1161 additions and 140 deletions
-71
View File
@@ -491,77 +491,6 @@ func (k *Kubernetes) SortServicesFirst(objs *[]runtime.Object) {
*objs = ret
}
func (k *Kubernetes) findDependentVolumes(svcname string, komposeObject kobject.KomposeObject) (volumes []api.Volume, volumeMounts []api.VolumeMount, err error) {
// Get all the volumes and volumemounts this particular service is dependent on
for _, dependentSvc := range komposeObject.ServiceConfigs[svcname].VolumesFrom {
vols, volMounts, err := k.findDependentVolumes(dependentSvc, komposeObject)
if err != nil {
err = errors.Wrap(err, "k.findDependentVolumes failed")
return nil, nil, err
}
volumes = append(volumes, vols...)
volumeMounts = append(volumeMounts, volMounts...)
}
// add the volumes info of this service
volMounts, vols, _, err := k.ConfigVolumes(svcname, komposeObject.ServiceConfigs[svcname])
if err != nil {
err = errors.Wrap(err, "k.ConfigVolumes failed")
return nil, nil, err
}
volumes = append(volumes, vols...)
volumeMounts = append(volumeMounts, volMounts...)
return volumes, volumeMounts, nil
}
// VolumesFrom creates volums and volumeMounts for volumes_from
func (k *Kubernetes) VolumesFrom(objects *[]runtime.Object, komposeObject kobject.KomposeObject) error {
for _, obj := range *objects {
switch t := obj.(type) {
case *api.ReplicationController:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts, err := k.findDependentVolumes(dependentSvc, komposeObject)
if err != nil {
return errors.Wrap(err, "k.findDependentVolumes")
}
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
case *extensions.Deployment:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts, err := k.findDependentVolumes(dependentSvc, komposeObject)
if err != nil {
return errors.Wrap(err, "k.findDependentVolumes")
}
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
case *extensions.DaemonSet:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts, err := k.findDependentVolumes(dependentSvc, komposeObject)
if err != nil {
return errors.Wrap(err, "k.findDependentVolumes")
}
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
case *deployapi.DeploymentConfig:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts, err := k.findDependentVolumes(dependentSvc, komposeObject)
if err != nil {
return errors.Wrap(err, "k.findDependentVolumes")
}
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
}
}
return nil
}
// SortedKeys Ensure the kubernetes objects are in a consistent order
func SortedKeys(komposeObject kobject.KomposeObject) []string {
var sortedKeys []string
+7 -6
View File
@@ -47,7 +47,7 @@ func TestCreateService(t *testing.T) {
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Network: []string{"network1", "network2"}, // not supported
Labels: nil,
Annotations: map[string]string{"abc": "def"},
@@ -91,7 +91,7 @@ func TestCreateServiceWithMemLimit(t *testing.T) {
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Network: []string{"network1", "network2"}, // not supported
Labels: nil,
Annotations: map[string]string{"abc": "def"},
@@ -140,7 +140,7 @@ func TestCreateServiceWithServiceUser(t *testing.T) {
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Network: []string{"network1", "network2"}, // not supported
Labels: nil,
Annotations: map[string]string{"kompose.service.type": "nodeport"},
@@ -184,7 +184,7 @@ func TestTransformWithPid(t *testing.T) {
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Network: []string{"network1", "network2"},
Restart: "always",
Pid: "host",
@@ -220,7 +220,7 @@ func TestTransformWithInvaildPid(t *testing.T) {
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Network: []string{"network1", "network2"},
Restart: "always",
Pid: "badvalue",
@@ -329,7 +329,8 @@ func TestRecreateStrategyWithVolumesPresent(t *testing.T) {
service := kobject.ServiceConfig{
ContainerName: "name",
Image: "image",
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Volumes: []kobject.Volumes{{SvcName: "app", MountPath: "/tmp/volume", PVCName: "app-claim0"}},
}
komposeObject := kobject.KomposeObject{
+24 -25
View File
@@ -49,6 +49,7 @@ import (
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/labels"
"sort"
"strings"
)
// Kubernetes implements Transformer interface and represents Kubernetes transformer
@@ -376,56 +377,53 @@ func (k *Kubernetes) ConfigVolumes(name string, service kobject.ServiceConfig) (
volumeMounts := []api.VolumeMount{}
volumes := []api.Volume{}
var PVCs []*api.PersistentVolumeClaim
var volumeName string
// Set a var based on if the user wants to use empty volumes
// as opposed to persistent volumes and volume claims
useEmptyVolumes := k.Opt.EmptyVols
var count int
//interating over array of `Vols` struct as it contains all necessary information about volumes
for _, volume := range service.Volumes {
volumeName, host, container, mode, err := transformer.ParseVolume(volume)
if err != nil {
log.Warningf("Failed to configure container volume: %v", err)
continue
}
log.Debug("Volume name %s", volumeName)
// check if ro/rw mode is defined, default rw
readonly := len(mode) > 0 && mode == "ro"
readonly := len(volume.Mode) > 0 && volume.Mode == "ro"
if volumeName == "" {
if volume.VolumeName == "" {
if useEmptyVolumes {
volumeName = fmt.Sprintf("%s-empty%d", name, count)
volumeName = strings.Replace(volume.PVCName, "claim", "empty", 1)
} else {
volumeName = fmt.Sprintf("%s-claim%d", name, count)
volumeName = volume.PVCName
}
count++
} else {
volumeName = volume.VolumeName
}
// create a new volume mount object and append to list
volmount := api.VolumeMount{
Name: volumeName,
ReadOnly: readonly,
MountPath: container,
MountPath: volume.Container,
}
volumeMounts = append(volumeMounts, volmount)
// Get a volume source based on the type of volume we are using
// For PVC we will also create a PVC object and add to list
var volsource *api.VolumeSource
if useEmptyVolumes {
volsource = k.ConfigEmptyVolumeSource("volume")
} else {
volsource = k.ConfigPVCVolumeSource(volumeName, readonly)
if volume.VFrom == "" {
createdPVC, err := k.CreatePVC(volumeName, volume.Mode)
createdPVC, err := k.CreatePVC(volumeName, mode)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "k.CreatePVC failed")
if err != nil {
return nil, nil, nil, errors.Wrap(err, "k.CreatePVC failed")
}
PVCs = append(PVCs, createdPVC)
}
PVCs = append(PVCs, createdPVC)
}
// create a new volume object using the volsource and add to list
@@ -435,10 +433,12 @@ func (k *Kubernetes) ConfigVolumes(name string, service kobject.ServiceConfig) (
}
volumes = append(volumes, vol)
if len(host) > 0 {
log.Warningf("Volume mount on the host %q isn't supported - ignoring path on the host", host)
if len(volume.Host) > 0 {
log.Warningf("Volume mount on the host %q isn't supported - ignoring path on the host", volume.Host)
}
}
return volumeMounts, volumes, PVCs, nil
}
@@ -603,8 +603,7 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
allobjects = append(allobjects, objects...)
}
// If docker-compose has a volumes_from directive it will be handled here
k.VolumesFrom(&allobjects, komposeObject)
// sort all object so Services are first
k.SortServicesFirst(&allobjects)
return allobjects, nil
@@ -40,7 +40,7 @@ func newServiceConfig() kobject.ServiceConfig {
Command: []string{"cmd"},
WorkingDir: "dir",
Args: []string{"arg1", "arg2"},
Volumes: []string{"/tmp/volume"},
VolList: []string{"/tmp/volume"},
Network: []string{"network1", "network2"}, // not supported
Labels: nil,
Annotations: map[string]string{"abc": "def"},
@@ -54,6 +54,7 @@ func newServiceConfig() kobject.ServiceConfig {
Tty: true,
TmpFs: []string{"/tmp"},
Replicas: 2,
Volumes: []kobject.Volumes{{SvcName: "app", MountPath: "/tmp/volume", PVCName: "app-claim0"}},
}
}