forked from LaconicNetwork/kompose
Create PVC object for docker-compose volumes
Instead of creating emptydir, create PersistentVolumeClaim for docker-compose volumes by default Fixes #150
This commit is contained in:
@@ -182,6 +182,8 @@ func PrintList(objects []runtime.Object, opt kobject.ConvertOptions) error {
|
||||
file = transformer.Print(t.Name, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
|
||||
case *api.Service:
|
||||
file = transformer.Print(t.Name, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
|
||||
case *api.PersistentVolumeClaim:
|
||||
file = transformer.Print(t.Name, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
|
||||
}
|
||||
files = append(files, file)
|
||||
}
|
||||
@@ -250,12 +252,20 @@ func CreateService(name string, service kobject.ServiceConfig, objects []runtime
|
||||
}
|
||||
|
||||
// load configurations to k8s objects
|
||||
func UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects []runtime.Object) {
|
||||
func UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects *[]runtime.Object) {
|
||||
// Configure the environment variables.
|
||||
envs := ConfigEnvs(name, service)
|
||||
|
||||
// Configure the container volumes.
|
||||
volumesMount, volumes := ConfigVolumes(service)
|
||||
volumesMount, volumes, pvc := ConfigVolumes(name, service)
|
||||
if pvc != nil {
|
||||
// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`
|
||||
// because the type of objects and pvc is different, but when doing append
|
||||
// one element at a time it gets converted to runtime.Object for objects slice
|
||||
for _, p := range pvc {
|
||||
*objects = append(*objects, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the container ports.
|
||||
ports := ConfigPorts(name, service)
|
||||
@@ -301,7 +311,7 @@ func UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects
|
||||
}
|
||||
|
||||
// update supported controller
|
||||
for _, obj := range objects {
|
||||
for _, obj := range *objects {
|
||||
UpdateController(obj, fillTemplate, fillObjectMeta)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
// install kubernetes api
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
@@ -146,6 +147,38 @@ func InitDS(name string, service kobject.ServiceConfig) *extensions.DaemonSet {
|
||||
return ds
|
||||
}
|
||||
|
||||
// Initialize PersistentVolumeClaim
|
||||
func CreatePVC(name string, mode string) *api.PersistentVolumeClaim {
|
||||
size, err := resource.ParseQuantity("100Mi")
|
||||
if err != nil {
|
||||
logrus.Fatalf("Error parsing size")
|
||||
}
|
||||
|
||||
pvc := &api.PersistentVolumeClaim{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "PersistentVolumeClaim",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: api.PersistentVolumeClaimSpec{
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.ResourceStorage: size,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if mode == "ro" {
|
||||
pvc.Spec.AccessModes = []api.PersistentVolumeAccessMode{"ReadWriteOnce"}
|
||||
} else {
|
||||
pvc.Spec.AccessModes = []api.PersistentVolumeAccessMode{"ReadWriteOnce"}
|
||||
}
|
||||
return pvc
|
||||
}
|
||||
|
||||
// Configure the container ports.
|
||||
func ConfigPorts(name string, service kobject.ServiceConfig) []api.ContainerPort {
|
||||
ports := []api.ContainerPort{}
|
||||
@@ -180,34 +213,49 @@ func ConfigServicePorts(name string, service kobject.ServiceConfig) []api.Servic
|
||||
}
|
||||
|
||||
// Configure the container volumes.
|
||||
func ConfigVolumes(service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume) {
|
||||
func ConfigVolumes(name string, service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume, []*api.PersistentVolumeClaim) {
|
||||
volumesMount := []api.VolumeMount{}
|
||||
volumes := []api.Volume{}
|
||||
volumeSource := api.VolumeSource{}
|
||||
var pvc []*api.PersistentVolumeClaim
|
||||
|
||||
var count int
|
||||
for _, volume := range service.Volumes {
|
||||
name, host, container, mode, err := transformer.ParseVolume(volume)
|
||||
volumeName, host, container, mode, err := transformer.ParseVolume(volume)
|
||||
if err != nil {
|
||||
logrus.Warningf("Failed to configure container volume: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// if volume name isn't specified, set it to a random string of 20 chars
|
||||
if len(name) == 0 {
|
||||
name = transformer.RandStringBytes(20)
|
||||
if volumeName == "" {
|
||||
volumeName = fmt.Sprintf("%s-claim%d", name, count)
|
||||
count++
|
||||
}
|
||||
// check if ro/rw mode is defined, default rw
|
||||
readonly := len(mode) > 0 && mode == "ro"
|
||||
|
||||
volumesMount = append(volumesMount, api.VolumeMount{Name: name, ReadOnly: readonly, MountPath: container})
|
||||
volmount := api.VolumeMount{
|
||||
Name: volumeName,
|
||||
ReadOnly: readonly,
|
||||
MountPath: container,
|
||||
}
|
||||
volumesMount = append(volumesMount, volmount)
|
||||
|
||||
vol := api.Volume{
|
||||
Name: volumeName,
|
||||
VolumeSource: api.VolumeSource{
|
||||
PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: volumeName,
|
||||
ReadOnly: readonly,
|
||||
},
|
||||
},
|
||||
}
|
||||
volumes = append(volumes, vol)
|
||||
|
||||
if len(host) > 0 {
|
||||
logrus.Warningf("Volume mount on the host %q isn't supported - ignoring path on the host", host)
|
||||
}
|
||||
volumeSource = api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}
|
||||
|
||||
volumes = append(volumes, api.Volume{Name: name, VolumeSource: volumeSource})
|
||||
pvc = append(pvc, CreatePVC(volumeName, mode))
|
||||
}
|
||||
return volumesMount, volumes
|
||||
return volumesMount, volumes, pvc
|
||||
}
|
||||
|
||||
// Configure the environment variables.
|
||||
@@ -255,7 +303,7 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
|
||||
objects = append(objects, svc)
|
||||
}
|
||||
|
||||
UpdateKubernetesObjects(name, service, objects)
|
||||
UpdateKubernetesObjects(name, service, &objects)
|
||||
|
||||
allobjects = append(allobjects, objects...)
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ func checkPodTemplate(config kobject.ServiceConfig, template api.PodTemplateSpec
|
||||
if !equalStringSlice(config.Args, container.Args) {
|
||||
return fmt.Errorf("Found different container args: %#v vs. %#v", config.Args, container.Args)
|
||||
}
|
||||
if len(template.Spec.Volumes) == 0 || len(template.Spec.Volumes[0].Name) == 0 || template.Spec.Volumes[0].VolumeSource.EmptyDir == nil {
|
||||
if len(template.Spec.Volumes) == 0 || len(template.Spec.Volumes[0].Name) == 0 || template.Spec.Volumes[0].VolumeSource.PersistentVolumeClaim == nil {
|
||||
return fmt.Errorf("Found incorrect volumes: %v vs. %#v", config.Volumes, template.Spec.Volumes)
|
||||
}
|
||||
// We only set controller labels here and k8s server will take care of other defaults, such as selectors
|
||||
@@ -202,10 +202,12 @@ func TestKomposeConvert(t *testing.T) {
|
||||
opt kobject.ConvertOptions
|
||||
expectedNumObjs int
|
||||
}{
|
||||
"Convert to Deployments (D)": {newKomposeObject(), kobject.ConvertOptions{CreateD: true, Replicas: replicas}, 2},
|
||||
"Convert to DaemonSets (DS)": {newKomposeObject(), kobject.ConvertOptions{CreateDS: true}, 2},
|
||||
"Convert to ReplicationController (RC)": {newKomposeObject(), kobject.ConvertOptions{CreateRC: true, Replicas: replicas}, 2},
|
||||
"Convert to D, DS, and RC": {newKomposeObject(), kobject.ConvertOptions{CreateD: true, CreateDS: true, CreateRC: true, Replicas: replicas}, 4},
|
||||
// objects generated are deployment, service and pvc
|
||||
"Convert to Deployments (D)": {newKomposeObject(), kobject.ConvertOptions{CreateD: true, Replicas: replicas}, 3},
|
||||
"Convert to DaemonSets (DS)": {newKomposeObject(), kobject.ConvertOptions{CreateDS: true}, 3},
|
||||
"Convert to ReplicationController (RC)": {newKomposeObject(), kobject.ConvertOptions{CreateRC: true, Replicas: replicas}, 3},
|
||||
// objects generated are deployment, daemonset, ReplicationController, service and pvc
|
||||
"Convert to D, DS, and RC": {newKomposeObject(), kobject.ConvertOptions{CreateD: true, CreateDS: true, CreateRC: true, Replicas: replicas}, 5},
|
||||
// TODO: add more tests
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ func (k *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
|
||||
objects = append(objects, svc)
|
||||
}
|
||||
|
||||
kubernetes.UpdateKubernetesObjects(name, service, objects)
|
||||
kubernetes.UpdateKubernetesObjects(name, service, &objects)
|
||||
|
||||
allobjects = append(allobjects, objects...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user