Support multiple hostnames on expose label in service for Kubernetes (#1092)

* Support multiple hostnames on label (kompose.service.expose) separated by semicolon (;)

* Multiple hostnames on expose label separated by comma; Ignore leading / trailing spaces and repeated commas; Updated test cases and documents.
This commit is contained in:
huikaihoo 2019-01-31 22:34:04 +08:00 committed by Charlie Drage
parent 75ecc88aef
commit 40c1b8cf87
9 changed files with 469 additions and 24 deletions

View File

@ -298,7 +298,7 @@ The currently supported options are:
| Key | Value |
|----------------------|-------------------------------------|
| kompose.service.type | nodeport / clusterip / loadbalancer / headless |
| kompose.service.expose | true / hostname |
| kompose.service.expose | true / hostnames (separated by comma) |
| kompose.service.expose.tls-secret | secret name |
| kompose.volume.size | kubernetes supported volume size |
| kompose.controller.type | deployment / daemonset / replicationcontroller |
@ -326,7 +326,7 @@ services:
```
- `kompose.service.expose` defines if the service needs to be made accessible from outside the cluster or not. If the value is set to "true", the provider sets the endpoint automatically, and for any other value, the value is set as the hostname. If multiple ports are defined in a service, the first one is chosen to be the exposed.
- For the Kubernetes provider, an ingress resource is created and it is assumed that an ingress controller has already been configured.
- For the Kubernetes provider, an ingress resource is created and it is assumed that an ingress controller has already been configured. If the value is set to a comma sepatated list, multiple hostnames are supported.
- For the OpenShift provider, a route is created.
- `kompose.service.expose.tls-secret` provides the name of the TLS secret to use with the Kubernetes ingress controller. This requires kompose.service.expose to be set.
@ -342,7 +342,7 @@ services:
links:
- redis
labels:
kompose.service.expose: "counter.example.com"
kompose.service.expose: "counter.example.com,foobar.example.com"
kompose.service.expose.tls-secret: "example-secret"
redis:
image: redis:3.0

View File

@ -243,7 +243,7 @@ func libComposeToKomposeMapping(composeObject *project.Project) (kobject.Kompose
serviceConfig.ServiceType = serviceType
case LabelServiceExpose:
serviceConfig.ExposeService = strings.ToLower(value)
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
default:

View File

@ -398,7 +398,7 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose
serviceConfig.ServiceType = serviceType
case LabelServiceExpose:
serviceConfig.ExposeService = strings.ToLower(value)
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
}

View File

@ -19,6 +19,7 @@ package kubernetes
import (
"fmt"
"reflect"
"regexp"
"strconv"
"time"
@ -324,6 +325,8 @@ func (k *Kubernetes) InitDS(name string, service kobject.ServiceConfig) *extensi
func (k *Kubernetes) initIngress(name string, service kobject.ServiceConfig, port int32) *extensions.Ingress {
hosts := regexp.MustCompile("[ ,]*,[ ,]*").Split(service.ExposeService, -1)
ingress := &extensions.Ingress{
TypeMeta: unversioned.TypeMeta{
Kind: "Ingress",
@ -334,36 +337,36 @@ func (k *Kubernetes) initIngress(name string, service kobject.ServiceConfig, por
Labels: transformer.ConfigLabels(name),
},
Spec: extensions.IngressSpec{
Rules: []extensions.IngressRule{
{
IngressRuleValue: extensions.IngressRuleValue{
HTTP: &extensions.HTTPIngressRuleValue{
Paths: []extensions.HTTPIngressPath{
{
Backend: extensions.IngressBackend{
ServiceName: name,
ServicePort: intstr.IntOrString{
IntVal: port,
},
},
Rules: make([]extensions.IngressRule, len(hosts)),
},
}
for i, host := range hosts {
ingress.Spec.Rules[i] = extensions.IngressRule{
IngressRuleValue: extensions.IngressRuleValue{
HTTP: &extensions.HTTPIngressRuleValue{
Paths: []extensions.HTTPIngressPath{
{
Backend: extensions.IngressBackend{
ServiceName: name,
ServicePort: intstr.IntOrString{
IntVal: port,
},
},
},
},
},
},
},
}
if host != "true" {
ingress.Spec.Rules[i].Host = host
}
}
if service.ExposeService != "true" {
ingress.Spec.Rules[0].Host = service.ExposeService
}
if service.ExposeServiceTLS != "" {
ingress.Spec.TLS = []extensions.IngressTLS{
{
Hosts: []string{
service.ExposeService,
},
Hosts: hosts,
SecretName: service.ExposeServiceTLS,
},
}

View File

@ -388,6 +388,14 @@ convert::expect_success "$cmd" "/tmp/output-k8s.json"
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-hostname-multiple-ports.yml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-hostname-multiple-ports.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
# when kompose.service.expose="<hostname_1>;<hostname_2>;...<hostname_N>"
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-multiple-hostname.yml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-multiple-hostname.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
# when kompose.service.expose="<hostname_1>;<hostname_2>;...<hostname_N>" and kompose.service.expose.tls-secret="<secret>"
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-multiple-hostname-tls.yml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-multiple-hostname-tls.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
#openshift tests
# when kompose.service.expose="True"

View File

@ -0,0 +1,13 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: "batman.example.com,batwoman.example.com"
kompose.service.expose.tls-secret: "test-secret"
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -0,0 +1,12 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: " batman.example.com ,, batwoman.example.com "
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -0,0 +1,210 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%"
}
},
"spec": {
"ports": [
{
"name": "6379",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"io.kompose.service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%",
"kompose.service.expose": "batman.example.com,batwoman.example.com",
"kompose.service.expose.tls-secret": "test-secret"
}
},
"spec": {
"ports": [
{
"name": "5000",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"io.kompose.service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": "redis:3.0",
"ports": [
{
"containerPort": 6379
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%",
"kompose.service.expose": "batman.example.com,batwoman.example.com",
"kompose.service.expose.tls-secret": "test-secret"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "tuna/docker-counter23",
"ports": [
{
"containerPort": 5000
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Ingress",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"tls": [
{
"hosts": [
"batman.example.com",
"batwoman.example.com"
],
"secretName": "test-secret"
}
],
"rules": [
{
"host": "batman.example.com",
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
},
{
"host": "batwoman.example.com",
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
}
]
}

View File

@ -0,0 +1,199 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%"
}
},
"spec": {
"ports": [
{
"name": "6379",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"io.kompose.service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%",
"kompose.service.expose": " batman.example.com ,, batwoman.example.com "
}
},
"spec": {
"ports": [
{
"name": "5000",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"io.kompose.service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": "redis:3.0",
"ports": [
{
"containerPort": 6379
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.version": "%VERSION%",
"kompose.service.expose": " batman.example.com ,, batwoman.example.com "
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "tuna/docker-counter23",
"ports": [
{
"containerPort": 5000
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Ingress",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"rules": [
{
"host": "batman.example.com",
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
},
{
"host": "batwoman.example.com",
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
}
]
}