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:
parent
676fead88e
commit
e879164c2e
@ -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...)
|
||||
}
|
||||
|
||||
@ -51,5 +51,12 @@ convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/ports-wit
|
||||
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/ports-with-proto/docker-compose.yml convert --stdout --dc" "$KOMPOSE_ROOT/script/test/fixtures/ports-with-proto/output-os.json"
|
||||
|
||||
|
||||
######
|
||||
# Tests related to docker-compose file in /script/test/fixtures/volume-mounts/simple-vol-mounts
|
||||
# kubernetes test
|
||||
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/simple-vol-mounts/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/volume-mounts/simple-vol-mounts/output-k8s.json"
|
||||
# openshift test
|
||||
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/volume-mounts/simple-vol-mounts/docker-compose.yml convert --stdout --dc" "$KOMPOSE_ROOT/script/test/fixtures/volume-mounts/simple-vol-mounts/output-os.json"
|
||||
|
||||
exit $EXIT_STATUS
|
||||
|
||||
|
||||
9
script/test/fixtures/volume-mounts/simple-vol-mounts/docker-compose.yml
vendored
Normal file
9
script/test/fixtures/volume-mounts/simple-vol-mounts/docker-compose.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
version: "2"
|
||||
|
||||
services:
|
||||
httpd:
|
||||
image: docker.io/fedora/apache
|
||||
ports:
|
||||
- "80"
|
||||
volumes:
|
||||
- /var/www/html
|
||||
104
script/test/fixtures/volume-mounts/simple-vol-mounts/output-k8s.json
vendored
Normal file
104
script/test/fixtures/volume-mounts/simple-vol-mounts/output-k8s.json
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
{
|
||||
"kind": "List",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "httpd",
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"ports": [
|
||||
{
|
||||
"name": "80",
|
||||
"protocol": "TCP",
|
||||
"port": 80,
|
||||
"targetPort": 80
|
||||
}
|
||||
],
|
||||
"selector": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"loadBalancer": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "extensions/v1beta1",
|
||||
"metadata": {
|
||||
"name": "httpd",
|
||||
"creationTimestamp": null
|
||||
},
|
||||
"spec": {
|
||||
"replicas": 1,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "httpd-claim0",
|
||||
"persistentVolumeClaim": {
|
||||
"claimName": "httpd-claim0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "httpd",
|
||||
"image": "docker.io/fedora/apache",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "httpd-claim0",
|
||||
"mountPath": "/var/www/html"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always"
|
||||
}
|
||||
},
|
||||
"strategy": {}
|
||||
},
|
||||
"status": {}
|
||||
},
|
||||
{
|
||||
"kind": "PersistentVolumeClaim",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "httpd-claim0",
|
||||
"creationTimestamp": null
|
||||
},
|
||||
"spec": {
|
||||
"accessModes": [
|
||||
"ReadWriteOnce"
|
||||
],
|
||||
"resources": {
|
||||
"requests": {
|
||||
"storage": "100Mi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
156
script/test/fixtures/volume-mounts/simple-vol-mounts/output-os.json
vendored
Normal file
156
script/test/fixtures/volume-mounts/simple-vol-mounts/output-os.json
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
{
|
||||
"kind": "List",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Service",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "httpd",
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"ports": [
|
||||
{
|
||||
"name": "80",
|
||||
"protocol": "TCP",
|
||||
"port": 80,
|
||||
"targetPort": 80
|
||||
}
|
||||
],
|
||||
"selector": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"loadBalancer": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "DeploymentConfig",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "httpd",
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"strategy": {
|
||||
"resources": {}
|
||||
},
|
||||
"triggers": [
|
||||
{
|
||||
"type": "ConfigChange"
|
||||
},
|
||||
{
|
||||
"type": "ImageChange",
|
||||
"imageChangeParams": {
|
||||
"automatic": true,
|
||||
"containerNames": [
|
||||
"httpd"
|
||||
],
|
||||
"from": {
|
||||
"kind": "ImageStreamTag",
|
||||
"name": "httpd:latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"replicas": 1,
|
||||
"test": false,
|
||||
"selector": {
|
||||
"service": "httpd"
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"service": "httpd"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "httpd-claim0",
|
||||
"persistentVolumeClaim": {
|
||||
"claimName": "httpd-claim0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "httpd",
|
||||
"image": " ",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "httpd-claim0",
|
||||
"mountPath": "/var/www/html"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {}
|
||||
},
|
||||
{
|
||||
"kind": "ImageStream",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "httpd",
|
||||
"creationTimestamp": null
|
||||
},
|
||||
"spec": {
|
||||
"tags": [
|
||||
{
|
||||
"name": "latest",
|
||||
"annotations": null,
|
||||
"from": {
|
||||
"kind": "DockerImage",
|
||||
"name": "docker.io/fedora/apache"
|
||||
},
|
||||
"generation": null,
|
||||
"importPolicy": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"dockerImageRepository": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "PersistentVolumeClaim",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "httpd-claim0",
|
||||
"creationTimestamp": null
|
||||
},
|
||||
"spec": {
|
||||
"accessModes": [
|
||||
"ReadWriteOnce"
|
||||
],
|
||||
"resources": {
|
||||
"requests": {
|
||||
"storage": "100Mi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user