diff --git a/docs/conversion.md b/docs/conversion.md index 28baf7ae..6804cb5a 100644 --- a/docs/conversion.md +++ b/docs/conversion.md @@ -31,7 +31,7 @@ __Glossary:__ | deploy | - | - | ✓ | | | | deploy: mode | - | - | ✓ | | | | deploy: replicas | - | - | ✓ | Deployment.Spec.Replicas / DeploymentConfig.Spec.Replicas | | -| deploy: placement | - | - | n | | | +| deploy: placement | - | - | ✓ | Pod.Spec.NodeSelector | | | deploy: update_config | - | - | n | | | | deploy: resources | - | - | ✓ | Containers.Resources.Limits.Memory | Support for memory but not CPU | | deploy: restart_policy | - | - | ✓ | Pod generation | This generated a Pod, see the [user guide on restart](http://kompose.io/user-guide/#restart) | diff --git a/pkg/kobject/kobject.go b/pkg/kobject/kobject.go index dc81990e..ec206837 100644 --- a/pkg/kobject/kobject.go +++ b/pkg/kobject/kobject.go @@ -103,6 +103,7 @@ type ServiceConfig struct { GroupAdd []int64 `compose:"group_add"` Volumes []Volumes `compose:""` HealthChecks HealthCheck `compose:""` + Placement map[string]string `compose:""` } // HealthCheck the healthcheck configuration for a service diff --git a/pkg/loader/compose/v3.go b/pkg/loader/compose/v3.go index 05fd1baa..b1fe685c 100644 --- a/pkg/loader/compose/v3.go +++ b/pkg/loader/compose/v3.go @@ -294,6 +294,20 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose serviceConfig.Replicas = int(*composeServiceConfig.Deploy.Replicas) } + // placement: + placement := make(map[string]string) + for _, j := range composeServiceConfig.Deploy.Placement.Constraints { + p := strings.Split(j, " == ") + if p[0] == "node.hostname" { + placement["kubernetes.io/hostname"] = p[1] + } else if p[0] == "engine.labels.operatingsystem" { + placement["beta.kubernetes.io/os"] = p[1] + } else { + log.Warn(p[0], " constraints in placement is not supported, only 'node.hostname' and 'engine.labels.operatingsystem' is only supported as a constraint ") + } + } + serviceConfig.Placement = placement + // TODO: Build is not yet supported, see: // https://github.com/docker/cli/blob/master/cli/compose/types/types.go#L9 // We will have to *manually* add this / parse. diff --git a/pkg/transformer/kubernetes/k8sutils.go b/pkg/transformer/kubernetes/k8sutils.go index 00a31bb2..6a0d7621 100644 --- a/pkg/transformer/kubernetes/k8sutils.go +++ b/pkg/transformer/kubernetes/k8sutils.go @@ -380,7 +380,7 @@ func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.Servic template.Spec.Containers[0].Stdin = service.Stdin template.Spec.Containers[0].TTY = service.Tty template.Spec.Volumes = volumes - + template.Spec.NodeSelector = service.Placement // Configure the HealthCheck // We check to see if it's blank if !reflect.DeepEqual(service.HealthChecks, kobject.HealthCheck{}) { diff --git a/script/test/cmd/tests.sh b/script/test/cmd/tests.sh index e79f6b0a..3f2be307 100755 --- a/script/test/cmd/tests.sh +++ b/script/test/cmd/tests.sh @@ -483,6 +483,29 @@ cmd="kompose convert -f $KOMPOSE_ROOT/script/test/fixtures/controller/docker-com sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/controller/output-k8s-rc-template.json > /tmp/output-k8s.json convert::expect_success "kompose convert -f $KOMPOSE_ROOT/script/test/fixtures/controller/docker-compose.yml --stdout -j --controller=replicationcontroller" "/tmp/output-k8s.json" +# Test the `placement` key in v3 + +# Kubernetes +cmd="kompose convert --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose.yml" +sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/placement/output-k8s-template.json > /tmp/output-k8s.json +convert::expect_success "kompose convert --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose.yml" "/tmp/output-k8s.json" + +## OpenShift +cmd="kompose convert --provider=openshift --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose.yml" +sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/placement/output-os-template.json > /tmp/output-os.json +convert::expect_success "kompose convert --provider=openshift --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose.yml" "/tmp/output-os.json" + +# Test the `placement` key with constraints in array in v3 + +# Kubernetes +cmd="kompose convert --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose-array.yml" +sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/placement/output-k8s-array-template.json > /tmp/output-k8s.json +convert::expect_success "kompose convert --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose-array.yml" "/tmp/output-k8s.json" + +## OpenShift +cmd="kompose convert --provider=openshift --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose-array.yml" +sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/placement/output-os-array-template.json > /tmp/output-os.json +convert::expect_success "kompose convert --provider=openshift --stdout -j -f $KOMPOSE_ROOT/script/test/fixtures/placement/docker-compose-array.yml" "/tmp/output-os.json" # Test the "full example" from https://raw.githubusercontent.com/aanand/compose-file/master/loader/example1.env diff --git a/script/test/fixtures/placement/docker-compose-array.yml b/script/test/fixtures/placement/docker-compose-array.yml new file mode 100644 index 00000000..b7af3b39 --- /dev/null +++ b/script/test/fixtures/placement/docker-compose-array.yml @@ -0,0 +1,8 @@ +version: '3' +services: + db: + image: postgres + deploy: + placement: + constraints: [node.hostname == machine] + diff --git a/script/test/fixtures/placement/docker-compose.yml b/script/test/fixtures/placement/docker-compose.yml new file mode 100644 index 00000000..5b48d155 --- /dev/null +++ b/script/test/fixtures/placement/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' +services: + db: + image: postgres + deploy: + placement: + constraints: + - node.hostname == machine + - engine.labels.operatingsystem == ubuntu 14.04 + diff --git a/script/test/fixtures/placement/output-k8s-array-template.json b/script/test/fixtures/placement/output-k8s-array-template.json new file mode 100644 index 00000000..89db8079 --- /dev/null +++ b/script/test/fixtures/placement/output-k8s-array-template.json @@ -0,0 +1,79 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "io.kompose.service": "db" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + } + }, + "spec": { + "containers": [ + { + "name": "db", + "image": "postgres", + "resources": {} + } + ], + "restartPolicy": "Always", + "nodeSelector": { + "kubernetes.io/hostname": "machine" + } + } + }, + "strategy": {} + }, + "status": {} + } + ] +} diff --git a/script/test/fixtures/placement/output-k8s-template.json b/script/test/fixtures/placement/output-k8s-template.json new file mode 100644 index 00000000..0b9506e1 --- /dev/null +++ b/script/test/fixtures/placement/output-k8s-template.json @@ -0,0 +1,80 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "io.kompose.service": "db" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + } + }, + "spec": { + "containers": [ + { + "name": "db", + "image": "postgres", + "resources": {} + } + ], + "restartPolicy": "Always", + "nodeSelector": { + "beta.kubernetes.io/os": "ubuntu 14.04", + "kubernetes.io/hostname": "machine" + } + } + }, + "strategy": {} + }, + "status": {} + } + ] +} diff --git a/script/test/fixtures/placement/output-os-array-template.json b/script/test/fixtures/placement/output-os-array-template.json new file mode 100644 index 00000000..65d00b4e --- /dev/null +++ b/script/test/fixtures/placement/output-os-array-template.json @@ -0,0 +1,131 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "io.kompose.service": "db" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "DeploymentConfig", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "strategy": { + "resources": {} + }, + "triggers": [ + { + "type": "ConfigChange" + }, + { + "type": "ImageChange", + "imageChangeParams": { + "automatic": true, + "containerNames": [ + "db" + ], + "from": { + "kind": "ImageStreamTag", + "name": "db:latest" + } + } + } + ], + "replicas": 1, + "test": false, + "selector": { + "io.kompose.service": "db" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + } + }, + "spec": { + "containers": [ + { + "name": "db", + "image": " ", + "resources": {} + } + ], + "restartPolicy": "Always", + "nodeSelector": { + "kubernetes.io/hostname": "machine" + } + } + } + }, + "status": {} + }, + { + "kind": "ImageStream", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + } + }, + "spec": { + "tags": [ + { + "name": "latest", + "annotations": null, + "from": { + "kind": "DockerImage", + "name": "postgres" + }, + "generation": null, + "importPolicy": {} + } + ] + }, + "status": { + "dockerImageRepository": "" + } + } + ] +} diff --git a/script/test/fixtures/placement/output-os-template.json b/script/test/fixtures/placement/output-os-template.json new file mode 100644 index 00000000..466ff546 --- /dev/null +++ b/script/test/fixtures/placement/output-os-template.json @@ -0,0 +1,132 @@ +{ + "kind": "List", + "apiVersion": "v1", + "metadata": {}, + "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "io.kompose.service": "db" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "DeploymentConfig", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + }, + "annotations": { + "kompose.cmd": "%CMD%", + "kompose.version": "%VERSION%" + } + }, + "spec": { + "strategy": { + "resources": {} + }, + "triggers": [ + { + "type": "ConfigChange" + }, + { + "type": "ImageChange", + "imageChangeParams": { + "automatic": true, + "containerNames": [ + "db" + ], + "from": { + "kind": "ImageStreamTag", + "name": "db:latest" + } + } + } + ], + "replicas": 1, + "test": false, + "selector": { + "io.kompose.service": "db" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + } + }, + "spec": { + "containers": [ + { + "name": "db", + "image": " ", + "resources": {} + } + ], + "restartPolicy": "Always", + "nodeSelector": { + "beta.kubernetes.io/os": "ubuntu 14.04", + "kubernetes.io/hostname": "machine" + } + } + } + }, + "status": {} + }, + { + "kind": "ImageStream", + "apiVersion": "v1", + "metadata": { + "name": "db", + "creationTimestamp": null, + "labels": { + "io.kompose.service": "db" + } + }, + "spec": { + "tags": [ + { + "name": "latest", + "annotations": null, + "from": { + "kind": "DockerImage", + "name": "postgres" + }, + "generation": null, + "importPolicy": {} + } + ] + }, + "status": { + "dockerImageRepository": "" + } + } + ] +}