func serviceName(lb loadbalancers.LoadBalancer) string {
	return strings.ToLower(lb.ID)
}
use the load balancer ID as the service name
context: heptio/gimbal #216
package openstack
import (
	"regexp"
	"strconv"
	"strings"
	"github.com/projectcontour/gimbal/pkg/translator"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers"
	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
)
func kubeServices(backendName, tenantName string, lbs []loadbalancers.LoadBalancer) []v1.Service {
	var svcs []v1.Service
	for _, lb := range lbs {
		svc := v1.Service{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: tenantName,
				Name:      translator.BuildDiscoveredName(backendName, serviceName(lb)),
				Labels:    translator.AddGimbalLabels(backendName, serviceName(lb), loadbalancerLabels(lb)),
			},
			Spec: v1.ServiceSpec{
				Type:      v1.ServiceTypeClusterIP,
				ClusterIP: "None",
			},
		}
		for _, l := range lb.Listeners {
			svc.Spec.Ports = append(svc.Spec.Ports, servicePort(&l))
		}
		svcs = append(svcs, svc)
	}
	return svcs
}
func kubeEndpoints(backendName, tenantName string, lbs []loadbalancers.LoadBalancer, ps []pools.Pool) []Endpoints {
	endpoints := []Endpoints{}
	for _, lb := range lbs {
		ep := v1.Endpoints{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: tenantName,
				Name:      translator.BuildDiscoveredName(backendName, serviceName(lb)),
				Labels:    translator.AddGimbalLabels(backendName, serviceName(lb), loadbalancerLabels(lb)),
			},
		}
		for _, l := range lb.Listeners {
			subsets := map[int]v1.EndpointSubset{}
			var pool pools.Pool
			for _, p := range ps {
				if l.DefaultPoolID == p.ID {
					pool = p
					break
				}
			}
			for _, member := range pool.Members {
				s := subsets[member.ProtocolPort]
				if len(s.Ports) == 0 {
					s.Ports = append(s.Ports, v1.EndpointPort{Name: portName(&l), Port: int32(member.ProtocolPort), Protocol: v1.ProtocolTCP})
				}
				s.Addresses = append(s.Addresses, v1.EndpointAddress{IP: member.Address})  
				subsets[member.ProtocolPort] = s
			}
			for _, s := range subsets {
				ep.Subsets = append(ep.Subsets, s)
			}
		}
		endpoints = append(endpoints, Endpoints{endpoints: ep, upstreamName: serviceNameOriginal(lb)})
	}
	return endpoints
}
func loadbalancerLabels(lb loadbalancers.LoadBalancer) map[string]string {
	name := lb.Name
	if name != "" {
		reg := regexp.MustCompile(`[^a-zA-Z0-9\-._]`)
		name = reg.ReplaceAllString(lb.Name, "-")
		if !isalphanum(name[0]) {
			name = "lb" + name
		}
		if !isalphanum(name[len(name)-1]) {
			name = name + "lb"
		}
		name = translator.ShortenKubernetesLabelValue(name)
	}
	return map[string]string{
		"gimbal.projectcontour.io/load-balancer-id":   lb.ID,
		"gimbal.projectcontour.io/load-balancer-name": name,
	}
}
func isalphanum(c byte) bool {
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
}