From 3193ac3bd710479f223274498f5b7c864ce2d8c9 Mon Sep 17 00:00:00 2001 From: sebgoa Date: Thu, 15 Sep 2016 12:31:40 +0200 Subject: [PATCH 1/4] Handle Headless Services when no ports are present --- pkg/transformer/kubernetes/k8sutils.go | 23 +- pkg/transformer/kubernetes/kubernetes.go | 3 + script/test/cmd/tests.sh | 9 +- .../test/fixtures/bundles/dsb/output-k8s.json | 89 +- .../entrypoint-command/output-k8s.json | 27 + .../envvars-separators/output-k8s.json | 1344 ++++++++++------- 6 files changed, 922 insertions(+), 573 deletions(-) diff --git a/pkg/transformer/kubernetes/k8sutils.go b/pkg/transformer/kubernetes/k8sutils.go index df54fe9c..76bfb743 100644 --- a/pkg/transformer/kubernetes/k8sutils.go +++ b/pkg/transformer/kubernetes/k8sutils.go @@ -258,7 +258,7 @@ func convertToVersion(obj runtime.Object, groupVersion unversioned.GroupVersion) // PortsExist checks if service has ports defined func (k *Kubernetes) PortsExist(name string, service kobject.ServiceConfig) bool { if len(service.Port) == 0 { - logrus.Warningf("[%s] Service cannot be created because of missing port.", name) + logrus.Warningf("[%s] No ports defined, we will create a Headless service.", name) return false } return true @@ -282,6 +282,27 @@ func (k *Kubernetes) CreateService(name string, service kobject.ServiceConfig, o return svc } +// CreateHeadlessService creates a k8s headless service +func (k *Kubernetes) CreateHeadlessService(name string, service kobject.ServiceConfig, objects []runtime.Object) *api.Service { + svc := k.InitSvc(name, service) + + servicePorts := []api.ServicePort{} + // Configure a dummy port: https://github.com/kubernetes/kubernetes/issues/32766. + servicePorts = append(servicePorts, api.ServicePort{ + Name: "headless", + Port: 55555, + }) + + svc.Spec.Ports = servicePorts + svc.Spec.ClusterIP = "None" + + // Configure annotations + annotations := transformer.ConfigAnnotations(service) + svc.ObjectMeta.Annotations = annotations + + return svc +} + // UpdateKubernetesObjects loads configurations to k8s objects func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects *[]runtime.Object) { // Configure the environment variables. diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index 9c15f553..1df93961 100644 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -477,6 +477,9 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject. if service.ExposeService != "" { objects = append(objects, k.initIngress(name, service, svc.Spec.Ports[0].Port)) } + } else { + svc := k.CreateHeadlessService(name, service, objects) + objects = append(objects, svc) } } diff --git a/script/test/cmd/tests.sh b/script/test/cmd/tests.sh index aca7d7f0..66a53b16 100755 --- a/script/test/cmd/tests.sh +++ b/script/test/cmd/tests.sh @@ -23,7 +23,8 @@ convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/ # commenting this test case out until image handling is fixed convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose-no-image.yml convert --stdout" -convert::expect_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose-no-ports.yml convert --stdout" "Service cannot be created because of missing port." +convert::expect_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose-no-ports.yml convert --stdout" "No ports defined, we will create a Headless service." + export $(cat $KOMPOSE_ROOT/script/test/fixtures/etherpad/envs) # kubernetes test convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/etherpad/output-k8s.json" "Unsupported depends_on key - ignoring" @@ -51,9 +52,9 @@ convert::expect_success_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/s ###### # Tests related to docker-compose file in /script/test/fixtures/entrypoint-command # kubernetes test -convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-k8s.json" "Service cannot be created because of missing port." +convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-k8s.json" "No ports defined, we will create a Headless service." # openshift test -convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-os.json" "Service cannot be created because of missing port." +convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-os.json" "No ports defined, we will create a Headless service." ###### @@ -105,7 +106,7 @@ convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_RO ###### # Test related to kompose --bundle convert to ensure that DSB bundles are converted properly -convert::expect_success_and_warning "kompose --bundle $KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/docker-voting-bundle.dsb convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/output-k8s.json" "Service cannot be created because of missing port." +convert::expect_success_and_warning "kompose --bundle $KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/docker-voting-bundle.dsb convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/output-k8s.json" "No ports defined, we will create a Headless service." ###### # Test related to restart options in docker-compose diff --git a/script/test/fixtures/bundles/dsb/output-k8s.json b/script/test/fixtures/bundles/dsb/output-k8s.json index df880bfc..b0912a25 100644 --- a/script/test/fixtures/bundles/dsb/output-k8s.json +++ b/script/test/fixtures/bundles/dsb/output-k8s.json @@ -3,6 +3,33 @@ "apiVersion": "v1", "metadata": {}, "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "worker", + "creationTimestamp": null, + "labels": { + "service": "worker" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "worker" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, { "kind": "Service", "apiVersion": "v1", @@ -117,6 +144,37 @@ "loadBalancer": {} } }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "worker", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "worker" + } + }, + "spec": { + "containers": [ + { + "name": "worker", + "image": "docker/example-voting-app-worker", + "resources": {} + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, { "kind": "Deployment", "apiVersion": "extensions/v1beta1", @@ -270,37 +328,6 @@ "strategy": {} }, "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "worker", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "worker" - } - }, - "spec": { - "containers": [ - { - "name": "worker", - "image": "docker/example-voting-app-worker", - "resources": {} - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} } ] } diff --git a/script/test/fixtures/entrypoint-command/output-k8s.json b/script/test/fixtures/entrypoint-command/output-k8s.json index f74f0546..3c402e50 100644 --- a/script/test/fixtures/entrypoint-command/output-k8s.json +++ b/script/test/fixtures/entrypoint-command/output-k8s.json @@ -39,6 +39,33 @@ "strategy": {} }, "status": {} + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "base", + "creationTimestamp": null, + "labels": { + "service": "base" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "base" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } } ] } diff --git a/script/test/fixtures/envvars-separators/output-k8s.json b/script/test/fixtures/envvars-separators/output-k8s.json index 76511123..587ef42e 100644 --- a/script/test/fixtures/envvars-separators/output-k8s.json +++ b/script/test/fixtures/envvars-separators/output-k8s.json @@ -30,6 +30,222 @@ "loadBalancer": {} } }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-udeploy-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-udeploy-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-udeploy-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-chat-ops-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-chat-ops-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-chat-ops-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-subversion-scm-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-subversion-scm-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-subversion-scm-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-versionone-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-versionone-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-versionone-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-github-scm-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-github-scm-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-github-scm-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-jenkins-build-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-jenkins-build-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-jenkins-build-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-sonar-codequality-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-sonar-codequality-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-sonar-codequality-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-jenkins-cucumber-test-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-jenkins-cucumber-test-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-jenkins-cucumber-test-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, { "kind": "Service", "apiVersion": "v1", @@ -57,6 +273,60 @@ "loadBalancer": {} } }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-bitbucket-scm-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-bitbucket-scm-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-bitbucket-scm-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-jira-feature-collector", + "creationTimestamp": null, + "labels": { + "service": "hygieia-jira-feature-collector" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "hygieia-jira-feature-collector" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, { "kind": "Service", "apiVersion": "v1", @@ -88,7 +358,7 @@ "kind": "Deployment", "apiVersion": "extensions/v1beta1", "metadata": { - "name": "hygieia-sonar-codequality-collector", + "name": "mongodb", "creationTimestamp": null }, "spec": { @@ -97,27 +367,37 @@ "metadata": { "creationTimestamp": null, "labels": { - "service": "hygieia-sonar-codequality-collector" + "service": "mongodb" } }, "spec": { "volumes": [ { - "name": "hygieia-sonar-codequality-collector-claim0", + "name": "mongodb-claim0", "persistentVolumeClaim": { - "claimName": "hygieia-sonar-codequality-collector-claim0" + "claimName": "mongodb-claim0" } } ], "containers": [ { - "name": "hygieia-sonar-codequality", - "image": "hygieia-sonar-codequality-collector:latest", + "name": "mongodb", + "image": "mongo:latest", + "args": [ + "mongod", + "--smallfiles" + ], + "ports": [ + { + "containerPort": 27017, + "protocol": "TCP" + } + ], "resources": {}, "volumeMounts": [ { - "name": "hygieia-sonar-codequality-collector-claim0", - "mountPath": "/hygieia/logs" + "name": "mongodb-claim0", + "mountPath": "/data/db" } ] } @@ -133,7 +413,7 @@ "kind": "PersistentVolumeClaim", "apiVersion": "v1", "metadata": { - "name": "hygieia-sonar-codequality-collector-claim0", + "name": "mongodb-claim0", "creationTimestamp": null }, "spec": { @@ -226,70 +506,6 @@ }, "status": {} }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-bitbucket-scm-collector", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-bitbucket-scm-collector" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-bitbucket-scm-collector-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-bitbucket-scm-collector-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-bitbucket", - "image": "hygieia-bitbucket-scm-collector:latest", - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-bitbucket-scm-collector-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-bitbucket-scm-collector-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, { "kind": "Deployment", "apiVersion": "extensions/v1beta1", @@ -354,6 +570,524 @@ }, "status": {} }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-subversion-scm-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-subversion-scm-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-subversion-scm-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-subversion-scm-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-subversion", + "image": "hygieia-subversion-scm-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-subversion-scm-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-subversion-scm-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-versionone-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-versionone-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-versionone-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-versionone-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-versionone", + "image": "hygieia-versionone-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-versionone-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-versionone-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-github-scm-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-github-scm-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-github-scm-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-github-scm-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-github", + "image": "hygieia-github-scm-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-github-scm-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-github-scm-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-jenkins-build-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-jenkins-build-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-jenkins-build-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-jenkins-build-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-jenkins-build", + "image": "hygieia-jenkins-build-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-jenkins-build-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-jenkins-build-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-sonar-codequality-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-sonar-codequality-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-sonar-codequality-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-sonar-codequality-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-sonar-codequality", + "image": "hygieia-sonar-codequality-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-sonar-codequality-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-sonar-codequality-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-jenkins-cucumber-test-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-jenkins-cucumber-test-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-jenkins-cucumber-test-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-jenkins-cucumber-test-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-jenkins-cucumber", + "image": "hygieia-jenkins-cucumber-test-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-jenkins-cucumber-test-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-jenkins-cucumber-test-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-api", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-api" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-api-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-api-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-api", + "image": "hygieia-api:latest", + "ports": [ + { + "containerPort": 8080, + "protocol": "TCP" + } + ], + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-api-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-api-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, + { + "kind": "Deployment", + "apiVersion": "extensions/v1beta1", + "metadata": { + "name": "hygieia-bitbucket-scm-collector", + "creationTimestamp": null + }, + "spec": { + "replicas": 1, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "service": "hygieia-bitbucket-scm-collector" + } + }, + "spec": { + "volumes": [ + { + "name": "hygieia-bitbucket-scm-collector-claim0", + "persistentVolumeClaim": { + "claimName": "hygieia-bitbucket-scm-collector-claim0" + } + } + ], + "containers": [ + { + "name": "hygieia-bitbucket", + "image": "hygieia-bitbucket-scm-collector:latest", + "resources": {}, + "volumeMounts": [ + { + "name": "hygieia-bitbucket-scm-collector-claim0", + "mountPath": "/hygieia/logs" + } + ] + } + ], + "restartPolicy": "Always" + } + }, + "strategy": {} + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "hygieia-bitbucket-scm-collector-claim0", + "creationTimestamp": null + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "100Mi" + } + } + }, + "status": {} + }, { "kind": "Deployment", "apiVersion": "extensions/v1beta1", @@ -428,406 +1162,6 @@ }, "status": {} }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-jenkins-build-collector", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-jenkins-build-collector" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-jenkins-build-collector-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-jenkins-build-collector-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-jenkins-build", - "image": "hygieia-jenkins-build-collector:latest", - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-jenkins-build-collector-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-jenkins-build-collector-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "mongodb", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "mongodb" - } - }, - "spec": { - "volumes": [ - { - "name": "mongodb-claim0", - "persistentVolumeClaim": { - "claimName": "mongodb-claim0" - } - } - ], - "containers": [ - { - "name": "mongodb", - "image": "mongo:latest", - "args": [ - "mongod", - "--smallfiles" - ], - "ports": [ - { - "containerPort": 27017, - "protocol": "TCP" - } - ], - "resources": {}, - "volumeMounts": [ - { - "name": "mongodb-claim0", - "mountPath": "/data/db" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "mongodb-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-github-scm-collector", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-github-scm-collector" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-github-scm-collector-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-github-scm-collector-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-github", - "image": "hygieia-github-scm-collector:latest", - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-github-scm-collector-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-github-scm-collector-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-api", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-api" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-api-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-api-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-api", - "image": "hygieia-api:latest", - "ports": [ - { - "containerPort": 8080, - "protocol": "TCP" - } - ], - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-api-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-api-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-jenkins-cucumber-test-collector", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-jenkins-cucumber-test-collector" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-jenkins-cucumber-test-collector-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-jenkins-cucumber-test-collector-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-jenkins-cucumber", - "image": "hygieia-jenkins-cucumber-test-collector:latest", - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-jenkins-cucumber-test-collector-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-jenkins-cucumber-test-collector-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-subversion-scm-collector", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-subversion-scm-collector" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-subversion-scm-collector-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-subversion-scm-collector-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-subversion", - "image": "hygieia-subversion-scm-collector:latest", - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-subversion-scm-collector-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-subversion-scm-collector-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} - }, { "kind": "Deployment", "apiVersion": "extensions/v1beta1", @@ -864,70 +1198,6 @@ "strategy": {} }, "status": {} - }, - { - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "hygieia-versionone-collector", - "creationTimestamp": null - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "service": "hygieia-versionone-collector" - } - }, - "spec": { - "volumes": [ - { - "name": "hygieia-versionone-collector-claim0", - "persistentVolumeClaim": { - "claimName": "hygieia-versionone-collector-claim0" - } - } - ], - "containers": [ - { - "name": "hygieia-versionone", - "image": "hygieia-versionone-collector:latest", - "resources": {}, - "volumeMounts": [ - { - "name": "hygieia-versionone-collector-claim0", - "mountPath": "/hygieia/logs" - } - ] - } - ], - "restartPolicy": "Always" - } - }, - "strategy": {} - }, - "status": {} - }, - { - "kind": "PersistentVolumeClaim", - "apiVersion": "v1", - "metadata": { - "name": "hygieia-versionone-collector-claim0", - "creationTimestamp": null - }, - "spec": { - "accessModes": [ - "ReadWriteOnce" - ], - "resources": { - "requests": { - "storage": "100Mi" - } - } - }, - "status": {} } ] } From 5a62864ef9da96fa7a7aba4a8b3902ce4a9d2f6a Mon Sep 17 00:00:00 2001 From: Tomas Kral Date: Tue, 3 Jan 2017 13:54:36 +0100 Subject: [PATCH 2/4] Handle Headless Services for OpenShift --- pkg/transformer/openshift/openshift.go | 3 +++ .../entrypoint-command/output-os.json | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/pkg/transformer/openshift/openshift.go b/pkg/transformer/openshift/openshift.go index f13fd5f9..72207550 100644 --- a/pkg/transformer/openshift/openshift.go +++ b/pkg/transformer/openshift/openshift.go @@ -371,6 +371,9 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C if service.ExposeService != "" { objects = append(objects, o.initRoute(name, service, svc.Spec.Ports[0].Port)) } + } else { + svc := o.CreateHeadlessService(name, service, objects) + objects = append(objects, svc) } } o.UpdateKubernetesObjects(name, service, &objects) diff --git a/script/test/fixtures/entrypoint-command/output-os.json b/script/test/fixtures/entrypoint-command/output-os.json index a4f66049..9e8918ce 100644 --- a/script/test/fixtures/entrypoint-command/output-os.json +++ b/script/test/fixtures/entrypoint-command/output-os.json @@ -3,6 +3,33 @@ "apiVersion": "v1", "metadata": {}, "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "base", + "creationTimestamp": null, + "labels": { + "service": "base" + } + }, + "spec": { + "ports": [ + { + "name": "headless", + "port": 55555, + "targetPort": 0 + } + ], + "selector": { + "service": "base" + }, + "clusterIP": "None" + }, + "status": { + "loadBalancer": {} + } + }, { "kind": "DeploymentConfig", "apiVersion": "v1", From 8f2dd5b03b70c387e26e4c0fbf06060470307e85 Mon Sep 17 00:00:00 2001 From: Tomas Kral Date: Mon, 23 Jan 2017 14:19:02 +0100 Subject: [PATCH 3/4] Test Headless Services --- pkg/testutils/kubernetes.go | 27 +++++++++++++++++++++ pkg/transformer/kubernetes/k8sutils.go | 6 ++++- pkg/transformer/kubernetes/k8sutils_test.go | 21 ++++++++++++++++ pkg/transformer/openshift/openshift_test.go | 20 +++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 pkg/testutils/kubernetes.go diff --git a/pkg/testutils/kubernetes.go b/pkg/testutils/kubernetes.go new file mode 100644 index 00000000..305db81f --- /dev/null +++ b/pkg/testutils/kubernetes.go @@ -0,0 +1,27 @@ +package testutils + +import ( + "errors" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/runtime" +) + +// CheckForHeadless is helper function for tests. +// It checks if all Services in objects are Headless Services and if there is at least one such Services. +func CheckForHeadless(objects []runtime.Object) error { + serviceCreated := false + for _, obj := range objects { + if svc, ok := obj.(*api.Service); ok { + serviceCreated = true + // Check if it is a headless services + if svc.Spec.ClusterIP != "None" { + return errors.New("this is not a Headless services") + } + } + } + if !serviceCreated { + return errors.New("no Service created") + } + return nil +} diff --git a/pkg/transformer/kubernetes/k8sutils.go b/pkg/transformer/kubernetes/k8sutils.go index 76bfb743..00d3bf4d 100644 --- a/pkg/transformer/kubernetes/k8sutils.go +++ b/pkg/transformer/kubernetes/k8sutils.go @@ -282,7 +282,11 @@ func (k *Kubernetes) CreateService(name string, service kobject.ServiceConfig, o return svc } -// CreateHeadlessService creates a k8s headless service +// CreateHeadlessService creates a k8s headless service. +// Thi is used for docker-compose services without ports. For such services we can't create regular Kubernetes Service. +// and without Service Pods can't find each other using DNS names. +// Instead of regular Kubernetes Service we create Headless Service. DNS of such service points directly to Pod IP address. +// You can find more about Headless Services in Kubernetes documentation https://kubernetes.io/docs/user-guide/services/#headless-services func (k *Kubernetes) CreateHeadlessService(name string, service kobject.ServiceConfig, objects []runtime.Object) *api.Service { svc := k.InitSvc(name, service) diff --git a/pkg/transformer/kubernetes/k8sutils_test.go b/pkg/transformer/kubernetes/k8sutils_test.go index 55a413c5..9da4dde6 100644 --- a/pkg/transformer/kubernetes/k8sutils_test.go +++ b/pkg/transformer/kubernetes/k8sutils_test.go @@ -24,6 +24,8 @@ import ( "path/filepath" "github.com/kubernetes-incubator/kompose/pkg/kobject" + "github.com/kubernetes-incubator/kompose/pkg/testutils" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" ) @@ -161,3 +163,22 @@ func TestIsDir(t *testing.T) { t.Errorf("Error removing the temporary directory during cleanup: %v", err) } } + +// TestServiceWithoutPort this tests if Headless Service is created for services without Port. +func TestServiceWithoutPort(t *testing.T) { + service := kobject.ServiceConfig{ + ContainerName: "name", + Image: "image", + } + + komposeObject := kobject.KomposeObject{ + ServiceConfigs: map[string]kobject.ServiceConfig{"app": service}, + } + k := Kubernetes{} + + objects := k.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1}) + if err := testutils.CheckForHeadless(objects); err != nil { + t.Error(err) + } + +} diff --git a/pkg/transformer/openshift/openshift_test.go b/pkg/transformer/openshift/openshift_test.go index 330bbe63..efec3a32 100644 --- a/pkg/transformer/openshift/openshift_test.go +++ b/pkg/transformer/openshift/openshift_test.go @@ -28,6 +28,7 @@ import ( "github.com/kubernetes-incubator/kompose/pkg/kobject" "github.com/kubernetes-incubator/kompose/pkg/testutils" + "github.com/kubernetes-incubator/kompose/pkg/transformer/kubernetes" ) func newServiceConfig() kobject.ServiceConfig { @@ -309,3 +310,22 @@ func TestInitBuildConfig(t *testing.T) { } } } + +// TestServiceWithoutPort this tests if Headless Service is created for services without Port. +func TestServiceWithoutPort(t *testing.T) { + service := kobject.ServiceConfig{ + ContainerName: "name", + Image: "image", + } + + komposeObject := kobject.KomposeObject{ + ServiceConfigs: map[string]kobject.ServiceConfig{"app": service}, + } + o := OpenShift{Kubernetes: kubernetes.Kubernetes{}} + + objects := o.Transform(komposeObject, kobject.ConvertOptions{CreateD: true, Replicas: 1}) + if err := testutils.CheckForHeadless(objects); err != nil { + t.Error(err) + } + +} From 90febe7f7f2cfa4ac195cb4e71779cb83cf9ccdf Mon Sep 17 00:00:00 2001 From: Tomas Kral Date: Tue, 24 Jan 2017 15:09:14 +0100 Subject: [PATCH 4/4] Change warning to debug for services without ports. --- pkg/transformer/kubernetes/k8sutils.go | 2 +- script/test/cmd/tests.sh | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/transformer/kubernetes/k8sutils.go b/pkg/transformer/kubernetes/k8sutils.go index 00d3bf4d..ba6b6d97 100644 --- a/pkg/transformer/kubernetes/k8sutils.go +++ b/pkg/transformer/kubernetes/k8sutils.go @@ -258,7 +258,7 @@ func convertToVersion(obj runtime.Object, groupVersion unversioned.GroupVersion) // PortsExist checks if service has ports defined func (k *Kubernetes) PortsExist(name string, service kobject.ServiceConfig) bool { if len(service.Port) == 0 { - logrus.Warningf("[%s] No ports defined, we will create a Headless service.", name) + logrus.Debugf("[%s] No ports defined. Headless service will be created.", name) return false } return true diff --git a/script/test/cmd/tests.sh b/script/test/cmd/tests.sh index 66a53b16..57665fe9 100755 --- a/script/test/cmd/tests.sh +++ b/script/test/cmd/tests.sh @@ -21,9 +21,7 @@ source $KOMPOSE_ROOT/script/test/cmd/lib.sh # Tests related to docker-compose file in /script/test/fixtures/etherpad convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose.yml convert --stdout" -# commenting this test case out until image handling is fixed convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose-no-image.yml convert --stdout" -convert::expect_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose-no-ports.yml convert --stdout" "No ports defined, we will create a Headless service." export $(cat $KOMPOSE_ROOT/script/test/fixtures/etherpad/envs) # kubernetes test @@ -52,9 +50,9 @@ convert::expect_success_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/s ###### # Tests related to docker-compose file in /script/test/fixtures/entrypoint-command # kubernetes test -convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-k8s.json" "No ports defined, we will create a Headless service." +convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-k8s.json" # openshift test -convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-os.json" "No ports defined, we will create a Headless service." +convert::expect_success "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/entrypoint-command/output-os.json" ###### @@ -106,7 +104,7 @@ convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_RO ###### # Test related to kompose --bundle convert to ensure that DSB bundles are converted properly -convert::expect_success_and_warning "kompose --bundle $KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/docker-voting-bundle.dsb convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/output-k8s.json" "No ports defined, we will create a Headless service." +convert::expect_success_and_warning "kompose --bundle $KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/docker-voting-bundle.dsb convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/bundles/dsb/output-k8s.json" "Unsupported Networks key - ignoring" ###### # Test related to restart options in docker-compose