// NewServiceAccountsController returns a new *ServiceAccountsController. func NewServiceAccountsController(cl clientset.Interface, options ServiceAccountsControllerOptions) *ServiceAccountsController { e := &ServiceAccountsController{ client: cl, serviceAccountsToEnsure: options.ServiceAccounts, } if cl != nil && cl.Core().GetRESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.Core().GetRESTClient().GetRateLimiter()) } accountSelector := fields.Everything() if len(options.ServiceAccounts) == 1 { // If we're maintaining a single account, we can scope the accounts we watch to just that name accountSelector = fields.SelectorFromSet(map[string]string{api.ObjectNameField: options.ServiceAccounts[0].Name}) } e.serviceAccounts, e.serviceAccountController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { options.FieldSelector = accountSelector return e.client.Core().ServiceAccounts(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { options.FieldSelector = accountSelector return e.client.Core().ServiceAccounts(api.NamespaceAll).Watch(options) }, }, &api.ServiceAccount{}, options.ServiceAccountResync, cache.ResourceEventHandlerFuncs{ DeleteFunc: e.serviceAccountDeleted, }, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, ) e.namespaces, e.namespaceController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return e.client.Core().Namespaces().List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return e.client.Core().Namespaces().Watch(options) }, }, &api.Namespace{}, options.NamespaceResync, cache.ResourceEventHandlerFuncs{ AddFunc: e.namespaceAdded, UpdateFunc: e.namespaceUpdated, }, cache.Indexers{"name": nameIndexFunc}, ) return e }
// NewEndpointController returns a new *EndpointController. func NewEndpointController(client *clientset.Clientset) *endpointController { e := &endpointController{ client: client, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "endpoint"), } e.serviceStore.Indexer, e.serviceController = cache.NewIndexerInformer( &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, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) 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 }
// newReplicationManager configures a replication manager with the specified event recorder func newReplicationManager(eventRecorder record.EventRecorder, podInformer cache.SharedIndexInformer, kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, burstReplicas int, lookupCacheSize int, garbageCollectorEnabled bool) *ReplicationManager { if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("replication_controller", kubeClient.Core().RESTClient().GetRateLimiter()) } rm := &ReplicationManager{ kubeClient: kubeClient, podControl: controller.RealPodControl{ KubeClient: kubeClient, Recorder: eventRecorder, }, burstReplicas: burstReplicas, expectations: controller.NewUIDTrackingControllerExpectations(controller.NewControllerExpectations()), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "replicationmanager"), garbageCollectorEnabled: garbageCollectorEnabled, } rm.rcStore.Indexer, rm.rcController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return rm.kubeClient.Core().ReplicationControllers(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return rm.kubeClient.Core().ReplicationControllers(api.NamespaceAll).Watch(options) }, }, &api.ReplicationController{}, // TODO: Can we have much longer period here? FullControllerResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: rm.enqueueController, UpdateFunc: rm.updateRC, // This will enter the sync loop and no-op, because the controller has been deleted from the store. // Note that deleting a controller immediately after scaling it to 0 will not work. The recommended // way of achieving this is by performing a `stop` operation on the controller. DeleteFunc: rm.enqueueController, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: rm.addPod, // This invokes the rc for every pod change, eg: host assignment. Though this might seem like overkill // the most frequent pod update is status, and the associated rc will only list from local storage, so // it should be ok. UpdateFunc: rm.updatePod, DeleteFunc: rm.deletePod, }) rm.podStore.Indexer = podInformer.GetIndexer() rm.podController = podInformer.GetController() rm.syncHandler = rm.syncReplicationController rm.podStoreSynced = rm.podController.HasSynced rm.lookupCache = controller.NewMatchingCache(lookupCacheSize) return rm }
// 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 }
// 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(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) recorder := broadcaster.NewRecorder(v1.EventSource{Component: "service-controller"}) if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("service_controller", kubeClient.Core().RESTClient().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.Indexer, s.serviceController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return s.kubeClient.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return s.kubeClient.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, serviceSyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: s.enqueueService, UpdateFunc: func(old, cur interface{}) { oldSvc, ok1 := old.(*v1.Service) curSvc, ok2 := cur.(*v1.Service) if ok1 && ok2 && s.needsUpdate(oldSvc, curSvc) { s.enqueueService(cur) } }, DeleteFunc: s.enqueueService, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) if err := s.init(); err != nil { return nil, err } return s, nil }
// NewEndpointController returns a new *EndpointController. func NewEndpointController(podInformer cache.SharedIndexInformer, client clientset.Interface) *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.Indexer, e.serviceController = cache.NewIndexerInformer( &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, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) 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 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 New(federationClient fedclientset.Interface, dns dnsprovider.Interface, federationName, serviceDnsSuffix, zoneName string, zoneID string) *ServiceController { broadcaster := record.NewBroadcaster() // federationClient event is not supported yet // broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")}) recorder := broadcaster.NewRecorder(v1.EventSource{Component: UserAgentName}) s := &ServiceController{ dns: dns, federationClient: federationClient, federationName: federationName, serviceDnsSuffix: serviceDnsSuffix, zoneName: zoneName, zoneID: zoneID, serviceCache: &serviceCache{fedServiceMap: make(map[string]*cachedService)}, clusterCache: &clusterClientCache{ rwlock: sync.Mutex{}, clientMap: make(map[string]*clusterCache), }, eventBroadcaster: broadcaster, eventRecorder: recorder, queue: workqueue.New(), knownClusterSet: make(sets.String), } s.serviceStore.Indexer, s.serviceController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return s.federationClient.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return s.federationClient.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, serviceSyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: s.enqueueService, UpdateFunc: func(old, cur interface{}) { // there is case that old and new are equals but we still catch the event now. if !reflect.DeepEqual(old, cur) { s.enqueueService(cur) } }, DeleteFunc: s.enqueueService, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) s.clusterStore.Store, s.clusterController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return s.federationClient.Federation().Clusters().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return s.federationClient.Federation().Clusters().Watch(options) }, }, &v1beta1.Cluster{}, clusterSyncPeriod, cache.ResourceEventHandlerFuncs{ DeleteFunc: s.clusterCache.delFromClusterSet, AddFunc: s.clusterCache.addToClientMap, UpdateFunc: func(old, cur interface{}) { oldCluster, ok := old.(*v1beta1.Cluster) if !ok { return } curCluster, ok := cur.(*v1beta1.Cluster) if !ok { return } if !reflect.DeepEqual(oldCluster.Spec, curCluster.Spec) { // update when spec is changed s.clusterCache.addToClientMap(cur) } pred := getClusterConditionPredicate() // only update when condition changed to ready from not-ready if !pred(*oldCluster) && pred(*curCluster) { s.clusterCache.addToClientMap(cur) } // did not handle ready -> not-ready // how could we stop a controller? }, }, ) s.endpointWorkerMap = make(map[string]bool) s.serviceWorkerMap = make(map[string]bool) s.endpointWorkerDoneChan = make(chan string, maxNoOfClusters) s.serviceWorkerDoneChan = make(chan string, maxNoOfClusters) return s }
// NewTokensController returns a new *TokensController. func NewTokensController(cl clientset.Interface, options TokensControllerOptions) *TokensController { maxRetries := options.MaxRetries if maxRetries == 0 { maxRetries = 10 } e := &TokensController{ client: cl, token: options.TokenGenerator, rootCA: options.RootCA, syncServiceAccountQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "serviceaccount_tokens_service"), syncSecretQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "serviceaccount_tokens_secret"), maxRetries: maxRetries, } if cl != nil && cl.Core().GetRESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.Core().GetRESTClient().GetRateLimiter()) } e.serviceAccounts, 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.ServiceAccountResync, cache.ResourceEventHandlerFuncs{ AddFunc: e.queueServiceAccountSync, UpdateFunc: e.queueServiceAccountUpdateSync, DeleteFunc: e.queueServiceAccountSync, }, ) tokenSelector := fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(api.SecretTypeServiceAccountToken)}) e.secrets, e.secretController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { options.FieldSelector = tokenSelector return e.client.Core().Secrets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { options.FieldSelector = tokenSelector return e.client.Core().Secrets(api.NamespaceAll).Watch(options) }, }, &api.Secret{}, options.SecretResync, cache.ResourceEventHandlerFuncs{ AddFunc: e.queueSecretSync, UpdateFunc: e.queueSecretUpdateSync, DeleteFunc: e.queueSecretSync, }, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, ) return e }
// Initializes the factory. func NewConfigFactory(client clientset.Interface, schedulerName string, hardPodAffinitySymmetricWeight int, failureDomains string) *ConfigFactory { stopEverything := make(chan struct{}) schedulerCache := schedulercache.New(30*time.Second, stopEverything) // TODO: pass this in as an argument... informerFactory := informers.NewSharedInformerFactory(client, nil, 0) pvcInformer := informerFactory.PersistentVolumeClaims() c := &ConfigFactory{ Client: client, PodQueue: cache.NewFIFO(cache.MetaNamespaceKeyFunc), ScheduledPodLister: &cache.StoreToPodLister{}, informerFactory: informerFactory, // Only nodes in the "Ready" condition with status == "True" are schedulable NodeLister: &cache.StoreToNodeLister{}, PVLister: &cache.StoreToPVFetcher{Store: cache.NewStore(cache.MetaNamespaceKeyFunc)}, PVCLister: pvcInformer.Lister(), pvcPopulator: pvcInformer.Informer().GetController(), ServiceLister: &cache.StoreToServiceLister{Indexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}, ControllerLister: &cache.StoreToReplicationControllerLister{Indexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}, ReplicaSetLister: &cache.StoreToReplicaSetLister{Indexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})}, 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(), &v1.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(), &v1.Node{}, 0, cache.ResourceEventHandlerFuncs{ AddFunc: c.addNodeToCache, UpdateFunc: c.updateNodeInCache, DeleteFunc: c.deleteNodeFromCache, }, ) // TODO(harryz) need to fill all the handlers here and below for equivalence cache c.PVLister.Store, c.pvPopulator = cache.NewInformer( c.createPersistentVolumeLW(), &v1.PersistentVolume{}, 0, cache.ResourceEventHandlerFuncs{}, ) c.ServiceLister.Indexer, c.servicePopulator = cache.NewIndexerInformer( c.createServiceLW(), &v1.Service{}, 0, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) c.ControllerLister.Indexer, c.controllerPopulator = cache.NewIndexerInformer( c.createControllerLW(), &v1.ReplicationController{}, 0, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) return c }
// NewclusterController returns a new cluster controller func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSetController { broadcaster := record.NewBroadcaster() broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(federationClient)) recorder := broadcaster.NewRecorder(api.EventSource{Component: "federated-replicaset-controller"}) frsc := &ReplicaSetController{ fedClient: federationClient, replicasetDeliverer: fedutil.NewDelayingDeliverer(), clusterDeliverer: fedutil.NewDelayingDeliverer(), replicasetWorkQueue: workqueue.New(), replicaSetBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute), defaultPlanner: planner.NewPlanner(&fed.FederatedReplicaSetPreferences{ Clusters: map[string]fed.ClusterReplicaSetPreferences{ "*": {Weight: 1}, }, }), eventRecorder: recorder, } replicaSetFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) { return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { versionedOptions := fedutil.VersionizeV1ListOptions(options) return clientset.Extensions().ReplicaSets(apiv1.NamespaceAll).List(versionedOptions) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { versionedOptions := fedutil.VersionizeV1ListOptions(options) return clientset.Extensions().ReplicaSets(apiv1.NamespaceAll).Watch(versionedOptions) }, }, &extensionsv1.ReplicaSet{}, controller.NoResyncPeriodFunc(), fedutil.NewTriggerOnAllChanges( func(obj runtime.Object) { frsc.deliverLocalReplicaSet(obj, replicaSetReviewDelay) }, ), ) } clusterLifecycle := fedutil.ClusterLifecycleHandlerFuncs{ ClusterAvailable: func(cluster *fedv1.Cluster) { frsc.clusterDeliverer.DeliverAfter(allClustersKey, nil, clusterAvailableDelay) }, ClusterUnavailable: func(cluster *fedv1.Cluster, _ []interface{}) { frsc.clusterDeliverer.DeliverAfter(allClustersKey, nil, clusterUnavailableDelay) }, } frsc.fedReplicaSetInformer = fedutil.NewFederatedInformer(federationClient, replicaSetFedInformerFactory, &clusterLifecycle) podFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.ControllerInterface) { return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { versionedOptions := fedutil.VersionizeV1ListOptions(options) return clientset.Core().Pods(apiv1.NamespaceAll).List(versionedOptions) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { versionedOptions := fedutil.VersionizeV1ListOptions(options) return clientset.Core().Pods(apiv1.NamespaceAll).Watch(versionedOptions) }, }, &apiv1.Pod{}, controller.NoResyncPeriodFunc(), fedutil.NewTriggerOnAllChanges( func(obj runtime.Object) { frsc.clusterDeliverer.DeliverAfter(allClustersKey, nil, allReplicaSetReviewDelay) }, ), ) } frsc.fedPodInformer = fedutil.NewFederatedInformer(federationClient, podFedInformerFactory, &fedutil.ClusterLifecycleHandlerFuncs{}) frsc.replicaSetStore.Indexer, frsc.replicaSetController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { versionedOptions := fedutil.VersionizeV1ListOptions(options) return frsc.fedClient.Extensions().ReplicaSets(apiv1.NamespaceAll).List(versionedOptions) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { versionedOptions := fedutil.VersionizeV1ListOptions(options) return frsc.fedClient.Extensions().ReplicaSets(apiv1.NamespaceAll).Watch(versionedOptions) }, }, &extensionsv1.ReplicaSet{}, controller.NoResyncPeriodFunc(), fedutil.NewTriggerOnMetaAndSpecChanges( func(obj runtime.Object) { frsc.deliverFedReplicaSetObj(obj, replicaSetReviewDelay) }, ), cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) frsc.fedUpdater = fedutil.NewFederatedUpdater(frsc.fedReplicaSetInformer, func(client kubeclientset.Interface, obj runtime.Object) error { rs := obj.(*extensionsv1.ReplicaSet) _, err := client.Extensions().ReplicaSets(rs.Namespace).Create(rs) return err }, func(client kubeclientset.Interface, obj runtime.Object) error { rs := obj.(*extensionsv1.ReplicaSet) _, err := client.Extensions().ReplicaSets(rs.Namespace).Update(rs) return err }, func(client kubeclientset.Interface, obj runtime.Object) error { rs := obj.(*extensionsv1.ReplicaSet) err := client.Extensions().ReplicaSets(rs.Namespace).Delete(rs.Name, &apiv1.DeleteOptions{}) return err }) frsc.deletionHelper = deletionhelper.NewDeletionHelper( frsc.hasFinalizerFunc, frsc.removeFinalizerFunc, frsc.addFinalizerFunc, // objNameFunc func(obj runtime.Object) string { replicaset := obj.(*extensionsv1.ReplicaSet) return replicaset.Name }, updateTimeout, frsc.eventRecorder, frsc.fedReplicaSetInformer, frsc.fedUpdater, ) return frsc }
// NewDeploymentController creates a new DeploymentController. func NewDeploymentController(client clientset.Interface, resyncPeriod controller.ResyncPeriodFunc) *DeploymentController { 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: client.Core().Events("")}) if client != nil && client.Core().GetRESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("deployment_controller", client.Core().GetRESTClient().GetRateLimiter()) } dc := &DeploymentController{ client: client, eventRecorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "deployment-controller"}), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "deployment"), } dc.dLister.Indexer, dc.dController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.client.Extensions().Deployments(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.client.Extensions().Deployments(api.NamespaceAll).Watch(options) }, }, &extensions.Deployment{}, FullDeploymentResyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: dc.addDeploymentNotification, UpdateFunc: dc.updateDeploymentNotification, // This will enter the sync loop and no-op, because the deployment has been deleted from the store. DeleteFunc: dc.deleteDeploymentNotification, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) dc.rsLister.Indexer, dc.rsController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.client.Extensions().ReplicaSets(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.client.Extensions().ReplicaSets(api.NamespaceAll).Watch(options) }, }, &extensions.ReplicaSet{}, resyncPeriod(), cache.ResourceEventHandlerFuncs{ AddFunc: dc.addReplicaSet, UpdateFunc: dc.updateReplicaSet, DeleteFunc: dc.deleteReplicaSet, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) dc.podLister.Indexer, dc.podController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (runtime.Object, error) { return dc.client.Core().Pods(api.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return dc.client.Core().Pods(api.NamespaceAll).Watch(options) }, }, &api.Pod{}, resyncPeriod(), cache.ResourceEventHandlerFuncs{ AddFunc: dc.addPod, UpdateFunc: dc.updatePod, DeleteFunc: dc.deletePod, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) dc.syncHandler = dc.syncDeployment dc.dListerSynced = dc.dController.HasSynced dc.rsListerSynced = dc.rsController.HasSynced dc.podListerSynced = dc.podController.HasSynced return dc }
// NewLoadBalancerController creates a controller for gce loadbalancers. // - kubeClient: A kubernetes REST client. // - clusterManager: A ClusterManager capable of creating all cloud resources // required for L7 loadbalancing. // - resyncPeriod: Watchers relist from the Kubernetes API server this often. func NewLoadBalancerController(kubeClient client.Interface, clusterManager *ClusterManager, resyncPeriod time.Duration, namespace string) (*LoadBalancerController, error) { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{ Interface: kubeClient.Core().Events(""), }) lbc := LoadBalancerController{ client: kubeClient, CloudClusterManager: clusterManager, stopCh: make(chan struct{}), recorder: eventBroadcaster.NewRecorder( api.EventSource{Component: "loadbalancer-controller"}), } lbc.nodeQueue = NewTaskQueue(lbc.syncNodes) lbc.ingQueue = NewTaskQueue(lbc.sync) lbc.hasSynced = lbc.storesSynced // Ingress watch handlers pathHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { addIng := obj.(*extensions.Ingress) if !isGCEIngress(addIng) { glog.Infof("Ignoring add for ingress %v based on annotation %v", addIng.Name, ingressClassKey) return } lbc.recorder.Eventf(addIng, api.EventTypeNormal, "ADD", fmt.Sprintf("%s/%s", addIng.Namespace, addIng.Name)) lbc.ingQueue.enqueue(obj) }, DeleteFunc: func(obj interface{}) { delIng := obj.(*extensions.Ingress) if !isGCEIngress(delIng) { glog.Infof("Ignoring delete for ingress %v based on annotation %v", delIng.Name, ingressClassKey) return } glog.Infof("Delete notification received for Ingress %v/%v", delIng.Namespace, delIng.Name) lbc.ingQueue.enqueue(obj) }, UpdateFunc: func(old, cur interface{}) { curIng := cur.(*extensions.Ingress) if !isGCEIngress(curIng) { return } if !reflect.DeepEqual(old, cur) { glog.V(3).Infof("Ingress %v changed, syncing", curIng.Name) } lbc.ingQueue.enqueue(cur) }, } lbc.ingLister.Store, lbc.ingController = cache.NewInformer( &cache.ListWatch{ ListFunc: ingressListFunc(lbc.client, namespace), WatchFunc: ingressWatchFunc(lbc.client, namespace), }, &extensions.Ingress{}, resyncPeriod, pathHandlers) // Service watch handlers svcHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: lbc.enqueueIngressForService, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { lbc.enqueueIngressForService(cur) } }, // Ingress deletes matter, service deletes don't. } lbc.svcLister.Indexer, lbc.svcController = cache.NewIndexerInformer( cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "services", namespace, fields.Everything()), &api.Service{}, resyncPeriod, svcHandlers, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) lbc.podLister.Indexer, lbc.podController = cache.NewIndexerInformer( cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "pods", namespace, fields.Everything()), &api.Pod{}, resyncPeriod, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) nodeHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: lbc.nodeQueue.enqueue, DeleteFunc: lbc.nodeQueue.enqueue, // Nodes are updated every 10s and we don't care, so no update handler. } // Node watch handlers lbc.nodeLister.Store, lbc.nodeController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(opts api.ListOptions) (runtime.Object, error) { return lbc.client.Core().RESTClient().Get(). Resource("nodes"). FieldsSelectorParam(fields.Everything()). Do(). Get() }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return lbc.client.Core().RESTClient().Get(). Prefix("watch"). Resource("nodes"). FieldsSelectorParam(fields.Everything()). Param("resourceVersion", options.ResourceVersion).Watch() }, }, &api.Node{}, 0, nodeHandlers) lbc.tr = &GCETranslator{&lbc} lbc.tlsLoader = &apiServerTLSLoader{client: lbc.client} glog.V(3).Infof("Created new loadbalancer controller") return &lbc, nil }
func (cc *clusterClientCache) startClusterLW(cluster *v1beta1.Cluster, clusterName string) { cachedClusterClient, ok := cc.clientMap[clusterName] // only create when no existing cachedClusterClient if ok { if !reflect.DeepEqual(cachedClusterClient.cluster.Spec, cluster.Spec) { //rebuild clientset when cluster spec is changed clientset, err := newClusterClientset(cluster) if err != nil || clientset == nil { glog.Errorf("Failed to create corresponding restclient of kubernetes cluster: %v", err) } glog.V(4).Infof("Cluster spec changed, rebuild clientset for cluster %s", clusterName) cachedClusterClient.clientset = clientset go cachedClusterClient.serviceController.Run(wait.NeverStop) go cachedClusterClient.endpointController.Run(wait.NeverStop) glog.V(2).Infof("Start watching services and endpoints on cluster %s", clusterName) } else { // do nothing when there is no spec change glog.V(4).Infof("Keep clientset for cluster %s", clusterName) return } } else { glog.V(4).Infof("No client cache for cluster %s, building new", clusterName) clientset, err := newClusterClientset(cluster) if err != nil || clientset == nil { glog.Errorf("Failed to create corresponding restclient of kubernetes cluster: %v", err) } cachedClusterClient = &clusterCache{ cluster: cluster, clientset: clientset, serviceQueue: workqueue.New(), endpointQueue: workqueue.New(), } cachedClusterClient.endpointStore.Store, cachedClusterClient.endpointController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) { return clientset.Core().Endpoints(v1.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return clientset.Core().Endpoints(v1.NamespaceAll).Watch(options) }, }, &v1.Endpoints{}, serviceSyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { cc.enqueueEndpoint(obj, clusterName) }, UpdateFunc: func(old, cur interface{}) { cc.enqueueEndpoint(cur, clusterName) }, DeleteFunc: func(obj interface{}) { cc.enqueueEndpoint(obj, clusterName) }, }, ) cachedClusterClient.serviceStore.Indexer, cachedClusterClient.serviceController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options api.ListOptions) (pkg_runtime.Object, error) { return clientset.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options api.ListOptions) (watch.Interface, error) { return clientset.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, serviceSyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { cc.enqueueService(obj, clusterName) }, UpdateFunc: func(old, cur interface{}) { oldService, ok := old.(*v1.Service) if !ok { return } curService, ok := cur.(*v1.Service) if !ok { return } if !reflect.DeepEqual(oldService.Status.LoadBalancer, curService.Status.LoadBalancer) { cc.enqueueService(cur, clusterName) } }, DeleteFunc: func(obj interface{}) { service, _ := obj.(*v1.Service) cc.enqueueService(obj, clusterName) glog.V(2).Infof("Service %s/%s deletion found and enque to service store %s", service.Namespace, service.Name, clusterName) }, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) cc.clientMap[clusterName] = cachedClusterClient go cachedClusterClient.serviceController.Run(wait.NeverStop) go cachedClusterClient.endpointController.Run(wait.NeverStop) glog.V(2).Infof("Start watching services and endpoints on cluster %s", clusterName) } }
func New(federationClient fedclientset.Interface, dns dnsprovider.Interface, federationName, serviceDnsSuffix, zoneName string, zoneID string) *ServiceController { broadcaster := record.NewBroadcaster() // federationClient event is not supported yet // broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")}) recorder := broadcaster.NewRecorder(v1.EventSource{Component: UserAgentName}) s := &ServiceController{ dns: dns, federationClient: federationClient, federationName: federationName, serviceDnsSuffix: serviceDnsSuffix, zoneName: zoneName, zoneID: zoneID, serviceCache: &serviceCache{fedServiceMap: make(map[string]*cachedService)}, clusterCache: &clusterClientCache{ rwlock: sync.Mutex{}, clientMap: make(map[string]*clusterCache), }, eventBroadcaster: broadcaster, eventRecorder: recorder, queue: workqueue.New(), knownClusterSet: make(sets.String), } s.clusterDeliverer = util.NewDelayingDeliverer() s.serviceStore.Indexer, s.serviceController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return s.federationClient.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return s.federationClient.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, serviceSyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: s.enqueueService, UpdateFunc: func(old, cur interface{}) { // there is case that old and new are equals but we still catch the event now. if !reflect.DeepEqual(old, cur) { s.enqueueService(cur) } }, DeleteFunc: s.enqueueService, }, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, ) s.clusterStore.Store, s.clusterController = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return s.federationClient.Federation().Clusters().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return s.federationClient.Federation().Clusters().Watch(options) }, }, &v1beta1.Cluster{}, clusterSyncPeriod, cache.ResourceEventHandlerFuncs{ DeleteFunc: s.clusterCache.delFromClusterSet, AddFunc: s.clusterCache.addToClientMap, UpdateFunc: func(old, cur interface{}) { oldCluster, ok := old.(*v1beta1.Cluster) if !ok { return } curCluster, ok := cur.(*v1beta1.Cluster) if !ok { return } if !reflect.DeepEqual(oldCluster.Spec, curCluster.Spec) { // update when spec is changed s.clusterCache.addToClientMap(cur) } pred := getClusterConditionPredicate() // only update when condition changed to ready from not-ready if !pred(*oldCluster) && pred(*curCluster) { s.clusterCache.addToClientMap(cur) } // did not handle ready -> not-ready // how could we stop a controller? }, }, ) clusterLifecycle := fedutil.ClusterLifecycleHandlerFuncs{ ClusterAvailable: func(cluster *v1beta1.Cluster) { s.clusterDeliverer.DeliverAfter(allClustersKey, nil, clusterAvailableDelay) }, } fedInformerFactory := func(cluster *v1beta1.Cluster, targetClient kubeclientset.Interface) (cache.Store, cache.Controller) { return cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (pkgruntime.Object, error) { return targetClient.Core().Services(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return targetClient.Core().Services(v1.NamespaceAll).Watch(options) }, }, &v1.Service{}, controller.NoResyncPeriodFunc(), // Trigger reconciliation whenever something in federated cluster is changed. In most cases it // would be just confirmation that some service operation succeeded. util.NewTriggerOnAllChanges( func(obj pkgruntime.Object) { // TODO: Use this to enque services. }, )) } s.federatedInformer = fedutil.NewFederatedInformer(federationClient, fedInformerFactory, &clusterLifecycle) federatedUpdater := fedutil.NewFederatedUpdater(s.federatedInformer, func(client kubeclientset.Interface, obj pkgruntime.Object) error { svc := obj.(*v1.Service) _, err := client.Core().Services(svc.Namespace).Create(svc) return err }, func(client kubeclientset.Interface, obj pkgruntime.Object) error { svc := obj.(*v1.Service) _, err := client.Core().Services(svc.Namespace).Update(svc) return err }, func(client kubeclientset.Interface, obj pkgruntime.Object) error { svc := obj.(*v1.Service) err := client.Core().Services(svc.Namespace).Delete(svc.Name, &v1.DeleteOptions{}) return err }) s.deletionHelper = deletionhelper.NewDeletionHelper( s.hasFinalizerFunc, s.removeFinalizerFunc, s.addFinalizerFunc, // objNameFunc func(obj pkgruntime.Object) string { service := obj.(*v1.Service) return service.Name }, updateTimeout, s.eventRecorder, s.federatedInformer, federatedUpdater, ) s.endpointWorkerMap = make(map[string]bool) s.serviceWorkerMap = make(map[string]bool) s.endpointWorkerDoneChan = make(chan string, maxNoOfClusters) s.serviceWorkerDoneChan = make(chan string, maxNoOfClusters) return s }
// newIngressController creates an Ingress controller func newIngressController(config *Configuration) *GenericController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{ Interface: config.Client.Core().Events(config.Namespace), }) ic := GenericController{ cfg: config, stopLock: &sync.Mutex{}, stopCh: make(chan struct{}), syncRateLimiter: flowcontrol.NewTokenBucketRateLimiter(0.1, 1), recorder: eventBroadcaster.NewRecorder(api.EventSource{ Component: "ingress-controller", }), sslCertTracker: newSSLCertTracker(), } ic.syncQueue = task.NewTaskQueue(ic.sync) ic.secretQueue = task.NewTaskQueue(ic.syncSecret) // from here to the end of the method all the code is just boilerplate // required to watch Ingress, Secrets, ConfigMaps and Endoints. // This is used to detect new content, updates or removals and act accordingly ingEventHandler := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { addIng := obj.(*extensions.Ingress) if !IsValidClass(addIng, config.IngressClass) { glog.Infof("ignoring add for ingress %v based on annotation %v", addIng.Name, ingressClassKey) return } ic.recorder.Eventf(addIng, api.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", addIng.Namespace, addIng.Name)) ic.syncQueue.Enqueue(obj) }, DeleteFunc: func(obj interface{}) { delIng := obj.(*extensions.Ingress) if !IsValidClass(delIng, config.IngressClass) { glog.Infof("ignoring add for ingress %v based on annotation %v", delIng.Name, ingressClassKey) return } ic.recorder.Eventf(delIng, api.EventTypeNormal, "DELETE", fmt.Sprintf("Ingress %s/%s", delIng.Namespace, delIng.Name)) ic.syncQueue.Enqueue(obj) }, UpdateFunc: func(old, cur interface{}) { curIng := cur.(*extensions.Ingress) if !IsValidClass(curIng, config.IngressClass) { return } if !reflect.DeepEqual(old, cur) { upIng := cur.(*extensions.Ingress) ic.recorder.Eventf(upIng, api.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", upIng.Namespace, upIng.Name)) ic.syncQueue.Enqueue(cur) } }, } secrEventHandler := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { sec := obj.(*api.Secret) ic.secretQueue.Enqueue(sec) }, DeleteFunc: func(obj interface{}) { sec := obj.(*api.Secret) ic.sslCertTracker.Delete(fmt.Sprintf("%v/%v", sec.Namespace, sec.Name)) }, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { sec := cur.(*api.Secret) ic.secretQueue.Enqueue(sec) } }, } eventHandler := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { ic.syncQueue.Enqueue(obj) }, DeleteFunc: func(obj interface{}) { ic.syncQueue.Enqueue(obj) }, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { ic.syncQueue.Enqueue(cur) } }, } mapEventHandler := cache.ResourceEventHandlerFuncs{ UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { upCmap := cur.(*api.ConfigMap) mapKey := fmt.Sprintf("%s/%s", upCmap.Namespace, upCmap.Name) // updates to configuration configmaps can trigger an update if mapKey == ic.cfg.ConfigMapName || mapKey == ic.cfg.TCPConfigMapName || mapKey == ic.cfg.UDPConfigMapName { ic.recorder.Eventf(upCmap, api.EventTypeNormal, "UPDATE", fmt.Sprintf("ConfigMap %v", mapKey)) ic.syncQueue.Enqueue(cur) } } }, } ic.ingLister.Store, ic.ingController = cache.NewInformer( cache.NewListWatchFromClient(ic.cfg.Client.Extensions().RESTClient(), "ingresses", ic.cfg.Namespace, fields.Everything()), &extensions.Ingress{}, ic.cfg.ResyncPeriod, ingEventHandler) ic.endpLister.Store, ic.endpController = cache.NewInformer( cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "endpoints", ic.cfg.Namespace, fields.Everything()), &api.Endpoints{}, ic.cfg.ResyncPeriod, eventHandler) ic.secrLister.Store, ic.secrController = cache.NewInformer( cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "secrets", ic.cfg.Namespace, fields.Everything()), &api.Secret{}, ic.cfg.ResyncPeriod, secrEventHandler) ic.mapLister.Store, ic.mapController = cache.NewInformer( cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "configmaps", ic.cfg.Namespace, fields.Everything()), &api.ConfigMap{}, ic.cfg.ResyncPeriod, mapEventHandler) ic.svcLister.Indexer, ic.svcController = cache.NewIndexerInformer( cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "services", ic.cfg.Namespace, fields.Everything()), &api.Service{}, ic.cfg.ResyncPeriod, cache.ResourceEventHandlerFuncs{}, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) ic.syncStatus = status.NewStatusSyncer(status.Config{ Client: config.Client, PublishService: ic.cfg.PublishService, IngressLister: ic.ingLister, }) return &ic }
// 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 }
func NewResourceQuotaController(options *ResourceQuotaControllerOptions) *ResourceQuotaController { // build the resource quota controller rq := &ResourceQuotaController{ kubeClient: options.KubeClient, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "resourcequota_primary"), missingUsageQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "resourcequota_priority"), resyncPeriod: options.ResyncPeriod, registry: options.Registry, replenishmentControllers: []cache.Controller{}, } if options.KubeClient != nil && options.KubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("resource_quota_controller", options.KubeClient.Core().RESTClient().GetRateLimiter()) } // set the synchronization handler rq.syncHandler = rq.syncResourceQuotaFromKey // build the controller that observes quota rq.rqIndexer, rq.rqController = cache.NewIndexerInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return rq.kubeClient.Core().ResourceQuotas(v1.NamespaceAll).List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return rq.kubeClient.Core().ResourceQuotas(v1.NamespaceAll).Watch(options) }, }, &v1.ResourceQuota{}, rq.resyncPeriod(), cache.ResourceEventHandlerFuncs{ AddFunc: rq.addQuota, UpdateFunc: func(old, cur interface{}) { // We are only interested in observing updates to quota.spec to drive updates to quota.status. // We ignore all updates to quota.Status because they are all driven by this controller. // IMPORTANT: // We do not use this function to queue up a full quota recalculation. To do so, would require // us to enqueue all quota.Status updates, and since quota.Status updates involve additional queries // that cannot be backed by a cache and result in a full query of a namespace's content, we do not // want to pay the price on spurious status updates. As a result, we have a separate routine that is // responsible for enqueue of all resource quotas when doing a full resync (enqueueAll) oldResourceQuota := old.(*v1.ResourceQuota) curResourceQuota := cur.(*v1.ResourceQuota) if quota.V1Equals(oldResourceQuota.Spec.Hard, curResourceQuota.Spec.Hard) { return } rq.addQuota(curResourceQuota) }, // This will enter the sync loop and no-op, because the controller has been deleted from the store. // Note that deleting a controller immediately after scaling it to 0 will not work. The recommended // way of achieving this is by performing a `stop` operation on the controller. DeleteFunc: rq.enqueueResourceQuota, }, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, ) for _, groupKindToReplenish := range options.GroupKindsToReplenish { controllerOptions := &ReplenishmentControllerOptions{ GroupKind: groupKindToReplenish, ResyncPeriod: options.ReplenishmentResyncPeriod, ReplenishmentFunc: rq.replenishQuota, } replenishmentController, err := options.ControllerFactory.NewController(controllerOptions) if err != nil { glog.Warningf("quota controller unable to replenish %s due to %v, changes only accounted during full resync", groupKindToReplenish, err) } else { rq.replenishmentControllers = append(rq.replenishmentControllers, replenishmentController) } } return rq }