Support assign nodeport port in labels (#1210)

This commit is contained in:
Hang Yan 2019-12-26 23:45:58 +08:00 committed by GitHub
parent 81bdf77d49
commit 1f0a097836
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 325 additions and 0 deletions

View File

@ -299,6 +299,7 @@ The currently supported options are:
|----------------------|-------------------------------------|
| kompose.service.type | nodeport / clusterip / loadbalancer / headless |
| kompose.service.expose | true / hostnames (separated by comma) |
| kompose.service.nodeport.port | port value (string) |
| kompose.service.expose.tls-secret | secret name |
| kompose.volume.size | kubernetes supported volume size |
| kompose.controller.type | deployment / daemonset / replicationcontroller |
@ -330,6 +331,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. If the value is set to a comma sepatated list, multiple hostnames are supported.
- For the OpenShift provider, a route is created.
- `kompose.service.nodeport.port` defines the port value when service type is `nodeport`, this label should only be set when the service only contains 1 port. Usually kubernetes define a port range for node port values, kompose will not validate this.
- `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.
For example:

View File

@ -96,6 +96,7 @@ type ServiceConfig struct {
User string `compose:"user"`
VolumesFrom []string `compose:"volumes_from"`
ServiceType string `compose:"kompose.service.type"`
NodePortPort int32 `compose:"kompose.service.nodeport.port"`
StopGracePeriod string `compose:"stop_grace_period"`
Build string `compose:"build"`
BuildArgs map[string]*string `compose:"build-args"`

View File

@ -31,6 +31,8 @@ import (
const (
// LabelServiceType defines the type of service to be created
LabelServiceType = "kompose.service.type"
// LabelNodePortPort defines the port value for NodePort service
LabelNodePortPort = "kompose.service.nodeport.port"
// LabelServiceExpose defines if the service needs to be made accessible from outside the cluster or not
LabelServiceExpose = "kompose.service.expose"
// LabelServiceExposeTLSSecret provides the name of the TLS secret to use with the Kubernetes ingress controller

View File

@ -18,6 +18,7 @@ package compose
import (
"fmt"
"github.com/spf13/cast"
"net"
"os"
"path/filepath"
@ -245,6 +246,8 @@ func libComposeToKomposeMapping(composeObject *project.Project) (kobject.Kompose
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
case LabelNodePortPort:
serviceConfig.NodePortPort = cast.ToInt32(value)
case LabelImagePullSecret:
serviceConfig.ImagePullSecret = value
case LabelImagePullPolicy:
@ -256,6 +259,15 @@ func libComposeToKomposeMapping(composeObject *project.Project) (kobject.Kompose
if serviceConfig.ExposeService == "" && serviceConfig.ExposeServiceTLS != "" {
return kobject.KomposeObject{}, errors.New("kompose.service.expose.tls-secret was specified without kompose.service.expose")
}
if serviceConfig.ServiceType != string(api.ServiceTypeNodePort) && serviceConfig.NodePortPort != 0 {
return kobject.KomposeObject{}, errors.New("kompose.service.type must be nodeport when assign node port value")
}
if len(serviceConfig.Port) > 1 && serviceConfig.NodePortPort != 0 {
return kobject.KomposeObject{}, errors.New("cannnot set kompose.service.nodeport.port when service has multiple ports")
}
err = checkLabelsPorts(len(serviceConfig.Port), composeServiceConfig.Labels[LabelServiceType], name)
if err != nil {
return kobject.KomposeObject{}, errors.Wrap(err, "kompose.service.type can't be set if service doesn't expose any ports.")

View File

@ -17,6 +17,7 @@ limitations under the License.
package compose
import (
"github.com/spf13/cast"
"strconv"
"strings"
"time"
@ -424,6 +425,8 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose
serviceConfig.ServiceType = serviceType
case LabelServiceExpose:
serviceConfig.ExposeService = strings.Trim(strings.ToLower(value), " ,")
case LabelNodePortPort:
serviceConfig.NodePortPort = cast.ToInt32(value)
case LabelServiceExposeTLSSecret:
serviceConfig.ExposeServiceTLS = value
case LabelImagePullSecret:
@ -437,6 +440,14 @@ func dockerComposeToKomposeMapping(composeObject *types.Config) (kobject.Kompose
return kobject.KomposeObject{}, errors.New("kompose.service.expose.tls-secret was specified without kompose.service.expose")
}
if serviceConfig.ServiceType != string(api.ServiceTypeNodePort) && serviceConfig.NodePortPort != 0 {
return kobject.KomposeObject{}, errors.New("kompose.service.type must be nodeport when assign node port value")
}
if len(serviceConfig.Port) > 1 && serviceConfig.NodePortPort != 0 {
return kobject.KomposeObject{}, errors.New("cannot set kompose.service.nodeport.port when service has multiple ports")
}
// Log if the name will been changed
if normalizeServiceNames(name) != name {
log.Infof("Service name in docker-compose has been changed from %q to %q", name, normalizeServiceNames(name))

View File

@ -525,6 +525,11 @@ func (k *Kubernetes) ConfigServicePorts(name string, service kobject.ServiceConf
Port: port.HostPort,
TargetPort: targetPort,
}
if service.ServiceType == string(api.ServiceTypeNodePort) && service.NodePortPort != 0 {
servicePort.NodePort = service.NodePortPort
}
// If the default is already TCP, no need to include it.
if port.Protocol != api.ProtocolTCP {
servicePort.Protocol = port.Protocol

View File

@ -488,6 +488,19 @@ convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/dockerfil
convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/label-port/docker-compose.yml convert --stdout"
####
# test node port with port set
cmd="kompose -f $KOMPOSE_ROOT/script/test/fixtures/service-label/docker-compose.yaml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/service-label/output-k8s.json > /tmp/output-k8s.json
convert::expect_success "$cmd" "/tmp/output-k8s.json"
cmd="kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/service-label/docker-compose.yaml convert --stdout -j"
sed -e "s;%VERSION%;$version;g" -e "s;%CMD%;$cmd;g" $KOMPOSE_ROOT/script/test/fixtures/service-label/output-oc.json > /tmp/output-oc.json
convert::expect_success "$cmd" "/tmp/output-oc.json"
######
# Test the output file behavior of kompose convert
# Default behavior without -o

View File

@ -0,0 +1,13 @@
version: '2'
services:
mariadb:
ports:
- '3306:3306'
labels:
kompose.service.type: nodeport
kompose.service.nodeport.port: "33111"
image: 'bitnami/mariadb:latest'
environment:
- MARIADB_USER=bn_wordpress
- MARIADB_DATABASE=bitnami_wordpress
- ALLOW_EMPTY_PASSWORD=yes

View File

@ -0,0 +1,114 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "mariadb",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.service.nodeport.port": "33111",
"kompose.service.type": "nodeport",
"kompose.version": "%VERSION%"
}
},
"spec": {
"ports": [
{
"name": "3306",
"port": 3306,
"targetPort": 3306,
"nodePort": 33111
}
],
"selector": {
"io.kompose.service": "mariadb"
},
"type": "NodePort"
},
"status": {
"loadBalancer": {}
}
},
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.service.nodeport.port": "33111",
"kompose.service.type": "nodeport",
"kompose.version": "%VERSION%"
},
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
},
"name": "mariadb"
},
"spec": {
"replicas": 1,
"selector": {
"matchLabels": {
"io.kompose.service": "mariadb"
}
},
"strategy": {},
"template": {
"metadata": {
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.service.nodeport.port": "33111",
"kompose.service.type": "nodeport",
"kompose.version": "%VERSION%"
},
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
}
},
"spec": {
"containers": [
{
"env": [
{
"name": "ALLOW_EMPTY_PASSWORD",
"value": "yes"
},
{
"name": "MARIADB_DATABASE",
"value": "bitnami_wordpress"
},
{
"name": "MARIADB_USER",
"value": "bn_wordpress"
}
],
"image": "bitnami/mariadb:latest",
"imagePullPolicy": "",
"name": "mariadb",
"ports": [
{
"containerPort": 3306
}
],
"resources": {}
}
],
"restartPolicy": "Always",
"serviceAccountName": "",
"volumes": null
}
}
},
"status": {}
}
]
}

View File

@ -0,0 +1,152 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "mariadb",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.service.nodeport.port": "33111",
"kompose.service.type": "nodeport",
"kompose.version": "%VERSION%"
}
},
"spec": {
"ports": [
{
"name": "3306",
"port": 3306,
"targetPort": 3306,
"nodePort": 33111
}
],
"selector": {
"io.kompose.service": "mariadb"
},
"type": "NodePort"
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "mariadb",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
},
"annotations": {
"kompose.cmd": "%CMD%",
"kompose.service.nodeport.port": "33111",
"kompose.service.type": "nodeport",
"kompose.version": "%VERSION%"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"mariadb"
],
"from": {
"kind": "ImageStreamTag",
"name": "mariadb:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "mariadb"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
}
},
"spec": {
"containers": [
{
"name": "mariadb",
"image": " ",
"ports": [
{
"containerPort": 3306
}
],
"env": [
{
"name": "ALLOW_EMPTY_PASSWORD",
"value": "yes"
},
{
"name": "MARIADB_DATABASE",
"value": "bitnami_wordpress"
},
{
"name": "MARIADB_USER",
"value": "bn_wordpress"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "mariadb",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "mariadb"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "bitnami/mariadb:latest"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
}
]
}