Skip to content

Commit

Permalink
Handling Volume at early stage
Browse files Browse the repository at this point in the history
It will resolve #544 as well as refactor volume handling part.
  • Loading branch information
surajnarwade committed Jun 15, 2017
1 parent 49ada13 commit a7a045b
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 100 deletions.
13 changes: 13 additions & 0 deletions pkg/kobject/kobject.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type ServiceConfig struct {
MemLimit yaml.MemStringorInt `compose:"mem_limit" bundle:""`
TmpFs []string `compose:"tmpfs" bundle:""`
Dockerfile string `compose:"dockerfile" bundle:""`
Vols []Volumes `compose:"" bundle:""`
}

// EnvVar holds the environment variable struct of a container
Expand All @@ -106,3 +107,15 @@ type Ports struct {
HostIP string
Protocol api.Protocol
}

// Volumes holds the volume struct of container
type Volumes struct {
SvcName string
MountPath string
VFrom string
VolumeName string
Host string
Container string
Mode string
PVCName string
}
122 changes: 122 additions & 0 deletions pkg/loader/compose/v1v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/docker/libcompose/project"
"github.com/kubernetes-incubator/kompose/pkg/kobject"
"github.com/pkg/errors"
"github.com/kubernetes-incubator/kompose/pkg/transformer"
)

// Parse Docker Compose with libcompose (only supports v1 and v2). Eventually we will
Expand Down Expand Up @@ -264,5 +265,126 @@ func libComposeToKomposeMapping(composeObject *project.Project) (kobject.Kompose
log.Infof("Service name in docker-compose has been changed from %q to %q", name, normalizeServiceNames(name))
}
}
//Handle Volumes
for name, _ := range komposeObject.ServiceConfigs {
vols := handleVolume(name, komposeObject)
var FinalVol []kobject.Volumes
for _, v := range vols {
if !findDuplicateVol(v, FinalVol) {
FinalVol = append(FinalVol, v)
}
}
var count int
for i, _ := range FinalVol {
vol := &FinalVol[i]
var err error
vol.VolumeName, vol.Host, vol.Container, vol.Mode, err = transformer.ParseVolume(vol.MountPath)
if err != nil {
log.Warningf("Failed to configure container volume: %v", err)
continue
}
log.Debug("Volume name %s", vol.VolumeName)

if vol.VFrom == "" {
vol.PVCName = fmt.Sprintf("%s-claim%d", vol.SvcName, count)
count++
}

}
var temp = komposeObject.ServiceConfigs[name]
temp.Vols = FinalVol
komposeObject.ServiceConfigs[name] = temp
}

for _, service := range komposeObject.ServiceConfigs {
for v, _ := range service.Vols {
vol := &service.Vols[v]
if vol.VFrom != "" {
for _, j := range komposeObject.ServiceConfigs[vol.VFrom].Vols {
if vol.MountPath == j.MountPath {
vol.PVCName = j.PVCName
}
}
}
}
}

return komposeObject, nil
}

func findDuplicateVol(vols kobject.Volumes, volumes []kobject.Volumes) bool {
for _, v := range volumes {
if vols.MountPath == v.MountPath {
return true
}
}
return false
}

func handleVolume(svcName string, komposeObject kobject.KomposeObject) (volume []kobject.Volumes) {

if komposeObject.ServiceConfigs[svcName].VolumesFrom != nil {
for _, depVol := range komposeObject.ServiceConfigs[svcName].VolumesFrom {

dVols := handleVolume(depVol, komposeObject)
var cVols []kobject.Volumes
for _, v := range komposeObject.ServiceConfigs[svcName].Volumes {
vol := kobject.Volumes{
SvcName: svcName,
MountPath: v,
}
cVols = append(cVols, vol)
}
for _, cv := range cVols {
i, dv := getVol(cv, dVols)
if i == true {
if dv.VFrom == "" {
cv.VFrom = dv.SvcName
cv.SvcName = dv.SvcName
} else {
cv.VFrom = dv.VFrom
cv.SvcName = dv.SvcName
}
}
volume = append(volume, cv)
}

for _, dv := range dVols {
if checkvolpresent(dv, cVols) {
dv.VFrom = dv.SvcName
volume = append(volume, dv)
}

}

}
} else {
for _, v := range komposeObject.ServiceConfigs[svcName].Volumes {
vol := kobject.Volumes{
SvcName: svcName,
MountPath: v,
}
volume = append(volume, vol)

}
}
return volume
}

func checkvolpresent(tofind kobject.Volumes, cVols []kobject.Volumes) bool {
for _, cv := range cVols {
if tofind.MountPath != cv.MountPath {
return true
}
}
return false
}

func getVol(tofind kobject.Volumes, dVols []kobject.Volumes) (bool, kobject.Volumes) {
for _, dv := range dVols {
if tofind.MountPath == dv.MountPath {
return true, dv
}
}
return false, kobject.Volumes{}
}
71 changes: 0 additions & 71 deletions pkg/transformer/kubernetes/k8sutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,77 +494,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
}

//Ensure the kubernetes objects are in a consistent order
func SortedKeys(komposeObject kobject.KomposeObject) []string {
var sortedKeys []string
Expand Down
51 changes: 24 additions & 27 deletions pkg/transformer/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -385,56 +386,51 @@ 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 emtpy volumes
// 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
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)
//POC work ############################
for _, vol1 := range service.Vols {

// check if ro/rw mode is defined, default rw
readonly := len(mode) > 0 && mode == "ro"
readonly := len(vol1.Mode) > 0 && vol1.Mode == "ro"

if volumeName == "" {
if vol1.VolumeName == "" {
if useEmptyVolumes {
volumeName = fmt.Sprintf("%s-empty%d", name, count)
volumeName = strings.Replace(vol1.PVCName, "claim", "empty", 1)
} else {
volumeName = fmt.Sprintf("%s-claim%d", name, count)
volumeName = vol1.PVCName
}
count++
}

// create a new volume mount object and append to list
volmount := api.VolumeMount{
Name: volumeName,
ReadOnly: readonly,
MountPath: container,
MountPath: vol1.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 vol1.VFrom == "" {
createdPVC, err := k.CreatePVC(volumeName, vol1.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
Expand All @@ -444,10 +440,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(vol1.Host) > 0 {
log.Warningf("Volume mount on the host %q isn't supported - ignoring path on the host", vol1.Host)
}

}

return volumeMounts, volumes, PVCs, nil
}

Expand Down Expand Up @@ -573,8 +571,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
Expand Down
1 change: 1 addition & 0 deletions pkg/transformer/kubernetes/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func newServiceConfig() kobject.ServiceConfig {
Stdin: true,
Tty: true,
TmpFs: []string{"/tmp"},
Vols: []kobject.Volumes{{SvcName: "app", MountPath: "/tmp/volume", PVCName: "app-claim0" }},
}
}

Expand Down
3 changes: 1 addition & 2 deletions pkg/transformer/openshift/openshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,7 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
if hasBuild {
log.Infof("Buildconfig using %s::%s as source.", buildRepo, buildBranch)
}
// If docker-compose has a volumes_from directive it will be handled here
o.VolumesFrom(&allobjects, komposeObject)

// sort all object so Services are first
o.SortServicesFirst(&allobjects)
return allobjects, nil
Expand Down

0 comments on commit a7a045b

Please sign in to comment.