Change:
<!-- This form is for bug reports and feature requests ONLY! If you're looking for help check and the . --Is this a BUG REPORT or FEATURE REQUEST?: /kind bug What happened: Currently APIServiceRegistrationController watch service change and find the related APIServices related if any. Then it AddAPIService/RemoveAPIService for APIAggregator. I dig into the kube-aggregator and find it no need totally, because update APIServices status when related service or endpoint change. So if does not watch services, it will not miss any event for APIServices. What you expected to happen: How to reproduce it (as minimally and precisely as possible): Anything else we need to know?: Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g. from /etc/os-release): Kernel (e.g. ): Install tools: Others:
/cc
/kind enhancement /sig api-machinery
/assign
that does not follow. AvailableConditionController modifies the APIService object. APIServiceRegistrationController must still watch the APIService objects to observe those changes.
oh, I misread the description. You're saying APIServiceRegistrationController doesn't need to watch v1.Service objects

Discussion:
importpath = "k8s.io/kube-aggregator/pkg/apiserver", deps = [ "//vendor/github.com/golang/glog:go_default_library", <del> "//vendor/k8s.io/api/core/v1:go_default_library", </del> "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",

"//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/proxy:go_default_library", <del> "//vendor/k8s.io/client-go/informers/core/v1:go_default_library", </del> "//vendor/k8s.io/client-go/listers/core/v1:go_default_library", "//vendor/k8s.io/client-go/pkg/version:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library",

s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", apisHandler) s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle("/apis/", apisHandler) <del> apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().InternalVersion().APIServices(), c.GenericConfig.SharedInformerFactory.Core().V1().Services(), s) </del> <ins> apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().InternalVersion().APIServices(), s) </ins> availableController := statuscontrollers.NewAvailableConditionController( informerFactory.Apiregistration().InternalVersion().APIServices(), c.GenericConfig.SharedInformerFactory.Core().V1().Services(),

"github.com/golang/glog" <del> "k8s.io/api/core/v1" </del> apierrors "k8s.io/apimachinery/pkg/api/errors" <del> "k8s.io/apimachinery/pkg/labels" </del> utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" <del> v1informers "k8s.io/client-go/informers/core/v1" v1listers "k8s.io/client-go/listers/core/v1" </del> "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue"

apiServiceLister listers.APIServiceLister apiServiceSynced cache.InformerSynced <del> // serviceLister is used to get the IP to create the transport for serviceLister  v1listers.ServiceLister servicesSynced cache.InformerSynced </del> // To allow injection for testing. syncFn func(key string) error queue workqueue.RateLimitingInterface } <del> func NewAPIServiceRegistrationController(apiServiceInformer informers.APIServiceInformer, serviceInformer v1informers.ServiceInformer, apiHandlerManager APIHandlerManager) *APIServiceRegistrationController { </del> <ins> func NewAPIServiceRegistrationController(apiServiceInformer informers.APIServiceInformer, apiHandlerManager APIHandlerManager) *APIServiceRegistrationController { </ins> c := &APIServiceRegistrationController{ apiHandlerManager: apiHandlerManager, apiServiceLister:  apiServiceInformer.Lister(), apiServiceSynced:  apiServiceInformer.Informer().HasSynced, <del> serviceLister:     serviceInformer.Lister(), servicesSynced:    serviceInformer.Informer().HasSynced, </del> queue:             workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "APIServiceRegistrationController"), }

DeleteFunc: c.deleteAPIService, }) <del> serviceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc:    c.addService, UpdateFunc: c.updateService, DeleteFunc: c.deleteService, }) </del> c.syncFn = c.sync return c

glog.Infof("Starting APIServiceRegistrationController") defer glog.Infof("Shutting down APIServiceRegistrationController") <del> if !controllers.WaitForCacheSync("APIServiceRegistrationController", stopCh, c.apiServiceSynced, c.servicesSynced) { </del> <ins> if !controllers.WaitForCacheSync("APIServiceRegistrationController", stopCh, c.apiServiceSynced) { </ins> return }

glog.V(4).Infof("Deleting %q", castObj.Name) c.enqueue(castObj) } <del> // there aren't very many apiservices, just check them all. func (c *APIServiceRegistrationController) getAPIServicesFor(service *v1.Service) []*apiregistration.APIService { var ret []*apiregistration.APIService apiServiceList, _ := c.apiServiceLister.List(labels.Everything()) for _, apiService := range apiServiceList { if apiService.Spec.Service == nil { continue } if apiService.Spec.Service.Namespace == service.Namespace && apiService.Spec.Service.Name == service.Name { ret = append(ret, apiService) } } return ret } // TODO, think of a way to avoid checking on every service manipulation func (c *APIServiceRegistrationController) addService(obj interface{}) { for _, apiService := range c.getAPIServicesFor(obj.(*v1.Service)) { c.enqueue(apiService) } } func (c *APIServiceRegistrationController) updateService(obj, _ interface{}) { for _, apiService := range c.getAPIServicesFor(obj.(*v1.Service)) { c.enqueue(apiService) } } func (c *APIServiceRegistrationController) deleteService(obj interface{}) { castObj, ok := obj.(*v1.Service) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.Errorf("Couldn't get object from tombstone %#v", obj) return } castObj, ok = tombstone.Obj.(*v1.Service) if !ok { glog.Errorf("Tombstone contained object that is not expected %#v", obj) return } } for _, apiService := range c.getAPIServicesFor(castObj) { c.enqueue(apiService) } } </del>