Initial support for Kubernetes ExternalName service type

This commit is contained in:
Regner Blok-Andersen 2017-02-09 17:25:38 -08:00
parent 01e3d7952a
commit 0947aa901e
2 changed files with 80 additions and 19 deletions

View file

@ -193,28 +193,38 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur
if port.Port == 443 { if port.Port == 443 {
protocol = "https" protocol = "https"
} }
endpoints, exists, err := k8sClient.GetEndpoints(service.ObjectMeta.Namespace, service.ObjectMeta.Name) if service.Spec.Type == "ExternalName" {
if err != nil || !exists { url := protocol + "://" + service.Spec.ExternalName
log.Errorf("Error retrieving endpoints %s/%s: %v", service.ObjectMeta.Namespace, service.ObjectMeta.Name, err) name := url
continue
} templateObjects.Backends[r.Host+pa.Path].Servers[name] = types.Server{
if len(endpoints.Subsets) == 0 { URL: url,
log.Warnf("Endpoints not found for %s/%s, falling back to Service ClusterIP", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{
URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(int(port.Port)),
Weight: 1, Weight: 1,
} }
} else { } else {
for _, subset := range endpoints.Subsets { endpoints, exists, err := k8sClient.GetEndpoints(service.ObjectMeta.Namespace, service.ObjectMeta.Name)
for _, address := range subset.Addresses { if err != nil || !exists {
url := protocol + "://" + address.IP + ":" + strconv.Itoa(endpointPortNumber(port, subset.Ports)) log.Errorf("Error retrieving endpoints %s/%s: %v", service.ObjectMeta.Namespace, service.ObjectMeta.Name, err)
name := url continue
if address.TargetRef != nil && address.TargetRef.Name != "" { }
name = address.TargetRef.Name if len(endpoints.Subsets) == 0 {
} log.Warnf("Endpoints not found for %s/%s, falling back to Service ClusterIP", service.ObjectMeta.Namespace, service.ObjectMeta.Name)
templateObjects.Backends[r.Host+pa.Path].Servers[name] = types.Server{ templateObjects.Backends[r.Host+pa.Path].Servers[string(service.UID)] = types.Server{
URL: url, URL: protocol + "://" + service.Spec.ClusterIP + ":" + strconv.Itoa(int(port.Port)),
Weight: 1, Weight: 1,
}
} else {
for _, subset := range endpoints.Subsets {
for _, address := range subset.Addresses {
url := protocol + "://" + address.IP + ":" + strconv.Itoa(endpointPortNumber(port, subset.Ports))
name := url
if address.TargetRef != nil && address.TargetRef.Name != "" {
name = address.TargetRef.Name
}
templateObjects.Backends[r.Host+pa.Path].Servers[name] = types.Server{
URL: url,
Weight: 1,
}
} }
} }
} }

View file

@ -31,6 +31,13 @@ func TestLoadIngresses(t *testing.T) {
ServicePort: intstr.FromInt(80), ServicePort: intstr.FromInt(80),
}, },
}, },
{
Path: "/namedthing",
Backend: v1beta1.IngressBackend{
ServiceName: "service4",
ServicePort: intstr.FromString("https"),
},
},
}, },
}, },
}, },
@ -110,6 +117,24 @@ func TestLoadIngresses(t *testing.T) {
}, },
}, },
}, },
{
ObjectMeta: v1.ObjectMeta{
Name: "service4",
UID: "4",
Namespace: "testing",
},
Spec: v1.ServiceSpec{
ClusterIP: "10.0.0.4",
Type: "ExternalName",
ExternalName: "example.com",
Ports: []v1.ServicePort{
{
Name: "https",
Port: 443,
},
},
},
},
} }
endpoints := []*v1.Endpoints{ endpoints := []*v1.Endpoints{
{ {
@ -221,6 +246,19 @@ func TestLoadIngresses(t *testing.T) {
Method: "wrr", Method: "wrr",
}, },
}, },
"foo/namedthing": {
Servers: map[string]types.Server{
"https://example.com": {
URL: "https://example.com",
Weight: 1,
},
},
CircuitBreaker: nil,
LoadBalancer: &types.LoadBalancer{
Sticky: false,
Method: "wrr",
},
},
"bar": { "bar": {
Servers: map[string]types.Server{ Servers: map[string]types.Server{
"2": { "2": {
@ -257,6 +295,19 @@ func TestLoadIngresses(t *testing.T) {
}, },
}, },
}, },
"foo/namedthing": {
Backend: "foo/namedthing",
PassHostHeader: true,
Priority: len("/namedthing"),
Routes: map[string]types.Route{
"/namedthing": {
Rule: "PathPrefix:/namedthing",
},
"foo": {
Rule: "Host:foo",
},
},
},
"bar": { "bar": {
Backend: "bar", Backend: "bar",
PassHostHeader: true, PassHostHeader: true,