mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Simplify proxy config for Endpoints by removing Mux.
This commit is contained in:
		@@ -308,14 +308,14 @@ func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, err
 | 
				
			|||||||
	serviceConfig := proxyconfig.NewServiceConfig()
 | 
						serviceConfig := proxyconfig.NewServiceConfig()
 | 
				
			||||||
	serviceConfig.RegisterHandler(proxier)
 | 
						serviceConfig.RegisterHandler(proxier)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	endpointsConfig := proxyconfig.NewEndpointsConfig()
 | 
						endpointsConfig := proxyconfig.NewEndpointsConfig(client.Core().RESTClient(), config.ConfigSyncPeriod)
 | 
				
			||||||
	endpointsConfig.RegisterHandler(endpointsHandler)
 | 
						endpointsConfig.RegisterHandler(endpointsHandler)
 | 
				
			||||||
 | 
						go endpointsConfig.Run(wait.NeverStop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proxyconfig.NewSourceAPI(
 | 
						proxyconfig.NewSourceAPI(
 | 
				
			||||||
		client.Core().RESTClient(),
 | 
							client.Core().RESTClient(),
 | 
				
			||||||
		config.ConfigSyncPeriod,
 | 
							config.ConfigSyncPeriod,
 | 
				
			||||||
		serviceConfig.Channel("api"),
 | 
							serviceConfig.Channel("api"),
 | 
				
			||||||
		endpointsConfig.Channel("api"),
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config.NodeRef = &clientv1.ObjectReference{
 | 
						config.NodeRef = &clientv1.ObjectReference{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/util/flag"
 | 
						"k8s.io/apiserver/pkg/util/flag"
 | 
				
			||||||
@@ -138,7 +139,7 @@ func main() {
 | 
				
			|||||||
		serviceConfig := proxyconfig.NewServiceConfig()
 | 
							serviceConfig := proxyconfig.NewServiceConfig()
 | 
				
			||||||
		serviceConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
 | 
							serviceConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		endpointsConfig := proxyconfig.NewEndpointsConfig()
 | 
							endpointsConfig := proxyconfig.NewEndpointsConfig(internalClientset.Core().RESTClient(), 15*time.Minute)
 | 
				
			||||||
		endpointsConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
 | 
							endpointsConfig.RegisterHandler(&kubemark.FakeProxyHandler{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		eventClient, err := clientgoclientset.NewForConfig(clientConfig)
 | 
							eventClient, err := clientgoclientset.NewForConfig(clientConfig)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,7 @@ go_library(
 | 
				
			|||||||
        "//vendor:github.com/golang/glog",
 | 
					        "//vendor:github.com/golang/glog",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/types",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/types",
 | 
				
			||||||
 | 
					        "//vendor:k8s.io/apimachinery/pkg/util/wait",
 | 
				
			||||||
        "//vendor:k8s.io/client-go/kubernetes/typed/core/v1",
 | 
					        "//vendor:k8s.io/client-go/kubernetes/typed/core/v1",
 | 
				
			||||||
        "//vendor:k8s.io/client-go/pkg/api/v1",
 | 
					        "//vendor:k8s.io/client-go/pkg/api/v1",
 | 
				
			||||||
        "//vendor:k8s.io/client-go/tools/record",
 | 
					        "//vendor:k8s.io/client-go/tools/record",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	v1core "k8s.io/client-go/kubernetes/typed/core/v1"
 | 
						v1core "k8s.io/client-go/kubernetes/typed/core/v1"
 | 
				
			||||||
	clientv1 "k8s.io/client-go/pkg/api/v1"
 | 
						clientv1 "k8s.io/client-go/pkg/api/v1"
 | 
				
			||||||
	"k8s.io/client-go/tools/record"
 | 
						"k8s.io/client-go/tools/record"
 | 
				
			||||||
@@ -71,11 +72,12 @@ func NewHollowProxyOrDie(
 | 
				
			|||||||
		UID:       types.UID(nodeName),
 | 
							UID:       types.UID(nodeName),
 | 
				
			||||||
		Namespace: "",
 | 
							Namespace: "",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go endpointsConfig.Run(wait.NeverStop)
 | 
				
			||||||
	proxyconfig.NewSourceAPI(
 | 
						proxyconfig.NewSourceAPI(
 | 
				
			||||||
		client.Core().RESTClient(),
 | 
							client.Core().RESTClient(),
 | 
				
			||||||
		15*time.Minute,
 | 
							15*time.Minute,
 | 
				
			||||||
		serviceConfig.Channel("api"),
 | 
							serviceConfig.Channel("api"),
 | 
				
			||||||
		endpointsConfig.Channel("api"),
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hollowProxy, err := proxyapp.NewProxyServer(client, eventClient, config, iptInterface, &FakeProxier{}, broadcaster, recorder, nil, "fake")
 | 
						hollowProxy, err := proxyapp.NewProxyServer(client, eventClient, config, iptInterface, &FakeProxier{}, broadcaster, recorder, nil, "fake")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,11 +18,13 @@ go_library(
 | 
				
			|||||||
    tags = ["automanaged"],
 | 
					    tags = ["automanaged"],
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
        "//pkg/api:go_default_library",
 | 
					        "//pkg/api:go_default_library",
 | 
				
			||||||
 | 
					        "//pkg/client/listers/core/internalversion:go_default_library",
 | 
				
			||||||
        "//pkg/util/config:go_default_library",
 | 
					        "//pkg/util/config:go_default_library",
 | 
				
			||||||
        "//vendor:github.com/davecgh/go-spew/spew",
 | 
					        "//vendor:github.com/davecgh/go-spew/spew",
 | 
				
			||||||
        "//vendor:github.com/golang/glog",
 | 
					        "//vendor:github.com/golang/glog",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/fields",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/fields",
 | 
				
			||||||
 | 
					        "//vendor:k8s.io/apimachinery/pkg/labels",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/types",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/types",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/util/runtime",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/util/runtime",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/util/wait",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/util/wait",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,31 +29,24 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewSourceAPI creates config source that watches for changes to the services and endpoints.
 | 
					// NewSourceAPI creates config source that watches for changes to the services and endpoints.
 | 
				
			||||||
func NewSourceAPI(c cache.Getter, period time.Duration, servicesChan chan<- ServiceUpdate, endpointsChan chan<- EndpointsUpdate) {
 | 
					func NewSourceAPI(c cache.Getter, period time.Duration, servicesChan chan<- ServiceUpdate) {
 | 
				
			||||||
	servicesLW := cache.NewListWatchFromClient(c, "services", metav1.NamespaceAll, fields.Everything())
 | 
						servicesLW := cache.NewListWatchFromClient(c, "services", metav1.NamespaceAll, fields.Everything())
 | 
				
			||||||
	endpointsLW := cache.NewListWatchFromClient(c, "endpoints", metav1.NamespaceAll, fields.Everything())
 | 
						newSourceAPI(servicesLW, period, servicesChan, wait.NeverStop)
 | 
				
			||||||
	newSourceAPI(servicesLW, endpointsLW, period, servicesChan, endpointsChan, wait.NeverStop)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newSourceAPI(
 | 
					func newSourceAPI(
 | 
				
			||||||
	servicesLW cache.ListerWatcher,
 | 
						servicesLW cache.ListerWatcher,
 | 
				
			||||||
	endpointsLW cache.ListerWatcher,
 | 
					 | 
				
			||||||
	period time.Duration,
 | 
						period time.Duration,
 | 
				
			||||||
	servicesChan chan<- ServiceUpdate,
 | 
						servicesChan chan<- ServiceUpdate,
 | 
				
			||||||
	endpointsChan chan<- EndpointsUpdate,
 | 
					 | 
				
			||||||
	stopCh <-chan struct{}) {
 | 
						stopCh <-chan struct{}) {
 | 
				
			||||||
	serviceController := NewServiceController(servicesLW, period, servicesChan)
 | 
						serviceController := NewServiceController(servicesLW, period, servicesChan)
 | 
				
			||||||
	go serviceController.Run(stopCh)
 | 
						go serviceController.Run(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	endpointsController := NewEndpointsController(endpointsLW, period, endpointsChan)
 | 
						if !cache.WaitForCacheSync(stopCh, serviceController.HasSynced) {
 | 
				
			||||||
	go endpointsController.Run(stopCh)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !cache.WaitForCacheSync(stopCh, serviceController.HasSynced, endpointsController.HasSynced) {
 | 
					 | 
				
			||||||
		utilruntime.HandleError(fmt.Errorf("source controllers not synced"))
 | 
							utilruntime.HandleError(fmt.Errorf("source controllers not synced"))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	servicesChan <- ServiceUpdate{Op: SYNCED}
 | 
						servicesChan <- ServiceUpdate{Op: SYNCED}
 | 
				
			||||||
	endpointsChan <- EndpointsUpdate{Op: SYNCED}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func sendAddService(servicesChan chan<- ServiceUpdate) func(obj interface{}) {
 | 
					func sendAddService(servicesChan chan<- ServiceUpdate) func(obj interface{}) {
 | 
				
			||||||
@@ -99,49 +92,6 @@ func sendDeleteService(servicesChan chan<- ServiceUpdate) func(obj interface{})
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func sendAddEndpoints(endpointsChan chan<- EndpointsUpdate) func(obj interface{}) {
 | 
					 | 
				
			||||||
	return func(obj interface{}) {
 | 
					 | 
				
			||||||
		endpoints, ok := obj.(*api.Endpoints)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			utilruntime.HandleError(fmt.Errorf("cannot convert to *api.Endpoints: %v", obj))
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		endpointsChan <- EndpointsUpdate{Op: ADD, Endpoints: endpoints}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sendUpdateEndpoints(endpointsChan chan<- EndpointsUpdate) func(oldObj, newObj interface{}) {
 | 
					 | 
				
			||||||
	return func(_, newObj interface{}) {
 | 
					 | 
				
			||||||
		endpoints, ok := newObj.(*api.Endpoints)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			utilruntime.HandleError(fmt.Errorf("cannot convert to *api.Endpoints: %v", newObj))
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		endpointsChan <- EndpointsUpdate{Op: UPDATE, Endpoints: endpoints}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sendDeleteEndpoints(endpointsChan chan<- EndpointsUpdate) func(obj interface{}) {
 | 
					 | 
				
			||||||
	return func(obj interface{}) {
 | 
					 | 
				
			||||||
		var endpoints *api.Endpoints
 | 
					 | 
				
			||||||
		switch t := obj.(type) {
 | 
					 | 
				
			||||||
		case *api.Endpoints:
 | 
					 | 
				
			||||||
			endpoints = t
 | 
					 | 
				
			||||||
		case cache.DeletedFinalStateUnknown:
 | 
					 | 
				
			||||||
			var ok bool
 | 
					 | 
				
			||||||
			endpoints, ok = t.Obj.(*api.Endpoints)
 | 
					 | 
				
			||||||
			if !ok {
 | 
					 | 
				
			||||||
				utilruntime.HandleError(fmt.Errorf("cannot convert to *api.Endpoints: %v", t.Obj))
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			utilruntime.HandleError(fmt.Errorf("cannot convert to *api.Endpoints: %v", obj))
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		endpointsChan <- EndpointsUpdate{Op: REMOVE, Endpoints: endpoints}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewServiceController creates a controller that is watching services and sending
 | 
					// NewServiceController creates a controller that is watching services and sending
 | 
				
			||||||
// updates into ServiceUpdate channel.
 | 
					// updates into ServiceUpdate channel.
 | 
				
			||||||
func NewServiceController(lw cache.ListerWatcher, period time.Duration, ch chan<- ServiceUpdate) cache.Controller {
 | 
					func NewServiceController(lw cache.ListerWatcher, period time.Duration, ch chan<- ServiceUpdate) cache.Controller {
 | 
				
			||||||
@@ -157,19 +107,3 @@ func NewServiceController(lw cache.ListerWatcher, period time.Duration, ch chan<
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	return serviceController
 | 
						return serviceController
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewEndpointsController creates a controller that is watching endpoints and sending
 | 
					 | 
				
			||||||
// updates into EndpointsUpdate channel.
 | 
					 | 
				
			||||||
func NewEndpointsController(lw cache.ListerWatcher, period time.Duration, ch chan<- EndpointsUpdate) cache.Controller {
 | 
					 | 
				
			||||||
	_, endpointsController := cache.NewInformer(
 | 
					 | 
				
			||||||
		lw,
 | 
					 | 
				
			||||||
		&api.Endpoints{},
 | 
					 | 
				
			||||||
		period,
 | 
					 | 
				
			||||||
		cache.ResourceEventHandlerFuncs{
 | 
					 | 
				
			||||||
			AddFunc:    sendAddEndpoints(ch),
 | 
					 | 
				
			||||||
			UpdateFunc: sendUpdateEndpoints(ch),
 | 
					 | 
				
			||||||
			DeleteFunc: sendDeleteEndpoints(ch),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	return endpointsController
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,68 +166,40 @@ func TestNewEndpointsSourceApi_UpdatesAndMultipleEndpoints(t *testing.T) {
 | 
				
			|||||||
		watchResp: fakeWatch,
 | 
							watchResp: fakeWatch,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ch := make(chan EndpointsUpdate)
 | 
						stopCh := make(chan struct{})
 | 
				
			||||||
 | 
						defer close(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	endpointsController := NewEndpointsController(lw, 30*time.Second, ch)
 | 
						ch := make(chan struct{})
 | 
				
			||||||
	go endpointsController.Run(wait.NeverStop)
 | 
						handler := newEpsHandler(t, nil, func() { ch <- struct{}{} })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endpointsConfig := newEndpointsConfig(lw, time.Minute)
 | 
				
			||||||
 | 
						endpointsConfig.RegisterHandler(handler)
 | 
				
			||||||
 | 
						go endpointsConfig.Run(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add the first endpoints
 | 
						// Add the first endpoints
 | 
				
			||||||
 | 
						handler.expected = []*api.Endpoints{endpoints1v1}
 | 
				
			||||||
	fakeWatch.Add(endpoints1v1)
 | 
						fakeWatch.Add(endpoints1v1)
 | 
				
			||||||
	got, ok := <-ch
 | 
						<-ch
 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		t.Errorf("Unable to read from channel when expected")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	expected := EndpointsUpdate{Op: ADD, Endpoints: endpoints1v1}
 | 
					 | 
				
			||||||
	if !apiequality.Semantic.DeepEqual(expected, got) {
 | 
					 | 
				
			||||||
		t.Errorf("Expected %#v; Got %#v", expected, got)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add another endpoints
 | 
						// Add another endpoints
 | 
				
			||||||
 | 
						handler.expected = []*api.Endpoints{endpoints1v1, endpoints2}
 | 
				
			||||||
	fakeWatch.Add(endpoints2)
 | 
						fakeWatch.Add(endpoints2)
 | 
				
			||||||
	got, ok = <-ch
 | 
						<-ch
 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		t.Errorf("Unable to read from channel when expected")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Could be sorted either of these two ways:
 | 
					 | 
				
			||||||
	expected = EndpointsUpdate{Op: ADD, Endpoints: endpoints2}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !apiequality.Semantic.DeepEqual(expected, got) {
 | 
					 | 
				
			||||||
		t.Errorf("Expected %#v, Got %#v", expected, got)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Modify endpoints1
 | 
						// Modify endpoints1
 | 
				
			||||||
 | 
						handler.expected = []*api.Endpoints{endpoints1v2, endpoints2}
 | 
				
			||||||
	fakeWatch.Modify(endpoints1v2)
 | 
						fakeWatch.Modify(endpoints1v2)
 | 
				
			||||||
	got, ok = <-ch
 | 
						<-ch
 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		t.Errorf("Unable to read from channel when expected")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	expected = EndpointsUpdate{Op: UPDATE, Endpoints: endpoints1v2}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !apiequality.Semantic.DeepEqual(expected, got) {
 | 
					 | 
				
			||||||
		t.Errorf("Expected %#v, Got %#v", expected, got)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete endpoints1
 | 
						// Delete endpoints1
 | 
				
			||||||
 | 
						handler.expected = []*api.Endpoints{endpoints2}
 | 
				
			||||||
	fakeWatch.Delete(endpoints1v2)
 | 
						fakeWatch.Delete(endpoints1v2)
 | 
				
			||||||
	got, ok = <-ch
 | 
						<-ch
 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		t.Errorf("Unable to read from channel when expected")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	expected = EndpointsUpdate{Op: REMOVE, Endpoints: endpoints1v2}
 | 
					 | 
				
			||||||
	if !apiequality.Semantic.DeepEqual(expected, got) {
 | 
					 | 
				
			||||||
		t.Errorf("Expected %#v, Got %#v", expected, got)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete endpoints2
 | 
						// Delete endpoints2
 | 
				
			||||||
 | 
						handler.expected = []*api.Endpoints{}
 | 
				
			||||||
	fakeWatch.Delete(endpoints2)
 | 
						fakeWatch.Delete(endpoints2)
 | 
				
			||||||
	got, ok = <-ch
 | 
						<-ch
 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		t.Errorf("Unable to read from channel when expected")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	expected = EndpointsUpdate{Op: REMOVE, Endpoints: endpoints2}
 | 
					 | 
				
			||||||
	if !apiequality.Semantic.DeepEqual(expected, got) {
 | 
					 | 
				
			||||||
		t.Errorf("Expected %#v, Got %#v", expected, got)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type svcHandler struct {
 | 
					type svcHandler struct {
 | 
				
			||||||
@@ -286,13 +258,6 @@ func TestInitialSync(t *testing.T) {
 | 
				
			|||||||
	// Wait for both services and endpoints handler.
 | 
						// Wait for both services and endpoints handler.
 | 
				
			||||||
	wg.Add(2)
 | 
						wg.Add(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	svcConfig := NewServiceConfig()
 | 
					 | 
				
			||||||
	epsConfig := NewEndpointsConfig()
 | 
					 | 
				
			||||||
	svcHandler := newSvcHandler(t, []api.Service{*svc2, *svc1}, wg.Done)
 | 
					 | 
				
			||||||
	svcConfig.RegisterHandler(svcHandler)
 | 
					 | 
				
			||||||
	epsHandler := newEpsHandler(t, []*api.Endpoints{eps2, eps1}, wg.Done)
 | 
					 | 
				
			||||||
	epsConfig.RegisterHandler(epsHandler)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Setup fake api client.
 | 
						// Setup fake api client.
 | 
				
			||||||
	fakeSvcWatch := watch.NewFake()
 | 
						fakeSvcWatch := watch.NewFake()
 | 
				
			||||||
	svcLW := fakeLW{
 | 
						svcLW := fakeLW{
 | 
				
			||||||
@@ -305,8 +270,16 @@ func TestInitialSync(t *testing.T) {
 | 
				
			|||||||
		watchResp: fakeEpsWatch,
 | 
							watchResp: fakeEpsWatch,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						svcConfig := NewServiceConfig()
 | 
				
			||||||
 | 
						epsConfig := newEndpointsConfig(epsLW, time.Minute)
 | 
				
			||||||
 | 
						svcHandler := newSvcHandler(t, []api.Service{*svc2, *svc1}, wg.Done)
 | 
				
			||||||
 | 
						svcConfig.RegisterHandler(svcHandler)
 | 
				
			||||||
 | 
						epsHandler := newEpsHandler(t, []*api.Endpoints{eps2, eps1}, wg.Done)
 | 
				
			||||||
 | 
						epsConfig.RegisterHandler(epsHandler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stopCh := make(chan struct{})
 | 
						stopCh := make(chan struct{})
 | 
				
			||||||
	defer close(stopCh)
 | 
						defer close(stopCh)
 | 
				
			||||||
	newSourceAPI(svcLW, epsLW, time.Minute, svcConfig.Channel("one"), epsConfig.Channel("two"), stopCh)
 | 
						go epsConfig.Run(stopCh)
 | 
				
			||||||
 | 
						newSourceAPI(svcLW, time.Minute, svcConfig.Channel("one"), stopCh)
 | 
				
			||||||
	wg.Wait()
 | 
						wg.Wait()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,12 +17,20 @@ limitations under the License.
 | 
				
			|||||||
package config
 | 
					package config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/davecgh/go-spew/spew"
 | 
						"github.com/davecgh/go-spew/spew"
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/fields"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/labels"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
 | 
						utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
				
			||||||
 | 
						"k8s.io/client-go/tools/cache"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api"
 | 
						"k8s.io/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						listers "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/config"
 | 
						"k8s.io/kubernetes/pkg/util/config"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,102 +84,100 @@ type EndpointsConfigHandler interface {
 | 
				
			|||||||
// EndpointsConfig tracks a set of endpoints configurations.
 | 
					// EndpointsConfig tracks a set of endpoints configurations.
 | 
				
			||||||
// It accepts "set", "add" and "remove" operations of endpoints via channels, and invokes registered handlers on change.
 | 
					// It accepts "set", "add" and "remove" operations of endpoints via channels, and invokes registered handlers on change.
 | 
				
			||||||
type EndpointsConfig struct {
 | 
					type EndpointsConfig struct {
 | 
				
			||||||
	mux     *config.Mux
 | 
						informer cache.Controller
 | 
				
			||||||
	bcaster *config.Broadcaster
 | 
						lister   listers.EndpointsLister
 | 
				
			||||||
	store   *endpointsStore
 | 
						handlers []EndpointsConfigHandler
 | 
				
			||||||
 | 
						// updates channel is used to trigger registered handlers.
 | 
				
			||||||
 | 
						updates chan struct{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewEndpointsConfig creates a new EndpointsConfig.
 | 
					// NewEndpointsConfig creates a new EndpointsConfig.
 | 
				
			||||||
// It immediately runs the created EndpointsConfig.
 | 
					func NewEndpointsConfig(c cache.Getter, period time.Duration) *EndpointsConfig {
 | 
				
			||||||
func NewEndpointsConfig() *EndpointsConfig {
 | 
						endpointsLW := cache.NewListWatchFromClient(c, "endpoints", metav1.NamespaceAll, fields.Everything())
 | 
				
			||||||
	// The updates channel is used to send interrupts to the Endpoints handler.
 | 
						return newEndpointsConfig(endpointsLW, period)
 | 
				
			||||||
	// It's buffered because we never want to block for as long as there is a
 | 
					}
 | 
				
			||||||
	// pending interrupt, but don't want to drop them if the handler is doing
 | 
					
 | 
				
			||||||
	// work.
 | 
					func newEndpointsConfig(lw cache.ListerWatcher, period time.Duration) *EndpointsConfig {
 | 
				
			||||||
	updates := make(chan struct{}, 1)
 | 
						result := &EndpointsConfig{}
 | 
				
			||||||
	store := &endpointsStore{updates: updates, endpoints: make(map[string]map[types.NamespacedName]*api.Endpoints)}
 | 
					
 | 
				
			||||||
	mux := config.NewMux(store)
 | 
						store, informer := cache.NewIndexerInformer(
 | 
				
			||||||
	bcaster := config.NewBroadcaster()
 | 
							lw,
 | 
				
			||||||
	go watchForUpdates(bcaster, store, updates)
 | 
							&api.Endpoints{},
 | 
				
			||||||
	return &EndpointsConfig{mux, bcaster, store}
 | 
							period,
 | 
				
			||||||
 | 
							cache.ResourceEventHandlerFuncs{
 | 
				
			||||||
 | 
								AddFunc:    result.handleAddEndpoints,
 | 
				
			||||||
 | 
								UpdateFunc: result.handleUpdateEndpoints,
 | 
				
			||||||
 | 
								DeleteFunc: result.handleDeleteEndpoints,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							cache.Indexers{},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						result.informer = informer
 | 
				
			||||||
 | 
						result.lister = listers.NewEndpointsLister(store)
 | 
				
			||||||
 | 
						return result
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterHandler registers a handler which is called on every endpoints change.
 | 
					// RegisterHandler registers a handler which is called on every endpoints change.
 | 
				
			||||||
func (c *EndpointsConfig) RegisterHandler(handler EndpointsConfigHandler) {
 | 
					func (c *EndpointsConfig) RegisterHandler(handler EndpointsConfigHandler) {
 | 
				
			||||||
	c.bcaster.Add(config.ListenerFunc(func(instance interface{}) {
 | 
						c.handlers = append(c.handlers, handler)
 | 
				
			||||||
		glog.V(3).Infof("Calling handler.OnEndpointsUpdate()")
 | 
					 | 
				
			||||||
		handler.OnEndpointsUpdate(instance.([]*api.Endpoints))
 | 
					 | 
				
			||||||
	}))
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Channel returns a channel to which endpoints updates should be delivered.
 | 
					func (c *EndpointsConfig) Run(stopCh <-chan struct{}) {
 | 
				
			||||||
func (c *EndpointsConfig) Channel(source string) chan EndpointsUpdate {
 | 
						// The updates channel is used to send interrupts to the Endpoints handler.
 | 
				
			||||||
	ch := c.mux.Channel(source)
 | 
						// It's buffered because we never want to block for as long as there is a
 | 
				
			||||||
	endpointsCh := make(chan EndpointsUpdate)
 | 
						// pending interrupt, but don't want to drop them if the handler is doing
 | 
				
			||||||
 | 
						// work.
 | 
				
			||||||
 | 
						c.updates = make(chan struct{}, 1)
 | 
				
			||||||
 | 
						go c.informer.Run(stopCh)
 | 
				
			||||||
 | 
						if !cache.WaitForCacheSync(stopCh, c.informer.HasSynced) {
 | 
				
			||||||
 | 
							utilruntime.HandleError(fmt.Errorf("endpoint controller not synced"))
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We have synced informers. Now we can start delivering updates
 | 
				
			||||||
 | 
						// to the registered handler.
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for update := range endpointsCh {
 | 
							for range c.updates {
 | 
				
			||||||
			ch <- update
 | 
								endpoints, err := c.lister.List(labels.Everything())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									glog.Errorf("Error while listing endpoints from cache: %v", err)
 | 
				
			||||||
 | 
									// This will cause a retry (if there isn't any other trigger in-flight).
 | 
				
			||||||
 | 
									c.dispatchUpdate()
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if endpoints == nil {
 | 
				
			||||||
 | 
									endpoints = []*api.Endpoints{}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for i := range c.handlers {
 | 
				
			||||||
 | 
									glog.V(3).Infof("Calling handler.OnEndpointsUpdate()")
 | 
				
			||||||
 | 
									c.handlers[i].OnEndpointsUpdate(endpoints)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	return endpointsCh
 | 
						// Close updates channel when stopCh is closed.
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							<-stopCh
 | 
				
			||||||
 | 
							close(c.updates)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Config returns list of all endpoints from underlying store.
 | 
					func (c *EndpointsConfig) handleAddEndpoints(_ interface{}) {
 | 
				
			||||||
func (c *EndpointsConfig) Config() []api.Endpoints {
 | 
						c.dispatchUpdate()
 | 
				
			||||||
	return c.store.MergedState().([]api.Endpoints)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type endpointsStore struct {
 | 
					func (c *EndpointsConfig) handleUpdateEndpoints(_, _ interface{}) {
 | 
				
			||||||
	endpointLock sync.RWMutex
 | 
						c.dispatchUpdate()
 | 
				
			||||||
	endpoints    map[string]map[types.NamespacedName]*api.Endpoints
 | 
					 | 
				
			||||||
	synced       bool
 | 
					 | 
				
			||||||
	updates      chan<- struct{}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *endpointsStore) Merge(source string, change interface{}) error {
 | 
					func (c *EndpointsConfig) handleDeleteEndpoints(_ interface{}) {
 | 
				
			||||||
	s.endpointLock.Lock()
 | 
						c.dispatchUpdate()
 | 
				
			||||||
	endpoints := s.endpoints[source]
 | 
					}
 | 
				
			||||||
	if endpoints == nil {
 | 
					
 | 
				
			||||||
		endpoints = make(map[types.NamespacedName]*api.Endpoints)
 | 
					func (c *EndpointsConfig) dispatchUpdate() {
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	update := change.(EndpointsUpdate)
 | 
					 | 
				
			||||||
	switch update.Op {
 | 
					 | 
				
			||||||
	case ADD, UPDATE:
 | 
					 | 
				
			||||||
		glog.V(5).Infof("Adding new endpoint from source %s : %s", source, spew.Sdump(update.Endpoints))
 | 
					 | 
				
			||||||
		name := types.NamespacedName{Namespace: update.Endpoints.Namespace, Name: update.Endpoints.Name}
 | 
					 | 
				
			||||||
		endpoints[name] = update.Endpoints
 | 
					 | 
				
			||||||
	case REMOVE:
 | 
					 | 
				
			||||||
		glog.V(5).Infof("Removing an endpoint %s", spew.Sdump(update.Endpoints))
 | 
					 | 
				
			||||||
		name := types.NamespacedName{Namespace: update.Endpoints.Namespace, Name: update.Endpoints.Name}
 | 
					 | 
				
			||||||
		delete(endpoints, name)
 | 
					 | 
				
			||||||
	case SYNCED:
 | 
					 | 
				
			||||||
		s.synced = true
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		glog.V(4).Infof("Received invalid update type: %s", spew.Sdump(update))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.endpoints[source] = endpoints
 | 
					 | 
				
			||||||
	synced := s.synced
 | 
					 | 
				
			||||||
	s.endpointLock.Unlock()
 | 
					 | 
				
			||||||
	if s.updates != nil && synced {
 | 
					 | 
				
			||||||
	select {
 | 
						select {
 | 
				
			||||||
		case s.updates <- struct{}{}:
 | 
						case c.updates <- struct{}{}:
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		glog.V(4).Infof("Endpoints handler already has a pending interrupt.")
 | 
							glog.V(4).Infof("Endpoints handler already has a pending interrupt.")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *endpointsStore) MergedState() interface{} {
 | 
					 | 
				
			||||||
	s.endpointLock.RLock()
 | 
					 | 
				
			||||||
	defer s.endpointLock.RUnlock()
 | 
					 | 
				
			||||||
	endpoints := make([]*api.Endpoints, 0)
 | 
					 | 
				
			||||||
	for _, sourceEndpoints := range s.endpoints {
 | 
					 | 
				
			||||||
		for _, value := range sourceEndpoints {
 | 
					 | 
				
			||||||
			endpoints = append(endpoints, value)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return endpoints
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ServiceConfig tracks a set of service configurations.
 | 
					// ServiceConfig tracks a set of service configurations.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/watch"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api"
 | 
						"k8s.io/kubernetes/pkg/api"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -228,98 +229,110 @@ func TestNewMultipleSourcesServicesMultipleHandlersAddedAndNotified(t *testing.T
 | 
				
			|||||||
	handler2.ValidateServices(t, services)
 | 
						handler2.ValidateServices(t, services)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewMultipleSourcesEndpointsMultipleHandlersAddedAndNotified(t *testing.T) {
 | 
					func TestNewEndpointsMultipleHandlersAddedAndNotified(t *testing.T) {
 | 
				
			||||||
	config := NewEndpointsConfig()
 | 
						fakeWatch := watch.NewFake()
 | 
				
			||||||
	config.store.synced = true
 | 
						lw := fakeLW{
 | 
				
			||||||
	channelOne := config.Channel("one")
 | 
							listResp:  &api.EndpointsList{Items: []api.Endpoints{}},
 | 
				
			||||||
	channelTwo := config.Channel("two")
 | 
							watchResp: fakeWatch,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stopCh := make(chan struct{})
 | 
				
			||||||
 | 
						defer close(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config := newEndpointsConfig(lw, time.Minute)
 | 
				
			||||||
	handler := NewEndpointsHandlerMock()
 | 
						handler := NewEndpointsHandlerMock()
 | 
				
			||||||
	handler2 := NewEndpointsHandlerMock()
 | 
						handler2 := NewEndpointsHandlerMock()
 | 
				
			||||||
	config.RegisterHandler(handler)
 | 
						config.RegisterHandler(handler)
 | 
				
			||||||
	config.RegisterHandler(handler2)
 | 
						config.RegisterHandler(handler2)
 | 
				
			||||||
	endpointsUpdate1 := CreateEndpointsUpdate(ADD, &api.Endpoints{
 | 
						go config.Run(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endpoints1 := &api.Endpoints{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foo"},
 | 
							ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foo"},
 | 
				
			||||||
		Subsets: []api.EndpointSubset{{
 | 
							Subsets: []api.EndpointSubset{{
 | 
				
			||||||
			Addresses: []api.EndpointAddress{{IP: "1.1.1.1"}, {IP: "2.2.2.2"}},
 | 
								Addresses: []api.EndpointAddress{{IP: "1.1.1.1"}, {IP: "2.2.2.2"}},
 | 
				
			||||||
			Ports:     []api.EndpointPort{{Port: 80}},
 | 
								Ports:     []api.EndpointPort{{Port: 80}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
	endpointsUpdate2 := CreateEndpointsUpdate(ADD, &api.Endpoints{
 | 
						endpoints2 := &api.Endpoints{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "bar"},
 | 
							ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "bar"},
 | 
				
			||||||
		Subsets: []api.EndpointSubset{{
 | 
							Subsets: []api.EndpointSubset{{
 | 
				
			||||||
			Addresses: []api.EndpointAddress{{IP: "3.3.3.3"}, {IP: "4.4.4.4"}},
 | 
								Addresses: []api.EndpointAddress{{IP: "3.3.3.3"}, {IP: "4.4.4.4"}},
 | 
				
			||||||
			Ports:     []api.EndpointPort{{Port: 80}},
 | 
								Ports:     []api.EndpointPort{{Port: 80}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
	channelOne <- endpointsUpdate1
 | 
						fakeWatch.Add(endpoints1)
 | 
				
			||||||
	channelTwo <- endpointsUpdate2
 | 
						fakeWatch.Add(endpoints2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	endpoints := []*api.Endpoints{endpointsUpdate2.Endpoints, endpointsUpdate1.Endpoints}
 | 
						endpoints := []*api.Endpoints{endpoints2, endpoints1}
 | 
				
			||||||
	handler.ValidateEndpoints(t, endpoints)
 | 
						handler.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
	handler2.ValidateEndpoints(t, endpoints)
 | 
						handler2.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewMultipleSourcesEndpointsMultipleHandlersAddRemoveSetAndNotified(t *testing.T) {
 | 
					func TestNewEndpointsMultipleHandlersAddRemoveSetAndNotified(t *testing.T) {
 | 
				
			||||||
	config := NewEndpointsConfig()
 | 
						fakeWatch := watch.NewFake()
 | 
				
			||||||
	config.store.synced = true
 | 
						lw := fakeLW{
 | 
				
			||||||
	channelOne := config.Channel("one")
 | 
							listResp:  &api.EndpointsList{Items: []api.Endpoints{}},
 | 
				
			||||||
	channelTwo := config.Channel("two")
 | 
							watchResp: fakeWatch,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stopCh := make(chan struct{})
 | 
				
			||||||
 | 
						defer close(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config := newEndpointsConfig(lw, time.Minute)
 | 
				
			||||||
	handler := NewEndpointsHandlerMock()
 | 
						handler := NewEndpointsHandlerMock()
 | 
				
			||||||
	handler2 := NewEndpointsHandlerMock()
 | 
						handler2 := NewEndpointsHandlerMock()
 | 
				
			||||||
	config.RegisterHandler(handler)
 | 
						config.RegisterHandler(handler)
 | 
				
			||||||
	config.RegisterHandler(handler2)
 | 
						config.RegisterHandler(handler2)
 | 
				
			||||||
	endpointsUpdate1 := CreateEndpointsUpdate(ADD, &api.Endpoints{
 | 
						go config.Run(stopCh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endpoints1 := &api.Endpoints{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foo"},
 | 
							ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foo"},
 | 
				
			||||||
		Subsets: []api.EndpointSubset{{
 | 
							Subsets: []api.EndpointSubset{{
 | 
				
			||||||
			Addresses: []api.EndpointAddress{{IP: "1.1.1.1"}, {IP: "2.2.2.2"}},
 | 
								Addresses: []api.EndpointAddress{{IP: "1.1.1.1"}, {IP: "2.2.2.2"}},
 | 
				
			||||||
			Ports:     []api.EndpointPort{{Port: 80}},
 | 
								Ports:     []api.EndpointPort{{Port: 80}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
	endpointsUpdate2 := CreateEndpointsUpdate(ADD, &api.Endpoints{
 | 
						endpoints2 := &api.Endpoints{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "bar"},
 | 
							ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "bar"},
 | 
				
			||||||
		Subsets: []api.EndpointSubset{{
 | 
							Subsets: []api.EndpointSubset{{
 | 
				
			||||||
			Addresses: []api.EndpointAddress{{IP: "3.3.3.3"}, {IP: "4.4.4.4"}},
 | 
								Addresses: []api.EndpointAddress{{IP: "3.3.3.3"}, {IP: "4.4.4.4"}},
 | 
				
			||||||
			Ports:     []api.EndpointPort{{Port: 80}},
 | 
								Ports:     []api.EndpointPort{{Port: 80}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
	channelOne <- endpointsUpdate1
 | 
						fakeWatch.Add(endpoints1)
 | 
				
			||||||
	channelTwo <- endpointsUpdate2
 | 
						fakeWatch.Add(endpoints2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	endpoints := []*api.Endpoints{endpointsUpdate2.Endpoints, endpointsUpdate1.Endpoints}
 | 
						endpoints := []*api.Endpoints{endpoints2, endpoints1}
 | 
				
			||||||
	handler.ValidateEndpoints(t, endpoints)
 | 
						handler.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
	handler2.ValidateEndpoints(t, endpoints)
 | 
						handler2.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add one more
 | 
						// Add one more
 | 
				
			||||||
	endpointsUpdate3 := CreateEndpointsUpdate(ADD, &api.Endpoints{
 | 
						endpoints3 := &api.Endpoints{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foobar"},
 | 
							ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foobar"},
 | 
				
			||||||
		Subsets: []api.EndpointSubset{{
 | 
							Subsets: []api.EndpointSubset{{
 | 
				
			||||||
			Addresses: []api.EndpointAddress{{IP: "5.5.5.5"}, {IP: "6.6.6.6"}},
 | 
								Addresses: []api.EndpointAddress{{IP: "5.5.5.5"}, {IP: "6.6.6.6"}},
 | 
				
			||||||
			Ports:     []api.EndpointPort{{Port: 80}},
 | 
								Ports:     []api.EndpointPort{{Port: 80}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
	channelTwo <- endpointsUpdate3
 | 
						fakeWatch.Add(endpoints3)
 | 
				
			||||||
	endpoints = []*api.Endpoints{endpointsUpdate2.Endpoints, endpointsUpdate1.Endpoints, endpointsUpdate3.Endpoints}
 | 
						endpoints = []*api.Endpoints{endpoints2, endpoints1, endpoints3}
 | 
				
			||||||
	handler.ValidateEndpoints(t, endpoints)
 | 
						handler.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
	handler2.ValidateEndpoints(t, endpoints)
 | 
						handler2.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Update the "foo" service with new endpoints
 | 
						// Update the "foo" service with new endpoints
 | 
				
			||||||
	endpointsUpdate1 = CreateEndpointsUpdate(ADD, &api.Endpoints{
 | 
						endpoints1v2 := &api.Endpoints{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foo"},
 | 
							ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "foo"},
 | 
				
			||||||
		Subsets: []api.EndpointSubset{{
 | 
							Subsets: []api.EndpointSubset{{
 | 
				
			||||||
			Addresses: []api.EndpointAddress{{IP: "7.7.7.7"}},
 | 
								Addresses: []api.EndpointAddress{{IP: "7.7.7.7"}},
 | 
				
			||||||
			Ports:     []api.EndpointPort{{Port: 80}},
 | 
								Ports:     []api.EndpointPort{{Port: 80}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
	})
 | 
						}
 | 
				
			||||||
	channelOne <- endpointsUpdate1
 | 
						fakeWatch.Modify(endpoints1v2)
 | 
				
			||||||
	endpoints = []*api.Endpoints{endpointsUpdate2.Endpoints, endpointsUpdate1.Endpoints, endpointsUpdate3.Endpoints}
 | 
						endpoints = []*api.Endpoints{endpoints2, endpoints1v2, endpoints3}
 | 
				
			||||||
	handler.ValidateEndpoints(t, endpoints)
 | 
						handler.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
	handler2.ValidateEndpoints(t, endpoints)
 | 
						handler2.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Remove "bar" service
 | 
						// Remove "bar" endpoints
 | 
				
			||||||
	endpointsUpdate2 = CreateEndpointsUpdate(REMOVE, &api.Endpoints{ObjectMeta: metav1.ObjectMeta{Namespace: "testnamespace", Name: "bar"}})
 | 
						fakeWatch.Delete(endpoints2)
 | 
				
			||||||
	channelTwo <- endpointsUpdate2
 | 
						endpoints = []*api.Endpoints{endpoints1v2, endpoints3}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	endpoints = []*api.Endpoints{endpointsUpdate1.Endpoints, endpointsUpdate3.Endpoints}
 | 
					 | 
				
			||||||
	handler.ValidateEndpoints(t, endpoints)
 | 
						handler.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
	handler2.ValidateEndpoints(t, endpoints)
 | 
						handler2.ValidateEndpoints(t, endpoints)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user