// NewDockercfgController returns a new *DockercfgController. func NewDockercfgController(cl kclientset.Interface, options DockercfgControllerOptions) *DockercfgController { e := &DockercfgController{ client: cl, queue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()), dockerURLsIntialized: options.DockerURLsIntialized, } var serviceAccountCache cache.Store serviceAccountCache, e.serviceAccountController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return e.client.Core().ServiceAccounts(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return e.client.Core().ServiceAccounts(api.NamespaceAll).Watch(options) }, }, &api.ServiceAccount{}, options.Resync, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { serviceAccount := obj.(*api.ServiceAccount) glog.V(5).Infof("Adding service account %s", serviceAccount.Name) e.enqueueServiceAccount(serviceAccount) }, UpdateFunc: func(old, cur interface{}) { serviceAccount := cur.(*api.ServiceAccount) glog.V(5).Infof("Updating service account %s", serviceAccount.Name) // Resync on service object relist. e.enqueueServiceAccount(serviceAccount) }, }, ) e.serviceAccountCache = NewEtcdMutationCache(serviceAccountCache) tokenSecretSelector := fields.OneTermEqualSelector(api.SecretTypeField, string(api.SecretTypeServiceAccountToken)) e.secretCache, e.secretController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { options.FieldSelector = tokenSecretSelector return e.client.Core().Secrets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { options.FieldSelector = tokenSecretSelector return e.client.Core().Secrets(api.NamespaceAll).Watch(options) }, }, &api.Secret{}, options.Resync, cache.ResourceEventHandlerFuncs{ AddFunc: func(cur interface{}) { e.handleTokenSecretUpdate(nil, cur) }, UpdateFunc: func(old, cur interface{}) { e.handleTokenSecretUpdate(old, cur) }, DeleteFunc: e.handleTokenSecretDelete, }, ) e.syncHandler = e.syncServiceAccount return e }
// NewSync for ConfigMap from namespace `ns` and `name`. func NewSync(client clientset.Interface, ns string, name string) Sync { sync := &kubeSync{ ns: ns, name: name, client: client, channel: make(chan *Config), } listWatch := &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { options.FieldSelector = fields.Set{"metadata.name": name}.AsSelector() return client.Core().ConfigMaps(ns).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { options.FieldSelector = fields.Set{"metadata.name": name}.AsSelector() return client.Core().ConfigMaps(ns).Watch(options) }, } store, controller := cache.NewInformer( listWatch, &api.ConfigMap{}, time.Duration(0), cache.ResourceEventHandlerFuncs{ AddFunc: sync.onAdd, DeleteFunc: sync.onDelete, UpdateFunc: sync.onUpdate, }) sync.store = store sync.controller = controller return sync }
// NewDockercfgDeletedController returns a new *DockercfgDeletedController. func NewDockercfgDeletedController(cl kclientset.Interface, options DockercfgDeletedControllerOptions) *DockercfgDeletedController { e := &DockercfgDeletedController{ client: cl, } dockercfgSelector := fields.OneTermEqualSelector(api.SecretTypeField, string(api.SecretTypeDockercfg)) _, e.secretController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { opts := api.ListOptions{FieldSelector: dockercfgSelector} return e.client.Core().Secrets(api.NamespaceAll).List(opts) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { opts := api.ListOptions{FieldSelector: dockercfgSelector, ResourceVersion: options.ResourceVersion} return e.client.Core().Secrets(api.NamespaceAll).Watch(opts) }, }, &api.Secret{}, options.Resync, cache.ResourceEventHandlerFuncs{ DeleteFunc: e.secretDeleted, }, ) return e }
func NewPodGC(kubeClient clientset.Interface, podInformer cache.SharedIndexInformer, terminatedPodThreshold int) *PodGCController { if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("gc_controller", kubeClient.Core().RESTClient().GetRateLimiter()) } gcc := &PodGCController{ kubeClient: kubeClient, terminatedPodThreshold: terminatedPodThreshold, deletePod: func(namespace, name string) error { glog.Infof("PodGC is force deleting Pod: %v:%v", namespace, name) return kubeClient.Core().Pods(namespace).Delete(name, v1.NewDeleteOptions(0)) }, } gcc.podStore.Indexer = podInformer.GetIndexer() gcc.podController = podInformer.GetController() gcc.nodeStore.Store, gcc.nodeController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return gcc.kubeClient.Core().Nodes().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return gcc.kubeClient.Core().Nodes().Watch(options) }, }, &v1.Node{}, controller.NoResyncPeriodFunc(), cache.ResourceEventHandlerFuncs{}, ) return gcc }
// NewclusterController returns a new cluster controller func NewclusterController(federationClient federationclientset.Interface, clusterMonitorPeriod time.Duration) *ClusterController { cc := &ClusterController{ knownClusterSet: make(sets.String), federationClient: federationClient, clusterMonitorPeriod: clusterMonitorPeriod, clusterClusterStatusMap: make(map[string]federationv1beta1.ClusterStatus), clusterKubeClientMap: make(map[string]ClusterClient), } cc.clusterStore.Store, cc.clusterController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return cc.federationClient.Federation().Clusters().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return cc.federationClient.Federation().Clusters().Watch(options) }, }, &federationv1beta1.Cluster{}, controller.NoResyncPeriodFunc(), cache.ResourceEventHandlerFuncs{ DeleteFunc: cc.delFromClusterSet, AddFunc: cc.addToClusterSet, }, ) return cc }
func New(routes cloudprovider.Routes, kubeClient clientset.Interface, clusterName string, clusterCIDR *net.IPNet) *RouteController { if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("route_controller", kubeClient.Core().RESTClient().GetRateLimiter()) } rc := &RouteController{ routes: routes, kubeClient: kubeClient, clusterName: clusterName, clusterCIDR: clusterCIDR, } rc.nodeStore.Store, rc.nodeController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return rc.kubeClient.Core().Nodes().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return rc.kubeClient.Core().Nodes().Watch(options) }, }, &v1.Node{}, controller.NoResyncPeriodFunc(), cache.ResourceEventHandlerFuncs{}, ) return rc }
func NewJobController(podInformer cache.SharedIndexInformer, kubeClient clientset.Interface) *JobController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) // TODO: remove the wrapper when every clients have moved to use the clientset. eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("job_controller", kubeClient.Core().RESTClient().GetRateLimiter()) } jm := &JobController{ kubeClient: kubeClient, podControl: controller.RealPodControl{ KubeClient: kubeClient, Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "job-controller"}), }, expectations: controller.NewControllerExpectations(), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "job"), recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "job-controller"}), } jm.jobStore.Store, jm.jobController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return jm.kubeClient.Batch().Jobs(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return jm.kubeClient.Batch().Jobs(api.NamespaceAll).Watch(options) }, }, &batch.Job{}, // TODO: Can we have much longer period here? replicationcontroller.FullControllerResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: jm.enqueueController, UpdateFunc: func(old, cur interface{}) { if job := cur.(*batch.Job); !IsJobFinished(job) { jm.enqueueController(job) } }, DeleteFunc: jm.enqueueController, }, ) podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: jm.addPod, UpdateFunc: jm.updatePod, DeleteFunc: jm.deletePod, }) jm.podStore.Indexer = podInformer.GetIndexer() jm.podStoreSynced = podInformer.HasSynced jm.updateHandler = jm.updateJobStatus jm.syncHandler = jm.syncJob return jm }
// NewPetSetController creates a new petset controller. func NewPetSetController(podInformer cache.SharedIndexInformer, kubeClient internalclientset.Interface, resyncPeriod time.Duration) *PetSetController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "petset"}) pc := &apiServerPetClient{kubeClient, recorder, &defaultPetHealthChecker{}} psc := &PetSetController{ kubeClient: kubeClient, blockingPetStore: newUnHealthyPetTracker(pc), newSyncer: func(blockingPet *pcb) *petSyncer { return &petSyncer{pc, blockingPet} }, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "petset"), } podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ // lookup the petset and enqueue AddFunc: psc.addPod, // lookup current and old petset if labels changed UpdateFunc: psc.updatePod, // lookup petset accounting for deletion tombstones DeleteFunc: psc.deletePod, }) psc.podStore.Indexer = podInformer.GetIndexer() psc.podController = podInformer.GetController() psc.psStore.Store, psc.psController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return psc.kubeClient.Apps().PetSets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return psc.kubeClient.Apps().PetSets(api.NamespaceAll).Watch(options) }, }, &apps.PetSet{}, petSetResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: psc.enqueuePetSet, UpdateFunc: func(old, cur interface{}) { oldPS := old.(*apps.PetSet) curPS := cur.(*apps.PetSet) if oldPS.Status.Replicas != curPS.Status.Replicas { glog.V(4).Infof("Observed updated replica count for PetSet: %v, %d->%d", curPS.Name, oldPS.Status.Replicas, curPS.Status.Replicas) } psc.enqueuePetSet(cur) }, DeleteFunc: psc.enqueuePetSet, }, ) // TODO: Watch volumes psc.podStoreSynced = psc.podController.HasSynced psc.syncHandler = psc.Sync return psc }
func NewCertificateController(kubeClient clientset.Interface, syncPeriod time.Duration, caCertFile, caKeyFile string, approveAllKubeletCSRsForGroup string) (*CertificateController, error) { // Send events to the apiserver eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) // Configure cfssl signer // TODO: support non-default policy and remote/pkcs11 signing policy := &config.Signing{ Default: config.DefaultConfig(), } ca, err := local.NewSignerFromFile(caCertFile, caKeyFile, policy) if err != nil { return nil, err } cc := &CertificateController{ kubeClient: kubeClient, queue: workqueue.NewNamed("certificate"), signer: ca, approveAllKubeletCSRsForGroup: approveAllKubeletCSRsForGroup, } // Manage the addition/update of certificate requests cc.csrStore.Store, cc.csrController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return cc.kubeClient.Certificates().CertificateSigningRequests().List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return cc.kubeClient.Certificates().CertificateSigningRequests().Watch(options) }, }, &certificates.CertificateSigningRequest{}, syncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { csr := obj.(*certificates.CertificateSigningRequest) glog.V(4).Infof("Adding certificate request %s", csr.Name) cc.enqueueCertificateRequest(obj) }, UpdateFunc: func(old, new interface{}) { oldCSR := old.(*certificates.CertificateSigningRequest) glog.V(4).Infof("Updating certificate request %s", oldCSR.Name) cc.enqueueCertificateRequest(new) }, DeleteFunc: func(obj interface{}) { csr := obj.(*certificates.CertificateSigningRequest) glog.V(4).Infof("Deleting certificate request %s", csr.Name) cc.enqueueCertificateRequest(obj) }, }, ) cc.syncHandler = cc.maybeSignCertificate return cc, nil }
// newReplicaSetController configures a replica set controller with the specified event recorder func newReplicaSetController(eventRecorder record.EventRecorder, podInformer cache.SharedIndexInformer, kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, burstReplicas int, lookupCacheSize int, garbageCollectorEnabled bool) *ReplicaSetController { if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("replicaset_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) } rsc := &ReplicaSetController{ kubeClient: kubeClient, podControl: controller.RealPodControl{ KubeClient: kubeClient, Recorder: eventRecorder, }, burstReplicas: burstReplicas, expectations: controller.NewUIDTrackingControllerExpectations(controller.NewControllerExpectations()), queue: workqueue.NewNamed("replicaset"), garbageCollectorEnabled: garbageCollectorEnabled, } rsc.rsStore.Store, rsc.rsController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return rsc.kubeClient.Extensions().ReplicaSets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return rsc.kubeClient.Extensions().ReplicaSets(api.NamespaceAll).Watch(options) }, }, &extensions.ReplicaSet{}, // TODO: Can we have much longer period here? FullControllerResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: rsc.enqueueReplicaSet, UpdateFunc: rsc.updateRS, // This will enter the sync loop and no-op, because the replica set has been deleted from the store. // Note that deleting a replica set immediately after scaling it to 0 will not work. The recommended // way of achieving this is by performing a `stop` operation on the replica set. DeleteFunc: rsc.enqueueReplicaSet, }, ) podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: rsc.addPod, // This invokes the ReplicaSet for every pod change, eg: host assignment. Though this might seem like // overkill the most frequent pod update is status, and the associated ReplicaSet will only list from // local storage, so it should be ok. UpdateFunc: rsc.updatePod, DeleteFunc: rsc.deletePod, }) rsc.podStore.Indexer = podInformer.GetIndexer() rsc.podController = podInformer.GetController() rsc.syncHandler = rsc.syncReplicaSet rsc.podStoreSynced = rsc.podController.HasSynced rsc.lookupCache = controller.NewMatchingCache(lookupCacheSize) return rsc }
// Returns true if a node update matching the predicate was emitted from the // system after performing the supplied action. func observeNodeUpdateAfterAction(f *framework.Framework, nodeName string, nodePredicate func(*v1.Node) bool, action func() error) (bool, error) { observedMatchingNode := false nodeSelector := fields.OneTermEqualSelector("metadata.name", nodeName) informerStartedChan := make(chan struct{}) var informerStartedGuard sync.Once _, controller := cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { options.FieldSelector = nodeSelector.String() ls, err := f.ClientSet.Core().Nodes().List(options) return ls, err }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { options.FieldSelector = nodeSelector.String() w, err := f.ClientSet.Core().Nodes().Watch(options) // Signal parent goroutine that watching has begun. informerStartedGuard.Do(func() { close(informerStartedChan) }) return w, err }, }, &v1.Node{}, 0, cache.ResourceEventHandlerFuncs{ UpdateFunc: func(oldObj, newObj interface{}) { n, ok := newObj.(*v1.Node) Expect(ok).To(Equal(true)) if nodePredicate(n) { observedMatchingNode = true } }, }, ) // Start the informer and block this goroutine waiting for the started signal. informerStopChan := make(chan struct{}) defer func() { close(informerStopChan) }() go controller.Run(informerStopChan) <-informerStartedChan // Invoke the action function. err := action() if err != nil { return false, err } // Poll whether the informer has found a matching node update with a timeout. // Wait up 2 minutes polling every second. timeout := 2 * time.Minute interval := 1 * time.Second err = wait.Poll(interval, timeout, func() (bool, error) { return observedMatchingNode, nil }) return err == nil, err }
// NewIngressIPController creates a new IngressIPController. // TODO this should accept a shared informer func NewIngressIPController(kc kclientset.Interface, ipNet *net.IPNet, resyncInterval time.Duration) *IngressIPController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartRecordingToSink(&kcoreclient.EventSinkImpl{Interface: kc.Core().Events("")}) recorder := eventBroadcaster.NewRecorder(kapi.EventSource{Component: "ingressip-controller"}) ic := &IngressIPController{ client: kc.Core(), queue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()), maxRetries: 10, recorder: recorder, } ic.cache, ic.controller = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options kapi.ListOptions) (runtime.Object, error) { return ic.client.Services(kapi.NamespaceAll).List(options) }, WatchFunc: func(options kapi.ListOptions) (watch.Interface, error) { return ic.client.Services(kapi.NamespaceAll).Watch(options) }, }, &kapi.Service{}, resyncInterval, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { service := obj.(*kapi.Service) glog.V(5).Infof("Adding service %s/%s", service.Namespace, service.Name) ic.enqueueChange(obj, nil) }, UpdateFunc: func(old, cur interface{}) { service := cur.(*kapi.Service) glog.V(5).Infof("Updating service %s/%s", service.Namespace, service.Name) ic.enqueueChange(cur, old) }, DeleteFunc: func(obj interface{}) { service := obj.(*kapi.Service) glog.V(5).Infof("Deleting service %s/%s", service.Namespace, service.Name) ic.enqueueChange(nil, obj) }, }, ) ic.changeHandler = ic.processChange ic.persistenceHandler = persistService ic.ipAllocator = ipallocator.NewAllocatorCIDRRange(ipNet, func(max int, rangeSpec string) allocator.Interface { return allocator.NewAllocationMap(max, rangeSpec) }) ic.allocationMap = make(map[string]string) ic.requeuedAllocations = sets.NewString() return ic }
// Initializes the factory. func NewConfigFactory(client *client.Client, schedulerName string, hardPodAffinitySymmetricWeight int, failureDomains string) *ConfigFactory { stopEverything := make(chan struct{}) schedulerCache := schedulercache.New(30*time.Second, stopEverything) c := &ConfigFactory{ Client: client, PodQueue: cache.NewFIFO(cache.MetaNamespaceKeyFunc), ScheduledPodLister: &cache.StoreToPodLister{}, // Only nodes in the "Ready" condition with status == "True" are schedulable NodeLister: &cache.StoreToNodeLister{}, PVLister: &cache.StoreToPVFetcher{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}, PVCLister: &cache.StoreToPVCFetcher{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}, ServiceLister: &cache.StoreToServiceLister{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}, ControllerLister: &cache.StoreToReplicationControllerLister{Indexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}, ReplicaSetLister: &cache.StoreToReplicaSetLister{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}, schedulerCache: schedulerCache, StopEverything: stopEverything, SchedulerName: schedulerName, HardPodAffinitySymmetricWeight: hardPodAffinitySymmetricWeight, FailureDomains: failureDomains, } c.PodLister = schedulerCache // On add/delete to the scheduled pods, remove from the assumed pods. // We construct this here instead of in CreateFromKeys because // ScheduledPodLister is something we provide to plug in functions that // they may need to call. c.ScheduledPodLister.Indexer, c.scheduledPodPopulator = cache.NewIndexerInformer( c.createAssignedNonTerminatedPodLW(), &api.Pod{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: c.addPodToCache, UpdateFunc: c.updatePodInCache, DeleteFunc: c.deletePodFromCache, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) c.NodeLister.Store, c.nodePopulator = cache.NewInformer( c.createNodeLW(), &api.Node{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: c.addNodeToCache, UpdateFunc: c.updateNodeInCache, DeleteFunc: c.deleteNodeFromCache, }, ) return c }
func (gc *GarbageCollector) monitorFor(resource schema.GroupVersionResource, kind schema.GroupVersionKind) (monitor, error) { // TODO: consider store in one storage. glog.V(6).Infof("create storage for resource %s", resource) var monitor monitor client, err := gc.metaOnlyClientPool.ClientForGroupVersionKind(kind) if err != nil { return monitor, err } gc.registeredRateLimiterForMonitors.registerIfNotPresent(resource.GroupVersion(), client, "garbage_collector_monitoring") setObjectTypeMeta := func(obj interface{}) { runtimeObject, ok := obj.(runtime.Object) if !ok { utilruntime.HandleError(fmt.Errorf("expected runtime.Object, got %#v", obj)) } runtimeObject.GetObjectKind().SetGroupVersionKind(kind) } monitor.store, monitor.controller = cache.NewInformer( gcListWatcher(client, resource), nil, ResourceResyncTime, cache.ResourceEventHandlerFuncs{ // add the event to the propagator's eventQueue. AddFunc: func(obj interface{}) { setObjectTypeMeta(obj) event := &event{ eventType: addEvent, obj: obj, } gc.propagator.eventQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: gc.clock.Now(), Object: event}) }, UpdateFunc: func(oldObj, newObj interface{}) { setObjectTypeMeta(newObj) event := &event{updateEvent, newObj, oldObj} gc.propagator.eventQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: gc.clock.Now(), Object: event}) }, DeleteFunc: func(obj interface{}) { // delta fifo may wrap the object in a cache.DeletedFinalStateUnknown, unwrap it if deletedFinalStateUnknown, ok := obj.(cache.DeletedFinalStateUnknown); ok { obj = deletedFinalStateUnknown.Obj } setObjectTypeMeta(obj) event := &event{ eventType: deleteEvent, obj: obj, } gc.propagator.eventQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: gc.clock.Now(), Object: event}) }, }, ) return monitor, nil }
// New returns a new service controller to keep cloud provider service resources // (like load balancers) in sync with the registry. func New(cloud cloudprovider.Interface, kubeClient clientset.Interface, clusterName string) (*ServiceController, error) { broadcaster := record.NewBroadcaster() broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")}) recorder := broadcaster.NewRecorder(api.EventSource{Component: "service-controller"}) if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("service_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) } s := &ServiceController{ cloud: cloud, knownHosts: []string{}, kubeClient: kubeClient, clusterName: clusterName, cache: &serviceCache{serviceMap: make(map[string]*cachedService)}, eventBroadcaster: broadcaster, eventRecorder: recorder, nodeLister: cache.StoreToNodeLister{ Store: cache.NewStore(cache.MetaNamespaceKeyFunc), }, workingQueue: workqueue.NewDelayingQueue(), } s.serviceStore.Store, s.serviceController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) { return s.kubeClient.Core().Services(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return s.kubeClient.Core().Services(api.NamespaceAll).Watch(options) }, }, &api.Service{}, serviceSyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: s.enqueueService, UpdateFunc: func(old, cur interface{}) { oldSvc, ok1 := old.(*api.Service) curSvc, ok2 := cur.(*api.Service) if ok1 && ok2 && s.needsUpdate(oldSvc, curSvc) { s.enqueueService(cur) } }, DeleteFunc: s.enqueueService, }, ) if err := s.init(); err != nil { return nil, err } return s, nil }
// Returns true if an event matching the predicate was emitted from the system // after performing the supplied action. func observeEventAfterAction(f *framework.Framework, eventPredicate func(*v1.Event) bool, action func() error) (bool, error) { observedMatchingEvent := false // Create an informer to list/watch events from the test framework namespace. _, controller := cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { ls, err := f.ClientSet.Core().Events(f.Namespace.Name).List(options) return ls, err }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { w, err := f.ClientSet.Core().Events(f.Namespace.Name).Watch(options) return w, err }, }, &v1.Event{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { e, ok := obj.(*v1.Event) By(fmt.Sprintf("Considering event: \nType = [%s], Reason = [%s], Message = [%s]", e.Type, e.Reason, e.Message)) Expect(ok).To(Equal(true)) if ok && eventPredicate(e) { observedMatchingEvent = true } }, }, ) informerStopChan := make(chan struct{}) defer func() { close(informerStopChan) }() go controller.Run(informerStopChan) // Invoke the action function. err := action() if err != nil { return false, err } // Poll whether the informer has found a matching event with a timeout. // Wait up 2 minutes polling every second. timeout := 2 * time.Minute interval := 1 * time.Second err = wait.Poll(interval, timeout, func() (bool, error) { return observedMatchingEvent, nil }) return err == nil, err }
// NewEndpointController returns a new *EndpointController. func NewEndpointController(client *clientset.Clientset) *endpointController { e := &endpointController{ client: client, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "endpoint"), } e.serviceStore.Store, e.serviceController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return e.client.Core().Services(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return e.client.Core().Services(api.NamespaceAll).Watch(options) }, }, &api.Service{}, kservice.FullServiceResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: e.enqueueService, UpdateFunc: func(old, cur interface{}) { e.enqueueService(cur) }, DeleteFunc: e.enqueueService, }, ) e.podStore.Indexer, e.podController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return e.client.Core().Pods(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return e.client.Core().Pods(api.NamespaceAll).Watch(options) }, }, &api.Pod{}, 5*time.Minute, cache.ResourceEventHandlerFuncs{ AddFunc: e.addPod, UpdateFunc: e.updatePod, DeleteFunc: e.deletePod, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) return e }
// newInformerWatchPod creates an informer to check whether all pods are running. func newInformerWatchPod(f *framework.Framework, mutex *sync.Mutex, watchTimes map[string]metav1.Time, podType string) *cache.Controller { ns := f.Namespace.Name checkPodRunning := func(p *v1.Pod) { mutex.Lock() defer mutex.Unlock() defer GinkgoRecover() if p.Status.Phase == v1.PodRunning { if _, found := watchTimes[p.Name]; !found { watchTimes[p.Name] = metav1.Now() } } } _, controller := cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { options.LabelSelector = labels.SelectorFromSet(labels.Set{"type": podType}).String() obj, err := f.ClientSet.Core().Pods(ns).List(options) return runtime.Object(obj), err }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { options.LabelSelector = labels.SelectorFromSet(labels.Set{"type": podType}).String() return f.ClientSet.Core().Pods(ns).Watch(options) }, }, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { p, ok := obj.(*v1.Pod) Expect(ok).To(Equal(true)) go checkPodRunning(p) }, UpdateFunc: func(oldObj, newObj interface{}) { p, ok := newObj.(*v1.Pod) Expect(ok).To(Equal(true)) go checkPodRunning(p) }, }, ) return controller }
func (kd *KubeDNS) setServicesStore() { // Returns a cache.ListWatch that gets all changes to services. kd.servicesStore, kd.serviceController = kcache.NewInformer( &kcache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return kd.kubeClient.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return kd.kubeClient.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, resyncPeriod, kcache.ResourceEventHandlerFuncs{ AddFunc: kd.newService, DeleteFunc: kd.removeService, UpdateFunc: kd.updateService, }, ) }
// NewEndpointController returns a new *EndpointController. func NewEndpointController(podInformer cache.SharedIndexInformer, client *clientset.Clientset) *EndpointController { if client != nil && client.Core().GetRESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("endpoint_controller", client.Core().GetRESTClient().GetRateLimiter()) } e := &EndpointController{ client: client, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "endpoint"), } e.serviceStore.Store, e.serviceController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return e.client.Core().Services(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return e.client.Core().Services(api.NamespaceAll).Watch(options) }, }, &api.Service{}, // TODO: Can we have much longer period here? FullServiceResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: e.enqueueService, UpdateFunc: func(old, cur interface{}) { e.enqueueService(cur) }, DeleteFunc: e.enqueueService, }, ) podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: e.addPod, UpdateFunc: e.updatePod, DeleteFunc: e.deletePod, }) e.podStore.Indexer = podInformer.GetIndexer() e.podController = podInformer.GetController() e.podStoreSynced = podInformer.HasSynced return e }
func (kd *KubeDNS) setEndpointsStore() { // Returns a cache.ListWatch that gets all changes to endpoints. kd.endpointsStore, kd.endpointsController = kcache.NewInformer( &kcache.ListWatch{ ListFunc: func(options kapi.ListOptions) (runtime.Object, error) { return kd.kubeClient.Core().Endpoints(kapi.NamespaceAll).List(options) }, WatchFunc: func(options kapi.ListOptions) (watch.Interface, error) { return kd.kubeClient.Core().Endpoints(kapi.NamespaceAll).Watch(options) }, }, &kapi.Endpoints{}, resyncPeriod, kcache.ResourceEventHandlerFuncs{ AddFunc: kd.handleEndpointAdd, UpdateFunc: func(oldObj, newObj interface{}) { // TODO: Avoid unwanted updates. kd.handleEndpointAdd(newObj) }, }, ) }
// blocks until it has finished syncing. func startEndpointWatcher(f *framework.Framework, q *endpointQueries) { _, controller := cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { obj, err := f.ClientSet.Core().Endpoints(f.Namespace.Name).List(options) return runtime.Object(obj), err }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return f.ClientSet.Core().Endpoints(f.Namespace.Name).Watch(options) }, }, &api.Endpoints{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if e, ok := obj.(*api.Endpoints); ok { if len(e.Subsets) > 0 && len(e.Subsets[0].Addresses) > 0 { q.added(e) } } }, UpdateFunc: func(old, cur interface{}) { if e, ok := cur.(*api.Endpoints); ok { if len(e.Subsets) > 0 && len(e.Subsets[0].Addresses) > 0 { q.added(e) } } }, }, ) go controller.Run(q.stop) // Wait for the controller to sync, so that we don't count any warm-up time. for !controller.HasSynced() { time.Sleep(100 * time.Millisecond) } }
func newInformer(controller *HorizontalController, resyncPeriod time.Duration) (cache.Store, *cache.Controller) { return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return controller.hpaNamespacer.HorizontalPodAutoscalers(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return controller.hpaNamespacer.HorizontalPodAutoscalers(api.NamespaceAll).Watch(options) }, }, &autoscaling.HorizontalPodAutoscaler{}, resyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { hpa := obj.(*autoscaling.HorizontalPodAutoscaler) hasCPUPolicy := hpa.Spec.TargetCPUUtilizationPercentage != nil _, hasCustomMetricsPolicy := hpa.Annotations[HpaCustomMetricsTargetAnnotationName] if !hasCPUPolicy && !hasCustomMetricsPolicy { controller.eventRecorder.Event(hpa, api.EventTypeNormal, "DefaultPolicy", "No scaling policy specified - will use default one. See documentation for details") } err := controller.reconcileAutoscaler(hpa) if err != nil { glog.Warningf("Failed to reconcile %s: %v", hpa.Name, err) } }, UpdateFunc: func(old, cur interface{}) { hpa := cur.(*autoscaling.HorizontalPodAutoscaler) err := controller.reconcileAutoscaler(hpa) if err != nil { glog.Warningf("Failed to reconcile %s: %v", hpa.Name, err) } }, // We are not interested in deletions. }, ) }
func (kd *KubeDNS) setEndpointsStore() { // Returns a cache.ListWatch that gets all changes to endpoints. kd.endpointsStore, kd.endpointsController = kcache.NewInformer( &kcache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return kd.kubeClient.Core().Endpoints(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return kd.kubeClient.Core().Endpoints(v1.NamespaceAll).Watch(options) }, }, &v1.Endpoints{}, resyncPeriod, kcache.ResourceEventHandlerFuncs{ AddFunc: kd.handleEndpointAdd, UpdateFunc: func(oldObj, newObj interface{}) { // TODO: Avoid unwanted updates. kd.handleEndpointAdd(newObj) }, // No DeleteFunc for EndpointsStore because endpoint object will be deleted // when corresponding service is deleted. }, ) }
// NewController creates a new PersistentVolume controller func NewController(p ControllerParameters) *PersistentVolumeController { eventRecorder := p.EventRecorder if eventRecorder == nil { broadcaster := record.NewBroadcaster() broadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: p.KubeClient.Core().Events("")}) eventRecorder = broadcaster.NewRecorder(v1.EventSource{Component: "persistentvolume-controller"}) } controller := &PersistentVolumeController{ volumes: newPersistentVolumeOrderedIndex(), claims: cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc), kubeClient: p.KubeClient, eventRecorder: eventRecorder, runningOperations: goroutinemap.NewGoRoutineMap(true /* exponentialBackOffOnError */), cloud: p.Cloud, enableDynamicProvisioning: p.EnableDynamicProvisioning, clusterName: p.ClusterName, createProvisionedPVRetryCount: createProvisionedPVRetryCount, createProvisionedPVInterval: createProvisionedPVInterval, alphaProvisioner: p.AlphaProvisioner, } controller.volumePluginMgr.InitPlugins(p.VolumePlugins, controller) if controller.alphaProvisioner != nil { if err := controller.alphaProvisioner.Init(controller); err != nil { glog.Errorf("PersistentVolumeController: error initializing alpha provisioner plugin: %v", err) } } volumeSource := p.VolumeSource if volumeSource == nil { volumeSource = &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return p.KubeClient.Core().PersistentVolumes().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return p.KubeClient.Core().PersistentVolumes().Watch(options) }, } } controller.volumeSource = volumeSource claimSource := p.ClaimSource if claimSource == nil { claimSource = &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return p.KubeClient.Core().PersistentVolumeClaims(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return p.KubeClient.Core().PersistentVolumeClaims(v1.NamespaceAll).Watch(options) }, } } controller.claimSource = claimSource classSource := p.ClassSource if classSource == nil { classSource = &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return p.KubeClient.Storage().StorageClasses().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return p.KubeClient.Storage().StorageClasses().Watch(options) }, } } controller.classSource = classSource _, controller.volumeController = cache.NewIndexerInformer( volumeSource, &v1.PersistentVolume{}, p.SyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: controller.addVolume, UpdateFunc: controller.updateVolume, DeleteFunc: controller.deleteVolume, }, cache.Indexers{"accessmodes": accessModesIndexFunc}, ) _, controller.claimController = cache.NewInformer( claimSource, &v1.PersistentVolumeClaim{}, p.SyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: controller.addClaim, UpdateFunc: controller.updateClaim, DeleteFunc: controller.deleteClaim, }, ) // This is just a cache of StorageClass instances, no special actions are // needed when a class is created/deleted/updated. controller.classes = cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) controller.classReflector = cache.NewReflector( classSource, &storage.StorageClass{}, controller.classes, p.SyncPeriod, ) return controller }
// NewNamespaceController returns a new namespace controller func NewNamespaceController(client federationclientset.Interface) *NamespaceController { broadcaster := record.NewBroadcaster() broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client)) recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-namespace-controller"}) nc := &NamespaceController{ federatedApiClient: client, namespaceReviewDelay: time.Second * 10, clusterAvailableDelay: time.Second * 20, smallDelay: time.Second * 3, updateTimeout: time.Second * 30, namespaceBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute), eventRecorder: recorder, } // Build delivereres for triggering reconciliations. nc.namespaceDeliverer = util.NewDelayingDeliverer() nc.clusterDeliverer = util.NewDelayingDeliverer() // Start informer in federated API servers on namespaces that should be federated. nc.namespaceInformerStore, nc.namespaceInformerController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) { return client.Core().Namespaces().List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return client.Core().Namespaces().Watch(options) }, }, &api_v1.Namespace{}, controller.NoResyncPeriodFunc(), util.NewTriggerOnAllChanges(func(obj pkg_runtime.Object) { nc.deliverNamespaceObj(obj, 0, false) })) // Federated informer on namespaces in members of federation. nc.namespaceFederatedInformer = util.NewFederatedInformer( client, func(cluster *federation_api.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) { return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) { return targetClient.Core().Namespaces().List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return targetClient.Core().Namespaces().Watch(options) }, }, &api_v1.Namespace{}, controller.NoResyncPeriodFunc(), // Trigger reconciliation whenever something in federated cluster is changed. In most cases it // would be just confirmation that some namespace opration succeeded. util.NewTriggerOnMetaAndSpecChanges( func(obj pkg_runtime.Object) { nc.deliverNamespaceObj(obj, nc.namespaceReviewDelay, false) }, )) }, &util.ClusterLifecycleHandlerFuncs{ ClusterAvailable: func(cluster *federation_api.Cluster) { // When new cluster becomes available process all the namespaces again. nc.clusterDeliverer.DeliverAfter(allClustersKey, nil, nc.clusterAvailableDelay) }, }, ) // Federated updeater along with Create/Update/Delete operations. nc.federatedUpdater = util.NewFederatedUpdater(nc.namespaceFederatedInformer, func(client kubeclientset.Interface, obj pkg_runtime.Object) error { namespace := obj.(*api_v1.Namespace) _, err := client.Core().Namespaces().Create(namespace) return err }, func(client kubeclientset.Interface, obj pkg_runtime.Object) error { namespace := obj.(*api_v1.Namespace) _, err := client.Core().Namespaces().Update(namespace) return err }, func(client kubeclientset.Interface, obj pkg_runtime.Object) error { namespace := obj.(*api_v1.Namespace) err := client.Core().Namespaces().Delete(namespace.Name, &api.DeleteOptions{}) return err }) return nc }
func NewDisruptionController(podInformer cache.SharedIndexInformer, kubeClient internalclientset.Interface) *DisruptionController { dc := &DisruptionController{ kubeClient: kubeClient, podController: podInformer.GetController(), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "disruption"), recheckQueue: workqueue.NewNamedDelayingQueue("disruption-recheck"), broadcaster: record.NewBroadcaster(), } dc.recorder = dc.broadcaster.NewRecorder(api.EventSource{Component: "controllermanager"}) dc.getUpdater = func() updater { return dc.writePdbStatus } dc.podLister.Indexer = podInformer.GetIndexer() podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: dc.addPod, UpdateFunc: dc.updatePod, DeleteFunc: dc.deletePod, }) dc.pdbStore, dc.pdbController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.kubeClient.Policy().PodDisruptionBudgets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.kubeClient.Policy().PodDisruptionBudgets(api.NamespaceAll).Watch(options) }, }, &policy.PodDisruptionBudget{}, 30*time.Second, cache.ResourceEventHandlerFuncs{ AddFunc: dc.addDb, UpdateFunc: dc.updateDb, DeleteFunc: dc.removeDb, }, ) dc.pdbLister.Store = dc.pdbStore dc.rcIndexer, dc.rcController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.kubeClient.Core().ReplicationControllers(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.kubeClient.Core().ReplicationControllers(api.NamespaceAll).Watch(options) }, }, &api.ReplicationController{}, 30*time.Second, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) dc.rcLister.Indexer = dc.rcIndexer dc.rsLister.Indexer, dc.rsController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.kubeClient.Extensions().ReplicaSets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.kubeClient.Extensions().ReplicaSets(api.NamespaceAll).Watch(options) }, }, &extensions.ReplicaSet{}, 30*time.Second, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) dc.rsStore = dc.rsLister.Indexer dc.dIndexer, dc.dController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.kubeClient.Extensions().Deployments(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.kubeClient.Extensions().Deployments(api.NamespaceAll).Watch(options) }, }, &extensions.Deployment{}, 30*time.Second, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) dc.dLister.Indexer = dc.dIndexer return dc }
// newIPVSController creates a new controller from the given config. func newIPVSController(kubeClient *unversioned.Client, namespace string, useUnicast bool, configMapName string) *ipvsControllerController { ipvsc := ipvsControllerController{ client: kubeClient, reloadRateLimiter: flowcontrol.NewTokenBucketRateLimiter(reloadQPS, int(reloadQPS)), ruCfg: []vip{}, configMapName: configMapName, stopCh: make(chan struct{}), } podInfo, err := getPodDetails(kubeClient) if err != nil { glog.Fatalf("Error getting POD information: %v", err) } pod, err := kubeClient.Pods(podInfo.PodNamespace).Get(podInfo.PodName) if err != nil { glog.Fatalf("Error getting %v: %v", podInfo.PodName, err) } selector := parseNodeSelector(pod.Spec.NodeSelector) clusterNodes := getClusterNodesIP(kubeClient, selector) nodeInfo, err := getNetworkInfo(podInfo.NodeIP) if err != nil { glog.Fatalf("Error getting local IP from nodes in the cluster: %v", err) } neighbors := getNodeNeighbors(nodeInfo, clusterNodes) execer := exec.New() dbus := utildbus.New() iptInterface := utiliptables.New(execer, dbus, utiliptables.ProtocolIpv4) ipvsc.keepalived = &keepalived{ iface: nodeInfo.iface, ip: nodeInfo.ip, netmask: nodeInfo.netmask, nodes: clusterNodes, neighbors: neighbors, priority: getNodePriority(nodeInfo.ip, clusterNodes), useUnicast: useUnicast, ipt: iptInterface, } ipvsc.syncQueue = NewTaskQueue(ipvsc.sync) err = ipvsc.keepalived.loadTemplate() if err != nil { glog.Fatalf("Error loading keepalived template: %v", err) } eventHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { ipvsc.syncQueue.enqueue(obj) }, DeleteFunc: func(obj interface{}) { ipvsc.syncQueue.enqueue(obj) }, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { ipvsc.syncQueue.enqueue(cur) } }, } ipvsc.svcLister.Indexer, ipvsc.svcController = cache.NewIndexerInformer( cache.NewListWatchFromClient( ipvsc.client, "services", namespace, fields.Everything()), &api.Service{}, resyncPeriod, eventHandlers, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) ipvsc.epLister.Store, ipvsc.epController = cache.NewInformer( cache.NewListWatchFromClient( ipvsc.client, "endpoints", namespace, fields.Everything()), &api.Endpoints{}, resyncPeriod, eventHandlers) return &ipvsc }
func (r *replenishmentControllerFactory) NewController(options *ReplenishmentControllerOptions) (result cache.ControllerInterface, err error) { if r.kubeClient != nil && r.kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("replenishment_controller", r.kubeClient.Core().RESTClient().GetRateLimiter()) } switch options.GroupKind { case api.Kind("Pod"): if r.sharedInformerFactory != nil { result, err = controllerFor(api.Resource("pods"), r.sharedInformerFactory, cache.ResourceEventHandlerFuncs{ UpdateFunc: PodReplenishmentUpdateFunc(options), DeleteFunc: ObjectReplenishmentDeleteFunc(options), }) break } result = informers.NewPodInformer(r.kubeClient, options.ResyncPeriod()) case api.Kind("Service"): // TODO move to informer when defined _, result = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return r.kubeClient.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return r.kubeClient.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, options.ResyncPeriod(), cache.ResourceEventHandlerFuncs{ UpdateFunc: ServiceReplenishmentUpdateFunc(options), DeleteFunc: ObjectReplenishmentDeleteFunc(options), }, ) case api.Kind("ReplicationController"): // TODO move to informer when defined _, result = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return r.kubeClient.Core().ReplicationControllers(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return r.kubeClient.Core().ReplicationControllers(v1.NamespaceAll).Watch(options) }, }, &v1.ReplicationController{}, options.ResyncPeriod(), cache.ResourceEventHandlerFuncs{ DeleteFunc: ObjectReplenishmentDeleteFunc(options), }, ) case api.Kind("PersistentVolumeClaim"): if r.sharedInformerFactory != nil { result, err = controllerFor(api.Resource("persistentvolumeclaims"), r.sharedInformerFactory, cache.ResourceEventHandlerFuncs{ DeleteFunc: ObjectReplenishmentDeleteFunc(options), }) break } // TODO (derekwaynecarr) remove me when we can require a sharedInformerFactory in all code paths... _, result = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return r.kubeClient.Core().PersistentVolumeClaims(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return r.kubeClient.Core().PersistentVolumeClaims(v1.NamespaceAll).Watch(options) }, }, &v1.PersistentVolumeClaim{}, options.ResyncPeriod(), cache.ResourceEventHandlerFuncs{ DeleteFunc: ObjectReplenishmentDeleteFunc(options), }, ) case api.Kind("Secret"): // TODO move to informer when defined _, result = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return r.kubeClient.Core().Secrets(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return r.kubeClient.Core().Secrets(v1.NamespaceAll).Watch(options) }, }, &v1.Secret{}, options.ResyncPeriod(), cache.ResourceEventHandlerFuncs{ DeleteFunc: ObjectReplenishmentDeleteFunc(options), }, ) case api.Kind("ConfigMap"): // TODO move to informer when defined _, result = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return r.kubeClient.Core().ConfigMaps(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return r.kubeClient.Core().ConfigMaps(v1.NamespaceAll).Watch(options) }, }, &v1.ConfigMap{}, options.ResyncPeriod(), cache.ResourceEventHandlerFuncs{ DeleteFunc: ObjectReplenishmentDeleteFunc(options), }, ) default: return nil, NewUnhandledGroupKindError(options.GroupKind) } return result, err }
// NewIngressController returns a new ingress controller func NewIngressController(client federationclientset.Interface) *IngressController { glog.V(4).Infof("->NewIngressController V(4)") broadcaster := record.NewBroadcaster() broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(client)) recorder := broadcaster.NewRecorder(v1.EventSource{Component: "federated-ingress-controller"}) ic := &IngressController{ federatedApiClient: client, ingressReviewDelay: time.Second * 10, configMapReviewDelay: time.Second * 10, clusterAvailableDelay: time.Second * 20, smallDelay: time.Second * 3, updateTimeout: time.Second * 30, ingressBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute), eventRecorder: recorder, configMapBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute), } // Build deliverers for triggering reconciliations. ic.ingressDeliverer = util.NewDelayingDeliverer() ic.clusterDeliverer = util.NewDelayingDeliverer() ic.configMapDeliverer = util.NewDelayingDeliverer() // Start informer in federated API servers on ingresses that should be federated. ic.ingressInformerStore, ic.ingressInformerController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return client.Extensions().Ingresses(api.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return client.Extensions().Ingresses(api.NamespaceAll).Watch(options) }, }, &extensionsv1beta1.Ingress{}, controller.NoResyncPeriodFunc(), util.NewTriggerOnAllChanges( func(obj pkgruntime.Object) { ic.deliverIngressObj(obj, 0, false) }, )) // Federated informer on ingresses in members of federation. ic.ingressFederatedInformer = util.NewFederatedInformer( client, func(cluster *federationapi.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) { return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return targetClient.Extensions().Ingresses(api.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return targetClient.Extensions().Ingresses(api.NamespaceAll).Watch(options) }, }, &extensionsv1beta1.Ingress{}, controller.NoResyncPeriodFunc(), // Trigger reconciliation whenever something in federated cluster is changed. In most cases it // would be just confirmation that some ingress operation succeeded. util.NewTriggerOnAllChanges( func(obj pkgruntime.Object) { ic.deliverIngressObj(obj, ic.ingressReviewDelay, false) }, )) }, &util.ClusterLifecycleHandlerFuncs{ ClusterAvailable: func(cluster *federationapi.Cluster) { // When new cluster becomes available process all the ingresses again, and configure it's ingress controller's configmap with the correct UID ic.clusterDeliverer.DeliverAfter(cluster.Name, cluster, ic.clusterAvailableDelay) }, }, ) // Federated informer on configmaps for ingress controllers in members of the federation. ic.configMapFederatedInformer = util.NewFederatedInformer( client, func(cluster *federationapi.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.ControllerInterface) { glog.V(4).Infof("Returning new informer for cluster %q", cluster.Name) return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { if targetClient == nil { glog.Errorf("Internal error: targetClient is nil") } return targetClient.Core().ConfigMaps(uidConfigMapNamespace).List(options) // we only want to list one by name - unfortunately Kubernetes don't have a selector for that. }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { if targetClient == nil { glog.Errorf("Internal error: targetClient is nil") } return targetClient.Core().ConfigMaps(uidConfigMapNamespace).Watch(options) // as above }, }, &v1.ConfigMap{}, controller.NoResyncPeriodFunc(), // Trigger reconcilation whenever the ingress controller's configmap in a federated cluster is changed. In most cases it // would be just confirmation that the configmap for the ingress controller is correct. util.NewTriggerOnAllChanges( func(obj pkgruntime.Object) { ic.deliverConfigMapObj(cluster.Name, obj, ic.configMapReviewDelay, false) }, )) }, &util.ClusterLifecycleHandlerFuncs{ ClusterAvailable: func(cluster *federationapi.Cluster) { ic.clusterDeliverer.DeliverAfter(cluster.Name, cluster, ic.clusterAvailableDelay) }, }, ) // Federated ingress updater along with Create/Update/Delete operations. ic.federatedIngressUpdater = util.NewFederatedUpdater(ic.ingressFederatedInformer, func(client kubeclientset.Interface, obj pkgruntime.Object) error { ingress := obj.(*extensionsv1beta1.Ingress) glog.V(4).Infof("Attempting to create Ingress: %v", ingress) _, err := client.Extensions().Ingresses(ingress.Namespace).Create(ingress) if err != nil { glog.Errorf("Error creating ingress %q: %v", types.NamespacedName{Name: ingress.Name, Namespace: ingress.Namespace}, err) } else { glog.V(4).Infof("Successfully created ingress %q", types.NamespacedName{Name: ingress.Name, Namespace: ingress.Namespace}) } return err }, func(client kubeclientset.Interface, obj pkgruntime.Object) error { ingress := obj.(*extensionsv1beta1.Ingress) glog.V(4).Infof("Attempting to update Ingress: %v", ingress) _, err := client.Extensions().Ingresses(ingress.Namespace).Update(ingress) if err != nil { glog.V(4).Infof("Failed to update Ingress: %v", err) } else { glog.V(4).Infof("Successfully updated Ingress: %q", types.NamespacedName{Name: ingress.Name, Namespace: ingress.Namespace}) } return err }, func(client kubeclientset.Interface, obj pkgruntime.Object) error { ingress := obj.(*extensionsv1beta1.Ingress) glog.V(4).Infof("Attempting to delete Ingress: %v", ingress) err := client.Extensions().Ingresses(ingress.Namespace).Delete(ingress.Name, &v1.DeleteOptions{}) return err }) // Federated configmap updater along with Create/Update/Delete operations. Only Update should ever be called. ic.federatedConfigMapUpdater = util.NewFederatedUpdater(ic.configMapFederatedInformer, func(client kubeclientset.Interface, obj pkgruntime.Object) error { configMap := obj.(*v1.ConfigMap) configMapName := types.NamespacedName{Name: configMap.Name, Namespace: configMap.Namespace} glog.Errorf("Internal error: Incorrectly attempting to create ConfigMap: %q", configMapName) _, err := client.Core().ConfigMaps(configMap.Namespace).Create(configMap) return err }, func(client kubeclientset.Interface, obj pkgruntime.Object) error { configMap := obj.(*v1.ConfigMap) configMapName := types.NamespacedName{Name: configMap.Name, Namespace: configMap.Namespace} glog.V(4).Infof("Attempting to update ConfigMap: %v", configMap) _, err := client.Core().ConfigMaps(configMap.Namespace).Update(configMap) if err == nil { glog.V(4).Infof("Successfully updated ConfigMap %q", configMapName) } else { glog.V(4).Infof("Failed to update ConfigMap %q: %v", configMapName, err) } return err }, func(client kubeclientset.Interface, obj pkgruntime.Object) error { configMap := obj.(*v1.ConfigMap) configMapName := types.NamespacedName{Name: configMap.Name, Namespace: configMap.Namespace} glog.Errorf("Internal error: Incorrectly attempting to delete ConfigMap: %q", configMapName) err := client.Core().ConfigMaps(configMap.Namespace).Delete(configMap.Name, &v1.DeleteOptions{}) return err }) ic.deletionHelper = deletionhelper.NewDeletionHelper( ic.hasFinalizerFunc, ic.removeFinalizerFunc, ic.addFinalizerFunc, // objNameFunc func(obj pkgruntime.Object) string { ingress := obj.(*extensionsv1beta1.Ingress) return ingress.Name }, ic.updateTimeout, ic.eventRecorder, ic.ingressFederatedInformer, ic.federatedIngressUpdater, ) return ic }