Merge pull request #681 from aledbf/add-lb-status

Update Ingress status information in nginx controller
This commit is contained in:
Prashanth B 2016-04-01 12:00:42 -07:00
commit f22e6d2690
15 changed files with 269 additions and 21 deletions

View file

@ -230,4 +230,4 @@ The previous behavior can be restored using `retry-non-idempotent=true` in the c
## Limitations
TODO
- Ingress rules for TLS require the definition of the field `host`

View file

@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/record"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/runtime"
@ -64,8 +65,14 @@ type loadBalancerController struct {
tcpConfigMap string
udpConfigMap string
recorder record.EventRecorder
syncQueue *taskQueue
// taskQueue used to update the status of the Ingress rules.
// this avoids a sync execution in the ResourceEventHandlerFuncs
ingQueue *taskQueue
// stopLock is used to enforce only a single call to Stop is active.
// Needed because we allow stopping through an http endpoint and
// allowing concurrent stoppers leads to stack traces.
@ -77,6 +84,11 @@ type loadBalancerController struct {
// newLoadBalancerController creates a controller for nginx loadbalancer
func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Duration, defaultSvc,
namespace, nxgConfigMapName, tcpConfigMapName, udpConfigMapName string, lbRuntimeInfo *lbInfo) (*loadBalancerController, error) {
eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(glog.Infof)
eventBroadcaster.StartRecordingToSink(kubeClient.Events(""))
lbc := loadBalancerController{
client: kubeClient,
stopCh: make(chan struct{}),
@ -86,9 +98,33 @@ func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
tcpConfigMap: tcpConfigMapName,
udpConfigMap: udpConfigMapName,
defaultSvc: defaultSvc,
recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "loadbalancer-controller"}),
}
lbc.syncQueue = NewTaskQueue(lbc.sync)
lbc.ingQueue = NewTaskQueue(lbc.updateIngressStatus)
ingEventHandler := framework.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
addIng := obj.(*extensions.Ingress)
lbc.recorder.Eventf(addIng, api.EventTypeNormal, "CREATE", fmt.Sprintf("%s/%s", addIng.Namespace, addIng.Name))
lbc.ingQueue.enqueue(obj)
lbc.syncQueue.enqueue(obj)
},
DeleteFunc: func(obj interface{}) {
upIng := obj.(*extensions.Ingress)
lbc.recorder.Eventf(upIng, api.EventTypeNormal, "DELETE", fmt.Sprintf("%s/%s", upIng.Namespace, upIng.Name))
lbc.syncQueue.enqueue(obj)
},
UpdateFunc: func(old, cur interface{}) {
if !reflect.DeepEqual(old, cur) {
upIng := cur.(*extensions.Ingress)
lbc.recorder.Eventf(upIng, api.EventTypeNormal, "UPDATE", fmt.Sprintf("%s/%s", upIng.Namespace, upIng.Name))
lbc.ingQueue.enqueue(cur)
lbc.syncQueue.enqueue(cur)
}
},
}
eventHandler := framework.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
@ -109,7 +145,7 @@ func newLoadBalancerController(kubeClient *client.Client, resyncPeriod time.Dura
ListFunc: ingressListFunc(lbc.client, namespace),
WatchFunc: ingressWatchFunc(lbc.client, namespace),
},
&extensions.Ingress{}, resyncPeriod, eventHandler)
&extensions.Ingress{}, resyncPeriod, ingEventHandler)
lbc.endpLister.Store, lbc.endpController = framework.NewInformer(
&cache.ListWatch{
@ -206,6 +242,57 @@ func (lbc *loadBalancerController) sync(key string) {
})
}
func (lbc *loadBalancerController) updateIngressStatus(key string) {
if !lbc.controllersInSync() {
lbc.ingQueue.requeue(key, fmt.Errorf("deferring sync till endpoints controller has synced"))
return
}
obj, ingExists, err := lbc.ingLister.Store.GetByKey(key)
if err != nil {
lbc.ingQueue.requeue(key, err)
return
}
if !ingExists {
return
}
ing := obj.(*extensions.Ingress)
ingClient := lbc.client.Extensions().Ingress(ing.Namespace)
currIng, err := ingClient.Get(ing.Name)
if err != nil {
glog.Errorf("unexpected error searching Ingress %v/%v: %v", ing.Namespace, ing.Name, err)
return
}
lbIPs := ing.Status.LoadBalancer.Ingress
if !lbc.isStatusIPDefined(lbIPs) {
glog.Infof("Updating loadbalancer %v/%v with IP %v", ing.Namespace, ing.Name, lbc.lbInfo.Address)
currIng.Status.LoadBalancer.Ingress = append(currIng.Status.LoadBalancer.Ingress, api.LoadBalancerIngress{
IP: lbc.lbInfo.Address,
})
if _, err := ingClient.UpdateStatus(currIng); err != nil {
lbc.recorder.Eventf(currIng, api.EventTypeWarning, "UPDATE", "error: %v", err)
return
}
lbc.recorder.Eventf(currIng, api.EventTypeNormal, "CREATE", "ip: %v", lbc.lbInfo.Address)
}
}
func (lbc *loadBalancerController) isStatusIPDefined(lbings []api.LoadBalancerIngress) bool {
for _, lbing := range lbings {
if lbing.IP == lbc.lbInfo.Address {
return true
}
}
return false
}
func (lbc *loadBalancerController) getTCPServices() []*nginx.Location {
if lbc.tcpConfigMap == "" {
// no configmap for TCP services
@ -505,10 +592,14 @@ func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[st
continue
}
pemFileName := lbc.nginx.AddOrUpdateCertAndKey(secretName, string(cert), string(key))
pemFileName, err := lbc.nginx.AddOrUpdateCertAndKey(fmt.Sprintf("%v-%v", ing.Namespace, secretName), string(cert), string(key))
if err != nil {
glog.Errorf("No valid SSL certificate found in secret %v: %v", secretName, err)
continue
}
cn, err := lbc.nginx.CheckSSLCertificate(pemFileName)
if err != nil {
glog.Warningf("No valid SSL certificate found in secret %v", secretName)
glog.Errorf("No valid SSL certificate found in secret %v: %v", secretName, err)
continue
}
@ -571,17 +662,59 @@ func (lbc *loadBalancerController) getEndpoints(s *api.Service, servicePort ints
}
// Stop stops the loadbalancer controller.
func (lbc *loadBalancerController) Stop() {
func (lbc *loadBalancerController) Stop() error {
// Stop is invoked from the http endpoint.
lbc.stopLock.Lock()
defer lbc.stopLock.Unlock()
// Only try draining the workqueue if we haven't already.
if !lbc.shutdown {
lbc.removeFromIngress()
close(lbc.stopCh)
glog.Infof("shutting down controller queues")
lbc.shutdown = true
lbc.syncQueue.shutdown()
return nil
}
return fmt.Errorf("shutdown already in progress")
}
func (lbc *loadBalancerController) removeFromIngress() {
ings := lbc.ingLister.Store.List()
glog.Infof("updating %v Ingress rule/s", len(ings))
for _, cur := range ings {
ing := cur.(*extensions.Ingress)
ingClient := lbc.client.Extensions().Ingress(ing.Namespace)
currIng, err := ingClient.Get(ing.Name)
if err != nil {
glog.Errorf("unexpected error searching Ingress %v/%v: %v", ing.Namespace, ing.Name, err)
continue
}
lbIPs := ing.Status.LoadBalancer.Ingress
if len(lbIPs) > 0 && lbc.isStatusIPDefined(lbIPs) {
glog.Infof("Updating loadbalancer %v/%v. Removing IP %v", ing.Namespace, ing.Name, lbc.lbInfo.Address)
for idx, lbStatus := range currIng.Status.LoadBalancer.Ingress {
if lbStatus.IP == lbc.lbInfo.Address {
currIng.Status.LoadBalancer.Ingress = append(currIng.Status.LoadBalancer.Ingress[:idx],
currIng.Status.LoadBalancer.Ingress[idx+1:]...)
break
}
}
if _, err := ingClient.UpdateStatus(currIng); err != nil {
lbc.recorder.Eventf(currIng, api.EventTypeWarning, "UPDATE", "error: %v", err)
continue
}
lbc.recorder.Eventf(currIng, api.EventTypeNormal, "DELETE", "ip: %v", lbc.lbInfo.Address)
}
}
}
@ -595,6 +728,7 @@ func (lbc *loadBalancerController) Run() {
go lbc.svcController.Run(lbc.stopCh)
go lbc.syncQueue.run(time.Second, lbc.stopCh)
go lbc.ingQueue.run(time.Second, lbc.stopCh)
<-lbc.stopCh
glog.Infof("shutting down NGINX loadbalancer controller")

View file

@ -14,8 +14,9 @@ spec:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.4
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -8,8 +8,9 @@ spec:
labels:
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.4
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -11,7 +11,7 @@ spec:
labels:
app: default-http-backend
spec:
terminationGracePeriodSeconds: 600
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
# Any image is permissable as long as:

View file

@ -14,8 +14,9 @@ spec:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.4
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -15,12 +15,13 @@ spec:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
volumes:
- name: dhparam-example
secret:
secretName: dhparam-example
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.4
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -14,8 +14,9 @@ spec:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.4
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -14,8 +14,9 @@ spec:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: gcr.io/google_containers/nginx-ingress-controller:0.4
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -14,8 +14,9 @@ spec:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: aledbf/nginx-third-party:0.9
- image: gcr.io/google_containers/nginx-ingress-controller:0.5
name: nginx-ingress-lb
imagePullPolicy: Always
livenessProbe:

View file

@ -22,6 +22,8 @@ import (
"net/http"
"net/http/pprof"
"os"
"os/signal"
"syscall"
"time"
"github.com/golang/glog"
@ -32,7 +34,6 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/healthz"
"k8s.io/kubernetes/pkg/runtime"
)
const (
@ -111,6 +112,7 @@ func main() {
}
go registerHandlers(lbc)
go handleSigterm(lbc)
lbc.Run()
@ -122,11 +124,10 @@ func main() {
// lbInfo contains runtime information about the pod
type lbInfo struct {
ObjectName string
DeployType runtime.Object
Podname string
PodIP string
PodNamespace string
Address string
}
func registerHandlers(lbc *loadBalancerController) {
@ -149,3 +150,18 @@ func registerHandlers(lbc *loadBalancerController) {
}
glog.Fatal(server.ListenAndServe())
}
func handleSigterm(lbc *loadBalancerController) {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGTERM)
<-signalChan
glog.Infof("Received SIGTERM, shutting down")
exitCode := 0
if err := lbc.Stop(); err != nil {
glog.Infof("Error during shutdown %v", err)
exitCode = 1
}
glog.Infof("Exiting with %v", exitCode)
os.Exit(exitCode)
}

View file

@ -77,7 +77,9 @@ const (
// Size of the SSL shared cache between all worker processes.
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache
sslSessionCacheSize = "10m"
)
var (
// Base directory that contains the mounted secrets with SSL certificates, keys and
sslDirectory = "/etc/nginx-ssl"
)

View file

@ -27,21 +27,21 @@ import (
)
// AddOrUpdateCertAndKey creates a .pem file wth the cert and the key with the specified name
func (nginx *Manager) AddOrUpdateCertAndKey(name string, cert string, key string) string {
func (nginx *Manager) AddOrUpdateCertAndKey(name string, cert string, key string) (string, error) {
pemFileName := sslDirectory + "/" + name + ".pem"
pem, err := os.Create(pemFileName)
if err != nil {
glog.Fatalf("Couldn't create pem file %v: %v", pemFileName, err)
return "", fmt.Errorf("Couldn't create pem file %v: %v", pemFileName, err)
}
defer pem.Close()
_, err = pem.WriteString(fmt.Sprintf("%v\n%v", key, cert))
_, err = pem.WriteString(fmt.Sprintf("%v\n%v", cert, key))
if err != nil {
glog.Fatalf("Couldn't write to pem file %v: %v", pemFileName, err)
return "", fmt.Errorf("Couldn't write to pem file %v: %v", pemFileName, err)
}
return pemFileName
return pemFileName, nil
}
// CheckSSLCertificate checks if the certificate and key file are valid

View file

@ -0,0 +1,68 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package nginx
import (
"encoding/base64"
"fmt"
"os"
"testing"
"time"
)
func TestAddOrUpdateCertAndKey(t *testing.T) {
sslDirectory = os.TempDir()
// openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls.key -out /tmp/tls.crt -subj "/CN=echoheaders/O=echoheaders"
tlsCrt := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURhakNDQWxLZ0F3SUJBZ0lKQUxHUXR5VVBKTFhYTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ3d4RkRBU0JnTlYKQkFNVEMyVmphRzlvWldGa1pYSnpNUlF3RWdZRFZRUUtFd3RsWTJodmFHVmhaR1Z5Y3pBZUZ3MHhOakF6TXpFeQpNekU1TkRoYUZ3MHhOekF6TXpFeU16RTVORGhhTUN3eEZEQVNCZ05WQkFNVEMyVmphRzlvWldGa1pYSnpNUlF3CkVnWURWUVFLRXd0bFkyaHZhR1ZoWkdWeWN6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0MKZ2dFQkFONzVmS0N5RWwxanFpMjUxTlNabDYzeGQweG5HMHZTVjdYL0xxTHJveVNraW5nbnI0NDZZWlE4UEJWOAo5TUZzdW5RRGt1QVoyZzA3NHM1YWhLSm9BRGJOMzhld053RXNsVDJkRzhRTUw0TktrTUNxL1hWbzRQMDFlWG1PCmkxR2txZFA1ZUExUHlPZCtHM3gzZmxPN2xOdmtJdHVHYXFyc0tvMEhtMHhqTDVtRUpwWUlOa0tGSVhsWWVLZS8KeHRDR25CU2tLVHFMTG0yeExKSGFFcnJpaDZRdkx4NXF5U2gzZTU2QVpEcTlkTERvcWdmVHV3Z2IzekhQekc2NwppZ0E0dkYrc2FRNHpZUE1NMHQyU1NiVkx1M2pScWNvL3lxZysrOVJBTTV4bjRubnorL0hUWFhHKzZ0RDBaeGI1CmVVRDNQakVhTnlXaUV2dTN6UFJmdysyNURMY0NBd0VBQWFPQmpqQ0JpekFkQmdOVkhRNEVGZ1FVcktMZFhHeUUKNUlEOGRvd2lZNkdzK3dNMHFKc3dYQVlEVlIwakJGVXdVNEFVcktMZFhHeUU1SUQ4ZG93aVk2R3Mrd00wcUp1aApNS1F1TUN3eEZEQVNCZ05WQkFNVEMyVmphRzlvWldGa1pYSnpNUlF3RWdZRFZRUUtFd3RsWTJodmFHVmhaR1Z5CmM0SUpBTEdRdHlVUEpMWFhNQXdHQTFVZEV3UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUZCUUFEZ2dFQkFNZVMKMHFia3VZa3Z1enlSWmtBeE1PdUFaSDJCK0Evb3N4ODhFRHB1ckV0ZWN5RXVxdnRvMmpCSVdCZ2RkR3VBYU5jVQorUUZDRm9NakJOUDVWVUxIWVhTQ3VaczN2Y25WRDU4N3NHNlBaLzhzbXJuYUhTUjg1ZVpZVS80bmFyNUErdWErClIvMHJrSkZnOTlQSmNJd3JmcWlYOHdRcWdJVVlLNE9nWEJZcUJRL0VZS2YvdXl6UFN3UVZYRnVJTTZTeDBXcTYKTUNML3d2RlhLS0FaWDBqb3J4cHRjcldkUXNCcmYzWVRnYmx4TE1sN20zL2VuR1drcEhDUHdYeVRCOC9rRkw3SApLL2ZHTU1NWGswUkVSbGFPM1hTSUhrZUQ2SXJiRnRNV3R1RlJwZms2ZFA2TXlMOHRmTmZ6a3VvUHVEWUFaWllWCnR1NnZ0c0FRS0xWb0pGaGV0b1k9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
tlsKey := "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBM3ZsOG9MSVNYV09xTGJuVTFKbVhyZkYzVEdjYlM5Slh0Zjh1b3V1akpLU0tlQ2V2CmpqcGhsRHc4Rlh6MHdXeTZkQU9TNEJuYURUdml6bHFFb21nQU5zM2Z4N0EzQVN5VlBaMGJ4QXd2ZzBxUXdLcjkKZFdqZy9UVjVlWTZMVWFTcDAvbDREVS9JNTM0YmZIZCtVN3VVMitRaTI0WnFxdXdxalFlYlRHTXZtWVFtbGdnMgpRb1VoZVZoNHA3L0cwSWFjRktRcE9vc3ViYkVza2RvU3V1S0hwQzh2SG1ySktIZDdub0JrT3IxMHNPaXFCOU83CkNCdmZNYy9NYnJ1S0FEaThYNnhwRGpOZzh3elMzWkpKdFV1N2VOR3B5ai9LcUQ3NzFFQXpuR2ZpZWZQNzhkTmQKY2I3cTBQUm5Gdmw1UVBjK01SbzNKYUlTKzdmTTlGL0Q3YmtNdHdJREFRQUJBb0lCQUViNmFEL0hMNjFtMG45bgp6bVkyMWwvYW83MUFmU0h2dlZnRCtWYUhhQkY4QjFBa1lmQUdpWlZrYjBQdjJRSFJtTERoaWxtb0lROWhadHVGCldQOVIxKythTFlnbGdmenZzanBBenR2amZTUndFaEFpM2pnSHdNY1p4S2Q3UnNJZ2hxY2huS093S0NYNHNNczQKUnBCbEFBZlhZWGs4R3F4NkxUbGptSDRDZk42QzZHM1EwTTlLMUxBN2lsck1Na3hwcngxMnBlVTNkczZMVmNpOQptOFdBL21YZ2I0c3pEbVNaWVpYRmNZMEhYNTgyS3JKRHpQWEVJdGQwZk5wd3I0eFIybzdzMEwvK2RnZCtqWERjCkh2SDBKZ3NqODJJaTIxWGZGM2tST3FxR3BKNmhVcncxTUZzVWRyZ29GL3pFck0vNWZKMDdVNEhodGFlalVzWTIKMFJuNXdpRUNnWUVBKzVUTVRiV084Wkg5K2pIdVQwc0NhZFBYcW50WTZYdTZmYU04Tm5CZWNoeTFoWGdlQVN5agpSWERlZGFWM1c0SjU5eWxIQ3FoOVdseVh4cDVTWWtyQU41RnQ3elFGYi91YmorUFIyWWhMTWZpYlBSYlYvZW1MCm5YaGF6MmtlNUUxT1JLY0x6QUVwSmpuZGQwZlZMZjdmQzFHeStnS2YyK3hTY1hjMHJqRE5iNGtDZ1lFQTR1UVEKQk91TlJQS3FKcDZUZS9zUzZrZitHbEpjQSs3RmVOMVlxM0E2WEVZVm9ydXhnZXQ4a2E2ZEo1QjZDOWtITGtNcQpwdnFwMzkxeTN3YW5uWC9ONC9KQlU2M2RxZEcyd1BWRUQ0REduaE54Qm1oaWZpQ1I0R0c2ZnE4MUV6ZE1vcTZ4CklTNHA2RVJaQnZkb1RqNk9pTHl6aUJMckpxeUhIMWR6c0hGRlNqOENnWUVBOWlSSEgyQ2JVazU4SnVYak8wRXcKUTBvNG4xdS9TZkQ4TFNBZ01VTVBwS1hpRTR2S0Qyd1U4a1BUNDFiWXlIZUh6UUpkdDFmU0RTNjZjR0ZHU1ZUSgphNVNsOG5yN051ejg3bkwvUmMzTGhFQ3Y0YjBOOFRjbW1oSy9CbDdiRXBOd0dFczNoNGs3TVdNOEF4QU15c3VxCmZmQ1pJM0tkNVJYNk0zbGwyV2QyRjhFQ2dZQlQ5RU9oTG0vVmhWMUVjUVR0cVZlMGJQTXZWaTVLSGozZm5UZkUKS0FEUVIvYVZncElLR3RLN0xUdGxlbVpPbi8yeU5wUS91UnpHZ3pDUUtldzNzU1RFSmMzYVlzbFVudzdhazJhZAp2ZTdBYXowMU84YkdHTk1oamNmdVBIS05LN2Nsc3pKRHJzcys4SnRvb245c0JHWEZYdDJuaWlpTTVPWVN5TTg4CkNJMjFEUUtCZ0hEQVRZbE84UWlDVWFBQlVqOFBsb1BtMDhwa3cyc1VmQW0xMzJCY00wQk9BN1hqYjhtNm1ManQKOUlteU5kZ2ZiM080UjlKVUxTb1pZSTc1dUxIL3k2SDhQOVlpWHZOdzMrTXl6VFU2b2d1YU8xSTNya2pna29NeAo5cU5pYlJFeGswS1A5MVZkckVLSEdHZEFwT05ES1N4VzF3ektvbUxHdmtYSTVKV05KRXFkCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg=="
dCrt, err := base64.StdEncoding.DecodeString(tlsCrt)
if err != nil {
t.Fatalf("Unexpected error: %+v", err)
return
}
dKey, err := base64.StdEncoding.DecodeString(tlsKey)
if err != nil {
t.Fatalf("Unexpected error: %+v", err)
}
ngx := &Manager{}
name := fmt.Sprintf("test-%v", time.Now().UnixNano())
pemPath, err := ngx.AddOrUpdateCertAndKey(name, string(dCrt), string(dKey))
if err != nil {
t.Fatalf("unexpected error checking SSL certificate: %v", err)
}
if pemPath == "" {
t.Fatalf("expected path to pem file but returned empty")
}
cnames, err := ngx.CheckSSLCertificate(pemPath)
if err != nil {
t.Fatalf("unexpected error checking SSL certificate: %v", err)
}
if len(cnames) == 0 {
t.Fatalf("expected at least one cname but none returned")
}
if cnames[0] != "echoheaders" {
t.Fatalf("expected cname echoheaders but %v returned", cnames[0])
}
}

View file

@ -24,6 +24,7 @@ import (
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/util/wait"
@ -108,10 +109,30 @@ func getLBDetails(kubeClient *unversioned.Client) (*lbInfo, error) {
return nil, fmt.Errorf("Unable to get POD information")
}
node, err := kubeClient.Nodes().Get(pod.Spec.NodeName)
if err != nil {
return nil, err
}
var externalIP string
for _, address := range node.Status.Addresses {
if address.Type == api.NodeExternalIP {
if address.Address != "" {
externalIP = address.Address
break
}
}
if externalIP == "" && address.Type == api.NodeLegacyHostIP {
externalIP = address.Address
}
}
return &lbInfo{
PodIP: podIP,
Podname: podName,
PodNamespace: podNs,
Address: externalIP,
}, nil
}